summaryrefslogtreecommitdiffstats
path: root/freebsd
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2013-10-09 22:42:09 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2013-10-10 09:06:58 +0200
commitbceabc95c1c85d793200446fa85f1ddc6313ea29 (patch)
tree973c8bd8deca9fd69913f2895cc91e0e6114d46c /freebsd
parentAdd FreeBSD sources as a submodule (diff)
downloadrtems-libbsd-bceabc95c1c85d793200446fa85f1ddc6313ea29.tar.bz2
Move files to match FreeBSD layout
Diffstat (limited to 'freebsd')
-rw-r--r--freebsd/cam/cam_queue.h1
-rw-r--r--freebsd/ddb/db_sym.h1
-rw-r--r--freebsd/ddb/ddb.h1
-rw-r--r--freebsd/geom/geom_disk.h1
-rw-r--r--freebsd/include/arpa/ftp.h109
-rw-r--r--freebsd/include/arpa/inet.h182
-rw-r--r--freebsd/include/arpa/nameser.h584
-rw-r--r--freebsd/include/arpa/nameser_compat.h203
-rw-r--r--freebsd/include/db.h221
-rw-r--r--freebsd/include/err.h86
-rw-r--r--freebsd/include/ifaddrs.h65
-rw-r--r--freebsd/include/mpool.h113
-rw-r--r--freebsd/include/netconfig.h96
-rw-r--r--freebsd/include/netdb.h297
-rw-r--r--freebsd/include/nlist.h53
-rw-r--r--freebsd/include/nsswitch.h251
-rw-r--r--freebsd/include/res_update.h75
-rw-r--r--freebsd/include/resolv.h502
-rw-r--r--freebsd/include/rpc/auth.h370
-rw-r--r--freebsd/include/rpc/auth_des.h126
-rw-r--r--freebsd/include/rpc/auth_unix.h84
-rw-r--r--freebsd/include/rpc/clnt.h557
-rw-r--r--freebsd/include/rpc/clnt_soc.h106
-rw-r--r--freebsd/include/rpc/clnt_stat.h83
-rw-r--r--freebsd/include/rpc/pmap_clnt.h86
-rw-r--r--freebsd/include/rpc/pmap_prot.h107
-rw-r--r--freebsd/include/rpc/rpc.h108
-rw-r--r--freebsd/include/rpc/rpc_msg.h214
-rw-r--r--freebsd/include/rpc/rpcb_clnt.h85
-rw-r--r--freebsd/include/rpc/rpcb_prot.x554
-rw-r--r--freebsd/include/rpc/rpcent.h67
-rw-r--r--freebsd/include/rpc/svc.h474
-rw-r--r--freebsd/include/rpc/svc_auth.h57
-rw-r--r--freebsd/include/rpc/svc_soc.h116
-rw-r--r--freebsd/include/rpc/xdr.h368
-rw-r--r--freebsd/include/sysexits.h118
-rw-r--r--freebsd/lib/libc/db/btree/bt_close.c180
-rw-r--r--freebsd/lib/libc/db/btree/bt_conv.c214
-rw-r--r--freebsd/lib/libc/db/btree/bt_debug.c318
-rw-r--r--freebsd/lib/libc/db/btree/bt_delete.c637
-rw-r--r--freebsd/lib/libc/db/btree/bt_get.c101
-rw-r--r--freebsd/lib/libc/db/btree/bt_open.c453
-rw-r--r--freebsd/lib/libc/db/btree/bt_overflow.c218
-rw-r--r--freebsd/lib/libc/db/btree/bt_page.c96
-rw-r--r--freebsd/lib/libc/db/btree/bt_put.c316
-rw-r--r--freebsd/lib/libc/db/btree/bt_search.c202
-rw-r--r--freebsd/lib/libc/db/btree/bt_seq.c443
-rw-r--r--freebsd/lib/libc/db/btree/bt_split.c798
-rw-r--r--freebsd/lib/libc/db/btree/bt_utils.c248
-rw-r--r--freebsd/lib/libc/db/btree/btree.h380
-rw-r--r--freebsd/lib/libc/db/btree/extern.h67
-rw-r--r--freebsd/lib/libc/db/db/db.c96
-rw-r--r--freebsd/lib/libc/db/mpool/mpool-compat.c43
-rw-r--r--freebsd/lib/libc/db/mpool/mpool.c495
-rw-r--r--freebsd/lib/libc/db/recno/extern.h51
-rw-r--r--freebsd/lib/libc/db/recno/rec_close.c186
-rw-r--r--freebsd/lib/libc/db/recno/rec_delete.c189
-rw-r--r--freebsd/lib/libc/db/recno/rec_get.c293
-rw-r--r--freebsd/lib/libc/db/recno/rec_open.c240
-rw-r--r--freebsd/lib/libc/db/recno/rec_put.c277
-rw-r--r--freebsd/lib/libc/db/recno/rec_search.c123
-rw-r--r--freebsd/lib/libc/db/recno/rec_seq.c129
-rw-r--r--freebsd/lib/libc/db/recno/rec_utils.c114
-rw-r--r--freebsd/lib/libc/db/recno/recno.h36
-rw-r--r--freebsd/lib/libc/gen/err.c197
-rw-r--r--freebsd/lib/libc/gen/gethostname.c59
-rw-r--r--freebsd/lib/libc/include/isc/eventlib.h206
-rw-r--r--freebsd/lib/libc/include/isc/list.h124
-rw-r--r--freebsd/lib/libc/include/isc/platform.h40
-rw-r--r--freebsd/lib/libc/include/libc_private.h229
-rw-r--r--freebsd/lib/libc/include/namespace.h71
-rw-r--r--freebsd/lib/libc/include/nss_tls.h75
-rw-r--r--freebsd/lib/libc/include/port_after.h (renamed from freebsd/local/opt_altq.h)0
-rw-r--r--freebsd/lib/libc/include/port_before.h41
-rw-r--r--freebsd/lib/libc/include/reentrant.h135
-rw-r--r--freebsd/lib/libc/include/resolv_mt.h47
-rw-r--r--freebsd/lib/libc/include/spinlock.h70
-rw-r--r--freebsd/lib/libc/include/un-namespace.h32
-rw-r--r--freebsd/lib/libc/inet/inet_addr.c215
-rw-r--r--freebsd/lib/libc/inet/inet_cidr_ntop.c263
-rw-r--r--freebsd/lib/libc/inet/inet_cidr_pton.c279
-rw-r--r--freebsd/lib/libc/inet/inet_lnaof.c70
-rw-r--r--freebsd/lib/libc/inet/inet_makeaddr.c73
-rw-r--r--freebsd/lib/libc/inet/inet_net_ntop.c288
-rw-r--r--freebsd/lib/libc/inet/inet_net_pton.c416
-rw-r--r--freebsd/lib/libc/inet/inet_neta.c98
-rw-r--r--freebsd/lib/libc/inet/inet_netof.c69
-rw-r--r--freebsd/lib/libc/inet/inet_network.c111
-rw-r--r--freebsd/lib/libc/inet/inet_ntoa.c78
-rw-r--r--freebsd/lib/libc/inet/inet_ntop.c203
-rw-r--r--freebsd/lib/libc/inet/inet_pton.c225
-rw-r--r--freebsd/lib/libc/inet/nsap_addr.c122
-rw-r--r--freebsd/lib/libc/isc/ev_streams.c318
-rw-r--r--freebsd/lib/libc/isc/ev_timers.c515
-rw-r--r--freebsd/lib/libc/isc/eventlib_p.h290
-rw-r--r--freebsd/lib/libc/nameser/ns_name.c975
-rw-r--r--freebsd/lib/libc/nameser/ns_netint.c60
-rw-r--r--freebsd/lib/libc/nameser/ns_parse.c213
-rw-r--r--freebsd/lib/libc/nameser/ns_print.c910
-rw-r--r--freebsd/lib/libc/nameser/ns_samedomain.c211
-rw-r--r--freebsd/lib/libc/nameser/ns_ttl.c164
-rw-r--r--freebsd/lib/libc/net/base64.c317
-rw-r--r--freebsd/lib/libc/net/ether_addr.c232
-rw-r--r--freebsd/lib/libc/net/gai_strerror.c124
-rw-r--r--freebsd/lib/libc/net/getaddrinfo.c2857
-rw-r--r--freebsd/lib/libc/net/gethostbydns.c787
-rw-r--r--freebsd/lib/libc/net/gethostbyht.c354
-rw-r--r--freebsd/lib/libc/net/gethostbynis.c354
-rw-r--r--freebsd/lib/libc/net/gethostnamadr.c740
-rw-r--r--freebsd/lib/libc/net/getifaddrs.c420
-rw-r--r--freebsd/lib/libc/net/getifmaddrs.c205
-rw-r--r--freebsd/lib/libc/net/getnameinfo.c455
-rw-r--r--freebsd/lib/libc/net/getnetbydns.c467
-rw-r--r--freebsd/lib/libc/net/getnetbyht.c290
-rw-r--r--freebsd/lib/libc/net/getnetbynis.c261
-rw-r--r--freebsd/lib/libc/net/getnetnamadr.c460
-rw-r--r--freebsd/lib/libc/net/getproto.c145
-rw-r--r--freebsd/lib/libc/net/getprotoent.c556
-rw-r--r--freebsd/lib/libc/net/getprotoname.c153
-rw-r--r--freebsd/lib/libc/net/getservent.c1375
-rw-r--r--freebsd/lib/libc/net/if_indextoname.c90
-rw-r--r--freebsd/lib/libc/net/if_nameindex.c149
-rw-r--r--freebsd/lib/libc/net/if_nametoindex.c102
-rw-r--r--freebsd/lib/libc/net/linkaddr.c158
-rw-r--r--freebsd/lib/libc/net/map_v4v6.c121
-rw-r--r--freebsd/lib/libc/net/name6.c1121
-rw-r--r--freebsd/lib/libc/net/netdb_private.h142
-rw-r--r--freebsd/lib/libc/net/nsdispatch.c778
-rw-r--r--freebsd/lib/libc/net/nslexer.l119
-rw-r--r--freebsd/lib/libc/net/nsparser.y184
-rw-r--r--freebsd/lib/libc/net/nss_backends.h43
-rw-r--r--freebsd/lib/libc/net/rcmd.c763
-rw-r--r--freebsd/lib/libc/net/recv.c52
-rw-r--r--freebsd/lib/libc/net/res_config.h6
-rw-r--r--freebsd/lib/libc/net/send.c52
-rw-r--r--freebsd/lib/libc/resolv/h_errno.c46
-rw-r--r--freebsd/lib/libc/resolv/herror.c128
-rw-r--r--freebsd/lib/libc/resolv/mtctxres.c141
-rw-r--r--freebsd/lib/libc/resolv/res_comp.c279
-rw-r--r--freebsd/lib/libc/resolv/res_data.c322
-rw-r--r--freebsd/lib/libc/resolv/res_debug.c1231
-rw-r--r--freebsd/lib/libc/resolv/res_debug.h35
-rw-r--r--freebsd/lib/libc/resolv/res_findzonecut.c727
-rw-r--r--freebsd/lib/libc/resolv/res_init.c874
-rw-r--r--freebsd/lib/libc/resolv/res_mkquery.c305
-rw-r--r--freebsd/lib/libc/resolv/res_mkupdate.c1198
-rw-r--r--freebsd/lib/libc/resolv/res_private.h24
-rw-r--r--freebsd/lib/libc/resolv/res_query.c491
-rw-r--r--freebsd/lib/libc/resolv/res_send.c1187
-rw-r--r--freebsd/lib/libc/resolv/res_state.c91
-rw-r--r--freebsd/lib/libc/resolv/res_update.c227
-rw-r--r--freebsd/lib/libc/stdio/fgetln.c169
-rw-r--r--freebsd/lib/libc/stdio/local.h142
-rw-r--r--freebsd/lib/libc/stdlib/strtonum.c68
-rw-r--r--freebsd/lib/libc/string/strsep.c77
-rw-r--r--freebsd/lib/libipsec/ipsec_dump_policy.c312
-rw-r--r--freebsd/lib/libipsec/ipsec_get_policylen.c54
-rw-r--r--freebsd/lib/libipsec/ipsec_strerror.c94
-rw-r--r--freebsd/lib/libipsec/ipsec_strerror.h63
-rw-r--r--freebsd/lib/libipsec/libpfkey.h86
-rw-r--r--freebsd/lib/libipsec/pfkey.c2132
-rw-r--r--freebsd/lib/libipsec/pfkey_dump.c646
-rw-r--r--freebsd/lib/libipsec/policy_parse.y443
-rw-r--r--freebsd/lib/libipsec/policy_token.l168
-rw-r--r--freebsd/lib/libkvm/kvm.h94
-rw-r--r--freebsd/lib/libmemstat/memstat.c421
-rw-r--r--freebsd/lib/libmemstat/memstat.h178
-rw-r--r--freebsd/lib/libmemstat/memstat_all.c60
-rw-r--r--freebsd/lib/libmemstat/memstat_internal.h124
-rw-r--r--freebsd/lib/libmemstat/memstat_malloc.c417
-rw-r--r--freebsd/lib/libmemstat/memstat_uma.c478
-rw-r--r--freebsd/lib/libutil/expand_number.c100
-rw-r--r--freebsd/lib/libutil/humanize_number.c146
-rw-r--r--freebsd/lib/libutil/libutil.h188
-rw-r--r--freebsd/lib/libutil/trimdomain.c118
-rw-r--r--freebsd/local/bus_if.c273
-rw-r--r--freebsd/local/bus_if.h786
-rw-r--r--freebsd/local/cryptodev_if.c54
-rw-r--r--freebsd/local/cryptodev_if.h69
-rw-r--r--freebsd/local/device_if.c106
-rw-r--r--freebsd/local/device_if.h340
-rw-r--r--freebsd/local/linker_if.h1
-rw-r--r--freebsd/local/miibus_if.c61
-rw-r--r--freebsd/local/miibus_if.h77
-rw-r--r--freebsd/local/miidevs.h376
-rw-r--r--freebsd/local/opt_atalk.h0
-rw-r--r--freebsd/local/opt_bce.h1
-rw-r--r--freebsd/local/opt_bootp.h0
-rw-r--r--freebsd/local/opt_bpf.h0
-rw-r--r--freebsd/local/opt_bus.h0
-rw-r--r--freebsd/local/opt_cam.h0
-rw-r--r--freebsd/local/opt_carp.h0
-rw-r--r--freebsd/local/opt_compat.h0
-rw-r--r--freebsd/local/opt_config.h0
-rw-r--r--freebsd/local/opt_cpu.h0
-rw-r--r--freebsd/local/opt_ddb.h0
-rw-r--r--freebsd/local/opt_device_polling.h0
-rw-r--r--freebsd/local/opt_ef.h0
-rw-r--r--freebsd/local/opt_enc.h1
-rw-r--r--freebsd/local/opt_hwpmc_hooks.h0
-rw-r--r--freebsd/local/opt_inet.h1
-rw-r--r--freebsd/local/opt_inet6.h0
-rw-r--r--freebsd/local/opt_init_path.h0
-rw-r--r--freebsd/local/opt_ipdivert.h0
-rw-r--r--freebsd/local/opt_ipdn.h0
-rw-r--r--freebsd/local/opt_ipfw.h0
-rw-r--r--freebsd/local/opt_ipsec.h0
-rw-r--r--freebsd/local/opt_ipstealth.h0
-rw-r--r--freebsd/local/opt_ipx.h0
-rw-r--r--freebsd/local/opt_kdb.h0
-rw-r--r--freebsd/local/opt_kdtrace.h0
-rw-r--r--freebsd/local/opt_ktrace.h0
-rw-r--r--freebsd/local/opt_mbuf_profiling.h0
-rw-r--r--freebsd/local/opt_mbuf_stress_test.h0
-rw-r--r--freebsd/local/opt_mpath.h0
-rw-r--r--freebsd/local/opt_mrouting.h0
-rw-r--r--freebsd/local/opt_natm.h0
-rw-r--r--freebsd/local/opt_netgraph.h0
-rw-r--r--freebsd/local/opt_ntp.h1
-rw-r--r--freebsd/local/opt_param.h0
-rw-r--r--freebsd/local/opt_pf.h0
-rw-r--r--freebsd/local/opt_posix.h0
-rw-r--r--freebsd/local/opt_printf.h0
-rw-r--r--freebsd/local/opt_route.h0
-rw-r--r--freebsd/local/opt_scsi.h0
-rw-r--r--freebsd/local/opt_sctp.h0
-rw-r--r--freebsd/local/opt_tcpdebug.h0
-rw-r--r--freebsd/local/opt_tdma.h0
-rw-r--r--freebsd/local/opt_usb.h19
-rw-r--r--freebsd/local/opt_vlan.h0
-rw-r--r--freebsd/local/opt_wlan.h0
-rw-r--r--freebsd/local/opt_zero.h0
-rw-r--r--freebsd/local/pci_if.c172
-rw-r--r--freebsd/local/pci_if.h245
-rw-r--r--freebsd/local/pcib_if.c101
-rw-r--r--freebsd/local/pcib_if.h137
-rw-r--r--freebsd/local/usb_if.c29
-rw-r--r--freebsd/local/usb_if.h31
-rw-r--r--freebsd/local/usbdevs.h3433
-rw-r--r--freebsd/local/usbdevs_data.h15530
-rw-r--r--freebsd/local/vnode_if.h1546
-rw-r--r--freebsd/local/vnode_if_newproto.h66
-rw-r--r--freebsd/local/vnode_if_typedef.h170
-rw-r--r--freebsd/machine/elf.h1
-rw-r--r--freebsd/machine/pcb.h1
-rw-r--r--freebsd/machine/resource.h10
-rw-r--r--freebsd/machine/smp.h1
-rw-r--r--freebsd/machine/vm.h1
-rw-r--r--freebsd/netgraph/ng_ipfw.h1
-rw-r--r--freebsd/sbin/dhclient/alloc.c79
-rw-r--r--freebsd/sbin/dhclient/bpf.c416
-rw-r--r--freebsd/sbin/dhclient/clparse.c943
-rw-r--r--freebsd/sbin/dhclient/conflex.c529
-rw-r--r--freebsd/sbin/dhclient/convert.c117
-rw-r--r--freebsd/sbin/dhclient/dhclient.c2669
-rw-r--r--freebsd/sbin/dhclient/dhcp.h183
-rw-r--r--freebsd/sbin/dhclient/dhcpd.h440
-rw-r--r--freebsd/sbin/dhclient/dhctoken.h136
-rw-r--r--freebsd/sbin/dhclient/dispatch.c507
-rw-r--r--freebsd/sbin/dhclient/errwarn.c237
-rw-r--r--freebsd/sbin/dhclient/hash.c122
-rw-r--r--freebsd/sbin/dhclient/inet.c121
-rw-r--r--freebsd/sbin/dhclient/options.c720
-rw-r--r--freebsd/sbin/dhclient/packet.c267
-rw-r--r--freebsd/sbin/dhclient/parse.c580
-rw-r--r--freebsd/sbin/dhclient/privsep.c238
-rw-r--r--freebsd/sbin/dhclient/privsep.h47
-rw-r--r--freebsd/sbin/dhclient/tables.c446
-rw-r--r--freebsd/sbin/dhclient/tree.c59
-rw-r--r--freebsd/sbin/dhclient/tree.h66
-rw-r--r--freebsd/sbin/ifconfig/af_atalk.c182
-rw-r--r--freebsd/sbin/ifconfig/af_inet.c213
-rw-r--r--freebsd/sbin/ifconfig/af_inet6.c560
-rw-r--r--freebsd/sbin/ifconfig/af_link.c133
-rw-r--r--freebsd/sbin/ifconfig/af_nd6.c238
-rw-r--r--freebsd/sbin/ifconfig/ifbridge.c767
-rw-r--r--freebsd/sbin/ifconfig/ifcarp.c204
-rw-r--r--freebsd/sbin/ifconfig/ifclone.c202
-rw-r--r--freebsd/sbin/ifconfig/ifconfig.c1259
-rw-r--r--freebsd/sbin/ifconfig/ifconfig.h166
-rw-r--r--freebsd/sbin/ifconfig/ifgif.c138
-rw-r--r--freebsd/sbin/ifconfig/ifgre.c102
-rw-r--r--freebsd/sbin/ifconfig/ifgroup.c190
-rw-r--r--freebsd/sbin/ifconfig/ifieee80211.c5295
-rw-r--r--freebsd/sbin/ifconfig/iflagg.c198
-rw-r--r--freebsd/sbin/ifconfig/ifmac.c125
-rw-r--r--freebsd/sbin/ifconfig/ifmedia.c844
-rw-r--r--freebsd/sbin/ifconfig/ifpfsync.c220
-rw-r--r--freebsd/sbin/ifconfig/ifvlan.c210
-rw-r--r--freebsd/sbin/ifconfig/regdomain.h126
-rw-r--r--freebsd/sbin/ping/ping.c1810
-rw-r--r--freebsd/sbin/ping6/ping6.c2837
-rw-r--r--freebsd/sbin/route/keywords55
-rw-r--r--freebsd/sbin/route/route.c1733
-rw-r--r--freebsd/security/audit/audit.h1
-rw-r--r--freebsd/sys/_types.h105
-rw-r--r--freebsd/sys/arm/arm/in_cksum.c (renamed from freebsd/arm/arm/in_cksum.c)0
-rw-r--r--freebsd/sys/arm/include/machine/cpufunc.h (renamed from freebsd/arm/include/freebsd/machine/cpufunc.h)0
-rw-r--r--freebsd/sys/arm/include/machine/in_cksum.h (renamed from freebsd/arm/include/freebsd/machine/in_cksum.h)0
-rw-r--r--freebsd/sys/arm/include/machine/legacyvar.h (renamed from freebsd/i386/include/freebsd/machine/legacyvar.h)0
-rw-r--r--freebsd/sys/arm/include/machine/pci_cfgreg.h (renamed from freebsd/i386/include/freebsd/machine/pci_cfgreg.h)0
-rw-r--r--freebsd/sys/arm/pci/pci_bus.c (renamed from freebsd/i386/pci/pci_bus.c)0
-rw-r--r--freebsd/sys/avr/include/machine/in_cksum.h (renamed from freebsd/i386/include/freebsd/machine/in_cksum.h)0
-rw-r--r--freebsd/sys/avr/pci/pci_bus.c71
-rw-r--r--freebsd/sys/bfin/include/machine/in_cksum.h (renamed from freebsd/mips/include/freebsd/machine/in_cksum.h)0
-rw-r--r--freebsd/sys/bio.h1
-rw-r--r--freebsd/sys/bsm/audit.h (renamed from freebsd/bsm/audit.h)0
-rw-r--r--freebsd/sys/bsm/audit_kevents.h (renamed from freebsd/bsm/audit_kevents.h)0
-rw-r--r--freebsd/sys/cam/ata/ata_all.h (renamed from freebsd/cam/ata/ata_all.h)0
-rw-r--r--freebsd/sys/cam/cam.c (renamed from freebsd/cam/cam.c)0
-rw-r--r--freebsd/sys/cam/cam.h (renamed from freebsd/cam/cam.h)0
-rw-r--r--freebsd/sys/cam/cam_ccb.h (renamed from freebsd/cam/cam_ccb.h)0
-rw-r--r--freebsd/sys/cam/cam_debug.h (renamed from freebsd/cam/cam_debug.h)0
-rw-r--r--freebsd/sys/cam/cam_periph.h (renamed from freebsd/cam/cam_periph.h)0
-rw-r--r--freebsd/sys/cam/cam_sim.h (renamed from freebsd/cam/cam_sim.h)0
-rw-r--r--freebsd/sys/cam/cam_xpt.h (renamed from freebsd/cam/cam_xpt.h)0
-rw-r--r--freebsd/sys/cam/cam_xpt_sim.h (renamed from freebsd/cam/cam_xpt_sim.h)0
-rw-r--r--freebsd/sys/cam/scsi/scsi_all.c (renamed from freebsd/cam/scsi/scsi_all.c)0
-rw-r--r--freebsd/sys/cam/scsi/scsi_all.h (renamed from freebsd/cam/scsi/scsi_all.h)0
-rw-r--r--freebsd/sys/cam/scsi/scsi_da.h (renamed from freebsd/cam/scsi/scsi_da.h)0
-rw-r--r--freebsd/sys/contrib/altq/altq/altq.h204
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_cbq.c1187
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_cbq.h221
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_cdnr.c1393
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_cdnr.h335
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_classq.h206
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_hfsc.c2279
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_hfsc.h320
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_priq.c1055
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_priq.h170
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_red.c1503
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_red.h198
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_rio.c855
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_rio.h144
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_rmclass.c1843
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_rmclass.h266
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_rmclass_debug.h112
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_subr.c2042
-rw-r--r--freebsd/sys/contrib/altq/altq/altq_var.h265
-rw-r--r--freebsd/sys/contrib/altq/altq/altqconf.h29
-rw-r--r--freebsd/sys/contrib/altq/altq/if_altq.h191
-rw-r--r--freebsd/sys/contrib/pf/net/if_pflog.c438
-rw-r--r--freebsd/sys/contrib/pf/net/if_pflog.h103
-rw-r--r--freebsd/sys/contrib/pf/net/if_pfsync.c2331
-rw-r--r--freebsd/sys/contrib/pf/net/if_pfsync.h375
-rw-r--r--freebsd/sys/contrib/pf/net/pf.c7771
-rw-r--r--freebsd/sys/contrib/pf/net/pf_if.c950
-rw-r--r--freebsd/sys/contrib/pf/net/pf_ioctl.c3896
-rw-r--r--freebsd/sys/contrib/pf/net/pf_mtag.h82
-rw-r--r--freebsd/sys/contrib/pf/net/pf_norm.c2062
-rw-r--r--freebsd/sys/contrib/pf/net/pf_osfp.c640
-rw-r--r--freebsd/sys/contrib/pf/net/pf_ruleset.c433
-rw-r--r--freebsd/sys/contrib/pf/net/pf_subr.c170
-rw-r--r--freebsd/sys/contrib/pf/net/pf_table.c2363
-rw-r--r--freebsd/sys/contrib/pf/net/pfvar.h1866
-rw-r--r--freebsd/sys/contrib/pf/netinet/in4_cksum.c122
-rw-r--r--freebsd/sys/copyright.h1
-rw-r--r--freebsd/sys/cpuset.h1
-rw-r--r--freebsd/sys/crypto/blowfish/bf_ecb.c (renamed from freebsd/crypto/blowfish/bf_ecb.c)0
-rw-r--r--freebsd/sys/crypto/blowfish/bf_enc.c (renamed from freebsd/crypto/blowfish/bf_enc.c)0
-rw-r--r--freebsd/sys/crypto/blowfish/bf_locl.h (renamed from freebsd/crypto/blowfish/bf_locl.h)0
-rw-r--r--freebsd/sys/crypto/blowfish/bf_pi.h (renamed from freebsd/crypto/blowfish/bf_pi.h)0
-rw-r--r--freebsd/sys/crypto/blowfish/bf_skey.c (renamed from freebsd/crypto/blowfish/bf_skey.c)0
-rw-r--r--freebsd/sys/crypto/blowfish/blowfish.h (renamed from freebsd/crypto/blowfish/blowfish.h)0
-rw-r--r--freebsd/sys/crypto/camellia/camellia-api.c (renamed from freebsd/crypto/camellia/camellia-api.c)0
-rw-r--r--freebsd/sys/crypto/camellia/camellia.c (renamed from freebsd/crypto/camellia/camellia.c)0
-rw-r--r--freebsd/sys/crypto/camellia/camellia.h (renamed from freebsd/crypto/camellia/camellia.h)0
-rw-r--r--freebsd/sys/crypto/des/des.h (renamed from freebsd/crypto/des/des.h)0
-rw-r--r--freebsd/sys/crypto/des/des_ecb.c (renamed from freebsd/crypto/des/des_ecb.c)0
-rw-r--r--freebsd/sys/crypto/des/des_enc.c (renamed from freebsd/crypto/des/des_enc.c)0
-rw-r--r--freebsd/sys/crypto/des/des_locl.h (renamed from freebsd/crypto/des/des_locl.h)0
-rw-r--r--freebsd/sys/crypto/des/des_setkey.c (renamed from freebsd/crypto/des/des_setkey.c)0
-rw-r--r--freebsd/sys/crypto/des/podd.h (renamed from freebsd/crypto/des/podd.h)0
-rw-r--r--freebsd/sys/crypto/des/sk.h (renamed from freebsd/crypto/des/sk.h)0
-rw-r--r--freebsd/sys/crypto/des/spr.h (renamed from freebsd/crypto/des/spr.h)0
-rw-r--r--freebsd/sys/crypto/rc4/rc4.c (renamed from freebsd/crypto/rc4/rc4.c)0
-rw-r--r--freebsd/sys/crypto/rc4/rc4.h (renamed from freebsd/crypto/rc4/rc4.h)0
-rw-r--r--freebsd/sys/crypto/rijndael/rijndael-alg-fst.c (renamed from freebsd/crypto/rijndael/rijndael-alg-fst.c)0
-rw-r--r--freebsd/sys/crypto/rijndael/rijndael-api-fst.c (renamed from freebsd/crypto/rijndael/rijndael-api-fst.c)0
-rw-r--r--freebsd/sys/crypto/rijndael/rijndael-api-fst.h (renamed from freebsd/crypto/rijndael/rijndael-api-fst.h)0
-rw-r--r--freebsd/sys/crypto/rijndael/rijndael-api.c (renamed from freebsd/crypto/rijndael/rijndael-api.c)0
-rw-r--r--freebsd/sys/crypto/rijndael/rijndael.h (renamed from freebsd/crypto/rijndael/rijndael.h)0
-rw-r--r--freebsd/sys/crypto/rijndael/rijndael_local.h (renamed from freebsd/crypto/rijndael/rijndael_local.h)0
-rw-r--r--freebsd/sys/crypto/sha1.c (renamed from freebsd/crypto/sha1.c)0
-rw-r--r--freebsd/sys/crypto/sha1.h (renamed from freebsd/crypto/sha1.h)0
-rw-r--r--freebsd/sys/crypto/sha2/sha2.c (renamed from freebsd/crypto/sha2/sha2.c)0
-rw-r--r--freebsd/sys/crypto/sha2/sha2.h (renamed from freebsd/crypto/sha2/sha2.h)0
-rw-r--r--freebsd/sys/dev/bce/if_bce.c (renamed from freebsd/dev/bce/if_bce.c)0
-rw-r--r--freebsd/sys/dev/bce/if_bcefw.h (renamed from freebsd/dev/bce/if_bcefw.h)0
-rw-r--r--freebsd/sys/dev/bce/if_bcereg.h (renamed from freebsd/dev/bce/if_bcereg.h)0
-rw-r--r--freebsd/sys/dev/bfe/if_bfe.c (renamed from freebsd/dev/bfe/if_bfe.c)0
-rw-r--r--freebsd/sys/dev/bfe/if_bfereg.h (renamed from freebsd/dev/bfe/if_bfereg.h)0
-rw-r--r--freebsd/sys/dev/bge/if_bge.c (renamed from freebsd/dev/bge/if_bge.c)0
-rw-r--r--freebsd/sys/dev/bge/if_bgereg.h (renamed from freebsd/dev/bge/if_bgereg.h)0
-rw-r--r--freebsd/sys/dev/dc/dcphy.c (renamed from freebsd/dev/dc/dcphy.c)0
-rw-r--r--freebsd/sys/dev/dc/if_dc.c (renamed from freebsd/dev/dc/if_dc.c)0
-rw-r--r--freebsd/sys/dev/dc/if_dcreg.h (renamed from freebsd/dev/dc/if_dcreg.h)0
-rw-r--r--freebsd/sys/dev/dc/pnphy.c (renamed from freebsd/dev/dc/pnphy.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_80003es2lan.c (renamed from freebsd/dev/e1000/e1000_80003es2lan.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_80003es2lan.h (renamed from freebsd/dev/e1000/e1000_80003es2lan.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82540.c (renamed from freebsd/dev/e1000/e1000_82540.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82541.c (renamed from freebsd/dev/e1000/e1000_82541.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82541.h (renamed from freebsd/dev/e1000/e1000_82541.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82542.c (renamed from freebsd/dev/e1000/e1000_82542.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82543.c (renamed from freebsd/dev/e1000/e1000_82543.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82543.h (renamed from freebsd/dev/e1000/e1000_82543.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82571.c (renamed from freebsd/dev/e1000/e1000_82571.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82571.h (renamed from freebsd/dev/e1000/e1000_82571.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82575.c (renamed from freebsd/dev/e1000/e1000_82575.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_82575.h (renamed from freebsd/dev/e1000/e1000_82575.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_api.c (renamed from freebsd/dev/e1000/e1000_api.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_api.h (renamed from freebsd/dev/e1000/e1000_api.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_defines.h (renamed from freebsd/dev/e1000/e1000_defines.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_hw.h (renamed from freebsd/dev/e1000/e1000_hw.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_ich8lan.c (renamed from freebsd/dev/e1000/e1000_ich8lan.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_ich8lan.h (renamed from freebsd/dev/e1000/e1000_ich8lan.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_mac.c (renamed from freebsd/dev/e1000/e1000_mac.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_mac.h (renamed from freebsd/dev/e1000/e1000_mac.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_manage.c (renamed from freebsd/dev/e1000/e1000_manage.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_manage.h (renamed from freebsd/dev/e1000/e1000_manage.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_mbx.c (renamed from freebsd/dev/e1000/e1000_mbx.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_mbx.h (renamed from freebsd/dev/e1000/e1000_mbx.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_nvm.c (renamed from freebsd/dev/e1000/e1000_nvm.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_nvm.h (renamed from freebsd/dev/e1000/e1000_nvm.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_osdep.c (renamed from freebsd/dev/e1000/e1000_osdep.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_osdep.h (renamed from freebsd/dev/e1000/e1000_osdep.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_phy.c (renamed from freebsd/dev/e1000/e1000_phy.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_phy.h (renamed from freebsd/dev/e1000/e1000_phy.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_regs.h (renamed from freebsd/dev/e1000/e1000_regs.h)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_vf.c (renamed from freebsd/dev/e1000/e1000_vf.c)0
-rw-r--r--freebsd/sys/dev/e1000/e1000_vf.h (renamed from freebsd/dev/e1000/e1000_vf.h)0
-rw-r--r--freebsd/sys/dev/e1000/if_em.c (renamed from freebsd/dev/e1000/if_em.c)0
-rw-r--r--freebsd/sys/dev/e1000/if_em.h (renamed from freebsd/dev/e1000/if_em.h)0
-rw-r--r--freebsd/sys/dev/e1000/if_igb.c (renamed from freebsd/dev/e1000/if_igb.c)0
-rw-r--r--freebsd/sys/dev/e1000/if_igb.h (renamed from freebsd/dev/e1000/if_igb.h)0
-rw-r--r--freebsd/sys/dev/e1000/if_lem.c (renamed from freebsd/dev/e1000/if_lem.c)0
-rw-r--r--freebsd/sys/dev/e1000/if_lem.h (renamed from freebsd/dev/e1000/if_lem.h)0
-rw-r--r--freebsd/sys/dev/fxp/if_fxp.c (renamed from freebsd/dev/fxp/if_fxp.c)0
-rw-r--r--freebsd/sys/dev/fxp/if_fxpreg.h (renamed from freebsd/dev/fxp/if_fxpreg.h)0
-rw-r--r--freebsd/sys/dev/fxp/if_fxpvar.h (renamed from freebsd/dev/fxp/if_fxpvar.h)0
-rw-r--r--freebsd/sys/dev/fxp/rcvbundl.h (renamed from freebsd/dev/fxp/rcvbundl.h)0
-rw-r--r--freebsd/sys/dev/led/led.c (renamed from freebsd/dev/led/led.c)0
-rw-r--r--freebsd/sys/dev/led/led.h (renamed from freebsd/dev/led/led.h)0
-rw-r--r--freebsd/sys/dev/mii/brgphy.c (renamed from freebsd/dev/mii/brgphy.c)0
-rw-r--r--freebsd/sys/dev/mii/brgphyreg.h (renamed from freebsd/dev/mii/brgphyreg.h)0
-rw-r--r--freebsd/sys/dev/mii/icsphy.c (renamed from freebsd/dev/mii/icsphy.c)0
-rw-r--r--freebsd/sys/dev/mii/icsphyreg.h (renamed from freebsd/dev/mii/icsphyreg.h)0
-rw-r--r--freebsd/sys/dev/mii/mii.c (renamed from freebsd/dev/mii/mii.c)0
-rw-r--r--freebsd/sys/dev/mii/mii.h (renamed from freebsd/dev/mii/mii.h)0
-rw-r--r--freebsd/sys/dev/mii/mii_physubr.c (renamed from freebsd/dev/mii/mii_physubr.c)0
-rw-r--r--freebsd/sys/dev/mii/miivar.h (renamed from freebsd/dev/mii/miivar.h)0
-rw-r--r--freebsd/sys/dev/pci/pci.c (renamed from freebsd/dev/pci/pci.c)0
-rw-r--r--freebsd/sys/dev/pci/pci_pci.c (renamed from freebsd/dev/pci/pci_pci.c)0
-rw-r--r--freebsd/sys/dev/pci/pci_private.h (renamed from freebsd/dev/pci/pci_private.h)0
-rw-r--r--freebsd/sys/dev/pci/pci_user.c (renamed from freebsd/dev/pci/pci_user.c)0
-rw-r--r--freebsd/sys/dev/pci/pcib_private.h (renamed from freebsd/dev/pci/pcib_private.h)0
-rw-r--r--freebsd/sys/dev/pci/pcireg.h (renamed from freebsd/dev/pci/pcireg.h)0
-rw-r--r--freebsd/sys/dev/pci/pcivar.h (renamed from freebsd/dev/pci/pcivar.h)0
-rw-r--r--freebsd/sys/dev/random/harvest.c (renamed from freebsd/dev/random/harvest.c)0
-rw-r--r--freebsd/sys/dev/random/randomdev_soft.h (renamed from freebsd/dev/random/randomdev_soft.h)0
-rw-r--r--freebsd/sys/dev/re/if_re.c (renamed from freebsd/dev/re/if_re.c)0
-rw-r--r--freebsd/sys/dev/smc/if_smc.c (renamed from freebsd/dev/smc/if_smc.c)0
-rw-r--r--freebsd/sys/dev/smc/if_smcreg.h (renamed from freebsd/dev/smc/if_smcreg.h)0
-rw-r--r--freebsd/sys/dev/smc/if_smcvar.h (renamed from freebsd/dev/smc/if_smcvar.h)0
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.c (renamed from freebsd/dev/usb/controller/ehci.c)0
-rw-r--r--freebsd/sys/dev/usb/controller/ehci.h (renamed from freebsd/dev/usb/controller/ehci.h)0
-rw-r--r--freebsd/sys/dev/usb/controller/ehcireg.h (renamed from freebsd/dev/usb/controller/ehcireg.h)0
-rw-r--r--freebsd/sys/dev/usb/controller/ohci.c (renamed from freebsd/dev/usb/controller/ohci.c)0
-rw-r--r--freebsd/sys/dev/usb/controller/ohci.h (renamed from freebsd/dev/usb/controller/ohci.h)0
-rw-r--r--freebsd/sys/dev/usb/controller/ohcireg.h (renamed from freebsd/dev/usb/controller/ohcireg.h)0
-rw-r--r--freebsd/sys/dev/usb/controller/usb_controller.c (renamed from freebsd/dev/usb/controller/usb_controller.c)0
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.c (renamed from freebsd/dev/usb/quirk/usb_quirk.c)0
-rw-r--r--freebsd/sys/dev/usb/quirk/usb_quirk.h (renamed from freebsd/dev/usb/quirk/usb_quirk.h)0
-rw-r--r--freebsd/sys/dev/usb/storage/umass.c (renamed from freebsd/dev/usb/storage/umass.c)0
-rw-r--r--freebsd/sys/dev/usb/ufm_ioctl.h (renamed from freebsd/dev/usb/ufm_ioctl.h)0
-rw-r--r--freebsd/sys/dev/usb/usb.h (renamed from freebsd/dev/usb/usb.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_bus.h (renamed from freebsd/dev/usb/usb_bus.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_busdma.c (renamed from freebsd/dev/usb/usb_busdma.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_busdma.h (renamed from freebsd/dev/usb/usb_busdma.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_cdc.h (renamed from freebsd/dev/usb/usb_cdc.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_controller.h (renamed from freebsd/dev/usb/usb_controller.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_core.c (renamed from freebsd/dev/usb/usb_core.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_core.h (renamed from freebsd/dev/usb/usb_core.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_debug.c (renamed from freebsd/dev/usb/usb_debug.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_debug.h (renamed from freebsd/dev/usb/usb_debug.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_dev.c (renamed from freebsd/dev/usb/usb_dev.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_dev.h (renamed from freebsd/dev/usb/usb_dev.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_device.c (renamed from freebsd/dev/usb/usb_device.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_device.h (renamed from freebsd/dev/usb/usb_device.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_dynamic.c (renamed from freebsd/dev/usb/usb_dynamic.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_dynamic.h (renamed from freebsd/dev/usb/usb_dynamic.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_endian.h (renamed from freebsd/dev/usb/usb_endian.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_error.c (renamed from freebsd/dev/usb/usb_error.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_freebsd.h (renamed from freebsd/dev/usb/usb_freebsd.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_generic.c (renamed from freebsd/dev/usb/usb_generic.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_generic.h (renamed from freebsd/dev/usb/usb_generic.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_handle_request.c (renamed from freebsd/dev/usb/usb_handle_request.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_hid.c (renamed from freebsd/dev/usb/usb_hid.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_hub.c (renamed from freebsd/dev/usb/usb_hub.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_hub.h (renamed from freebsd/dev/usb/usb_hub.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_ioctl.h (renamed from freebsd/dev/usb/usb_ioctl.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_lookup.c (renamed from freebsd/dev/usb/usb_lookup.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_mbuf.c (renamed from freebsd/dev/usb/usb_mbuf.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_mbuf.h (renamed from freebsd/dev/usb/usb_mbuf.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_msctest.c (renamed from freebsd/dev/usb/usb_msctest.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_msctest.h (renamed from freebsd/dev/usb/usb_msctest.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_parse.c (renamed from freebsd/dev/usb/usb_parse.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_process.c (renamed from freebsd/dev/usb/usb_process.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_process.h (renamed from freebsd/dev/usb/usb_process.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_request.c (renamed from freebsd/dev/usb/usb_request.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_request.h (renamed from freebsd/dev/usb/usb_request.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_transfer.c (renamed from freebsd/dev/usb/usb_transfer.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_transfer.h (renamed from freebsd/dev/usb/usb_transfer.h)0
-rw-r--r--freebsd/sys/dev/usb/usb_util.c (renamed from freebsd/dev/usb/usb_util.c)0
-rw-r--r--freebsd/sys/dev/usb/usb_util.h (renamed from freebsd/dev/usb/usb_util.h)0
-rw-r--r--freebsd/sys/dev/usb/usbdi.h (renamed from freebsd/dev/usb/usbdi.h)0
-rw-r--r--freebsd/sys/dev/usb/usbdi_util.h (renamed from freebsd/dev/usb/usbdi_util.h)0
-rw-r--r--freebsd/sys/dev/usb/usbhid.h (renamed from freebsd/dev/usb/usbhid.h)0
-rw-r--r--freebsd/sys/errno.h194
-rw-r--r--freebsd/sys/exec.h1
-rw-r--r--freebsd/sys/fail.h1
-rw-r--r--freebsd/sys/fs/devfs/devfs_int.h (renamed from freebsd/fs/devfs/devfs_int.h)0
-rw-r--r--freebsd/sys/h8300/include/machine/in_cksum.h (renamed from freebsd/powerpc/include/freebsd/machine/in_cksum.h)0
-rw-r--r--freebsd/sys/i386/i386/in_cksum.c (renamed from freebsd/i386/i386/in_cksum.c)0
-rw-r--r--freebsd/sys/i386/i386/legacy.c (renamed from freebsd/i386/i386/legacy.c)0
-rw-r--r--freebsd/sys/i386/include/machine/cpufunc.h (renamed from freebsd/i386/include/freebsd/machine/cpufunc.h)0
-rw-r--r--freebsd/sys/i386/include/machine/in_cksum.h (renamed from freebsd/sparc64/include/freebsd/machine/in_cksum.h)0
-rw-r--r--freebsd/sys/i386/include/machine/intr_machdep.h (renamed from freebsd/i386/include/freebsd/machine/intr_machdep.h)0
-rw-r--r--freebsd/sys/i386/include/machine/md_var.h (renamed from freebsd/i386/include/freebsd/machine/md_var.h)0
-rw-r--r--freebsd/sys/i386/include/machine/specialreg.h (renamed from freebsd/i386/include/freebsd/machine/specialreg.h)0
-rw-r--r--freebsd/sys/isa/isavar.h (renamed from freebsd/isa/isavar.h)0
-rw-r--r--freebsd/sys/isa/pnpvar.h (renamed from freebsd/isa/pnpvar.h)0
-rw-r--r--freebsd/sys/kern/init_main.c (renamed from freebsd/kern/init_main.c)0
-rw-r--r--freebsd/sys/kern/kern_descrip.c (renamed from freebsd/kern/kern_descrip.c)0
-rw-r--r--freebsd/sys/kern/kern_environment.c (renamed from freebsd/kern/kern_environment.c)0
-rw-r--r--freebsd/sys/kern/kern_event.c (renamed from freebsd/kern/kern_event.c)0
-rw-r--r--freebsd/sys/kern/kern_intr.c (renamed from freebsd/kern/kern_intr.c)0
-rw-r--r--freebsd/sys/kern/kern_linker.c (renamed from freebsd/kern/kern_linker.c)0
-rw-r--r--freebsd/sys/kern/kern_mbuf.c (renamed from freebsd/kern/kern_mbuf.c)0
-rw-r--r--freebsd/sys/kern/kern_mib.c (renamed from freebsd/kern/kern_mib.c)0
-rw-r--r--freebsd/sys/kern/kern_module.c (renamed from freebsd/kern/kern_module.c)0
-rw-r--r--freebsd/sys/kern/kern_mtxpool.c (renamed from freebsd/kern/kern_mtxpool.c)0
-rw-r--r--freebsd/sys/kern/kern_ntptime.c (renamed from freebsd/kern/kern_ntptime.c)0
-rw-r--r--freebsd/sys/kern/kern_proc.c (renamed from freebsd/kern/kern_proc.c)0
-rw-r--r--freebsd/sys/kern/kern_prot.c (renamed from freebsd/kern/kern_prot.c)0
-rw-r--r--freebsd/sys/kern/kern_resource.c (renamed from freebsd/kern/kern_resource.c)0
-rw-r--r--freebsd/sys/kern/kern_subr.c (renamed from freebsd/kern/kern_subr.c)0
-rw-r--r--freebsd/sys/kern/kern_sysctl.c (renamed from freebsd/kern/kern_sysctl.c)0
-rw-r--r--freebsd/sys/kern/kern_tc.c (renamed from freebsd/kern/kern_tc.c)0
-rw-r--r--freebsd/sys/kern/kern_time.c (renamed from freebsd/kern/kern_time.c)0
-rw-r--r--freebsd/sys/kern/kern_timeout.c (renamed from freebsd/kern/kern_timeout.c)0
-rw-r--r--freebsd/sys/kern/subr_bufring.c (renamed from freebsd/kern/subr_bufring.c)0
-rw-r--r--freebsd/sys/kern/subr_bus.c (renamed from freebsd/kern/subr_bus.c)0
-rw-r--r--freebsd/sys/kern/subr_eventhandler.c (renamed from freebsd/kern/subr_eventhandler.c)0
-rw-r--r--freebsd/sys/kern/subr_hints.c (renamed from freebsd/kern/subr_hints.c)0
-rw-r--r--freebsd/sys/kern/subr_kobj.c (renamed from freebsd/kern/subr_kobj.c)0
-rw-r--r--freebsd/sys/kern/subr_module.c (renamed from freebsd/kern/subr_module.c)0
-rw-r--r--freebsd/sys/kern/subr_rman.c (renamed from freebsd/kern/subr_rman.c)0
-rw-r--r--freebsd/sys/kern/subr_sbuf.c (renamed from freebsd/kern/subr_sbuf.c)0
-rw-r--r--freebsd/sys/kern/subr_unit.c (renamed from freebsd/kern/subr_unit.c)0
-rw-r--r--freebsd/sys/kern/sys_generic.c (renamed from freebsd/kern/sys_generic.c)0
-rw-r--r--freebsd/sys/kern/uipc_accf.c (renamed from freebsd/kern/uipc_accf.c)0
-rw-r--r--freebsd/sys/kern/uipc_domain.c (renamed from freebsd/kern/uipc_domain.c)0
-rw-r--r--freebsd/sys/kern/uipc_mbuf.c (renamed from freebsd/kern/uipc_mbuf.c)0
-rw-r--r--freebsd/sys/kern/uipc_mbuf2.c (renamed from freebsd/kern/uipc_mbuf2.c)0
-rw-r--r--freebsd/sys/kern/uipc_sockbuf.c (renamed from freebsd/kern/uipc_sockbuf.c)0
-rw-r--r--freebsd/sys/kern/uipc_socket.c (renamed from freebsd/kern/uipc_socket.c)0
-rw-r--r--freebsd/sys/libkern/arc4random.c (renamed from freebsd/libkern/arc4random.c)0
-rw-r--r--freebsd/sys/libkern/fls.c (renamed from freebsd/libkern/fls.c)0
-rw-r--r--freebsd/sys/libkern/inet_ntoa.c (renamed from freebsd/libkern/inet_ntoa.c)0
-rw-r--r--freebsd/sys/libkern/random.c (renamed from freebsd/libkern/random.c)0
-rw-r--r--freebsd/sys/lock.h319
-rw-r--r--freebsd/sys/mips/include/machine/cpufunc.h (renamed from freebsd/mips/include/freebsd/machine/cpufunc.h)0
-rw-r--r--freebsd/sys/mips/include/machine/cpuregs.h (renamed from freebsd/mips/include/freebsd/machine/cpuregs.h)0
-rw-r--r--freebsd/sys/mips/mips/in_cksum.c (renamed from freebsd/mips/mips/in_cksum.c)0
-rw-r--r--freebsd/sys/namei.h1
-rw-r--r--freebsd/sys/net/bpf.c (renamed from freebsd/net/bpf.c)0
-rw-r--r--freebsd/sys/net/bpf.h (renamed from freebsd/net/bpf.h)0
-rw-r--r--freebsd/sys/net/bpf_buffer.c (renamed from freebsd/net/bpf_buffer.c)0
-rw-r--r--freebsd/sys/net/bpf_buffer.h (renamed from freebsd/net/bpf_buffer.h)0
-rw-r--r--freebsd/sys/net/bpf_filter.c (renamed from freebsd/net/bpf_filter.c)0
-rw-r--r--freebsd/sys/net/bpf_jitter.c (renamed from freebsd/net/bpf_jitter.c)0
-rw-r--r--freebsd/sys/net/bpf_jitter.h (renamed from freebsd/net/bpf_jitter.h)0
-rw-r--r--freebsd/sys/net/bpf_zerocopy.h (renamed from freebsd/net/bpf_zerocopy.h)0
-rw-r--r--freebsd/sys/net/bpfdesc.h (renamed from freebsd/net/bpfdesc.h)0
-rw-r--r--freebsd/sys/net/bridgestp.c (renamed from freebsd/net/bridgestp.c)0
-rw-r--r--freebsd/sys/net/bridgestp.h (renamed from freebsd/net/bridgestp.h)0
-rw-r--r--freebsd/sys/net/ethernet.h2
-rw-r--r--freebsd/sys/net/fddi.h (renamed from freebsd/net/fddi.h)0
-rw-r--r--freebsd/sys/net/firewire.h (renamed from freebsd/net/firewire.h)0
-rw-r--r--freebsd/sys/net/flowtable.h (renamed from freebsd/net/flowtable.h)0
-rw-r--r--freebsd/sys/net/ieee8023ad_lacp.c (renamed from freebsd/net/ieee8023ad_lacp.c)0
-rw-r--r--freebsd/sys/net/ieee8023ad_lacp.h (renamed from freebsd/net/ieee8023ad_lacp.h)0
-rw-r--r--freebsd/sys/net/if.c (renamed from freebsd/net/if.c)0
-rw-r--r--freebsd/sys/net/if.h2
-rw-r--r--freebsd/sys/net/if_arc.h (renamed from freebsd/net/if_arc.h)0
-rw-r--r--freebsd/sys/net/if_arcsubr.c (renamed from freebsd/net/if_arcsubr.c)0
-rw-r--r--freebsd/sys/net/if_arp.h2
-rw-r--r--freebsd/sys/net/if_atm.h (renamed from freebsd/net/if_atm.h)0
-rw-r--r--freebsd/sys/net/if_atmsubr.c (renamed from freebsd/net/if_atmsubr.c)0
-rw-r--r--freebsd/sys/net/if_bridge.c (renamed from freebsd/net/if_bridge.c)0
-rw-r--r--freebsd/sys/net/if_bridgevar.h (renamed from freebsd/net/if_bridgevar.h)0
-rw-r--r--freebsd/sys/net/if_clone.c (renamed from freebsd/net/if_clone.c)0
-rw-r--r--freebsd/sys/net/if_clone.h (renamed from freebsd/net/if_clone.h)0
-rw-r--r--freebsd/sys/net/if_dead.c (renamed from freebsd/net/if_dead.c)0
-rw-r--r--freebsd/sys/net/if_disc.c (renamed from freebsd/net/if_disc.c)0
-rw-r--r--freebsd/sys/net/if_dl.h2
-rw-r--r--freebsd/sys/net/if_edsc.c (renamed from freebsd/net/if_edsc.c)0
-rw-r--r--freebsd/sys/net/if_ef.c (renamed from freebsd/net/if_ef.c)0
-rw-r--r--freebsd/sys/net/if_enc.c (renamed from freebsd/net/if_enc.c)0
-rw-r--r--freebsd/sys/net/if_enc.h (renamed from freebsd/net/if_enc.h)0
-rw-r--r--freebsd/sys/net/if_epair.c (renamed from freebsd/net/if_epair.c)0
-rw-r--r--freebsd/sys/net/if_ethersubr.c (renamed from freebsd/net/if_ethersubr.c)0
-rw-r--r--freebsd/sys/net/if_faith.c (renamed from freebsd/net/if_faith.c)0
-rw-r--r--freebsd/sys/net/if_fddisubr.c (renamed from freebsd/net/if_fddisubr.c)0
-rw-r--r--freebsd/sys/net/if_fwsubr.c (renamed from freebsd/net/if_fwsubr.c)0
-rw-r--r--freebsd/sys/net/if_gif.c (renamed from freebsd/net/if_gif.c)0
-rw-r--r--freebsd/sys/net/if_gif.h (renamed from freebsd/net/if_gif.h)0
-rw-r--r--freebsd/sys/net/if_gre.c (renamed from freebsd/net/if_gre.c)0
-rw-r--r--freebsd/sys/net/if_gre.h (renamed from freebsd/net/if_gre.h)0
-rw-r--r--freebsd/sys/net/if_iso88025subr.c (renamed from freebsd/net/if_iso88025subr.c)0
-rw-r--r--freebsd/sys/net/if_lagg.c (renamed from freebsd/net/if_lagg.c)0
-rw-r--r--freebsd/sys/net/if_lagg.h (renamed from freebsd/net/if_lagg.h)0
-rw-r--r--freebsd/sys/net/if_llatbl.c (renamed from freebsd/net/if_llatbl.c)0
-rw-r--r--freebsd/sys/net/if_llatbl.h (renamed from freebsd/net/if_llatbl.h)0
-rw-r--r--freebsd/sys/net/if_llc.h (renamed from freebsd/net/if_llc.h)0
-rw-r--r--freebsd/sys/net/if_loop.c (renamed from freebsd/net/if_loop.c)0
-rw-r--r--freebsd/sys/net/if_media.c (renamed from freebsd/net/if_media.c)0
-rw-r--r--freebsd/sys/net/if_media.h (renamed from freebsd/net/if_media.h)0
-rw-r--r--freebsd/sys/net/if_mib.c (renamed from freebsd/net/if_mib.c)0
-rw-r--r--freebsd/sys/net/if_mib.h (renamed from freebsd/net/if_mib.h)0
-rw-r--r--freebsd/sys/net/if_sppp.h (renamed from freebsd/net/if_sppp.h)0
-rw-r--r--freebsd/sys/net/if_spppfr.c (renamed from freebsd/net/if_spppfr.c)0
-rw-r--r--freebsd/sys/net/if_spppsubr.c (renamed from freebsd/net/if_spppsubr.c)0
-rw-r--r--freebsd/sys/net/if_stf.c (renamed from freebsd/net/if_stf.c)0
-rw-r--r--freebsd/sys/net/if_stf.h (renamed from freebsd/net/if_stf.h)0
-rw-r--r--freebsd/sys/net/if_tap.c (renamed from freebsd/net/if_tap.c)0
-rw-r--r--freebsd/sys/net/if_tap.h (renamed from freebsd/net/if_tap.h)0
-rw-r--r--freebsd/sys/net/if_tapvar.h (renamed from freebsd/net/if_tapvar.h)0
-rw-r--r--freebsd/sys/net/if_tun.c (renamed from freebsd/net/if_tun.c)0
-rw-r--r--freebsd/sys/net/if_tun.h (renamed from freebsd/net/if_tun.h)0
-rw-r--r--freebsd/sys/net/if_types.h2
-rw-r--r--freebsd/sys/net/if_var.h (renamed from freebsd/net/if_var.h)0
-rw-r--r--freebsd/sys/net/if_vlan.c (renamed from freebsd/net/if_vlan.c)0
-rw-r--r--freebsd/sys/net/if_vlan_var.h (renamed from freebsd/net/if_vlan_var.h)0
-rw-r--r--freebsd/sys/net/iso88025.h (renamed from freebsd/net/iso88025.h)0
-rw-r--r--freebsd/sys/net/netisr.c (renamed from freebsd/net/netisr.c)0
-rw-r--r--freebsd/sys/net/netisr.h (renamed from freebsd/net/netisr.h)0
-rw-r--r--freebsd/sys/net/pfil.c (renamed from freebsd/net/pfil.c)0
-rw-r--r--freebsd/sys/net/pfil.h (renamed from freebsd/net/pfil.h)0
-rw-r--r--freebsd/sys/net/pfkeyv2.h (renamed from freebsd/net/pfkeyv2.h)0
-rw-r--r--freebsd/sys/net/ppp_defs.h (renamed from freebsd/net/ppp_defs.h)0
-rw-r--r--freebsd/sys/net/radix.c (renamed from freebsd/net/radix.c)0
-rw-r--r--freebsd/sys/net/radix.h (renamed from freebsd/net/radix.h)0
-rw-r--r--freebsd/sys/net/radix_mpath.c (renamed from freebsd/net/radix_mpath.c)0
-rw-r--r--freebsd/sys/net/radix_mpath.h (renamed from freebsd/net/radix_mpath.h)0
-rw-r--r--freebsd/sys/net/raw_cb.c (renamed from freebsd/net/raw_cb.c)0
-rw-r--r--freebsd/sys/net/raw_cb.h (renamed from freebsd/net/raw_cb.h)0
-rw-r--r--freebsd/sys/net/raw_usrreq.c (renamed from freebsd/net/raw_usrreq.c)0
-rw-r--r--freebsd/sys/net/route.c (renamed from freebsd/net/route.c)0
-rw-r--r--freebsd/sys/net/route.h2
-rw-r--r--freebsd/sys/net/rtsock.c (renamed from freebsd/net/rtsock.c)0
-rw-r--r--freebsd/sys/net/slcompress.c (renamed from freebsd/net/slcompress.c)0
-rw-r--r--freebsd/sys/net/slcompress.h (renamed from freebsd/net/slcompress.h)0
-rw-r--r--freebsd/sys/net/vnet.h (renamed from freebsd/net/vnet.h)0
-rw-r--r--freebsd/sys/net/zlib.c (renamed from freebsd/net/zlib.c)0
-rw-r--r--freebsd/sys/net/zlib.h (renamed from freebsd/net/zlib.h)0
-rw-r--r--freebsd/sys/net80211/_ieee80211.h (renamed from freebsd/net80211/_ieee80211.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211.c (renamed from freebsd/net80211/ieee80211.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211.h (renamed from freebsd/net80211/ieee80211.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_acl.c (renamed from freebsd/net80211/ieee80211_acl.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_action.c (renamed from freebsd/net80211/ieee80211_action.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_action.h (renamed from freebsd/net80211/ieee80211_action.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_adhoc.c (renamed from freebsd/net80211/ieee80211_adhoc.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_adhoc.h (renamed from freebsd/net80211/ieee80211_adhoc.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ageq.c (renamed from freebsd/net80211/ieee80211_ageq.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ageq.h (renamed from freebsd/net80211/ieee80211_ageq.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_amrr.c (renamed from freebsd/net80211/ieee80211_amrr.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_amrr.h (renamed from freebsd/net80211/ieee80211_amrr.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_crypto.c (renamed from freebsd/net80211/ieee80211_crypto.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_crypto.h (renamed from freebsd/net80211/ieee80211_crypto.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_crypto_ccmp.c (renamed from freebsd/net80211/ieee80211_crypto_ccmp.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_crypto_none.c (renamed from freebsd/net80211/ieee80211_crypto_none.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_crypto_tkip.c (renamed from freebsd/net80211/ieee80211_crypto_tkip.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_crypto_wep.c (renamed from freebsd/net80211/ieee80211_crypto_wep.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ddb.c (renamed from freebsd/net80211/ieee80211_ddb.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_dfs.c (renamed from freebsd/net80211/ieee80211_dfs.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_dfs.h (renamed from freebsd/net80211/ieee80211_dfs.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_freebsd.c (renamed from freebsd/net80211/ieee80211_freebsd.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_freebsd.h (renamed from freebsd/net80211/ieee80211_freebsd.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_hostap.c (renamed from freebsd/net80211/ieee80211_hostap.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_hostap.h (renamed from freebsd/net80211/ieee80211_hostap.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ht.c (renamed from freebsd/net80211/ieee80211_ht.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ht.h (renamed from freebsd/net80211/ieee80211_ht.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_hwmp.c (renamed from freebsd/net80211/ieee80211_hwmp.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_input.c (renamed from freebsd/net80211/ieee80211_input.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_input.h (renamed from freebsd/net80211/ieee80211_input.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ioctl.c (renamed from freebsd/net80211/ieee80211_ioctl.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ioctl.h (renamed from freebsd/net80211/ieee80211_ioctl.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_mesh.c (renamed from freebsd/net80211/ieee80211_mesh.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_mesh.h (renamed from freebsd/net80211/ieee80211_mesh.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_monitor.c (renamed from freebsd/net80211/ieee80211_monitor.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_monitor.h (renamed from freebsd/net80211/ieee80211_monitor.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_node.c (renamed from freebsd/net80211/ieee80211_node.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_node.h (renamed from freebsd/net80211/ieee80211_node.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_output.c (renamed from freebsd/net80211/ieee80211_output.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_phy.c (renamed from freebsd/net80211/ieee80211_phy.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_phy.h (renamed from freebsd/net80211/ieee80211_phy.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_power.c (renamed from freebsd/net80211/ieee80211_power.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_power.h (renamed from freebsd/net80211/ieee80211_power.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_proto.c (renamed from freebsd/net80211/ieee80211_proto.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_proto.h (renamed from freebsd/net80211/ieee80211_proto.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_radiotap.c (renamed from freebsd/net80211/ieee80211_radiotap.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_radiotap.h (renamed from freebsd/net80211/ieee80211_radiotap.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ratectl.c (renamed from freebsd/net80211/ieee80211_ratectl.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ratectl.h (renamed from freebsd/net80211/ieee80211_ratectl.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_ratectl_none.c (renamed from freebsd/net80211/ieee80211_ratectl_none.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_regdomain.c (renamed from freebsd/net80211/ieee80211_regdomain.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_regdomain.h (renamed from freebsd/net80211/ieee80211_regdomain.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_rssadapt.c (renamed from freebsd/net80211/ieee80211_rssadapt.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_rssadapt.h (renamed from freebsd/net80211/ieee80211_rssadapt.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_scan.c (renamed from freebsd/net80211/ieee80211_scan.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_scan.h (renamed from freebsd/net80211/ieee80211_scan.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_scan_sta.c (renamed from freebsd/net80211/ieee80211_scan_sta.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_sta.c (renamed from freebsd/net80211/ieee80211_sta.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_sta.h (renamed from freebsd/net80211/ieee80211_sta.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_superg.c (renamed from freebsd/net80211/ieee80211_superg.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_superg.h (renamed from freebsd/net80211/ieee80211_superg.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_tdma.c (renamed from freebsd/net80211/ieee80211_tdma.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_tdma.h (renamed from freebsd/net80211/ieee80211_tdma.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_var.h (renamed from freebsd/net80211/ieee80211_var.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_wds.c (renamed from freebsd/net80211/ieee80211_wds.c)0
-rw-r--r--freebsd/sys/net80211/ieee80211_wds.h (renamed from freebsd/net80211/ieee80211_wds.h)0
-rw-r--r--freebsd/sys/net80211/ieee80211_xauth.c (renamed from freebsd/net80211/ieee80211_xauth.c)0
-rw-r--r--freebsd/sys/netatalk/aarp.c (renamed from freebsd/netatalk/aarp.c)0
-rw-r--r--freebsd/sys/netatalk/aarp.h (renamed from freebsd/netatalk/aarp.h)0
-rw-r--r--freebsd/sys/netatalk/at.h2
-rw-r--r--freebsd/sys/netatalk/at_control.c (renamed from freebsd/netatalk/at_control.c)0
-rw-r--r--freebsd/sys/netatalk/at_extern.h (renamed from freebsd/netatalk/at_extern.h)0
-rw-r--r--freebsd/sys/netatalk/at_proto.c (renamed from freebsd/netatalk/at_proto.c)0
-rw-r--r--freebsd/sys/netatalk/at_rmx.c (renamed from freebsd/netatalk/at_rmx.c)0
-rw-r--r--freebsd/sys/netatalk/at_var.h (renamed from freebsd/netatalk/at_var.h)0
-rw-r--r--freebsd/sys/netatalk/ddp.h (renamed from freebsd/netatalk/ddp.h)0
-rw-r--r--freebsd/sys/netatalk/ddp_input.c (renamed from freebsd/netatalk/ddp_input.c)0
-rw-r--r--freebsd/sys/netatalk/ddp_output.c (renamed from freebsd/netatalk/ddp_output.c)0
-rw-r--r--freebsd/sys/netatalk/ddp_pcb.c (renamed from freebsd/netatalk/ddp_pcb.c)0
-rw-r--r--freebsd/sys/netatalk/ddp_pcb.h (renamed from freebsd/netatalk/ddp_pcb.h)0
-rw-r--r--freebsd/sys/netatalk/ddp_usrreq.c (renamed from freebsd/netatalk/ddp_usrreq.c)0
-rw-r--r--freebsd/sys/netatalk/ddp_var.h (renamed from freebsd/netatalk/ddp_var.h)0
-rw-r--r--freebsd/sys/netatalk/endian.h (renamed from freebsd/netatalk/endian.h)0
-rw-r--r--freebsd/sys/netatalk/phase2.h (renamed from freebsd/netatalk/phase2.h)0
-rw-r--r--freebsd/sys/netinet/accf_data.c (renamed from freebsd/netinet/accf_data.c)0
-rw-r--r--freebsd/sys/netinet/accf_dns.c (renamed from freebsd/netinet/accf_dns.c)0
-rw-r--r--freebsd/sys/netinet/accf_http.c (renamed from freebsd/netinet/accf_http.c)0
-rw-r--r--freebsd/sys/netinet/icmp6.h2
-rw-r--r--freebsd/sys/netinet/icmp_var.h (renamed from freebsd/netinet/icmp_var.h)0
-rw-r--r--freebsd/sys/netinet/if_atm.c (renamed from freebsd/netinet/if_atm.c)0
-rw-r--r--freebsd/sys/netinet/if_atm.h (renamed from freebsd/netinet/if_atm.h)0
-rw-r--r--freebsd/sys/netinet/if_ether.c (renamed from freebsd/netinet/if_ether.c)0
-rw-r--r--freebsd/sys/netinet/if_ether.h2
-rw-r--r--freebsd/sys/netinet/igmp.c (renamed from freebsd/netinet/igmp.c)0
-rw-r--r--freebsd/sys/netinet/igmp.h2
-rw-r--r--freebsd/sys/netinet/igmp_var.h (renamed from freebsd/netinet/igmp_var.h)0
-rw-r--r--freebsd/sys/netinet/in.c (renamed from freebsd/netinet/in.c)0
-rw-r--r--freebsd/sys/netinet/in.h2
-rw-r--r--freebsd/sys/netinet/in_gif.c (renamed from freebsd/netinet/in_gif.c)0
-rw-r--r--freebsd/sys/netinet/in_gif.h (renamed from freebsd/netinet/in_gif.h)0
-rw-r--r--freebsd/sys/netinet/in_mcast.c (renamed from freebsd/netinet/in_mcast.c)0
-rw-r--r--freebsd/sys/netinet/in_pcb.c (renamed from freebsd/netinet/in_pcb.c)0
-rw-r--r--freebsd/sys/netinet/in_pcb.h (renamed from freebsd/netinet/in_pcb.h)0
-rw-r--r--freebsd/sys/netinet/in_proto.c (renamed from freebsd/netinet/in_proto.c)0
-rw-r--r--freebsd/sys/netinet/in_rmx.c (renamed from freebsd/netinet/in_rmx.c)0
-rw-r--r--freebsd/sys/netinet/in_systm.h2
-rw-r--r--freebsd/sys/netinet/in_var.h (renamed from freebsd/netinet/in_var.h)0
-rw-r--r--freebsd/sys/netinet/ip.h2
-rw-r--r--freebsd/sys/netinet/ip6.h2
-rw-r--r--freebsd/sys/netinet/ip_carp.c (renamed from freebsd/netinet/ip_carp.c)0
-rw-r--r--freebsd/sys/netinet/ip_carp.h (renamed from freebsd/netinet/ip_carp.h)0
-rw-r--r--freebsd/sys/netinet/ip_divert.c (renamed from freebsd/netinet/ip_divert.c)0
-rw-r--r--freebsd/sys/netinet/ip_divert.h (renamed from freebsd/netinet/ip_divert.h)0
-rw-r--r--freebsd/sys/netinet/ip_dummynet.h (renamed from freebsd/netinet/ip_dummynet.h)0
-rw-r--r--freebsd/sys/netinet/ip_ecn.c (renamed from freebsd/netinet/ip_ecn.c)0
-rw-r--r--freebsd/sys/netinet/ip_ecn.h (renamed from freebsd/netinet/ip_ecn.h)0
-rw-r--r--freebsd/sys/netinet/ip_encap.c (renamed from freebsd/netinet/ip_encap.c)0
-rw-r--r--freebsd/sys/netinet/ip_encap.h (renamed from freebsd/netinet/ip_encap.h)0
-rw-r--r--freebsd/sys/netinet/ip_fastfwd.c (renamed from freebsd/netinet/ip_fastfwd.c)0
-rw-r--r--freebsd/sys/netinet/ip_fw.h (renamed from freebsd/netinet/ip_fw.h)0
-rw-r--r--freebsd/sys/netinet/ip_gre.c (renamed from freebsd/netinet/ip_gre.c)0
-rw-r--r--freebsd/sys/netinet/ip_gre.h (renamed from freebsd/netinet/ip_gre.h)0
-rw-r--r--freebsd/sys/netinet/ip_icmp.c (renamed from freebsd/netinet/ip_icmp.c)0
-rw-r--r--freebsd/sys/netinet/ip_icmp.h2
-rw-r--r--freebsd/sys/netinet/ip_id.c (renamed from freebsd/netinet/ip_id.c)0
-rw-r--r--freebsd/sys/netinet/ip_input.c (renamed from freebsd/netinet/ip_input.c)0
-rw-r--r--freebsd/sys/netinet/ip_ipsec.c (renamed from freebsd/netinet/ip_ipsec.c)0
-rw-r--r--freebsd/sys/netinet/ip_ipsec.h (renamed from freebsd/netinet/ip_ipsec.h)0
-rw-r--r--freebsd/sys/netinet/ip_mroute.c (renamed from freebsd/netinet/ip_mroute.c)0
-rw-r--r--freebsd/sys/netinet/ip_mroute.h (renamed from freebsd/netinet/ip_mroute.h)0
-rw-r--r--freebsd/sys/netinet/ip_options.c (renamed from freebsd/netinet/ip_options.c)0
-rw-r--r--freebsd/sys/netinet/ip_options.h (renamed from freebsd/netinet/ip_options.h)0
-rw-r--r--freebsd/sys/netinet/ip_output.c (renamed from freebsd/netinet/ip_output.c)0
-rw-r--r--freebsd/sys/netinet/ip_var.h (renamed from freebsd/netinet/ip_var.h)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_heap.c (renamed from freebsd/netinet/ipfw/dn_heap.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_heap.h (renamed from freebsd/netinet/ipfw/dn_heap.h)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_sched.h (renamed from freebsd/netinet/ipfw/dn_sched.h)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_sched_fifo.c (renamed from freebsd/netinet/ipfw/dn_sched_fifo.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_sched_prio.c (renamed from freebsd/netinet/ipfw/dn_sched_prio.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_sched_qfq.c (renamed from freebsd/netinet/ipfw/dn_sched_qfq.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_sched_rr.c (renamed from freebsd/netinet/ipfw/dn_sched_rr.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/dn_sched_wf2q.c (renamed from freebsd/netinet/ipfw/dn_sched_wf2q.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dn_glue.c (renamed from freebsd/netinet/ipfw/ip_dn_glue.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dn_io.c (renamed from freebsd/netinet/ipfw/ip_dn_io.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dn_private.h (renamed from freebsd/netinet/ipfw/ip_dn_private.h)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_dummynet.c (renamed from freebsd/netinet/ipfw/ip_dummynet.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw2.c (renamed from freebsd/netinet/ipfw/ip_fw2.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_log.c (renamed from freebsd/netinet/ipfw/ip_fw_log.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_nat.c (renamed from freebsd/netinet/ipfw/ip_fw_nat.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_pfil.c (renamed from freebsd/netinet/ipfw/ip_fw_pfil.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_private.h (renamed from freebsd/netinet/ipfw/ip_fw_private.h)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_sockopt.c (renamed from freebsd/netinet/ipfw/ip_fw_sockopt.c)0
-rw-r--r--freebsd/sys/netinet/ipfw/ip_fw_table.c (renamed from freebsd/netinet/ipfw/ip_fw_table.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias.c (renamed from freebsd/netinet/libalias/alias.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias.h (renamed from freebsd/netinet/libalias/alias.h)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_cuseeme.c (renamed from freebsd/netinet/libalias/alias_cuseeme.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_db.c (renamed from freebsd/netinet/libalias/alias_db.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_dummy.c (renamed from freebsd/netinet/libalias/alias_dummy.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_ftp.c (renamed from freebsd/netinet/libalias/alias_ftp.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_irc.c (renamed from freebsd/netinet/libalias/alias_irc.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_local.h (renamed from freebsd/netinet/libalias/alias_local.h)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_mod.c (renamed from freebsd/netinet/libalias/alias_mod.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_mod.h (renamed from freebsd/netinet/libalias/alias_mod.h)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_nbt.c (renamed from freebsd/netinet/libalias/alias_nbt.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_pptp.c (renamed from freebsd/netinet/libalias/alias_pptp.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_proxy.c (renamed from freebsd/netinet/libalias/alias_proxy.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_sctp.c (renamed from freebsd/netinet/libalias/alias_sctp.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_sctp.h (renamed from freebsd/netinet/libalias/alias_sctp.h)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_skinny.c (renamed from freebsd/netinet/libalias/alias_skinny.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_smedia.c (renamed from freebsd/netinet/libalias/alias_smedia.c)0
-rw-r--r--freebsd/sys/netinet/libalias/alias_util.c (renamed from freebsd/netinet/libalias/alias_util.c)0
-rw-r--r--freebsd/sys/netinet/pim.h (renamed from freebsd/netinet/pim.h)0
-rw-r--r--freebsd/sys/netinet/pim_var.h (renamed from freebsd/netinet/pim_var.h)0
-rw-r--r--freebsd/sys/netinet/raw_ip.c (renamed from freebsd/netinet/raw_ip.c)0
-rw-r--r--freebsd/sys/netinet/sctp.h (renamed from freebsd/netinet/sctp.h)0
-rw-r--r--freebsd/sys/netinet/sctp_asconf.c (renamed from freebsd/netinet/sctp_asconf.c)0
-rw-r--r--freebsd/sys/netinet/sctp_asconf.h (renamed from freebsd/netinet/sctp_asconf.h)0
-rw-r--r--freebsd/sys/netinet/sctp_auth.c (renamed from freebsd/netinet/sctp_auth.c)0
-rw-r--r--freebsd/sys/netinet/sctp_auth.h (renamed from freebsd/netinet/sctp_auth.h)0
-rw-r--r--freebsd/sys/netinet/sctp_bsd_addr.c (renamed from freebsd/netinet/sctp_bsd_addr.c)0
-rw-r--r--freebsd/sys/netinet/sctp_bsd_addr.h (renamed from freebsd/netinet/sctp_bsd_addr.h)0
-rw-r--r--freebsd/sys/netinet/sctp_cc_functions.c (renamed from freebsd/netinet/sctp_cc_functions.c)0
-rw-r--r--freebsd/sys/netinet/sctp_cc_functions.h (renamed from freebsd/netinet/sctp_cc_functions.h)0
-rw-r--r--freebsd/sys/netinet/sctp_constants.h (renamed from freebsd/netinet/sctp_constants.h)0
-rw-r--r--freebsd/sys/netinet/sctp_crc32.c (renamed from freebsd/netinet/sctp_crc32.c)0
-rw-r--r--freebsd/sys/netinet/sctp_crc32.h (renamed from freebsd/netinet/sctp_crc32.h)0
-rw-r--r--freebsd/sys/netinet/sctp_header.h (renamed from freebsd/netinet/sctp_header.h)0
-rw-r--r--freebsd/sys/netinet/sctp_indata.c (renamed from freebsd/netinet/sctp_indata.c)0
-rw-r--r--freebsd/sys/netinet/sctp_indata.h (renamed from freebsd/netinet/sctp_indata.h)0
-rw-r--r--freebsd/sys/netinet/sctp_input.c (renamed from freebsd/netinet/sctp_input.c)0
-rw-r--r--freebsd/sys/netinet/sctp_input.h (renamed from freebsd/netinet/sctp_input.h)0
-rw-r--r--freebsd/sys/netinet/sctp_lock_bsd.h (renamed from freebsd/netinet/sctp_lock_bsd.h)0
-rw-r--r--freebsd/sys/netinet/sctp_os.h (renamed from freebsd/netinet/sctp_os.h)0
-rw-r--r--freebsd/sys/netinet/sctp_os_bsd.h (renamed from freebsd/netinet/sctp_os_bsd.h)0
-rw-r--r--freebsd/sys/netinet/sctp_output.c (renamed from freebsd/netinet/sctp_output.c)0
-rw-r--r--freebsd/sys/netinet/sctp_output.h (renamed from freebsd/netinet/sctp_output.h)0
-rw-r--r--freebsd/sys/netinet/sctp_pcb.c (renamed from freebsd/netinet/sctp_pcb.c)0
-rw-r--r--freebsd/sys/netinet/sctp_pcb.h (renamed from freebsd/netinet/sctp_pcb.h)0
-rw-r--r--freebsd/sys/netinet/sctp_peeloff.c (renamed from freebsd/netinet/sctp_peeloff.c)0
-rw-r--r--freebsd/sys/netinet/sctp_peeloff.h (renamed from freebsd/netinet/sctp_peeloff.h)0
-rw-r--r--freebsd/sys/netinet/sctp_structs.h (renamed from freebsd/netinet/sctp_structs.h)0
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.c (renamed from freebsd/netinet/sctp_sysctl.c)0
-rw-r--r--freebsd/sys/netinet/sctp_sysctl.h (renamed from freebsd/netinet/sctp_sysctl.h)0
-rw-r--r--freebsd/sys/netinet/sctp_timer.c (renamed from freebsd/netinet/sctp_timer.c)0
-rw-r--r--freebsd/sys/netinet/sctp_timer.h (renamed from freebsd/netinet/sctp_timer.h)0
-rw-r--r--freebsd/sys/netinet/sctp_uio.h (renamed from freebsd/netinet/sctp_uio.h)0
-rw-r--r--freebsd/sys/netinet/sctp_usrreq.c (renamed from freebsd/netinet/sctp_usrreq.c)0
-rw-r--r--freebsd/sys/netinet/sctp_var.h (renamed from freebsd/netinet/sctp_var.h)0
-rw-r--r--freebsd/sys/netinet/sctputil.c (renamed from freebsd/netinet/sctputil.c)0
-rw-r--r--freebsd/sys/netinet/sctputil.h (renamed from freebsd/netinet/sctputil.h)0
-rw-r--r--freebsd/sys/netinet/tcp.h2
-rw-r--r--freebsd/sys/netinet/tcp_debug.c (renamed from freebsd/netinet/tcp_debug.c)0
-rw-r--r--freebsd/sys/netinet/tcp_debug.h (renamed from freebsd/netinet/tcp_debug.h)0
-rw-r--r--freebsd/sys/netinet/tcp_fsm.h (renamed from freebsd/netinet/tcp_fsm.h)0
-rw-r--r--freebsd/sys/netinet/tcp_hostcache.c (renamed from freebsd/netinet/tcp_hostcache.c)0
-rw-r--r--freebsd/sys/netinet/tcp_hostcache.h (renamed from freebsd/netinet/tcp_hostcache.h)0
-rw-r--r--freebsd/sys/netinet/tcp_input.c (renamed from freebsd/netinet/tcp_input.c)0
-rw-r--r--freebsd/sys/netinet/tcp_lro.c (renamed from freebsd/netinet/tcp_lro.c)0
-rw-r--r--freebsd/sys/netinet/tcp_lro.h (renamed from freebsd/netinet/tcp_lro.h)0
-rw-r--r--freebsd/sys/netinet/tcp_offload.c (renamed from freebsd/netinet/tcp_offload.c)0
-rw-r--r--freebsd/sys/netinet/tcp_offload.h (renamed from freebsd/netinet/tcp_offload.h)0
-rw-r--r--freebsd/sys/netinet/tcp_output.c (renamed from freebsd/netinet/tcp_output.c)0
-rw-r--r--freebsd/sys/netinet/tcp_reass.c (renamed from freebsd/netinet/tcp_reass.c)0
-rw-r--r--freebsd/sys/netinet/tcp_sack.c (renamed from freebsd/netinet/tcp_sack.c)0
-rw-r--r--freebsd/sys/netinet/tcp_seq.h (renamed from freebsd/netinet/tcp_seq.h)0
-rw-r--r--freebsd/sys/netinet/tcp_subr.c (renamed from freebsd/netinet/tcp_subr.c)0
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c (renamed from freebsd/netinet/tcp_syncache.c)0
-rw-r--r--freebsd/sys/netinet/tcp_syncache.h (renamed from freebsd/netinet/tcp_syncache.h)0
-rw-r--r--freebsd/sys/netinet/tcp_timer.c (renamed from freebsd/netinet/tcp_timer.c)0
-rw-r--r--freebsd/sys/netinet/tcp_timer.h (renamed from freebsd/netinet/tcp_timer.h)0
-rw-r--r--freebsd/sys/netinet/tcp_timewait.c (renamed from freebsd/netinet/tcp_timewait.c)0
-rw-r--r--freebsd/sys/netinet/tcp_usrreq.c (renamed from freebsd/netinet/tcp_usrreq.c)0
-rw-r--r--freebsd/sys/netinet/tcp_var.h (renamed from freebsd/netinet/tcp_var.h)0
-rw-r--r--freebsd/sys/netinet/tcpip.h (renamed from freebsd/netinet/tcpip.h)0
-rw-r--r--freebsd/sys/netinet/toedev.h (renamed from freebsd/netinet/toedev.h)0
-rw-r--r--freebsd/sys/netinet/udp.h2
-rw-r--r--freebsd/sys/netinet/udp_usrreq.c (renamed from freebsd/netinet/udp_usrreq.c)0
-rw-r--r--freebsd/sys/netinet/udp_var.h (renamed from freebsd/netinet/udp_var.h)0
-rw-r--r--freebsd/sys/netinet6/dest6.c (renamed from freebsd/netinet6/dest6.c)0
-rw-r--r--freebsd/sys/netinet6/frag6.c (renamed from freebsd/netinet6/frag6.c)0
-rw-r--r--freebsd/sys/netinet6/icmp6.c (renamed from freebsd/netinet6/icmp6.c)0
-rw-r--r--freebsd/sys/netinet6/icmp6.h (renamed from freebsd/netinet6/icmp6.h)0
-rw-r--r--freebsd/sys/netinet6/in6.c (renamed from freebsd/netinet6/in6.c)0
-rw-r--r--freebsd/sys/netinet6/in6.h (renamed from freebsd/netinet6/in6.h)0
-rw-r--r--freebsd/sys/netinet6/in6_cksum.c (renamed from freebsd/netinet6/in6_cksum.c)0
-rw-r--r--freebsd/sys/netinet6/in6_gif.c (renamed from freebsd/netinet6/in6_gif.c)0
-rw-r--r--freebsd/sys/netinet6/in6_gif.h (renamed from freebsd/netinet6/in6_gif.h)0
-rw-r--r--freebsd/sys/netinet6/in6_ifattach.c (renamed from freebsd/netinet6/in6_ifattach.c)0
-rw-r--r--freebsd/sys/netinet6/in6_ifattach.h (renamed from freebsd/netinet6/in6_ifattach.h)0
-rw-r--r--freebsd/sys/netinet6/in6_mcast.c (renamed from freebsd/netinet6/in6_mcast.c)0
-rw-r--r--freebsd/sys/netinet6/in6_pcb.c (renamed from freebsd/netinet6/in6_pcb.c)0
-rw-r--r--freebsd/sys/netinet6/in6_pcb.h (renamed from freebsd/netinet6/in6_pcb.h)0
-rw-r--r--freebsd/sys/netinet6/in6_proto.c (renamed from freebsd/netinet6/in6_proto.c)0
-rw-r--r--freebsd/sys/netinet6/in6_rmx.c (renamed from freebsd/netinet6/in6_rmx.c)0
-rw-r--r--freebsd/sys/netinet6/in6_src.c (renamed from freebsd/netinet6/in6_src.c)0
-rw-r--r--freebsd/sys/netinet6/in6_var.h (renamed from freebsd/netinet6/in6_var.h)0
-rw-r--r--freebsd/sys/netinet6/ip6.h (renamed from freebsd/netinet6/ip6.h)0
-rw-r--r--freebsd/sys/netinet6/ip6_ecn.h (renamed from freebsd/netinet6/ip6_ecn.h)0
-rw-r--r--freebsd/sys/netinet6/ip6_forward.c (renamed from freebsd/netinet6/ip6_forward.c)0
-rw-r--r--freebsd/sys/netinet6/ip6_id.c (renamed from freebsd/netinet6/ip6_id.c)0
-rw-r--r--freebsd/sys/netinet6/ip6_input.c (renamed from freebsd/netinet6/ip6_input.c)0
-rw-r--r--freebsd/sys/netinet6/ip6_ipsec.c (renamed from freebsd/netinet6/ip6_ipsec.c)0
-rw-r--r--freebsd/sys/netinet6/ip6_ipsec.h (renamed from freebsd/netinet6/ip6_ipsec.h)0
-rw-r--r--freebsd/sys/netinet6/ip6_mroute.c (renamed from freebsd/netinet6/ip6_mroute.c)0
-rw-r--r--freebsd/sys/netinet6/ip6_mroute.h (renamed from freebsd/netinet6/ip6_mroute.h)0
-rw-r--r--freebsd/sys/netinet6/ip6_output.c (renamed from freebsd/netinet6/ip6_output.c)0
-rw-r--r--freebsd/sys/netinet6/ip6_var.h (renamed from freebsd/netinet6/ip6_var.h)0
-rw-r--r--freebsd/sys/netinet6/ip6protosw.h (renamed from freebsd/netinet6/ip6protosw.h)0
-rw-r--r--freebsd/sys/netinet6/mld6.c (renamed from freebsd/netinet6/mld6.c)0
-rw-r--r--freebsd/sys/netinet6/mld6.h (renamed from freebsd/netinet6/mld6.h)0
-rw-r--r--freebsd/sys/netinet6/mld6_var.h (renamed from freebsd/netinet6/mld6_var.h)0
-rw-r--r--freebsd/sys/netinet6/nd6.c (renamed from freebsd/netinet6/nd6.c)0
-rw-r--r--freebsd/sys/netinet6/nd6.h (renamed from freebsd/netinet6/nd6.h)0
-rw-r--r--freebsd/sys/netinet6/nd6_nbr.c (renamed from freebsd/netinet6/nd6_nbr.c)0
-rw-r--r--freebsd/sys/netinet6/nd6_rtr.c (renamed from freebsd/netinet6/nd6_rtr.c)0
-rw-r--r--freebsd/sys/netinet6/pim6.h (renamed from freebsd/netinet6/pim6.h)0
-rw-r--r--freebsd/sys/netinet6/pim6_var.h (renamed from freebsd/netinet6/pim6_var.h)0
-rw-r--r--freebsd/sys/netinet6/raw_ip6.c (renamed from freebsd/netinet6/raw_ip6.c)0
-rw-r--r--freebsd/sys/netinet6/raw_ip6.h (renamed from freebsd/netinet6/raw_ip6.h)0
-rw-r--r--freebsd/sys/netinet6/route6.c (renamed from freebsd/netinet6/route6.c)0
-rw-r--r--freebsd/sys/netinet6/scope6.c (renamed from freebsd/netinet6/scope6.c)0
-rw-r--r--freebsd/sys/netinet6/scope6_var.h (renamed from freebsd/netinet6/scope6_var.h)0
-rw-r--r--freebsd/sys/netinet6/sctp6_usrreq.c (renamed from freebsd/netinet6/sctp6_usrreq.c)0
-rw-r--r--freebsd/sys/netinet6/sctp6_var.h (renamed from freebsd/netinet6/sctp6_var.h)0
-rw-r--r--freebsd/sys/netinet6/tcp6_var.h (renamed from freebsd/netinet6/tcp6_var.h)0
-rw-r--r--freebsd/sys/netinet6/udp6_usrreq.c (renamed from freebsd/netinet6/udp6_usrreq.c)0
-rw-r--r--freebsd/sys/netinet6/udp6_var.h (renamed from freebsd/netinet6/udp6_var.h)0
-rw-r--r--freebsd/sys/netipsec/ah.h (renamed from freebsd/netipsec/ah.h)0
-rw-r--r--freebsd/sys/netipsec/ah_var.h (renamed from freebsd/netipsec/ah_var.h)0
-rw-r--r--freebsd/sys/netipsec/esp.h (renamed from freebsd/netipsec/esp.h)0
-rw-r--r--freebsd/sys/netipsec/esp_var.h (renamed from freebsd/netipsec/esp_var.h)0
-rw-r--r--freebsd/sys/netipsec/ipcomp.h (renamed from freebsd/netipsec/ipcomp.h)0
-rw-r--r--freebsd/sys/netipsec/ipcomp_var.h (renamed from freebsd/netipsec/ipcomp_var.h)0
-rw-r--r--freebsd/sys/netipsec/ipip_var.h (renamed from freebsd/netipsec/ipip_var.h)0
-rw-r--r--freebsd/sys/netipsec/ipsec.c (renamed from freebsd/netipsec/ipsec.c)0
-rw-r--r--freebsd/sys/netipsec/ipsec.h (renamed from freebsd/netipsec/ipsec.h)0
-rw-r--r--freebsd/sys/netipsec/ipsec6.h (renamed from freebsd/netipsec/ipsec6.h)0
-rw-r--r--freebsd/sys/netipsec/ipsec_input.c (renamed from freebsd/netipsec/ipsec_input.c)0
-rw-r--r--freebsd/sys/netipsec/ipsec_mbuf.c (renamed from freebsd/netipsec/ipsec_mbuf.c)0
-rw-r--r--freebsd/sys/netipsec/ipsec_output.c (renamed from freebsd/netipsec/ipsec_output.c)0
-rw-r--r--freebsd/sys/netipsec/key.c (renamed from freebsd/netipsec/key.c)0
-rw-r--r--freebsd/sys/netipsec/key.h (renamed from freebsd/netipsec/key.h)0
-rw-r--r--freebsd/sys/netipsec/key_debug.c (renamed from freebsd/netipsec/key_debug.c)0
-rw-r--r--freebsd/sys/netipsec/key_debug.h (renamed from freebsd/netipsec/key_debug.h)0
-rw-r--r--freebsd/sys/netipsec/key_var.h (renamed from freebsd/netipsec/key_var.h)0
-rw-r--r--freebsd/sys/netipsec/keydb.h (renamed from freebsd/netipsec/keydb.h)0
-rw-r--r--freebsd/sys/netipsec/keysock.c (renamed from freebsd/netipsec/keysock.c)0
-rw-r--r--freebsd/sys/netipsec/keysock.h (renamed from freebsd/netipsec/keysock.h)0
-rw-r--r--freebsd/sys/netipsec/xform.h (renamed from freebsd/netipsec/xform.h)0
-rw-r--r--freebsd/sys/netipsec/xform_ah.c (renamed from freebsd/netipsec/xform_ah.c)0
-rw-r--r--freebsd/sys/netipsec/xform_esp.c (renamed from freebsd/netipsec/xform_esp.c)0
-rw-r--r--freebsd/sys/netipsec/xform_ipcomp.c (renamed from freebsd/netipsec/xform_ipcomp.c)0
-rw-r--r--freebsd/sys/netipsec/xform_ipip.c (renamed from freebsd/netipsec/xform_ipip.c)0
-rw-r--r--freebsd/sys/netipsec/xform_tcp.c (renamed from freebsd/netipsec/xform_tcp.c)0
-rw-r--r--freebsd/sys/opencrypto/cast.c (renamed from freebsd/opencrypto/cast.c)0
-rw-r--r--freebsd/sys/opencrypto/cast.h (renamed from freebsd/opencrypto/cast.h)0
-rw-r--r--freebsd/sys/opencrypto/castsb.h (renamed from freebsd/opencrypto/castsb.h)0
-rw-r--r--freebsd/sys/opencrypto/criov.c (renamed from freebsd/opencrypto/criov.c)0
-rw-r--r--freebsd/sys/opencrypto/crypto.c (renamed from freebsd/opencrypto/crypto.c)0
-rw-r--r--freebsd/sys/opencrypto/cryptodev.c (renamed from freebsd/opencrypto/cryptodev.c)0
-rw-r--r--freebsd/sys/opencrypto/cryptodev.h (renamed from freebsd/opencrypto/cryptodev.h)0
-rw-r--r--freebsd/sys/opencrypto/cryptosoft.c (renamed from freebsd/opencrypto/cryptosoft.c)0
-rw-r--r--freebsd/sys/opencrypto/cryptosoft.h (renamed from freebsd/opencrypto/cryptosoft.h)0
-rw-r--r--freebsd/sys/opencrypto/deflate.c (renamed from freebsd/opencrypto/deflate.c)0
-rw-r--r--freebsd/sys/opencrypto/deflate.h (renamed from freebsd/opencrypto/deflate.h)0
-rw-r--r--freebsd/sys/opencrypto/rmd160.c (renamed from freebsd/opencrypto/rmd160.c)0
-rw-r--r--freebsd/sys/opencrypto/rmd160.h (renamed from freebsd/opencrypto/rmd160.h)0
-rw-r--r--freebsd/sys/opencrypto/skipjack.c (renamed from freebsd/opencrypto/skipjack.c)0
-rw-r--r--freebsd/sys/opencrypto/skipjack.h (renamed from freebsd/opencrypto/skipjack.h)0
-rw-r--r--freebsd/sys/opencrypto/xform.c (renamed from freebsd/opencrypto/xform.c)0
-rw-r--r--freebsd/sys/opencrypto/xform.h (renamed from freebsd/opencrypto/xform.h)0
-rw-r--r--freebsd/sys/param.h332
-rw-r--r--freebsd/sys/pci/if_rlreg.h (renamed from freebsd/pci/if_rlreg.h)0
-rw-r--r--freebsd/sys/powerpc/include/machine/cpufunc.h (renamed from freebsd/powerpc/include/freebsd/machine/cpufunc.h)0
-rw-r--r--freebsd/sys/powerpc/include/machine/psl.h (renamed from freebsd/powerpc/include/freebsd/machine/psl.h)0
-rw-r--r--freebsd/sys/powerpc/include/machine/spr.h (renamed from freebsd/powerpc/include/freebsd/machine/spr.h)0
-rw-r--r--freebsd/sys/powerpc/powerpc/in_cksum.c (renamed from freebsd/powerpc/powerpc/in_cksum.c)0
-rw-r--r--freebsd/sys/resource.h176
-rw-r--r--freebsd/sys/rpc/types.h118
-rw-r--r--freebsd/sys/security/mac/mac_framework.h (renamed from freebsd/security/mac/mac_framework.h)0
-rw-r--r--freebsd/sys/sleepqueue.h1
-rw-r--r--freebsd/sys/sparc64/include/machine/asi.h (renamed from freebsd/sparc64/include/freebsd/machine/asi.h)0
-rw-r--r--freebsd/sys/sparc64/include/machine/cpufunc.h (renamed from freebsd/sparc64/include/freebsd/machine/cpufunc.h)0
-rw-r--r--freebsd/sys/sparc64/include/machine/pstate.h (renamed from freebsd/sparc64/include/freebsd/machine/pstate.h)0
-rw-r--r--freebsd/sys/sparc64/sparc64/in_cksum.c (renamed from freebsd/sparc64/sparc64/in_cksum.c)0
-rw-r--r--freebsd/sys/sys/_bus_dma.h (renamed from freebsd/sys/_bus_dma.h)0
-rw-r--r--freebsd/sys/sys/_lock.h (renamed from freebsd/sys/_lock.h)0
-rw-r--r--freebsd/sys/sys/_lockmgr.h (renamed from freebsd/sys/_lockmgr.h)0
-rw-r--r--freebsd/sys/sys/_mutex.h (renamed from freebsd/sys/_mutex.h)0
-rw-r--r--freebsd/sys/sys/_null.h45
-rw-r--r--freebsd/sys/sys/_rmlock.h (renamed from freebsd/sys/_rmlock.h)0
-rw-r--r--freebsd/sys/sys/_rwlock.h (renamed from freebsd/sys/_rwlock.h)0
-rw-r--r--freebsd/sys/sys/_semaphore.h (renamed from freebsd/sys/_semaphore.h)0
-rw-r--r--freebsd/sys/sys/_sigset.h (renamed from freebsd/sys/_sigset.h)0
-rw-r--r--freebsd/sys/sys/_sx.h (renamed from freebsd/sys/_sx.h)0
-rw-r--r--freebsd/sys/sys/_task.h (renamed from freebsd/sys/_task.h)0
-rw-r--r--freebsd/sys/sys/_timeval.h (renamed from freebsd/sys/_timeval.h)0
-rw-r--r--freebsd/sys/sys/acl.h (renamed from freebsd/sys/acl.h)0
-rw-r--r--freebsd/sys/sys/aio.h (renamed from freebsd/sys/aio.h)0
-rw-r--r--freebsd/sys/sys/ata.h (renamed from freebsd/sys/ata.h)0
-rw-r--r--freebsd/sys/sys/bitstring.h (renamed from freebsd/sys/bitstring.h)0
-rw-r--r--freebsd/sys/sys/buf.h (renamed from freebsd/sys/buf.h)0
-rw-r--r--freebsd/sys/sys/buf_ring.h (renamed from freebsd/sys/buf_ring.h)0
-rw-r--r--freebsd/sys/sys/bufobj.h (renamed from freebsd/sys/bufobj.h)0
-rw-r--r--freebsd/sys/sys/bus.h (renamed from freebsd/sys/bus.h)0
-rw-r--r--freebsd/sys/sys/bus_dma.h (renamed from freebsd/sys/bus_dma.h)0
-rw-r--r--freebsd/sys/sys/callout.h (renamed from freebsd/sys/callout.h)0
-rw-r--r--freebsd/sys/sys/condvar.h (renamed from freebsd/sys/condvar.h)0
-rw-r--r--freebsd/sys/sys/conf.h (renamed from freebsd/sys/conf.h)0
-rw-r--r--freebsd/sys/sys/cpu.h (renamed from freebsd/sys/cpu.h)0
-rw-r--r--freebsd/sys/sys/ctype.h (renamed from freebsd/sys/ctype.h)0
-rw-r--r--freebsd/sys/sys/domain.h (renamed from freebsd/sys/domain.h)0
-rw-r--r--freebsd/sys/sys/endian.h (renamed from freebsd/sys/endian.h)0
-rw-r--r--freebsd/sys/sys/event.h (renamed from freebsd/sys/event.h)0
-rw-r--r--freebsd/sys/sys/eventhandler.h (renamed from freebsd/sys/eventhandler.h)0
-rw-r--r--freebsd/sys/sys/eventvar.h (renamed from freebsd/sys/eventvar.h)0
-rw-r--r--freebsd/sys/sys/fcntl.h (renamed from freebsd/sys/fcntl.h)0
-rw-r--r--freebsd/sys/sys/file.h (renamed from freebsd/sys/file.h)0
-rw-r--r--freebsd/sys/sys/filedesc.h (renamed from freebsd/sys/filedesc.h)0
-rw-r--r--freebsd/sys/sys/filio.h (renamed from freebsd/sys/filio.h)0
-rw-r--r--freebsd/sys/sys/fnv_hash.h (renamed from freebsd/sys/fnv_hash.h)0
-rw-r--r--freebsd/sys/sys/hash.h (renamed from freebsd/sys/hash.h)0
-rw-r--r--freebsd/sys/sys/interrupt.h (renamed from freebsd/sys/interrupt.h)0
-rw-r--r--freebsd/sys/sys/jail.h (renamed from freebsd/sys/jail.h)0
-rw-r--r--freebsd/sys/sys/kenv.h (renamed from freebsd/sys/kenv.h)0
-rw-r--r--freebsd/sys/sys/kernel.h (renamed from freebsd/sys/kernel.h)0
-rw-r--r--freebsd/sys/sys/kobj.h (renamed from freebsd/sys/kobj.h)0
-rw-r--r--freebsd/sys/sys/kthread.h (renamed from freebsd/sys/kthread.h)0
-rw-r--r--freebsd/sys/sys/ktr.h (renamed from freebsd/sys/ktr.h)0
-rw-r--r--freebsd/sys/sys/libkern.h (renamed from freebsd/sys/libkern.h)0
-rw-r--r--freebsd/sys/sys/limits.h9
-rw-r--r--freebsd/sys/sys/linker.h (renamed from freebsd/sys/linker.h)0
-rw-r--r--freebsd/sys/sys/linker_set.h (renamed from freebsd/sys/linker_set.h)0
-rw-r--r--freebsd/sys/sys/lock_profile.h (renamed from freebsd/sys/lock_profile.h)0
-rw-r--r--freebsd/sys/sys/lockmgr.h (renamed from freebsd/sys/lockmgr.h)0
-rw-r--r--freebsd/sys/sys/lockstat.h (renamed from freebsd/sys/lockstat.h)0
-rw-r--r--freebsd/sys/sys/mac.h (renamed from freebsd/sys/mac.h)0
-rw-r--r--freebsd/sys/sys/malloc.h (renamed from freebsd/sys/malloc.h)0
-rw-r--r--freebsd/sys/sys/mbuf.h (renamed from freebsd/sys/mbuf.h)0
-rw-r--r--freebsd/sys/sys/md5.h (renamed from freebsd/sys/md5.h)0
-rw-r--r--freebsd/sys/sys/mman.h3
-rw-r--r--freebsd/sys/sys/module.h (renamed from freebsd/sys/module.h)0
-rw-r--r--freebsd/sys/sys/mount.h (renamed from freebsd/sys/mount.h)0
-rw-r--r--freebsd/sys/sys/mqueue.h (renamed from freebsd/sys/mqueue.h)0
-rw-r--r--freebsd/sys/sys/mutex.h (renamed from freebsd/sys/mutex.h)0
-rw-r--r--freebsd/sys/sys/nlist_aout.h113
-rw-r--r--freebsd/sys/sys/osd.h (renamed from freebsd/sys/osd.h)0
-rw-r--r--freebsd/sys/sys/pciio.h (renamed from freebsd/sys/pciio.h)0
-rw-r--r--freebsd/sys/sys/pcpu.h (renamed from freebsd/sys/pcpu.h)0
-rw-r--r--freebsd/sys/sys/poll.h (renamed from freebsd/sys/poll.h)0
-rw-r--r--freebsd/sys/sys/priority.h (renamed from freebsd/sys/priority.h)0
-rw-r--r--freebsd/sys/sys/priv.h (renamed from freebsd/sys/priv.h)0
-rw-r--r--freebsd/sys/sys/proc.h (renamed from freebsd/sys/proc.h)0
-rw-r--r--freebsd/sys/sys/protosw.h (renamed from freebsd/sys/protosw.h)0
-rw-r--r--freebsd/sys/sys/queue.h (renamed from freebsd/sys/queue.h)0
-rw-r--r--freebsd/sys/sys/random.h (renamed from freebsd/sys/random.h)0
-rw-r--r--freebsd/sys/sys/reboot.h (renamed from freebsd/sys/reboot.h)0
-rw-r--r--freebsd/sys/sys/refcount.h (renamed from freebsd/sys/refcount.h)0
-rw-r--r--freebsd/sys/sys/resourcevar.h (renamed from freebsd/sys/resourcevar.h)0
-rw-r--r--freebsd/sys/sys/rman.h (renamed from freebsd/sys/rman.h)0
-rw-r--r--freebsd/sys/sys/rmlock.h (renamed from freebsd/sys/rmlock.h)0
-rw-r--r--freebsd/sys/sys/rtprio.h (renamed from freebsd/sys/rtprio.h)0
-rw-r--r--freebsd/sys/sys/runq.h (renamed from freebsd/sys/runq.h)0
-rw-r--r--freebsd/sys/sys/rwlock.h (renamed from freebsd/sys/rwlock.h)0
-rw-r--r--freebsd/sys/sys/sbuf.h (renamed from freebsd/sys/sbuf.h)0
-rw-r--r--freebsd/sys/sys/sdt.h (renamed from freebsd/sys/sdt.h)0
-rw-r--r--freebsd/sys/sys/select.h3
-rw-r--r--freebsd/sys/sys/selinfo.h (renamed from freebsd/sys/selinfo.h)0
-rw-r--r--freebsd/sys/sys/sf_buf.h (renamed from freebsd/sys/sf_buf.h)0
-rw-r--r--freebsd/sys/sys/sigio.h (renamed from freebsd/sys/sigio.h)0
-rw-r--r--freebsd/sys/sys/smp.h (renamed from freebsd/sys/smp.h)0
-rw-r--r--freebsd/sys/sys/sockbuf.h (renamed from freebsd/sys/sockbuf.h)0
-rw-r--r--freebsd/sys/sys/socket.h2
-rw-r--r--freebsd/sys/sys/socketvar.h2
-rw-r--r--freebsd/sys/sys/sockio.h (renamed from freebsd/sys/sockio.h)0
-rw-r--r--freebsd/sys/sys/sockopt.h (renamed from freebsd/sys/sockopt.h)0
-rw-r--r--freebsd/sys/sys/sockstate.h (renamed from freebsd/sys/sockstate.h)0
-rw-r--r--freebsd/sys/sys/stddef.h (renamed from freebsd/sys/stddef.h)0
-rw-r--r--freebsd/sys/sys/stdint.h (renamed from freebsd/sys/stdint.h)0
-rw-r--r--freebsd/sys/sys/sx.h (renamed from freebsd/sys/sx.h)0
-rw-r--r--freebsd/sys/sys/sysctl.h2
-rw-r--r--freebsd/sys/sys/syslog.h203
-rw-r--r--freebsd/sys/sys/systm.h (renamed from freebsd/sys/systm.h)0
-rw-r--r--freebsd/sys/sys/taskqueue.h (renamed from freebsd/sys/taskqueue.h)0
-rw-r--r--freebsd/sys/sys/timepps.h (renamed from freebsd/sys/timepps.h)0
-rw-r--r--freebsd/sys/sys/timetc.h (renamed from freebsd/sys/timetc.h)0
-rw-r--r--freebsd/sys/sys/timex.h (renamed from freebsd/sys/timex.h)0
-rw-r--r--freebsd/sys/sys/tree.h (renamed from freebsd/sys/tree.h)0
-rw-r--r--freebsd/sys/sys/tty.h (renamed from freebsd/sys/tty.h)0
-rw-r--r--freebsd/sys/sys/ttycom.h (renamed from freebsd/sys/ttycom.h)0
-rw-r--r--freebsd/sys/sys/ttydevsw.h (renamed from freebsd/sys/ttydevsw.h)0
-rw-r--r--freebsd/sys/sys/ttydisc.h (renamed from freebsd/sys/ttydisc.h)0
-rw-r--r--freebsd/sys/sys/ttyhook.h (renamed from freebsd/sys/ttyhook.h)0
-rw-r--r--freebsd/sys/sys/ttyqueue.h (renamed from freebsd/sys/ttyqueue.h)0
-rw-r--r--freebsd/sys/sys/ucred.h (renamed from freebsd/sys/ucred.h)0
-rw-r--r--freebsd/sys/sys/un.h70
-rw-r--r--freebsd/sys/sys/user.h (renamed from freebsd/sys/user.h)0
-rw-r--r--freebsd/sys/sys/vmmeter.h (renamed from freebsd/sys/vmmeter.h)0
-rw-r--r--freebsd/sys/syscallsubr.h1
-rw-r--r--freebsd/sys/sysent.h1
-rw-r--r--freebsd/sys/sysproto.h1
-rw-r--r--freebsd/sys/time.h351
-rw-r--r--freebsd/sys/types.h360
-rw-r--r--freebsd/sys/ucontext.h1
-rw-r--r--freebsd/sys/unistd.h188
-rw-r--r--freebsd/sys/vm/uma.h (renamed from freebsd/vm/uma.h)0
-rw-r--r--freebsd/sys/vm/uma_core.c (renamed from freebsd/vm/uma_core.c)0
-rw-r--r--freebsd/sys/vm/uma_dbg.h (renamed from freebsd/vm/uma_dbg.h)0
-rw-r--r--freebsd/sys/vm/uma_int.h (renamed from freebsd/vm/uma_int.h)0
-rw-r--r--freebsd/sys/vm/vm.h (renamed from freebsd/vm/vm.h)0
-rw-r--r--freebsd/sys/vnode.h1
-rw-r--r--freebsd/usr.bin/netstat/atalk.c293
-rw-r--r--freebsd/usr.bin/netstat/bpf.c158
-rw-r--r--freebsd/usr.bin/netstat/if.c752
-rw-r--r--freebsd/usr.bin/netstat/inet.c1312
-rw-r--r--freebsd/usr.bin/netstat/inet6.c1175
-rw-r--r--freebsd/usr.bin/netstat/ipsec.c481
-rw-r--r--freebsd/usr.bin/netstat/main.c1229
-rw-r--r--freebsd/usr.bin/netstat/mbuf.c323
-rw-r--r--freebsd/usr.bin/netstat/mroute.c391
-rw-r--r--freebsd/usr.bin/netstat/mroute6.c279
-rw-r--r--freebsd/usr.bin/netstat/netstat.h179
-rw-r--r--freebsd/usr.bin/netstat/pfkey.c184
-rw-r--r--freebsd/usr.bin/netstat/route.c1173
-rw-r--r--freebsd/usr.bin/netstat/sctp.c703
-rw-r--r--freebsd/usr.bin/netstat/unix.c302
-rw-r--r--freebsd/vm/pmap.h1
-rw-r--r--freebsd/vm/vm_map.h1
-rw-r--r--freebsd/vm/vm_param.h1
1156 files changed, 124226 insertions, 25686 deletions
diff --git a/freebsd/cam/cam_queue.h b/freebsd/cam/cam_queue.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/cam/cam_queue.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/ddb/db_sym.h b/freebsd/ddb/db_sym.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/ddb/db_sym.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/ddb/ddb.h b/freebsd/ddb/ddb.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/ddb/ddb.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/geom/geom_disk.h b/freebsd/geom/geom_disk.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/geom/geom_disk.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/include/arpa/ftp.h b/freebsd/include/arpa/ftp.h
new file mode 100644
index 00000000..9a364885
--- /dev/null
+++ b/freebsd/include/arpa/ftp.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ *
+ * @(#)ftp.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _ARPA_FTP_H_
+#define _ARPA_FTP_H_
+
+/* Definitions for FTP; see RFC-765. */
+
+/*
+ * Reply codes.
+ */
+#define PRELIM 1 /* positive preliminary */
+#define COMPLETE 2 /* positive completion */
+#define CONTINUE 3 /* positive intermediate */
+#define TRANSIENT 4 /* transient negative completion */
+#define ERROR 5 /* permanent negative completion */
+
+/*
+ * Type codes
+ */
+#define TYPE_A 1 /* ASCII */
+#define TYPE_E 2 /* EBCDIC */
+#define TYPE_I 3 /* image */
+#define TYPE_L 4 /* local byte size */
+
+#ifdef FTP_NAMES
+char *typenames[] = {"0", "ASCII", "EBCDIC", "Image", "Local" };
+#endif
+
+/*
+ * Form codes
+ */
+#define FORM_N 1 /* non-print */
+#define FORM_T 2 /* telnet format effectors */
+#define FORM_C 3 /* carriage control (ASA) */
+#ifdef FTP_NAMES
+char *formnames[] = {"0", "Nonprint", "Telnet", "Carriage-control" };
+#endif
+
+/*
+ * Structure codes
+ */
+#define STRU_F 1 /* file (no record structure) */
+#define STRU_R 2 /* record structure */
+#define STRU_P 3 /* page structure */
+#ifdef FTP_NAMES
+char *strunames[] = {"0", "File", "Record", "Page" };
+#endif
+
+/*
+ * Mode types
+ */
+#define MODE_S 1 /* stream */
+#define MODE_B 2 /* block */
+#define MODE_C 3 /* compressed */
+#ifdef FTP_NAMES
+char *modenames[] = {"0", "Stream", "Block", "Compressed" };
+#endif
+
+/*
+ * Record Tokens
+ */
+#define REC_ESC '\377' /* Record-mode Escape */
+#define REC_EOR '\001' /* Record-mode End-of-Record */
+#define REC_EOF '\002' /* Record-mode End-of-File */
+
+/*
+ * Block Header
+ */
+#define BLK_EOR 0x80 /* Block is End-of-Record */
+#define BLK_EOF 0x40 /* Block is End-of-File */
+#define BLK_ERRORS 0x20 /* Block is suspected of containing errors */
+#define BLK_RESTART 0x10 /* Block is Restart Marker */
+
+#define BLK_BYTECOUNT 2 /* Bytes in this block */
+
+#endif /* !_FTP_H_ */
diff --git a/freebsd/include/arpa/inet.h b/freebsd/include/arpa/inet.h
new file mode 100644
index 00000000..91733a9c
--- /dev/null
+++ b/freebsd/include/arpa/inet.h
@@ -0,0 +1,182 @@
+/*
+ * ++Copyright++ 1983, 1993
+ * -
+ * Copyright (c) 1983, 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+
+/*%
+ * @(#)inet.h 8.1 (Berkeley) 6/2/93
+ * $Id: inet.h,v 1.2.18.1 2005/04/27 05:00:50 sra Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _ARPA_INET_H_
+#define _ARPA_INET_H_
+
+/* External definitions for functions in inet(3). */
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+/* Required for byteorder(3) functions. */
+#include <machine/endian.h>
+
+#define INET_ADDRSTRLEN 16
+#define INET6_ADDRSTRLEN 46
+
+#ifndef _UINT16_T_DECLARED
+typedef __uint16_t uint16_t;
+#define _UINT16_T_DECLARED
+#endif
+
+#ifndef _UINT32_T_DECLARED
+typedef __uint32_t uint32_t;
+#define _UINT32_T_DECLARED
+#endif
+
+#ifndef _IN_ADDR_T_DECLARED
+typedef uint32_t in_addr_t;
+#define _IN_ADDR_T_DECLARED
+#endif
+
+#ifndef _IN_PORT_T_DECLARED
+typedef uint16_t in_port_t;
+#define _IN_PORT_T_DECLARED
+#endif
+
+#if __BSD_VISIBLE
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+#endif
+
+/*
+ * XXX socklen_t is used by a POSIX.1-2001 interface, but not required by
+ * POSIX.1-2001.
+ */
+#ifndef _SOCKLEN_T_DECLARED
+typedef __socklen_t socklen_t;
+#define _SOCKLEN_T_DECLARED
+#endif
+
+#ifndef _STRUCT_IN_ADDR_DECLARED
+struct in_addr {
+ in_addr_t s_addr;
+};
+#define _STRUCT_IN_ADDR_DECLARED
+#endif
+
+/* XXX all new diversions!! argh!! */
+#if __BSD_VISIBLE
+#define inet_addr __inet_addr
+#define inet_aton __inet_aton
+#define inet_lnaof __inet_lnaof
+#define inet_makeaddr __inet_makeaddr
+#define inet_neta __inet_neta
+#define inet_netof __inet_netof
+#define inet_network __inet_network
+#define inet_net_ntop __inet_net_ntop
+#define inet_net_pton __inet_net_pton
+#define inet_cidr_ntop __inet_cidr_ntop
+#define inet_cidr_pton __inet_cidr_pton
+#define inet_ntoa __inet_ntoa
+#define inet_ntoa_r __inet_ntoa_r
+#define inet_pton __inet_pton
+#define inet_ntop __inet_ntop
+#define inet_nsap_addr __inet_nsap_addr
+#define inet_nsap_ntoa __inet_nsap_ntoa
+#endif /* __BSD_VISIBLE */
+
+__BEGIN_DECLS
+#ifndef _BYTEORDER_PROTOTYPED
+#define _BYTEORDER_PROTOTYPED
+uint32_t htonl(uint32_t);
+uint16_t htons(uint16_t);
+uint32_t ntohl(uint32_t);
+uint16_t ntohs(uint16_t);
+#endif
+
+in_addr_t inet_addr(const char *);
+/*const*/ char *inet_ntoa(struct in_addr);
+const char *inet_ntop(int, const void * __restrict, char * __restrict,
+ socklen_t);
+int inet_pton(int, const char * __restrict, void * __restrict);
+
+#if __BSD_VISIBLE
+int inet_aton(const char *, struct in_addr *);
+in_addr_t inet_lnaof(struct in_addr);
+struct in_addr inet_makeaddr(in_addr_t, in_addr_t);
+char * inet_neta(in_addr_t, char *, size_t);
+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);
+char *inet_nsap_ntoa(int, const unsigned char *, char *);
+#endif /* __BSD_VISIBLE */
+__END_DECLS
+
+#ifndef _BYTEORDER_FUNC_DEFINED
+#define _BYTEORDER_FUNC_DEFINED
+#define htonl(x) __htonl(x)
+#define htons(x) __htons(x)
+#define ntohl(x) __ntohl(x)
+#define ntohs(x) __ntohs(x)
+#endif
+
+#endif /* !_ARPA_INET_H_ */
+
+/*! \file */
diff --git a/freebsd/include/arpa/nameser.h b/freebsd/include/arpa/nameser.h
new file mode 100644
index 00000000..ce2f2e06
--- /dev/null
+++ b/freebsd/include/arpa/nameser.h
@@ -0,0 +1,584 @@
+/*
+ * Copyright (c) 1983, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id: nameser.h,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _ARPA_NAMESER_H_
+#define _ARPA_NAMESER_H_
+
+/*! \file */
+
+#define BIND_4_COMPAT
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+/*%
+ * Revision information. This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not
+ * compare for equality; rather, use it to determine whether your libbind.a
+ * contains a new enough lib/nameser/ to support the feature you need.
+ */
+
+#define __NAMESER 19991006 /*%< New interface version stamp. */
+/*
+ * Define constants based on RFC0883, RFC1034, RFC 1035
+ */
+#define NS_PACKETSZ 512 /*%< default UDP packet size */
+#define NS_MAXDNAME 1025 /*%< maximum domain name */
+#define NS_MAXMSG 65535 /*%< maximum message size */
+#define NS_MAXCDNAME 255 /*%< maximum compressed domain name */
+#define NS_MAXLABEL 63 /*%< maximum length of domain label */
+#define NS_HFIXEDSZ 12 /*%< #/bytes of fixed data in header */
+#define NS_QFIXEDSZ 4 /*%< #/bytes of fixed data in query */
+#define NS_RRFIXEDSZ 10 /*%< #/bytes of fixed data in r record */
+#define NS_INT32SZ 4 /*%< #/bytes of data in a u_int32_t */
+#define NS_INT16SZ 2 /*%< #/bytes of data in a u_int16_t */
+#define NS_INT8SZ 1 /*%< #/bytes of data in a u_int8_t */
+#define NS_INADDRSZ 4 /*%< IPv4 T_A */
+#define NS_IN6ADDRSZ 16 /*%< IPv6 T_AAAA */
+#define NS_CMPRSFLGS 0xc0 /*%< Flag bits indicating name compression. */
+#define NS_DEFAULTPORT 53 /*%< For both TCP and UDP. */
+/*
+ * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord()
+ * in synch with it.
+ */
+typedef enum __ns_sect {
+ ns_s_qd = 0, /*%< Query: Question. */
+ ns_s_zn = 0, /*%< Update: Zone. */
+ ns_s_an = 1, /*%< Query: Answer. */
+ ns_s_pr = 1, /*%< Update: Prerequisites. */
+ ns_s_ns = 2, /*%< Query: Name servers. */
+ ns_s_ud = 2, /*%< Update: Update. */
+ ns_s_ar = 3, /*%< Query|Update: Additional records. */
+ ns_s_max = 4
+} ns_sect;
+
+/*%
+ * This is a message handle. It is caller allocated and has no dynamic data.
+ * This structure is intended to be opaque to all but ns_parse.c, thus the
+ * leading _'s on the member names. Use the accessor functions, not the _'s.
+ */
+typedef struct __ns_msg {
+ const u_char *_msg, *_eom;
+ u_int16_t _id, _flags, _counts[ns_s_max];
+ const u_char *_sections[ns_s_max];
+ ns_sect _sect;
+ int _rrnum;
+ const u_char *_msg_ptr;
+} ns_msg;
+
+/* Private data structure - do not use from outside library. */
+struct _ns_flagdata { int mask, shift; };
+extern struct _ns_flagdata _ns_flagdata[];
+
+/* Accessor macros - this is part of the public interface. */
+
+#define ns_msg_id(handle) ((handle)._id + 0)
+#define ns_msg_base(handle) ((handle)._msg + 0)
+#define ns_msg_end(handle) ((handle)._eom + 0)
+#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
+#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
+
+/*%
+ * This is a parsed record. It is caller allocated and has no dynamic data.
+ */
+typedef struct __ns_rr {
+ char name[NS_MAXDNAME];
+ u_int16_t type;
+ u_int16_t rr_class;
+ u_int32_t ttl;
+ u_int16_t rdlength;
+ const u_char * rdata;
+} ns_rr;
+
+/* Accessor macros - this is part of the public interface. */
+#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
+#define ns_rr_type(rr) ((ns_type)((rr).type + 0))
+#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0))
+#define ns_rr_ttl(rr) ((rr).ttl + 0)
+#define ns_rr_rdlen(rr) ((rr).rdlength + 0)
+#define ns_rr_rdata(rr) ((rr).rdata + 0)
+
+/*%
+ * These don't have to be in the same order as in the packet flags word,
+ * and they can even overlap in some cases, but they will need to be kept
+ * in synch with ns_parse.c:ns_flagdata[].
+ */
+typedef enum __ns_flag {
+ ns_f_qr, /*%< Question/Response. */
+ ns_f_opcode, /*%< Operation code. */
+ ns_f_aa, /*%< Authoritative Answer. */
+ ns_f_tc, /*%< Truncation occurred. */
+ ns_f_rd, /*%< Recursion Desired. */
+ ns_f_ra, /*%< Recursion Available. */
+ ns_f_z, /*%< MBZ. */
+ ns_f_ad, /*%< Authentic Data (DNSSEC). */
+ ns_f_cd, /*%< Checking Disabled (DNSSEC). */
+ ns_f_rcode, /*%< Response code. */
+ ns_f_max
+} ns_flag;
+
+/*%
+ * Currently defined opcodes.
+ */
+typedef enum __ns_opcode {
+ ns_o_query = 0, /*%< Standard query. */
+ ns_o_iquery = 1, /*%< Inverse query (deprecated/unsupported). */
+ ns_o_status = 2, /*%< Name server status query (unsupported). */
+ /* Opcode 3 is undefined/reserved. */
+ ns_o_notify = 4, /*%< Zone change notification. */
+ ns_o_update = 5, /*%< Zone update message. */
+ ns_o_max = 6
+} ns_opcode;
+
+/*%
+ * Currently defined response codes.
+ */
+typedef enum __ns_rcode {
+ ns_r_noerror = 0, /*%< No error occurred. */
+ ns_r_formerr = 1, /*%< Format error. */
+ ns_r_servfail = 2, /*%< Server failure. */
+ ns_r_nxdomain = 3, /*%< Name error. */
+ ns_r_notimpl = 4, /*%< Unimplemented. */
+ ns_r_refused = 5, /*%< Operation refused. */
+ /* these are for BIND_UPDATE */
+ ns_r_yxdomain = 6, /*%< Name exists */
+ ns_r_yxrrset = 7, /*%< RRset exists */
+ ns_r_nxrrset = 8, /*%< RRset does not exist */
+ ns_r_notauth = 9, /*%< Not authoritative for zone */
+ ns_r_notzone = 10, /*%< Zone of record different from zone section */
+ ns_r_max = 11,
+ /* The following are EDNS extended rcodes */
+ ns_r_badvers = 16,
+ /* The following are TSIG errors */
+ ns_r_badsig = 16,
+ ns_r_badkey = 17,
+ ns_r_badtime = 18
+} ns_rcode;
+
+/* BIND_UPDATE */
+typedef enum __ns_update_operation {
+ ns_uop_delete = 0,
+ ns_uop_add = 1,
+ ns_uop_max = 2
+} ns_update_operation;
+
+/*%
+ * This structure is used for TSIG authenticated messages
+ */
+struct ns_tsig_key {
+ char name[NS_MAXDNAME], alg[NS_MAXDNAME];
+ unsigned char *data;
+ int len;
+};
+typedef struct ns_tsig_key ns_tsig_key;
+
+/*%
+ * This structure is used for TSIG authenticated TCP messages
+ */
+struct ns_tcp_tsig_state {
+ int counter;
+ struct dst_key *key;
+ void *ctx;
+ unsigned char sig[NS_PACKETSZ];
+ int siglen;
+};
+typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
+
+#define NS_TSIG_FUDGE 300
+#define NS_TSIG_TCP_COUNT 100
+#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
+
+#define NS_TSIG_ERROR_NO_TSIG -10
+#define NS_TSIG_ERROR_NO_SPACE -11
+#define NS_TSIG_ERROR_FORMERR -12
+
+/*%
+ * Currently defined type values for resources and queries.
+ */
+typedef enum __ns_type {
+ ns_t_invalid = 0, /*%< Cookie. */
+ ns_t_a = 1, /*%< Host address. */
+ ns_t_ns = 2, /*%< Authoritative server. */
+ ns_t_md = 3, /*%< Mail destination. */
+ ns_t_mf = 4, /*%< Mail forwarder. */
+ ns_t_cname = 5, /*%< Canonical name. */
+ ns_t_soa = 6, /*%< Start of authority zone. */
+ ns_t_mb = 7, /*%< Mailbox domain name. */
+ ns_t_mg = 8, /*%< Mail group member. */
+ ns_t_mr = 9, /*%< Mail rename name. */
+ ns_t_null = 10, /*%< Null resource record. */
+ ns_t_wks = 11, /*%< Well known service. */
+ ns_t_ptr = 12, /*%< Domain name pointer. */
+ ns_t_hinfo = 13, /*%< Host information. */
+ ns_t_minfo = 14, /*%< Mailbox information. */
+ ns_t_mx = 15, /*%< Mail routing information. */
+ ns_t_txt = 16, /*%< Text strings. */
+ ns_t_rp = 17, /*%< Responsible person. */
+ ns_t_afsdb = 18, /*%< AFS cell database. */
+ ns_t_x25 = 19, /*%< X_25 calling address. */
+ ns_t_isdn = 20, /*%< ISDN calling address. */
+ ns_t_rt = 21, /*%< Router. */
+ ns_t_nsap = 22, /*%< NSAP address. */
+ ns_t_nsap_ptr = 23, /*%< Reverse NSAP lookup (deprecated). */
+ ns_t_sig = 24, /*%< Security signature. */
+ ns_t_key = 25, /*%< Security key. */
+ ns_t_px = 26, /*%< X.400 mail mapping. */
+ ns_t_gpos = 27, /*%< Geographical position (withdrawn). */
+ ns_t_aaaa = 28, /*%< Ip6 Address. */
+ ns_t_loc = 29, /*%< Location Information. */
+ ns_t_nxt = 30, /*%< Next domain (security). */
+ ns_t_eid = 31, /*%< Endpoint identifier. */
+ ns_t_nimloc = 32, /*%< Nimrod Locator. */
+ ns_t_srv = 33, /*%< Server Selection. */
+ ns_t_atma = 34, /*%< ATM Address */
+ ns_t_naptr = 35, /*%< Naming Authority PoinTeR */
+ ns_t_kx = 36, /*%< Key Exchange */
+ ns_t_cert = 37, /*%< Certification record */
+ ns_t_a6 = 38, /*%< IPv6 address (deprecates AAAA) */
+ ns_t_dname = 39, /*%< Non-terminal DNAME (for IPv6) */
+ ns_t_sink = 40, /*%< Kitchen sink (experimentatl) */
+ ns_t_opt = 41, /*%< EDNS0 option (meta-RR) */
+ ns_t_apl = 42, /*%< Address prefix list (RFC3123) */
+ ns_t_tkey = 249, /*%< Transaction key */
+ ns_t_tsig = 250, /*%< Transaction signature. */
+ ns_t_ixfr = 251, /*%< Incremental zone transfer. */
+ ns_t_axfr = 252, /*%< Transfer zone of authority. */
+ ns_t_mailb = 253, /*%< Transfer mailbox records. */
+ ns_t_maila = 254, /*%< Transfer mail agent records. */
+ ns_t_any = 255, /*%< Wildcard match. */
+ ns_t_zxfr = 256, /*%< BIND-specific, nonstandard. */
+ ns_t_max = 65536
+} ns_type;
+
+/* Exclusively a QTYPE? (not also an RTYPE) */
+#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
+ (t) == ns_t_mailb || (t) == ns_t_maila)
+/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */
+#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
+/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */
+#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
+#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
+#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
+ (t) == ns_t_zxfr)
+
+/*%
+ * Values for class field
+ */
+typedef enum __ns_class {
+ ns_c_invalid = 0, /*%< Cookie. */
+ ns_c_in = 1, /*%< Internet. */
+ ns_c_2 = 2, /*%< unallocated/unsupported. */
+ ns_c_chaos = 3, /*%< MIT Chaos-net. */
+ ns_c_hs = 4, /*%< MIT Hesiod. */
+ /* Query class values which do not appear in resource records */
+ ns_c_none = 254, /*%< for prereq. sections in update requests */
+ ns_c_any = 255, /*%< Wildcard match. */
+ ns_c_max = 65536
+} ns_class;
+
+/* DNSSEC constants. */
+
+typedef enum __ns_key_types {
+ ns_kt_rsa = 1, /*%< key type RSA/MD5 */
+ ns_kt_dh = 2, /*%< Diffie Hellman */
+ ns_kt_dsa = 3, /*%< Digital Signature Standard (MANDATORY) */
+ ns_kt_private = 254 /*%< Private key type starts with OID */
+} ns_key_types;
+
+typedef enum __ns_cert_types {
+ cert_t_pkix = 1, /*%< PKIX (X.509v3) */
+ cert_t_spki = 2, /*%< SPKI */
+ cert_t_pgp = 3, /*%< PGP */
+ cert_t_url = 253, /*%< URL private type */
+ cert_t_oid = 254 /*%< OID private type */
+} ns_cert_types;
+
+/* Flags field of the KEY RR rdata. */
+#define NS_KEY_TYPEMASK 0xC000 /*%< Mask for "type" bits */
+#define NS_KEY_TYPE_AUTH_CONF 0x0000 /*%< Key usable for both */
+#define NS_KEY_TYPE_CONF_ONLY 0x8000 /*%< Key usable for confidentiality */
+#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /*%< Key usable for authentication */
+#define NS_KEY_TYPE_NO_KEY 0xC000 /*%< No key usable for either; no key */
+/* The type bits can also be interpreted independently, as single bits: */
+#define NS_KEY_NO_AUTH 0x8000 /*%< Key unusable for authentication */
+#define NS_KEY_NO_CONF 0x4000 /*%< Key unusable for confidentiality */
+#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */
+#define NS_KEY_EXTENDED_FLAGS 0x1000 /*%< reserved - must be zero */
+#define NS_KEY_RESERVED4 0x0800 /*%< reserved - must be zero */
+#define NS_KEY_RESERVED5 0x0400 /*%< reserved - must be zero */
+#define NS_KEY_NAME_TYPE 0x0300 /*%< these bits determine the type */
+#define NS_KEY_NAME_USER 0x0000 /*%< key is assoc. with user */
+#define NS_KEY_NAME_ENTITY 0x0200 /*%< key is assoc. with entity eg host */
+#define NS_KEY_NAME_ZONE 0x0100 /*%< key is zone key */
+#define NS_KEY_NAME_RESERVED 0x0300 /*%< reserved meaning */
+#define NS_KEY_RESERVED8 0x0080 /*%< reserved - must be zero */
+#define NS_KEY_RESERVED9 0x0040 /*%< reserved - must be zero */
+#define NS_KEY_RESERVED10 0x0020 /*%< reserved - must be zero */
+#define NS_KEY_RESERVED11 0x0010 /*%< reserved - must be zero */
+#define NS_KEY_SIGNATORYMASK 0x000F /*%< key can sign RR's of same name */
+#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
+ NS_KEY_RESERVED4 | \
+ NS_KEY_RESERVED5 | \
+ NS_KEY_RESERVED8 | \
+ NS_KEY_RESERVED9 | \
+ NS_KEY_RESERVED10 | \
+ NS_KEY_RESERVED11 )
+#define NS_KEY_RESERVED_BITMASK2 0xFFFF /*%< no bits defined here */
+/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
+#define NS_ALG_MD5RSA 1 /*%< MD5 with RSA */
+#define NS_ALG_DH 2 /*%< Diffie Hellman KEY */
+#define NS_ALG_DSA 3 /*%< DSA KEY */
+#define NS_ALG_DSS NS_ALG_DSA
+#define NS_ALG_EXPIRE_ONLY 253 /*%< No alg, no security */
+#define NS_ALG_PRIVATE_OID 254 /*%< Key begins with OID giving alg */
+/* Protocol values */
+/* value 0 is reserved */
+#define NS_KEY_PROT_TLS 1
+#define NS_KEY_PROT_EMAIL 2
+#define NS_KEY_PROT_DNSSEC 3
+#define NS_KEY_PROT_IPSEC 4
+#define NS_KEY_PROT_ANY 255
+
+/* Signatures */
+#define NS_MD5RSA_MIN_BITS 512 /*%< Size of a mod or exp in bits */
+#define NS_MD5RSA_MAX_BITS 4096
+ /* Total of binary mod and exp */
+#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
+ /* Max length of text sig block */
+#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
+#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8)
+#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8)
+
+#define NS_DSA_SIG_SIZE 41
+#define NS_DSA_MIN_SIZE 213
+#define NS_DSA_MAX_BYTES 405
+
+/* Offsets into SIG record rdata to find various values */
+#define NS_SIG_TYPE 0 /*%< Type flags */
+#define NS_SIG_ALG 2 /*%< Algorithm */
+#define NS_SIG_LABELS 3 /*%< How many labels in name */
+#define NS_SIG_OTTL 4 /*%< Original TTL */
+#define NS_SIG_EXPIR 8 /*%< Expiration time */
+#define NS_SIG_SIGNED 12 /*%< Signature time */
+#define NS_SIG_FOOT 16 /*%< Key footprint */
+#define NS_SIG_SIGNER 18 /*%< Domain name of who signed it */
+/* How RR types are represented as bit-flags in NXT records */
+#define NS_NXT_BITS 8
+#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS)))
+#define NS_NXT_MAX 127
+
+/*%
+ * EDNS0 extended flags and option codes, host order.
+ */
+#define NS_OPT_DNSSEC_OK 0x8000U
+#define NS_OPT_NSID 3
+
+/*%
+ * Inline versions of get/put short/long. Pointer is advanced.
+ */
+#define NS_GET16(s, cp) do { \
+ register const u_char *t_cp = (const u_char *)(cp); \
+ (s) = ((u_int16_t)t_cp[0] << 8) \
+ | ((u_int16_t)t_cp[1]) \
+ ; \
+ (cp) += NS_INT16SZ; \
+} while (0)
+
+#define NS_GET32(l, cp) do { \
+ register const u_char *t_cp = (const u_char *)(cp); \
+ (l) = ((u_int32_t)t_cp[0] << 24) \
+ | ((u_int32_t)t_cp[1] << 16) \
+ | ((u_int32_t)t_cp[2] << 8) \
+ | ((u_int32_t)t_cp[3]) \
+ ; \
+ (cp) += NS_INT32SZ; \
+} while (0)
+
+#define NS_PUT16(s, cp) do { \
+ register u_int16_t t_s = (u_int16_t)(s); \
+ register u_char *t_cp = (u_char *)(cp); \
+ *t_cp++ = t_s >> 8; \
+ *t_cp = t_s; \
+ (cp) += NS_INT16SZ; \
+} while (0)
+
+#define NS_PUT32(l, cp) do { \
+ register u_int32_t t_l = (u_int32_t)(l); \
+ register u_char *t_cp = (u_char *)(cp); \
+ *t_cp++ = t_l >> 24; \
+ *t_cp++ = t_l >> 16; \
+ *t_cp++ = t_l >> 8; \
+ *t_cp = t_l; \
+ (cp) += NS_INT32SZ; \
+} while (0)
+
+/*%
+ * ANSI C identifier hiding for bind's lib/nameser.
+ */
+#define ns_msg_getflag __ns_msg_getflag
+#define ns_get16 __ns_get16
+#define ns_get32 __ns_get32
+#define ns_put16 __ns_put16
+#define ns_put32 __ns_put32
+#define ns_initparse __ns_initparse
+#define ns_skiprr __ns_skiprr
+#define ns_parserr __ns_parserr
+#define ns_sprintrr __ns_sprintrr
+#define ns_sprintrrf __ns_sprintrrf
+#define ns_format_ttl __ns_format_ttl
+#define ns_parse_ttl __ns_parse_ttl
+#if 0
+#define ns_datetosecs __ns_datetosecs
+#endif
+#define ns_name_ntol __ns_name_ntol
+#define ns_name_ntop __ns_name_ntop
+#define ns_name_pton __ns_name_pton
+#define ns_name_unpack __ns_name_unpack
+#define ns_name_pack __ns_name_pack
+#define ns_name_compress __ns_name_compress
+#define ns_name_uncompress __ns_name_uncompress
+#define ns_name_skip __ns_name_skip
+#define ns_name_rollback __ns_name_rollback
+#if 0
+#define ns_sign __ns_sign
+#define ns_sign2 __ns_sign2
+#define ns_sign_tcp __ns_sign_tcp
+#define ns_sign_tcp2 __ns_sign_tcp2
+#define ns_sign_tcp_init __ns_sign_tcp_init
+#define ns_find_tsig __ns_find_tsig
+#define ns_verify __ns_verify
+#define ns_verify_tcp __ns_verify_tcp
+#define ns_verify_tcp_init __ns_verify_tcp_init
+#endif
+#define ns_samedomain __ns_samedomain
+#if 0
+#define ns_subdomain __ns_subdomain
+#endif
+#define ns_makecanon __ns_makecanon
+#define ns_samename __ns_samename
+
+__BEGIN_DECLS
+int ns_msg_getflag(ns_msg, int);
+u_int ns_get16(const u_char *);
+u_long ns_get32(const u_char *);
+void ns_put16(u_int, u_char *);
+void ns_put32(u_long, u_char *);
+int ns_initparse(const u_char *, int, ns_msg *);
+int ns_skiprr(const u_char *, const u_char *, ns_sect, int);
+int ns_parserr(ns_msg *, ns_sect, int, ns_rr *);
+int ns_sprintrr(const ns_msg *, const ns_rr *,
+ const char *, const char *, char *, size_t);
+int ns_sprintrrf(const u_char *, size_t, const char *,
+ ns_class, ns_type, u_long, const u_char *,
+ size_t, const char *, const char *,
+ char *, size_t);
+int ns_format_ttl(u_long, char *, size_t);
+int ns_parse_ttl(const char *, u_long *);
+#if 0
+u_int32_t ns_datetosecs(const char *cp, int *errp);
+#endif
+int ns_name_ntol(const u_char *, u_char *, size_t);
+int ns_name_ntop(const u_char *, char *, size_t);
+int ns_name_pton(const char *, u_char *, size_t);
+int ns_name_unpack(const u_char *, const u_char *,
+ const u_char *, u_char *, size_t);
+int ns_name_pack(const u_char *, u_char *, int,
+ const u_char **, const u_char **);
+int ns_name_uncompress(const u_char *, const u_char *,
+ const u_char *, char *, size_t);
+int ns_name_compress(const char *, u_char *, size_t,
+ const u_char **, const u_char **);
+int ns_name_skip(const u_char **, const u_char *);
+void ns_name_rollback(const u_char *, const u_char **,
+ const u_char **);
+#if 0
+int ns_sign(u_char *, int *, int, int, void *,
+ const u_char *, int, u_char *, int *, time_t);
+int ns_sign2(u_char *, int *, int, int, void *,
+ const u_char *, int, u_char *, int *, time_t,
+ u_char **, u_char **);
+int ns_sign_tcp(u_char *, int *, int, int,
+ ns_tcp_tsig_state *, int);
+int ns_sign_tcp2(u_char *, int *, int, int,
+ ns_tcp_tsig_state *, int,
+ u_char **, u_char **);
+int ns_sign_tcp_init(void *, const u_char *, int,
+ ns_tcp_tsig_state *);
+u_char *ns_find_tsig(u_char *, u_char *);
+int ns_verify(u_char *, int *, void *,
+ const u_char *, int, u_char *, int *,
+ time_t *, int);
+int ns_verify_tcp(u_char *, int *, ns_tcp_tsig_state *, int);
+int ns_verify_tcp_init(void *, const u_char *, int,
+ ns_tcp_tsig_state *);
+#endif
+int ns_samedomain(const char *, const char *);
+#if 0
+int ns_subdomain(const char *, const char *);
+#endif
+int ns_makecanon(const char *, char *, size_t);
+int ns_samename(const char *, const char *);
+__END_DECLS
+
+#ifdef BIND_4_COMPAT
+#include <arpa/nameser_compat.h>
+#endif
+
+#endif /* !_ARPA_NAMESER_H_ */
+/*! \file */
diff --git a/freebsd/include/arpa/nameser_compat.h b/freebsd/include/arpa/nameser_compat.h
new file mode 100644
index 00000000..c7c5b95a
--- /dev/null
+++ b/freebsd/include/arpa/nameser_compat.h
@@ -0,0 +1,203 @@
+/* Copyright (c) 1983, 1989
+ * 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 nameser.h 8.1 (Berkeley) 6/2/93
+ * $Id: nameser_compat.h,v 1.5.18.3 2006/05/19 02:36:00 marka Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _ARPA_NAMESER_COMPAT_
+#define _ARPA_NAMESER_COMPAT_
+
+#define __BIND 19950621 /*%< (DEAD) interface version stamp. */
+
+#include <freebsd/machine/endian.h>
+
+#if !defined(_BYTE_ORDER) || \
+ (_BYTE_ORDER != _BIG_ENDIAN && _BYTE_ORDER != _LITTLE_ENDIAN && \
+ _BYTE_ORDER != _PDP_ENDIAN)
+ /* you must determine what the correct bit order is for
+ * your compiler - the next line is an intentional error
+ * which will force your compiles to bomb until you fix
+ * the above macros.
+ */
+#error "Undefined or invalid _BYTE_ORDER";
+#endif
+
+/*%
+ * Structure for query header. The order of the fields is machine- and
+ * compiler-dependent, depending on the byte/bit order and the layout
+ * of bit fields. We use bit fields only in int variables, as this
+ * is all ANSI requires. This requires a somewhat confusing rearrangement.
+ */
+
+typedef struct {
+ unsigned id :16; /*%< query identification number */
+#if _BYTE_ORDER == _BIG_ENDIAN
+ /* fields in third byte */
+ unsigned qr: 1; /*%< response flag */
+ unsigned opcode: 4; /*%< purpose of message */
+ unsigned aa: 1; /*%< authoritive answer */
+ unsigned tc: 1; /*%< truncated message */
+ unsigned rd: 1; /*%< recursion desired */
+ /* fields in fourth byte */
+ unsigned ra: 1; /*%< recursion available */
+ unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */
+ unsigned ad: 1; /*%< authentic data from named */
+ unsigned cd: 1; /*%< checking disabled by resolver */
+ unsigned rcode :4; /*%< response code */
+#endif
+#if _BYTE_ORDER == _LITTLE_ENDIAN || _BYTE_ORDER == _PDP_ENDIAN
+ /* fields in third byte */
+ unsigned rd :1; /*%< recursion desired */
+ unsigned tc :1; /*%< truncated message */
+ unsigned aa :1; /*%< authoritive answer */
+ unsigned opcode :4; /*%< purpose of message */
+ unsigned qr :1; /*%< response flag */
+ /* fields in fourth byte */
+ unsigned rcode :4; /*%< response code */
+ unsigned cd: 1; /*%< checking disabled by resolver */
+ unsigned ad: 1; /*%< authentic data from named */
+ unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */
+ unsigned ra :1; /*%< recursion available */
+#endif
+ /* remaining bytes */
+ unsigned qdcount :16; /*%< number of question entries */
+ unsigned ancount :16; /*%< number of answer entries */
+ unsigned nscount :16; /*%< number of authority entries */
+ unsigned arcount :16; /*%< number of resource entries */
+} HEADER;
+
+#define PACKETSZ NS_PACKETSZ
+#define MAXDNAME NS_MAXDNAME
+#define MAXCDNAME NS_MAXCDNAME
+#define MAXLABEL NS_MAXLABEL
+#define HFIXEDSZ NS_HFIXEDSZ
+#define QFIXEDSZ NS_QFIXEDSZ
+#define RRFIXEDSZ NS_RRFIXEDSZ
+#define INT32SZ NS_INT32SZ
+#define INT16SZ NS_INT16SZ
+#define INT8SZ NS_INT8SZ
+#define INADDRSZ NS_INADDRSZ
+#define IN6ADDRSZ NS_IN6ADDRSZ
+#define INDIR_MASK NS_CMPRSFLGS
+#define NAMESERVER_PORT NS_DEFAULTPORT
+
+#define S_ZONE ns_s_zn
+#define S_PREREQ ns_s_pr
+#define S_UPDATE ns_s_ud
+#define S_ADDT ns_s_ar
+
+#define QUERY ns_o_query
+#define IQUERY ns_o_iquery
+#define STATUS ns_o_status
+#define NS_NOTIFY_OP ns_o_notify
+#define NS_UPDATE_OP ns_o_update
+
+#define NOERROR ns_r_noerror
+#define FORMERR ns_r_formerr
+#define SERVFAIL ns_r_servfail
+#define NXDOMAIN ns_r_nxdomain
+#define NOTIMP ns_r_notimpl
+#define REFUSED ns_r_refused
+#define YXDOMAIN ns_r_yxdomain
+#define YXRRSET ns_r_yxrrset
+#define NXRRSET ns_r_nxrrset
+#define NOTAUTH ns_r_notauth
+#define NOTZONE ns_r_notzone
+/*#define BADSIG ns_r_badsig*/
+/*#define BADKEY ns_r_badkey*/
+/*#define BADTIME ns_r_badtime*/
+
+
+#define DELETE ns_uop_delete
+#define ADD ns_uop_add
+
+#define T_A ns_t_a
+#define T_NS ns_t_ns
+#define T_MD ns_t_md
+#define T_MF ns_t_mf
+#define T_CNAME ns_t_cname
+#define T_SOA ns_t_soa
+#define T_MB ns_t_mb
+#define T_MG ns_t_mg
+#define T_MR ns_t_mr
+#define T_NULL ns_t_null
+#define T_WKS ns_t_wks
+#define T_PTR ns_t_ptr
+#define T_HINFO ns_t_hinfo
+#define T_MINFO ns_t_minfo
+#define T_MX ns_t_mx
+#define T_TXT ns_t_txt
+#define T_RP ns_t_rp
+#define T_AFSDB ns_t_afsdb
+#define T_X25 ns_t_x25
+#define T_ISDN ns_t_isdn
+#define T_RT ns_t_rt
+#define T_NSAP ns_t_nsap
+#define T_NSAP_PTR ns_t_nsap_ptr
+#define T_SIG ns_t_sig
+#define T_KEY ns_t_key
+#define T_PX ns_t_px
+#define T_GPOS ns_t_gpos
+#define T_AAAA ns_t_aaaa
+#define T_LOC ns_t_loc
+#define T_NXT ns_t_nxt
+#define T_EID ns_t_eid
+#define T_NIMLOC ns_t_nimloc
+#define T_SRV ns_t_srv
+#define T_ATMA ns_t_atma
+#define T_NAPTR ns_t_naptr
+#define T_A6 ns_t_a6
+#define T_OPT ns_t_opt
+#define T_TSIG ns_t_tsig
+#define T_IXFR ns_t_ixfr
+#define T_AXFR ns_t_axfr
+#define T_MAILB ns_t_mailb
+#define T_MAILA ns_t_maila
+#define T_ANY ns_t_any
+
+#define C_IN ns_c_in
+#define C_CHAOS ns_c_chaos
+#define C_HS ns_c_hs
+/* BIND_UPDATE */
+#define C_NONE ns_c_none
+#define C_ANY ns_c_any
+
+#define GETSHORT NS_GET16
+#define GETLONG NS_GET32
+#define PUTSHORT NS_PUT16
+#define PUTLONG NS_PUT32
+
+#endif /* _ARPA_NAMESER_COMPAT_ */
+/*! \file */
diff --git a/freebsd/include/db.h b/freebsd/include/db.h
new file mode 100644
index 00000000..e845fa8e
--- /dev/null
+++ b/freebsd/include/db.h
@@ -0,0 +1,221 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ *
+ * @(#)db.h 8.7 (Berkeley) 6/16/94
+ * $FreeBSD$
+ */
+
+#ifndef _DB_H_
+#define _DB_H_
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+
+#include <limits.h>
+
+#define RET_ERROR -1 /* Return values. */
+#define RET_SUCCESS 0
+#define RET_SPECIAL 1
+
+#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */
+typedef uint32_t pgno_t;
+#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */
+typedef uint16_t indx_t;
+#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */
+typedef uint32_t recno_t;
+
+/* Key/data structure -- a Data-Base Thang. */
+typedef struct {
+ void *data; /* data */
+ size_t size; /* data length */
+} DBT;
+
+/* Routine flags. */
+#define R_CURSOR 1 /* del, put, seq */
+#define __R_UNUSED 2 /* UNUSED */
+#define R_FIRST 3 /* seq */
+#define R_IAFTER 4 /* put (RECNO) */
+#define R_IBEFORE 5 /* put (RECNO) */
+#define R_LAST 6 /* seq (BTREE, RECNO) */
+#define R_NEXT 7 /* seq */
+#define R_NOOVERWRITE 8 /* put */
+#define R_PREV 9 /* seq (BTREE, RECNO) */
+#define R_SETCURSOR 10 /* put (RECNO) */
+#define R_RECNOSYNC 11 /* sync (RECNO) */
+
+typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
+
+/*
+ * !!!
+ * The following flags are included in the dbopen(3) call as part of the
+ * open(2) flags. In order to avoid conflicts with the open flags, start
+ * at the top of the 16 or 32-bit number space and work our way down. If
+ * the open flags were significantly expanded in the future, it could be
+ * a problem. Wish I'd left another flags word in the dbopen call.
+ *
+ * !!!
+ * None of this stuff is implemented yet. The only reason that it's here
+ * is so that the access methods can skip copying the key/data pair when
+ * the DB_LOCK flag isn't set.
+ */
+#if UINT_MAX > 65535
+#define DB_LOCK 0x20000000 /* Do locking. */
+#define DB_SHMEM 0x40000000 /* Use shared memory. */
+#define DB_TXN 0x80000000 /* Do transactions. */
+#else
+#define DB_LOCK 0x2000 /* Do locking. */
+#define DB_SHMEM 0x4000 /* Use shared memory. */
+#define DB_TXN 0x8000 /* Do transactions. */
+#endif
+
+/* Access method description structure. */
+typedef struct __db {
+ DBTYPE type; /* Underlying db type. */
+ int (*close)(struct __db *);
+ 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;
+
+#define BTREEMAGIC 0x053162
+#define BTREEVERSION 3
+
+/* Structure used to pass parameters to the btree routines. */
+typedef struct {
+#define R_DUP 0x01 /* duplicate keys */
+ 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
+#define HASHVERSION 2
+
+/* Structure used to pass parameters to the hashing routines. */
+typedef struct {
+ 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;
+
+/* Structure used to pass parameters to the record routines. */
+typedef struct {
+#define R_FIXEDLEN 0x01 /* fixed-length records */
+#define R_NOKEY 0x02 /* key not required */
+#define R_SNAPSHOT 0x04 /* snapshot the input */
+ 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;
+
+#ifdef __DBINTERFACE_PRIVATE
+/*
+ * Little endian <==> big endian 32-bit swap macros.
+ * M_32_SWAP swap a memory location
+ * P_32_SWAP swap a referenced memory location
+ * P_32_COPY swap from one location to another
+ */
+#define M_32_SWAP(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) { \
+ uint32_t _tmp = *(uint32_t *)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_COPY(a, b) { \
+ ((char *)&(b))[0] = ((char *)&(a))[3]; \
+ ((char *)&(b))[1] = ((char *)&(a))[2]; \
+ ((char *)&(b))[2] = ((char *)&(a))[1]; \
+ ((char *)&(b))[3] = ((char *)&(a))[0]; \
+}
+
+/*
+ * Little endian <==> big endian 16-bit swap macros.
+ * M_16_SWAP swap a memory location
+ * P_16_SWAP swap a referenced memory location
+ * P_16_COPY swap from one location to another
+ */
+#define M_16_SWAP(a) { \
+ uint16_t _tmp = a; \
+ ((char *)&a)[0] = ((char *)&_tmp)[1]; \
+ ((char *)&a)[1] = ((char *)&_tmp)[0]; \
+}
+#define P_16_SWAP(a) { \
+ uint16_t _tmp = *(uint16_t *)a; \
+ ((char *)a)[0] = ((char *)&_tmp)[1]; \
+ ((char *)a)[1] = ((char *)&_tmp)[0]; \
+}
+#define P_16_COPY(a, b) { \
+ ((char *)&(b))[0] = ((char *)&(a))[1]; \
+ ((char *)&(b))[1] = ((char *)&(a))[0]; \
+}
+#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);
+DB *__hash_open(const char *, int, int, const HASHINFO *, int);
+DB *__rec_open(const char *, int, int, const RECNOINFO *, int);
+void __dbpanic(DB *dbp);
+#endif
+__END_DECLS
+#endif /* !_DB_H_ */
diff --git a/freebsd/include/err.h b/freebsd/include/err.h
new file mode 100644
index 00000000..90c93da7
--- /dev/null
+++ b/freebsd/include/err.h
@@ -0,0 +1,86 @@
+/*-
+ * 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. 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.
+ *
+ * @(#)err.h 8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+#ifndef _ERR_H_
+#define _ERR_H_
+
+/*
+ * Don't use va_list in the err/warn prototypes. Va_list is typedef'd in two
+ * places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
+ * of them here we may collide with the utility's includes. It's unreasonable
+ * for utilities to have to include one of them to include err.h, so we get
+ * __va_list from <sys/_types.h> and use it.
+ */
+#include <freebsd/bsd.h>
+#include <sys/cdefs.h>
+#ifdef __rtems__
+#include <freebsd/sys/_types.h>
+#else
+#include <sys/_types.h>
+#endif
+
+#ifdef __rtems__
+#include <setjmp.h>
+typedef struct rtems_shell_globals_s {
+ jmp_buf exit_jmp;
+ int exit_code;
+} rtems_shell_globals_t;
+extern rtems_shell_globals_t *rtems_shell_globals;
+void rtems_shell_exit (int code);
+
+#define exit rtems_shell_exit
+#endif
+
+
+__BEGIN_DECLS
+void err(int, const char *, ...) __dead2 __printf0like(2, 3);
+void verr(int, const char *, __va_list) __dead2 __printf0like(2, 0);
+void errc(int, int, const char *, ...) __dead2 __printf0like(3, 4);
+void verrc(int, int, const char *, __va_list) __dead2
+ __printf0like(3, 0);
+void errx(int, const char *, ...) __dead2 __printf0like(2, 3);
+void verrx(int, const char *, __va_list) __dead2 __printf0like(2, 0);
+void warn(const char *, ...) __printf0like(1, 2);
+void vwarn(const char *, __va_list) __printf0like(1, 0);
+void warnc(int, const char *, ...) __printf0like(2, 3);
+void vwarnc(int, const char *, __va_list) __printf0like(2, 0);
+void warnx(const char *, ...) __printflike(1, 2);
+void vwarnx(const char *, __va_list) __printflike(1, 0);
+void err_set_file(void *);
+void err_set_exit(void (*)(int));
+__END_DECLS
+
+#endif /* !_ERR_H_ */
diff --git a/freebsd/include/ifaddrs.h b/freebsd/include/ifaddrs.h
new file mode 100644
index 00000000..f0911a48
--- /dev/null
+++ b/freebsd/include/ifaddrs.h
@@ -0,0 +1,65 @@
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 1995, 1999
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, 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 Berkeley Software Design, 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.
+ *
+ * BSDI ifaddrs.h,v 2.5 2000/02/23 14:51:59 dab Exp
+ */
+
+#ifndef _IFADDRS_H_
+#define _IFADDRS_H_
+
+struct ifaddrs {
+ struct ifaddrs *ifa_next;
+ char *ifa_name;
+ u_int ifa_flags;
+ struct sockaddr *ifa_addr;
+ struct sockaddr *ifa_netmask;
+ struct sockaddr *ifa_dstaddr;
+ void *ifa_data;
+};
+
+/*
+ * This may have been defined in <net/if.h>. Note that if <net/if.h> is
+ * to be included it must be included before this header file.
+ */
+#ifndef ifa_broadaddr
+#define ifa_broadaddr ifa_dstaddr /* broadcast address interface */
+#endif
+
+struct ifmaddrs {
+ struct ifmaddrs *ifma_next;
+ struct sockaddr *ifma_name;
+ struct sockaddr *ifma_addr;
+ struct sockaddr *ifma_lladdr;
+};
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int getifaddrs(struct ifaddrs **);
+extern void freeifaddrs(struct ifaddrs *);
+extern int getifmaddrs(struct ifmaddrs **);
+extern void freeifmaddrs(struct ifmaddrs *);
+__END_DECLS
+
+#endif
diff --git a/freebsd/include/mpool.h b/freebsd/include/mpool.h
new file mode 100644
index 00000000..c74764d7
--- /dev/null
+++ b/freebsd/include/mpool.h
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ *
+ * @(#)mpool.h 8.4 (Berkeley) 11/2/95
+ * $FreeBSD$
+ */
+
+#ifndef _MPOOL_H_
+#define _MPOOL_H_
+
+#include <sys/queue.h>
+
+/*
+ * The memory pool scheme is a simple one. Each in-memory page is referenced
+ * by a bucket which is threaded in up to two of three ways. All active pages
+ * are threaded on a hash chain (hashed by page number) and an lru chain.
+ * Inactive pages are threaded on a free chain. Each reference to a memory
+ * pool is handed an opaque MPOOL cookie which stores all of this information.
+ */
+#define HASHSIZE 128
+#define HASHKEY(pgno) ((pgno - 1 + HASHSIZE) % HASHSIZE)
+
+/* The BKT structures are the elements of the queues. */
+typedef struct _bkt {
+ TAILQ_ENTRY(_bkt) hq; /* hash queue */
+ TAILQ_ENTRY(_bkt) q; /* lru queue */
+ void *page; /* page */
+ pgno_t pgno; /* page number */
+
+#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;
+
+typedef struct MPOOL {
+ TAILQ_HEAD(_lqh, _bkt) lqh; /* lru queue head */
+ /* hash queue array */
+ TAILQ_HEAD(_hqh, _bkt) hqh[HASHSIZE];
+ 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 */
+ unsigned long pagesize; /* file page size */
+ int fd; /* file descriptor */
+ /* page in conversion routine */
+ void (*pgin)(void *, pgno_t, void *);
+ /* page out conversion routine */
+ void (*pgout)(void *, pgno_t, void *);
+ void *pgcookie; /* cookie for page in/out routines */
+#ifdef STATISTICS
+ 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 *, 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
+void mpool_stat(MPOOL *);
+#endif
+__END_DECLS
+
+#endif
diff --git a/freebsd/include/netconfig.h b/freebsd/include/netconfig.h
new file mode 100644
index 00000000..80dc0da2
--- /dev/null
+++ b/freebsd/include/netconfig.h
@@ -0,0 +1,96 @@
+/* $NetBSD: netconfig.h,v 1.1 2000/06/02 22:57:54 fvdl Exp $ */
+/* $FreeBSD$ */
+
+
+#ifndef _NETCONFIG_H_
+#define _NETCONFIG_H_
+
+#include <sys/cdefs.h>
+
+#define NETCONFIG "/etc/netconfig"
+#define NETPATH "NETPATH"
+
+struct netconfig {
+ char *nc_netid; /* Network ID */
+ unsigned long nc_semantics; /* Semantics (see below) */
+ unsigned long nc_flag; /* Flags (see below) */
+ char *nc_protofmly; /* Protocol family */
+ char *nc_proto; /* Protocol name */
+ char *nc_device; /* Network device pathname */
+ unsigned long nc_nlookups; /* Number of directory lookup libs */
+ char **nc_lookups; /* Names of the libraries */
+ unsigned long nc_unused[9]; /* reserved */
+};
+
+typedef struct {
+ struct netconfig **nc_head;
+ struct netconfig **nc_curr;
+} NCONF_HANDLE;
+
+/*
+ * nc_semantics values
+ */
+#define NC_TPI_CLTS 1
+#define NC_TPI_COTS 2
+#define NC_TPI_COTS_ORD 3
+#define NC_TPI_RAW 4
+
+/*
+ * nc_flag values
+ */
+#define NC_NOFLAG 0x00
+#define NC_VISIBLE 0x01
+#define NC_BROADCAST 0x02
+
+/*
+ * nc_protofmly values
+ */
+#define NC_NOPROTOFMLY "-"
+#define NC_LOOPBACK "loopback"
+#define NC_INET "inet"
+#define NC_INET6 "inet6"
+#define NC_IMPLINK "implink"
+#define NC_PUP "pup"
+#define NC_CHAOS "chaos"
+#define NC_NS "ns"
+#define NC_NBS "nbs"
+#define NC_ECMA "ecma"
+#define NC_DATAKIT "datakit"
+#define NC_CCITT "ccitt"
+#define NC_SNA "sna"
+#define NC_DECNET "decnet"
+#define NC_DLI "dli"
+#define NC_LAT "lat"
+#define NC_HYLINK "hylink"
+#define NC_APPLETALK "appletalk"
+#define NC_NIT "nit"
+#define NC_IEEE802 "ieee802"
+#define NC_OSI "osi"
+#define NC_X25 "x25"
+#define NC_OSINET "osinet"
+#define NC_GOSIP "gosip"
+
+/*
+ * nc_proto values
+ */
+#define NC_NOPROTO "-"
+#define NC_TCP "tcp"
+#define NC_UDP "udp"
+#define NC_ICMP "icmp"
+
+__BEGIN_DECLS
+void *setnetconfig(void);
+struct netconfig *getnetconfig(void *);
+struct netconfig *getnetconfigent(const char *);
+void freenetconfigent(struct netconfig *);
+int endnetconfig(void *);
+
+void *setnetpath(void);
+struct netconfig *getnetpath(void *);
+int endnetpath(void *);
+
+void nc_perror(const char *);
+char *nc_sperror(void);
+__END_DECLS
+
+#endif /* _NETCONFIG_H_ */
diff --git a/freebsd/include/netdb.h b/freebsd/include/netdb.h
new file mode 100644
index 00000000..c15b2845
--- /dev/null
+++ b/freebsd/include/netdb.h
@@ -0,0 +1,297 @@
+/*-
+ * Copyright (c) 1980, 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+
+/*
+ * @(#)netdb.h 8.1 (Berkeley) 6/2/93
+ * From: Id: netdb.h,v 8.9 1996/11/19 08:39:29 vixie Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _NETDB_H_
+#define _NETDB_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+
+#ifndef _SOCKLEN_T_DECLARED
+typedef __socklen_t socklen_t;
+#define _SOCKLEN_T_DECLARED
+#endif
+
+#ifndef _UINT32_T_DECLARED
+typedef __uint32_t uint32_t;
+#define _UINT32_T_DECLARED
+#endif
+
+#ifndef _PATH_HEQUIV
+# define _PATH_HEQUIV "/etc/hosts.equiv"
+#endif
+#define _PATH_HOSTS "/etc/hosts"
+#define _PATH_NETWORKS "/etc/networks"
+#define _PATH_PROTOCOLS "/etc/protocols"
+#define _PATH_SERVICES "/etc/services"
+#define _PATH_SERVICES_DB "/var/db/services.db"
+
+#define h_errno (*__h_errno())
+
+/*
+ * Structures returned by network data base library. All addresses are
+ * supplied in host order, and returned in network order (suitable for
+ * use in system calls).
+ */
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+};
+
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ int n_addrtype; /* net address type */
+ uint32_t n_net; /* network # */
+};
+
+struct servent {
+ char *s_name; /* official service name */
+ char **s_aliases; /* alias list */
+ int s_port; /* port # */
+ char *s_proto; /* protocol to use */
+};
+
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ socklen_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for hostname */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+
+/*
+ * Error return codes from gethostbyname() and gethostbyaddr()
+ * (left in h_errno).
+ */
+
+#define NETDB_INTERNAL -1 /* see errno */
+#define NETDB_SUCCESS 0 /* no problem */
+#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */
+#define TRY_AGAIN 2 /* Non-Authoritative Host not found, or SERVERFAIL */
+#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */
+#define NO_DATA 4 /* Valid name, no data record of requested type */
+#define NO_ADDRESS NO_DATA /* no address, look for MX record */
+
+/*
+ * Error return codes from getaddrinfo()
+ */
+#if 0
+/* obsoleted */
+#define EAI_ADDRFAMILY 1 /* address family for hostname not supported */
+#endif
+#define EAI_AGAIN 2 /* temporary failure in name resolution */
+#define EAI_BADFLAGS 3 /* invalid value for ai_flags */
+#define EAI_FAIL 4 /* non-recoverable failure in name resolution */
+#define EAI_FAMILY 5 /* ai_family not supported */
+#define EAI_MEMORY 6 /* memory allocation failure */
+#if 0
+/* obsoleted */
+#define EAI_NODATA 7 /* no address associated with hostname */
+#endif
+#define EAI_NONAME 8 /* hostname nor servname provided, or not known */
+#define EAI_SERVICE 9 /* servname not supported for ai_socktype */
+#define EAI_SOCKTYPE 10 /* ai_socktype not supported */
+#define EAI_SYSTEM 11 /* system error returned in errno */
+#define EAI_BADHINTS 12 /* invalid value for hints */
+#define EAI_PROTOCOL 13 /* resolved protocol is unknown */
+#define EAI_OVERFLOW 14 /* argument buffer overflow */
+#define EAI_MAX 15
+
+/*
+ * Flag values for getaddrinfo()
+ */
+#define AI_PASSIVE 0x00000001 /* get address to use bind() */
+#define AI_CANONNAME 0x00000002 /* fill ai_canonname */
+#define AI_NUMERICHOST 0x00000004 /* prevent host name resolution */
+#define AI_NUMERICSERV 0x00000008 /* prevent service name resolution */
+/* valid flags for addrinfo (not a standard def, apps should not use it) */
+#define AI_MASK \
+ (AI_PASSIVE | AI_CANONNAME | AI_NUMERICHOST | AI_NUMERICSERV | \
+ AI_ADDRCONFIG)
+
+#define AI_ALL 0x00000100 /* IPv6 and IPv4-mapped (with AI_V4MAPPED) */
+#define AI_V4MAPPED_CFG 0x00000200 /* accept IPv4-mapped if kernel supports */
+#define AI_ADDRCONFIG 0x00000400 /* only if any address is assigned */
+#define AI_V4MAPPED 0x00000800 /* accept IPv4-mapped IPv6 address */
+/* special recommended flags for getipnodebyname */
+#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+
+/*
+ * Constants for getnameinfo()
+ */
+#define NI_MAXHOST 1025
+#define NI_MAXSERV 32
+
+/*
+ * Flag values for getnameinfo()
+ */
+#define NI_NOFQDN 0x00000001
+#define NI_NUMERICHOST 0x00000002
+#define NI_NAMEREQD 0x00000004
+#define NI_NUMERICSERV 0x00000008
+#define NI_DGRAM 0x00000010
+#if 0 /* obsolete */
+#define NI_WITHSCOPEID 0x00000020
+#endif
+
+/*
+ * Scope delimit character
+ */
+#define SCOPE_DELIMITER '%'
+
+__BEGIN_DECLS
+void endhostent(void);
+void endnetent(void);
+void endprotoent(void);
+void endservent(void);
+#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 *);
+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 *);
+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 *);
+int getnetbyaddr_r(uint32_t, int, struct netent *, char *, size_t,
+ struct netent**, int *);
+int getnetbyname_r(const char *, struct netent *, char *, size_t,
+ struct netent **, int *);
+int getnetent_r(struct netent *, char *, size_t, struct netent **,
+ int *);
+int getnetgrent(char **, char **, char **);
+int getprotobyname_r(const char *, struct protoent *, char *,
+ size_t, struct protoent **);
+int getprotobynumber_r(int, struct protoent *, char *, size_t,
+ struct protoent **);
+int getprotoent_r(struct protoent *, char *, size_t,
+ struct protoent **);
+int getservbyname_r(const char *, const char *, struct servent *,
+ char *, size_t, struct servent **);
+int getservbyport_r(int, const char *, struct servent *, char *,
+ size_t, struct servent **);
+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 setnetgrent(const char *);
+#endif
+
+
+/*
+ * PRIVATE functions specific to the FreeBSD implementation
+ */
+
+/* DO NOT USE THESE, THEY ARE SUBJECT TO CHANGE AND ARE NOT PORTABLE!!! */
+int * __h_errno(void);
+__END_DECLS
+
+#endif /* !_NETDB_H_ */
diff --git a/freebsd/include/nlist.h b/freebsd/include/nlist.h
new file mode 100644
index 00000000..3dccf9e7
--- /dev/null
+++ b/freebsd/include/nlist.h
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ *
+ * @(#)nlist.h 8.2 (Berkeley) 1/21/94
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NLIST_H_
+#define _NLIST_H_
+
+#include <sys/nlist_aout.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+int nlist(const char *, struct nlist *);
+__END_DECLS
+
+#endif /* !_NLIST_H_ */
diff --git a/freebsd/include/nsswitch.h b/freebsd/include/nsswitch.h
new file mode 100644
index 00000000..8aea5ad1
--- /dev/null
+++ b/freebsd/include/nsswitch.h
@@ -0,0 +1,251 @@
+/* $NetBSD: nsswitch.h,v 1.6 1999/01/26 01:04:07 lukem Exp $ */
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NSSWITCH_H
+#define _NSSWITCH_H 1
+
+#include <sys/types.h>
+#include <stdarg.h>
+
+#define NSS_MODULE_INTERFACE_VERSION 1
+
+#ifndef _PATH_NS_CONF
+#define _PATH_NS_CONF "/etc/nsswitch.conf"
+#endif
+
+/* NSS source actions */
+#define NS_ACTION_CONTINUE 0 /* try the next source */
+#define NS_ACTION_RETURN 1 /* look no further */
+
+#define NS_SUCCESS (1<<0) /* entry was found */
+#define NS_UNAVAIL (1<<1) /* source not responding, or corrupt */
+#define NS_NOTFOUND (1<<2) /* source responded 'no such entry' */
+#define NS_TRYAGAIN (1<<3) /* source busy, may respond to retry */
+#define NS_RETURN (1<<4) /* stop search, e.g. for ERANGE */
+#define NS_TERMINATE (NS_SUCCESS|NS_RETURN) /* flags that end search */
+#define NS_STATUSMASK 0x000000ff /* bitmask to get the status flags */
+
+/*
+ * currently implemented sources
+ */
+#define NSSRC_FILES "files" /* local files */
+#define NSSRC_DB "db" /* database */
+#define NSSRC_DNS "dns" /* DNS; IN for hosts, HS for others */
+#define NSSRC_NIS "nis" /* YP/NIS */
+#define NSSRC_COMPAT "compat" /* passwd,group in YP compat mode */
+#define NSSRC_CACHE "cache" /* nscd daemon */
+#define NSSRC_FALLBACK "__fallback" /* internal fallback source */
+
+/*
+ * currently implemented databases
+ */
+#define NSDB_HOSTS "hosts"
+#define NSDB_GROUP "group"
+#define NSDB_GROUP_COMPAT "group_compat"
+#define NSDB_NETGROUP "netgroup"
+#define NSDB_NETWORKS "networks"
+#define NSDB_PASSWD "passwd"
+#define NSDB_PASSWD_COMPAT "passwd_compat"
+#define NSDB_SHELLS "shells"
+#define NSDB_SERVICES "services"
+#define NSDB_SERVICES_COMPAT "services_compat"
+#define NSDB_SSH_HOSTKEYS "ssh_hostkeys"
+#define NSDB_PROTOCOLS "protocols"
+#define NSDB_RPC "rpc"
+
+/*
+ * suggested databases to implement
+ */
+#define NSDB_ALIASES "aliases"
+#define NSDB_AUTH "auth"
+#define NSDB_AUTOMOUNT "automount"
+#define NSDB_BOOTPARAMS "bootparams"
+#define NSDB_ETHERS "ethers"
+#define NSDB_EXPORTS "exports"
+#define NSDB_NETMASKS "netmasks"
+#define NSDB_PHONES "phones"
+#define NSDB_PRINTCAP "printcap"
+#define NSDB_REMOTE "remote"
+#define NSDB_SENDMAILVARS "sendmailvars"
+#define NSDB_TERMCAP "termcap"
+#define NSDB_TTYS "ttys"
+
+/*
+ * ns_dtab `method' function signature.
+ */
+typedef int (*nss_method)(void *_retval, void *_mdata, va_list _ap);
+
+/*
+ * Macro for generating method prototypes.
+ */
+#define NSS_METHOD_PROTOTYPE(method) \
+ int method(void *, void *, va_list)
+
+/*
+ * ns_dtab - `nsswitch dispatch table'
+ * Contains an entry for each source and the appropriate function to
+ * call. ns_dtabs are used in the nsdispatch() API in order to allow
+ * the application to override built-in actions.
+ */
+typedef struct _ns_dtab {
+ const char *src; /* Source this entry implements */
+ nss_method method; /* Method to be called */
+ void *mdata; /* Data passed to method */
+} ns_dtab;
+
+/*
+ * macros to help build an ns_dtab[]
+ */
+#define NS_FILES_CB(F,C) { NSSRC_FILES, F, C },
+#define NS_COMPAT_CB(F,C) { NSSRC_COMPAT, F, C },
+#define NS_FALLBACK_CB(F) { NSSRC_FALLBACK, F, NULL },
+
+#ifdef HESIOD
+# define NS_DNS_CB(F,C) { NSSRC_DNS, F, C },
+#else
+# define NS_DNS_CB(F,C)
+#endif
+
+#ifdef YP
+# define NS_NIS_CB(F,C) { NSSRC_NIS, F, C },
+#else
+# define NS_NIS_CB(F,C)
+#endif
+
+/*
+ * ns_src - `nsswitch source'
+ * used by the nsparser routines to store a mapping between a source
+ * and its dispatch control flags for a given database.
+ */
+typedef struct _ns_src {
+ const char *name;
+ u_int32_t flags;
+} ns_src;
+
+
+/*
+ * default sourcelist (if nsswitch.conf is missing, corrupt,
+ * or the requested database doesn't have an entry.
+ */
+extern const ns_src __nsdefaultsrc[];
+
+/*
+ * ns_mtab - NSS method table
+ * An NSS module provides a mapping from (database name, method name)
+ * tuples to the nss_method and associated data.
+ */
+typedef struct _ns_mtab {
+ const char *database;
+ const char *name;
+ nss_method method;
+ void *mdata;
+} ns_mtab;
+
+/*
+ * NSS module de-registration, called at module unload.
+ */
+typedef void (*nss_module_unregister_fn)(ns_mtab *, unsigned int);
+
+/*
+ * NSS module registration, called at module load.
+ */
+typedef ns_mtab *(*nss_module_register_fn)(const char *, unsigned int *,
+ nss_module_unregister_fn *);
+
+/*
+ * Many NSS interfaces follow the getXXnam, getXXid, getXXent pattern.
+ * Developers are encouraged to use nss_lookup_type where approriate.
+ */
+enum nss_lookup_type {
+ nss_lt_name = 1,
+ nss_lt_id = 2,
+ nss_lt_all = 3
+};
+
+#ifdef _NS_PRIVATE
+/*
+ * private data structures for back-end nsswitch implementation
+ */
+
+/*
+ * ns_dbt - `nsswitch database thang'
+ * for each database in /etc/nsswitch.conf there is a ns_dbt, with its
+ * name and a list of ns_src's containing the source information.
+ */
+typedef struct _ns_dbt {
+ const char *name; /* name of database */
+ ns_src *srclist; /* list of sources */
+ int srclistsize; /* size of srclist */
+} ns_dbt;
+
+/*
+ * ns_mod - NSS module
+ */
+typedef struct _ns_mod {
+ char *name; /* module name */
+ void *handle; /* handle from dlopen */
+ ns_mtab *mtab; /* method table */
+ unsigned int mtabsize; /* count of entries in method table */
+ nss_module_unregister_fn unregister; /* called to unload module */
+} ns_mod;
+
+#endif /* _NS_PRIVATE */
+
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern int nsdispatch(void *, const ns_dtab [], const char *,
+ const char *, const ns_src [], ...);
+
+#ifdef _NS_PRIVATE
+extern void _nsdbtaddsrc(ns_dbt *, const ns_src *);
+extern void _nsdbtput(const ns_dbt *);
+extern void _nsyyerror(const char *);
+extern int _nsyylex(void);
+extern int _nsyyparse(void);
+extern int _nsyylineno;
+#ifdef _NSS_DEBUG
+extern void _nsdbtdump(const ns_dbt *);
+#endif
+#endif /* _NS_PRIVATE */
+
+__END_DECLS
+
+#endif /* !_NSSWITCH_H */
diff --git a/freebsd/include/res_update.h b/freebsd/include/res_update.h
new file mode 100644
index 00000000..f09d3a1a
--- /dev/null
+++ b/freebsd/include/res_update.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1999 by Internet Software Consortium, Inc.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * $Id: res_update.h,v 1.2.18.1 2005/04/27 05:00:49 sra Exp $
+ * $FreeBSD$
+ */
+
+#ifndef __RES_UPDATE_H
+#define __RES_UPDATE_H
+
+/*! \file */
+
+#include <sys/types.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+/*%
+ * This RR-like structure is particular to UPDATE.
+ */
+struct ns_updrec {
+ struct {
+ struct ns_updrec *prev;
+ struct ns_updrec *next;
+ } r_link, r_glink;
+ ns_sect r_section; /*%< ZONE/PREREQUISITE/UPDATE */
+ char * r_dname; /*%< owner of the RR */
+ ns_class r_class; /*%< class number */
+ ns_type r_type; /*%< type number */
+ u_int32_t r_ttl; /*%< time to live */
+ u_char * r_data; /*%< rdata fields as text string */
+ u_int r_size; /*%< size of r_data field */
+ int r_opcode; /*%< type of operation */
+ /* following fields for private use by the resolver/server routines */
+ struct databuf *r_dp; /*%< databuf to process */
+ struct databuf *r_deldp; /*%< databuf's deleted/overwritten */
+ u_int r_zone; /*%< zone number on server */
+};
+typedef struct ns_updrec ns_updrec;
+typedef struct {
+ ns_updrec *head;
+ ns_updrec *tail;
+} ns_updque;
+
+#define res_mkupdate __res_mkupdate
+#define res_update __res_update
+#define res_mkupdrec __res_mkupdrec
+#define res_freeupdrec __res_freeupdrec
+#define res_nmkupdate __res_nmkupdate
+#define res_nupdate __res_nupdate
+
+int res_mkupdate(ns_updrec *, u_char *, int);
+int res_update(ns_updrec *);
+ns_updrec * res_mkupdrec(int, const char *, u_int, u_int, u_long);
+void res_freeupdrec(ns_updrec *);
+int res_nmkupdate(res_state, ns_updrec *, u_char *, int);
+int res_nupdate(res_state, ns_updrec *, ns_tsig_key *);
+
+#endif /*__RES_UPDATE_H*/
+
+/*! \file */
diff --git a/freebsd/include/resolv.h b/freebsd/include/resolv.h
new file mode 100644
index 00000000..20f7954e
--- /dev/null
+++ b/freebsd/include/resolv.h
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 1983, 1987, 1989
+ * 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*%
+ * @(#)resolv.h 8.1 (Berkeley) 6/2/93
+ * $Id: resolv.h,v 1.19.18.4 2008/04/03 23:15:15 marka Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _RESOLV_H_
+#define _RESOLV_H_
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <arpa/nameser.h>
+
+/*%
+ * Revision information. This is the release date in YYYYMMDD format.
+ * It can change every day so the right thing to do with it is use it
+ * in preprocessor commands such as "#if (__RES > 19931104)". Do not
+ * compare for equality; rather, use it to determine whether your resolver
+ * is new enough to contain a certain feature.
+ */
+
+#define __RES 20030124
+
+/*%
+ * This used to be defined in res_query.c, now it's in herror.c.
+ * [XXX no it's not. It's in irs/irs_data.c]
+ * It was
+ * never extern'd by any *.h file before it was placed here. For thread
+ * aware programs, the last h_errno value set is stored in res->h_errno.
+ *
+ * XXX: There doesn't seem to be a good reason for exposing RES_SET_H_ERRNO
+ * (and __h_errno_set) to the public via <resolv.h>.
+ * XXX: __h_errno_set is really part of IRS, not part of the resolver.
+ * If somebody wants to build and use a resolver that doesn't use IRS,
+ * what do they do? Perhaps something like
+ * #ifdef WANT_IRS
+ * # define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x)
+ * #else
+ * # define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x))
+ * #endif
+ */
+
+#define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x)
+struct __res_state; /*%< forward */
+__BEGIN_DECLS
+void __h_errno_set(struct __res_state *, int);
+__END_DECLS
+
+/*%
+ * Resolver configuration file.
+ * Normally not present, but may contain the address of the
+ * initial name server(s) to query and the domain search list.
+ */
+
+#ifndef _PATH_RESCONF
+#define _PATH_RESCONF "/etc/resolv.conf"
+#endif
+
+typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
+ res_sendhookact;
+
+typedef res_sendhookact (*res_send_qhook)(struct sockaddr * const *,
+ const u_char **, int *,
+ u_char *, int, int *);
+
+typedef res_sendhookact (*res_send_rhook)(const struct sockaddr *,
+ const u_char *, int, u_char *,
+ int, int *);
+
+struct res_sym {
+ int number; /*%< Identifying number, like T_MX */
+ const char * name; /*%< Its symbolic name, like "MX" */
+ const char * humanname; /*%< Its fun name, like "mail exchanger" */
+};
+
+/*%
+ * Global defines and variables for resolver stub.
+ */
+#define MAXNS 3 /*%< max # name servers we'll track */
+#define MAXDFLSRCH 3 /*%< # default domain levels to try */
+#define MAXDNSRCH 6 /*%< max # domains in search path */
+#define LOCALDOMAINPARTS 2 /*%< min levels in name that is "local" */
+#define RES_TIMEOUT 5 /*%< min. seconds between retries */
+#define MAXRESOLVSORT 10 /*%< number of net to sort on */
+#define RES_MAXNDOTS 15 /*%< should reflect bit field size */
+#define RES_MAXRETRANS 30 /*%< only for resolv.conf/RES_OPTIONS */
+#define RES_MAXRETRY 5 /*%< only for resolv.conf/RES_OPTIONS */
+#define RES_DFLRETRY 2 /*%< Default #/tries. */
+#define RES_MAXTIME 65535 /*%< Infinity, in milliseconds. */
+struct __res_state_ext;
+
+struct __res_state {
+ int retrans; /*%< retransmission time interval */
+ int retry; /*%< number of times to retransmit */
+ /*
+ * XXX: If `sun' is defined, `options' and `pfcode' are
+ * defined as u_int in original BIND9 distribution. However,
+ * it breaks binary backward compatibility against FreeBSD's
+ * resolver. So, we changed not to see `sun'.
+ */
+#if defined(sun) && 0
+ u_int options; /*%< option flags - see below. */
+#else
+ u_long options; /*%< option flags - see below. */
+#endif
+ int nscount; /*%< number of name servers */
+ struct sockaddr_in
+ nsaddr_list[MAXNS]; /*%< address of name server */
+#define nsaddr nsaddr_list[0] /*%< for backward compatibility */
+ u_short id; /*%< current message id */
+ char *dnsrch[MAXDNSRCH+1]; /*%< components of domain to search */
+ char defdname[256]; /*%< default domain (deprecated) */
+#if defined(sun) && 0
+ u_int pfcode; /*%< RES_PRF_ flags - see below. */
+#else
+ u_long pfcode; /*%< RES_PRF_ flags - see below. */
+#endif
+ unsigned ndots:4; /*%< threshold for initial abs. query */
+ unsigned nsort:4; /*%< number of elements in sort_list[] */
+ char unused[3];
+ struct {
+ struct in_addr addr;
+ u_int32_t mask;
+ } sort_list[MAXRESOLVSORT];
+ res_send_qhook qhook; /*%< query hook */
+ res_send_rhook rhook; /*%< response hook */
+ int res_h_errno; /*%< last one set for this context */
+ int _vcsock; /*%< PRIVATE: for res_send VC i/o */
+ u_int _flags; /*%< PRIVATE: see below */
+ u_int _pad; /*%< make _u 64 bit aligned */
+ union {
+ /* On an 32-bit arch this means 512b total. */
+ char pad[72 - 4*sizeof (int) - 2*sizeof (void *)];
+ struct {
+ u_int16_t nscount;
+ u_int16_t nstimes[MAXNS]; /*%< ms. */
+ int nssocks[MAXNS];
+ struct __res_state_ext *ext; /*%< extention for IPv6 */
+ } _ext;
+ } _u;
+};
+
+typedef struct __res_state *res_state;
+
+union res_sockaddr_union {
+ struct sockaddr_in sin;
+#ifdef IN6ADDR_ANY_INIT
+ struct sockaddr_in6 sin6;
+#endif
+#ifdef ISC_ALIGN64
+ int64_t __align64; /*%< 64bit alignment */
+#else
+ int32_t __align32; /*%< 32bit alignment */
+#endif
+ char __space[128]; /*%< max size */
+};
+
+/*%
+ * Resolver flags (used to be discrete per-module statics ints).
+ */
+#define RES_F_VC 0x00000001 /*%< socket is TCP */
+#define RES_F_CONN 0x00000002 /*%< socket is connected */
+#define RES_F_EDNS0ERR 0x00000004 /*%< EDNS0 caused errors */
+#define RES_F__UNUSED 0x00000008 /*%< (unused) */
+#define RES_F_LASTMASK 0x000000F0 /*%< ordinal server of last res_nsend */
+#define RES_F_LASTSHIFT 4 /*%< bit position of LASTMASK "flag" */
+#define RES_GETLAST(res) (((res)._flags & RES_F_LASTMASK) >> RES_F_LASTSHIFT)
+
+/* res_findzonecut2() options */
+#define RES_EXHAUSTIVE 0x00000001 /*%< always do all queries */
+#define RES_IPV4ONLY 0x00000002 /*%< IPv4 only */
+#define RES_IPV6ONLY 0x00000004 /*%< IPv6 only */
+
+/*%
+ * Resolver options (keep these in synch with res_debug.c, please)
+ */
+#define RES_INIT 0x00000001 /*%< address initialized */
+#define RES_DEBUG 0x00000002 /*%< print debug messages */
+#define RES_AAONLY 0x00000004 /*%< authoritative answers only (!IMPL)*/
+#define RES_USEVC 0x00000008 /*%< use virtual circuit */
+#define RES_PRIMARY 0x00000010 /*%< query primary server only (!IMPL) */
+#define RES_IGNTC 0x00000020 /*%< ignore truncation errors */
+#define RES_RECURSE 0x00000040 /*%< recursion desired */
+#define RES_DEFNAMES 0x00000080 /*%< use default domain name */
+#define RES_STAYOPEN 0x00000100 /*%< Keep TCP socket open */
+#define RES_DNSRCH 0x00000200 /*%< search up local domain tree */
+#define RES_INSECURE1 0x00000400 /*%< type 1 security disabled */
+#define RES_INSECURE2 0x00000800 /*%< type 2 security disabled */
+#define RES_NOALIASES 0x00001000 /*%< shuts off HOSTALIASES feature */
+#define RES_USE_INET6 0x00002000 /*%< use/map IPv6 in gethostbyname() */
+#define RES_ROTATE 0x00004000 /*%< rotate ns list after each query */
+#define RES_NOCHECKNAME 0x00008000 /*%< do not check names for sanity. */
+#define RES_KEEPTSIG 0x00010000 /*%< do not strip TSIG records */
+#define RES_BLAST 0x00020000 /*%< blast all recursive servers */
+#define RES_NSID 0x00040000 /*%< request name server ID */
+#define RES_NOTLDQUERY 0x00100000 /*%< don't unqualified name as a tld */
+#define RES_USE_DNSSEC 0x00200000 /*%< use DNSSEC using OK bit in OPT */
+/* #define RES_DEBUG2 0x00400000 */ /* nslookup internal */
+/* KAME extensions: use higher bit to avoid conflict with ISC use */
+#define RES_USE_DNAME 0x10000000 /*%< use DNAME */
+#define RES_USE_EDNS0 0x40000000 /*%< use EDNS0 if configured */
+#define RES_NO_NIBBLE2 0x80000000 /*%< disable alternate nibble lookup */
+
+#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | \
+ RES_DNSRCH | RES_NO_NIBBLE2)
+
+/*%
+ * Resolver "pfcode" values. Used by dig.
+ */
+#define RES_PRF_STATS 0x00000001
+#define RES_PRF_UPDATE 0x00000002
+#define RES_PRF_CLASS 0x00000004
+#define RES_PRF_CMD 0x00000008
+#define RES_PRF_QUES 0x00000010
+#define RES_PRF_ANS 0x00000020
+#define RES_PRF_AUTH 0x00000040
+#define RES_PRF_ADD 0x00000080
+#define RES_PRF_HEAD1 0x00000100
+#define RES_PRF_HEAD2 0x00000200
+#define RES_PRF_TTLID 0x00000400
+#define RES_PRF_HEADX 0x00000800
+#define RES_PRF_QUERY 0x00001000
+#define RES_PRF_REPLY 0x00002000
+#define RES_PRF_INIT 0x00004000
+#define RES_PRF_TRUNC 0x00008000
+/* 0x00010000 */
+
+/* Things involving an internal (static) resolver context. */
+__BEGIN_DECLS
+extern struct __res_state *__res_state(void);
+__END_DECLS
+#define _res (*__res_state())
+
+#ifndef __BIND_NOSTATIC
+#define fp_nquery __fp_nquery
+#define fp_query __fp_query
+#define hostalias __hostalias
+#define p_query __p_query
+#define res_close __res_close
+#define res_init __res_init
+#define res_isourserver __res_isourserver
+#define res_mkquery __res_mkquery
+#define res_opt __res_opt
+#define res_query __res_query
+#define res_querydomain __res_querydomain
+#define res_search __res_search
+#define res_send __res_send
+#define res_sendsigned __res_sendsigned
+
+__BEGIN_DECLS
+void fp_nquery(const u_char *, int, FILE *);
+void fp_query(const u_char *, FILE *);
+const char * hostalias(const char *);
+void p_query(const u_char *);
+void res_close(void);
+int res_init(void);
+int res_isourserver(const struct sockaddr_in *);
+int res_mkquery(int, const char *, int, int, const u_char *,
+ int, const u_char *, u_char *, int);
+int res_opt(int, u_char *, int, int);
+int res_query(const char *, int, int, u_char *, int);
+int res_querydomain(const char *, const char *, int, int,
+ u_char *, int);
+int res_search(const char *, int, int, u_char *, int);
+int res_send(const u_char *, int, u_char *, int);
+int res_sendsigned(const u_char *, int, ns_tsig_key *,
+ u_char *, int);
+__END_DECLS
+#endif
+
+#if !defined(SHARED_LIBBIND) || defined(LIB)
+/*
+ * If libbind is a shared object (well, DLL anyway)
+ * these externs break the linker when resolv.h is
+ * included by a lib client (like named)
+ * Make them go away if a client is including this
+ *
+ */
+extern const struct res_sym __p_key_syms[];
+extern const struct res_sym __p_cert_syms[];
+extern const struct res_sym __p_class_syms[];
+extern const struct res_sym __p_type_syms[];
+extern const struct res_sym __p_rcode_syms[];
+#endif /* SHARED_LIBBIND */
+
+#define b64_ntop __b64_ntop
+#define b64_pton __b64_pton
+#define dn_comp __dn_comp
+#define dn_count_labels __dn_count_labels
+#define dn_expand __dn_expand
+#define dn_skipname __dn_skipname
+#define fp_resstat __fp_resstat
+#define loc_aton __loc_aton
+#define loc_ntoa __loc_ntoa
+#define p_cdname __p_cdname
+#define p_cdnname __p_cdnname
+#define p_class __p_class
+#define p_fqname __p_fqname
+#define p_fqnname __p_fqnname
+#define p_option __p_option
+#define p_secstodate __p_secstodate
+#define p_section __p_section
+#define p_time __p_time
+#define p_type __p_type
+#define p_rcode __p_rcode
+#define p_sockun __p_sockun
+#define putlong __putlong
+#define putshort __putshort
+#define res_dnok __res_dnok
+#if 0
+#define res_findzonecut __res_findzonecut
+#endif
+#define res_findzonecut2 __res_findzonecut2
+#define res_hnok __res_hnok
+#define res_hostalias __res_hostalias
+#define res_mailok __res_mailok
+#define res_nameinquery __res_nameinquery
+#define res_nclose __res_nclose
+#define res_ninit __res_ninit
+#define res_nmkquery __res_nmkquery
+#define res_pquery __res_pquery
+#define res_nquery __res_nquery
+#define res_nquerydomain __res_nquerydomain
+#define res_nsearch __res_nsearch
+#define res_nsend __res_nsend
+#if 0
+#define res_nsendsigned __res_nsendsigned
+#endif
+#define res_nisourserver __res_nisourserver
+#define res_ownok __res_ownok
+#define res_queriesmatch __res_queriesmatch
+#define res_randomid __res_randomid
+#define sym_ntop __sym_ntop
+#define sym_ntos __sym_ntos
+#define sym_ston __sym_ston
+#define res_nopt __res_nopt
+#define res_nopt_rdata __res_nopt_rdata
+#define res_ndestroy __res_ndestroy
+#define res_nametoclass __res_nametoclass
+#define res_nametotype __res_nametotype
+#define res_setservers __res_setservers
+#define res_getservers __res_getservers
+#if 0
+#define res_buildprotolist __res_buildprotolist
+#define res_destroyprotolist __res_destroyprotolist
+#define res_destroyservicelist __res_destroyservicelist
+#define res_get_nibblesuffix __res_get_nibblesuffix
+#define res_get_nibblesuffix2 __res_get_nibblesuffix2
+#endif
+#define res_ourserver_p __res_ourserver_p
+#if 0
+#define res_protocolname __res_protocolname
+#define res_protocolnumber __res_protocolnumber
+#endif
+#define res_send_setqhook __res_send_setqhook
+#define res_send_setrhook __res_send_setrhook
+#if 0
+#define res_servicename __res_servicename
+#define res_servicenumber __res_servicenumber
+#endif
+__BEGIN_DECLS
+int res_hnok(const char *);
+int res_ownok(const char *);
+int res_mailok(const char *);
+int res_dnok(const char *);
+int sym_ston(const struct res_sym *, const char *, int *);
+const char * sym_ntos(const struct res_sym *, int, int *);
+const char * sym_ntop(const struct res_sym *, int, int *);
+int b64_ntop(u_char const *, size_t, char *, size_t);
+int b64_pton(char const *, u_char *, size_t);
+int loc_aton(const char *, u_char *);
+const char * loc_ntoa(const u_char *, char *);
+int dn_skipname(const u_char *, const u_char *);
+void putlong(u_int32_t, u_char *);
+void putshort(u_int16_t, u_char *);
+#ifndef __ultrix__
+u_int16_t _getshort(const u_char *);
+u_int32_t _getlong(const u_char *);
+#endif
+const char * p_class(int);
+const char * p_time(u_int32_t);
+const char * p_type(int);
+const char * p_rcode(int);
+const char * p_sockun(union res_sockaddr_union, char *, size_t);
+const u_char * p_cdnname(const u_char *, const u_char *, int, FILE *);
+const u_char * p_cdname(const u_char *, const u_char *, FILE *);
+const u_char * p_fqnname(const u_char *, const u_char *, int, char *, int);
+const u_char * p_fqname(const u_char *, const u_char *, FILE *);
+const char * p_option(u_long);
+char * p_secstodate(u_long);
+int dn_count_labels(const char *);
+int dn_comp(const char *, u_char *, int, u_char **, u_char **);
+int dn_expand(const u_char *, const u_char *, const u_char *,
+ char *, int);
+u_int res_randomid(void);
+int res_nameinquery(const char *, int, int, const u_char *,
+ const u_char *);
+int res_queriesmatch(const u_char *, const u_char *,
+ const u_char *, const u_char *);
+const char * p_section(int, int);
+/* Things involving a resolver context. */
+int res_ninit(res_state);
+int res_nisourserver(const res_state, const struct sockaddr_in *);
+void fp_resstat(const res_state, FILE *);
+void res_pquery(const res_state, const u_char *, int, FILE *);
+const char * res_hostalias(const res_state, const char *, char *, size_t);
+int res_nquery(res_state, const char *, int, int, u_char *, int);
+int res_nsearch(res_state, const char *, int, int, u_char *, int);
+int res_nquerydomain(res_state, const char *, const char *,
+ int, int, u_char *, int);
+int res_nmkquery(res_state, int, const char *, int, int,
+ const u_char *, int, const u_char *,
+ u_char *, int);
+int res_nsend(res_state, const u_char *, int, u_char *, int);
+#if 0
+int res_nsendsigned(res_state, const u_char *, int,
+ ns_tsig_key *, u_char *, int);
+int res_findzonecut(res_state, const char *, ns_class, int,
+ char *, size_t, struct in_addr *, int);
+#endif
+int res_findzonecut2(res_state, const char *, ns_class, int,
+ char *, size_t,
+ union res_sockaddr_union *, int);
+void res_nclose(res_state);
+int res_nopt(res_state, int, u_char *, int, int);
+int res_nopt_rdata(res_state, int, u_char *, int, u_char *,
+ u_short, u_short, u_char *);
+void res_send_setqhook(res_send_qhook);
+void res_send_setrhook(res_send_rhook);
+int __res_vinit(res_state, int);
+#if 0
+void res_destroyservicelist(void);
+const char * res_servicename(u_int16_t, const char *);
+const char * res_protocolname(int);
+void res_destroyprotolist(void);
+void res_buildprotolist(void);
+const char * res_get_nibblesuffix(res_state);
+const char * res_get_nibblesuffix2(res_state);
+#endif
+void res_ndestroy(res_state);
+u_int16_t res_nametoclass(const char *, int *);
+u_int16_t res_nametotype(const char *, int *);
+void res_setservers(res_state, const union res_sockaddr_union *,
+ int);
+int res_getservers(res_state, union res_sockaddr_union *, int);
+__END_DECLS
+
+#endif /* !_RESOLV_H_ */
+/*! \file */
diff --git a/freebsd/include/rpc/auth.h b/freebsd/include/rpc/auth.h
new file mode 100644
index 00000000..d39ad120
--- /dev/null
+++ b/freebsd/include/rpc/auth.h
@@ -0,0 +1,370 @@
+/* $NetBSD: auth.h,v 1.15 2000/06/02 22:57:55 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)auth.h 1.17 88/02/08 SMI
+ * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC
+ * from: @(#)auth.h 1.43 98/02/02 SMI
+ * $FreeBSD$
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The data structures are completely opaque to the client. The client
+ * is required to pass an AUTH * to routines that create rpc
+ * "sessions".
+ */
+
+#ifndef _RPC_AUTH_H
+#define _RPC_AUTH_H
+#include <rpc/xdr.h>
+#include <rpc/clnt_stat.h>
+#include <sys/cdefs.h>
+#include <sys/socket.h>
+
+#define MAX_AUTH_BYTES 400
+#define MAXNETNAMELEN 255 /* maximum length of network user's name */
+
+/*
+ * Client side authentication/security data
+ */
+
+typedef struct sec_data {
+ u_int secmod; /* security mode number e.g. in nfssec.conf */
+ u_int rpcflavor; /* rpc flavors:AUTH_UNIX,AUTH_DES,RPCSEC_GSS */
+ int flags; /* AUTH_F_xxx flags */
+ caddr_t data; /* opaque data per flavor */
+} sec_data_t;
+
+#ifdef _SYSCALL32_IMPL
+struct sec_data32 {
+ uint32_t secmod; /* security mode number e.g. in nfssec.conf */
+ uint32_t rpcflavor; /* rpc flavors:AUTH_UNIX,AUTH_DES,RPCSEC_GSS */
+ int32_t flags; /* AUTH_F_xxx flags */
+ caddr32_t data; /* opaque data per flavor */
+};
+#endif /* _SYSCALL32_IMPL */
+
+/*
+ * AUTH_DES flavor specific data from sec_data opaque data field.
+ * AUTH_KERB has the same structure.
+ */
+typedef struct des_clnt_data {
+ struct netbuf syncaddr; /* time sync addr */
+ struct knetconfig *knconf; /* knetconfig info that associated */
+ /* with the syncaddr. */
+ char *netname; /* server's netname */
+ int netnamelen; /* server's netname len */
+} dh_k4_clntdata_t;
+
+#ifdef _SYSCALL32_IMPL
+struct des_clnt_data32 {
+ struct netbuf32 syncaddr; /* time sync addr */
+ caddr32_t knconf; /* knetconfig info that associated */
+ /* with the syncaddr. */
+ caddr32_t netname; /* server's netname */
+ int32_t netnamelen; /* server's netname len */
+};
+#endif /* _SYSCALL32_IMPL */
+
+#ifdef KERBEROS
+/*
+ * flavor specific data to hold the data for AUTH_DES/AUTH_KERB(v4)
+ * in sec_data->data opaque field.
+ */
+typedef struct krb4_svc_data {
+ int window; /* window option value */
+} krb4_svcdata_t;
+
+typedef struct krb4_svc_data des_svcdata_t;
+#endif /* KERBEROS */
+
+/*
+ * authentication/security specific flags
+ */
+#define AUTH_F_RPCTIMESYNC 0x001 /* use RPC to do time sync */
+#define AUTH_F_TRYNONE 0x002 /* allow fall back to AUTH_NONE */
+
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+ AUTH_OK=0,
+ /*
+ * failed at remote end
+ */
+ AUTH_BADCRED=1, /* bogus credentials (seal broken) */
+ AUTH_REJECTEDCRED=2, /* client should begin new session */
+ AUTH_BADVERF=3, /* bogus verifier (seal broken) */
+ AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */
+ AUTH_TOOWEAK=5, /* rejected due to security reasons */
+ /*
+ * failed locally
+ */
+ AUTH_INVALIDRESP=6, /* bogus response verifier */
+ AUTH_FAILED=7, /* some unknown reason */
+#ifdef KERBEROS
+ /*
+ * kerberos errors
+ */
+ ,
+ AUTH_KERB_GENERIC = 8, /* kerberos generic error */
+ AUTH_TIMEEXPIRE = 9, /* time of credential expired */
+ AUTH_TKT_FILE = 10, /* something wrong with ticket file */
+ AUTH_DECODE = 11, /* can't decode authenticator */
+ AUTH_NET_ADDR = 12, /* wrong net address in ticket */
+#endif /* KERBEROS */
+ /*
+ * RPCSEC_GSS errors
+ */
+ RPCSEC_GSS_CREDPROBLEM = 13,
+ RPCSEC_GSS_CTXPROBLEM = 14,
+ RPCSEC_GSS_NODISPATCH = 0x8000000
+};
+
+union des_block {
+ struct {
+ uint32_t high;
+ uint32_t low;
+ } key;
+ char c[8];
+};
+typedef union des_block des_block;
+__BEGIN_DECLS
+extern bool_t xdr_des_block(XDR *, des_block *);
+__END_DECLS
+
+/*
+ * Authentication info. Opaque to client.
+ */
+struct opaque_auth {
+ enum_t oa_flavor; /* flavor of auth */
+ caddr_t oa_base; /* address of more auth stuff */
+ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
+};
+
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+typedef struct __auth {
+ struct opaque_auth ah_cred;
+ struct opaque_auth ah_verf;
+ union des_block ah_key;
+ struct auth_ops {
+ void (*ah_nextverf) (struct __auth *);
+ /* nextverf & serialize */
+ int (*ah_marshal) (struct __auth *, XDR *);
+ /* validate verifier */
+ int (*ah_validate) (struct __auth *,
+ struct opaque_auth *);
+ /* refresh credentials */
+ int (*ah_refresh) (struct __auth *, void *);
+ /* destroy this structure */
+ void (*ah_destroy) (struct __auth *);
+ } *ah_ops;
+ void *ah_private;
+} AUTH;
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH *auth;
+ * XDR *xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+#define auth_refresh(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+
+#define AUTH_DESTROY(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+__BEGIN_DECLS
+extern struct opaque_auth _null_auth;
+__END_DECLS
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * System style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ * char *machname;
+ * int uid;
+ * int gid;
+ * int len;
+ * int *aup_gids;
+ */
+__BEGIN_DECLS
+extern AUTH *authunix_create(char *, int, int, int,
+ int *);
+extern AUTH *authunix_create_default(void); /* takes no parameters */
+extern AUTH *authnone_create(void); /* takes no parameters */
+__END_DECLS
+/*
+ * DES style authentication
+ * AUTH *authsecdes_create(servername, window, timehost, ckey)
+ * char *servername; - network name of server
+ * u_int window; - time to live
+ * const char *timehost; - optional hostname to sync with
+ * des_block *ckey; - optional conversation key to use
+ */
+__BEGIN_DECLS
+extern AUTH *authdes_create (char *, u_int, struct sockaddr *, des_block *);
+extern AUTH *authdes_seccreate (const char *, const u_int, const char *,
+ const des_block *);
+__END_DECLS
+
+__BEGIN_DECLS
+extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *);
+__END_DECLS
+
+#define authsys_create(c,i1,i2,i3,ip) authunix_create((c),(i1),(i2),(i3),(ip))
+#define authsys_create_default() authunix_create_default()
+
+/*
+ * Netname manipulation routines.
+ */
+__BEGIN_DECLS
+extern int getnetname(char *);
+extern int host2netname(char *, const char *, const char *);
+extern int user2netname(char *, const uid_t, const char *);
+extern int netname2user(char *, uid_t *, gid_t *, int *, gid_t *);
+extern int netname2host(char *, char *, const int);
+extern void passwd2des ( char *, char * );
+__END_DECLS
+
+/*
+ *
+ * These routines interface to the keyserv daemon
+ *
+ */
+__BEGIN_DECLS
+extern int key_decryptsession(const char *, des_block *);
+extern int key_encryptsession(const char *, des_block *);
+extern int key_gendes(des_block *);
+extern int key_setsecret(const char *);
+extern int key_secretkey_is_set(void);
+__END_DECLS
+
+/*
+ * Publickey routines.
+ */
+__BEGIN_DECLS
+extern int getpublickey (const char *, char *);
+extern int getpublicandprivatekey (const char *, char *);
+extern int getsecretkey (char *, char *, char *);
+__END_DECLS
+
+#ifdef KERBEROS
+/*
+ * Kerberos style authentication
+ * AUTH *authkerb_seccreate(service, srv_inst, realm, window, timehost, status)
+ * const char *service; - service name
+ * const char *srv_inst; - server instance
+ * const char *realm; - server realm
+ * const u_int window; - time to live
+ * const char *timehost; - optional hostname to sync with
+ * int *status; - kerberos status returned
+ */
+__BEGIN_DECLS
+extern AUTH *authkerb_seccreate(const char *, const char *, const char *,
+ const u_int, const char *, int *);
+__END_DECLS
+
+/*
+ * Map a kerberos credential into a unix cred.
+ *
+ * authkerb_getucred(rqst, uid, gid, grouplen, groups)
+ * const struct svc_req *rqst; - request pointer
+ * uid_t *uid;
+ * gid_t *gid;
+ * short *grouplen;
+ * int *groups;
+ *
+ */
+__BEGIN_DECLS
+extern int authkerb_getucred(/* struct svc_req *, uid_t *, gid_t *,
+ short *, int * */);
+__END_DECLS
+#endif /* KERBEROS */
+
+__BEGIN_DECLS
+struct svc_req;
+struct rpc_msg;
+enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *);
+enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *);
+enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *);
+__END_DECLS
+
+#define AUTH_NONE 0 /* no authentication */
+#define AUTH_NULL 0 /* backward compatibility */
+#define AUTH_SYS 1 /* unix style (uid, gids) */
+#define AUTH_UNIX AUTH_SYS
+#define AUTH_SHORT 2 /* short hand unix style */
+#define AUTH_DH 3 /* for Diffie-Hellman mechanism */
+#define AUTH_DES AUTH_DH /* for backward compatibility */
+#define AUTH_KERB 4 /* kerberos style */
+#define RPCSEC_GSS 6 /* RPCSEC_GSS */
+
+/*
+ * Pseudo auth flavors for RPCSEC_GSS.
+ */
+#define RPCSEC_GSS_KRB5 390003
+#define RPCSEC_GSS_KRB5I 390004
+#define RPCSEC_GSS_KRB5P 390005
+
+#endif /* !_RPC_AUTH_H */
diff --git a/freebsd/include/rpc/auth_des.h b/freebsd/include/rpc/auth_des.h
new file mode 100644
index 00000000..fff4ebfe
--- /dev/null
+++ b/freebsd/include/rpc/auth_des.h
@@ -0,0 +1,126 @@
+/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */
+/* $FreeBSD$ */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC
+ * from: @(#)auth_des.h 1.14 94/04/25 SMI
+ */
+
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * auth_des.h, Protocol for DES style authentication for RPC
+ */
+
+#ifndef _AUTH_DES_
+#define _AUTH_DES_
+
+/*
+ * There are two kinds of "names": fullnames and nicknames
+ */
+enum authdes_namekind {
+ ADN_FULLNAME,
+ ADN_NICKNAME
+};
+
+/*
+ * A fullname contains the network name of the client,
+ * a conversation key and the window
+ */
+struct authdes_fullname {
+ char *name; /* network name of client, up to MAXNETNAMELEN */
+ des_block key; /* conversation key */
+ u_long window; /* associated window */
+};
+
+
+/*
+ * A credential
+ */
+struct authdes_cred {
+ enum authdes_namekind adc_namekind;
+ struct authdes_fullname adc_fullname;
+ u_long adc_nickname;
+};
+
+
+
+/*
+ * A des authentication verifier
+ */
+struct authdes_verf {
+ union {
+ struct timeval adv_ctime; /* clear time */
+ des_block adv_xtime; /* crypt time */
+ } adv_time_u;
+ u_long adv_int_u;
+};
+
+/*
+ * des authentication verifier: client variety
+ *
+ * adv_timestamp is the current time.
+ * adv_winverf is the credential window + 1.
+ * Both are encrypted using the conversation key.
+ */
+#define adv_timestamp adv_time_u.adv_ctime
+#define adv_xtimestamp adv_time_u.adv_xtime
+#define adv_winverf adv_int_u
+
+/*
+ * des authentication verifier: server variety
+ *
+ * adv_timeverf is the client's timestamp + client's window
+ * adv_nickname is the server's nickname for the client.
+ * adv_timeverf is encrypted using the conversation key.
+ */
+#define adv_timeverf adv_time_u.adv_ctime
+#define adv_xtimeverf adv_time_u.adv_xtime
+#define adv_nickname adv_int_u
+
+/*
+ * Map a des credential into a unix cred.
+ *
+ */
+__BEGIN_DECLS
+extern int authdes_getucred( struct authdes_cred *, uid_t *, gid_t *, int *, gid_t * );
+__END_DECLS
+
+__BEGIN_DECLS
+extern bool_t xdr_authdes_cred(XDR *, struct authdes_cred *);
+extern bool_t xdr_authdes_verf(XDR *, struct authdes_verf *);
+extern int rtime(dev_t, struct netbuf *, int, struct timeval *,
+ struct timeval *);
+extern void kgetnetname(char *);
+extern enum auth_stat _svcauth_des(struct svc_req *, struct rpc_msg *);
+__END_DECLS
+
+#endif /* ndef _AUTH_DES_ */
diff --git a/freebsd/include/rpc/auth_unix.h b/freebsd/include/rpc/auth_unix.h
new file mode 100644
index 00000000..48373b2c
--- /dev/null
+++ b/freebsd/include/rpc/auth_unix.h
@@ -0,0 +1,84 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)auth_unix.h 1.8 88/02/08 SMI
+ * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * The system is very weak. The client uses no encryption for it
+ * credentials and only sends null verifiers. The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ */
+
+#ifndef _RPC_AUTH_UNIX_H
+#define _RPC_AUTH_UNIX_H
+#include <sys/cdefs.h>
+
+/* The machine name is part of a credential; it may not exceed 255 bytes */
+#define MAX_MACHINE_NAME 255
+
+/* gids compose part of a credential; there may not be more than 16 of them */
+#define NGRPS 16
+
+/*
+ * Unix style credentials.
+ */
+struct authunix_parms {
+ u_long aup_time;
+ char *aup_machname;
+ int aup_uid;
+ int aup_gid;
+ u_int aup_len;
+ int *aup_gids;
+};
+
+#define authsys_parms authunix_parms
+
+__BEGIN_DECLS
+extern bool_t xdr_authunix_parms(XDR *, struct authunix_parms *);
+__END_DECLS
+
+/*
+ * If a response verifier has flavor AUTH_SHORT,
+ * then the body of the response verifier encapsulates the following structure;
+ * again it is serialized in the obvious fashion.
+ */
+struct short_hand_verf {
+ struct opaque_auth new_cred;
+};
+
+#endif /* !_RPC_AUTH_UNIX_H */
diff --git a/freebsd/include/rpc/clnt.h b/freebsd/include/rpc/clnt.h
new file mode 100644
index 00000000..1c85a4a7
--- /dev/null
+++ b/freebsd/include/rpc/clnt.h
@@ -0,0 +1,557 @@
+/* $NetBSD: clnt.h,v 1.14 2000/06/02 22:57:55 fvdl Exp $ */
+
+/*
+ * The contents of this file are subject to the Sun Standards
+ * License Version 1.0 the (the "License";) You may not use
+ * this file except in compliance with the License. You may
+ * obtain a copy of the License at lib/libc/rpc/LICENSE
+ *
+ * Software distributed under the License is distributed on
+ * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is Copyright 1998 by Sun Microsystems, Inc
+ *
+ * The Initial Developer of the Original Code is: Sun
+ * Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)clnt.h 1.31 94/04/29 SMI
+ * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ *
+ * Copyright (c) 1986-1991,1994-1999 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _RPC_CLNT_H_
+#define _RPC_CLNT_H_
+#include <rpc/clnt_stat.h>
+#include <sys/cdefs.h>
+#include <netconfig.h>
+#include <sys/un.h>
+
+/*
+ * Well-known IPV6 RPC broadcast address.
+ */
+#define RPCB_MULTICAST_ADDR "ff02::202"
+
+/*
+ * the following errors are in general unrecoverable. The caller
+ * should give up rather than retry.
+ */
+#define IS_UNRECOVERABLE_RPC(s) (((s) == RPC_AUTHERROR) || \
+ ((s) == RPC_CANTENCODEARGS) || \
+ ((s) == RPC_CANTDECODERES) || \
+ ((s) == RPC_VERSMISMATCH) || \
+ ((s) == RPC_PROCUNAVAIL) || \
+ ((s) == RPC_PROGUNAVAIL) || \
+ ((s) == RPC_PROGVERSMISMATCH) || \
+ ((s) == RPC_CANTDECODEARGS))
+
+/*
+ * Error info.
+ */
+struct rpc_err {
+ enum clnt_stat re_status;
+ union {
+ int RE_errno; /* related system error */
+ enum auth_stat RE_why; /* why the auth error occurred */
+ struct {
+ rpcvers_t low; /* lowest version supported */
+ rpcvers_t high; /* highest version supported */
+ } RE_vers;
+ struct { /* maybe meaningful if RPC_FAILED */
+ int32_t s1;
+ int32_t s2;
+ } RE_lb; /* life boot & debugging only */
+ } ru;
+#define re_errno ru.RE_errno
+#define re_why ru.RE_why
+#define re_vers ru.RE_vers
+#define re_lb ru.RE_lb
+};
+
+
+/*
+ * Client rpc handle.
+ * Created by individual implementations
+ * Client is responsible for initializing auth, see e.g. auth_none.c.
+ */
+typedef struct __rpc_client {
+ AUTH *cl_auth; /* authenticator */
+ struct clnt_ops {
+ /* call remote procedure */
+ enum clnt_stat (*cl_call)(struct __rpc_client *,
+ rpcproc_t, xdrproc_t, void *, xdrproc_t,
+ void *, struct timeval);
+ /* abort a call */
+ void (*cl_abort)(struct __rpc_client *);
+ /* get specific error code */
+ void (*cl_geterr)(struct __rpc_client *,
+ struct rpc_err *);
+ /* frees results */
+ bool_t (*cl_freeres)(struct __rpc_client *,
+ xdrproc_t, void *);
+ /* destroy this structure */
+ void (*cl_destroy)(struct __rpc_client *);
+ /* the ioctl() of rpc */
+ bool_t (*cl_control)(struct __rpc_client *, u_int,
+ void *);
+ } *cl_ops;
+ void *cl_private; /* private stuff */
+ char *cl_netid; /* network token */
+ char *cl_tp; /* device name */
+} CLIENT;
+
+
+/*
+ * Timers used for the pseudo-transport protocol when using datagrams
+ */
+struct rpc_timers {
+ u_short rt_srtt; /* smoothed round-trip time */
+ u_short rt_deviate; /* estimated deviation */
+ u_long rt_rtxcur; /* current (backed-off) rto */
+};
+
+/*
+ * Feedback values used for possible congestion and rate control
+ */
+#define FEEDBACK_REXMIT1 1 /* first retransmit */
+#define FEEDBACK_OK 2 /* no retransmits */
+
+/* Used to set version of portmapper used in broadcast */
+
+#define CLCR_SET_LOWVERS 3
+#define CLCR_GET_LOWVERS 4
+
+#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+
+/*
+ * client side rpc interface ops
+ *
+ * Parameter types are:
+ *
+ */
+
+/*
+ * enum clnt_stat
+ * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
+ * CLIENT *rh;
+ * rpcproc_t proc;
+ * xdrproc_t xargs;
+ * void *argsp;
+ * xdrproc_t xres;
+ * void *resp;
+ * struct timeval timeout;
+ */
+#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, \
+ argsp, xres, resp, secs))
+#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, \
+ argsp, xres, resp, secs))
+
+/*
+ * void
+ * CLNT_ABORT(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+
+/*
+ * struct rpc_err
+ * CLNT_GETERR(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+
+
+/*
+ * bool_t
+ * CLNT_FREERES(rh, xres, resp);
+ * CLIENT *rh;
+ * xdrproc_t xres;
+ * void *resp;
+ */
+#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+
+/*
+ * bool_t
+ * CLNT_CONTROL(cl, request, info)
+ * CLIENT *cl;
+ * u_int request;
+ * char *info;
+ */
+#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+
+/*
+ * control operations that apply to both udp and tcp transports
+ */
+#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
+#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
+#define CLGET_FD 6 /* get connections file descriptor */
+#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) */
+#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */
+#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy */
+#define CLGET_XID 10 /* Get xid */
+#define CLSET_XID 11 /* Set xid */
+#define CLGET_VERS 12 /* Get version number */
+#define CLSET_VERS 13 /* Set version number */
+#define CLGET_PROG 14 /* Get program number */
+#define CLSET_PROG 15 /* Set program number */
+#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) */
+#define CLSET_PUSH_TIMOD 17 /* push timod if not already present */
+#define CLSET_POP_TIMOD 18 /* pop timod */
+/*
+ * Connectionless only control operations
+ */
+#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */
+#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */
+#define CLSET_ASYNC 19
+#define CLSET_CONNECT 20 /* Use connect() for UDP. (int) */
+
+/*
+ * void
+ * CLNT_DESTROY(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+
+
+/*
+ * RPCTEST is a test program which is accessible on every rpc
+ * transport/port. It is used for testing, performance evaluation,
+ * and network administration.
+ */
+
+#define RPCTEST_PROGRAM ((rpcprog_t)1)
+#define RPCTEST_VERSION ((rpcvers_t)1)
+#define RPCTEST_NULL_PROC ((rpcproc_t)2)
+#define RPCTEST_NULL_BATCH_PROC ((rpcproc_t)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((rpcproc_t)0)
+
+/*
+ * Below are the client handle creation routines for the various
+ * implementations of client side rpc. They can return NULL if a
+ * creation failure occurs.
+ */
+
+/*
+ * Generic client creation routine. Supported protocols are those that
+ * belong to the nettype namespace (/etc/netconfig).
+ */
+__BEGIN_DECLS
+extern CLIENT *clnt_create(const char *, const rpcprog_t, const rpcvers_t,
+ const char *);
+/*
+ *
+ * const char *hostname; -- hostname
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const char *nettype; -- network type
+ */
+
+ /*
+ * Generic client creation routine. Just like clnt_create(), except
+ * it takes an additional timeout parameter.
+ */
+extern CLIENT * clnt_create_timed(const char *, const rpcprog_t,
+ const rpcvers_t, const char *, const struct timeval *);
+/*
+ *
+ * const char *hostname; -- hostname
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const char *nettype; -- network type
+ * const struct timeval *tp; -- timeout
+ */
+
+/*
+ * Generic client creation routine. Supported protocols are which belong
+ * to the nettype name space.
+ */
+extern CLIENT *clnt_create_vers(const char *, const rpcprog_t, rpcvers_t *,
+ const rpcvers_t, const rpcvers_t,
+ const char *);
+/*
+ * const char *host; -- hostname
+ * const rpcprog_t prog; -- program number
+ * rpcvers_t *vers_out; -- servers highest available version
+ * const rpcvers_t vers_low; -- low version number
+ * const rpcvers_t vers_high; -- high version number
+ * const char *nettype; -- network type
+ */
+
+/*
+ * Generic client creation routine. Supported protocols are which belong
+ * to the nettype name space.
+ */
+extern CLIENT * clnt_create_vers_timed(const char *, const rpcprog_t,
+ rpcvers_t *, const rpcvers_t, const rpcvers_t, const char *,
+ const struct timeval *);
+/*
+ * const char *host; -- hostname
+ * const rpcprog_t prog; -- program number
+ * rpcvers_t *vers_out; -- servers highest available version
+ * const rpcvers_t vers_low; -- low version number
+ * const rpcvers_t vers_high; -- high version number
+ * const char *nettype; -- network type
+ * const struct timeval *tp -- timeout
+ */
+
+/*
+ * Generic client creation routine. It takes a netconfig structure
+ * instead of nettype
+ */
+extern CLIENT *clnt_tp_create(const char *, const rpcprog_t,
+ const rpcvers_t, const struct netconfig *);
+/*
+ * const char *hostname; -- hostname
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const struct netconfig *netconf; -- network config structure
+ */
+
+/*
+ * Generic client creation routine. Just like clnt_tp_create(), except
+ * it takes an additional timeout parameter.
+ */
+extern CLIENT * clnt_tp_create_timed(const char *, const rpcprog_t,
+ const rpcvers_t, const struct netconfig *, const struct timeval *);
+/*
+ * const char *hostname; -- hostname
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const struct netconfig *netconf; -- network config structure
+ * const struct timeval *tp -- timeout
+ */
+
+/*
+ * Generic TLI create routine. Only provided for compatibility.
+ */
+
+extern CLIENT *clnt_tli_create(const int, const struct netconfig *,
+ struct netbuf *, const rpcprog_t,
+ const rpcvers_t, const u_int, const u_int);
+/*
+ * const register int fd; -- fd
+ * const struct netconfig *nconf; -- netconfig structure
+ * struct netbuf *svcaddr; -- servers address
+ * const u_long prog; -- program number
+ * const u_long vers; -- version number
+ * const u_int sendsz; -- send size
+ * const u_int recvsz; -- recv size
+ */
+
+/*
+ * Low level clnt create routine for connectionful transports, e.g. tcp.
+ */
+extern CLIENT *clnt_vc_create(const int, const struct netbuf *,
+ const rpcprog_t, const rpcvers_t,
+ u_int, u_int);
+/*
+ * Added for compatibility to old rpc 4.0. Obsoleted by clnt_vc_create().
+ */
+extern CLIENT *clntunix_create(struct sockaddr_un *,
+ u_long, u_long, int *, u_int, u_int);
+/*
+ * const int fd; -- open file descriptor
+ * const struct netbuf *svcaddr; -- servers address
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const u_int sendsz; -- buffer recv size
+ * const u_int recvsz; -- buffer send size
+ */
+
+/*
+ * Low level clnt create routine for connectionless transports, e.g. udp.
+ */
+extern CLIENT *clnt_dg_create(const int, const struct netbuf *,
+ const rpcprog_t, const rpcvers_t,
+ const u_int, const u_int);
+/*
+ * const int fd; -- open file descriptor
+ * const struct netbuf *svcaddr; -- servers address
+ * const rpcprog_t program; -- program number
+ * const rpcvers_t version; -- version number
+ * const u_int sendsz; -- buffer recv size
+ * const u_int recvsz; -- buffer send size
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ * CLIENT *
+ * clnt_raw_create(prog, vers)
+ * u_long prog;
+ * u_long vers;
+ */
+extern CLIENT *clnt_raw_create(rpcprog_t, rpcvers_t);
+
+__END_DECLS
+
+
+/*
+ * Print why creation failed
+ */
+__BEGIN_DECLS
+extern void clnt_pcreateerror(const char *); /* stderr */
+extern char *clnt_spcreateerror(const char *); /* string */
+__END_DECLS
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */
+__BEGIN_DECLS
+extern void clnt_perrno(enum clnt_stat); /* stderr */
+extern char *clnt_sperrno(enum clnt_stat); /* string */
+__END_DECLS
+
+/*
+ * Print an English error message, given the client error code
+ */
+__BEGIN_DECLS
+extern void clnt_perror(CLIENT *, const char *); /* stderr */
+extern char *clnt_sperror(CLIENT *, const char *); /* string */
+__END_DECLS
+
+
+/*
+ * If a creation fails, the following allows the user to figure out why.
+ */
+struct rpc_createerr {
+ enum clnt_stat cf_stat;
+ struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
+};
+
+__BEGIN_DECLS
+extern struct rpc_createerr *__rpc_createerr(void);
+__END_DECLS
+#define rpc_createerr (*(__rpc_createerr()))
+
+/*
+ * The simplified interface:
+ * enum clnt_stat
+ * rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
+ * const char *host;
+ * const rpcprog_t prognum;
+ * const rpcvers_t versnum;
+ * const rpcproc_t procnum;
+ * const xdrproc_t inproc, outproc;
+ * const char *in;
+ * char *out;
+ * const char *nettype;
+ */
+__BEGIN_DECLS
+extern enum clnt_stat rpc_call(const char *, const rpcprog_t,
+ const rpcvers_t, const rpcproc_t,
+ const xdrproc_t, const char *,
+ const xdrproc_t, char *, const char *);
+__END_DECLS
+
+/*
+ * RPC broadcast interface
+ * The call is broadcasted to all locally connected nets.
+ *
+ * extern enum clnt_stat
+ * rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
+ * eachresult, nettype)
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const rpcproc_t proc; -- procedure number
+ * const xdrproc_t xargs; -- xdr routine for args
+ * caddr_t argsp; -- pointer to args
+ * const xdrproc_t xresults; -- xdr routine for results
+ * caddr_t resultsp; -- pointer to results
+ * const resultproc_t eachresult; -- call with each result
+ * const char *nettype; -- Transport type
+ *
+ * For each valid response received, the procedure eachresult is called.
+ * Its form is:
+ * done = eachresult(resp, raddr, nconf)
+ * bool_t done;
+ * caddr_t resp;
+ * struct netbuf *raddr;
+ * struct netconfig *nconf;
+ * where resp points to the results of the call and raddr is the
+ * address if the responder to the broadcast. nconf is the transport
+ * on which the response was received.
+ *
+ * extern enum clnt_stat
+ * rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
+ * eachresult, inittime, waittime, nettype)
+ * const rpcprog_t prog; -- program number
+ * const rpcvers_t vers; -- version number
+ * const rpcproc_t proc; -- procedure number
+ * const xdrproc_t xargs; -- xdr routine for args
+ * caddr_t argsp; -- pointer to args
+ * const xdrproc_t xresults; -- xdr routine for results
+ * caddr_t resultsp; -- pointer to results
+ * const resultproc_t eachresult; -- call with each result
+ * const int inittime; -- how long to wait initially
+ * const int waittime; -- maximum time to wait
+ * const char *nettype; -- Transport type
+ */
+
+typedef bool_t (*resultproc_t)(caddr_t, ...);
+
+__BEGIN_DECLS
+extern enum clnt_stat rpc_broadcast(const rpcprog_t, const rpcvers_t,
+ const rpcproc_t, const xdrproc_t,
+ caddr_t, const xdrproc_t, caddr_t,
+ const resultproc_t, const char *);
+extern enum clnt_stat rpc_broadcast_exp(const rpcprog_t, const rpcvers_t,
+ const rpcproc_t, const xdrproc_t,
+ caddr_t, const xdrproc_t, caddr_t,
+ const resultproc_t, const int,
+ const int, const char *);
+__END_DECLS
+
+/* For backward compatibility */
+#include <rpc/clnt_soc.h>
+
+#endif /* !_RPC_CLNT_H_ */
diff --git a/freebsd/include/rpc/clnt_soc.h b/freebsd/include/rpc/clnt_soc.h
new file mode 100644
index 00000000..1e7a0dea
--- /dev/null
+++ b/freebsd/include/rpc/clnt_soc.h
@@ -0,0 +1,106 @@
+/* $NetBSD: clnt_soc.h,v 1.1 2000/06/02 22:57:55 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ */
+
+#ifndef _RPC_CLNT_SOC_H
+#define _RPC_CLNT_SOC_H
+
+/* derived from clnt_soc.h 1.3 88/12/17 SMI */
+
+/*
+ * All the following declarations are only for backward compatibility
+ * with TS-RPC.
+ */
+
+#include <sys/cdefs.h>
+
+#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long prog;
+ * u_long version;
+ * register int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clnttcp_create(struct sockaddr_in *, u_long, u_long, int *,
+ u_int, u_int);
+__END_DECLS
+
+/*
+ * Raw (memory) rpc.
+ */
+__BEGIN_DECLS
+extern CLIENT *clntraw_create(u_long, u_long);
+__END_DECLS
+
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clntudp_create(struct sockaddr_in *, u_long, u_long,
+ struct timeval, int *);
+extern CLIENT *clntudp_bufcreate(struct sockaddr_in *, u_long, u_long,
+ struct timeval, int *, u_int, u_int);
+__END_DECLS
+
+#endif /* _RPC_CLNT_SOC_H */
diff --git a/freebsd/include/rpc/clnt_stat.h b/freebsd/include/rpc/clnt_stat.h
new file mode 100644
index 00000000..6148b4eb
--- /dev/null
+++ b/freebsd/include/rpc/clnt_stat.h
@@ -0,0 +1,83 @@
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 1986 - 1991, 1994, 1996, 1997 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+/*
+ * clnt_stat.h - Client side remote procedure call enum
+ *
+ */
+
+#ifndef _RPC_CLNT_STAT_H
+#define _RPC_CLNT_STAT_H
+
+/* #pragma ident "@(#)clnt_stat.h 1.2 97/04/28 SMI" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum clnt_stat {
+ RPC_SUCCESS = 0, /* call succeeded */
+ /*
+ * local errors
+ */
+ RPC_CANTENCODEARGS = 1, /* can't encode arguments */
+ RPC_CANTDECODERES = 2, /* can't decode results */
+ RPC_CANTSEND = 3, /* failure in sending call */
+ RPC_CANTRECV = 4,
+ /* failure in receiving result */
+ RPC_TIMEDOUT = 5, /* call timed out */
+ RPC_INTR = 18, /* call interrupted */
+ RPC_UDERROR = 23, /* recv got uderr indication */
+ /*
+ * remote errors
+ */
+ RPC_VERSMISMATCH = 6, /* rpc versions not compatible */
+ RPC_AUTHERROR = 7, /* authentication error */
+ RPC_PROGUNAVAIL = 8, /* program not available */
+ RPC_PROGVERSMISMATCH = 9, /* program version mismatched */
+ RPC_PROCUNAVAIL = 10, /* procedure unavailable */
+ RPC_CANTDECODEARGS = 11, /* decode arguments error */
+ RPC_SYSTEMERROR = 12, /* generic "other problem" */
+
+ /*
+ * rpc_call & clnt_create errors
+ */
+ RPC_UNKNOWNHOST = 13, /* unknown host name */
+ RPC_UNKNOWNPROTO = 17, /* unknown protocol */
+ RPC_UNKNOWNADDR = 19, /* Remote address unknown */
+ RPC_NOBROADCAST = 21, /* Broadcasting not supported */
+
+ /*
+ * rpcbind errors
+ */
+ RPC_RPCBFAILURE = 14, /* the pmapper failed in its call */
+#define RPC_PMAPFAILURE RPC_RPCBFAILURE
+ RPC_PROGNOTREGISTERED = 15, /* remote program is not registered */
+ RPC_N2AXLATEFAILURE = 22,
+ /* Name to address translation failed */
+ /*
+ * Misc error in the TLI library
+ */
+ RPC_TLIERROR = 20,
+ /*
+ * unspecified error
+ */
+ RPC_FAILED = 16,
+ /*
+ * asynchronous errors
+ */
+ RPC_INPROGRESS = 24,
+ RPC_STALERACHANDLE = 25,
+ RPC_CANTCONNECT = 26, /* couldn't make connection (cots) */
+ RPC_XPRTFAILED = 27, /* received discon from remote (cots) */
+ RPC_CANTCREATESTREAM = 28 /* can't push rpc module (cots) */
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_RPC_CLNT_STAT_H */
diff --git a/freebsd/include/rpc/pmap_clnt.h b/freebsd/include/rpc/pmap_clnt.h
new file mode 100644
index 00000000..89f1614a
--- /dev/null
+++ b/freebsd/include/rpc/pmap_clnt.h
@@ -0,0 +1,86 @@
+/* $NetBSD: pmap_clnt.h,v 1.9 2000/06/02 22:57:55 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI
+ * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * pmap_clnt.h
+ * Supplies C routines to get to portmap services.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Usage:
+ * success = pmap_set(program, version, protocol, port);
+ * success = pmap_unset(program, version);
+ * port = pmap_getport(address, program, version, protocol);
+ * head = pmap_getmaps(address);
+ * clnt_stat = pmap_rmtcall(address, program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ * (works for udp only.)
+ * clnt_stat = clnt_broadcast(program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, eachresult)
+ * (like pmap_rmtcall, except the call is broadcasted to all
+ * locally connected nets. For each valid response received,
+ * the procedure eachresult is called. Its form is:
+ * done = eachresult(resp, raddr)
+ * bool_t done;
+ * caddr_t resp;
+ * struct sockaddr_in raddr;
+ * where resp points to the results of the call and raddr is the
+ * address if the responder to the broadcast.
+ */
+
+#ifndef _RPC_PMAP_CLNT_H_
+#define _RPC_PMAP_CLNT_H_
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern bool_t pmap_set(u_long, u_long, int, int);
+extern bool_t pmap_unset(u_long, u_long);
+extern struct pmaplist *pmap_getmaps(struct sockaddr_in *);
+extern enum clnt_stat pmap_rmtcall(struct sockaddr_in *,
+ u_long, u_long, u_long,
+ xdrproc_t, caddr_t,
+ xdrproc_t, caddr_t,
+ struct timeval, u_long *);
+extern enum clnt_stat clnt_broadcast(u_long, u_long, u_long,
+ xdrproc_t, void *,
+ xdrproc_t, void *,
+ resultproc_t);
+extern u_short pmap_getport(struct sockaddr_in *,
+ u_long, u_long, u_int);
+__END_DECLS
+
+#endif /* !_RPC_PMAP_CLNT_H_ */
diff --git a/freebsd/include/rpc/pmap_prot.h b/freebsd/include/rpc/pmap_prot.h
new file mode 100644
index 00000000..366832a7
--- /dev/null
+++ b/freebsd/include/rpc/pmap_prot.h
@@ -0,0 +1,107 @@
+/* $NetBSD: pmap_prot.h,v 1.8 2000/06/02 22:57:55 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)pmap_prot.h 1.14 88/02/08 SMI
+ * from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * pmap_prot.h
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The following procedures are supported by the protocol:
+ *
+ * PMAPPROC_NULL() returns ()
+ * takes nothing, returns nothing
+ *
+ * PMAPPROC_SET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Registers the tuple
+ * [prog, vers, prot, port].
+ *
+ * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Un-registers pair
+ * [prog, vers]. prot and port are ignored.
+ *
+ * PMAPPROC_GETPORT(struct pmap) returns (long unsigned).
+ * 0 is failure. Otherwise returns the port number where the pair
+ * [prog, vers] is registered. It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
+ * RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * Calls the procedure on the local machine. If it is not registered,
+ * this procedure is quite; ie it does not return error information!!!
+ * This procedure only is supported on rpc/udp and calls via
+ * rpc/udp. This routine only passes null authentication parameters.
+ * This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#ifndef _RPC_PMAP_PROT_H
+#define _RPC_PMAP_PROT_H
+#include <sys/cdefs.h>
+
+#define PMAPPORT ((u_short)111)
+#define PMAPPROG ((u_long)100000)
+#define PMAPVERS ((u_long)2)
+#define PMAPVERS_PROTO ((u_long)2)
+#define PMAPVERS_ORIG ((u_long)1)
+#define PMAPPROC_NULL ((u_long)0)
+#define PMAPPROC_SET ((u_long)1)
+#define PMAPPROC_UNSET ((u_long)2)
+#define PMAPPROC_GETPORT ((u_long)3)
+#define PMAPPROC_DUMP ((u_long)4)
+#define PMAPPROC_CALLIT ((u_long)5)
+
+struct pmap {
+ long unsigned pm_prog;
+ long unsigned pm_vers;
+ long unsigned pm_prot;
+ long unsigned pm_port;
+};
+
+struct pmaplist {
+ struct pmap pml_map;
+ struct pmaplist *pml_next;
+};
+
+__BEGIN_DECLS
+extern bool_t xdr_pmap(XDR *, struct pmap *);
+extern bool_t xdr_pmaplist(XDR *, struct pmaplist **);
+extern bool_t xdr_pmaplist_ptr(XDR *, struct pmaplist *);
+__END_DECLS
+
+#endif /* !_RPC_PMAP_PROT_H */
diff --git a/freebsd/include/rpc/rpc.h b/freebsd/include/rpc/rpc.h
new file mode 100644
index 00000000..725b542a
--- /dev/null
+++ b/freebsd/include/rpc/rpc.h
@@ -0,0 +1,108 @@
+/* $NetBSD: rpc.h,v 1.13 2000/06/02 22:57:56 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)rpc.h 1.9 88/02/08 SMI
+ * from: @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+#ifndef _RPC_RPC_H
+#define _RPC_RPC_H
+
+#include <rpc/types.h> /* some typedefs */
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/* external data representation interfaces */
+#include <rpc/xdr.h> /* generic (de)serializer */
+
+/* Client side only authentication */
+#include <rpc/auth.h> /* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include <rpc/clnt.h> /* generic rpc stuff */
+
+/* semi-private protocol headers */
+#include <rpc/rpc_msg.h> /* protocol for rpc messages */
+#include <rpc/auth_unix.h> /* protocol for unix style cred */
+/*
+ * Uncomment-out the next line if you are building the rpc library with
+ * DES Authentication (see the README file in the secure_rpc/ directory).
+ */
+#include <rpc/auth_des.h> /* protocol for des style cred */
+
+/* Server side only remote procedure callee */
+#include <rpc/svc.h> /* service manager and multiplexer */
+#include <rpc/svc_auth.h> /* service side authenticator */
+
+/* Portmapper client, server, and protocol headers */
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+
+#ifndef _KERNEL
+#include <rpc/rpcb_clnt.h> /* rpcbind interface functions */
+#endif
+
+#include <rpc/rpcent.h>
+
+__BEGIN_DECLS
+extern int get_myaddress(struct sockaddr_in *);
+extern int bindresvport(int, struct sockaddr_in *);
+extern int registerrpc(int, int, int, char *(*)(char [UDPMSGSIZE]),
+ xdrproc_t, xdrproc_t);
+extern int callrpc(const char *, int, int, int, xdrproc_t, void *,
+ xdrproc_t , void *);
+extern int getrpcport(char *, int, int, int);
+
+char *taddr2uaddr(const struct netconfig *, const struct netbuf *);
+struct netbuf *uaddr2taddr(const struct netconfig *, const char *);
+
+struct sockaddr;
+extern int bindresvport_sa(int, struct sockaddr *);
+__END_DECLS
+
+/*
+ * The following are not exported interfaces, they are for internal library
+ * and rpcbind use only. Do not use, they may change without notice.
+ */
+__BEGIN_DECLS
+int __rpc_nconf2fd(const struct netconfig *);
+int __rpc_nconf2sockinfo(const struct netconfig *, struct __rpc_sockinfo *);
+int __rpc_fd2sockinfo(int, struct __rpc_sockinfo *);
+u_int __rpc_get_t_size(int, int, int);
+__END_DECLS
+
+#endif /* !_RPC_RPC_H */
diff --git a/freebsd/include/rpc/rpc_msg.h b/freebsd/include/rpc/rpc_msg.h
new file mode 100644
index 00000000..354b3414
--- /dev/null
+++ b/freebsd/include/rpc/rpc_msg.h
@@ -0,0 +1,214 @@
+/* $NetBSD: rpc_msg.h,v 1.11 2000/06/02 22:57:56 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)rpc_msg.h 1.7 86/07/16 SMI
+ * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_RPC_MSG_H
+#define _RPC_RPC_MSG_H
+
+#define RPC_MSG_VERSION ((u_int32_t) 2)
+#define RPC_SERVICE_PORT ((u_short) 2048)
+
+/*
+ * Bottom up definition of an rpc message.
+ * NOTE: call and reply use the same overall stuct but
+ * different parts of unions within it.
+ */
+
+enum msg_type {
+ CALL=0,
+ REPLY=1
+};
+
+enum reply_stat {
+ MSG_ACCEPTED=0,
+ MSG_DENIED=1
+};
+
+enum accept_stat {
+ SUCCESS=0,
+ PROG_UNAVAIL=1,
+ PROG_MISMATCH=2,
+ PROC_UNAVAIL=3,
+ GARBAGE_ARGS=4,
+ SYSTEM_ERR=5
+};
+
+enum reject_stat {
+ RPC_MISMATCH=0,
+ AUTH_ERROR=1
+};
+
+/*
+ * Reply part of an rpc exchange
+ */
+
+/*
+ * Reply to an rpc request that was accepted by the server.
+ * Note: there could be an error even though the request was
+ * accepted.
+ */
+struct accepted_reply {
+ struct opaque_auth ar_verf;
+ enum accept_stat ar_stat;
+ union {
+ struct {
+ rpcvers_t low;
+ rpcvers_t high;
+ } AR_versions;
+ struct {
+ caddr_t where;
+ xdrproc_t proc;
+ } AR_results;
+ /* and many other null cases */
+ } ru;
+#define ar_results ru.AR_results
+#define ar_vers ru.AR_versions
+};
+
+/*
+ * Reply to an rpc request that was rejected by the server.
+ */
+struct rejected_reply {
+ enum reject_stat rj_stat;
+ union {
+ struct {
+ rpcvers_t low;
+ rpcvers_t high;
+ } RJ_versions;
+ enum auth_stat RJ_why; /* why authentication did not work */
+ } ru;
+#define rj_vers ru.RJ_versions
+#define rj_why ru.RJ_why
+};
+
+/*
+ * Body of a reply to an rpc request.
+ */
+struct reply_body {
+ enum reply_stat rp_stat;
+ union {
+ struct accepted_reply RP_ar;
+ struct rejected_reply RP_dr;
+ } ru;
+#define rp_acpt ru.RP_ar
+#define rp_rjct ru.RP_dr
+};
+
+/*
+ * Body of an rpc request call.
+ */
+struct call_body {
+ rpcvers_t cb_rpcvers; /* must be equal to two */
+ rpcprog_t cb_prog;
+ rpcvers_t cb_vers;
+ rpcproc_t cb_proc;
+ struct opaque_auth cb_cred;
+ struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+ u_int32_t rm_xid;
+ enum msg_type rm_direction;
+ union {
+ struct call_body RM_cmb;
+ struct reply_body RM_rmb;
+ } ru;
+#define rm_call ru.RM_cmb
+#define rm_reply ru.RM_rmb
+};
+#define acpted_rply ru.RM_rmb.ru.RP_ar
+#define rjcted_rply ru.RM_rmb.ru.RP_dr
+
+__BEGIN_DECLS
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callmsg(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callhdr(XDR *, struct rpc_msg *);
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *rmsg;
+ */
+extern bool_t xdr_replymsg(XDR *, struct rpc_msg *);
+
+
+/*
+ * XDR routine to handle an accepted rpc reply.
+ * xdr_accepted_reply(xdrs, rej)
+ * XDR *xdrs;
+ * struct accepted_reply *rej;
+ */
+extern bool_t xdr_accepted_reply(XDR *, struct accepted_reply *);
+
+/*
+ * XDR routine to handle a rejected rpc reply.
+ * xdr_rejected_reply(xdrs, rej)
+ * XDR *xdrs;
+ * struct rejected_reply *rej;
+ */
+extern bool_t xdr_rejected_reply(XDR *, struct rejected_reply *);
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * struct rpc_msg *msg;
+ * struct rpc_err *error;
+ */
+extern void _seterr_reply(struct rpc_msg *, struct rpc_err *);
+__END_DECLS
+
+#endif /* !_RPC_RPC_MSG_H */
diff --git a/freebsd/include/rpc/rpcb_clnt.h b/freebsd/include/rpc/rpcb_clnt.h
new file mode 100644
index 00000000..fa64a853
--- /dev/null
+++ b/freebsd/include/rpc/rpcb_clnt.h
@@ -0,0 +1,85 @@
+/* $NetBSD: rpcb_clnt.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * rpcb_clnt.h
+ * Supplies C routines to get to rpcbid services.
+ *
+ */
+
+/*
+ * Usage:
+ * success = rpcb_set(program, version, nconf, address);
+ * success = rpcb_unset(program, version, nconf);
+ * success = rpcb_getaddr(program, version, nconf, host);
+ * head = rpcb_getmaps(nconf, host);
+ * clnt_stat = rpcb_rmtcall(nconf, host, program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, tout, addr_ptr)
+ * success = rpcb_gettime(host, timep)
+ * uaddr = rpcb_taddr2uaddr(nconf, taddr);
+ * taddr = rpcb_uaddr2uaddr(nconf, uaddr);
+ */
+
+#ifndef _RPC_RPCB_CLNT_H
+#define _RPC_RPCB_CLNT_H
+
+/* #pragma ident "@(#)rpcb_clnt.h 1.13 94/04/25 SMI" */
+/* rpcb_clnt.h 1.3 88/12/05 SMI */
+
+#include <rpc/types.h>
+#include <rpc/rpcb_prot.h>
+
+__BEGIN_DECLS
+extern bool_t rpcb_set(const rpcprog_t, const rpcvers_t,
+ const struct netconfig *, const struct netbuf *);
+extern bool_t rpcb_unset(const rpcprog_t, const rpcvers_t,
+ const struct netconfig *);
+extern rpcblist *rpcb_getmaps(const struct netconfig *, const char *);
+extern enum clnt_stat rpcb_rmtcall(const struct netconfig *,
+ const char *, const rpcprog_t,
+ const rpcvers_t, const rpcproc_t,
+ const xdrproc_t, const caddr_t,
+ const xdrproc_t, const caddr_t,
+ const struct timeval,
+ const struct netbuf *);
+extern bool_t rpcb_getaddr(const rpcprog_t, const rpcvers_t,
+ const struct netconfig *, struct netbuf *,
+ const char *);
+extern bool_t rpcb_gettime(const char *, time_t *);
+extern char *rpcb_taddr2uaddr(struct netconfig *, struct netbuf *);
+extern struct netbuf *rpcb_uaddr2taddr(struct netconfig *, char *);
+__END_DECLS
+
+#endif /* !_RPC_RPCB_CLNT_H */
diff --git a/freebsd/include/rpc/rpcb_prot.x b/freebsd/include/rpc/rpcb_prot.x
new file mode 100644
index 00000000..c5748413
--- /dev/null
+++ b/freebsd/include/rpc/rpcb_prot.x
@@ -0,0 +1,554 @@
+%/*
+% * $FreeBSD$
+% *
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+%/*
+% * Copyright (c) 1988 by Sun Microsystems, Inc.
+% */
+
+%/* from rpcb_prot.x */
+
+#ifdef RPC_HDR
+%
+%/* #pragma ident "@(#)rpcb_prot.x 1.5 94/04/29 SMI" */
+%
+%#ifndef _KERNEL
+%
+#endif
+
+/*
+ * rpcb_prot.x
+ * rpcbind protocol, versions 3 and 4, in RPC Language
+ */
+%
+%/*
+% * The following procedures are supported by the protocol in version 3:
+% *
+% * RPCBPROC_NULL() returns ()
+% * takes nothing, returns nothing
+% *
+% * RPCBPROC_SET(rpcb) returns (bool_t)
+% * TRUE is success, FALSE is failure. Registers the tuple
+% * [prog, vers, address, owner, netid].
+% * Finds out owner and netid information on its own.
+% *
+% * RPCBPROC_UNSET(rpcb) returns (bool_t)
+% * TRUE is success, FALSE is failure. Un-registers tuple
+% * [prog, vers, netid]. addresses is ignored.
+% * If netid is NULL, unregister all.
+% *
+% * RPCBPROC_GETADDR(rpcb) returns (string).
+% * 0 is failure. Otherwise returns the universal address where the
+% * triple [prog, vers, netid] is registered. Ignore address and owner.
+% *
+% * RPCBPROC_DUMP() RETURNS (rpcblist_ptr)
+% * used to dump the entire rpcbind maps
+% *
+% * RPCBPROC_CALLIT(rpcb_rmtcallargs)
+% * RETURNS (rpcb_rmtcallres);
+% * Calls the procedure on the remote machine. If it is not registered,
+% * this procedure is quiet; i.e. it does not return error information!!!
+% * This routine only passes null authentication parameters.
+% * It has no interface to xdr routines for RPCBPROC_CALLIT.
+% *
+% * RPCBPROC_GETTIME() returns (int).
+% * Gets the remote machines time
+% *
+% * RPCBPROC_UADDR2TADDR(strint) RETURNS (struct netbuf)
+% * Returns the netbuf address from universal address.
+% *
+% * RPCBPROC_TADDR2UADDR(struct netbuf) RETURNS (string)
+% * Returns the universal address from netbuf address.
+% *
+% * END OF RPCBIND VERSION 3 PROCEDURES
+% */
+%/*
+% * Except for RPCBPROC_CALLIT, the procedures above are carried over to
+% * rpcbind version 4. Those below are added or modified for version 4.
+% * NOTE: RPCBPROC_BCAST HAS THE SAME FUNCTIONALITY AND PROCEDURE NUMBER
+% * AS RPCBPROC_CALLIT.
+% *
+% * RPCBPROC_BCAST(rpcb_rmtcallargs)
+% * RETURNS (rpcb_rmtcallres);
+% * Calls the procedure on the remote machine. If it is not registered,
+% * this procedure IS quiet; i.e. it DOES NOT return error information!!!
+% * This routine should be used for broadcasting and nothing else.
+% *
+% * RPCBPROC_GETVERSADDR(rpcb) returns (string).
+% * 0 is failure. Otherwise returns the universal address where the
+% * triple [prog, vers, netid] is registered. Ignore address and owner.
+% * Same as RPCBPROC_GETADDR except that if the given version number
+% * is not available, the address is not returned.
+% *
+% * RPCBPROC_INDIRECT(rpcb_rmtcallargs)
+% * RETURNS (rpcb_rmtcallres);
+% * Calls the procedure on the remote machine. If it is not registered,
+% * this procedure is NOT quiet; i.e. it DOES return error information!!!
+% * as any normal application would expect.
+% *
+% * RPCBPROC_GETADDRLIST(rpcb) returns (rpcb_entry_list_ptr).
+% * Same as RPCBPROC_GETADDR except that it returns a list of all the
+% * addresses registered for the combination (prog, vers) (for all
+% * transports).
+% *
+% * RPCBPROC_GETSTAT(void) returns (rpcb_stat_byvers)
+% * Returns the statistics about the kind of requests received by rpcbind.
+% */
+%
+%/*
+% * A mapping of (program, version, network ID) to address
+% */
+struct rpcb {
+ rpcprog_t r_prog; /* program number */
+ rpcvers_t r_vers; /* version number */
+ string r_netid<>; /* network id */
+ string r_addr<>; /* universal address */
+ string r_owner<>; /* owner of this service */
+};
+#ifdef RPC_HDR
+%
+%typedef rpcb RPCB;
+%
+#endif
+%
+%/*
+% * A list of mappings
+% *
+% * Below are two definitions for the rpcblist structure. This is done because
+% * xdr_rpcblist() is specified to take a struct rpcblist **, rather than a
+% * struct rpcblist * that rpcgen would produce. One version of the rpcblist
+% * structure (actually called rp__list) is used with rpcgen, and the other is
+% * defined only in the header file for compatibility with the specified
+% * interface.
+% */
+
+struct rp__list {
+ rpcb rpcb_map;
+ struct rp__list *rpcb_next;
+};
+
+typedef rp__list *rpcblist_ptr; /* results of RPCBPROC_DUMP */
+
+#ifdef RPC_HDR
+%
+%typedef struct rp__list rpcblist;
+%typedef struct rp__list RPCBLIST;
+%
+%#ifndef __cplusplus
+%struct rpcblist {
+% RPCB rpcb_map;
+% struct rpcblist *rpcb_next;
+%};
+%#endif
+%
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+%extern bool_t xdr_rpcblist(XDR *, rpcblist**);
+%#ifdef __cplusplus
+%}
+%#endif
+%
+#endif
+
+%
+%/*
+% * Arguments of remote calls
+% */
+struct rpcb_rmtcallargs {
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ rpcproc_t proc; /* procedure number */
+ opaque args<>; /* argument */
+};
+#ifdef RPC_HDR
+%
+%/*
+% * Client-side only representation of rpcb_rmtcallargs structure.
+% *
+% * The routine that XDRs the rpcb_rmtcallargs structure must deal with the
+% * opaque arguments in the "args" structure. xdr_rpcb_rmtcallargs() needs to
+% * be passed the XDR routine that knows the args' structure. This routine
+% * doesn't need to go over-the-wire (and it wouldn't make sense anyway) since
+% * the application being called already knows the args structure. So we use a
+% * different "XDR" structure on the client side, r_rpcb_rmtcallargs, which
+% * includes the args' XDR routine.
+% */
+%struct r_rpcb_rmtcallargs {
+% rpcprog_t prog;
+% rpcvers_t vers;
+% rpcproc_t proc;
+% struct {
+% u_int args_len;
+% char *args_val;
+% } args;
+% xdrproc_t xdr_args; /* encodes args */
+%};
+%
+#endif /* def RPC_HDR */
+%
+%/*
+% * Results of the remote call
+% */
+struct rpcb_rmtcallres {
+ string addr<>; /* remote universal address */
+ opaque results<>; /* result */
+};
+#ifdef RPC_HDR
+%
+%/*
+% * Client-side only representation of rpcb_rmtcallres structure.
+% */
+%struct r_rpcb_rmtcallres {
+% char *addr;
+% struct {
+% u_int32_t results_len;
+% char *results_val;
+% } results;
+% xdrproc_t xdr_res; /* decodes results */
+%};
+#endif /* RPC_HDR */
+%
+%/*
+% * rpcb_entry contains a merged address of a service on a particular
+% * transport, plus associated netconfig information. A list of rpcb_entrys
+% * is returned by RPCBPROC_GETADDRLIST. See netconfig.h for values used
+% * in r_nc_* fields.
+% */
+struct rpcb_entry {
+ string r_maddr<>; /* merged address of service */
+ string r_nc_netid<>; /* netid field */
+ unsigned int r_nc_semantics; /* semantics of transport */
+ string r_nc_protofmly<>; /* protocol family */
+ string r_nc_proto<>; /* protocol name */
+};
+%
+%/*
+% * A list of addresses supported by a service.
+% */
+struct rpcb_entry_list {
+ rpcb_entry rpcb_entry_map;
+ struct rpcb_entry_list *rpcb_entry_next;
+};
+
+typedef rpcb_entry_list *rpcb_entry_list_ptr;
+
+%
+%/*
+% * rpcbind statistics
+% */
+%
+const rpcb_highproc_2 = RPCBPROC_CALLIT;
+const rpcb_highproc_3 = RPCBPROC_TADDR2UADDR;
+const rpcb_highproc_4 = RPCBPROC_GETSTAT;
+
+const RPCBSTAT_HIGHPROC = 13; /* # of procs in rpcbind V4 plus one */
+const RPCBVERS_STAT = 3; /* provide only for rpcbind V2, V3 and V4 */
+const RPCBVERS_4_STAT = 2;
+const RPCBVERS_3_STAT = 1;
+const RPCBVERS_2_STAT = 0;
+%
+%/* Link list of all the stats about getport and getaddr */
+struct rpcbs_addrlist {
+ rpcprog_t prog;
+ rpcvers_t vers;
+ int success;
+ int failure;
+ string netid<>;
+ struct rpcbs_addrlist *next;
+};
+%
+%/* Link list of all the stats about rmtcall */
+struct rpcbs_rmtcalllist {
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcproc_t proc;
+ int success;
+ int failure;
+ int indirect; /* whether callit or indirect */
+ string netid<>;
+ struct rpcbs_rmtcalllist *next;
+};
+
+typedef int rpcbs_proc[RPCBSTAT_HIGHPROC];
+typedef rpcbs_addrlist *rpcbs_addrlist_ptr;
+typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr;
+
+struct rpcb_stat {
+ rpcbs_proc info;
+ int setinfo;
+ int unsetinfo;
+ rpcbs_addrlist_ptr addrinfo;
+ rpcbs_rmtcalllist_ptr rmtinfo;
+};
+%
+%/*
+% * One rpcb_stat structure is returned for each version of rpcbind
+% * being monitored.
+% */
+
+typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT];
+
+#ifdef RPC_HDR
+%
+%/*
+% * We don't define netbuf in RPCL, since it would contain structure member
+% * names that would conflict with the definition of struct netbuf in
+% * <tiuser.h>. Instead we merely declare the XDR routine xdr_netbuf() here,
+% * and implement it ourselves in rpc/rpcb_prot.c.
+% */
+%#ifdef __cplusplus
+%extern "C" bool_t xdr_netbuf(XDR *, struct netbuf *);
+%
+%#else /* __STDC__ */
+%extern bool_t xdr_netbuf(XDR *, struct netbuf *);
+%
+%#endif
+#endif /* def RPC_HDR */
+
+/*
+ * rpcbind procedures
+ */
+program RPCBPROG {
+ version RPCBVERS {
+ bool
+ RPCBPROC_SET(rpcb) = 1;
+
+ bool
+ RPCBPROC_UNSET(rpcb) = 2;
+
+ string
+ RPCBPROC_GETADDR(rpcb) = 3;
+
+ rpcblist_ptr
+ RPCBPROC_DUMP(void) = 4;
+
+ rpcb_rmtcallres
+ RPCBPROC_CALLIT(rpcb_rmtcallargs) = 5;
+
+ unsigned int
+ RPCBPROC_GETTIME(void) = 6;
+
+ struct netbuf
+ RPCBPROC_UADDR2TADDR(string) = 7;
+
+ string
+ RPCBPROC_TADDR2UADDR(struct netbuf) = 8;
+ } = 3;
+
+ version RPCBVERS4 {
+ bool
+ RPCBPROC_SET(rpcb) = 1;
+
+ bool
+ RPCBPROC_UNSET(rpcb) = 2;
+
+ string
+ RPCBPROC_GETADDR(rpcb) = 3;
+
+ rpcblist_ptr
+ RPCBPROC_DUMP(void) = 4;
+
+ /*
+ * NOTE: RPCBPROC_BCAST has the same functionality as CALLIT;
+ * the new name is intended to indicate that this
+ * procedure should be used for broadcast RPC, and
+ * RPCBPROC_INDIRECT should be used for indirect calls.
+ */
+ rpcb_rmtcallres
+ RPCBPROC_BCAST(rpcb_rmtcallargs) = RPCBPROC_CALLIT;
+
+ unsigned int
+ RPCBPROC_GETTIME(void) = 6;
+
+ struct netbuf
+ RPCBPROC_UADDR2TADDR(string) = 7;
+
+ string
+ RPCBPROC_TADDR2UADDR(struct netbuf) = 8;
+
+ string
+ RPCBPROC_GETVERSADDR(rpcb) = 9;
+
+ rpcb_rmtcallres
+ RPCBPROC_INDIRECT(rpcb_rmtcallargs) = 10;
+
+ rpcb_entry_list_ptr
+ RPCBPROC_GETADDRLIST(rpcb) = 11;
+
+ rpcb_stat_byvers
+ RPCBPROC_GETSTAT(void) = 12;
+ } = 4;
+} = 100000;
+#ifdef RPC_HDR
+%
+%#define RPCBVERS_3 RPCBVERS
+%#define RPCBVERS_4 RPCBVERS4
+%
+%#define _PATH_RPCBINDSOCK "/var/run/rpcbind.sock"
+%
+%#else /* ndef _KERNEL */
+%#ifdef __cplusplus
+%extern "C" {
+%#endif
+%
+%/*
+% * A mapping of (program, version, network ID) to address
+% */
+%struct rpcb {
+% rpcprog_t r_prog; /* program number */
+% rpcvers_t r_vers; /* version number */
+% char *r_netid; /* network id */
+% char *r_addr; /* universal address */
+% char *r_owner; /* owner of the mapping */
+%};
+%typedef struct rpcb RPCB;
+%
+%/*
+% * A list of mappings
+% */
+%struct rpcblist {
+% RPCB rpcb_map;
+% struct rpcblist *rpcb_next;
+%};
+%typedef struct rpcblist RPCBLIST;
+%typedef struct rpcblist *rpcblist_ptr;
+%
+%/*
+% * Remote calls arguments
+% */
+%struct rpcb_rmtcallargs {
+% rpcprog_t prog; /* program number */
+% rpcvers_t vers; /* version number */
+% rpcproc_t proc; /* procedure number */
+% u_int32_t arglen; /* arg len */
+% caddr_t args_ptr; /* argument */
+% xdrproc_t xdr_args; /* XDR routine for argument */
+%};
+%typedef struct rpcb_rmtcallargs rpcb_rmtcallargs;
+%
+%/*
+% * Remote calls results
+% */
+%struct rpcb_rmtcallres {
+% char *addr_ptr; /* remote universal address */
+% u_int32_t resultslen; /* results length */
+% caddr_t results_ptr; /* results */
+% xdrproc_t xdr_results; /* XDR routine for result */
+%};
+%typedef struct rpcb_rmtcallres rpcb_rmtcallres;
+%
+%struct rpcb_entry {
+% char *r_maddr;
+% char *r_nc_netid;
+% unsigned int r_nc_semantics;
+% char *r_nc_protofmly;
+% char *r_nc_proto;
+%};
+%typedef struct rpcb_entry rpcb_entry;
+%
+%/*
+% * A list of addresses supported by a service.
+% */
+%
+%struct rpcb_entry_list {
+% rpcb_entry rpcb_entry_map;
+% struct rpcb_entry_list *rpcb_entry_next;
+%};
+%typedef struct rpcb_entry_list rpcb_entry_list;
+%
+%typedef rpcb_entry_list *rpcb_entry_list_ptr;
+%
+%/*
+% * rpcbind statistics
+% */
+%
+%#define rpcb_highproc_2 RPCBPROC_CALLIT
+%#define rpcb_highproc_3 RPCBPROC_TADDR2UADDR
+%#define rpcb_highproc_4 RPCBPROC_GETSTAT
+%#define RPCBSTAT_HIGHPROC 13
+%#define RPCBVERS_STAT 3
+%#define RPCBVERS_4_STAT 2
+%#define RPCBVERS_3_STAT 1
+%#define RPCBVERS_2_STAT 0
+%
+%/* Link list of all the stats about getport and getaddr */
+%
+%struct rpcbs_addrlist {
+% rpcprog_t prog;
+% rpcvers_t vers;
+% int success;
+% int failure;
+% char *netid;
+% struct rpcbs_addrlist *next;
+%};
+%typedef struct rpcbs_addrlist rpcbs_addrlist;
+%
+%/* Link list of all the stats about rmtcall */
+%
+%struct rpcbs_rmtcalllist {
+% rpcprog_t prog;
+% rpcvers_t vers;
+% rpcproc_t proc;
+% int success;
+% int failure;
+% int indirect;
+% char *netid;
+% struct rpcbs_rmtcalllist *next;
+%};
+%typedef struct rpcbs_rmtcalllist rpcbs_rmtcalllist;
+%
+%typedef int rpcbs_proc[RPCBSTAT_HIGHPROC];
+%
+%typedef rpcbs_addrlist *rpcbs_addrlist_ptr;
+%
+%typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr;
+%
+%struct rpcb_stat {
+% rpcbs_proc info;
+% int setinfo;
+% int unsetinfo;
+% rpcbs_addrlist_ptr addrinfo;
+% rpcbs_rmtcalllist_ptr rmtinfo;
+%};
+%typedef struct rpcb_stat rpcb_stat;
+%
+%/*
+% * One rpcb_stat structure is returned for each version of rpcbind
+% * being monitored.
+% */
+%
+%typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT];
+%
+%#ifdef __cplusplus
+%}
+%#endif
+%
+%#endif /* ndef _KERNEL */
+#endif /* RPC_HDR */
diff --git a/freebsd/include/rpc/rpcent.h b/freebsd/include/rpc/rpcent.h
new file mode 100644
index 00000000..876b488b
--- /dev/null
+++ b/freebsd/include/rpc/rpcent.h
@@ -0,0 +1,67 @@
+/* $NetBSD: rpcent.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * rpcent.h,
+ * For converting rpc program numbers to names etc.
+ *
+ */
+
+#ifndef _RPC_RPCENT_H
+#define _RPC_RPCENT_H
+
+/* #pragma ident "@(#)rpcent.h 1.13 94/04/25 SMI" */
+/* @(#)rpcent.h 1.1 88/12/06 SMI */
+
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+
+__BEGIN_DECLS
+/*
+ * These interfaces are currently implemented through nsswitch and are
+ * MT-safe.
+ */
+extern struct rpcent *getrpcbyname(char *);
+extern struct rpcent *getrpcbynumber(int);
+extern struct rpcent *getrpcent(void);
+extern void setrpcent(int);
+extern void endrpcent(void);
+__END_DECLS
+
+#endif /* !_RPC_CENT_H */
diff --git a/freebsd/include/rpc/svc.h b/freebsd/include/rpc/svc.h
new file mode 100644
index 00000000..8466ef8b
--- /dev/null
+++ b/freebsd/include/rpc/svc.h
@@ -0,0 +1,474 @@
+/* $NetBSD: svc.h,v 1.17 2000/06/02 22:57:56 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)svc.h 1.35 88/12/17 SMI
+ * from: @(#)svc.h 1.27 94/04/25 SMI
+ * $FreeBSD$
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ *
+ * Copyright (C) 1986-1993 by Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_SVC_H
+#define _RPC_SVC_H
+#include <sys/cdefs.h>
+
+/*
+ * This interface must manage two items concerning remote procedure calling:
+ *
+ * 1) An arbitrary number of transport connections upon which rpc requests
+ * are received. The two most notable transports are TCP and UDP; they are
+ * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
+ * they in turn call xprt_register and xprt_unregister.
+ *
+ * 2) An arbitrary number of locally registered services. Services are
+ * described by the following four data: program number, version number,
+ * "service dispatch" function, a transport handle, and a boolean that
+ * indicates whether or not the exported program should be registered with a
+ * local binder service; if true the program's number and version and the
+ * port number from the transport handle are registered with the binder.
+ * These data are registered with the rpc svc system via svc_register.
+ *
+ * A service's dispatch function is called whenever an rpc request comes in
+ * on a transport. The request's program and version numbers must match
+ * those of the registered service. The dispatch function is passed two
+ * parameters, struct svc_req * and SVCXPRT *, defined below.
+ */
+
+/*
+ * Service control requests
+ */
+#define SVCGET_VERSQUIET 1
+#define SVCSET_VERSQUIET 2
+#define SVCGET_CONNMAXREC 3
+#define SVCSET_CONNMAXREC 4
+
+/*
+ * Operations for rpc_control().
+ */
+#define RPC_SVC_CONNMAXREC_SET 0 /* set max rec size, enable nonblock */
+#define RPC_SVC_CONNMAXREC_GET 1
+
+enum xprt_stat {
+ XPRT_DIED,
+ XPRT_MOREREQS,
+ XPRT_IDLE
+};
+
+/*
+ * Server side transport handle
+ */
+typedef struct __rpc_svcxprt {
+ int xp_fd;
+ u_short xp_port; /* associated port number */
+ const struct xp_ops {
+ /* receive incoming requests */
+ bool_t (*xp_recv)(struct __rpc_svcxprt *, struct rpc_msg *);
+ /* get transport status */
+ enum xprt_stat (*xp_stat)(struct __rpc_svcxprt *);
+ /* get arguments */
+ bool_t (*xp_getargs)(struct __rpc_svcxprt *, xdrproc_t,
+ void *);
+ /* send reply */
+ bool_t (*xp_reply)(struct __rpc_svcxprt *, struct rpc_msg *);
+ /* free mem allocated for args */
+ bool_t (*xp_freeargs)(struct __rpc_svcxprt *, xdrproc_t,
+ void *);
+ /* destroy this struct */
+ void (*xp_destroy)(struct __rpc_svcxprt *);
+ } *xp_ops;
+ int xp_addrlen; /* length of remote address */
+ struct sockaddr_in xp_raddr; /* remote addr. (backward ABI compat) */
+ /* XXX - fvdl stick this here for ABI backward compat reasons */
+ const struct xp_ops2 {
+ /* catch-all function */
+ bool_t (*xp_control)(struct __rpc_svcxprt *, const u_int,
+ void *);
+ } *xp_ops2;
+ char *xp_tp; /* transport provider device name */
+ char *xp_netid; /* network token */
+ struct netbuf xp_ltaddr; /* local transport address */
+ struct netbuf xp_rtaddr; /* remote transport address */
+ struct opaque_auth xp_verf; /* raw response verifier */
+ void *xp_p1; /* private: for use by svc ops */
+ void *xp_p2; /* private: for use by svc ops */
+ void *xp_p3; /* private: for use by svc lib */
+ int xp_type; /* transport type */
+} SVCXPRT;
+
+/*
+ * Interface to server-side authentication flavors.
+ */
+typedef struct __rpc_svcauth {
+ struct svc_auth_ops {
+ int (*svc_ah_wrap)(struct __rpc_svcauth *, XDR *,
+ xdrproc_t, caddr_t);
+ int (*svc_ah_unwrap)(struct __rpc_svcauth *, XDR *,
+ xdrproc_t, caddr_t);
+ } *svc_ah_ops;
+ void *svc_ah_private;
+} SVCAUTH;
+
+/*
+ * Server transport extensions (accessed via xp_p3).
+ */
+typedef struct __rpc_svcxprt_ext {
+ int xp_flags; /* versquiet */
+ SVCAUTH xp_auth; /* interface to auth methods */
+} SVCXPRT_EXT;
+
+/*
+ * Service request
+ */
+struct svc_req {
+ u_int32_t rq_prog; /* service program number */
+ u_int32_t rq_vers; /* service protocol version */
+ u_int32_t rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ void *rq_clntcred; /* read only cooked cred */
+ SVCXPRT *rq_xprt; /* associated transport */
+};
+
+/*
+ * Approved way of getting address of caller
+ */
+#define svc_getrpccaller(x) (&(x)->xp_rtaddr)
+
+/*
+ * Operations defined on an SVCXPRT handle
+ *
+ * SVCXPRT *xprt;
+ * struct rpc_msg *msg;
+ * xdrproc_t xargs;
+ * void * argsp;
+ */
+#define SVC_RECV(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+#define svc_recv(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+
+#define SVC_STAT(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+#define svc_stat(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+
+#define SVC_GETARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+#define svc_getargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+
+#define SVC_REPLY(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+#define svc_reply(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+
+#define SVC_FREEARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+#define svc_freeargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+
+#define SVC_DESTROY(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+#define svc_destroy(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+
+#define SVC_CONTROL(xprt, rq, in) \
+ (*(xprt)->xp_ops2->xp_control)((xprt), (rq), (in))
+
+#define SVC_EXT(xprt) \
+ ((SVCXPRT_EXT *) xprt->xp_p3)
+
+#define SVC_AUTH(xprt) \
+ (SVC_EXT(xprt)->xp_auth)
+
+/*
+ * Operations defined on an SVCAUTH handle
+ */
+#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((auth)->svc_ah_ops->svc_ah_wrap(auth, xdrs, xfunc, xwhere))
+#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((auth)->svc_ah_ops->svc_ah_unwrap(auth, xdrs, xfunc, xwhere))
+
+/*
+ * Service registration
+ *
+ * svc_reg(xprt, prog, vers, dispatch, nconf)
+ * const SVCXPRT *xprt;
+ * const rpcprog_t prog;
+ * const rpcvers_t vers;
+ * const void (*dispatch)();
+ * const struct netconfig *nconf;
+ */
+
+__BEGIN_DECLS
+extern bool_t svc_reg(SVCXPRT *, const rpcprog_t, const rpcvers_t,
+ void (*)(struct svc_req *, SVCXPRT *),
+ const struct netconfig *);
+__END_DECLS
+
+/*
+ * Service un-registration
+ *
+ * svc_unreg(prog, vers)
+ * const rpcprog_t prog;
+ * const rpcvers_t vers;
+ */
+
+__BEGIN_DECLS
+extern void svc_unreg(const rpcprog_t, const rpcvers_t);
+__END_DECLS
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ * SVCXPRT *xprt;
+ */
+__BEGIN_DECLS
+extern void xprt_register(SVCXPRT *);
+__END_DECLS
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ * SVCXPRT *xprt;
+ */
+__BEGIN_DECLS
+extern void xprt_unregister(SVCXPRT *);
+__END_DECLS
+
+
+/*
+ * When the service routine is called, it must first check to see if it
+ * knows about the procedure; if not, it should call svcerr_noproc
+ * and return. If so, it should deserialize its arguments via
+ * SVC_GETARGS (defined above). If the deserialization does not work,
+ * svcerr_decode should be called followed by a return. Successful
+ * decoding of the arguments should be followed the execution of the
+ * procedure's code and a call to svc_sendreply.
+ *
+ * Also, if the service refuses to execute the procedure due to too-
+ * weak authentication parameters, svcerr_weakauth should be called.
+ * Note: do not confuse access-control failure with weak authentication!
+ *
+ * NB: In pure implementations of rpc, the caller always waits for a reply
+ * msg. This message is sent when svc_sendreply is called.
+ * Therefore pure service implementations should always call
+ * svc_sendreply even if the function logically returns void; use
+ * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows
+ * for the abuse of pure rpc via batched calling or pipelining. In the
+ * case of a batched call, svc_sendreply should NOT be called since
+ * this would send a return message, which is what batching tries to avoid.
+ * It is the service/protocol writer's responsibility to know which calls are
+ * batched and which are not. Warning: responding to batch calls may
+ * deadlock the caller and server processes!
+ */
+
+__BEGIN_DECLS
+extern bool_t svc_sendreply(SVCXPRT *, xdrproc_t, void *);
+extern void svcerr_decode(SVCXPRT *);
+extern void svcerr_weakauth(SVCXPRT *);
+extern void svcerr_noproc(SVCXPRT *);
+extern void svcerr_progvers(SVCXPRT *, rpcvers_t, rpcvers_t);
+extern void svcerr_auth(SVCXPRT *, enum auth_stat);
+extern void svcerr_noprog(SVCXPRT *);
+extern void svcerr_systemerr(SVCXPRT *);
+extern int rpc_reg(rpcprog_t, rpcvers_t, rpcproc_t,
+ char *(*)(char *), xdrproc_t, xdrproc_t,
+ char *);
+__END_DECLS
+
+/*
+ * Lowest level dispatching -OR- who owns this process anyway.
+ * Somebody has to wait for incoming requests and then call the correct
+ * service routine. The routine svc_run does infinite waiting; i.e.,
+ * svc_run never returns.
+ * Since another (co-existant) package may wish to selectively wait for
+ * incoming calls or other events outside of the rpc architecture, the
+ * routine svc_getreq is provided. It must be passed readfds, the
+ * "in-place" results of a select system call (see select, section 2).
+ */
+
+/*
+ * Global keeper of rpc service descriptors in use
+ * dynamic; must be inspected before each call to select
+ */
+extern int svc_maxfd;
+#ifdef FD_SETSIZE
+extern fd_set svc_fdset;
+#define svc_fds svc_fdset.fds_bits[0] /* compatibility */
+#else
+extern int svc_fds;
+#endif /* def FD_SETSIZE */
+
+/*
+ * A set of null auth methods used by any authentication protocols
+ * that don't need to inspect or modify the message body.
+ */
+extern SVCAUTH _svc_auth_null;
+
+/*
+ * a small program implemented by the svc_rpc implementation itself;
+ * also see clnt.h for protocol numbers.
+ */
+__BEGIN_DECLS
+extern void rpctest_service(void);
+__END_DECLS
+
+__BEGIN_DECLS
+extern SVCXPRT *svc_xprt_alloc(void);
+extern void svc_xprt_free(SVCXPRT *);
+extern void svc_getreq(int);
+extern void svc_getreqset(fd_set *);
+extern void svc_getreq_common(int);
+struct pollfd;
+extern void svc_getreq_poll(struct pollfd *, int);
+
+extern void svc_run(void);
+extern void svc_exit(void);
+__END_DECLS
+
+/*
+ * Socket to use on svcxxx_create call to get default socket
+ */
+#define RPC_ANYSOCK -1
+#define RPC_ANYFD RPC_ANYSOCK
+
+/*
+ * These are the existing service side transport implementations
+ */
+
+__BEGIN_DECLS
+/*
+ * Transport independent svc_create routine.
+ */
+extern int svc_create(void (*)(struct svc_req *, SVCXPRT *),
+ const rpcprog_t, const rpcvers_t, const char *);
+/*
+ * void (*dispatch)(); -- dispatch routine
+ * const rpcprog_t prognum; -- program number
+ * const rpcvers_t versnum; -- version number
+ * const char *nettype; -- network type
+ */
+
+
+/*
+ * Generic server creation routine. It takes a netconfig structure
+ * instead of a nettype.
+ */
+
+extern SVCXPRT *svc_tp_create(void (*)(struct svc_req *, SVCXPRT *),
+ const rpcprog_t, const rpcvers_t,
+ const struct netconfig *);
+ /*
+ * void (*dispatch)(); -- dispatch routine
+ * const rpcprog_t prognum; -- program number
+ * const rpcvers_t versnum; -- version number
+ * const struct netconfig *nconf; -- netconfig structure
+ */
+
+
+/*
+ * Generic TLI create routine
+ */
+extern SVCXPRT *svc_tli_create(const int, const struct netconfig *,
+ const struct t_bind *, const u_int,
+ const u_int);
+/*
+ * const int fd; -- connection end point
+ * const struct netconfig *nconf; -- netconfig structure for network
+ * const struct t_bind *bindaddr; -- local bind address
+ * const u_int sendsz; -- max sendsize
+ * const u_int recvsz; -- max recvsize
+ */
+
+/*
+ * Connectionless and connectionful create routines
+ */
+
+extern SVCXPRT *svc_vc_create(const int, const u_int, const u_int);
+/*
+ * const int fd; -- open connection end point
+ * const u_int sendsize; -- max send size
+ * const u_int recvsize; -- max recv size
+ */
+
+/*
+ * Added for compatibility to old rpc 4.0. Obsoleted by svc_vc_create().
+ */
+extern SVCXPRT *svcunix_create(int, u_int, u_int, char *);
+
+extern SVCXPRT *svc_dg_create(const int, const u_int, const u_int);
+ /*
+ * const int fd; -- open connection
+ * const u_int sendsize; -- max send size
+ * const u_int recvsize; -- max recv size
+ */
+
+
+/*
+ * the routine takes any *open* connection
+ * descriptor as its first input and is used for open connections.
+ */
+extern SVCXPRT *svc_fd_create(const int, const u_int, const u_int);
+/*
+ * const int fd; -- open connection end point
+ * const u_int sendsize; -- max send size
+ * const u_int recvsize; -- max recv size
+ */
+
+/*
+ * Added for compatibility to old rpc 4.0. Obsoleted by svc_fd_create().
+ */
+extern SVCXPRT *svcunixfd_create(int, u_int, u_int);
+
+/*
+ * Memory based rpc (for speed check and testing)
+ */
+extern SVCXPRT *svc_raw_create(void);
+
+/*
+ * svc_dg_enable_cache() enables the cache on dg transports.
+ */
+int svc_dg_enablecache(SVCXPRT *, const u_int);
+
+int __rpc_get_local_uid(SVCXPRT *_transp, uid_t *_uid);
+
+__END_DECLS
+
+
+/* for backward compatibility */
+#include <rpc/svc_soc.h>
+
+#endif /* !_RPC_SVC_H */
diff --git a/freebsd/include/rpc/svc_auth.h b/freebsd/include/rpc/svc_auth.h
new file mode 100644
index 00000000..41fc82b0
--- /dev/null
+++ b/freebsd/include/rpc/svc_auth.h
@@ -0,0 +1,57 @@
+/* $NetBSD: svc_auth.h,v 1.8 2000/06/02 22:57:57 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)svc_auth.h 1.6 86/07/16 SMI
+ * @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_SVC_AUTH_H
+#define _RPC_SVC_AUTH_H
+
+/*
+ * Server side authenticator
+ */
+__BEGIN_DECLS
+extern struct svc_auth_ops svc_auth_null_ops;
+
+extern enum auth_stat _authenticate(struct svc_req *, struct rpc_msg *);
+extern int svc_auth_reg(int, enum auth_stat (*)(struct svc_req *,
+ struct rpc_msg *));
+
+__END_DECLS
+
+#endif /* !_RPC_SVC_AUTH_H */
diff --git a/freebsd/include/rpc/svc_soc.h b/freebsd/include/rpc/svc_soc.h
new file mode 100644
index 00000000..6c528dbc
--- /dev/null
+++ b/freebsd/include/rpc/svc_soc.h
@@ -0,0 +1,116 @@
+/* $NetBSD: svc_soc.h,v 1.1 2000/06/02 22:57:57 fvdl Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ */
+
+#ifndef _RPC_SVC_SOC_H
+#define _RPC_SVC_SOC_H
+#include <sys/cdefs.h>
+
+/* #pragma ident "@(#)svc_soc.h 1.11 94/04/25 SMI" */
+/* svc_soc.h 1.8 89/05/01 SMI */
+
+/*
+ * All the following declarations are only for backward compatibility
+ * with TS-RPC
+ */
+
+/*
+ * Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ * SVCXPRT *xprt;
+ * u_long prog;
+ * u_long vers;
+ * void (*dispatch)();
+ * int protocol; like TCP or UDP, zero means do not register
+ */
+__BEGIN_DECLS
+extern bool_t svc_register(SVCXPRT *, u_long, u_long,
+ void (*)(struct svc_req *, SVCXPRT *), int);
+__END_DECLS
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ * u_long prog;
+ * u_long vers;
+ */
+__BEGIN_DECLS
+extern void svc_unregister(u_long, u_long);
+__END_DECLS
+
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcraw_create(void);
+__END_DECLS
+
+
+/*
+ * Udp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcudp_create(int);
+extern SVCXPRT *svcudp_bufcreate(int, u_int, u_int);
+extern int svcudp_enablecache(SVCXPRT *, u_long);
+__END_DECLS
+
+
+/*
+ * Tcp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svctcp_create(int, u_int, u_int);
+__END_DECLS
+
+/*
+ * Fd based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcfd_create(int, u_int, u_int);
+__END_DECLS
+
+#endif /* !_RPC_SVC_SOC_H */
diff --git a/freebsd/include/rpc/xdr.h b/freebsd/include/rpc/xdr.h
new file mode 100644
index 00000000..a02291bc
--- /dev/null
+++ b/freebsd/include/rpc/xdr.h
@@ -0,0 +1,368 @@
+/* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)xdr.h 1.19 87/04/22 SMI
+ * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_XDR_H
+#define _RPC_XDR_H
+#include <sys/cdefs.h>
+
+/*
+ * XDR provides a conventional way for converting between C data
+ * types and an external bit-string representation. Library supplied
+ * routines provide for the conversion on built-in C data types. These
+ * routines and utility routines defined here are used to help implement
+ * a type encode/decode routine for each user-defined type.
+ *
+ * Each data type provides a single procedure which takes two arguments:
+ *
+ * bool_t
+ * xdrproc(xdrs, argresp)
+ * XDR *xdrs;
+ * <type> *argresp;
+ *
+ * xdrs is an instance of a XDR handle, to which or from which the data
+ * type is to be converted. argresp is a pointer to the structure to be
+ * converted. The XDR handle contains an operation field which indicates
+ * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
+ *
+ * XDR_DECODE may allocate space if the pointer argresp is null. This
+ * data can be freed with the XDR_FREE operation.
+ *
+ * We write only one procedure per data type to make it easy
+ * to keep the encode and decode procedures for a data type consistent.
+ * In many cases the same code performs all operations on a user defined type,
+ * because all the hard work is done in the component type routines.
+ * decode as a series of calls on the nested data types.
+ */
+
+/*
+ * Xdr operations. XDR_ENCODE causes the type to be encoded into the
+ * stream. XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+ XDR_ENCODE=0,
+ XDR_DECODE=1,
+ XDR_FREE=2
+};
+
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT (4)
+#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
+ * BYTES_PER_XDR_UNIT)
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the particular implementation (e.g. see xdr_mem.c),
+ * and two private fields for the use of the particular implementation.
+ */
+typedef struct __rpc_xdr {
+ enum xdr_op x_op; /* operation; fast additional param */
+ const struct xdr_ops {
+ /* get a long from underlying stream */
+ bool_t (*x_getlong)(struct __rpc_xdr *, long *);
+ /* put a long to " */
+ bool_t (*x_putlong)(struct __rpc_xdr *, const long *);
+ /* get some bytes from " */
+ bool_t (*x_getbytes)(struct __rpc_xdr *, char *, u_int);
+ /* put some bytes to " */
+ bool_t (*x_putbytes)(struct __rpc_xdr *, const char *, u_int);
+ /* returns bytes off from beginning */
+ u_int (*x_getpostn)(struct __rpc_xdr *);
+ /* lets you reposition the stream */
+ bool_t (*x_setpostn)(struct __rpc_xdr *, u_int);
+ /* buf quick ptr to buffered data */
+ int32_t *(*x_inline)(struct __rpc_xdr *, u_int);
+ /* free privates of this xdr_stream */
+ void (*x_destroy)(struct __rpc_xdr *);
+ bool_t (*x_control)(struct __rpc_xdr *, int, void *);
+ } *x_ops;
+ char * x_public; /* users' data */
+ void * x_private; /* pointer to private data */
+ char * x_base; /* private used for position info */
+ u_int x_handy; /* extra private word */
+} XDR;
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or decoded.
+ *
+ * The second argument to the xdrproc_t is a pointer to an opaque pointer.
+ * The opaque pointer generally points to a structure of the data type
+ * to be decoded. If this pointer is 0, then the type routines should
+ * allocate dynamic storage of the appropriate size and return it.
+ */
+#ifdef _KERNEL
+typedef bool_t (*xdrproc_t)(XDR *, void *, u_int);
+#else
+/*
+ * XXX can't actually prototype it, because some take three args!!!
+ */
+typedef bool_t (*xdrproc_t)(XDR *, ...);
+#endif
+
+/*
+ * Operations defined on a XDR handle
+ *
+ * XDR *xdrs;
+ * long *longp;
+ * char * addr;
+ * u_int len;
+ * u_int pos;
+ */
+#define XDR_GETLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+#define xdr_getlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+
+#define XDR_PUTLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+#define xdr_putlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+
+static __inline int
+xdr_getint32(XDR *xdrs, int32_t *ip)
+{
+ long l;
+
+ if (!xdr_getlong(xdrs, &l))
+ return (FALSE);
+ *ip = (int32_t)l;
+ return (TRUE);
+}
+
+static __inline int
+xdr_putint32(XDR *xdrs, int32_t *ip)
+{
+ long l;
+
+ l = (long)*ip;
+ return xdr_putlong(xdrs, &l);
+}
+
+#define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p)
+#define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p)
+
+#define XDR_GETBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+#define xdr_getbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+
+#define XDR_PUTBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+#define xdr_putbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+
+#define XDR_GETPOS(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+#define xdr_getpos(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+
+#define XDR_SETPOS(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+#define xdr_setpos(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+
+#define XDR_INLINE(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+#define xdr_inline(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+
+#define XDR_DESTROY(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+#define xdr_destroy(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+
+#define XDR_CONTROL(xdrs, req, op) \
+ if ((xdrs)->x_ops->x_control) \
+ (*(xdrs)->x_ops->x_control)(xdrs, req, op)
+#define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op)
+
+/*
+ * Solaris strips the '_t' from these types -- not sure why.
+ * But, let's be compatible.
+ */
+#define xdr_rpcvers(xdrs, versp) xdr_u_int32(xdrs, versp)
+#define xdr_rpcprog(xdrs, progp) xdr_u_int32(xdrs, progp)
+#define xdr_rpcproc(xdrs, procp) xdr_u_int32(xdrs, procp)
+#define xdr_rpcprot(xdrs, protp) xdr_u_int32(xdrs, protp)
+#define xdr_rpcport(xdrs, portp) xdr_u_int32(xdrs, portp)
+
+/*
+ * Support struct for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * an entry with a null procedure pointer. The xdr_union routine gets
+ * the discriminant value and then searches the array of structures
+ * for a matching value. If a match is found the associated xdr routine
+ * is called to handle that part of the union. If there is
+ * no match, then a default routine may be called.
+ * If there is no match and no default routine it is an error.
+ */
+#define NULL_xdrproc_t ((xdrproc_t)0)
+struct xdr_discrim {
+ int value;
+ xdrproc_t proc;
+};
+
+/*
+ * In-line routines for fast encode/decode of primitive data types.
+ * Caveat emptor: these use single memory cycles to get the
+ * data from the underlying buffer, and will fail to operate
+ * properly if the data is not aligned. The standard way to use these
+ * is to say:
+ * if ((buf = XDR_INLINE(xdrs, count)) == NULL)
+ * return (FALSE);
+ * <<< macro calls >>>
+ * where ``count'' is the number of bytes of data occupied
+ * by the primitive data types.
+ *
+ * N.B. and frozen for all time: each data type here uses 4 bytes
+ * of external representation.
+ */
+#define IXDR_GET_INT32(buf) ((int32_t)__ntohl((u_int32_t)*(buf)++))
+#define IXDR_PUT_INT32(buf, v) (*(buf)++ =(int32_t)__htonl((u_int32_t)v))
+#define IXDR_GET_U_INT32(buf) ((u_int32_t)IXDR_GET_INT32(buf))
+#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v)))
+
+#define IXDR_GET_LONG(buf) ((long)__ntohl((u_int32_t)*(buf)++))
+#define IXDR_PUT_LONG(buf, v) (*(buf)++ =(int32_t)__htonl((u_int32_t)v))
+
+#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf))
+#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf))
+
+#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))
+#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+__BEGIN_DECLS
+extern bool_t xdr_void(void);
+extern bool_t xdr_int(XDR *, int *);
+extern bool_t xdr_u_int(XDR *, u_int *);
+extern bool_t xdr_long(XDR *, long *);
+extern bool_t xdr_u_long(XDR *, u_long *);
+extern bool_t xdr_short(XDR *, short *);
+extern bool_t xdr_u_short(XDR *, u_short *);
+extern bool_t xdr_int16_t(XDR *, int16_t *);
+extern bool_t xdr_u_int16_t(XDR *, u_int16_t *);
+extern bool_t xdr_uint16_t(XDR *, u_int16_t *);
+extern bool_t xdr_int32_t(XDR *, int32_t *);
+extern bool_t xdr_u_int32_t(XDR *, u_int32_t *);
+extern bool_t xdr_uint32_t(XDR *, u_int32_t *);
+extern bool_t xdr_int64_t(XDR *, int64_t *);
+extern bool_t xdr_u_int64_t(XDR *, u_int64_t *);
+extern bool_t xdr_uint64_t(XDR *, u_int64_t *);
+extern bool_t xdr_bool(XDR *, bool_t *);
+extern bool_t xdr_enum(XDR *, enum_t *);
+extern bool_t xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t);
+extern bool_t xdr_bytes(XDR *, char **, u_int *, u_int);
+extern bool_t xdr_opaque(XDR *, char *, u_int);
+extern bool_t xdr_string(XDR *, char **, u_int);
+extern bool_t xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t);
+extern bool_t xdr_char(XDR *, char *);
+extern bool_t xdr_u_char(XDR *, u_char *);
+extern bool_t xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t);
+extern bool_t xdr_float(XDR *, float *);
+extern bool_t xdr_double(XDR *, double *);
+extern bool_t xdr_quadruple(XDR *, long double *);
+extern bool_t xdr_reference(XDR *, char **, u_int, xdrproc_t);
+extern bool_t xdr_pointer(XDR *, char **, u_int, xdrproc_t);
+extern bool_t xdr_wrapstring(XDR *, char **);
+extern void xdr_free(xdrproc_t, void *);
+extern bool_t xdr_hyper(XDR *, quad_t *);
+extern bool_t xdr_u_hyper(XDR *, u_quad_t *);
+extern bool_t xdr_longlong_t(XDR *, quad_t *);
+extern bool_t xdr_u_longlong_t(XDR *, u_quad_t *);
+__END_DECLS
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 1024
+struct netobj {
+ u_int n_len;
+ char *n_bytes;
+};
+typedef struct netobj netobj;
+extern bool_t xdr_netobj(XDR *, struct netobj *);
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+__BEGIN_DECLS
+/* XDR using memory buffers */
+extern void xdrmem_create(XDR *, char *, u_int, enum xdr_op);
+
+/* XDR using stdio library */
+#ifdef _STDIO_H_
+extern void xdrstdio_create(XDR *, FILE *, enum xdr_op);
+#endif
+
+/* XDR pseudo records for tcp */
+extern void xdrrec_create(XDR *, u_int, u_int, void *,
+ int (*)(void *, void *, int),
+ int (*)(void *, void *, int));
+
+/* make end of xdr record */
+extern bool_t xdrrec_endofrecord(XDR *, int);
+
+/* move to beginning of next record */
+extern bool_t xdrrec_skiprecord(XDR *);
+
+/* true if no more input */
+extern bool_t xdrrec_eof(XDR *);
+extern u_int xdrrec_readbytes(XDR *, caddr_t, u_int);
+__END_DECLS
+
+#endif /* !_RPC_XDR_H */
diff --git a/freebsd/include/sysexits.h b/freebsd/include/sysexits.h
new file mode 100644
index 00000000..464cb11b
--- /dev/null
+++ b/freebsd/include/sysexits.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 1987, 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.
+ *
+ * @(#)sysexits.h 8.1 (Berkeley) 6/2/93
+ */
+
+#ifndef _SYSEXITS_H_
+#define _SYSEXITS_H_
+
+/*
+ * SYSEXITS.H -- Exit status codes for system programs.
+ *
+ * This include file attempts to categorize possible error
+ * exit statuses for system programs, notably delivermail
+ * and the Berkeley network.
+ *
+ * Error numbers begin at EX__BASE to reduce the possibility of
+ * clashing with other exit statuses that random programs may
+ * already return. The meaning of the codes is approximately
+ * as follows:
+ *
+ * EX_USAGE -- The command was used incorrectly, e.g., with
+ * the wrong number of arguments, a bad flag, a bad
+ * syntax in a parameter, or whatever.
+ * EX_DATAERR -- The input data was incorrect in some way.
+ * This should only be used for user's data & not
+ * system files.
+ * EX_NOINPUT -- An input file (not a system file) did not
+ * exist or was not readable. This could also include
+ * errors like "No message" to a mailer (if it cared
+ * to catch it).
+ * EX_NOUSER -- The user specified did not exist. This might
+ * be used for mail addresses or remote logins.
+ * EX_NOHOST -- The host specified did not exist. This is used
+ * in mail addresses or network requests.
+ * EX_UNAVAILABLE -- A service is unavailable. This can occur
+ * if a support program or file does not exist. This
+ * can also be used as a catchall message when something
+ * you wanted to do doesn't work, but you don't know
+ * why.
+ * EX_SOFTWARE -- An internal software error has been detected.
+ * This should be limited to non-operating system related
+ * errors as possible.
+ * EX_OSERR -- An operating system error has been detected.
+ * This is intended to be used for such things as "cannot
+ * fork", "cannot create pipe", or the like. It includes
+ * things like getuid returning a user that does not
+ * exist in the passwd file.
+ * EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
+ * etc.) does not exist, cannot be opened, or has some
+ * sort of error (e.g., syntax error).
+ * EX_CANTCREAT -- A (user specified) output file cannot be
+ * created.
+ * EX_IOERR -- An error occurred while doing I/O on some file.
+ * EX_TEMPFAIL -- temporary failure, indicating something that
+ * is not really an error. In sendmail, this means
+ * that a mailer (e.g.) could not create a connection,
+ * and the request should be reattempted later.
+ * EX_PROTOCOL -- the remote system returned something that
+ * was "not possible" during a protocol exchange.
+ * EX_NOPERM -- You did not have sufficient permission to
+ * perform the operation. This is not intended for
+ * file system problems, which should use NOINPUT or
+ * CANTCREAT, but rather for higher level permissions.
+ */
+
+#define EX_OK 0 /* successful termination */
+
+#define EX__BASE 64 /* base value for error messages */
+
+#define EX_USAGE 64 /* command line usage error */
+#define EX_DATAERR 65 /* data format error */
+#define EX_NOINPUT 66 /* cannot open input */
+#define EX_NOUSER 67 /* addressee unknown */
+#define EX_NOHOST 68 /* host name unknown */
+#define EX_UNAVAILABLE 69 /* service unavailable */
+#define EX_SOFTWARE 70 /* internal software error */
+#define EX_OSERR 71 /* system error (e.g., can't fork) */
+#define EX_OSFILE 72 /* critical OS file missing */
+#define EX_CANTCREAT 73 /* can't create (user) output file */
+#define EX_IOERR 74 /* input/output error */
+#define EX_TEMPFAIL 75 /* temp failure; user is invited to retry */
+#define EX_PROTOCOL 76 /* remote error in protocol */
+#define EX_NOPERM 77 /* permission denied */
+#define EX_CONFIG 78 /* configuration error */
+
+#define EX__MAX 78 /* maximum listed value */
+
+#endif /* !_SYSEXITS_H_ */
diff --git a/freebsd/lib/libc/db/btree/bt_close.c b/freebsd/lib/libc/db/btree/bt_close.c
new file mode 100644
index 00000000..b15d67ca
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_close.c
@@ -0,0 +1,180 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "btree.h"
+
+static int bt_meta(BTREE *);
+
+/*
+ * BT_CLOSE -- Close a btree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_close(DB *dbp)
+{
+ BTREE *t;
+ int fd;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Sync the tree. */
+ if (__bt_sync(dbp, 0) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Close the memory pool. */
+ if (mpool_close(t->bt_mp) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Free random memory. */
+ if (t->bt_cursor.key.data != NULL) {
+ free(t->bt_cursor.key.data);
+ t->bt_cursor.key.size = 0;
+ t->bt_cursor.key.data = NULL;
+ }
+ if (t->bt_rkey.data) {
+ free(t->bt_rkey.data);
+ t->bt_rkey.size = 0;
+ t->bt_rkey.data = NULL;
+ }
+ if (t->bt_rdata.data) {
+ free(t->bt_rdata.data);
+ t->bt_rdata.size = 0;
+ t->bt_rdata.data = NULL;
+ }
+
+ fd = t->bt_fd;
+ free(t);
+ free(dbp);
+ return (_close(fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * BT_SYNC -- sync the btree to disk.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_sync(const DB *dbp, u_int flags)
+{
+ BTREE *t;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Sync doesn't currently take any flags. */
+ if (flags != 0) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
+ return (RET_SUCCESS);
+
+ if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
+ return (RET_ERROR);
+
+ if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
+ F_CLR(t, B_MODIFIED);
+
+ return (status);
+}
+
+/*
+ * BT_META -- write the tree meta data to disk.
+ *
+ * Parameters:
+ * t: tree
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_meta(BTREE *t)
+{
+ BTMETA m;
+ void *p;
+
+ if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Fill in metadata. */
+ m.magic = BTREEMAGIC;
+ m.version = BTREEVERSION;
+ m.psize = t->bt_psize;
+ m.free = t->bt_free;
+ m.nrecs = t->bt_nrecs;
+ m.flags = F_ISSET(t, SAVEMETA);
+
+ memmove(p, &m, sizeof(BTMETA));
+ mpool_put(t->bt_mp, p, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_conv.c b/freebsd/lib/libc/db/btree/bt_conv.c
new file mode 100644
index 00000000..d84da442
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_conv.c
@@ -0,0 +1,214 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static void mswap(PAGE *);
+
+/*
+ * __BT_BPGIN, __BT_BPGOUT --
+ * Convert host-specific number layout to/from the host-independent
+ * format stored on disk.
+ *
+ * Parameters:
+ * t: tree
+ * pg: page number
+ * h: page to convert
+ */
+void
+__bt_pgin(void *t, pgno_t pg, void *pp)
+{
+ PAGE *h;
+ indx_t i, top;
+ u_char flags;
+ char *p;
+
+ if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+ return;
+ if (pg == P_META) {
+ mswap(pp);
+ return;
+ }
+
+ h = pp;
+ M_32_SWAP(h->pgno);
+ M_32_SWAP(h->prevpg);
+ M_32_SWAP(h->nextpg);
+ M_32_SWAP(h->flags);
+ M_16_SWAP(h->lower);
+ M_16_SWAP(h->upper);
+
+ top = NEXTINDEX(h);
+ if ((h->flags & P_TYPE) == P_BINTERNAL)
+ for (i = 0; i < top; i++) {
+ M_16_SWAP(h->linp[i]);
+ p = (char *)GETBINTERNAL(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ if (*(u_char *)p & P_BIGKEY) {
+ p += sizeof(u_char);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ }
+ else if ((h->flags & P_TYPE) == P_BLEAF)
+ for (i = 0; i < top; i++) {
+ M_16_SWAP(h->linp[i]);
+ p = (char *)GETBLEAF(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ flags = *(u_char *)p;
+ if (flags & (P_BIGKEY | P_BIGDATA)) {
+ p += sizeof(u_char);
+ if (flags & P_BIGKEY) {
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ if (flags & P_BIGDATA) {
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ }
+ }
+}
+
+void
+__bt_pgout(void *t, pgno_t pg, void *pp)
+{
+ PAGE *h;
+ indx_t i, top;
+ u_char flags;
+ char *p;
+
+ if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+ return;
+ if (pg == P_META) {
+ mswap(pp);
+ return;
+ }
+
+ h = pp;
+ top = NEXTINDEX(h);
+ if ((h->flags & P_TYPE) == P_BINTERNAL)
+ for (i = 0; i < top; i++) {
+ p = (char *)GETBINTERNAL(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ if (*(u_char *)p & P_BIGKEY) {
+ p += sizeof(u_char);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ M_16_SWAP(h->linp[i]);
+ }
+ else if ((h->flags & P_TYPE) == P_BLEAF)
+ for (i = 0; i < top; i++) {
+ p = (char *)GETBLEAF(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ flags = *(u_char *)p;
+ if (flags & (P_BIGKEY | P_BIGDATA)) {
+ p += sizeof(u_char);
+ if (flags & P_BIGKEY) {
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ if (flags & P_BIGDATA) {
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ }
+ M_16_SWAP(h->linp[i]);
+ }
+
+ M_32_SWAP(h->pgno);
+ M_32_SWAP(h->prevpg);
+ M_32_SWAP(h->nextpg);
+ M_32_SWAP(h->flags);
+ M_16_SWAP(h->lower);
+ M_16_SWAP(h->upper);
+}
+
+/*
+ * MSWAP -- Actually swap the bytes on the meta page.
+ *
+ * Parameters:
+ * p: page to convert
+ */
+static void
+mswap(PAGE *pg)
+{
+ char *p;
+
+ p = (char *)pg;
+ P_32_SWAP(p); /* magic */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* version */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* psize */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* free */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* nrecs */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* flags */
+ p += sizeof(u_int32_t);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_debug.c b/freebsd/lib/libc/db/btree/bt_debug.c
new file mode 100644
index 00000000..ce7849a9
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_debug.c
@@ -0,0 +1,318 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+#ifdef DEBUG
+/*
+ * BT_DUMP -- Dump the tree
+ *
+ * Parameters:
+ * dbp: pointer to the DB
+ */
+void
+__bt_dump(DB *dbp)
+{
+ BTREE *t;
+ PAGE *h;
+ pgno_t i;
+ char *sep;
+
+ t = dbp->internal;
+ (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);
+#undef X
+#define X(flag, name) \
+ if (F_ISSET(t, flag)) { \
+ (void)fprintf(stderr, "%s%s", sep, name); \
+ sep = ", "; \
+ }
+ if (t->flags != 0) {
+ sep = " flags (";
+ X(R_FIXLEN, "FIXLEN");
+ X(B_INMEM, "INMEM");
+ X(B_NODUPS, "NODUPS");
+ X(B_RDONLY, "RDONLY");
+ X(R_RECNO, "RECNO");
+ X(B_METADIRTY,"METADIRTY");
+ (void)fprintf(stderr, ")\n");
+ }
+#undef X
+
+ for (i = P_ROOT;
+ (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
+ __bt_dpage(h);
+}
+
+/*
+ * BT_DMPAGE -- Dump the meta page
+ *
+ * Parameters:
+ * h: pointer to the PAGE
+ */
+void
+__bt_dmpage(PAGE *h)
+{
+ BTMETA *m;
+ char *sep;
+
+ m = (BTMETA *)h;
+ (void)fprintf(stderr, "magic %x\n", m->magic);
+ (void)fprintf(stderr, "version %u\n", m->version);
+ (void)fprintf(stderr, "psize %u\n", m->psize);
+ (void)fprintf(stderr, "free %u\n", m->free);
+ (void)fprintf(stderr, "nrecs %u\n", m->nrecs);
+ (void)fprintf(stderr, "flags %u", m->flags);
+#undef X
+#define X(flag, name) \
+ if (m->flags & flag) { \
+ (void)fprintf(stderr, "%s%s", sep, name); \
+ sep = ", "; \
+ }
+ if (m->flags) {
+ sep = " (";
+ X(B_NODUPS, "NODUPS");
+ X(R_RECNO, "RECNO");
+ (void)fprintf(stderr, ")");
+ }
+}
+
+/*
+ * BT_DNPAGE -- Dump the page
+ *
+ * Parameters:
+ * n: page number to dump.
+ */
+void
+__bt_dnpage(DB *dbp, pgno_t pgno)
+{
+ BTREE *t;
+ PAGE *h;
+
+ t = dbp->internal;
+ if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL)
+ __bt_dpage(h);
+}
+
+/*
+ * BT_DPAGE -- Dump the page
+ *
+ * Parameters:
+ * h: pointer to the PAGE
+ */
+void
+__bt_dpage(PAGE *h)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ RINTERNAL *ri;
+ RLEAF *rl;
+ indx_t cur, top;
+ char *sep;
+
+ (void)fprintf(stderr, " page %u: (", h->pgno);
+#undef X
+#define X(flag, name) \
+ if (h->flags & flag) { \
+ (void)fprintf(stderr, "%s%s", sep, name); \
+ sep = ", "; \
+ }
+ sep = "";
+ X(P_BINTERNAL, "BINTERNAL") /* types */
+ X(P_BLEAF, "BLEAF")
+ X(P_RINTERNAL, "RINTERNAL") /* types */
+ X(P_RLEAF, "RLEAF")
+ X(P_OVERFLOW, "OVERFLOW")
+ X(P_PRESERVE, "PRESERVE");
+ (void)fprintf(stderr, ")\n");
+#undef X
+
+ (void)fprintf(stderr, "\tprev %2u next %2u", h->prevpg, h->nextpg);
+ if (h->flags & P_OVERFLOW)
+ return;
+
+ top = NEXTINDEX(h);
+ (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n",
+ h->lower, h->upper, top);
+ for (cur = 0; cur < top; cur++) {
+ (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]);
+ switch (h->flags & P_TYPE) {
+ case P_BINTERNAL:
+ bi = GETBINTERNAL(h, cur);
+ (void)fprintf(stderr,
+ "size %03d pgno %03d", bi->ksize, bi->pgno);
+ if (bi->flags & P_BIGKEY)
+ (void)fprintf(stderr, " (indirect)");
+ else if (bi->ksize)
+ (void)fprintf(stderr,
+ " {%.*s}", (int)bi->ksize, bi->bytes);
+ break;
+ case P_RINTERNAL:
+ ri = GETRINTERNAL(h, cur);
+ (void)fprintf(stderr, "entries %03d pgno %03d",
+ ri->nrecs, ri->pgno);
+ break;
+ case P_BLEAF:
+ bl = GETBLEAF(h, cur);
+ if (bl->flags & P_BIGKEY)
+ (void)fprintf(stderr,
+ "big key page %u size %u/",
+ *(pgno_t *)bl->bytes,
+ *(u_int32_t *)(bl->bytes + sizeof(pgno_t)));
+ else if (bl->ksize)
+ (void)fprintf(stderr, "%.*s/",
+ bl->ksize, bl->bytes);
+ if (bl->flags & P_BIGDATA)
+ (void)fprintf(stderr,
+ "big data page %u size %u",
+ *(pgno_t *)(bl->bytes + bl->ksize),
+ *(u_int32_t *)(bl->bytes + bl->ksize +
+ sizeof(pgno_t)));
+ else if (bl->dsize)
+ (void)fprintf(stderr, "%.*s",
+ (int)bl->dsize, bl->bytes + bl->ksize);
+ break;
+ case P_RLEAF:
+ rl = GETRLEAF(h, cur);
+ if (rl->flags & P_BIGDATA)
+ (void)fprintf(stderr,
+ "big data page %u size %u",
+ *(pgno_t *)rl->bytes,
+ *(u_int32_t *)(rl->bytes + sizeof(pgno_t)));
+ else if (rl->dsize)
+ (void)fprintf(stderr,
+ "%.*s", (int)rl->dsize, rl->bytes);
+ break;
+ }
+ (void)fprintf(stderr, "\n");
+ }
+}
+#endif
+
+#ifdef STATISTICS
+/*
+ * BT_STAT -- Gather/print the tree statistics
+ *
+ * Parameters:
+ * dbp: pointer to the DB
+ */
+void
+__bt_stat(DB *dbp)
+{
+ extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit;
+ extern u_long bt_sortsplit, bt_split;
+ BTREE *t;
+ PAGE *h;
+ pgno_t i, pcont, pinternal, pleaf;
+ u_long ifree, lfree, nkeys;
+ int levels;
+
+ t = dbp->internal;
+ pcont = pinternal = pleaf = 0;
+ nkeys = ifree = lfree = 0;
+ 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:
+ ++pinternal;
+ ifree += h->upper - h->lower;
+ break;
+ case P_BLEAF:
+ case P_RLEAF:
+ ++pleaf;
+ lfree += h->upper - h->lower;
+ nkeys += NEXTINDEX(h);
+ break;
+ case P_OVERFLOW:
+ ++pcont;
+ break;
+ }
+
+ /* Count the levels of the tree. */
+ for (i = P_ROOT, levels = 0 ;; ++levels) {
+ h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN);
+ if (h->flags & (P_BLEAF|P_RLEAF)) {
+ if (levels == 0)
+ levels = 1;
+ break;
+ }
+ i = F_ISSET(t, R_RECNO) ?
+ GETRINTERNAL(h, 0)->pgno :
+ GETBINTERNAL(h, 0)->pgno;
+ }
+
+ (void)fprintf(stderr, "%d level%s with %lu keys",
+ levels, levels == 1 ? "" : "s", nkeys);
+ if (F_ISSET(t, R_RECNO))
+ (void)fprintf(stderr, " (%u header count)", t->bt_nrecs);
+ (void)fprintf(stderr,
+ "\n%u pages (leaf %u, internal %u, overflow %u)\n",
+ pinternal + pleaf + pcont, pleaf, pinternal, pcont);
+ (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 (%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 (%lu bytes used, %lu bytes free\n",
+ ((double)(pinternal - ifree) / pinternal) * 100,
+ pinternal - ifree, ifree);
+ if (bt_pfxsaved)
+ (void)fprintf(stderr, "prefix checking removed %lu bytes.\n",
+ bt_pfxsaved);
+}
+#endif
diff --git a/freebsd/lib/libc/db/btree/bt_delete.c b/freebsd/lib/libc/db/btree/bt_delete.c
new file mode 100644
index 00000000..ac295016
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_delete.c
@@ -0,0 +1,637 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_bdelete(BTREE *, const DBT *);
+static int __bt_curdel(BTREE *, const DBT *, PAGE *, u_int);
+static int __bt_pdelete(BTREE *, PAGE *);
+static int __bt_relink(BTREE *, PAGE *);
+static int __bt_stkacq(BTREE *, PAGE **, CURSOR *);
+
+/*
+ * __bt_delete
+ * Delete the item(s) referenced by a key.
+ *
+ * Return RET_SPECIAL if the key is not found.
+ */
+int
+__bt_delete(const DB *dbp, const DBT *key, u_int flags)
+{
+ BTREE *t;
+ CURSOR *c;
+ PAGE *h;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Check for change to a read-only tree. */
+ if (F_ISSET(t, B_RDONLY)) {
+ errno = EPERM;
+ return (RET_ERROR);
+ }
+
+ switch (flags) {
+ case 0:
+ status = __bt_bdelete(t, key);
+ break;
+ case R_CURSOR:
+ /*
+ * If flags is R_CURSOR, delete the cursor. Must already
+ * have started a scan and not have already deleted it.
+ */
+ c = &t->bt_cursor;
+ if (F_ISSET(c, CURS_INIT)) {
+ if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+ return (RET_ERROR);
+
+ /*
+ * If the page is about to be emptied, we'll need to
+ * delete it, which means we have to acquire a stack.
+ */
+ if (NEXTINDEX(h) == 1)
+ if (__bt_stkacq(t, &h, &t->bt_cursor))
+ return (RET_ERROR);
+
+ status = __bt_dleaf(t, NULL, h, c->pg.index);
+
+ if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
+ if (__bt_pdelete(t, h))
+ return (RET_ERROR);
+ } else
+ mpool_put(t->bt_mp,
+ h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+ if (status == RET_SUCCESS)
+ F_SET(t, B_MODIFIED);
+ return (status);
+}
+
+/*
+ * __bt_stkacq --
+ * Acquire a stack so we can delete a cursor entry.
+ *
+ * Parameters:
+ * t: tree
+ * hp: pointer to current, pinned PAGE pointer
+ * c: pointer to the cursor
+ *
+ * Returns:
+ * 0 on success, 1 on failure
+ */
+static int
+__bt_stkacq(BTREE *t, PAGE **hp, CURSOR *c)
+{
+ BINTERNAL *bi;
+ EPG *e;
+ EPGNO *parent;
+ PAGE *h;
+ indx_t idx;
+ pgno_t pgno;
+ recno_t nextpg, prevpg;
+ int exact, level;
+
+ /*
+ * Find the first occurrence of the key in the tree. Toss the
+ * currently locked page so we don't hit an already-locked page.
+ */
+ h = *hp;
+ mpool_put(t->bt_mp, h, 0);
+ if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+ return (1);
+ h = e->page;
+
+ /* See if we got it in one shot. */
+ if (h->pgno == c->pg.pgno)
+ goto ret;
+
+ /*
+ * Move right, looking for the page. At each move we have to move
+ * up the stack until we don't have to move to the next page. If
+ * we have to change pages at an internal level, we have to fix the
+ * stack back up.
+ */
+ while (h->pgno != c->pg.pgno) {
+ if ((nextpg = h->nextpg) == P_INVALID)
+ break;
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Move up the stack. */
+ for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+ /* Get the parent page. */
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ return (1);
+
+ /* Move to the next index. */
+ if (parent->index != NEXTINDEX(h) - 1) {
+ idx = parent->index + 1;
+ BT_PUSH(t, h->pgno, idx);
+ break;
+ }
+ mpool_put(t->bt_mp, h, 0);
+ }
+
+ /* Restore the stack. */
+ while (level--) {
+ /* Push the next level down onto the stack. */
+ bi = GETBINTERNAL(h, idx);
+ pgno = bi->pgno;
+ BT_PUSH(t, pgno, 0);
+
+ /* Lose the currently pinned page. */
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Get the next level down. */
+ if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+ return (1);
+ idx = 0;
+ }
+ mpool_put(t->bt_mp, h, 0);
+ if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
+ return (1);
+ }
+
+ if (h->pgno == c->pg.pgno)
+ goto ret;
+
+ /* Reacquire the original stack. */
+ mpool_put(t->bt_mp, h, 0);
+ if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+ return (1);
+ h = e->page;
+
+ /*
+ * Move left, looking for the page. At each move we have to move
+ * up the stack until we don't have to change pages to move to the
+ * next page. If we have to change pages at an internal level, we
+ * have to fix the stack back up.
+ */
+ while (h->pgno != c->pg.pgno) {
+ if ((prevpg = h->prevpg) == P_INVALID)
+ break;
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Move up the stack. */
+ for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+ /* Get the parent page. */
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ return (1);
+
+ /* Move to the next index. */
+ if (parent->index != 0) {
+ idx = parent->index - 1;
+ BT_PUSH(t, h->pgno, idx);
+ break;
+ }
+ mpool_put(t->bt_mp, h, 0);
+ }
+
+ /* Restore the stack. */
+ while (level--) {
+ /* Push the next level down onto the stack. */
+ bi = GETBINTERNAL(h, idx);
+ pgno = bi->pgno;
+
+ /* Lose the currently pinned page. */
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Get the next level down. */
+ if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+ return (1);
+
+ idx = NEXTINDEX(h) - 1;
+ BT_PUSH(t, pgno, idx);
+ }
+ mpool_put(t->bt_mp, h, 0);
+ if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
+ return (1);
+ }
+
+
+ret: mpool_put(t->bt_mp, h, 0);
+ return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
+}
+
+/*
+ * __bt_bdelete --
+ * Delete all key/data pairs matching the specified key.
+ *
+ * Parameters:
+ * t: tree
+ * key: key to delete
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+__bt_bdelete(BTREE *t, const DBT *key)
+{
+ EPG *e;
+ PAGE *h;
+ int deleted, exact, redo;
+
+ deleted = 0;
+
+ /* Find any matching record; __bt_search pins the page. */
+loop: if ((e = __bt_search(t, key, &exact)) == NULL)
+ return (deleted ? RET_SUCCESS : RET_ERROR);
+ if (!exact) {
+ mpool_put(t->bt_mp, e->page, 0);
+ return (deleted ? RET_SUCCESS : RET_SPECIAL);
+ }
+
+ /*
+ * Delete forward, then delete backward, from the found key. If
+ * there are duplicates and we reach either side of the page, do
+ * the key search again, so that we get them all.
+ */
+ redo = 0;
+ h = e->page;
+ do {
+ if (__bt_dleaf(t, key, h, e->index)) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ if (F_ISSET(t, B_NODUPS)) {
+ if (NEXTINDEX(h) == 0) {
+ if (__bt_pdelete(t, h))
+ return (RET_ERROR);
+ } else
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+ }
+ deleted = 1;
+ } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
+
+ /* Check for right-hand edge of the page. */
+ if (e->index == NEXTINDEX(h))
+ redo = 1;
+
+ /* Delete from the key to the beginning of the page. */
+ while (e->index-- > 0) {
+ if (__bt_cmp(t, key, e) != 0)
+ break;
+ if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ if (e->index == 0)
+ redo = 1;
+ }
+
+ /* Check for an empty page. */
+ if (NEXTINDEX(h) == 0) {
+ if (__bt_pdelete(t, h))
+ return (RET_ERROR);
+ goto loop;
+ }
+
+ /* Put the page. */
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ if (redo)
+ goto loop;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_pdelete --
+ * Delete a single page from the tree.
+ *
+ * Parameters:
+ * t: tree
+ * h: leaf page
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ *
+ * Side-effects:
+ * mpool_put's the page
+ */
+static int
+__bt_pdelete(BTREE *t, PAGE *h)
+{
+ BINTERNAL *bi;
+ PAGE *pg;
+ EPGNO *parent;
+ indx_t cnt, idx, *ip, offset;
+ u_int32_t nksize;
+ char *from;
+
+ /*
+ * Walk the parent page stack -- a LIFO stack of the pages that were
+ * traversed when we searched for the page where the delete occurred.
+ * Each stack entry is a page number and a page index offset. The
+ * offset is for the page traversed on the search. We've just deleted
+ * a page, so we have to delete the key from the parent page.
+ *
+ * If the delete from the parent page makes it empty, this process may
+ * continue all the way up the tree. We stop if we reach the root page
+ * (which is never deleted, it's just not worth the effort) or if the
+ * delete does not empty the page.
+ */
+ while ((parent = BT_POP(t)) != NULL) {
+ /* Get the parent page. */
+ if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ return (RET_ERROR);
+
+ idx = parent->index;
+ bi = GETBINTERNAL(pg, idx);
+
+ /* Free any overflow pages. */
+ if (bi->flags & P_BIGKEY &&
+ __ovfl_delete(t, bi->bytes) == RET_ERROR) {
+ mpool_put(t->bt_mp, pg, 0);
+ return (RET_ERROR);
+ }
+
+ /*
+ * Free the parent if it has only the one key and it's not the
+ * root page. If it's the rootpage, turn it back into an empty
+ * leaf page.
+ */
+ if (NEXTINDEX(pg) == 1) {
+ if (pg->pgno == P_ROOT) {
+ pg->lower = BTDATAOFF;
+ pg->upper = t->bt_psize;
+ pg->flags = P_BLEAF;
+ } else {
+ if (__bt_relink(t, pg) || __bt_free(t, pg))
+ return (RET_ERROR);
+ continue;
+ }
+ } else {
+ /* Pack remaining key items at the end of the page. */
+ nksize = NBINTERNAL(bi->ksize);
+ from = (char *)pg + pg->upper;
+ memmove(from + nksize, from, (char *)bi - from);
+ pg->upper += nksize;
+
+ /* Adjust indices' offsets, shift the indices down. */
+ offset = pg->linp[idx];
+ for (cnt = idx, ip = &pg->linp[0]; cnt--; ++ip)
+ if (ip[0] < offset)
+ ip[0] += nksize;
+ for (cnt = NEXTINDEX(pg) - idx; --cnt; ++ip)
+ ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
+ pg->lower -= sizeof(indx_t);
+ }
+
+ mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+ break;
+ }
+
+ /* Free the leaf page, as long as it wasn't the root. */
+ if (h->pgno == P_ROOT) {
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+ }
+ return (__bt_relink(t, h) || __bt_free(t, h));
+}
+
+/*
+ * __bt_dleaf --
+ * Delete a single record from a leaf page.
+ *
+ * Parameters:
+ * t: tree
+ * key: referenced key
+ * h: page
+ * idx: index on page to delete
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_dleaf(BTREE *t, const DBT *key, PAGE *h, u_int idx)
+{
+ BLEAF *bl;
+ indx_t cnt, *ip, offset;
+ u_int32_t nbytes;
+ void *to;
+ char *from;
+
+ /* If this record is referenced by the cursor, delete the cursor. */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == idx &&
+ __bt_curdel(t, key, h, idx))
+ return (RET_ERROR);
+
+ /* If the entry uses overflow pages, make them available for reuse. */
+ to = bl = GETBLEAF(h, idx);
+ if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
+ return (RET_ERROR);
+ if (bl->flags & P_BIGDATA &&
+ __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Pack the remaining key/data items at the end of the page. */
+ nbytes = NBLEAF(bl);
+ from = (char *)h + h->upper;
+ memmove(from + nbytes, from, (char *)to - from);
+ h->upper += nbytes;
+
+ /* Adjust the indices' offsets, shift the indices down. */
+ offset = h->linp[idx];
+ for (cnt = idx, ip = &h->linp[0]; cnt--; ++ip)
+ if (ip[0] < offset)
+ ip[0] += nbytes;
+ for (cnt = NEXTINDEX(h) - idx; --cnt; ++ip)
+ ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+ h->lower -= sizeof(indx_t);
+
+ /* If the cursor is on this page, adjust it as necessary. */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > idx)
+ --t->bt_cursor.pg.index;
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_curdel --
+ * Delete the cursor.
+ *
+ * Parameters:
+ * t: tree
+ * key: referenced key (or NULL)
+ * h: page
+ * idx: index on page to delete
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+static int
+__bt_curdel(BTREE *t, const DBT *key, PAGE *h, u_int idx)
+{
+ CURSOR *c;
+ EPG e;
+ PAGE *pg;
+ int curcopy, status;
+
+ /*
+ * If there are duplicates, move forward or backward to one.
+ * Otherwise, copy the key into the cursor area.
+ */
+ c = &t->bt_cursor;
+ F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
+
+ curcopy = 0;
+ if (!F_ISSET(t, B_NODUPS)) {
+ /*
+ * We're going to have to do comparisons. If we weren't
+ * provided a copy of the key, i.e. the user is deleting
+ * the current cursor position, get one.
+ */
+ if (key == NULL) {
+ e.page = h;
+ e.index = idx;
+ if ((status = __bt_ret(t, &e,
+ &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
+ return (status);
+ curcopy = 1;
+ key = &c->key;
+ }
+ /* Check previous key, if not at the beginning of the page. */
+ if (idx > 0) {
+ e.page = h;
+ e.index = idx - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_BEFORE);
+ goto dup2;
+ }
+ }
+ /* Check next key, if not at the end of the page. */
+ if (idx < NEXTINDEX(h) - 1) {
+ e.page = h;
+ e.index = idx + 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_AFTER);
+ goto dup2;
+ }
+ }
+ /* Check previous key if at the beginning of the page. */
+ if (idx == 0 && h->prevpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+ return (RET_ERROR);
+ e.page = pg;
+ e.index = NEXTINDEX(pg) - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_BEFORE);
+ goto dup1;
+ }
+ mpool_put(t->bt_mp, pg, 0);
+ }
+ /* Check next key if at the end of the page. */
+ if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+ return (RET_ERROR);
+ e.page = pg;
+ e.index = 0;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_AFTER);
+dup1: mpool_put(t->bt_mp, pg, 0);
+dup2: c->pg.pgno = e.page->pgno;
+ c->pg.index = e.index;
+ return (RET_SUCCESS);
+ }
+ mpool_put(t->bt_mp, pg, 0);
+ }
+ }
+ e.page = h;
+ e.index = idx;
+ if (curcopy || (status =
+ __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
+ F_SET(c, CURS_ACQUIRE);
+ return (RET_SUCCESS);
+ }
+ return (status);
+}
+
+/*
+ * __bt_relink --
+ * Link around a deleted page.
+ *
+ * Parameters:
+ * t: tree
+ * h: page to be deleted
+ */
+static int
+__bt_relink(BTREE *t, PAGE *h)
+{
+ PAGE *pg;
+
+ if (h->nextpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+ return (RET_ERROR);
+ pg->prevpg = h->prevpg;
+ mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+ }
+ if (h->prevpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+ return (RET_ERROR);
+ pg->nextpg = h->nextpg;
+ mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+ }
+ return (0);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_get.c b/freebsd/lib/libc/db/btree/bt_get.c
new file mode 100644
index 00000000..b335e1ba
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_get.c
@@ -0,0 +1,101 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __BT_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key to find
+ * data: data to return
+ * flag: currently unused
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__bt_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG *e;
+ int exact, status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Get currently doesn't take any flags. */
+ if (flags) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if ((e = __bt_search(t, key, &exact)) == NULL)
+ return (RET_ERROR);
+ if (!exact) {
+ mpool_put(t->bt_mp, e->page, 0);
+ return (RET_SPECIAL);
+ }
+
+ status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0);
+
+ /*
+ * If the user is doing concurrent access, we copied the
+ * key/data, toss the page.
+ */
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e->page, 0);
+ else
+ t->bt_pinned = e->page;
+ return (status);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_open.c b/freebsd/lib/libc/db/btree/bt_open.c
new file mode 100644
index 00000000..1e37c0e5
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_open.c
@@ -0,0 +1,453 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Implementation of btree access method for 4.4BSD.
+ *
+ * The design here was originally based on that of the btree access method
+ * used in the Postgres database system at UC Berkeley. This implementation
+ * is wholly independent of the Postgres code.
+ */
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "btree.h"
+
+#ifdef DEBUG
+#undef MINPSIZE
+#define MINPSIZE 128
+#endif
+
+static int byteorder(void);
+static int nroot(BTREE *);
+static int tmp(void);
+
+/*
+ * __BT_OPEN -- Open a btree.
+ *
+ * Creates and fills a DB struct, and calls the routine that actually
+ * opens the btree.
+ *
+ * Parameters:
+ * fname: filename (NULL for in-memory trees)
+ * flags: open flag bits
+ * mode: open permission bits
+ * b: BTREEINFO pointer
+ *
+ * Returns:
+ * NULL on failure, pointer to DB on success.
+ *
+ */
+DB *
+__bt_open(const char *fname, int flags, int mode, const BTREEINFO *openinfo, int dflags)
+{
+ struct stat sb;
+ BTMETA m;
+ BTREE *t;
+ BTREEINFO b;
+ DB *dbp;
+ pgno_t ncache;
+ ssize_t nr;
+ int machine_lorder, saved_errno;
+
+ t = NULL;
+
+ /*
+ * Intention is to make sure all of the user's selections are okay
+ * here and then use them without checking. Can't be complete, since
+ * we don't know the right page size, lorder or flags until the backing
+ * file is opened. Also, the file's page size can cause the cachesize
+ * to change.
+ */
+ machine_lorder = byteorder();
+ if (openinfo) {
+ b = *openinfo;
+
+ /* Flags: R_DUP. */
+ if (b.flags & ~(R_DUP))
+ goto einval;
+
+ /*
+ * Page size must be indx_t aligned and >= MINPSIZE. Default
+ * page size is set farther on, based on the underlying file
+ * transfer size.
+ */
+ if (b.psize &&
+ (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
+ b.psize & (sizeof(indx_t) - 1) ))
+ goto einval;
+
+ /* Minimum number of keys per page; absolute minimum is 2. */
+ if (b.minkeypage) {
+ if (b.minkeypage < 2)
+ goto einval;
+ } else
+ b.minkeypage = DEFMINKEYPAGE;
+
+ /* If no comparison, use default comparison and prefix. */
+ if (b.compare == NULL) {
+ b.compare = __bt_defcmp;
+ if (b.prefix == NULL)
+ b.prefix = __bt_defpfx;
+ }
+
+ if (b.lorder == 0)
+ b.lorder = machine_lorder;
+ } else {
+ b.compare = __bt_defcmp;
+ b.cachesize = 0;
+ b.flags = 0;
+ b.lorder = machine_lorder;
+ b.minkeypage = DEFMINKEYPAGE;
+ b.prefix = __bt_defpfx;
+ b.psize = 0;
+ }
+
+ /* Check for the ubiquitous PDP-11. */
+ if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN)
+ goto einval;
+
+ /* Allocate and initialize DB and BTREE structures. */
+ if ((t = (BTREE *)calloc(1, sizeof(BTREE))) == NULL)
+ goto err;
+ t->bt_fd = -1; /* Don't close unopened fd on error. */
+ t->bt_lorder = b.lorder;
+ t->bt_order = NOT;
+ t->bt_cmp = b.compare;
+ t->bt_pfx = b.prefix;
+ t->bt_rfd = -1;
+
+ if ((t->bt_dbp = dbp = (DB *)calloc(1, sizeof(DB))) == NULL)
+ goto err;
+ if (t->bt_lorder != machine_lorder)
+ F_SET(t, B_NEEDSWAP);
+
+ dbp->type = DB_BTREE;
+ dbp->internal = t;
+ dbp->close = __bt_close;
+ dbp->del = __bt_delete;
+ dbp->fd = __bt_fd;
+ dbp->get = __bt_get;
+ dbp->put = __bt_put;
+ dbp->seq = __bt_seq;
+ dbp->sync = __bt_sync;
+
+ /*
+ * If no file name was supplied, this is an in-memory btree and we
+ * open a backing temporary file. Otherwise, it's a disk-based tree.
+ */
+ if (fname) {
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ F_SET(t, B_RDONLY);
+ break;
+ case O_RDWR:
+ break;
+ case O_WRONLY:
+ default:
+ goto einval;
+ }
+
+ if ((t->bt_fd = _open(fname, flags, mode)) < 0)
+ goto err;
+
+ } else {
+ if ((flags & O_ACCMODE) != O_RDWR)
+ goto einval;
+ if ((t->bt_fd = tmp()) == -1)
+ goto err;
+ F_SET(t, B_INMEM);
+ }
+
+ if (_fcntl(t->bt_fd, F_SETFD, 1) == -1)
+ goto err;
+
+ if (_fstat(t->bt_fd, &sb))
+ goto err;
+ if (sb.st_size) {
+ if ((nr = _read(t->bt_fd, &m, sizeof(BTMETA))) < 0)
+ goto err;
+ if (nr != sizeof(BTMETA))
+ goto eftype;
+
+ /*
+ * Read in the meta-data. This can change the notion of what
+ * the lorder, page size and flags are, and, when the page size
+ * changes, the cachesize value can change too. If the user
+ * specified the wrong byte order for an existing database, we
+ * don't bother to return an error, we just clear the NEEDSWAP
+ * bit.
+ */
+ if (m.magic == BTREEMAGIC)
+ F_CLR(t, B_NEEDSWAP);
+ else {
+ F_SET(t, B_NEEDSWAP);
+ M_32_SWAP(m.magic);
+ M_32_SWAP(m.version);
+ M_32_SWAP(m.psize);
+ M_32_SWAP(m.free);
+ M_32_SWAP(m.nrecs);
+ M_32_SWAP(m.flags);
+ }
+ if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
+ goto eftype;
+ if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
+ m.psize & (sizeof(indx_t) - 1) )
+ goto eftype;
+ if (m.flags & ~SAVEMETA)
+ goto eftype;
+ b.psize = m.psize;
+ F_SET(t, m.flags);
+ t->bt_free = m.free;
+ t->bt_nrecs = m.nrecs;
+ } else {
+ /*
+ * Set the page size to the best value for I/O to this file.
+ * Don't overflow the page offset type.
+ */
+ if (b.psize == 0) {
+ b.psize = sb.st_blksize;
+ if (b.psize < MINPSIZE)
+ b.psize = MINPSIZE;
+ if (b.psize > MAX_PAGE_OFFSET + 1)
+ b.psize = MAX_PAGE_OFFSET + 1;
+ }
+
+ /* Set flag if duplicates permitted. */
+ if (!(b.flags & R_DUP))
+ F_SET(t, B_NODUPS);
+
+ t->bt_free = P_INVALID;
+ t->bt_nrecs = 0;
+ F_SET(t, B_METADIRTY);
+ }
+
+ t->bt_psize = b.psize;
+
+ /* Set the cache size; must be a multiple of the page size. */
+ if (b.cachesize && b.cachesize & (b.psize - 1) )
+ b.cachesize += (~b.cachesize & (b.psize - 1) ) + 1;
+ if (b.cachesize < b.psize * MINCACHE)
+ b.cachesize = b.psize * MINCACHE;
+
+ /* Calculate number of pages to cache. */
+ ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;
+
+ /*
+ * The btree data structure requires that at least two keys can fit on
+ * a page, but other than that there's no fixed requirement. The user
+ * specified a minimum number per page, and we translated that into the
+ * number of bytes a key/data pair can use before being placed on an
+ * overflow page. This calculation includes the page header, the size
+ * of the index referencing the leaf item and the size of the leaf item
+ * structure. Also, don't let the user specify a minkeypage such that
+ * a key/data pair won't fit even if both key and data are on overflow
+ * pages.
+ */
+ t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
+ (sizeof(indx_t) + NBLEAFDBT(0, 0));
+ if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
+ t->bt_ovflsize =
+ NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);
+
+ /* Initialize the buffer pool. */
+ if ((t->bt_mp =
+ mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
+ goto err;
+ if (!F_ISSET(t, B_INMEM))
+ mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
+
+ /* Create a root page if new tree. */
+ if (nroot(t) == RET_ERROR)
+ goto err;
+
+ /* Global flags. */
+ if (dflags & DB_LOCK)
+ F_SET(t, B_DB_LOCK);
+ if (dflags & DB_SHMEM)
+ F_SET(t, B_DB_SHMEM);
+ if (dflags & DB_TXN)
+ F_SET(t, B_DB_TXN);
+
+ return (dbp);
+
+einval: errno = EINVAL;
+ goto err;
+
+eftype: errno = EFTYPE;
+ goto err;
+
+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);
+}
+
+/*
+ * NROOT -- Create the root of a new tree.
+ *
+ * Parameters:
+ * t: tree
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+nroot(BTREE *t)
+{
+ PAGE *meta, *root;
+ pgno_t npg;
+
+ 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, MPOOL_PAGE_NEXT)) == NULL)
+ return (RET_ERROR);
+
+ if ((root = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
+ return (RET_ERROR);
+
+ if (npg != P_ROOT)
+ return (RET_ERROR);
+ root->pgno = npg;
+ root->prevpg = root->nextpg = P_INVALID;
+ root->lower = BTDATAOFF;
+ root->upper = t->bt_psize;
+ root->flags = P_BLEAF;
+ memset(meta, 0, t->bt_psize);
+ mpool_put(t->bt_mp, meta, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, root, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
+
+static int
+tmp(void)
+{
+ sigset_t set, oset;
+ int fd, len;
+ char *envtmp = NULL;
+ char path[MAXPATHLEN];
+
+ if (issetugid() == 0)
+ envtmp = getenv("TMPDIR");
+ 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);
+ if ((fd = mkstemp(path)) != -1)
+ (void)unlink(path);
+ (void)_sigprocmask(SIG_SETMASK, &oset, NULL);
+ return(fd);
+}
+
+static int
+byteorder(void)
+{
+ u_int32_t x;
+ u_char *p;
+
+ x = 0x01020304;
+ p = (u_char *)&x;
+ switch (*p) {
+ case 1:
+ return (BIG_ENDIAN);
+ case 4:
+ return (LITTLE_ENDIAN);
+ default:
+ return (0);
+ }
+}
+
+int
+__bt_fd(const DB *dbp)
+{
+ BTREE *t;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* In-memory database can't have a file descriptor. */
+ if (F_ISSET(t, B_INMEM)) {
+ errno = ENOENT;
+ return (-1);
+ }
+ return (t->bt_fd);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_overflow.c b/freebsd/lib/libc/db/btree/bt_overflow.c
new file mode 100644
index 00000000..7079453a
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_overflow.c
@@ -0,0 +1,218 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * Big key/data code.
+ *
+ * Big key and data entries are stored on linked lists of pages. The initial
+ * reference is byte string stored with the key or data and is the page number
+ * and size. The actual record is stored in a chain of pages linked by the
+ * nextpg field of the PAGE header.
+ *
+ * The first page of the chain has a special property. If the record is used
+ * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
+ * in the header.
+ *
+ * XXX
+ * A single DBT is written to each chain, so a lot of space on the last page
+ * is wasted. This is a fairly major bug for some data sets.
+ */
+
+/*
+ * __OVFL_GET -- Get an overflow key/data item.
+ *
+ * Parameters:
+ * t: tree
+ * p: pointer to { pgno_t, u_int32_t }
+ * buf: storage address
+ * bufsz: storage size
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_get(BTREE *t, void *p, size_t *ssz, void **buf, size_t *bufsz)
+{
+ PAGE *h;
+ pgno_t pg;
+ size_t nb, plen;
+ u_int32_t sz;
+
+ memmove(&pg, p, sizeof(pgno_t));
+ memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+ *ssz = sz;
+
+#ifdef DEBUG
+ if (pg == P_INVALID || sz == 0)
+ abort();
+#endif
+ /* Make the buffer bigger as necessary. */
+ if (*bufsz < sz) {
+ *buf = reallocf(*buf, sz);
+ if (*buf == NULL)
+ return (RET_ERROR);
+ *bufsz = sz;
+ }
+
+ /*
+ * Step through the linked list of pages, copying the data on each one
+ * into the buffer. Never copy more than the data's length.
+ */
+ plen = t->bt_psize - BTDATAOFF;
+ for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ nb = MIN(sz, plen);
+ memmove(p, (char *)h + BTDATAOFF, nb);
+ mpool_put(t->bt_mp, h, 0);
+
+ if ((sz -= nb) == 0)
+ break;
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_PUT -- Store an overflow key/data item.
+ *
+ * Parameters:
+ * t: tree
+ * data: DBT to store
+ * pgno: storage page number
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_put(BTREE *t, const DBT *dbt, pgno_t *pg)
+{
+ PAGE *h, *last;
+ void *p;
+ pgno_t npg;
+ size_t nb, plen;
+ u_int32_t sz;
+
+ /*
+ * Allocate pages and copy the key/data record into them. Store the
+ * number of the first page in the chain.
+ */
+ plen = t->bt_psize - BTDATAOFF;
+ for (last = NULL, p = dbt->data, sz = dbt->size;;
+ p = (char *)p + plen, last = h) {
+ if ((h = __bt_new(t, &npg)) == NULL)
+ return (RET_ERROR);
+
+ h->pgno = npg;
+ h->nextpg = h->prevpg = P_INVALID;
+ h->flags = P_OVERFLOW;
+ h->lower = h->upper = 0;
+
+ nb = MIN(sz, plen);
+ memmove((char *)h + BTDATAOFF, p, nb);
+
+ if (last) {
+ last->nextpg = h->pgno;
+ mpool_put(t->bt_mp, last, MPOOL_DIRTY);
+ } else
+ *pg = h->pgno;
+
+ if ((sz -= nb) == 0) {
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ }
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_DELETE -- Delete an overflow chain.
+ *
+ * Parameters:
+ * t: tree
+ * p: pointer to { pgno_t, u_int32_t }
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_delete(BTREE *t, void *p)
+{
+ PAGE *h;
+ pgno_t pg;
+ size_t plen;
+ u_int32_t sz;
+
+ memmove(&pg, p, sizeof(pgno_t));
+ memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+
+#ifdef DEBUG
+ if (pg == P_INVALID || sz == 0)
+ abort();
+#endif
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Don't delete chains used by internal pages. */
+ if (h->flags & P_PRESERVE) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SUCCESS);
+ }
+
+ /* Step through the chain, calling the free routine for each page. */
+ for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
+ pg = h->nextpg;
+ __bt_free(t, h);
+ if (sz <= plen)
+ break;
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ }
+ return (RET_SUCCESS);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_page.c b/freebsd/lib/libc/db/btree/bt_page.c
new file mode 100644
index 00000000..dc30566b
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_page.c
@@ -0,0 +1,96 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_free --
+ * Put a page on the freelist.
+ *
+ * Parameters:
+ * t: tree
+ * h: page to free
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ *
+ * Side-effect:
+ * mpool_put's the page.
+ */
+int
+__bt_free(BTREE *t, PAGE *h)
+{
+ /* Insert the page at the head of the free list. */
+ h->prevpg = P_INVALID;
+ h->nextpg = t->bt_free;
+ t->bt_free = h->pgno;
+ F_SET(t, B_METADIRTY);
+
+ /* Make sure the page gets written back. */
+ return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
+}
+
+/*
+ * __bt_new --
+ * Get a new page, preferably from the freelist.
+ *
+ * Parameters:
+ * t: tree
+ * npg: storage for page number.
+ *
+ * Returns:
+ * Pointer to a page, NULL on error.
+ */
+PAGE *
+__bt_new(BTREE *t, pgno_t *npg)
+{
+ PAGE *h;
+
+ if (t->bt_free != P_INVALID &&
+ (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
+ *npg = t->bt_free;
+ t->bt_free = h->nextpg;
+ F_SET(t, B_METADIRTY);
+ return (h);
+ }
+ return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT));
+}
diff --git a/freebsd/lib/libc/db/btree/bt_put.c b/freebsd/lib/libc/db/btree/bt_put.c
new file mode 100644
index 00000000..51c241c7
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_put.c
@@ -0,0 +1,316 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static EPG *bt_fast(BTREE *, const DBT *, const DBT *, int *);
+
+/*
+ * __BT_PUT -- Add a btree item to the tree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key
+ * data: data
+ * flag: R_NOOVERWRITE
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
+ * tree and R_NOOVERWRITE specified.
+ */
+int
+__bt_put(const DB *dbp, DBT *key, const DBT *data, u_int flags)
+{
+ BTREE *t;
+ DBT tkey, tdata;
+ EPG *e;
+ PAGE *h;
+ indx_t idx, nxtindex;
+ pgno_t pg;
+ u_int32_t nbytes, tmp;
+ int dflags, exact, status;
+ char *dest, db[NOVFLSIZE], kb[NOVFLSIZE];
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Check for change to a read-only tree. */
+ if (F_ISSET(t, B_RDONLY)) {
+ errno = EPERM;
+ return (RET_ERROR);
+ }
+
+ switch (flags) {
+ case 0:
+ case R_NOOVERWRITE:
+ break;
+ case R_CURSOR:
+ /*
+ * If flags is R_CURSOR, put the cursor. Must already
+ * have started a scan and not have already deleted it.
+ */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor,
+ CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+ break;
+ /* FALLTHROUGH */
+ default:
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ /*
+ * If the key/data pair won't fit on a page, store it on overflow
+ * pages. Only put the key on the overflow page if the pair are
+ * still too big after moving the data to an overflow page.
+ *
+ * XXX
+ * If the insert fails later on, the overflow pages aren't recovered.
+ */
+ dflags = 0;
+ if (key->size + data->size > t->bt_ovflsize) {
+ if (key->size > t->bt_ovflsize) {
+storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
+ return (RET_ERROR);
+ tkey.data = kb;
+ tkey.size = NOVFLSIZE;
+ memmove(kb, &pg, sizeof(pgno_t));
+ tmp = key->size;
+ memmove(kb + sizeof(pgno_t),
+ &tmp, sizeof(u_int32_t));
+ dflags |= P_BIGKEY;
+ key = &tkey;
+ }
+ if (key->size + data->size > t->bt_ovflsize) {
+ if (__ovfl_put(t, data, &pg) == RET_ERROR)
+ return (RET_ERROR);
+ tdata.data = db;
+ tdata.size = NOVFLSIZE;
+ memmove(db, &pg, sizeof(pgno_t));
+ tmp = data->size;
+ memmove(db + sizeof(pgno_t),
+ &tmp, sizeof(u_int32_t));
+ dflags |= P_BIGDATA;
+ data = &tdata;
+ }
+ if (key->size + data->size > t->bt_ovflsize)
+ goto storekey;
+ }
+
+ /* Replace the cursor. */
+ if (flags == R_CURSOR) {
+ if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
+ return (RET_ERROR);
+ idx = t->bt_cursor.pg.index;
+ goto delete;
+ }
+
+ /*
+ * Find the key to delete, or, the location at which to insert.
+ * Bt_fast and __bt_search both pin the returned page.
+ */
+ if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL)
+ if ((e = __bt_search(t, key, &exact)) == NULL)
+ return (RET_ERROR);
+ h = e->page;
+ idx = e->index;
+
+ /*
+ * Add the key/data pair to the tree. If an identical key is already
+ * in the tree, and R_NOOVERWRITE is set, an error is returned. If
+ * R_NOOVERWRITE is not set, the key is either added (if duplicates are
+ * permitted) or an error is returned.
+ */
+ switch (flags) {
+ case R_NOOVERWRITE:
+ if (!exact)
+ break;
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ default:
+ if (!exact || !F_ISSET(t, B_NODUPS))
+ break;
+ /*
+ * !!!
+ * Note, the delete may empty the page, so we need to put a
+ * new entry into the page immediately.
+ */
+delete: if (__bt_dleaf(t, key, h, idx) == RET_ERROR) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ break;
+ }
+
+ /*
+ * If not enough room, or the user has put a ceiling on the number of
+ * keys permitted in the page, split the page. The split code will
+ * insert the key and data and unpin the current page. If inserting
+ * into the offset array, shift the pointers up.
+ */
+ nbytes = NBLEAFDBT(key->size, data->size);
+ 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);
+ goto success;
+ }
+
+ if (idx < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + idx + 1, h->linp + idx,
+ (nxtindex - idx) * sizeof(indx_t));
+ h->lower += sizeof(indx_t);
+
+ h->linp[idx] = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ WR_BLEAF(dest, key, data, dflags);
+
+ /* If the cursor is on this page, adjust it as necessary. */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= idx)
+ ++t->bt_cursor.pg.index;
+
+ if (t->bt_order == NOT) {
+ if (h->nextpg == P_INVALID) {
+ if (idx == NEXTINDEX(h) - 1) {
+ t->bt_order = FORWARD;
+ t->bt_last.index = idx;
+ t->bt_last.pgno = h->pgno;
+ }
+ } else if (h->prevpg == P_INVALID) {
+ if (idx == 0) {
+ t->bt_order = BACK;
+ t->bt_last.index = 0;
+ t->bt_last.pgno = h->pgno;
+ }
+ }
+ }
+
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+success:
+ if (flags == R_SETCURSOR)
+ __bt_setcur(t, e->page->pgno, e->index);
+
+ F_SET(t, B_MODIFIED);
+ return (RET_SUCCESS);
+}
+
+#ifdef STATISTICS
+u_long bt_cache_hit, bt_cache_miss;
+#endif
+
+/*
+ * BT_FAST -- Do a quick check for sorted data.
+ *
+ * Parameters:
+ * t: tree
+ * key: key to insert
+ *
+ * Returns:
+ * EPG for new record or NULL if not found.
+ */
+static EPG *
+bt_fast(BTREE *t, const DBT *key, const DBT *data, int *exactp)
+{
+ PAGE *h;
+ u_int32_t nbytes;
+ int cmp;
+
+ if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) {
+ t->bt_order = NOT;
+ return (NULL);
+ }
+ t->bt_cur.page = h;
+ t->bt_cur.index = t->bt_last.index;
+
+ /*
+ * If won't fit in this page or have too many keys in this page,
+ * have to search to get split stack.
+ */
+ nbytes = NBLEAFDBT(key->size, data->size);
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t))
+ goto miss;
+
+ if (t->bt_order == FORWARD) {
+ if (t->bt_cur.page->nextpg != P_INVALID)
+ goto miss;
+ if (t->bt_cur.index != NEXTINDEX(h) - 1)
+ goto miss;
+ if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0)
+ goto miss;
+ t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index;
+ } else {
+ if (t->bt_cur.page->prevpg != P_INVALID)
+ goto miss;
+ if (t->bt_cur.index != 0)
+ goto miss;
+ if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0)
+ goto miss;
+ t->bt_last.index = 0;
+ }
+ *exactp = cmp == 0;
+#ifdef STATISTICS
+ ++bt_cache_hit;
+#endif
+ return (&t->bt_cur);
+
+miss:
+#ifdef STATISTICS
+ ++bt_cache_miss;
+#endif
+ t->bt_order = NOT;
+ mpool_put(t->bt_mp, h, 0);
+ return (NULL);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_search.c b/freebsd/lib/libc/db/btree/bt_search.c
new file mode 100644
index 00000000..d5e859bc
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_search.c
@@ -0,0 +1,202 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_snext(BTREE *, PAGE *, const DBT *, int *);
+static int __bt_sprev(BTREE *, PAGE *, const DBT *, int *);
+
+/*
+ * __bt_search --
+ * Search a btree for a key.
+ *
+ * Parameters:
+ * t: tree to search
+ * key: key to find
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * The EPG for matching record, if any, or the EPG for the location
+ * of the key, if it were inserted into the tree, is entered into
+ * the bt_cur field of the tree. A pointer to the field is returned.
+ */
+EPG *
+__bt_search(BTREE *t, const DBT *key, int *exactp)
+{
+ PAGE *h;
+ indx_t base, idx, lim;
+ pgno_t pg;
+ int cmp;
+
+ BT_CLR(t);
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (NULL);
+
+ /* Do a binary search on the current page. */
+ t->bt_cur.page = h;
+ for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
+ t->bt_cur.index = idx = base + (lim >> 1);
+ if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
+ if (h->flags & P_BLEAF) {
+ *exactp = 1;
+ return (&t->bt_cur);
+ }
+ goto next;
+ }
+ if (cmp > 0) {
+ base = idx + 1;
+ --lim;
+ }
+ }
+
+ /*
+ * If it's a leaf page, we're almost done. If no duplicates
+ * are allowed, or we have an exact match, we're done. Else,
+ * it's possible that there were matching keys on this page,
+ * which later deleted, and we're on a page with no matches
+ * while there are matches on other pages. If at the start or
+ * end of a page, check the adjacent page.
+ */
+ if (h->flags & P_BLEAF) {
+ if (!F_ISSET(t, B_NODUPS)) {
+ if (base == 0 &&
+ h->prevpg != P_INVALID &&
+ __bt_sprev(t, h, key, exactp))
+ return (&t->bt_cur);
+ if (base == NEXTINDEX(h) &&
+ h->nextpg != P_INVALID &&
+ __bt_snext(t, h, key, exactp))
+ return (&t->bt_cur);
+ }
+ *exactp = 0;
+ t->bt_cur.index = base;
+ return (&t->bt_cur);
+ }
+
+ /*
+ * No match found. Base is the smallest index greater than
+ * key and may be zero or a last + 1 index. If it's non-zero,
+ * decrement by one, and record the internal page which should
+ * be a parent page for the key. If a split later occurs, the
+ * inserted page will be to the right of the saved page.
+ */
+ idx = base ? base - 1 : base;
+
+next: BT_PUSH(t, h->pgno, idx);
+ pg = GETBINTERNAL(h, idx)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ }
+}
+
+/*
+ * __bt_snext --
+ * Check for an exact match after the key.
+ *
+ * Parameters:
+ * t: tree
+ * h: current page
+ * key: key
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * If an exact match found.
+ */
+static int
+__bt_snext(BTREE *t, PAGE *h, const DBT *key, int *exactp)
+{
+ EPG e;
+
+ /*
+ * Get the next page. The key is either an exact
+ * match, or not as good as the one we already have.
+ */
+ if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+ return (0);
+ e.index = 0;
+ if (__bt_cmp(t, key, &e) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ t->bt_cur = e;
+ *exactp = 1;
+ return (1);
+ }
+ mpool_put(t->bt_mp, e.page, 0);
+ return (0);
+}
+
+/*
+ * __bt_sprev --
+ * Check for an exact match before the key.
+ *
+ * Parameters:
+ * t: tree
+ * h: current page
+ * key: key
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * If an exact match found.
+ */
+static int
+__bt_sprev(BTREE *t, PAGE *h, const DBT *key, int *exactp)
+{
+ EPG e;
+
+ /*
+ * Get the previous page. The key is either an exact
+ * match, or not as good as the one we already have.
+ */
+ if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+ return (0);
+ e.index = NEXTINDEX(e.page) - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ t->bt_cur = e;
+ *exactp = 1;
+ return (1);
+ }
+ mpool_put(t->bt_mp, e.page, 0);
+ return (0);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_seq.c b/freebsd/lib/libc/db/btree/bt_seq.c
new file mode 100644
index 00000000..5e92c855
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_seq.c
@@ -0,0 +1,443 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_first(BTREE *, const DBT *, EPG *, int *);
+static int __bt_seqadv(BTREE *, EPG *, int);
+static int __bt_seqset(BTREE *, EPG *, DBT *, int);
+
+/*
+ * Sequential scan support.
+ *
+ * The tree can be scanned sequentially, starting from either end of the
+ * tree or from any specific key. A scan request before any scanning is
+ * done is initialized as starting from the least node.
+ */
+
+/*
+ * __bt_seq --
+ * Btree sequential scan interface.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key for positioning and return value
+ * data: data return value
+ * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG e;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /*
+ * If scan unitialized as yet, or starting at a specific record, set
+ * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin
+ * the page the cursor references if they're successful.
+ */
+ switch (flags) {
+ case R_NEXT:
+ case R_PREV:
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ status = __bt_seqadv(t, &e, flags);
+ break;
+ }
+ /* FALLTHROUGH */
+ case R_FIRST:
+ case R_LAST:
+ case R_CURSOR:
+ status = __bt_seqset(t, &e, key, flags);
+ break;
+ default:
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (status == RET_SUCCESS) {
+ __bt_setcur(t, e.page->pgno, e.index);
+
+ status =
+ __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
+
+ /*
+ * If the user is doing concurrent access, we copied the
+ * key/data, toss the page.
+ */
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e.page, 0);
+ else
+ t->bt_pinned = e.page;
+ }
+ return (status);
+}
+
+/*
+ * __bt_seqset --
+ * Set the sequential scan to a specific key.
+ *
+ * Parameters:
+ * t: tree
+ * ep: storage for returned key
+ * key: key for initial scan position
+ * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
+ *
+ * Side effects:
+ * Pins the page the cursor references.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags)
+{
+ PAGE *h;
+ pgno_t pg;
+ int exact;
+
+ /*
+ * Find the first, last or specific key in the tree and point the
+ * cursor at it. The cursor may not be moved until a new key has
+ * been found.
+ */
+ switch (flags) {
+ case R_CURSOR: /* Keyed scan. */
+ /*
+ * Find the first instance of the key or the smallest key
+ * which is greater than or equal to the specified key.
+ */
+ if (key->data == NULL || key->size == 0) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+ return (__bt_first(t, key, ep, &exact));
+ case R_FIRST: /* First record. */
+ case R_NEXT:
+ /* Walk down the left-hand side of the tree. */
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Check for an empty tree. */
+ if (NEXTINDEX(h) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ }
+
+ if (h->flags & (P_BLEAF | P_RLEAF))
+ break;
+ pg = GETBINTERNAL(h, 0)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ }
+ ep->page = h;
+ ep->index = 0;
+ break;
+ case R_LAST: /* Last record. */
+ case R_PREV:
+ /* Walk down the right-hand side of the tree. */
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Check for an empty tree. */
+ if (NEXTINDEX(h) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ }
+
+ if (h->flags & (P_BLEAF | P_RLEAF))
+ break;
+ pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ }
+
+ ep->page = h;
+ ep->index = NEXTINDEX(h) - 1;
+ break;
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_seqadvance --
+ * Advance the sequential scan.
+ *
+ * Parameters:
+ * t: tree
+ * flags: R_NEXT, R_PREV
+ *
+ * Side effects:
+ * Pins the page the new key/data record is on.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqadv(BTREE *t, EPG *ep, int flags)
+{
+ CURSOR *c;
+ PAGE *h;
+ indx_t idx;
+ pgno_t pg;
+ int exact;
+
+ /*
+ * There are a couple of states that we can be in. The cursor has
+ * been initialized by the time we get here, but that's all we know.
+ */
+ c = &t->bt_cursor;
+
+ /*
+ * The cursor was deleted where there weren't any duplicate records,
+ * so the key was saved. Find out where that key would go in the
+ * current tree. It doesn't matter if the returned key is an exact
+ * match or not -- if it's an exact match, the record was added after
+ * the delete so we can just return it. If not, as long as there's
+ * a record there, return it.
+ */
+ if (F_ISSET(c, CURS_ACQUIRE))
+ return (__bt_first(t, &c->key, ep, &exact));
+
+ /* Get the page referenced by the cursor. */
+ if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+ return (RET_ERROR);
+
+ /*
+ * Find the next/previous record in the tree and point the cursor at
+ * it. The cursor may not be moved until a new key has been found.
+ */
+ switch (flags) {
+ case R_NEXT: /* Next record. */
+ /*
+ * The cursor was deleted in duplicate records, and moved
+ * forward to a record that has yet to be returned. Clear
+ * that flag, and return the record.
+ */
+ if (F_ISSET(c, CURS_AFTER))
+ goto usecurrent;
+ idx = c->pg.index;
+ if (++idx == NEXTINDEX(h)) {
+ pg = h->nextpg;
+ mpool_put(t->bt_mp, h, 0);
+ if (pg == P_INVALID)
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ idx = 0;
+ }
+ break;
+ case R_PREV: /* Previous record. */
+ /*
+ * The cursor was deleted in duplicate records, and moved
+ * backward to a record that has yet to be returned. Clear
+ * that flag, and return the record.
+ */
+ if (F_ISSET(c, CURS_BEFORE)) {
+usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE);
+ ep->page = h;
+ ep->index = c->pg.index;
+ return (RET_SUCCESS);
+ }
+ idx = c->pg.index;
+ if (idx == 0) {
+ pg = h->prevpg;
+ mpool_put(t->bt_mp, h, 0);
+ if (pg == P_INVALID)
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ idx = NEXTINDEX(h) - 1;
+ } else
+ --idx;
+ break;
+ }
+
+ ep->page = h;
+ ep->index = idx;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_first --
+ * Find the first entry.
+ *
+ * Parameters:
+ * t: the tree
+ * key: the key
+ * erval: return EPG
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * The first entry in the tree greater than or equal to key,
+ * or RET_SPECIAL if no such key exists.
+ */
+static int
+__bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp)
+{
+ PAGE *h;
+ EPG *ep, save;
+ pgno_t pg;
+
+ /*
+ * Find any matching record; __bt_search pins the page.
+ *
+ * If it's an exact match and duplicates are possible, walk backwards
+ * in the tree until we find the first one. Otherwise, make sure it's
+ * a valid key (__bt_search may return an index just past the end of a
+ * page) and return it.
+ */
+ if ((ep = __bt_search(t, key, exactp)) == NULL)
+ return (0);
+ if (*exactp) {
+ if (F_ISSET(t, B_NODUPS)) {
+ *erval = *ep;
+ return (RET_SUCCESS);
+ }
+
+ /*
+ * Walk backwards, as long as the entry matches and there are
+ * keys left in the tree. Save a copy of each match in case
+ * we go too far.
+ */
+ save = *ep;
+ h = ep->page;
+ do {
+ if (save.page->pgno != ep->page->pgno) {
+ mpool_put(t->bt_mp, save.page, 0);
+ save = *ep;
+ } else
+ save.index = ep->index;
+
+ /*
+ * Don't unpin the page the last (or original) match
+ * was on, but make sure it's unpinned if an error
+ * occurs.
+ */
+ if (ep->index == 0) {
+ if (h->prevpg == P_INVALID)
+ break;
+ if (h->pgno != save.page->pgno)
+ mpool_put(t->bt_mp, h, 0);
+ if ((h = mpool_get(t->bt_mp,
+ h->prevpg, 0)) == NULL) {
+ if (h->pgno == save.page->pgno)
+ mpool_put(t->bt_mp,
+ save.page, 0);
+ return (RET_ERROR);
+ }
+ ep->page = h;
+ ep->index = NEXTINDEX(h);
+ }
+ --ep->index;
+ } while (__bt_cmp(t, key, ep) == 0);
+
+ /*
+ * Reach here with the last page that was looked at pinned,
+ * which may or may not be the same as the last (or original)
+ * match page. If it's not useful, release it.
+ */
+ if (h->pgno != save.page->pgno)
+ mpool_put(t->bt_mp, h, 0);
+
+ *erval = save;
+ return (RET_SUCCESS);
+ }
+
+ /* If at the end of a page, find the next entry. */
+ if (ep->index == NEXTINDEX(ep->page)) {
+ h = ep->page;
+ pg = h->nextpg;
+ mpool_put(t->bt_mp, h, 0);
+ if (pg == P_INVALID)
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ ep->index = 0;
+ ep->page = h;
+ }
+ *erval = *ep;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_setcur --
+ * Set the cursor to an entry in the tree.
+ *
+ * Parameters:
+ * t: the tree
+ * pgno: page number
+ * idx: page index
+ */
+void
+__bt_setcur(BTREE *t, pgno_t pgno, u_int idx)
+{
+ /* Lose any already deleted key. */
+ if (t->bt_cursor.key.data != NULL) {
+ free(t->bt_cursor.key.data);
+ t->bt_cursor.key.size = 0;
+ t->bt_cursor.key.data = NULL;
+ }
+ F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+
+ /* Update the cursor. */
+ t->bt_cursor.pg.pgno = pgno;
+ t->bt_cursor.pg.index = idx;
+ F_SET(&t->bt_cursor, CURS_INIT);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_split.c b/freebsd/lib/libc/db/btree/bt_split.c
new file mode 100644
index 00000000..e47de805
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_split.c
@@ -0,0 +1,798 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_split.c 8.10 (Berkeley) 1/9/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int bt_broot(BTREE *, PAGE *, PAGE *, PAGE *);
+static PAGE *bt_page(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static int bt_preserve(BTREE *, pgno_t);
+static PAGE *bt_psplit(BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
+static PAGE *bt_root(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static int bt_rroot(BTREE *, PAGE *, PAGE *, PAGE *);
+static recno_t rec_total(PAGE *);
+
+#ifdef STATISTICS
+u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
+#endif
+
+/*
+ * __BT_SPLIT -- Split the tree.
+ *
+ * Parameters:
+ * t: tree
+ * sp: page to split
+ * key: key to insert
+ * data: data to insert
+ * flags: BIGKEY/BIGDATA flags
+ * ilen: insert length
+ * skip: index to leave open
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, int flags,
+ size_t ilen, u_int32_t argskip)
+{
+ BINTERNAL *bi;
+ BLEAF *bl, *tbl;
+ DBT a, b;
+ EPGNO *parent;
+ PAGE *h, *l, *r, *lchild, *rchild;
+ indx_t nxtindex;
+ u_int16_t skip;
+ u_int32_t n, nbytes, nksize;
+ int parentsplit;
+ char *dest;
+
+ /*
+ * Split the page into two pages, l and r. The split routines return
+ * a pointer to the page into which the key should be inserted and with
+ * skip set to the offset which should be used. Additionally, l and r
+ * are pinned.
+ */
+ skip = argskip;
+ h = sp->pgno == P_ROOT ?
+ bt_root(t, sp, &l, &r, &skip, ilen) :
+ bt_page(t, sp, &l, &r, &skip, ilen);
+ if (h == NULL)
+ return (RET_ERROR);
+
+ /*
+ * Insert the new key/data pair into the leaf page. (Key inserts
+ * always cause a leaf page to split first.)
+ */
+ h->linp[skip] = h->upper -= ilen;
+ dest = (char *)h + h->upper;
+ if (F_ISSET(t, R_RECNO))
+ WR_RLEAF(dest, data, flags)
+ else
+ WR_BLEAF(dest, key, data, flags)
+
+ /* If the root page was split, make it look right. */
+ if (sp->pgno == P_ROOT &&
+ (F_ISSET(t, R_RECNO) ?
+ bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+ goto err2;
+
+ /*
+ * Now we walk the parent page stack -- a LIFO stack of the pages that
+ * were traversed when we searched for the page that split. Each stack
+ * entry is a page number and a page index offset. The offset is for
+ * the page traversed on the search. We've just split a page, so we
+ * have to insert a new key into the parent page.
+ *
+ * If the insert into the parent page causes it to split, may have to
+ * continue splitting all the way up the tree. We stop if the root
+ * splits or the page inserted into didn't have to split to hold the
+ * new key. Some algorithms replace the key for the old page as well
+ * as the new page. We don't, as there's no reason to believe that the
+ * first key on the old page is any better than the key we have, and,
+ * in the case of a key being placed at index 0 causing the split, the
+ * key is unavailable.
+ *
+ * There are a maximum of 5 pages pinned at any time. We keep the left
+ * and right pages pinned while working on the parent. The 5 are the
+ * two children, left parent and right parent (when the parent splits)
+ * and the root page or the overflow key page when calling bt_preserve.
+ * This code must make sure that all pins are released other than the
+ * root page or overflow page which is unlocked elsewhere.
+ */
+ while ((parent = BT_POP(t)) != NULL) {
+ lchild = l;
+ rchild = r;
+
+ /* Get the parent page. */
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ goto err2;
+
+ /*
+ * The new key goes ONE AFTER the index, because the split
+ * was to the right.
+ */
+ skip = parent->index + 1;
+
+ /*
+ * Calculate the space needed on the parent page.
+ *
+ * Prefix trees: space hack when inserting into BINTERNAL
+ * pages. Retain only what's needed to distinguish between
+ * the new entry and the LAST entry on the page to its left.
+ * If the keys compare equal, retain the entire key. Note,
+ * we don't touch overflow keys, and the entire key must be
+ * retained for the next-to-left most key on the leftmost
+ * page of each level, or the search will fail. Applicable
+ * ONLY to internal pages that have leaf pages as children.
+ * Further reduction of the key between pairs of internal
+ * pages loses too much information.
+ */
+ switch (rchild->flags & P_TYPE) {
+ case P_BINTERNAL:
+ bi = GETBINTERNAL(rchild, 0);
+ nbytes = NBINTERNAL(bi->ksize);
+ break;
+ case P_BLEAF:
+ bl = GETBLEAF(rchild, 0);
+ nbytes = NBINTERNAL(bl->ksize);
+ if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
+ (h->prevpg != P_INVALID || skip > 1)) {
+ tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
+ a.size = tbl->ksize;
+ a.data = tbl->bytes;
+ b.size = bl->ksize;
+ b.data = bl->bytes;
+ nksize = t->bt_pfx(&a, &b);
+ n = NBINTERNAL(nksize);
+ if (n < nbytes) {
+#ifdef STATISTICS
+ bt_pfxsaved += nbytes - n;
+#endif
+ nbytes = n;
+ } else
+ nksize = 0;
+ } else
+ nksize = 0;
+ break;
+ case P_RINTERNAL:
+ case P_RLEAF:
+ nbytes = NRINTERNAL;
+ break;
+ default:
+ abort();
+ }
+
+ /* Split the parent page if necessary or shift the indices. */
+ 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) :
+ bt_page(t, h, &l, &r, &skip, nbytes);
+ if (h == NULL)
+ goto err1;
+ parentsplit = 1;
+ } else {
+ if (skip < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + skip + 1, h->linp + skip,
+ (nxtindex - skip) * sizeof(indx_t));
+ h->lower += sizeof(indx_t);
+ parentsplit = 0;
+ }
+
+ /* Insert the key into the parent page. */
+ switch (rchild->flags & P_TYPE) {
+ case P_BINTERNAL:
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ memmove(dest, bi, nbytes);
+ ((BINTERNAL *)dest)->pgno = rchild->pgno;
+ break;
+ case P_BLEAF:
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
+ rchild->pgno, bl->flags & P_BIGKEY);
+ memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
+ if (bl->flags & P_BIGKEY &&
+ bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+ goto err1;
+ break;
+ case P_RINTERNAL:
+ /*
+ * Update the left page count. If split
+ * added at index 0, fix the correct page.
+ */
+ if (skip > 0)
+ dest = (char *)h + h->linp[skip - 1];
+ else
+ dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+ ((RINTERNAL *)dest)->nrecs = rec_total(lchild);
+ ((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+ /* Update the right page count. */
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ ((RINTERNAL *)dest)->nrecs = rec_total(rchild);
+ ((RINTERNAL *)dest)->pgno = rchild->pgno;
+ break;
+ case P_RLEAF:
+ /*
+ * Update the left page count. If split
+ * added at index 0, fix the correct page.
+ */
+ if (skip > 0)
+ dest = (char *)h + h->linp[skip - 1];
+ else
+ dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+ ((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
+ ((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+ /* Update the right page count. */
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ ((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
+ ((RINTERNAL *)dest)->pgno = rchild->pgno;
+ break;
+ default:
+ abort();
+ }
+
+ /* Unpin the held pages. */
+ if (!parentsplit) {
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ }
+
+ /* If the root page was split, make it look right. */
+ if (sp->pgno == P_ROOT &&
+ (F_ISSET(t, R_RECNO) ?
+ bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+ goto err1;
+
+ mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+ }
+
+ /* Unpin the held pages. */
+ mpool_put(t->bt_mp, l, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, r, MPOOL_DIRTY);
+
+ /* Clear any pages left on the stack. */
+ return (RET_SUCCESS);
+
+ /*
+ * If something fails in the above loop we were already walking back
+ * up the tree and the tree is now inconsistent. Nothing much we can
+ * do about it but release any memory we're holding.
+ */
+err1: mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+
+err2: mpool_put(t->bt_mp, l, 0);
+ mpool_put(t->bt_mp, r, 0);
+ __dbpanic(t->bt_dbp);
+ return (RET_ERROR);
+}
+
+/*
+ * BT_PAGE -- Split a non-root page of a btree.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * lp: pointer to left page pointer
+ * rp: pointer to right page pointer
+ * skip: pointer to index to leave open
+ * ilen: insert length
+ *
+ * Returns:
+ * Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
+{
+ PAGE *l, *r, *tp;
+ pgno_t npg;
+
+#ifdef STATISTICS
+ ++bt_split;
+#endif
+ /* Put the new right page for the split into place. */
+ if ((r = __bt_new(t, &npg)) == NULL)
+ return (NULL);
+ r->pgno = npg;
+ r->lower = BTDATAOFF;
+ r->upper = t->bt_psize;
+ r->nextpg = h->nextpg;
+ r->prevpg = h->pgno;
+ r->flags = h->flags & P_TYPE;
+
+ /*
+ * If we're splitting the last page on a level because we're appending
+ * a key to it (skip is NEXTINDEX()), it's likely that the data is
+ * sorted. Adding an empty page on the side of the level is less work
+ * and can push the fill factor much higher than normal. If we're
+ * wrong it's no big deal, we'll just do the split the right way next
+ * time. It may look like it's equally easy to do a similar hack for
+ * reverse sorted data, that is, split the tree left, but it's not.
+ * Don't even try.
+ */
+ if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
+#ifdef STATISTICS
+ ++bt_sortsplit;
+#endif
+ h->nextpg = r->pgno;
+ r->lower = BTDATAOFF + sizeof(indx_t);
+ *skip = 0;
+ *lp = h;
+ *rp = r;
+ return (r);
+ }
+
+ /* Put the new left page for the split into place. */
+ if ((l = (PAGE *)calloc(1, t->bt_psize)) == NULL) {
+ mpool_put(t->bt_mp, r, 0);
+ return (NULL);
+ }
+ l->pgno = h->pgno;
+ l->nextpg = r->pgno;
+ l->prevpg = h->prevpg;
+ l->lower = BTDATAOFF;
+ l->upper = t->bt_psize;
+ l->flags = h->flags & P_TYPE;
+
+ /* Fix up the previous pointer of the page after the split page. */
+ if (h->nextpg != P_INVALID) {
+ if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
+ free(l);
+ /* XXX mpool_free(t->bt_mp, r->pgno); */
+ return (NULL);
+ }
+ tp->prevpg = r->pgno;
+ mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
+ }
+
+ /*
+ * Split right. The key/data pairs aren't sorted in the btree page so
+ * it's simpler to copy the data from the split page onto two new pages
+ * instead of copying half the data to the right page and compacting
+ * the left page in place. Since the left page can't change, we have
+ * to swap the original and the allocated left page after the split.
+ */
+ tp = bt_psplit(t, h, l, r, skip, ilen);
+
+ /* Move the new left page onto the old left page. */
+ memmove(h, l, t->bt_psize);
+ if (tp == l)
+ tp = h;
+ free(l);
+
+ *lp = h;
+ *rp = r;
+ return (tp);
+}
+
+/*
+ * BT_ROOT -- Split the root page of a btree.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * lp: pointer to left page pointer
+ * rp: pointer to right page pointer
+ * skip: pointer to index to leave open
+ * ilen: insert length
+ *
+ * Returns:
+ * Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_root(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
+{
+ PAGE *l, *r, *tp;
+ pgno_t lnpg, rnpg;
+
+#ifdef STATISTICS
+ ++bt_split;
+ ++bt_rootsplit;
+#endif
+ /* Put the new left and right pages for the split into place. */
+ if ((l = __bt_new(t, &lnpg)) == NULL ||
+ (r = __bt_new(t, &rnpg)) == NULL)
+ return (NULL);
+ l->pgno = lnpg;
+ r->pgno = rnpg;
+ l->nextpg = r->pgno;
+ r->prevpg = l->pgno;
+ l->prevpg = r->nextpg = P_INVALID;
+ l->lower = r->lower = BTDATAOFF;
+ l->upper = r->upper = t->bt_psize;
+ l->flags = r->flags = h->flags & P_TYPE;
+
+ /* Split the root page. */
+ tp = bt_psplit(t, h, l, r, skip, ilen);
+
+ *lp = l;
+ *rp = r;
+ return (tp);
+}
+
+/*
+ * BT_RROOT -- Fix up the recno root page after it has been split.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * l: left page
+ * r: right page
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_rroot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
+{
+ char *dest;
+
+ /* Insert the left and right keys, set the header information. */
+ h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
+ dest = (char *)h + h->upper;
+ WR_RINTERNAL(dest,
+ l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
+
+ h->linp[1] = h->upper -= NRINTERNAL;
+ dest = (char *)h + h->upper;
+ WR_RINTERNAL(dest,
+ r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
+
+ h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+ /* Unpin the root page, set to recno internal page. */
+ h->flags &= ~P_TYPE;
+ h->flags |= P_RINTERNAL;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * BT_BROOT -- Fix up the btree root page after it has been split.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * l: left page
+ * r: right page
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_broot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ u_int32_t nbytes;
+ char *dest;
+
+ /*
+ * If the root page was a leaf page, change it into an internal page.
+ * We copy the key we split on (but not the key's data, in the case of
+ * a leaf page) to the new root page.
+ *
+ * The btree comparison code guarantees that the left-most key on any
+ * level of the tree is never used, so it doesn't need to be filled in.
+ */
+ nbytes = NBINTERNAL(0);
+ h->linp[0] = h->upper = t->bt_psize - nbytes;
+ dest = (char *)h + h->upper;
+ WR_BINTERNAL(dest, 0, l->pgno, 0);
+
+ switch (h->flags & P_TYPE) {
+ case P_BLEAF:
+ bl = GETBLEAF(r, 0);
+ nbytes = NBINTERNAL(bl->ksize);
+ h->linp[1] = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
+ memmove(dest, bl->bytes, bl->ksize);
+
+ /*
+ * If the key is on an overflow page, mark the overflow chain
+ * so it isn't deleted when the leaf copy of the key is deleted.
+ */
+ if (bl->flags & P_BIGKEY &&
+ bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+ return (RET_ERROR);
+ break;
+ case P_BINTERNAL:
+ bi = GETBINTERNAL(r, 0);
+ nbytes = NBINTERNAL(bi->ksize);
+ h->linp[1] = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ memmove(dest, bi, nbytes);
+ ((BINTERNAL *)dest)->pgno = r->pgno;
+ break;
+ default:
+ abort();
+ }
+
+ /* There are two keys on the page. */
+ h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+ /* Unpin the root page, set to btree internal page. */
+ h->flags &= ~P_TYPE;
+ h->flags |= P_BINTERNAL;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * BT_PSPLIT -- Do the real work of splitting the page.
+ *
+ * Parameters:
+ * t: tree
+ * h: page to be split
+ * l: page to put lower half of data
+ * r: page to put upper half of data
+ * pskip: pointer to index to leave open
+ * ilen: insert length
+ *
+ * Returns:
+ * Pointer to page in which to insert.
+ */
+static PAGE *
+bt_psplit(BTREE *t, PAGE *h, PAGE *l, PAGE *r, indx_t *pskip, size_t ilen)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ CURSOR *c;
+ RLEAF *rl;
+ PAGE *rval;
+ void *src;
+ indx_t full, half, nxt, off, skip, top, used;
+ u_int32_t nbytes;
+ int bigkeycnt, isbigkey;
+
+ /*
+ * Split the data to the left and right pages. Leave the skip index
+ * open. Additionally, make some effort not to split on an overflow
+ * key. This makes internal page processing faster and can save
+ * space as overflow keys used by internal pages are never deleted.
+ */
+ bigkeycnt = 0;
+ skip = *pskip;
+ full = t->bt_psize - BTDATAOFF;
+ half = full / 2;
+ used = 0;
+ for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
+ if (skip == off) {
+ nbytes = ilen;
+ isbigkey = 0; /* XXX: not really known. */
+ } else
+ switch (h->flags & P_TYPE) {
+ case P_BINTERNAL:
+ src = bi = GETBINTERNAL(h, nxt);
+ nbytes = NBINTERNAL(bi->ksize);
+ isbigkey = bi->flags & P_BIGKEY;
+ break;
+ case P_BLEAF:
+ src = bl = GETBLEAF(h, nxt);
+ nbytes = NBLEAF(bl);
+ isbigkey = bl->flags & P_BIGKEY;
+ break;
+ case P_RINTERNAL:
+ src = GETRINTERNAL(h, nxt);
+ nbytes = NRINTERNAL;
+ isbigkey = 0;
+ break;
+ case P_RLEAF:
+ src = rl = GETRLEAF(h, nxt);
+ nbytes = NRLEAF(rl);
+ isbigkey = 0;
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * If the key/data pairs are substantial fractions of the max
+ * possible size for the page, it's possible to get situations
+ * where we decide to try and copy too much onto the left page.
+ * Make sure that doesn't happen.
+ */
+ if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) ||
+ nxt == top - 1) {
+ --off;
+ break;
+ }
+
+ /* Copy the key/data pair, if not the skipped index. */
+ if (skip != off) {
+ ++nxt;
+
+ l->linp[off] = l->upper -= nbytes;
+ memmove((char *)l + l->upper, src, nbytes);
+ }
+
+ used += nbytes + sizeof(indx_t);
+ if (used >= half) {
+ if (!isbigkey || bigkeycnt == 3)
+ break;
+ else
+ ++bigkeycnt;
+ }
+ }
+
+ /*
+ * Off is the last offset that's valid for the left page.
+ * Nxt is the first offset to be placed on the right page.
+ */
+ l->lower += (off + 1) * sizeof(indx_t);
+
+ /*
+ * If splitting the page that the cursor was on, the cursor has to be
+ * adjusted to point to the same record as before the split. If the
+ * cursor is at or past the skipped slot, the cursor is incremented by
+ * one. If the cursor is on the right page, it is decremented by the
+ * number of records split to the left page.
+ */
+ c = &t->bt_cursor;
+ if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) {
+ if (c->pg.index >= skip)
+ ++c->pg.index;
+ if (c->pg.index < nxt) /* Left page. */
+ c->pg.pgno = l->pgno;
+ else { /* Right page. */
+ c->pg.pgno = r->pgno;
+ c->pg.index -= nxt;
+ }
+ }
+
+ /*
+ * If the skipped index was on the left page, just return that page.
+ * Otherwise, adjust the skip index to reflect the new position on
+ * the right page.
+ */
+ if (skip <= off) {
+ skip = MAX_PAGE_OFFSET;
+ rval = l;
+ } else {
+ rval = r;
+ *pskip -= nxt;
+ }
+
+ for (off = 0; nxt < top; ++off) {
+ if (skip == nxt) {
+ ++off;
+ skip = MAX_PAGE_OFFSET;
+ }
+ switch (h->flags & P_TYPE) {
+ case P_BINTERNAL:
+ src = bi = GETBINTERNAL(h, nxt);
+ nbytes = NBINTERNAL(bi->ksize);
+ break;
+ case P_BLEAF:
+ src = bl = GETBLEAF(h, nxt);
+ nbytes = NBLEAF(bl);
+ break;
+ case P_RINTERNAL:
+ src = GETRINTERNAL(h, nxt);
+ nbytes = NRINTERNAL;
+ break;
+ case P_RLEAF:
+ src = rl = GETRLEAF(h, nxt);
+ nbytes = NRLEAF(rl);
+ break;
+ default:
+ abort();
+ }
+ ++nxt;
+ r->linp[off] = r->upper -= nbytes;
+ memmove((char *)r + r->upper, src, nbytes);
+ }
+ r->lower += off * sizeof(indx_t);
+
+ /* If the key is being appended to the page, adjust the index. */
+ if (skip == top)
+ r->lower += sizeof(indx_t);
+
+ return (rval);
+}
+
+/*
+ * BT_PRESERVE -- Mark a chain of pages as used by an internal node.
+ *
+ * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
+ * record that references them gets deleted. Chains pointed to by internal
+ * pages never get deleted. This routine marks a chain as pointed to by an
+ * internal page.
+ *
+ * Parameters:
+ * t: tree
+ * pg: page number of first page in the chain.
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+static int
+bt_preserve(BTREE *t, pgno_t pg)
+{
+ PAGE *h;
+
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ h->flags |= P_PRESERVE;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
+
+/*
+ * REC_TOTAL -- Return the number of recno entries below a page.
+ *
+ * Parameters:
+ * h: page
+ *
+ * Returns:
+ * The number of recno entries below a page.
+ *
+ * XXX
+ * These values could be set by the bt_psplit routine. The problem is that the
+ * entry has to be popped off of the stack etc. or the values have to be passed
+ * all the way back to bt_split/bt_rroot and it's not very clean.
+ */
+static recno_t
+rec_total(PAGE *h)
+{
+ recno_t recs;
+ indx_t nxt, top;
+
+ for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
+ recs += GETRINTERNAL(h, nxt)->nrecs;
+ return (recs);
+}
diff --git a/freebsd/lib/libc/db/btree/bt_utils.c b/freebsd/lib/libc/db/btree/bt_utils.c
new file mode 100644
index 00000000..fbfff3ac
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/bt_utils.c
@@ -0,0 +1,248 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_ret --
+ * Build return key/data pair.
+ *
+ * Parameters:
+ * t: tree
+ * e: key/data pair to be returned
+ * key: user's key structure (NULL if not to be filled in)
+ * rkey: memory area to hold key
+ * data: user's data structure (NULL if not to be filled in)
+ * rdata: memory area to hold data
+ * copy: always copy the key/data item
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_ret(BTREE *t, EPG *e, DBT *key, DBT *rkey, DBT *data, DBT *rdata, int copy)
+{
+ BLEAF *bl;
+ void *p;
+
+ bl = GETBLEAF(e->page, e->index);
+
+ /*
+ * We must copy big keys/data to make them contigous. Otherwise,
+ * leave the page pinned and don't copy unless the user specified
+ * concurrent access.
+ */
+ if (key == NULL)
+ goto dataonly;
+
+ if (bl->flags & P_BIGKEY) {
+ if (__ovfl_get(t, bl->bytes,
+ &key->size, &rkey->data, &rkey->size))
+ return (RET_ERROR);
+ key->data = rkey->data;
+ } else if (copy || F_ISSET(t, B_DB_LOCK)) {
+ if (bl->ksize > rkey->size) {
+ p = realloc(rkey->data, bl->ksize);
+ if (p == NULL)
+ return (RET_ERROR);
+ rkey->data = p;
+ rkey->size = bl->ksize;
+ }
+ memmove(rkey->data, bl->bytes, bl->ksize);
+ key->size = bl->ksize;
+ key->data = rkey->data;
+ } else {
+ key->size = bl->ksize;
+ key->data = bl->bytes;
+ }
+
+dataonly:
+ if (data == NULL)
+ return (RET_SUCCESS);
+
+ if (bl->flags & P_BIGDATA) {
+ if (__ovfl_get(t, bl->bytes + bl->ksize,
+ &data->size, &rdata->data, &rdata->size))
+ return (RET_ERROR);
+ data->data = rdata->data;
+ } else if (copy || F_ISSET(t, B_DB_LOCK)) {
+ /* Use +1 in case the first record retrieved is 0 length. */
+ if (bl->dsize + 1 > rdata->size) {
+ p = realloc(rdata->data, bl->dsize + 1);
+ if (p == NULL)
+ return (RET_ERROR);
+ rdata->data = p;
+ rdata->size = bl->dsize + 1;
+ }
+ memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);
+ data->size = bl->dsize;
+ data->data = rdata->data;
+ } else {
+ data->size = bl->dsize;
+ data->data = bl->bytes + bl->ksize;
+ }
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * __BT_CMP -- Compare a key to a given record.
+ *
+ * Parameters:
+ * t: tree
+ * k1: DBT pointer of first arg to comparison
+ * e: pointer to EPG for comparison
+ *
+ * Returns:
+ * < 0 if k1 is < record
+ * = 0 if k1 is = record
+ * > 0 if k1 is > record
+ */
+int
+__bt_cmp(BTREE *t, const DBT *k1, EPG *e)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ DBT k2;
+ PAGE *h;
+ void *bigkey;
+
+ /*
+ * The left-most key on internal pages, at any level of the tree, is
+ * guaranteed by the following code to be less than any user key.
+ * This saves us from having to update the leftmost key on an internal
+ * page when the user inserts a new key in the tree smaller than
+ * anything we've yet seen.
+ */
+ h = e->page;
+ if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
+ return (1);
+
+ bigkey = NULL;
+ if (h->flags & P_BLEAF) {
+ bl = GETBLEAF(h, e->index);
+ if (bl->flags & P_BIGKEY)
+ bigkey = bl->bytes;
+ else {
+ k2.data = bl->bytes;
+ k2.size = bl->ksize;
+ }
+ } else {
+ bi = GETBINTERNAL(h, e->index);
+ if (bi->flags & P_BIGKEY)
+ bigkey = bi->bytes;
+ else {
+ k2.data = bi->bytes;
+ k2.size = bi->ksize;
+ }
+ }
+
+ if (bigkey) {
+ if (__ovfl_get(t, bigkey,
+ &k2.size, &t->bt_rdata.data, &t->bt_rdata.size))
+ return (RET_ERROR);
+ k2.data = t->bt_rdata.data;
+ }
+ return ((*t->bt_cmp)(k1, &k2));
+}
+
+/*
+ * __BT_DEFCMP -- Default comparison routine.
+ *
+ * Parameters:
+ * a: DBT #1
+ * b: DBT #2
+ *
+ * Returns:
+ * < 0 if a is < b
+ * = 0 if a is = b
+ * > 0 if a is > b
+ */
+int
+__bt_defcmp(const DBT *a, const DBT *b)
+{
+ size_t len;
+ u_char *p1, *p2;
+
+ /*
+ * XXX
+ * If a size_t doesn't fit in an int, this routine can lose.
+ * What we need is an integral type which is guaranteed to be
+ * larger than a size_t, and there is no such thing.
+ */
+ len = MIN(a->size, b->size);
+ for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
+ if (*p1 != *p2)
+ return ((int)*p1 - (int)*p2);
+ return ((int)a->size - (int)b->size);
+}
+
+/*
+ * __BT_DEFPFX -- Default prefix routine.
+ *
+ * Parameters:
+ * a: DBT #1
+ * b: DBT #2
+ *
+ * Returns:
+ * Number of bytes needed to distinguish b from a.
+ */
+size_t
+__bt_defpfx(const DBT *a, const DBT *b)
+{
+ u_char *p1, *p2;
+ size_t cnt, len;
+
+ cnt = 1;
+ len = MIN(a->size, b->size);
+ for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
+ if (*p1 != *p2)
+ return (cnt);
+
+ /* a->size must be <= b->size, or they wouldn't be in this order. */
+ return (a->size < b->size ? a->size + 1 : a->size);
+}
diff --git a/freebsd/lib/libc/db/btree/btree.h b/freebsd/lib/libc/db/btree/btree.h
new file mode 100644
index 00000000..a1766dc3
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/btree.h
@@ -0,0 +1,380 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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.
+ *
+ * @(#)btree.h 8.11 (Berkeley) 8/17/94
+ * $FreeBSD$
+ */
+
+/* Macros to set/clear/test flags. */
+#define F_SET(p, f) (p)->flags |= (f)
+#define F_CLR(p, f) (p)->flags &= ~(f)
+#define F_ISSET(p, f) ((p)->flags & (f))
+
+#include <mpool.h>
+
+#define DEFMINKEYPAGE (2) /* Minimum keys per page */
+#define MINCACHE (5) /* Minimum cached pages */
+#define MINPSIZE (512) /* Minimum page size */
+
+/*
+ * Page 0 of a btree file contains a copy of the meta-data. This page is also
+ * used as an out-of-band page, i.e. page pointers that point to nowhere point
+ * to page 0. Page 1 is the root of the btree.
+ */
+#define P_INVALID 0 /* Invalid tree page number. */
+#define P_META 0 /* Tree metadata page number. */
+#define P_ROOT 1 /* Tree root page number. */
+
+/*
+ * There are five page layouts in the btree: btree internal pages (BINTERNAL),
+ * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages
+ * (RLEAF) and overflow pages. All five page types have a page header (PAGE).
+ * This implementation requires that values within structures NOT be padded.
+ * (ANSI C permits random padding.) If your compiler pads randomly you'll have
+ * to do some work to get this package to run.
+ */
+typedef struct _page {
+ pgno_t pgno; /* this page's page number */
+ pgno_t prevpg; /* left sibling */
+ pgno_t nextpg; /* right sibling */
+
+#define P_BINTERNAL 0x01 /* btree internal page */
+#define P_BLEAF 0x02 /* leaf page */
+#define P_OVERFLOW 0x04 /* overflow page */
+#define P_RINTERNAL 0x08 /* recno internal page */
+#define P_RLEAF 0x10 /* leaf page */
+#define P_TYPE 0x1f /* type mask */
+#define P_PRESERVE 0x20 /* never delete this chain of pages */
+ u_int32_t flags;
+
+ indx_t lower; /* lower bound of free space on page */
+ indx_t upper; /* upper bound of free space on page */
+ indx_t linp[1]; /* indx_t-aligned VAR. LENGTH DATA */
+} PAGE;
+
+/* First and next index. */
+#define BTDATAOFF \
+ (sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) + \
+ sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t))
+#define NEXTINDEX(p) (((p)->lower - BTDATAOFF) / sizeof(indx_t))
+
+/*
+ * For pages other than overflow pages, there is an array of offsets into the
+ * rest of the page immediately following the page header. Each offset is to
+ * an item which is unique to the type of page. The h_lower offset is just
+ * past the last filled-in index. The h_upper offset is the first item on the
+ * page. Offsets are from the beginning of the page.
+ *
+ * If an item is too big to store on a single page, a flag is set and the item
+ * is a { page, size } pair such that the page is the first page of an overflow
+ * chain with size bytes of item. Overflow pages are simply bytes without any
+ * external structure.
+ *
+ * The page number and size fields in the items are pgno_t-aligned so they can
+ * be manipulated without copying. (This presumes that 32 bit items can be
+ * manipulated on this system.)
+ */
+#define LALIGN(n) (((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1))
+#define NOVFLSIZE (sizeof(pgno_t) + sizeof(u_int32_t))
+
+/*
+ * For the btree internal pages, the item is a key. BINTERNALs are {key, pgno}
+ * pairs, such that the key compares less than or equal to all of the records
+ * on that page. For a tree without duplicate keys, an internal page with two
+ * consecutive keys, a and b, will have all records greater than or equal to a
+ * and less than b stored on the page associated with a. Duplicate keys are
+ * somewhat special and can cause duplicate internal and leaf page records and
+ * some minor modifications of the above rule.
+ */
+typedef struct _binternal {
+ u_int32_t ksize; /* key size */
+ pgno_t pgno; /* page number stored on */
+#define P_BIGDATA 0x01 /* overflow data */
+#define P_BIGKEY 0x02 /* overflow key */
+ u_char flags;
+ char bytes[1]; /* data */
+} BINTERNAL;
+
+/* Get the page's BINTERNAL structure at index indx. */
+#define GETBINTERNAL(pg, indx) \
+ ((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBINTERNAL(len) \
+ LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len))
+
+/* Copy a BINTERNAL entry to the page. */
+#define WR_BINTERNAL(p, size, pgno, flags) { \
+ *(u_int32_t *)p = size; \
+ p += sizeof(u_int32_t); \
+ *(pgno_t *)p = pgno; \
+ p += sizeof(pgno_t); \
+ *(u_char *)p = flags; \
+ p += sizeof(u_char); \
+}
+
+/*
+ * For the recno internal pages, the item is a page number with the number of
+ * keys found on that page and below.
+ */
+typedef struct _rinternal {
+ recno_t nrecs; /* number of records */
+ pgno_t pgno; /* page number stored below */
+} RINTERNAL;
+
+/* Get the page's RINTERNAL structure at index indx. */
+#define GETRINTERNAL(pg, indx) \
+ ((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRINTERNAL \
+ LALIGN(sizeof(recno_t) + sizeof(pgno_t))
+
+/* Copy a RINTERAL entry to the page. */
+#define WR_RINTERNAL(p, nrecs, pgno) { \
+ *(recno_t *)p = nrecs; \
+ p += sizeof(recno_t); \
+ *(pgno_t *)p = pgno; \
+}
+
+/* For the btree leaf pages, the item is a key and data pair. */
+typedef struct _bleaf {
+ u_int32_t ksize; /* size of key */
+ u_int32_t dsize; /* size of data */
+ u_char flags; /* P_BIGDATA, P_BIGKEY */
+ char bytes[1]; /* data */
+} BLEAF;
+
+/* Get the page's BLEAF structure at index indx. */
+#define GETBLEAF(pg, indx) \
+ ((BLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBLEAF(p) NBLEAFDBT((p)->ksize, (p)->dsize)
+
+/* Get the number of bytes in the user's key/data pair. */
+#define NBLEAFDBT(ksize, dsize) \
+ LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) + \
+ (ksize) + (dsize))
+
+/* Copy a BLEAF entry to the page. */
+#define WR_BLEAF(p, key, data, flags) { \
+ *(u_int32_t *)p = key->size; \
+ p += sizeof(u_int32_t); \
+ *(u_int32_t *)p = data->size; \
+ p += sizeof(u_int32_t); \
+ *(u_char *)p = flags; \
+ p += sizeof(u_char); \
+ memmove(p, key->data, key->size); \
+ p += key->size; \
+ memmove(p, data->data, data->size); \
+}
+
+/* For the recno leaf pages, the item is a data entry. */
+typedef struct _rleaf {
+ u_int32_t dsize; /* size of data */
+ u_char flags; /* P_BIGDATA */
+ char bytes[1];
+} RLEAF;
+
+/* Get the page's RLEAF structure at index indx. */
+#define GETRLEAF(pg, indx) \
+ ((RLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRLEAF(p) NRLEAFDBT((p)->dsize)
+
+/* Get the number of bytes from the user's data. */
+#define NRLEAFDBT(dsize) \
+ LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize))
+
+/* Copy a RLEAF entry to the page. */
+#define WR_RLEAF(p, data, flags) { \
+ *(u_int32_t *)p = data->size; \
+ p += sizeof(u_int32_t); \
+ *(u_char *)p = flags; \
+ p += sizeof(u_char); \
+ memmove(p, data->data, data->size); \
+}
+
+/*
+ * A record in the tree is either a pointer to a page and an index in the page
+ * or a page number and an index. These structures are used as a cursor, stack
+ * entry and search returns as well as to pass records to other routines.
+ *
+ * One comment about searches. Internal page searches must find the largest
+ * record less than key in the tree so that descents work. Leaf page searches
+ * must find the smallest record greater than key so that the returned index
+ * is the record's correct position for insertion.
+ */
+typedef struct _epgno {
+ pgno_t pgno; /* the page number */
+ indx_t index; /* the index on the page */
+} EPGNO;
+
+typedef struct _epg {
+ PAGE *page; /* the (pinned) page */
+ indx_t index; /* the index on the page */
+} EPG;
+
+/*
+ * About cursors. The cursor (and the page that contained the key/data pair
+ * that it referenced) can be deleted, which makes things a bit tricky. If
+ * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set
+ * or there simply aren't any duplicates of the key) we copy the key that it
+ * referenced when it's deleted, and reacquire a new cursor key if the cursor
+ * is used again. If there are duplicates keys, we move to the next/previous
+ * key, and set a flag so that we know what happened. NOTE: if duplicate (to
+ * the cursor) keys are added to the tree during this process, it is undefined
+ * if they will be returned or not in a cursor scan.
+ *
+ * The flags determine the possible states of the cursor:
+ *
+ * CURS_INIT The cursor references *something*.
+ * CURS_ACQUIRE The cursor was deleted, and a key has been saved so that
+ * we can reacquire the right position in the tree.
+ * CURS_AFTER, CURS_BEFORE
+ * The cursor was deleted, and now references a key/data pair
+ * that has not yet been returned, either before or after the
+ * deleted key/data pair.
+ * XXX
+ * This structure is broken out so that we can eventually offer multiple
+ * cursors as part of the DB interface.
+ */
+typedef struct _cursor {
+ EPGNO pg; /* B: Saved tree reference. */
+ DBT key; /* B: Saved key, or key.data == NULL. */
+ recno_t rcursor; /* R: recno cursor (1-based) */
+
+#define CURS_ACQUIRE 0x01 /* B: Cursor needs to be reacquired. */
+#define CURS_AFTER 0x02 /* B: Unreturned cursor after key. */
+#define CURS_BEFORE 0x04 /* B: Unreturned cursor before key. */
+#define CURS_INIT 0x08 /* RB: Cursor initialized. */
+ u_int8_t flags;
+} CURSOR;
+
+/*
+ * The metadata of the tree. The nrecs field is used only by the RECNO code.
+ * This is because the btree doesn't really need it and it requires that every
+ * put or delete call modify the metadata.
+ */
+typedef struct _btmeta {
+ u_int32_t magic; /* magic number */
+ u_int32_t version; /* version */
+ u_int32_t psize; /* page size */
+ u_int32_t free; /* page number of first free page */
+ u_int32_t nrecs; /* R: number of records */
+
+#define SAVEMETA (B_NODUPS | R_RECNO)
+ u_int32_t flags; /* bt_flags & SAVEMETA */
+} BTMETA;
+
+/* The in-memory btree/recno data structure. */
+typedef struct _btree {
+ MPOOL *bt_mp; /* memory pool cookie */
+
+ DB *bt_dbp; /* pointer to enclosing DB */
+
+ EPG bt_cur; /* current (pinned) page */
+ PAGE *bt_pinned; /* page pinned across calls */
+
+ CURSOR bt_cursor; /* cursor */
+
+#define BT_PUSH(t, p, i) { \
+ t->bt_sp->pgno = p; \
+ t->bt_sp->index = i; \
+ ++t->bt_sp; \
+}
+#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
+#define BT_CLR(t) (t->bt_sp = t->bt_stack)
+ EPGNO bt_stack[50]; /* stack of parent pages */
+ EPGNO *bt_sp; /* current stack pointer */
+
+ DBT bt_rkey; /* returned key */
+ DBT bt_rdata; /* returned data */
+
+ int bt_fd; /* tree file descriptor */
+
+ pgno_t bt_free; /* next free page */
+ u_int32_t bt_psize; /* page size */
+ indx_t bt_ovflsize; /* cut-off for key/data overflow */
+ int bt_lorder; /* byte order */
+ /* sorted order */
+ enum { NOT, BACK, FORWARD } bt_order;
+ EPGNO bt_last; /* last insert */
+
+ /* B: key comparison function */
+ int (*bt_cmp)(const DBT *, const DBT *);
+ /* B: prefix comparison function */
+ size_t (*bt_pfx)(const DBT *, const DBT *);
+ /* R: recno input function */
+ int (*bt_irec)(struct _btree *, recno_t);
+
+ FILE *bt_rfp; /* R: record FILE pointer */
+ int bt_rfd; /* R: record file descriptor */
+
+ caddr_t bt_cmap; /* R: current point in mapped space */
+ caddr_t bt_smap; /* R: start of mapped space */
+ caddr_t bt_emap; /* R: end of mapped space */
+ size_t bt_msize; /* R: size of mapped region. */
+
+ recno_t bt_nrecs; /* R: number of records */
+ size_t bt_reclen; /* R: fixed record length */
+ u_char bt_bval; /* R: delimiting byte/pad character */
+
+/*
+ * NB:
+ * B_NODUPS and R_RECNO are stored on disk, and may not be changed.
+ */
+#define B_INMEM 0x00001 /* in-memory tree */
+#define B_METADIRTY 0x00002 /* need to write metadata */
+#define B_MODIFIED 0x00004 /* tree modified */
+#define B_NEEDSWAP 0x00008 /* if byte order requires swapping */
+#define B_RDONLY 0x00010 /* read-only tree */
+
+#define B_NODUPS 0x00020 /* no duplicate keys permitted */
+#define R_RECNO 0x00080 /* record oriented tree */
+
+#define R_CLOSEFP 0x00040 /* opened a file pointer */
+#define R_EOF 0x00100 /* end of input file reached. */
+#define R_FIXLEN 0x00200 /* fixed length records */
+#define R_MEMMAPPED 0x00400 /* memory mapped file. */
+#define R_INMEM 0x00800 /* in-memory file */
+#define R_MODIFIED 0x01000 /* modified file */
+#define R_RDONLY 0x02000 /* read-only file */
+
+#define B_DB_LOCK 0x04000 /* DB_LOCK specified. */
+#define B_DB_SHMEM 0x08000 /* DB_SHMEM specified. */
+#define B_DB_TXN 0x10000 /* DB_TXN specified. */
+ u_int32_t flags;
+} BTREE;
+
+#include "extern.h"
diff --git a/freebsd/lib/libc/db/btree/extern.h b/freebsd/lib/libc/db/btree/extern.h
new file mode 100644
index 00000000..0abd594c
--- /dev/null
+++ b/freebsd/lib/libc/db/btree/extern.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ *
+ * @(#)extern.h 8.10 (Berkeley) 7/20/94
+ * $FreeBSD$
+ */
+
+int __bt_close(DB *);
+int __bt_cmp(BTREE *, const DBT *, EPG *);
+int __bt_crsrdel(BTREE *, EPGNO *);
+int __bt_defcmp(const DBT *, const DBT *);
+size_t __bt_defpfx(const DBT *, const DBT *);
+int __bt_delete(const DB *, const DBT *, u_int);
+int __bt_dleaf(BTREE *, const DBT *, PAGE *, u_int);
+int __bt_fd(const DB *);
+int __bt_free(BTREE *, PAGE *);
+int __bt_get(const DB *, const DBT *, DBT *, u_int);
+PAGE *__bt_new(BTREE *, pgno_t *);
+void __bt_pgin(void *, pgno_t, void *);
+void __bt_pgout(void *, pgno_t, void *);
+int __bt_push(BTREE *, pgno_t, int);
+int __bt_put(const DB *dbp, DBT *, const DBT *, u_int);
+int __bt_ret(BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int);
+EPG *__bt_search(BTREE *, const DBT *, int *);
+int __bt_seq(const DB *, DBT *, DBT *, u_int);
+void __bt_setcur(BTREE *, pgno_t, u_int);
+int __bt_split(BTREE *, PAGE *,
+ const DBT *, const DBT *, int, size_t, u_int32_t);
+int __bt_sync(const DB *, u_int);
+
+int __ovfl_delete(BTREE *, void *);
+int __ovfl_get(BTREE *, void *, size_t *, void **, size_t *);
+int __ovfl_put(BTREE *, const DBT *, pgno_t *);
+
+#ifdef DEBUG
+void __bt_dnpage(DB *, pgno_t);
+void __bt_dpage(PAGE *);
+void __bt_dump(DB *);
+#endif
+#ifdef STATISTICS
+void __bt_stat(DB *);
+#endif
diff --git a/freebsd/lib/libc/db/db/db.c b/freebsd/lib/libc/db/db/db.c
new file mode 100644
index 00000000..e450c626
--- /dev/null
+++ b/freebsd/lib/libc/db/db/db.c
@@ -0,0 +1,96 @@
+#include "port_before.h"
+
+/*-
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+
+static int __dberr(void);
+
+DB *
+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_NOFOLLOW | O_NONBLOCK | \
+ O_RDONLY | O_RDWR | O_SHLOCK | O_SYNC | O_TRUNC)
+
+ if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
+ switch (type) {
+ case DB_BTREE:
+ return (__bt_open(fname, flags & USE_OPEN_FLAGS,
+ mode, openinfo, flags & DB_FLAGS));
+ case DB_HASH:
+ return (__hash_open(fname, flags & USE_OPEN_FLAGS,
+ mode, openinfo, flags & DB_FLAGS));
+ case DB_RECNO:
+ return (__rec_open(fname, flags & USE_OPEN_FLAGS,
+ mode, openinfo, flags & DB_FLAGS));
+ }
+ errno = EINVAL;
+ return (NULL);
+}
+
+static int
+__dberr(void)
+{
+ return (RET_ERROR);
+}
+
+/*
+ * __DBPANIC -- Stop.
+ *
+ * Parameters:
+ * dbp: pointer to the DB structure.
+ */
+void
+__dbpanic(DB *dbp)
+{
+ /* The only thing that can succeed is a close. */
+ dbp->del = (int (*)(const struct __db *, const DBT*, u_int))__dberr;
+ dbp->fd = (int (*)(const struct __db *))__dberr;
+ dbp->get = (int (*)(const struct __db *, const DBT*, DBT *, u_int))__dberr;
+ dbp->put = (int (*)(const struct __db *, DBT *, const DBT *, u_int))__dberr;
+ dbp->seq = (int (*)(const struct __db *, DBT *, DBT *, u_int))__dberr;
+ dbp->sync = (int (*)(const struct __db *, u_int))__dberr;
+}
diff --git a/freebsd/lib/libc/db/mpool/mpool-compat.c b/freebsd/lib/libc/db/mpool/mpool-compat.c
new file mode 100644
index 00000000..9df76ff0
--- /dev/null
+++ b/freebsd/lib/libc/db/mpool/mpool-compat.c
@@ -0,0 +1,43 @@
+/*-
+ * 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
+ * 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 <db.h>
+#include <mpool.h>
+
+void *__mpool_new__44bsd(MPOOL *, pgno_t *);
+
+void *
+__mpool_new__44bsd(MPOOL *mp, pgno_t *pgnoaddr)
+{
+
+ return (mpool_new(mp, pgnoaddr, MPOOL_PAGE_NEXT));
+}
+
+__sym_compat(mpool_new, __mpool_new_44bsd, FBSD_1.0);
diff --git a/freebsd/lib/libc/db/mpool/mpool.c b/freebsd/lib/libc/db/mpool/mpool.c
new file mode 100644
index 00000000..ee7e143d
--- /dev/null
+++ b/freebsd/lib/libc/db/mpool/mpool.c
@@ -0,0 +1,495 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mpool.c 8.7 (Berkeley) 11/2/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+
+#define __MPOOLINTERFACE_PRIVATE
+#include <mpool.h>
+
+static BKT *mpool_bkt(MPOOL *);
+static BKT *mpool_look(MPOOL *, pgno_t);
+static int mpool_write(MPOOL *, BKT *);
+
+/*
+ * mpool_open --
+ * Initialize a memory pool.
+ */
+/* ARGSUSED */
+MPOOL *
+mpool_open(void *key, int fd, pgno_t pagesize, pgno_t maxcache)
+{
+ struct stat sb;
+ MPOOL *mp;
+ int entry;
+
+ /*
+ * Get information about the file.
+ *
+ * XXX
+ * We don't currently handle pipes, although we should.
+ */
+ if (_fstat(fd, &sb))
+ return (NULL);
+ if (!S_ISREG(sb.st_mode)) {
+ errno = ESPIPE;
+ return (NULL);
+ }
+
+ /* Allocate and initialize the MPOOL cookie. */
+ if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
+ return (NULL);
+ TAILQ_INIT(&mp->lqh);
+ for (entry = 0; entry < HASHSIZE; ++entry)
+ TAILQ_INIT(&mp->hqh[entry]);
+ mp->maxcache = maxcache;
+ mp->npages = sb.st_size / pagesize;
+ mp->pagesize = pagesize;
+ mp->fd = fd;
+ return (mp);
+}
+
+/*
+ * mpool_filter --
+ * Initialize input/output filters.
+ */
+void
+mpool_filter(MPOOL *mp, void (*pgin) (void *, pgno_t, void *),
+ void (*pgout) (void *, pgno_t, void *), void *pgcookie)
+{
+ mp->pgin = pgin;
+ mp->pgout = pgout;
+ mp->pgcookie = pgcookie;
+}
+
+/*
+ * mpool_new --
+ * Get a new page of memory.
+ */
+void *
+mpool_new(MPOOL *mp, pgno_t *pgnoaddr, u_int flags)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ if (mp->npages == MAX_PAGE_NUMBER) {
+ (void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
+ abort();
+ }
+#ifdef STATISTICS
+ ++mp->pagenew;
+#endif
+ /*
+ * Get a BKT from the cache. Assign a new page number, attach
+ * it to the head of the hash chain, the tail of the lru chain,
+ * and return.
+ */
+ if ((bp = mpool_bkt(mp)) == NULL)
+ return (NULL);
+ 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);
+ TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+ 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.
+ */
+/* ARGSUSED */
+void *
+mpool_get(MPOOL *mp, pgno_t pgno,
+ u_int flags) /* XXX not used? */
+{
+ struct _hqh *head;
+ BKT *bp;
+ off_t off;
+ int nr;
+
+#ifdef STATISTICS
+ ++mp->pageget;
+#endif
+
+ /* Check for a page that is cached. */
+ if ((bp = mpool_look(mp, pgno)) != NULL) {
+#ifdef DEBUG
+ if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) {
+ (void)fprintf(stderr,
+ "mpool_get: page %d already pinned\n", bp->pgno);
+ abort();
+ }
+#endif
+ /*
+ * Move the page to the head of the hash chain and the tail
+ * of the lru chain.
+ */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_REMOVE(head, bp, hq);
+ TAILQ_INSERT_HEAD(head, bp, hq);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+ TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+ /* Return a pinned page. */
+ bp->flags |= MPOOL_PINNED;
+ return (bp->page);
+ }
+
+ /* Get a page from the cache. */
+ if ((bp = mpool_bkt(mp)) == NULL)
+ 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
+
+ /* Set the page number, pin the page. */
+ bp->pgno = pgno;
+ 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
+ * of the lru chain.
+ */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_INSERT_HEAD(head, bp, hq);
+ TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+ /* Run through the user's filter. */
+ if (mp->pgin != NULL)
+ (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
+ return (bp->page);
+}
+
+/*
+ * mpool_put
+ * Return a page.
+ */
+/* ARGSUSED */
+int
+mpool_put(MPOOL *mp, void *page, u_int flags)
+{
+ BKT *bp;
+
+#ifdef STATISTICS
+ ++mp->pageput;
+#endif
+ bp = (BKT *)((char *)page - sizeof(BKT));
+#ifdef DEBUG
+ if (!(bp->flags & MPOOL_PINNED)) {
+ (void)fprintf(stderr,
+ "mpool_put: page %d not pinned\n", bp->pgno);
+ abort();
+ }
+#endif
+ bp->flags &= ~MPOOL_PINNED;
+ if (flags & MPOOL_DIRTY)
+ bp->flags |= flags & MPOOL_DIRTY;
+ return (RET_SUCCESS);
+}
+
+/*
+ * mpool_close
+ * Close the buffer pool.
+ */
+int
+mpool_close(MPOOL *mp)
+{
+ BKT *bp;
+
+ /* Free up any space allocated to the lru pages. */
+ while (!TAILQ_EMPTY(&mp->lqh)) {
+ bp = TAILQ_FIRST(&mp->lqh);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+ free(bp);
+ }
+
+ /* Free the MPOOL cookie. */
+ free(mp);
+ return (RET_SUCCESS);
+}
+
+/*
+ * mpool_sync
+ * Sync the pool to disk.
+ */
+int
+mpool_sync(MPOOL *mp)
+{
+ BKT *bp;
+
+ /* Walk the lru chain, flushing any dirty pages to disk. */
+ TAILQ_FOREACH(bp, &mp->lqh, q)
+ if (bp->flags & MPOOL_DIRTY &&
+ mpool_write(mp, bp) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Sync the file descriptor. */
+ return (_fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * mpool_bkt
+ * Get a page from the cache (or create one).
+ */
+static BKT *
+mpool_bkt(MPOOL *mp)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ /* If under the max cached, always create a new page. */
+ if (mp->curcache < mp->maxcache)
+ goto new;
+
+ /*
+ * If the cache is max'd out, walk the lru list for a buffer we
+ * can flush. If we find one, write it (if necessary) and take it
+ * off any lists. If we don't find anything we grow the cache anyway.
+ * The cache never shrinks.
+ */
+ TAILQ_FOREACH(bp, &mp->lqh, q)
+ if (!(bp->flags & MPOOL_PINNED)) {
+ /* Flush if dirty. */
+ if (bp->flags & MPOOL_DIRTY &&
+ mpool_write(mp, bp) == RET_ERROR)
+ return (NULL);
+#ifdef STATISTICS
+ ++mp->pageflush;
+#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);
+#ifdef DEBUG
+ { void *spage;
+ spage = bp->page;
+ memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+ bp->page = spage;
+ }
+#endif
+ bp->flags = 0;
+ return (bp);
+ }
+
+new: if ((bp = (BKT *)calloc(1, sizeof(BKT) + mp->pagesize)) == NULL)
+ return (NULL);
+#ifdef STATISTICS
+ ++mp->pagealloc;
+#endif
+ bp->page = (char *)bp + sizeof(BKT);
+ bp->flags = 0;
+ ++mp->curcache;
+ return (bp);
+}
+
+/*
+ * mpool_write
+ * Write a page to disk.
+ */
+static int
+mpool_write(MPOOL *mp, BKT *bp)
+{
+ off_t off;
+
+#ifdef STATISTICS
+ ++mp->pagewrite;
+#endif
+
+ /* Run through the user's filter. */
+ if (mp->pgout)
+ (mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
+
+ off = mp->pagesize * bp->pgno;
+ 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);
+}
+
+/*
+ * mpool_look
+ * Lookup a page in the cache.
+ */
+static BKT *
+mpool_look(MPOOL *mp, pgno_t pgno)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ head = &mp->hqh[HASHKEY(pgno)];
+ TAILQ_FOREACH(bp, head, hq)
+ if ((bp->pgno == pgno) &&
+ ((bp->flags & MPOOL_INUSE) == MPOOL_INUSE)) {
+#ifdef STATISTICS
+ ++mp->cachehit;
+#endif
+ return (bp);
+ }
+#ifdef STATISTICS
+ ++mp->cachemiss;
+#endif
+ return (NULL);
+}
+
+#ifdef STATISTICS
+/*
+ * mpool_stat
+ * Print out cache statistics.
+ */
+void
+mpool_stat(MPOOL *mp)
+{
+ BKT *bp;
+ int cnt;
+ char *sep;
+
+ (void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
+ (void)fprintf(stderr,
+ "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);
+ (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
+ mp->pagealloc, mp->pageflush);
+ if (mp->cachehit + mp->cachemiss)
+ (void)fprintf(stderr,
+ "%.0f%% cache hit rate (%lu hits, %lu misses)\n",
+ ((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
+ * 100, mp->cachehit, mp->cachemiss);
+ (void)fprintf(stderr, "%lu page reads, %lu page writes\n",
+ mp->pageread, mp->pagewrite);
+
+ sep = "";
+ cnt = 0;
+ TAILQ_FOREACH(bp, &mp->lqh, q) {
+ (void)fprintf(stderr, "%s%d", sep, bp->pgno);
+ if (bp->flags & MPOOL_DIRTY)
+ (void)fprintf(stderr, "d");
+ if (bp->flags & MPOOL_PINNED)
+ (void)fprintf(stderr, "P");
+ if (++cnt == 10) {
+ sep = "\n";
+ cnt = 0;
+ } else
+ sep = ", ";
+
+ }
+ (void)fprintf(stderr, "\n");
+}
+#endif
diff --git a/freebsd/lib/libc/db/recno/extern.h b/freebsd/lib/libc/db/recno/extern.h
new file mode 100644
index 00000000..53916bd4
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/extern.h
@@ -0,0 +1,51 @@
+/*-
+ * 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.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 6/4/94
+ * $FreeBSD$
+ */
+
+#include "../btree/extern.h"
+
+int __rec_close(DB *);
+int __rec_delete(const DB *, const DBT *, u_int);
+int __rec_dleaf(BTREE *, PAGE *, u_int32_t);
+int __rec_fd(const DB *);
+int __rec_fmap(BTREE *, recno_t);
+int __rec_fout(BTREE *);
+int __rec_fpipe(BTREE *, recno_t);
+int __rec_get(const DB *, const DBT *, DBT *, u_int);
+int __rec_iput(BTREE *, recno_t, const DBT *, u_int);
+int __rec_put(const DB *dbp, DBT *, const DBT *, u_int);
+int __rec_ret(BTREE *, EPG *, recno_t, DBT *, DBT *);
+EPG *__rec_search(BTREE *, recno_t, enum SRCHOP);
+int __rec_seq(const DB *, DBT *, DBT *, u_int);
+int __rec_sync(const DB *, u_int);
+int __rec_vmap(BTREE *, recno_t);
+int __rec_vout(BTREE *);
+int __rec_vpipe(BTREE *, recno_t);
diff --git a/freebsd/lib/libc/db/recno/rec_close.c b/freebsd/lib/libc/db/recno/rec_close.c
new file mode 100644
index 00000000..388ee4a9
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_close.c
@@ -0,0 +1,186 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_CLOSE -- Close a recno tree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_close(DB *dbp)
+{
+ BTREE *t;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ if (__rec_sync(dbp, 0) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Committed to closing. */
+ status = RET_SUCCESS;
+
+#ifndef __rtems__ /* XXX */
+ if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
+ status = RET_ERROR;
+#endif
+ if (!F_ISSET(t, R_INMEM)) {
+ if (F_ISSET(t, R_CLOSEFP)) {
+ if (fclose(t->bt_rfp))
+ status = RET_ERROR;
+ } else {
+ if (_close(t->bt_rfd))
+ status = RET_ERROR;
+ }
+ }
+
+ if (__bt_close(dbp) == RET_ERROR)
+ status = RET_ERROR;
+
+ return (status);
+}
+
+/*
+ * __REC_SYNC -- sync the recno tree to disk.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_sync(const DB *dbp, u_int flags)
+{
+ struct iovec iov[2];
+ BTREE *t;
+ DBT data, key;
+ off_t off;
+ recno_t scursor, trec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ if (flags == R_RECNOSYNC)
+ return (__bt_sync(dbp, 0));
+
+ if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
+ return (RET_SUCCESS);
+
+ /* Read any remaining records into the tree. */
+ if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Rewind the file descriptor. */
+ if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
+ return (RET_ERROR);
+
+ /* Save the cursor. */
+ scursor = t->bt_cursor.rcursor;
+
+ key.size = sizeof(recno_t);
+ key.data = &trec;
+
+ if (F_ISSET(t, R_FIXLEN)) {
+ /*
+ * We assume that fixed length records are all fixed length.
+ * Any that aren't are either EINVAL'd or corrected by the
+ * record put code.
+ */
+ status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+ while (status == RET_SUCCESS) {
+ if (_write(t->bt_rfd, data.data, data.size) !=
+ (ssize_t)data.size)
+ return (RET_ERROR);
+ status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+ }
+ } else {
+ iov[1].iov_base = &t->bt_bval;
+ iov[1].iov_len = 1;
+
+ status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+ while (status == RET_SUCCESS) {
+ iov[0].iov_base = data.data;
+ iov[0].iov_len = data.size;
+ if (_writev(t->bt_rfd, iov, 2) != (ssize_t)(data.size + 1))
+ return (RET_ERROR);
+ status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+ }
+ }
+
+ /* Restore the cursor. */
+ t->bt_cursor.rcursor = scursor;
+
+ if (status == RET_ERROR)
+ return (RET_ERROR);
+ if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
+ return (RET_ERROR);
+ if (ftruncate(t->bt_rfd, off))
+ return (RET_ERROR);
+ F_CLR(t, R_MODIFIED);
+ return (RET_SUCCESS);
+}
diff --git a/freebsd/lib/libc/db/recno/rec_delete.c b/freebsd/lib/libc/db/recno/rec_delete.c
new file mode 100644
index 00000000..ffaa50bf
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_delete.c
@@ -0,0 +1,189 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+static int rec_rdelete(BTREE *, recno_t);
+
+/*
+ * __REC_DELETE -- Delete the item(s) referenced by a key.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key to delete
+ * flags: R_CURSOR if deleting what the cursor references
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_delete(const DB *dbp, const DBT *key, u_int flags)
+{
+ BTREE *t;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ switch(flags) {
+ case 0:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ if (nrec > t->bt_nrecs)
+ return (RET_SPECIAL);
+ --nrec;
+ status = rec_rdelete(t, nrec);
+ break;
+ case R_CURSOR:
+ if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+ goto einval;
+ if (t->bt_nrecs == 0)
+ return (RET_SPECIAL);
+ status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
+ if (status == RET_SUCCESS)
+ --t->bt_cursor.rcursor;
+ break;
+ default:
+einval: errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (status == RET_SUCCESS)
+ F_SET(t, B_MODIFIED | R_MODIFIED);
+ return (status);
+}
+
+/*
+ * REC_RDELETE -- Delete the data matching the specified key.
+ *
+ * Parameters:
+ * tree: tree
+ * nrec: record to delete
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+rec_rdelete(BTREE *t, recno_t nrec)
+{
+ EPG *e;
+ PAGE *h;
+ int status;
+
+ /* Find the record; __rec_search pins the page. */
+ if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
+ return (RET_ERROR);
+
+ /* Delete the record. */
+ h = e->page;
+ status = __rec_dleaf(t, h, e->index);
+ if (status != RET_SUCCESS) {
+ mpool_put(t->bt_mp, h, 0);
+ return (status);
+ }
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_DLEAF -- Delete a single record from a recno leaf page.
+ *
+ * Parameters:
+ * t: tree
+ * idx: index on current page to delete
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_dleaf(BTREE *t, PAGE *h, u_int32_t idx)
+{
+ RLEAF *rl;
+ indx_t *ip, cnt, offset;
+ u_int32_t nbytes;
+ char *from;
+ void *to;
+
+ /*
+ * Delete a record from a recno leaf page. Internal records are never
+ * deleted from internal pages, regardless of the records that caused
+ * them to be added being deleted. Pages made empty by deletion are
+ * not reclaimed. They are, however, made available for reuse.
+ *
+ * Pack the remaining entries at the end of the page, shift the indices
+ * down, overwriting the deleted record and its index. If the record
+ * uses overflow pages, make them available for reuse.
+ */
+ to = rl = GETRLEAF(h, idx);
+ if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
+ return (RET_ERROR);
+ nbytes = NRLEAF(rl);
+
+ /*
+ * Compress the key/data pairs. Compress and adjust the [BR]LEAF
+ * offsets. Reset the headers.
+ */
+ from = (char *)h + h->upper;
+ memmove(from + nbytes, from, (char *)to - from);
+ h->upper += nbytes;
+
+ offset = h->linp[idx];
+ for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip)
+ if (ip[0] < offset)
+ ip[0] += nbytes;
+ for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
+ ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+ h->lower -= sizeof(indx_t);
+ --t->bt_nrecs;
+ return (RET_SUCCESS);
+}
diff --git a/freebsd/lib/libc/db/recno/rec_get.c b/freebsd/lib/libc/db/recno/rec_get.c
new file mode 100644
index 00000000..ef749add
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_get.c
@@ -0,0 +1,293 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key to find
+ * data: data to return
+ * flag: currently unused
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG *e;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Get currently doesn't take any flags, and keys of 0 are illegal. */
+ if (flags || (nrec = *(recno_t *)key->data) == 0) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ /*
+ * If we haven't seen this record yet, try to find it in the
+ * original file.
+ */
+ if (nrec > t->bt_nrecs) {
+ if (F_ISSET(t, R_EOF | R_INMEM))
+ return (RET_SPECIAL);
+ if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+ return (status);
+ }
+
+ --nrec;
+ if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
+ return (RET_ERROR);
+
+ status = __rec_ret(t, e, 0, NULL, data);
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e->page, 0);
+ else
+ t->bt_pinned = e->page;
+ return (status);
+}
+
+/*
+ * __REC_FPIPE -- Get fixed length records from a pipe.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fpipe(BTREE *t, recno_t top)
+{
+ DBT data;
+ recno_t nrec;
+ size_t len;
+ int ch;
+ u_char *p;
+
+ if (t->bt_rdata.size < t->bt_reclen) {
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.size = t->bt_reclen;
+ }
+ data.data = t->bt_rdata.data;
+ data.size = t->bt_reclen;
+
+ for (nrec = t->bt_nrecs; nrec < top;) {
+ len = t->bt_reclen;
+ for (p = t->bt_rdata.data;; *p++ = ch)
+ if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
+ if (ch != EOF)
+ *p = ch;
+ if (len != 0)
+ memset(p, t->bt_bval, len);
+ if (__rec_iput(t,
+ nrec, &data, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ ++nrec;
+ break;
+ }
+ if (ch == EOF)
+ break;
+ }
+ if (nrec < top) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VPIPE -- Get variable length records from a pipe.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vpipe(BTREE *t, recno_t top)
+{
+ DBT data;
+ recno_t nrec;
+ size_t len;
+ size_t sz;
+ int bval, ch;
+ u_char *p;
+
+ bval = t->bt_bval;
+ for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+ for (p = t->bt_rdata.data,
+ sz = t->bt_rdata.size;; *p++ = ch, --sz) {
+ if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
+ data.data = t->bt_rdata.data;
+ data.size = p - (u_char *)t->bt_rdata.data;
+ if (ch == EOF && data.size == 0)
+ break;
+ if (__rec_iput(t, nrec, &data, 0)
+ != RET_SUCCESS)
+ return (RET_ERROR);
+ break;
+ }
+ if (sz == 0) {
+ len = p - (u_char *)t->bt_rdata.data;
+ t->bt_rdata.size += (sz = 256);
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_rdata.size);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ p = (u_char *)t->bt_rdata.data + len;
+ }
+ }
+ if (ch == EOF)
+ break;
+ }
+ if (nrec < top) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_FMAP -- Get fixed length records from a file.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fmap(BTREE *t, recno_t top)
+{
+ DBT data;
+ recno_t nrec;
+ u_char *sp, *ep, *p;
+ size_t len;
+
+ if (t->bt_rdata.size < t->bt_reclen) {
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.size = t->bt_reclen;
+ }
+ data.data = t->bt_rdata.data;
+ data.size = t->bt_reclen;
+
+ sp = (u_char *)t->bt_cmap;
+ ep = (u_char *)t->bt_emap;
+ for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+ if (sp >= ep) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ len = t->bt_reclen;
+ for (p = t->bt_rdata.data;
+ sp < ep && len > 0; *p++ = *sp++, --len);
+ if (len != 0)
+ memset(p, t->bt_bval, len);
+ if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ }
+ t->bt_cmap = (caddr_t)sp;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VMAP -- Get variable length records from a file.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vmap(BTREE *t, recno_t top)
+{
+ DBT data;
+ u_char *sp, *ep;
+ recno_t nrec;
+ int bval;
+
+ sp = (u_char *)t->bt_cmap;
+ ep = (u_char *)t->bt_emap;
+ bval = t->bt_bval;
+
+ for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+ if (sp >= ep) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ for (data.data = sp; sp < ep && *sp != bval; ++sp);
+ data.size = sp - (u_char *)data.data;
+ if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ ++sp;
+ }
+ t->bt_cmap = (caddr_t)sp;
+ return (RET_SUCCESS);
+}
diff --git a/freebsd/lib/libc/db/recno/rec_open.c b/freebsd/lib/libc/db/recno/rec_open.c
new file mode 100644
index 00000000..a0248aca
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_open.c
@@ -0,0 +1,240 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "recno.h"
+
+DB *
+__rec_open(const char *fname, int flags, int mode, const RECNOINFO *openinfo,
+ int dflags)
+{
+ BTREE *t;
+ BTREEINFO btopeninfo;
+ DB *dbp;
+ PAGE *h;
+ struct stat sb;
+ int rfd, sverrno;
+
+ /* Open the user's file -- if this fails, we're done. */
+ if (fname != NULL && (rfd = _open(fname, flags, mode)) < 0)
+ return (NULL);
+
+ /* Create a btree in memory (backed by disk). */
+ dbp = NULL;
+ if (openinfo) {
+ if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
+ goto einval;
+ btopeninfo.flags = 0;
+ btopeninfo.cachesize = openinfo->cachesize;
+ btopeninfo.maxkeypage = 0;
+ btopeninfo.minkeypage = 0;
+ btopeninfo.psize = openinfo->psize;
+ btopeninfo.compare = NULL;
+ btopeninfo.prefix = NULL;
+ btopeninfo.lorder = openinfo->lorder;
+ dbp = __bt_open(openinfo->bfname,
+ O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
+ } else
+ dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
+ if (dbp == NULL)
+ goto err;
+
+ /*
+ * Some fields in the tree structure are recno specific. Fill them
+ * in and make the btree structure look like a recno structure. We
+ * don't change the bt_ovflsize value, it's close enough and slightly
+ * bigger.
+ */
+ t = dbp->internal;
+ if (openinfo) {
+ if (openinfo->flags & R_FIXEDLEN) {
+ F_SET(t, R_FIXLEN);
+ t->bt_reclen = openinfo->reclen;
+ if (t->bt_reclen == 0)
+ goto einval;
+ }
+ t->bt_bval = openinfo->bval;
+ } else
+ t->bt_bval = '\n';
+
+ F_SET(t, R_RECNO);
+ if (fname == NULL)
+ F_SET(t, R_EOF | R_INMEM);
+ else
+ t->bt_rfd = rfd;
+
+ if (fname != NULL) {
+ /*
+ * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
+ * Unfortunately, that's not portable, so we use lseek
+ * and check the errno values.
+ */
+ errno = 0;
+ if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ F_SET(t, R_RDONLY);
+ break;
+ default:
+ goto einval;
+ }
+slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
+ goto err;
+ F_SET(t, R_CLOSEFP);
+ t->bt_irec =
+ F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
+ } else {
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ F_SET(t, R_RDONLY);
+ break;
+ case O_RDWR:
+ break;
+ default:
+ goto einval;
+ }
+
+ if (_fstat(rfd, &sb))
+ goto err;
+ /*
+ * Kluge -- we'd like to test to see if the file is too
+ * big to mmap. Since, we don't know what size or type
+ * off_t's or size_t's are, what the largest unsigned
+ * integral type is, or what random insanity the local
+ * C compiler will perpetrate, doing the comparison in
+ * a portable way is flatly impossible. Hope that mmap
+ * fails if the file is too large.
+ */
+ if (sb.st_size == 0)
+ F_SET(t, R_EOF);
+ else {
+#ifdef MMAP_NOT_AVAILABLE
+ /*
+ * XXX
+ * Mmap doesn't work correctly on many current
+ * systems. In particular, it can fail subtly,
+ * with cache coherency problems. Don't use it
+ * for now.
+ */
+ t->bt_msize = sb.st_size;
+ if ((t->bt_smap = mmap(NULL, t->bt_msize,
+ PROT_READ, MAP_PRIVATE, rfd,
+ (off_t)0)) == MAP_FAILED)
+ goto slow;
+ t->bt_cmap = t->bt_smap;
+ t->bt_emap = t->bt_smap + sb.st_size;
+ t->bt_irec = F_ISSET(t, R_FIXLEN) ?
+ __rec_fmap : __rec_vmap;
+ F_SET(t, R_MEMMAPPED);
+#else
+ goto slow;
+#endif
+ }
+ }
+ }
+
+ /* Use the recno routines. */
+ dbp->close = __rec_close;
+ dbp->del = __rec_delete;
+ dbp->fd = __rec_fd;
+ dbp->get = __rec_get;
+ dbp->put = __rec_put;
+ dbp->seq = __rec_seq;
+ dbp->sync = __rec_sync;
+
+ /* If the root page was created, reset the flags. */
+ if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
+ goto err;
+ if ((h->flags & P_TYPE) == P_BLEAF) {
+ F_CLR(h, P_TYPE);
+ F_SET(h, P_RLEAF);
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ } else
+ mpool_put(t->bt_mp, h, 0);
+
+ if (openinfo && openinfo->flags & R_SNAPSHOT &&
+ !F_ISSET(t, R_EOF | R_INMEM) &&
+ t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+ goto err;
+ return (dbp);
+
+einval: errno = EINVAL;
+err: sverrno = errno;
+ if (dbp != NULL)
+ (void)__bt_close(dbp);
+ if (fname != NULL)
+ (void)_close(rfd);
+ errno = sverrno;
+ return (NULL);
+}
+
+int
+__rec_fd(const DB *dbp)
+{
+ BTREE *t;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* In-memory database can't have a file descriptor. */
+ if (F_ISSET(t, R_INMEM)) {
+ errno = ENOENT;
+ return (-1);
+ }
+ return (t->bt_rfd);
+}
diff --git a/freebsd/lib/libc/db/recno/rec_put.c b/freebsd/lib/libc/db/recno/rec_put.c
new file mode 100644
index 00000000..58c1f566
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_put.c
@@ -0,0 +1,277 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_PUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key
+ * data: data
+ * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
+ * already in the tree and R_NOOVERWRITE specified.
+ */
+int
+__rec_put(const DB *dbp, DBT *key, const DBT *data, u_int flags)
+{
+ BTREE *t;
+ DBT fdata, tdata;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /*
+ * If using fixed-length records, and the record is long, return
+ * EINVAL. If it's short, pad it out. Use the record data return
+ * memory, it's only short-term.
+ */
+ if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) {
+ if (data->size > t->bt_reclen)
+ goto einval;
+
+ if (t->bt_rdata.size < t->bt_reclen) {
+ t->bt_rdata.data =
+ reallocf(t->bt_rdata.data, t->bt_reclen);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.size = t->bt_reclen;
+ }
+ memmove(t->bt_rdata.data, data->data, data->size);
+ memset((char *)t->bt_rdata.data + data->size,
+ t->bt_bval, t->bt_reclen - data->size);
+ fdata.data = t->bt_rdata.data;
+ fdata.size = t->bt_reclen;
+ } else {
+ fdata.data = data->data;
+ fdata.size = data->size;
+ }
+
+ switch (flags) {
+ case R_CURSOR:
+ if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+ goto einval;
+ nrec = t->bt_cursor.rcursor;
+ break;
+ case R_SETCURSOR:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ break;
+ case R_IAFTER:
+ if ((nrec = *(recno_t *)key->data) == 0) {
+ nrec = 1;
+ flags = R_IBEFORE;
+ }
+ break;
+ case 0:
+ case R_IBEFORE:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ break;
+ case R_NOOVERWRITE:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ if (nrec <= t->bt_nrecs)
+ return (RET_SPECIAL);
+ break;
+ default:
+einval: errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ /*
+ * Make sure that records up to and including the put record are
+ * already in the database. If skipping records, create empty ones.
+ */
+ if (nrec > t->bt_nrecs) {
+ if (!F_ISSET(t, R_EOF | R_INMEM) &&
+ t->bt_irec(t, nrec) == RET_ERROR)
+ return (RET_ERROR);
+ if (nrec > t->bt_nrecs + 1) {
+ if (F_ISSET(t, R_FIXLEN)) {
+ if ((tdata.data =
+ (void *)malloc(t->bt_reclen)) == NULL)
+ return (RET_ERROR);
+ tdata.size = t->bt_reclen;
+ memset(tdata.data, t->bt_bval, tdata.size);
+ } else {
+ tdata.data = NULL;
+ tdata.size = 0;
+ }
+ while (nrec > t->bt_nrecs + 1)
+ if (__rec_iput(t,
+ t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ if (F_ISSET(t, R_FIXLEN))
+ free(tdata.data);
+ }
+ }
+
+ if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
+ return (status);
+
+ switch (flags) {
+ case R_IAFTER:
+ nrec++;
+ break;
+ case R_SETCURSOR:
+ t->bt_cursor.rcursor = nrec;
+ break;
+ }
+
+ F_SET(t, R_MODIFIED);
+ return (__rec_ret(t, NULL, nrec, key, NULL));
+}
+
+/*
+ * __REC_IPUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ * t: tree
+ * nrec: record number
+ * data: data
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_iput(BTREE *t, recno_t nrec, const DBT *data, u_int flags)
+{
+ DBT tdata;
+ EPG *e;
+ PAGE *h;
+ indx_t idx, nxtindex;
+ pgno_t pg;
+ u_int32_t nbytes;
+ int dflags, status;
+ char *dest, db[NOVFLSIZE];
+
+ /*
+ * If the data won't fit on a page, store it on indirect pages.
+ *
+ * XXX
+ * If the insert fails later on, these pages aren't recovered.
+ */
+ if (data->size > t->bt_ovflsize) {
+ if (__ovfl_put(t, data, &pg) == RET_ERROR)
+ return (RET_ERROR);
+ tdata.data = db;
+ tdata.size = NOVFLSIZE;
+ *(pgno_t *)db = pg;
+ *(u_int32_t *)(db + sizeof(pgno_t)) = data->size;
+ dflags = P_BIGDATA;
+ data = &tdata;
+ } else
+ dflags = 0;
+
+ /* __rec_search pins the returned page. */
+ if ((e = __rec_search(t, nrec,
+ nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
+ SINSERT : SEARCH)) == NULL)
+ return (RET_ERROR);
+
+ h = e->page;
+ idx = e->index;
+
+ /*
+ * Add the specified key/data pair to the tree. The R_IAFTER and
+ * R_IBEFORE flags insert the key after/before the specified key.
+ *
+ * Pages are split as required.
+ */
+ switch (flags) {
+ case R_IAFTER:
+ ++idx;
+ break;
+ case R_IBEFORE:
+ break;
+ default:
+ if (nrec < t->bt_nrecs &&
+ __rec_dleaf(t, h, idx) == RET_ERROR) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ break;
+ }
+
+ /*
+ * If not enough room, split the page. The split code will insert
+ * the key and data and unpin the current page. If inserting into
+ * the offset array, shift the pointers up.
+ */
+ nbytes = NRLEAFDBT(data->size);
+ 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;
+ return (status);
+ }
+
+ if (idx < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + idx + 1, h->linp + idx,
+ (nxtindex - idx) * sizeof(indx_t));
+ h->lower += sizeof(indx_t);
+
+ h->linp[idx] = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ WR_RLEAF(dest, data, dflags);
+
+ ++t->bt_nrecs;
+ F_SET(t, B_MODIFIED);
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ return (RET_SUCCESS);
+}
diff --git a/freebsd/lib/libc/db/recno/rec_search.c b/freebsd/lib/libc/db/recno/rec_search.c
new file mode 100644
index 00000000..2d98b95e
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_search.c
@@ -0,0 +1,123 @@
+#include "port_before.h"
+
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEARCH -- Search a btree for a key.
+ *
+ * Parameters:
+ * t: tree to search
+ * recno: key to find
+ * op: search operation
+ *
+ * Returns:
+ * EPG for matching record, if any, or the EPG for the location of the
+ * key, if it were inserted into the tree.
+ *
+ * Returns:
+ * The EPG for matching record, if any, or the EPG for the location
+ * of the key, if it were inserted into the tree, is entered into
+ * the bt_cur field of the tree. A pointer to the field is returned.
+ */
+EPG *
+__rec_search(BTREE *t, recno_t recno, enum SRCHOP op)
+{
+ indx_t idx;
+ PAGE *h;
+ EPGNO *parent;
+ RINTERNAL *r;
+ pgno_t pg;
+ indx_t top;
+ recno_t total;
+ int sverrno;
+
+ BT_CLR(t);
+ for (pg = P_ROOT, total = 0;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ goto err;
+ if (h->flags & P_RLEAF) {
+ t->bt_cur.page = h;
+ t->bt_cur.index = recno - total;
+ return (&t->bt_cur);
+ }
+ for (idx = 0, top = NEXTINDEX(h);;) {
+ r = GETRINTERNAL(h, idx);
+ if (++idx == top || total + r->nrecs > recno)
+ break;
+ total += r->nrecs;
+ }
+
+ BT_PUSH(t, pg, idx - 1);
+
+ pg = r->pgno;
+ switch (op) {
+ case SDELETE:
+ --GETRINTERNAL(h, (idx - 1))->nrecs;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ case SINSERT:
+ ++GETRINTERNAL(h, (idx - 1))->nrecs;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ case SEARCH:
+ mpool_put(t->bt_mp, h, 0);
+ break;
+ }
+
+ }
+ /* Try and recover the tree. */
+err: sverrno = errno;
+ if (op != SEARCH)
+ while ((parent = BT_POP(t)) != NULL) {
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ break;
+ if (op == SINSERT)
+ --GETRINTERNAL(h, parent->index)->nrecs;
+ else
+ ++GETRINTERNAL(h, parent->index)->nrecs;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ }
+ errno = sverrno;
+ return (NULL);
+}
diff --git a/freebsd/lib/libc/db/recno/rec_seq.c b/freebsd/lib/libc/db/recno/rec_seq.c
new file mode 100644
index 00000000..b6430aab
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_seq.c
@@ -0,0 +1,129 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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>
+#ifndef lint
+/* XXX use __SCCSID */
+static char sccsid[] __unused = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94";
+#endif /* not lint */
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEQ -- Recno sequential scan interface.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key for positioning and return value
+ * data: data return value
+ * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__rec_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG *e;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ switch(flags) {
+ case R_CURSOR:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ break;
+ case R_NEXT:
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ nrec = t->bt_cursor.rcursor + 1;
+ break;
+ }
+ /* FALLTHROUGH */
+ case R_FIRST:
+ nrec = 1;
+ break;
+ case R_PREV:
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ if ((nrec = t->bt_cursor.rcursor - 1) == 0)
+ return (RET_SPECIAL);
+ break;
+ }
+ /* FALLTHROUGH */
+ case R_LAST:
+ if (!F_ISSET(t, R_EOF | R_INMEM) &&
+ t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+ return (RET_ERROR);
+ nrec = t->bt_nrecs;
+ break;
+ default:
+einval: errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
+ if (!F_ISSET(t, R_EOF | R_INMEM) &&
+ (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+ return (status);
+ if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
+ return (RET_SPECIAL);
+ }
+
+ if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
+ return (RET_ERROR);
+
+ F_SET(&t->bt_cursor, CURS_INIT);
+ t->bt_cursor.rcursor = nrec;
+
+ status = __rec_ret(t, e, nrec, key, data);
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e->page, 0);
+ else
+ t->bt_pinned = e->page;
+ return (status);
+}
diff --git a/freebsd/lib/libc/db/recno/rec_utils.c b/freebsd/lib/libc/db/recno/rec_utils.c
new file mode 100644
index 00000000..4bd45301
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/rec_utils.c
@@ -0,0 +1,114 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __rec_ret --
+ * Build return data.
+ *
+ * Parameters:
+ * t: tree
+ * e: key/data pair to be returned
+ * nrec: record number
+ * key: user's key structure
+ * data: user's data structure
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_ret(BTREE *t, EPG *e, recno_t nrec, DBT *key, DBT *data)
+{
+ RLEAF *rl;
+ void *p;
+
+ if (key == NULL)
+ goto dataonly;
+
+ /* We have to copy the key, it's not on the page. */
+ if (sizeof(recno_t) > t->bt_rkey.size) {
+ p = realloc(t->bt_rkey.data, sizeof(recno_t));
+ if (p == NULL)
+ return (RET_ERROR);
+ t->bt_rkey.data = p;
+ t->bt_rkey.size = sizeof(recno_t);
+ }
+ memmove(t->bt_rkey.data, &nrec, sizeof(recno_t));
+ key->size = sizeof(recno_t);
+ key->data = t->bt_rkey.data;
+
+dataonly:
+ if (data == NULL)
+ return (RET_SUCCESS);
+
+ /*
+ * We must copy big keys/data to make them contigous. Otherwise,
+ * leave the page pinned and don't copy unless the user specified
+ * concurrent access.
+ */
+ rl = GETRLEAF(e->page, e->index);
+ if (rl->flags & P_BIGDATA) {
+ if (__ovfl_get(t, rl->bytes,
+ &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
+ return (RET_ERROR);
+ data->data = t->bt_rdata.data;
+ } else if (F_ISSET(t, B_DB_LOCK)) {
+ /* Use +1 in case the first record retrieved is 0 length. */
+ if (rl->dsize + 1 > t->bt_rdata.size) {
+ p = realloc(t->bt_rdata.data, rl->dsize + 1);
+ if (p == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.data = p;
+ t->bt_rdata.size = rl->dsize + 1;
+ }
+ memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
+ data->size = rl->dsize;
+ data->data = t->bt_rdata.data;
+ } else {
+ data->size = rl->dsize;
+ data->data = rl->bytes;
+ }
+ return (RET_SUCCESS);
+}
diff --git a/freebsd/lib/libc/db/recno/recno.h b/freebsd/lib/libc/db/recno/recno.h
new file mode 100644
index 00000000..5c561703
--- /dev/null
+++ b/freebsd/lib/libc/db/recno/recno.h
@@ -0,0 +1,36 @@
+/*-
+ * 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.
+ *
+ * @(#)recno.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */
+
+#include "../btree/btree.h"
+#include "extern.h"
diff --git a/freebsd/lib/libc/gen/err.c b/freebsd/lib/libc/gen/err.c
new file mode 100644
index 00000000..bbd5bffc
--- /dev/null
+++ b/freebsd/lib/libc/gen/err.c
@@ -0,0 +1,197 @@
+#include "port_before.h"
+
+/*-
+ * 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.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+/*
+ * This is declared to take a `void *' so that the caller is not required
+ * to include <stdio.h> first. However, it is really a `FILE *', and the
+ * manual page documents it as such.
+ */
+void
+err_set_file(void *fp)
+{
+ if (fp)
+ err_file = fp;
+ else
+ err_file = stderr;
+}
+
+void
+err_set_exit(void (*ef)(int))
+{
+ err_exit = ef;
+}
+
+__weak_reference(_err, err);
+
+void
+_err(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, errno, fmt, ap);
+ va_end(ap);
+}
+
+void
+verr(eval, fmt, ap)
+ int eval;
+ const char *fmt;
+ va_list ap;
+{
+ verrc(eval, errno, fmt, ap);
+}
+
+void
+errc(int eval, int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, code, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrc(int eval, int code, const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL) {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void
+errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrx(int eval, const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+__weak_reference(_warn, warn);
+
+void
+_warn(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(errno, fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarn(const char *fmt, va_list ap)
+{
+ vwarnc(errno, fmt, ap);
+}
+
+void
+warnc(int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(code, fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnc(int code, const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL) {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+}
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnx(const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+}
diff --git a/freebsd/lib/libc/gen/gethostname.c b/freebsd/lib/libc/gen/gethostname.c
new file mode 100644
index 00000000..f744652c
--- /dev/null
+++ b/freebsd/lib/libc/gen/gethostname.c
@@ -0,0 +1,59 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+int
+gethostname(name, namelen)
+ char *name;
+ size_t namelen;
+{
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTNAME;
+ if (sysctl(mib, 2, name, &namelen, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ return (0);
+}
diff --git a/freebsd/lib/libc/include/isc/eventlib.h b/freebsd/lib/libc/include/isc/eventlib.h
new file mode 100644
index 00000000..50038231
--- /dev/null
+++ b/freebsd/lib/libc/include/isc/eventlib.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* eventlib.h - exported interfaces for eventlib
+ * vix 09sep95 [initial]
+ *
+ * $Id: eventlib.h,v 1.3.18.3 2008/01/23 02:12:01 marka Exp $
+ */
+
+#ifndef _EVENTLIB_H
+#define _EVENTLIB_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+#include <isc/platform.h>
+
+#ifndef __P
+# define __EVENTLIB_P_DEFINED
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+/* In the absence of branded types... */
+typedef struct { void *opaque; } evConnID;
+typedef struct { void *opaque; } evFileID;
+typedef struct { void *opaque; } evStreamID;
+typedef struct { void *opaque; } evTimerID;
+typedef struct { void *opaque; } evWaitID;
+typedef struct { void *opaque; } evContext;
+typedef struct { void *opaque; } evEvent;
+
+#define evInitID(id) ((id)->opaque = NULL)
+#define evTestID(id) ((id).opaque != NULL)
+
+typedef void (*evConnFunc)__P((evContext, void *, int, const void *, int,
+ const void *, int));
+typedef void (*evFileFunc)__P((evContext, void *, int, int));
+typedef void (*evStreamFunc)__P((evContext, void *, int, int));
+typedef void (*evTimerFunc)__P((evContext, void *,
+ struct timespec, struct timespec));
+typedef void (*evWaitFunc)__P((evContext, void *, const void *));
+
+typedef struct { unsigned char mask[256/8]; } evByteMask;
+#define EV_BYTEMASK_BYTE(b) ((b) / 8)
+#define EV_BYTEMASK_MASK(b) (1 << ((b) % 8))
+#define EV_BYTEMASK_SET(bm, b) \
+ ((bm).mask[EV_BYTEMASK_BYTE(b)] |= EV_BYTEMASK_MASK(b))
+#define EV_BYTEMASK_CLR(bm, b) \
+ ((bm).mask[EV_BYTEMASK_BYTE(b)] &= ~EV_BYTEMASK_MASK(b))
+#define EV_BYTEMASK_TST(bm, b) \
+ ((bm).mask[EV_BYTEMASK_BYTE(b)] & EV_BYTEMASK_MASK(b))
+
+#define EV_POLL 1
+#define EV_WAIT 2
+#define EV_NULL 4
+
+#define EV_READ 1
+#define EV_WRITE 2
+#define EV_EXCEPT 4
+
+#define EV_WASNONBLOCKING 8 /* Internal library use. */
+
+/* eventlib.c */
+#define evCreate __evCreate
+#define evSetDebug __evSetDebug
+#define evDestroy __evDestroy
+#define evGetNext __evGetNext
+#define evDispatch __evDispatch
+#define evDrop __evDrop
+#define evMainLoop __evMainLoop
+#define evHighestFD __evHighestFD
+#define evGetOption __evGetOption
+#define evSetOption __evSetOption
+
+int evCreate __P((evContext *));
+void evSetDebug __P((evContext, int, FILE *));
+int evDestroy __P((evContext));
+int evGetNext __P((evContext, evEvent *, int));
+int evDispatch __P((evContext, evEvent));
+void evDrop __P((evContext, evEvent));
+int evMainLoop __P((evContext));
+int evHighestFD __P((evContext));
+int evGetOption __P((evContext *, const char *, int *));
+int evSetOption __P((evContext *, const char *, int));
+
+/* ev_connects.c */
+#define evListen __evListen
+#define evConnect __evConnect
+#define evCancelConn __evCancelConn
+#define evHold __evHold
+#define evUnhold __evUnhold
+#define evTryAccept __evTryAccept
+
+int evListen __P((evContext, int, int, evConnFunc, void *, evConnID *));
+int evConnect __P((evContext, int, const void *, int,
+ evConnFunc, void *, evConnID *));
+int evCancelConn __P((evContext, evConnID));
+int evHold __P((evContext, evConnID));
+int evUnhold __P((evContext, evConnID));
+int evTryAccept __P((evContext, evConnID, int *));
+
+/* ev_files.c */
+#define evSelectFD __evSelectFD
+#define evDeselectFD __evDeselectFD
+
+int evSelectFD __P((evContext, int, int, evFileFunc, void *, evFileID *));
+int evDeselectFD __P((evContext, evFileID));
+
+/* ev_streams.c */
+#define evConsIovec __evConsIovec
+#define evWrite __evWrite
+#define evRead __evRead
+#define evTimeRW __evTimeRW
+#define evUntimeRW __evUntimeRW
+#define evCancelRW __evCancelRW
+
+struct iovec evConsIovec __P((void *, size_t));
+int evWrite __P((evContext, int, const struct iovec *, int,
+ evStreamFunc func, void *, evStreamID *));
+int evRead __P((evContext, int, const struct iovec *, int,
+ evStreamFunc func, void *, evStreamID *));
+int evTimeRW __P((evContext, evStreamID, evTimerID timer));
+int evUntimeRW __P((evContext, evStreamID));
+int evCancelRW __P((evContext, evStreamID));
+
+/* ev_timers.c */
+#define evConsTime __evConsTime
+#define evAddTime __evAddTime
+#define evSubTime __evSubTime
+#define evCmpTime __evCmpTime
+#define evTimeSpec __evTimeSpec
+#define evTimeVal __evTimeVal
+
+#define evNowTime __evNowTime
+#define evUTCTime __evUTCTime
+#define evLastEventTime __evLastEventTime
+#define evSetTimer __evSetTimer
+#define evClearTimer __evClearTimer
+#define evConfigTimer __evConfigTimer
+#define evResetTimer __evResetTimer
+#define evSetIdleTimer __evSetIdleTimer
+#define evClearIdleTimer __evClearIdleTimer
+#define evResetIdleTimer __evResetIdleTimer
+#define evTouchIdleTimer __evTouchIdleTimer
+
+struct timespec evConsTime __P((time_t sec, long nsec));
+struct timespec evAddTime __P((struct timespec, struct timespec));
+struct timespec evSubTime __P((struct timespec, struct timespec));
+struct timespec evNowTime __P((void));
+struct timespec evUTCTime __P((void));
+struct timespec evLastEventTime __P((evContext));
+struct timespec evTimeSpec __P((struct timeval));
+struct timeval evTimeVal __P((struct timespec));
+int evCmpTime __P((struct timespec, struct timespec));
+int evSetTimer __P((evContext, evTimerFunc, void *, struct timespec,
+ struct timespec, evTimerID *));
+int evClearTimer __P((evContext, evTimerID));
+int evConfigTimer __P((evContext, evTimerID, const char *param,
+ int value));
+int evResetTimer __P((evContext, evTimerID, evTimerFunc, void *,
+ struct timespec, struct timespec));
+int evSetIdleTimer __P((evContext, evTimerFunc, void *, struct timespec,
+ evTimerID *));
+int evClearIdleTimer __P((evContext, evTimerID));
+int evResetIdleTimer __P((evContext, evTimerID, evTimerFunc, void *,
+ struct timespec));
+int evTouchIdleTimer __P((evContext, evTimerID));
+
+/* ev_waits.c */
+#define evWaitFor __evWaitFor
+#define evDo __evDo
+#define evUnwait __evUnwait
+#define evDefer __evDefer
+
+int evWaitFor __P((evContext, const void *, evWaitFunc, void *, evWaitID *));
+int evDo __P((evContext, const void *));
+int evUnwait __P((evContext, evWaitID));
+int evDefer __P((evContext, evWaitFunc, void *));
+
+#ifdef __EVENTLIB_P_DEFINED
+# undef __P
+#endif
+
+#endif /*_EVENTLIB_H*/
+
+/*! \file */
diff --git a/freebsd/lib/libc/include/isc/list.h b/freebsd/lib/libc/include/isc/list.h
new file mode 100644
index 00000000..fef631b4
--- /dev/null
+++ b/freebsd/lib/libc/include/isc/list.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1997,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $FreeBSD$ */
+
+#ifndef LIST_H
+#define LIST_H 1
+#ifdef _LIBC
+#include <assert.h>
+#define INSIST(cond) assert(cond)
+#else
+#include <isc/assertions.h>
+#endif
+
+#define LIST(type) struct { type *head, *tail; }
+#define INIT_LIST(list) \
+ do { (list).head = NULL; (list).tail = NULL; } while (0)
+
+#define LINK(type) struct { type *prev, *next; }
+#define INIT_LINK_TYPE(elt, link, type) \
+ do { \
+ (elt)->link.prev = (type *)(-1); \
+ (elt)->link.next = (type *)(-1); \
+ } while (0)
+#define INIT_LINK(elt, link) \
+ INIT_LINK_TYPE(elt, link, void)
+#define LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1))
+
+#define HEAD(list) ((list).head)
+#define TAIL(list) ((list).tail)
+#define EMPTY(list) ((list).head == NULL)
+
+#define PREPEND(list, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((list).head != NULL) \
+ (list).head->link.prev = (elt); \
+ else \
+ (list).tail = (elt); \
+ (elt)->link.prev = NULL; \
+ (elt)->link.next = (list).head; \
+ (list).head = (elt); \
+ } while (0)
+
+#define APPEND(list, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((list).tail != NULL) \
+ (list).tail->link.next = (elt); \
+ else \
+ (list).head = (elt); \
+ (elt)->link.prev = (list).tail; \
+ (elt)->link.next = NULL; \
+ (list).tail = (elt); \
+ } while (0)
+
+#define UNLINK_TYPE(list, elt, link, type) \
+ do { \
+ INSIST(LINKED(elt, link));\
+ if ((elt)->link.next != NULL) \
+ (elt)->link.next->link.prev = (elt)->link.prev; \
+ else { \
+ INSIST((list).tail == (elt)); \
+ (list).tail = (elt)->link.prev; \
+ } \
+ if ((elt)->link.prev != NULL) \
+ (elt)->link.prev->link.next = (elt)->link.next; \
+ else { \
+ INSIST((list).head == (elt)); \
+ (list).head = (elt)->link.next; \
+ } \
+ INIT_LINK_TYPE(elt, link, type); \
+ } while (0)
+#define UNLINK(list, elt, link) \
+ UNLINK_TYPE(list, elt, link, void)
+
+#define PREV(elt, link) ((elt)->link.prev)
+#define NEXT(elt, link) ((elt)->link.next)
+
+#define INSERT_BEFORE(list, before, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((before)->link.prev == NULL) \
+ PREPEND(list, elt, link); \
+ else { \
+ (elt)->link.prev = (before)->link.prev; \
+ (before)->link.prev = (elt); \
+ (elt)->link.prev->link.next = (elt); \
+ (elt)->link.next = (before); \
+ } \
+ } while (0)
+
+#define INSERT_AFTER(list, after, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((after)->link.next == NULL) \
+ APPEND(list, elt, link); \
+ else { \
+ (elt)->link.next = (after)->link.next; \
+ (after)->link.next = (elt); \
+ (elt)->link.next->link.prev = (elt); \
+ (elt)->link.prev = (after); \
+ } \
+ } while (0)
+
+#define ENQUEUE(list, elt, link) APPEND(list, elt, link)
+#define DEQUEUE(list, elt, link) UNLINK(list, elt, link)
+
+#endif /* LIST_H */
+/*! \file */
diff --git a/freebsd/lib/libc/include/isc/platform.h b/freebsd/lib/libc/include/isc/platform.h
new file mode 100644
index 00000000..bd11a255
--- /dev/null
+++ b/freebsd/lib/libc/include/isc/platform.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 1999-2001 Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: platform.h.in,v 1.28 2001/11/19 03:08:26 mayer Exp $ */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H 1
+
+
+#ifndef ISC_PLATFORM_USEDECLSPEC
+#define LIBISC_EXTERNAL_DATA
+#define LIBDNS_EXTERNAL_DATA
+#define LIBISCCC_EXTERNAL_DATA
+#define LIBISCCFG_EXTERNAL_DATA
+#define LIBBIND9_EXTERNAL_DATA
+#endif /* ISC_PLATFORM_USEDECLSPEC */
+
+/*
+ * Tell emacs to use C mode for this file.
+ *
+ * Local Variables:
+ * mode: c
+ * End:
+ */
+
+#endif /* ISC_PLATFORM_H */
diff --git a/freebsd/lib/libc/include/libc_private.h b/freebsd/lib/libc/include/libc_private.h
new file mode 100644
index 00000000..060f77e0
--- /dev/null
+++ b/freebsd/lib/libc/include/libc_private.h
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
+ * 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 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 JOHN BIRRELL 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$
+ *
+ * Private definitions for libc, libc_r and libpthread.
+ *
+ */
+
+#ifndef _LIBC_PRIVATE_H_
+#define _LIBC_PRIVATE_H_
+#include <sys/_pthreadtypes.h>
+
+/*
+ * This global flag is non-zero when a process has created one
+ * or more threads. It is used to avoid calling locking functions
+ * when they are not required.
+ */
+#ifdef __rtems__
+#define __isthreaded 1
+#else
+extern int __isthreaded;
+#endif
+
+/*
+ * libc should use libc_dlopen internally, which respects a global
+ * flag where loading of new shared objects can be restricted.
+ */
+void *libc_dlopen(const char *, int);
+
+/*
+ * For dynamic linker.
+ */
+void _rtld_error(const char *fmt, ...);
+
+/*
+ * File lock contention is difficult to diagnose without knowing
+ * where locks were set. Allow a debug library to be built which
+ * records the source file and line number of each lock call.
+ */
+#ifdef _FLOCK_DEBUG
+#define _FLOCKFILE(x) _flockfile_debug(x, __FILE__, __LINE__)
+#else
+#define _FLOCKFILE(x) _flockfile(x)
+#endif
+
+/*
+ * Macros for locking and unlocking FILEs. These test if the
+ * process is threaded to avoid locking when not required.
+ */
+#define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp)
+#define FUNLOCKFILE(fp) if (__isthreaded) _funlockfile(fp)
+
+/*
+ * Indexes into the pthread jump table.
+ *
+ * Warning! If you change this type, you must also change the threads
+ * libraries that reference it (libc_r, libpthread).
+ */
+typedef enum {
+ PJT_ATFORK,
+ PJT_ATTR_DESTROY,
+ PJT_ATTR_GETDETACHSTATE,
+ PJT_ATTR_GETGUARDSIZE,
+ PJT_ATTR_GETINHERITSCHED,
+ PJT_ATTR_GETSCHEDPARAM,
+ PJT_ATTR_GETSCHEDPOLICY,
+ PJT_ATTR_GETSCOPE,
+ PJT_ATTR_GETSTACKADDR,
+ PJT_ATTR_GETSTACKSIZE,
+ PJT_ATTR_INIT,
+ PJT_ATTR_SETDETACHSTATE,
+ PJT_ATTR_SETGUARDSIZE,
+ PJT_ATTR_SETINHERITSCHED,
+ PJT_ATTR_SETSCHEDPARAM,
+ PJT_ATTR_SETSCHEDPOLICY,
+ PJT_ATTR_SETSCOPE,
+ PJT_ATTR_SETSTACKADDR,
+ PJT_ATTR_SETSTACKSIZE,
+ PJT_CANCEL,
+ PJT_CLEANUP_POP,
+ PJT_CLEANUP_PUSH,
+ PJT_COND_BROADCAST,
+ PJT_COND_DESTROY,
+ PJT_COND_INIT,
+ PJT_COND_SIGNAL,
+ PJT_COND_TIMEDWAIT,
+ PJT_COND_WAIT,
+ PJT_DETACH,
+ PJT_EQUAL,
+ PJT_EXIT,
+ PJT_GETSPECIFIC,
+ PJT_JOIN,
+ PJT_KEY_CREATE,
+ PJT_KEY_DELETE,
+ PJT_KILL,
+ PJT_MAIN_NP,
+ PJT_MUTEXATTR_DESTROY,
+ PJT_MUTEXATTR_INIT,
+ PJT_MUTEXATTR_SETTYPE,
+ PJT_MUTEX_DESTROY,
+ PJT_MUTEX_INIT,
+ PJT_MUTEX_LOCK,
+ PJT_MUTEX_TRYLOCK,
+ PJT_MUTEX_UNLOCK,
+ PJT_ONCE,
+ PJT_RWLOCK_DESTROY,
+ PJT_RWLOCK_INIT,
+ PJT_RWLOCK_RDLOCK,
+ PJT_RWLOCK_TRYRDLOCK,
+ PJT_RWLOCK_TRYWRLOCK,
+ PJT_RWLOCK_UNLOCK,
+ PJT_RWLOCK_WRLOCK,
+ PJT_SELF,
+ PJT_SETCANCELSTATE,
+ PJT_SETCANCELTYPE,
+ PJT_SETSPECIFIC,
+ PJT_SIGMASK,
+ PJT_TESTCANCEL,
+ PJT_MAX
+} pjt_index_t;
+
+typedef int (*pthread_func_t)(void);
+typedef pthread_func_t pthread_func_entry_t[2];
+
+extern pthread_func_entry_t __thr_jtable[];
+
+/*
+ * yplib internal interfaces
+ */
+#ifdef YP
+int _yp_check(char **);
+#endif
+
+/*
+ * Initialise TLS for static programs
+ */
+void _init_tls(void);
+
+/*
+ * Provides pthread_once()-like functionality for both single-threaded
+ * and multi-threaded applications.
+ */
+int _once(pthread_once_t *, void (*)(void));
+
+/*
+ * Set the TLS thread pointer
+ */
+void _set_tp(void *tp);
+
+/*
+ * This is a pointer in the C run-time startup code. It is used
+ * by getprogname() and setprogname().
+ */
+extern const char *__progname;
+
+/*
+ * This function is used by the threading libraries to notify malloc that a
+ * thread is exiting.
+ */
+void _malloc_thread_cleanup(void);
+
+/*
+ * These functions are used by the threading libraries in order to protect
+ * malloc across fork().
+ */
+void _malloc_prefork(void);
+void _malloc_postfork(void);
+
+/*
+ * Function to clean up streams, called from abort() and exit().
+ */
+extern void (*__cleanup)(void);
+
+/*
+ * Get kern.osreldate to detect ABI revisions. Explicitly
+ * ignores value of $OSVERSION and caches result. Prototypes
+ * for the wrapped "new" pad-less syscalls are here for now.
+ */
+extern int __getosreldate(void);
+#include <sys/_types.h>
+/* Without pad */
+extern __off_t __sys_lseek(int, __off_t, int);
+extern int __sys_ftruncate(int, __off_t);
+extern int __sys_truncate(const char *, __off_t);
+extern __ssize_t __sys_pread(int, void *, __size_t, __off_t);
+extern __ssize_t __sys_pwrite(int, const void *, __size_t, __off_t);
+extern void * __sys_mmap(void *, __size_t, int, int, int, __off_t);
+
+/* With pad */
+extern __off_t __sys_freebsd6_lseek(int, int, __off_t, int);
+extern int __sys_freebsd6_ftruncate(int, int, __off_t);
+extern int __sys_freebsd6_truncate(const char *, int, __off_t);
+extern __ssize_t __sys_freebsd6_pread(int, void *, __size_t, int, __off_t);
+extern __ssize_t __sys_freebsd6_pwrite(int, const void *, __size_t, int, __off_t);
+extern void * __sys_freebsd6_mmap(void *, __size_t, int, int, int, int, __off_t);
+
+/* Without back-compat translation */
+extern int __sys_fcntl(int, int, ...);
+
+/* execve() with PATH processing to implement posix_spawnp() */
+int _execvpe(const char *, char * const *, char * const *);
+
+#endif /* _LIBC_PRIVATE_H_ */
diff --git a/freebsd/lib/libc/include/namespace.h b/freebsd/lib/libc/include/namespace.h
new file mode 100644
index 00000000..83be334e
--- /dev/null
+++ b/freebsd/lib/libc/include/namespace.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) XXX
+ * 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 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 _NAMESPACE_H_
+#define _NAMESPACE_H_
+
+/*
+ * Reverse the use of "hidden" names in the source code.
+ *
+ * README: When modifying this file don't forget to make the appropriate
+ * changes in un-namespace.h!!!
+ */
+
+
+#define _pthread_getspecific pthread_getspecific
+#define _pthread_key_create pthread_key_create
+#define _pthread_main_np pthread_main_np
+#define _pthread_once pthread_once
+#define _pthread_setspecific pthread_setspecific
+#define _pthread_mutex_trylock pthread_mutex_trylock
+#define _pthread_mutex_unlock pthread_mutex_unlock
+#define _pthread_rwlock_rdlock pthread_rwlock_rdlock
+#define _pthread_rwlock_unlock pthread_rwlock_unlock
+#define _pthread_rwlock_wrlock pthread_rwlock_wrlock
+
+#define _open open
+#define _close close
+#define _read read
+#define _write write
+#define _writev writev
+#define _fcntl fcntl
+#define _fsync fsync
+#define _fstat fstat
+#define _stat stat
+#define _ioctl ioctl
+
+#define _sigprocmask sigprocmask
+
+#define _recvfrom recvfrom
+#define _sendto sendto
+#define _setsockopt setsockopt
+#define _socket socket
+#define _connect connect
+#define _getpeername getpeername
+#define _getprogname getprogname
+#define _getsockname getsockname
+
+#endif /* _NAMESPACE_H_ */
diff --git a/freebsd/lib/libc/include/nss_tls.h b/freebsd/lib/libc/include/nss_tls.h
new file mode 100644
index 00000000..03cf9923
--- /dev/null
+++ b/freebsd/lib/libc/include/nss_tls.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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$
+ *
+ * Macros which generate thread local storage handling code in NSS modules.
+ */
+#ifndef _NSS_TLS_H_
+#define _NSS_TLS_H_
+
+#define NSS_TLS_HANDLING(name) \
+static pthread_key_t name##_state_key; \
+static void name##_keyinit(void); \
+static int name##_getstate(struct name##_state **); \
+\
+static void \
+name##_keyinit(void) \
+{ \
+ (void)_pthread_key_create(&name##_state_key, name##_endstate); \
+} \
+\
+static int \
+name##_getstate(struct name##_state **p) \
+{ \
+ static pthread_once_t keyinit = PTHREAD_ONCE_INIT; \
+ int rv; \
+ \
+ rv = _pthread_once(&keyinit, name##_keyinit); \
+ if (rv != 0) \
+ return (rv); \
+ *p = _pthread_getspecific(name##_state_key); \
+ if (*p != NULL) \
+ return (0); \
+ *p = calloc(1, sizeof(**p)); \
+ if (*p == NULL) \
+ return (ENOMEM); \
+ rv = _pthread_setspecific(name##_state_key, *p); \
+ if (rv != 0) { \
+ free(*p); \
+ *p = NULL; \
+ } \
+ return (rv); \
+} \
+/* allow the macro invocation to end with a semicolon */ \
+struct _clashproof_bmVjdGFy
+
+#endif /* _NSS_TLS_H_ */
diff --git a/freebsd/local/opt_altq.h b/freebsd/lib/libc/include/port_after.h
index e69de29b..e69de29b 100644
--- a/freebsd/local/opt_altq.h
+++ b/freebsd/lib/libc/include/port_after.h
diff --git a/freebsd/lib/libc/include/port_before.h b/freebsd/lib/libc/include/port_before.h
new file mode 100644
index 00000000..64075171
--- /dev/null
+++ b/freebsd/lib/libc/include/port_before.h
@@ -0,0 +1,41 @@
+#include <freebsd/bsd.h>
+
+#include <freebsd/sys/_types.h>
+
+/*********************************************************************
+ * These are also defined in the FreeBSD version of this file.
+ *********************************************************************/
+
+#define _LIBC 1
+/*
+ * This is defined in the FreeBSD source but we have no code yet which
+ * relies upon it.
+ */
+/* #define DO_PTHREADS 1 */
+#define USE_KQUEUE 1
+
+#define ISC_SOCKLEN_T socklen_t
+#define ISC_FORMAT_PRINTF(fmt, args) \
+ __attribute__((__format__(__printf__, fmt, args)))
+#define DE_CONST(konst, var) \
+ do { \
+ union { const void *k; void *v; } _u; \
+ _u.k = konst; \
+ var = _u.v; \
+ } while (0)
+
+#define UNUSED(x) (x) = (x)
+
+
+/*********************************************************************
+ * FROM HERE DOWN, THESE ARE NOT IN THE FreeBSD VERSION!!!
+ *********************************************************************/
+#ifndef __ssize_t
+#define __ssize_t ssize_t
+#endif
+
+#include <freebsd/machine/_align.h>
+
+#ifdef __rtems__
+#include <freebsd/machine/endian.h>
+#endif
diff --git a/freebsd/lib/libc/include/reentrant.h b/freebsd/lib/libc/include/reentrant.h
new file mode 100644
index 00000000..8ab328bc
--- /dev/null
+++ b/freebsd/lib/libc/include/reentrant.h
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 1997,98 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Requirements:
+ *
+ * 1. The thread safe mechanism should be lightweight so the library can
+ * be used by non-threaded applications without unreasonable overhead.
+ *
+ * 2. There should be no dependency on a thread engine for non-threaded
+ * applications.
+ *
+ * 3. There should be no dependency on any particular thread engine.
+ *
+ * 4. The library should be able to be compiled without support for thread
+ * safety.
+ *
+ *
+ * Rationale:
+ *
+ * One approach for thread safety is to provide discrete versions of the
+ * library: one thread safe, the other not. The disadvantage of this is
+ * that libc is rather large, and two copies of a library which are 99%+
+ * identical is not an efficent use of resources.
+ *
+ * Another approach is to provide a single thread safe library. However,
+ * it should not add significant run time or code size overhead to non-
+ * threaded applications.
+ *
+ * Since the NetBSD C library is used in other projects, it should be
+ * easy to replace the mutual exclusion primitives with ones provided by
+ * another system. Similarly, it should also be easy to remove all
+ * support for thread safety completely if the target environment does
+ * not support threads.
+ *
+ *
+ * Implementation Details:
+ *
+ * The mutex primitives used by the library (mutex_t, mutex_lock, etc.)
+ * are macros which expand to the cooresponding primitives provided by
+ * the thread engine or to nothing. The latter is used so that code is
+ * not unreasonably cluttered with #ifdefs when all thread safe support
+ * is removed.
+ *
+ * The mutex macros can be directly mapped to the mutex primitives from
+ * pthreads, however it should be reasonably easy to wrap another mutex
+ * implementation so it presents a similar interface.
+ *
+ * Stub implementations of the mutex functions are provided with *weak*
+ * linkage. These functions simply return success. When linked with a
+ * thread library (i.e. -lpthread), the functions will override the
+ * stubs.
+ */
+
+#include <pthread.h>
+#include <pthread_np.h>
+#include "libc_private.h"
+
+#define mutex_t pthread_mutex_t
+#define cond_t pthread_cond_t
+#define rwlock_t pthread_rwlock_t
+#define once_t pthread_once_t
+
+#define thread_key_t pthread_key_t
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
+#define ONCE_INITIALIZER PTHREAD_ONCE_INIT
+
+#define mutex_init(m, a) _pthread_mutex_init(m, a)
+#define mutex_lock(m) if (__isthreaded) \
+ _pthread_mutex_lock(m)
+#define mutex_unlock(m) if (__isthreaded) \
+ _pthread_mutex_unlock(m)
+#define mutex_trylock(m) (__isthreaded ? 0 : _pthread_mutex_trylock(m))
+
+#define cond_init(c, a, p) _pthread_cond_init(c, a)
+#define cond_signal(m) if (__isthreaded) \
+ _pthread_cond_signal(m)
+#define cond_broadcast(m) if (__isthreaded) \
+ _pthread_cond_broadcast(m)
+#define cond_wait(c, m) if (__isthreaded) \
+ _pthread_cond_wait(c, m)
+
+#define rwlock_init(l, a) _pthread_rwlock_init(l, a)
+#define rwlock_rdlock(l) if (__isthreaded) \
+ _pthread_rwlock_rdlock(l)
+#define rwlock_wrlock(l) if (__isthreaded) \
+ _pthread_rwlock_wrlock(l)
+#define rwlock_unlock(l) if (__isthreaded) \
+ _pthread_rwlock_unlock(l)
+
+#define thr_keycreate(k, d) _pthread_key_create(k, d)
+#define thr_setspecific(k, p) _pthread_setspecific(k, p)
+#define thr_getspecific(k) _pthread_getspecific(k)
+#define thr_sigsetmask(f, n, o) _pthread_sigmask(f, n, o)
+
+#define thr_once(o, i) _pthread_once(o, i)
+#define thr_self() _pthread_self()
+#define thr_exit(x) _pthread_exit(x)
+#define thr_main() _pthread_main_np()
diff --git a/freebsd/lib/libc/include/resolv_mt.h b/freebsd/lib/libc/include/resolv_mt.h
new file mode 100644
index 00000000..27963a12
--- /dev/null
+++ b/freebsd/lib/libc/include/resolv_mt.h
@@ -0,0 +1,47 @@
+#ifndef _RESOLV_MT_H
+#define _RESOLV_MT_H
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+/* Access functions for the libresolv private interface */
+
+int __res_enable_mt(void);
+int __res_disable_mt(void);
+
+/* Per-thread context */
+
+typedef struct {
+int no_hosts_fallback_private;
+int retry_save;
+int retry_private;
+char inet_nsap_ntoa_tmpbuf[255*3];
+char sym_ntos_unname[20];
+char sym_ntop_unname[20];
+char p_option_nbuf[40];
+char p_time_nbuf[40];
+char precsize_ntoa_retbuf[sizeof "90000000.00"];
+char loc_ntoa_tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+char p_secstodate_output[15];
+} mtctxres_t;
+
+/* Thread-specific data (TSD) */
+
+mtctxres_t *___mtctxres(void);
+#define mtctxres (___mtctxres())
+
+/* Various static data that should be TSD */
+
+#define sym_ntos_unname (mtctxres->sym_ntos_unname)
+#define sym_ntop_unname (mtctxres->sym_ntop_unname)
+#define inet_nsap_ntoa_tmpbuf (mtctxres->inet_nsap_ntoa_tmpbuf)
+#define p_option_nbuf (mtctxres->p_option_nbuf)
+#define p_time_nbuf (mtctxres->p_time_nbuf)
+#define precsize_ntoa_retbuf (mtctxres->precsize_ntoa_retbuf)
+#define loc_ntoa_tmpbuf (mtctxres->loc_ntoa_tmpbuf)
+#define p_secstodate_output (mtctxres->p_secstodate_output)
+
+#endif /* _RESOLV_MT_H */
diff --git a/freebsd/lib/libc/include/spinlock.h b/freebsd/lib/libc/include/spinlock.h
new file mode 100644
index 00000000..c9facc51
--- /dev/null
+++ b/freebsd/lib/libc/include/spinlock.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
+ * 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 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 JOHN BIRRELL 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$
+ *
+ * Lock definitions used in both libc and libpthread.
+ *
+ */
+
+#ifndef _SPINLOCK_H_
+#define _SPINLOCK_H_
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*
+ * Lock structure with room for debugging information.
+ */
+struct _spinlock {
+ volatile long access_lock;
+ volatile long lock_owner;
+ volatile char *fname;
+ volatile int lineno;
+};
+typedef struct _spinlock spinlock_t;
+
+#define _SPINLOCK_INITIALIZER { 0, 0, 0, 0 }
+
+#define _SPINUNLOCK(_lck) _spinunlock(_lck);
+#ifdef _LOCK_DEBUG
+#define _SPINLOCK(_lck) _spinlock_debug(_lck, __FILE__, __LINE__)
+#else
+#define _SPINLOCK(_lck) _spinlock(_lck)
+#endif
+
+/*
+ * Thread function prototype definitions:
+ */
+__BEGIN_DECLS
+long _atomic_lock(volatile long *);
+void _spinlock(spinlock_t *);
+void _spinunlock(spinlock_t *);
+void _spinlock_debug(spinlock_t *, char *, int);
+__END_DECLS
+
+#endif /* _SPINLOCK_H_ */
diff --git a/freebsd/lib/libc/include/un-namespace.h b/freebsd/lib/libc/include/un-namespace.h
new file mode 100644
index 00000000..287a2382
--- /dev/null
+++ b/freebsd/lib/libc/include/un-namespace.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) XXX
+ * 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 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 _UN_NAMESPACE_H_
+#define _UN_NAMESPACE_H_
+
+#endif /* _UN_NAMESPACE_H_ */
diff --git a/freebsd/lib/libc/inet/inet_addr.c b/freebsd/lib/libc/inet/inet_addr.c
new file mode 100644
index 00000000..e606d345
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_addr.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static const char rcsid[] = "$Id: inet_addr.c,v 1.4.18.1 2005/04/27 05:00:52 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+
+#include "port_after.h"
+
+/*%
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+in_addr_t /* XXX should be struct in_addr :( */
+inet_addr(const char *cp) {
+ struct in_addr val;
+
+ if (inet_aton(cp, &val))
+ return (val.s_addr);
+ return (INADDR_NONE);
+}
+
+/*%
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr) {
+ u_long val;
+ int base, n;
+ char c;
+ u_int8_t parts[4];
+ u_int8_t *pp = parts;
+ int digit;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit((unsigned char)c))
+ return (0);
+ val = 0; base = 10; digit = 0;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
+ else {
+ base = 8;
+ digit = 1 ;
+ }
+ }
+ for (;;) {
+ if (isascii(c) && isdigit((unsigned char)c)) {
+ if (base == 8 && (c == '8' || c == '9'))
+ return (0);
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ digit = 1;
+ } else if (base == 16 && isascii(c) &&
+ isxdigit((unsigned char)c)) {
+ val = (val << 4) |
+ (c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
+ c = *++cp;
+ digit = 1;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xffU)
+ return (0);
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace((unsigned char)c)))
+ return (0);
+ /*
+ * Did we get a valid digit?
+ */
+ if (!digit)
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+ case 1: /*%< a -- 32 bits */
+ break;
+
+ case 2: /*%< a.b -- 8.24 bits */
+ if (val > 0xffffffU)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /*%< a.b.c -- 8.8.16 bits */
+ if (val > 0xffffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /*%< a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr != NULL)
+ addr->s_addr = htonl(val);
+ return (1);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_addr
+__weak_reference(__inet_addr, inet_addr);
+#undef inet_aton
+__weak_reference(__inet_aton, inet_aton);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_cidr_ntop.c b/freebsd/lib/libc/inet/inet_cidr_ntop.c
new file mode 100644
index 00000000..645b3cd5
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_cidr_ntop.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1998,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 1.4.18.3 2006/10/11 02:32:47 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char *
+inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size);
+static char *
+inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size);
+
+/*%
+ * char *
+ * inet_cidr_ntop(af, src, bits, dst, size)
+ * convert network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by inet_net_ntop() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+char *
+inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_cidr_ntop_ipv4(src, bits, dst, size));
+ case AF_INET6:
+ return (inet_cidr_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+static int
+decoct(const u_char *src, int bytes, char *dst, size_t size) {
+ char *odst = dst;
+ char *t;
+ int b;
+
+ for (b = 1; b <= bytes; b++) {
+ if (size < sizeof "255.")
+ return (0);
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b != bytes) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+ return (dst - odst);
+}
+
+/*%
+ * static char *
+ * inet_cidr_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+static char *
+inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) {
+ char *odst = dst;
+ size_t len = 4;
+ size_t b;
+ size_t bytes;
+
+ if ((bits < -1) || (bits > 32)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Find number of significant bytes in address. */
+ if (bits == -1)
+ len = 4;
+ else
+ for (len = 1, b = 1 ; b < 4U; b++)
+ if (*(src + b))
+ len = b + 1;
+
+ /* Format whole octets plus nonzero trailing octets. */
+ bytes = (((bits <= 0) ? 1 : bits) + 7) / 8;
+ if (len > bytes)
+ bytes = len;
+ b = decoct(src, bytes, dst, size);
+ if (b == 0U)
+ goto emsgsize;
+ dst += b;
+ size -= b;
+
+ if (bits != -1) {
+ /* Format CIDR /width. */
+ if (size < sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ }
+
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+static char *
+inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
+ char *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ if ((bits < -1) || (bits > 128)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ int n;
+
+ if (src[15] || bits == -1 || bits > 120)
+ n = 4;
+ else if (src[14] || bits > 112)
+ n = 3;
+ else
+ n = 2;
+ n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp));
+ if (n == 0) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp = '\0';
+
+ if (bits != -1)
+ tp += SPRINTF((tp, "/%u", bits));
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_cidr_pton.c b/freebsd/lib/libc/inet/inet_cidr_pton.c
new file mode 100644
index 00000000..b0586ff3
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_cidr_pton.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1998,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_cidr_pton.c,v 1.5.18.1 2005/04/27 05:00:53 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst,
+ int *bits, int ipv6));
+static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst,
+ int *bits));
+
+static int getbits(const char *, int ipv6);
+
+/*%
+ * int
+ * inet_cidr_pton(af, src, dst, *bits)
+ * convert network address from presentation to network format.
+ * accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
+ * "dst" is assumed large enough for its "af". "bits" is set to the
+ * /CIDR prefix length, which can have defaults (like /32 for IPv4).
+ * return:
+ * -1 if an error occurred (inspect errno; ENOENT means bad format).
+ * 0 if successful conversion occurred.
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by inet_net_pton() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+int
+inet_cidr_pton(int af, const char *src, void *dst, int *bits) {
+ switch (af) {
+ case AF_INET:
+ return (inet_cidr_pton_ipv4(src, dst, bits, 0));
+ case AF_INET6:
+ return (inet_cidr_pton_ipv6(src, dst, bits));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+static const char digits[] = "0123456789";
+
+static int
+inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) {
+ const u_char *odst = dst;
+ int n, ch, tmp, bits;
+ size_t size = 4;
+
+ /* Get the mantissa. */
+ while (ch = *src++, (isascii(ch) && isdigit(ch))) {
+ tmp = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (size-- == 0U)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ }
+
+ /* Get the prefix length if any. */
+ bits = -1;
+ if (ch == '/' && dst > odst) {
+ bits = getbits(src, ipv6);
+ if (bits == -2)
+ goto enoent;
+ } else if (ch != '\0')
+ goto enoent;
+
+ /* Prefix length can default to /32 only if all four octets spec'd. */
+ if (bits == -1) {
+ if (dst - odst == 4)
+ bits = ipv6 ? 128 : 32;
+ else
+ goto enoent;
+ }
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+
+ /* If prefix length overspecifies mantissa, life is bad. */
+ if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst))
+ goto enoent;
+
+ /* Extend address to four octets. */
+ while (size-- > 0U)
+ *dst++ = 0;
+
+ *pbits = bits;
+ return (0);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int bits;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ bits = -1;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return (0);
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+ if (ch == '/') {
+ bits = getbits(src, 1);
+ if (bits == -2)
+ goto enoent;
+ break;
+ }
+ goto enoent;
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ goto emsgsize;
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ goto enoent;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+
+ *pbits = bits;
+ return (0);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+getbits(const char *src, int ipv6) {
+ int bits = 0;
+ char *cp, ch;
+
+ if (*src == '\0') /*%< syntax */
+ return (-2);
+ do {
+ ch = *src++;
+ cp = strchr(digits, ch);
+ if (cp == NULL) /*%< syntax */
+ return (-2);
+ bits *= 10;
+ bits += cp - digits;
+ if (bits == 0 && *src != '\0') /*%< no leading zeros */
+ return (-2);
+ if (bits > (ipv6 ? 128 : 32)) /*%< range error */
+ return (-2);
+ } while (*src != '\0');
+
+ return (bits);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_lnaof.c b/freebsd/lib/libc/inet/inet_lnaof.c
new file mode 100644
index 00000000..7cab8946
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_lnaof.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*%
+ * Return the local network address portion of an
+ * internet address; handles class a/b/c network
+ * number formats.
+ */
+in_addr_t
+inet_lnaof(in)
+ struct in_addr in;
+{
+ in_addr_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return ((i)&IN_CLASSA_HOST);
+ else if (IN_CLASSB(i))
+ return ((i)&IN_CLASSB_HOST);
+ else
+ return ((i)&IN_CLASSC_HOST);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_lnaof
+__weak_reference(__inet_lnaof, inet_lnaof);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_makeaddr.c b/freebsd/lib/libc/inet/inet_makeaddr.c
new file mode 100644
index 00000000..04a37a03
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_makeaddr.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*%
+ * Formulate an Internet address from network + host. Used in
+ * building addresses stored in the ifnet structure.
+ */
+struct in_addr
+inet_makeaddr(net, host)
+ in_addr_t net, host;
+{
+ struct in_addr a;
+
+ if (net < 128U)
+ a.s_addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
+ else if (net < 65536U)
+ a.s_addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
+ else if (net < 16777216L)
+ a.s_addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
+ else
+ a.s_addr = net | host;
+ a.s_addr = htonl(a.s_addr);
+ return (a);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_makeaddr
+__weak_reference(__inet_makeaddr, inet_makeaddr);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_net_ntop.c b/freebsd/lib/libc/inet/inet_net_ntop.c
new file mode 100644
index 00000000..867f441a
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_net_ntop.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.3.18.2 2006/06/20 02:51:32 marka Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_net_ntop_ipv4(const u_char *src, int bits, char *dst,
+ size_t size);
+static char * inet_net_ntop_ipv6(const u_char *src, int bits, char *dst,
+ size_t size);
+
+/*%
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ * convert network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(af, src, bits, dst, size)
+ int af;
+ const void *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ case AF_INET6:
+ return (inet_net_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*%
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(src, bits, dst, size)
+ const u_char *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ char *odst = dst;
+ char *t;
+ u_int m;
+ int b;
+
+ if (bits < 0 || bits > 32) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (bits == 0) {
+ if (size < sizeof "0")
+ goto emsgsize;
+ *dst++ = '0';
+ size--;
+ *dst = '\0';
+ }
+
+ /* Format whole octets. */
+ for (b = bits / 8; b > 0; b--) {
+ if (size <= sizeof "255.")
+ goto emsgsize;
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b > 1) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format partial octet. */
+ b = bits % 8;
+ if (b > 0) {
+ if (size <= sizeof ".255")
+ goto emsgsize;
+ t = dst;
+ if (dst != odst)
+ *dst++ = '.';
+ m = ((1 << b) - 1) << (8 - b);
+ dst += SPRINTF((dst, "%u", *src & m));
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format CIDR /width. */
+ if (size <= sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*%
+ * static char *
+ * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
+ * convert IPv6 network number from network to presentation format.
+ * generates CIDR style result always. Picks the shortest representation
+ * unless the IP is really IPv4.
+ * always prints specified number of bits (bits).
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Vadim Kogan (UCB), June 2001
+ * Original version (IPv4) by Paul Vixie (ISC), July 1996
+ */
+
+static char *
+inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
+ u_int m;
+ int b;
+ int p;
+ int zero_s, zero_l, tmp_zero_s, tmp_zero_l;
+ int i;
+ int is_ipv4 = 0;
+ unsigned char inbuf[16];
+ char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
+ char *cp;
+ int words;
+ u_char *s;
+
+ if (bits < 0 || bits > 128) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ cp = outbuf;
+
+ if (bits == 0) {
+ *cp++ = ':';
+ *cp++ = ':';
+ *cp = '\0';
+ } else {
+ /* Copy src to private buffer. Zero host part. */
+ p = (bits + 7) / 8;
+ memcpy(inbuf, src, p);
+ memset(inbuf + p, 0, 16 - p);
+ b = bits % 8;
+ if (b != 0) {
+ m = ~0 << (8 - b);
+ inbuf[p-1] &= m;
+ }
+
+ s = inbuf;
+
+ /* how many words need to be displayed in output */
+ words = (bits + 15) / 16;
+ if (words == 1)
+ words = 2;
+
+ /* Find the longest substring of zero's */
+ zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
+ for (i = 0; i < (words * 2); i += 2) {
+ if ((s[i] | s[i+1]) == 0) {
+ if (tmp_zero_l == 0)
+ tmp_zero_s = i / 2;
+ tmp_zero_l++;
+ } else {
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ tmp_zero_l = 0;
+ }
+ }
+ }
+
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ }
+
+ if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
+ ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
+ ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
+ is_ipv4 = 1;
+
+ /* Format whole words. */
+ for (p = 0; p < words; p++) {
+ if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) {
+ /* Time to skip some zeros */
+ if (p == zero_s)
+ *cp++ = ':';
+ if (p == words - 1)
+ *cp++ = ':';
+ s++;
+ s++;
+ continue;
+ }
+
+ if (is_ipv4 && p > 5 ) {
+ *cp++ = (p == 6) ? ':' : '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ /* we can potentially drop the last octet */
+ if (p != 7 || bits > 120) {
+ *cp++ = '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ }
+ } else {
+ if (cp != outbuf)
+ *cp++ = ':';
+ cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
+ s += 2;
+ }
+ }
+ }
+ /* Format CIDR /width. */
+ sprintf(cp, "/%u", bits);
+ if (strlen(outbuf) + 1 > size)
+ goto emsgsize;
+ strcpy(dst, outbuf);
+
+ return (dst);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_net_ntop
+__weak_reference(__inet_net_ntop, inet_net_ntop);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_net_pton.c b/freebsd/lib/libc/inet/inet_net_pton.c
new file mode 100644
index 00000000..74df38b9
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_net_pton.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*%
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ * convert IPv4 network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not an IPv4 network specification.
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
+ static const char xdigits[] = "0123456789abcdef";
+ static const char digits[] = "0123456789";
+ int n, ch, tmp = 0, dirty, bits;
+ const u_char *odst = dst;
+
+ ch = *src++;
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+ && isascii((unsigned char)(src[1]))
+ && isxdigit((unsigned char)(src[1]))) {
+ /* Hexadecimal: Eat nybble string. */
+ if (size <= 0U)
+ goto emsgsize;
+ dirty = 0;
+ src++; /*%< skip x or X. */
+ while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
+ if (isupper(ch))
+ ch = tolower(ch);
+ n = strchr(xdigits, ch) - xdigits;
+ assert(n >= 0 && n <= 15);
+ if (dirty == 0)
+ tmp = n;
+ else
+ tmp = (tmp << 4) | n;
+ if (++dirty == 2) {
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ dirty = 0;
+ }
+ }
+ if (dirty) { /*%< Odd trailing nybble? */
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = (u_char) (tmp << 4);
+ }
+ } else if (isascii(ch) && isdigit(ch)) {
+ /* Decimal: eat dotted digit string. */
+ for (;;) {
+ tmp = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' &&
+ isascii(ch) && isdigit(ch));
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ ch = *src++;
+ if (!isascii(ch) || !isdigit(ch))
+ goto enoent;
+ }
+ } else
+ goto enoent;
+
+ bits = -1;
+ if (ch == '/' && isascii((unsigned char)(src[0])) &&
+ isdigit((unsigned char)(src[0])) && dst > odst) {
+ /* CIDR width specifier. Nothing can follow it. */
+ ch = *src++; /*%< Skip over the /. */
+ bits = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ bits *= 10;
+ bits += n;
+ if (bits > 32)
+ goto enoent;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (ch != '\0')
+ goto enoent;
+ }
+
+ /* Firey death and destruction unless we prefetched EOS. */
+ if (ch != '\0')
+ goto enoent;
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+ /* If no CIDR spec was given, infer width from net class. */
+ if (bits == -1) {
+ if (*odst >= 240) /*%< Class E */
+ bits = 32;
+ else if (*odst >= 224) /*%< Class D */
+ bits = 8;
+ else if (*odst >= 192) /*%< Class C */
+ bits = 24;
+ else if (*odst >= 128) /*%< Class B */
+ bits = 16;
+ else /*%< Class A */
+ bits = 8;
+ /* If imputed mask is narrower than specified octets, widen. */
+ if (bits < ((dst - odst) * 8))
+ bits = (dst - odst) * 8;
+ /*
+ * If there are no additional bits specified for a class D
+ * address adjust bits to 4.
+ */
+ if (bits == 8 && *odst == 224)
+ bits = 4;
+ }
+ /* Extend network to cover the actual mask. */
+ while (bits > ((dst - odst) * 8)) {
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = '\0';
+ }
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+getbits(const char *src, int *bitsp) {
+ static const char digits[] = "0123456789";
+ int n;
+ int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /*%< no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 128) /*%< range */
+ return (0);
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ *bitsp = val;
+ return (1);
+}
+
+static int
+getv4(const char *src, u_char *dst, int *bitsp) {
+ static const char digits[] = "0123456789";
+ u_char *odst = dst;
+ int n;
+ u_int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /*%< no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 255) /*%< range */
+ return (0);
+ continue;
+ }
+ if (ch == '.' || ch == '/') {
+ if (dst - odst > 3) /*%< too many octets? */
+ return (0);
+ *dst++ = val;
+ if (ch == '/')
+ return (getbits(src, bitsp));
+ val = 0;
+ n = 0;
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ if (dst - odst > 3) /*%< too many octets? */
+ return (0);
+ *dst++ = val;
+ return (1);
+}
+
+static int
+inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int digits;
+ int bits;
+ size_t bytes;
+ int words;
+ int ipv4;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ goto enoent;
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ digits = 0;
+ bits = -1;
+ ipv4 = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++digits > 4)
+ goto enoent;
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ goto enoent;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0')
+ goto enoent;
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ digits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ getv4(curtok, tp, &bits) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ ipv4 = 1;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+ if (ch == '/' && getbits(src, &bits) > 0)
+ break;
+ goto enoent;
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ goto enoent;
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (bits == -1)
+ bits = 128;
+
+ words = (bits + 15) / 16;
+ if (words < 2)
+ words = 2;
+ if (ipv4)
+ words = 8;
+ endp = tmp + 2 * words;
+
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ goto enoent;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ goto enoent;
+
+ bytes = (bits + 7) / 8;
+ if (bytes > size)
+ goto emsgsize;
+ memcpy(dst, tmp, bytes);
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+/*%
+ * int
+ * inet_net_pton(af, src, dst, size)
+ * convert network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not a valid network specification.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(int af, const char *src, void *dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ case AF_INET6:
+ return (inet_net_pton_ipv6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_net_pton
+__weak_reference(__inet_net_pton, inet_net_pton);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_neta.c b/freebsd/lib/libc/inet/inet_neta.c
new file mode 100644
index 00000000..72ac549f
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_neta.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_neta.c,v 1.2.18.1 2005/04/27 05:00:53 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*%
+ * char *
+ * inet_neta(src, dst, size)
+ * format an in_addr_t network number into presentation format.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * format of ``src'' is as for inet_network().
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_neta(src, dst, size)
+ in_addr_t src;
+ char *dst;
+ size_t size;
+{
+ char *odst = dst;
+ char *tp;
+
+ while (src & 0xffffffff) {
+ u_char b = (src & 0xff000000) >> 24;
+
+ src <<= 8;
+ if (b) {
+ if (size < sizeof "255.")
+ goto emsgsize;
+ tp = dst;
+ dst += SPRINTF((dst, "%u", b));
+ if (src != 0L) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - tp);
+ }
+ }
+ if (dst == odst) {
+ if (size < sizeof "0.0.0.0")
+ goto emsgsize;
+ strcpy(dst, "0.0.0.0");
+ }
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_neta
+__weak_reference(__inet_neta, inet_neta);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_netof.c b/freebsd/lib/libc/inet/inet_netof.c
new file mode 100644
index 00000000..8931c30f
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_netof.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*%
+ * Return the network number from an internet
+ * address; handles class a/b/c network #'s.
+ */
+in_addr_t
+inet_netof(in)
+ struct in_addr in;
+{
+ in_addr_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
+ else if (IN_CLASSB(i))
+ return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
+ else
+ return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_netof
+__weak_reference(__inet_netof, inet_netof);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_network.c b/freebsd/lib/libc/inet/inet_network.c
new file mode 100644
index 00000000..254db41a
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_network.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#include "port_after.h"
+
+/*%
+ * Internet network address interpretation routine.
+ * The library routines call this routine to interpret
+ * network numbers.
+ */
+in_addr_t
+inet_network(cp)
+ const char *cp;
+{
+ in_addr_t val, base, n;
+ char c;
+ in_addr_t parts[4], *pp = parts;
+ int i, digit;
+
+again:
+ val = 0; base = 10; digit = 0;
+ if (*cp == '0')
+ digit = 1, base = 8, cp++;
+ if (*cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ while ((c = *cp) != 0) {
+ if (isdigit((unsigned char)c)) {
+ if (base == 8U && (c == '8' || c == '9'))
+ return (INADDR_NONE);
+ val = (val * base) + (c - '0');
+ cp++;
+ digit = 1;
+ continue;
+ }
+ if (base == 16U && isxdigit((unsigned char)c)) {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
+ cp++;
+ digit = 1;
+ continue;
+ }
+ break;
+ }
+ if (!digit)
+ return (INADDR_NONE);
+ if (pp >= parts + 4 || val > 0xffU)
+ return (INADDR_NONE);
+ if (*cp == '.') {
+ *pp++ = val, cp++;
+ goto again;
+ }
+ if (*cp && !isspace(*cp&0xff))
+ return (INADDR_NONE);
+ *pp++ = val;
+ n = pp - parts;
+ if (n > 4U)
+ return (INADDR_NONE);
+ for (val = 0, i = 0; i < n; i++) {
+ val <<= 8;
+ val |= parts[i] & 0xff;
+ }
+ return (val);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_network
+__weak_reference(__inet_network, inet_network);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_ntoa.c b/freebsd/lib/libc/inet/inet_ntoa.c
new file mode 100644
index 00000000..f5d69fac
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_ntoa.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: inet_ntoa.c,v 1.1.352.1 2005/04/27 05:00:54 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*%
+ * Convert network-format internet address
+ * to base 256 d.d.d.d representation.
+ */
+/*const*/ char *
+inet_ntoa(struct in_addr in) {
+ static char ret[18];
+
+ strcpy(ret, "[inet_ntoa error]");
+ (void) inet_ntop(AF_INET, &in, ret, sizeof ret);
+ return (ret);
+}
+
+char *
+inet_ntoa_r(struct in_addr in, char *buf, socklen_t size)
+{
+
+ (void) inet_ntop(AF_INET, &in, buf, size);
+ return (buf);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_ntoa
+__weak_reference(__inet_ntoa, inet_ntoa);
+__weak_reference(__inet_ntoa_r, inet_ntoa_r);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_ntop.c b/freebsd/lib/libc/inet/inet_ntop.c
new file mode 100644
index 00000000..6d210279
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_ntop.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_ntop.c,v 1.3.18.2 2005/11/03 23:02:22 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*%
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const u_char *src, char *dst, socklen_t size);
+static const char *inet_ntop6(const u_char *src, char *dst, socklen_t size);
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(int af, const void * __restrict src, char * __restrict dst,
+ socklen_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a u_char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const u_char *src, char *dst, socklen_t size)
+{
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+ int l;
+
+ l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+ if (l <= 0 || (socklen_t) l >= size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strlcpy(dst, tmp, size);
+ return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(const u_char *src, char *dst, socklen_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ tp += sprintf(tp, "%x", words[i]);
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((socklen_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_ntop
+__weak_reference(__inet_ntop, inet_ntop);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/inet_pton.c b/freebsd/lib/libc/inet/inet_pton.c
new file mode 100644
index 00000000..ae650990
--- /dev/null
+++ b/freebsd/lib/libc/inet/inet_pton.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_pton.c,v 1.3.18.2 2005/07/28 07:38:07 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include "port_after.h"
+
+/*%
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, u_char *dst);
+static int inet_pton6(const char *src, u_char *dst);
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(int af, const char * __restrict src, void * __restrict dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, u_char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ u_int new = *tp * 10 + (pch - digits);
+
+ if (saw_digit && *tp == 0)
+ return (0);
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, u_char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, seen_xdigits;
+ u_int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ seen_xdigits = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++seen_xdigits > 4)
+ return (0);
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!seen_xdigits) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return (0);
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ seen_xdigits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ seen_xdigits = 0;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (seen_xdigits) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ return (0);
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_pton
+__weak_reference(__inet_pton, inet_pton);
+
+/*! \file */
diff --git a/freebsd/lib/libc/inet/nsap_addr.c b/freebsd/lib/libc/inet/nsap_addr.c
new file mode 100644
index 00000000..29474729
--- /dev/null
+++ b/freebsd/lib/libc/inet/nsap_addr.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nsap_addr.c,v 1.3.18.2 2005/07/28 07:38:08 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <resolv_mt.h>
+
+#include "port_after.h"
+
+static char
+xtob(int c) {
+ return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int
+inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) {
+ u_char c, nib;
+ u_int len = 0;
+
+ if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X'))
+ return (0);
+ ascii += 2;
+
+ while ((c = *ascii++) != '\0' && len < (u_int)maxlen) {
+ if (c == '.' || c == '+' || c == '/')
+ continue;
+ if (!isascii(c))
+ return (0);
+ if (islower(c))
+ c = toupper(c);
+ if (isxdigit(c)) {
+ nib = xtob(c);
+ c = *ascii++;
+ if (c != '\0') {
+ c = toupper(c);
+ if (isxdigit(c)) {
+ *binary++ = (nib << 4) | xtob(c);
+ len++;
+ } else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ return (len);
+}
+
+char *
+inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) {
+ int nib;
+ int i;
+ char *tmpbuf = inet_nsap_ntoa_tmpbuf;
+ char *start;
+
+ if (ascii)
+ start = ascii;
+ else {
+ ascii = tmpbuf;
+ start = tmpbuf;
+ }
+
+ *ascii++ = '0';
+ *ascii++ = 'x';
+
+ if (binlen > 255)
+ binlen = 255;
+
+ for (i = 0; i < binlen; i++) {
+ nib = *binary >> 4;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ nib = *binary++ & 0x0f;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ if (((i % 2) == 0 && (i + 1) < binlen))
+ *ascii++ = '.';
+ }
+ *ascii = '\0';
+ return (start);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_nsap_addr
+__weak_reference(__inet_nsap_addr, inet_nsap_addr);
+#undef inet_nsap_ntoa
+__weak_reference(__inet_nsap_ntoa, inet_nsap_ntoa);
+
+/*! \file */
diff --git a/freebsd/lib/libc/isc/ev_streams.c b/freebsd/lib/libc/isc/ev_streams.c
new file mode 100644
index 00000000..06bdfad5
--- /dev/null
+++ b/freebsd/lib/libc/isc/ev_streams.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ev_streams.c - implement asynch stream file IO for the eventlib
+ * vix 04mar96 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: ev_streams.c,v 1.4.18.1 2005/04/27 05:01:06 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#ifndef _LIBC
+#include "fd_setsize.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+
+#include <isc/eventlib.h>
+#ifndef _LIBC
+#include <isc/assertions.h>
+#endif
+#include "eventlib_p.h"
+
+#include "port_after.h"
+
+#ifndef _LIBC
+static int copyvec(evStream *str, const struct iovec *iov, int iocnt);
+static void consume(evStream *str, size_t bytes);
+static void done(evContext opaqueCtx, evStream *str);
+static void writable(evContext opaqueCtx, void *uap, int fd, int evmask);
+static void readable(evContext opaqueCtx, void *uap, int fd, int evmask);
+#endif
+
+struct iovec
+evConsIovec(void *buf, size_t cnt) {
+ struct iovec ret;
+
+ memset(&ret, 0xf5, sizeof ret);
+ ret.iov_base = buf;
+ ret.iov_len = cnt;
+ return (ret);
+}
+
+#ifndef _LIBC
+int
+evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
+ evStreamFunc func, void *uap, evStreamID *id)
+{
+ evContext_p *ctx = opaqueCtx.opaque;
+ evStream *new;
+ int save;
+
+ OKNEW(new);
+ new->func = func;
+ new->uap = uap;
+ new->fd = fd;
+ new->flags = 0;
+ if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0)
+ goto free;
+ if (copyvec(new, iov, iocnt) < 0)
+ goto free;
+ new->prevDone = NULL;
+ new->nextDone = NULL;
+ if (ctx->streams != NULL)
+ ctx->streams->prev = new;
+ new->prev = NULL;
+ new->next = ctx->streams;
+ ctx->streams = new;
+ if (id != NULL)
+ id->opaque = new;
+ return (0);
+ free:
+ save = errno;
+ FREE(new);
+ errno = save;
+ return (-1);
+}
+
+int
+evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
+ evStreamFunc func, void *uap, evStreamID *id)
+{
+ evContext_p *ctx = opaqueCtx.opaque;
+ evStream *new;
+ int save;
+
+ OKNEW(new);
+ new->func = func;
+ new->uap = uap;
+ new->fd = fd;
+ new->flags = 0;
+ if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0)
+ goto free;
+ if (copyvec(new, iov, iocnt) < 0)
+ goto free;
+ new->prevDone = NULL;
+ new->nextDone = NULL;
+ if (ctx->streams != NULL)
+ ctx->streams->prev = new;
+ new->prev = NULL;
+ new->next = ctx->streams;
+ ctx->streams = new;
+ if (id)
+ id->opaque = new;
+ return (0);
+ free:
+ save = errno;
+ FREE(new);
+ errno = save;
+ return (-1);
+}
+
+int
+evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ {
+ evStream *str = id.opaque;
+
+ UNUSED(opaqueCtx);
+
+ str->timer = timer;
+ str->flags |= EV_STR_TIMEROK;
+ return (0);
+}
+
+int
+evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ {
+ evStream *str = id.opaque;
+
+ UNUSED(opaqueCtx);
+
+ str->flags &= ~EV_STR_TIMEROK;
+ return (0);
+}
+
+int
+evCancelRW(evContext opaqueCtx, evStreamID id) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evStream *old = id.opaque;
+
+ /*
+ * The streams list is doubly threaded. First, there's ctx->streams
+ * that's used by evDestroy() to find and cancel all streams. Second,
+ * there's ctx->strDone (head) and ctx->strLast (tail) which thread
+ * through the potentially smaller number of "IO completed" streams,
+ * used in evGetNext() to avoid scanning the entire list.
+ */
+
+ /* Unlink from ctx->streams. */
+ if (old->prev != NULL)
+ old->prev->next = old->next;
+ else
+ ctx->streams = old->next;
+ if (old->next != NULL)
+ old->next->prev = old->prev;
+
+ /*
+ * If 'old' is on the ctx->strDone list, remove it. Update
+ * ctx->strLast if necessary.
+ */
+ if (old->prevDone == NULL && old->nextDone == NULL) {
+ /*
+ * Either 'old' is the only item on the done list, or it's
+ * not on the done list. If the former, then we unlink it
+ * from the list. If the latter, we leave the list alone.
+ */
+ if (ctx->strDone == old) {
+ ctx->strDone = NULL;
+ ctx->strLast = NULL;
+ }
+ } else {
+ if (old->prevDone != NULL)
+ old->prevDone->nextDone = old->nextDone;
+ else
+ ctx->strDone = old->nextDone;
+ if (old->nextDone != NULL)
+ old->nextDone->prevDone = old->prevDone;
+ else
+ ctx->strLast = old->prevDone;
+ }
+
+ /* Deallocate the stream. */
+ if (old->file.opaque)
+ evDeselectFD(opaqueCtx, old->file);
+ memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount);
+ FREE(old);
+ return (0);
+}
+
+/* Copy a scatter/gather vector and initialize a stream handler's IO. */
+static int
+copyvec(evStream *str, const struct iovec *iov, int iocnt) {
+ int i;
+
+ str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt);
+ if (str->iovOrig == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ str->ioTotal = 0;
+ for (i = 0; i < iocnt; i++) {
+ str->iovOrig[i] = iov[i];
+ str->ioTotal += iov[i].iov_len;
+ }
+ str->iovOrigCount = iocnt;
+ str->iovCur = str->iovOrig;
+ str->iovCurCount = str->iovOrigCount;
+ str->ioDone = 0;
+ return (0);
+}
+
+/* Pull off or truncate lead iovec(s). */
+static void
+consume(evStream *str, size_t bytes) {
+ while (bytes > 0U) {
+ if (bytes < (size_t)str->iovCur->iov_len) {
+ str->iovCur->iov_len -= bytes;
+ str->iovCur->iov_base = (void *)
+ ((u_char *)str->iovCur->iov_base + bytes);
+ str->ioDone += bytes;
+ bytes = 0;
+ } else {
+ bytes -= str->iovCur->iov_len;
+ str->ioDone += str->iovCur->iov_len;
+ str->iovCur++;
+ str->iovCurCount--;
+ }
+ }
+}
+
+/* Add a stream to Done list and deselect the FD. */
+static void
+done(evContext opaqueCtx, evStream *str) {
+ evContext_p *ctx = opaqueCtx.opaque;
+
+ if (ctx->strLast != NULL) {
+ str->prevDone = ctx->strLast;
+ ctx->strLast->nextDone = str;
+ ctx->strLast = str;
+ } else {
+ INSIST(ctx->strDone == NULL);
+ ctx->strDone = ctx->strLast = str;
+ }
+ evDeselectFD(opaqueCtx, str->file);
+ str->file.opaque = NULL;
+ /* evDrop() will call evCancelRW() on us. */
+}
+
+/* Dribble out some bytes on the stream. (Called by evDispatch().) */
+static void
+writable(evContext opaqueCtx, void *uap, int fd, int evmask) {
+ evStream *str = uap;
+ int bytes;
+
+ UNUSED(evmask);
+
+ bytes = writev(fd, str->iovCur, str->iovCurCount);
+ if (bytes > 0) {
+ if ((str->flags & EV_STR_TIMEROK) != 0)
+ evTouchIdleTimer(opaqueCtx, str->timer);
+ consume(str, bytes);
+ } else {
+ if (bytes < 0 && errno != EINTR) {
+ str->ioDone = -1;
+ str->ioErrno = errno;
+ }
+ }
+ if (str->ioDone == -1 || str->ioDone == str->ioTotal)
+ done(opaqueCtx, str);
+}
+
+/* Scoop up some bytes from the stream. (Called by evDispatch().) */
+static void
+readable(evContext opaqueCtx, void *uap, int fd, int evmask) {
+ evStream *str = uap;
+ int bytes;
+
+ UNUSED(evmask);
+
+ bytes = readv(fd, str->iovCur, str->iovCurCount);
+ if (bytes > 0) {
+ if ((str->flags & EV_STR_TIMEROK) != 0)
+ evTouchIdleTimer(opaqueCtx, str->timer);
+ consume(str, bytes);
+ } else {
+ if (bytes == 0)
+ str->ioDone = 0;
+ else {
+ if (errno != EINTR) {
+ str->ioDone = -1;
+ str->ioErrno = errno;
+ }
+ }
+ }
+ if (str->ioDone <= 0 || str->ioDone == str->ioTotal)
+ done(opaqueCtx, str);
+}
+#endif
+
+/*! \file */
diff --git a/freebsd/lib/libc/isc/ev_timers.c b/freebsd/lib/libc/isc/ev_timers.c
new file mode 100644
index 00000000..66fc1861
--- /dev/null
+++ b/freebsd/lib/libc/isc/ev_timers.c
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ev_timers.c - implement timers for the eventlib
+ * vix 09sep95 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: ev_timers.c,v 1.5.18.1 2005/04/27 05:01:06 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Import. */
+
+#include "port_before.h"
+#ifndef _LIBC
+#include "fd_setsize.h"
+#endif
+
+#include <errno.h>
+
+#ifndef _LIBC
+#include <isc/assertions.h>
+#endif
+#include <isc/eventlib.h>
+#include "eventlib_p.h"
+
+#include "port_after.h"
+
+/* Constants. */
+
+#define MILLION 1000000
+#define BILLION 1000000000
+
+/* Forward. */
+
+#ifdef _LIBC
+static int __evOptMonoTime;
+#else
+static int due_sooner(void *, void *);
+static void set_index(void *, int);
+static void free_timer(void *, void *);
+static void print_timer(void *, void *);
+static void idle_timeout(evContext, void *, struct timespec, struct timespec);
+
+/* Private type. */
+
+typedef struct {
+ evTimerFunc func;
+ void * uap;
+ struct timespec lastTouched;
+ struct timespec max_idle;
+ evTimer * timer;
+} idle_timer;
+#endif
+
+/* Public. */
+
+struct timespec
+evConsTime(time_t sec, long nsec) {
+ struct timespec x;
+
+ x.tv_sec = sec;
+ x.tv_nsec = nsec;
+ return (x);
+}
+
+struct timespec
+evAddTime(struct timespec addend1, struct timespec addend2) {
+ struct timespec x;
+
+ x.tv_sec = addend1.tv_sec + addend2.tv_sec;
+ x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
+ if (x.tv_nsec >= BILLION) {
+ x.tv_sec++;
+ x.tv_nsec -= BILLION;
+ }
+ return (x);
+}
+
+struct timespec
+evSubTime(struct timespec minuend, struct timespec subtrahend) {
+ struct timespec x;
+
+ x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
+ if (minuend.tv_nsec >= subtrahend.tv_nsec)
+ x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
+ else {
+ x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
+ x.tv_sec--;
+ }
+ return (x);
+}
+
+int
+evCmpTime(struct timespec a, struct timespec b) {
+ long x = a.tv_sec - b.tv_sec;
+
+ if (x == 0L)
+ x = a.tv_nsec - b.tv_nsec;
+ return (x < 0L ? (-1) : x > 0L ? (1) : (0));
+}
+
+struct timespec
+evNowTime() {
+ struct timeval now;
+#ifdef CLOCK_REALTIME
+ struct timespec tsnow;
+ int m = CLOCK_REALTIME;
+
+#ifdef CLOCK_MONOTONIC
+ if (__evOptMonoTime)
+ m = CLOCK_MONOTONIC;
+#endif
+ if (clock_gettime(m, &tsnow) == 0)
+ return (tsnow);
+#endif
+ if (gettimeofday(&now, NULL) < 0)
+ return (evConsTime(0, 0));
+ return (evTimeSpec(now));
+}
+
+struct timespec
+evUTCTime() {
+ struct timeval now;
+#ifdef CLOCK_REALTIME
+ struct timespec tsnow;
+ if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0)
+ return (tsnow);
+#endif
+ if (gettimeofday(&now, NULL) < 0)
+ return (evConsTime(0, 0));
+ return (evTimeSpec(now));
+}
+
+#ifndef _LIBC
+struct timespec
+evLastEventTime(evContext opaqueCtx) {
+ evContext_p *ctx = opaqueCtx.opaque;
+
+ return (ctx->lastEventTime);
+}
+#endif
+
+struct timespec
+evTimeSpec(struct timeval tv) {
+ struct timespec ts;
+
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ return (ts);
+}
+
+#if !defined(USE_KQUEUE) || !defined(_LIBC)
+struct timeval
+evTimeVal(struct timespec ts) {
+ struct timeval tv;
+
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000;
+ return (tv);
+}
+#endif
+
+#ifndef _LIBC
+int
+evSetTimer(evContext opaqueCtx,
+ evTimerFunc func,
+ void *uap,
+ struct timespec due,
+ struct timespec inter,
+ evTimerID *opaqueID
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *id;
+
+ evPrintf(ctx, 1,
+"evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n",
+ ctx, func, uap,
+ (long)due.tv_sec, due.tv_nsec,
+ (long)inter.tv_sec, inter.tv_nsec);
+
+#ifdef __hpux
+ /*
+ * tv_sec and tv_nsec are unsigned.
+ */
+ if (due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#else
+ if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#endif
+
+ /* due={0,0} is a magic cookie meaning "now." */
+ if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L)
+ due = evNowTime();
+
+ /* Allocate and fill. */
+ OKNEW(id);
+ id->func = func;
+ id->uap = uap;
+ id->due = due;
+ id->inter = inter;
+
+ if (heap_insert(ctx->timers, id) < 0)
+ return (-1);
+
+ /* Remember the ID if the caller provided us a place for it. */
+ if (opaqueID)
+ opaqueID->opaque = id;
+
+ if (ctx->debug > 7) {
+ evPrintf(ctx, 7, "timers after evSetTimer:\n");
+ (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
+ }
+
+ return (0);
+}
+
+int
+evClearTimer(evContext opaqueCtx, evTimerID id) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *del = id.opaque;
+
+ if (ctx->cur != NULL &&
+ ctx->cur->type == Timer &&
+ ctx->cur->u.timer.this == del) {
+ evPrintf(ctx, 8, "deferring delete of timer (executing)\n");
+ /*
+ * Setting the interval to zero ensures that evDrop() will
+ * clean up the timer.
+ */
+ del->inter = evConsTime(0, 0);
+ return (0);
+ }
+
+ if (heap_element(ctx->timers, del->index) != del)
+ EV_ERR(ENOENT);
+
+ if (heap_delete(ctx->timers, del->index) < 0)
+ return (-1);
+ FREE(del);
+
+ if (ctx->debug > 7) {
+ evPrintf(ctx, 7, "timers after evClearTimer:\n");
+ (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
+ }
+
+ return (0);
+}
+
+int
+evConfigTimer(evContext opaqueCtx,
+ evTimerID id,
+ const char *param,
+ int value
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *timer = id.opaque;
+ int result=0;
+
+ UNUSED(value);
+
+ if (heap_element(ctx->timers, timer->index) != timer)
+ EV_ERR(ENOENT);
+
+ if (strcmp(param, "rate") == 0)
+ timer->mode |= EV_TMR_RATE;
+ else if (strcmp(param, "interval") == 0)
+ timer->mode &= ~EV_TMR_RATE;
+ else
+ EV_ERR(EINVAL);
+
+ return (result);
+}
+
+int
+evResetTimer(evContext opaqueCtx,
+ evTimerID id,
+ evTimerFunc func,
+ void *uap,
+ struct timespec due,
+ struct timespec inter
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *timer = id.opaque;
+ struct timespec old_due;
+ int result=0;
+
+ if (heap_element(ctx->timers, timer->index) != timer)
+ EV_ERR(ENOENT);
+
+#ifdef __hpux
+ /*
+ * tv_sec and tv_nsec are unsigned.
+ */
+ if (due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#else
+ if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#endif
+
+ old_due = timer->due;
+
+ timer->func = func;
+ timer->uap = uap;
+ timer->due = due;
+ timer->inter = inter;
+
+ switch (evCmpTime(due, old_due)) {
+ case -1:
+ result = heap_increased(ctx->timers, timer->index);
+ break;
+ case 0:
+ result = 0;
+ break;
+ case 1:
+ result = heap_decreased(ctx->timers, timer->index);
+ break;
+ }
+
+ if (ctx->debug > 7) {
+ evPrintf(ctx, 7, "timers after evResetTimer:\n");
+ (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
+ }
+
+ return (result);
+}
+
+int
+evSetIdleTimer(evContext opaqueCtx,
+ evTimerFunc func,
+ void *uap,
+ struct timespec max_idle,
+ evTimerID *opaqueID
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ idle_timer *tt;
+
+ /* Allocate and fill. */
+ OKNEW(tt);
+ tt->func = func;
+ tt->uap = uap;
+ tt->lastTouched = ctx->lastEventTime;
+ tt->max_idle = max_idle;
+
+ if (evSetTimer(opaqueCtx, idle_timeout, tt,
+ evAddTime(ctx->lastEventTime, max_idle),
+ max_idle, opaqueID) < 0) {
+ FREE(tt);
+ return (-1);
+ }
+
+ tt->timer = opaqueID->opaque;
+
+ return (0);
+}
+
+int
+evClearIdleTimer(evContext opaqueCtx, evTimerID id) {
+ evTimer *del = id.opaque;
+ idle_timer *tt = del->uap;
+
+ FREE(tt);
+ return (evClearTimer(opaqueCtx, id));
+}
+
+int
+evResetIdleTimer(evContext opaqueCtx,
+ evTimerID opaqueID,
+ evTimerFunc func,
+ void *uap,
+ struct timespec max_idle
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *timer = opaqueID.opaque;
+ idle_timer *tt = timer->uap;
+
+ tt->func = func;
+ tt->uap = uap;
+ tt->lastTouched = ctx->lastEventTime;
+ tt->max_idle = max_idle;
+
+ return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt,
+ evAddTime(ctx->lastEventTime, max_idle),
+ max_idle));
+}
+
+int
+evTouchIdleTimer(evContext opaqueCtx, evTimerID id) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *t = id.opaque;
+ idle_timer *tt = t->uap;
+
+ tt->lastTouched = ctx->lastEventTime;
+
+ return (0);
+}
+
+/* Public to the rest of eventlib. */
+
+heap_context
+evCreateTimers(const evContext_p *ctx) {
+
+ UNUSED(ctx);
+
+ return (heap_new(due_sooner, set_index, 2048));
+}
+
+void
+evDestroyTimers(const evContext_p *ctx) {
+ (void) heap_for_each(ctx->timers, free_timer, NULL);
+ (void) heap_free(ctx->timers);
+}
+
+/* Private. */
+
+static int
+due_sooner(void *a, void *b) {
+ evTimer *a_timer, *b_timer;
+
+ a_timer = a;
+ b_timer = b;
+ return (evCmpTime(a_timer->due, b_timer->due) < 0);
+}
+
+static void
+set_index(void *what, int index) {
+ evTimer *timer;
+
+ timer = what;
+ timer->index = index;
+}
+
+static void
+free_timer(void *what, void *uap) {
+ evTimer *t = what;
+
+ UNUSED(uap);
+
+ FREE(t);
+}
+
+static void
+print_timer(void *what, void *uap) {
+ evTimer *cur = what;
+ evContext_p *ctx = uap;
+
+ cur = what;
+ evPrintf(ctx, 7,
+ " func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n",
+ cur->func, cur->uap,
+ (long)cur->due.tv_sec, cur->due.tv_nsec,
+ (long)cur->inter.tv_sec, cur->inter.tv_nsec);
+}
+
+static void
+idle_timeout(evContext opaqueCtx,
+ void *uap,
+ struct timespec due,
+ struct timespec inter
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ idle_timer *this = uap;
+ struct timespec idle;
+
+ UNUSED(due);
+ UNUSED(inter);
+
+ idle = evSubTime(ctx->lastEventTime, this->lastTouched);
+ if (evCmpTime(idle, this->max_idle) >= 0) {
+ (this->func)(opaqueCtx, this->uap, this->timer->due,
+ this->max_idle);
+ /*
+ * Setting the interval to zero will cause the timer to
+ * be cleaned up in evDrop().
+ */
+ this->timer->inter = evConsTime(0, 0);
+ FREE(this);
+ } else {
+ /* evDrop() will reschedule the timer. */
+ this->timer->inter = evSubTime(this->max_idle, idle);
+ }
+}
+#endif
+
+/*! \file */
diff --git a/freebsd/lib/libc/isc/eventlib_p.h b/freebsd/lib/libc/isc/eventlib_p.h
new file mode 100644
index 00000000..951af003
--- /dev/null
+++ b/freebsd/lib/libc/isc/eventlib_p.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file
+ * \brief private interfaces for eventlib
+ * \author vix 09sep95 [initial]
+ *
+ * $Id: eventlib_p.h,v 1.5.18.4 2006/03/10 00:20:08 marka Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _EVENTLIB_P_H
+#define _EVENTLIB_P_H
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#define EVENTLIB_DEBUG 1
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _LIBC
+#include <isc/list.h>
+#include <isc/heap.h>
+#include <isc/memcluster.h>
+#endif
+
+#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT)
+#define EV_ERR(e) return (errno = (e), -1)
+#define OK(x) if ((x) < 0) EV_ERR(errno); else (void)NULL
+#define OKFREE(x, y) if ((x) < 0) { FREE((y)); EV_ERR(errno); } \
+ else (void)NULL
+
+#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \
+ FILL(p); \
+ else \
+ (void)NULL;
+#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \
+ errno = ENOMEM; \
+ return (-1); \
+ } else \
+ FILL(p)
+#define FREE(p) memput((p), sizeof *(p))
+
+#if EVENTLIB_DEBUG
+#define FILL(p) memset((p), 0xF5, sizeof *(p))
+#else
+#define FILL(p)
+#endif
+
+#ifdef USE_POLL
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+#include <poll.h>
+#endif /* USE_POLL */
+
+typedef struct evConn {
+ evConnFunc func;
+ void * uap;
+ int fd;
+ int flags;
+#define EV_CONN_LISTEN 0x0001 /*%< Connection is a listener. */
+#define EV_CONN_SELECTED 0x0002 /*%< evSelectFD(conn->file). */
+#define EV_CONN_BLOCK 0x0004 /*%< Listener fd was blocking. */
+ evFileID file;
+ struct evConn * prev;
+ struct evConn * next;
+} evConn;
+
+#ifndef _LIBC
+typedef struct evAccept {
+ int fd;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#ifndef NO_SOCKADDR_UN
+ struct sockaddr_un un;
+#endif
+ } la;
+ ISC_SOCKLEN_T lalen;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#ifndef NO_SOCKADDR_UN
+ struct sockaddr_un un;
+#endif
+ } ra;
+ ISC_SOCKLEN_T ralen;
+ int ioErrno;
+ evConn * conn;
+ LINK(struct evAccept) link;
+} evAccept;
+
+typedef struct evFile {
+ evFileFunc func;
+ void * uap;
+ int fd;
+ int eventmask;
+ int preemptive;
+ struct evFile * prev;
+ struct evFile * next;
+ struct evFile * fdprev;
+ struct evFile * fdnext;
+} evFile;
+
+typedef struct evStream {
+ evStreamFunc func;
+ void * uap;
+ evFileID file;
+ evTimerID timer;
+ int flags;
+#define EV_STR_TIMEROK 0x0001 /*%< IFF timer valid. */
+ int fd;
+ struct iovec * iovOrig;
+ int iovOrigCount;
+ struct iovec * iovCur;
+ int iovCurCount;
+ int ioTotal;
+ int ioDone;
+ int ioErrno;
+ struct evStream *prevDone, *nextDone;
+ struct evStream *prev, *next;
+} evStream;
+
+typedef struct evTimer {
+ evTimerFunc func;
+ void * uap;
+ struct timespec due, inter;
+ int index;
+ int mode;
+#define EV_TMR_RATE 1
+} evTimer;
+
+typedef struct evWait {
+ evWaitFunc func;
+ void * uap;
+ const void * tag;
+ struct evWait * next;
+} evWait;
+
+typedef struct evWaitList {
+ evWait * first;
+ evWait * last;
+ struct evWaitList * prev;
+ struct evWaitList * next;
+} evWaitList;
+
+typedef struct evEvent_p {
+ enum { Accept, File, Stream, Timer, Wait, Free, Null } type;
+ union {
+ struct { evAccept *this; } accept;
+ struct { evFile *this; int eventmask; } file;
+ struct { evStream *this; } stream;
+ struct { evTimer *this; } timer;
+ struct { evWait *this; } wait;
+ struct { struct evEvent_p *next; } free;
+ struct { const void *placeholder; } null;
+ } u;
+} evEvent_p;
+#endif
+
+#ifdef USE_POLL
+typedef struct {
+ void *ctx; /* pointer to the evContext_p */
+ uint32_t type; /* READ, WRITE, EXCEPT, nonblk */
+ uint32_t result; /* 1 => revents, 0 => events */
+} __evEmulMask;
+
+#define emulMaskInit(ctx, field, ev, lastnext) \
+ ctx->field.ctx = ctx; \
+ ctx->field.type = ev; \
+ ctx->field.result = lastnext;
+
+extern short *__fd_eventfield(int fd, __evEmulMask *maskp);
+extern short __poll_event(__evEmulMask *maskp);
+extern void __fd_clr(int fd, __evEmulMask *maskp);
+extern void __fd_set(int fd, __evEmulMask *maskp);
+
+#undef FD_ZERO
+#define FD_ZERO(maskp)
+
+#undef FD_SET
+#define FD_SET(fd, maskp) \
+ __fd_set(fd, maskp)
+
+#undef FD_CLR
+#define FD_CLR(fd, maskp) \
+ __fd_clr(fd, maskp)
+
+#undef FD_ISSET
+#define FD_ISSET(fd, maskp) \
+ ((*__fd_eventfield(fd, maskp) & __poll_event(maskp)) != 0)
+
+#endif /* USE_POLL */
+
+#ifndef _LIBC
+typedef struct {
+ /* Global. */
+ const evEvent_p *cur;
+ /* Debugging. */
+ int debug;
+ FILE *output;
+ /* Connections. */
+ evConn *conns;
+ LIST(evAccept) accepts;
+ /* Files. */
+ evFile *files, *fdNext;
+#ifndef USE_POLL
+ fd_set rdLast, rdNext;
+ fd_set wrLast, wrNext;
+ fd_set exLast, exNext;
+ fd_set nonblockBefore;
+ int fdMax, fdCount, highestFD;
+ evFile *fdTable[FD_SETSIZE];
+#else
+ struct pollfd *pollfds; /* Allocated as needed */
+ evFile **fdTable; /* Ditto */
+ int maxnfds; /* # elements in above */
+ int firstfd; /* First active fd */
+ int fdMax; /* Last active fd */
+ int fdCount; /* # fd:s with I/O */
+ int highestFD; /* max fd allowed by OS */
+ __evEmulMask rdLast, rdNext;
+ __evEmulMask wrLast, wrNext;
+ __evEmulMask exLast, exNext;
+ __evEmulMask nonblockBefore;
+#endif /* USE_POLL */
+#ifdef EVENTLIB_TIME_CHECKS
+ struct timespec lastSelectTime;
+ int lastFdCount;
+#endif
+ /* Streams. */
+ evStream *streams;
+ evStream *strDone, *strLast;
+ /* Timers. */
+ struct timespec lastEventTime;
+ heap_context timers;
+ /* Waits. */
+ evWaitList *waitLists;
+ evWaitList waitDone;
+} evContext_p;
+
+/* eventlib.c */
+#define evPrintf __evPrintf
+void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+#ifdef USE_POLL
+extern int evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd);
+#endif /* USE_POLL */
+
+/* ev_timers.c */
+#define evCreateTimers __evCreateTimers
+heap_context evCreateTimers(const evContext_p *);
+#define evDestroyTimers __evDestroyTimers
+void evDestroyTimers(const evContext_p *);
+
+/* ev_waits.c */
+#define evFreeWait __evFreeWait
+evWait *evFreeWait(evContext_p *ctx, evWait *old);
+#endif
+
+/* Global options */
+#ifndef _LIBC
+extern int __evOptMonoTime;
+#endif
+
+#endif /*_EVENTLIB_P_H*/
diff --git a/freebsd/lib/libc/nameser/ns_name.c b/freebsd/lib/libc/nameser/ns_name.c
new file mode 100644
index 00000000..ce7ee4d6
--- /dev/null
+++ b/freebsd/lib/libc/nameser/ns_name.c
@@ -0,0 +1,975 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_name.c,v 1.8.18.2 2005/04/27 05:01:08 sra Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+#define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */
+#define DNS_LABELTYPE_BITSTRING 0x41
+
+/* Data. */
+
+static const char digits[] = "0123456789";
+
+static const char digitvalue[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
+};
+
+/* Forward. */
+
+static int special(int);
+static int printable(int);
+static int dn_find(const u_char *, const u_char *,
+ const u_char * const *,
+ const u_char * const *);
+static int encode_bitsring(const char **, const char *,
+ unsigned char **, unsigned char **,
+ unsigned const char *);
+static int labellen(const u_char *);
+static int decode_bitstring(const unsigned char **,
+ char *, const char *);
+
+/* Public. */
+
+/*%
+ * Convert an encoded domain name to printable ascii as per RFC1035.
+
+ * return:
+ *\li Number of bytes written to buffer, or -1 (with errno set)
+ *
+ * notes:
+ *\li The root is returned as "."
+ *\li All other domains are returned in non absolute form
+ */
+int
+ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
+{
+ const u_char *cp;
+ char *dn, *eom;
+ u_char c;
+ u_int n;
+ int l;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn != dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE; /*%< XXX */
+ return(-1);
+ }
+ if (dn + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+ int m;
+
+ if (n != DNS_LABELTYPE_BITSTRING) {
+ /* XXX: labellen should reject this case */
+ errno = EINVAL;
+ return(-1);
+ }
+ if ((m = decode_bitstring(&cp, dn, eom)) < 0)
+ {
+ errno = EMSGSIZE;
+ return(-1);
+ }
+ dn += m;
+ continue;
+ }
+ for ((void)NULL; l > 0; l--) {
+ c = *cp++;
+ if (special(c)) {
+ if (dn + 1 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = (char)c;
+ } else if (!printable(c)) {
+ if (dn + 3 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = digits[c / 100];
+ *dn++ = digits[(c % 100) / 10];
+ *dn++ = digits[c % 10];
+ } else {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = (char)c;
+ }
+ }
+ }
+ if (dn == dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*%
+ * Convert a ascii string into an encoded domain name as per RFC1035.
+ *
+ * return:
+ *
+ *\li -1 if it fails
+ *\li 1 if string was fully qualified
+ *\li 0 is string was not fully qualified
+ *
+ * notes:
+ *\li Enforces label and domain length limits.
+ */
+
+int
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
+{
+ u_char *label, *bp, *eom;
+ int c, n, escaped, e = 0;
+ char *cp;
+
+ escaped = 0;
+ bp = dst;
+ eom = dst + dstsiz;
+ label = bp++;
+
+ while ((c = *src++) != 0) {
+ if (escaped) {
+ if (c == '[') { /*%< start a bit string label */
+ if ((cp = strchr(src, ']')) == NULL) {
+ errno = EINVAL; /*%< ??? */
+ return(-1);
+ }
+ if ((e = encode_bitsring(&src, cp + 2,
+ &label, &bp, eom))
+ != 0) {
+ errno = e;
+ return(-1);
+ }
+ escaped = 0;
+ label = bp++;
+ if ((c = *src++) == 0)
+ goto done;
+ else if (c != '.') {
+ errno = EINVAL;
+ return(-1);
+ }
+ continue;
+ }
+ else if ((cp = strchr(digits, c)) != NULL) {
+ n = (cp - digits) * 100;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits) * 10;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits);
+ if (n > 255) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ c = n;
+ }
+ escaped = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ continue;
+ } else if (c == '.') {
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ /* Fully qualified ? */
+ if (*src == '\0') {
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = '\0';
+ }
+ if ((bp - dst) > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (1);
+ }
+ if (c == 0 || *src == '.') {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ label = bp++;
+ continue;
+ }
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = (u_char)c;
+ }
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ done:
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = 0;
+ }
+ if ((bp - dst) > MAXCDNAME) { /*%< src too big */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (0);
+}
+
+/*%
+ * Convert a network strings labels into all lowercase.
+ *
+ * return:
+ *\li Number of bytes written to buffer, or -1 (with errno set)
+ *
+ * notes:
+ *\li Enforces label and domain length limits.
+ */
+
+int
+ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
+{
+ const u_char *cp;
+ u_char *dn, *eom;
+ u_char c;
+ u_int n;
+ int l;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = n;
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ for ((void)NULL; l > 0; l--) {
+ c = *cp++;
+ if (isupper(c))
+ *dn++ = tolower(c);
+ else
+ *dn++ = c;
+ }
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*%
+ * Unpack a domain name from a message, source may be compressed.
+ *
+ * return:
+ *\li -1 if it fails, or consumed octets if it succeeds.
+ */
+int
+ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+ u_char *dst, size_t dstsiz)
+{
+ const u_char *srcp, *dstlim;
+ u_char *dstp;
+ int n, len, checked, l;
+
+ len = -1;
+ checked = 0;
+ dstp = dst;
+ srcp = src;
+ dstlim = dst + dstsiz;
+ if (srcp < msg || srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ /* Fetch next label in domain name. */
+ while ((n = *srcp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0:
+ case NS_TYPE_ELT:
+ /* Limit checks. */
+ if ((l = labellen(srcp - 1)) < 0) {
+ errno = EMSGSIZE;
+ return(-1);
+ }
+ if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += l + 1;
+ *dstp++ = n;
+ memcpy(dstp, srcp, l);
+ dstp += l;
+ srcp += l;
+ break;
+
+ case NS_CMPRSFLGS:
+ if (srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (len < 0)
+ len = srcp - src + 1;
+ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+ if (srcp < msg || srcp >= eom) { /*%< Out of range. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eom - msg) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+
+ default:
+ errno = EMSGSIZE;
+ return (-1); /*%< flag error */
+ }
+ }
+ *dstp = '\0';
+ if (len < 0)
+ len = srcp - src;
+ return (len);
+}
+
+/*%
+ * Pack domain name 'domain' into 'comp_dn'.
+ *
+ * return:
+ *\li Size of the compressed name, or -1.
+ *
+ * notes:
+ *\li 'dnptrs' is an array of pointers to previous compressed names.
+ *\li dnptrs[0] is a pointer to the beginning of the message. The array
+ * ends with NULL.
+ *\li 'lastdnptr' is a pointer to the end of the array pointed to
+ * by 'dnptrs'.
+ *
+ * Side effects:
+ *\li The list of pointers in dnptrs is updated for labels inserted into
+ * the message as we compress the name. If 'dnptr' is NULL, we don't
+ * try to compress names. If 'lastdnptr' is NULL, we don't update the
+ * list.
+ */
+int
+ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char *dstp;
+ const u_char **cpp, **lpp, *eob, *msg;
+ const u_char *srcp;
+ int n, l, first = 1;
+
+ srcp = src;
+ dstp = dst;
+ eob = dstp + dstsiz;
+ lpp = cpp = NULL;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ (void)NULL;
+ lpp = cpp; /*%< end of list to search */
+ }
+ } else
+ msg = NULL;
+
+ /* make sure the domain we are about to add is legal */
+ l = 0;
+ do {
+ int l0;
+
+ n = *srcp;
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if ((l0 = labellen(srcp)) < 0) {
+ errno = EINVAL;
+ return(-1);
+ }
+ l += l0 + 1;
+ if (l > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ srcp += l0 + 1;
+ } while (n != 0);
+
+ /* from here on we need to reset compression pointer array on error */
+ srcp = src;
+ do {
+ /* Look to see if we can use pointers. */
+ n = *srcp;
+ if (n != 0 && msg != NULL) {
+ l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+ (const u_char * const *)lpp);
+ if (l >= 0) {
+ if (dstp + 1 >= eob) {
+ goto cleanup;
+ }
+ *dstp++ = (l >> 8) | NS_CMPRSFLGS;
+ *dstp++ = l % 256;
+ return (dstp - dst);
+ }
+ /* Not found, save it. */
+ if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ (dstp - msg) < 0x4000 && first) {
+ *cpp++ = dstp;
+ *cpp = NULL;
+ first = 0;
+ }
+ }
+ /* copy label to buffer */
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Should not happen. */
+ goto cleanup;
+ }
+ n = labellen(srcp);
+ if (dstp + 1 + n >= eob) {
+ goto cleanup;
+ }
+ memcpy(dstp, srcp, n + 1);
+ srcp += n + 1;
+ dstp += n + 1;
+ } while (n != 0);
+
+ if (dstp > eob) {
+cleanup:
+ if (msg != NULL)
+ *lpp = NULL;
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (dstp - dst);
+}
+
+/*%
+ * Expand compressed domain name to presentation format.
+ *
+ * return:
+ *\li Number of bytes read out of `src', or -1 (with errno set).
+ *
+ * note:
+ *\li Root domain returns as "." not "".
+ */
+int
+ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, size_t dstsiz)
+{
+ u_char tmp[NS_MAXCDNAME];
+ int n;
+
+ if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
+ return (-1);
+ if (ns_name_ntop(tmp, dst, dstsiz) == -1)
+ return (-1);
+ return (n);
+}
+
+/*%
+ * Compress a domain name into wire format, using compression pointers.
+ *
+ * return:
+ *\li Number of bytes consumed in `dst' or -1 (with errno set).
+ *
+ * notes:
+ *\li 'dnptrs' is an array of pointers to previous compressed names.
+ *\li dnptrs[0] is a pointer to the beginning of the message.
+ *\li The list ends with NULL. 'lastdnptr' is a pointer to the end of the
+ * array pointed to by 'dnptrs'. Side effect is to update the list of
+ * pointers for labels inserted into the message as we compress the name.
+ *\li If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+int
+ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char tmp[NS_MAXCDNAME];
+
+ if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+ return (-1);
+ return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+}
+
+/*%
+ * Reset dnptrs so that there are no active references to pointers at or
+ * after src.
+ */
+void
+ns_name_rollback(const u_char *src, const u_char **dnptrs,
+ const u_char **lastdnptr)
+{
+ while (dnptrs < lastdnptr && *dnptrs != NULL) {
+ if (*dnptrs >= src) {
+ *dnptrs = NULL;
+ break;
+ }
+ dnptrs++;
+ }
+}
+
+/*%
+ * Advance *ptrptr to skip over the compressed name it points at.
+ *
+ * return:
+ *\li 0 on success, -1 (with errno set) on failure.
+ */
+int
+ns_name_skip(const u_char **ptrptr, const u_char *eom)
+{
+ const u_char *cp;
+ u_int n;
+ int l;
+
+ cp = *ptrptr;
+ while (cp < eom && (n = *cp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /*%< normal case, n == len */
+ cp += n;
+ continue;
+ case NS_TYPE_ELT: /*%< EDNS0 extended label */
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE; /*%< XXX */
+ return(-1);
+ }
+ cp += l;
+ continue;
+ case NS_CMPRSFLGS: /*%< indirection */
+ cp++;
+ break;
+ default: /*%< illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+ }
+ if (cp > eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *ptrptr = cp;
+ return (0);
+}
+
+/* Private. */
+
+/*%
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this characted special ("in need of quoting") ?
+ *
+ * return:
+ *\li boolean.
+ */
+static int
+special(int ch) {
+ switch (ch) {
+ case 0x22: /*%< '"' */
+ case 0x2E: /*%< '.' */
+ case 0x3B: /*%< ';' */
+ case 0x5C: /*%< '\\' */
+ case 0x28: /*%< '(' */
+ case 0x29: /*%< ')' */
+ /* Special modifiers in zone files. */
+ case 0x40: /*%< '@' */
+ case 0x24: /*%< '$' */
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+/*%
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this character visible and not a space when printed ?
+ *
+ * return:
+ *\li boolean.
+ */
+static int
+printable(int ch) {
+ return (ch > 0x20 && ch < 0x7f);
+}
+
+/*%
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * convert this character to lower case if it's upper case.
+ */
+static int
+mklower(int ch) {
+ if (ch >= 0x41 && ch <= 0x5A)
+ return (ch + 0x20);
+ return (ch);
+}
+
+/*%
+ * Search for the counted-label name in an array of compressed names.
+ *
+ * return:
+ *\li offset from msg if found, or -1.
+ *
+ * notes:
+ *\li dnptrs is the pointer to the first name on the list,
+ *\li not the pointer to the start of the message.
+ */
+static int
+dn_find(const u_char *domain, const u_char *msg,
+ const u_char * const *dnptrs,
+ const u_char * const *lastdnptr)
+{
+ const u_char *dn, *cp, *sp;
+ const u_char * const *cpp;
+ u_int n;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ sp = *cpp;
+ /*
+ * terminate search on:
+ * root label
+ * compression pointer
+ * unusable offset
+ */
+ while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
+ (sp - msg) < 0x4000) {
+ dn = domain;
+ cp = sp;
+ while ((n = *cp++) != 0) {
+ /*
+ * check for indirection
+ */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /*%< normal case, n == len */
+ n = labellen(cp - 1); /*%< XXX */
+ if (n != *dn++)
+ goto next;
+
+ for ((void)NULL; n > 0; n--)
+ if (mklower(*dn++) !=
+ mklower(*cp++))
+ goto next;
+ /* Is next root for both ? */
+ if (*dn == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (*dn)
+ continue;
+ goto next;
+ case NS_CMPRSFLGS: /*%< indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /*%< illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ }
+ next: ;
+ sp += *sp + 1;
+ }
+ }
+ errno = ENOENT;
+ return (-1);
+}
+
+static int
+decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
+{
+ const unsigned char *cp = *cpp;
+ char *beg = dn, tc;
+ int b, blen, plen, i;
+
+ if ((blen = (*cp & 0xff)) == 0)
+ blen = 256;
+ plen = (blen + 3) / 4;
+ plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
+ if (dn + plen >= eom)
+ return(-1);
+
+ cp++;
+ i = SPRINTF((dn, "\\[x"));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ for (b = blen; b > 7; b -= 8, cp++) {
+ i = SPRINTF((dn, "%02x", *cp & 0xff));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ }
+ if (b > 4) {
+ tc = *cp++;
+ i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ } else if (b > 0) {
+ tc = *cp++;
+ i = SPRINTF((dn, "%1x",
+ ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ }
+ i = SPRINTF((dn, "/%d]", blen));
+ if (i < 0)
+ return (-1);
+ dn += i;
+
+ *cpp = cp;
+ return(dn - beg);
+}
+
+static int
+encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
+ unsigned char ** dst, unsigned const char *eom)
+{
+ int afterslash = 0;
+ const char *cp = *bp;
+ unsigned char *tp;
+ char c;
+ const char *beg_blen;
+ char *end_blen = NULL;
+ int value = 0, count = 0, tbcount = 0, blen = 0;
+
+ beg_blen = end_blen = NULL;
+
+ /* a bitstring must contain at least 2 characters */
+ if (end - cp < 2)
+ return(EINVAL);
+
+ /* XXX: currently, only hex strings are supported */
+ if (*cp++ != 'x')
+ return(EINVAL);
+ if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
+ return(EINVAL);
+
+ for (tp = *dst + 1; cp < end && tp < eom; cp++) {
+ switch((c = *cp)) {
+ case ']': /*%< end of the bitstring */
+ if (afterslash) {
+ if (beg_blen == NULL)
+ return(EINVAL);
+ blen = (int)strtol(beg_blen, &end_blen, 10);
+ if (*end_blen != ']')
+ return(EINVAL);
+ }
+ if (count)
+ *tp++ = ((value << 4) & 0xff);
+ cp++; /*%< skip ']' */
+ goto done;
+ case '/':
+ afterslash = 1;
+ break;
+ default:
+ if (afterslash) {
+ if (!isdigit(c&0xff))
+ return(EINVAL);
+ if (beg_blen == NULL) {
+
+ if (c == '0') {
+ /* blen never begings with 0 */
+ return(EINVAL);
+ }
+ beg_blen = cp;
+ }
+ } else {
+ if (!isxdigit(c&0xff))
+ return(EINVAL);
+ value <<= 4;
+ value += digitvalue[(int)c];
+ count += 4;
+ tbcount += 4;
+ if (tbcount > 256)
+ return(EINVAL);
+ if (count == 8) {
+ *tp++ = value;
+ count = 0;
+ }
+ }
+ break;
+ }
+ }
+ done:
+ if (cp >= end || tp >= eom)
+ return(EMSGSIZE);
+
+ /*
+ * bit length validation:
+ * If a <length> is present, the number of digits in the <bit-data>
+ * MUST be just sufficient to contain the number of bits specified
+ * by the <length>. If there are insignificant bits in a final
+ * hexadecimal or octal digit, they MUST be zero.
+ * RFC2673, Section 3.2.
+ */
+ if (blen > 0) {
+ int traillen;
+
+ if (((blen + 3) & ~3) != tbcount)
+ return(EINVAL);
+ traillen = tbcount - blen; /*%< between 0 and 3 */
+ if (((value << (8 - traillen)) & 0xff) != 0)
+ return(EINVAL);
+ }
+ else
+ blen = tbcount;
+ if (blen == 256)
+ blen = 0;
+
+ /* encode the type and the significant bit fields */
+ **labelp = DNS_LABELTYPE_BITSTRING;
+ **dst = blen;
+
+ *bp = cp;
+ *dst = tp;
+
+ return(0);
+}
+
+static int
+labellen(const u_char *lp)
+{
+ int bitlen;
+ u_char l = *lp;
+
+ if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* should be avoided by the caller */
+ return(-1);
+ }
+
+ if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+ if (l == DNS_LABELTYPE_BITSTRING) {
+ if ((bitlen = *(lp + 1)) == 0)
+ bitlen = 256;
+ return((bitlen + 7 ) / 8 + 1);
+ }
+ return(-1); /*%< unknwon ELT */
+ }
+ return(l);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/nameser/ns_netint.c b/freebsd/lib/libc/nameser/ns_netint.c
new file mode 100644
index 00000000..7e4b0818
--- /dev/null
+++ b/freebsd/lib/libc/nameser/ns_netint.c
@@ -0,0 +1,60 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_netint.c,v 1.2.18.1 2005/04/27 05:01:08 sra Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <arpa/nameser.h>
+
+#include "port_after.h"
+
+/* Public. */
+
+u_int
+ns_get16(const u_char *src) {
+ u_int dst;
+
+ NS_GET16(dst, src);
+ return (dst);
+}
+
+u_long
+ns_get32(const u_char *src) {
+ u_long dst;
+
+ NS_GET32(dst, src);
+ return (dst);
+}
+
+void
+ns_put16(u_int src, u_char *dst) {
+ NS_PUT16(src, dst);
+}
+
+void
+ns_put32(u_long src, u_char *dst) {
+ NS_PUT32(src, dst);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/nameser/ns_parse.c b/freebsd/lib/libc/nameser/ns_parse.c
new file mode 100644
index 00000000..2d794eab
--- /dev/null
+++ b/freebsd/lib/libc/nameser/ns_parse.c
@@ -0,0 +1,213 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_parse.c,v 1.5.18.4 2007/08/27 03:34:24 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/* Forward. */
+
+static void setsection(ns_msg *msg, ns_sect sect);
+
+/* Macros. */
+
+#if !defined(SOLARIS2) || defined(__COVERITY__)
+#define RETERR(err) do { errno = (err); return (-1); } while (0)
+#else
+#define RETERR(err) \
+ do { errno = (err); if (errno == errno) return (-1); } while (0)
+#endif
+
+/* Public. */
+
+/* These need to be in the same order as the nres.h:ns_flag enum. */
+struct _ns_flagdata _ns_flagdata[16] = {
+ { 0x8000, 15 }, /*%< qr. */
+ { 0x7800, 11 }, /*%< opcode. */
+ { 0x0400, 10 }, /*%< aa. */
+ { 0x0200, 9 }, /*%< tc. */
+ { 0x0100, 8 }, /*%< rd. */
+ { 0x0080, 7 }, /*%< ra. */
+ { 0x0040, 6 }, /*%< z. */
+ { 0x0020, 5 }, /*%< ad. */
+ { 0x0010, 4 }, /*%< cd. */
+ { 0x000f, 0 }, /*%< rcode. */
+ { 0x0000, 0 }, /*%< expansion (1/6). */
+ { 0x0000, 0 }, /*%< expansion (2/6). */
+ { 0x0000, 0 }, /*%< expansion (3/6). */
+ { 0x0000, 0 }, /*%< expansion (4/6). */
+ { 0x0000, 0 }, /*%< expansion (5/6). */
+ { 0x0000, 0 }, /*%< expansion (6/6). */
+};
+
+int ns_msg_getflag(ns_msg handle, int flag) {
+ return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift);
+}
+
+int
+ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
+ const u_char *optr = ptr;
+
+ for ((void)NULL; count > 0; count--) {
+ int b, rdlength;
+
+ b = dn_skipname(ptr, eom);
+ if (b < 0)
+ RETERR(EMSGSIZE);
+ ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
+ if (section != ns_s_qd) {
+ if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ ptr += NS_INT32SZ/*TTL*/;
+ NS_GET16(rdlength, ptr);
+ ptr += rdlength/*RData*/;
+ }
+ }
+ if (ptr > eom)
+ RETERR(EMSGSIZE);
+ return (ptr - optr);
+}
+
+int
+ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
+ const u_char *eom = msg + msglen;
+ int i;
+
+ memset(handle, 0x5e, sizeof *handle);
+ handle->_msg = msg;
+ handle->_eom = eom;
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_id, msg);
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_flags, msg);
+ for (i = 0; i < ns_s_max; i++) {
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_counts[i], msg);
+ }
+ for (i = 0; i < ns_s_max; i++)
+ if (handle->_counts[i] == 0)
+ handle->_sections[i] = NULL;
+ else {
+ int b = ns_skiprr(msg, eom, (ns_sect)i,
+ handle->_counts[i]);
+
+ if (b < 0)
+ return (-1);
+ handle->_sections[i] = msg;
+ msg += b;
+ }
+ if (msg != eom)
+ RETERR(EMSGSIZE);
+ setsection(handle, ns_s_max);
+ return (0);
+}
+
+int
+ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
+ int b;
+ int tmp;
+
+ /* Make section right. */
+ tmp = section;
+ if (tmp < 0 || section >= ns_s_max)
+ RETERR(ENODEV);
+ if (section != handle->_sect)
+ setsection(handle, section);
+
+ /* Make rrnum right. */
+ if (rrnum == -1)
+ rrnum = handle->_rrnum;
+ if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
+ RETERR(ENODEV);
+ if (rrnum < handle->_rrnum)
+ setsection(handle, section);
+ if (rrnum > handle->_rrnum) {
+ b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
+ rrnum - handle->_rrnum);
+
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ handle->_rrnum = rrnum;
+ }
+
+ /* Do the parse. */
+ b = dn_expand(handle->_msg, handle->_eom,
+ handle->_msg_ptr, rr->name, NS_MAXDNAME);
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(rr->type, handle->_msg_ptr);
+ NS_GET16(rr->rr_class, handle->_msg_ptr);
+ if (section == ns_s_qd) {
+ rr->ttl = 0;
+ rr->rdlength = 0;
+ rr->rdata = NULL;
+ } else {
+ if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET32(rr->ttl, handle->_msg_ptr);
+ NS_GET16(rr->rdlength, handle->_msg_ptr);
+ if (handle->_msg_ptr + rr->rdlength > handle->_eom)
+ RETERR(EMSGSIZE);
+ rr->rdata = handle->_msg_ptr;
+ handle->_msg_ptr += rr->rdlength;
+ }
+ if (++handle->_rrnum > handle->_counts[(int)section])
+ setsection(handle, (ns_sect)((int)section + 1));
+
+ /* All done. */
+ return (0);
+}
+
+/* Private. */
+
+static void
+setsection(ns_msg *msg, ns_sect sect) {
+ msg->_sect = sect;
+ if (sect == ns_s_max) {
+ msg->_rrnum = -1;
+ msg->_msg_ptr = NULL;
+ } else {
+ msg->_rrnum = 0;
+ msg->_msg_ptr = msg->_sections[(int)sect];
+ }
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/nameser/ns_print.c b/freebsd/lib/libc/nameser/ns_print.c
new file mode 100644
index 00000000..a4095e00
--- /dev/null
+++ b/freebsd/lib/libc/nameser/ns_print.c
@@ -0,0 +1,910 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_print.c,v 1.6.18.4 2005/04/27 05:01:09 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#ifdef _LIBC
+#include <assert.h>
+#define INSIST(cond) assert(cond)
+#else
+#include <isc/assertions.h>
+#include <isc/dst.h>
+#endif
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static size_t prune_origin(const char *name, const char *origin);
+static int charstr(const u_char *rdata, const u_char *edata,
+ char **buf, size_t *buflen);
+static int addname(const u_char *msg, size_t msglen,
+ const u_char **p, const char *origin,
+ char **buf, size_t *buflen);
+static void addlen(size_t len, char **buf, size_t *buflen);
+static int addstr(const char *src, size_t len,
+ char **buf, size_t *buflen);
+static int addtab(size_t len, size_t target, int spaced,
+ char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) \
+ do { \
+ if ((x) < 0) \
+ return (-1); \
+ } while (0)
+
+/* Public. */
+
+/*%
+ * Convert an RR to presentation format.
+ *
+ * return:
+ *\li Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ int n;
+
+ n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
+ ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
+ ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
+ name_ctx, origin, buf, buflen);
+ return (n);
+}
+
+/*%
+ * Convert the fields of an RR into presentation format.
+ *
+ * return:
+ *\li Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrrf(const u_char *msg, size_t msglen,
+ const char *name, ns_class class, ns_type type,
+ u_long ttl, const u_char *rdata, size_t rdlen,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ const char *obuf = buf;
+ const u_char *edata = rdata + rdlen;
+ int spaced = 0;
+
+ const char *comment;
+ char tmp[100];
+ int len, x;
+
+ /*
+ * Owner.
+ */
+ if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
+ T(addstr("\t\t\t", 3, &buf, &buflen));
+ } else {
+ len = prune_origin(name, origin);
+ if (*name == '\0') {
+ goto root;
+ } else if (len == 0) {
+ T(addstr("@\t\t\t", 4, &buf, &buflen));
+ } else {
+ T(addstr(name, len, &buf, &buflen));
+ /* Origin not used or not root, and no trailing dot? */
+ if (((origin == NULL || origin[0] == '\0') ||
+ (origin[0] != '.' && origin[1] != '\0' &&
+ name[len] == '\0')) && name[len - 1] != '.') {
+ root:
+ T(addstr(".", 1, &buf, &buflen));
+ len++;
+ }
+ T(spaced = addtab(len, 24, spaced, &buf, &buflen));
+ }
+ }
+
+ /*
+ * TTL, Class, Type.
+ */
+ T(x = ns_format_ttl(ttl, buf, buflen));
+ addlen(x, &buf, &buflen);
+ len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
+
+ /*
+ * RData.
+ */
+ switch (type) {
+ case ns_t_a:
+ if (rdlen != (size_t)NS_INADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ case ns_t_ns:
+ case ns_t_ptr:
+ case ns_t_dname:
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+
+ case ns_t_hinfo:
+ case ns_t_isdn:
+ /* First word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+
+ /* Second word, optional in ISDN records. */
+ if (type == ns_t_isdn && rdata == edata)
+ break;
+
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_soa: {
+ u_long t;
+
+ /* Server name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Administrator name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" (\n", 3, &buf, &buflen));
+ spaced = 0;
+
+ if ((edata - rdata) != 5*NS_INT32SZ)
+ goto formerr;
+
+ /* Serial number. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ len = SPRINTF((tmp, "%lu", t));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; serial\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Refresh interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; refresh\n", 10, &buf, &buflen));
+ spaced = 0;
+
+ /* Retry interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; retry\n", 8, &buf, &buflen));
+ spaced = 0;
+
+ /* Expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; expiry\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Minimum TTL. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(addstr(" )", 2, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; minimum\n", 10, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_rt: {
+ u_int t;
+
+ if (rdlen < (size_t)NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Target. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_px: {
+ u_int t;
+
+ if (rdlen < (size_t)NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_x25:
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_txt:
+ while (rdata < edata) {
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ if (rdata < edata)
+ T(addstr(" ", 1, &buf, &buflen));
+ }
+ break;
+
+ case ns_t_nsap: {
+ char t[2+255*3];
+
+ (void) inet_nsap_ntoa(rdlen, rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_aaaa:
+ if (rdlen != (size_t)NS_IN6ADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET6, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_loc: {
+ char t[255];
+
+ /* XXX protocol format checking? */
+ (void) loc_ntoa(rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_naptr: {
+ u_int order, preference;
+ char t[50];
+
+ if (rdlen < 2U*NS_INT16SZ)
+ goto formerr;
+
+ /* Order, Precedence. */
+ order = ns_get16(rdata); rdata += NS_INT16SZ;
+ preference = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u ", order, preference));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Flags. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Service. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Regexp. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len < 0)
+ return (-1);
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_srv: {
+ u_int priority, weight, port;
+ char t[50];
+
+ if (rdlen < 3U*NS_INT16SZ)
+ goto formerr;
+
+ /* Priority, Weight, Port. */
+ priority = ns_get16(rdata); rdata += NS_INT16SZ;
+ weight = ns_get16(rdata); rdata += NS_INT16SZ;
+ port = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u %u ", priority, weight, port));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_minfo:
+ case ns_t_rp:
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+
+ case ns_t_wks: {
+ int n, lcnt;
+
+ if (rdlen < 1U + NS_INT32SZ)
+ goto formerr;
+
+ /* Address. */
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += NS_INADDRSZ;
+
+ /* Protocol. */
+ len = SPRINTF((tmp, " %u ( ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ rdata += NS_INT8SZ;
+
+ /* Bit map. */
+ n = 0;
+ lcnt = 0;
+ while (rdata < edata) {
+ u_int c = *rdata++;
+ do {
+ if (c & 0200) {
+ if (lcnt == 0) {
+ T(addstr("\n\t\t\t\t", 5,
+ &buf, &buflen));
+ lcnt = 10;
+ spaced = 0;
+ }
+ len = SPRINTF((tmp, "%d ", n));
+ T(addstr(tmp, len, &buf, &buflen));
+ lcnt--;
+ }
+ c <<= 1;
+ } while (++n & 07);
+ }
+ T(addstr(")", 1, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_key: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int keyflags, protocol, algorithm, key_id;
+ const char *leader;
+ int n;
+
+ if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
+ goto formerr;
+
+ /* Key flags, Protocol, Algorithm. */
+#ifndef _LIBC
+ key_id = dst_s_dns_key_id(rdata, edata-rdata);
+#else
+ key_id = 0;
+#endif
+ keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
+ protocol = *rdata++;
+ algorithm = *rdata++;
+ len = SPRINTF((tmp, "0x%04x %u %u",
+ keyflags, protocol, algorithm));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Public key data. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len < 0)
+ goto formerr;
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ n = SPRINTF((tmp, " ; key_tag= %u", key_id));
+ T(addstr(tmp, n, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_sig: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int type, algorithm, labels, footprint;
+ const char *leader;
+ u_long t;
+ int n;
+
+ if (rdlen < 22U)
+ goto formerr;
+
+ /* Type covered, Algorithm, Label count, Original TTL. */
+ type = ns_get16(rdata); rdata += NS_INT16SZ;
+ algorithm = *rdata++;
+ labels = *rdata++;
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s %d %d %lu ",
+ p_type(type), algorithm, labels, t));
+ T(addstr(tmp, len, &buf, &buflen));
+ if (labels > (u_int)dn_count_labels(name))
+ goto formerr;
+
+ /* Signature expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Time signed. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signature Footprint. */
+ footprint = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", footprint));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signer's name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Signature. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ if (len < 0)
+ goto formerr;
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_nxt: {
+ int n, c;
+
+ /* Next domain name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Type bit map. */
+ n = edata - rdata;
+ for (c = 0; c < n*8; c++)
+ if (NS_NXT_BIT_ISSET(c, rdata)) {
+ len = SPRINTF((tmp, " %s", p_type(c)));
+ T(addstr(tmp, len, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_cert: {
+ u_int c_type, key_tag, alg;
+ int n;
+ unsigned int siz;
+ char base64_cert[8192], tmp[40];
+ const char *leader;
+
+ c_type = ns_get16(rdata); rdata += NS_INT16SZ;
+ key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
+ alg = (u_int) *rdata++;
+
+ len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
+ T(addstr(tmp, len, &buf, &buflen));
+ siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
+ if (siz > sizeof(base64_cert) * 3/4) {
+ const char *str = "record too long to print";
+ T(addstr(str, strlen(str), &buf, &buflen));
+ }
+ else {
+ len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
+
+ if (len < 0)
+ goto formerr;
+ else if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ }
+ else
+ leader = " ";
+
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader),
+ &buf, &buflen));
+ T(addstr(base64_cert + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_tkey: {
+ /* KJD - need to complete this */
+ u_long t;
+ int mode, err, keysize;
+
+ /* Algorithm name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Inception. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Experation. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Mode , Error, Key Size. */
+ /* Priority, Weight, Port. */
+ mode = ns_get16(rdata); rdata += NS_INT16SZ;
+ err = ns_get16(rdata); rdata += NS_INT16SZ;
+ keysize = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* XXX need to dump key, print otherdata length & other data */
+ break;
+ }
+
+ case ns_t_tsig: {
+ /* BEW - need to complete this */
+ int n;
+
+ T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+ rdata += 8; /*%< time */
+ n = ns_get16(rdata); rdata += INT16SZ;
+ rdata += n; /*%< sig */
+ n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
+ sprintf(buf, "%d", ns_get16(rdata));
+ rdata += INT16SZ;
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+ }
+
+ case ns_t_a6: {
+ struct in6_addr a;
+ int pbyte, pbit;
+
+ /* prefix length */
+ if (rdlen == 0U) goto formerr;
+ len = SPRINTF((tmp, "%d ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ pbit = *rdata;
+ if (pbit > 128) goto formerr;
+ pbyte = (pbit & ~7) / 8;
+ rdata++;
+
+ /* address suffix: provided only when prefix len != 128 */
+ if (pbit < 128) {
+ if (rdata + pbyte >= edata) goto formerr;
+ memset(&a, 0, sizeof(a));
+ memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
+ (void) inet_ntop(AF_INET6, &a, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += sizeof(a) - pbyte;
+ }
+
+ /* prefix name: provided only when prefix len > 0 */
+ if (pbit == 0)
+ break;
+ if (rdata >= edata) goto formerr;
+ T(addstr(" ", 1, &buf, &buflen));
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_opt: {
+ len = SPRINTF((tmp, "%u bytes", class));
+ T(addstr(tmp, len, &buf, &buflen));
+ break;
+ }
+
+ default:
+ comment = "unknown RR type";
+ goto hexify;
+ }
+ return (buf - obuf);
+ formerr:
+ comment = "RR format error";
+ hexify: {
+ int n, m;
+ char *p;
+
+ len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
+ rdlen != 0U ? " (" : "", comment));
+ T(addstr(tmp, len, &buf, &buflen));
+ while (rdata < edata) {
+ p = tmp;
+ p += SPRINTF((p, "\n\t"));
+ spaced = 0;
+ n = MIN(16, edata - rdata);
+ for (m = 0; m < n; m++)
+ p += SPRINTF((p, "%02x ", rdata[m]));
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ if (n < 16) {
+ T(addstr(")", 1, &buf, &buflen));
+ T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
+ }
+ p = tmp;
+ p += SPRINTF((p, "; "));
+ for (m = 0; m < n; m++)
+ *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
+ ? rdata[m]
+ : '.';
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ rdata += n;
+ }
+ return (buf - obuf);
+ }
+}
+
+/* Private. */
+
+/*%
+ * size_t
+ * prune_origin(name, origin)
+ * Find out if the name is at or under the current origin.
+ * return:
+ * Number of characters in name before start of origin,
+ * or length of name if origin does not match.
+ * notes:
+ * This function should share code with samedomain().
+ */
+static size_t
+prune_origin(const char *name, const char *origin) {
+ const char *oname = name;
+
+ while (*name != '\0') {
+ if (origin != NULL && ns_samename(name, origin) == 1)
+ return (name - oname - (name > oname));
+ while (*name != '\0') {
+ if (*name == '\\') {
+ name++;
+ /* XXX need to handle \nnn form. */
+ if (*name == '\0')
+ break;
+ } else if (*name == '.') {
+ name++;
+ break;
+ }
+ name++;
+ }
+ }
+ return (name - oname);
+}
+
+/*%
+ * int
+ * charstr(rdata, edata, buf, buflen)
+ * Format a <character-string> into the presentation buffer.
+ * return:
+ * Number of rdata octets consumed
+ * 0 for protocol format error
+ * -1 for output buffer error
+ * side effects:
+ * buffer is advanced on success.
+ */
+static int
+charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
+ const u_char *odata = rdata;
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ if (rdata < edata) {
+ int n = *rdata;
+
+ if (rdata + 1 + n <= edata) {
+ rdata++;
+ while (n-- > 0) {
+ if (strchr("\n\"\\", *rdata) != NULL)
+ if (addstr("\\", 1, buf, buflen) < 0)
+ goto enospc;
+ if (addstr((const char *)rdata, 1,
+ buf, buflen) < 0)
+ goto enospc;
+ rdata++;
+ }
+ }
+ }
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ return (rdata - odata);
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static int
+addname(const u_char *msg, size_t msglen,
+ const u_char **pp, const char *origin,
+ char **buf, size_t *buflen)
+{
+ size_t newlen, save_buflen = *buflen;
+ char *save_buf = *buf;
+ int n;
+
+ n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
+ if (n < 0)
+ goto enospc; /*%< Guess. */
+ newlen = prune_origin(*buf, origin);
+ if (**buf == '\0') {
+ goto root;
+ } else if (newlen == 0U) {
+ /* Use "@" instead of name. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for "@\0". */
+ (*buf)[newlen++] = '@';
+ (*buf)[newlen] = '\0';
+ } else {
+ if (((origin == NULL || origin[0] == '\0') ||
+ (origin[0] != '.' && origin[1] != '\0' &&
+ (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
+ /* No trailing dot. */
+ root:
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for ".\0". */
+ (*buf)[newlen++] = '.';
+ (*buf)[newlen] = '\0';
+ }
+ }
+ *pp += n;
+ addlen(newlen, buf, buflen);
+ **buf = '\0';
+ return (newlen);
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static void
+addlen(size_t len, char **buf, size_t *buflen) {
+ INSIST(len <= *buflen);
+ *buf += len;
+ *buflen -= len;
+}
+
+static int
+addstr(const char *src, size_t len, char **buf, size_t *buflen) {
+ if (len >= *buflen) {
+ errno = ENOSPC;
+ return (-1);
+ }
+ memcpy(*buf, src, len);
+ addlen(len, buf, buflen);
+ **buf = '\0';
+ return (0);
+}
+
+static int
+addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+ int t;
+
+ if (spaced || len >= target - 1) {
+ T(addstr(" ", 2, buf, buflen));
+ spaced = 1;
+ } else {
+ for (t = (target - len - 1) / 8; t >= 0; t--)
+ if (addstr("\t", 1, buf, buflen) < 0) {
+ *buflen = save_buflen;
+ *buf = save_buf;
+ return (-1);
+ }
+ spaced = 0;
+ }
+ return (spaced);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/nameser/ns_samedomain.c b/freebsd/lib/libc/nameser/ns_samedomain.c
new file mode 100644
index 00000000..9c43c79e
--- /dev/null
+++ b/freebsd/lib/libc/nameser/ns_samedomain.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_samedomain.c,v 1.5.18.1 2005/04/27 05:01:09 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*%
+ * Check whether a name belongs to a domain.
+ *
+ * Inputs:
+ *\li a - the domain whose ancestory is being verified
+ *\li b - the potential ancestor we're checking against
+ *
+ * Return:
+ *\li boolean - is a at or below b?
+ *
+ * Notes:
+ *\li Trailing dots are first removed from name and domain.
+ * Always compare complete subdomains, not only whether the
+ * domain name is the trailing string of the given name.
+ *
+ *\li "host.foobar.top" lies in "foobar.top" and in "top" and in ""
+ * but NOT in "bar.top"
+ */
+
+int
+ns_samedomain(const char *a, const char *b) {
+ size_t la, lb;
+ int diff, i, escaped;
+ const char *cp;
+
+ la = strlen(a);
+ lb = strlen(b);
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
+ if (la != 0U && a[la - 1] == '.') {
+ escaped = 0;
+ /* Note this loop doesn't get executed if la==1. */
+ for (i = la - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ la--;
+ }
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
+ if (lb != 0U && b[lb - 1] == '.') {
+ escaped = 0;
+ /* note this loop doesn't get executed if lb==1 */
+ for (i = lb - 2; i >= 0; i--)
+ if (b[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ lb--;
+ }
+
+ /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
+ if (lb == 0U)
+ return (1);
+
+ /* 'b' longer than 'a' means 'a' can't be in 'b'. */
+ if (lb > la)
+ return (0);
+
+ /* 'a' and 'b' being equal at this point indicates sameness. */
+ if (lb == la)
+ return (strncasecmp(a, b, lb) == 0);
+
+ /* Ok, we know la > lb. */
+
+ diff = la - lb;
+
+ /*
+ * If 'a' is only 1 character longer than 'b', then it can't be
+ * a subdomain of 'b' (because of the need for the '.' label
+ * separator).
+ */
+ if (diff < 2)
+ return (0);
+
+ /*
+ * If the character before the last 'lb' characters of 'b'
+ * isn't '.', then it can't be a match (this lets us avoid
+ * having "foobar.com" match "bar.com").
+ */
+ if (a[diff - 1] != '.')
+ return (0);
+
+ /*
+ * We're not sure about that '.', however. It could be escaped
+ * and thus not a really a label separator.
+ */
+ escaped = 0;
+ for (i = diff - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (escaped)
+ return (0);
+
+ /* Now compare aligned trailing substring. */
+ cp = a + diff;
+ return (strncasecmp(cp, b, lb) == 0);
+}
+
+#ifndef _LIBC
+/*%
+ * is "a" a subdomain of "b"?
+ */
+int
+ns_subdomain(const char *a, const char *b) {
+ return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
+}
+#endif
+
+/*%
+ * make a canonical copy of domain name "src"
+ *
+ * notes:
+ * \code
+ * foo -> foo.
+ * foo. -> foo.
+ * foo.. -> foo.
+ * foo\. -> foo\..
+ * foo\\. -> foo\\.
+ * \endcode
+ */
+
+int
+ns_makecanon(const char *src, char *dst, size_t dstsize) {
+ size_t n = strlen(src);
+
+ if (n + sizeof "." > dstsize) { /*%< Note: sizeof == 2 */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ strcpy(dst, src);
+ while (n >= 1U && dst[n - 1] == '.') /*%< Ends in "." */
+ if (n >= 2U && dst[n - 2] == '\\' && /*%< Ends in "\." */
+ (n < 3U || dst[n - 3] != '\\')) /*%< But not "\\." */
+ break;
+ else
+ dst[--n] = '\0';
+ dst[n++] = '.';
+ dst[n] = '\0';
+ return (0);
+}
+
+/*%
+ * determine whether domain name "a" is the same as domain name "b"
+ *
+ * return:
+ *\li -1 on error
+ *\li 0 if names differ
+ *\li 1 if names are the same
+ */
+
+int
+ns_samename(const char *a, const char *b) {
+ char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
+
+ if (ns_makecanon(a, ta, sizeof ta) < 0 ||
+ ns_makecanon(b, tb, sizeof tb) < 0)
+ return (-1);
+ if (strcasecmp(ta, tb) == 0)
+ return (1);
+ else
+ return (0);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/nameser/ns_ttl.c b/freebsd/lib/libc/nameser/ns_ttl.c
new file mode 100644
index 00000000..821c531f
--- /dev/null
+++ b/freebsd/lib/libc/nameser/ns_ttl.c
@@ -0,0 +1,164 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_ttl.c,v 1.2.18.2 2005/07/28 07:38:10 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static int fmt1(int t, char s, char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) if ((x) < 0) return (-1); else (void)NULL
+
+/* Public. */
+
+int
+ns_format_ttl(u_long src, char *dst, size_t dstlen) {
+ char *odst = dst;
+ int secs, mins, hours, days, weeks, x;
+ char *p;
+
+ secs = src % 60; src /= 60;
+ mins = src % 60; src /= 60;
+ hours = src % 24; src /= 24;
+ days = src % 7; src /= 7;
+ weeks = src; src = 0;
+
+ x = 0;
+ if (weeks) {
+ T(fmt1(weeks, 'W', &dst, &dstlen));
+ x++;
+ }
+ if (days) {
+ T(fmt1(days, 'D', &dst, &dstlen));
+ x++;
+ }
+ if (hours) {
+ T(fmt1(hours, 'H', &dst, &dstlen));
+ x++;
+ }
+ if (mins) {
+ T(fmt1(mins, 'M', &dst, &dstlen));
+ x++;
+ }
+ if (secs || !(weeks || days || hours || mins)) {
+ T(fmt1(secs, 'S', &dst, &dstlen));
+ x++;
+ }
+
+ if (x > 1) {
+ int ch;
+
+ for (p = odst; (ch = *p) != '\0'; p++)
+ if (isascii(ch) && isupper(ch))
+ *p = tolower(ch);
+ }
+
+ return (dst - odst);
+}
+
+int
+ns_parse_ttl(const char *src, u_long *dst) {
+ u_long ttl, tmp;
+ int ch, digits, dirty;
+
+ ttl = 0;
+ tmp = 0;
+ digits = 0;
+ dirty = 0;
+ while ((ch = *src++) != '\0') {
+ if (!isascii(ch) || !isprint(ch))
+ goto einval;
+ if (isdigit(ch)) {
+ tmp *= 10;
+ tmp += (ch - '0');
+ digits++;
+ continue;
+ }
+ if (digits == 0)
+ goto einval;
+ if (islower(ch))
+ ch = toupper(ch);
+ switch (ch) {
+ case 'W': tmp *= 7;
+ case 'D': tmp *= 24;
+ case 'H': tmp *= 60;
+ case 'M': tmp *= 60;
+ case 'S': break;
+ default: goto einval;
+ }
+ ttl += tmp;
+ tmp = 0;
+ digits = 0;
+ dirty = 1;
+ }
+ if (digits > 0) {
+ if (dirty)
+ goto einval;
+ else
+ ttl += tmp;
+ } else if (!dirty)
+ goto einval;
+ *dst = ttl;
+ return (0);
+
+ einval:
+ errno = EINVAL;
+ return (-1);
+}
+
+/* Private. */
+
+static int
+fmt1(int t, char s, char **buf, size_t *buflen) {
+ char tmp[50];
+ size_t len;
+
+ len = SPRINTF((tmp, "%d%c", t, s));
+ if (len + 1 > *buflen)
+ return (-1);
+ strcpy(*buf, tmp);
+ *buf += len;
+ *buflen -= len;
+ return (0);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/net/base64.c b/freebsd/lib/libc/net/base64.c
new file mode 100644
index 00000000..6d3a79d6
--- /dev/null
+++ b/freebsd/lib/libc/net/base64.c
@@ -0,0 +1,317 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * 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 INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ u_char input[3];
+ u_char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(src, target, targsize)
+ char const *src;
+ u_char *target;
+ size_t targsize;
+{
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace((unsigned char)ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace((unsigned char)ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/freebsd/lib/libc/net/ether_addr.c b/freebsd/lib/libc/net/ether_addr.c
new file mode 100644
index 00000000..a16b97d3
--- /dev/null
+++ b/freebsd/lib/libc/net/ether_addr.c
@@ -0,0 +1,232 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>.
+ * Copyright (c) 2007 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
+ * 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 Bill Paul 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.
+ *
+ * ethernet address conversion and lookup routines
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _PATH_ETHERS
+#define _PATH_ETHERS "/etc/ethers"
+#endif
+
+/*
+ * Parse a string of text containing an ethernet address and hostname and
+ * separate it into its component parts.
+ */
+int
+ether_line(const char *l, struct ether_addr *e, char *hostname)
+{
+ int i, o[6];
+
+ i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3],
+ &o[4], &o[5], hostname);
+ if (i != 7)
+ return (i);
+ for (i=0; i<6; i++)
+ e->octet[i] = o[i];
+ return (0);
+}
+
+/*
+ * Convert an ASCII representation of an ethernet address to binary form.
+ */
+struct ether_addr *
+ether_aton_r(const char *a, struct ether_addr *e)
+{
+ int i;
+ unsigned int o0, o1, o2, o3, o4, o5;
+
+ i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
+ if (i != 6)
+ return (NULL);
+ e->octet[0]=o0;
+ e->octet[1]=o1;
+ e->octet[2]=o2;
+ e->octet[3]=o3;
+ e->octet[4]=o4;
+ e->octet[5]=o5;
+ return (e);
+}
+
+struct ether_addr *
+ether_aton(const char *a)
+{
+ static struct ether_addr e;
+
+ return (ether_aton_r(a, &e));
+}
+
+/*
+ * Convert a binary representation of an ethernet address to an ASCII string.
+ */
+char *
+ether_ntoa_r(const struct ether_addr *n, char *a)
+{
+ int i;
+
+ i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0],
+ n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]);
+ if (i < 17)
+ return (NULL);
+ return (a);
+}
+
+char *
+ether_ntoa(const struct ether_addr *n)
+{
+ static char a[18];
+
+ return (ether_ntoa_r(n, a));
+}
+
+/*
+ * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP.
+ */
+int
+ether_ntohost(char *hostname, const struct ether_addr *e)
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct ether_addr local_ether;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char *ether_a;
+ char *yp_domain;
+#endif
+
+ if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
+ return (1);
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ ether_a = ether_ntoa(e);
+ if (yp_match(yp_domain, "ethers.byaddr", ether_a,
+ strlen(ether_a), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (!ether_line(buf, &local_ether, local_host)) {
+ if (!bcmp((char *)&local_ether.octet[0],
+ (char *)&e->octet[0], 6)) {
+ /* We have a match. */
+ strcpy(hostname, local_host);
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
+
+/*
+ * Map a hostname to an ethernet address using /etc/ethers or NIS/YP.
+ */
+int
+ether_hostton(const char *hostname, struct ether_addr *e)
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct ether_addr local_ether;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char *yp_domain;
+#endif
+
+ if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
+ return (1);
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ if (yp_match(yp_domain, "ethers.byname", hostname,
+ strlen(hostname), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (!ether_line(buf, &local_ether, local_host)) {
+ if (!strcmp(hostname, local_host)) {
+ /* We have a match. */
+ bcopy((char *)&local_ether.octet[0],
+ (char *)&e->octet[0], 6);
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
diff --git a/freebsd/lib/libc/net/gai_strerror.c b/freebsd/lib/libc/net/gai_strerror.c
new file mode 100644
index 00000000..b1feb7b8
--- /dev/null
+++ b/freebsd/lib/libc/net/gai_strerror.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+#ifdef __rtems__
+#include <freebsd/machine/rtems-bsd-config.h>
+#include <freebsd/sys/_types.h>
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <netdb.h>
+#if defined(NLS)
+#include <nl_types.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include "reentrant.h"
+#endif
+#include "un-namespace.h"
+
+/* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */
+/* for backward compatibility with userland code prior to 2553bis-02 */
+static const char *ai_errlist[] = {
+ "Success", /* 0 */
+ "Address family for hostname not supported", /* 1 */
+ "Temporary failure in name resolution", /* EAI_AGAIN */
+ "Invalid value for ai_flags", /* EAI_BADFLAGS */
+ "Non-recoverable failure in name resolution", /* EAI_FAIL */
+ "ai_family not supported", /* EAI_FAMILY */
+ "Memory allocation failure", /* EAI_MEMORY */
+ "No address associated with hostname", /* 7 */
+ "hostname nor servname provided, or not known", /* EAI_NONAME */
+ "servname not supported for ai_socktype", /* EAI_SERVICE */
+ "ai_socktype not supported", /* EAI_SOCKTYPE */
+ "System error returned in errno", /* EAI_SYSTEM */
+ "Invalid value for hints", /* EAI_BADHINTS */
+ "Resolved protocol is unknown", /* EAI_PROTOCOL */
+ "Argument buffer overflow" /* EAI_OVERFLOW */
+};
+
+#if defined(NLS)
+static char gai_buf[NL_TEXTMAX];
+static once_t gai_init_once = ONCE_INITIALIZER;
+static thread_key_t gai_key;
+static int gai_keycreated = 0;
+
+static void
+gai_keycreate(void)
+{
+ gai_keycreated = (thr_keycreate(&gai_key, free) == 0);
+}
+#endif
+
+const char *
+gai_strerror(int ecode)
+{
+#if defined(NLS)
+ nl_catd catd;
+ char *buf;
+
+ if (thr_main() != 0)
+ buf = gai_buf;
+ else {
+ if (thr_once(&gai_init_once, gai_keycreate) != 0 ||
+ !gai_keycreated)
+ goto thr_err;
+ if ((buf = thr_getspecific(gai_key)) == NULL) {
+ if ((buf = malloc(sizeof(gai_buf))) == NULL)
+ goto thr_err;
+ if (thr_setspecific(gai_key, buf) != 0) {
+ free(buf);
+ goto thr_err;
+ }
+ }
+ }
+
+ catd = catopen("libc", NL_CAT_LOCALE);
+ if (ecode > 0 && ecode < EAI_MAX)
+ strlcpy(buf, catgets(catd, 3, ecode, ai_errlist[ecode]),
+ sizeof(gai_buf));
+ else if (ecode == 0)
+ strlcpy(buf, catgets(catd, 3, NL_MSGMAX - 1, "Success"),
+ sizeof(gai_buf));
+ else
+ strlcpy(buf, catgets(catd, 3, NL_MSGMAX, "Unknown error"),
+ sizeof(gai_buf));
+ catclose(catd);
+ return buf;
+
+thr_err:
+#endif
+ if (ecode >= 0 && ecode < EAI_MAX)
+ return ai_errlist[ecode];
+ return "Unknown error";
+}
diff --git a/freebsd/lib/libc/net/getaddrinfo.c b/freebsd/lib/libc/net/getaddrinfo.c
new file mode 100644
index 00000000..b9b52794
--- /dev/null
+++ b/freebsd/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,2857 @@
+#include "port_before.h"
+
+/* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
+ *
+ * Issues to be discussed:
+ * - Return values. There are nonstandard return values defined and used
+ * in the source code. This is because RFC2553 is silent about which error
+ * code must be returned for which situation.
+ * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
+ * invalid. current code - SEGV on freeaddrinfo(NULL)
+ *
+ * Note:
+ * - The code filters out AFs that are not supported by the kernel,
+ * when globbing NULL hostname (to loopback, or wildcard). Is it the right
+ * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
+ * in ai_flags?
+ * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
+ * (1) what should we do against numeric hostname (2) what should we do
+ * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
+ * non-loopback address configured? global address configured?
+ *
+ * OS specific notes for freebsd4:
+ * - FreeBSD supported $GAI. The code does not.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/queue.h>
+#ifdef INET6
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <freebsd/netinet6/in6_var.h> /* XXX */
+#else
+#include <net/if_var.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <netinet6/in6_var.h> /* XXX */
+#endif
+#endif
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "res_config.h"
+
+#ifdef DEBUG
+#include <syslog.h>
+#endif
+
+#include <stdarg.h>
+#include <nsswitch.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+#if defined(__KAME__) && defined(INET6)
+# define FAITH
+#endif
+
+#define ANY 0
+#define YES 1
+#define NO 0
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in_loopback[] = { 127, 0, 0, 1 };
+#ifdef INET6
+static const char in6_addrany[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in6_loopback[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+#endif
+
+struct policyqueue {
+ TAILQ_ENTRY(policyqueue) pc_entry;
+#ifdef INET6
+ struct in6_addrpolicy pc_policy;
+#endif
+};
+TAILQ_HEAD(policyhead, policyqueue);
+
+static const struct afd {
+ int a_af;
+ int a_addrlen;
+ socklen_t a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
+ int a_scoped;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback, 1},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback, 0},
+ {0, 0, 0, 0, NULL, NULL, 0},
+};
+
+struct explore {
+ int e_af;
+ int e_socktype;
+ int e_protocol;
+ const char *e_protostr;
+ int e_wild;
+#define WILD_AF(ex) ((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
+};
+
+static const struct explore explore[] = {
+#if 0
+ { 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 },
+ { -1, 0, 0, NULL, 0 },
+};
+
+#ifdef INET6
+#define PTON_MAX 16
+#else
+#define PTON_MAX 4
+#endif
+
+#define AIO_SRCFLAG_DEPRECATED 0x1
+
+struct ai_order {
+ union {
+ struct sockaddr_storage aiou_ss;
+ struct sockaddr aiou_sa;
+ } aio_src_un;
+#define aio_srcsa aio_src_un.aiou_sa
+ u_int32_t aio_srcflag;
+ int aio_srcscope;
+ int aio_dstscope;
+ struct policyqueue *aio_srcpolicy;
+ struct policyqueue *aio_dstpolicy;
+ struct addrinfo *aio_ai;
+ int aio_matchlen;
+};
+
+static const ns_src default_dns_files[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NSSRC_DNS, NS_SUCCESS },
+ { 0 }
+};
+
+struct res_target {
+ struct res_target *next;
+ const char *name; /* domain name */
+ int qclass, qtype; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer buffer */
+ int n; /* result length */
+};
+
+#define MAXPACKET (64*1024)
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} 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 *,
+ const char *, struct addrinfo **, const char *);
+static int explore_numeric_scope(const struct addrinfo *, const char *,
+ const char *, struct addrinfo **);
+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);
+static int addrconfig(struct addrinfo *);
+static void set_source(struct ai_order *, struct policyhead *);
+static int comp_dst(const void *, const void *);
+#ifdef INET6
+static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
+#endif
+static int gai_addr2scopetype(struct sockaddr *);
+
+static int explore_fqdn(const struct addrinfo *, const char *,
+ const char *, struct addrinfo **);
+
+static int reorder(struct addrinfo *);
+static int get_addrselectpolicy(struct policyhead *);
+static void free_addrselectpolicy(struct policyhead *);
+static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
+ struct policyhead *);
+static int matchlen(struct sockaddr *, struct sockaddr *);
+
+static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
+ const struct addrinfo *, res_state);
+#if defined(RESOLVSORT)
+static int addr4sort(struct addrinfo *, res_state);
+#endif
+static int _dns_getaddrinfo(void *, void *, va_list);
+static void _sethtent(FILE **);
+static void _endhtent(FILE **);
+static struct addrinfo *_gethtent(FILE **, const char *,
+ const struct addrinfo *);
+static int _files_getaddrinfo(void *, void *, va_list);
+#ifdef YP
+static struct addrinfo *_yphostent(char *, const struct addrinfo *);
+static int _yp_getaddrinfo(void *, void *, va_list);
+#endif
+#ifdef NS_CACHING
+static int addrinfo_id_func(char *, size_t *, va_list, void *);
+static int addrinfo_marshal_func(char *, size_t *, void *, va_list, void *);
+static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int res_queryN(const char *, struct res_target *, res_state);
+static int res_searchN(const char *, struct res_target *, res_state);
+static int res_querydomainN(const char *, const char *,
+ struct res_target *, res_state);
+
+/* XXX macros that make external reference is BAD. */
+
+#define GET_AI(ai, afd, addr) \
+do { \
+ /* external reference: pai, error, and label free */ \
+ (ai) = get_ai(pai, (afd), (addr)); \
+ if ((ai) == NULL) { \
+ error = EAI_MEMORY; \
+ goto free; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define GET_PORT(ai, serv) \
+do { \
+ /* external reference: error and label free */ \
+ error = get_port((ai), (serv), 0); \
+ if (error != 0) \
+ goto free; \
+} while (/*CONSTCOND*/0)
+
+#define GET_CANONNAME(ai, str) \
+do { \
+ /* external reference: pai, error and label free */ \
+ error = get_canonname(pai, (ai), (str)); \
+ if (error != 0) \
+ goto free; \
+} while (/*CONSTCOND*/0)
+
+#define ERR(err) \
+do { \
+ /* external reference: error, and label bad */ \
+ error = (err); \
+ goto bad; \
+ /*NOTREACHED*/ \
+} while (/*CONSTCOND*/0)
+
+#define MATCH_FAMILY(x, y, w) \
+ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
+#define MATCH(x, y, w) \
+ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
+
+void
+freeaddrinfo(struct addrinfo *ai)
+{
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ ai = next;
+ } while (ai);
+}
+
+static int
+str2number(const char *p, int *portp)
+{
+ char *ep;
+ unsigned long v;
+
+ if (*p == '\0')
+ return -1;
+ ep = NULL;
+ errno = 0;
+ v = strtoul(p, &ep, 10);
+ if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) {
+ *portp = v;
+ return 0;
+ } else
+ return -1;
+}
+
+int
+getaddrinfo(const char *hostname, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo sentinel;
+ struct addrinfo *cur;
+ int error = 0;
+ 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;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
+#ifdef INET6
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+
+ /*
+ * if both socktype/protocol are specified, check if they
+ * are meaningful combination.
+ */
+ if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ 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)))
+ continue;
+
+ /* matched */
+ break;
+ }
+
+ if (ex->e_af < 0)
+ ERR(EAI_BADHINTS);
+ }
+ }
+
+ /*
+ * check for special cases. (1) numeric servname is disallowed if
+ * socktype/protocol are left unspecified. (2) servname is disallowed
+ * for raw and other inet{,6} sockets.
+ */
+ if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
+#ifdef PF_INET6
+ || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+#endif
+ ) {
+ ai0 = *pai; /* backup *pai */
+
+ if (pai->ai_family == PF_UNSPEC) {
+#ifdef PF_INET6
+ pai->ai_family = PF_INET6;
+#else
+ pai->ai_family = PF_INET;
+#endif
+ }
+ error = get_portmatch(pai, servname);
+ if (error)
+ ERR(error);
+
+ *pai = ai0;
+ }
+
+ ai0 = *pai;
+
+ /*
+ * 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;
+
+ if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
+ continue;
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = afd->a_af;
+
+ 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,
+ &afailist[afd - afdl]);
+
+ /*
+ * 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.
+ */
+ }
+
+ if (!error && afailist[afd - afdl])
+ found++;
+ }
+ if (found) {
+ numeric = 1;
+ goto globcopy;
+ }
+
+ if (hostname == NULL)
+ ERR(EAI_NONAME); /* used to be EAI_NODATA */
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+
+ if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))
+ ERR(EAI_FAIL);
+
+ /*
+ * hostname as alphabetical name.
+ */
+ *pai = ai0;
+ error = explore_fqdn(pai, hostname, servname, &afai_unspec);
+
+globcopy:
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ *pai = ai0;
+
+ 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)))
+ 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;
+
+ /*
+ * 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;
+ }
+
+ /*
+ * ensure we return either:
+ * - error == 0, non-NULL *res
+ * - error != 0, NULL *res
+ */
+ if (error == 0) {
+ if (sentinel.ai_next) {
+ /*
+ * If the returned entry is for an active connection,
+ * and the given name is not numeric, reorder the
+ * list, so that the application would try the list
+ * in the most efficient order. Since the head entry
+ * of the original list may contain ai_canonname and
+ * that entry may be moved elsewhere in the new list,
+ * we keep the pointer and will restore it in the new
+ * head entry. (Note that RFC3493 requires the head
+ * entry store it when requested by the caller).
+ */
+ if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) {
+ if (!numeric) {
+ char *canonname;
+
+ canonname =
+ sentinel.ai_next->ai_canonname;
+ sentinel.ai_next->ai_canonname = NULL;
+ (void)reorder(&sentinel);
+ if (sentinel.ai_next->ai_canonname ==
+ NULL) {
+ sentinel.ai_next->ai_canonname
+ = canonname;
+ } else if (canonname != NULL)
+ free(canonname);
+ }
+ }
+ *res = sentinel.ai_next;
+ } else
+ error = EAI_FAIL;
+ }
+
+bad:
+ 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
+reorder(struct addrinfo *sentinel)
+{
+ struct addrinfo *ai, **aip;
+ struct ai_order *aio;
+ int i, n;
+ struct policyhead policyhead;
+
+ /* count the number of addrinfo elements for sorting. */
+ for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++)
+ ;
+
+ /*
+ * If the number is small enough, we can skip the reordering process.
+ */
+ if (n <= 1)
+ return(n);
+
+ /* allocate a temporary array for sort and initialization of it. */
+ if ((aio = malloc(sizeof(*aio) * n)) == NULL)
+ return(n); /* give up reordering */
+ memset(aio, 0, sizeof(*aio) * n);
+
+ /* retrieve address selection policy from the kernel */
+ TAILQ_INIT(&policyhead);
+ if (!get_addrselectpolicy(&policyhead)) {
+ /* no policy is installed into kernel, we don't sort. */
+ free(aio);
+ return (n);
+ }
+
+ for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) {
+ aio[i].aio_ai = ai;
+ aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr);
+ aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr,
+ &policyhead);
+ set_source(&aio[i], &policyhead);
+ }
+
+ /* perform sorting. */
+ qsort(aio, n, sizeof(*aio), comp_dst);
+
+ /* reorder the addrinfo chain. */
+ for (i = 0, aip = &sentinel->ai_next; i < n; i++) {
+ *aip = aio[i].aio_ai;
+ aip = &aio[i].aio_ai->ai_next;
+ }
+ *aip = NULL;
+
+ /* cleanup and return */
+ free(aio);
+ free_addrselectpolicy(&policyhead);
+ return(n);
+}
+
+static int
+get_addrselectpolicy(struct policyhead *head)
+{
+#ifdef INET6
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
+ size_t l;
+ char *buf;
+ struct in6_addrpolicy *pol, *ep;
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
+ return (0);
+ if ((buf = malloc(l)) == NULL)
+ return (0);
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ free(buf);
+ return (0);
+ }
+
+ ep = (struct in6_addrpolicy *)(buf + l);
+ for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
+ struct policyqueue *new;
+
+ if ((new = malloc(sizeof(*new))) == NULL) {
+ free_addrselectpolicy(head); /* make the list empty */
+ break;
+ }
+ new->pc_policy = *pol;
+ TAILQ_INSERT_TAIL(head, new, pc_entry);
+ }
+
+ free(buf);
+ return (1);
+#else
+ return (0);
+#endif
+}
+
+static void
+free_addrselectpolicy(struct policyhead *head)
+{
+ struct policyqueue *ent, *nent;
+
+ for (ent = TAILQ_FIRST(head); ent; ent = nent) {
+ nent = TAILQ_NEXT(ent, pc_entry);
+ TAILQ_REMOVE(head, ent, pc_entry);
+ free(ent);
+ }
+}
+
+static struct policyqueue *
+match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
+{
+#ifdef INET6
+ struct policyqueue *ent, *bestent = NULL;
+ struct in6_addrpolicy *pol;
+ int matchlen, bestmatchlen = -1;
+ u_char *mp, *ep, *k, *p, m;
+ struct sockaddr_in6 key;
+
+ switch(addr->sa_family) {
+ case AF_INET6:
+ key = *(struct sockaddr_in6 *)addr;
+ break;
+ case AF_INET:
+ /* convert the address into IPv4-mapped IPv6 address. */
+ memset(&key, 0, sizeof(key));
+ key.sin6_family = AF_INET6;
+ key.sin6_len = sizeof(key);
+ key.sin6_addr.s6_addr[10] = 0xff;
+ key.sin6_addr.s6_addr[11] = 0xff;
+ memcpy(&key.sin6_addr.s6_addr[12],
+ &((struct sockaddr_in *)addr)->sin_addr, 4);
+ break;
+ default:
+ return(NULL);
+ }
+
+ for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
+ pol = &ent->pc_policy;
+ matchlen = 0;
+
+ mp = (u_char *)&pol->addrmask.sin6_addr;
+ ep = mp + 16; /* XXX: scope field? */
+ k = (u_char *)&key.sin6_addr;
+ p = (u_char *)&pol->addr.sin6_addr;
+ for (; mp < ep && *mp; mp++, k++, p++) {
+ m = *mp;
+ if ((*k & m) != *p)
+ goto next; /* not match */
+ if (m == 0xff) /* short cut for a typical case */
+ matchlen += 8;
+ else {
+ while (m >= 0x80) {
+ matchlen++;
+ m <<= 1;
+ }
+ }
+ }
+
+ /* matched. check if this is better than the current best. */
+ if (matchlen > bestmatchlen) {
+ bestent = ent;
+ bestmatchlen = matchlen;
+ }
+
+ next:
+ continue;
+ }
+
+ return(bestent);
+#else
+ return(NULL);
+#endif
+
+}
+
+static void
+set_source(struct ai_order *aio, struct policyhead *ph)
+{
+ struct addrinfo ai = *aio->aio_ai;
+ struct sockaddr_storage ss;
+ socklen_t srclen;
+ int s;
+
+ /* set unspec ("no source is available"), just in case */
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ aio->aio_srcscope = -1;
+
+ switch(ai.ai_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default: /* ignore unsupported AFs explicitly */
+ return;
+ }
+
+ /* XXX: make a dummy addrinfo to call connect() */
+ ai.ai_socktype = SOCK_DGRAM;
+ ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */
+ ai.ai_next = NULL;
+ memset(&ss, 0, sizeof(ss));
+ memcpy(&ss, ai.ai_addr, ai.ai_addrlen);
+ ai.ai_addr = (struct sockaddr *)&ss;
+ get_port(&ai, "1", 0);
+
+ /* open a socket to get the source address for the given dst */
+ if ((s = _socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol)) < 0)
+ return; /* give up */
+ if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0)
+ goto cleanup;
+ srclen = ai.ai_addrlen;
+ if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ goto cleanup;
+ }
+ aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
+ aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
+ aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr);
+#ifdef INET6
+ if (ai.ai_family == AF_INET6) {
+ struct in6_ifreq ifr6;
+ u_int32_t flags6;
+
+ /* XXX: interface name should not be hardcoded */
+ strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
+ memset(&ifr6, 0, sizeof(ifr6));
+ memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen);
+ if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
+ flags6 = ifr6.ifr_ifru.ifru_flags6;
+ if ((flags6 & IN6_IFF_DEPRECATED))
+ aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
+ }
+ }
+#endif
+
+ cleanup:
+ _close(s);
+ return;
+}
+
+static int
+matchlen(struct sockaddr *src, struct sockaddr *dst)
+{
+ int match = 0;
+ u_char *s, *d;
+ u_char *lim, r;
+ int addrlen;
+
+ switch (src->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
+ d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
+ addrlen = sizeof(struct in6_addr);
+ lim = s + addrlen;
+ break;
+#endif
+ case AF_INET:
+ s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
+ d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
+ addrlen = sizeof(struct in_addr);
+ lim = s + addrlen;
+ break;
+ default:
+ return(0);
+ }
+
+ while (s < lim)
+ if ((r = (*d++ ^ *s++)) != 0) {
+ while (r < addrlen * 8) {
+ match++;
+ r <<= 1;
+ }
+ break;
+ } else
+ match += 8;
+ return(match);
+}
+
+static int
+comp_dst(const void *arg1, const void *arg2)
+{
+ const struct ai_order *dst1 = arg1, *dst2 = arg2;
+
+ /*
+ * Rule 1: Avoid unusable destinations.
+ * XXX: we currently do not consider if an appropriate route exists.
+ */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family == AF_UNSPEC) {
+ return(-1);
+ }
+ if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ return(1);
+ }
+
+ /* Rule 2: Prefer matching scope. */
+ if (dst1->aio_dstscope == dst1->aio_srcscope &&
+ dst2->aio_dstscope != dst2->aio_srcscope) {
+ return(-1);
+ }
+ if (dst1->aio_dstscope != dst1->aio_srcscope &&
+ dst2->aio_dstscope == dst2->aio_srcscope) {
+ return(1);
+ }
+
+ /* Rule 3: Avoid deprecated addresses. */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(-1);
+ }
+ if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(1);
+ }
+ }
+
+ /* Rule 4: Prefer home addresses. */
+ /* XXX: not implemented yet */
+
+ /* Rule 5: Prefer matching label. */
+#ifdef INET6
+ if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
+ dst1->aio_srcpolicy->pc_policy.label ==
+ dst1->aio_dstpolicy->pc_policy.label &&
+ (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
+ dst2->aio_srcpolicy->pc_policy.label !=
+ dst2->aio_dstpolicy->pc_policy.label)) {
+ return(-1);
+ }
+ if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
+ dst2->aio_srcpolicy->pc_policy.label ==
+ dst2->aio_dstpolicy->pc_policy.label &&
+ (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
+ dst1->aio_srcpolicy->pc_policy.label !=
+ dst1->aio_dstpolicy->pc_policy.label)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 6: Prefer higher precedence. */
+#ifdef INET6
+ if (dst1->aio_dstpolicy &&
+ (dst2->aio_dstpolicy == NULL ||
+ dst1->aio_dstpolicy->pc_policy.preced >
+ dst2->aio_dstpolicy->pc_policy.preced)) {
+ return(-1);
+ }
+ if (dst2->aio_dstpolicy &&
+ (dst1->aio_dstpolicy == NULL ||
+ dst2->aio_dstpolicy->pc_policy.preced >
+ dst1->aio_dstpolicy->pc_policy.preced)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 7: Prefer native transport. */
+ /* XXX: not implemented yet */
+
+ /* Rule 8: Prefer smaller scope. */
+ if (dst1->aio_dstscope >= 0 &&
+ dst1->aio_dstscope < dst2->aio_dstscope) {
+ return(-1);
+ }
+ if (dst2->aio_dstscope >= 0 &&
+ dst2->aio_dstscope < dst1->aio_dstscope) {
+ return(1);
+ }
+
+ /*
+ * Rule 9: Use longest matching prefix.
+ * We compare the match length in a same AF only.
+ */
+ if (dst1->aio_ai->ai_addr->sa_family ==
+ dst2->aio_ai->ai_addr->sa_family) {
+ if (dst1->aio_matchlen > dst2->aio_matchlen) {
+ return(-1);
+ }
+ if (dst1->aio_matchlen < dst2->aio_matchlen) {
+ return(1);
+ }
+ }
+
+ /* Rule 10: Otherwise, leave the order unchanged. */
+ return(-1);
+}
+
+/*
+ * Copy from scope.c.
+ * XXX: we should standardize the functions and link them as standard
+ * library.
+ */
+static int
+gai_addr2scopetype(struct sockaddr *sa)
+{
+#ifdef INET6
+ struct sockaddr_in6 *sa6;
+#endif
+ struct sockaddr_in *sa4;
+
+ switch(sa->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
+ /* just use the scope field of the multicast address */
+ return(sa6->sin6_addr.s6_addr[2] & 0x0f);
+ }
+ /*
+ * Unicast addresses: map scope type to corresponding scope
+ * value defined for multcast addresses.
+ * XXX: hardcoded scope type values are bad...
+ */
+ if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
+ return(1); /* node local scope */
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
+ return(2); /* link-local scope */
+ if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
+ return(5); /* site-local scope */
+ return(14); /* global scope */
+ break;
+#endif
+ case AF_INET:
+ /*
+ * IPv4 pseudo scoping according to RFC 3484.
+ */
+ sa4 = (struct sockaddr_in *)sa;
+ /* IPv4 autoconfiguration addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 169 &&
+ ((u_char *)&sa4->sin_addr)[1] == 254)
+ return(2);
+ /* Private addresses have site-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 10 ||
+ (((u_char *)&sa4->sin_addr)[0] == 172 &&
+ (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
+ (((u_char *)&sa4->sin_addr)[0] == 192 &&
+ ((u_char *)&sa4->sin_addr)[1] == 168))
+ return(14); /* XXX: It should be 5 unless NAT */
+ /* Loopback addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 127)
+ return(2);
+ return(14);
+ break;
+ default:
+ errno = EAFNOSUPPORT; /* is this a good error? */
+ return(-1);
+ }
+}
+
+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 ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(const struct addrinfo *pai, const char *servname,
+ struct addrinfo **res)
+{
+ int s;
+ const struct afd *afd;
+ struct addrinfo *ai;
+ int error;
+
+ *res = NULL;
+ ai = NULL;
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = _socket(pai->ai_family, SOCK_DGRAM, 0);
+ if (s < 0) {
+ if (errno != EMFILE)
+ return 0;
+ } else
+ _close(s);
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(ai, afd, afd->a_addrany);
+ GET_PORT(ai, servname);
+ } else {
+ GET_AI(ai, afd, afd->a_loopback);
+ GET_PORT(ai, servname);
+ }
+
+ *res = ai;
+ return 0;
+
+free:
+ if (ai != NULL)
+ freeaddrinfo(ai);
+ return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(const struct addrinfo *pai, const char *hostname,
+ const char *servname, struct addrinfo **res, const char *canonname)
+{
+ const struct afd *afd;
+ struct addrinfo *ai;
+ int error;
+ char pton[PTON_MAX];
+
+ *res = NULL;
+ ai = NULL;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ switch (afd->a_af) {
+ case AF_INET:
+ /*
+ * RFC3493 requires getaddrinfo() to accept AF_INET formats
+ * that are accepted by inet_addr() and its family. The
+ * accepted forms includes the "classful" one, which inet_pton
+ * does not accept. So we need to separate the case for
+ * AF_INET.
+ */
+ if (inet_aton(hostname, (struct in_addr *)pton) != 1)
+ return 0;
+ break;
+ default:
+ if (inet_pton(afd->a_af, hostname, pton) != 1)
+ return 0;
+ break;
+ }
+
+ if (pai->ai_family == afd->a_af) {
+ GET_AI(ai, afd, pton);
+ GET_PORT(ai, servname);
+ if ((pai->ai_flags & AI_CANONNAME)) {
+ /*
+ * Set the numeric address itself as the canonical
+ * name, based on a clarification in RFC3493.
+ */
+ GET_CANONNAME(ai, canonname);
+ }
+ } else {
+ /*
+ * XXX: This should not happen since we already matched the AF
+ * by find_afd.
+ */
+ ERR(EAI_FAMILY);
+ }
+
+ *res = ai;
+ return 0;
+
+free:
+bad:
+ if (ai != NULL)
+ freeaddrinfo(ai);
+ return error;
+}
+
+/*
+ * numeric hostname with scope
+ */
+static int
+explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
+ const char *servname, struct addrinfo **res)
+{
+#if !defined(SCOPE_DELIMITER) || !defined(INET6)
+ return explore_numeric(pai, hostname, servname, res, hostname);
+#else
+ const struct afd *afd;
+ struct addrinfo *cur;
+ int error;
+ char *cp, *hostname2 = NULL, *scope, *addr;
+ struct sockaddr_in6 *sin6;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ if (!afd->a_scoped)
+ return explore_numeric(pai, hostname, servname, res, hostname);
+
+ cp = strchr(hostname, SCOPE_DELIMITER);
+ if (cp == NULL)
+ return explore_numeric(pai, hostname, servname, res, hostname);
+
+ /*
+ * Handle special case of <scoped_address><delimiter><scope id>
+ */
+ hostname2 = strdup(hostname);
+ if (hostname2 == NULL)
+ return EAI_MEMORY;
+ /* terminate at the delimiter */
+ hostname2[cp - hostname] = '\0';
+ addr = hostname2;
+ scope = cp + 1;
+
+ error = explore_numeric(pai, addr, servname, res, hostname);
+ if (error == 0) {
+ u_int32_t scopeid;
+
+ for (cur = *res; cur; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET6)
+ continue;
+ 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;
+ }
+ }
+
+ free(hostname2);
+
+ if (error && *res) {
+ freeaddrinfo(*res);
+ *res = NULL;
+ }
+ return error;
+#endif
+}
+
+static int
+get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
+{
+ if ((pai->ai_flags & AI_CANONNAME) != 0) {
+ ai->ai_canonname = strdup(str);
+ if (ai->ai_canonname == NULL)
+ return EAI_MEMORY;
+ }
+ return 0;
+}
+
+static struct addrinfo *
+get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
+{
+ char *p;
+ struct addrinfo *ai;
+#ifdef FAITH
+ struct in6_addr faith_prefix;
+ char *fp_str;
+ int translate = 0;
+#endif
+
+#ifdef FAITH
+ /*
+ * Transfrom an IPv4 addr into a special IPv6 addr format for
+ * IPv6->IPv4 translation gateway. (only TCP is supported now)
+ *
+ * +-----------------------------------+------------+
+ * | faith prefix part (12 bytes) | embedded |
+ * | | IPv4 addr part (4 bytes)
+ * +-----------------------------------+------------+
+ *
+ * faith prefix part is specified as ascii IPv6 addr format
+ * in environmental variable GAI.
+ * For FAITH to work correctly, routing to faith prefix must be
+ * setup toward a machine where a FAITH daemon operates.
+ * Also, the machine must enable some mechanizm
+ * (e.g. faith interface hack) to divert those packet with
+ * faith prefixed destination addr to user-land FAITH daemon.
+ */
+ fp_str = getenv("GAI");
+ if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
+ afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
+ u_int32_t v4a;
+ u_int8_t v4a_top;
+
+ memcpy(&v4a, addr, sizeof v4a);
+ v4a_top = v4a >> IN_CLASSA_NSHIFT;
+ if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
+ v4a_top != 0 && v4a != IN_LOOPBACKNET) {
+ afd = &afdl[N_INET6];
+ memcpy(&faith_prefix.s6_addr[12], addr,
+ sizeof(struct in_addr));
+ translate = 1;
+ }
+ }
+#endif
+
+ ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+ + (afd->a_socklen));
+ if (ai == NULL)
+ return NULL;
+
+ memcpy(ai, pai, sizeof(struct addrinfo));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
+ ai->ai_addr->sa_len = afd->a_socklen;
+ ai->ai_addrlen = afd->a_socklen;
+ ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+ p = (char *)(void *)(ai->ai_addr);
+#ifdef FAITH
+ if (translate == 1)
+ memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen);
+ else
+#endif
+ memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
+ 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)
+{
+
+ /* get_port does not touch first argument when matchonly == 1. */
+ /* LINTED const cast */
+ return get_port((struct addrinfo *)ai, servname, 1);
+}
+
+static int
+get_port(struct addrinfo *ai, const char *servname, int matchonly)
+{
+ const char *proto;
+ struct servent *sp;
+ int port, error;
+ int allownumeric;
+
+ if (servname == NULL)
+ return 0;
+ switch (ai->ai_family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ return 0;
+ }
+
+ switch (ai->ai_socktype) {
+ case SOCK_RAW:
+ return EAI_SERVICE;
+ case SOCK_DGRAM:
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ allownumeric = 1;
+ break;
+ case ANY:
+ 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;
+ }
+
+ error = str2number(servname, &port);
+ if (error == 0) {
+ if (!allownumeric)
+ return EAI_SERVICE;
+ if (port < 0 || port > 65535)
+ return EAI_SERVICE;
+ port = htons(port);
+ } else {
+ if (ai->ai_flags & AI_NUMERICSERV)
+ return EAI_NONAME;
+
+ switch (ai->ai_protocol) {
+ case IPPROTO_UDP:
+ proto = "udp";
+ break;
+ case IPPROTO_TCP:
+ proto = "tcp";
+ break;
+ case IPPROTO_SCTP:
+ proto = "sctp";
+ break;
+ default:
+ proto = NULL;
+ break;
+ }
+
+ if ((sp = getservbyname(servname, proto)) == NULL)
+ return EAI_SERVICE;
+ port = sp->s_port;
+ }
+
+ if (!matchonly) {
+ switch (ai->ai_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)(void *)
+ ai->ai_addr)->sin_port = port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)(void *)
+ ai->ai_addr)->sin6_port = port;
+ break;
+#endif
+ }
+ }
+
+ return 0;
+}
+
+static const struct afd *
+find_afd(int af)
+{
+ const struct afd *afd;
+
+ if (af == PF_UNSPEC)
+ return NULL;
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afd->a_af == af)
+ return afd;
+ }
+ return NULL;
+}
+
+/*
+ * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
+ * will take care of it.
+ * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
+ * if the code is right or not.
+ *
+ * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
+ * _dns_getaddrinfo.
+ */
+static int
+addrconfig(struct addrinfo *pai)
+{
+ int s, af;
+
+ /*
+ * TODO:
+ * Note that implementation dependent test for address
+ * configuration should be done everytime called
+ * (or apropriate interval),
+ * because addresses will be dynamically assigned or deleted.
+ */
+ af = pai->ai_family;
+ if (af == AF_UNSPEC) {
+ if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ af = AF_INET;
+ else {
+ _close(s);
+ if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ af = AF_INET6;
+ else
+ _close(s);
+ }
+ }
+ if (af != AF_UNSPEC) {
+ if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
+ return 0;
+ _close(s);
+ }
+ pai->ai_family = af;
+ return 1;
+}
+
+#ifdef INET6
+/* convert a string to a scope identifier. XXX: IPv6 specific */
+static int
+ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
+{
+ u_long lscopeid;
+ struct in6_addr *a6;
+ char *ep;
+
+ a6 = &sin6->sin6_addr;
+
+ /* empty scopeid portion is invalid */
+ if (*scope == '\0')
+ return -1;
+
+ if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) {
+ /*
+ * We currently assume a one-to-one mapping between links
+ * and interfaces, so we simply use interface indices for
+ * like-local scopes.
+ */
+ *scopeid = if_nametoindex(scope);
+ if (*scopeid == 0)
+ goto trynumeric;
+ return 0;
+ }
+
+ /* still unclear about literal, allow numeric only - placeholder */
+ if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
+ goto trynumeric;
+ if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
+ goto trynumeric;
+ else
+ goto trynumeric; /* global */
+
+ /* try to convert to a numeric id as a last resort */
+ trynumeric:
+ errno = 0;
+ lscopeid = strtoul(scope, &ep, 10);
+ *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
+ if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
+ return 0;
+ else
+ return -1;
+}
+#endif
+
+
+#ifdef NS_CACHING
+static int
+addrinfo_id_func(char *buffer, size_t *buffer_size, va_list ap,
+ void *cache_mdata)
+{
+ res_state statp;
+ u_long res_options;
+
+ const int op_id = 0; /* identifies the getaddrinfo for the cache */
+ char *hostname;
+ struct addrinfo *hints;
+
+ char *p;
+ int ai_flags, ai_family, ai_socktype, ai_protocol;
+ size_t desired_size, size;
+
+ statp = __res_state();
+ res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
+ RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
+
+ hostname = va_arg(ap, char *);
+ hints = va_arg(ap, struct addrinfo *);
+
+ desired_size = sizeof(res_options) + sizeof(int) + sizeof(int) * 4;
+ if (hostname != NULL) {
+ size = strlen(hostname);
+ desired_size += size + 1;
+ } else
+ size = 0;
+
+ if (desired_size > *buffer_size) {
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ if (hints == NULL)
+ ai_flags = ai_family = ai_socktype = ai_protocol = 0;
+ else {
+ ai_flags = hints->ai_flags;
+ ai_family = hints->ai_family;
+ ai_socktype = hints->ai_socktype;
+ ai_protocol = hints->ai_protocol;
+ }
+
+ p = buffer;
+ memcpy(p, &res_options, sizeof(res_options));
+ p += sizeof(res_options);
+
+ memcpy(p, &op_id, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_flags, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_family, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_socktype, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_protocol, sizeof(int));
+ p += sizeof(int);
+
+ if (hostname != NULL)
+ memcpy(p, hostname, size);
+
+ *buffer_size = desired_size;
+ return (NS_SUCCESS);
+}
+
+static int
+addrinfo_marshal_func(char *buffer, size_t *buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ struct addrinfo *ai, *cai;
+ char *p;
+ size_t desired_size, size, ai_size;
+
+ ai = *((struct addrinfo **)retval);
+
+ desired_size = sizeof(size_t);
+ ai_size = 0;
+ for (cai = ai; cai != NULL; cai = cai->ai_next) {
+ desired_size += sizeof(struct addrinfo) + cai->ai_addrlen;
+ if (cai->ai_canonname != NULL)
+ desired_size += sizeof(size_t) +
+ strlen(cai->ai_canonname);
+ ++ai_size;
+ }
+
+ if (desired_size > *buffer_size) {
+ /* this assignment is here for future use */
+ errno = ERANGE;
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memset(buffer, 0, desired_size);
+ p = buffer;
+
+ memcpy(p, &ai_size, sizeof(size_t));
+ p += sizeof(size_t);
+ for (cai = ai; cai != NULL; cai = cai->ai_next) {
+ memcpy(p, cai, sizeof(struct addrinfo));
+ p += sizeof(struct addrinfo);
+
+ memcpy(p, cai->ai_addr, cai->ai_addrlen);
+ p += cai->ai_addrlen;
+
+ if (cai->ai_canonname != NULL) {
+ size = strlen(cai->ai_canonname);
+ memcpy(p, &size, sizeof(size_t));
+ p += sizeof(size_t);
+
+ memcpy(p, cai->ai_canonname, size);
+ p += size;
+ }
+ }
+
+ return (NS_SUCCESS);
+}
+
+static int
+addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ struct addrinfo new_ai, *result, *sentinel, *lasts;
+
+ char *p;
+ size_t ai_size, ai_i, size;
+
+ p = buffer;
+ memcpy(&ai_size, p, sizeof(size_t));
+ p += sizeof(size_t);
+
+ result = NULL;
+ lasts = NULL;
+ for (ai_i = 0; ai_i < ai_size; ++ai_i) {
+ memcpy(&new_ai, p, sizeof(struct addrinfo));
+ p += sizeof(struct addrinfo);
+ size = new_ai.ai_addrlen + sizeof(struct addrinfo) +
+ _ALIGNBYTES;
+
+ sentinel = (struct addrinfo *)malloc(size);
+ memset(sentinel, 0, size);
+
+ memcpy(sentinel, &new_ai, sizeof(struct addrinfo));
+ sentinel->ai_addr = (struct sockaddr *)_ALIGN((char *)sentinel +
+ sizeof(struct addrinfo));
+
+ memcpy(sentinel->ai_addr, p, new_ai.ai_addrlen);
+ p += new_ai.ai_addrlen;
+
+ if (new_ai.ai_canonname != NULL) {
+ memcpy(&size, p, sizeof(size_t));
+ p += sizeof(size_t);
+
+ sentinel->ai_canonname = (char *)malloc(size + 1);
+ memset(sentinel->ai_canonname, 0, size + 1);
+
+ memcpy(sentinel->ai_canonname, p, size);
+ p += size;
+ }
+
+ if (result == NULL) {
+ result = sentinel;
+ lasts = sentinel;
+ } else {
+ lasts->ai_next = sentinel;
+ lasts = sentinel;
+ }
+ }
+
+ *((struct addrinfo **)retval) = result;
+ return (NS_SUCCESS);
+}
+#endif /* NS_CACHING */
+
+/*
+ * FQDN hostname, DNS lookup
+ */
+static int
+explore_fqdn(const struct addrinfo *pai, const char *hostname,
+ const char *servname, struct addrinfo **res)
+{
+ struct addrinfo *result;
+ struct addrinfo *cur;
+ int error = 0;
+
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ hosts, NULL, addrinfo_id_func, addrinfo_marshal_func,
+ addrinfo_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_files_getaddrinfo, NULL)
+ { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
+ NS_NIS_CB(_yp_getaddrinfo, NULL)
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+
+ result = NULL;
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ return 0;
+
+ switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
+ default_dns_files, hostname, pai)) {
+ case NS_TRYAGAIN:
+ error = EAI_AGAIN;
+ goto free;
+ case NS_UNAVAIL:
+ error = EAI_FAIL;
+ goto free;
+ case NS_NOTFOUND:
+ error = EAI_NONAME;
+ goto free;
+ case NS_SUCCESS:
+ error = 0;
+ for (cur = result; cur; cur = cur->ai_next) {
+ GET_PORT(cur, servname);
+ /* canonname should be filled already */
+ }
+ break;
+ }
+
+ *res = result;
+
+ return 0;
+
+free:
+ if (result)
+ freeaddrinfo(result);
+ return error;
+}
+
+#ifdef DEBUG
+static const char AskedForGot[] =
+ "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+#endif
+
+static struct addrinfo *
+getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
+ const struct addrinfo *pai, res_state res)
+{
+ struct addrinfo sentinel, *cur;
+ struct addrinfo ai;
+ const struct afd *afd;
+ char *canonname;
+ const HEADER *hp;
+ const u_char *cp;
+ int n;
+ const u_char *eom;
+ char *bp, *ep;
+ int type, class, ancount, qdcount;
+ int haveanswer, had_error;
+ char tbuf[MAXDNAME];
+ int (*name_ok)(const char *);
+ char hostbuf[8*1024];
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ canonname = NULL;
+ eom = answer->buf + anslen;
+ switch (qtype) {
+ case T_A:
+ case T_AAAA:
+ case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
+ name_ok = res_hnok;
+ break;
+ default:
+ return (NULL); /* XXX should be abort(); */
+ }
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ bp = hostbuf;
+ ep = hostbuf + sizeof hostbuf;
+ cp = answer->buf + HFIXEDSZ;
+ if (qdcount != 1) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (NULL);
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (NULL);
+ }
+ cp += n + QFIXEDSZ;
+ if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (NULL);
+ }
+ canonname = bp;
+ bp += n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = canonname;
+ }
+ haveanswer = 0;
+ had_error = 0;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ type = _getshort(cp);
+ cp += INT16SZ; /* type */
+ class = _getshort(cp);
+ cp += INT16SZ + INT32SZ; /* class, TTL */
+ n = _getshort(cp);
+ cp += INT16SZ; /* len */
+ if (class != C_IN) {
+ /* XXX - debug? syslog? */
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
+ type == T_CNAME) {
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if ((n < 0) || !(*name_ok)(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strlcpy(bp, tbuf, ep - bp);
+ canonname = bp;
+ bp += n;
+ continue;
+ }
+ if (qtype == T_ANY) {
+ if (!(type == T_A || type == T_AAAA)) {
+ cp += n;
+ continue;
+ }
+ } else if (type != qtype) {
+#ifdef DEBUG
+ if (type != T_KEY && type != T_SIG &&
+ type != ns_t_dname)
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+#endif
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ switch (type) {
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(canonname, bp) != 0) {
+#ifdef DEBUG
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, canonname, bp);
+#endif
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (type == T_A && n != INADDRSZ) {
+ cp += n;
+ continue;
+ }
+ if (type == T_AAAA && n != IN6ADDRSZ) {
+ cp += n;
+ continue;
+ }
+#ifdef FILTER_V4MAPPED
+ if (type == T_AAAA) {
+ struct in6_addr in6;
+ memcpy(&in6, cp, sizeof(in6));
+ if (IN6_IS_ADDR_V4MAPPED(&in6)) {
+ cp += n;
+ continue;
+ }
+ }
+#endif
+ if (!haveanswer) {
+ int nn;
+
+ canonname = bp;
+ nn = strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ }
+
+ /* don't overwrite pai */
+ ai = *pai;
+ ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
+ afd = find_afd(ai.ai_family);
+ if (afd == NULL) {
+ cp += n;
+ continue;
+ }
+ cur->ai_next = get_ai(&ai, afd, (const char *)cp);
+ if (cur->ai_next == NULL)
+ had_error++;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ cp += n;
+ break;
+ default:
+ abort();
+ }
+ if (!had_error)
+ haveanswer++;
+ }
+ if (haveanswer) {
+#if defined(RESOLVSORT)
+ /*
+ * We support only IPv4 address for backward
+ * compatibility against gethostbyname(3).
+ */
+ if (res->nsort && qtype == T_A) {
+ if (addr4sort(&sentinel, res) < 0) {
+ freeaddrinfo(sentinel.ai_next);
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return NULL;
+ }
+ }
+#endif /*RESOLVSORT*/
+ if (!canonname)
+ (void)get_canonname(pai, sentinel.ai_next, qname);
+ else
+ (void)get_canonname(pai, sentinel.ai_next, canonname);
+ RES_SET_H_ERRNO(res, NETDB_SUCCESS);
+ return sentinel.ai_next;
+ }
+
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return NULL;
+}
+
+#ifdef RESOLVSORT
+struct addr_ptr {
+ struct addrinfo *ai;
+ int aval;
+};
+
+static int
+addr4sort(struct addrinfo *sentinel, res_state res)
+{
+ struct addrinfo *ai;
+ struct addr_ptr *addrs, addr;
+ struct sockaddr_in *sin;
+ int naddrs, i, j;
+ int needsort = 0;
+
+ if (!sentinel)
+ return -1;
+ naddrs = 0;
+ for (ai = sentinel->ai_next; ai; ai = ai->ai_next)
+ naddrs++;
+ if (naddrs < 2)
+ return 0; /* We don't need sorting. */
+ if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL)
+ return -1;
+ i = 0;
+ for (ai = sentinel->ai_next; ai; ai = ai->ai_next) {
+ sin = (struct sockaddr_in *)ai->ai_addr;
+ for (j = 0; (unsigned)j < res->nsort; j++) {
+ if (res->sort_list[j].addr.s_addr ==
+ (sin->sin_addr.s_addr & res->sort_list[j].mask))
+ break;
+ }
+ addrs[i].ai = ai;
+ addrs[i].aval = j;
+ if (needsort == 0 && i > 0 && j < addrs[i - 1].aval)
+ needsort = i;
+ i++;
+ }
+ if (!needsort) {
+ free(addrs);
+ return 0;
+ }
+
+ while (needsort < naddrs) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (addrs[j].aval > addrs[j+1].aval) {
+ addr = addrs[j];
+ addrs[j] = addrs[j + 1];
+ addrs[j + 1] = addr;
+ } else
+ break;
+ }
+ needsort++;
+ }
+
+ ai = sentinel;
+ for (i = 0; i < naddrs; ++i) {
+ ai->ai_next = addrs[i].ai;
+ ai = ai->ai_next;
+ }
+ ai->ai_next = NULL;
+ free(addrs);
+ return 0;
+}
+#endif /*RESOLVSORT*/
+
+/*ARGSUSED*/
+static int
+_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
+{
+ struct addrinfo *ai;
+ querybuf *buf, *buf2;
+ const char *hostname;
+ const struct addrinfo *pai;
+ struct addrinfo sentinel, *cur;
+ struct res_target q, q2;
+ res_state res;
+
+ hostname = va_arg(ap, char *);
+ pai = va_arg(ap, const struct addrinfo *);
+
+ memset(&q, 0, sizeof(q));
+ memset(&q2, 0, sizeof(q2));
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ buf = malloc(sizeof(*buf));
+ if (!buf) {
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ return NS_NOTFOUND;
+ }
+ buf2 = malloc(sizeof(*buf2));
+ if (!buf2) {
+ free(buf);
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ return NS_NOTFOUND;
+ }
+
+ switch (pai->ai_family) {
+ case AF_UNSPEC:
+ q.name = hostname;
+ q.qclass = C_IN;
+ q.qtype = T_A;
+ q.answer = buf->buf;
+ q.anslen = sizeof(buf->buf);
+ q.next = &q2;
+ q2.name = hostname;
+ q2.qclass = C_IN;
+ q2.qtype = T_AAAA;
+ q2.answer = buf2->buf;
+ q2.anslen = sizeof(buf2->buf);
+ break;
+ case AF_INET:
+ q.name = hostname;
+ q.qclass = C_IN;
+ q.qtype = T_A;
+ q.answer = buf->buf;
+ q.anslen = sizeof(buf->buf);
+ break;
+ case AF_INET6:
+ q.name = hostname;
+ q.qclass = C_IN;
+ q.qtype = T_AAAA;
+ q.answer = buf->buf;
+ q.anslen = sizeof(buf->buf);
+ break;
+ default:
+ free(buf);
+ free(buf2);
+ return NS_UNAVAIL;
+ }
+
+ res = __res_state();
+ if ((res->options & RES_INIT) == 0 && res_ninit(res) == -1) {
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ free(buf);
+ free(buf2);
+ return NS_NOTFOUND;
+ }
+
+ if (res_searchN(hostname, &q, res) < 0) {
+ free(buf);
+ free(buf2);
+ return NS_NOTFOUND;
+ }
+ /* prefer IPv6 */
+ if (q.next) {
+ ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, res);
+ if (ai) {
+ cur->ai_next = ai;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ }
+ ai = getanswer(buf, q.n, q.name, q.qtype, pai, res);
+ if (ai)
+ cur->ai_next = ai;
+ free(buf);
+ free(buf2);
+ if (sentinel.ai_next == NULL)
+ switch (res->res_h_errno) {
+ case HOST_NOT_FOUND:
+ return NS_NOTFOUND;
+ case TRY_AGAIN:
+ return NS_TRYAGAIN;
+ default:
+ return NS_UNAVAIL;
+ }
+ *((struct addrinfo **)rv) = sentinel.ai_next;
+ return NS_SUCCESS;
+}
+
+static void
+_sethtent(FILE **hostf)
+{
+ if (!*hostf)
+ *hostf = fopen(_PATH_HOSTS, "r");
+ else
+ rewind(*hostf);
+}
+
+static void
+_endhtent(FILE **hostf)
+{
+ if (*hostf) {
+ (void) fclose(*hostf);
+ *hostf = NULL;
+ }
+}
+
+static struct addrinfo *
+_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
+{
+ char *p;
+ char *cp, *tname, *cname;
+ struct addrinfo hints, *res0, *res;
+ int error;
+ const char *addr;
+ char hostbuf[8*1024];
+
+ if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r")))
+ return (NULL);
+again:
+ if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ if (!(cp = strpbrk(p, " \t")))
+ goto again;
+ *cp++ = '\0';
+ addr = p;
+ cname = NULL;
+ /* if this is not something we're looking for, skip it. */
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ tname = cp;
+ if (cname == NULL)
+ cname = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ if (strcasecmp(name, tname) == 0)
+ goto found;
+ }
+ goto again;
+
+found:
+ /* we should not glob socktype/protocol here */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pai->ai_family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = 0;
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(addr, "0", &hints, &res0);
+ if (error)
+ goto again;
+#ifdef FILTER_V4MAPPED
+ /* XXX should check all items in the chain */
+ if (res0->ai_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {
+ freeaddrinfo(res0);
+ goto again;
+ }
+#endif
+ for (res = res0; res; res = res->ai_next) {
+ /* cover it up */
+ res->ai_flags = pai->ai_flags;
+ res->ai_socktype = pai->ai_socktype;
+ res->ai_protocol = pai->ai_protocol;
+
+ if (pai->ai_flags & AI_CANONNAME) {
+ if (get_canonname(pai, res, cname) != 0) {
+ freeaddrinfo(res0);
+ goto again;
+ }
+ }
+ }
+ return res0;
+}
+
+/*ARGSUSED*/
+static int
+_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
+{
+ const char *name;
+ const struct addrinfo *pai;
+ struct addrinfo sentinel, *cur;
+ struct addrinfo *p;
+ FILE *hostf = NULL;
+
+ name = va_arg(ap, char *);
+ pai = va_arg(ap, struct addrinfo *);
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ _sethtent(&hostf);
+ while ((p = _gethtent(&hostf, name, pai)) != NULL) {
+ cur->ai_next = p;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ _endhtent(&hostf);
+
+ *((struct addrinfo **)rv) = sentinel.ai_next;
+ if (sentinel.ai_next == NULL)
+ return NS_NOTFOUND;
+ return NS_SUCCESS;
+}
+
+#ifdef YP
+/*ARGSUSED*/
+static struct addrinfo *
+_yphostent(char *line, const struct addrinfo *pai)
+{
+ struct addrinfo sentinel, *cur;
+ struct addrinfo hints, *res, *res0;
+ int error;
+ char *p = line;
+ const char *addr, *canonname;
+ char *nextline;
+ char *cp;
+
+ addr = canonname = NULL;
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+nextline:
+ /* terminate line */
+ cp = strchr(p, '\n');
+ if (cp) {
+ *cp++ = '\0';
+ nextline = cp;
+ } else
+ nextline = NULL;
+
+ cp = strpbrk(p, " \t");
+ if (cp == NULL) {
+ if (canonname == NULL)
+ return (NULL);
+ else
+ goto done;
+ }
+ *cp++ = '\0';
+
+ addr = p;
+
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (!canonname)
+ canonname = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ }
+
+ hints = *pai;
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(addr, NULL, &hints, &res0);
+ if (error == 0) {
+ for (res = res0; res; res = res->ai_next) {
+ /* cover it up */
+ res->ai_flags = pai->ai_flags;
+
+ if (pai->ai_flags & AI_CANONNAME)
+ (void)get_canonname(pai, res, canonname);
+ }
+ } else
+ res0 = NULL;
+ if (res0) {
+ cur->ai_next = res0;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+
+ if (nextline) {
+ p = nextline;
+ goto nextline;
+ }
+
+done:
+ return sentinel.ai_next;
+}
+
+/*ARGSUSED*/
+static int
+_yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
+{
+ struct addrinfo sentinel, *cur;
+ struct addrinfo *ai = NULL;
+ char *ypbuf;
+ int ypbuflen, r;
+ const char *name;
+ const struct addrinfo *pai;
+ char *ypdomain;
+
+ if (_yp_check(&ypdomain) == 0)
+ return NS_UNAVAIL;
+
+ name = va_arg(ap, char *);
+ pai = va_arg(ap, const struct addrinfo *);
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ /* hosts.byname is only for IPv4 (Solaris8) */
+ if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
+ r = yp_match(ypdomain, "hosts.byname", name,
+ (int)strlen(name), &ypbuf, &ypbuflen);
+ if (r == 0) {
+ struct addrinfo ai4;
+
+ ai4 = *pai;
+ ai4.ai_family = AF_INET;
+ ai = _yphostent(ypbuf, &ai4);
+ if (ai) {
+ cur->ai_next = ai;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ free(ypbuf);
+ }
+ }
+
+ /* ipnodes.byname can hold both IPv4/v6 */
+ r = yp_match(ypdomain, "ipnodes.byname", name,
+ (int)strlen(name), &ypbuf, &ypbuflen);
+ if (r == 0) {
+ ai = _yphostent(ypbuf, pai);
+ if (ai)
+ cur->ai_next = ai;
+ free(ypbuf);
+ }
+
+ if (sentinel.ai_next == NULL) {
+ RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND);
+ return NS_NOTFOUND;
+ }
+ *((struct addrinfo **)rv) = sentinel.ai_next;
+ return NS_SUCCESS;
+}
+#endif
+
+/* resolver logic */
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in h_errno.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+static int
+res_queryN(const char *name, struct res_target *target, res_state res)
+{
+ u_char *buf;
+ HEADER *hp;
+ int n;
+ u_int oflags;
+ struct res_target *t;
+ int rcode;
+ int ancount;
+
+ rcode = NOERROR;
+ ancount = 0;
+
+ buf = malloc(MAXPACKET);
+ if (!buf) {
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ return -1;
+ }
+
+ for (t = target; t; t = t->next) {
+ int class, type;
+ u_char *answer;
+ int anslen;
+
+ hp = (HEADER *)(void *)t->answer;
+
+ /* make it easier... */
+ class = t->qclass;
+ type = t->qtype;
+ answer = t->answer;
+ anslen = t->anslen;
+
+ oflags = res->_flags;
+
+again:
+ hp->rcode = NOERROR; /* default */
+
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
+ buf, MAXPACKET);
+ if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 &&
+ (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
+ n = res_nopt(res, n, buf, MAXPACKET, anslen);
+ if (n <= 0) {
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ free(buf);
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (n);
+ }
+ n = res_nsend(res, buf, n, answer, anslen);
+ if (n < 0) {
+ /*
+ * if the query choked with EDNS0, retry
+ * without EDNS0
+ */
+ if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC))
+ != 0U &&
+ ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) {
+ res->_flags |= RES_F_EDNS0ERR;
+ if (res->options & RES_DEBUG)
+ printf(";; res_nquery: retry without EDNS0\n");
+ goto again;
+ }
+ rcode = hp->rcode; /* record most recent error */
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ continue;
+ }
+
+ if (n > anslen)
+ hp->rcode = FORMERR; /* XXX not very informative */
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+ rcode = hp->rcode; /* record most recent error */
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; rcode = %u, ancount=%u\n", hp->rcode,
+ ntohs(hp->ancount));
+#endif
+ continue;
+ }
+
+ ancount += ntohs(hp->ancount);
+
+ t->n = n;
+ }
+
+ free(buf);
+
+ if (ancount == 0) {
+ switch (rcode) {
+ case NXDOMAIN:
+ RES_SET_H_ERRNO(res, HOST_NOT_FOUND);
+ break;
+ case SERVFAIL:
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ break;
+ case NOERROR:
+ RES_SET_H_ERRNO(res, NO_DATA);
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ break;
+ }
+ return (-1);
+ }
+ return (ancount);
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected. Error code, if any, is left in h_errno.
+ */
+static int
+res_searchN(const char *name, struct res_target *target, res_state res)
+{
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, root_on_list = 0;
+ int tried_as_is = 0;
+ int searched = 0;
+ char abuf[MAXDNAME];
+
+ errno = 0;
+ RES_SET_H_ERRNO(res, HOST_NOT_FOUND); /* default, if we never query */
+ dots = 0;
+ for (cp = name; *cp; cp++)
+ dots += (*cp == '.');
+ trailing_dot = 0;
+ if (cp > name && *--cp == '.')
+ trailing_dot++;
+
+ /*
+ * if there aren't any dots, it could be a user-level alias
+ */
+ if (!dots &&
+ (cp = res_hostalias(res, name, abuf, sizeof(abuf))) != NULL)
+ return (res_queryN(cp, target, res));
+
+ /*
+ * If there are enough dots in the name, let's just give it a
+ * try 'as is'. The threshold can be set with the "ndots" option.
+ * Also, query 'as is', if there is a trailing dot in the name.
+ */
+ saved_herrno = -1;
+ if (dots >= res->ndots || trailing_dot) {
+ ret = res_querydomainN(name, NULL, target, res);
+ if (ret > 0 || trailing_dot)
+ return (ret);
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ return (-1);
+ }
+ switch (res->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ return (-1);
+ }
+ saved_herrno = res->res_h_errno;
+ tried_as_is++;
+ }
+
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((!dots && (res->options & RES_DEFNAMES)) ||
+ (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
+ int done = 0;
+
+ for (domain = (const char * const *)res->dnsrch;
+ *domain && !done;
+ domain++) {
+ searched = 1;
+
+ if (domain[0][0] == '\0' ||
+ (domain[0][0] == '.' && domain[0][1] == '\0'))
+ root_on_list++;
+
+ if (root_on_list && tried_as_is)
+ continue;
+
+ ret = res_querydomainN(name, *domain, target, res);
+ if (ret > 0)
+ return (ret);
+
+ /*
+ * If no server present, give up.
+ * If name isn't found in this domain,
+ * keep trying higher domains in the search list
+ * (if that's enabled).
+ * On a NO_DATA error, keep trying, otherwise
+ * a wildcard entry of another type could keep us
+ * from finding this entry higher in the domain.
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
+ * but try the input name below in case it's
+ * fully-qualified.
+ */
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ return (-1);
+ }
+
+ switch (res->res_h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ got_servfail++;
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* anything else implies that we're done */
+ done++;
+ }
+ /*
+ * if we got here for some reason other than DNSRCH,
+ * we only wanted one iteration of the loop, so stop.
+ */
+ if (!(res->options & RES_DNSRCH))
+ done++;
+ }
+ }
+
+ switch (res->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ goto giveup;
+ }
+
+ /*
+ * If the query has not already been tried as is then try it
+ * unless RES_NOTLDQUERY is set and there were no dots.
+ */
+ if ((dots || !searched || !(res->options & RES_NOTLDQUERY)) &&
+ !(tried_as_is || root_on_list)) {
+ ret = res_querydomainN(name, NULL, target, res);
+ if (ret > 0)
+ return (ret);
+ }
+
+ /*
+ * if we got here, we didn't satisfy the search.
+ * if we did an initial full query, return that query's h_errno
+ * (note that we wouldn't be here if that query had succeeded).
+ * else if we ever got a nodata, send that back as the reason.
+ * else send back meaningless h_errno, that being the one from
+ * the last DNSRCH we did.
+ */
+giveup:
+ if (saved_herrno != -1)
+ RES_SET_H_ERRNO(res, saved_herrno);
+ else if (got_nodata)
+ RES_SET_H_ERRNO(res, NO_DATA);
+ else if (got_servfail)
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ return (-1);
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+static int
+res_querydomainN(const char *name, const char *domain,
+ struct res_target *target, res_state res)
+{
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+ size_t n, d;
+
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_querydomain(%s, %s)\n",
+ name, domain?domain:"<Nil>");
+#endif
+ if (domain == NULL) {
+ /*
+ * Check for trailing '.';
+ * copy without '.' if present.
+ */
+ n = strlen(name);
+ if (n >= MAXDNAME) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (-1);
+ }
+ if (n > 0 && name[--n] == '.') {
+ strncpy(nbuf, name, n);
+ nbuf[n] = '\0';
+ } else
+ longname = name;
+ } else {
+ n = strlen(name);
+ d = strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (-1);
+ }
+ snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
+ }
+ return (res_queryN(longname, target, res));
+}
diff --git a/freebsd/lib/libc/net/gethostbydns.c b/freebsd/lib/libc/net/gethostbydns.c
new file mode 100644
index 00000000..2993a678
--- /dev/null
+++ b/freebsd/lib/libc/net/gethostbydns.c
@@ -0,0 +1,787 @@
+#include "port_before.h"
+
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+
+#include "netdb_private.h"
+#include "res_config.h"
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+static const char AskedForGot[] =
+ "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
+
+#ifdef RESOLVSORT
+static void addrsort(char **, int, res_state);
+#endif
+
+#ifdef DEBUG
+static void DPRINTF(char *, int, res_state) __printflike(1, 0);
+#endif
+
+#define MAXPACKET (64*1024)
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+int _dns_ttl_;
+
+#ifdef DEBUG
+static void
+DPRINTF(msg, num, res)
+ char *msg;
+ int num;
+ res_state res;
+{
+ if (res->options & RES_DEBUG) {
+ int save = errno;
+
+ printf(msg, num);
+ errno = save;
+ }
+}
+#else
+# define DPRINTF(msg, num, res) /*nada*/
+#endif
+
+#define BOUNDED_INCR(x) \
+ do { \
+ cp += x; \
+ if (cp > eom) { \
+ RES_SET_H_ERRNO(statp, NO_RECOVERY); \
+ return (-1); \
+ } \
+ } while (0)
+
+#define BOUNDS_CHECK(ptr, count) \
+ do { \
+ if ((ptr) + (count) > eom) { \
+ RES_SET_H_ERRNO(statp, NO_RECOVERY); \
+ return (-1); \
+ } \
+ } while (0)
+
+static int
+gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
+ struct hostent *he, struct hostent_data *hed, res_state statp)
+{
+ const HEADER *hp;
+ const u_char *cp;
+ int n;
+ const u_char *eom, *erdata;
+ char *bp, *ep, **ap, **hap;
+ int type, class, ancount, qdcount;
+ int haveanswer, had_error;
+ int toobig = 0;
+ char tbuf[MAXDNAME];
+ const char *tname;
+ int (*name_ok)(const char *);
+
+ tname = qname;
+ he->h_name = NULL;
+ eom = answer->buf + anslen;
+ switch (qtype) {
+ case T_A:
+ case T_AAAA:
+ name_ok = res_hnok;
+ break;
+ case T_PTR:
+ name_ok = res_dnok;
+ break;
+ default:
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1); /* XXX should be abort(); */
+ }
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ cp = answer->buf;
+ BOUNDED_INCR(HFIXEDSZ);
+ if (qdcount != 1) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ BOUNDED_INCR(n + QFIXEDSZ);
+ if (qtype == T_A || qtype == T_AAAA) {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ he->h_name = bp;
+ bp += n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = he->h_name;
+ }
+ ap = hed->host_aliases;
+ *ap = NULL;
+ he->h_aliases = hed->host_aliases;
+ hap = hed->h_addr_ptrs;
+ *hap = NULL;
+ he->h_addr_list = hed->h_addr_ptrs;
+ haveanswer = 0;
+ had_error = 0;
+ _dns_ttl_ = -1;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+ type = _getshort(cp);
+ cp += INT16SZ; /* type */
+ class = _getshort(cp);
+ cp += INT16SZ; /* class */
+ if (qtype == T_A && type == T_A)
+ _dns_ttl_ = _getlong(cp);
+ cp += INT32SZ; /* TTL */
+ n = _getshort(cp);
+ cp += INT16SZ; /* len */
+ BOUNDS_CHECK(cp, n);
+ erdata = cp + n;
+ if (class != C_IN) {
+ /* XXX - debug? syslog? */
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
+ if (ap >= &hed->host_aliases[_MAXALIASES-1])
+ continue;
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if ((n < 0) || !(*name_ok)(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ /* Store alias. */
+ *ap++ = bp;
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ bp += n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ he->h_name = bp;
+ bp += n;
+ continue;
+ }
+ if (qtype == T_PTR && type == T_CNAME) {
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if (n < 0 || !res_dnok(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ tname = bp;
+ bp += n;
+ continue;
+ }
+ if (type != qtype) {
+ if (type != T_SIG && type != ns_t_dname)
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ switch (type) {
+ case T_PTR:
+ if (strcasecmp(tname, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, qname, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !res_hnok(bp)) {
+ had_error++;
+ break;
+ }
+#if MULTI_PTRS_ARE_ALIASES
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ if (!haveanswer)
+ he->h_name = bp;
+ else if (ap < &hed->host_aliases[_MAXALIASES-1])
+ *ap++ = bp;
+ else
+ n = -1;
+ if (n != -1) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ }
+ break;
+#else
+ he->h_name = bp;
+#ifdef INET6
+ if (statp->options & RES_USE_INET6) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ _map_v4v6_hostent(he, &bp, ep);
+ }
+#endif
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+#endif
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(he->h_name, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, he->h_name, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (n != he->h_length) {
+ cp += n;
+ continue;
+ }
+ if (!haveanswer) {
+ int nn;
+
+ he->h_name = bp;
+ nn = strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ }
+
+ bp += sizeof(align) - ((u_long)bp % sizeof(align));
+
+ if (bp + n >= ep) {
+ DPRINTF("size (%d) too big\n", n, statp);
+ had_error++;
+ continue;
+ }
+ if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) {
+ if (!toobig++)
+ DPRINTF("Too many addresses (%d)\n",
+ _MAXADDRS, statp);
+ cp += n;
+ continue;
+ }
+ memcpy(*hap++ = bp, cp, n);
+ bp += n;
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ break;
+ default:
+ DPRINTF("Impossible condition (type=%d)\n", type,
+ statp);
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ /* BIND has abort() here, too risky on bad data */
+ }
+ if (!had_error)
+ haveanswer++;
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ *hap = NULL;
+# if defined(RESOLVSORT)
+ /*
+ * Note: we sort even if host can take only one address
+ * in its return structures - should give it the "best"
+ * address in that case, not some random one
+ */
+ if (statp->nsort && haveanswer > 1 && qtype == T_A)
+ addrsort(hed->h_addr_ptrs, haveanswer, statp);
+# endif /*RESOLVSORT*/
+ if (!he->h_name) {
+ n = strlen(qname) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN)
+ goto no_recovery;
+ strcpy(bp, qname);
+ he->h_name = bp;
+ bp += n;
+ }
+#ifdef INET6
+ if (statp->options & RES_USE_INET6)
+ _map_v4v6_hostent(he, &bp, ep);
+#endif
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+ }
+ no_recovery:
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+}
+
+/* XXX: for async DNS resolver in ypserv */
+struct hostent *
+__dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
+{
+ struct hostent *he;
+ struct hostent_data *hed;
+ int error;
+ res_state statp;
+
+ statp = __res_state();
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (NULL);
+ }
+ switch (qtype) {
+ case T_AAAA:
+ he->h_addrtype = AF_INET6;
+ he->h_length = NS_IN6ADDRSZ;
+ break;
+ case T_A:
+ default:
+ he->h_addrtype = AF_INET;
+ he->h_length = NS_INADDRSZ;
+ break;
+ }
+
+ error = gethostanswer((const querybuf *)answer, anslen, qname, qtype,
+ he, hed, statp);
+ return (error == 0) ? he : NULL;
+}
+
+int
+_dns_gethostbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *name;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ querybuf *buf;
+ int n, type, error;
+ res_state statp;
+
+ name = va_arg(ap, const char *);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ he.h_addrtype = af;
+ switch (af) {
+ case AF_INET:
+ he.h_length = NS_INADDRSZ;
+ type = T_A;
+ break;
+ case AF_INET6:
+ he.h_length = NS_IN6ADDRSZ;
+ type = T_AAAA;
+ break;
+ default:
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ errno = EAFNOSUPPORT;
+ return (NS_UNAVAIL);
+ }
+
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ n = res_nsearch(statp, name, C_IN, type, buf->buf, sizeof(buf->buf));
+ if (n < 0) {
+ free(buf);
+ DPRINTF("res_nsearch failed (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ } else if (n > sizeof(buf->buf)) {
+ free(buf);
+ DPRINTF("static buffer is too small (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ error = gethostanswer(buf, n, name, type, &he, hed, statp);
+ free(buf);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ switch (statp->res_h_errno) {
+ case HOST_NOT_FOUND:
+ return (NS_NOTFOUND);
+ case TRY_AGAIN:
+ return (NS_TRYAGAIN);
+ default:
+ return (NS_UNAVAIL);
+ }
+ /*NOTREACHED*/
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
+
+int
+_dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ const void *addr;
+ socklen_t len;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ const u_char *uaddr;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ int n;
+ querybuf *buf;
+ char qbuf[MAXDNAME+1], *qp;
+ res_state statp;
+#ifdef SUNSECURITY
+ struct hostdata rhd;
+ struct hostent *rhe;
+ char **haddr;
+ u_long old_options;
+ char hname2[MAXDNAME+1], numaddr[46];
+ int ret_h_error;
+#endif /*SUNSECURITY*/
+
+ addr = va_arg(ap, const void *);
+ len = va_arg(ap, socklen_t);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+ uaddr = (const u_char *)addr;
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ switch (af) {
+ case AF_INET:
+ (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+ (uaddr[3] & 0xff),
+ (uaddr[2] & 0xff),
+ (uaddr[1] & 0xff),
+ (uaddr[0] & 0xff));
+ break;
+ case AF_INET6:
+ qp = qbuf;
+ for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
+ qp += SPRINTF((qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf));
+ }
+ strlcat(qbuf, "ip6.arpa", sizeof(qbuf));
+ break;
+ default:
+ abort();
+ }
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return NS_NOTFOUND;
+ }
+ n = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf->buf,
+ sizeof buf->buf);
+ if (n < 0) {
+ free(buf);
+ DPRINTF("res_nquery failed (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if (n > sizeof buf->buf) {
+ free(buf);
+ DPRINTF("static buffer is too small (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if (gethostanswer(buf, n, qbuf, T_PTR, &he, hed, statp) != 0) {
+ free(buf);
+ *h_errnop = statp->res_h_errno;
+ switch (statp->res_h_errno) {
+ case HOST_NOT_FOUND:
+ return (NS_NOTFOUND);
+ case TRY_AGAIN:
+ return (NS_TRYAGAIN);
+ default:
+ return (NS_UNAVAIL);
+ }
+ /*NOTREACHED*/
+ }
+ free(buf);
+#ifdef SUNSECURITY
+ if (af == AF_INET) {
+ /*
+ * turn off search as the name should be absolute,
+ * 'localhost' should be matched by defnames
+ */
+ strncpy(hname2, he.h_name, MAXDNAME);
+ hname2[MAXDNAME] = '\0';
+ old_options = statp->options;
+ statp->options &= ~RES_DNSRCH;
+ statp->options |= RES_DEFNAMES;
+ memset(&rhd, 0, sizeof rhd);
+ rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data,
+ sizeof(rhd.data), &ret_h_error);
+ if (rhe == NULL) {
+ if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
+ strlcpy(numaddr, "UNKNOWN", sizeof(numaddr));
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: No A record for %s (verifying [%s])",
+ hname2, numaddr);
+ statp->options = old_options;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ statp->options = old_options;
+ for (haddr = rhe->h_addr_list; *haddr; haddr++)
+ if (!memcmp(*haddr, addr, NS_INADDRSZ))
+ break;
+ if (!*haddr) {
+ if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
+ strlcpy(numaddr, "UNKNOWN", sizeof(numaddr));
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: A record of %s != PTR record [%s]",
+ hname2, numaddr);
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ }
+#endif /*SUNSECURITY*/
+ he.h_addrtype = af;
+ he.h_length = len;
+ memcpy(hed->host_addr, uaddr, len);
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+#ifdef INET6
+ if (af == AF_INET && (statp->options & RES_USE_INET6)) {
+ _map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr);
+ he.h_addrtype = AF_INET6;
+ he.h_length = NS_IN6ADDRSZ;
+ }
+#endif
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
+
+#ifdef RESOLVSORT
+static void
+addrsort(char **ap, int num, res_state res)
+{
+ int i, j;
+ char **p;
+ short aval[_MAXADDRS];
+ int needsort = 0;
+
+ p = ap;
+ for (i = 0; i < num; i++, p++) {
+ for (j = 0 ; (unsigned)j < res->nsort; j++)
+ if (res->sort_list[j].addr.s_addr ==
+ (((struct in_addr *)(*p))->s_addr & res->sort_list[j].mask))
+ break;
+ aval[i] = j;
+ if (needsort == 0 && i > 0 && j < aval[i-1])
+ needsort = i;
+ }
+ if (!needsort)
+ return;
+
+ while (needsort < num) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (aval[j] > aval[j+1]) {
+ char *hp;
+
+ i = aval[j];
+ aval[j] = aval[j+1];
+ aval[j+1] = i;
+
+ hp = ap[j];
+ ap[j] = ap[j+1];
+ ap[j+1] = hp;
+
+ } else
+ break;
+ }
+ needsort++;
+ }
+}
+#endif
+
+void
+_sethostdnsent(int stayopen)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1)
+ return;
+ if (stayopen)
+ statp->options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endhostdnsent()
+{
+ res_state statp;
+
+ statp = __res_state();
+ statp->options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_nclose(statp);
+}
diff --git a/freebsd/lib/libc/net/gethostbyht.c b/freebsd/lib/libc/net/gethostbyht.c
new file mode 100644
index 00000000..eb995b96
--- /dev/null
+++ b/freebsd/lib/libc/net/gethostbyht.c
@@ -0,0 +1,354 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <arpa/nameser.h> /* XXX */
+#include <resolv.h> /* XXX */
+#include "netdb_private.h"
+
+void
+_sethosthtent(int f, struct hostent_data *hed)
+{
+ if (!hed->hostf)
+ hed->hostf = fopen(_PATH_HOSTS, "r");
+ else
+ rewind(hed->hostf);
+ hed->stayopen = f;
+}
+
+void
+_endhosthtent(struct hostent_data *hed)
+{
+ if (hed->hostf && !hed->stayopen) {
+ (void) fclose(hed->hostf);
+ hed->hostf = NULL;
+ }
+}
+
+static int
+gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped,
+ res_state statp)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ int af, len;
+ char hostbuf[BUFSIZ + 1];
+
+ if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ again:
+ if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ if (!(cp = strpbrk(p, " \t")))
+ goto again;
+ *cp++ = '\0';
+#ifdef INET6
+ if (inet_pton(AF_INET6, p, hed->host_addr) > 0) {
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else if (inet_pton(AF_INET, p, hed->host_addr) > 0) {
+ if (mapped) {
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else {
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ } else {
+ goto again;
+ }
+#else
+ if (inet_pton(AF_INET, p, hed->host_addr) > 0) {
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+#endif
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ he->h_addr_list = hed->h_addr_ptrs;
+ he->h_length = len;
+ he->h_addrtype = af;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ he->h_name = bp;
+ q = he->h_aliases = hed->host_aliases;
+ if ((p = strpbrk(cp, " \t")) != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, cp, ep - bp);
+ bp += len;
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q >= &hed->host_aliases[_MAXALIASES - 1])
+ break;
+ if ((p = strpbrk(cp, " \t")) != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += len;
+ cp = p;
+ }
+ *q = NULL;
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+}
+
+int
+gethostent_r(struct hostent *hptr, char *buffer, size_t buflen,
+ struct hostent **result, int *h_errnop)
+{
+ struct hostent_data *hed;
+ struct hostent he;
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+#ifdef INET6
+ if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0)
+ return (-1);
+#endif
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return ((errno != 0) ? errno : -1);
+ }
+ *result = hptr;
+ return (0);
+}
+
+struct hostent *
+gethostent(void)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+int
+_ht_gethostbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *name;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ char **cp;
+ res_state statp;
+ int error;
+
+ name = va_arg(ap, const char *);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ _sethosthtent(0, hed);
+ while ((error = gethostent_p(&he, hed, 0, statp)) == 0) {
+ if (he.h_addrtype != af)
+ continue;
+#ifdef INET6
+ if (he.h_addrtype == AF_INET &&
+ statp->options & RES_USE_INET6) {
+ _map_v4v6_address(he.h_addr, he.h_addr);
+ he.h_length = IN6ADDRSZ;
+ he.h_addrtype = AF_INET6;
+ }
+#endif
+ if (strcasecmp(he.h_name, name) == 0)
+ break;
+ for (cp = he.h_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ _endhosthtent(hed);
+
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
+
+int
+_ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ const void *addr;
+ socklen_t len;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ res_state statp;
+ int error;
+
+ addr = va_arg(ap, const void *);
+ len = va_arg(ap, socklen_t);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ _sethosthtent(0, hed);
+ while ((error = gethostent_p(&he, hed, 0, statp)) == 0)
+#ifdef INET6
+ if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) {
+ if (he.h_addrtype == AF_INET &&
+ statp->options & RES_USE_INET6) {
+ _map_v4v6_address(he.h_addr, he.h_addr);
+ he.h_length = IN6ADDRSZ;
+ he.h_addrtype = AF_INET6;
+ }
+ break;
+ }
+#endif
+ _endhosthtent(hed);
+
+ if (error != 0)
+ return (NS_NOTFOUND);
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
diff --git a/freebsd/lib/libc/net/gethostbynis.c b/freebsd/lib/libc/net/gethostbynis.c
new file mode 100644
index 00000000..81f00932
--- /dev/null
+++ b/freebsd/lib/libc/net/gethostbynis.c
@@ -0,0 +1,354 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <resolv.h> /* XXX */
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include "netdb_private.h"
+
+#ifdef YP
+static int
+_gethostbynis(const char *name, char *map, int af, struct hostent *he,
+ struct hostent_data *hed)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ char *result;
+ int resultlen, size, addrok = 0;
+ char ypbuf[YPMAXRECORD + 2];
+ res_state statp;
+
+ statp = __res_state();
+ switch(af) {
+ case AF_INET:
+ size = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ size = NS_IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ if (hed->yp_domain == (char *)NULL)
+ if (yp_get_default_domain (&hed->yp_domain)) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
+ &resultlen)) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+
+ /* avoid potential memory leak */
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ he->h_addr_list = hed->h_addr_ptrs;
+ he->h_addr = (char *)hed->host_addr;
+ switch (af) {
+ case AF_INET:
+ addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
+ if (addrok != 1)
+ break;
+ if (statp->options & RES_USE_INET6) {
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
+ af = AF_INET6;
+ size = NS_IN6ADDRSZ;
+ }
+ break;
+ case AF_INET6:
+ addrok = inet_pton(af, result, hed->host_addr);
+ break;
+ }
+ if (addrok != 1) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+ he->h_addr_list[1] = NULL;
+ he->h_length = size;
+ he->h_addrtype = af;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ he->h_name = bp;
+ q = he->h_aliases = hed->host_aliases;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ size = strlen(cp) + 1;
+ if (ep - bp < size) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, cp, ep - bp);
+ bp += size;
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q >= &hed->host_aliases[_MAXALIASES - 1])
+ break;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ size = strlen(cp) + 1;
+ if (ep - bp < size)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += size;
+ cp = p;
+ }
+ *q = NULL;
+ return (0);
+}
+
+static int
+_gethostbynisname_r(const char *name, int af, struct hostent *he,
+ struct hostent_data *hed)
+{
+ char *map;
+
+ switch (af) {
+ case AF_INET:
+ map = "hosts.byname";
+ break;
+ default:
+ map = "ipnodes.byname";
+ break;
+ }
+ return (_gethostbynis(name, map, af, he, hed));
+}
+
+static int
+_gethostbynisaddr_r(const void *addr, socklen_t len, int af,
+ struct hostent *he, struct hostent_data *hed)
+{
+ char *map;
+ char numaddr[46];
+
+ switch (af) {
+ case AF_INET:
+ map = "hosts.byaddr";
+ break;
+ default:
+ map = "ipnodes.byaddr";
+ break;
+ }
+ if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
+ return (-1);
+ return (_gethostbynis(numaddr, map, af, he, hed));
+}
+#endif /* YP */
+
+/* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */
+struct hostent *
+_gethostbynisname(const char *name, int af)
+{
+#ifdef YP
+ struct hostent *he;
+ struct hostent_data *hed;
+ u_long oresopt;
+ int error;
+ res_state statp;
+
+ statp = __res_state();
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (NULL);
+ }
+
+ oresopt = statp->options;
+ statp->options &= ~RES_USE_INET6;
+ error = _gethostbynisname_r(name, af, he, hed);
+ statp->options = oresopt;
+ return (error == 0) ? he : NULL;
+#else
+ return (NULL);
+#endif
+}
+
+struct hostent *
+_gethostbynisaddr(const void *addr, socklen_t len, int af)
+{
+#ifdef YP
+ struct hostent *he;
+ struct hostent_data *hed;
+ u_long oresopt;
+ int error;
+ res_state statp;
+
+ statp = __res_state();
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (NULL);
+ }
+
+ oresopt = statp->options;
+ statp->options &= ~RES_USE_INET6;
+ error = _gethostbynisaddr_r(addr, len, af, he, hed);
+ statp->options = oresopt;
+ return (error == 0) ? he : NULL;
+#else
+ return (NULL);
+#endif
+}
+
+int
+_nis_gethostbyname(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ const char *name;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ res_state statp;
+
+ name = va_arg(ap, const char *);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (_gethostbynisname_r(name, af, &he, hed) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+#else
+ *((struct hostent **)rval) = NULL;
+ return (NS_UNAVAIL);
+#endif
+}
+
+int
+_nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ const void *addr;
+ socklen_t len;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ res_state statp;
+
+ addr = va_arg(ap, const void *);
+ len = va_arg(ap, socklen_t);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+#else
+ *((struct hostent **)rval) = NULL;
+ return (NS_UNAVAIL);
+#endif
+}
diff --git a/freebsd/lib/libc/net/gethostnamadr.c b/freebsd/lib/libc/net/gethostnamadr.c
new file mode 100644
index 00000000..d663e286
--- /dev/null
+++ b/freebsd/lib/libc/net/gethostnamadr.c
@@ -0,0 +1,740 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 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 "namespace.h"
+#include "reentrant.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <arpa/nameser.h> /* XXX hack for _res */
+#include <resolv.h> /* XXX hack for _res */
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+extern int _ht_gethostbyname(void *, void *, va_list);
+extern int _dns_gethostbyname(void *, void *, va_list);
+extern int _nis_gethostbyname(void *, void *, va_list);
+extern int _ht_gethostbyaddr(void *, void *, va_list);
+extern int _dns_gethostbyaddr(void *, void *, va_list);
+extern int _nis_gethostbyaddr(void *, void *, va_list);
+
+static int gethostbyname_internal(const char *, int, struct hostent *, char *,
+ size_t, struct hostent **, int *, res_state);
+
+/* Host lookup order if nsswitch.conf is broken or nonexistant */
+static const ns_src default_src[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NSSRC_DNS, NS_SUCCESS },
+ { 0 }
+};
+#ifdef NS_CACHING
+static int host_id_func(char *, size_t *, va_list, void *);
+static int host_marshal_func(char *, size_t *, void *, va_list, void *);
+static int host_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+NETDB_THREAD_ALLOC(hostent)
+NETDB_THREAD_ALLOC(hostent_data)
+NETDB_THREAD_ALLOC(hostdata)
+
+static void
+hostent_free(void *ptr)
+{
+ free(ptr);
+}
+
+static void
+hostent_data_free(void *ptr)
+{
+ struct hostent_data *hed = ptr;
+
+ if (hed == NULL)
+ return;
+ hed->stayopen = 0;
+ _endhosthtent(hed);
+ free(hed);
+}
+
+static void
+hostdata_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf,
+ size_t buflen)
+{
+ char *cp;
+ char **ptr;
+ int i, n;
+ int nptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ nptr = 2; /* NULL ptrs */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; he->h_addr_list[i]; i++, nptr++) {
+ len += he->h_length;
+ }
+ for (i = 0; he->h_aliases[i]; i++, nptr++) {
+ len += strlen(he->h_aliases[i]) + 1;
+ }
+ len += strlen(he->h_name) + 1;
+ len += nptr * sizeof(char*);
+
+ if (len > buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy address size and type */
+ hptr->h_addrtype = he->h_addrtype;
+ n = hptr->h_length = he->h_length;
+
+ ptr = (char **)ALIGN(buf);
+ cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
+
+ /* copy address list */
+ hptr->h_addr_list = ptr;
+ for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
+ memcpy(cp, he->h_addr_list[i], n);
+ hptr->h_addr_list[i] = cp;
+ cp += n;
+ }
+ hptr->h_addr_list[i] = NULL;
+ ptr++;
+
+ /* copy official name */
+ n = strlen(he->h_name) + 1;
+ strcpy(cp, he->h_name);
+ hptr->h_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ hptr->h_aliases = ptr;
+ for (i = 0 ; he->h_aliases[i]; i++) {
+ n = strlen(he->h_aliases[i]) + 1;
+ strcpy(cp, he->h_aliases[i]);
+ hptr->h_aliases[i] = cp;
+ cp += n;
+ }
+ hptr->h_aliases[i] = NULL;
+
+ return (0);
+}
+
+#ifdef NS_CACHING
+static int
+host_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ res_state statp;
+ u_long res_options;
+
+ const int op_id = 1;
+ char *str;
+ void *addr;
+ socklen_t len;
+ int type;
+
+ size_t desired_size, size;
+ enum nss_lookup_type lookup_type;
+ char *p;
+ int res = NS_UNAVAIL;
+
+ statp = __res_state();
+ res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
+ RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ str = va_arg(ap, char *);
+ type = va_arg(ap, int);
+
+ size = strlen(str);
+ desired_size = sizeof(res_options) + sizeof(int) +
+ sizeof(enum nss_lookup_type) + sizeof(int) + size + 1;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ p = buffer;
+
+ memcpy(p, &res_options, sizeof(res_options));
+ p += sizeof(res_options);
+
+ memcpy(p, &op_id, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
+ p += sizeof(int);
+
+ memcpy(p, &type, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, str, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ addr = va_arg(ap, void *);
+ len = va_arg(ap, socklen_t);
+ type = va_arg(ap, int);
+
+ desired_size = sizeof(res_options) + sizeof(int) +
+ sizeof(enum nss_lookup_type) + sizeof(int) +
+ sizeof(socklen_t) + len;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ p = buffer;
+ memcpy(p, &res_options, sizeof(res_options));
+ p += sizeof(res_options);
+
+ memcpy(p, &op_id, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
+ p += sizeof(int);
+
+ memcpy(p, &type, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &len, sizeof(socklen_t));
+ p += sizeof(socklen_t);
+
+ memcpy(p, addr, len);
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+static int
+host_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *str;
+ void *addr;
+ socklen_t len;
+ int type;
+ struct hostent *ht;
+
+ struct hostent new_ht;
+ size_t desired_size, aliases_size, addr_size, size;
+ char *p, **iter;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ str = va_arg(ap, char *);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_id:
+ addr = va_arg(ap, void *);
+ len = va_arg(ap, socklen_t);
+ type = va_arg(ap, int);
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+ ht = va_arg(ap, struct hostent *);
+
+ desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *);
+ if (ht->h_name != NULL)
+ desired_size += strlen(ht->h_name) + 1;
+
+ if (ht->h_aliases != NULL) {
+ aliases_size = 0;
+ for (iter = ht->h_aliases; *iter; ++iter) {
+ desired_size += strlen(*iter) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES +
+ (aliases_size + 1) * sizeof(char *);
+ }
+
+ if (ht->h_addr_list != NULL) {
+ addr_size = 0;
+ for (iter = ht->h_addr_list; *iter; ++iter)
+ ++addr_size;
+
+ desired_size += addr_size * _ALIGN(ht->h_length);
+ desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *);
+ }
+
+ if (desired_size > *buffer_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_ht, ht, sizeof(struct hostent));
+ memset(buffer, 0, desired_size);
+
+ *buffer_size = desired_size;
+ p = buffer + sizeof(struct hostent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_ht.h_name != NULL) {
+ size = strlen(new_ht.h_name);
+ memcpy(p, new_ht.h_name, size);
+ new_ht.h_name = p;
+ p += size + 1;
+ }
+
+ if (new_ht.h_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size);
+ new_ht.h_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (iter = new_ht.h_aliases; *iter; ++iter) {
+ size = strlen(*iter);
+ memcpy(p, *iter, size);
+ *iter = p;
+ p += size + 1;
+ }
+ }
+
+ if (new_ht.h_addr_list != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size);
+ new_ht.h_addr_list = (char **)p;
+ p += sizeof(char *) * (addr_size + 1);
+
+ size = _ALIGN(new_ht.h_length);
+ for (iter = new_ht.h_addr_list; *iter; ++iter) {
+ memcpy(p, *iter, size);
+ *iter = p;
+ p += size + 1;
+ }
+ }
+ memcpy(buffer, &new_ht, sizeof(struct hostent));
+ return (NS_SUCCESS);
+}
+
+static int
+host_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *str;
+ void *addr;
+ socklen_t len;
+ int type;
+ struct hostent *ht;
+
+ char *p;
+ char **iter;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ str = va_arg(ap, char *);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_id:
+ addr = va_arg(ap, void *);
+ len = va_arg(ap, socklen_t);
+ type = va_arg(ap, int);
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ ht = va_arg(ap, struct hostent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct hostent) - sizeof(char *)) {
+ errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(ht, buffer, sizeof(struct hostent));
+ memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct hostent) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct hostent) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *);
+ if (ht->h_aliases != NULL) {
+ NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **);
+
+ for (iter = ht->h_aliases; *iter; ++iter)
+ NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
+ }
+
+ if (ht->h_addr_list != NULL) {
+ NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **);
+
+ for (iter = ht->h_addr_list; *iter; ++iter)
+ NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
+ }
+
+ *((struct hostent **)retval) = ht;
+ return (NS_SUCCESS);
+}
+#endif /* NS_CACHING */
+
+static int
+fakeaddr(const char *name, int af, struct hostent *hp, char *buf,
+ size_t buflen, res_state statp)
+{
+ struct hostent_data *hed;
+ struct hostent he;
+
+ if ((hed = __hostent_data_init()) == NULL) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ if ((af != AF_INET ||
+ inet_aton(name, (struct in_addr *)hed->host_addr) != 1) &&
+ inet_pton(af, name, hed->host_addr) != 1) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+ strncpy(hed->hostbuf, name, MAXDNAME);
+ hed->hostbuf[MAXDNAME] = '\0';
+#ifdef INET6
+ if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) {
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
+ af = AF_INET6;
+ }
+#endif
+ he.h_addrtype = af;
+ switch(af) {
+ case AF_INET:
+ he.h_length = NS_INADDRSZ;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ he.h_length = NS_IN6ADDRSZ;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ he.h_name = hed->hostbuf;
+ he.h_aliases = hed->host_aliases;
+ hed->host_aliases[0] = NULL;
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ he.h_addr_list = hed->h_addr_ptrs;
+ if (__copy_hostent(&he, hp, buf, buflen) != 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+}
+
+int
+gethostbyname_r(const char *name, struct hostent *he, char *buffer,
+ size_t buflen, struct hostent **result, int *h_errnop)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ if (statp->options & RES_USE_INET6) {
+ if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) {
+ *result = he;
+ return (0);
+ }
+ if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen,
+ result, h_errnop, statp) == 0)
+ return (0);
+ }
+ return (gethostbyname_internal(name, AF_INET, he, buffer, buflen,
+ result, h_errnop, statp));
+}
+
+int
+gethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer,
+ size_t buflen, struct hostent **result, int *h_errnop)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (gethostbyname_internal(name, af, he, buffer, buflen, result,
+ h_errnop, statp));
+}
+
+int
+gethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf,
+ size_t buflen, struct hostent **result, int *h_errnop, res_state statp)
+{
+ const char *cp;
+ int rval, ret_errno = 0;
+ char abuf[MAXDNAME];
+
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ hosts, (void *)nss_lt_name,
+ host_id_func, host_marshal_func, host_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_gethostbyname, NULL)
+ { NSSRC_DNS, _dns_gethostbyname, NULL },
+ NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+
+ switch (af) {
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_query() since we are not the only
+ * function that looks up host names.
+ */
+ if (!strchr(name, '.') &&
+ (cp = res_hostalias(statp, name, abuf, sizeof abuf)))
+ name = cp;
+
+ if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) {
+ *result = hp;
+ return (0);
+ }
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
+ "gethostbyname2_r", default_src, name, af, hp, buf, buflen,
+ &ret_errno, h_errnop);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+int
+gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
+ char *buf, size_t buflen, struct hostent **result, int *h_errnop)
+{
+ const u_char *uaddr = (const u_char *)addr;
+ const struct in6_addr *addr6;
+ socklen_t size;
+ int rval, ret_errno = 0;
+ res_state statp;
+
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ hosts, (void *)nss_lt_id,
+ host_id_func, host_marshal_func, host_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_gethostbyaddr, NULL)
+ { NSSRC_DNS, _dns_gethostbyaddr, NULL },
+ NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+
+ if (af == AF_INET6 && len == NS_IN6ADDRSZ) {
+ addr6 = (const struct in6_addr *)addr;
+ if (IN6_IS_ADDR_LINKLOCAL(addr6)) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (IN6_IS_ADDR_V4MAPPED(addr6) ||
+ IN6_IS_ADDR_V4COMPAT(addr6)) {
+ /* Unmap. */
+ uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
+ af = AF_INET;
+ len = NS_INADDRSZ;
+ }
+ }
+ switch (af) {
+ case AF_INET:
+ size = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ size = NS_IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (size != len) {
+ errno = EINVAL;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
+ "gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen,
+ &ret_errno, h_errnop);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+struct hostent *
+gethostbyname(const char *name)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+struct hostent *
+gethostbyname2(const char *name, int af)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data),
+ &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+struct hostent *
+gethostbyaddr(const void *addr, socklen_t len, int af)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data,
+ sizeof(hd->data), &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+void
+sethostent(int stayopen)
+{
+ struct hostent_data *hed;
+
+ if ((hed = __hostent_data_init()) == NULL)
+ return;
+ _sethosthtent(stayopen, hed);
+ _sethostdnsent(stayopen);
+}
+
+void
+endhostent(void)
+{
+ struct hostent_data *hed;
+
+ if ((hed = __hostent_data_init()) == NULL)
+ return;
+ _endhosthtent(hed);
+ _endhostdnsent();
+}
diff --git a/freebsd/lib/libc/net/getifaddrs.c b/freebsd/lib/libc/net/getifaddrs.c
new file mode 100644
index 00000000..2eceadb7
--- /dev/null
+++ b/freebsd/lib/libc/net/getifaddrs.c
@@ -0,0 +1,420 @@
+#include "port_before.h"
+
+/* $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $ */
+
+/*
+ * Copyright (c) 1995, 1999
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, 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 Berkeley Software Design, 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.
+ *
+ * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
+ */
+/*
+ * NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform
+ * try-and-error for region size.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#ifdef NET_RT_IFLIST
+#include <sys/param.h>
+#include <net/route.h>
+#include <sys/sysctl.h>
+#include <net/if_dl.h>
+#endif
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#if !defined(AF_LINK)
+#define SA_LEN(sa) sizeof(struct sockaddr)
+#endif
+
+#if !defined(SA_LEN)
+#define SA_LEN(sa) (sa)->sa_len
+#endif
+
+#define SALIGN (sizeof(long) - 1)
+#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
+
+#ifndef ALIGNBYTES
+/*
+ * On systems with a routing socket, ALIGNBYTES should match the value
+ * that the kernel uses when building the messages.
+ */
+#define ALIGNBYTES XXX
+#endif
+#ifndef ALIGN
+#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+#endif
+
+#if _BSDI_VERSION >= 199701
+#define HAVE_IFM_DATA
+#endif
+
+#if _BSDI_VERSION >= 199802
+/* ifam_data is very specific to recent versions of bsdi */
+#define HAVE_IFAM_DATA
+#endif
+
+#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
+#define HAVE_IFM_DATA
+#endif
+
+#define MAX_SYSCTL_TRY 5
+
+int
+getifaddrs(struct ifaddrs **pif)
+{
+ int icnt = 1;
+ int dcnt = 0;
+ int ncnt = 0;
+#ifdef NET_RT_IFLIST
+ int ntry = 0;
+ int mib[6];
+ size_t needed;
+ char *buf;
+ char *next;
+ struct ifaddrs *cif = 0;
+ char *p, *p0;
+ struct rt_msghdr *rtm;
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+ struct sockaddr_dl *dl;
+ struct sockaddr *sa;
+ struct ifaddrs *ifa, *ift;
+ u_short idx = 0;
+#else /* NET_RT_IFLIST */
+ char buf[1024];
+ int m, sock;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ struct ifreq *lifr;
+#endif /* NET_RT_IFLIST */
+ int i;
+ size_t len, alen;
+ char *data;
+ char *names;
+
+#ifdef NET_RT_IFLIST
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0; /* protocol */
+ mib[3] = 0; /* wildcard address family */
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0; /* no flags */
+ do {
+ /*
+ * We'll try to get addresses several times in case that
+ * the number of addresses is unexpectedly increased during
+ * the two sysctl calls. This should rarely happen, but we'll
+ * try to do our best for applications that assume success of
+ * this library (which should usually be the case).
+ * Portability note: since FreeBSD does not add margin of
+ * memory at the first sysctl, the possibility of failure on
+ * the second sysctl call is a bit higher.
+ */
+
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ return (-1);
+ if ((buf = malloc(needed)) == NULL)
+ return (-1);
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ free(buf);
+ return (-1);
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)(void *)rtm;
+ if (ifm->ifm_addrs & RTA_IFP) {
+ idx = ifm->ifm_index;
+ ++icnt;
+ dl = (struct sockaddr_dl *)(void *)(ifm + 1);
+ dcnt += SA_RLEN((struct sockaddr *)(void*)dl) +
+ ALIGNBYTES;
+#ifdef HAVE_IFM_DATA
+ dcnt += sizeof(ifm->ifm_data);
+#endif /* HAVE_IFM_DATA */
+ ncnt += dl->sdl_nlen + 1;
+ } else
+ idx = 0;
+ break;
+
+ case RTM_NEWADDR:
+ ifam = (struct ifa_msghdr *)(void *)rtm;
+ if (idx && ifam->ifam_index != idx)
+ abort(); /* this cannot happen */
+
+#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
+ if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
+ break;
+ p = (char *)(void *)(ifam + 1);
+ ++icnt;
+#ifdef HAVE_IFAM_DATA
+ dcnt += sizeof(ifam->ifam_data) + ALIGNBYTES;
+#endif /* HAVE_IFAM_DATA */
+ /* Scan to look for length of address */
+ alen = 0;
+ for (p0 = p, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ if (i == RTAX_IFA) {
+ alen = len;
+ break;
+ }
+ p += len;
+ }
+ for (p = p0, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ if (i == RTAX_NETMASK && SA_LEN(sa) == 0)
+ dcnt += alen;
+ else
+ dcnt += len;
+ p += len;
+ }
+ break;
+ }
+ }
+#else /* NET_RT_IFLIST */
+ ifc.ifc_buf = buf;
+ ifc.ifc_len = sizeof(buf);
+
+ if ((sock = _socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ return (-1);
+ i = _ioctl(sock, SIOCGIFCONF, (char *)&ifc);
+ _close(sock);
+ if (i < 0)
+ return (-1);
+
+ ifr = ifc.ifc_req;
+ lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
+
+ while (ifr < lifr) {
+ struct sockaddr *sa;
+
+ sa = &ifr->ifr_addr;
+ ++icnt;
+ dcnt += SA_RLEN(sa);
+ ncnt += sizeof(ifr->ifr_name) + 1;
+
+ if (SA_LEN(sa) < sizeof(*sa))
+ ifr = (struct ifreq *)(((char *)sa) + sizeof(*sa));
+ else
+ ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
+ }
+#endif /* NET_RT_IFLIST */
+
+ if (icnt + dcnt + ncnt == 1) {
+ *pif = NULL;
+ free(buf);
+ return (0);
+ }
+ data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
+ if (data == NULL) {
+ free(buf);
+ return(-1);
+ }
+
+ ifa = (struct ifaddrs *)(void *)data;
+ data += sizeof(struct ifaddrs) * icnt;
+ names = data + dcnt;
+
+ memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
+ ift = ifa;
+
+#ifdef NET_RT_IFLIST
+ idx = 0;
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)(void *)rtm;
+ if (ifm->ifm_addrs & RTA_IFP) {
+ idx = ifm->ifm_index;
+ dl = (struct sockaddr_dl *)(void *)(ifm + 1);
+
+ cif = ift;
+ ift->ifa_name = names;
+ ift->ifa_flags = (int)ifm->ifm_flags;
+ memcpy(names, dl->sdl_data,
+ (size_t)dl->sdl_nlen);
+ names[dl->sdl_nlen] = 0;
+ names += dl->sdl_nlen + 1;
+
+ ift->ifa_addr = (struct sockaddr *)(void *)data;
+ memcpy(data, dl,
+ (size_t)SA_LEN((struct sockaddr *)
+ (void *)dl));
+ data += SA_RLEN((struct sockaddr *)(void *)dl);
+
+#ifdef HAVE_IFM_DATA
+ /* ifm_data needs to be aligned */
+ ift->ifa_data = data = (void *)ALIGN(data);
+ memcpy(data, &ifm->ifm_data, sizeof(ifm->ifm_data));
+ data += sizeof(ifm->ifm_data);
+#else /* HAVE_IFM_DATA */
+ ift->ifa_data = NULL;
+#endif /* HAVE_IFM_DATA */
+
+ ift = (ift->ifa_next = ift + 1);
+ } else
+ idx = 0;
+ break;
+
+ case RTM_NEWADDR:
+ ifam = (struct ifa_msghdr *)(void *)rtm;
+ if (idx && ifam->ifam_index != idx)
+ abort(); /* this cannot happen */
+
+ if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
+ break;
+ ift->ifa_name = cif->ifa_name;
+ ift->ifa_flags = cif->ifa_flags;
+ ift->ifa_data = NULL;
+ p = (char *)(void *)(ifam + 1);
+ /* Scan to look for length of address */
+ alen = 0;
+ for (p0 = p, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ if (i == RTAX_IFA) {
+ alen = len;
+ break;
+ }
+ p += len;
+ }
+ for (p = p0, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ switch (i) {
+ case RTAX_IFA:
+ ift->ifa_addr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_NETMASK:
+ ift->ifa_netmask =
+ (struct sockaddr *)(void *)data;
+ if (SA_LEN(sa) == 0) {
+ memset(data, 0, alen);
+ data += alen;
+ break;
+ }
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_BRD:
+ ift->ifa_broadaddr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+ }
+ p += len;
+ }
+
+#ifdef HAVE_IFAM_DATA
+ /* ifam_data needs to be aligned */
+ ift->ifa_data = data = (void *)ALIGN(data);
+ memcpy(data, &ifam->ifam_data, sizeof(ifam->ifam_data));
+ data += sizeof(ifam->ifam_data);
+#endif /* HAVE_IFAM_DATA */
+
+ ift = (ift->ifa_next = ift + 1);
+ break;
+ }
+ }
+
+ free(buf);
+#else /* NET_RT_IFLIST */
+ ifr = ifc.ifc_req;
+ lifr = (struct ifreq *)&ifc.ifc_buf[ifc.ifc_len];
+
+ while (ifr < lifr) {
+ struct sockaddr *sa;
+
+ ift->ifa_name = names;
+ names[sizeof(ifr->ifr_name)] = 0;
+ strncpy(names, ifr->ifr_name, sizeof(ifr->ifr_name));
+ while (*names++)
+ ;
+
+ ift->ifa_addr = (struct sockaddr *)data;
+ sa = &ifr->ifr_addr;
+ memcpy(data, sa, SA_LEN(sa));
+ data += SA_RLEN(sa);
+
+ ifr = (struct ifreq *)(((char *)sa) + SA_LEN(sa));
+ ift = (ift->ifa_next = ift + 1);
+ }
+#endif /* NET_RT_IFLIST */
+ if (--ift >= ifa) {
+ ift->ifa_next = NULL;
+ *pif = ifa;
+ } else {
+ *pif = NULL;
+ free(ifa);
+ }
+ return (0);
+}
+
+void
+freeifaddrs(struct ifaddrs *ifp)
+{
+
+ free(ifp);
+}
diff --git a/freebsd/lib/libc/net/getifmaddrs.c b/freebsd/lib/libc/net/getifmaddrs.c
new file mode 100644
index 00000000..708c7ae2
--- /dev/null
+++ b/freebsd/lib/libc/net/getifmaddrs.c
@@ -0,0 +1,205 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2003 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.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bruce M. Simpson.
+ * 4. Neither the name of Bruce M. Simpson nor the names of other
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRUCE M. SIMPSON AND AFFILIATES
+ * ``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 BRUCE M. SIMPSON 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 "namespace.h"
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#define SALIGN (sizeof(long) - 1)
+#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \
+ (SALIGN + 1))
+#define MAX_SYSCTL_TRY 5
+#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA)
+
+int
+getifmaddrs(struct ifmaddrs **pif)
+{
+ int icnt = 1;
+ int dcnt = 0;
+ int ntry = 0;
+ size_t len;
+ size_t needed;
+ int mib[6];
+ int i;
+ char *buf;
+ char *data;
+ char *next;
+ char *p;
+ struct ifma_msghdr *ifmam;
+ struct ifmaddrs *ifa, *ift;
+ struct rt_msghdr *rtm;
+ struct sockaddr *sa;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0; /* protocol */
+ mib[3] = 0; /* wildcard address family */
+ mib[4] = NET_RT_IFMALIST;
+ mib[5] = 0; /* no flags */
+ do {
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ return (-1);
+ if ((buf = malloc(needed)) == NULL)
+ return (-1);
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ free(buf);
+ return (-1);
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_NEWMADDR:
+ ifmam = (struct ifma_msghdr *)(void *)rtm;
+ if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
+ break;
+ icnt++;
+ p = (char *)(ifmam + 1);
+ for (i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifmam->ifmam_addrs &
+ (1 << i)) == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ dcnt += len;
+ p += len;
+ }
+ break;
+ }
+ }
+
+ data = malloc(sizeof(struct ifmaddrs) * icnt + dcnt);
+ if (data == NULL) {
+ free(buf);
+ return (-1);
+ }
+
+ ifa = (struct ifmaddrs *)(void *)data;
+ data += sizeof(struct ifmaddrs) * icnt;
+
+ memset(ifa, 0, sizeof(struct ifmaddrs) * icnt);
+ ift = ifa;
+
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+
+ switch (rtm->rtm_type) {
+ case RTM_NEWMADDR:
+ ifmam = (struct ifma_msghdr *)(void *)rtm;
+ if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
+ break;
+
+ p = (char *)(ifmam + 1);
+ for (i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifmam->ifmam_addrs &
+ (1 << i)) == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ switch (i) {
+ case RTAX_GATEWAY:
+ ift->ifma_lladdr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_IFP:
+ ift->ifma_name =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_IFA:
+ ift->ifma_addr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ default:
+ data += len;
+ break;
+ }
+ p += len;
+ }
+ ift->ifma_next = ift + 1;
+ ift = ift->ifma_next;
+ break;
+ }
+ }
+
+ free(buf);
+
+ if (ift > ifa) {
+ ift--;
+ ift->ifma_next = NULL;
+ *pif = ifa;
+ } else {
+ *pif = NULL;
+ free(ifa);
+ }
+ return (0);
+}
+
+void
+freeifmaddrs(struct ifmaddrs *ifmp)
+{
+
+ free(ifmp);
+}
diff --git a/freebsd/lib/libc/net/getnameinfo.c b/freebsd/lib/libc/net/getnameinfo.c
new file mode 100644
index 00000000..4abd11ff
--- /dev/null
+++ b/freebsd/lib/libc/net/getnameinfo.c
@@ -0,0 +1,455 @@
+#include "port_before.h"
+
+/* $KAME: getnameinfo.c,v 1.61 2002/06/27 09:25:47 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2000 Ben Harris.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - RFC2553 says that we should raise error on short buffer. X/Open says
+ * we need to truncate the result. We obey RFC2553 (and X/Open should be
+ * modified). ipngwg rough consensus seems to follow RFC2553.
+ * - What is "local" in NI_FQDN?
+ * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
+ * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
+ * sin6_scope_id is filled - standardization status?
+ * XXX breaks backward compat for code that expects no scopeid.
+ * beware on merge.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stddef.h>
+#include <errno.h>
+
+static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *,
+ size_t, char *, size_t, int);
+#ifdef INET6
+static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
+ size_t, int);
+static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
+#endif
+static int getnameinfo_link(const struct sockaddr *, socklen_t, char *,
+ size_t, char *, size_t, int);
+static int hexname(const u_int8_t *, size_t, char *, size_t);
+
+int
+getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv, size_t servlen,
+ int flags)
+{
+
+ switch (sa->sa_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ return getnameinfo_inet(sa, salen, host, hostlen, serv,
+ servlen, flags);
+ case AF_LINK:
+ return getnameinfo_link(sa, salen, host, hostlen, serv,
+ servlen, flags);
+ default:
+ return EAI_FAMILY;
+ }
+}
+
+static const struct afd {
+ int a_af;
+ size_t a_addrlen;
+ socklen_t a_socklen;
+ int a_off;
+} afdl [] = {
+#ifdef INET6
+ {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
+#endif
+ {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0},
+};
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+static int
+getnameinfo_inet(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv, size_t servlen,
+ int flags)
+{
+ const struct afd *afd;
+ struct servent *sp;
+ struct hostent *hp;
+ u_short port;
+ int family, i;
+ const char *addr;
+ u_int32_t v4a;
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
+
+ if (sa == NULL)
+ return EAI_FAIL;
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return EAI_FAMILY;
+
+ found:
+ if (salen != afd->a_socklen)
+ return EAI_FAIL;
+
+ /* network byte order */
+ port = ((const struct sockinet *)sa)->si_port;
+ addr = (const char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /*
+ * do nothing in this case.
+ * in case you are wondering if "&&" is more correct than
+ * "||" here: rfc2553bis-03 says that serv == NULL OR
+ * servlen == 0 means that the caller does not want the result.
+ */
+ } else {
+ if (flags & NI_NUMERICSERV)
+ sp = NULL;
+ else {
+ sp = getservbyport(port,
+ (flags & NI_DGRAM) ? "udp" : "tcp");
+ }
+ if (sp) {
+ if (strlen(sp->s_name) + 1 > servlen)
+ return EAI_MEMORY;
+ strlcpy(serv, sp->s_name, servlen);
+ } else {
+ snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
+ if (strlen(numserv) + 1 > servlen)
+ return EAI_MEMORY;
+ strlcpy(serv, numserv, servlen);
+ }
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = (u_int32_t)
+ ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0)
+ flags |= NI_NUMERICHOST;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ {
+ const struct sockaddr_in6 *sin6;
+ sin6 = (const struct sockaddr_in6 *)sa;
+ switch (sin6->sin6_addr.s6_addr[0]) {
+ case 0x00:
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ ;
+ else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+ ;
+ else
+ flags |= NI_NUMERICHOST;
+ break;
+ default:
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ flags |= NI_NUMERICHOST;
+ }
+ else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+ flags |= NI_NUMERICHOST;
+ break;
+ }
+ }
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ /*
+ * do nothing in this case.
+ * in case you are wondering if "&&" is more correct than
+ * "||" here: rfc2553bis-03 says that host == NULL or
+ * hostlen == 0 means that the caller does not want the result.
+ */
+ } else if (flags & NI_NUMERICHOST) {
+ size_t numaddrlen;
+
+ /* NUMERICHOST and NAMEREQD conflicts with each other */
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+
+ switch(afd->a_af) {
+#ifdef INET6
+ case AF_INET6:
+ {
+ int error;
+
+ if ((error = ip6_parsenumeric(sa, addr, host,
+ hostlen, flags)) != 0)
+ return(error);
+ break;
+ }
+#endif
+ default:
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return EAI_SYSTEM;
+ numaddrlen = strlen(numaddr);
+ if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+ return EAI_MEMORY;
+ strlcpy(host, numaddr, hostlen);
+ break;
+ }
+ } else {
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+
+ if (hp) {
+#if 0
+ /*
+ * commented out, since "for local host" is not
+ * implemented here - see RFC2553 p30
+ */
+ if (flags & NI_NOFQDN) {
+ char *p;
+ p = strchr(hp->h_name, '.');
+ if (p)
+ *p = '\0';
+ }
+#endif
+ if (strlen(hp->h_name) + 1 > hostlen) {
+ freehostent(hp);
+ return EAI_MEMORY;
+ }
+ strlcpy(host, hp->h_name, hostlen);
+ freehostent(hp);
+ } else {
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+ switch(afd->a_af) {
+#ifdef INET6
+ case AF_INET6:
+ {
+ int error;
+
+ if ((error = ip6_parsenumeric(sa, addr, host,
+ hostlen,
+ flags)) != 0)
+ return(error);
+ break;
+ }
+#endif
+ default:
+ if (inet_ntop(afd->a_af, addr, host,
+ hostlen) == NULL)
+ return EAI_SYSTEM;
+ break;
+ }
+ }
+ }
+ return(0);
+}
+
+#ifdef INET6
+static int
+ip6_parsenumeric(const struct sockaddr *sa, const char *addr,
+ char *host, size_t hostlen, int flags)
+{
+ size_t numaddrlen;
+ char numaddr[512];
+
+ if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
+ return EAI_SYSTEM;
+
+ numaddrlen = strlen(numaddr);
+ if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+ return EAI_OVERFLOW;
+ strlcpy(host, numaddr, hostlen);
+
+ if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
+ char zonebuf[MAXHOSTNAMELEN];
+ int zonelen;
+
+ zonelen = ip6_sa2str(
+ (const struct sockaddr_in6 *)(const void *)sa,
+ zonebuf, sizeof(zonebuf), flags);
+ if (zonelen < 0)
+ return EAI_OVERFLOW;
+ if (zonelen + 1 + numaddrlen + 1 > hostlen)
+ return EAI_OVERFLOW;
+
+ /* construct <numeric-addr><delim><zoneid> */
+ memcpy(host + numaddrlen + 1, zonebuf,
+ (size_t)zonelen);
+ host[numaddrlen] = SCOPE_DELIMITER;
+ host[numaddrlen + 1 + zonelen] = '\0';
+ }
+
+ return 0;
+}
+
+/* ARGSUSED */
+static int
+ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
+{
+ unsigned int ifindex;
+ const struct in6_addr *a6;
+ int n;
+
+ ifindex = (unsigned int)sa6->sin6_scope_id;
+ a6 = &sa6->sin6_addr;
+
+#ifdef NI_NUMERICSCOPE
+ if ((flags & NI_NUMERICSCOPE) != 0) {
+ n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
+ if (n < 0 || n >= bufsiz)
+ return -1;
+ else
+ return n;
+ }
+#endif
+
+ /* if_indextoname() does not take buffer size. not a good api... */
+ if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
+ IN6_IS_ADDR_MC_NODELOCAL(a6)) && bufsiz >= IF_NAMESIZE) {
+ char *p = if_indextoname(ifindex, buf);
+ if (p) {
+ return(strlen(p));
+ }
+ }
+
+ /* last resort */
+ n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
+ if (n < 0 || (size_t)n >= bufsiz)
+ return -1;
+ else
+ return n;
+}
+#endif /* INET6 */
+
+/*
+ * getnameinfo_link():
+ * Format a link-layer address into a printable format, paying attention to
+ * the interface type.
+ */
+/* ARGSUSED */
+static int
+getnameinfo_link(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv, size_t servlen, int flags)
+{
+ const struct sockaddr_dl *sdl =
+ (const struct sockaddr_dl *)(const void *)sa;
+ int n;
+
+ if (serv != NULL && servlen > 0)
+ *serv = '\0';
+
+ if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) {
+ n = snprintf(host, hostlen, "link#%d", sdl->sdl_index);
+ if (n > hostlen) {
+ *host = '\0';
+ return EAI_MEMORY;
+ }
+ return 0;
+ }
+
+ switch (sdl->sdl_type) {
+ /*
+ * The following have zero-length addresses.
+ * IFT_ATM (net/if_atmsubr.c)
+ * IFT_FAITH (net/if_faith.c)
+ * IFT_GIF (net/if_gif.c)
+ * IFT_LOOP (net/if_loop.c)
+ * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c)
+ * IFT_SLIP (net/if_sl.c, net/if_strip.c)
+ * IFT_STF (net/if_stf.c)
+ * IFT_L2VLAN (net/if_vlan.c)
+ * IFT_BRIDGE (net/if_bridge.h>
+ */
+ /*
+ * The following use IPv4 addresses as link-layer addresses:
+ * IFT_OTHER (net/if_gre.c)
+ * IFT_OTHER (netinet/ip_ipip.c)
+ */
+ /* default below is believed correct for all these. */
+ case IFT_ARCNET:
+ case IFT_ETHER:
+ case IFT_FDDI:
+ case IFT_HIPPI:
+ case IFT_ISO88025:
+ default:
+ return hexname((u_int8_t *)LLADDR(sdl), (size_t)sdl->sdl_alen,
+ host, hostlen);
+ }
+}
+
+static int
+hexname(cp, len, host, hostlen)
+ const u_int8_t *cp;
+ char *host;
+ size_t len, hostlen;
+{
+ int i, n;
+ char *outp = host;
+
+ *outp = '\0';
+ for (i = 0; i < len; i++) {
+ n = snprintf(outp, hostlen, "%s%02x",
+ i ? ":" : "", cp[i]);
+ if (n < 0 || n >= hostlen) {
+ *host = '\0';
+ return EAI_MEMORY;
+ }
+ outp += n;
+ hostlen -= n;
+ }
+ return 0;
+}
diff --git a/freebsd/lib/libc/net/getnetbydns.c b/freebsd/lib/libc/net/getnetbydns.c
new file mode 100644
index 00000000..7dd23837
--- /dev/null
+++ b/freebsd/lib/libc/net/getnetbydns.c
@@ -0,0 +1,467 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+
+#include "netdb_private.h"
+#include "res_config.h"
+
+#define BYADDR 0
+#define BYNAME 1
+
+#define MAXPACKET (64*1024)
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+/*
+ * Reverse the order of first four dotted entries of in.
+ * Out must contain space for at least strlen(in) characters.
+ * The result does not include any leading 0s of in.
+ */
+static void
+ipreverse(char *in, char *out)
+{
+ char *pos[4];
+ int len[4];
+ char *p, *start;
+ int i = 0;
+ int leading = 1;
+
+ /* Fill-in element positions and lengths: pos[], len[]. */
+ start = p = in;
+ for (;;) {
+ if (*p == '.' || *p == '\0') {
+ /* Leading 0? */
+ if (leading && p - start == 1 && *start == '0')
+ len[i] = 0;
+ else {
+ len[i] = p - start;
+ leading = 0;
+ }
+ pos[i] = start;
+ start = p + 1;
+ i++;
+ }
+ if (i == 4)
+ break;
+ if (*p == 0) {
+ for (; i < 4; i++) {
+ pos[i] = p;
+ len[i] = 0;
+ }
+ break;
+ }
+ p++;
+ }
+
+ /* Copy the entries in reverse order */
+ p = out;
+ leading = 1;
+ for (i = 3; i >= 0; i--) {
+ memcpy(p, pos[i], len[i]);
+ if (len[i])
+ leading = 0;
+ p += len[i];
+ /* Need a . separator? */
+ if (!leading && i > 0 && len[i - 1])
+ *p++ = '.';
+ }
+ *p = '\0';
+}
+
+static int
+getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne,
+ struct netent_data *ned, res_state statp)
+{
+
+ HEADER *hp;
+ u_char *cp;
+ int n;
+ u_char *eom;
+ int type, class, ancount, qdcount, haveanswer;
+ char aux[MAXHOSTNAMELEN];
+ char ans[MAXHOSTNAMELEN];
+ char *in, *bp, *ep, **ap;
+
+ /*
+ * find first satisfactory answer
+ *
+ * answer --> +------------+ ( MESSAGE )
+ * | Header |
+ * +------------+
+ * | Question | the question for the name server
+ * +------------+
+ * | Answer | RRs answering the question
+ * +------------+
+ * | Authority | RRs pointing toward an authority
+ * | Additional | RRs holding additional information
+ * +------------+
+ */
+ eom = answer->buf + anslen;
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount); /* #/records in the answer section */
+ qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
+ bp = ned->netbuf;
+ ep = ned->netbuf + sizeof(ned->netbuf);
+ cp = answer->buf + HFIXEDSZ;
+ if (!qdcount) {
+ if (hp->aa)
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ else
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+ }
+ while (qdcount-- > 0)
+ cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+ ap = ned->net_aliases;
+ *ap = NULL;
+ ne->n_aliases = ned->net_aliases;
+ haveanswer = 0;
+ while (--ancount >= 0 && cp < eom) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !res_dnok(bp))
+ break;
+ cp += n;
+ ans[0] = '\0';
+ (void)strncpy(&ans[0], bp, sizeof(ans) - 1);
+ ans[sizeof(ans) - 1] = '\0';
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ cp += INT32SZ; /* TTL */
+ GETSHORT(n, cp);
+ if (class == C_IN && type == T_PTR) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !res_hnok(bp)) {
+ cp += n;
+ return (-1);
+ }
+ cp += n;
+ *ap++ = bp;
+ n = strlen(bp) + 1;
+ bp += n;
+ ne->n_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
+ haveanswer++;
+ }
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ switch (net_i) {
+ case BYADDR:
+ ne->n_name = *ne->n_aliases;
+ ne->n_net = 0L;
+ break;
+ case BYNAME:
+ in = *ne->n_aliases;
+ n = strlen(ans) + 1;
+ if (ep - bp < n) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ errno = ENOBUFS;
+ return (-1);
+ }
+ strlcpy(bp, ans, ep - bp);
+ ne->n_name = bp;
+ if (strlen(in) + 1 > sizeof(aux)) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ errno = ENOBUFS;
+ return (-1);
+ }
+ ipreverse(in, aux);
+ ne->n_net = inet_network(aux);
+ break;
+ }
+ ne->n_aliases++;
+ return (0);
+ }
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+}
+
+int
+_dns_getnetbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ uint32_t net;
+ int net_type;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ unsigned int netbr[4];
+ int nn, anslen, error;
+ querybuf *buf;
+ char qbuf[MAXDNAME];
+ uint32_t net2;
+ res_state statp;
+
+ net = va_arg(ap, uint32_t);
+ net_type = va_arg(ap, int);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ *((struct netent **)rval) = NULL;
+
+ if (net_type != AF_INET) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ for (nn = 4, net2 = net; net2; net2 >>= 8)
+ netbr[--nn] = net2 & 0xff;
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]);
+ break;
+ case 1: /* Class C */
+ sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1], netbr[0]);
+ break;
+ }
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ anslen = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf,
+ sizeof(*buf));
+ if (anslen < 0) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_nsearch failed\n");
+#endif
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ } else if (anslen > sizeof(*buf)) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_nsearch static buffer too small\n");
+#endif
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ error = getnetanswer(buf, anslen, BYADDR, &ne, ned, statp);
+ free(buf);
+ if (error == 0) {
+ /* Strip trailing zeros */
+ while ((net & 0xff) == 0 && net != 0)
+ net >>= 8;
+ ne.n_net = net;
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+ }
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+}
+
+int
+_dns_getnetbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *net;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ int anslen, error;
+ querybuf *buf;
+ char qbuf[MAXDNAME];
+ res_state statp;
+
+ net = va_arg(ap, const char *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ *((struct netent **)rval) = NULL;
+
+ strncpy(qbuf, net, sizeof(qbuf) - 1);
+ qbuf[sizeof(qbuf) - 1] = '\0';
+ anslen = res_nsearch(statp, qbuf, C_IN, T_PTR, (u_char *)buf,
+ sizeof(*buf));
+ if (anslen < 0) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_nsearch failed\n");
+#endif
+ return (NS_UNAVAIL);
+ } else if (anslen > sizeof(*buf)) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_search static buffer too small\n");
+#endif
+ return (NS_UNAVAIL);
+ }
+ error = getnetanswer(buf, anslen, BYNAME, &ne, ned, statp);
+ free(buf);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+}
+
+void
+_setnetdnsent(int stayopen)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1)
+ return;
+ if (stayopen)
+ statp->options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endnetdnsent()
+{
+ res_state statp;
+
+ statp = __res_state();
+ statp->options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_nclose(statp);
+}
diff --git a/freebsd/lib/libc/net/getnetbyht.c b/freebsd/lib/libc/net/getnetbyht.c
new file mode 100644
index 00000000..1076cf21
--- /dev/null
+++ b/freebsd/lib/libc/net/getnetbyht.c
@@ -0,0 +1,290 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * 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.
+ *
+ * from getnetent.c 1.1 (Coimbra) 93/06/02
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: getnetent.c,v 8.4 1997/06/01 20:34:37 vixie Exp";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include "netdb_private.h"
+
+void
+_setnethtent(int f, struct netent_data *ned)
+{
+
+ if (ned->netf == NULL)
+ ned->netf = fopen(_PATH_NETWORKS, "r");
+ else
+ rewind(ned->netf);
+ ned->stayopen |= f;
+}
+
+void
+_endnethtent(struct netent_data *ned)
+{
+
+ if (ned->netf) {
+ fclose(ned->netf);
+ ned->netf = NULL;
+ }
+ ned->stayopen = 0;
+}
+
+static int
+getnetent_p(struct netent *ne, struct netent_data *ned)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ int len;
+ char line[BUFSIZ + 1];
+
+ if (ned->netf == NULL &&
+ (ned->netf = fopen(_PATH_NETWORKS, "r")) == NULL)
+ return (-1);
+again:
+ p = fgets(line, sizeof line, ned->netf);
+ if (p == NULL)
+ return (-1);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ bp = ned->netbuf;
+ ep = ned->netbuf + sizeof ned->netbuf;
+ ne->n_name = bp;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ len = strlen(p) + 1;
+ if (ep - bp < len) {
+ RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, p, ep - bp);
+ bp += len;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ ne->n_net = inet_network(cp);
+ ne->n_addrtype = AF_INET;
+ q = ne->n_aliases = ned->net_aliases;
+ if (p != NULL) {
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q >= &ned->net_aliases[_MAXALIASES - 1])
+ break;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += len;
+ cp = p;
+ }
+ }
+ *q = NULL;
+ return (0);
+}
+
+int
+getnetent_r(struct netent *nptr, char *buffer, size_t buflen,
+ struct netent **result, int *h_errnop)
+{
+ struct netent_data *ned;
+ struct netent ne;
+ res_state statp;
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (getnetent_p(&ne, ned) != 0)
+ return (-1);
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return ((errno != 0) ? errno : -1);
+ }
+ *result = nptr;
+ return (0);
+}
+
+struct netent *
+getnetent(void)
+{
+ struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
+
+ if ((nd = __netdata_init()) == NULL)
+ return (NULL);
+ if (getnetent_r(&nd->net, nd->data, sizeof(nd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+int
+_ht_getnetbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *name;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ char **cp;
+ res_state statp;
+ int error;
+
+ name = va_arg(ap, const char *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ _setnethtent(ned->stayopen, ned);
+ while ((error = getnetent_p(&ne, ned)) == 0) {
+ if (strcasecmp(ne.n_name, name) == 0)
+ break;
+ for (cp = ne.n_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!ned->stayopen)
+ _endnethtent(ned);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+}
+
+int
+_ht_getnetbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ uint32_t net;
+ int type;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ res_state statp;
+ int error;
+
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ _setnethtent(ned->stayopen, ned);
+ while ((error = getnetent_p(&ne, ned)) == 0)
+ if (ne.n_addrtype == type && ne.n_net == net)
+ break;
+ if (!ned->stayopen)
+ _endnethtent(ned);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+}
diff --git a/freebsd/lib/libc/net/getnetbynis.c b/freebsd/lib/libc/net/getnetbynis.c
new file mode 100644
index 00000000..805bc9d1
--- /dev/null
+++ b/freebsd/lib/libc/net/getnetbynis.c
@@ -0,0 +1,261 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <arpa/nameser.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include "netdb_private.h"
+
+#ifdef YP
+static int
+_getnetbynis(const char *name, char *map, int af, struct netent *ne,
+ struct netent_data *ned)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ char *result;
+ int resultlen, len;
+ char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ if (ned->yp_domain == (char *)NULL)
+ if (yp_get_default_domain (&ned->yp_domain))
+ return (-1);
+
+ if (yp_match(ned->yp_domain, map, name, strlen(name), &result,
+ &resultlen))
+ return (-1);
+
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = index(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ bp = ned->netbuf;
+ ep = ned->netbuf + sizeof ned->netbuf;
+ len = strlen(result) + 1;
+ if (ep - bp < len) {
+ RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, result, ep - bp);
+ ne->n_name = bp;
+ bp += len;
+
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+
+ ne->n_net = inet_network(cp);
+ ne->n_addrtype = AF_INET;
+
+ q = ne->n_aliases = ned->net_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q > &ned->net_aliases[_MAXALIASES - 1])
+ break;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += len;
+ cp = p;
+ }
+ *q = NULL;
+ return (0);
+}
+#endif /* YP */
+
+int
+_nis_getnetbyname(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ const char *name;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ res_state statp;
+
+ name = va_arg(ap, const char *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ if (_getnetbynis(name, "networks.byname", AF_INET, &ne, ned) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+#else
+ return (NS_UNAVAIL);
+#endif
+
+}
+
+int
+_nis_getnetbyaddr(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ uint32_t addr;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ char *str, *cp;
+ uint32_t net2;
+ int nn;
+ unsigned int netbr[4];
+ char buf[MAXDNAME];
+ res_state statp;
+
+ addr = va_arg(ap, uint32_t);
+ af = va_arg(ap, int);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ if (af != AF_INET) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ errno = EAFNOSUPPORT;
+ return (NS_UNAVAIL);
+ }
+
+ for (nn = 4, net2 = addr; net2; net2 >>= 8) {
+ netbr[--nn] = net2 & 0xff;
+ }
+
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(buf, "%u", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(buf, "%u.%u", netbr[2], netbr[3]);
+ break;
+ case 1: /* Class C */
+ sprintf(buf, "%u.%u.%u", netbr[1], netbr[2], netbr[3]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(buf, "%u.%u.%u.%u", netbr[0], netbr[1],
+ netbr[2], netbr[3]);
+ break;
+ }
+
+ str = (char *)&buf;
+ cp = str + (strlen(str) - 2);
+
+ while(!strcmp(cp, ".0")) {
+ *cp = '\0';
+ cp = str + (strlen(str) - 2);
+ }
+
+ if (_getnetbynis(str, "networks.byaddr", af, &ne, ned) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+#else
+ return (NS_UNAVAIL);
+#endif /* YP */
+}
diff --git a/freebsd/lib/libc/net/getnetnamadr.c b/freebsd/lib/libc/net/getnetnamadr.c
new file mode 100644
index 00000000..7ae162c3
--- /dev/null
+++ b/freebsd/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,460 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * 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 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 "namespace.h"
+#include "reentrant.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+extern int _ht_getnetbyname(void *, void *, va_list);
+extern int _dns_getnetbyname(void *, void *, va_list);
+extern int _nis_getnetbyname(void *, void *, va_list);
+extern int _ht_getnetbyaddr(void *, void *, va_list);
+extern int _dns_getnetbyaddr(void *, void *, va_list);
+extern int _nis_getnetbyaddr(void *, void *, va_list);
+
+/* Network lookup order if nsswitch.conf is broken or nonexistant */
+static const ns_src default_src[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NSSRC_DNS, NS_SUCCESS },
+ { 0 }
+};
+
+NETDB_THREAD_ALLOC(netent_data)
+NETDB_THREAD_ALLOC(netdata)
+
+#ifdef NS_CACHING
+static int
+net_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ char *name;
+ uint32_t net;
+ int type;
+
+ size_t desired_size, size;
+ enum nss_lookup_type lookup_type;
+ int res = NS_UNAVAIL;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+
+ desired_size = sizeof(enum nss_lookup_type) +
+ sizeof(uint32_t) + sizeof(int);
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &net,
+ sizeof(uint32_t));
+ memcpy(buffer + sizeof(enum nss_lookup_type) + sizeof(uint32_t),
+ &type, sizeof(int));
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+
+static int
+net_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ uint32_t net;
+ int type;
+ struct netent *ne;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct netent new_ne;
+ size_t desired_size, size, aliases_size;
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ ne = va_arg(ap, struct netent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct netent) + sizeof(char *);
+ if (ne->n_name != NULL)
+ desired_size += strlen(ne->n_name) + 1;
+
+ if (ne->n_aliases != NULL) {
+ aliases_size = 0;
+ for (alias = ne->n_aliases; *alias; ++alias) {
+ desired_size += strlen(*alias) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES +
+ (aliases_size + 1) * sizeof(char *);
+ }
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_ne, ne, sizeof(struct netent));
+
+ *buffer_size = desired_size;
+ memset(buffer, 0, desired_size);
+ p = buffer + sizeof(struct netent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct netent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_ne.n_name != NULL) {
+ size = strlen(new_ne.n_name);
+ memcpy(p, new_ne.n_name, size);
+ new_ne.n_name = p;
+ p += size + 1;
+ }
+
+ if (new_ne.n_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_ne.n_aliases, sizeof(char *) * aliases_size);
+ new_ne.n_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (alias = new_ne.n_aliases; *alias; ++alias) {
+ size = strlen(*alias);
+ memcpy(p, *alias, size);
+ *alias = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_ne, sizeof(struct netent));
+ return (NS_SUCCESS);
+}
+
+static int
+net_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ uint32_t net;
+ int type;
+ struct netent *ne;
+ char *orig_buf;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ ne = va_arg(ap, struct netent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct netent) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(ne, buffer, sizeof(struct netent));
+ memcpy(&p, buffer + sizeof(struct netent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct netent) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct netent) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(ne->n_name, orig_buf, p, char *);
+ if (ne->n_aliases != NULL) {
+ NS_APPLY_OFFSET(ne->n_aliases, orig_buf, p, char **);
+
+ for (alias = ne->n_aliases; *alias; ++alias)
+ NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct netent **)retval) = ne;
+
+ return (NS_SUCCESS);
+}
+#endif /* NS_CACHING */
+
+static void
+netent_data_free(void *ptr)
+{
+ struct netent_data *ned = ptr;
+
+ if (ned == NULL)
+ return;
+ ned->stayopen = 0;
+ _endnethtent(ned);
+ free(ned);
+}
+
+static void
+netdata_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen)
+{
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; ne->n_aliases[i]; i++, numptr++) {
+ len += strlen(ne->n_aliases[i]) + 1;
+ }
+ len += strlen(ne->n_name) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy net value and type */
+ nptr->n_addrtype = ne->n_addrtype;
+ nptr->n_net = ne->n_net;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(ne->n_name) + 1;
+ strcpy(cp, ne->n_name);
+ nptr->n_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ nptr->n_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; ne->n_aliases[i]; i++) {
+ n = strlen(ne->n_aliases[i]) + 1;
+ strcpy(cp, ne->n_aliases[i]);
+ nptr->n_aliases[i] = cp;
+ cp += n;
+ }
+ nptr->n_aliases[i] = NULL;
+
+ return (0);
+}
+
+int
+getnetbyname_r(const char *name, struct netent *ne, char *buffer,
+ size_t buflen, struct netent **result, int *h_errorp)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ networks, (void *)nss_lt_name,
+ net_id_func, net_marshal_func, net_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_getnetbyname, NULL)
+ { NSSRC_DNS, _dns_getnetbyname, NULL },
+ NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+ int rval, ret_errno = 0;
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
+ "getnetbyname_r", default_src, name, ne, buffer, buflen,
+ &ret_errno, h_errorp);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+int
+getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer,
+ size_t buflen, struct netent **result, int *h_errorp)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ networks, (void *)nss_lt_id,
+ net_id_func, net_marshal_func, net_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_getnetbyaddr, NULL)
+ { NSSRC_DNS, _dns_getnetbyaddr, NULL },
+ NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+ int rval, ret_errno = 0;
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
+ "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen,
+ &ret_errno, h_errorp);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+struct netent *
+getnetbyname(const char *name)
+{
+ struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
+
+ if ((nd = __netdata_init()) == NULL)
+ return (NULL);
+ if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+struct netent *
+getnetbyaddr(uint32_t addr, int af)
+{
+ struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
+
+ if ((nd = __netdata_init()) == NULL)
+ return (NULL);
+ if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data),
+ &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+void
+setnetent(int stayopen)
+{
+ struct netent_data *ned;
+
+ if ((ned = __netent_data_init()) == NULL)
+ return;
+ _setnethtent(stayopen, ned);
+ _setnetdnsent(stayopen);
+}
+
+void
+endnetent(void)
+{
+ struct netent_data *ned;
+
+ if ((ned = __netent_data_init()) == NULL)
+ return;
+ _endnethtent(ned);
+ _endnetdnsent();
+}
diff --git a/freebsd/lib/libc/net/getproto.c b/freebsd/lib/libc/net/getproto.c
new file mode 100644
index 00000000..a679db6d
--- /dev/null
+++ b/freebsd/lib/libc/net/getproto.c
@@ -0,0 +1,145 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getproto.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+#ifdef NS_CACHING
+extern int __proto_id_func(char *, size_t *, va_list, void *);
+extern int __proto_marshal_func(char *, size_t *, void *, va_list, void *);
+extern int __proto_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+files_getprotobynumber(void *retval, void *mdata, va_list ap)
+{
+ struct protoent pe;
+ struct protoent_data *ped;
+ int error;
+
+ int number;
+ struct protoent *pptr;
+ char *buffer;
+ size_t buflen;
+ int *errnop;
+
+ number = va_arg(ap, int);
+ pptr = va_arg(ap, struct protoent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ if ((ped = __protoent_data_init()) == NULL) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ __setprotoent_p(ped->stayopen, ped);
+ while ((error = __getprotoent_p(&pe, ped)) == 0)
+ if (pe.p_proto == number)
+ break;
+ if (!ped->stayopen)
+ __endprotoent_p(ped);
+ if (error != 0) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ return (NS_RETURN);
+ }
+
+ *((struct protoent **)retval) = pptr;
+ return (NS_SUCCESS);
+}
+
+int
+getprotobynumber_r(int proto, struct protoent *pptr, char *buffer,
+ size_t buflen, struct protoent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_id,
+ __proto_id_func, __proto_marshal_func, __proto_unmarshal_func);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_getprotobynumber, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotobynumber_r",
+ defaultsrc, proto, pptr, buffer, buflen, &ret_errno);
+
+ if (rv != NS_SUCCESS) {
+ errno = ret_errno;
+ return (ret_errno);
+ }
+ return (0);
+}
+
+struct protoent *
+getprotobynumber(int proto)
+{
+ struct protodata *pd;
+ struct protoent *rval;
+
+ if ((pd = __protodata_init()) == NULL)
+ return (NULL);
+ if (getprotobynumber_r(proto, &pd->proto, pd->data, sizeof(pd->data),
+ &rval) != 0)
+ return (NULL);
+ return (rval);
+}
diff --git a/freebsd/lib/libc/net/getprotoent.c b/freebsd/lib/libc/net/getprotoent.c
new file mode 100644
index 00000000..c817cb5b
--- /dev/null
+++ b/freebsd/lib/libc/net/getprotoent.c
@@ -0,0 +1,556 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+NETDB_THREAD_ALLOC(protoent_data)
+NETDB_THREAD_ALLOC(protodata)
+
+static void
+protoent_data_clear(struct protoent_data *ped)
+{
+ if (ped->fp) {
+ fclose(ped->fp);
+ ped->fp = NULL;
+ }
+}
+
+static void
+protoent_data_free(void *ptr)
+{
+ struct protoent_data *ped = ptr;
+
+ protoent_data_clear(ped);
+ free(ped);
+}
+
+static void
+protodata_free(void *ptr)
+{
+ free(ptr);
+}
+
+#ifdef NS_CACHING
+int
+__proto_id_func(char *buffer, size_t *buffer_size, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ int proto;
+
+ size_t desired_size, size;
+ enum nss_lookup_type lookup_type;
+ int res = NS_UNAVAIL;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ proto = va_arg(ap, int);
+
+ desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &proto,
+ sizeof(int));
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+
+int
+__proto_marshal_func(char *buffer, size_t *buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ char *name;
+ int num;
+ struct protoent *proto;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct protoent new_proto;
+ size_t desired_size, size, aliases_size;
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ num = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ proto = va_arg(ap, struct protoent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct protoent) + sizeof(char *);
+ if (proto->p_name != NULL)
+ desired_size += strlen(proto->p_name) + 1;
+
+ if (proto->p_aliases != NULL) {
+ aliases_size = 0;
+ for (alias = proto->p_aliases; *alias; ++alias) {
+ desired_size += strlen(*alias) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES + (aliases_size + 1) *
+ sizeof(char *);
+ }
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_proto, proto, sizeof(struct protoent));
+
+ *buffer_size = desired_size;
+ memset(buffer, 0, desired_size);
+ p = buffer + sizeof(struct protoent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct protoent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_proto.p_name != NULL) {
+ size = strlen(new_proto.p_name);
+ memcpy(p, new_proto.p_name, size);
+ new_proto.p_name = p;
+ p += size + 1;
+ }
+
+ if (new_proto.p_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_proto.p_aliases, sizeof(char *) * aliases_size);
+ new_proto.p_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (alias = new_proto.p_aliases; *alias; ++alias) {
+ size = strlen(*alias);
+ memcpy(p, *alias, size);
+ *alias = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_proto, sizeof(struct protoent));
+ return (NS_SUCCESS);
+}
+
+int
+__proto_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ char *name;
+ int num;
+ struct protoent *proto;
+ char *orig_buf;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ num = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ proto = va_arg(ap, struct protoent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct protoent) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(proto, buffer, sizeof(struct protoent));
+ memcpy(&p, buffer + sizeof(struct protoent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct protoent) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct protoent) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(proto->p_name, orig_buf, p, char *);
+ if (proto->p_aliases != NULL) {
+ NS_APPLY_OFFSET(proto->p_aliases, orig_buf, p, char **);
+
+ for (alias = proto->p_aliases; *alias; ++alias)
+ NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct protoent **)retval) = proto;
+
+ return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(protocols);
+#endif /* NS_CACHING */
+
+int
+__copy_protoent(struct protoent *pe, struct protoent *pptr, char *buf,
+ size_t buflen)
+{
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; pe->p_aliases[i]; i++, numptr++) {
+ len += strlen(pe->p_aliases[i]) + 1;
+ }
+ len += strlen(pe->p_name) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy protocol value*/
+ pptr->p_proto = pe->p_proto;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(pe->p_name) + 1;
+ strcpy(cp, pe->p_name);
+ pptr->p_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ pptr->p_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; pe->p_aliases[i]; i++) {
+ n = strlen(pe->p_aliases[i]) + 1;
+ strcpy(cp, pe->p_aliases[i]);
+ pptr->p_aliases[i] = cp;
+ cp += n;
+ }
+ pptr->p_aliases[i] = NULL;
+
+ return (0);
+}
+
+void
+__setprotoent_p(int f, struct protoent_data *ped)
+{
+ if (ped->fp == NULL)
+ ped->fp = fopen(_PATH_PROTOCOLS, "r");
+ else
+ rewind(ped->fp);
+ ped->stayopen |= f;
+}
+
+void
+__endprotoent_p(struct protoent_data *ped)
+{
+ if (ped->fp) {
+ fclose(ped->fp);
+ ped->fp = NULL;
+ }
+ ped->stayopen = 0;
+}
+
+int
+__getprotoent_p(struct protoent *pe, struct protoent_data *ped)
+{
+ char *p;
+ char *cp, **q, *endp;
+ long l;
+
+ if (ped->fp == NULL && (ped->fp = fopen(_PATH_PROTOCOLS, "r")) == NULL)
+ return (-1);
+again:
+ if ((p = fgets(ped->line, sizeof ped->line, ped->fp)) == NULL)
+ return (-1);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ pe->p_name = p;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ l = strtol(cp, &endp, 10);
+ if (endp == cp || *endp != '\0' || l < 0 || l > USHRT_MAX)
+ goto again;
+ pe->p_proto = l;
+ q = pe->p_aliases = ped->aliases;
+ if (p != NULL) {
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &ped->aliases[_MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+ return (0);
+}
+
+static int
+files_getprotoent_r(void *retval, void *mdata, va_list ap)
+{
+ struct protoent pe;
+ struct protoent_data *ped;
+
+ struct protoent *pptr;
+ char *buffer;
+ size_t buflen;
+ int *errnop;
+
+ pptr = va_arg(ap, struct protoent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ if ((ped = __protoent_data_init()) == NULL) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (__getprotoent_p(&pe, ped) != 0) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ return (NS_RETURN);
+ }
+
+ *((struct protoent **)retval) = pptr;
+ return (NS_SUCCESS);
+}
+
+static int
+files_setprotoent(void *retval, void *mdata, va_list ap)
+{
+ struct protoent_data *ped;
+ int f;
+
+ f = va_arg(ap, int);
+ if ((ped = __protoent_data_init()) == NULL)
+ return (NS_UNAVAIL);
+
+ __setprotoent_p(f, ped);
+ return (NS_UNAVAIL);
+}
+
+static int
+files_endprotoent(void *retval, void *mdata, va_list ap)
+{
+ struct protoent_data *ped;
+
+ if ((ped = __protoent_data_init()) == NULL)
+ return (NS_UNAVAIL);
+
+ __endprotoent_p(ped);
+ return (NS_UNAVAIL);
+}
+
+int
+getprotoent_r(struct protoent *pptr, char *buffer, size_t buflen,
+ struct protoent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_all,
+ __proto_marshal_func, __proto_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_getprotoent_r, (void *)nss_lt_all },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotoent_r",
+ defaultsrc, pptr, buffer, buflen, &ret_errno);
+
+ if (rv != NS_SUCCESS) {
+ errno = ret_errno;
+ return (ret_errno);
+ }
+ return (0);
+}
+
+void
+setprotoent(int stayopen)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setprotoent, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "setprotoent", defaultsrc,
+ stayopen);
+}
+
+void
+endprotoent(void)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_endprotoent, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "endprotoent", defaultsrc);
+}
+
+struct protoent *
+getprotoent(void)
+{
+ struct protodata *pd;
+ struct protoent *rval;
+
+ if ((pd = __protodata_init()) == NULL)
+ return (NULL);
+ if (getprotoent_r(&pd->proto, pd->data, sizeof(pd->data), &rval) != 0)
+ return (NULL);
+ return (rval);
+}
diff --git a/freebsd/lib/libc/net/getprotoname.c b/freebsd/lib/libc/net/getprotoname.c
new file mode 100644
index 00000000..4199b213
--- /dev/null
+++ b/freebsd/lib/libc/net/getprotoname.c
@@ -0,0 +1,153 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include <string.h>
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+#ifdef NS_CACHING
+extern int __proto_id_func(char *, size_t *, va_list, void *);
+extern int __proto_marshal_func(char *, size_t *, void *, va_list, void *);
+extern int __proto_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+files_getprotobyname(void *retval, void *mdata, va_list ap)
+{
+ struct protoent pe;
+ struct protoent_data *ped;
+ char **cp;
+ int error;
+
+ char *name;
+ struct protoent *pptr;
+ char *buffer;
+ size_t buflen;
+ int *errnop;
+
+ name = va_arg(ap, char *);
+ pptr = va_arg(ap, struct protoent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+
+ if ((ped = __protoent_data_init()) == NULL) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ __setprotoent_p(ped->stayopen, ped);
+ while ((error = __getprotoent_p(&pe, ped)) == 0) {
+ if (strcmp(pe.p_name, name) == 0)
+ break;
+ for (cp = pe.p_aliases; *cp != 0; cp++)
+ if (strcmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!ped->stayopen)
+ __endprotoent_p(ped);
+ if (error != 0) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ return (NS_RETURN);
+ }
+
+ *((struct protoent **)retval) = pptr;
+ return (NS_SUCCESS);
+}
+
+
+int
+getprotobyname_r(const char *name, struct protoent *pptr, char *buffer,
+ size_t buflen, struct protoent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_name,
+ __proto_id_func, __proto_marshal_func, __proto_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_getprotobyname, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotobyname_r",
+ defaultsrc, name, pptr, buffer, buflen, &ret_errno);
+
+ if (rv != NS_SUCCESS) {
+ errno = ret_errno;
+ return (ret_errno);
+ }
+ return (0);
+}
+
+struct protoent *
+getprotobyname(const char *name)
+{
+ struct protodata *pd;
+ struct protoent *rval;
+
+ if ((pd = __protodata_init()) == NULL)
+ return (NULL);
+ if (getprotobyname_r(name, &pd->proto, pd->data, sizeof(pd->data),
+ &rval) != 0)
+ return (NULL);
+ return (rval);
+}
diff --git a/freebsd/lib/libc/net/getservent.c b/freebsd/lib/libc/net/getservent.c
new file mode 100644
index 00000000..65ffb2cb
--- /dev/null
+++ b/freebsd/lib/libc/net/getservent.c
@@ -0,0 +1,1375 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1983, 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+enum constants
+{
+ SETSERVENT = 1,
+ ENDSERVENT = 2,
+ SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
+ SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
+};
+
+struct servent_mdata
+{
+ enum nss_lookup_type how;
+ int compat_mode;
+};
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_COMPAT, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+static int servent_unpack(char *, struct servent *, char **, size_t, int *);
+
+/* files backend declarations */
+struct files_state
+{
+ FILE *fp;
+ int stayopen;
+
+ int compat_mode_active;
+};
+static void files_endstate(void *);
+NSS_TLS_HANDLING(files);
+
+static int files_servent(void *, void *, va_list);
+static int files_setservent(void *, void *, va_list);
+
+/* db backend declarations */
+struct db_state
+{
+ DB *db;
+ int stayopen;
+ int keynum;
+};
+static void db_endstate(void *);
+NSS_TLS_HANDLING(db);
+
+static int db_servent(void *, void *, va_list);
+static int db_setservent(void *, void *, va_list);
+
+#ifdef YP
+/* nis backend declarations */
+static int nis_servent(void *, void *, va_list);
+static int nis_setservent(void *, void *, va_list);
+
+struct nis_state
+{
+ int yp_stepping;
+ char yp_domain[MAXHOSTNAMELEN];
+ char *yp_key;
+ int yp_keylen;
+};
+static void nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+
+static int nis_servent(void *, void *, va_list);
+static int nis_setservent(void *, void *, va_list);
+#endif
+
+/* compat backend declarations */
+static int compat_setservent(void *, void *, va_list);
+
+/* get** wrappers for get**_r functions declarations */
+struct servent_state {
+ struct servent serv;
+ char *buffer;
+ size_t bufsize;
+};
+static void servent_endstate(void *);
+NSS_TLS_HANDLING(servent);
+
+struct key {
+ const char *proto;
+ union {
+ const char *name;
+ int port;
+ };
+};
+
+static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t,
+ struct servent **);
+static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t,
+ struct servent **);
+static int wrap_getservent_r(struct key, struct servent *, char *, size_t,
+ struct servent **);
+static struct servent *getserv(int (*fn)(struct key, struct servent *, char *,
+ size_t, struct servent **), struct key);
+
+#ifdef NS_CACHING
+static int serv_id_func(char *, size_t *, va_list, void *);
+static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
+static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+servent_unpack(char *p, struct servent *serv, char **aliases,
+ size_t aliases_size, int *errnop)
+{
+ char *cp, **q, *endp;
+ long l;
+
+ if (*p == '#')
+ return -1;
+
+ memset(serv, 0, sizeof(struct servent));
+
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ serv->s_name = p;
+
+ p = strpbrk(p, " \t");
+ if (p == NULL)
+ return -1;
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ cp = strpbrk(p, ",/");
+ if (cp == NULL)
+ return -1;
+
+ *cp++ = '\0';
+ l = strtol(p, &endp, 10);
+ if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
+ return -1;
+ serv->s_port = htons((in_port_t)l);
+ serv->s_proto = cp;
+
+ q = serv->s_aliases = aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &aliases[aliases_size - 1]) {
+ *q++ = cp;
+ } else {
+ *q = NULL;
+ *errnop = ERANGE;
+ return -1;
+ }
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+
+ return 0;
+}
+
+static int
+parse_result(struct servent *serv, char *buffer, size_t bufsize,
+ char *resultbuf, size_t resultbuflen, int *errnop)
+{
+ char **aliases;
+ int aliases_size;
+
+ if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) {
+ *errnop = ERANGE;
+ return (NS_RETURN);
+ }
+ aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]);
+ aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *);
+ if (aliases_size < 1) {
+ *errnop = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(buffer, resultbuf, resultbuflen);
+ buffer[resultbuflen] = '\0';
+
+ if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0)
+ return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN);
+ return (NS_SUCCESS);
+}
+
+/* files backend implementation */
+static void
+files_endstate(void *p)
+{
+ FILE * f;
+
+ if (p == NULL)
+ return;
+
+ f = ((struct files_state *)p)->fp;
+ if (f != NULL)
+ fclose(f);
+
+ free(p);
+}
+
+/*
+ * compat structures. compat and files sources functionalities are almost
+ * equal, so they all are managed by files_servent function
+ */
+static int
+files_servent(void *retval, void *mdata, va_list ap)
+{
+ static const ns_src compat_src[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab compat_dtab[] = {
+ { NSSRC_DB, db_servent,
+ (void *)((struct servent_mdata *)mdata)->how },
+#ifdef YP
+ { NSSRC_NIS, nis_servent,
+ (void *)((struct servent_mdata *)mdata)->how },
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ struct files_state *st;
+ int rv;
+ int stayopen;
+
+ struct servent_mdata *serv_mdata;
+ char *name;
+ char *proto;
+ int port;
+
+ struct servent *serv;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ size_t linesize;
+ char *line;
+ char **cp;
+
+ name = NULL;
+ proto = NULL;
+ serv_mdata = (struct servent_mdata *)mdata;
+ switch (serv_mdata->how) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return NS_NOTFOUND;
+ };
+
+ serv = va_arg(ap, struct servent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap,int *);
+
+ *errnop = files_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (st->fp == NULL)
+ st->compat_mode_active = 0;
+
+ if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "r")) == NULL) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+
+ if (serv_mdata->how == nss_lt_all)
+ stayopen = 1;
+ else {
+ rewind(st->fp);
+ stayopen = st->stayopen;
+ }
+
+ rv = NS_NOTFOUND;
+ do {
+ if (!st->compat_mode_active) {
+ if ((line = fgetln(st->fp, &linesize)) == NULL) {
+ *errnop = errno;
+ rv = NS_RETURN;
+ break;
+ }
+
+ if (*line=='+' && serv_mdata->compat_mode != 0)
+ st->compat_mode_active = 1;
+ }
+
+ if (st->compat_mode_active != 0) {
+ switch (serv_mdata->how) {
+ case nss_lt_name:
+ rv = nsdispatch(retval, compat_dtab,
+ NSDB_SERVICES_COMPAT, "getservbyname_r",
+ compat_src, name, proto, serv, buffer,
+ bufsize, errnop);
+ break;
+ case nss_lt_id:
+ rv = nsdispatch(retval, compat_dtab,
+ NSDB_SERVICES_COMPAT, "getservbyport_r",
+ compat_src, port, proto, serv, buffer,
+ bufsize, errnop);
+ break;
+ case nss_lt_all:
+ rv = nsdispatch(retval, compat_dtab,
+ NSDB_SERVICES_COMPAT, "getservent_r",
+ compat_src, serv, buffer, bufsize, errnop);
+ break;
+ }
+
+ if (!(rv & NS_TERMINATE) ||
+ serv_mdata->how != nss_lt_all)
+ st->compat_mode_active = 0;
+
+ continue;
+ }
+
+ rv = parse_result(serv, buffer, bufsize, line, linesize,
+ errnop);
+ if (rv == NS_NOTFOUND)
+ continue;
+ if (rv == NS_RETURN)
+ break;
+
+ rv = NS_NOTFOUND;
+ switch (serv_mdata->how) {
+ case nss_lt_name:
+ if (strcmp(name, serv->s_name) == 0)
+ goto gotname;
+ for (cp = serv->s_aliases; *cp; cp++)
+ if (strcmp(name, *cp) == 0)
+ goto gotname;
+
+ continue;
+ gotname:
+ if (proto == 0 || strcmp(serv->s_proto, proto) == 0)
+ rv = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ if (port != serv->s_port)
+ continue;
+
+ if (proto == 0 || strcmp(serv->s_proto, proto) == 0)
+ rv = NS_SUCCESS;
+ break;
+ case nss_lt_all:
+ rv = NS_SUCCESS;
+ break;
+ }
+
+ } while (!(rv & NS_TERMINATE));
+
+ if (!stayopen && st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+
+ if ((rv == NS_SUCCESS) && (retval != NULL))
+ *(struct servent **)retval=serv;
+
+ return (rv);
+}
+
+static int
+files_setservent(void *retval, void *mdata, va_list ap)
+{
+ struct files_state *st;
+ int rv;
+ int f;
+
+ rv = files_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ f = va_arg(ap,int);
+ if (st->fp == NULL)
+ st->fp = fopen(_PATH_SERVICES, "r");
+ else
+ rewind(st->fp);
+ st->stayopen |= f;
+ break;
+ case ENDSERVENT:
+ if (st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+ st->stayopen = 0;
+ break;
+ default:
+ break;
+ };
+
+ st->compat_mode_active = 0;
+ return (NS_UNAVAIL);
+}
+
+/* db backend implementation */
+static void
+db_endstate(void *p)
+{
+ DB *db;
+
+ if (p == NULL)
+ return;
+
+ db = ((struct db_state *)p)->db;
+ if (db != NULL)
+ db->close(db);
+
+ free(p);
+}
+
+static int
+db_servent(void *retval, void *mdata, va_list ap)
+{
+ char buf[BUFSIZ];
+ DBT key, data, *result;
+ DB *db;
+
+ struct db_state *st;
+ int rv;
+ int stayopen;
+
+ enum nss_lookup_type how;
+ char *name;
+ char *proto;
+ int port;
+
+ struct servent *serv;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ name = NULL;
+ proto = NULL;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return NS_NOTFOUND;
+ };
+
+ serv = va_arg(ap, struct servent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap,int *);
+
+ *errnop = db_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (how == nss_lt_all && st->keynum < 0)
+ return (NS_NOTFOUND);
+
+ if (st->db == NULL) {
+ st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
+ if (st->db == NULL) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+
+ stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
+ db = st->db;
+
+ do {
+ switch (how) {
+ case nss_lt_name:
+ key.data = buf;
+ if (proto == NULL)
+ key.size = snprintf(buf, sizeof(buf),
+ "\376%s", name);
+ else
+ key.size = snprintf(buf, sizeof(buf),
+ "\376%s/%s", name, proto);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0 ||
+ db->get(db, &data, &key, 0) != 0) {
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ result = &key;
+ break;
+ case nss_lt_id:
+ key.data = buf;
+ port = htons(port);
+ if (proto == NULL)
+ key.size = snprintf(buf, sizeof(buf),
+ "\377%d", port);
+ else
+ key.size = snprintf(buf, sizeof(buf),
+ "\377%d/%s", port, proto);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0 ||
+ db->get(db, &data, &key, 0) != 0) {
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ result = &key;
+ break;
+ case nss_lt_all:
+ key.data = buf;
+ key.size = snprintf(buf, sizeof(buf), "%d",
+ st->keynum++);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0) {
+ st->keynum = -1;
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ result = &data;
+ break;
+ }
+
+ rv = parse_result(serv, buffer, bufsize, result->data,
+ result->size - 1, errnop);
+
+ } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
+
+db_fin:
+ if (!stayopen && st->db != NULL) {
+ db->close(db);
+ st->db = NULL;
+ }
+
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct servent **)retval = serv;
+
+ return (rv);
+}
+
+static int
+db_setservent(void *retval, void *mdata, va_list ap)
+{
+ DB *db;
+ struct db_state *st;
+ int rv;
+ int f;
+
+ rv = db_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ f = va_arg(ap, int);
+ st->stayopen |= f;
+ st->keynum = 0;
+ break;
+ case ENDSERVENT:
+ db = st->db;
+ if (db != NULL) {
+ db->close(db);
+ st->db = NULL;
+ }
+ st->stayopen = 0;
+ break;
+ default:
+ break;
+ };
+
+ return (NS_UNAVAIL);
+}
+
+/* nis backend implementation */
+#ifdef YP
+static void
+nis_endstate(void *p)
+{
+ if (p == NULL)
+ return;
+
+ free(((struct nis_state *)p)->yp_key);
+ free(p);
+}
+
+static int
+nis_servent(void *retval, void *mdata, va_list ap)
+{
+ char *resultbuf, *lastkey;
+ int resultbuflen;
+ char buf[YPMAXRECORD + 2];
+
+ struct nis_state *st;
+ int rv;
+
+ enum nss_lookup_type how;
+ char *name;
+ char *proto;
+ int port;
+
+ struct servent *serv;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ name = NULL;
+ proto = NULL;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return NS_NOTFOUND;
+ };
+
+ serv = va_arg(ap, struct servent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ *errnop = nis_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (st->yp_domain[0] == '\0') {
+ if (getdomainname(st->yp_domain, sizeof st->yp_domain)) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+
+ do {
+ switch (how) {
+ case nss_lt_name:
+ snprintf(buf, sizeof(buf), "%s/%s", name, proto);
+ if (yp_match(st->yp_domain, "services.byname", buf,
+ strlen(buf), &resultbuf, &resultbuflen)) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ break;
+ case nss_lt_id:
+ snprintf(buf, sizeof(buf), "%d/%s", ntohs(port),
+ proto);
+
+ /*
+ * We have to be a little flexible
+ * here. Ideally you're supposed to have both
+ * a services.byname and a services.byport
+ * map, but some systems have only
+ * services.byname. FreeBSD cheats a little by
+ * putting the services.byport information in
+ * the same map as services.byname so that
+ * either case will work. We allow for both
+ * possibilities here: if there is no
+ * services.byport map, we try services.byname
+ * instead.
+ */
+ rv = yp_match(st->yp_domain, "services.byport", buf,
+ strlen(buf), &resultbuf, &resultbuflen);
+ if (rv) {
+ if (rv == YPERR_MAP) {
+ if (yp_match(st->yp_domain,
+ "services.byname", buf,
+ strlen(buf), &resultbuf,
+ &resultbuflen)) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ } else {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ }
+
+ break;
+ case nss_lt_all:
+ if (!st->yp_stepping) {
+ free(st->yp_key);
+ rv = yp_first(st->yp_domain, "services.byname",
+ &st->yp_key, &st->yp_keylen, &resultbuf,
+ &resultbuflen);
+ if (rv) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ st->yp_stepping = 1;
+ } else {
+ lastkey = st->yp_key;
+ rv = yp_next(st->yp_domain, "services.byname",
+ st->yp_key, st->yp_keylen, &st->yp_key,
+ &st->yp_keylen, &resultbuf, &resultbuflen);
+ free(lastkey);
+ if (rv) {
+ st->yp_stepping = 0;
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ }
+ break;
+ };
+
+ rv = parse_result(serv, buffer, bufsize, resultbuf,
+ resultbuflen, errnop);
+ free(resultbuf);
+
+ } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
+
+fin:
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct servent **)retval = serv;
+
+ return (rv);
+}
+
+static int
+nis_setservent(void *result, void *mdata, va_list ap)
+{
+ struct nis_state *st;
+ int rv;
+
+ rv = nis_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ case ENDSERVENT:
+ free(st->yp_key);
+ st->yp_key = NULL;
+ st->yp_stepping = 0;
+ break;
+ default:
+ break;
+ };
+
+ return (NS_UNAVAIL);
+}
+#endif
+
+/* compat backend implementation */
+static int
+compat_setservent(void *retval, void *mdata, va_list ap)
+{
+ static const ns_src compat_src[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab compat_dtab[] = {
+ { NSSRC_DB, db_setservent, mdata },
+#ifdef YP
+ { NSSRC_NIS, nis_setservent, mdata },
+#endif
+ { NULL, NULL, NULL }
+ };
+ int f;
+
+ (void)files_setservent(retval, mdata, ap);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ f = va_arg(ap,int);
+ (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
+ "setservent", compat_src, f);
+ break;
+ case ENDSERVENT:
+ (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
+ "endservent", compat_src);
+ break;
+ default:
+ break;
+ }
+
+ return (NS_UNAVAIL);
+}
+
+#ifdef NS_CACHING
+static int
+serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ char *name;
+ char *proto;
+ int port;
+
+ size_t desired_size, size, size2;
+ enum nss_lookup_type lookup_type;
+ int res = NS_UNAVAIL;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (proto != NULL) {
+ size2 = strlen(proto);
+ desired_size += size2 + 1;
+ } else
+ size2 = 0;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ if (proto != NULL)
+ memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1,
+ proto, size2 + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+
+ desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
+ if (proto != NULL) {
+ size = strlen(proto);
+ desired_size += size + 1;
+ } else
+ size = 0;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &port,
+ sizeof(int));
+
+ if (proto != NULL)
+ memcpy(buffer + sizeof(enum nss_lookup_type) +
+ sizeof(int), proto, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+int
+serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ char *proto;
+ int port;
+ struct servent *serv;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct servent new_serv;
+ size_t desired_size;
+ char **alias;
+ char *p;
+ size_t size;
+ size_t aliases_size;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ serv = va_arg(ap, struct servent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
+ if (serv->s_name != NULL)
+ desired_size += strlen(serv->s_name) + 1;
+ if (serv->s_proto != NULL)
+ desired_size += strlen(serv->s_proto) + 1;
+
+ aliases_size = 0;
+ if (serv->s_aliases != NULL) {
+ for (alias = serv->s_aliases; *alias; ++alias) {
+ desired_size += strlen(*alias) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES +
+ sizeof(char *) * (aliases_size + 1);
+ }
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_serv, serv, sizeof(struct servent));
+ memset(buffer, 0, desired_size);
+
+ *buffer_size = desired_size;
+ p = buffer + sizeof(struct servent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_serv.s_name != NULL) {
+ size = strlen(new_serv.s_name);
+ memcpy(p, new_serv.s_name, size);
+ new_serv.s_name = p;
+ p += size + 1;
+ }
+
+ if (new_serv.s_proto != NULL) {
+ size = strlen(new_serv.s_proto);
+ memcpy(p, new_serv.s_proto, size);
+ new_serv.s_proto = p;
+ p += size + 1;
+ }
+
+ if (new_serv.s_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
+ new_serv.s_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (alias = new_serv.s_aliases; *alias; ++alias) {
+ size = strlen(*alias);
+ memcpy(p, *alias, size);
+ *alias = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_serv, sizeof(struct servent));
+ return (NS_SUCCESS);
+}
+
+int
+serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ char *proto;
+ int port;
+ struct servent *serv;
+ char *orig_buf;
+ char *p;
+ char **alias;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ serv = va_arg(ap, struct servent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct servent) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(serv, buffer, sizeof(struct servent));
+ memcpy(&p, buffer + sizeof(struct servent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) +
+ (_ALIGN(p) - (size_t)p),
+ buffer_size - sizeof(struct servent) - sizeof(char *) -
+ (_ALIGN(p) - (size_t)p));
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *);
+ NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *);
+ if (serv->s_aliases != NULL) {
+ NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **);
+
+ for (alias = serv->s_aliases; *alias; ++alias)
+ NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct servent **)retval) = serv;
+ return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(services);
+#endif /* NS_CACHING */
+
+/* get**_r functions implementation */
+int
+getservbyname_r(const char *name, const char *proto, struct servent *serv,
+ char *buffer, size_t bufsize, struct servent **result)
+{
+ static const struct servent_mdata mdata = { nss_lt_name, 0 };
+ static const struct servent_mdata compat_mdata = { nss_lt_name, 1 };
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_name,
+ serv_id_func, serv_marshal_func, serv_unmarshal_func);
+#endif /* NS_CACHING */
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_name },
+#ifdef YP
+ { NSSRC_NIS, nis_servent, (void *)nss_lt_name },
+#endif
+ { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r",
+ defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+int
+getservbyport_r(int port, const char *proto, struct servent *serv,
+ char *buffer, size_t bufsize, struct servent **result)
+{
+ static const struct servent_mdata mdata = { nss_lt_id, 0 };
+ static const struct servent_mdata compat_mdata = { nss_lt_id, 1 };
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_id,
+ serv_id_func, serv_marshal_func, serv_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_id },
+#ifdef YP
+ { NSSRC_NIS, nis_servent, (void *)nss_lt_id },
+#endif
+ { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r",
+ defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+int
+getservent_r(struct servent *serv, char *buffer, size_t bufsize,
+ struct servent **result)
+{
+ static const struct servent_mdata mdata = { nss_lt_all, 0 };
+ static const struct servent_mdata compat_mdata = { nss_lt_all, 1 };
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_all,
+ serv_marshal_func, serv_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_all },
+#ifdef YP
+ { NSSRC_NIS, nis_servent, (void *)nss_lt_all },
+#endif
+ { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r",
+ defaultsrc, serv, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+void
+setservent(int stayopen)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setservent, (void *)SETSERVENT },
+ { NSSRC_DB, db_setservent, (void *)SETSERVENT },
+#ifdef YP
+ { NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
+#endif
+ { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc,
+ stayopen);
+}
+
+void
+endservent()
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
+ { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
+#ifdef YP
+ { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
+#endif
+ { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
+}
+
+/* get** wrappers for get**_r functions implementation */
+static void
+servent_endstate(void *p)
+{
+ if (p == NULL)
+ return;
+
+ free(((struct servent_state *)p)->buffer);
+ free(p);
+}
+
+static int
+wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer,
+ size_t bufsize, struct servent **res)
+{
+ return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize,
+ res));
+}
+
+static int
+wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer,
+ size_t bufsize, struct servent **res)
+{
+ return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize,
+ res));
+}
+
+static int
+wrap_getservent_r(struct key key, struct servent *serv, char *buffer,
+ size_t bufsize, struct servent **res)
+{
+ return (getservent_r(serv, buffer, bufsize, res));
+}
+
+static struct servent *
+getserv(int (*fn)(struct key, struct servent *, char *, size_t,
+ struct servent **), struct key key)
+{
+ int rv;
+ struct servent *res;
+ struct servent_state * st;
+
+ rv = servent_getstate(&st);
+ if (rv != 0) {
+ errno = rv;
+ return NULL;
+ }
+
+ if (st->buffer == NULL) {
+ st->buffer = malloc(SERVENT_STORAGE_INITIAL);
+ if (st->buffer == NULL)
+ return (NULL);
+ st->bufsize = SERVENT_STORAGE_INITIAL;
+ }
+ do {
+ rv = fn(key, &st->serv, st->buffer, st->bufsize, &res);
+ if (res == NULL && rv == ERANGE) {
+ free(st->buffer);
+ if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) {
+ st->buffer = NULL;
+ errno = ERANGE;
+ return (NULL);
+ }
+ st->bufsize <<= 1;
+ st->buffer = malloc(st->bufsize);
+ if (st->buffer == NULL)
+ return (NULL);
+ }
+ } while (res == NULL && rv == ERANGE);
+ if (rv != 0)
+ errno = rv;
+
+ return (res);
+}
+
+struct servent *
+getservbyname(const char *name, const char *proto)
+{
+ struct key key;
+
+ key.name = name;
+ key.proto = proto;
+
+ return (getserv(wrap_getservbyname_r, key));
+}
+
+struct servent *
+getservbyport(int port, const char *proto)
+{
+ struct key key;
+
+ key.port = port;
+ key.proto = proto;
+
+ return (getserv(wrap_getservbyport_r, key));
+}
+
+struct servent *
+getservent()
+{
+ struct key key;
+
+ key.proto = NULL;
+ key.port = 0;
+
+ return (getserv(wrap_getservent_r, key));
+}
diff --git a/freebsd/lib/libc/net/if_indextoname.c b/freebsd/lib/libc/net/if_indextoname.c
new file mode 100644
index 00000000..efbcae86
--- /dev/null
+++ b/freebsd/lib/libc/net/if_indextoname.c
@@ -0,0 +1,90 @@
+#include "port_before.h"
+
+/* $KAME: if_indextoname.c,v 1.7 2000/11/08 03:09:30 itojun Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2000
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, 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 Berkeley Software Design, 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.
+ *
+ * BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * From RFC 2533:
+ *
+ * The second function maps an interface index into its corresponding
+ * name.
+ *
+ * #include <net/if.h>
+ *
+ * char *if_indextoname(unsigned int ifindex, char *ifname);
+ *
+ * The ifname argument must point to a buffer of at least IF_NAMESIZE
+ * bytes into which the interface name corresponding to the specified
+ * index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
+ * its value includes a terminating null byte at the end of the
+ * interface name.) This pointer is also the return value of the
+ * function. If there is no interface corresponding to the specified
+ * index, NULL is returned, and errno is set to ENXIO, if there was a
+ * system error (such as running out of memory), if_indextoname returns
+ * NULL and errno would be set to the proper value (e.g., ENOMEM).
+ */
+
+char *
+if_indextoname(unsigned int ifindex, char *ifname)
+{
+ struct ifaddrs *ifaddrs, *ifa;
+ int error = 0;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return(NULL); /* getifaddrs properly set errno */
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK &&
+ ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
+ break;
+ }
+
+ if (ifa == NULL) {
+ error = ENXIO;
+ ifname = NULL;
+ }
+ else
+ strncpy(ifname, ifa->ifa_name, IFNAMSIZ);
+
+ freeifaddrs(ifaddrs);
+
+ errno = error;
+ return(ifname);
+}
diff --git a/freebsd/lib/libc/net/if_nameindex.c b/freebsd/lib/libc/net/if_nameindex.c
new file mode 100644
index 00000000..85073759
--- /dev/null
+++ b/freebsd/lib/libc/net/if_nameindex.c
@@ -0,0 +1,149 @@
+#include "port_before.h"
+
+/* $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2000
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, 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 Berkeley Software Design, 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.
+ *
+ * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * From RFC 2553:
+ *
+ * 4.3 Return All Interface Names and Indexes
+ *
+ * The if_nameindex structure holds the information about a single
+ * interface and is defined as a result of including the <net/if.h>
+ * header.
+ *
+ * struct if_nameindex {
+ * unsigned int if_index;
+ * char *if_name;
+ * };
+ *
+ * The final function returns an array of if_nameindex structures, one
+ * structure per interface.
+ *
+ * struct if_nameindex *if_nameindex(void);
+ *
+ * The end of the array of structures is indicated by a structure with
+ * an if_index of 0 and an if_name of NULL. The function returns a NULL
+ * pointer upon an error, and would set errno to the appropriate value.
+ *
+ * The memory used for this array of structures along with the interface
+ * names pointed to by the if_name members is obtained dynamically.
+ * This memory is freed by the next function.
+ *
+ * 4.4. Free Memory
+ *
+ * The following function frees the dynamic memory that was allocated by
+ * if_nameindex().
+ *
+ * #include <net/if.h>
+ *
+ * void if_freenameindex(struct if_nameindex *ptr);
+ *
+ * The argument to this function must be a pointer that was returned by
+ * if_nameindex().
+ */
+
+struct if_nameindex *
+if_nameindex(void)
+{
+ struct ifaddrs *ifaddrs, *ifa;
+ unsigned int ni;
+ int nbytes;
+ struct if_nameindex *ifni, *ifni2;
+ char *cp;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return(NULL);
+
+ /*
+ * First, find out how many interfaces there are, and how
+ * much space we need for the string names.
+ */
+ ni = 0;
+ nbytes = 0;
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK) {
+ nbytes += strlen(ifa->ifa_name) + 1;
+ ni++;
+ }
+ }
+
+ /*
+ * Next, allocate a chunk of memory, use the first part
+ * for the array of structures, and the last part for
+ * the strings.
+ */
+ cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
+ ifni = (struct if_nameindex *)cp;
+ if (ifni == NULL)
+ goto out;
+ cp += (ni + 1) * sizeof(struct if_nameindex);
+
+ /*
+ * Now just loop through the list of interfaces again,
+ * filling in the if_nameindex array and making copies
+ * of all the strings.
+ */
+ ifni2 = ifni;
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK) {
+ ifni2->if_index =
+ ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
+ ifni2->if_name = cp;
+ strcpy(cp, ifa->ifa_name);
+ ifni2++;
+ cp += strlen(cp) + 1;
+ }
+ }
+ /*
+ * Finally, don't forget to terminate the array.
+ */
+ ifni2->if_index = 0;
+ ifni2->if_name = NULL;
+out:
+ freeifaddrs(ifaddrs);
+ return(ifni);
+}
+
+void
+if_freenameindex(struct if_nameindex *ptr)
+{
+ free(ptr);
+}
diff --git a/freebsd/lib/libc/net/if_nametoindex.c b/freebsd/lib/libc/net/if_nametoindex.c
new file mode 100644
index 00000000..a278ca07
--- /dev/null
+++ b/freebsd/lib/libc/net/if_nametoindex.c
@@ -0,0 +1,102 @@
+/* $KAME: if_nametoindex.c,v 1.6 2000/11/24 08:18:54 itojun Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2000
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, 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 Berkeley Software Design, 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.
+ *
+ * BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#ifdef __rtems__
+#include <freebsd/sys/sockio.h>
+#endif
+
+/*
+ * From RFC 2553:
+ *
+ * 4.1 Name-to-Index
+ *
+ *
+ * The first function maps an interface name into its corresponding
+ * index.
+ *
+ * #include <net/if.h>
+ *
+ * unsigned int if_nametoindex(const char *ifname);
+ *
+ * If the specified interface name does not exist, the return value is
+ * 0, and errno is set to ENXIO. If there was a system error (such as
+ * running out of memory), the return value is 0 and errno is set to the
+ * proper value (e.g., ENOMEM).
+ */
+
+unsigned int
+if_nametoindex(const char *ifname)
+{
+ int s;
+ struct ifreq ifr;
+ struct ifaddrs *ifaddrs, *ifa;
+ unsigned int ni;
+
+ s = _socket(AF_INET, SOCK_DGRAM, 0);
+ if (s != -1) {
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (_ioctl(s, SIOCGIFINDEX, &ifr) != -1) {
+ _close(s);
+ return (ifr.ifr_index);
+ }
+ _close(s);
+ }
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return(0);
+
+ ni = 0;
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK &&
+ strcmp(ifa->ifa_name, ifname) == 0) {
+ ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
+ break;
+ }
+ }
+
+ freeifaddrs(ifaddrs);
+ if (!ni)
+ errno = ENXIO;
+ return(ni);
+}
diff --git a/freebsd/lib/libc/net/linkaddr.c b/freebsd/lib/libc/net/linkaddr.c
new file mode 100644
index 00000000..761b5ae5
--- /dev/null
+++ b/freebsd/lib/libc/net/linkaddr.c
@@ -0,0 +1,158 @@
+#include "port_before.h"
+
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <string.h>
+
+/* States*/
+#define NAMING 0
+#define GOTONE 1
+#define GOTTWO 2
+#define RESET 3
+/* Inputs */
+#define DIGIT (4*0)
+#define END (4*1)
+#define DELIM (4*2)
+#define LETTER (4*3)
+
+void
+link_addr(addr, sdl)
+ const char *addr;
+ struct sockaddr_dl *sdl;
+{
+ char *cp = sdl->sdl_data;
+ char *cplim = sdl->sdl_len + (char *)sdl;
+ int byte = 0, state = NAMING, new;
+
+ bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
+ sdl->sdl_family = AF_LINK;
+ do {
+ state &= ~LETTER;
+ if ((*addr >= '0') && (*addr <= '9')) {
+ new = *addr - '0';
+ } else if ((*addr >= 'a') && (*addr <= 'f')) {
+ new = *addr - 'a' + 10;
+ } else if ((*addr >= 'A') && (*addr <= 'F')) {
+ new = *addr - 'A' + 10;
+ } else if (*addr == 0) {
+ state |= END;
+ } else if (state == NAMING &&
+ (((*addr >= 'A') && (*addr <= 'Z')) ||
+ ((*addr >= 'a') && (*addr <= 'z'))))
+ state |= LETTER;
+ else
+ state |= DELIM;
+ addr++;
+ switch (state /* | INPUT */) {
+ case NAMING | DIGIT:
+ case NAMING | LETTER:
+ *cp++ = addr[-1];
+ continue;
+ case NAMING | DELIM:
+ state = RESET;
+ sdl->sdl_nlen = cp - sdl->sdl_data;
+ continue;
+ case GOTTWO | DIGIT:
+ *cp++ = byte;
+ /* FALLTHROUGH */
+ case RESET | DIGIT:
+ state = GOTONE;
+ byte = new;
+ continue;
+ case GOTONE | DIGIT:
+ state = GOTTWO;
+ byte = new + (byte << 4);
+ continue;
+ default: /* | DELIM */
+ state = RESET;
+ *cp++ = byte;
+ byte = 0;
+ continue;
+ case GOTONE | END:
+ case GOTTWO | END:
+ *cp++ = byte;
+ /* FALLTHROUGH */
+ case RESET | END:
+ break;
+ }
+ break;
+ } while (cp < cplim);
+ sdl->sdl_alen = cp - LLADDR(sdl);
+ new = cp - (char *)sdl;
+ if (new > sizeof(*sdl))
+ sdl->sdl_len = new;
+ return;
+}
+
+static char hexlist[] = "0123456789abcdef";
+
+char *
+link_ntoa(sdl)
+ const struct sockaddr_dl *sdl;
+{
+ static char obuf[64];
+ char *out = obuf;
+ int i;
+ u_char *in = (u_char *)LLADDR(sdl);
+ u_char *inlim = in + sdl->sdl_alen;
+ int firsttime = 1;
+
+ if (sdl->sdl_nlen) {
+ bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
+ out += sdl->sdl_nlen;
+ if (sdl->sdl_alen)
+ *out++ = ':';
+ }
+ while (in < inlim) {
+ if (firsttime)
+ firsttime = 0;
+ else
+ *out++ = '.';
+ i = *in++;
+ if (i > 0xf) {
+ out[1] = hexlist[i & 0xf];
+ i >>= 4;
+ out[0] = hexlist[i];
+ out += 2;
+ } else
+ *out++ = hexlist[i];
+ }
+ *out = 0;
+ return (obuf);
+}
diff --git a/freebsd/lib/libc/net/map_v4v6.c b/freebsd/lib/libc/net/map_v4v6.c
new file mode 100644
index 00000000..000ed9e2
--- /dev/null
+++ b/freebsd/lib/libc/net/map_v4v6.c
@@ -0,0 +1,121 @@
+#include "port_before.h"
+
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <syslog.h>
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+void
+_map_v4v6_address(const char *src, char *dst)
+{
+ u_char *p = (u_char *)dst;
+ char tmp[NS_INADDRSZ];
+ int i;
+
+ /* Stash a temporary copy so our caller can update in place. */
+ memcpy(tmp, src, NS_INADDRSZ);
+ /* Mark this ipv6 addr as a mapped ipv4. */
+ for (i = 0; i < 10; i++)
+ *p++ = 0x00;
+ *p++ = 0xff;
+ *p++ = 0xff;
+ /* Retrieve the saved copy and we're done. */
+ memcpy((void*)p, tmp, NS_INADDRSZ);
+}
+
+void
+_map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) {
+ char **ap;
+
+ if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+ return;
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ for (ap = hp->h_addr_list; *ap; ap++) {
+ int i = (u_long)*bpp % sizeof(align);
+
+ if (i != 0)
+ i = sizeof(align) - i;
+
+ if ((ep - *bpp) < (i + IN6ADDRSZ)) {
+ /* Out of memory. Truncate address list here. */
+ *ap = NULL;
+ return;
+ }
+ *bpp += i;
+ _map_v4v6_address(*ap, *bpp);
+ *ap = *bpp;
+ *bpp += IN6ADDRSZ;
+ }
+}
diff --git a/freebsd/lib/libc/net/name6.c b/freebsd/lib/libc/net/name6.c
new file mode 100644
index 00000000..20763f88
--- /dev/null
+++ b/freebsd/lib/libc/net/name6.c
@@ -0,0 +1,1121 @@
+#include "port_before.h"
+/* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ * -
+ * --Copyright--
+ */
+
+/*
+ * Atsushi Onoe <onoe@sm.sony.co.jp>
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#ifdef INET6
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <freebsd/netinet6/in6_var.h> /* XXX */
+#else
+#include <net/if_var.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <netinet6/in6_var.h> /* XXX */
+#endif
+#endif
+
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "netdb_private.h"
+#include "res_private.h"
+
+#ifndef MAXALIASES
+#define MAXALIASES 10
+#endif
+#ifndef MAXADDRS
+#define MAXADDRS 20
+#endif
+#ifndef MAXDNAME
+#define MAXDNAME 1025
+#endif
+
+#ifdef INET6
+#define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \
+ sizeof(struct in_addr))
+#else
+#define ADDRLEN(af) sizeof(struct in_addr)
+#endif
+
+#define MAPADDR(ab, ina) \
+do { \
+ memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \
+ memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \
+ memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \
+} while (0)
+#define MAPADDRENABLED(flags) \
+ (((flags) & AI_V4MAPPED) || \
+ (((flags) & AI_V4MAPPED_CFG)))
+
+union inx_addr {
+ struct in_addr in_addr;
+#ifdef INET6
+ struct in6_addr in6_addr;
+#endif
+ struct {
+ u_char mau_zero[10];
+ u_char mau_one[2];
+ struct in_addr mau_inaddr;
+ } map_addr_un;
+#define map_zero map_addr_un.mau_zero
+#define map_one map_addr_un.mau_one
+#define map_inaddr map_addr_un.mau_inaddr
+};
+
+struct policyqueue {
+ TAILQ_ENTRY(policyqueue) pc_entry;
+#ifdef INET6
+ struct in6_addrpolicy pc_policy;
+#endif
+};
+TAILQ_HEAD(policyhead, policyqueue);
+
+#define AIO_SRCFLAG_DEPRECATED 0x1
+
+struct hp_order {
+ union {
+ struct sockaddr_storage aiou_ss;
+ struct sockaddr aiou_sa;
+ } aio_src_un;
+#define aio_srcsa aio_src_un.aiou_sa
+ u_int32_t aio_srcflag;
+ int aio_srcscope;
+ int aio_dstscope;
+ struct policyqueue *aio_srcpolicy;
+ struct policyqueue *aio_dstpolicy;
+ union {
+ struct sockaddr_storage aiou_ss;
+ struct sockaddr aiou_sa;
+ } aio_un;
+#define aio_sa aio_un.aiou_sa
+ int aio_matchlen;
+ char *aio_h_addr;
+};
+
+static struct hostent *_hpcopy(struct hostent *, int *);
+static struct hostent *_hpaddr(int, const char *, void *, int *);
+#ifdef INET6
+static struct hostent *_hpmerge(struct hostent *, struct hostent *, int *);
+static struct hostent *_hpmapv6(struct hostent *, int *);
+#endif
+static struct hostent *_hpsort(struct hostent *, res_state);
+
+static struct hostent *_hpreorder(struct hostent *);
+static int get_addrselectpolicy(struct policyhead *);
+static void free_addrselectpolicy(struct policyhead *);
+static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
+ struct policyhead *);
+static void set_source(struct hp_order *, struct policyhead *);
+static int matchlen(struct sockaddr *, struct sockaddr *);
+static int comp_dst(const void *, const void *);
+static int gai_addr2scopetype(struct sockaddr *);
+
+/*
+ * Functions defined in RFC2553
+ * getipnodebyname, getipnodebyaddr, freehostent
+ */
+
+struct hostent *
+getipnodebyname(const char *name, int af, int flags, int *errp)
+{
+ struct hostent *hp;
+ union inx_addr addrbuf;
+ res_state statp;
+ u_long options;
+
+ switch (af) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+
+ if (flags & AI_ADDRCONFIG) {
+ int s;
+
+ if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
+ return NULL;
+ /*
+ * TODO:
+ * Note that implementation dependent test for address
+ * configuration should be done everytime called
+ * (or apropriate interval),
+ * because addresses will be dynamically assigned or deleted.
+ */
+ _close(s);
+ }
+
+#ifdef INET6
+ /* special case for literal address */
+ if (inet_pton(AF_INET6, name, &addrbuf) == 1) {
+ if (af != AF_INET6) {
+ *errp = HOST_NOT_FOUND;
+ return NULL;
+ }
+ return _hpaddr(af, name, &addrbuf, errp);
+ }
+#endif
+ if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) {
+ if (af != AF_INET) {
+ if (MAPADDRENABLED(flags)) {
+ MAPADDR(&addrbuf, &addrbuf.in_addr);
+ } else {
+ *errp = HOST_NOT_FOUND;
+ return NULL;
+ }
+ }
+ return _hpaddr(af, name, &addrbuf, errp);
+ }
+
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0) {
+ if (res_ninit(statp) < 0) {
+ *errp = NETDB_INTERNAL;
+ return NULL;
+ }
+ }
+
+ options = statp->options;
+ statp->options &= ~RES_USE_INET6;
+
+ hp = gethostbyname2(name, af);
+ hp = _hpcopy(hp, errp);
+
+#ifdef INET6
+ if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) &&
+ MAPADDRENABLED(flags)) {
+ struct hostent *hp2 = gethostbyname2(name, AF_INET);
+ if (hp == NULL)
+ if (hp2 == NULL)
+ *errp = statp->res_h_errno;
+ else
+ hp = _hpmapv6(hp2, errp);
+ else {
+ if (hp2 && strcmp(hp->h_name, hp2->h_name) == 0) {
+ struct hostent *hpb = hp;
+ hp = _hpmerge(hpb, hp2, errp);
+ freehostent(hpb);
+ }
+ }
+ }
+#endif
+
+ if (hp == NULL)
+ *errp = statp->res_h_errno;
+
+ statp->options = options;
+ return _hpreorder(_hpsort(hp, statp));
+}
+
+struct hostent *
+getipnodebyaddr(const void *src, size_t len, int af, int *errp)
+{
+ struct hostent *hp;
+ res_state statp;
+ u_long options;
+
+#ifdef INET6
+ struct in6_addr addrbuf;
+#else
+ struct in_addr addrbuf;
+#endif
+
+ switch (af) {
+ case AF_INET:
+ if (len != sizeof(struct in_addr)) {
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ if ((long)src & ~(sizeof(struct in_addr) - 1)) {
+ memcpy(&addrbuf, src, len);
+ src = &addrbuf;
+ }
+ if (((struct in_addr *)src)->s_addr == 0)
+ return NULL;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (len != sizeof(struct in6_addr)) {
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/
+ memcpy(&addrbuf, src, len);
+ src = &addrbuf;
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src))
+ return NULL;
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)
+ || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) {
+ src = (char *)src +
+ (sizeof(struct in6_addr) - sizeof(struct in_addr));
+ af = AF_INET;
+ len = sizeof(struct in_addr);
+ }
+ break;
+#endif
+ default:
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0) {
+ if (res_ninit(statp) < 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return NULL;
+ }
+ }
+
+ options = statp->options;
+ statp->options &= ~RES_USE_INET6;
+
+ hp = gethostbyaddr(src, len, af);
+ if (hp == NULL)
+ *errp = statp->res_h_errno;
+
+ statp->options = options;
+ return (_hpcopy(hp, errp));
+}
+
+void
+freehostent(struct hostent *ptr)
+{
+ free(ptr);
+}
+
+/*
+ * Private utility functions
+ */
+
+/*
+ * _hpcopy: allocate and copy hostent structure
+ */
+static struct hostent *
+_hpcopy(struct hostent *hp, int *errp)
+{
+ struct hostent *nhp;
+ char *cp, **pp;
+ int size, addrsize;
+ int nalias = 0, naddr = 0;
+ int al_off;
+ int i;
+
+ if (hp == NULL)
+ return hp;
+
+ /* count size to be allocated */
+ size = sizeof(struct hostent);
+ if (hp->h_name != NULL)
+ size += strlen(hp->h_name) + 1;
+ if ((pp = hp->h_aliases) != NULL) {
+ for (i = 0; *pp != NULL; i++, pp++) {
+ if (**pp != '\0') {
+ size += strlen(*pp) + 1;
+ nalias++;
+ }
+ }
+ }
+ /* adjust alignment */
+ size = ALIGN(size);
+ al_off = size;
+ size += sizeof(char *) * (nalias + 1);
+ addrsize = ALIGN(hp->h_length);
+ if ((pp = hp->h_addr_list) != NULL) {
+ while (*pp++ != NULL)
+ naddr++;
+ }
+ size += addrsize * naddr;
+ size += sizeof(char *) * (naddr + 1);
+
+ /* copy */
+ if ((nhp = (struct hostent *)malloc(size)) == NULL) {
+ *errp = TRY_AGAIN;
+ return NULL;
+ }
+ cp = (char *)&nhp[1];
+ if (hp->h_name != NULL) {
+ nhp->h_name = cp;
+ strcpy(cp, hp->h_name);
+ cp += strlen(cp) + 1;
+ } else
+ nhp->h_name = NULL;
+ nhp->h_aliases = (char **)((char *)nhp + al_off);
+ if ((pp = hp->h_aliases) != NULL) {
+ for (i = 0; *pp != NULL; pp++) {
+ if (**pp != '\0') {
+ nhp->h_aliases[i++] = cp;
+ strcpy(cp, *pp);
+ cp += strlen(cp) + 1;
+ }
+ }
+ }
+ nhp->h_aliases[nalias] = NULL;
+ cp = (char *)&nhp->h_aliases[nalias + 1];
+ nhp->h_addrtype = hp->h_addrtype;
+ nhp->h_length = hp->h_length;
+ nhp->h_addr_list = (char **)cp;
+ if ((pp = hp->h_addr_list) != NULL) {
+ cp = (char *)&nhp->h_addr_list[naddr + 1];
+ for (i = 0; *pp != NULL; pp++) {
+ nhp->h_addr_list[i++] = cp;
+ memcpy(cp, *pp, hp->h_length);
+ cp += addrsize;
+ }
+ }
+ nhp->h_addr_list[naddr] = NULL;
+ return nhp;
+}
+
+/*
+ * _hpaddr: construct hostent structure with one address
+ */
+static struct hostent *
+_hpaddr(int af, const char *name, void *addr, int *errp)
+{
+ struct hostent *hp, hpbuf;
+ char *addrs[2];
+
+ hp = &hpbuf;
+ hp->h_name = (char *)name;
+ hp->h_aliases = NULL;
+ hp->h_addrtype = af;
+ hp->h_length = ADDRLEN(af);
+ hp->h_addr_list = addrs;
+ addrs[0] = (char *)addr;
+ addrs[1] = NULL;
+ return (_hpcopy(hp, errp));
+}
+
+#ifdef INET6
+/*
+ * _hpmerge: merge 2 hostent structure, arguments will be freed
+ */
+static struct hostent *
+_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp)
+{
+ int i, j;
+ int naddr, nalias;
+ char **pp;
+ struct hostent *hp, hpbuf;
+ char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1];
+ union inx_addr addrbuf[MAXADDRS];
+
+ if (hp1 == NULL)
+ return _hpcopy(hp2, errp);
+ if (hp2 == NULL)
+ return _hpcopy(hp1, errp);
+
+#define HP(i) (i == 1 ? hp1 : hp2)
+ hp = &hpbuf;
+ hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
+ hp->h_aliases = aliases;
+ nalias = 0;
+ for (i = 1; i <= 2; i++) {
+ if ((pp = HP(i)->h_aliases) == NULL)
+ continue;
+ for (; nalias < MAXALIASES && *pp != NULL; pp++) {
+ /* check duplicates */
+ for (j = 0; j < nalias; j++)
+ if (strcasecmp(*pp, aliases[j]) == 0)
+ break;
+ if (j == nalias)
+ aliases[nalias++] = *pp;
+ }
+ }
+ aliases[nalias] = NULL;
+ if (hp1->h_length != hp2->h_length) {
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = sizeof(struct in6_addr);
+ } else {
+ hp->h_addrtype = hp1->h_addrtype;
+ hp->h_length = hp1->h_length;
+ }
+
+ hp->h_addr_list = addrs;
+ naddr = 0;
+ for (i = 1; i <= 2; i++) {
+ if ((pp = HP(i)->h_addr_list) == NULL)
+ continue;
+ if (HP(i)->h_length == hp->h_length) {
+ while (naddr < MAXADDRS && *pp != NULL)
+ addrs[naddr++] = *pp++;
+ } else {
+ /* copy IPv4 addr as mapped IPv6 addr */
+ while (naddr < MAXADDRS && *pp != NULL) {
+ MAPADDR(&addrbuf[naddr], *pp++);
+ addrs[naddr] = (char *)&addrbuf[naddr];
+ naddr++;
+ }
+ }
+ }
+ addrs[naddr] = NULL;
+ return (_hpcopy(hp, errp));
+}
+#endif
+
+/*
+ * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
+ */
+#ifdef INET6
+static struct hostent *
+_hpmapv6(struct hostent *hp, int *errp)
+{
+ struct hostent hp6;
+
+ if (hp == NULL)
+ return NULL;
+ if (hp->h_addrtype == AF_INET6)
+ return _hpcopy(hp, errp);
+
+ memset(&hp6, 0, sizeof(struct hostent));
+ hp6.h_addrtype = AF_INET6;
+ hp6.h_length = sizeof(struct in6_addr);
+ return _hpmerge(&hp6, hp, errp);
+}
+#endif
+
+/*
+ * _hpsort: sort address by sortlist
+ */
+static struct hostent *
+_hpsort(struct hostent *hp, res_state statp)
+{
+ int i, j, n;
+ u_char *ap, *sp, *mp, **pp;
+ char t;
+ char order[MAXADDRS];
+ int nsort = statp->nsort;
+
+ if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0)
+ return hp;
+ for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) {
+ for (j = 0; j < nsort; j++) {
+#ifdef INET6
+ if (statp->_u._ext.ext->sort_list[j].af !=
+ hp->h_addrtype)
+ continue;
+ sp = (u_char *)&statp->_u._ext.ext->sort_list[j].addr;
+ mp = (u_char *)&statp->_u._ext.ext->sort_list[j].mask;
+#else
+ sp = (u_char *)&statp->sort_list[j].addr;
+ mp = (u_char *)&statp->sort_list[j].mask;
+#endif
+ for (n = 0; n < hp->h_length; n++) {
+ if ((ap[n] & mp[n]) != sp[n])
+ break;
+ }
+ if (n == hp->h_length)
+ break;
+ }
+ order[i] = j;
+ }
+ n = i;
+ pp = (u_char **)hp->h_addr_list;
+ for (i = 0; i < n - 1; i++) {
+ for (j = i + 1; j < n; j++) {
+ if (order[i] > order[j]) {
+ ap = pp[i];
+ pp[i] = pp[j];
+ pp[j] = ap;
+ t = order[i];
+ order[i] = order[j];
+ order[j] = t;
+ }
+ }
+ }
+ return hp;
+}
+
+/*
+ * _hpreorder: sort address by default address selection
+ */
+static struct hostent *
+_hpreorder(struct hostent *hp)
+{
+ struct hp_order *aio;
+ int i, n;
+ char *ap;
+ struct sockaddr *sa;
+ struct policyhead policyhead;
+
+ if (hp == NULL)
+ return hp;
+
+ switch (hp->h_addrtype) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ free_addrselectpolicy(&policyhead);
+ return hp;
+ }
+
+ /* count the number of addrinfo elements for sorting. */
+ for (n = 0; hp->h_addr_list[n] != NULL; n++)
+ ;
+
+ /*
+ * If the number is small enough, we can skip the reordering process.
+ */
+ if (n <= 1)
+ return hp;
+
+ /* allocate a temporary array for sort and initialization of it. */
+ if ((aio = malloc(sizeof(*aio) * n)) == NULL)
+ return hp; /* give up reordering */
+ memset(aio, 0, sizeof(*aio) * n);
+
+ /* retrieve address selection policy from the kernel */
+ TAILQ_INIT(&policyhead);
+ if (!get_addrselectpolicy(&policyhead)) {
+ /* no policy is installed into kernel, we don't sort. */
+ free(aio);
+ return hp;
+ }
+
+ for (i = 0; i < n; i++) {
+ ap = hp->h_addr_list[i];
+ aio[i].aio_h_addr = ap;
+ sa = &aio[i].aio_sa;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ sa->sa_family = AF_INET;
+ sa->sa_len = sizeof(struct sockaddr_in);
+ memcpy(&((struct sockaddr_in *)sa)->sin_addr, ap,
+ sizeof(struct in_addr));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ sa->sa_family = AF_INET;
+ sa->sa_len = sizeof(struct sockaddr_in);
+ memcpy(&((struct sockaddr_in *)sa)->sin_addr,
+ &ap[12], sizeof(struct in_addr));
+ } else {
+ sa->sa_family = AF_INET6;
+ sa->sa_len = sizeof(struct sockaddr_in6);
+ memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr,
+ ap, sizeof(struct in6_addr));
+ }
+ break;
+#endif
+ }
+ aio[i].aio_dstscope = gai_addr2scopetype(sa);
+ aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead);
+ set_source(&aio[i], &policyhead);
+ }
+
+ /* perform sorting. */
+ qsort(aio, n, sizeof(*aio), comp_dst);
+
+ /* reorder the h_addr_list. */
+ for (i = 0; i < n; i++)
+ hp->h_addr_list[i] = aio[i].aio_h_addr;
+
+ /* cleanup and return */
+ free(aio);
+ free_addrselectpolicy(&policyhead);
+ return hp;
+}
+
+static int
+get_addrselectpolicy(struct policyhead *head)
+{
+#ifdef INET6
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
+ size_t l;
+ char *buf;
+ struct in6_addrpolicy *pol, *ep;
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
+ return (0);
+ if ((buf = malloc(l)) == NULL)
+ return (0);
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ free(buf);
+ return (0);
+ }
+
+ ep = (struct in6_addrpolicy *)(buf + l);
+ for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
+ struct policyqueue *new;
+
+ if ((new = malloc(sizeof(*new))) == NULL) {
+ free_addrselectpolicy(head); /* make the list empty */
+ break;
+ }
+ new->pc_policy = *pol;
+ TAILQ_INSERT_TAIL(head, new, pc_entry);
+ }
+
+ free(buf);
+ return (1);
+#else
+ return (0);
+#endif
+}
+
+static void
+free_addrselectpolicy(struct policyhead *head)
+{
+ struct policyqueue *ent, *nent;
+
+ for (ent = TAILQ_FIRST(head); ent; ent = nent) {
+ nent = TAILQ_NEXT(ent, pc_entry);
+ TAILQ_REMOVE(head, ent, pc_entry);
+ free(ent);
+ }
+}
+
+static struct policyqueue *
+match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
+{
+#ifdef INET6
+ struct policyqueue *ent, *bestent = NULL;
+ struct in6_addrpolicy *pol;
+ int matchlen, bestmatchlen = -1;
+ u_char *mp, *ep, *k, *p, m;
+ struct sockaddr_in6 key;
+
+ switch(addr->sa_family) {
+ case AF_INET6:
+ key = *(struct sockaddr_in6 *)addr;
+ break;
+ case AF_INET:
+ /* convert the address into IPv4-mapped IPv6 address. */
+ memset(&key, 0, sizeof(key));
+ key.sin6_family = AF_INET6;
+ key.sin6_len = sizeof(key);
+ key.sin6_addr.s6_addr[10] = 0xff;
+ key.sin6_addr.s6_addr[11] = 0xff;
+ memcpy(&key.sin6_addr.s6_addr[12],
+ &((struct sockaddr_in *)addr)->sin_addr, 4);
+ break;
+ default:
+ return(NULL);
+ }
+
+ for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
+ pol = &ent->pc_policy;
+ matchlen = 0;
+
+ mp = (u_char *)&pol->addrmask.sin6_addr;
+ ep = mp + 16; /* XXX: scope field? */
+ k = (u_char *)&key.sin6_addr;
+ p = (u_char *)&pol->addr.sin6_addr;
+ for (; mp < ep && *mp; mp++, k++, p++) {
+ m = *mp;
+ if ((*k & m) != *p)
+ goto next; /* not match */
+ if (m == 0xff) /* short cut for a typical case */
+ matchlen += 8;
+ else {
+ while (m >= 0x80) {
+ matchlen++;
+ m <<= 1;
+ }
+ }
+ }
+
+ /* matched. check if this is better than the current best. */
+ if (matchlen > bestmatchlen) {
+ bestent = ent;
+ bestmatchlen = matchlen;
+ }
+
+ next:
+ continue;
+ }
+
+ return(bestent);
+#else
+ return(NULL);
+#endif
+
+}
+
+static void
+set_source(struct hp_order *aio, struct policyhead *ph)
+{
+ struct sockaddr_storage ss = aio->aio_un.aiou_ss;
+ socklen_t srclen;
+ int s;
+
+ /* set unspec ("no source is available"), just in case */
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ aio->aio_srcscope = -1;
+
+ switch(ss.ss_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)&ss)->sin_port = htons(1);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&ss)->sin6_port = htons(1);
+ break;
+#endif
+ default: /* ignore unsupported AFs explicitly */
+ return;
+ }
+
+ /* open a socket to get the source address for the given dst */
+ if ((s = _socket(ss.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ return; /* give up */
+ if (_connect(s, (struct sockaddr *)&ss, ss.ss_len) < 0)
+ goto cleanup;
+ srclen = ss.ss_len;
+ if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ goto cleanup;
+ }
+ aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
+ aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
+ aio->aio_matchlen = matchlen(&aio->aio_srcsa, (struct sockaddr *)&ss);
+#ifdef INET6
+ if (ss.ss_family == AF_INET6) {
+ struct in6_ifreq ifr6;
+ u_int32_t flags6;
+
+ /* XXX: interface name should not be hardcoded */
+ strncpy(ifr6.ifr_name, "lo0", sizeof(ifr6.ifr_name));
+ memset(&ifr6, 0, sizeof(ifr6));
+ memcpy(&ifr6.ifr_addr, &ss, ss.ss_len);
+ if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
+ flags6 = ifr6.ifr_ifru.ifru_flags6;
+ if ((flags6 & IN6_IFF_DEPRECATED))
+ aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
+ }
+ }
+#endif
+
+ cleanup:
+ _close(s);
+ return;
+}
+
+static int
+matchlen(struct sockaddr *src, struct sockaddr *dst)
+{
+ int match = 0;
+ u_char *s, *d;
+ u_char *lim, r;
+ int addrlen;
+
+ switch (src->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
+ d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
+ addrlen = sizeof(struct in6_addr);
+ lim = s + addrlen;
+ break;
+#endif
+ case AF_INET:
+ s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
+ d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
+ addrlen = sizeof(struct in_addr);
+ lim = s + addrlen;
+ break;
+ default:
+ return(0);
+ }
+
+ while (s < lim)
+ if ((r = (*d++ ^ *s++)) != 0) {
+ while (r < addrlen * 8) {
+ match++;
+ r <<= 1;
+ }
+ break;
+ } else
+ match += 8;
+ return(match);
+}
+
+static int
+comp_dst(const void *arg1, const void *arg2)
+{
+ const struct hp_order *dst1 = arg1, *dst2 = arg2;
+
+ /*
+ * Rule 1: Avoid unusable destinations.
+ * XXX: we currently do not consider if an appropriate route exists.
+ */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family == AF_UNSPEC) {
+ return(-1);
+ }
+ if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ return(1);
+ }
+
+ /* Rule 2: Prefer matching scope. */
+ if (dst1->aio_dstscope == dst1->aio_srcscope &&
+ dst2->aio_dstscope != dst2->aio_srcscope) {
+ return(-1);
+ }
+ if (dst1->aio_dstscope != dst1->aio_srcscope &&
+ dst2->aio_dstscope == dst2->aio_srcscope) {
+ return(1);
+ }
+
+ /* Rule 3: Avoid deprecated addresses. */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(-1);
+ }
+ if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(1);
+ }
+ }
+
+ /* Rule 4: Prefer home addresses. */
+ /* XXX: not implemented yet */
+
+ /* Rule 5: Prefer matching label. */
+#ifdef INET6
+ if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
+ dst1->aio_srcpolicy->pc_policy.label ==
+ dst1->aio_dstpolicy->pc_policy.label &&
+ (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
+ dst2->aio_srcpolicy->pc_policy.label !=
+ dst2->aio_dstpolicy->pc_policy.label)) {
+ return(-1);
+ }
+ if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
+ dst2->aio_srcpolicy->pc_policy.label ==
+ dst2->aio_dstpolicy->pc_policy.label &&
+ (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
+ dst1->aio_srcpolicy->pc_policy.label !=
+ dst1->aio_dstpolicy->pc_policy.label)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 6: Prefer higher precedence. */
+#ifdef INET6
+ if (dst1->aio_dstpolicy &&
+ (dst2->aio_dstpolicy == NULL ||
+ dst1->aio_dstpolicy->pc_policy.preced >
+ dst2->aio_dstpolicy->pc_policy.preced)) {
+ return(-1);
+ }
+ if (dst2->aio_dstpolicy &&
+ (dst1->aio_dstpolicy == NULL ||
+ dst2->aio_dstpolicy->pc_policy.preced >
+ dst1->aio_dstpolicy->pc_policy.preced)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 7: Prefer native transport. */
+ /* XXX: not implemented yet */
+
+ /* Rule 8: Prefer smaller scope. */
+ if (dst1->aio_dstscope >= 0 &&
+ dst1->aio_dstscope < dst2->aio_dstscope) {
+ return(-1);
+ }
+ if (dst2->aio_dstscope >= 0 &&
+ dst2->aio_dstscope < dst1->aio_dstscope) {
+ return(1);
+ }
+
+ /*
+ * Rule 9: Use longest matching prefix.
+ * We compare the match length in a same AF only.
+ */
+ if (dst1->aio_sa.sa_family == dst2->aio_sa.sa_family) {
+ if (dst1->aio_matchlen > dst2->aio_matchlen) {
+ return(-1);
+ }
+ if (dst1->aio_matchlen < dst2->aio_matchlen) {
+ return(1);
+ }
+ }
+
+ /* Rule 10: Otherwise, leave the order unchanged. */
+ return(-1);
+}
+
+/*
+ * Copy from scope.c.
+ * XXX: we should standardize the functions and link them as standard
+ * library.
+ */
+static int
+gai_addr2scopetype(struct sockaddr *sa)
+{
+#ifdef INET6
+ struct sockaddr_in6 *sa6;
+#endif
+ struct sockaddr_in *sa4;
+
+ switch(sa->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
+ /* just use the scope field of the multicast address */
+ return(sa6->sin6_addr.s6_addr[2] & 0x0f);
+ }
+ /*
+ * Unicast addresses: map scope type to corresponding scope
+ * value defined for multcast addresses.
+ * XXX: hardcoded scope type values are bad...
+ */
+ if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
+ return(1); /* node local scope */
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
+ return(2); /* link-local scope */
+ if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
+ return(5); /* site-local scope */
+ return(14); /* global scope */
+ break;
+#endif
+ case AF_INET:
+ /*
+ * IPv4 pseudo scoping according to RFC 3484.
+ */
+ sa4 = (struct sockaddr_in *)sa;
+ /* IPv4 autoconfiguration addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 169 &&
+ ((u_char *)&sa4->sin_addr)[1] == 254)
+ return(2);
+ /* Private addresses have site-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 10 ||
+ (((u_char *)&sa4->sin_addr)[0] == 172 &&
+ (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
+ (((u_char *)&sa4->sin_addr)[0] == 192 &&
+ ((u_char *)&sa4->sin_addr)[1] == 168))
+ return(14); /* XXX: It should be 5 unless NAT */
+ /* Loopback addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 127)
+ return(2);
+ return(14);
+ break;
+ default:
+ errno = EAFNOSUPPORT; /* is this a good error? */
+ return(-1);
+ }
+}
diff --git a/freebsd/lib/libc/net/netdb_private.h b/freebsd/lib/libc/net/netdb_private.h
new file mode 100644
index 00000000..9892c010
--- /dev/null
+++ b/freebsd/lib/libc/net/netdb_private.h
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (C) 2005 The FreeBSD Project. 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 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 _NETDB_PRIVATE_H_
+#define _NETDB_PRIVATE_H_
+
+#include <stdio.h> /* XXX: for FILE */
+
+#define NETDB_THREAD_ALLOC(name) \
+static thread_key_t name##_key; \
+static once_t name##_init_once = ONCE_INITIALIZER; \
+static int name##_thr_keycreated = 0; \
+\
+static void name##_free(void *); \
+\
+static void \
+name##_keycreate(void) \
+{ \
+ name##_thr_keycreated = \
+ (thr_keycreate(&name##_key, name##_free) == 0); \
+} \
+\
+struct name * \
+__##name##_init(void) \
+{ \
+ struct name *he; \
+ \
+ if (thr_once(&name##_init_once, name##_keycreate) != 0 || \
+ !name##_thr_keycreated) \
+ return (NULL); \
+ if ((he = thr_getspecific(name##_key)) != NULL) \
+ return (he); \
+ if ((he = calloc(1, sizeof(*he))) == NULL) \
+ return (NULL); \
+ if (thr_setspecific(name##_key, he) == 0) \
+ return (he); \
+ free(he); \
+ return (NULL); \
+}
+
+#define _MAXALIASES 35
+#define _MAXLINELEN 1024
+#define _MAXADDRS 35
+#define _HOSTBUFSIZE (8 * 1024)
+#define _NETBUFSIZE 1025
+
+struct hostent_data {
+ uint32_t host_addr[4]; /* IPv4 or IPv6 */
+ char *h_addr_ptrs[_MAXADDRS + 1];
+ char *host_aliases[_MAXALIASES];
+ char hostbuf[_HOSTBUFSIZE];
+ FILE *hostf;
+ int stayopen;
+#ifdef YP
+ char *yp_domain;
+#endif
+};
+
+struct netent_data {
+ char *net_aliases[_MAXALIASES];
+ char netbuf[_NETBUFSIZE];
+ FILE *netf;
+ int stayopen;
+#ifdef YP
+ char *yp_domain;
+#endif
+};
+
+struct protoent_data {
+ FILE *fp;
+ char *aliases[_MAXALIASES];
+ int stayopen;
+ char line[_MAXLINELEN + 1];
+};
+
+struct hostdata {
+ struct hostent host;
+ char data[sizeof(struct hostent_data)];
+};
+
+struct netdata {
+ struct netent net;
+ char data[sizeof(struct netent_data)];
+};
+
+struct protodata {
+ struct protoent proto;
+ char data[sizeof(struct protoent_data)];
+};
+
+struct hostdata *__hostdata_init(void);
+struct hostent *__hostent_init(void);
+struct hostent_data *__hostent_data_init(void);
+struct netdata *__netdata_init(void);
+struct netent_data *__netent_data_init(void);
+struct protodata *__protodata_init(void);
+struct protoent_data *__protoent_data_init(void);
+int __copy_hostent(struct hostent *, struct hostent *, char *, size_t);
+int __copy_netent(struct netent *, struct netent *, char *, size_t);
+int __copy_protoent(struct protoent *, struct protoent *, char *, size_t);
+
+void __endprotoent_p(struct protoent_data *);
+int __getprotoent_p(struct protoent *, struct protoent_data *);
+void __setprotoent_p(int, struct protoent_data *);
+void _endhostdnsent(void);
+void _endhosthtent(struct hostent_data *);
+void _endnetdnsent(void);
+void _endnethtent(struct netent_data *);
+struct hostent *_gethostbynisaddr(const void *, socklen_t, int);
+struct hostent *_gethostbynisname(const char *, int);
+void _map_v4v6_address(const char *, char *);
+void _map_v4v6_hostent(struct hostent *, char **, char *);
+void _sethostdnsent(int);
+void _sethosthtent(int, struct hostent_data *);
+void _setnetdnsent(int);
+void _setnethtent(int, struct netent_data *);
+
+#endif /* _NETDB_PRIVATE_H_ */
diff --git a/freebsd/lib/libc/net/nsdispatch.c b/freebsd/lib/libc/net/nsdispatch.c
new file mode 100644
index 00000000..dcd7438f
--- /dev/null
+++ b/freebsd/lib/libc/net/nsdispatch.c
@@ -0,0 +1,778 @@
+#include "port_before.h"
+
+/* $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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 "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#ifndef __rtems__
+#include <dlfcn.h>
+#else
+#include <stdint.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "nss_tls.h"
+#include "libc_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+enum _nss_constants {
+ /* Number of elements allocated when we grow a vector */
+ ELEMSPERCHUNK = 8
+};
+
+/*
+ * Global NSS data structures are mostly read-only, but we update
+ * them when we read or re-read the nsswitch.conf.
+ */
+static pthread_rwlock_t nss_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/*
+ * Runtime determination of whether we are dynamically linked or not.
+ */
+extern int _DYNAMIC __attribute__ ((weak));
+#define is_dynamic() (&_DYNAMIC != NULL)
+
+/*
+ * default sourcelist: `files'
+ */
+const ns_src __nsdefaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { 0 },
+};
+
+/* Database, source mappings. */
+static unsigned int _nsmapsize;
+static ns_dbt *_nsmap = NULL;
+
+/* NSS modules. */
+static unsigned int _nsmodsize;
+static ns_mod *_nsmod;
+
+/* Placeholder for builtin modules' dlopen `handle'. */
+static int __nss_builtin_handle;
+static void *nss_builtin_handle = &__nss_builtin_handle;
+
+#ifdef NS_CACHING
+/*
+ * Cache lookup cycle prevention function - if !NULL then no cache lookups
+ * will be made
+ */
+static void *nss_cache_cycle_prevention_func = NULL;
+#endif
+
+/*
+ * When this is set to 1, nsdispatch won't use nsswitch.conf
+ * but will consult the 'defaults' source list only.
+ * NOTE: nested fallbacks (when nsdispatch calls fallback functions,
+ * which in turn calls nsdispatch, which should call fallback
+ * function) are not supported
+ */
+struct fb_state {
+ int fb_dispatch;
+};
+static void fb_endstate(void *);
+NSS_TLS_HANDLING(fb);
+
+/*
+ * Attempt to spew relatively uniform messages to syslog.
+ */
+#define nss_log(level, fmt, ...) \
+ syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__)
+#define nss_log_simple(level, s) \
+ syslog((level), "NSSWITCH(%s): " s, __func__)
+
+/*
+ * Dynamically growable arrays are used for lists of databases, sources,
+ * and modules. The following `vector' interface is used to isolate the
+ * common operations.
+ */
+typedef int (*vector_comparison)(const void *, const void *);
+typedef void (*vector_free_elem)(void *);
+static void vector_sort(void *, unsigned int, size_t,
+ vector_comparison);
+static void vector_free(void *, unsigned int *, size_t,
+ vector_free_elem);
+static void *vector_ref(unsigned int, void *, unsigned int, size_t);
+static void *vector_search(const void *, void *, unsigned int, size_t,
+ vector_comparison);
+static void *vector_append(const void *, void *, unsigned int *, size_t);
+
+
+/*
+ * Internal interfaces.
+ */
+static int string_compare(const void *, const void *);
+static int mtab_compare(const void *, const void *);
+static int nss_configure(void);
+static void ns_dbt_free(ns_dbt *);
+static void ns_mod_free(ns_mod *);
+static void ns_src_free(ns_src **, int);
+static void nss_load_builtin_modules(void);
+static void nss_load_module(const char *, nss_module_register_fn);
+static void nss_atexit(void);
+/* nsparser */
+extern FILE *_nsyyin;
+
+
+/*
+ * The vector operations
+ */
+static void
+vector_sort(void *vec, unsigned int count, size_t esize,
+ vector_comparison comparison)
+{
+ qsort(vec, count, esize, comparison);
+}
+
+
+static void *
+vector_search(const void *key, void *vec, unsigned int count, size_t esize,
+ vector_comparison comparison)
+{
+ return (bsearch(key, vec, count, esize, comparison));
+}
+
+
+static void *
+vector_append(const void *elem, void *vec, unsigned int *count, size_t esize)
+{
+ void *p;
+
+ if ((*count % ELEMSPERCHUNK) == 0) {
+ p = realloc(vec, (*count + ELEMSPERCHUNK) * esize);
+ if (p == NULL) {
+ nss_log_simple(LOG_ERR, "memory allocation failure");
+ return (vec);
+ }
+ vec = p;
+ }
+ memmove((void *)(((uintptr_t)vec) + (*count * esize)), elem, esize);
+ (*count)++;
+ return (vec);
+}
+
+
+static void *
+vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize)
+{
+ if (i < count)
+ return (void *)((uintptr_t)vec + (i * esize));
+ else
+ return (NULL);
+}
+
+
+#define VECTOR_FREE(v, c, s, f) \
+ do { vector_free(v, c, s, f); v = NULL; } while (0)
+static void
+vector_free(void *vec, unsigned int *count, size_t esize,
+ vector_free_elem free_elem)
+{
+ unsigned int i;
+ void *elem;
+
+ for (i = 0; i < *count; i++) {
+ elem = vector_ref(i, vec, *count, esize);
+ if (elem != NULL)
+ free_elem(elem);
+ }
+ free(vec);
+ *count = 0;
+}
+
+/*
+ * Comparison functions for vector_search.
+ */
+static int
+string_compare(const void *a, const void *b)
+{
+ return (strcasecmp(*(const char * const *)a, *(const char * const *)b));
+}
+
+
+static int
+mtab_compare(const void *a, const void *b)
+{
+ int cmp;
+
+ cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name);
+ if (cmp != 0)
+ return (cmp);
+ else
+ return (strcmp(((const ns_mtab *)a)->database,
+ ((const ns_mtab *)b)->database));
+}
+
+/*
+ * NSS nsmap management.
+ */
+void
+_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src)
+{
+ const ns_mod *modp;
+
+ dbt->srclist = vector_append(src, dbt->srclist, &dbt->srclistsize,
+ sizeof(*src));
+ modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod),
+ string_compare);
+ if (modp == NULL)
+ nss_load_module(src->name, NULL);
+}
+
+
+#ifdef _NSS_DEBUG
+void
+_nsdbtdump(const ns_dbt *dbt)
+{
+ int i;
+
+ printf("%s (%d source%s):", dbt->name, dbt->srclistsize,
+ dbt->srclistsize == 1 ? "" : "s");
+ for (i = 0; i < (int)dbt->srclistsize; i++) {
+ printf(" %s", dbt->srclist[i].name);
+ if (!(dbt->srclist[i].flags &
+ (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) &&
+ (dbt->srclist[i].flags & NS_SUCCESS))
+ continue;
+ printf(" [");
+ if (!(dbt->srclist[i].flags & NS_SUCCESS))
+ printf(" SUCCESS=continue");
+ if (dbt->srclist[i].flags & NS_UNAVAIL)
+ printf(" UNAVAIL=return");
+ if (dbt->srclist[i].flags & NS_NOTFOUND)
+ printf(" NOTFOUND=return");
+ if (dbt->srclist[i].flags & NS_TRYAGAIN)
+ printf(" TRYAGAIN=return");
+ printf(" ]");
+ }
+ printf("\n");
+}
+#endif
+
+
+/*
+ * The first time nsdispatch is called (during a process's lifetime,
+ * or after nsswitch.conf has been updated), nss_configure will
+ * prepare global data needed by NSS.
+ */
+static int
+nss_configure(void)
+{
+ static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
+ static time_t confmod;
+ struct stat statbuf;
+ int result, isthreaded;
+ const char *path;
+#ifdef NS_CACHING
+ void *handle;
+#endif
+
+ result = 0;
+ isthreaded = __isthreaded;
+#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT)
+ /* NOTE WELL: THIS IS A SECURITY HOLE. This must only be built
+ * for debugging purposes and MUST NEVER be used in production.
+ */
+ path = getenv("NSSWITCH_CONF");
+ if (path == NULL)
+#endif
+ path = _PATH_NS_CONF;
+ if (stat(path, &statbuf) != 0)
+ return (0);
+ if (statbuf.st_mtime <= confmod)
+ return (0);
+ if (isthreaded) {
+ result = _pthread_mutex_trylock(&conf_lock);
+ if (result != 0)
+ return (0);
+ (void)_pthread_rwlock_unlock(&nss_lock);
+ result = _pthread_rwlock_wrlock(&nss_lock);
+ if (result != 0)
+ goto fin2;
+ }
+ _nsyyin = fopen(path, "r");
+ if (_nsyyin == NULL)
+ goto fin;
+ VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+ (vector_free_elem)ns_dbt_free);
+ VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+ (vector_free_elem)ns_mod_free);
+ nss_load_builtin_modules();
+ _nsyyparse();
+ (void)fclose(_nsyyin);
+ vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare);
+ if (confmod == 0)
+ (void)atexit(nss_atexit);
+ confmod = statbuf.st_mtime;
+
+#ifdef NS_CACHING
+ handle = libc_dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+ if (handle != NULL) {
+ nss_cache_cycle_prevention_func = dlsym(handle,
+ "_nss_cache_cycle_prevention_function");
+ dlclose(handle);
+ }
+#endif
+fin:
+ if (isthreaded) {
+ (void)_pthread_rwlock_unlock(&nss_lock);
+ if (result == 0)
+ result = _pthread_rwlock_rdlock(&nss_lock);
+ }
+fin2:
+ if (isthreaded)
+ (void)_pthread_mutex_unlock(&conf_lock);
+ return (result);
+}
+
+
+void
+_nsdbtput(const ns_dbt *dbt)
+{
+ unsigned int i;
+ ns_dbt *p;
+
+ for (i = 0; i < _nsmapsize; i++) {
+ p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap));
+ if (string_compare(&dbt->name, &p->name) == 0) {
+ /* overwrite existing entry */
+ if (p->srclist != NULL)
+ ns_src_free(&p->srclist, p->srclistsize);
+ memmove(p, dbt, sizeof(*dbt));
+ return;
+ }
+ }
+ _nsmap = vector_append(dbt, _nsmap, &_nsmapsize, sizeof(*_nsmap));
+}
+
+
+static void
+ns_dbt_free(ns_dbt *dbt)
+{
+ ns_src_free(&dbt->srclist, dbt->srclistsize);
+ if (dbt->name)
+ free((void *)dbt->name);
+}
+
+
+static void
+ns_src_free(ns_src **src, int srclistsize)
+{
+ int i;
+
+ for (i = 0; i < srclistsize; i++)
+ if ((*src)[i].name != NULL)
+ /* This one was allocated by nslexer. You'll just
+ * have to trust me.
+ */
+ free((void *)((*src)[i].name));
+ free(*src);
+ *src = NULL;
+}
+
+
+
+/*
+ * NSS module management.
+ */
+/* The built-in NSS modules are all loaded at once. */
+#define NSS_BACKEND(name, reg) \
+ns_mtab *reg(unsigned int *, nss_module_unregister_fn *);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+
+static void
+nss_load_builtin_modules(void)
+{
+#define NSS_BACKEND(name, reg) nss_load_module(#name, reg);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+}
+
+
+/* Load a built-in or dynamically linked module. If the `reg_fn'
+ * argument is non-NULL, assume a built-in module and use reg_fn to
+ * register it. Otherwise, search for a dynamic NSS module.
+ */
+static void
+nss_load_module(const char *source, nss_module_register_fn reg_fn)
+{
+ char buf[PATH_MAX];
+ ns_mod mod;
+ nss_module_register_fn fn;
+
+ memset(&mod, 0, sizeof(mod));
+ mod.name = strdup(source);
+ if (mod.name == NULL) {
+ nss_log_simple(LOG_ERR, "memory allocation failure");
+ return;
+ }
+ if (reg_fn != NULL) {
+ /* The placeholder is required, as a NULL handle
+ * represents an invalid module.
+ */
+ mod.handle = nss_builtin_handle;
+ fn = reg_fn;
+ } else if (!is_dynamic())
+ goto fin;
+#ifndef __rtems__
+ else {
+ if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name,
+ NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf))
+ goto fin;
+ mod.handle = libc_dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
+ if (mod.handle == NULL) {
+#ifdef _NSS_DEBUG
+ /* This gets pretty annoying since the built-in
+ * sources aren't modules yet.
+ */
+ nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror());
+#endif
+ goto fin;
+ }
+ fn = (nss_module_register_fn)dlfunc(mod.handle,
+ "nss_module_register");
+ if (fn == NULL) {
+ (void)dlclose(mod.handle);
+ mod.handle = NULL;
+ nss_log(LOG_ERR, "%s, %s", mod.name, dlerror());
+ goto fin;
+ }
+ }
+#endif
+ mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister);
+ if (mod.mtab == NULL || mod.mtabsize == 0) {
+#ifndef __rtems__
+ if (mod.handle != nss_builtin_handle)
+ (void)dlclose(mod.handle);
+#endif
+ mod.handle = NULL;
+ nss_log(LOG_ERR, "%s, registration failed", mod.name);
+ goto fin;
+ }
+ if (mod.mtabsize > 1)
+ qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]),
+ mtab_compare);
+fin:
+ _nsmod = vector_append(&mod, _nsmod, &_nsmodsize, sizeof(*_nsmod));
+ vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare);
+}
+
+
+
+static void
+ns_mod_free(ns_mod *mod)
+{
+
+ free(mod->name);
+ if (mod->handle == NULL)
+ return;
+ if (mod->unregister != NULL)
+ mod->unregister(mod->mtab, mod->mtabsize);
+#ifndef __rtems__
+ if (mod->handle != nss_builtin_handle)
+ (void)dlclose(mod->handle);
+#endif
+}
+
+
+
+/*
+ * Cleanup
+ */
+static void
+nss_atexit(void)
+{
+ int isthreaded;
+
+ isthreaded = __isthreaded;
+ if (isthreaded)
+ (void)_pthread_rwlock_wrlock(&nss_lock);
+ VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+ (vector_free_elem)ns_dbt_free);
+ VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+ (vector_free_elem)ns_mod_free);
+ if (isthreaded)
+ (void)_pthread_rwlock_unlock(&nss_lock);
+}
+
+
+
+/*
+ * Finally, the actual implementation.
+ */
+static nss_method
+nss_method_lookup(const char *source, const char *database,
+ const char *method, const ns_dtab disp_tab[], void **mdata)
+{
+ ns_mod *mod;
+ ns_mtab *match, key;
+ int i;
+
+ if (disp_tab != NULL)
+ for (i = 0; disp_tab[i].src != NULL; i++)
+ if (strcasecmp(source, disp_tab[i].src) == 0) {
+ *mdata = disp_tab[i].mdata;
+ return (disp_tab[i].method);
+ }
+ mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod),
+ string_compare);
+ if (mod != NULL && mod->handle != NULL) {
+ key.database = database;
+ key.name = method;
+ match = bsearch(&key, mod->mtab, mod->mtabsize,
+ sizeof(mod->mtab[0]), mtab_compare);
+ if (match != NULL) {
+ *mdata = match->mdata;
+ return (match->method);
+ }
+ }
+
+ *mdata = NULL;
+ return (NULL);
+}
+
+static void
+fb_endstate(void *p)
+{
+ free(p);
+}
+
+__weak_reference(_nsdispatch, nsdispatch);
+
+int
+_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
+ const char *method_name, const ns_src defaults[], ...)
+{
+ va_list ap;
+ const ns_dbt *dbt;
+ const ns_src *srclist;
+ nss_method method, fb_method;
+ void *mdata;
+ int isthreaded, serrno, i, result, srclistsize;
+ struct fb_state *st;
+
+#ifdef NS_CACHING
+ nss_cache_data cache_data;
+ nss_cache_data *cache_data_p;
+ int cache_flag;
+#endif
+
+ dbt = NULL;
+ fb_method = NULL;
+
+ isthreaded = __isthreaded;
+ serrno = errno;
+ if (isthreaded) {
+ result = _pthread_rwlock_rdlock(&nss_lock);
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
+ }
+
+ result = fb_getstate(&st);
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
+
+ result = nss_configure();
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
+ if (st->fb_dispatch == 0) {
+ dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
+ string_compare);
+ fb_method = nss_method_lookup(NSSRC_FALLBACK, database,
+ method_name, disp_tab, &mdata);
+ }
+
+ if (dbt != NULL) {
+ srclist = dbt->srclist;
+ srclistsize = dbt->srclistsize;
+ } else {
+ srclist = defaults;
+ srclistsize = 0;
+ while (srclist[srclistsize].name != NULL)
+ srclistsize++;
+ }
+
+#ifdef NS_CACHING
+ cache_data_p = NULL;
+ cache_flag = 0;
+#endif
+ for (i = 0; i < srclistsize; i++) {
+ result = NS_NOTFOUND;
+ method = nss_method_lookup(srclist[i].name, database,
+ method_name, disp_tab, &mdata);
+
+ if (method != NULL) {
+#ifdef NS_CACHING
+ if (strcmp(srclist[i].name, NSSRC_CACHE) == 0 &&
+ nss_cache_cycle_prevention_func == NULL) {
+#ifdef NS_STRICT_LIBC_EID_CHECKING
+ if (issetugid() != 0)
+ continue;
+#endif
+ cache_flag = 1;
+
+ memset(&cache_data, 0, sizeof(nss_cache_data));
+ cache_data.info = (nss_cache_info const *)mdata;
+ cache_data_p = &cache_data;
+
+ va_start(ap, defaults);
+ if (cache_data.info->id_func != NULL)
+ result = __nss_common_cache_read(retval,
+ cache_data_p, ap);
+ else if (cache_data.info->marshal_func != NULL)
+ result = __nss_mp_cache_read(retval,
+ cache_data_p, ap);
+ else
+ result = __nss_mp_cache_end(retval,
+ cache_data_p, ap);
+ va_end(ap);
+ } else {
+ cache_flag = 0;
+ errno = 0;
+ va_start(ap, defaults);
+ result = method(retval, mdata, ap);
+ va_end(ap);
+ }
+#else /* NS_CACHING */
+ errno = 0;
+ va_start(ap, defaults);
+ result = method(retval, mdata, ap);
+ va_end(ap);
+#endif /* NS_CACHING */
+
+ if (result & (srclist[i].flags))
+ break;
+ } else {
+ if (fb_method != NULL) {
+ st->fb_dispatch = 1;
+ va_start(ap, defaults);
+ result = fb_method(retval,
+ (void *)srclist[i].name, ap);
+ va_end(ap);
+ st->fb_dispatch = 0;
+ } else
+ nss_log(LOG_DEBUG, "%s, %s, %s, not found, "
+ "and no fallback provided",
+ srclist[i].name, database, method_name);
+ }
+ }
+
+#ifdef NS_CACHING
+ if (cache_data_p != NULL &&
+ (result & (NS_NOTFOUND | NS_SUCCESS)) && cache_flag == 0) {
+ va_start(ap, defaults);
+ if (result == NS_SUCCESS) {
+ if (cache_data.info->id_func != NULL)
+ __nss_common_cache_write(retval, cache_data_p,
+ ap);
+ else if (cache_data.info->marshal_func != NULL)
+ __nss_mp_cache_write(retval, cache_data_p, ap);
+ } else if (result == NS_NOTFOUND) {
+ if (cache_data.info->id_func == NULL) {
+ if (cache_data.info->marshal_func != NULL)
+ __nss_mp_cache_write_submit(retval,
+ cache_data_p, ap);
+ } else
+ __nss_common_cache_write_negative(cache_data_p);
+ }
+ va_end(ap);
+ }
+#endif /* NS_CACHING */
+
+ if (isthreaded)
+ (void)_pthread_rwlock_unlock(&nss_lock);
+fin:
+ errno = serrno;
+ return (result);
+}
diff --git a/freebsd/lib/libc/net/nslexer.l b/freebsd/lib/libc/net/nslexer.l
new file mode 100644
index 00000000..34c79d92
--- /dev/null
+++ b/freebsd/lib/libc/net/nslexer.l
@@ -0,0 +1,119 @@
+%{
+/* $NetBSD: nslexer.l,v 1.3 1999/01/25 00:16:17 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid =
+ "$FreeBSD$";
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+#include <ctype.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "nsparser.h"
+
+#define YY_NO_UNPUT
+
+%}
+
+%option yylineno
+
+BLANK [ \t]
+CR \n
+STRING [a-zA-Z][a-zA-Z0-9_]*
+
+%%
+
+{BLANK}+ ; /* skip whitespace */
+
+#.* ; /* skip comments */
+
+\\{CR} ; /* allow continuation */
+
+{CR} return NL;
+
+[sS][uU][cC][cC][eE][sS][sS] return SUCCESS;
+[uU][nN][aA][vV][aA][iI][lL] return UNAVAIL;
+[nN][oO][tT][fF][oO][uU][nN][dD] return NOTFOUND;
+[tT][rR][yY][aA][gG][aA][iI][nN] return TRYAGAIN;
+
+[rR][eE][tT][uU][rR][nN] return RETURN;
+[cC][oO][nN][tT][iI][nN][uU][eE] return CONTINUE;
+
+{STRING} {
+ char *p;
+ int i;
+
+ if ((p = strdup(yytext)) == NULL) {
+ syslog(LOG_ERR,
+ "NSSWITCH(nslexer): memory allocation failure");
+ return ERRORTOKEN;
+ }
+ for (i = 0; i < strlen(p); i++) {
+ if (isupper((unsigned char)p[i]))
+ p[i] = tolower((unsigned char)p[i]);
+ }
+ _nsyylval.str = p;
+ return STRING;
+ }
+
+. return yytext[0];
+
+%%
+
+#undef _nsyywrap
+int
+_nsyywrap()
+{
+ return 1;
+} /* _nsyywrap */
+
+void
+_nsyyerror(msg)
+ const char *msg;
+{
+
+ syslog(LOG_ERR, "NSSWITCH(nslexer): %s line %d: %s at '%s'",
+ _PATH_NS_CONF, yylineno, msg, yytext);
+} /* _nsyyerror */
diff --git a/freebsd/lib/libc/net/nsparser.y b/freebsd/lib/libc/net/nsparser.y
new file mode 100644
index 00000000..730458a3
--- /dev/null
+++ b/freebsd/lib/libc/net/nsparser.y
@@ -0,0 +1,184 @@
+%{
+/* $NetBSD: nsparser.y,v 1.3 1999/01/25 00:16:18 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+static void _nsaddsrctomap(const char *);
+
+static ns_dbt curdbt;
+static ns_src cursrc;
+%}
+
+%union {
+ char *str;
+ int mapval;
+}
+
+%token NL
+%token SUCCESS UNAVAIL NOTFOUND TRYAGAIN
+%token RETURN CONTINUE
+%token ERRORTOKEN
+%token <str> STRING
+
+%type <mapval> Status Action
+
+%%
+
+File
+ : /* empty */
+ | Lines
+ ;
+
+Lines
+ : Entry
+ | Lines Entry
+ ;
+
+Entry
+ : NL
+ | Database ':' NL
+ {
+ free((char*)curdbt.name);
+ }
+ | Database ':' Srclist NL
+ {
+ _nsdbtput(&curdbt);
+ }
+ | error NL
+ {
+ yyerrok;
+ }
+ ;
+
+Database
+ : STRING
+ {
+ curdbt.name = yylval.str;
+ curdbt.srclist = NULL;
+ curdbt.srclistsize = 0;
+ }
+ ;
+
+Srclist
+ : Item
+ | Srclist Item
+ ;
+
+Item
+ : STRING
+ {
+ cursrc.flags = NS_TERMINATE;
+ _nsaddsrctomap($1);
+ }
+ | STRING '[' { cursrc.flags = NS_SUCCESS; } Criteria ']'
+ {
+ _nsaddsrctomap($1);
+ }
+ ;
+
+Criteria
+ : Criterion
+ | Criteria Criterion
+ ;
+
+Criterion
+ : Status '=' Action
+ {
+ if ($3) /* if action == RETURN set RETURN bit */
+ cursrc.flags |= $1;
+ else /* else unset it */
+ cursrc.flags &= ~$1;
+ }
+ ;
+
+Status
+ : SUCCESS { $$ = NS_SUCCESS; }
+ | UNAVAIL { $$ = NS_UNAVAIL; }
+ | NOTFOUND { $$ = NS_NOTFOUND; }
+ | TRYAGAIN { $$ = NS_TRYAGAIN; }
+ ;
+
+Action
+ : RETURN { $$ = NS_ACTION_RETURN; }
+ | CONTINUE { $$ = NS_ACTION_CONTINUE; }
+ ;
+
+%%
+
+static void
+_nsaddsrctomap(elem)
+ const char *elem;
+{
+ int i, lineno;
+ extern int _nsyylineno;
+ extern char * _nsyytext;
+
+ lineno = _nsyylineno - (*_nsyytext == '\n' ? 1 : 0);
+ if (curdbt.srclistsize > 0) {
+ if (((strcasecmp(elem, NSSRC_COMPAT) == 0) &&
+ (strcasecmp(curdbt.srclist[0].name, NSSRC_CACHE) != 0)) ||
+ (strcasecmp(curdbt.srclist[0].name, NSSRC_COMPAT) == 0)) {
+ syslog(LOG_ERR,
+ "NSSWITCH(nsparser): %s line %d: 'compat' used with sources, other than 'cache'",
+ _PATH_NS_CONF, lineno);
+ free((void*)elem);
+ return;
+ }
+ }
+ for (i = 0; i < curdbt.srclistsize; i++) {
+ if (strcasecmp(curdbt.srclist[i].name, elem) == 0) {
+ syslog(LOG_ERR,
+ "NSSWITCH(nsparser): %s line %d: duplicate source '%s'",
+ _PATH_NS_CONF, lineno, elem);
+ free((void*)elem);
+ return;
+ }
+ }
+ cursrc.name = elem;
+ _nsdbtaddsrc(&curdbt, &cursrc);
+}
diff --git a/freebsd/lib/libc/net/nss_backends.h b/freebsd/lib/libc/net/nss_backends.h
new file mode 100644
index 00000000..9bea37b1
--- /dev/null
+++ b/freebsd/lib/libc/net/nss_backends.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * 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$
+ */
+/*
+ * Eventually, the implementations of existing built-in NSS functions
+ * may be moved into NSS modules and live here.
+ */
+#if 0
+NSS_BACKEND( files, _files_nss_module_register )
+NSS_BACKEND( dns, _dns_nss_module_register )
+NSS_BACKEND( nis, _nis_nss_module_register )
+NSS_BACKEND( compat, _compat_nss_module_register )
+#endif
diff --git a/freebsd/lib/libc/net/rcmd.c b/freebsd/lib/libc/net/rcmd.c
new file mode 100644
index 00000000..1045e88b
--- /dev/null
+++ b/freebsd/lib/libc/net/rcmd.c
@@ -0,0 +1,763 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <arpa/nameser.h>
+#include "un-namespace.h"
+
+extern int innetgr( const char *, const char *, const char *, const char * );
+
+#define max(a, b) ((a > b) ? a : b)
+
+int __ivaliduser(FILE *, u_int32_t, const char *, const char *);
+int __ivaliduser_af(FILE *,const void *, const char *, const char *, int, int);
+int __ivaliduser_sa(FILE *, const struct sockaddr *, socklen_t, const char *,
+ const char *);
+static int __icheckhost(const struct sockaddr *, socklen_t, const char *);
+
+char paddr[NI_MAXHOST];
+
+int
+rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
+ char **ahost;
+ u_short rport;
+ const char *locuser, *remuser, *cmd;
+ int *fd2p;
+{
+ return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
+}
+
+int
+rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
+ char **ahost;
+ u_short rport;
+ const char *locuser, *remuser, *cmd;
+ int *fd2p;
+ int af;
+{
+ struct addrinfo hints, *res, *ai;
+ struct sockaddr_storage from;
+ fd_set reads;
+ sigset_t oldmask, newmask;
+ pid_t pid;
+ int s, aport, lport, timo, error;
+ char c, *p;
+ int refused, nres;
+ char num[8];
+ static char canonnamebuf[MAXDNAME]; /* is it proper here? */
+
+ /* call rcmdsh() with specified remote shell if appropriate. */
+ if (!issetugid() && (p = getenv("RSH"))) {
+ struct servent *sp = getservbyname("shell", "tcp");
+
+ if (sp && sp->s_port == rport)
+ return (rcmdsh(ahost, rport, locuser, remuser,
+ cmd, p));
+ }
+
+ /* use rsh(1) if non-root and remote port is shell. */
+ if (geteuid()) {
+ struct servent *sp = getservbyname("shell", "tcp");
+
+ if (sp && sp->s_port == rport)
+ return (rcmdsh(ahost, rport, locuser, remuser,
+ cmd, NULL));
+ }
+
+ pid = getpid();
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ (void)snprintf(num, sizeof(num), "%d", ntohs(rport));
+ error = getaddrinfo(*ahost, num, &hints, &res);
+ if (error) {
+ fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+ gai_strerror(error));
+ if (error == EAI_SYSTEM)
+ fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+
+ if (res->ai_canonname
+ && strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) {
+ strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf));
+ *ahost = canonnamebuf;
+ }
+ nres = 0;
+ for (ai = res; ai; ai = ai->ai_next)
+ nres++;
+ ai = res;
+ refused = 0;
+ sigemptyset(&newmask);
+ sigaddset(&newmask, SIGURG);
+ _sigprocmask(SIG_BLOCK, (const sigset_t *)&newmask, &oldmask);
+ for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
+ s = rresvport_af(&lport, ai->ai_family);
+ if (s < 0) {
+ if (errno != EAGAIN && ai->ai_next) {
+ ai = ai->ai_next;
+ continue;
+ }
+ if (errno == EAGAIN)
+ (void)fprintf(stderr,
+ "rcmd: socket: All ports in use\n");
+ else
+ (void)fprintf(stderr, "rcmd: socket: %s\n",
+ strerror(errno));
+ freeaddrinfo(res);
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
+ NULL);
+ return (-1);
+ }
+ _fcntl(s, F_SETOWN, pid);
+ if (_connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
+ break;
+ (void)_close(s);
+ if (errno == EADDRINUSE) {
+ lport--;
+ continue;
+ }
+ if (errno == ECONNREFUSED)
+ refused = 1;
+ if (ai->ai_next == NULL && (!refused || timo > 16)) {
+ (void)fprintf(stderr, "%s: %s\n",
+ *ahost, strerror(errno));
+ freeaddrinfo(res);
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
+ NULL);
+ return (-1);
+ }
+ if (nres > 1) {
+ int oerrno = errno;
+
+ getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
+ sizeof(paddr), NULL, 0, NI_NUMERICHOST);
+ (void)fprintf(stderr, "connect to address %s: ",
+ paddr);
+ errno = oerrno;
+ perror(0);
+ }
+ if ((ai = ai->ai_next) == NULL) {
+ /* refused && timo <= 16 */
+ struct timespec time_to_sleep, time_remaining;
+
+ time_to_sleep.tv_sec = timo;
+ time_to_sleep.tv_nsec = 0;
+ (void)_nanosleep(&time_to_sleep, &time_remaining);
+ timo *= 2;
+ ai = res;
+ refused = 0;
+ }
+ if (nres > 1) {
+ getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
+ sizeof(paddr), NULL, 0, NI_NUMERICHOST);
+ fprintf(stderr, "Trying %s...\n", paddr);
+ }
+ }
+ lport--;
+ if (fd2p == 0) {
+ _write(s, "", 1);
+ lport = 0;
+ } else {
+ int s2 = rresvport_af(&lport, ai->ai_family), s3;
+ socklen_t len = ai->ai_addrlen;
+ int nfds;
+
+ if (s2 < 0)
+ goto bad;
+ _listen(s2, 1);
+ (void)snprintf(num, sizeof(num), "%d", lport);
+ if (_write(s, num, strlen(num)+1) != strlen(num)+1) {
+ (void)fprintf(stderr,
+ "rcmd: write (setting up stderr): %s\n",
+ strerror(errno));
+ (void)_close(s2);
+ goto bad;
+ }
+ nfds = max(s, s2)+1;
+ if(nfds > FD_SETSIZE) {
+ fprintf(stderr, "rcmd: too many files\n");
+ (void)_close(s2);
+ goto bad;
+ }
+again:
+ FD_ZERO(&reads);
+ FD_SET(s, &reads);
+ FD_SET(s2, &reads);
+ errno = 0;
+ if (_select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
+ if (errno != 0)
+ (void)fprintf(stderr,
+ "rcmd: select (setting up stderr): %s\n",
+ strerror(errno));
+ else
+ (void)fprintf(stderr,
+ "select: protocol failure in circuit setup\n");
+ (void)_close(s2);
+ goto bad;
+ }
+ s3 = _accept(s2, (struct sockaddr *)&from, &len);
+ switch (from.ss_family) {
+ case AF_INET:
+ aport = ntohs(((struct sockaddr_in *)&from)->sin_port);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
+ break;
+#endif
+ default:
+ aport = 0; /* error */
+ break;
+ }
+ /*
+ * XXX careful for ftp bounce attacks. If discovered, shut them
+ * down and check for the real auxiliary channel to connect.
+ */
+ if (aport == 20) {
+ _close(s3);
+ goto again;
+ }
+ (void)_close(s2);
+ if (s3 < 0) {
+ (void)fprintf(stderr,
+ "rcmd: accept: %s\n", strerror(errno));
+ lport = 0;
+ goto bad;
+ }
+ *fd2p = s3;
+ if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {
+ (void)fprintf(stderr,
+ "socket: protocol failure in circuit setup.\n");
+ goto bad2;
+ }
+ }
+ (void)_write(s, locuser, strlen(locuser)+1);
+ (void)_write(s, remuser, strlen(remuser)+1);
+ (void)_write(s, cmd, strlen(cmd)+1);
+ if (_read(s, &c, 1) != 1) {
+ (void)fprintf(stderr,
+ "rcmd: %s: %s\n", *ahost, strerror(errno));
+ goto bad2;
+ }
+ if (c != 0) {
+ while (_read(s, &c, 1) == 1) {
+ (void)_write(STDERR_FILENO, &c, 1);
+ if (c == '\n')
+ break;
+ }
+ goto bad2;
+ }
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
+ freeaddrinfo(res);
+ return (s);
+bad2:
+ if (lport)
+ (void)_close(*fd2p);
+bad:
+ (void)_close(s);
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
+ freeaddrinfo(res);
+ return (-1);
+}
+
+int
+rresvport(port)
+ int *port;
+{
+ return rresvport_af(port, AF_INET);
+}
+
+int
+rresvport_af(alport, family)
+ int *alport, family;
+{
+ int s;
+ struct sockaddr_storage ss;
+ u_short *sport;
+
+ memset(&ss, 0, sizeof(ss));
+ ss.ss_family = family;
+ switch (family) {
+ case AF_INET:
+ ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in);
+ sport = &((struct sockaddr_in *)&ss)->sin_port;
+ ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6);
+ sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
+ ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ s = _socket(ss.ss_family, SOCK_STREAM, 0);
+ if (s < 0)
+ return (-1);
+#if 0 /* compat_exact_traditional_rresvport_semantics */
+ sin.sin_port = htons((u_short)*alport);
+ if (_bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
+ (void)_close(s);
+ return (-1);
+ }
+#endif
+ *sport = 0;
+ if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {
+ (void)_close(s);
+ return (-1);
+ }
+ *alport = (int)ntohs(*sport);
+ return (s);
+}
+
+int __check_rhosts_file = 1;
+char *__rcmd_errstr;
+
+int
+ruserok(rhost, superuser, ruser, luser)
+ const char *rhost, *ruser, *luser;
+ int superuser;
+{
+ struct addrinfo hints, *res, *r;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ error = getaddrinfo(rhost, "0", &hints, &res);
+ if (error)
+ return (-1);
+
+ for (r = res; r; r = r->ai_next) {
+ if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
+ luser) == 0) {
+ freeaddrinfo(res);
+ return (0);
+ }
+ }
+ freeaddrinfo(res);
+ return (-1);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver. When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok(raddr, superuser, ruser, luser)
+ unsigned long raddr;
+ int superuser;
+ const char *ruser, *luser;
+{
+ struct sockaddr_in sin;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
+ return iruserok_sa((struct sockaddr *)&sin, sin.sin_len, superuser,
+ ruser, luser);
+}
+
+/*
+ * AF independent extension of iruserok.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok_sa(ra, rlen, superuser, ruser, luser)
+ const void *ra;
+ int rlen;
+ int superuser;
+ const char *ruser, *luser;
+{
+ char *cp;
+ struct stat sbuf;
+ struct passwd *pwd;
+ FILE *hostf;
+ uid_t uid;
+ int first;
+ char pbuf[MAXPATHLEN];
+ const struct sockaddr *raddr;
+ struct sockaddr_storage ss;
+
+ /* avoid alignment issue */
+ if (rlen > sizeof(ss))
+ return(-1);
+ memcpy(&ss, ra, rlen);
+ raddr = (struct sockaddr *)&ss;
+
+ first = 1;
+ hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) {
+ (void)fclose(hostf);
+ return (0);
+ }
+ (void)fclose(hostf);
+ }
+ if (first == 1 && (__check_rhosts_file || superuser)) {
+ first = 0;
+ if ((pwd = getpwnam(luser)) == NULL)
+ return (-1);
+ (void)strcpy(pbuf, pwd->pw_dir);
+ (void)strcat(pbuf, "/.rhosts");
+
+ /*
+ * Change effective uid while opening .rhosts. If root and
+ * reading an NFS mounted file system, can't read files that
+ * are protected read/write owner only.
+ */
+ uid = geteuid();
+ (void)seteuid(pwd->pw_uid);
+ hostf = fopen(pbuf, "r");
+ (void)seteuid(uid);
+
+ if (hostf == NULL)
+ return (-1);
+ /*
+ * If not a regular file, or is owned by someone other than
+ * user or root or if writeable by anyone but the owner, quit.
+ */
+ cp = NULL;
+ if (lstat(pbuf, &sbuf) < 0)
+ cp = ".rhosts lstat failed";
+ else if (!S_ISREG(sbuf.st_mode))
+ cp = ".rhosts not regular file";
+ else if (_fstat(fileno(hostf), &sbuf) < 0)
+ cp = ".rhosts fstat failed";
+ else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+ cp = "bad .rhosts owner";
+ else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+ cp = ".rhosts writeable by other than owner";
+ /* If there were any problems, quit. */
+ if (cp) {
+ __rcmd_errstr = cp;
+ (void)fclose(hostf);
+ return (-1);
+ }
+ goto again;
+ }
+ return (-1);
+}
+
+/*
+ * XXX
+ * Don't make static, used by lpd(8).
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+__ivaliduser(hostf, raddr, luser, ruser)
+ FILE *hostf;
+ u_int32_t raddr;
+ const char *luser, *ruser;
+{
+ struct sockaddr_in sin;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
+ return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
+ luser, ruser);
+}
+
+/*
+ * Returns 0 if ok, -1 if not ok.
+ *
+ * XXX obsolete API.
+ */
+int
+__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
+ FILE *hostf;
+ const void *raddr;
+ const char *luser, *ruser;
+ int af, len;
+{
+ struct sockaddr *sa = NULL;
+ struct sockaddr_in *sin = NULL;
+#ifdef INET6
+ struct sockaddr_in6 *sin6 = NULL;
+#endif
+ struct sockaddr_storage ss;
+
+ memset(&ss, 0, sizeof(ss));
+ switch (af) {
+ case AF_INET:
+ if (len != sizeof(sin->sin_addr))
+ return -1;
+ sin = (struct sockaddr_in *)&ss;
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (len != sizeof(sin6->sin6_addr))
+ return -1;
+ /* you will lose scope info */
+ sin6 = (struct sockaddr_in6 *)&ss;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr));
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ sa = (struct sockaddr *)&ss;
+ return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser);
+}
+
+int
+__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
+ FILE *hostf;
+ const struct sockaddr *raddr;
+ socklen_t salen;
+ const char *luser, *ruser;
+{
+ char *user, *p;
+ int ch;
+ char buf[MAXHOSTNAMELEN + 128]; /* host + login */
+ char hname[MAXHOSTNAMELEN];
+ /* Presumed guilty until proven innocent. */
+ int userok = 0, hostok = 0;
+#ifdef YP
+ char *ypdomain;
+
+ if (yp_get_default_domain(&ypdomain))
+ ypdomain = NULL;
+#else
+#define ypdomain NULL
+#endif
+ /* We need to get the damn hostname back for netgroup matching. */
+ if (getnameinfo(raddr, salen, hname, sizeof(hname), NULL, 0,
+ NI_NAMEREQD) != 0)
+ hname[0] = '\0';
+
+ while (fgets(buf, sizeof(buf), hostf)) {
+ p = buf;
+ /* Skip lines that are too long. */
+ if (strchr(p, '\n') == NULL) {
+ while ((ch = getc(hostf)) != '\n' && ch != EOF);
+ continue;
+ }
+ if (*p == '\n' || *p == '#') {
+ /* comment... */
+ continue;
+ }
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p;
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' &&
+ *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+ /*
+ * Do +/- and +@/-@ checking. This looks really nasty,
+ * but it matches SunOS's behavior so far as I can tell.
+ */
+ switch(buf[0]) {
+ case '+':
+ if (!buf[1]) { /* '+' matches all hosts */
+ hostok = 1;
+ break;
+ }
+ if (buf[1] == '@') /* match a host by netgroup */
+ hostok = hname[0] != '\0' &&
+ innetgr(&buf[2], hname, NULL, ypdomain);
+ else /* match a host by addr */
+ hostok = __icheckhost(raddr, salen,
+ (char *)&buf[1]);
+ break;
+ case '-': /* reject '-' hosts and all their users */
+ if (buf[1] == '@') {
+ if (hname[0] == '\0' ||
+ innetgr(&buf[2], hname, NULL, ypdomain))
+ return(-1);
+ } else {
+ if (__icheckhost(raddr, salen,
+ (char *)&buf[1]))
+ return(-1);
+ }
+ break;
+ default: /* if no '+' or '-', do a simple match */
+ hostok = __icheckhost(raddr, salen, buf);
+ break;
+ }
+ switch(*user) {
+ case '+':
+ if (!*(user+1)) { /* '+' matches all users */
+ userok = 1;
+ break;
+ }
+ if (*(user+1) == '@') /* match a user by netgroup */
+ userok = innetgr(user+2, NULL, ruser, ypdomain);
+ else /* match a user by direct specification */
+ userok = !(strcmp(ruser, user+1));
+ break;
+ case '-': /* if we matched a hostname, */
+ if (hostok) { /* check for user field rejections */
+ if (!*(user+1))
+ return(-1);
+ if (*(user+1) == '@') {
+ if (innetgr(user+2, NULL,
+ ruser, ypdomain))
+ return(-1);
+ } else {
+ if (!strcmp(ruser, user+1))
+ return(-1);
+ }
+ }
+ break;
+ default: /* no rejections: try to match the user */
+ if (hostok)
+ userok = !(strcmp(ruser,*user ? user : luser));
+ break;
+ }
+ if (hostok && userok)
+ return(0);
+ }
+ return (-1);
+}
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+static int
+__icheckhost(raddr, salen, lhost)
+ const struct sockaddr *raddr;
+ socklen_t salen;
+ const char *lhost;
+{
+ struct sockaddr_in sin;
+ struct sockaddr_in6 *sin6;
+ struct addrinfo hints, *res, *r;
+ int error;
+ char h1[NI_MAXHOST], h2[NI_MAXHOST];
+
+ if (raddr->sa_family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)raddr;
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
+ sizeof(sin.sin_addr));
+ raddr = (struct sockaddr *)&sin;
+ salen = sin.sin_len;
+ }
+ }
+
+ h1[0] = '\0';
+ if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
+ NI_NUMERICHOST) != 0)
+ return (0);
+
+ /* Resolve laddr into sockaddr */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = raddr->sa_family;
+ hints.ai_socktype = SOCK_DGRAM; /*XXX dummy*/
+ res = NULL;
+ error = getaddrinfo(lhost, "0", &hints, &res);
+ if (error)
+ return (0);
+
+ for (r = res; r ; r = r->ai_next) {
+ h2[0] = '\0';
+ if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
+ NULL, 0, NI_NUMERICHOST) != 0)
+ continue;
+ if (strcmp(h1, h2) == 0) {
+ freeaddrinfo(res);
+ return (1);
+ }
+ }
+
+ /* No match. */
+ freeaddrinfo(res);
+ return (0);
+}
diff --git a/freebsd/lib/libc/net/recv.c b/freebsd/lib/libc/net/recv.c
new file mode 100644
index 00000000..c625c0ac
--- /dev/null
+++ b/freebsd/lib/libc/net/recv.c
@@ -0,0 +1,52 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)recv.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stddef.h>
+#include "un-namespace.h"
+
+ssize_t
+recv(s, buf, len, flags)
+ int s, flags;
+ size_t len;
+ void *buf;
+{
+ return (_recvfrom(s, buf, len, flags, NULL, 0));
+}
diff --git a/freebsd/lib/libc/net/res_config.h b/freebsd/lib/libc/net/res_config.h
new file mode 100644
index 00000000..05909bca
--- /dev/null
+++ b/freebsd/lib/libc/net/res_config.h
@@ -0,0 +1,6 @@
+/* $FreeBSD$ */
+
+#define DEBUG 1 /* enable debugging code (needed for dig) */
+#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
+#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */
+#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
diff --git a/freebsd/lib/libc/net/send.c b/freebsd/lib/libc/net/send.c
new file mode 100644
index 00000000..0ba2f4bc
--- /dev/null
+++ b/freebsd/lib/libc/net/send.c
@@ -0,0 +1,52 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)send.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stddef.h>
+#include "un-namespace.h"
+
+ssize_t
+send(s, msg, len, flags)
+ int s, flags;
+ size_t len;
+ const void *msg;
+{
+ return (_sendto(s, msg, len, flags, NULL, 0));
+}
diff --git a/freebsd/lib/libc/resolv/h_errno.c b/freebsd/lib/libc/resolv/h_errno.c
new file mode 100644
index 00000000..88d15aee
--- /dev/null
+++ b/freebsd/lib/libc/resolv/h_errno.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2006 The FreeBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#undef h_errno
+extern int h_errno;
+
+int *
+__h_errno(void)
+{
+ return (&__res_state()->res_h_errno);
+}
+
+void
+__h_errno_set(res_state res, int err)
+{
+ h_errno = res->res_h_errno = err;
+}
diff --git a/freebsd/lib/libc/resolv/herror.c b/freebsd/lib/libc/resolv/herror.c
new file mode 100644
index 00000000..5a6e020e
--- /dev/null
+++ b/freebsd/lib/libc/resolv/herror.c
@@ -0,0 +1,128 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1987, 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: herror.c,v 1.3.18.1 2005/04/27 05:01:09 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "port_after.h"
+
+const char *h_errlist[] = {
+ "Resolver Error 0 (no error)",
+ "Unknown host", /*%< 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /*%< 2 TRY_AGAIN */
+ "Unknown server error", /*%< 3 NO_RECOVERY */
+ "No address associated with name", /*%< 4 NO_ADDRESS */
+};
+const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+
+#undef h_errno
+int h_errno;
+
+/*%
+ * herror --
+ * print the error indicated by the h_errno value.
+ */
+void
+herror(const char *s) {
+ struct iovec iov[4], *v = iov;
+ char *t;
+
+ if (s != NULL && *s != '\0') {
+ DE_CONST(s, t);
+ v->iov_base = t;
+ v->iov_len = strlen(t);
+ v++;
+ DE_CONST(": ", t);
+ v->iov_base = t;
+ v->iov_len = 2;
+ v++;
+ }
+ DE_CONST(hstrerror(*__h_errno()), t);
+ v->iov_base = t;
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ DE_CONST("\n", t);
+ v->iov_base = t;
+ v->iov_len = 1;
+ _writev(STDERR_FILENO, iov, (v - iov) + 1);
+}
+
+/*%
+ * hstrerror --
+ * return the string associated with a given "host" errno value.
+ */
+const char *
+hstrerror(int err) {
+ if (err < 0)
+ return ("Resolver internal error");
+ else if (err < h_nerr)
+ return (h_errlist[err]);
+ return ("Unknown resolver error");
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/mtctxres.c b/freebsd/lib/libc/resolv/mtctxres.c
new file mode 100644
index 00000000..f02a7f50
--- /dev/null
+++ b/freebsd/lib/libc/resolv/mtctxres.c
@@ -0,0 +1,141 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <port_before.h>
+#ifdef DO_PTHREADS
+#include <pthread.h>
+#ifdef _LIBC
+#include <pthread_np.h>
+#endif
+#endif
+#include <errno.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <resolv_mt.h>
+#include <port_after.h>
+
+#ifdef DO_PTHREADS
+static pthread_key_t key;
+static int mt_key_initialized = 0;
+
+static int __res_init_ctx(void);
+static void __res_destroy_ctx(void *);
+
+#if defined(sun) && !defined(__GNUC__)
+#pragma init (_mtctxres_init)
+#endif
+#endif
+
+static mtctxres_t sharedctx;
+
+#ifdef DO_PTHREADS
+/*
+ * Initialize the TSD key. By doing this at library load time, we're
+ * implicitly running without interference from other threads, so there's
+ * no need for locking.
+ */
+static void
+_mtctxres_init(void) {
+ int pthread_keycreate_ret;
+
+ pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
+ if (pthread_keycreate_ret == 0)
+ mt_key_initialized = 1;
+}
+#endif
+
+#ifndef _LIBC
+/*
+ * To support binaries that used the private MT-safe interface in
+ * Solaris 8, we still need to provide the __res_enable_mt()
+ * and __res_disable_mt() entry points. They're do-nothing routines.
+ */
+int
+__res_enable_mt(void) {
+ return (-1);
+}
+
+int
+__res_disable_mt(void) {
+ return (0);
+}
+#endif
+
+#ifdef DO_PTHREADS
+static int
+__res_init_ctx(void) {
+
+ mtctxres_t *mt;
+ int ret;
+
+
+ if (pthread_getspecific(key) != 0) {
+ /* Already exists */
+ return (0);
+ }
+
+ if ((mt = malloc(sizeof (mtctxres_t))) == 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ memset(mt, 0, sizeof (mtctxres_t));
+
+ if ((ret = pthread_setspecific(key, mt)) != 0) {
+ free(mt);
+ errno = ret;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+__res_destroy_ctx(void *value) {
+
+ mtctxres_t *mt = (mtctxres_t *)value;
+
+ if (mt != 0)
+ free(mt);
+}
+#endif
+
+mtctxres_t *
+___mtctxres(void) {
+#ifdef DO_PTHREADS
+ mtctxres_t *mt;
+
+#ifdef _LIBC
+ if (pthread_main_np() != 0)
+ return (&sharedctx);
+#endif
+
+ /*
+ * This if clause should only be executed if we are linking
+ * statically. When linked dynamically _mtctxres_init() should
+ * be called at binding time due the #pragma above.
+ */
+ if (!mt_key_initialized) {
+ static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
+ if (pthread_mutex_lock(&keylock) == 0) {
+ _mtctxres_init();
+ (void) pthread_mutex_unlock(&keylock);
+ }
+ }
+
+ /*
+ * If we have already been called in this thread return the existing
+ * context. Otherwise recreat a new context and return it. If
+ * that fails return a global context.
+ */
+ if (mt_key_initialized) {
+ if (((mt = pthread_getspecific(key)) != 0) ||
+ (__res_init_ctx() == 0 &&
+ (mt = pthread_getspecific(key)) != 0)) {
+ return (mt);
+ }
+ }
+#endif
+ return (&sharedctx);
+}
diff --git a/freebsd/lib/libc/resolv/res_comp.c b/freebsd/lib/libc/resolv/res_comp.c
new file mode 100644
index 00000000..cbddb6be
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_comp.c
@@ -0,0 +1,279 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1985, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_comp.c,v 1.3.18.2 2005/07/28 07:38:11 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "port_after.h"
+
+/*%
+ * Expand compressed domain name 'src' to full domain name.
+ *
+ * \li 'msg' is a pointer to the begining of the message,
+ * \li 'eom' points to the first location after the message,
+ * \li 'dst' is a pointer to a buffer of size 'dstsiz' for the result.
+ * \li Return size of compressed name or -1 if there was an error.
+ */
+int
+dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, int dstsiz)
+{
+ int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
+
+ if (n > 0 && dst[0] == '.')
+ dst[0] = '\0';
+ return (n);
+}
+
+/*%
+ * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
+ *
+ * \li Return the size of the compressed name or -1.
+ * \li 'length' is the size of the array pointed to by 'comp_dn'.
+ */
+int
+dn_comp(const char *src, u_char *dst, int dstsiz,
+ u_char **dnptrs, u_char **lastdnptr)
+{
+ return (ns_name_compress(src, dst, (size_t)dstsiz,
+ (const u_char **)dnptrs,
+ (const u_char **)lastdnptr));
+}
+
+/*%
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+int
+dn_skipname(const u_char *ptr, const u_char *eom) {
+ const u_char *saveptr = ptr;
+
+ if (ns_name_skip(&ptr, eom) == -1)
+ return (-1);
+ return (ptr - saveptr);
+}
+
+/*%
+ * Verify that a domain name uses an acceptable character set.
+ *
+ * Note the conspicuous absence of ctype macros in these definitions. On
+ * non-ASCII hosts, we can't depend on string literals or ctype macros to
+ * tell us anything about network-format data. The rest of the BIND system
+ * is not careful about this, but for some reason, we're doing it right here.
+ */
+#define PERIOD 0x2e
+#define hyphenchar(c) ((c) == 0x2d)
+#define bslashchar(c) ((c) == 0x5c)
+#define underscorechar(c) ((c) == 0x5f)
+#define periodchar(c) ((c) == PERIOD)
+#define asterchar(c) ((c) == 0x2a)
+#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
+ || ((c) >= 0x61 && (c) <= 0x7a))
+#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+
+#define borderchar(c) (alphachar(c) || digitchar(c))
+#ifdef RES_ENFORCE_RFC1034
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#else
+#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c))
+#endif
+#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+int
+res_hnok(const char *dn) {
+ int pch = PERIOD, ch = *dn++;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (periodchar(ch)) {
+ (void)NULL;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ pch = ch, ch = nch;
+ }
+ return (1);
+}
+
+/*%
+ * hostname-like (A, MX, WKS) owners can have "*" as their first label
+ * but must otherwise be as a host name.
+ */
+int
+res_ownok(const char *dn) {
+ if (asterchar(dn[0])) {
+ if (periodchar(dn[1]))
+ return (res_hnok(dn+2));
+ if (dn[1] == '\0')
+ return (1);
+ }
+ return (res_hnok(dn));
+}
+
+/*%
+ * SOA RNAMEs and RP RNAMEs can have any printable character in their first
+ * label, but the rest of the name has to look like a host name.
+ */
+int
+res_mailok(const char *dn) {
+ int ch, escaped = 0;
+
+ /* "." is a valid missing representation */
+ if (*dn == '\0')
+ return (1);
+
+ /* otherwise <label>.<hostname> */
+ while ((ch = *dn++) != '\0') {
+ if (!domainchar(ch))
+ return (0);
+ if (!escaped && periodchar(ch))
+ break;
+ if (escaped)
+ escaped = 0;
+ else if (bslashchar(ch))
+ escaped = 1;
+ }
+ if (periodchar(ch))
+ return (res_hnok(dn));
+ return (0);
+}
+
+/*%
+ * This function is quite liberal, since RFC1034's character sets are only
+ * recommendations.
+ */
+int
+res_dnok(const char *dn) {
+ int ch;
+
+ while ((ch = *dn++) != '\0')
+ if (!domainchar(ch))
+ return (0);
+ return (1);
+}
+
+#ifdef BIND_4_COMPAT
+/*%
+ * This module must export the following externally-visible symbols:
+ * ___putlong
+ * ___putshort
+ * __getlong
+ * __getshort
+ * Note that one _ comes from C and the others come from us.
+ */
+
+#ifdef SOLARIS2
+#ifdef __putlong
+#undef __putlong
+#endif
+#ifdef __putshort
+#undef __putshort
+#endif
+#pragma weak putlong = __putlong
+#pragma weak putshort = __putshort
+#endif /* SOLARIS2 */
+
+void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+#ifndef __ultrix__
+u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
+u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
+#endif /*__ultrix__*/
+#endif /*BIND_4_COMPAT*/
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <resolv.h>.
+ */
+#undef dn_comp
+__weak_reference(__dn_comp, dn_comp);
+#undef dn_expand
+__weak_reference(__dn_expand, dn_expand);
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_data.c b/freebsd/lib/libc/resolv/res_data.c
new file mode 100644
index 00000000..20ffe188
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_data.c
@@ -0,0 +1,322 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: res_data.c,v 1.3.18.2 2007/09/14 05:35:47 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "port_after.h"
+
+const char *_res_opcodes[] = {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU", /*%< experimental */
+ "NOTIFY", /*%< experimental */
+ "UPDATE",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+#ifdef BIND_UPDATE
+const char *_res_sectioncodes[] = {
+ "ZONE",
+ "PREREQUISITES",
+ "UPDATE",
+ "ADDITIONAL",
+};
+#endif
+
+#ifndef __BIND_NOSTATIC
+
+/* Proto. */
+
+int res_ourserver_p(const res_state, const struct sockaddr_in *);
+
+int
+res_init(void) {
+ extern int __res_vinit(res_state, int);
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = RES_DFLRETRY;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
+ return (__res_vinit(&_res, 1));
+}
+
+void
+p_query(const u_char *msg) {
+ fp_query(msg, stdout);
+}
+
+void
+fp_query(const u_char *msg, FILE *file) {
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+void
+fp_nquery(const u_char *msg, int len, FILE *file) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1)
+ return;
+
+ res_pquery(&_res, msg, len, file);
+}
+
+int
+res_mkquery(int op, /*!< opcode of query */
+ const char *dname, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ const u_char *data, /*!< resource record data */
+ int datalen, /*!< length of data */
+ const u_char *newrr_in, /*!< new rr for modify or append */
+ u_char *buf, /*!< buffer to put query */
+ int buflen) /*!< size of buffer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nmkquery(&_res, op, dname, class, type,
+ data, datalen,
+ newrr_in, buf, buflen));
+}
+
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
+}
+
+int
+res_query(const char *name, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ u_char *answer, /*!< buffer to put answer */
+ int anslen) /*!< size of answer buffer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nquery(&_res, name, class, type, answer, anslen));
+}
+
+#ifndef _LIBC
+void
+res_send_setqhook(res_send_qhook hook) {
+ _res.qhook = hook;
+}
+
+void
+res_send_setrhook(res_send_rhook hook) {
+ _res.rhook = hook;
+}
+#endif
+
+int
+res_isourserver(const struct sockaddr_in *inp) {
+ return (res_ourserver_p(&_res, inp));
+}
+
+int
+res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsend(&_res, buf, buflen, ans, anssiz));
+}
+
+#ifndef _LIBC
+int
+res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
+ u_char *ans, int anssiz)
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
+}
+#endif
+
+void
+res_close(void) {
+ res_nclose(&_res);
+}
+
+int
+res_update(ns_updrec *rrecp_in) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nupdate(&_res, rrecp_in, NULL));
+}
+
+int
+res_search(const char *name, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ u_char *answer, /*!< buffer to put answer */
+ int anslen) /*!< size of answer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nsearch(&_res, name, class, type, answer, anslen));
+}
+
+int
+res_querydomain(const char *name,
+ const char *domain,
+ int class, int type, /*!< class and type of query */
+ u_char *answer, /*!< buffer to put answer */
+ int anslen) /*!< size of answer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nquerydomain(&_res, name, domain,
+ class, type,
+ answer, anslen));
+}
+
+int
+res_opt(int n0, u_char *buf, int buflen, int anslen)
+{
+ return (res_nopt(&_res, n0, buf, buflen, anslen));
+}
+
+const char *
+hostalias(const char *name) {
+ static char abuf[MAXDNAME];
+
+ return (res_hostalias(&_res, name, abuf, sizeof abuf));
+}
+
+#ifdef ultrix
+int
+local_hostname_length(const char *hostname) {
+ int len_host, len_domain;
+
+ if (!*_res.defdname)
+ res_init();
+ len_host = strlen(hostname);
+ len_domain = strlen(_res.defdname);
+ if (len_host > len_domain &&
+ !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+ hostname[len_host - len_domain - 1] == '.')
+ return (len_host - len_domain - 1);
+ return (0);
+}
+#endif /*ultrix*/
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <resolv.h>.
+ */
+#undef res_init
+__weak_reference(__res_init, res_init);
+#undef p_query
+__weak_reference(__p_query, p_query);
+#undef res_mkquery
+__weak_reference(__res_mkquery, res_mkquery);
+#undef res_query
+__weak_reference(__res_query, res_query);
+#undef res_send
+__weak_reference(__res_send, res_send);
+#undef res_close
+__weak_reference(__res_close, _res_close);
+#undef res_search
+__weak_reference(__res_search, res_search);
+#undef res_querydomain
+__weak_reference(__res_querydomain, res_querydomain);
+
+#endif
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_debug.c b/freebsd/lib/libc/resolv/res_debug.c
new file mode 100644
index 00000000..317319ee
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_debug.c
@@ -0,0 +1,1231 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1985
+ * 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_debug.c,v 1.10.18.6 2008/04/03 23:15:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <resolv_mt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) sprintf x
+#endif
+
+extern const char *_res_opcodes[];
+extern const char *_res_sectioncodes[];
+
+/*%
+ * Print the current options.
+ */
+void
+fp_resstat(const res_state statp, FILE *file) {
+ u_long mask;
+
+ fprintf(file, ";; res options:");
+ for (mask = 1; mask != 0U; mask <<= 1)
+ if (statp->options & mask)
+ fprintf(file, " %s", p_option(mask));
+ putc('\n', file);
+}
+
+static void
+do_section(const res_state statp,
+ ns_msg *handle, ns_sect section,
+ int pflag, FILE *file)
+{
+ int n, sflag, rrnum;
+ static int buflen = 2048;
+ char *buf;
+ ns_opcode opcode;
+ ns_rr rr;
+
+ /*
+ * Print answer records.
+ */
+ sflag = (statp->pfcode & pflag);
+ if (statp->pfcode && !sflag)
+ return;
+
+ buf = malloc(buflen);
+ if (buf == NULL) {
+ fprintf(file, ";; memory allocation failure\n");
+ return;
+ }
+
+ opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
+ rrnum = 0;
+ for (;;) {
+ if (ns_parserr(handle, section, rrnum, &rr)) {
+ if (errno != ENODEV)
+ fprintf(file, ";; ns_parserr: %s\n",
+ strerror(errno));
+ else if (rrnum > 0 && sflag != 0 &&
+ (statp->pfcode & RES_PRF_HEAD1))
+ putc('\n', file);
+ goto cleanup;
+ }
+ if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
+ fprintf(file, ";; %s SECTION:\n",
+ p_section(section, opcode));
+ if (section == ns_s_qd)
+ fprintf(file, ";;\t%s, type = %s, class = %s\n",
+ ns_rr_name(rr),
+ p_type(ns_rr_type(rr)),
+ p_class(ns_rr_class(rr)));
+ else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
+ u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr);
+ u_int32_t ttl = ns_rr_ttl(rr);
+
+ fprintf(file,
+ "; EDNS: version: %u, udp=%u, flags=%04x\n",
+ (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
+
+ while (rdatalen >= 4) {
+ const u_char *cp = ns_rr_rdata(rr);
+ int i;
+
+ GETSHORT(optcode, cp);
+ GETSHORT(optlen, cp);
+
+ if (optcode == NS_OPT_NSID) {
+ fputs("; NSID: ", file);
+ if (optlen == 0) {
+ fputs("; NSID\n", file);
+ } else {
+ fputs("; NSID: ", file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i])?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ } else {
+ if (optlen == 0) {
+ fprintf(file, "; OPT=%u\n",
+ optcode);
+ } else {
+ fprintf(file, "; OPT=%u: ",
+ optcode);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i]) ?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ }
+ rdatalen -= 4 + optlen;
+ }
+ } else {
+ n = ns_sprintrr(handle, &rr, NULL, NULL,
+ buf, buflen);
+ if (n < 0) {
+ if (errno == ENOSPC) {
+ free(buf);
+ buf = NULL;
+ if (buflen < 131072)
+ buf = malloc(buflen += 1024);
+ if (buf == NULL) {
+ fprintf(file,
+ ";; memory allocation failure\n");
+ return;
+ }
+ continue;
+ }
+ fprintf(file, ";; ns_sprintrr: %s\n",
+ strerror(errno));
+ goto cleanup;
+ }
+ fputs(buf, file);
+ fputc('\n', file);
+ }
+ rrnum++;
+ }
+ cleanup:
+ if (buf != NULL)
+ free(buf);
+}
+
+/*%
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
+ ns_msg handle;
+ int qdcount, ancount, nscount, arcount;
+ u_int opcode, rcode, id;
+
+ if (ns_initparse(msg, len, &handle) < 0) {
+ fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
+ return;
+ }
+ opcode = ns_msg_getflag(handle, ns_f_opcode);
+ rcode = ns_msg_getflag(handle, ns_f_rcode);
+ id = ns_msg_id(handle);
+ qdcount = ns_msg_count(handle, ns_s_qd);
+ ancount = ns_msg_count(handle, ns_s_an);
+ nscount = ns_msg_count(handle, ns_s_ns);
+ arcount = ns_msg_count(handle, ns_s_ar);
+
+ /*
+ * Print header fields.
+ */
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
+ fprintf(file,
+ ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+ _res_opcodes[opcode], p_rcode(rcode), id);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
+ putc(';', file);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
+ fprintf(file, "; flags:");
+ if (ns_msg_getflag(handle, ns_f_qr))
+ fprintf(file, " qr");
+ if (ns_msg_getflag(handle, ns_f_aa))
+ fprintf(file, " aa");
+ if (ns_msg_getflag(handle, ns_f_tc))
+ fprintf(file, " tc");
+ if (ns_msg_getflag(handle, ns_f_rd))
+ fprintf(file, " rd");
+ if (ns_msg_getflag(handle, ns_f_ra))
+ fprintf(file, " ra");
+ if (ns_msg_getflag(handle, ns_f_z))
+ fprintf(file, " ??");
+ if (ns_msg_getflag(handle, ns_f_ad))
+ fprintf(file, " ad");
+ if (ns_msg_getflag(handle, ns_f_cd))
+ fprintf(file, " cd");
+ }
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
+ fprintf(file, "; %s: %d",
+ p_section(ns_s_qd, opcode), qdcount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_an, opcode), ancount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ns, opcode), nscount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ar, opcode), arcount);
+ }
+ if ((!statp->pfcode) || (statp->pfcode &
+ (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+ putc('\n',file);
+ }
+ /*
+ * Print the various sections.
+ */
+ do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
+ do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
+ do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
+ do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
+ if (qdcount == 0 && ancount == 0 &&
+ nscount == 0 && arcount == 0)
+ putc('\n', file);
+}
+
+const u_char *
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
+ char name[MAXDNAME];
+ int n;
+
+ if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
+ return (NULL);
+ if (name[0] == '\0')
+ putc('.', file);
+ else
+ fputs(name, file);
+ return (cp + n);
+}
+
+const u_char *
+p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
+ return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+/*%
+ * Return a fully-qualified domain name from a compressed name (with
+ length supplied). */
+
+const u_char *
+p_fqnname(cp, msg, msglen, name, namelen)
+ const u_char *cp, *msg;
+ int msglen;
+ char *name;
+ int namelen;
+{
+ int n, newlen;
+
+ if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+ return (NULL);
+ newlen = strlen(name);
+ if (newlen == 0 || name[newlen - 1] != '.') {
+ if (newlen + 1 >= namelen) /*%< Lack space for final dot */
+ return (NULL);
+ else
+ strcpy(name + newlen, ".");
+ }
+ return (cp + n);
+}
+
+/* XXX: the rest of these functions need to become length-limited, too. */
+
+const u_char *
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
+ char name[MAXDNAME];
+ const u_char *n;
+
+ n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+ if (n == NULL)
+ return (NULL);
+ fputs(name, file);
+ return (n);
+}
+
+/*%
+ * Names of RR classes and qclasses. Classes and qclasses are the same, except
+ * that C_ANY is a qclass but not a class. (You can ask for records of class
+ * C_ANY, but you can't have any records of that class in the database.)
+ */
+const struct res_sym __p_class_syms[] = {
+ {C_IN, "IN", (char *)0},
+ {C_CHAOS, "CH", (char *)0},
+ {C_CHAOS, "CHAOS", (char *)0},
+ {C_HS, "HS", (char *)0},
+ {C_HS, "HESIOD", (char *)0},
+ {C_ANY, "ANY", (char *)0},
+ {C_NONE, "NONE", (char *)0},
+ {C_IN, (char *)0, (char *)0}
+};
+
+/*%
+ * Names of message sections.
+ */
+static const struct res_sym __p_default_section_syms[] = {
+ {ns_s_qd, "QUERY", (char *)0},
+ {ns_s_an, "ANSWER", (char *)0},
+ {ns_s_ns, "AUTHORITY", (char *)0},
+ {ns_s_ar, "ADDITIONAL", (char *)0},
+ {0, (char *)0, (char *)0}
+};
+
+static const struct res_sym __p_update_section_syms[] = {
+ {S_ZONE, "ZONE", (char *)0},
+ {S_PREREQ, "PREREQUISITE", (char *)0},
+ {S_UPDATE, "UPDATE", (char *)0},
+ {S_ADDT, "ADDITIONAL", (char *)0},
+ {0, (char *)0, (char *)0}
+};
+
+const struct res_sym __p_key_syms[] = {
+ {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"},
+ {NS_ALG_DH, "DH", "Diffie Hellman"},
+ {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"},
+ {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
+ {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"},
+ {0, NULL, NULL}
+};
+
+const struct res_sym __p_cert_syms[] = {
+ {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"},
+ {cert_t_spki, "SPKI", "SPKI certificate"},
+ {cert_t_pgp, "PGP", "PGP certificate"},
+ {cert_t_url, "URL", "URL Private"},
+ {cert_t_oid, "OID", "OID Private"},
+ {0, NULL, NULL}
+};
+
+/*%
+ * Names of RR types and qtypes. Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type. (You can ask for records of type
+ * T_ANY, but you can't have any records of that type in the database.)
+ */
+const struct res_sym __p_type_syms[] = {
+ {ns_t_a, "A", "address"},
+ {ns_t_ns, "NS", "name server"},
+ {ns_t_md, "MD", "mail destination (deprecated)"},
+ {ns_t_mf, "MF", "mail forwarder (deprecated)"},
+ {ns_t_cname, "CNAME", "canonical name"},
+ {ns_t_soa, "SOA", "start of authority"},
+ {ns_t_mb, "MB", "mailbox"},
+ {ns_t_mg, "MG", "mail group member"},
+ {ns_t_mr, "MR", "mail rename"},
+ {ns_t_null, "NULL", "null"},
+ {ns_t_wks, "WKS", "well-known service (deprecated)"},
+ {ns_t_ptr, "PTR", "domain name pointer"},
+ {ns_t_hinfo, "HINFO", "host information"},
+ {ns_t_minfo, "MINFO", "mailbox information"},
+ {ns_t_mx, "MX", "mail exchanger"},
+ {ns_t_txt, "TXT", "text"},
+ {ns_t_rp, "RP", "responsible person"},
+ {ns_t_afsdb, "AFSDB", "DCE or AFS server"},
+ {ns_t_x25, "X25", "X25 address"},
+ {ns_t_isdn, "ISDN", "ISDN address"},
+ {ns_t_rt, "RT", "router"},
+ {ns_t_nsap, "NSAP", "nsap address"},
+ {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"},
+ {ns_t_sig, "SIG", "signature"},
+ {ns_t_key, "KEY", "key"},
+ {ns_t_px, "PX", "mapping information"},
+ {ns_t_gpos, "GPOS", "geographical position (withdrawn)"},
+ {ns_t_aaaa, "AAAA", "IPv6 address"},
+ {ns_t_loc, "LOC", "location"},
+ {ns_t_nxt, "NXT", "next valid name (unimplemented)"},
+ {ns_t_eid, "EID", "endpoint identifier (unimplemented)"},
+ {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"},
+ {ns_t_srv, "SRV", "server selection"},
+ {ns_t_atma, "ATMA", "ATM address (unimplemented)"},
+ {ns_t_tkey, "TKEY", "tkey"},
+ {ns_t_tsig, "TSIG", "transaction signature"},
+ {ns_t_ixfr, "IXFR", "incremental zone transfer"},
+ {ns_t_axfr, "AXFR", "zone transfer"},
+ {ns_t_zxfr, "ZXFR", "compressed zone transfer"},
+ {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"},
+ {ns_t_maila, "MAILA", "mail agent (deprecated)"},
+ {ns_t_naptr, "NAPTR", "URN Naming Authority"},
+ {ns_t_kx, "KX", "Key Exchange"},
+ {ns_t_cert, "CERT", "Certificate"},
+ {ns_t_a6, "A6", "IPv6 Address"},
+ {ns_t_dname, "DNAME", "dname"},
+ {ns_t_sink, "SINK", "Kitchen Sink (experimental)"},
+ {ns_t_opt, "OPT", "EDNS Options"},
+ {ns_t_any, "ANY", "\"any\""},
+ {0, NULL, NULL}
+};
+
+/*%
+ * Names of DNS rcodes.
+ */
+const struct res_sym __p_rcode_syms[] = {
+ {ns_r_noerror, "NOERROR", "no error"},
+ {ns_r_formerr, "FORMERR", "format error"},
+ {ns_r_servfail, "SERVFAIL", "server failed"},
+ {ns_r_nxdomain, "NXDOMAIN", "no such domain name"},
+ {ns_r_notimpl, "NOTIMP", "not implemented"},
+ {ns_r_refused, "REFUSED", "refused"},
+ {ns_r_yxdomain, "YXDOMAIN", "domain name exists"},
+ {ns_r_yxrrset, "YXRRSET", "rrset exists"},
+ {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"},
+ {ns_r_notauth, "NOTAUTH", "not authoritative"},
+ {ns_r_notzone, "NOTZONE", "Not in zone"},
+ {ns_r_max, "", ""},
+ {ns_r_badsig, "BADSIG", "bad signature"},
+ {ns_r_badkey, "BADKEY", "bad key"},
+ {ns_r_badtime, "BADTIME", "bad time"},
+ {0, NULL, NULL}
+};
+
+int
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (strcasecmp (name, syms->name) == 0) {
+ if (success)
+ *success = 1;
+ return (syms->number);
+ }
+ }
+ if (success)
+ *success = 0;
+ return (syms->number); /*%< The default value. */
+}
+
+const char *
+sym_ntos(const struct res_sym *syms, int number, int *success) {
+ char *unname = sym_ntos_unname;
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->name);
+ }
+ }
+
+ sprintf(unname, "%d", number); /*%< XXX nonreentrant */
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+const char *
+sym_ntop(const struct res_sym *syms, int number, int *success) {
+ char *unname = sym_ntop_unname;
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->humanname);
+ }
+ }
+ sprintf(unname, "%d", number); /*%< XXX nonreentrant */
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+/*%
+ * Return a string for the type.
+ */
+const char *
+p_type(int type) {
+ int success;
+ const char *result;
+ static char typebuf[20];
+
+ result = sym_ntos(__p_type_syms, type, &success);
+ if (success)
+ return (result);
+ if (type < 0 || type > 0xffff)
+ return ("BADTYPE");
+ sprintf(typebuf, "TYPE%d", type);
+ return (typebuf);
+}
+
+/*%
+ * Return a string for the type.
+ */
+const char *
+p_section(int section, int opcode) {
+ const struct res_sym *symbols;
+
+ switch (opcode) {
+ case ns_o_update:
+ symbols = __p_update_section_syms;
+ break;
+ default:
+ symbols = __p_default_section_syms;
+ break;
+ }
+ return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*%
+ * Return a mnemonic for class.
+ */
+const char *
+p_class(int class) {
+ int success;
+ const char *result;
+ static char classbuf[20];
+
+ result = sym_ntos(__p_class_syms, class, &success);
+ if (success)
+ return (result);
+ if (class < 0 || class > 0xffff)
+ return ("BADCLASS");
+ sprintf(classbuf, "CLASS%d", class);
+ return (classbuf);
+}
+
+/*%
+ * Return a mnemonic for an option
+ */
+const char *
+p_option(u_long option) {
+ char *nbuf = p_option_nbuf;
+
+ switch (option) {
+ case RES_INIT: return "init";
+ case RES_DEBUG: return "debug";
+ case RES_AAONLY: return "aaonly(unimpl)";
+ case RES_USEVC: return "usevc";
+ case RES_PRIMARY: return "primry(unimpl)";
+ case RES_IGNTC: return "igntc";
+ case RES_RECURSE: return "recurs";
+ case RES_DEFNAMES: return "defnam";
+ case RES_STAYOPEN: return "styopn";
+ case RES_DNSRCH: return "dnsrch";
+ case RES_INSECURE1: return "insecure1";
+ case RES_INSECURE2: return "insecure2";
+ case RES_NOALIASES: return "noaliases";
+ case RES_USE_INET6: return "inet6";
+#ifdef RES_USE_EDNS0 /*%< KAME extension */
+ case RES_USE_EDNS0: return "edns0";
+ case RES_NSID: return "nsid";
+#endif
+#ifdef RES_USE_DNAME
+ case RES_USE_DNAME: return "dname";
+#endif
+#ifdef RES_USE_DNSSEC
+ case RES_USE_DNSSEC: return "dnssec";
+#endif
+#ifdef RES_NOTLDQUERY
+ case RES_NOTLDQUERY: return "no-tld-query";
+#endif
+#ifdef RES_NO_NIBBLE2
+ case RES_NO_NIBBLE2: return "no-nibble2";
+#endif
+ /* XXX nonreentrant */
+ default: sprintf(nbuf, "?0x%lx?", (u_long)option);
+ return (nbuf);
+ }
+}
+
+/*%
+ * Return a mnemonic for a time to live.
+ */
+const char *
+p_time(u_int32_t value) {
+ char *nbuf = p_time_nbuf;
+
+ if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
+ sprintf(nbuf, "%u", value);
+ return (nbuf);
+}
+
+/*%
+ * Return a string for the rcode.
+ */
+const char *
+p_rcode(int rcode) {
+ return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
+}
+
+/*%
+ * Return a string for a res_sockaddr_union.
+ */
+const char *
+p_sockun(union res_sockaddr_union u, char *buf, size_t size) {
+ char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"];
+
+ switch (u.sin.sin_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret);
+ break;
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret);
+ break;
+#endif
+ default:
+ sprintf(ret, "[af%d]", u.sin.sin_family);
+ break;
+ }
+ if (size > 0U) {
+ strncpy(buf, ret, size - 1);
+ buf[size - 1] = '0';
+ }
+ return (buf);
+}
+
+/*%
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/*% takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+ u_int8_t prec;
+{
+ char *retbuf = precsize_ntoa_retbuf;
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100);
+ return (retbuf);
+}
+
+/*% converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
+static u_int8_t
+precsize_aton(const char **strptr) {
+ unsigned int mval = 0, cmval = 0;
+ u_int8_t retval = 0;
+ const char *cp;
+ int exponent;
+ int mantissa;
+
+ cp = *strptr;
+
+ while (isdigit((unsigned char)*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /*%< centimeters */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ cmval = (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ cmval += (*cp++ - '0');
+ }
+ }
+ }
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
+
+ retval = (mantissa << 4) | exponent;
+
+ *strptr = cp;
+
+ return (retval);
+}
+
+/*% converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
+static u_int32_t
+latlon2ul(const char **latlonstrptr, int *which) {
+ const char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit((unsigned char)*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!(isdigit((unsigned char)*cp)))
+ goto fndhemi;
+
+ while (isdigit((unsigned char)*cp))
+ min = min * 10 + (*cp++ - '0');
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!(isdigit((unsigned char)*cp)))
+ goto fndhemi;
+
+ while (isdigit((unsigned char)*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /*%< decimal seconds */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */
+ cp++;
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ fndhemi:
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'E': case 'e':
+ retval = ((unsigned)1<<31)
+ + (((((deg * 60) + min) * 60) + secs) * 1000)
+ + secsfrac;
+ break;
+ case 'S': case 's':
+ case 'W': case 'w':
+ retval = ((unsigned)1<<31)
+ - (((((deg * 60) + min) * 60) + secs) * 1000)
+ - secsfrac;
+ break;
+ default:
+ retval = 0; /*%< invalid value -- indicates error */
+ break;
+ }
+
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'S': case 's':
+ *which = 1; /*%< latitude */
+ break;
+ case 'E': case 'e':
+ case 'W': case 'w':
+ *which = 2; /*%< longitude */
+ break;
+ default:
+ *which = 0; /*%< error */
+ break;
+ }
+
+ cp++; /*%< skip the hemisphere */
+ while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */
+ cp++;
+
+ while (isspace((unsigned char)*cp)) /*%< move to next field */
+ cp++;
+
+ *latlonstrptr = cp;
+
+ return (retval);
+}
+
+/*%
+ * converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(ascii, binary)
+ const char *ascii;
+ u_char *binary;
+{
+ const char *cp, *maxcp;
+ u_char *bcp;
+
+ u_int32_t latit = 0, longit = 0, alt = 0;
+ u_int32_t lltemp1 = 0, lltemp2 = 0;
+ int altmeters = 0, altfrac = 0, altsign = 1;
+ u_int8_t hp = 0x16; /*%< default = 1e6 cm = 10000.00m = 10km */
+ u_int8_t vp = 0x13; /*%< default = 1e3 cm = 10.00m */
+ u_int8_t siz = 0x12; /*%< default = 1e2 cm = 1.00m */
+ int which1 = 0, which2 = 0;
+
+ cp = ascii;
+ maxcp = cp + strlen(ascii);
+
+ lltemp1 = latlon2ul(&cp, &which1);
+
+ lltemp2 = latlon2ul(&cp, &which2);
+
+ switch (which1 + which2) {
+ case 3: /*%< 1 + 2, the only valid combination */
+ if ((which1 == 1) && (which2 == 2)) { /*%< normal case */
+ latit = lltemp1;
+ longit = lltemp2;
+ } else if ((which1 == 2) && (which2 == 1)) { /*%< reversed */
+ longit = lltemp1;
+ latit = lltemp2;
+ } else { /*%< some kind of brokenness */
+ return (0);
+ }
+ break;
+ default: /*%< we didn't get one of each */
+ return (0);
+ }
+
+ /* altitude */
+ if (*cp == '-') {
+ altsign = -1;
+ cp++;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ while (isdigit((unsigned char)*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /*%< decimal meters */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton(&cp);
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton(&cp);
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ vp = precsize_aton(&cp);
+
+ defaults:
+
+ bcp = binary;
+ *bcp++ = (u_int8_t) 0; /*%< version byte */
+ *bcp++ = siz;
+ *bcp++ = hp;
+ *bcp++ = vp;
+ PUTLONG(latit,bcp);
+ PUTLONG(longit,bcp);
+ PUTLONG(alt,bcp);
+
+ return (16); /*%< size of RR in octets */
+}
+
+/*% takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+ const u_char *binary;
+ char *ascii;
+{
+ static const char *error = "?";
+ static char tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+ const u_char *cp = binary;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ const char *altsign;
+ int altmeters, altfrac;
+
+ const u_int32_t referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ versionval = *cp++;
+
+ if (ascii == NULL)
+ ascii = tmpbuf;
+
+ if (versionval) {
+ (void) sprintf(ascii, "; error: unknown LOC RR version");
+ return (ascii);
+ }
+
+ sizeval = *cp++;
+
+ hpval = *cp++;
+ vpval = *cp++;
+
+ GETLONG(templ, cp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ if (templ < referencealt) { /*%< below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = "-";
+ } else {
+ altval = templ - referencealt;
+ altsign = "";
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ } else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ } else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100);
+
+ sizestr = strdup(precsize_ntoa(sizeval));
+ hpstr = strdup(precsize_ntoa(hpval));
+ vpstr = strdup(precsize_ntoa(vpval));
+
+ sprintf(ascii,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altsign, altmeters, altfrac,
+ (sizestr != NULL) ? sizestr : error,
+ (hpstr != NULL) ? hpstr : error,
+ (vpstr != NULL) ? vpstr : error);
+
+ if (sizestr != NULL)
+ free(sizestr);
+ if (hpstr != NULL)
+ free(hpstr);
+ if (vpstr != NULL)
+ free(vpstr);
+
+ return (ascii);
+}
+
+
+/*% Return the number of DNS hierarchy levels in the name. */
+int
+dn_count_labels(const char *name) {
+ int i, len, count;
+
+ len = strlen(name);
+ for (i = 0, count = 0; i < len; i++) {
+ /* XXX need to check for \. or use named's nlabels(). */
+ if (name[i] == '.')
+ count++;
+ }
+
+ /* don't count initial wildcard */
+ if (name[0] == '*')
+ if (count)
+ count--;
+
+ /* don't count the null label for root. */
+ /* if terminating '.' not found, must adjust */
+ /* count to include last label */
+ if (len > 0 && name[len-1] != '.')
+ count++;
+ return (count);
+}
+
+/*%
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+ * SIG records are required to be printed like this, by the Secure DNS RFC.
+ */
+char *
+p_secstodate (u_long secs) {
+ char *output = p_secstodate_output;
+ time_t clock = secs;
+ struct tm *time;
+#ifdef HAVE_TIME_R
+ struct tm res;
+
+ time = gmtime_r(&clock, &res);
+#else
+ time = gmtime(&clock);
+#endif
+ time->tm_year += 1900;
+ time->tm_mon += 1;
+ sprintf(output, "%04d%02d%02d%02d%02d%02d",
+ time->tm_year, time->tm_mon, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ return (output);
+}
+
+u_int16_t
+res_nametoclass(const char *buf, int *successp) {
+ unsigned long result;
+ char *endptr;
+ int success;
+
+ result = sym_ston(__p_class_syms, buf, &success);
+ if (success)
+ goto done;
+
+ if (strncasecmp(buf, "CLASS", 5) != 0 ||
+ !isdigit((unsigned char)buf[5]))
+ goto done;
+ errno = 0;
+ result = strtoul(buf + 5, &endptr, 10);
+ if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
+ success = 1;
+ done:
+ if (successp)
+ *successp = success;
+ return (result);
+}
+
+u_int16_t
+res_nametotype(const char *buf, int *successp) {
+ unsigned long result;
+ char *endptr;
+ int success;
+
+ result = sym_ston(__p_type_syms, buf, &success);
+ if (success)
+ goto done;
+
+ if (strncasecmp(buf, "type", 4) != 0 ||
+ !isdigit((unsigned char)buf[4]))
+ goto done;
+ errno = 0;
+ result = strtoul(buf + 4, &endptr, 10);
+ if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
+ success = 1;
+ done:
+ if (successp)
+ *successp = success;
+ return (result);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <resolv.h>.
+ */
+#undef fp_resstat
+__weak_reference(__fp_resstat, fp_resstat);
+#undef p_fqnname
+__weak_reference(__p_fqnname, p_fqnname);
+#undef sym_ston
+__weak_reference(__sym_ston, sym_ston);
+#undef sym_ntos
+__weak_reference(__sym_ntos, sym_ntos);
+#undef sym_ntop
+__weak_reference(__sym_ntop, sym_ntop);
+#undef dn_count_labels
+__weak_reference(__dn_count_labels, dn_count_labels);
+#undef p_secstodate
+__weak_reference(__p_secstodate, p_secstodate);
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_debug.h b/freebsd/lib/libc/resolv/res_debug.h
new file mode 100644
index 00000000..c28171d7
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_debug.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _RES_DEBUG_H_
+#define _RES_DEBUG_H_
+
+#ifndef DEBUG
+# define Dprint(cond, args) /*empty*/
+# define DprintQ(cond, args, query, size) /*empty*/
+# define Aerror(statp, file, string, error, address) /*empty*/
+# define Perror(statp, file, string, error) /*empty*/
+#else
+# define Dprint(cond, args) if (cond) {fprintf args;} else {}
+# define DprintQ(cond, args, query, size) if (cond) {\
+ fprintf args;\
+ res_pquery(statp, query, size, stdout);\
+ } else {}
+#endif
+
+#endif /* _RES_DEBUG_H_ */
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_findzonecut.c b/freebsd/lib/libc/resolv/res_findzonecut.c
new file mode 100644
index 00000000..23c1af4f
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_findzonecut.c
@@ -0,0 +1,727 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_findzonecut.c,v 1.7.18.3 2005/10/11 00:25:11 marka Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+
+#include "port_after.h"
+
+#include <resolv.h>
+
+/* Data structures. */
+
+typedef struct rr_a {
+ LINK(struct rr_a) link;
+ union res_sockaddr_union addr;
+} rr_a;
+typedef LIST(rr_a) rrset_a;
+
+typedef struct rr_ns {
+ LINK(struct rr_ns) link;
+ const char * name;
+ unsigned int flags;
+ rrset_a addrs;
+} rr_ns;
+typedef LIST(rr_ns) rrset_ns;
+
+#define RR_NS_HAVE_V4 0x01
+#define RR_NS_HAVE_V6 0x02
+
+/* Forward. */
+
+static int satisfy(res_state, const char *, rrset_ns *,
+ union res_sockaddr_union *, int);
+static int add_addrs(res_state, rr_ns *,
+ union res_sockaddr_union *, int);
+static int get_soa(res_state, const char *, ns_class, int,
+ char *, size_t, char *, size_t,
+ rrset_ns *);
+static int get_ns(res_state, const char *, ns_class, int, rrset_ns *);
+static int get_glue(res_state, ns_class, int, rrset_ns *);
+static int save_ns(res_state, ns_msg *, ns_sect,
+ const char *, ns_class, int, rrset_ns *);
+static int save_a(res_state, ns_msg *, ns_sect,
+ const char *, ns_class, int, rr_ns *);
+static void free_nsrrset(rrset_ns *);
+static void free_nsrr(rrset_ns *, rr_ns *);
+static rr_ns * find_ns(rrset_ns *, const char *);
+static int do_query(res_state, const char *, ns_class, ns_type,
+ u_char *, ns_msg *);
+static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
+
+/* Macros. */
+
+#define DPRINTF(x) do {\
+ int save_errno = errno; \
+ if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \
+ errno = save_errno; \
+ } while (0)
+
+/* Public. */
+
+/*%
+ * find enclosing zone for a <dname,class>, and some server addresses
+ *
+ * parameters:
+ *\li res - resolver context to work within (is modified)
+ *\li dname - domain name whose enclosing zone is desired
+ *\li class - class of dname (and its enclosing zone)
+ *\li zname - found zone name
+ *\li zsize - allocated size of zname
+ *\li addrs - found server addresses
+ *\li naddrs - max number of addrs
+ *
+ * return values:
+ *\li < 0 - an error occurred (check errno)
+ *\li = 0 - zname is now valid, but addrs[] wasn't changed
+ *\li > 0 - zname is now valid, and return value is number of addrs[] found
+ *
+ * notes:
+ *\li this function calls res_nsend() which means it depends on correctly
+ * functioning recursive nameservers (usually defined in /etc/resolv.conf
+ * or its local equivilent).
+ *
+ *\li we start by asking for an SOA<dname,class>. if we get one as an
+ * answer, that just means <dname,class> is a zone top, which is fine.
+ * more than likely we'll be told to go pound sand, in the form of a
+ * negative answer.
+ *
+ *\li note that we are not prepared to deal with referrals since that would
+ * only come from authority servers and our correctly functioning local
+ * recursive server would have followed the referral and got us something
+ * more definite.
+ *
+ *\li if the authority section contains an SOA, this SOA should also be the
+ * closest enclosing zone, since any intermediary zone cuts would've been
+ * returned as referrals and dealt with by our correctly functioning local
+ * recursive name server. but an SOA in the authority section should NOT
+ * match our dname (since that would have been returned in the answer
+ * section). an authority section SOA has to be "above" our dname.
+ *
+ *\li however, since authority section SOA's were once optional, it's
+ * possible that we'll have to go hunting for the enclosing SOA by
+ * ripping labels off the front of our dname -- this is known as "doing
+ * it the hard way."
+ *
+ *\li ultimately we want some server addresses, which are ideally the ones
+ * pertaining to the SOA.MNAME, but only if there is a matching NS RR.
+ * so the second phase (after we find an SOA) is to go looking for the
+ * NS RRset for that SOA's zone.
+ *
+ *\li no answer section processed by this code is allowed to contain CNAME
+ * or DNAME RR's. for the SOA query this means we strip a label and
+ * keep going. for the NS and A queries this means we just give up.
+ */
+
+#ifndef _LIBC
+int
+res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, struct in_addr *addrs, int naddrs)
+{
+ int result, i;
+ union res_sockaddr_union *u;
+
+
+ opts |= RES_IPV4ONLY;
+ opts &= ~RES_IPV6ONLY;
+
+ u = calloc(naddrs, sizeof(*u));
+ if (u == NULL)
+ return(-1);
+
+ result = res_findzonecut2(statp, dname, class, opts, zname, zsize,
+ u, naddrs);
+
+ for (i = 0; i < result; i++) {
+ addrs[i] = u[i].sin.sin_addr;
+ }
+ free(u);
+ return (result);
+}
+#endif
+
+int
+res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, union res_sockaddr_union *addrs,
+ int naddrs)
+{
+ char mname[NS_MAXDNAME];
+ u_long save_pfcode;
+ rrset_ns nsrrs;
+ int n;
+
+ DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d",
+ dname, p_class(class), (long)zsize, naddrs));
+ save_pfcode = statp->pfcode;
+ statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX |
+ RES_PRF_QUES | RES_PRF_ANS |
+ RES_PRF_AUTH | RES_PRF_ADD;
+ INIT_LIST(nsrrs);
+
+ DPRINTF(("get the soa, and see if it has enough glue"));
+ if ((n = get_soa(statp, dname, class, opts, zname, zsize,
+ mname, sizeof mname, &nsrrs)) < 0 ||
+ ((opts & RES_EXHAUSTIVE) == 0 &&
+ (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
+ goto done;
+
+ DPRINTF(("get the ns rrset and see if it has enough glue"));
+ if ((n = get_ns(statp, zname, class, opts, &nsrrs)) < 0 ||
+ ((opts & RES_EXHAUSTIVE) == 0 &&
+ (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
+ goto done;
+
+ DPRINTF(("get the missing glue and see if it's finally enough"));
+ if ((n = get_glue(statp, class, opts, &nsrrs)) >= 0)
+ n = satisfy(statp, mname, &nsrrs, addrs, naddrs);
+
+ done:
+ DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK"));
+ free_nsrrset(&nsrrs);
+ statp->pfcode = save_pfcode;
+ return (n);
+}
+
+/* Private. */
+
+static int
+satisfy(res_state statp, const char *mname, rrset_ns *nsrrsp,
+ union res_sockaddr_union *addrs, int naddrs)
+{
+ rr_ns *nsrr;
+ int n, x;
+
+ n = 0;
+ nsrr = find_ns(nsrrsp, mname);
+ if (nsrr != NULL) {
+ x = add_addrs(statp, nsrr, addrs, naddrs);
+ addrs += x;
+ naddrs -= x;
+ n += x;
+ }
+ for (nsrr = HEAD(*nsrrsp);
+ nsrr != NULL && naddrs > 0;
+ nsrr = NEXT(nsrr, link))
+ if (ns_samename(nsrr->name, mname) != 1) {
+ x = add_addrs(statp, nsrr, addrs, naddrs);
+ addrs += x;
+ naddrs -= x;
+ n += x;
+ }
+ DPRINTF(("satisfy(%s): %d", mname, n));
+ return (n);
+}
+
+static int
+add_addrs(res_state statp, rr_ns *nsrr,
+ union res_sockaddr_union *addrs, int naddrs)
+{
+ rr_a *arr;
+ int n = 0;
+
+ for (arr = HEAD(nsrr->addrs); arr != NULL; arr = NEXT(arr, link)) {
+ if (naddrs <= 0)
+ return (0);
+ *addrs++ = arr->addr;
+ naddrs--;
+ n++;
+ }
+ DPRINTF(("add_addrs: %d", n));
+ return (n);
+}
+
+static int
+get_soa(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, char *mname, size_t msize,
+ rrset_ns *nsrrsp)
+{
+ char tname[NS_MAXDNAME];
+ u_char *resp = NULL;
+ int n, i, ancount, nscount;
+ ns_sect sect;
+ ns_msg msg;
+ u_int rcode;
+
+ /*
+ * Find closest enclosing SOA, even if it's for the root zone.
+ */
+
+ /* First canonicalize dname (exactly one unescaped trailing "."). */
+ if (ns_makecanon(dname, tname, sizeof tname) < 0)
+ goto cleanup;
+ dname = tname;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ goto cleanup;
+
+ /* Now grovel the subdomains, hunting for an SOA answer or auth. */
+ for (;;) {
+ /* Leading or inter-label '.' are skipped here. */
+ while (*dname == '.')
+ dname++;
+
+ /* Is there an SOA? */
+ n = do_query(statp, dname, class, ns_t_soa, resp, &msg);
+ if (n < 0) {
+ DPRINTF(("get_soa: do_query('%s', %s) failed (%d)",
+ dname, p_class(class), n));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF(("get_soa: CNAME or DNAME found"));
+ sect = ns_s_max, n = 0;
+ } else {
+ rcode = ns_msg_getflag(msg, ns_f_rcode);
+ ancount = ns_msg_count(msg, ns_s_an);
+ nscount = ns_msg_count(msg, ns_s_ns);
+ if (ancount > 0 && rcode == ns_r_noerror)
+ sect = ns_s_an, n = ancount;
+ else if (nscount > 0)
+ sect = ns_s_ns, n = nscount;
+ else
+ sect = ns_s_max, n = 0;
+ }
+ for (i = 0; i < n; i++) {
+ const char *t;
+ const u_char *rdata;
+ ns_rr rr;
+
+ if (ns_parserr(&msg, sect, i, &rr) < 0) {
+ DPRINTF(("get_soa: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ goto cleanup;
+ }
+ if (ns_rr_type(rr) == ns_t_cname ||
+ ns_rr_type(rr) == ns_t_dname)
+ break;
+ if (ns_rr_type(rr) != ns_t_soa ||
+ ns_rr_class(rr) != class)
+ continue;
+ t = ns_rr_name(rr);
+ switch (sect) {
+ case ns_s_an:
+ if (ns_samedomain(dname, t) == 0) {
+ DPRINTF(
+ ("get_soa: ns_samedomain('%s', '%s') == 0",
+ dname, t)
+ );
+ errno = EPROTOTYPE;
+ goto cleanup;
+ }
+ break;
+ case ns_s_ns:
+ if (ns_samename(dname, t) == 1 ||
+ ns_samedomain(dname, t) == 0) {
+ DPRINTF(
+ ("get_soa: ns_samename() || !ns_samedomain('%s', '%s')",
+ dname, t)
+ );
+ errno = EPROTOTYPE;
+ goto cleanup;
+ }
+ break;
+ default:
+ abort();
+ }
+ if (strlen(t) + 1 > zsize) {
+ DPRINTF(("get_soa: zname(%lu) too small (%lu)",
+ (unsigned long)zsize,
+ (unsigned long)strlen(t) + 1));
+ errno = EMSGSIZE;
+ goto cleanup;
+ }
+ strcpy(zname, t);
+ rdata = ns_rr_rdata(rr);
+ if (ns_name_uncompress(resp, ns_msg_end(msg), rdata,
+ mname, msize) < 0) {
+ DPRINTF(("get_soa: ns_name_uncompress failed")
+ );
+ goto cleanup;
+ }
+ if (save_ns(statp, &msg, ns_s_ns,
+ zname, class, opts, nsrrsp) < 0) {
+ DPRINTF(("get_soa: save_ns failed"));
+ goto cleanup;
+ }
+ free(resp);
+ return (0);
+ }
+
+ /* If we're out of labels, then not even "." has an SOA! */
+ if (*dname == '\0')
+ break;
+
+ /* Find label-terminating "."; top of loop will skip it. */
+ while (*dname != '.') {
+ if (*dname == '\\')
+ if (*++dname == '\0') {
+ errno = EMSGSIZE;
+ goto cleanup;
+ }
+ dname++;
+ }
+ }
+ DPRINTF(("get_soa: out of labels"));
+ errno = EDESTADDRREQ;
+ cleanup:
+ if (resp != NULL)
+ free(resp);
+ return (-1);
+}
+
+static int
+get_ns(res_state statp, const char *zname, ns_class class, int opts,
+ rrset_ns *nsrrsp)
+{
+ u_char *resp;
+ ns_msg msg;
+ int n;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ return (-1);
+
+ /* Go and get the NS RRs for this zone. */
+ n = do_query(statp, zname, class, ns_t_ns, resp, &msg);
+ if (n != 0) {
+ DPRINTF(("get_ns: do_query('%s', %s) failed (%d)",
+ zname, p_class(class), n));
+ free(resp);
+ return (-1);
+ }
+
+ /* Remember the NS RRs and associated A RRs that came back. */
+ if (save_ns(statp, &msg, ns_s_an, zname, class, opts, nsrrsp) < 0) {
+ DPRINTF(("get_ns save_ns('%s', %s) failed",
+ zname, p_class(class)));
+ free(resp);
+ return (-1);
+ }
+
+ free(resp);
+ return (0);
+}
+
+static int
+get_glue(res_state statp, ns_class class, int opts, rrset_ns *nsrrsp) {
+ rr_ns *nsrr, *nsrr_n;
+ u_char *resp;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ return(-1);
+
+ /* Go and get the A RRs for each empty NS RR on our list. */
+ for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) {
+ ns_msg msg;
+ int n;
+
+ nsrr_n = NEXT(nsrr, link);
+
+ if ((nsrr->flags & RR_NS_HAVE_V4) == 0) {
+ n = do_query(statp, nsrr->name, class, ns_t_a,
+ resp, &msg);
+ if (n < 0) {
+ DPRINTF(
+ ("get_glue: do_query('%s', %s') failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF((
+ "get_glue: do_query('%s', %s') CNAME or DNAME found",
+ nsrr->name, p_class(class)));
+ }
+ if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
+ opts, nsrr) < 0) {
+ DPRINTF(("get_glue: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ }
+
+ if ((nsrr->flags & RR_NS_HAVE_V6) == 0) {
+ n = do_query(statp, nsrr->name, class, ns_t_aaaa,
+ resp, &msg);
+ if (n < 0) {
+ DPRINTF(
+ ("get_glue: do_query('%s', %s') failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF((
+ "get_glue: do_query('%s', %s') CNAME or DNAME found",
+ nsrr->name, p_class(class)));
+ }
+ if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
+ opts, nsrr) < 0) {
+ DPRINTF(("get_glue: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ }
+
+ /* If it's still empty, it's just chaff. */
+ if (EMPTY(nsrr->addrs)) {
+ DPRINTF(("get_glue: removing empty '%s' NS",
+ nsrr->name));
+ free_nsrr(nsrrsp, nsrr);
+ }
+ }
+ free(resp);
+ return (0);
+
+ cleanup:
+ free(resp);
+ return (-1);
+}
+
+static int
+save_ns(res_state statp, ns_msg *msg, ns_sect sect,
+ const char *owner, ns_class class, int opts,
+ rrset_ns *nsrrsp)
+{
+ int i;
+
+ for (i = 0; i < ns_msg_count(*msg, sect); i++) {
+ char tname[MAXDNAME];
+ const u_char *rdata;
+ rr_ns *nsrr;
+ ns_rr rr;
+
+ if (ns_parserr(msg, sect, i, &rr) < 0) {
+ DPRINTF(("save_ns: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ return (-1);
+ }
+ if (ns_rr_type(rr) != ns_t_ns ||
+ ns_rr_class(rr) != class ||
+ ns_samename(ns_rr_name(rr), owner) != 1)
+ continue;
+ nsrr = find_ns(nsrrsp, ns_rr_name(rr));
+ if (nsrr == NULL) {
+ nsrr = malloc(sizeof *nsrr);
+ if (nsrr == NULL) {
+ DPRINTF(("save_ns: malloc failed"));
+ return (-1);
+ }
+ rdata = ns_rr_rdata(rr);
+ if (ns_name_uncompress(ns_msg_base(*msg),
+ ns_msg_end(*msg), rdata,
+ tname, sizeof tname) < 0) {
+ DPRINTF(("save_ns: ns_name_uncompress failed")
+ );
+ free(nsrr);
+ return (-1);
+ }
+ nsrr->name = strdup(tname);
+ if (nsrr->name == NULL) {
+ DPRINTF(("save_ns: strdup failed"));
+ free(nsrr);
+ return (-1);
+ }
+ INIT_LINK(nsrr, link);
+ INIT_LIST(nsrr->addrs);
+ nsrr->flags = 0;
+ APPEND(*nsrrsp, nsrr, link);
+ }
+ if (save_a(statp, msg, ns_s_ar,
+ nsrr->name, class, opts, nsrr) < 0) {
+ DPRINTF(("save_ns: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static int
+save_a(res_state statp, ns_msg *msg, ns_sect sect,
+ const char *owner, ns_class class, int opts,
+ rr_ns *nsrr)
+{
+ int i;
+
+ for (i = 0; i < ns_msg_count(*msg, sect); i++) {
+ ns_rr rr;
+ rr_a *arr;
+
+ if (ns_parserr(msg, sect, i, &rr) < 0) {
+ DPRINTF(("save_a: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ return (-1);
+ }
+ if ((ns_rr_type(rr) != ns_t_a &&
+ ns_rr_type(rr) != ns_t_aaaa) ||
+ ns_rr_class(rr) != class ||
+ ns_samename(ns_rr_name(rr), owner) != 1 ||
+ ns_rr_rdlen(rr) != NS_INADDRSZ)
+ continue;
+ if ((opts & RES_IPV6ONLY) != 0 && ns_rr_type(rr) != ns_t_aaaa)
+ continue;
+ if ((opts & RES_IPV4ONLY) != 0 && ns_rr_type(rr) != ns_t_a)
+ continue;
+ arr = malloc(sizeof *arr);
+ if (arr == NULL) {
+ DPRINTF(("save_a: malloc failed"));
+ return (-1);
+ }
+ INIT_LINK(arr, link);
+ memset(&arr->addr, 0, sizeof(arr->addr));
+ switch (ns_rr_type(rr)) {
+ case ns_t_a:
+ arr->addr.sin.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ arr->addr.sin.sin_len = sizeof(arr->addr.sin);
+#endif
+ memcpy(&arr->addr.sin.sin_addr, ns_rr_rdata(rr),
+ NS_INADDRSZ);
+ arr->addr.sin.sin_port = htons(NAMESERVER_PORT);
+ nsrr->flags |= RR_NS_HAVE_V4;
+ break;
+ case ns_t_aaaa:
+ arr->addr.sin6.sin6_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ arr->addr.sin6.sin6_len = sizeof(arr->addr.sin6);
+#endif
+ memcpy(&arr->addr.sin6.sin6_addr, ns_rr_rdata(rr), 16);
+ arr->addr.sin.sin_port = htons(NAMESERVER_PORT);
+ nsrr->flags |= RR_NS_HAVE_V6;
+ break;
+ default:
+ abort();
+ }
+ APPEND(nsrr->addrs, arr, link);
+ }
+ return (0);
+}
+
+static void
+free_nsrrset(rrset_ns *nsrrsp) {
+ rr_ns *nsrr;
+
+ while ((nsrr = HEAD(*nsrrsp)) != NULL)
+ free_nsrr(nsrrsp, nsrr);
+}
+
+static void
+free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) {
+ rr_a *arr;
+ char *tmp;
+
+ while ((arr = HEAD(nsrr->addrs)) != NULL) {
+ UNLINK(nsrr->addrs, arr, link);
+ free(arr);
+ }
+ DE_CONST(nsrr->name, tmp);
+ free(tmp);
+ UNLINK(*nsrrsp, nsrr, link);
+ free(nsrr);
+}
+
+static rr_ns *
+find_ns(rrset_ns *nsrrsp, const char *dname) {
+ rr_ns *nsrr;
+
+ for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = NEXT(nsrr, link))
+ if (ns_samename(nsrr->name, dname) == 1)
+ return (nsrr);
+ return (NULL);
+}
+
+static int
+do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
+ u_char *resp, ns_msg *msg)
+{
+ u_char req[NS_PACKETSZ];
+ int i, n;
+
+ n = res_nmkquery(statp, ns_o_query, dname, class, qtype,
+ NULL, 0, NULL, req, NS_PACKETSZ);
+ if (n < 0) {
+ DPRINTF(("do_query: res_nmkquery failed"));
+ return (-1);
+ }
+ n = res_nsend(statp, req, n, resp, NS_MAXMSG);
+ if (n < 0) {
+ DPRINTF(("do_query: res_nsend failed"));
+ return (-1);
+ }
+ if (n == 0) {
+ DPRINTF(("do_query: res_nsend returned 0"));
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (ns_initparse(resp, n, msg) < 0) {
+ DPRINTF(("do_query: ns_initparse failed"));
+ return (-1);
+ }
+ n = 0;
+ for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) {
+ ns_rr rr;
+
+ if (ns_parserr(msg, ns_s_an, i, &rr) < 0) {
+ DPRINTF(("do_query: ns_parserr failed"));
+ return (-1);
+ }
+ n += (ns_rr_class(rr) == class &&
+ (ns_rr_type(rr) == ns_t_cname ||
+ ns_rr_type(rr) == ns_t_dname));
+ }
+ return (n);
+}
+
+static void
+res_dprintf(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ fputs(";; res_findzonecut: ", stderr);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_init.c b/freebsd/lib/libc/resolv/res_init.c
new file mode 100644
index 00000000..ec74e5bd
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_init.c
@@ -0,0 +1,874 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static const char rcsid[] = "$Id: res_init.c,v 1.16.18.7 2007/07/09 01:52:58 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+
+#include "un-namespace.h"
+
+#include "port_after.h"
+
+/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
+#include <resolv.h>
+
+#include "res_private.h"
+
+/*% Options. Should all be left alone. */
+#define RESOLVSORT
+#define DEBUG
+
+#ifdef SOLARIS2
+#include <sys/systeminfo.h>
+#endif
+
+static void res_setoptions(res_state, const char *, const char *);
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask(struct in_addr);
+#endif
+
+#if !defined(isascii) /*%< XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+/*%
+ * Set up default settings. If the configuration file exist, the values
+ * there will have precedence. Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server. It
+ * was later decided that since the recommended practice is to always
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain. If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_ninit(res_state statp) {
+ extern int __res_vinit(res_state, int);
+
+ return (__res_vinit(statp, 0));
+}
+
+/*% This function has to be reachable by res_data.c but not publically. */
+int
+__res_vinit(res_state statp, int preinit) {
+ FILE *fp;
+ char *cp, **pp;
+ int n;
+ char buf[BUFSIZ];
+ int nserv = 0; /*%< number of nameserver records read from file */
+ int haveenv = 0;
+ int havesearch = 0;
+#ifdef RESOLVSORT
+ int nsort = 0;
+ char *net;
+#endif
+ int dots;
+ union res_sockaddr_union u[2];
+ int maxns = MAXNS;
+
+ RES_SET_H_ERRNO(statp, 0);
+ if (statp->_u._ext.ext != NULL)
+ res_ndestroy(statp);
+
+ if (!preinit) {
+ statp->retrans = RES_TIMEOUT;
+ statp->retry = RES_DFLRETRY;
+ statp->options = RES_DEFAULT;
+ statp->id = res_randomid();
+ }
+
+ memset(u, 0, sizeof(u));
+#ifdef USELOOPBACK
+ u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+ u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
+#endif
+ u[nserv].sin.sin_family = AF_INET;
+ u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+ u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
+#endif
+ nserv++;
+#ifdef HAS_INET6_STRUCTS
+#ifdef USELOOPBACK
+ u[nserv].sin6.sin6_addr = in6addr_loopback;
+#else
+ u[nserv].sin6.sin6_addr = in6addr_any;
+#endif
+ u[nserv].sin6.sin6_family = AF_INET6;
+ u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+ u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ nserv++;
+#endif
+ statp->nscount = 0;
+ statp->ndots = 1;
+ statp->pfcode = 0;
+ statp->_vcsock = -1;
+ statp->_flags = 0;
+ statp->qhook = NULL;
+ statp->rhook = NULL;
+ statp->_u._ext.nscount = 0;
+ statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
+ if (statp->_u._ext.ext != NULL) {
+ memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
+ statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
+ strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
+ strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
+ } else {
+ /*
+ * Historically res_init() rarely, if at all, failed.
+ * Examples and applications exist which do not check
+ * our return code. Furthermore several applications
+ * simply call us to get the systems domainname. So
+ * rather then immediately fail here we store the
+ * failure, which is returned later, in h_errno. And
+ * prevent the collection of 'nameserver' information
+ * by setting maxns to 0. Thus applications that fail
+ * to check our return code wont be able to make
+ * queries anyhow.
+ */
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ maxns = 0;
+ }
+#ifdef RESOLVSORT
+ statp->nsort = 0;
+#endif
+ res_setservers(statp, u, nserv);
+
+#ifdef SOLARIS2
+ /*
+ * The old libresolv derived the defaultdomain from NIS/NIS+.
+ * We want to keep this behaviour
+ */
+ {
+ char buf[sizeof(statp->defdname)], *cp;
+ int ret;
+
+ if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 &&
+ (unsigned int)ret <= sizeof(buf)) {
+ if (buf[0] == '+')
+ buf[0] = '.';
+ cp = strchr(buf, '.');
+ cp = (cp == NULL) ? buf : (cp + 1);
+ strncpy(statp->defdname, cp,
+ sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ }
+ }
+#endif /* SOLARIS2 */
+
+ /* Allow user to override the local domain definition */
+ if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
+ (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ haveenv++;
+
+ /*
+ * Set search list to be blank-separated strings
+ * from rest of env value. Permits users of LOCALDOMAIN
+ * to still have a search list, and anyone to set the
+ * one that they want to use as an individual (even more
+ * important now that the rfc1535 stuff restricts searches)
+ */
+ cp = statp->defdname;
+ pp = statp->dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == '\n') /*%< silly backwards compat */
+ break;
+ else if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ havesearch = 1;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ }
+
+#define MATCH(line, name) \
+ (!strncmp(line, name, sizeof(name) - 1) && \
+ (line[sizeof(name) - 1] == ' ' || \
+ line[sizeof(name) - 1] == '\t'))
+
+ nserv = 0;
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ /* read the config file */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ /* skip comments */
+ if (*buf == ';' || *buf == '#')
+ continue;
+ /* read default domain name */
+ if (MATCH(buf, "domain")) {
+ if (haveenv) /*%< skip if have from environ */
+ continue;
+ cp = buf + sizeof("domain") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
+ *cp = '\0';
+ havesearch = 0;
+ continue;
+ }
+ /* set search list */
+ if (MATCH(buf, "search")) {
+ if (haveenv) /*%< skip if have from environ */
+ continue;
+ cp = buf + sizeof("search") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strchr(statp->defdname, '\n')) != NULL)
+ *cp = '\0';
+ /*
+ * Set search list to be blank-separated strings
+ * on rest of line.
+ */
+ cp = statp->defdname;
+ pp = statp->dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ havesearch = 1;
+ continue;
+ }
+ /* read nameservers to query */
+ if (MATCH(buf, "nameserver") && nserv < maxns) {
+ struct addrinfo hints, *ai;
+ char sbuf[NI_MAXSERV];
+ const size_t minsiz =
+ sizeof(statp->_u._ext.ext->nsaddrs[0]);
+
+ cp = buf + sizeof("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ cp[strcspn(cp, ";# \t\n")] = '\0';
+ if ((*cp != '\0') && (*cp != '\n')) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ sprintf(sbuf, "%u", NAMESERVER_PORT);
+ if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
+ ai->ai_addrlen <= minsiz) {
+ if (statp->_u._ext.ext != NULL) {
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ ai->ai_addr, ai->ai_addrlen);
+ }
+ if (ai->ai_addrlen <=
+ sizeof(statp->nsaddr_list[nserv])) {
+ memcpy(&statp->nsaddr_list[nserv],
+ ai->ai_addr, ai->ai_addrlen);
+ } else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ freeaddrinfo(ai);
+ nserv++;
+ }
+ }
+ continue;
+ }
+#ifdef RESOLVSORT
+ if (MATCH(buf, "sortlist")) {
+ struct in_addr a;
+ struct in6_addr a6;
+ int m, i;
+ u_char *u;
+ struct __res_state_ext *ext = statp->_u._ext.ext;
+
+ cp = buf + sizeof("sortlist") - 1;
+ while (nsort < MAXRESOLVSORT) {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ break;
+ net = cp;
+ while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+ isascii(*cp) && !isspace((unsigned char)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ statp->sort_list[nsort].addr = a;
+ if (ISSORTMASK(n)) {
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) &&
+ !isspace((unsigned char)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ statp->sort_list[nsort].mask = a.s_addr;
+ } else {
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
+ }
+ } else {
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
+ }
+ ext->sort_list[nsort].af = AF_INET;
+ ext->sort_list[nsort].addr.ina =
+ statp->sort_list[nsort].addr;
+ ext->sort_list[nsort].mask.ina.s_addr =
+ statp->sort_list[nsort].mask;
+ nsort++;
+ }
+ else if (inet_pton(AF_INET6, net, &a6) == 1) {
+
+ ext->sort_list[nsort].af = AF_INET6;
+ ext->sort_list[nsort].addr.in6a = a6;
+ u = (u_char *)&ext->sort_list[nsort].mask.in6a;
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) && !isspace(*cp))
+ cp++;
+ m = n;
+ n = *cp;
+ *cp = 0;
+ switch (m) {
+ case '/':
+ m = atoi(net);
+ break;
+ case '&':
+ if (inet_pton(AF_INET6, net, u) == 1) {
+ m = -1;
+ break;
+ }
+ /*FALLTHROUGH*/
+ default:
+ m = sizeof(struct in6_addr) * CHAR_BIT;
+ break;
+ }
+ if (m >= 0) {
+ for (i = 0; i < sizeof(struct in6_addr); i++) {
+ if (m <= 0) {
+ *u = 0;
+ } else {
+ m -= CHAR_BIT;
+ *u = (u_char)~0;
+ if (m < 0)
+ *u <<= -m;
+ }
+ u++;
+ }
+ }
+ statp->sort_list[nsort].addr.s_addr =
+ (u_int32_t)0xffffffff;
+ statp->sort_list[nsort].mask =
+ (u_int32_t)0xffffffff;
+ nsort++;
+ }
+ *cp = n;
+ }
+ continue;
+ }
+#endif
+ if (MATCH(buf, "options")) {
+ res_setoptions(statp, buf + sizeof("options") - 1, "conf");
+ continue;
+ }
+ }
+ if (nserv > 0)
+ statp->nscount = nserv;
+#ifdef RESOLVSORT
+ statp->nsort = nsort;
+#endif
+ (void) fclose(fp);
+ }
+/*
+ * Last chance to get a nameserver. This should not normally
+ * be necessary
+ */
+#ifdef NO_RESOLV_CONF
+ if(nserv == 0)
+ nserv = get_nameservers(statp);
+#endif
+
+ if (statp->defdname[0] == 0 &&
+ gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
+ (cp = strchr(buf, '.')) != NULL)
+ strcpy(statp->defdname, cp + 1);
+
+ /* find components of local domain that might be searched */
+ if (havesearch == 0) {
+ pp = statp->dnsrch;
+ *pp++ = statp->defdname;
+ *pp = NULL;
+
+ dots = 0;
+ for (cp = statp->defdname; *cp; cp++)
+ dots += (*cp == '.');
+
+ cp = statp->defdname;
+ while (pp < statp->dnsrch + MAXDFLSRCH) {
+ if (dots < LOCALDOMAINPARTS)
+ break;
+ cp = strchr(cp, '.') + 1; /*%< we know there is one */
+ *pp++ = cp;
+ dots--;
+ }
+ *pp = NULL;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG) {
+ printf(";; res_init()... default dnsrch list:\n");
+ for (pp = statp->dnsrch; *pp; pp++)
+ printf(";;\t%s\n", *pp);
+ printf(";;\t..END..\n");
+ }
+#endif
+ }
+
+ if (issetugid())
+ statp->options |= RES_NOALIASES;
+ else if ((cp = getenv("RES_OPTIONS")) != NULL)
+ res_setoptions(statp, cp, "env");
+ statp->options |= RES_INIT;
+ return (statp->res_h_errno);
+}
+
+static void
+res_setoptions(res_state statp, const char *options, const char *source)
+{
+ const char *cp = options;
+ int i;
+#ifndef _LIBC
+ struct __res_state_ext *ext = statp->_u._ext.ext;
+#endif
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+ options, source);
+#endif
+ while (*cp) {
+ /* skip leading and inner runs of spaces */
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ /* search for and process individual options */
+ if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+ i = atoi(cp + sizeof("ndots:") - 1);
+ if (i <= RES_MAXNDOTS)
+ statp->ndots = i;
+ else
+ statp->ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";;\tndots=%d\n", statp->ndots);
+#endif
+ } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
+ i = atoi(cp + sizeof("timeout:") - 1);
+ if (i <= RES_MAXRETRANS)
+ statp->retrans = i;
+ else
+ statp->retrans = RES_MAXRETRANS;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";;\ttimeout=%d\n", statp->retrans);
+#endif
+#ifdef SOLARIS2
+ } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) {
+ /*
+ * For backward compatibility, 'retrans' is
+ * supported as an alias for 'timeout', though
+ * without an imposed maximum.
+ */
+ statp->retrans = atoi(cp + sizeof("retrans:") - 1);
+ } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){
+ /*
+ * For backward compatibility, 'retry' is
+ * supported as an alias for 'attempts', though
+ * without an imposed maximum.
+ */
+ statp->retry = atoi(cp + sizeof("retry:") - 1);
+#endif /* SOLARIS2 */
+ } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
+ i = atoi(cp + sizeof("attempts:") - 1);
+ if (i <= RES_MAXRETRY)
+ statp->retry = i;
+ else
+ statp->retry = RES_MAXRETRY;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";;\tattempts=%d\n", statp->retry);
+#endif
+ } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+ if (!(statp->options & RES_DEBUG)) {
+ printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+ options, source);
+ statp->options |= RES_DEBUG;
+ }
+ printf(";;\tdebug\n");
+#endif
+ } else if (!strncmp(cp, "no_tld_query",
+ sizeof("no_tld_query") - 1) ||
+ !strncmp(cp, "no-tld-query",
+ sizeof("no-tld-query") - 1)) {
+ statp->options |= RES_NOTLDQUERY;
+ } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+ statp->options |= RES_USE_INET6;
+ } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
+ statp->options |= RES_INSECURE1;
+ } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
+ statp->options |= RES_INSECURE2;
+ } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
+ statp->options |= RES_ROTATE;
+ } else if (!strncmp(cp, "no-check-names",
+ sizeof("no-check-names") - 1)) {
+ statp->options |= RES_NOCHECKNAME;
+ }
+#ifdef RES_USE_EDNS0
+ else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
+ statp->options |= RES_USE_EDNS0;
+ }
+#endif
+#ifndef _LIBC
+ else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
+ statp->options |= RES_USE_DNAME;
+ }
+ else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
+ if (ext == NULL)
+ goto skip;
+ cp += sizeof("nibble:") - 1;
+ i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
+ strncpy(ext->nsuffix, cp, i);
+ ext->nsuffix[i] = '\0';
+ }
+ else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
+ if (ext == NULL)
+ goto skip;
+ cp += sizeof("nibble2:") - 1;
+ i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
+ strncpy(ext->nsuffix2, cp, i);
+ ext->nsuffix2[i] = '\0';
+ }
+ else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
+ cp += sizeof("v6revmode:") - 1;
+ /* "nibble" and "bitstring" used to be valid */
+ if (!strncmp(cp, "single", sizeof("single") - 1)) {
+ statp->options |= RES_NO_NIBBLE2;
+ } else if (!strncmp(cp, "both", sizeof("both") - 1)) {
+ statp->options &=
+ ~RES_NO_NIBBLE2;
+ }
+ }
+#endif
+ else {
+ /* XXX - print a warning here? */
+ }
+#ifndef _LIBC
+ skip:
+#endif
+ /* skip to next run of spaces */
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ }
+}
+
+#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
+static u_int32_t
+net_mask(in) /*!< XXX - should really use system's version of this */
+ struct in_addr in;
+{
+ u_int32_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (htonl(IN_CLASSA_NET));
+ else if (IN_CLASSB(i))
+ return (htonl(IN_CLASSB_NET));
+ return (htonl(IN_CLASSC_NET));
+}
+#endif
+
+u_int
+res_randomid(void) {
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}
+
+/*%
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it. This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+res_nclose(res_state statp) {
+ int ns;
+
+ if (statp->_vcsock >= 0) {
+ (void) _close(statp->_vcsock);
+ statp->_vcsock = -1;
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
+ }
+ for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
+ if (statp->_u._ext.nssocks[ns] != -1) {
+ (void) _close(statp->_u._ext.nssocks[ns]);
+ statp->_u._ext.nssocks[ns] = -1;
+ }
+ }
+}
+
+void
+res_ndestroy(res_state statp) {
+ res_nclose(statp);
+ if (statp->_u._ext.ext != NULL)
+ free(statp->_u._ext.ext);
+ statp->options &= ~RES_INIT;
+ statp->_u._ext.ext = NULL;
+}
+
+#ifndef _LIBC
+const char *
+res_get_nibblesuffix(res_state statp) {
+ if (statp->_u._ext.ext)
+ return (statp->_u._ext.ext->nsuffix);
+ return ("ip6.arpa");
+}
+
+const char *
+res_get_nibblesuffix2(res_state statp) {
+ if (statp->_u._ext.ext)
+ return (statp->_u._ext.ext->nsuffix2);
+ return ("ip6.int");
+}
+#endif
+
+void
+res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
+ int i, nserv;
+ size_t size;
+
+ /* close open servers */
+ res_nclose(statp);
+
+ /* cause rtt times to be forgotten */
+ statp->_u._ext.nscount = 0;
+
+ nserv = 0;
+ for (i = 0; i < cnt && nserv < MAXNS; i++) {
+ switch (set->sin.sin_family) {
+ case AF_INET:
+ size = sizeof(set->sin);
+ if (statp->_u._ext.ext)
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ &set->sin, size);
+ if (size <= sizeof(statp->nsaddr_list[nserv]))
+ memcpy(&statp->nsaddr_list[nserv],
+ &set->sin, size);
+ else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ nserv++;
+ break;
+
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ size = sizeof(set->sin6);
+ if (statp->_u._ext.ext)
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ &set->sin6, size);
+ if (size <= sizeof(statp->nsaddr_list[nserv]))
+ memcpy(&statp->nsaddr_list[nserv],
+ &set->sin6, size);
+ else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ nserv++;
+ break;
+#endif
+
+ default:
+ break;
+ }
+ set++;
+ }
+ statp->nscount = nserv;
+
+}
+
+int
+res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
+ int i;
+ size_t size;
+ u_int16_t family;
+
+ for (i = 0; i < statp->nscount && i < cnt; i++) {
+ if (statp->_u._ext.ext)
+ family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
+ else
+ family = statp->nsaddr_list[i].sin_family;
+
+ switch (family) {
+ case AF_INET:
+ size = sizeof(set->sin);
+ if (statp->_u._ext.ext)
+ memcpy(&set->sin,
+ &statp->_u._ext.ext->nsaddrs[i],
+ size);
+ else
+ memcpy(&set->sin, &statp->nsaddr_list[i],
+ size);
+ break;
+
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ size = sizeof(set->sin6);
+ if (statp->_u._ext.ext)
+ memcpy(&set->sin6,
+ &statp->_u._ext.ext->nsaddrs[i],
+ size);
+ else
+ memcpy(&set->sin6, &statp->nsaddr_list[i],
+ size);
+ break;
+#endif
+
+ default:
+ set->sin.sin_family = 0;
+ break;
+ }
+ set++;
+ }
+ return (statp->nscount);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_mkquery.c b/freebsd/lib/libc/resolv/res_mkquery.c
new file mode 100644
index 00000000..074817c4
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_mkquery.c
@@ -0,0 +1,305 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1985, 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_mkquery.c,v 1.5.18.2 2008/04/03 23:15:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+
+extern const char *_res_opcodes[];
+
+/*%
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_nmkquery(res_state statp,
+ int op, /*!< opcode of query */
+ const char *dname, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ const u_char *data, /*!< resource record data */
+ int datalen, /*!< length of data */
+ const u_char *newrr_in, /*!< new rr for modify or append */
+ u_char *buf, /*!< buffer to put query */
+ int buflen) /*!< size of buffer */
+{
+ HEADER *hp;
+ u_char *cp, *ep;
+ int n;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ UNUSED(newrr_in);
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+ _res_opcodes[op], dname, p_class(class), p_type(type));
+#endif
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++statp->id);
+ hp->opcode = op;
+ hp->rd = (statp->options & RES_RECURSE) != 0U;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ ep = buf + buflen;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+ /*
+ * perform opcode specific processing
+ */
+ switch (op) {
+ case QUERY: /*FALLTHROUGH*/
+ case NS_NOTIFY_OP:
+ if (ep - cp < QFIXEDSZ)
+ return (-1);
+ if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ns_put16(type, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ hp->qdcount = htons(1);
+ if (op == QUERY || data == NULL)
+ break;
+ /*
+ * Make an additional record for completion domain.
+ */
+ if ((ep - cp) < RRFIXEDSZ)
+ return (-1);
+ n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ns_put16(T_NULL, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ ns_put32(0, cp);
+ cp += INT32SZ;
+ ns_put16(0, cp);
+ cp += INT16SZ;
+ hp->arcount = htons(1);
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (ep - cp < 1 + RRFIXEDSZ + datalen)
+ return (-1);
+ *cp++ = '\0'; /*%< no domain name */
+ ns_put16(type, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ ns_put32(0, cp);
+ cp += INT32SZ;
+ ns_put16(datalen, cp);
+ cp += INT16SZ;
+ if (datalen) {
+ memcpy(cp, data, datalen);
+ cp += datalen;
+ }
+ hp->ancount = htons(1);
+ break;
+
+ default:
+ return (-1);
+ }
+ return (cp - buf);
+}
+
+#ifdef RES_USE_EDNS0
+/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
+
+int
+res_nopt(res_state statp,
+ int n0, /*%< current offset in buffer */
+ u_char *buf, /*%< buffer to put query */
+ int buflen, /*%< size of buffer */
+ int anslen) /*%< UDP answer buffer size */
+{
+ HEADER *hp;
+ u_char *cp, *ep;
+ u_int16_t flags = 0;
+
+#ifdef DEBUG
+ if ((statp->options & RES_DEBUG) != 0U)
+ printf(";; res_nopt()\n");
+#endif
+
+ hp = (HEADER *) buf;
+ cp = buf + n0;
+ ep = buf + buflen;
+
+ if ((ep - cp) < 1 + RRFIXEDSZ)
+ return (-1);
+
+ *cp++ = 0; /*%< "." */
+ ns_put16(ns_t_opt, cp); /*%< TYPE */
+ cp += INT16SZ;
+ if (anslen > 0xffff)
+ anslen = 0xffff; /* limit to 16bit value */
+ ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
+ cp += INT16SZ;
+ *cp++ = NOERROR; /*%< extended RCODE */
+ *cp++ = 0; /*%< EDNS version */
+
+ if (statp->options & RES_USE_DNSSEC) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_opt()... ENDS0 DNSSEC\n");
+#endif
+ flags |= NS_OPT_DNSSEC_OK;
+ }
+ ns_put16(flags, cp);
+ cp += INT16SZ;
+
+ ns_put16(0U, cp); /*%< RDLEN */
+ cp += INT16SZ;
+
+ hp->arcount = htons(ntohs(hp->arcount) + 1);
+
+ return (cp - buf);
+}
+
+/*
+ * Construct variable data (RDATA) block for OPT psuedo-RR, append it
+ * to the buffer, then update the RDLEN field (previously set to zero by
+ * res_nopt()) with the new RDATA length.
+ */
+int
+res_nopt_rdata(res_state statp,
+ int n0, /*%< current offset in buffer */
+ u_char *buf, /*%< buffer to put query */
+ int buflen, /*%< size of buffer */
+ u_char *rdata, /*%< ptr to start of opt rdata */
+ u_short code, /*%< OPTION-CODE */
+ u_short len, /*%< OPTION-LENGTH */
+ u_char *data) /*%< OPTION_DATA */
+{
+ register u_char *cp, *ep;
+
+#ifdef DEBUG
+ if ((statp->options & RES_DEBUG) != 0U)
+ printf(";; res_nopt_rdata()\n");
+#endif
+
+ cp = buf + n0;
+ ep = buf + buflen;
+
+ if ((ep - cp) < (4 + len))
+ return (-1);
+
+ if (rdata < (buf + 2) || rdata >= ep)
+ return (-1);
+
+ ns_put16(code, cp);
+ cp += INT16SZ;
+
+ ns_put16(len, cp);
+ cp += INT16SZ;
+
+ memcpy(cp, data, len);
+ cp += len;
+
+ len = cp - rdata;
+ ns_put16(len, rdata - 2); /* Update RDLEN field */
+
+ return (cp - buf);
+}
+#endif
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_mkupdate.c b/freebsd/lib/libc/resolv/res_mkupdate.c
new file mode 100644
index 00000000..63f40cbe
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_mkupdate.c
@@ -0,0 +1,1198 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file
+ * \brief
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * &lt;viraj_bais@ccm.fm.intel.com>
+ */
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_mkupdate.c,v 1.4.18.4 2005/10/14 05:44:12 marka Exp $";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifdef _LIBC
+#include <isc/list.h>
+#endif
+
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+#define MAXPORT 1024
+
+static int getnum_str(u_char **, u_char *);
+static int gethexnum_str(u_char **, u_char *);
+static int getword_str(char *, int, u_char **, u_char *);
+static int getstr_str(char *, int, u_char **, u_char *);
+
+#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
+
+/* Forward. */
+
+#ifdef _LIBC
+static
+#endif
+int res_protocolnumber(const char *);
+#ifdef _LIBC
+static
+#endif
+int res_servicenumber(const char *);
+
+/*%
+ * Form update packets.
+ * Returns the size of the resulting packet if no error
+ *
+ * On error,
+ * returns
+ *\li -1 if error in reading a word/number in rdata
+ * portion for update packets
+ *\li -2 if length of buffer passed is insufficient
+ *\li -3 if zone section is not the first section in
+ * the linked list, or section order has a problem
+ *\li -4 on a number overflow
+ *\li -5 unknown operation or no records
+ */
+int
+res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ ns_updrec *rrecp_start = rrecp_in;
+ HEADER *hp;
+ u_char *cp, *sp2, *startp, *endp;
+ int n, i, soanum, multiline;
+ ns_updrec *rrecp;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ char buf2[MAXDNAME];
+ u_char buf3[MAXDNAME];
+ int section, numrrs = 0, counts[ns_s_max];
+ u_int16_t rtype, rclass;
+ u_int32_t n1, rttl;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+#ifndef _LIBC
+ int siglen;
+#endif
+ int keylen, certlen;
+
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++statp->id);
+ hp->opcode = ns_o_update;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+ if (rrecp_start == NULL)
+ return (-5);
+ else if (rrecp_start->r_section != S_ZONE)
+ return (-3);
+
+ memset(counts, 0, sizeof counts);
+ for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) {
+ numrrs++;
+ section = rrecp->r_section;
+ if (section < 0 || section >= ns_s_max)
+ return (-1);
+ counts[section]++;
+ for (i = section + 1; i < ns_s_max; i++)
+ if (counts[i])
+ return (-3);
+ rtype = rrecp->r_type;
+ rclass = rrecp->r_class;
+ rttl = rrecp->r_ttl;
+ /* overload class and type */
+ if (section == S_PREREQ) {
+ rttl = 0;
+ switch (rrecp->r_opcode) {
+ case YXDOMAIN:
+ rclass = C_ANY;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXDOMAIN:
+ rclass = C_NONE;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXRRSET:
+ rclass = C_NONE;
+ rrecp->r_size = 0;
+ break;
+ case YXRRSET:
+ if (rrecp->r_size == 0)
+ rclass = C_ANY;
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ } else if (section == S_UPDATE) {
+ switch (rrecp->r_opcode) {
+ case DELETE:
+ rclass = rrecp->r_size == 0 ? C_ANY : C_NONE;
+ break;
+ case ADD:
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ }
+
+ /*
+ * XXX appending default domain to owner name is omitted,
+ * fqdn must be provided
+ */
+ if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n + 2*INT16SZ);
+ PUTSHORT(rtype, cp);
+ PUTSHORT(rclass, cp);
+ if (section == S_ZONE) {
+ if (numrrs != 1 || rrecp->r_type != T_SOA)
+ return (-3);
+ continue;
+ }
+ ShrinkBuffer(INT32SZ + INT16SZ);
+ PUTLONG(rttl, cp);
+ sp2 = cp; /*%< save pointer to length byte */
+ cp += INT16SZ;
+ if (rrecp->r_size == 0) {
+ if (section == S_UPDATE && rclass != C_ANY)
+ return (-1);
+ else {
+ PUTSHORT(0, sp2);
+ continue;
+ }
+ }
+ startp = rrecp->r_data;
+ endp = startp + rrecp->r_size - 1;
+ /* XXX this should be done centrally. */
+ switch (rrecp->r_type) {
+ case T_A:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ case ns_t_dname:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_MINFO:
+ case T_SOA:
+ case T_RP:
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ if (rrecp->r_type == T_SOA) {
+ ShrinkBuffer(5 * INT32SZ);
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp == '(') {
+ multiline = 1;
+ startp++;
+ } else
+ multiline = 0;
+ /* serial, refresh, retry, expire, minimum */
+ for (i = 0; i < 5; i++) {
+ soanum = getnum_str(&startp, endp);
+ if (soanum < 0)
+ return (-1);
+ PUTLONG(soanum, cp);
+ }
+ if (multiline) {
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp != ')')
+ return (-1);
+ }
+ }
+ break;
+ case T_MX:
+ case T_AFSDB:
+ case T_RT:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_SRV:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_PX:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ PUTSHORT(n, cp);
+ ShrinkBuffer(INT16SZ);
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs,
+ lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ break;
+ case T_WKS: {
+ char bm[MAXPORT/8];
+ unsigned int maxbm = 0;
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if ((i = res_protocolnumber(buf2)) < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = i & 0xff;
+
+ for (i = 0; i < MAXPORT/8 ; i++)
+ bm[i] = 0;
+
+ while (getword_str(buf2, sizeof buf2, &startp, endp)) {
+ if ((n = res_servicenumber(buf2)) <= 0)
+ return (-1);
+
+ if (n < MAXPORT) {
+ bm[n/8] |= (0x80>>(n%8));
+ if ((unsigned)n > maxbm)
+ maxbm = n;
+ } else
+ return (-1);
+ }
+ maxbm = maxbm/8 + 1;
+ ShrinkBuffer(maxbm);
+ memcpy(cp, bm, maxbm);
+ cp += maxbm;
+ break;
+ }
+ case T_HINFO:
+ for (i = 0; i < 2; i++) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
+ case T_TXT:
+ for (;;) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ if (cp != (sp2 + INT16SZ))
+ break;
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
+ case T_X25:
+ /* RFC1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
+ case T_ISDN:
+ /* RFC1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if ((n > 255) || (n == 0))
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ n = 0;
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
+ case T_NSAP:
+ if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else {
+ return (-1);
+ }
+ break;
+ case T_LOC:
+ if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else
+ return (-1);
+ break;
+ case ns_t_sig:
+#ifdef _LIBC
+ return (-1);
+#else
+ {
+ int sig_type, success, dateerror;
+ u_int32_t exptime, timesigned;
+
+ /* type */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ sig_type = sym_ston(__p_type_syms, buf2, &success);
+ if (!success || sig_type == ns_t_any)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(sig_type, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* labels */
+ n = getnum_str(&startp, endp);
+ if (n <= 0 || n > 255)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* ottl & expire */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(rttl, cp);
+ }
+ else {
+ char *ulendp;
+ u_int32_t ottl;
+
+ errno = 0;
+ ottl = strtoul(buf2, &ulendp, 10);
+ if (errno != 0 ||
+ (ulendp != NULL && *ulendp != '\0'))
+ return (-1);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(ottl, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (dateerror)
+ return (-1);
+ }
+ /* expire */
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(exptime, cp);
+ /* timesigned */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ timesigned = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(timesigned, cp);
+ }
+ else
+ return (-1);
+ /* footprint */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* signer name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ /* sig */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ siglen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (siglen < 0)
+ return (-1);
+ ShrinkBuffer(siglen);
+ memcpy(cp, buf3, siglen);
+ cp += siglen;
+ break;
+ }
+#endif
+ case ns_t_key:
+ /* flags */
+ n = gethexnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* proto */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* key */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ keylen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (keylen < 0)
+ return (-1);
+ ShrinkBuffer(keylen);
+ memcpy(cp, buf3, keylen);
+ cp += keylen;
+ break;
+ case ns_t_nxt:
+ {
+ int success, nxt_type;
+ u_char data[32];
+ int maxtype;
+
+ /* next name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ maxtype = 0;
+ memset(data, 0, sizeof data);
+ for (;;) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ break;
+ nxt_type = sym_ston(__p_type_syms, buf2,
+ &success);
+ if (!success || !ns_t_rr_p(nxt_type))
+ return (-1);
+ NS_NXT_BIT_SET(nxt_type, data);
+ if (nxt_type > maxtype)
+ maxtype = nxt_type;
+ }
+ n = maxtype/NS_NXT_BITS+1;
+ ShrinkBuffer(n);
+ memcpy(cp, data, n);
+ cp += n;
+ break;
+ }
+ case ns_t_cert:
+ /* type */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* key tag */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* cert */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ certlen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (certlen < 0)
+ return (-1);
+ ShrinkBuffer(certlen);
+ memcpy(cp, buf3, certlen);
+ cp += certlen;
+ break;
+ case ns_t_aaaa:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (inet_pton(AF_INET6, buf2, &in6a) <= 0)
+ return (-1);
+ ShrinkBuffer(NS_IN6ADDRSZ);
+ memcpy(cp, &in6a, NS_IN6ADDRSZ);
+ cp += NS_IN6ADDRSZ;
+ break;
+ case ns_t_naptr:
+ /* Order Preference Flags Service Replacement Regexp */
+ /* Order */
+ n = getnum_str(&startp, endp);
+ if (n < 0 || n > 65535)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* Preference */
+ n = getnum_str(&startp, endp);
+ if (n < 0 || n > 65535)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* Flags */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Service Classes */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Pattern */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Replacement */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ default:
+ return (-1);
+ } /*switch*/
+ n = (u_int16_t)((cp - sp2) - INT16SZ);
+ PUTSHORT(n, sp2);
+ } /*for*/
+
+ hp->qdcount = htons(counts[0]);
+ hp->ancount = htons(counts[1]);
+ hp->nscount = htons(counts[2]);
+ hp->arcount = htons(counts[3]);
+ return (cp - buf);
+}
+
+/*%
+ * Get a whitespace delimited word from a string (not file)
+ * into buf. modify the start pointer to point after the
+ * word in the string.
+ */
+static int
+getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c;
+
+ for (cp = buf; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (cp != buf) /*%< trailing whitespace */
+ break;
+ else { /*%< leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ (*startpp)++;
+ if (cp >= buf+size-1)
+ break;
+ *cp++ = (u_char)c;
+ }
+ *cp = '\0';
+ return (cp != buf);
+}
+
+/*%
+ * get a white spae delimited string from memory. Process quoted strings
+ * and \\DDD escapes. Return length or -1 on error. Returned string may
+ * contain nulls.
+ */
+static char digits[] = "0123456789";
+static int
+getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c, c1 = 0;
+ int inquote = 0;
+ int seen_quote = 0;
+ int escape = 0;
+ int dig = 0;
+
+ for (cp = buf; *startpp <= endp; ) {
+ if ((c = **startpp) == '\0')
+ break;
+ /* leading white space */
+ if ((cp == buf) && !seen_quote && isspace(c)) {
+ (*startpp)++;
+ continue;
+ }
+
+ switch (c) {
+ case '\\':
+ if (!escape) {
+ escape = 1;
+ dig = 0;
+ c1 = 0;
+ (*startpp)++;
+ continue;
+ }
+ goto do_escape;
+ case '"':
+ if (!escape) {
+ inquote = !inquote;
+ seen_quote = 1;
+ (*startpp)++;
+ continue;
+ }
+ /* fall through */
+ default:
+ do_escape:
+ if (escape) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c1 * 10 +
+ (strchr(digits, c) - digits);
+
+ if (++dig == 3) {
+ c = c1 &0xff;
+ break;
+ }
+ (*startpp)++;
+ continue;
+ }
+ escape = 0;
+ } else if (!inquote && isspace(c))
+ goto done;
+ if (cp >= buf+size-1)
+ goto done;
+ *cp++ = (u_char)c;
+ (*startpp)++;
+ }
+ }
+ done:
+ *cp = '\0';
+ return ((cp == buf)? (seen_quote? 0: -1): (cp - buf));
+}
+
+/*%
+ * Get a whitespace delimited base 16 number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+gethexnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0)
+ return getnum_str(startpp, endp);
+ (*startpp)+=2;
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /*%< trailing whitespace */
+ break;
+ else { /*%< leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isxdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ if (isdigit(c))
+ n = n * 16 + (c - '0');
+ else
+ n = n * 16 + (tolower(c) - 'a' + 10);
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*%
+ * Get a whitespace delimited base 10 number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+getnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /*%< trailing whitespace */
+ break;
+ else { /*%< leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ n = n * 10 + (c - '0');
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*%
+ * Allocate a resource record buffer & save rr info.
+ */
+ns_updrec *
+res_mkupdrec(int section, const char *dname,
+ u_int class, u_int type, u_long ttl) {
+ ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
+
+ if (!rrecp || !(rrecp->r_dname = strdup(dname))) {
+ if (rrecp)
+ free((char *)rrecp);
+ return (NULL);
+ }
+ INIT_LINK(rrecp, r_link);
+ INIT_LINK(rrecp, r_glink);
+ rrecp->r_class = (ns_class)class;
+ rrecp->r_type = (ns_type)type;
+ rrecp->r_ttl = ttl;
+ rrecp->r_section = (ns_sect)section;
+ return (rrecp);
+}
+
+/*%
+ * Free a resource record buffer created by res_mkupdrec.
+ */
+void
+res_freeupdrec(ns_updrec *rrecp) {
+ /* Note: freeing r_dp is the caller's responsibility. */
+ if (rrecp->r_dname != NULL)
+ free(rrecp->r_dname);
+ free(rrecp);
+}
+
+struct valuelist {
+ struct valuelist * next;
+ struct valuelist * prev;
+ char * name;
+ char * proto;
+ int port;
+};
+static struct valuelist *servicelist, *protolist;
+
+static void
+res_buildservicelist() {
+ struct servent *sp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setservent(0);
+#else
+ setservent(1);
+#endif
+ while ((sp = getservent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(sp->s_name);
+ slp->proto = strdup(sp->s_proto);
+ if ((slp->name == NULL) || (slp->proto == NULL)) {
+ if (slp->name) free(slp->name);
+ if (slp->proto) free(slp->proto);
+ free(slp);
+ break;
+ }
+ slp->port = ntohs((u_int16_t)sp->s_port); /*%< host byt order */
+ slp->next = servicelist;
+ slp->prev = NULL;
+ if (servicelist)
+ servicelist->prev = slp;
+ servicelist = slp;
+ }
+ endservent();
+}
+
+#ifndef _LIBC
+void
+res_destroyservicelist() {
+ struct valuelist *slp, *slp_next;
+
+ for (slp = servicelist; slp != NULL; slp = slp_next) {
+ slp_next = slp->next;
+ free(slp->name);
+ free(slp->proto);
+ free(slp);
+ }
+ servicelist = (struct valuelist *)0;
+}
+#endif
+
+#ifdef _LIBC
+static
+#endif
+void
+res_buildprotolist(void) {
+ struct protoent *pp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setprotoent(0);
+#else
+ setprotoent(1);
+#endif
+ while ((pp = getprotoent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(pp->p_name);
+ if (slp->name == NULL) {
+ free(slp);
+ break;
+ }
+ slp->port = pp->p_proto; /*%< host byte order */
+ slp->next = protolist;
+ slp->prev = NULL;
+ if (protolist)
+ protolist->prev = slp;
+ protolist = slp;
+ }
+ endprotoent();
+}
+
+#ifndef _LIBC
+void
+res_destroyprotolist(void) {
+ struct valuelist *plp, *plp_next;
+
+ for (plp = protolist; plp != NULL; plp = plp_next) {
+ plp_next = plp->next;
+ free(plp->name);
+ free(plp);
+ }
+ protolist = (struct valuelist *)0;
+}
+#endif
+
+static int
+findservice(const char *s, struct valuelist **list) {
+ struct valuelist *lp = *list;
+ int n;
+
+ for (; lp != NULL; lp = lp->next)
+ if (strcasecmp(lp->name, s) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ return (lp->port); /*%< host byte order */
+ }
+ if (sscanf(s, "%d", &n) != 1 || n <= 0)
+ n = -1;
+ return (n);
+}
+
+/*%
+ * Convert service name or (ascii) number to int.
+ */
+#ifdef _LIBC
+static
+#endif
+int
+res_servicenumber(const char *p) {
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ return (findservice(p, &servicelist));
+}
+
+/*%
+ * Convert protocol name or (ascii) number to int.
+ */
+#ifdef _LIBC
+static
+#endif
+int
+res_protocolnumber(const char *p) {
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ return (findservice(p, &protolist));
+}
+
+#ifndef _LIBC
+static struct servent *
+cgetservbyport(u_int16_t port, const char *proto) { /*%< Host byte order. */
+ struct valuelist **list = &servicelist;
+ struct valuelist *lp = *list;
+ static struct servent serv;
+
+ port = ntohs(port);
+ for (; lp != NULL; lp = lp->next) {
+ if (port != (u_int16_t)lp->port) /*%< Host byte order. */
+ continue;
+ if (strcasecmp(lp->proto, proto) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ serv.s_name = lp->name;
+ serv.s_port = htons((u_int16_t)lp->port);
+ serv.s_proto = lp->proto;
+ return (&serv);
+ }
+ }
+ return (0);
+}
+
+static struct protoent *
+cgetprotobynumber(int proto) { /*%< Host byte order. */
+ struct valuelist **list = &protolist;
+ struct valuelist *lp = *list;
+ static struct protoent prot;
+
+ for (; lp != NULL; lp = lp->next)
+ if (lp->port == proto) { /*%< Host byte order. */
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ prot.p_name = lp->name;
+ prot.p_proto = lp->port; /*%< Host byte order. */
+ return (&prot);
+ }
+ return (0);
+}
+
+const char *
+res_protocolname(int num) {
+ static char number[8];
+ struct protoent *pp;
+
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ pp = cgetprotobynumber(num);
+ if (pp == 0) {
+ (void) sprintf(number, "%d", num);
+ return (number);
+ }
+ return (pp->p_name);
+}
+
+const char *
+res_servicename(u_int16_t port, const char *proto) { /*%< Host byte order. */
+ static char number[8];
+ struct servent *ss;
+
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ ss = cgetservbyport(htons(port), proto);
+ if (ss == 0) {
+ (void) sprintf(number, "%d", port);
+ return (number);
+ }
+ return (ss->s_name);
+}
+#endif
diff --git a/freebsd/lib/libc/resolv/res_private.h b/freebsd/lib/libc/resolv/res_private.h
new file mode 100644
index 00000000..75217406
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_private.h
@@ -0,0 +1,24 @@
+#include "port_before.h"
+
+#ifndef res_private_h
+#define res_private_h
+
+struct __res_state_ext {
+ union res_sockaddr_union nsaddrs[MAXNS];
+ struct sort_list {
+ int af;
+ union {
+ struct in_addr ina;
+ struct in6_addr in6a;
+ } addr, mask;
+ } sort_list[MAXRESOLVSORT];
+ char nsuffix[64];
+ char nsuffix2[64];
+};
+
+extern int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa);
+
+#endif
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_query.c b/freebsd/lib/libc/resolv/res_query.c
new file mode 100644
index 00000000..734e043a
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_query.c
@@ -0,0 +1,491 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_query.c,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+/*%
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in H_ERRNO.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+int
+res_nquery(res_state statp,
+ const char *name, /*%< domain name */
+ int class, int type, /*%< class and type of query */
+ u_char *answer, /*%< buffer to put answer */
+ int anslen) /*%< size of answer buffer */
+{
+ u_char buf[MAXPACKET];
+ HEADER *hp = (HEADER *) answer;
+ u_int oflags;
+ u_char *rdata;
+ int n;
+
+ oflags = statp->_flags;
+
+again:
+ hp->rcode = NOERROR; /*%< default */
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
+#ifdef RES_USE_EDNS0
+ if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
+ (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) {
+ n = res_nopt(statp, n, buf, sizeof(buf), anslen);
+ rdata = &buf[n];
+ if (n > 0 && (statp->options & RES_NSID) != 0U) {
+ n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata,
+ NS_OPT_NSID, 0, NULL);
+ }
+ }
+#endif
+ if (n <= 0) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (n);
+ }
+
+ n = res_nsend(statp, buf, n, answer, anslen);
+ if (n < 0) {
+#ifdef RES_USE_EDNS0
+ /* if the query choked with EDNS0, retry without EDNS0 */
+ if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U &&
+ ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
+ statp->_flags |= RES_F_EDNS0ERR;
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquery: retry without EDNS0\n");
+ goto again;
+ }
+#endif
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (n);
+ }
+
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n",
+ p_rcode(hp->rcode),
+ ntohs(hp->ancount),
+ ntohs(hp->nscount),
+ ntohs(hp->arcount));
+#endif
+ switch (hp->rcode) {
+ case NXDOMAIN:
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ break;
+ case SERVFAIL:
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ break;
+ case NOERROR:
+ RES_SET_H_ERRNO(statp, NO_DATA);
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ break;
+ }
+ return (-1);
+ }
+ return (n);
+}
+
+/*%
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected. Error code, if any, is left in H_ERRNO.
+ */
+int
+res_nsearch(res_state statp,
+ const char *name, /*%< domain name */
+ int class, int type, /*%< class and type of query */
+ u_char *answer, /*%< buffer to put answer */
+ int anslen) /*%< size of answer */
+{
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *) answer;
+ char tmp[NS_MAXDNAME];
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, root_on_list = 0;
+ int tried_as_is = 0;
+ int searched = 0;
+
+ errno = 0;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /*%< True if we never query. */
+ dots = 0;
+ for (cp = name; *cp != '\0'; cp++)
+ dots += (*cp == '.');
+ trailing_dot = 0;
+ if (cp > name && *--cp == '.')
+ trailing_dot++;
+
+ /* If there aren't any dots, it could be a user-level alias. */
+ if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
+ return (res_nquery(statp, cp, class, type, answer, anslen));
+
+ /*
+ * If there are enough dots in the name, let's just give it a
+ * try 'as is'. The threshold can be set with the "ndots" option.
+ * Also, query 'as is', if there is a trailing dot in the name.
+ */
+ saved_herrno = -1;
+ if (dots >= statp->ndots || trailing_dot) {
+ ret = res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen);
+ if (ret > 0 || trailing_dot)
+ return (ret);
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+ }
+ switch (statp->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ return (-1);
+ }
+ saved_herrno = statp->res_h_errno;
+ tried_as_is++;
+ }
+
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((!dots && (statp->options & RES_DEFNAMES) != 0U) ||
+ (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) {
+ int done = 0;
+
+ for (domain = (const char * const *)statp->dnsrch;
+ *domain && !done;
+ domain++) {
+ searched = 1;
+
+ if (domain[0][0] == '\0' ||
+ (domain[0][0] == '.' && domain[0][1] == '\0'))
+ root_on_list++;
+
+ if (root_on_list && tried_as_is)
+ continue;
+
+ ret = res_nquerydomain(statp, name, *domain,
+ class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+
+ /*
+ * If no server present, give up.
+ * If name isn't found in this domain,
+ * keep trying higher domains in the search list
+ * (if that's enabled).
+ * On a NO_DATA error, keep trying, otherwise
+ * a wildcard entry of another type could keep us
+ * from finding this entry higher in the domain.
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
+ * but try the input name below in case it's
+ * fully-qualified.
+ */
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+ }
+
+ switch (statp->res_h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ /*
+ * This can occur due to a server failure
+ * (that is, all listed servers have failed),
+ * or all listed servers have timed out.
+ * ((HEADER *)answer)->rcode may not be set
+ * to SERVFAIL in the case of a timeout.
+ *
+ * Either way we must return TRY_AGAIN in
+ * order to avoid non-deterministic
+ * return codes.
+ * For example, loaded name servers or races
+ * against network startup/validation (dhcp,
+ * ppp, etc) can cause the search to timeout
+ * on one search element, e.g. 'fu.bar.com',
+ * and return a definitive failure on the
+ * next search element, e.g. 'fu.'.
+ */
+ got_servfail++;
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* anything else implies that we're done */
+ done++;
+ }
+
+ /* if we got here for some reason other than DNSRCH,
+ * we only wanted one iteration of the loop, so stop.
+ */
+ if ((statp->options & RES_DNSRCH) == 0U)
+ done++;
+ }
+ }
+
+ switch (statp->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ goto giveup;
+ }
+
+ /*
+ * If the query has not already been tried as is then try it
+ * unless RES_NOTLDQUERY is set and there were no dots.
+ */
+ if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) &&
+ !(tried_as_is || root_on_list)) {
+ ret = res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+ }
+
+ /* if we got here, we didn't satisfy the search.
+ * if we did an initial full query, return that query's H_ERRNO
+ * (note that we wouldn't be here if that query had succeeded).
+ * else if we ever got a nodata, send that back as the reason.
+ * else send back meaningless H_ERRNO, that being the one from
+ * the last DNSRCH we did.
+ */
+giveup:
+ if (saved_herrno != -1)
+ RES_SET_H_ERRNO(statp, saved_herrno);
+ else if (got_nodata)
+ RES_SET_H_ERRNO(statp, NO_DATA);
+ else if (got_servfail)
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+}
+
+/*%
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+int
+res_nquerydomain(res_state statp,
+ const char *name,
+ const char *domain,
+ int class, int type, /*%< class and type of query */
+ u_char *answer, /*%< buffer to put answer */
+ int anslen) /*%< size of answer */
+{
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+ int n, d;
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
+ name, domain?domain:"<Nil>", class, type);
+#endif
+ if (domain == NULL) {
+ /*
+ * Check for trailing '.';
+ * copy without '.' if present.
+ */
+ n = strlen(name);
+ if (n >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ n--;
+ if (n >= 0 && name[n] == '.') {
+ strncpy(nbuf, name, n);
+ nbuf[n] = '\0';
+ } else
+ longname = name;
+ } else {
+ n = strlen(name);
+ d = strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ sprintf(nbuf, "%s.%s", name, domain);
+ }
+ return (res_nquery(statp, longname, class, type, answer, anslen));
+}
+
+const char *
+res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
+ char *file, *cp1, *cp2;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ if (statp->options & RES_NOALIASES)
+ return (NULL);
+ if (issetugid())
+ return (NULL);
+ file = getenv("HOSTALIASES");
+ if (file == NULL || (fp = fopen(file, "r")) == NULL)
+ return (NULL);
+ setbuf(fp, NULL);
+ buf[sizeof(buf) - 1] = '\0';
+ while (fgets(buf, sizeof(buf), fp)) {
+ for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1)
+ ;
+ if (!*cp1)
+ break;
+ *cp1 = '\0';
+ if (ns_samename(buf, name) == 1) {
+ while (isspace((unsigned char)*++cp1))
+ ;
+ if (!*cp1)
+ break;
+ for (cp2 = cp1 + 1; *cp2 &&
+ !isspace((unsigned char)*cp2); ++cp2)
+ ;
+ *cp2 = '\0';
+ strncpy(dst, cp1, siz - 1);
+ dst[siz - 1] = '\0';
+ fclose(fp);
+ return (dst);
+ }
+ }
+ fclose(fp);
+ return (NULL);
+}
+
+/*! \file */
diff --git a/freebsd/lib/libc/resolv/res_send.c b/freebsd/lib/libc/resolv/res_send.c
new file mode 100644
index 00000000..0d52762c
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_send.c
@@ -0,0 +1,1187 @@
+#include "port_before.h"
+
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * 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, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION 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.
+ */
+
+/*
+ * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_send.c,v 1.9.18.10 2008/01/27 02:06:26 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*! \file
+ * \brief
+ * Send query to name server and wait for reply.
+ */
+
+#include "port_before.h"
+#ifndef USE_KQUEUE
+#include "fd_setsize.h"
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/eventlib.h>
+
+#include "port_after.h"
+
+#ifdef USE_KQUEUE
+#ifdef __rtems__
+#include <freebsd/sys/event.h>
+#else
+#include <sys/event.h>
+#endif /* __rtems__ */
+#else
+#ifdef USE_POLL
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+#include <poll.h>
+#endif /* USE_POLL */
+#endif
+
+#include "un-namespace.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+#include "res_debug.h"
+#include "res_private.h"
+
+#define EXT(res) ((res)->_u._ext)
+
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
+static const int highestFD = FD_SETSIZE - 1;
+#endif
+
+/* Forward. */
+
+static int get_salen(const struct sockaddr *);
+static struct sockaddr * get_nsaddr(res_state, size_t);
+static int send_vc(res_state, const u_char *, int,
+ u_char *, int, int *, int);
+static int send_dg(res_state,
+#ifdef USE_KQUEUE
+ int kq,
+#endif
+ const u_char *, int,
+ u_char *, int, int *, int, int,
+ int *, int *);
+static void Aerror(const res_state, FILE *, const char *, int,
+ const struct sockaddr *, int);
+static void Perror(const res_state, FILE *, const char *, int);
+static int sock_eq(struct sockaddr *, struct sockaddr *);
+#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
+static int pselect(int, void *, void *, void *,
+ struct timespec *,
+ const sigset_t *);
+#endif
+void res_pquery(const res_state, const u_char *, int, FILE *);
+
+static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+
+/* Public. */
+
+/*%
+ * looks up "ina" in _res.ns_addr_list[]
+ *
+ * returns:
+ *\li 0 : not found
+ *\li >0 : found
+ *
+ * author:
+ *\li paul vixie, 29may94
+ */
+int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
+ const struct sockaddr_in *inp, *srv;
+ const struct sockaddr_in6 *in6p, *srv6;
+ int ns;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ inp = (const struct sockaddr_in *)sa;
+ for (ns = 0; ns < statp->nscount; ns++) {
+ srv = (struct sockaddr_in *)get_nsaddr(statp, ns);
+ if (srv->sin_family == inp->sin_family &&
+ srv->sin_port == inp->sin_port &&
+ (srv->sin_addr.s_addr == INADDR_ANY ||
+ srv->sin_addr.s_addr == inp->sin_addr.s_addr))
+ return (1);
+ }
+ break;
+ case AF_INET6:
+ if (EXT(statp).ext == NULL)
+ break;
+ in6p = (const struct sockaddr_in6 *)sa;
+ for (ns = 0; ns < statp->nscount; ns++) {
+ srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns);
+ if (srv6->sin6_family == in6p->sin6_family &&
+ srv6->sin6_port == in6p->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+ (srv6->sin6_scope_id == 0 ||
+ srv6->sin6_scope_id == in6p->sin6_scope_id) &&
+#endif
+ (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
+ IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
+ return (1);
+ }
+ break;
+ default:
+ break;
+ }
+ return (0);
+}
+
+/*%
+ * look for (name,type,class) in the query section of packet (buf,eom)
+ *
+ * requires:
+ *\li buf + HFIXEDSZ <= eom
+ *
+ * returns:
+ *\li -1 : format error
+ *\li 0 : not found
+ *\li >0 : found
+ *
+ * author:
+ *\li paul vixie, 29may94
+ */
+int
+res_nameinquery(const char *name, int type, int class,
+ const u_char *buf, const u_char *eom)
+{
+ const u_char *cp = buf + HFIXEDSZ;
+ int qdcount = ntohs(((const HEADER*)buf)->qdcount);
+
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf, eom, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (ttype == type && tclass == class &&
+ ns_samename(tname, name) == 1)
+ return (1);
+ }
+ return (0);
+}
+
+/*%
+ * is there a 1:1 mapping of (name,type,class)
+ * in (buf1,eom1) and (buf2,eom2)?
+ *
+ * returns:
+ *\li -1 : format error
+ *\li 0 : not a 1:1 mapping
+ *\li >0 : is a 1:1 mapping
+ *
+ * author:
+ *\li paul vixie, 29may94
+ */
+int
+res_queriesmatch(const u_char *buf1, const u_char *eom1,
+ const u_char *buf2, const u_char *eom2)
+{
+ const u_char *cp = buf1 + HFIXEDSZ;
+ int qdcount = ntohs(((const HEADER*)buf1)->qdcount);
+
+ if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
+ return (-1);
+
+ /*
+ * Only header section present in replies to
+ * dynamic update packets.
+ */
+ if ((((const HEADER *)buf1)->opcode == ns_o_update) &&
+ (((const HEADER *)buf2)->opcode == ns_o_update))
+ return (1);
+
+ if (qdcount != ntohs(((const HEADER*)buf2)->qdcount))
+ return (0);
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom1)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+ return (0);
+ }
+ return (1);
+}
+
+int
+res_nsend(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz)
+{
+ int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
+#ifdef USE_KQUEUE
+ int kq;
+#endif
+ char abuf[NI_MAXHOST];
+
+ /* No name servers or res_init() failure */
+ if (statp->nscount == 0 || EXT(statp).ext == NULL) {
+ errno = ESRCH;
+ return (-1);
+ }
+ if (anssiz < HFIXEDSZ) {
+ errno = EINVAL;
+ return (-1);
+ }
+ DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
+ (stdout, ";; res_send()\n"), buf, buflen);
+ v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
+ gotsomewhere = 0;
+ terrno = ETIMEDOUT;
+
+#ifdef USE_KQUEUE
+ if ((kq = kqueue()) < 0) {
+ Perror(statp, stderr, "kqueue", errno);
+ return (-1);
+ }
+#endif
+
+ /*
+ * If the ns_addr_list in the resolver context has changed, then
+ * invalidate our cached copy and the associated timing data.
+ */
+ if (EXT(statp).nscount != 0) {
+ int needclose = 0;
+ struct sockaddr_storage peer;
+ ISC_SOCKLEN_T peerlen;
+
+ if (EXT(statp).nscount != statp->nscount)
+ needclose++;
+ else
+ for (ns = 0; ns < statp->nscount; ns++) {
+ if (statp->nsaddr_list[ns].sin_family &&
+ !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns],
+ (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) {
+ needclose++;
+ break;
+ }
+
+ if (EXT(statp).nssocks[ns] == -1)
+ continue;
+ peerlen = sizeof(peer);
+ if (_getsockname(EXT(statp).nssocks[ns],
+ (struct sockaddr *)&peer, &peerlen) < 0) {
+ needclose++;
+ break;
+ }
+ if (!sock_eq((struct sockaddr *)&peer,
+ get_nsaddr(statp, ns))) {
+ needclose++;
+ break;
+ }
+ }
+ if (needclose) {
+ res_nclose(statp);
+ EXT(statp).nscount = 0;
+ }
+ }
+
+ /*
+ * Maybe initialize our private copy of the ns_addr_list.
+ */
+ if (EXT(statp).nscount == 0) {
+ for (ns = 0; ns < statp->nscount; ns++) {
+ EXT(statp).nstimes[ns] = RES_MAXTIME;
+ EXT(statp).nssocks[ns] = -1;
+ if (!statp->nsaddr_list[ns].sin_family)
+ continue;
+ EXT(statp).ext->nsaddrs[ns].sin =
+ statp->nsaddr_list[ns];
+ }
+ EXT(statp).nscount = statp->nscount;
+ }
+
+ /*
+ * Some resolvers want to even out the load on their nameservers.
+ * Note that RES_BLAST overrides RES_ROTATE.
+ */
+ if ((statp->options & RES_ROTATE) != 0U &&
+ (statp->options & RES_BLAST) == 0U) {
+ union res_sockaddr_union inu;
+ struct sockaddr_in ina;
+ int lastns = statp->nscount - 1;
+ int fd;
+ u_int16_t nstime;
+
+ if (EXT(statp).ext != NULL)
+ inu = EXT(statp).ext->nsaddrs[0];
+ ina = statp->nsaddr_list[0];
+ fd = EXT(statp).nssocks[0];
+ nstime = EXT(statp).nstimes[0];
+ for (ns = 0; ns < lastns; ns++) {
+ if (EXT(statp).ext != NULL)
+ EXT(statp).ext->nsaddrs[ns] =
+ EXT(statp).ext->nsaddrs[ns + 1];
+ statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
+ EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
+ EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
+ }
+ if (EXT(statp).ext != NULL)
+ EXT(statp).ext->nsaddrs[lastns] = inu;
+ statp->nsaddr_list[lastns] = ina;
+ EXT(statp).nssocks[lastns] = fd;
+ EXT(statp).nstimes[lastns] = nstime;
+ }
+
+ /*
+ * Send request, RETRY times, or until successful.
+ */
+ for (tries = 0; tries < statp->retry; tries++) {
+ for (ns = 0; ns < statp->nscount; ns++) {
+ struct sockaddr *nsap;
+ int nsaplen;
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+ statp->_flags &= ~RES_F_LASTMASK;
+ statp->_flags |= (ns << RES_F_LASTSHIFT);
+ same_ns:
+ if (statp->qhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*statp->qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ done = 1;
+ break;
+ case res_nextns:
+ res_nclose(statp);
+ goto next_ns;
+ case res_done:
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ return (resplen);
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ goto fail;
+ }
+ } while (!done);
+ }
+
+ Dprint(((statp->options & RES_DEBUG) &&
+ getnameinfo(nsap, nsaplen, abuf, sizeof(abuf),
+ NULL, 0, niflags) == 0),
+ (stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, abuf));
+
+
+ if (v_circuit) {
+ /* Use VC; at most one attempt per server. */
+ tries = statp->retry;
+ n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
+ ns);
+ if (n < 0)
+ goto fail;
+ if (n == 0)
+ goto next_ns;
+ resplen = n;
+ } else {
+ /* Use datagrams. */
+ n = send_dg(statp,
+#ifdef USE_KQUEUE
+ kq,
+#endif
+ buf, buflen, ans, anssiz, &terrno,
+ ns, tries, &v_circuit, &gotsomewhere);
+ if (n < 0)
+ goto fail;
+ if (n == 0)
+ goto next_ns;
+ if (v_circuit)
+ goto same_ns;
+ resplen = n;
+ }
+
+ Dprint((statp->options & RES_DEBUG) ||
+ ((statp->pfcode & RES_PRF_REPLY) &&
+ (statp->pfcode & RES_PRF_HEAD1)),
+ (stdout, ";; got answer:\n"));
+
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, "%s", ""),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+
+ /*
+ * If we have temporarily opened a virtual circuit,
+ * or if we haven't been asked to keep a socket open,
+ * close the socket.
+ */
+ if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
+ (statp->options & RES_STAYOPEN) == 0U) {
+ res_nclose(statp);
+ }
+ if (statp->rhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*statp->rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ case res_done:
+ done = 1;
+ break;
+ case res_nextns:
+ res_nclose(statp);
+ goto next_ns;
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ goto fail;
+ }
+ } while (!done);
+
+ }
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ return (resplen);
+ next_ns: ;
+ } /*foreach ns*/
+ } /*foreach retry*/
+ res_nclose(statp);
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ if (!v_circuit) {
+ if (!gotsomewhere)
+ errno = ECONNREFUSED; /*%< no nameservers found */
+ else
+ errno = ETIMEDOUT; /*%< no answer obtained */
+ } else
+ errno = terrno;
+ return (-1);
+ fail:
+ res_nclose(statp);
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ return (-1);
+}
+
+/* Private */
+
+static int
+get_salen(sa)
+ const struct sockaddr *sa;
+{
+
+#ifdef HAVE_SA_LEN
+ /* There are people do not set sa_len. Be forgiving to them. */
+ if (sa->sa_len)
+ return (sa->sa_len);
+#endif
+
+ if (sa->sa_family == AF_INET)
+ return (sizeof(struct sockaddr_in));
+ else if (sa->sa_family == AF_INET6)
+ return (sizeof(struct sockaddr_in6));
+ else
+ return (0); /*%< unknown, die on connect */
+}
+
+/*%
+ * pick appropriate nsaddr_list for use. see res_init() for initialization.
+ */
+static struct sockaddr *
+get_nsaddr(statp, n)
+ res_state statp;
+ size_t n;
+{
+
+ if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
+ /*
+ * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
+ * than struct sockaddr, and
+ * - user code did not update statp->nsaddr_list[n].
+ */
+ return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
+ } else {
+ /*
+ * - user code updated statp->nsaddr_list[n], or
+ * - statp->nsaddr_list[n] has the same content as
+ * EXT(statp).ext->nsaddrs[n].
+ */
+ return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
+ }
+}
+
+static int
+send_vc(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz,
+ int *terrno, int ns)
+{
+ const HEADER *hp = (const HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ struct sockaddr *nsap;
+ int nsaplen;
+ int truncating, connreset, resplen, n;
+ struct iovec iov[2];
+ u_short len;
+ u_char *cp;
+ void *tmp;
+#ifdef SO_NOSIGPIPE
+ int on = 1;
+#endif
+
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+
+ connreset = 0;
+ same_ns:
+ truncating = 0;
+
+ /* Are we still talking to whom we want to talk to? */
+ if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
+ struct sockaddr_storage peer;
+ ISC_SOCKLEN_T size = sizeof peer;
+
+ if (_getpeername(statp->_vcsock,
+ (struct sockaddr *)&peer, &size) < 0 ||
+ !sock_eq((struct sockaddr *)&peer, nsap)) {
+ res_nclose(statp);
+ statp->_flags &= ~RES_F_VC;
+ }
+ }
+
+ if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
+ if (statp->_vcsock >= 0)
+ res_nclose(statp);
+
+ statp->_vcsock = _socket(nsap->sa_family, SOCK_STREAM, 0);
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
+ if (statp->_vcsock > highestFD) {
+ res_nclose(statp);
+ errno = ENOTSOCK;
+ }
+#endif
+ if (statp->_vcsock < 0) {
+ switch (errno) {
+ case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT:
+#endif
+ case EAFNOSUPPORT:
+ Perror(statp, stderr, "socket(vc)", errno);
+ return (0);
+ default:
+ *terrno = errno;
+ Perror(statp, stderr, "socket(vc)", errno);
+ return (-1);
+ }
+ }
+#ifdef SO_NOSIGPIPE
+ /*
+ * Disable generation of SIGPIPE when writing to a closed
+ * socket. Write should return -1 and set errno to EPIPE
+ * instead.
+ *
+ * Push on even if setsockopt(SO_NOSIGPIPE) fails.
+ */
+ (void)_setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
+ sizeof(on));
+#endif
+ errno = 0;
+ if (_connect(statp->_vcsock, nsap, nsaplen) < 0) {
+ *terrno = errno;
+ Aerror(statp, stderr, "connect/vc", errno, nsap,
+ nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+ statp->_flags |= RES_F_VC;
+ }
+
+ /*
+ * Send length & message
+ */
+ ns_put16((u_short)buflen, (u_char*)&len);
+ iov[0] = evConsIovec(&len, INT16SZ);
+ DE_CONST(buf, tmp);
+ iov[1] = evConsIovec(tmp, buflen);
+ if (_writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
+ *terrno = errno;
+ Perror(statp, stderr, "write failed", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ /*
+ * Receive length & response
+ */
+ read_len:
+ cp = ans;
+ len = INT16SZ;
+ while ((n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ if ((len -= n) == 0)
+ break;
+ }
+ if (n <= 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "read failed", errno);
+ res_nclose(statp);
+ /*
+ * A long running process might get its TCP
+ * connection reset if the remote server was
+ * restarted. Requery the server instead of
+ * trying a new one. When there is only one
+ * server, this means that a query might work
+ * instead of failing. We only allow one reset
+ * per query to prevent looping.
+ */
+ if (*terrno == ECONNRESET && !connreset) {
+ connreset = 1;
+ res_nclose(statp);
+ goto same_ns;
+ }
+ res_nclose(statp);
+ return (0);
+ }
+ resplen = ns_get16(ans);
+ if (resplen > anssiz) {
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; response truncated\n")
+ );
+ truncating = 1;
+ len = anssiz;
+ } else
+ len = resplen;
+ if (len < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n", len));
+ *terrno = EMSGSIZE;
+ res_nclose(statp);
+ return (0);
+ }
+ cp = ans;
+ while (len != 0 &&
+ (n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ len -= n;
+ }
+ if (n <= 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "read(vc)", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ if (truncating) {
+ /*
+ * Flush rest of answer so connection stays in synch.
+ */
+ anhp->tc = 1;
+ len = resplen - anssiz;
+ while (len != 0) {
+ char junk[PACKETSZ];
+
+ n = _read(statp->_vcsock, junk,
+ (len > sizeof junk) ? sizeof junk : len);
+ if (n > 0)
+ len -= n;
+ else
+ break;
+ }
+ }
+ /*
+ * If the calling applicating has bailed out of
+ * a previous call and failed to arrange to have
+ * the circuit closed or the server has got
+ * itself confused, then drop the packet and
+ * wait for the correct one.
+ */
+ if (hp->id != anhp->id) {
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer (unexpected):\n"),
+ ans, (resplen > anssiz) ? anssiz: resplen);
+ goto read_len;
+ }
+
+ /*
+ * All is well, or the error is fatal. Signal that the
+ * next nameserver ought not be tried.
+ */
+ return (resplen);
+}
+
+static int
+send_dg(res_state statp,
+#ifdef USE_KQUEUE
+ int kq,
+#endif
+ const u_char *buf, int buflen, u_char *ans,
+ int anssiz, int *terrno, int ns, int tries, int *v_circuit,
+ int *gotsomewhere)
+{
+ const HEADER *hp = (const HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ const struct sockaddr *nsap;
+ int nsaplen;
+ struct timespec now, timeout, finish;
+ struct sockaddr_storage from;
+ ISC_SOCKLEN_T fromlen;
+ int resplen, seconds, n, s;
+#ifdef USE_KQUEUE
+ struct kevent kv;
+#else
+#ifdef USE_POLL
+ int polltimeout;
+ struct pollfd pollfd;
+#else
+ fd_set dsmask;
+#endif
+#endif
+
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+ if (EXT(statp).nssocks[ns] == -1) {
+ EXT(statp).nssocks[ns] = _socket(nsap->sa_family,
+ SOCK_DGRAM, 0);
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
+ if (EXT(statp).nssocks[ns] > highestFD) {
+ res_nclose(statp);
+ errno = ENOTSOCK;
+ }
+#endif
+ if (EXT(statp).nssocks[ns] < 0) {
+ switch (errno) {
+ case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT:
+#endif
+ case EAFNOSUPPORT:
+ Perror(statp, stderr, "socket(dg)", errno);
+ return (0);
+ default:
+ *terrno = errno;
+ Perror(statp, stderr, "socket(dg)", errno);
+ return (-1);
+ }
+ }
+#ifndef CANNOT_CONNECT_DGRAM
+ /*
+ * On a 4.3BSD+ machine (client and server,
+ * actually), sending to a nameserver datagram
+ * port with no nameserver will cause an
+ * ICMP port unreachable message to be returned.
+ * If our datagram socket is "connected" to the
+ * server, we get an ECONNREFUSED error on the next
+ * socket operation, and select returns if the
+ * error message is received. We can thus detect
+ * the absence of a nameserver without timing out.
+ *
+ * When the option "insecure1" is specified, we'd
+ * rather expect to see responses from an "unknown"
+ * address. In order to let the kernel accept such
+ * responses, do not connect the socket here.
+ * XXX: or do we need an explicit option to disable
+ * connecting?
+ */
+ if (!(statp->options & RES_INSECURE1) &&
+ _connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {
+ Aerror(statp, stderr, "connect(dg)", errno, nsap,
+ nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; new DG socket\n"))
+ }
+ s = EXT(statp).nssocks[ns];
+#ifndef CANNOT_CONNECT_DGRAM
+ if (statp->options & RES_INSECURE1) {
+ if (_sendto(s,
+ (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) {
+ Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+ } else if (send(s, (const char*)buf, buflen, 0) != buflen) {
+ Perror(statp, stderr, "send", errno);
+ res_nclose(statp);
+ return (0);
+ }
+#else /* !CANNOT_CONNECT_DGRAM */
+ if (_sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
+ {
+ Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+
+ /*
+ * Wait for reply.
+ */
+ seconds = (statp->retrans << tries);
+ if (ns > 0)
+ seconds /= statp->nscount;
+ if (seconds <= 0)
+ seconds = 1;
+ now = evNowTime();
+ timeout = evConsTime(seconds, 0);
+ finish = evAddTime(now, timeout);
+ goto nonow;
+ wait:
+ now = evNowTime();
+ nonow:
+#ifndef USE_POLL
+ if (evCmpTime(finish, now) > 0)
+ timeout = evSubTime(finish, now);
+ else
+ timeout = evConsTime(0, 0);
+#ifdef USE_KQUEUE
+ EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0);
+ n = _kevent(kq, &kv, 1, &kv, 1, &timeout);
+#else
+ FD_ZERO(&dsmask);
+ FD_SET(s, &dsmask);
+ n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
+#endif
+#else
+ timeout = evSubTime(finish, now);
+ if (timeout.tv_sec < 0)
+ timeout = evConsTime(0, 0);
+ polltimeout = 1000*timeout.tv_sec +
+ timeout.tv_nsec/1000000;
+ pollfd.fd = s;
+ pollfd.events = POLLRDNORM;
+ n = poll(&pollfd, 1, polltimeout);
+#endif /* USE_POLL */
+
+ if (n == 0) {
+ Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
+ *gotsomewhere = 1;
+ return (0);
+ }
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+#ifdef USE_KQUEUE
+ Perror(statp, stderr, "kevent", errno);
+#else
+#ifndef USE_POLL
+ Perror(statp, stderr, "select", errno);
+#else
+ Perror(statp, stderr, "poll", errno);
+#endif /* USE_POLL */
+#endif
+ res_nclose(statp);
+ return (0);
+ }
+#ifdef USE_KQUEUE
+ if (kv.ident != s)
+ goto wait;
+#endif
+ errno = 0;
+ fromlen = sizeof(from);
+ resplen = _recvfrom(s, (char*)ans, anssiz,0,
+ (struct sockaddr *)&from, &fromlen);
+ if (resplen <= 0) {
+ Perror(statp, stderr, "recvfrom", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ *gotsomewhere = 1;
+ if (resplen < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n",
+ resplen));
+ *terrno = EMSGSIZE;
+ res_nclose(statp);
+ return (0);
+ }
+ if (hp->id != anhp->id) {
+ /*
+ * response from old query, ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+ if (!(statp->options & RES_INSECURE1) &&
+ !res_ourserver_p(statp, (struct sockaddr *)&from)) {
+ /*
+ * response from wrong server? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; not our server:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+#ifdef RES_USE_EDNS0
+ if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
+ /*
+ * Do not retry if the server do not understand EDNS0.
+ * The case has to be captured here, as FORMERR packet do not
+ * carry query section, hence res_queriesmatch() returns 0.
+ */
+ DprintQ(statp->options & RES_DEBUG,
+ (stdout, "server rejected query with EDNS0:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ /* record the error */
+ statp->_flags |= RES_F_EDNS0ERR;
+ res_nclose(statp);
+ return (0);
+ }
+#endif
+ if (!(statp->options & RES_INSECURE2) &&
+ !res_queriesmatch(buf, buf + buflen,
+ ans, ans + anssiz)) {
+ /*
+ * response contains wrong query? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; wrong query name:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+ if (anhp->rcode == SERVFAIL ||
+ anhp->rcode == NOTIMP ||
+ anhp->rcode == REFUSED) {
+ DprintQ(statp->options & RES_DEBUG,
+ (stdout, "server rejected query:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ res_nclose(statp);
+ /* don't retry if called from dig */
+ if (!statp->pfcode)
+ return (0);
+ }
+ if (!(statp->options & RES_IGNTC) && anhp->tc) {
+ /*
+ * To get the rest of answer,
+ * use TCP with same server.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; truncated answer\n"));
+ *v_circuit = 1;
+ res_nclose(statp);
+ return (1);
+ }
+ /*
+ * All is well, or the error is fatal. Signal that the
+ * next nameserver ought not be tried.
+ */
+ return (resplen);
+}
+
+static void
+Aerror(const res_state statp, FILE *file, const char *string, int error,
+ const struct sockaddr *address, int alen)
+{
+ int save = errno;
+ char hbuf[NI_MAXHOST];
+ char sbuf[NI_MAXSERV];
+
+ alen = alen;
+
+ if ((statp->options & RES_DEBUG) != 0U) {
+ if (getnameinfo(address, alen, hbuf, sizeof(hbuf),
+ sbuf, sizeof(sbuf), niflags)) {
+ strncpy(hbuf, "?", sizeof(hbuf) - 1);
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ strncpy(sbuf, "?", sizeof(sbuf) - 1);
+ sbuf[sizeof(sbuf) - 1] = '\0';
+ }
+ fprintf(file, "res_send: %s ([%s].%s): %s\n",
+ string, hbuf, sbuf, strerror(error));
+ }
+ errno = save;
+}
+
+static void
+Perror(const res_state statp, FILE *file, const char *string, int error) {
+ int save = errno;
+
+ if ((statp->options & RES_DEBUG) != 0U)
+ fprintf(file, "res_send: %s: %s\n",
+ string, strerror(error));
+ errno = save;
+}
+
+static int
+sock_eq(struct sockaddr *a, struct sockaddr *b) {
+ struct sockaddr_in *a4, *b4;
+ struct sockaddr_in6 *a6, *b6;
+
+ if (a->sa_family != b->sa_family)
+ return 0;
+ switch (a->sa_family) {
+ case AF_INET:
+ a4 = (struct sockaddr_in *)a;
+ b4 = (struct sockaddr_in *)b;
+ return a4->sin_port == b4->sin_port &&
+ a4->sin_addr.s_addr == b4->sin_addr.s_addr;
+ case AF_INET6:
+ a6 = (struct sockaddr_in6 *)a;
+ b6 = (struct sockaddr_in6 *)b;
+ return a6->sin6_port == b6->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+ a6->sin6_scope_id == b6->sin6_scope_id &&
+#endif
+ IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
+ default:
+ return 0;
+ }
+}
+
+#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
+/* XXX needs to move to the porting library. */
+static int
+pselect(int nfds, void *rfds, void *wfds, void *efds,
+ struct timespec *tsp, const sigset_t *sigmask)
+{
+ struct timeval tv, *tvp;
+ sigset_t sigs;
+ int n;
+
+ if (tsp) {
+ tvp = &tv;
+ tv = evTimeVal(*tsp);
+ } else
+ tvp = NULL;
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, sigmask, &sigs);
+ n = select(nfds, rfds, wfds, efds, tvp);
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigs, NULL);
+ if (tsp)
+ *tsp = evTimeSpec(tv);
+ return (n);
+}
+#endif
diff --git a/freebsd/lib/libc/resolv/res_state.c b/freebsd/lib/libc/resolv/res_state.c
new file mode 100644
index 00000000..8a82db7e
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_state.c
@@ -0,0 +1,91 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 2006 The FreeBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <stdlib.h>
+
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+
+#undef _res
+
+struct __res_state _res;
+
+static thread_key_t res_key;
+static once_t res_init_once = ONCE_INITIALIZER;
+static int res_thr_keycreated = 0;
+
+static void
+free_res(void *ptr)
+{
+ res_state statp = ptr;
+
+ if (statp->_u._ext.ext != NULL)
+ res_ndestroy(statp);
+ free(statp);
+}
+
+static void
+res_keycreate(void)
+{
+ res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0;
+}
+
+res_state
+__res_state(void)
+{
+ res_state statp;
+
+#ifndef __rtems__
+ if (thr_main() != 0)
+ return (&_res);
+#endif /* __rtems__ */
+
+ if (thr_once(&res_init_once, res_keycreate) != 0 ||
+ !res_thr_keycreated)
+ return (&_res);
+
+ statp = thr_getspecific(res_key);
+ if (statp != NULL)
+ return (statp);
+ statp = calloc(1, sizeof(*statp));
+ if (statp == NULL)
+ return (&_res);
+#ifdef __BIND_RES_TEXT
+ statp->options = RES_TIMEOUT; /* Motorola, et al. */
+#endif
+ if (thr_setspecific(res_key, statp) == 0)
+ return (statp);
+ free(statp);
+ return (&_res);
+}
diff --git a/freebsd/lib/libc/resolv/res_update.c b/freebsd/lib/libc/resolv/res_update.c
new file mode 100644
index 00000000..58faac9c
--- /dev/null
+++ b/freebsd/lib/libc/resolv/res_update.c
@@ -0,0 +1,227 @@
+#include "port_before.h"
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_update.c,v 1.12.18.1 2005/04/27 05:01:12 sra Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file
+ * \brief
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * &lt;viraj_bais@ccm.fm.intel.com>
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <res_update.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __rtems__
+#include <isc/print.h>
+#endif
+#include <isc/list.h>
+#include <resolv.h>
+
+#include "port_after.h"
+#include "res_private.h"
+
+/*%
+ * Separate a linked list of records into groups so that all records
+ * in a group will belong to a single zone on the nameserver.
+ * Create a dynamic update packet for each zone and send it to the
+ * nameservers for that zone, and await answer.
+ * Abort if error occurs in updating any zone.
+ * Return the number of zones updated on success, < 0 on error.
+ *
+ * On error, caller must deal with the unsynchronized zones
+ * eg. an A record might have been successfully added to the forward
+ * zone but the corresponding PTR record would be missing if error
+ * was encountered while updating the reverse zone.
+ */
+
+struct zonegrp {
+ char z_origin[MAXDNAME];
+ ns_class z_class;
+ union res_sockaddr_union z_nsaddrs[MAXNS];
+ int z_nscount;
+ int z_flags;
+ LIST(ns_updrec) z_rrlist;
+ LINK(struct zonegrp) z_link;
+};
+
+#define ZG_F_ZONESECTADDED 0x0001
+
+/* Forward. */
+
+static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
+
+/* Macros. */
+
+#define DPRINTF(x) do {\
+ int save_errno = errno; \
+ if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \
+ errno = save_errno; \
+ } while (0)
+
+/* Public. */
+
+int
+res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) {
+ ns_updrec *rrecp;
+ u_char answer[PACKETSZ];
+ u_char *packet;
+ struct zonegrp *zptr, tgrp;
+ LIST(struct zonegrp) zgrps;
+ int nzones = 0, nscount = 0, n;
+ union res_sockaddr_union nsaddrs[MAXNS];
+
+ packet = malloc(NS_MAXMSG);
+ if (packet == NULL) {
+ DPRINTF(("malloc failed"));
+ return (0);
+ }
+ /* Thread all of the updates onto a list of groups. */
+ INIT_LIST(zgrps);
+ memset(&tgrp, 0, sizeof (tgrp));
+ for (rrecp = rrecp_in; rrecp;
+ rrecp = LINKED(rrecp, r_link) ? NEXT(rrecp, r_link) : NULL) {
+ int nscnt;
+ /* Find the origin for it if there is one. */
+ tgrp.z_class = rrecp->r_class;
+ nscnt = res_findzonecut2(statp, rrecp->r_dname, tgrp.z_class,
+ RES_EXHAUSTIVE, tgrp.z_origin,
+ sizeof tgrp.z_origin,
+ tgrp.z_nsaddrs, MAXNS);
+ if (nscnt <= 0) {
+ DPRINTF(("res_findzonecut failed (%d)", nscnt));
+ goto done;
+ }
+ tgrp.z_nscount = nscnt;
+ /* Find the group for it if there is one. */
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link))
+ if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 &&
+ tgrp.z_class == zptr->z_class)
+ break;
+ /* Make a group for it if there isn't one. */
+ if (zptr == NULL) {
+ zptr = malloc(sizeof *zptr);
+ if (zptr == NULL) {
+ DPRINTF(("malloc failed"));
+ goto done;
+ }
+ *zptr = tgrp;
+ zptr->z_flags = 0;
+ INIT_LINK(zptr, z_link);
+ INIT_LIST(zptr->z_rrlist);
+ APPEND(zgrps, zptr, z_link);
+ }
+ /* Thread this rrecp onto the right group. */
+ APPEND(zptr->z_rrlist, rrecp, r_glink);
+ }
+
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) {
+ /* Construct zone section and prepend it. */
+ rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
+ zptr->z_class, ns_t_soa, 0);
+ if (rrecp == NULL) {
+ DPRINTF(("res_mkupdrec failed"));
+ goto done;
+ }
+ PREPEND(zptr->z_rrlist, rrecp, r_glink);
+ zptr->z_flags |= ZG_F_ZONESECTADDED;
+
+ /* Marshall the update message. */
+ n = res_nmkupdate(statp, HEAD(zptr->z_rrlist),
+ packet, NS_MAXMSG);
+ DPRINTF(("res_mkupdate -> %d", n));
+ if (n < 0)
+ goto done;
+
+ /* Temporarily replace the resolver's nameserver set. */
+ nscount = res_getservers(statp, nsaddrs, MAXNS);
+ res_setservers(statp, zptr->z_nsaddrs, zptr->z_nscount);
+
+ /* Send the update and remember the result. */
+ if (key != NULL) {
+#ifdef _LIBC
+ DPRINTF(("TSIG is not supported\n"));
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ goto done;
+#else
+ n = res_nsendsigned(statp, packet, n, key,
+ answer, sizeof answer);
+#endif
+ } else
+ n = res_nsend(statp, packet, n, answer, sizeof answer);
+ if (n < 0) {
+ DPRINTF(("res_nsend: send error, n=%d (%s)\n",
+ n, strerror(errno)));
+ goto done;
+ }
+ if (((HEADER *)answer)->rcode == NOERROR)
+ nzones++;
+
+ /* Restore resolver's nameserver set. */
+ res_setservers(statp, nsaddrs, nscount);
+ nscount = 0;
+ }
+ done:
+ while (!EMPTY(zgrps)) {
+ zptr = HEAD(zgrps);
+ if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0)
+ res_freeupdrec(HEAD(zptr->z_rrlist));
+ UNLINK(zgrps, zptr, z_link);
+ free(zptr);
+ }
+ if (nscount != 0)
+ res_setservers(statp, nsaddrs, nscount);
+
+ free(packet);
+ return (nzones);
+}
+
+/* Private. */
+
+static void
+res_dprintf(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ fputs(";; res_nupdate: ", stderr);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
diff --git a/freebsd/lib/libc/stdio/fgetln.c b/freebsd/lib/libc/stdio/fgetln.c
new file mode 100644
index 00000000..72f3b620
--- /dev/null
+++ b/freebsd/lib/libc/stdio/fgetln.c
@@ -0,0 +1,169 @@
+#include "port_before.h"
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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 defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+/*
+ * Expand the line buffer. Return -1 on error.
+#ifdef notdef
+ * The `new size' does not account for a terminating '\0',
+ * so we add 1 here.
+#endif
+ */
+int
+__slbexpand(FILE *fp, size_t newsize)
+{
+ void *p;
+
+#ifdef notdef
+ ++newsize;
+#endif
+ if (fp->_lb._size >= newsize)
+ return (0);
+ if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+ return (-1);
+ fp->_lb._base = p;
+ fp->_lb._size = newsize;
+ return (0);
+}
+
+/*
+ * Get an input line. The returned pointer often (but not always)
+ * points into a stdio buffer. Fgetln does not alter the text of
+ * the returned line (which is thus not a C string because it will
+ * not necessarily end with '\0'), but does allow callers to modify
+ * it if they wish. Thus, we set __SMOD in case the caller does.
+ */
+char *
+fgetln(FILE *fp, size_t *lenp)
+{
+ unsigned char *p;
+ size_t len;
+ size_t off;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+ /* make sure there is input */
+ if (fp->_r <= 0 && __srefill(fp)) {
+ *lenp = 0;
+ FUNLOCKFILE(fp);
+ return (NULL);
+ }
+
+ /* look for a newline in the input */
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
+ char *ret;
+
+ /*
+ * Found one. Flag buffer as modified to keep fseek from
+ * `optimising' a backward seek, in case the user stomps on
+ * the text.
+ */
+ p++; /* advance over it */
+ ret = (char *)fp->_p;
+ *lenp = len = p - fp->_p;
+#ifndef __rtems__
+
+ fp->_flags |= __SMOD;
+#endif
+ fp->_r -= len;
+ fp->_p = p;
+ FUNLOCKFILE(fp);
+ return (ret);
+ }
+
+ /*
+ * We have to copy the current buffered data to the line buffer.
+ * As a bonus, though, we can leave off the __SMOD.
+ *
+ * OPTIMISTIC is length that we (optimistically) expect will
+ * accomodate the `rest' of the string, on each trip through the
+ * loop below.
+ */
+#define OPTIMISTIC 80
+
+ for (len = fp->_r, off = 0;; len += fp->_r) {
+ size_t diff;
+
+ /*
+ * Make sure there is room for more bytes. Copy data from
+ * file buffer to line buffer, refill file and look for
+ * newline. The loop stops only when we find a newline.
+ */
+ if (__slbexpand(fp, len + OPTIMISTIC))
+ goto error;
+ (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+ len - off);
+ off = len;
+ if (__srefill(fp))
+ break; /* EOF or error: return partial line */
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
+ continue;
+
+ /* got it: finish up the line (like code above) */
+ p++;
+ diff = p - fp->_p;
+ len += diff;
+ if (__slbexpand(fp, len))
+ goto error;
+ (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+ diff);
+ fp->_r -= diff;
+ fp->_p = p;
+ break;
+ }
+ *lenp = len;
+#ifdef notdef
+ fp->_lb._base[len] = 0;
+#endif
+ FUNLOCKFILE(fp);
+ return ((char *)fp->_lb._base);
+
+error:
+ *lenp = 0; /* ??? */
+ FUNLOCKFILE(fp);
+ return (NULL); /* ??? */
+}
diff --git a/freebsd/lib/libc/stdio/local.h b/freebsd/lib/libc/stdio/local.h
new file mode 100644
index 00000000..986e8994
--- /dev/null
+++ b/freebsd/lib/libc/stdio/local.h
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * 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.
+ *
+ * @(#)local.h 8.3 (Berkeley) 7/3/94
+ * $FreeBSD$
+ */
+
+#include <sys/types.h> /* for off_t */
+#include <pthread.h>
+#include <string.h>
+#include <wchar.h>
+
+/*
+ * Information local to this implementation of stdio,
+ * in particular, macros and private variables.
+ */
+
+extern int _sread(FILE *, char *, int);
+extern int _swrite(FILE *, char const *, int);
+extern fpos_t _sseek(FILE *, fpos_t, int);
+extern int _ftello(FILE *, fpos_t *);
+extern int _fseeko(FILE *, off_t, int, int);
+extern int __fflush(FILE *fp);
+extern void __fcloseall(void);
+extern wint_t __fgetwc(FILE *);
+extern wint_t __fputwc(wchar_t, FILE *);
+extern int __sflush(FILE *);
+extern FILE *__sfp(void);
+extern int __slbexpand(FILE *, size_t);
+#ifndef __rtems__
+extern int __srefill(FILE *);
+#else
+/*
+ * __srefill is used by fgetln(). The method is in newlib but the
+ * prototype is in a private .h which is not installed.
+ * allows it to be pulled from newlib.
+ */
+extern int __srefill_r(struct _reent *,FILE *);
+
+#define __srefill(_x) __srefill_r(__getreent(), _x)
+#endif
+extern int __sread(void *, char *, int);
+extern int __swrite(void *, char const *, int);
+extern fpos_t __sseek(void *, fpos_t, int);
+extern int __sclose(void *);
+extern void __sinit(void);
+extern void _cleanup(void);
+extern void __smakebuf(FILE *);
+extern int __swhatbuf(FILE *, size_t *, int *);
+extern int _fwalk(int (*)(FILE *));
+extern int __svfscanf(FILE *, const char *, __va_list);
+extern int __swsetup(FILE *);
+extern int __sflags(const char *, int *);
+extern int __ungetc(int, FILE *);
+extern wint_t __ungetwc(wint_t, FILE *);
+extern int __vfprintf(FILE *, const char *, __va_list);
+extern int __vfscanf(FILE *, const char *, __va_list);
+extern int __vfwprintf(FILE *, const wchar_t *, __va_list);
+extern int __vfwscanf(FILE * __restrict, const wchar_t * __restrict,
+ __va_list);
+extern size_t __fread(void * __restrict buf, size_t size, size_t count,
+ FILE * __restrict fp);
+extern int __sdidinit;
+
+
+/*
+ * Prepare the given FILE for writing, and return 0 iff it
+ * can be written now. Otherwise, return EOF and set errno.
+ */
+#define prepwrite(fp) \
+ ((((fp)->_flags & __SWR) == 0 || \
+ ((fp)->_bf._base == NULL && ((fp)->_flags & __SSTR) == 0)) && \
+ __swsetup(fp))
+
+/*
+ * Test whether the given stdio file has an active ungetc buffer;
+ * release such a buffer, without restoring ordinary unread data.
+ */
+#define HASUB(fp) ((fp)->_ub._base != NULL)
+#define FREEUB(fp) { \
+ if ((fp)->_ub._base != (fp)->_ubuf) \
+ free((char *)(fp)->_ub._base); \
+ (fp)->_ub._base = NULL; \
+}
+
+/*
+ * test for an fgetln() buffer.
+ */
+#define HASLB(fp) ((fp)->_lb._base != NULL)
+#define FREELB(fp) { \
+ free((char *)(fp)->_lb._base); \
+ (fp)->_lb._base = NULL; \
+}
+
+/*
+ * Structure initializations for 'fake' FILE objects.
+ */
+#define FAKE_FILE { \
+ ._file = -1, \
+ ._fl_mutex = PTHREAD_MUTEX_INITIALIZER, \
+}
+
+/*
+ * Set the orientation for a stream. If o > 0, the stream has wide-
+ * orientation. If o < 0, the stream has byte-orientation.
+ */
+#ifdef __rtems__
+#define ORIENT(fp, o)
+#else
+#define ORIENT(fp, o) do { \
+ if ((fp)->_orientation == 0) \
+ (fp)->_orientation = (o); \
+} while (0)
+#endif
diff --git a/freebsd/lib/libc/stdlib/strtonum.c b/freebsd/lib/libc/stdlib/strtonum.c
new file mode 100644
index 00000000..6dccd973
--- /dev/null
+++ b/freebsd/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define INVALID 1
+#define TOOSMALL 2
+#define TOOLARGE 3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+ const char **errstrp)
+{
+ long long ll = 0;
+ char *ep;
+ int error = 0;
+ struct errval {
+ const char *errstr;
+ int err;
+ } ev[4] = {
+ { NULL, 0 },
+ { "invalid", EINVAL },
+ { "too small", ERANGE },
+ { "too large", ERANGE },
+ };
+
+ ev[0].err = errno;
+ errno = 0;
+ if (minval > maxval)
+ error = INVALID;
+ else {
+ ll = strtoll(numstr, &ep, 10);
+ if (errno == EINVAL || numstr == ep || *ep != '\0')
+ error = INVALID;
+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+ error = TOOSMALL;
+ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+ error = TOOLARGE;
+ }
+ if (errstrp != NULL)
+ *errstrp = ev[error].errstr;
+ errno = ev[error].err;
+ if (error)
+ ll = 0;
+
+ return (ll);
+}
diff --git a/freebsd/lib/libc/string/strsep.c b/freebsd/lib/libc/string/strsep.c
new file mode 100644
index 00000000..afdbee6d
--- /dev/null
+++ b/freebsd/lib/libc/string/strsep.c
@@ -0,0 +1,77 @@
+#include "port_before.h"
+
+/*-
+ * 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(char **stringp, const char *delim)
+{
+ char *s;
+ const char *spanp;
+ int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/freebsd/lib/libipsec/ipsec_dump_policy.c b/freebsd/lib/libipsec/ipsec_dump_policy.c
new file mode 100644
index 00000000..80cad7a0
--- /dev/null
+++ b/freebsd/lib/libipsec/ipsec_dump_policy.c
@@ -0,0 +1,312 @@
+/* $KAME: ipsec_dump_policy.c,v 1.13 2002/06/27 14:35:11 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#ifdef __rtems__
+#include <freebsd/netipsec/key_var.h>
+#include <freebsd/netinet/in.h>
+#include <freebsd/netipsec/ipsec.h>
+#else
+#include <netipsec/key_var.h>
+#include <netinet/in.h>
+#include <netipsec/ipsec.h>
+#endif
+
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+
+#include "ipsec_strerror.h"
+
+static const char *ipsp_dir_strs[] = {
+ "any", "in", "out",
+};
+
+static const char *ipsp_policy_strs[] = {
+ "discard", "none", "ipsec", "entrust", "bypass",
+};
+
+static char *ipsec_dump_ipsecrequest(char *, size_t,
+ struct sadb_x_ipsecrequest *, size_t);
+static int set_addresses(char *, size_t, struct sockaddr *, struct sockaddr *);
+static char *set_address(char *, size_t, struct sockaddr *);
+
+/*
+ * policy is sadb_x_policy buffer.
+ * Must call free() later.
+ * When delimiter == NULL, alternatively ' '(space) is applied.
+ */
+char *
+ipsec_dump_policy(policy, delimiter)
+ caddr_t policy;
+ char *delimiter;
+{
+ struct sadb_x_policy *xpl = (struct sadb_x_policy *)policy;
+ struct sadb_x_ipsecrequest *xisr;
+ size_t off, buflen;
+ char *buf;
+ char isrbuf[1024];
+ char *newbuf;
+
+ /* sanity check */
+ if (policy == NULL)
+ return NULL;
+ if (xpl->sadb_x_policy_exttype != SADB_X_EXT_POLICY) {
+ __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
+ return NULL;
+ }
+
+ /* set delimiter */
+ if (delimiter == NULL)
+ delimiter = " ";
+
+ switch (xpl->sadb_x_policy_dir) {
+ case IPSEC_DIR_ANY:
+ case IPSEC_DIR_INBOUND:
+ case IPSEC_DIR_OUTBOUND:
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_DIR;
+ return NULL;
+ }
+
+ switch (xpl->sadb_x_policy_type) {
+ case IPSEC_POLICY_DISCARD:
+ case IPSEC_POLICY_NONE:
+ case IPSEC_POLICY_IPSEC:
+ case IPSEC_POLICY_BYPASS:
+ case IPSEC_POLICY_ENTRUST:
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_POLICY;
+ return NULL;
+ }
+
+ buflen = strlen(ipsp_dir_strs[xpl->sadb_x_policy_dir])
+ + 1 /* space */
+ + strlen(ipsp_policy_strs[xpl->sadb_x_policy_type])
+ + 1; /* NUL */
+
+ if ((buf = malloc(buflen)) == NULL) {
+ __ipsec_errcode = EIPSEC_NO_BUFS;
+ return NULL;
+ }
+ snprintf(buf, buflen, "%s %s", ipsp_dir_strs[xpl->sadb_x_policy_dir],
+ ipsp_policy_strs[xpl->sadb_x_policy_type]);
+
+ if (xpl->sadb_x_policy_type != IPSEC_POLICY_IPSEC) {
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return buf;
+ }
+
+ /* count length of buffer for use */
+ off = sizeof(*xpl);
+ while (off < PFKEY_EXTLEN(xpl)) {
+ xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off);
+ off += xisr->sadb_x_ipsecrequest_len;
+ }
+
+ /* validity check */
+ if (off != PFKEY_EXTLEN(xpl)) {
+ __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
+ free(buf);
+ return NULL;
+ }
+
+ off = sizeof(*xpl);
+ while (off < PFKEY_EXTLEN(xpl)) {
+ xisr = (struct sadb_x_ipsecrequest *)((caddr_t)xpl + off);
+
+ if (ipsec_dump_ipsecrequest(isrbuf, sizeof(isrbuf), xisr,
+ PFKEY_EXTLEN(xpl) - off) == NULL) {
+ free(buf);
+ return NULL;
+ }
+
+ buflen = strlen(buf) + strlen(delimiter) + strlen(isrbuf) + 1;
+ newbuf = (char *)realloc(buf, buflen);
+ if (newbuf == NULL) {
+ __ipsec_errcode = EIPSEC_NO_BUFS;
+ free(buf);
+ return NULL;
+ }
+ buf = newbuf;
+ snprintf(buf, buflen, "%s%s%s", buf, delimiter, isrbuf);
+
+ off += xisr->sadb_x_ipsecrequest_len;
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return buf;
+}
+
+static char *
+ipsec_dump_ipsecrequest(buf, len, xisr, bound)
+ char *buf;
+ size_t len;
+ struct sadb_x_ipsecrequest *xisr;
+ size_t bound; /* boundary */
+{
+ const char *proto, *mode, *level;
+ char abuf[NI_MAXHOST * 2 + 2];
+
+ if (xisr->sadb_x_ipsecrequest_len > bound) {
+ __ipsec_errcode = EIPSEC_INVAL_PROTO;
+ return NULL;
+ }
+
+ switch (xisr->sadb_x_ipsecrequest_proto) {
+ case IPPROTO_ESP:
+ proto = "esp";
+ break;
+ case IPPROTO_AH:
+ proto = "ah";
+ break;
+ case IPPROTO_IPCOMP:
+ proto = "ipcomp";
+ break;
+ case IPPROTO_TCP:
+ proto = "tcp";
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_PROTO;
+ return NULL;
+ }
+
+ switch (xisr->sadb_x_ipsecrequest_mode) {
+ case IPSEC_MODE_ANY:
+ mode = "any";
+ break;
+ case IPSEC_MODE_TRANSPORT:
+ mode = "transport";
+ break;
+ case IPSEC_MODE_TUNNEL:
+ mode = "tunnel";
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_MODE;
+ return NULL;
+ }
+
+ abuf[0] = '\0';
+ if (xisr->sadb_x_ipsecrequest_len > sizeof(*xisr)) {
+ struct sockaddr *sa1, *sa2;
+ caddr_t p;
+
+ p = (caddr_t)(xisr + 1);
+ sa1 = (struct sockaddr *)p;
+ sa2 = (struct sockaddr *)(p + sa1->sa_len);
+ if (sizeof(*xisr) + sa1->sa_len + sa2->sa_len !=
+ xisr->sadb_x_ipsecrequest_len) {
+ __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
+ return NULL;
+ }
+ if (set_addresses(abuf, sizeof(abuf), sa1, sa2) != 0) {
+ __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
+ return NULL;
+ }
+ }
+
+ switch (xisr->sadb_x_ipsecrequest_level) {
+ case IPSEC_LEVEL_DEFAULT:
+ level = "default";
+ break;
+ case IPSEC_LEVEL_USE:
+ level = "use";
+ break;
+ case IPSEC_LEVEL_REQUIRE:
+ level = "require";
+ break;
+ case IPSEC_LEVEL_UNIQUE:
+ level = "unique";
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_LEVEL;
+ return NULL;
+ }
+
+ if (xisr->sadb_x_ipsecrequest_reqid == 0)
+ snprintf(buf, len, "%s/%s/%s/%s", proto, mode, abuf, level);
+ else {
+ int ch;
+
+ if (xisr->sadb_x_ipsecrequest_reqid > IPSEC_MANUAL_REQID_MAX)
+ ch = '#';
+ else
+ ch = ':';
+ snprintf(buf, len, "%s/%s/%s/%s%c%u", proto, mode, abuf, level,
+ ch, xisr->sadb_x_ipsecrequest_reqid);
+ }
+
+ return buf;
+}
+
+static int
+set_addresses(buf, len, sa1, sa2)
+ char *buf;
+ size_t len;
+ struct sockaddr *sa1;
+ struct sockaddr *sa2;
+{
+ char tmp1[NI_MAXHOST], tmp2[NI_MAXHOST];
+
+ if (set_address(tmp1, sizeof(tmp1), sa1) == NULL ||
+ set_address(tmp2, sizeof(tmp2), sa2) == NULL)
+ return -1;
+ if (strlen(tmp1) + 1 + strlen(tmp2) + 1 > len)
+ return -1;
+ snprintf(buf, len, "%s-%s", tmp1, tmp2);
+ return 0;
+}
+
+static char *
+set_address(buf, len, sa)
+ char *buf;
+ size_t len;
+ struct sockaddr *sa;
+{
+ const int niflags = NI_NUMERICHOST;
+
+ if (len < 1)
+ return NULL;
+ buf[0] = '\0';
+ if (getnameinfo(sa, sa->sa_len, buf, len, NULL, 0, niflags) != 0)
+ return NULL;
+ return buf;
+}
diff --git a/freebsd/lib/libipsec/ipsec_get_policylen.c b/freebsd/lib/libipsec/ipsec_get_policylen.c
new file mode 100644
index 00000000..d2d47980
--- /dev/null
+++ b/freebsd/lib/libipsec/ipsec_get_policylen.c
@@ -0,0 +1,54 @@
+/* $KAME: ipsec_get_policylen.c,v 1.5 2000/05/07 05:25:03 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#ifdef __rtems__
+#include <freebsd/netipsec/ipsec.h>
+
+#include <freebsd/net/pfkeyv2.h>
+#else
+#include <netipsec/ipsec.h>
+
+#include <net/pfkeyv2.h>
+#endif
+#include "ipsec_strerror.h"
+
+int
+ipsec_get_policylen(policy)
+ caddr_t policy;
+{
+ return policy ? PFKEY_EXTLEN(policy) : -1;
+}
diff --git a/freebsd/lib/libipsec/ipsec_strerror.c b/freebsd/lib/libipsec/ipsec_strerror.c
new file mode 100644
index 00000000..b51893eb
--- /dev/null
+++ b/freebsd/lib/libipsec/ipsec_strerror.c
@@ -0,0 +1,94 @@
+/* $KAME: ipsec_strerror.c,v 1.7 2000/07/30 00:45:12 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <string.h>
+#ifdef __rtems__
+#include <freebsd/netipsec/ipsec.h>
+#else
+#include <netipsec/ipsec.h>
+#endif
+
+#include "ipsec_strerror.h"
+
+int __ipsec_errcode;
+
+static const char *ipsec_errlist[] = {
+"Success", /*EIPSEC_NO_ERROR*/
+"Not supported", /*EIPSEC_NOT_SUPPORTED*/
+"Invalid argument", /*EIPSEC_INVAL_ARGUMENT*/
+"Invalid sadb message", /*EIPSEC_INVAL_SADBMSG*/
+"Invalid version", /*EIPSEC_INVAL_VERSION*/
+"Invalid security policy", /*EIPSEC_INVAL_POLICY*/
+"Invalid address specification", /*EIPSEC_INVAL_ADDRESS*/
+"Invalid ipsec protocol", /*EIPSEC_INVAL_PROTO*/
+"Invalid ipsec mode", /*EIPSEC_INVAL_MODE*/
+"Invalid ipsec level", /*EIPSEC_INVAL_LEVEL*/
+"Invalid SA type", /*EIPSEC_INVAL_SATYPE*/
+"Invalid message type", /*EIPSEC_INVAL_MSGTYPE*/
+"Invalid extension type", /*EIPSEC_INVAL_EXTTYPE*/
+"Invalid algorithm type", /*EIPSEC_INVAL_ALGS*/
+"Invalid key length", /*EIPSEC_INVAL_KEYLEN*/
+"Invalid address family", /*EIPSEC_INVAL_FAMILY*/
+"Invalid prefix length", /*EIPSEC_INVAL_PREFIXLEN*/
+"Invalid direciton", /*EIPSEC_INVAL_DIR*/
+"SPI range violation", /*EIPSEC_INVAL_SPI*/
+"No protocol specified", /*EIPSEC_NO_PROTO*/
+"No algorithm specified", /*EIPSEC_NO_ALGS*/
+"No buffers available", /*EIPSEC_NO_BUFS*/
+"Must get supported algorithms list first", /*EIPSEC_DO_GET_SUPP_LIST*/
+"Protocol mismatch", /*EIPSEC_PROTO_MISMATCH*/
+"Family mismatch", /*EIPSEC_FAMILY_MISMATCH*/
+"Too few arguments", /*EIPSEC_FEW_ARGUMENTS*/
+NULL, /*EIPSEC_SYSTEM_ERROR*/
+"Unknown error", /*EIPSEC_MAX*/
+};
+
+const char *ipsec_strerror(void)
+{
+ if (__ipsec_errcode < 0 || __ipsec_errcode > EIPSEC_MAX)
+ __ipsec_errcode = EIPSEC_MAX;
+
+ return ipsec_errlist[__ipsec_errcode];
+}
+
+void __ipsec_set_strerror(const char *str)
+{
+ __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
+ ipsec_errlist[EIPSEC_SYSTEM_ERROR] = str;
+
+ return;
+}
diff --git a/freebsd/lib/libipsec/ipsec_strerror.h b/freebsd/lib/libipsec/ipsec_strerror.h
new file mode 100644
index 00000000..d9a1f0de
--- /dev/null
+++ b/freebsd/lib/libipsec/ipsec_strerror.h
@@ -0,0 +1,63 @@
+/* $FreeBSD$ */
+/* $KAME: ipsec_strerror.h,v 1.8 2000/07/30 00:45:12 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+extern int __ipsec_errcode;
+extern void __ipsec_set_strerror(const char *);
+
+#define EIPSEC_NO_ERROR 0 /*success*/
+#define EIPSEC_NOT_SUPPORTED 1 /*not supported*/
+#define EIPSEC_INVAL_ARGUMENT 2 /*invalid argument*/
+#define EIPSEC_INVAL_SADBMSG 3 /*invalid sadb message*/
+#define EIPSEC_INVAL_VERSION 4 /*invalid version*/
+#define EIPSEC_INVAL_POLICY 5 /*invalid security policy*/
+#define EIPSEC_INVAL_ADDRESS 6 /*invalid address specification*/
+#define EIPSEC_INVAL_PROTO 7 /*invalid ipsec protocol*/
+#define EIPSEC_INVAL_MODE 8 /*Invalid ipsec mode*/
+#define EIPSEC_INVAL_LEVEL 9 /*invalid ipsec level*/
+#define EIPSEC_INVAL_SATYPE 10 /*invalid SA type*/
+#define EIPSEC_INVAL_MSGTYPE 11 /*invalid message type*/
+#define EIPSEC_INVAL_EXTTYPE 12 /*invalid extension type*/
+#define EIPSEC_INVAL_ALGS 13 /*Invalid algorithm type*/
+#define EIPSEC_INVAL_KEYLEN 14 /*invalid key length*/
+#define EIPSEC_INVAL_FAMILY 15 /*invalid address family*/
+#define EIPSEC_INVAL_PREFIXLEN 16 /*SPI range violation*/
+#define EIPSEC_INVAL_DIR 17 /*Invalid direciton*/
+#define EIPSEC_INVAL_SPI 18 /*invalid prefixlen*/
+#define EIPSEC_NO_PROTO 19 /*no protocol specified*/
+#define EIPSEC_NO_ALGS 20 /*No algorithm specified*/
+#define EIPSEC_NO_BUFS 21 /*no buffers available*/
+#define EIPSEC_DO_GET_SUPP_LIST 22 /*must get supported algorithm first*/
+#define EIPSEC_PROTO_MISMATCH 23 /*protocol mismatch*/
+#define EIPSEC_FAMILY_MISMATCH 24 /*family mismatch*/
+#define EIPSEC_FEW_ARGUMENTS 25 /*Too few arguments*/
+#define EIPSEC_SYSTEM_ERROR 26 /*system error*/
+#define EIPSEC_MAX 27 /*unknown error*/
diff --git a/freebsd/lib/libipsec/libpfkey.h b/freebsd/lib/libipsec/libpfkey.h
new file mode 100644
index 00000000..07ff582e
--- /dev/null
+++ b/freebsd/lib/libipsec/libpfkey.h
@@ -0,0 +1,86 @@
+/* $FreeBSD$ */
+/* $KAME: libpfkey.h,v 1.6 2001/03/05 18:22:17 thorpej Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+struct sadb_msg;
+extern void pfkey_sadump(struct sadb_msg *);
+extern void pfkey_spdump(struct sadb_msg *);
+
+struct sockaddr;
+struct sadb_alg;
+int ipsec_check_keylen(u_int, u_int, u_int);
+int ipsec_check_keylen2(u_int, u_int, u_int);
+int ipsec_get_keylen(u_int, u_int, struct sadb_alg *);
+u_int pfkey_set_softrate(u_int, u_int);
+u_int pfkey_get_softrate(u_int);
+int pfkey_send_getspi(int, u_int, u_int, struct sockaddr *, struct sockaddr *,
+ u_int32_t, u_int32_t, u_int32_t, u_int32_t);
+int pfkey_send_update(int, u_int, u_int, struct sockaddr *, struct sockaddr *,
+ u_int32_t, u_int32_t, u_int, caddr_t, u_int, u_int, u_int, u_int,
+ u_int, u_int32_t, u_int64_t, u_int64_t, u_int64_t, u_int32_t);
+int pfkey_send_add(int, u_int, u_int, struct sockaddr *, struct sockaddr *,
+ u_int32_t, u_int32_t, u_int, caddr_t, u_int, u_int, u_int, u_int,
+ u_int, u_int32_t, u_int64_t, u_int64_t, u_int64_t, u_int32_t);
+int pfkey_send_delete(int, u_int, u_int, struct sockaddr *, struct sockaddr *,
+ u_int32_t);
+int pfkey_send_delete_all(int, u_int, u_int, struct sockaddr *,
+ struct sockaddr *);
+int pfkey_send_get(int, u_int, u_int, struct sockaddr *, struct sockaddr *,
+ u_int32_t);
+int pfkey_send_register(int, u_int);
+int pfkey_recv_register(int);
+int pfkey_set_supported(struct sadb_msg *, int);
+int pfkey_send_flush(int, u_int);
+int pfkey_send_dump(int, u_int);
+int pfkey_send_promisc_toggle(int, int);
+int pfkey_send_spdadd(int, struct sockaddr *, u_int, struct sockaddr *, u_int,
+ u_int, caddr_t, int, u_int32_t);
+int pfkey_send_spdadd2(int, struct sockaddr *, u_int, struct sockaddr *, u_int,
+ u_int, u_int64_t, u_int64_t, caddr_t, int, u_int32_t);
+int pfkey_send_spdupdate(int, struct sockaddr *, u_int, struct sockaddr *,
+ u_int, u_int, caddr_t, int, u_int32_t);
+int pfkey_send_spdupdate2(int, struct sockaddr *, u_int, struct sockaddr *,
+ u_int, u_int, u_int64_t, u_int64_t, caddr_t, int, u_int32_t);
+int pfkey_send_spddelete(int, struct sockaddr *, u_int, struct sockaddr *,
+ u_int, u_int, caddr_t, int, u_int32_t);
+int pfkey_send_spddelete2(int, u_int32_t);
+int pfkey_send_spdget(int, u_int32_t);
+int pfkey_send_spdsetidx(int, struct sockaddr *, u_int, struct sockaddr *,
+ u_int, u_int, caddr_t, int, u_int32_t);
+int pfkey_send_spdflush(int);
+int pfkey_send_spddump(int);
+
+int pfkey_open(void);
+void pfkey_close(int);
+struct sadb_msg *pfkey_recv(int);
+int pfkey_send(int, struct sadb_msg *, int);
+int pfkey_align(struct sadb_msg *, caddr_t *);
+int pfkey_check(caddr_t *);
diff --git a/freebsd/lib/libipsec/pfkey.c b/freebsd/lib/libipsec/pfkey.c
new file mode 100644
index 00000000..0bcea66d
--- /dev/null
+++ b/freebsd/lib/libipsec/pfkey.c
@@ -0,0 +1,2132 @@
+/* $KAME: pfkey.c,v 1.46 2003/08/26 03:37:06 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#ifdef __rtems__
+#include <freebsd/net/pfkeyv2.h>
+#include <freebsd/netipsec/key_var.h>
+#include <freebsd/netinet/in.h>
+#include <freebsd/netipsec/ipsec.h>
+#else
+#include <net/pfkeyv2.h>
+#include <netipsec/key_var.h>
+#include <netinet/in.h>
+#include <netipsec/ipsec.h>
+#endif
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "ipsec_strerror.h"
+#include "libpfkey.h"
+
+#define CALLOC(size, cast) (cast)calloc(1, (size))
+
+static int findsupportedmap(int);
+static int setsupportedmap(struct sadb_supported *);
+static struct sadb_alg *findsupportedalg(u_int, u_int);
+static int pfkey_send_x1(int, u_int, u_int, u_int, struct sockaddr *,
+ struct sockaddr *, u_int32_t, u_int32_t, u_int, caddr_t,
+ u_int, u_int, u_int, u_int, u_int, u_int32_t, u_int32_t,
+ u_int32_t, u_int32_t, u_int32_t);
+static int pfkey_send_x2(int, u_int, u_int, u_int,
+ struct sockaddr *, struct sockaddr *, u_int32_t);
+static int pfkey_send_x3(int, u_int, u_int);
+static int pfkey_send_x4(int, u_int, struct sockaddr *, u_int,
+ struct sockaddr *, u_int, u_int, u_int64_t, u_int64_t,
+ char *, int, u_int32_t);
+static int pfkey_send_x5(int, u_int, u_int32_t);
+
+static caddr_t pfkey_setsadbmsg(caddr_t, caddr_t, u_int, u_int,
+ u_int, u_int32_t, pid_t);
+static caddr_t pfkey_setsadbsa(caddr_t, caddr_t, u_int32_t, u_int,
+ u_int, u_int, u_int32_t);
+static caddr_t pfkey_setsadbaddr(caddr_t, caddr_t, u_int,
+ struct sockaddr *, u_int, u_int);
+static caddr_t pfkey_setsadbkey(caddr_t, caddr_t, u_int, caddr_t, u_int);
+static caddr_t pfkey_setsadblifetime(caddr_t, caddr_t, u_int, u_int32_t,
+ u_int32_t, u_int32_t, u_int32_t);
+static caddr_t pfkey_setsadbxsa2(caddr_t, caddr_t, u_int32_t, u_int32_t);
+
+/*
+ * make and search supported algorithm structure.
+ */
+static struct sadb_supported *ipsec_supported[] = { NULL, NULL, NULL, NULL };
+
+static int supported_map[] = {
+ SADB_SATYPE_AH,
+ SADB_SATYPE_ESP,
+ SADB_X_SATYPE_IPCOMP,
+ SADB_X_SATYPE_TCPSIGNATURE
+};
+
+static int
+findsupportedmap(satype)
+ int satype;
+{
+ int i;
+
+ for (i = 0; i < sizeof(supported_map)/sizeof(supported_map[0]); i++)
+ if (supported_map[i] == satype)
+ return i;
+ return -1;
+}
+
+static struct sadb_alg *
+findsupportedalg(satype, alg_id)
+ u_int satype, alg_id;
+{
+ int algno;
+ int tlen;
+ caddr_t p;
+
+ /* validity check */
+ algno = findsupportedmap(satype);
+ if (algno == -1) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return NULL;
+ }
+ if (ipsec_supported[algno] == NULL) {
+ __ipsec_errcode = EIPSEC_DO_GET_SUPP_LIST;
+ return NULL;
+ }
+
+ tlen = ipsec_supported[algno]->sadb_supported_len
+ - sizeof(struct sadb_supported);
+ p = (caddr_t)(ipsec_supported[algno] + 1);
+ while (tlen > 0) {
+ if (tlen < sizeof(struct sadb_alg)) {
+ /* invalid format */
+ break;
+ }
+ if (((struct sadb_alg *)p)->sadb_alg_id == alg_id)
+ return (struct sadb_alg *)p;
+
+ tlen -= sizeof(struct sadb_alg);
+ p += sizeof(struct sadb_alg);
+ }
+
+ __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
+ return NULL;
+}
+
+static int
+setsupportedmap(sup)
+ struct sadb_supported *sup;
+{
+ struct sadb_supported **ipsup;
+
+ switch (sup->sadb_supported_exttype) {
+ case SADB_EXT_SUPPORTED_AUTH:
+ ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_AH)];
+ break;
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ ipsup = &ipsec_supported[findsupportedmap(SADB_SATYPE_ESP)];
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+
+ if (*ipsup)
+ free(*ipsup);
+
+ *ipsup = malloc(sup->sadb_supported_len);
+ if (!*ipsup) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ memcpy(*ipsup, sup, sup->sadb_supported_len);
+
+ return 0;
+}
+
+/*
+ * check key length against algorithm specified.
+ * This function is called with SADB_EXT_SUPPORTED_{AUTH,ENCRYPT} as the
+ * augument, and only calls to ipsec_check_keylen2();
+ * keylen is the unit of bit.
+ * OUT:
+ * -1: invalid.
+ * 0: valid.
+ */
+int
+ipsec_check_keylen(supported, alg_id, keylen)
+ u_int supported;
+ u_int alg_id;
+ u_int keylen;
+{
+ int satype;
+
+ /* validity check */
+ switch (supported) {
+ case SADB_EXT_SUPPORTED_AUTH:
+ satype = SADB_SATYPE_AH;
+ break;
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ satype = SADB_SATYPE_ESP;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ return ipsec_check_keylen2(satype, alg_id, keylen);
+}
+
+/*
+ * check key length against algorithm specified.
+ * satype is one of satype defined at pfkeyv2.h.
+ * keylen is the unit of bit.
+ * OUT:
+ * -1: invalid.
+ * 0: valid.
+ */
+int
+ipsec_check_keylen2(satype, alg_id, keylen)
+ u_int satype;
+ u_int alg_id;
+ u_int keylen;
+{
+ struct sadb_alg *alg;
+
+ alg = findsupportedalg(satype, alg_id);
+ if (!alg)
+ return -1;
+
+ if (keylen < alg->sadb_alg_minbits || keylen > alg->sadb_alg_maxbits) {
+ __ipsec_errcode = EIPSEC_INVAL_KEYLEN;
+ return -1;
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+/*
+ * get max/min key length against algorithm specified.
+ * satype is one of satype defined at pfkeyv2.h.
+ * keylen is the unit of bit.
+ * OUT:
+ * -1: invalid.
+ * 0: valid.
+ */
+int
+ipsec_get_keylen(supported, alg_id, alg0)
+ u_int supported, alg_id;
+ struct sadb_alg *alg0;
+{
+ struct sadb_alg *alg;
+ u_int satype;
+
+ /* validity check */
+ if (!alg0) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ switch (supported) {
+ case SADB_EXT_SUPPORTED_AUTH:
+ satype = SADB_SATYPE_AH;
+ break;
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ satype = SADB_SATYPE_ESP;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ alg = findsupportedalg(satype, alg_id);
+ if (!alg)
+ return -1;
+
+ memcpy(alg0, alg, sizeof(*alg0));
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+/*
+ * set the rate for SOFT lifetime against HARD one.
+ * If rate is more than 100 or equal to zero, then set to 100.
+ */
+static u_int soft_lifetime_allocations_rate = PFKEY_SOFT_LIFETIME_RATE;
+static u_int soft_lifetime_bytes_rate = PFKEY_SOFT_LIFETIME_RATE;
+static u_int soft_lifetime_addtime_rate = PFKEY_SOFT_LIFETIME_RATE;
+static u_int soft_lifetime_usetime_rate = PFKEY_SOFT_LIFETIME_RATE;
+
+u_int
+pfkey_set_softrate(type, rate)
+ u_int type, rate;
+{
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+
+ if (rate > 100 || rate == 0)
+ rate = 100;
+
+ switch (type) {
+ case SADB_X_LIFETIME_ALLOCATIONS:
+ soft_lifetime_allocations_rate = rate;
+ return 0;
+ case SADB_X_LIFETIME_BYTES:
+ soft_lifetime_bytes_rate = rate;
+ return 0;
+ case SADB_X_LIFETIME_ADDTIME:
+ soft_lifetime_addtime_rate = rate;
+ return 0;
+ case SADB_X_LIFETIME_USETIME:
+ soft_lifetime_usetime_rate = rate;
+ return 0;
+ }
+
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return 1;
+}
+
+/*
+ * get current rate for SOFT lifetime against HARD one.
+ * ATTENTION: ~0 is returned if invalid type was passed.
+ */
+u_int
+pfkey_get_softrate(type)
+ u_int type;
+{
+ switch (type) {
+ case SADB_X_LIFETIME_ALLOCATIONS:
+ return soft_lifetime_allocations_rate;
+ case SADB_X_LIFETIME_BYTES:
+ return soft_lifetime_bytes_rate;
+ case SADB_X_LIFETIME_ADDTIME:
+ return soft_lifetime_addtime_rate;
+ case SADB_X_LIFETIME_USETIME:
+ return soft_lifetime_usetime_rate;
+ }
+
+ return ~0;
+}
+
+/*
+ * sending SADB_GETSPI message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_getspi(so, satype, mode, src, dst, min, max, reqid, seq)
+ int so;
+ u_int satype, mode;
+ struct sockaddr *src, *dst;
+ u_int32_t min, max, reqid, seq;
+{
+ struct sadb_msg *newmsg;
+ caddr_t ep;
+ int len;
+ int need_spirange = 0;
+ caddr_t p;
+ int plen;
+
+ /* validity check */
+ if (src == NULL || dst == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+ if (src->sa_family != dst->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+ if (min > max || (min > 0 && min <= 255)) {
+ __ipsec_errcode = EIPSEC_INVAL_SPI;
+ return -1;
+ }
+ switch (src->sa_family) {
+ case AF_INET:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+ case AF_INET6:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_FAMILY;
+ return -1;
+ }
+
+ /* create new sadb_msg to send. */
+ len = sizeof(struct sadb_msg)
+ + sizeof(struct sadb_x_sa2)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(src->sa_len)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(dst->sa_len);
+
+ if (min > 255 && max < ~0) {
+ need_spirange++;
+ len += sizeof(struct sadb_spirange);
+ }
+
+ if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ ep = ((caddr_t)newmsg) + len;
+
+ p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_GETSPI,
+ len, satype, seq, getpid());
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ p = pfkey_setsadbxsa2(p, ep, mode, reqid);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* set sadb_address for source */
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* set sadb_address for destination */
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* proccessing spi range */
+ if (need_spirange) {
+ struct sadb_spirange spirange;
+
+ if (p + sizeof(spirange) > ep) {
+ free(newmsg);
+ return -1;
+ }
+
+ memset(&spirange, 0, sizeof(spirange));
+ spirange.sadb_spirange_len = PFKEY_UNIT64(sizeof(spirange));
+ spirange.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
+ spirange.sadb_spirange_min = min;
+ spirange.sadb_spirange_max = max;
+
+ memcpy(p, &spirange, sizeof(spirange));
+
+ p += sizeof(spirange);
+ }
+ if (p != ep) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* send message */
+ len = pfkey_send(so, newmsg, len);
+ free(newmsg);
+
+ if (len < 0)
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/*
+ * sending SADB_UPDATE message to the kernel.
+ * The length of key material is a_keylen + e_keylen.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_update(so, satype, mode, src, dst, spi, reqid, wsize,
+ keymat, e_type, e_keylen, a_type, a_keylen, flags,
+ l_alloc, l_bytes, l_addtime, l_usetime, seq)
+ int so;
+ u_int satype, mode, wsize;
+ struct sockaddr *src, *dst;
+ u_int32_t spi, reqid;
+ caddr_t keymat;
+ u_int e_type, e_keylen, a_type, a_keylen, flags;
+ u_int32_t l_alloc;
+ u_int64_t l_bytes, l_addtime, l_usetime;
+ u_int32_t seq;
+{
+ int len;
+ if ((len = pfkey_send_x1(so, SADB_UPDATE, satype, mode, src, dst, spi,
+ reqid, wsize,
+ keymat, e_type, e_keylen, a_type, a_keylen, flags,
+ l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_ADD message to the kernel.
+ * The length of key material is a_keylen + e_keylen.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_add(so, satype, mode, src, dst, spi, reqid, wsize,
+ keymat, e_type, e_keylen, a_type, a_keylen, flags,
+ l_alloc, l_bytes, l_addtime, l_usetime, seq)
+ int so;
+ u_int satype, mode, wsize;
+ struct sockaddr *src, *dst;
+ u_int32_t spi, reqid;
+ caddr_t keymat;
+ u_int e_type, e_keylen, a_type, a_keylen, flags;
+ u_int32_t l_alloc;
+ u_int64_t l_bytes, l_addtime, l_usetime;
+ u_int32_t seq;
+{
+ int len;
+ if ((len = pfkey_send_x1(so, SADB_ADD, satype, mode, src, dst, spi,
+ reqid, wsize,
+ keymat, e_type, e_keylen, a_type, a_keylen, flags,
+ l_alloc, l_bytes, l_addtime, l_usetime, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_DELETE message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_delete(so, satype, mode, src, dst, spi)
+ int so;
+ u_int satype, mode;
+ struct sockaddr *src, *dst;
+ u_int32_t spi;
+{
+ int len;
+ if ((len = pfkey_send_x2(so, SADB_DELETE, satype, mode, src, dst, spi)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_DELETE without spi to the kernel. This is
+ * the "delete all" request (an extension also present in
+ * Solaris).
+ *
+ * OUT:
+ * positive: success and return length sent
+ * -1 : error occured, and set errno
+ */
+int
+pfkey_send_delete_all(so, satype, mode, src, dst)
+ int so;
+ u_int satype, mode;
+ struct sockaddr *src, *dst;
+{
+ struct sadb_msg *newmsg;
+ int len;
+ caddr_t p;
+ int plen;
+ caddr_t ep;
+
+ /* validity check */
+ if (src == NULL || dst == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+ if (src->sa_family != dst->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+ switch (src->sa_family) {
+ case AF_INET:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+ case AF_INET6:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_FAMILY;
+ return -1;
+ }
+
+ /* create new sadb_msg to reply. */
+ len = sizeof(struct sadb_msg)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(src->sa_len)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(dst->sa_len);
+
+ if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ ep = ((caddr_t)newmsg) + len;
+
+ p = pfkey_setsadbmsg((caddr_t)newmsg, ep, SADB_DELETE, len, satype, 0,
+ getpid());
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p || p != ep) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* send message */
+ len = pfkey_send(so, newmsg, len);
+ free(newmsg);
+
+ if (len < 0)
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/*
+ * sending SADB_GET message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_get(so, satype, mode, src, dst, spi)
+ int so;
+ u_int satype, mode;
+ struct sockaddr *src, *dst;
+ u_int32_t spi;
+{
+ int len;
+ if ((len = pfkey_send_x2(so, SADB_GET, satype, mode, src, dst, spi)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_REGISTER message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_register(so, satype)
+ int so;
+ u_int satype;
+{
+ int len, algno;
+
+ if (satype == PF_UNSPEC) {
+ for (algno = 0;
+ algno < sizeof(supported_map)/sizeof(supported_map[0]);
+ algno++) {
+ if (ipsec_supported[algno]) {
+ free(ipsec_supported[algno]);
+ ipsec_supported[algno] = NULL;
+ }
+ }
+ } else {
+ algno = findsupportedmap(satype);
+ if (algno == -1) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ if (ipsec_supported[algno]) {
+ free(ipsec_supported[algno]);
+ ipsec_supported[algno] = NULL;
+ }
+ }
+
+ if ((len = pfkey_send_x3(so, SADB_REGISTER, satype)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * receiving SADB_REGISTER message from the kernel, and copy buffer for
+ * sadb_supported returned into ipsec_supported.
+ * OUT:
+ * 0: success and return length sent.
+ * -1: error occured, and set errno.
+ */
+int
+pfkey_recv_register(so)
+ int so;
+{
+ pid_t pid = getpid();
+ struct sadb_msg *newmsg;
+ int error = -1;
+
+ /* receive message */
+ for (;;) {
+ if ((newmsg = pfkey_recv(so)) == NULL)
+ return -1;
+ if (newmsg->sadb_msg_type == SADB_REGISTER &&
+ newmsg->sadb_msg_pid == pid)
+ break;
+ free(newmsg);
+ }
+
+ /* check and fix */
+ newmsg->sadb_msg_len = PFKEY_UNUNIT64(newmsg->sadb_msg_len);
+
+ error = pfkey_set_supported(newmsg, newmsg->sadb_msg_len);
+ free(newmsg);
+
+ if (error == 0)
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+
+ return error;
+}
+
+/*
+ * receiving SADB_REGISTER message from the kernel, and copy buffer for
+ * sadb_supported returned into ipsec_supported.
+ * NOTE: sadb_msg_len must be host order.
+ * IN:
+ * tlen: msg length, it's to makeing sure.
+ * OUT:
+ * 0: success and return length sent.
+ * -1: error occured, and set errno.
+ */
+int
+pfkey_set_supported(msg, tlen)
+ struct sadb_msg *msg;
+ int tlen;
+{
+ struct sadb_supported *sup;
+ caddr_t p;
+ caddr_t ep;
+
+ /* validity */
+ if (msg->sadb_msg_len != tlen) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ p = (caddr_t)msg;
+ ep = p + tlen;
+
+ p += sizeof(struct sadb_msg);
+
+ while (p < ep) {
+ sup = (struct sadb_supported *)p;
+ if (ep < p + sizeof(*sup) ||
+ PFKEY_EXTLEN(sup) < sizeof(*sup) ||
+ ep < p + sup->sadb_supported_len) {
+ /* invalid format */
+ break;
+ }
+
+ switch (sup->sadb_supported_exttype) {
+ case SADB_EXT_SUPPORTED_AUTH:
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+
+ /* fixed length */
+ sup->sadb_supported_len = PFKEY_EXTLEN(sup);
+
+ /* set supported map */
+ if (setsupportedmap(sup) != 0)
+ return -1;
+
+ p += sup->sadb_supported_len;
+ }
+
+ if (p != ep) {
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+
+ return 0;
+}
+
+/*
+ * sending SADB_FLUSH message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_flush(so, satype)
+ int so;
+ u_int satype;
+{
+ int len;
+
+ if ((len = pfkey_send_x3(so, SADB_FLUSH, satype)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_DUMP message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_dump(so, satype)
+ int so;
+ u_int satype;
+{
+ int len;
+
+ if ((len = pfkey_send_x3(so, SADB_DUMP, satype)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_PROMISC message to the kernel.
+ * NOTE that this function handles promisc mode toggle only.
+ * IN:
+ * flag: set promisc off if zero, set promisc on if non-zero.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ * 0 : error occured, and set errno.
+ * others: a pointer to new allocated buffer in which supported
+ * algorithms is.
+ */
+int
+pfkey_send_promisc_toggle(so, flag)
+ int so;
+ int flag;
+{
+ int len;
+
+ if ((len = pfkey_send_x3(so, SADB_X_PROMISC, (flag ? 1 : 0))) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDADD message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spdadd(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+ int so;
+ struct sockaddr *src, *dst;
+ u_int prefs, prefd, proto;
+ caddr_t policy;
+ int policylen;
+ u_int32_t seq;
+{
+ int len;
+
+ if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
+ src, prefs, dst, prefd, proto,
+ 0, 0,
+ policy, policylen, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDADD message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spdadd2(so, src, prefs, dst, prefd, proto, ltime, vtime,
+ policy, policylen, seq)
+ int so;
+ struct sockaddr *src, *dst;
+ u_int prefs, prefd, proto;
+ u_int64_t ltime, vtime;
+ caddr_t policy;
+ int policylen;
+ u_int32_t seq;
+{
+ int len;
+
+ if ((len = pfkey_send_x4(so, SADB_X_SPDADD,
+ src, prefs, dst, prefd, proto,
+ ltime, vtime,
+ policy, policylen, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDUPDATE message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spdupdate(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+ int so;
+ struct sockaddr *src, *dst;
+ u_int prefs, prefd, proto;
+ caddr_t policy;
+ int policylen;
+ u_int32_t seq;
+{
+ int len;
+
+ if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
+ src, prefs, dst, prefd, proto,
+ 0, 0,
+ policy, policylen, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDUPDATE message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spdupdate2(so, src, prefs, dst, prefd, proto, ltime, vtime,
+ policy, policylen, seq)
+ int so;
+ struct sockaddr *src, *dst;
+ u_int prefs, prefd, proto;
+ u_int64_t ltime, vtime;
+ caddr_t policy;
+ int policylen;
+ u_int32_t seq;
+{
+ int len;
+
+ if ((len = pfkey_send_x4(so, SADB_X_SPDUPDATE,
+ src, prefs, dst, prefd, proto,
+ ltime, vtime,
+ policy, policylen, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDDELETE message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spddelete(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+ int so;
+ struct sockaddr *src, *dst;
+ u_int prefs, prefd, proto;
+ caddr_t policy;
+ int policylen;
+ u_int32_t seq;
+{
+ int len;
+
+ if (policylen != sizeof(struct sadb_x_policy)) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ if ((len = pfkey_send_x4(so, SADB_X_SPDDELETE,
+ src, prefs, dst, prefd, proto,
+ 0, 0,
+ policy, policylen, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDDELETE message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spddelete2(so, spid)
+ int so;
+ u_int32_t spid;
+{
+ int len;
+
+ if ((len = pfkey_send_x5(so, SADB_X_SPDDELETE2, spid)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDGET message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spdget(so, spid)
+ int so;
+ u_int32_t spid;
+{
+ int len;
+
+ if ((len = pfkey_send_x5(so, SADB_X_SPDGET, spid)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_X_SPDSETIDX message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spdsetidx(so, src, prefs, dst, prefd, proto, policy, policylen, seq)
+ int so;
+ struct sockaddr *src, *dst;
+ u_int prefs, prefd, proto;
+ caddr_t policy;
+ int policylen;
+ u_int32_t seq;
+{
+ int len;
+
+ if (policylen != sizeof(struct sadb_x_policy)) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ if ((len = pfkey_send_x4(so, SADB_X_SPDSETIDX,
+ src, prefs, dst, prefd, proto,
+ 0, 0,
+ policy, policylen, seq)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_SPDFLUSH message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spdflush(so)
+ int so;
+{
+ int len;
+
+ if ((len = pfkey_send_x3(so, SADB_X_SPDFLUSH, SADB_SATYPE_UNSPEC)) < 0)
+ return -1;
+
+ return len;
+}
+
+/*
+ * sending SADB_SPDDUMP message to the kernel.
+ * OUT:
+ * positive: success and return length sent.
+ * -1 : error occured, and set errno.
+ */
+int
+pfkey_send_spddump(so)
+ int so;
+{
+ int len;
+
+ if ((len = pfkey_send_x3(so, SADB_X_SPDDUMP, SADB_SATYPE_UNSPEC)) < 0)
+ return -1;
+
+ return len;
+}
+
+/* sending SADB_ADD or SADB_UPDATE message to the kernel */
+static int
+pfkey_send_x1(so, type, satype, mode, src, dst, spi, reqid, wsize,
+ keymat, e_type, e_keylen, a_type, a_keylen, flags,
+ l_alloc, l_bytes, l_addtime, l_usetime, seq)
+ int so;
+ u_int type, satype, mode;
+ struct sockaddr *src, *dst;
+ u_int32_t spi, reqid;
+ u_int wsize;
+ caddr_t keymat;
+ u_int e_type, e_keylen, a_type, a_keylen, flags;
+ u_int32_t l_alloc, l_bytes, l_addtime, l_usetime, seq;
+{
+ struct sadb_msg *newmsg;
+ int len;
+ caddr_t p;
+ int plen;
+ caddr_t ep;
+
+ /* validity check */
+ if (src == NULL || dst == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+ if (src->sa_family != dst->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+ switch (src->sa_family) {
+ case AF_INET:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+ case AF_INET6:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_FAMILY;
+ return -1;
+ }
+
+ switch (satype) {
+ case SADB_SATYPE_ESP:
+ if (e_type == SADB_EALG_NONE) {
+ __ipsec_errcode = EIPSEC_NO_ALGS;
+ return -1;
+ }
+ break;
+ case SADB_SATYPE_AH:
+ if (e_type != SADB_EALG_NONE) {
+ __ipsec_errcode = EIPSEC_INVAL_ALGS;
+ return -1;
+ }
+ if (a_type == SADB_AALG_NONE) {
+ __ipsec_errcode = EIPSEC_NO_ALGS;
+ return -1;
+ }
+ break;
+ case SADB_X_SATYPE_IPCOMP:
+ if (e_type == SADB_X_CALG_NONE) {
+ __ipsec_errcode = EIPSEC_INVAL_ALGS;
+ return -1;
+ }
+ if (a_type != SADB_AALG_NONE) {
+ __ipsec_errcode = EIPSEC_NO_ALGS;
+ return -1;
+ }
+ break;
+ case SADB_X_SATYPE_TCPSIGNATURE:
+ if (e_type != SADB_EALG_NONE) {
+ __ipsec_errcode = EIPSEC_INVAL_ALGS;
+ return -1;
+ }
+ if (a_type != SADB_X_AALG_TCP_MD5) {
+ __ipsec_errcode = EIPSEC_INVAL_ALGS;
+ return -1;
+ }
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+
+ /* create new sadb_msg to reply. */
+ len = sizeof(struct sadb_msg)
+ + sizeof(struct sadb_sa)
+ + sizeof(struct sadb_x_sa2)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(src->sa_len)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(dst->sa_len)
+ + sizeof(struct sadb_lifetime)
+ + sizeof(struct sadb_lifetime);
+
+ if (e_type != SADB_EALG_NONE)
+ len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(e_keylen));
+ if (a_type != SADB_AALG_NONE)
+ len += (sizeof(struct sadb_key) + PFKEY_ALIGN8(a_keylen));
+
+ if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ ep = ((caddr_t)newmsg) + len;
+
+ p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
+ satype, seq, getpid());
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbsa(p, ep, spi, wsize, a_type, e_type, flags);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbxsa2(p, ep, mode, reqid);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ if (e_type != SADB_EALG_NONE) {
+ p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_ENCRYPT,
+ keymat, e_keylen);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ }
+ if (a_type != SADB_AALG_NONE) {
+ p = pfkey_setsadbkey(p, ep, SADB_EXT_KEY_AUTH,
+ keymat + e_keylen, a_keylen);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ }
+
+ /* set sadb_lifetime for destination */
+ p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
+ l_alloc, l_bytes, l_addtime, l_usetime);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_SOFT,
+ l_alloc, l_bytes, l_addtime, l_usetime);
+ if (!p || p != ep) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* send message */
+ len = pfkey_send(so, newmsg, len);
+ free(newmsg);
+
+ if (len < 0)
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/* sending SADB_DELETE or SADB_GET message to the kernel */
+static int
+pfkey_send_x2(so, type, satype, mode, src, dst, spi)
+ int so;
+ u_int type, satype, mode;
+ struct sockaddr *src, *dst;
+ u_int32_t spi;
+{
+ struct sadb_msg *newmsg;
+ int len;
+ caddr_t p;
+ int plen;
+ caddr_t ep;
+
+ /* validity check */
+ if (src == NULL || dst == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+ if (src->sa_family != dst->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+ switch (src->sa_family) {
+ case AF_INET:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+ case AF_INET6:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_FAMILY;
+ return -1;
+ }
+
+ /* create new sadb_msg to reply. */
+ len = sizeof(struct sadb_msg)
+ + sizeof(struct sadb_sa)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(src->sa_len)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(dst->sa_len);
+
+ if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ ep = ((caddr_t)newmsg) + len;
+
+ p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
+ getpid());
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbsa(p, ep, spi, 0, 0, 0, 0);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, plen,
+ IPSEC_ULPROTO_ANY);
+ if (!p || p != ep) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* send message */
+ len = pfkey_send(so, newmsg, len);
+ free(newmsg);
+
+ if (len < 0)
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/*
+ * sending SADB_REGISTER, SADB_FLUSH, SADB_DUMP or SADB_X_PROMISC message
+ * to the kernel
+ */
+static int
+pfkey_send_x3(so, type, satype)
+ int so;
+ u_int type, satype;
+{
+ struct sadb_msg *newmsg;
+ int len;
+ caddr_t p;
+ caddr_t ep;
+
+ /* validity check */
+ switch (type) {
+ case SADB_X_PROMISC:
+ if (satype != 0 && satype != 1) {
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+ break;
+ default:
+ switch (satype) {
+ case SADB_SATYPE_UNSPEC:
+ case SADB_SATYPE_AH:
+ case SADB_SATYPE_ESP:
+ case SADB_X_SATYPE_IPCOMP:
+ case SADB_X_SATYPE_TCPSIGNATURE:
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+ }
+
+ /* create new sadb_msg to send. */
+ len = sizeof(struct sadb_msg);
+
+ if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ ep = ((caddr_t)newmsg) + len;
+
+ p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len, satype, 0,
+ getpid());
+ if (!p || p != ep) {
+ free(newmsg);
+ return -1;
+ }
+
+ /* send message */
+ len = pfkey_send(so, newmsg, len);
+ free(newmsg);
+
+ if (len < 0)
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/* sending SADB_X_SPDADD message to the kernel */
+static int
+pfkey_send_x4(so, type, src, prefs, dst, prefd, proto,
+ ltime, vtime, policy, policylen, seq)
+ int so;
+ struct sockaddr *src, *dst;
+ u_int type, prefs, prefd, proto;
+ u_int64_t ltime, vtime;
+ char *policy;
+ int policylen;
+ u_int32_t seq;
+{
+ struct sadb_msg *newmsg;
+ int len;
+ caddr_t p;
+ int plen;
+ caddr_t ep;
+
+ /* validity check */
+ if (src == NULL || dst == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+ if (src->sa_family != dst->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+
+ switch (src->sa_family) {
+ case AF_INET:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+ case AF_INET6:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_FAMILY;
+ return -1;
+ }
+ if (prefs > plen || prefd > plen) {
+ __ipsec_errcode = EIPSEC_INVAL_PREFIXLEN;
+ return -1;
+ }
+
+ /* create new sadb_msg to reply. */
+ len = sizeof(struct sadb_msg)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(src->sa_len)
+ + sizeof(struct sadb_address)
+ + PFKEY_ALIGN8(src->sa_len)
+ + sizeof(struct sadb_lifetime)
+ + policylen;
+
+ if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ ep = ((caddr_t)newmsg) + len;
+
+ p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
+ SADB_SATYPE_UNSPEC, seq, getpid());
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_SRC, src, prefs, proto);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadbaddr(p, ep, SADB_EXT_ADDRESS_DST, dst, prefd, proto);
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+ p = pfkey_setsadblifetime(p, ep, SADB_EXT_LIFETIME_HARD,
+ 0, 0, ltime, vtime);
+ if (!p || p + policylen != ep) {
+ free(newmsg);
+ return -1;
+ }
+ memcpy(p, policy, policylen);
+
+ /* send message */
+ len = pfkey_send(so, newmsg, len);
+ free(newmsg);
+
+ if (len < 0)
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/* sending SADB_X_SPDGET or SADB_X_SPDDELETE message to the kernel */
+static int
+pfkey_send_x5(so, type, spid)
+ int so;
+ u_int type;
+ u_int32_t spid;
+{
+ struct sadb_msg *newmsg;
+ struct sadb_x_policy xpl;
+ int len;
+ caddr_t p;
+ caddr_t ep;
+
+ /* create new sadb_msg to reply. */
+ len = sizeof(struct sadb_msg)
+ + sizeof(xpl);
+
+ if ((newmsg = CALLOC(len, struct sadb_msg *)) == NULL) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+ ep = ((caddr_t)newmsg) + len;
+
+ p = pfkey_setsadbmsg((caddr_t)newmsg, ep, type, len,
+ SADB_SATYPE_UNSPEC, 0, getpid());
+ if (!p) {
+ free(newmsg);
+ return -1;
+ }
+
+ if (p + sizeof(xpl) != ep) {
+ free(newmsg);
+ return -1;
+ }
+ memset(&xpl, 0, sizeof(xpl));
+ xpl.sadb_x_policy_len = PFKEY_UNIT64(sizeof(xpl));
+ xpl.sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ xpl.sadb_x_policy_id = spid;
+ memcpy(p, &xpl, sizeof(xpl));
+
+ /* send message */
+ len = pfkey_send(so, newmsg, len);
+ free(newmsg);
+
+ if (len < 0)
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/*
+ * open a socket.
+ * OUT:
+ * -1: fail.
+ * others : success and return value of socket.
+ */
+int
+pfkey_open()
+{
+ int so;
+ const int bufsiz = 128 * 1024; /*is 128K enough?*/
+
+ if ((so = socket(PF_KEY, SOCK_RAW, PF_KEY_V2)) < 0) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+
+ /*
+ * This is a temporary workaround for KAME PR 154.
+ * Don't really care even if it fails.
+ */
+ (void)setsockopt(so, SOL_SOCKET, SO_SNDBUF, &bufsiz, sizeof(bufsiz));
+ (void)setsockopt(so, SOL_SOCKET, SO_RCVBUF, &bufsiz, sizeof(bufsiz));
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return so;
+}
+
+/*
+ * close a socket.
+ * OUT:
+ * 0: success.
+ * -1: fail.
+ */
+void
+pfkey_close(so)
+ int so;
+{
+ (void)close(so);
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return;
+}
+
+/*
+ * receive sadb_msg data, and return pointer to new buffer allocated.
+ * Must free this buffer later.
+ * OUT:
+ * NULL : error occured.
+ * others : a pointer to sadb_msg structure.
+ *
+ * XXX should be rewritten to pass length explicitly
+ */
+struct sadb_msg *
+pfkey_recv(so)
+ int so;
+{
+ struct sadb_msg buf, *newmsg;
+ int len, reallen;
+
+ while ((len = recv(so, (caddr_t)&buf, sizeof(buf), MSG_PEEK)) < 0) {
+ if (errno == EINTR)
+ continue;
+ __ipsec_set_strerror(strerror(errno));
+ return NULL;
+ }
+
+ if (len < sizeof(buf)) {
+ recv(so, (caddr_t)&buf, sizeof(buf), 0);
+ __ipsec_errcode = EIPSEC_MAX;
+ return NULL;
+ }
+
+ /* read real message */
+ reallen = PFKEY_UNUNIT64(buf.sadb_msg_len);
+ if ((newmsg = CALLOC(reallen, struct sadb_msg *)) == 0) {
+ __ipsec_set_strerror(strerror(errno));
+ return NULL;
+ }
+
+ while ((len = recv(so, (caddr_t)newmsg, reallen, 0)) < 0) {
+ if (errno == EINTR)
+ continue;
+ __ipsec_set_strerror(strerror(errno));
+ free(newmsg);
+ return NULL;
+ }
+
+ if (len != reallen) {
+ __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
+ free(newmsg);
+ return NULL;
+ }
+
+ /* don't trust what the kernel says, validate! */
+ if (PFKEY_UNUNIT64(newmsg->sadb_msg_len) != len) {
+ __ipsec_errcode = EIPSEC_SYSTEM_ERROR;
+ free(newmsg);
+ return NULL;
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return newmsg;
+}
+
+/*
+ * send message to a socket.
+ * OUT:
+ * others: success and return length sent.
+ * -1 : fail.
+ */
+int
+pfkey_send(so, msg, len)
+ int so;
+ struct sadb_msg *msg;
+ int len;
+{
+ if ((len = send(so, (caddr_t)msg, len, 0)) < 0) {
+ __ipsec_set_strerror(strerror(errno));
+ return -1;
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return len;
+}
+
+/*
+ * %%% Utilities
+ * NOTE: These functions are derived from netkey/key.c in KAME.
+ */
+/*
+ * set the pointer to each header in this message buffer.
+ * IN: msg: pointer to message buffer.
+ * mhp: pointer to the buffer initialized like below:
+ * caddr_t mhp[SADB_EXT_MAX + 1];
+ * OUT: -1: invalid.
+ * 0: valid.
+ *
+ * XXX should be rewritten to obtain length explicitly
+ */
+int
+pfkey_align(msg, mhp)
+ struct sadb_msg *msg;
+ caddr_t *mhp;
+{
+ struct sadb_ext *ext;
+ int i;
+ caddr_t p;
+ caddr_t ep; /* XXX should be passed from upper layer */
+
+ /* validity check */
+ if (msg == NULL || mhp == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ /* initialize */
+ for (i = 0; i < SADB_EXT_MAX + 1; i++)
+ mhp[i] = NULL;
+
+ mhp[0] = (caddr_t)msg;
+
+ /* initialize */
+ p = (caddr_t) msg;
+ ep = p + PFKEY_UNUNIT64(msg->sadb_msg_len);
+
+ /* skip base header */
+ p += sizeof(struct sadb_msg);
+
+ while (p < ep) {
+ ext = (struct sadb_ext *)p;
+ if (ep < p + sizeof(*ext) || PFKEY_EXTLEN(ext) < sizeof(*ext) ||
+ ep < p + PFKEY_EXTLEN(ext)) {
+ /* invalid format */
+ break;
+ }
+
+ /* duplicate check */
+ /* XXX Are there duplication either KEY_AUTH or KEY_ENCRYPT ?*/
+ if (mhp[ext->sadb_ext_type] != NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
+ return -1;
+ }
+
+ /* set pointer */
+ switch (ext->sadb_ext_type) {
+ case SADB_EXT_SA:
+ case SADB_EXT_LIFETIME_CURRENT:
+ case SADB_EXT_LIFETIME_HARD:
+ case SADB_EXT_LIFETIME_SOFT:
+ case SADB_EXT_ADDRESS_SRC:
+ case SADB_EXT_ADDRESS_DST:
+ case SADB_EXT_ADDRESS_PROXY:
+ case SADB_EXT_KEY_AUTH:
+ /* XXX should to be check weak keys. */
+ case SADB_EXT_KEY_ENCRYPT:
+ /* XXX should to be check weak keys. */
+ case SADB_EXT_IDENTITY_SRC:
+ case SADB_EXT_IDENTITY_DST:
+ case SADB_EXT_SENSITIVITY:
+ case SADB_EXT_PROPOSAL:
+ case SADB_EXT_SUPPORTED_AUTH:
+ case SADB_EXT_SUPPORTED_ENCRYPT:
+ case SADB_EXT_SPIRANGE:
+ case SADB_X_EXT_POLICY:
+ case SADB_X_EXT_SA2:
+ mhp[ext->sadb_ext_type] = (caddr_t)ext;
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_EXTTYPE;
+ return -1;
+ }
+
+ p += PFKEY_EXTLEN(ext);
+ }
+
+ if (p != ep) {
+ __ipsec_errcode = EIPSEC_INVAL_SADBMSG;
+ return -1;
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+/*
+ * check basic usage for sadb_msg,
+ * NOTE: This routine is derived from netkey/key.c in KAME.
+ * IN: msg: pointer to message buffer.
+ * mhp: pointer to the buffer initialized like below:
+ *
+ * caddr_t mhp[SADB_EXT_MAX + 1];
+ *
+ * OUT: -1: invalid.
+ * 0: valid.
+ */
+int
+pfkey_check(mhp)
+ caddr_t *mhp;
+{
+ struct sadb_msg *msg;
+
+ /* validity check */
+ if (mhp == NULL || mhp[0] == NULL) {
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return -1;
+ }
+
+ msg = (struct sadb_msg *)mhp[0];
+
+ /* check version */
+ if (msg->sadb_msg_version != PF_KEY_V2) {
+ __ipsec_errcode = EIPSEC_INVAL_VERSION;
+ return -1;
+ }
+
+ /* check type */
+ if (msg->sadb_msg_type > SADB_MAX) {
+ __ipsec_errcode = EIPSEC_INVAL_MSGTYPE;
+ return -1;
+ }
+
+ /* check SA type */
+ switch (msg->sadb_msg_satype) {
+ case SADB_SATYPE_UNSPEC:
+ switch (msg->sadb_msg_type) {
+ case SADB_GETSPI:
+ case SADB_UPDATE:
+ case SADB_ADD:
+ case SADB_DELETE:
+ case SADB_GET:
+ case SADB_ACQUIRE:
+ case SADB_EXPIRE:
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+ break;
+ case SADB_SATYPE_ESP:
+ case SADB_SATYPE_AH:
+ case SADB_X_SATYPE_IPCOMP:
+ case SADB_X_SATYPE_TCPSIGNATURE:
+ switch (msg->sadb_msg_type) {
+ case SADB_X_SPDADD:
+ case SADB_X_SPDDELETE:
+ case SADB_X_SPDGET:
+ case SADB_X_SPDDUMP:
+ case SADB_X_SPDFLUSH:
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+ break;
+ case SADB_SATYPE_RSVP:
+ case SADB_SATYPE_OSPFV2:
+ case SADB_SATYPE_RIPV2:
+ case SADB_SATYPE_MIP:
+ __ipsec_errcode = EIPSEC_NOT_SUPPORTED;
+ return -1;
+ case 1: /* XXX: What does it do ? */
+ if (msg->sadb_msg_type == SADB_X_PROMISC)
+ break;
+ /*FALLTHROUGH*/
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_SATYPE;
+ return -1;
+ }
+
+ /* check field of upper layer protocol and address family */
+ if (mhp[SADB_EXT_ADDRESS_SRC] != NULL
+ && mhp[SADB_EXT_ADDRESS_DST] != NULL) {
+ struct sadb_address *src0, *dst0;
+
+ src0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_SRC]);
+ dst0 = (struct sadb_address *)(mhp[SADB_EXT_ADDRESS_DST]);
+
+ if (src0->sadb_address_proto != dst0->sadb_address_proto) {
+ __ipsec_errcode = EIPSEC_PROTO_MISMATCH;
+ return -1;
+ }
+
+ if (PFKEY_ADDR_SADDR(src0)->sa_family
+ != PFKEY_ADDR_SADDR(dst0)->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+
+ switch (PFKEY_ADDR_SADDR(src0)->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
+ __ipsec_errcode = EIPSEC_INVAL_FAMILY;
+ return -1;
+ }
+
+ /*
+ * prefixlen == 0 is valid because there must be the case
+ * all addresses are matched.
+ */
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+/*
+ * set data into sadb_msg.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbmsg(buf, lim, type, tlen, satype, seq, pid)
+ caddr_t buf;
+ caddr_t lim;
+ u_int type, satype;
+ u_int tlen;
+ u_int32_t seq;
+ pid_t pid;
+{
+ struct sadb_msg *p;
+ u_int len;
+
+ p = (struct sadb_msg *)buf;
+ len = sizeof(struct sadb_msg);
+
+ if (buf + len > lim)
+ return NULL;
+
+ memset(p, 0, len);
+ p->sadb_msg_version = PF_KEY_V2;
+ p->sadb_msg_type = type;
+ p->sadb_msg_errno = 0;
+ p->sadb_msg_satype = satype;
+ p->sadb_msg_len = PFKEY_UNIT64(tlen);
+ p->sadb_msg_reserved = 0;
+ p->sadb_msg_seq = seq;
+ p->sadb_msg_pid = (u_int32_t)pid;
+
+ return(buf + len);
+}
+
+/*
+ * copy secasvar data into sadb_address.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbsa(buf, lim, spi, wsize, auth, enc, flags)
+ caddr_t buf;
+ caddr_t lim;
+ u_int32_t spi, flags;
+ u_int wsize, auth, enc;
+{
+ struct sadb_sa *p;
+ u_int len;
+
+ p = (struct sadb_sa *)buf;
+ len = sizeof(struct sadb_sa);
+
+ if (buf + len > lim)
+ return NULL;
+
+ memset(p, 0, len);
+ p->sadb_sa_len = PFKEY_UNIT64(len);
+ p->sadb_sa_exttype = SADB_EXT_SA;
+ p->sadb_sa_spi = spi;
+ p->sadb_sa_replay = wsize;
+ p->sadb_sa_state = SADB_SASTATE_LARVAL;
+ p->sadb_sa_auth = auth;
+ p->sadb_sa_encrypt = enc;
+ p->sadb_sa_flags = flags;
+
+ return(buf + len);
+}
+
+/*
+ * set data into sadb_address.
+ * `buf' must has been allocated sufficiently.
+ * prefixlen is in bits.
+ */
+static caddr_t
+pfkey_setsadbaddr(buf, lim, exttype, saddr, prefixlen, ul_proto)
+ caddr_t buf;
+ caddr_t lim;
+ u_int exttype;
+ struct sockaddr *saddr;
+ u_int prefixlen;
+ u_int ul_proto;
+{
+ struct sadb_address *p;
+ u_int len;
+
+ p = (struct sadb_address *)buf;
+ len = sizeof(struct sadb_address) + PFKEY_ALIGN8(saddr->sa_len);
+
+ if (buf + len > lim)
+ return NULL;
+
+ memset(p, 0, len);
+ p->sadb_address_len = PFKEY_UNIT64(len);
+ p->sadb_address_exttype = exttype & 0xffff;
+ p->sadb_address_proto = ul_proto & 0xff;
+ p->sadb_address_prefixlen = prefixlen;
+ p->sadb_address_reserved = 0;
+
+ memcpy(p + 1, saddr, saddr->sa_len);
+
+ return(buf + len);
+}
+
+/*
+ * set sadb_key structure after clearing buffer with zero.
+ * OUT: the pointer of buf + len.
+ */
+static caddr_t
+pfkey_setsadbkey(buf, lim, type, key, keylen)
+ caddr_t buf;
+ caddr_t lim;
+ caddr_t key;
+ u_int type, keylen;
+{
+ struct sadb_key *p;
+ u_int len;
+
+ p = (struct sadb_key *)buf;
+ len = sizeof(struct sadb_key) + PFKEY_ALIGN8(keylen);
+
+ if (buf + len > lim)
+ return NULL;
+
+ memset(p, 0, len);
+ p->sadb_key_len = PFKEY_UNIT64(len);
+ p->sadb_key_exttype = type;
+ p->sadb_key_bits = keylen << 3;
+ p->sadb_key_reserved = 0;
+
+ memcpy(p + 1, key, keylen);
+
+ return buf + len;
+}
+
+/*
+ * set sadb_lifetime structure after clearing buffer with zero.
+ * OUT: the pointer of buf + len.
+ */
+static caddr_t
+pfkey_setsadblifetime(buf, lim, type, l_alloc, l_bytes, l_addtime, l_usetime)
+ caddr_t buf;
+ caddr_t lim;
+ u_int type;
+ u_int32_t l_alloc, l_bytes, l_addtime, l_usetime;
+{
+ struct sadb_lifetime *p;
+ u_int len;
+
+ p = (struct sadb_lifetime *)buf;
+ len = sizeof(struct sadb_lifetime);
+
+ if (buf + len > lim)
+ return NULL;
+
+ memset(p, 0, len);
+ p->sadb_lifetime_len = PFKEY_UNIT64(len);
+ p->sadb_lifetime_exttype = type;
+
+ switch (type) {
+ case SADB_EXT_LIFETIME_SOFT:
+ p->sadb_lifetime_allocations
+ = (l_alloc * soft_lifetime_allocations_rate) /100;
+ p->sadb_lifetime_bytes
+ = (l_bytes * soft_lifetime_bytes_rate) /100;
+ p->sadb_lifetime_addtime
+ = (l_addtime * soft_lifetime_addtime_rate) /100;
+ p->sadb_lifetime_usetime
+ = (l_usetime * soft_lifetime_usetime_rate) /100;
+ break;
+ case SADB_EXT_LIFETIME_HARD:
+ p->sadb_lifetime_allocations = l_alloc;
+ p->sadb_lifetime_bytes = l_bytes;
+ p->sadb_lifetime_addtime = l_addtime;
+ p->sadb_lifetime_usetime = l_usetime;
+ break;
+ }
+
+ return buf + len;
+}
+
+/*
+ * copy secasvar data into sadb_address.
+ * `buf' must has been allocated sufficiently.
+ */
+static caddr_t
+pfkey_setsadbxsa2(buf, lim, mode0, reqid)
+ caddr_t buf;
+ caddr_t lim;
+ u_int32_t mode0;
+ u_int32_t reqid;
+{
+ struct sadb_x_sa2 *p;
+ u_int8_t mode = mode0 & 0xff;
+ u_int len;
+
+ p = (struct sadb_x_sa2 *)buf;
+ len = sizeof(struct sadb_x_sa2);
+
+ if (buf + len > lim)
+ return NULL;
+
+ memset(p, 0, len);
+ p->sadb_x_sa2_len = PFKEY_UNIT64(len);
+ p->sadb_x_sa2_exttype = SADB_X_EXT_SA2;
+ p->sadb_x_sa2_mode = mode;
+ p->sadb_x_sa2_reqid = reqid;
+
+ return(buf + len);
+}
diff --git a/freebsd/lib/libipsec/pfkey_dump.c b/freebsd/lib/libipsec/pfkey_dump.c
new file mode 100644
index 00000000..5d83d224
--- /dev/null
+++ b/freebsd/lib/libipsec/pfkey_dump.c
@@ -0,0 +1,646 @@
+/* $KAME: pfkey_dump.c,v 1.45 2003/09/08 10:14:56 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#ifdef __rtems__
+#include <freebsd/netipsec/ipsec.h>
+#include <freebsd/net/pfkeyv2.h>
+#include <freebsd/netipsec/key_var.h>
+#include <freebsd/netipsec/key_debug.h>
+
+#include <freebsd/netinet/in.h>
+#else
+#include <netipsec/ipsec.h>
+#include <net/pfkeyv2.h>
+#include <netipsec/key_var.h>
+#include <netipsec/key_debug.h>
+
+#include <netinet/in.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <netdb.h>
+
+#include "ipsec_strerror.h"
+#include "libpfkey.h"
+
+/* cope with old kame headers - ugly */
+#ifndef SADB_X_AALG_MD5
+#define SADB_X_AALG_MD5 SADB_AALG_MD5
+#endif
+#ifndef SADB_X_AALG_SHA
+#define SADB_X_AALG_SHA SADB_AALG_SHA
+#endif
+#ifndef SADB_X_AALG_NULL
+#define SADB_X_AALG_NULL SADB_AALG_NULL
+#endif
+
+#ifndef SADB_X_EALG_BLOWFISHCBC
+#define SADB_X_EALG_BLOWFISHCBC SADB_EALG_BLOWFISHCBC
+#endif
+#ifndef SADB_X_EALG_CAST128CBC
+#define SADB_X_EALG_CAST128CBC SADB_EALG_CAST128CBC
+#endif
+#ifndef SADB_X_EALG_RC5CBC
+#ifdef SADB_EALG_RC5CBC
+#define SADB_X_EALG_RC5CBC SADB_EALG_RC5CBC
+#endif
+#endif
+
+#define GETMSGSTR(str, num) \
+do { \
+ if (sizeof((str)[0]) == 0 \
+ || num >= sizeof(str)/sizeof((str)[0])) \
+ printf("%u ", (num)); \
+ else if (strlen((str)[(num)]) == 0) \
+ printf("%u ", (num)); \
+ else \
+ printf("%s ", (str)[(num)]); \
+} while (0)
+
+#define GETMSGV2S(v2s, num) \
+do { \
+ struct val2str *p; \
+ for (p = (v2s); p && p->str; p++) { \
+ if (p->val == (num)) \
+ break; \
+ } \
+ if (p && p->str) \
+ printf("%s ", p->str); \
+ else \
+ printf("%u ", (num)); \
+} while (0)
+
+static char *str_ipaddr(struct sockaddr *);
+static char *str_prefport(u_int, u_int, u_int, u_int);
+static void str_upperspec(u_int, u_int, u_int);
+static char *str_time(time_t);
+static void str_lifetime_byte(struct sadb_lifetime *, char *);
+
+struct val2str {
+ int val;
+ const char *str;
+};
+
+/*
+ * Must to be re-written about following strings.
+ */
+static char *str_satype[] = {
+ "unspec",
+ "unknown",
+ "ah",
+ "esp",
+ "unknown",
+ "rsvp",
+ "ospfv2",
+ "ripv2",
+ "mip",
+ "ipcomp",
+ "policy",
+ "tcp"
+};
+
+static char *str_mode[] = {
+ "any",
+ "transport",
+ "tunnel",
+};
+
+static char *str_state[] = {
+ "larval",
+ "mature",
+ "dying",
+ "dead",
+};
+
+static struct val2str str_alg_auth[] = {
+ { SADB_AALG_NONE, "none", },
+ { SADB_AALG_MD5HMAC, "hmac-md5", },
+ { SADB_AALG_SHA1HMAC, "hmac-sha1", },
+ { SADB_X_AALG_MD5, "md5", },
+ { SADB_X_AALG_SHA, "sha", },
+ { SADB_X_AALG_NULL, "null", },
+ { SADB_X_AALG_TCP_MD5, "tcp-md5", },
+#ifdef SADB_X_AALG_SHA2_256
+ { SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
+#endif
+#ifdef SADB_X_AALG_SHA2_384
+ { SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
+#endif
+#ifdef SADB_X_AALG_SHA2_512
+ { SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
+#endif
+#ifdef SADB_X_AALG_RIPEMD160HMAC
+ { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", },
+#endif
+#ifdef SADB_X_AALG_AES_XCBC_MAC
+ { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
+#endif
+ { -1, NULL, },
+};
+
+static struct val2str str_alg_enc[] = {
+ { SADB_EALG_NONE, "none", },
+ { SADB_EALG_DESCBC, "des-cbc", },
+ { SADB_EALG_3DESCBC, "3des-cbc", },
+ { SADB_EALG_NULL, "null", },
+#ifdef SADB_X_EALG_RC5CBC
+ { SADB_X_EALG_RC5CBC, "rc5-cbc", },
+#endif
+ { SADB_X_EALG_CAST128CBC, "cast128-cbc", },
+ { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", },
+#ifdef SADB_X_EALG_RIJNDAELCBC
+ { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", },
+#endif
+#ifdef SADB_X_EALG_TWOFISHCBC
+ { SADB_X_EALG_TWOFISHCBC, "twofish-cbc", },
+#endif
+#ifdef SADB_X_EALG_AESCTR
+ { SADB_X_EALG_AESCTR, "aes-ctr", },
+#endif
+#ifdef SADB_X_EALG_CAMELLIACBC
+ { SADB_X_EALG_CAMELLIACBC, "camellia-cbc", },
+#endif
+ { -1, NULL, },
+};
+
+static struct val2str str_alg_comp[] = {
+ { SADB_X_CALG_NONE, "none", },
+ { SADB_X_CALG_OUI, "oui", },
+ { SADB_X_CALG_DEFLATE, "deflate", },
+ { SADB_X_CALG_LZS, "lzs", },
+ { -1, NULL, },
+};
+
+/*
+ * dump SADB_MSG formated. For debugging, you should use kdebug_sadb().
+ */
+void
+pfkey_sadump(m)
+ struct sadb_msg *m;
+{
+ caddr_t mhp[SADB_EXT_MAX + 1];
+ struct sadb_sa *m_sa;
+ struct sadb_x_sa2 *m_sa2;
+ struct sadb_lifetime *m_lftc, *m_lfth, *m_lfts;
+ struct sadb_address *m_saddr, *m_daddr, *m_paddr;
+ struct sadb_key *m_auth, *m_enc;
+ struct sadb_ident *m_sid, *m_did;
+ struct sadb_sens *m_sens;
+
+ /* check pfkey message. */
+ if (pfkey_align(m, mhp)) {
+ printf("%s\n", ipsec_strerror());
+ return;
+ }
+ if (pfkey_check(mhp)) {
+ printf("%s\n", ipsec_strerror());
+ return;
+ }
+
+ m_sa = (struct sadb_sa *)mhp[SADB_EXT_SA];
+ m_sa2 = (struct sadb_x_sa2 *)mhp[SADB_X_EXT_SA2];
+ m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
+ m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
+ m_lfts = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_SOFT];
+ m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+ m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+ m_paddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_PROXY];
+ m_auth = (struct sadb_key *)mhp[SADB_EXT_KEY_AUTH];
+ m_enc = (struct sadb_key *)mhp[SADB_EXT_KEY_ENCRYPT];
+ m_sid = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_SRC];
+ m_did = (struct sadb_ident *)mhp[SADB_EXT_IDENTITY_DST];
+ m_sens = (struct sadb_sens *)mhp[SADB_EXT_SENSITIVITY];
+
+ /* source address */
+ if (m_saddr == NULL) {
+ printf("no ADDRESS_SRC extension.\n");
+ return;
+ }
+ printf("%s ", str_ipaddr((struct sockaddr *)(m_saddr + 1)));
+
+ /* destination address */
+ if (m_daddr == NULL) {
+ printf("no ADDRESS_DST extension.\n");
+ return;
+ }
+ printf("%s ", str_ipaddr((struct sockaddr *)(m_daddr + 1)));
+
+ /* SA type */
+ if (m_sa == NULL) {
+ printf("no SA extension.\n");
+ return;
+ }
+ if (m_sa2 == NULL) {
+ printf("no SA2 extension.\n");
+ return;
+ }
+ printf("\n\t");
+
+ GETMSGSTR(str_satype, m->sadb_msg_satype);
+
+ printf("mode=");
+ GETMSGSTR(str_mode, m_sa2->sadb_x_sa2_mode);
+
+ printf("spi=%u(0x%08x) reqid=%u(0x%08x)\n",
+ (u_int32_t)ntohl(m_sa->sadb_sa_spi),
+ (u_int32_t)ntohl(m_sa->sadb_sa_spi),
+ (u_int32_t)m_sa2->sadb_x_sa2_reqid,
+ (u_int32_t)m_sa2->sadb_x_sa2_reqid);
+
+ /* encryption key */
+ if (m->sadb_msg_satype == SADB_X_SATYPE_IPCOMP) {
+ printf("\tC: ");
+ GETMSGV2S(str_alg_comp, m_sa->sadb_sa_encrypt);
+ } else if (m->sadb_msg_satype == SADB_SATYPE_ESP) {
+ if (m_enc != NULL) {
+ printf("\tE: ");
+ GETMSGV2S(str_alg_enc, m_sa->sadb_sa_encrypt);
+ ipsec_hexdump((caddr_t)m_enc + sizeof(*m_enc),
+ m_enc->sadb_key_bits / 8);
+ printf("\n");
+ }
+ }
+
+ /* authentication key */
+ if (m_auth != NULL) {
+ printf("\tA: ");
+ GETMSGV2S(str_alg_auth, m_sa->sadb_sa_auth);
+ ipsec_hexdump((caddr_t)m_auth + sizeof(*m_auth),
+ m_auth->sadb_key_bits / 8);
+ printf("\n");
+ }
+
+ /* replay windoe size & flags */
+ printf("\tseq=0x%08x replay=%u flags=0x%08x ",
+ m_sa2->sadb_x_sa2_sequence,
+ m_sa->sadb_sa_replay,
+ m_sa->sadb_sa_flags);
+
+ /* state */
+ printf("state=");
+ GETMSGSTR(str_state, m_sa->sadb_sa_state);
+ printf("\n");
+
+ /* lifetime */
+ if (m_lftc != NULL) {
+ time_t tmp_time = time(0);
+
+ printf("\tcreated: %s",
+ str_time(m_lftc->sadb_lifetime_addtime));
+ printf("\tcurrent: %s\n", str_time(tmp_time));
+ printf("\tdiff: %lu(s)",
+ (u_long)(m_lftc->sadb_lifetime_addtime == 0 ?
+ 0 : (tmp_time - m_lftc->sadb_lifetime_addtime)));
+
+ printf("\thard: %lu(s)",
+ (u_long)(m_lfth == NULL ?
+ 0 : m_lfth->sadb_lifetime_addtime));
+ printf("\tsoft: %lu(s)\n",
+ (u_long)(m_lfts == NULL ?
+ 0 : m_lfts->sadb_lifetime_addtime));
+
+ printf("\tlast: %s",
+ str_time(m_lftc->sadb_lifetime_usetime));
+ printf("\thard: %lu(s)",
+ (u_long)(m_lfth == NULL ?
+ 0 : m_lfth->sadb_lifetime_usetime));
+ printf("\tsoft: %lu(s)\n",
+ (u_long)(m_lfts == NULL ?
+ 0 : m_lfts->sadb_lifetime_usetime));
+
+ str_lifetime_byte(m_lftc, "current");
+ str_lifetime_byte(m_lfth, "hard");
+ str_lifetime_byte(m_lfts, "soft");
+ printf("\n");
+
+ printf("\tallocated: %lu",
+ (unsigned long)m_lftc->sadb_lifetime_allocations);
+ printf("\thard: %lu",
+ (u_long)(m_lfth == NULL ?
+ 0 : m_lfth->sadb_lifetime_allocations));
+ printf("\tsoft: %lu\n",
+ (u_long)(m_lfts == NULL ?
+ 0 : m_lfts->sadb_lifetime_allocations));
+ }
+
+ printf("\tsadb_seq=%lu pid=%lu ",
+ (u_long)m->sadb_msg_seq,
+ (u_long)m->sadb_msg_pid);
+
+ /* XXX DEBUG */
+ printf("refcnt=%u\n", m->sadb_msg_reserved);
+
+ return;
+}
+
+void
+pfkey_spdump(m)
+ struct sadb_msg *m;
+{
+ char pbuf[NI_MAXSERV];
+ caddr_t mhp[SADB_EXT_MAX + 1];
+ struct sadb_address *m_saddr, *m_daddr;
+ struct sadb_x_policy *m_xpl;
+ struct sadb_lifetime *m_lftc = NULL, *m_lfth = NULL;
+ struct sockaddr *sa;
+ u_int16_t sport = 0, dport = 0;
+
+ /* check pfkey message. */
+ if (pfkey_align(m, mhp)) {
+ printf("%s\n", ipsec_strerror());
+ return;
+ }
+ if (pfkey_check(mhp)) {
+ printf("%s\n", ipsec_strerror());
+ return;
+ }
+
+ m_saddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_SRC];
+ m_daddr = (struct sadb_address *)mhp[SADB_EXT_ADDRESS_DST];
+ m_xpl = (struct sadb_x_policy *)mhp[SADB_X_EXT_POLICY];
+ m_lftc = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_CURRENT];
+ m_lfth = (struct sadb_lifetime *)mhp[SADB_EXT_LIFETIME_HARD];
+
+ if (m_saddr && m_daddr) {
+ /* source address */
+ sa = (struct sockaddr *)(m_saddr + 1);
+ switch (sa->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ if (getnameinfo(sa, sa->sa_len, NULL, 0,
+ pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
+ sport = 0; /*XXX*/
+ else
+ sport = atoi(pbuf);
+ printf("%s%s ", str_ipaddr(sa),
+ str_prefport(sa->sa_family,
+ m_saddr->sadb_address_prefixlen, sport,
+ m_saddr->sadb_address_proto));
+ break;
+ default:
+ printf("unknown-af ");
+ break;
+ }
+
+ /* destination address */
+ sa = (struct sockaddr *)(m_daddr + 1);
+ switch (sa->sa_family) {
+ case AF_INET:
+ case AF_INET6:
+ if (getnameinfo(sa, sa->sa_len, NULL, 0,
+ pbuf, sizeof(pbuf), NI_NUMERICSERV) != 0)
+ dport = 0; /*XXX*/
+ else
+ dport = atoi(pbuf);
+ printf("%s%s ", str_ipaddr(sa),
+ str_prefport(sa->sa_family,
+ m_daddr->sadb_address_prefixlen, dport,
+ m_saddr->sadb_address_proto));
+ break;
+ default:
+ printf("unknown-af ");
+ break;
+ }
+
+ /* upper layer protocol */
+ if (m_saddr->sadb_address_proto !=
+ m_daddr->sadb_address_proto) {
+ printf("upper layer protocol mismatched.\n");
+ return;
+ }
+ str_upperspec(m_saddr->sadb_address_proto, sport, dport);
+ }
+ else
+ printf("(no selector, probably per-socket policy) ");
+
+ /* policy */
+ {
+ char *d_xpl;
+
+ if (m_xpl == NULL) {
+ printf("no X_POLICY extension.\n");
+ return;
+ }
+ d_xpl = ipsec_dump_policy((char *)m_xpl, "\n\t");
+
+ /* dump SPD */
+ printf("\n\t%s\n", d_xpl);
+ free(d_xpl);
+ }
+
+ /* lifetime */
+ if (m_lftc) {
+ printf("\tcreated: %s ",
+ str_time(m_lftc->sadb_lifetime_addtime));
+ printf("lastused: %s\n",
+ str_time(m_lftc->sadb_lifetime_usetime));
+ }
+ if (m_lfth) {
+ printf("\tlifetime: %lu(s) ",
+ (u_long)m_lfth->sadb_lifetime_addtime);
+ printf("validtime: %lu(s)\n",
+ (u_long)m_lfth->sadb_lifetime_usetime);
+ }
+
+
+ printf("\tspid=%ld seq=%ld pid=%ld\n",
+ (u_long)m_xpl->sadb_x_policy_id,
+ (u_long)m->sadb_msg_seq,
+ (u_long)m->sadb_msg_pid);
+
+ /* XXX TEST */
+ printf("\trefcnt=%u\n", m->sadb_msg_reserved);
+
+ return;
+}
+
+/*
+ * set "ipaddress" to buffer.
+ */
+static char *
+str_ipaddr(sa)
+ struct sockaddr *sa;
+{
+ static char buf[NI_MAXHOST];
+ const int niflag = NI_NUMERICHOST;
+
+ if (sa == NULL)
+ return "";
+
+ if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, niflag) == 0)
+ return buf;
+ return NULL;
+}
+
+/*
+ * set "/prefix[port number]" to buffer.
+ */
+static char *
+str_prefport(family, pref, port, ulp)
+ u_int family, pref, port, ulp;
+{
+ static char buf[128];
+ char prefbuf[128];
+ char portbuf[128];
+ int plen;
+
+ switch (family) {
+ case AF_INET:
+ plen = sizeof(struct in_addr) << 3;
+ break;
+ case AF_INET6:
+ plen = sizeof(struct in6_addr) << 3;
+ break;
+ default:
+ return "?";
+ }
+
+ if (pref == plen)
+ prefbuf[0] = '\0';
+ else
+ snprintf(prefbuf, sizeof(prefbuf), "/%u", pref);
+
+ if (ulp == IPPROTO_ICMPV6)
+ memset(portbuf, 0, sizeof(portbuf));
+ else {
+ if (port == IPSEC_PORT_ANY)
+ snprintf(portbuf, sizeof(portbuf), "[%s]", "any");
+ else
+ snprintf(portbuf, sizeof(portbuf), "[%u]", port);
+ }
+
+ snprintf(buf, sizeof(buf), "%s%s", prefbuf, portbuf);
+
+ return buf;
+}
+
+static void
+str_upperspec(ulp, p1, p2)
+ u_int ulp, p1, p2;
+{
+ if (ulp == IPSEC_ULPROTO_ANY)
+ printf("any");
+ else if (ulp == IPPROTO_ICMPV6) {
+ printf("icmp6");
+ if (!(p1 == IPSEC_PORT_ANY && p2 == IPSEC_PORT_ANY))
+ printf(" %u,%u", p1, p2);
+ } else {
+ struct protoent *ent;
+
+ switch (ulp) {
+ case IPPROTO_IPV4:
+ printf("ip4");
+ break;
+ default:
+ ent = getprotobynumber(ulp);
+ if (ent)
+ printf("%s", ent->p_name);
+ else
+ printf("%u", ulp);
+
+ endprotoent();
+ break;
+ }
+ }
+}
+
+/*
+ * set "Mon Day Time Year" to buffer
+ */
+static char *
+str_time(t)
+ time_t t;
+{
+ static char buf[128];
+
+ if (t == 0) {
+ int i = 0;
+ for (;i < 20;) buf[i++] = ' ';
+ } else {
+ char *t0;
+ t0 = ctime(&t);
+ memcpy(buf, t0 + 4, 20);
+ }
+
+ buf[20] = '\0';
+
+ return(buf);
+}
+
+static void
+str_lifetime_byte(x, str)
+ struct sadb_lifetime *x;
+ char *str;
+{
+ double y;
+ char *unit;
+ int w;
+
+ if (x == NULL) {
+ printf("\t%s: 0(bytes)", str);
+ return;
+ }
+
+#if 0
+ if ((x->sadb_lifetime_bytes) / 1024 / 1024) {
+ y = (x->sadb_lifetime_bytes) * 1.0 / 1024 / 1024;
+ unit = "M";
+ w = 1;
+ } else if ((x->sadb_lifetime_bytes) / 1024) {
+ y = (x->sadb_lifetime_bytes) * 1.0 / 1024;
+ unit = "K";
+ w = 1;
+ } else {
+ y = (x->sadb_lifetime_bytes) * 1.0;
+ unit = "";
+ w = 0;
+ }
+#else
+ y = (x->sadb_lifetime_bytes) * 1.0;
+ unit = "";
+ w = 0;
+#endif
+ printf("\t%s: %.*f(%sbytes)", str, w, y, unit);
+}
diff --git a/freebsd/lib/libipsec/policy_parse.y b/freebsd/lib/libipsec/policy_parse.y
new file mode 100644
index 00000000..9e290f41
--- /dev/null
+++ b/freebsd/lib/libipsec/policy_parse.y
@@ -0,0 +1,443 @@
+/* $KAME: policy_parse.y,v 1.14 2003/06/27 03:39:20 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * IN/OUT bound policy configuration take place such below:
+ * in <policy>
+ * out <policy>
+ *
+ * <policy> is one of following:
+ * "discard", "none", "ipsec <requests>", "entrust", "bypass",
+ *
+ * The following requests are accepted as <requests>:
+ *
+ * protocol/mode/src-dst/level
+ * protocol/mode/src-dst parsed as protocol/mode/src-dst/default
+ * protocol/mode/src-dst/ parsed as protocol/mode/src-dst/default
+ * protocol/transport parsed as protocol/mode/any-any/default
+ * protocol/transport//level parsed as protocol/mode/any-any/level
+ *
+ * You can concatenate these requests with either ' '(single space) or '\n'.
+ */
+
+%{
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/netipsec/ipsec.h>
+#else
+#include <netipsec/ipsec.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+
+#include "ipsec_strerror.h"
+
+#define ATOX(c) \
+ (isdigit(c) ? (c - '0') : (isupper(c) ? (c - 'A' + 10) : (c - 'a' + 10) ))
+
+static caddr_t pbuf = NULL; /* sadb_x_policy buffer */
+static int tlen = 0; /* total length of pbuf */
+static int offset = 0; /* offset of pbuf */
+static int p_dir, p_type, p_protocol, p_mode, p_level, p_reqid;
+static struct sockaddr *p_src = NULL;
+static struct sockaddr *p_dst = NULL;
+
+struct _val;
+extern void yyerror(char *msg);
+static struct sockaddr *parse_sockaddr(struct _val *buf);
+static int rule_check(void);
+static int init_x_policy(void);
+static int set_x_request(struct sockaddr *src, struct sockaddr *dst);
+static int set_sockaddr(struct sockaddr *addr);
+static void policy_parse_request_init(void);
+static caddr_t policy_parse(char *msg, int msglen);
+
+extern void __policy__strbuffer__init__(char *msg);
+extern void __policy__strbuffer__free__(void);
+extern int yyparse(void);
+extern int yylex(void);
+
+extern char *__libipsecyytext; /*XXX*/
+
+%}
+
+%union {
+ u_int num;
+ struct _val {
+ int len;
+ char *buf;
+ } val;
+}
+
+%token DIR ACTION PROTOCOL MODE LEVEL LEVEL_SPECIFY
+%token IPADDRESS
+%token ME ANY
+%token SLASH HYPHEN
+%type <num> DIR ACTION PROTOCOL MODE LEVEL
+%type <val> IPADDRESS LEVEL_SPECIFY
+
+%%
+policy_spec
+ : DIR ACTION
+ {
+ p_dir = $1;
+ p_type = $2;
+
+ if (init_x_policy())
+ return -1;
+ }
+ rules
+ | DIR
+ {
+ p_dir = $1;
+ p_type = 0; /* ignored it by kernel */
+
+ if (init_x_policy())
+ return -1;
+ }
+ ;
+
+rules
+ : /*NOTHING*/
+ | rules rule {
+ if (rule_check() < 0)
+ return -1;
+
+ if (set_x_request(p_src, p_dst) < 0)
+ return -1;
+
+ policy_parse_request_init();
+ }
+ ;
+
+rule
+ : protocol SLASH mode SLASH addresses SLASH level
+ | protocol SLASH mode SLASH addresses SLASH
+ | protocol SLASH mode SLASH addresses
+ | protocol SLASH mode SLASH
+ | protocol SLASH mode SLASH SLASH level
+ | protocol SLASH mode
+ | protocol SLASH {
+ __ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
+ return -1;
+ }
+ | protocol {
+ __ipsec_errcode = EIPSEC_FEW_ARGUMENTS;
+ return -1;
+ }
+ ;
+
+protocol
+ : PROTOCOL { p_protocol = $1; }
+ ;
+
+mode
+ : MODE { p_mode = $1; }
+ ;
+
+level
+ : LEVEL {
+ p_level = $1;
+ p_reqid = 0;
+ }
+ | LEVEL_SPECIFY {
+ p_level = IPSEC_LEVEL_UNIQUE;
+ p_reqid = atol($1.buf); /* atol() is good. */
+ }
+ ;
+
+addresses
+ : IPADDRESS {
+ p_src = parse_sockaddr(&$1);
+ if (p_src == NULL)
+ return -1;
+ }
+ HYPHEN
+ IPADDRESS {
+ p_dst = parse_sockaddr(&$4);
+ if (p_dst == NULL)
+ return -1;
+ }
+ | ME HYPHEN ANY {
+ if (p_dir != IPSEC_DIR_OUTBOUND) {
+ __ipsec_errcode = EIPSEC_INVAL_DIR;
+ return -1;
+ }
+ }
+ | ANY HYPHEN ME {
+ if (p_dir != IPSEC_DIR_INBOUND) {
+ __ipsec_errcode = EIPSEC_INVAL_DIR;
+ return -1;
+ }
+ }
+ /*
+ | ME HYPHEN ME
+ */
+ ;
+
+%%
+
+void
+yyerror(msg)
+ char *msg;
+{
+ fprintf(stderr, "libipsec: %s while parsing \"%s\"\n",
+ msg, __libipsecyytext);
+
+ return;
+}
+
+static struct sockaddr *
+parse_sockaddr(buf)
+ struct _val *buf;
+{
+ struct addrinfo hints, *res;
+ char *serv = NULL;
+ int error;
+ struct sockaddr *newaddr = NULL;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(buf->buf, serv, &hints, &res);
+ if (error != 0) {
+ yyerror("invalid IP address");
+ __ipsec_set_strerror(gai_strerror(error));
+ return NULL;
+ }
+
+ if (res->ai_addr == NULL) {
+ yyerror("invalid IP address");
+ __ipsec_set_strerror(gai_strerror(error));
+ return NULL;
+ }
+
+ newaddr = malloc(res->ai_addr->sa_len);
+ if (newaddr == NULL) {
+ __ipsec_errcode = EIPSEC_NO_BUFS;
+ freeaddrinfo(res);
+ return NULL;
+ }
+ memcpy(newaddr, res->ai_addr, res->ai_addr->sa_len);
+
+ freeaddrinfo(res);
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return newaddr;
+}
+
+static int
+rule_check()
+{
+ if (p_type == IPSEC_POLICY_IPSEC) {
+ if (p_protocol == IPPROTO_IP) {
+ __ipsec_errcode = EIPSEC_NO_PROTO;
+ return -1;
+ }
+
+ if (p_mode != IPSEC_MODE_TRANSPORT
+ && p_mode != IPSEC_MODE_TUNNEL) {
+ __ipsec_errcode = EIPSEC_INVAL_MODE;
+ return -1;
+ }
+
+ if (p_src == NULL && p_dst == NULL) {
+ if (p_mode != IPSEC_MODE_TRANSPORT) {
+ __ipsec_errcode = EIPSEC_INVAL_ADDRESS;
+ return -1;
+ }
+ }
+ else if (p_src->sa_family != p_dst->sa_family) {
+ __ipsec_errcode = EIPSEC_FAMILY_MISMATCH;
+ return -1;
+ }
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+static int
+init_x_policy()
+{
+ struct sadb_x_policy *p;
+
+ tlen = sizeof(struct sadb_x_policy);
+
+ pbuf = malloc(tlen);
+ if (pbuf == NULL) {
+ __ipsec_errcode = EIPSEC_NO_BUFS;
+ return -1;
+ }
+ memset(pbuf, 0, tlen);
+ p = (struct sadb_x_policy *)pbuf;
+ p->sadb_x_policy_len = 0; /* must update later */
+ p->sadb_x_policy_exttype = SADB_X_EXT_POLICY;
+ p->sadb_x_policy_type = p_type;
+ p->sadb_x_policy_dir = p_dir;
+ p->sadb_x_policy_id = 0;
+
+ offset = tlen;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+static int
+set_x_request(src, dst)
+ struct sockaddr *src, *dst;
+{
+ struct sadb_x_ipsecrequest *p;
+ int reqlen;
+
+ reqlen = sizeof(*p)
+ + (src ? src->sa_len : 0)
+ + (dst ? dst->sa_len : 0);
+ tlen += reqlen; /* increment to total length */
+
+ pbuf = realloc(pbuf, tlen);
+ if (pbuf == NULL) {
+ __ipsec_errcode = EIPSEC_NO_BUFS;
+ return -1;
+ }
+ p = (struct sadb_x_ipsecrequest *)&pbuf[offset];
+ p->sadb_x_ipsecrequest_len = reqlen;
+ p->sadb_x_ipsecrequest_proto = p_protocol;
+ p->sadb_x_ipsecrequest_mode = p_mode;
+ p->sadb_x_ipsecrequest_level = p_level;
+ p->sadb_x_ipsecrequest_reqid = p_reqid;
+ offset += sizeof(*p);
+
+ if (set_sockaddr(src) || set_sockaddr(dst))
+ return -1;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+static int
+set_sockaddr(addr)
+ struct sockaddr *addr;
+{
+ if (addr == NULL) {
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+ }
+
+ /* tlen has already incremented */
+
+ memcpy(&pbuf[offset], addr, addr->sa_len);
+
+ offset += addr->sa_len;
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return 0;
+}
+
+static void
+policy_parse_request_init()
+{
+ p_protocol = IPPROTO_IP;
+ p_mode = IPSEC_MODE_ANY;
+ p_level = IPSEC_LEVEL_DEFAULT;
+ p_reqid = 0;
+ if (p_src != NULL) {
+ free(p_src);
+ p_src = NULL;
+ }
+ if (p_dst != NULL) {
+ free(p_dst);
+ p_dst = NULL;
+ }
+
+ return;
+}
+
+static caddr_t
+policy_parse(msg, msglen)
+ char *msg;
+ int msglen;
+{
+ int error;
+ pbuf = NULL;
+ tlen = 0;
+
+ /* initialize */
+ p_dir = IPSEC_DIR_INVALID;
+ p_type = IPSEC_POLICY_DISCARD;
+ policy_parse_request_init();
+ __policy__strbuffer__init__(msg);
+
+ error = yyparse(); /* it must be set errcode. */
+ __policy__strbuffer__free__();
+
+ if (error) {
+ if (pbuf != NULL)
+ free(pbuf);
+ return NULL;
+ }
+
+ /* update total length */
+ ((struct sadb_x_policy *)pbuf)->sadb_x_policy_len = PFKEY_UNIT64(tlen);
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+
+ return pbuf;
+}
+
+caddr_t
+ipsec_set_policy(msg, msglen)
+ char *msg;
+ int msglen;
+{
+ caddr_t policy;
+
+ policy = policy_parse(msg, msglen);
+ if (policy == NULL) {
+ if (__ipsec_errcode == EIPSEC_NO_ERROR)
+ __ipsec_errcode = EIPSEC_INVAL_ARGUMENT;
+ return NULL;
+ }
+
+ __ipsec_errcode = EIPSEC_NO_ERROR;
+ return policy;
+}
+
diff --git a/freebsd/lib/libipsec/policy_token.l b/freebsd/lib/libipsec/policy_token.l
new file mode 100644
index 00000000..d28ea727
--- /dev/null
+++ b/freebsd/lib/libipsec/policy_token.l
@@ -0,0 +1,168 @@
+/* $FreeBSD$ */
+/* $KAME: policy_token.l,v 1.13 2003/05/09 05:19:55 sakane Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/route.h>
+#ifdef __rtems__
+#include <freebsd/net/pfkeyv2.h>
+#include <freebsd/netipsec/keydb.h>
+#include <freebsd/netinet/in.h>
+#include <freebsd/netipsec/ipsec.h>
+#else
+#include <net/pfkeyv2.h>
+#include <netipsec/keydb.h>
+#include <netinet/in.h>
+#include <netipsec/ipsec.h>
+#endif
+
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+#ifdef __rtems__
+/* XXX - Jennifer doesn't know where to get this from */
+YY_BUFFER_STATE yy_current_buffer;
+#endif
+
+#include "y.tab.h"
+
+#define yylval __libipsecyylval /* XXX */
+
+int yylex(void);
+%}
+
+%option noyywrap
+%option nounput
+
+/* common section */
+nl \n
+ws [ \t]+
+digit [0-9]
+hexdigit [0-9A-Fa-f]
+special [()+\|\?\*,]
+dot \.
+comma \,
+hyphen \-
+colon \:
+slash \/
+bcl \{
+ecl \}
+blcl \[
+elcl \]
+percent \%
+semi \;
+usec {dot}{digit}{1,6}
+comment \#.*
+ccomment "/*"
+bracketstring \<[^>]*\>
+quotedstring \"[^"]*\"
+decstring {digit}+
+hexpair {hexdigit}{hexdigit}
+hexstring 0[xX]{hexdigit}+
+octetstring {octet}({dot}{octet})+
+ipaddress [a-zA-Z0-9:\._][a-zA-Z0-9:\._]*(%[a-zA-Z0-9]+)?
+
+%%
+
+in { yylval.num = IPSEC_DIR_INBOUND; return(DIR); }
+out { yylval.num = IPSEC_DIR_OUTBOUND; return(DIR); }
+
+discard { yylval.num = IPSEC_POLICY_DISCARD; return(ACTION); }
+none { yylval.num = IPSEC_POLICY_NONE; return(ACTION); }
+ipsec { yylval.num = IPSEC_POLICY_IPSEC; return(ACTION); }
+bypass { yylval.num = IPSEC_POLICY_BYPASS; return(ACTION); }
+entrust { yylval.num = IPSEC_POLICY_ENTRUST; return(ACTION); }
+
+esp { yylval.num = IPPROTO_ESP; return(PROTOCOL); }
+ah { yylval.num = IPPROTO_AH; return(PROTOCOL); }
+ipcomp { yylval.num = IPPROTO_IPCOMP; return(PROTOCOL); }
+tcp { yylval.num = IPPROTO_TCP; return(PROTOCOL); }
+
+transport { yylval.num = IPSEC_MODE_TRANSPORT; return(MODE); }
+tunnel { yylval.num = IPSEC_MODE_TUNNEL; return(MODE); }
+
+me { return(ME); }
+any { return(ANY); }
+
+default { yylval.num = IPSEC_LEVEL_DEFAULT; return(LEVEL); }
+use { yylval.num = IPSEC_LEVEL_USE; return(LEVEL); }
+require { yylval.num = IPSEC_LEVEL_REQUIRE; return(LEVEL); }
+unique{colon}{decstring} {
+ yylval.val.len = strlen(yytext + 7);
+ yylval.val.buf = yytext + 7;
+ return(LEVEL_SPECIFY);
+ }
+unique { yylval.num = IPSEC_LEVEL_UNIQUE; return(LEVEL); }
+{slash} { return(SLASH); }
+
+{ipaddress} {
+ yylval.val.len = strlen(yytext);
+ yylval.val.buf = yytext;
+ return(IPADDRESS);
+ }
+
+{hyphen} { return(HYPHEN); }
+
+{ws} { ; }
+{nl} { ; }
+
+%%
+
+void __policy__strbuffer__init__(char *);
+void __policy__strbuffer__free__(void);
+
+static YY_BUFFER_STATE strbuffer;
+
+void
+__policy__strbuffer__init__(msg)
+ char *msg;
+{
+ if (yy_current_buffer)
+ yy_delete_buffer(yy_current_buffer);
+ strbuffer = (YY_BUFFER_STATE)yy_scan_string(msg);
+ yy_switch_to_buffer(strbuffer);
+
+ return;
+}
+
+void
+__policy__strbuffer__free__()
+{
+ yy_delete_buffer(strbuffer);
+
+ return;
+}
diff --git a/freebsd/lib/libkvm/kvm.h b/freebsd/lib/libkvm/kvm.h
new file mode 100644
index 00000000..0427bd1c
--- /dev/null
+++ b/freebsd/lib/libkvm/kvm.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ *
+ * @(#)kvm.h 8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+#ifndef _KVM_H_
+#define _KVM_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+#include <nlist.h>
+
+/* Default version symbol. */
+#define VRS_SYM "_version"
+#define VRS_KEY "VERSION"
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+
+#ifndef _SSIZE_T_DECLARED
+typedef __ssize_t ssize_t;
+#define _SSIZE_T_DECLARED
+#endif
+
+typedef struct __kvm kvm_t;
+
+struct kinfo_proc;
+struct proc;
+
+struct kvm_swap {
+ char ksw_devname[32];
+ int ksw_used;
+ int ksw_total;
+ int ksw_flags;
+ int ksw_reserved1;
+ int ksw_reserved2;
+};
+
+#define SWIF_DEV_PREFIX 0x0002
+
+__BEGIN_DECLS
+int kvm_close(kvm_t *);
+char **kvm_getargv(kvm_t *, const struct kinfo_proc *, int);
+int kvm_getcptime(kvm_t *, long *);
+char **kvm_getenvv(kvm_t *, const struct kinfo_proc *, int);
+char *kvm_geterr(kvm_t *);
+char *kvm_getfiles(kvm_t *, int, int, int *);
+int kvm_getloadavg(kvm_t *, double [], int);
+int kvm_getmaxcpu(kvm_t *);
+void *kvm_getpcpu(kvm_t *, int);
+struct kinfo_proc *
+ kvm_getprocs(kvm_t *, int, int, int *);
+int kvm_getswapinfo(kvm_t *, struct kvm_swap *, int, int);
+int kvm_nlist(kvm_t *, struct nlist *);
+kvm_t *kvm_open
+ (const char *, const char *, const char *, int, const char *);
+kvm_t *kvm_openfiles
+ (const char *, const char *, const char *, int, char *);
+ssize_t kvm_read(kvm_t *, unsigned long, void *, size_t);
+ssize_t kvm_uread
+ (kvm_t *, struct kinfo_proc *, unsigned long, char *, size_t);
+ssize_t kvm_write(kvm_t *, unsigned long, const void *, size_t);
+__END_DECLS
+
+#endif /* !_KVM_H_ */
diff --git a/freebsd/lib/libmemstat/memstat.c b/freebsd/lib/libmemstat/memstat.c
new file mode 100644
index 00000000..28e48138
--- /dev/null
+++ b/freebsd/lib/libmemstat/memstat.c
@@ -0,0 +1,421 @@
+/*-
+ * Copyright (c) 2005 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "memstat.h"
+#include "memstat_internal.h"
+
+const char *
+memstat_strerror(int error)
+{
+
+ switch (error) {
+ case MEMSTAT_ERROR_NOMEMORY:
+ return ("Cannot allocate memory");
+ case MEMSTAT_ERROR_VERSION:
+ return ("Version mismatch");
+ case MEMSTAT_ERROR_PERMISSION:
+ return ("Permission denied");
+ case MEMSTAT_ERROR_TOOMANYCPUS:
+ return ("Too many CPUs");
+ case MEMSTAT_ERROR_DATAERROR:
+ return ("Data format error");
+ case MEMSTAT_ERROR_KVM:
+ return ("KVM error");
+ case MEMSTAT_ERROR_KVM_NOSYMBOL:
+ return ("KVM unable to find symbol");
+ case MEMSTAT_ERROR_KVM_SHORTREAD:
+ return ("KVM short read");
+ case MEMSTAT_ERROR_UNDEFINED:
+ default:
+ return ("Unknown error");
+ }
+}
+
+struct memory_type_list *
+memstat_mtl_alloc(void)
+{
+ struct memory_type_list *mtlp;
+
+ mtlp = malloc(sizeof(*mtlp));
+ if (mtlp == NULL)
+ return (NULL);
+
+ LIST_INIT(&mtlp->mtl_list);
+ mtlp->mtl_error = MEMSTAT_ERROR_UNDEFINED;
+ return (mtlp);
+}
+
+struct memory_type *
+memstat_mtl_first(struct memory_type_list *list)
+{
+
+ return (LIST_FIRST(&list->mtl_list));
+}
+
+struct memory_type *
+memstat_mtl_next(struct memory_type *mtp)
+{
+
+ return (LIST_NEXT(mtp, mt_list));
+}
+
+void
+_memstat_mtl_empty(struct memory_type_list *list)
+{
+ struct memory_type *mtp;
+
+ while ((mtp = LIST_FIRST(&list->mtl_list))) {
+ LIST_REMOVE(mtp, mt_list);
+ free(mtp);
+ }
+}
+
+void
+memstat_mtl_free(struct memory_type_list *list)
+{
+
+ _memstat_mtl_empty(list);
+ free(list);
+}
+
+int
+memstat_mtl_geterror(struct memory_type_list *list)
+{
+
+ return (list->mtl_error);
+}
+
+/*
+ * Look for an existing memory_type entry in a memory_type list, based on the
+ * allocator and name of the type. If not found, return NULL. No errno or
+ * memstat error.
+ */
+struct memory_type *
+memstat_mtl_find(struct memory_type_list *list, int allocator,
+ const char *name)
+{
+ struct memory_type *mtp;
+
+ LIST_FOREACH(mtp, &list->mtl_list, mt_list) {
+ if ((mtp->mt_allocator == allocator ||
+ allocator == ALLOCATOR_ANY) &&
+ strcmp(mtp->mt_name, name) == 0)
+ return (mtp);
+ }
+ return (NULL);
+}
+
+/*
+ * Allocate a new memory_type with the specificed allocator type and name,
+ * then insert into the list. The structure will be zero'd.
+ *
+ * libmemstat(3) internal function.
+ */
+struct memory_type *
+_memstat_mt_allocate(struct memory_type_list *list, int allocator,
+ const char *name)
+{
+ struct memory_type *mtp;
+
+ mtp = malloc(sizeof(*mtp));
+ if (mtp == NULL)
+ return (NULL);
+
+ bzero(mtp, sizeof(*mtp));
+
+ mtp->mt_allocator = allocator;
+ strlcpy(mtp->mt_name, name, MEMTYPE_MAXNAME);
+ LIST_INSERT_HEAD(&list->mtl_list, mtp, mt_list);
+ return (mtp);
+}
+
+/*
+ * Reset any libmemstat(3)-owned statistics in a memory_type record so that
+ * it can be reused without incremental addition problems. Caller-owned
+ * memory is left "as-is", and must be updated by the caller if desired.
+ *
+ * libmemstat(3) internal function.
+ */
+void
+_memstat_mt_reset_stats(struct memory_type *mtp)
+{
+ int i;
+
+ mtp->mt_countlimit = 0;
+ mtp->mt_byteslimit = 0;
+ mtp->mt_sizemask = 0;
+ mtp->mt_size = 0;
+
+ mtp->mt_memalloced = 0;
+ mtp->mt_memfreed = 0;
+ mtp->mt_numallocs = 0;
+ mtp->mt_numfrees = 0;
+ mtp->mt_bytes = 0;
+ mtp->mt_count = 0;
+ mtp->mt_free = 0;
+ mtp->mt_failures = 0;
+
+ mtp->mt_zonefree = 0;
+ mtp->mt_kegfree = 0;
+
+ for (i = 0; i < MEMSTAT_MAXCPU; i++) {
+ mtp->mt_percpu_alloc[i].mtp_memalloced = 0;
+ mtp->mt_percpu_alloc[i].mtp_memfreed = 0;
+ mtp->mt_percpu_alloc[i].mtp_numallocs = 0;
+ mtp->mt_percpu_alloc[i].mtp_numfrees = 0;
+ mtp->mt_percpu_alloc[i].mtp_sizemask = 0;
+ mtp->mt_percpu_cache[i].mtp_free = 0;
+ }
+}
+
+/*
+ * Accessor methods for struct memory_type. Avoids encoding the structure
+ * ABI into the application.
+ */
+const char *
+memstat_get_name(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_name);
+}
+
+int
+memstat_get_allocator(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_allocator);
+}
+
+uint64_t
+memstat_get_countlimit(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_countlimit);
+}
+
+uint64_t
+memstat_get_byteslimit(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_byteslimit);
+}
+
+uint64_t
+memstat_get_sizemask(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_sizemask);
+}
+
+uint64_t
+memstat_get_size(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_size);
+}
+
+uint64_t
+memstat_get_memalloced(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_memalloced);
+}
+
+uint64_t
+memstat_get_memfreed(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_memfreed);
+}
+
+uint64_t
+memstat_get_numallocs(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_numallocs);
+}
+
+uint64_t
+memstat_get_numfrees(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_numfrees);
+}
+
+uint64_t
+memstat_get_bytes(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_bytes);
+}
+
+uint64_t
+memstat_get_count(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_count);
+}
+
+uint64_t
+memstat_get_free(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_free);
+}
+
+uint64_t
+memstat_get_failures(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_failures);
+}
+
+void *
+memstat_get_caller_pointer(const struct memory_type *mtp, int index)
+{
+
+ return (mtp->mt_caller_pointer[index]);
+}
+
+void
+memstat_set_caller_pointer(struct memory_type *mtp, int index, void *value)
+{
+
+ mtp->mt_caller_pointer[index] = value;
+}
+
+uint64_t
+memstat_get_caller_uint64(const struct memory_type *mtp, int index)
+{
+
+ return (mtp->mt_caller_uint64[index]);
+}
+
+void
+memstat_set_caller_uint64(struct memory_type *mtp, int index, uint64_t value)
+{
+
+ mtp->mt_caller_uint64[index] = value;
+}
+
+uint64_t
+memstat_get_zonefree(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_zonefree);
+}
+
+uint64_t
+memstat_get_kegfree(const struct memory_type *mtp)
+{
+
+ return (mtp->mt_kegfree);
+}
+
+uint64_t
+memstat_get_percpu_memalloced(const struct memory_type *mtp, int cpu)
+{
+
+ return (mtp->mt_percpu_alloc[cpu].mtp_memalloced);
+}
+
+uint64_t
+memstat_get_percpu_memfreed(const struct memory_type *mtp, int cpu)
+{
+
+ return (mtp->mt_percpu_alloc[cpu].mtp_memfreed);
+}
+
+uint64_t
+memstat_get_percpu_numallocs(const struct memory_type *mtp, int cpu)
+{
+
+ return (mtp->mt_percpu_alloc[cpu].mtp_numallocs);
+}
+
+uint64_t
+memstat_get_percpu_numfrees(const struct memory_type *mtp, int cpu)
+{
+
+ return (mtp->mt_percpu_alloc[cpu].mtp_numfrees);
+}
+
+uint64_t
+memstat_get_percpu_sizemask(const struct memory_type *mtp, int cpu)
+{
+
+ return (mtp->mt_percpu_alloc[cpu].mtp_sizemask);
+}
+
+void *
+memstat_get_percpu_caller_pointer(const struct memory_type *mtp, int cpu,
+ int index)
+{
+
+ return (mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index]);
+}
+
+void
+memstat_set_percpu_caller_pointer(struct memory_type *mtp, int cpu,
+ int index, void *value)
+{
+
+ mtp->mt_percpu_alloc[cpu].mtp_caller_pointer[index] = value;
+}
+
+uint64_t
+memstat_get_percpu_caller_uint64(const struct memory_type *mtp, int cpu,
+ int index)
+{
+
+ return (mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index]);
+}
+
+void
+memstat_set_percpu_caller_uint64(struct memory_type *mtp, int cpu, int index,
+ uint64_t value)
+{
+
+ mtp->mt_percpu_alloc[cpu].mtp_caller_uint64[index] = value;
+}
+
+uint64_t
+memstat_get_percpu_free(const struct memory_type *mtp, int cpu)
+{
+
+ return (mtp->mt_percpu_cache[cpu].mtp_free);
+}
diff --git a/freebsd/lib/libmemstat/memstat.h b/freebsd/lib/libmemstat/memstat.h
new file mode 100644
index 00000000..5991a8f2
--- /dev/null
+++ b/freebsd/lib/libmemstat/memstat.h
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 2005 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
+ * 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 _MEMSTAT_H_
+#define _MEMSTAT_H_
+
+#ifdef __rtems__
+#include <stdint.h>
+#endif
+
+/*
+ * Number of CPU slots in library-internal data structures. This should be
+ * at least the value of MAXCPU from param.h.
+ */
+#define MEMSTAT_MAXCPU 32
+
+/*
+ * Amount of caller data to maintain for each caller data slot. Applications
+ * must not request more than this number of caller save data, or risk
+ * corrupting internal libmemstat(3) data structures. A compile time check
+ * in the application is probably appropriate.
+ */
+#define MEMSTAT_MAXCALLER 16
+
+/*
+ * libmemstat(3) is able to extract memory data from different allocators;
+ * when it does so, it tags which allocator it got the data from so that
+ * consumers can determine which fields are usable, as data returned varies
+ * some.
+ */
+#define ALLOCATOR_UNKNOWN 0
+#define ALLOCATOR_MALLOC 1
+#define ALLOCATOR_UMA 2
+#define ALLOCATOR_ANY 255
+
+/*
+ * Library maximum type name. Should be max(set of name maximums over
+ * various allocators).
+ */
+#define MEMTYPE_MAXNAME 32
+
+/*
+ * Library error conditions, mostly from the underlying data sources. On
+ * failure, functions typically return (-1) or (NULL); on success, (0) or a
+ * valid data pointer. The error from the last operation is stored in
+ * struct memory_type_list, and accessed via memstat_get_error(list).
+ */
+#define MEMSTAT_ERROR_UNDEFINED 0 /* Initialization value. */
+#define MEMSTAT_ERROR_NOMEMORY 1 /* Out of memory. */
+#define MEMSTAT_ERROR_VERSION 2 /* Unsupported version. */
+#define MEMSTAT_ERROR_PERMISSION 3 /* Permission denied. */
+#define MEMSTAT_ERROR_TOOMANYCPUS 4 /* Too many CPUs. */
+#define MEMSTAT_ERROR_DATAERROR 5 /* Error in stat data. */
+#define MEMSTAT_ERROR_KVM 6 /* See kvm_geterr() for err. */
+#define MEMSTAT_ERROR_KVM_NOSYMBOL 7 /* Symbol not available. */
+#define MEMSTAT_ERROR_KVM_SHORTREAD 8 /* Short kvm_read return. */
+
+/*
+ * Forward declare struct memory_type, which holds per-type properties and
+ * statistics. This is an opaque type, to be frobbed only from within the
+ * library, in order to avoid building ABI assumptions into the application.
+ * Accessor methods should be used to get and sometimes set the fields from
+ * consumers of the library.
+ */
+struct memory_type;
+
+/*
+ * struct memory_type_list is the head of a list of memory types and
+ * statistics.
+ */
+struct memory_type_list;
+
+__BEGIN_DECLS
+/*
+ * Functions that operate without memory type or memory type list context.
+ */
+const char *memstat_strerror(int error);
+
+/*
+ * Functions for managing memory type and statistics data.
+ */
+struct memory_type_list *memstat_mtl_alloc(void);
+struct memory_type *memstat_mtl_first(struct memory_type_list *list);
+struct memory_type *memstat_mtl_next(struct memory_type *mtp);
+struct memory_type *memstat_mtl_find(struct memory_type_list *list,
+ int allocator, const char *name);
+void memstat_mtl_free(struct memory_type_list *list);
+int memstat_mtl_geterror(struct memory_type_list *list);
+
+/*
+ * Functions to retrieve data from a live kernel using sysctl.
+ */
+int memstat_sysctl_all(struct memory_type_list *list, int flags);
+int memstat_sysctl_malloc(struct memory_type_list *list, int flags);
+int memstat_sysctl_uma(struct memory_type_list *list, int flags);
+
+/*
+ * Functions to retrieve data from a kernel core (or /dev/kmem).
+ */
+int memstat_kvm_all(struct memory_type_list *list, void *kvm_handle);
+int memstat_kvm_malloc(struct memory_type_list *list, void *kvm_handle);
+int memstat_kvm_uma(struct memory_type_list *list, void *kvm_handle);
+
+/*
+ * Accessor methods for struct memory_type.
+ */
+const char *memstat_get_name(const struct memory_type *mtp);
+int memstat_get_allocator(const struct memory_type *mtp);
+uint64_t memstat_get_countlimit(const struct memory_type *mtp);
+uint64_t memstat_get_byteslimit(const struct memory_type *mtp);
+uint64_t memstat_get_sizemask(const struct memory_type *mtp);
+uint64_t memstat_get_size(const struct memory_type *mtp);
+uint64_t memstat_get_memalloced(const struct memory_type *mtp);
+uint64_t memstat_get_memfreed(const struct memory_type *mtp);
+uint64_t memstat_get_numallocs(const struct memory_type *mtp);
+uint64_t memstat_get_numfrees(const struct memory_type *mtp);
+uint64_t memstat_get_bytes(const struct memory_type *mtp);
+uint64_t memstat_get_count(const struct memory_type *mtp);
+uint64_t memstat_get_free(const struct memory_type *mtp);
+uint64_t memstat_get_failures(const struct memory_type *mtp);
+void *memstat_get_caller_pointer(const struct memory_type *mtp,
+ int index);
+void memstat_set_caller_pointer(struct memory_type *mtp,
+ int index, void *value);
+uint64_t memstat_get_caller_uint64(const struct memory_type *mtp,
+ int index);
+void memstat_set_caller_uint64(struct memory_type *mtp, int index,
+ uint64_t value);
+uint64_t memstat_get_zonefree(const struct memory_type *mtp);
+uint64_t memstat_get_kegfree(const struct memory_type *mtp);
+uint64_t memstat_get_percpu_memalloced(const struct memory_type *mtp,
+ int cpu);
+uint64_t memstat_get_percpu_memfreed(const struct memory_type *mtp,
+ int cpu);
+uint64_t memstat_get_percpu_numallocs(const struct memory_type *mtp,
+ int cpu);
+uint64_t memstat_get_percpu_numfrees(const struct memory_type *mtp,
+ int cpu);
+uint64_t memstat_get_percpu_sizemask(const struct memory_type *mtp,
+ int cpu);
+void *memstat_get_percpu_caller_pointer(
+ const struct memory_type *mtp, int cpu, int index);
+void memstat_set_percpu_caller_pointer(struct memory_type *mtp,
+ int cpu, int index, void *value);
+uint64_t memstat_get_percpu_caller_uint64(
+ const struct memory_type *mtp, int cpu, int index);
+void memstat_set_percpu_caller_uint64(struct memory_type *mtp,
+ int cpu, int index, uint64_t value);
+uint64_t memstat_get_percpu_free(const struct memory_type *mtp,
+ int cpu);
+__END_DECLS
+
+#endif /* !_MEMSTAT_H_ */
diff --git a/freebsd/lib/libmemstat/memstat_all.c b/freebsd/lib/libmemstat/memstat_all.c
new file mode 100644
index 00000000..a943e653
--- /dev/null
+++ b/freebsd/lib/libmemstat/memstat_all.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2005 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include "memstat.h"
+
+/*
+ * Query all available memory allocator sources. Currently this consists of
+ * malloc(9) and UMA(9).
+ */
+int
+memstat_sysctl_all(struct memory_type_list *mtlp, int flags)
+{
+
+ if (memstat_sysctl_malloc(mtlp, flags) < 0)
+ return (-1);
+ if (memstat_sysctl_uma(mtlp, flags) < 0)
+ return (-1);
+ return (0);
+}
+
+#ifndef __rtems__
+int
+memstat_kvm_all(struct memory_type_list *mtlp, void *kvm_handle)
+{
+
+ if (memstat_kvm_malloc(mtlp, kvm_handle) < 0)
+ return (-1);
+ if (memstat_kvm_uma(mtlp, kvm_handle) < 0)
+ return (-1);
+ return (0);
+}
+#endif
diff --git a/freebsd/lib/libmemstat/memstat_internal.h b/freebsd/lib/libmemstat/memstat_internal.h
new file mode 100644
index 00000000..7123518e
--- /dev/null
+++ b/freebsd/lib/libmemstat/memstat_internal.h
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 2005 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
+ * 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 _MEMSTAT_INTERNAL_H_
+#define _MEMSTAT_INTERNAL_H_
+
+/*
+ * memstat maintains its own internal notion of statistics on each memory
+ * type, common across UMA and kernel malloc. Some fields are straight from
+ * the allocator statistics, others are derived when extracted from the
+ * kernel. A struct memory_type will describe each type supported by an
+ * allocator. memory_type structures can be chained into lists.
+ */
+struct memory_type {
+ /*
+ * Static properties of type.
+ */
+ int mt_allocator; /* malloc(9), uma(9), etc. */
+ char mt_name[MEMTYPE_MAXNAME]; /* name of memory type. */
+
+ /*
+ * (Relatively) static zone settings, that don't uniquely identify
+ * the zone, but also don't change much.
+ */
+ uint64_t mt_countlimit; /* 0, or maximum allocations. */
+ uint64_t mt_byteslimit; /* 0, or maximum bytes. */
+ uint64_t mt_sizemask; /* malloc: allocated size bitmask. */
+ uint64_t mt_size; /* uma: size of objects. */
+
+ /*
+ * Zone or type information that includes all caches and any central
+ * zone state. Depending on the allocator, this may be synthesized
+ * from several sources, or directly measured.
+ */
+ uint64_t mt_memalloced; /* Bytes allocated over life time. */
+ uint64_t mt_memfreed; /* Bytes freed over life time. */
+ uint64_t mt_numallocs; /* Allocations over life time. */
+ uint64_t mt_numfrees; /* Frees over life time. */
+ uint64_t mt_bytes; /* Bytes currently allocated. */
+ uint64_t mt_count; /* Number of current allocations. */
+ uint64_t mt_free; /* Number of cached free items. */
+ uint64_t mt_failures; /* Number of allocation failures. */
+
+ /*
+ * Caller-owned memory.
+ */
+ void *mt_caller_pointer[MEMSTAT_MAXCALLER]; /* Pointers. */
+ uint64_t mt_caller_uint64[MEMSTAT_MAXCALLER]; /* Integers. */
+
+ /*
+ * For allocators making use of per-CPU caches, we also provide raw
+ * statistics from the central allocator and each per-CPU cache,
+ * which (combined) sometimes make up the above general statistics.
+ *
+ * First, central zone/type state, all numbers excluding any items
+ * cached in per-CPU caches.
+ *
+ * XXXRW: Might be desirable to separately expose allocation stats
+ * from zone, which should (combined with per-cpu) add up to the
+ * global stats above.
+ */
+ uint64_t mt_zonefree; /* Free items in zone. */
+ uint64_t mt_kegfree; /* Free items in keg. */
+
+ /*
+ * Per-CPU measurements fall into two categories: per-CPU allocation,
+ * and per-CPU cache state.
+ */
+ struct {
+ uint64_t mtp_memalloced;/* Per-CPU mt_memalloced. */
+ uint64_t mtp_memfreed; /* Per-CPU mt_memfreed. */
+ uint64_t mtp_numallocs; /* Per-CPU mt_numallocs. */
+ uint64_t mtp_numfrees; /* Per-CPU mt_numfrees. */
+ uint64_t mtp_sizemask; /* Per-CPU mt_sizemask. */
+ void *mtp_caller_pointer[MEMSTAT_MAXCALLER];
+ uint64_t mtp_caller_uint64[MEMSTAT_MAXCALLER];
+ } mt_percpu_alloc[MEMSTAT_MAXCPU];
+
+ struct {
+ uint64_t mtp_free; /* Per-CPU cache free items. */
+ } mt_percpu_cache[MEMSTAT_MAXCPU];
+
+ LIST_ENTRY(memory_type) mt_list; /* List of types. */
+};
+
+/*
+ * Description of struct memory_type_list is in memstat.h.
+ */
+struct memory_type_list {
+ LIST_HEAD(, memory_type) mtl_list;
+ int mtl_error;
+};
+
+void _memstat_mtl_empty(struct memory_type_list *list);
+struct memory_type *_memstat_mt_allocate(struct memory_type_list *list,
+ int allocator, const char *name);
+void _memstat_mt_reset_stats(struct memory_type *mtp);
+
+#endif /* !_MEMSTAT_INTERNAL_H_ */
diff --git a/freebsd/lib/libmemstat/memstat_malloc.c b/freebsd/lib/libmemstat/memstat_malloc.c
new file mode 100644
index 00000000..96ff8a16
--- /dev/null
+++ b/freebsd/lib/libmemstat/memstat_malloc.c
@@ -0,0 +1,417 @@
+#include "port_before.h"
+/*-
+ * Copyright (c) 2005 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+#include <sys/param.h>
+#ifdef __rtems__
+#include <freebsd/sys/malloc.h>
+#else
+#include <sys/malloc.h>
+#endif
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <errno.h>
+#ifndef __rtems__
+#include <kvm.h>
+#endif
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "memstat.h"
+#include "memstat_internal.h"
+
+static struct nlist namelist[] = {
+#define X_KMEMSTATISTICS 0
+ { .n_name = "_kmemstatistics" },
+#define X_MP_MAXCPUS 1
+ { .n_name = "_mp_maxcpus" },
+ { .n_name = "" },
+};
+
+/*
+ * Extract malloc(9) statistics from the running kernel, and store all memory
+ * type information in the passed list. For each type, check the list for an
+ * existing entry with the right name/allocator -- if present, update that
+ * entry. Otherwise, add a new entry. On error, the entire list will be
+ * cleared, as entries will be in an inconsistent state.
+ *
+ * To reduce the level of work for a list that starts empty, we keep around a
+ * hint as to whether it was empty when we began, so we can avoid searching
+ * the list for entries to update. Updates are O(n^2) due to searching for
+ * each entry before adding it.
+ */
+int
+memstat_sysctl_malloc(struct memory_type_list *list, int flags)
+{
+ struct malloc_type_stream_header *mtshp;
+ struct malloc_type_header *mthp;
+ struct malloc_type_stats *mtsp;
+ struct memory_type *mtp;
+ int count, hint_dontsearch, i, j, maxcpus;
+ char *buffer, *p;
+ size_t size;
+
+ hint_dontsearch = LIST_EMPTY(&list->mtl_list);
+
+ /*
+ * Query the number of CPUs, number of malloc types so that we can
+ * guess an initial buffer size. We loop until we succeed or really
+ * fail. Note that the value of maxcpus we query using sysctl is not
+ * the version we use when processing the real data -- that is read
+ * from the header.
+ */
+retry:
+ size = sizeof(maxcpus);
+ if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
+ return (-1);
+ }
+ if (size != sizeof(maxcpus)) {
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
+ return (-1);
+ }
+
+ if (maxcpus > MEMSTAT_MAXCPU) {
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
+ return (-1);
+ }
+
+ size = sizeof(count);
+ if (sysctlbyname("kern.malloc_count", &count, &size, NULL, 0) < 0) {
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ return (-1);
+ }
+ if (size != sizeof(count)) {
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
+ return (-1);
+ }
+
+ size = sizeof(*mthp) + count * (sizeof(*mthp) + sizeof(*mtsp) *
+ maxcpus);
+
+ buffer = malloc(size);
+ if (buffer == NULL) {
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+
+ if (sysctlbyname("kern.malloc_stats", buffer, &size, NULL, 0) < 0) {
+ /*
+ * XXXRW: ENOMEM is an ambiguous return, we should bound the
+ * number of loops, perhaps.
+ */
+ if (errno == ENOMEM) {
+ free(buffer);
+ goto retry;
+ }
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ free(buffer);
+ return (-1);
+ }
+
+ if (size == 0) {
+ free(buffer);
+ return (0);
+ }
+
+ if (size < sizeof(*mtshp)) {
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ free(buffer);
+ return (-1);
+ }
+ p = buffer;
+ mtshp = (struct malloc_type_stream_header *)p;
+ p += sizeof(*mtshp);
+
+ if (mtshp->mtsh_version != MALLOC_TYPE_STREAM_VERSION) {
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ free(buffer);
+ return (-1);
+ }
+
+ if (mtshp->mtsh_maxcpus > MEMSTAT_MAXCPU) {
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
+ free(buffer);
+ return (-1);
+ }
+
+ /*
+ * For the remainder of this function, we are quite trusting about
+ * the layout of structures and sizes, since we've determined we have
+ * a matching version and acceptable CPU count.
+ */
+ maxcpus = mtshp->mtsh_maxcpus;
+ count = mtshp->mtsh_count;
+ for (i = 0; i < count; i++) {
+ mthp = (struct malloc_type_header *)p;
+ p += sizeof(*mthp);
+
+ if (hint_dontsearch == 0) {
+ mtp = memstat_mtl_find(list, ALLOCATOR_MALLOC,
+ mthp->mth_name);
+ } else
+ mtp = NULL;
+ if (mtp == NULL)
+ mtp = _memstat_mt_allocate(list, ALLOCATOR_MALLOC,
+ mthp->mth_name);
+ if (mtp == NULL) {
+ _memstat_mtl_empty(list);
+ free(buffer);
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+
+ /*
+ * Reset the statistics on a current node.
+ */
+ _memstat_mt_reset_stats(mtp);
+
+ for (j = 0; j < maxcpus; j++) {
+ mtsp = (struct malloc_type_stats *)p;
+ p += sizeof(*mtsp);
+
+ /*
+ * Sumarize raw statistics across CPUs into coalesced
+ * statistics.
+ */
+ mtp->mt_memalloced += mtsp->mts_memalloced;
+ mtp->mt_memfreed += mtsp->mts_memfreed;
+ mtp->mt_numallocs += mtsp->mts_numallocs;
+ mtp->mt_numfrees += mtsp->mts_numfrees;
+ mtp->mt_sizemask |= mtsp->mts_size;
+
+ /*
+ * Copies of per-CPU statistics.
+ */
+ mtp->mt_percpu_alloc[j].mtp_memalloced =
+ mtsp->mts_memalloced;
+ mtp->mt_percpu_alloc[j].mtp_memfreed =
+ mtsp->mts_memfreed;
+ mtp->mt_percpu_alloc[j].mtp_numallocs =
+ mtsp->mts_numallocs;
+ mtp->mt_percpu_alloc[j].mtp_numfrees =
+ mtsp->mts_numfrees;
+ mtp->mt_percpu_alloc[j].mtp_sizemask =
+ mtsp->mts_size;
+ }
+
+ /*
+ * Derived cross-CPU statistics.
+ */
+ mtp->mt_bytes = mtp->mt_memalloced - mtp->mt_memfreed;
+ mtp->mt_count = mtp->mt_numallocs - mtp->mt_numfrees;
+ }
+
+ free(buffer);
+
+ return (0);
+}
+
+#ifndef __rtems__
+static int
+kread(kvm_t *kvm, void *kvm_pointer, void *address, size_t size,
+ size_t offset)
+{
+ ssize_t ret;
+
+ ret = kvm_read(kvm, (unsigned long)kvm_pointer + offset, address,
+ size);
+ if (ret < 0)
+ return (MEMSTAT_ERROR_KVM);
+ if ((size_t)ret != size)
+ return (MEMSTAT_ERROR_KVM_SHORTREAD);
+ return (0);
+}
+
+static int
+kread_string(kvm_t *kvm, const void *kvm_pointer, char *buffer, int buflen)
+{
+ ssize_t ret;
+ int i;
+
+ for (i = 0; i < buflen; i++) {
+ ret = kvm_read(kvm, __DECONST(unsigned long, kvm_pointer) +
+ i, &(buffer[i]), sizeof(char));
+ if (ret < 0)
+ return (MEMSTAT_ERROR_KVM);
+ if ((size_t)ret != sizeof(char))
+ return (MEMSTAT_ERROR_KVM_SHORTREAD);
+ if (buffer[i] == '\0')
+ return (0);
+ }
+ /* Truncate. */
+ buffer[i-1] = '\0';
+ return (0);
+}
+
+static int
+kread_symbol(kvm_t *kvm, int index, void *address, size_t size,
+ size_t offset)
+{
+ ssize_t ret;
+
+ ret = kvm_read(kvm, namelist[index].n_value + offset, address, size);
+ if (ret < 0)
+ return (MEMSTAT_ERROR_KVM);
+ if ((size_t)ret != size)
+ return (MEMSTAT_ERROR_KVM_SHORTREAD);
+ return (0);
+}
+
+int
+memstat_kvm_malloc(struct memory_type_list *list, void *kvm_handle)
+{
+ struct memory_type *mtp;
+ void *kmemstatistics;
+ int hint_dontsearch, j, mp_maxcpus, ret;
+ char name[MEMTYPE_MAXNAME];
+ struct malloc_type_stats mts[MEMSTAT_MAXCPU], *mtsp;
+ struct malloc_type_internal *mtip;
+ struct malloc_type type, *typep;
+ kvm_t *kvm;
+
+ kvm = (kvm_t *)kvm_handle;
+
+ hint_dontsearch = LIST_EMPTY(&list->mtl_list);
+
+ if (kvm_nlist(kvm, namelist) != 0) {
+ list->mtl_error = MEMSTAT_ERROR_KVM;
+ return (-1);
+ }
+
+ if (namelist[X_KMEMSTATISTICS].n_type == 0 ||
+ namelist[X_KMEMSTATISTICS].n_value == 0) {
+ list->mtl_error = MEMSTAT_ERROR_KVM_NOSYMBOL;
+ return (-1);
+ }
+
+ ret = kread_symbol(kvm, X_MP_MAXCPUS, &mp_maxcpus,
+ sizeof(mp_maxcpus), 0);
+ if (ret != 0) {
+ list->mtl_error = ret;
+ return (-1);
+ }
+
+ if (mp_maxcpus > MEMSTAT_MAXCPU) {
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
+ return (-1);
+ }
+
+ ret = kread_symbol(kvm, X_KMEMSTATISTICS, &kmemstatistics,
+ sizeof(kmemstatistics), 0);
+ if (ret != 0) {
+ list->mtl_error = ret;
+ return (-1);
+ }
+
+ for (typep = kmemstatistics; typep != NULL; typep = type.ks_next) {
+ ret = kread(kvm, typep, &type, sizeof(type), 0);
+ if (ret != 0) {
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+ ret = kread_string(kvm, (void *)type.ks_shortdesc, name,
+ MEMTYPE_MAXNAME);
+ if (ret != 0) {
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+
+ /*
+ * Since our compile-time value for MAXCPU may differ from the
+ * kernel's, we populate our own array.
+ */
+ mtip = type.ks_handle;
+ ret = kread(kvm, mtip->mti_stats, mts, mp_maxcpus *
+ sizeof(struct malloc_type_stats), 0);
+ if (ret != 0) {
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+
+ if (hint_dontsearch == 0) {
+ mtp = memstat_mtl_find(list, ALLOCATOR_MALLOC, name);
+ } else
+ mtp = NULL;
+ if (mtp == NULL)
+ mtp = _memstat_mt_allocate(list, ALLOCATOR_MALLOC,
+ name);
+ if (mtp == NULL) {
+ _memstat_mtl_empty(list);
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+
+ /*
+ * This logic is replicated from kern_malloc.c, and should
+ * be kept in sync.
+ */
+ _memstat_mt_reset_stats(mtp);
+ for (j = 0; j < mp_maxcpus; j++) {
+ mtsp = &mts[j];
+ mtp->mt_memalloced += mtsp->mts_memalloced;
+ mtp->mt_memfreed += mtsp->mts_memfreed;
+ mtp->mt_numallocs += mtsp->mts_numallocs;
+ mtp->mt_numfrees += mtsp->mts_numfrees;
+ mtp->mt_sizemask |= mtsp->mts_size;
+
+ mtp->mt_percpu_alloc[j].mtp_memalloced =
+ mtsp->mts_memalloced;
+ mtp->mt_percpu_alloc[j].mtp_memfreed =
+ mtsp->mts_memfreed;
+ mtp->mt_percpu_alloc[j].mtp_numallocs =
+ mtsp->mts_numallocs;
+ mtp->mt_percpu_alloc[j].mtp_numfrees =
+ mtsp->mts_numfrees;
+ mtp->mt_percpu_alloc[j].mtp_sizemask =
+ mtsp->mts_size;
+ }
+
+ mtp->mt_bytes = mtp->mt_memalloced - mtp->mt_memfreed;
+ mtp->mt_count = mtp->mt_numallocs - mtp->mt_numfrees;
+ }
+
+ return (0);
+}
+#endif
diff --git a/freebsd/lib/libmemstat/memstat_uma.c b/freebsd/lib/libmemstat/memstat_uma.c
new file mode 100644
index 00000000..deac50d7
--- /dev/null
+++ b/freebsd/lib/libmemstat/memstat_uma.c
@@ -0,0 +1,478 @@
+#include "port_before.h"
+/*-
+ * Copyright (c) 2005-2006 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
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#define LIBMEMSTAT /* Cause vm_page.h not to include opt_vmpage.h */
+#ifdef __rtems__
+#include <freebsd/sys/types.h>
+#include <freebsd/vm/vm.h>
+// #include <vm/vm_page.h>
+#include <freebsd/vm/uma.h>
+#include <freebsd/vm/uma_int.h>
+#else
+#include <vm/vm.h>
+#include <vm/vm_page.h>
+#include <vm/uma.h>
+#include <vm/uma_int.h>
+#endif
+
+
+#include <err.h>
+#include <errno.h>
+#ifndef __rtems__
+#include <kvm.h>
+#endif
+#include <nlist.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "memstat.h"
+#include "memstat_internal.h"
+
+static struct nlist namelist[] = {
+#define X_UMA_KEGS 0
+ { .n_name = "_uma_kegs" },
+#define X_MP_MAXID 1
+ { .n_name = "_mp_maxid" },
+#define X_ALL_CPUS 2
+ { .n_name = "_all_cpus" },
+ { .n_name = "" },
+};
+
+/*
+ * Extract uma(9) statistics from the running kernel, and store all memory
+ * type information in the passed list. For each type, check the list for an
+ * existing entry with the right name/allocator -- if present, update that
+ * entry. Otherwise, add a new entry. On error, the entire list will be
+ * cleared, as entries will be in an inconsistent state.
+ *
+ * To reduce the level of work for a list that starts empty, we keep around a
+ * hint as to whether it was empty when we began, so we can avoid searching
+ * the list for entries to update. Updates are O(n^2) due to searching for
+ * each entry before adding it.
+ */
+int
+memstat_sysctl_uma(struct memory_type_list *list, int flags)
+{
+ struct uma_stream_header *ushp;
+ struct uma_type_header *uthp;
+ struct uma_percpu_stat *upsp;
+ struct memory_type *mtp;
+ int count, hint_dontsearch, i, j, maxcpus;
+ char *buffer, *p;
+ size_t size;
+
+ hint_dontsearch = LIST_EMPTY(&list->mtl_list);
+
+ /*
+ * Query the number of CPUs, number of malloc types so that we can
+ * guess an initial buffer size. We loop until we succeed or really
+ * fail. Note that the value of maxcpus we query using sysctl is not
+ * the version we use when processing the real data -- that is read
+ * from the header.
+ */
+retry:
+ size = sizeof(maxcpus);
+ if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) {
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
+ return (-1);
+ }
+ if (size != sizeof(maxcpus)) {
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
+ return (-1);
+ }
+
+ if (maxcpus > MEMSTAT_MAXCPU) {
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
+ return (-1);
+ }
+
+ size = sizeof(count);
+ if (sysctlbyname("vm.zone_count", &count, &size, NULL, 0) < 0) {
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ return (-1);
+ }
+ if (size != sizeof(count)) {
+ list->mtl_error = MEMSTAT_ERROR_DATAERROR;
+ return (-1);
+ }
+
+ size = sizeof(*uthp) + count * (sizeof(*uthp) + sizeof(*upsp) *
+ maxcpus);
+
+ buffer = malloc(size);
+ if (buffer == NULL) {
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+
+ if (sysctlbyname("vm.zone_stats", buffer, &size, NULL, 0) < 0) {
+ /*
+ * XXXRW: ENOMEM is an ambiguous return, we should bound the
+ * number of loops, perhaps.
+ */
+ if (errno == ENOMEM) {
+ free(buffer);
+ goto retry;
+ }
+ if (errno == EACCES || errno == EPERM)
+ list->mtl_error = MEMSTAT_ERROR_PERMISSION;
+ else
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ free(buffer);
+ return (-1);
+ }
+
+ if (size == 0) {
+ free(buffer);
+ return (0);
+ }
+
+ if (size < sizeof(*ushp)) {
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ free(buffer);
+ return (-1);
+ }
+ p = buffer;
+ ushp = (struct uma_stream_header *)p;
+ p += sizeof(*ushp);
+
+ if (ushp->ush_version != UMA_STREAM_VERSION) {
+ list->mtl_error = MEMSTAT_ERROR_VERSION;
+ free(buffer);
+ return (-1);
+ }
+
+ if (ushp->ush_maxcpus > MEMSTAT_MAXCPU) {
+ list->mtl_error = MEMSTAT_ERROR_TOOMANYCPUS;
+ free(buffer);
+ return (-1);
+ }
+
+ /*
+ * For the remainder of this function, we are quite trusting about
+ * the layout of structures and sizes, since we've determined we have
+ * a matching version and acceptable CPU count.
+ */
+ maxcpus = ushp->ush_maxcpus;
+ count = ushp->ush_count;
+ for (i = 0; i < count; i++) {
+ uthp = (struct uma_type_header *)p;
+ p += sizeof(*uthp);
+
+ if (hint_dontsearch == 0) {
+ mtp = memstat_mtl_find(list, ALLOCATOR_UMA,
+ uthp->uth_name);
+ } else
+ mtp = NULL;
+ if (mtp == NULL)
+ mtp = _memstat_mt_allocate(list, ALLOCATOR_UMA,
+ uthp->uth_name);
+ if (mtp == NULL) {
+ _memstat_mtl_empty(list);
+ free(buffer);
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+
+ /*
+ * Reset the statistics on a current node.
+ */
+ _memstat_mt_reset_stats(mtp);
+
+ mtp->mt_numallocs = uthp->uth_allocs;
+ mtp->mt_numfrees = uthp->uth_frees;
+ mtp->mt_failures = uthp->uth_fails;
+
+ for (j = 0; j < maxcpus; j++) {
+ upsp = (struct uma_percpu_stat *)p;
+ p += sizeof(*upsp);
+
+ mtp->mt_percpu_cache[j].mtp_free =
+ upsp->ups_cache_free;
+ mtp->mt_free += upsp->ups_cache_free;
+ mtp->mt_numallocs += upsp->ups_allocs;
+ mtp->mt_numfrees += upsp->ups_frees;
+ }
+
+ mtp->mt_size = uthp->uth_size;
+ mtp->mt_memalloced = mtp->mt_numallocs * uthp->uth_size;
+ mtp->mt_memfreed = mtp->mt_numfrees * uthp->uth_size;
+ mtp->mt_bytes = mtp->mt_memalloced - mtp->mt_memfreed;
+ mtp->mt_countlimit = uthp->uth_limit;
+ mtp->mt_byteslimit = uthp->uth_limit * uthp->uth_size;
+
+ mtp->mt_count = mtp->mt_numallocs - mtp->mt_numfrees;
+ mtp->mt_zonefree = uthp->uth_zone_free;
+
+ /*
+ * UMA secondary zones share a keg with the primary zone. To
+ * avoid double-reporting of free items, report keg free
+ * items only in the primary zone.
+ */
+ if (!(uthp->uth_zone_flags & UTH_ZONE_SECONDARY)) {
+ mtp->mt_kegfree = uthp->uth_keg_free;
+ mtp->mt_free += mtp->mt_kegfree;
+ }
+ mtp->mt_free += mtp->mt_zonefree;
+ }
+
+ free(buffer);
+
+ return (0);
+}
+
+#ifndef __rtems__
+static int
+kread(kvm_t *kvm, void *kvm_pointer, void *address, size_t size,
+ size_t offset)
+{
+ ssize_t ret;
+
+ ret = kvm_read(kvm, (unsigned long)kvm_pointer + offset, address,
+ size);
+ if (ret < 0)
+ return (MEMSTAT_ERROR_KVM);
+ if ((size_t)ret != size)
+ return (MEMSTAT_ERROR_KVM_SHORTREAD);
+ return (0);
+}
+
+static int
+kread_string(kvm_t *kvm, void *kvm_pointer, char *buffer, int buflen)
+{
+ ssize_t ret;
+ int i;
+
+ for (i = 0; i < buflen; i++) {
+ ret = kvm_read(kvm, (unsigned long)kvm_pointer + i,
+ &(buffer[i]), sizeof(char));
+ if (ret < 0)
+ return (MEMSTAT_ERROR_KVM);
+ if ((size_t)ret != sizeof(char))
+ return (MEMSTAT_ERROR_KVM_SHORTREAD);
+ if (buffer[i] == '\0')
+ return (0);
+ }
+ /* Truncate. */
+ buffer[i-1] = '\0';
+ return (0);
+}
+
+static int
+kread_symbol(kvm_t *kvm, int index, void *address, size_t size,
+ size_t offset)
+{
+ ssize_t ret;
+
+ ret = kvm_read(kvm, namelist[index].n_value + offset, address, size);
+ if (ret < 0)
+ return (MEMSTAT_ERROR_KVM);
+ if ((size_t)ret != size)
+ return (MEMSTAT_ERROR_KVM_SHORTREAD);
+ return (0);
+}
+
+/*
+ * memstat_kvm_uma() is similar to memstat_sysctl_uma(), only it extracts
+ * UMA(9) statistics from a kernel core/memory file.
+ */
+int
+memstat_kvm_uma(struct memory_type_list *list, void *kvm_handle)
+{
+ LIST_HEAD(, uma_keg) uma_kegs;
+ struct memory_type *mtp;
+ struct uma_bucket *ubp, ub;
+ struct uma_cache *ucp, *ucp_array;
+ struct uma_zone *uzp, uz;
+ struct uma_keg *kzp, kz;
+ int hint_dontsearch, i, mp_maxid, ret;
+ char name[MEMTYPE_MAXNAME];
+ __cpumask_t all_cpus;
+ kvm_t *kvm;
+
+ kvm = (kvm_t *)kvm_handle;
+ hint_dontsearch = LIST_EMPTY(&list->mtl_list);
+ if (kvm_nlist(kvm, namelist) != 0) {
+ list->mtl_error = MEMSTAT_ERROR_KVM;
+ return (-1);
+ }
+ if (namelist[X_UMA_KEGS].n_type == 0 ||
+ namelist[X_UMA_KEGS].n_value == 0) {
+ list->mtl_error = MEMSTAT_ERROR_KVM_NOSYMBOL;
+ return (-1);
+ }
+ ret = kread_symbol(kvm, X_MP_MAXID, &mp_maxid, sizeof(mp_maxid), 0);
+ if (ret != 0) {
+ list->mtl_error = ret;
+ return (-1);
+ }
+ ret = kread_symbol(kvm, X_UMA_KEGS, &uma_kegs, sizeof(uma_kegs), 0);
+ if (ret != 0) {
+ list->mtl_error = ret;
+ return (-1);
+ }
+ ret = kread_symbol(kvm, X_ALL_CPUS, &all_cpus, sizeof(all_cpus), 0);
+ if (ret != 0) {
+ list->mtl_error = ret;
+ return (-1);
+ }
+ ucp_array = malloc(sizeof(struct uma_cache) * (mp_maxid + 1));
+ if (ucp_array == NULL) {
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+ for (kzp = LIST_FIRST(&uma_kegs); kzp != NULL; kzp =
+ LIST_NEXT(&kz, uk_link)) {
+ ret = kread(kvm, kzp, &kz, sizeof(kz), 0);
+ if (ret != 0) {
+ free(ucp_array);
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+ for (uzp = LIST_FIRST(&kz.uk_zones); uzp != NULL; uzp =
+ LIST_NEXT(&uz, uz_link)) {
+ ret = kread(kvm, uzp, &uz, sizeof(uz), 0);
+ if (ret != 0) {
+ free(ucp_array);
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+ ret = kread(kvm, uzp, ucp_array,
+ sizeof(struct uma_cache) * (mp_maxid + 1),
+ offsetof(struct uma_zone, uz_cpu[0]));
+ if (ret != 0) {
+ free(ucp_array);
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+ ret = kread_string(kvm, uz.uz_name, name,
+ MEMTYPE_MAXNAME);
+ if (ret != 0) {
+ free(ucp_array);
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+ if (hint_dontsearch == 0) {
+ mtp = memstat_mtl_find(list, ALLOCATOR_UMA,
+ name);
+ } else
+ mtp = NULL;
+ if (mtp == NULL)
+ mtp = _memstat_mt_allocate(list, ALLOCATOR_UMA,
+ name);
+ if (mtp == NULL) {
+ free(ucp_array);
+ _memstat_mtl_empty(list);
+ list->mtl_error = MEMSTAT_ERROR_NOMEMORY;
+ return (-1);
+ }
+ /*
+ * Reset the statistics on a current node.
+ */
+ _memstat_mt_reset_stats(mtp);
+ mtp->mt_numallocs = uz.uz_allocs;
+ mtp->mt_numfrees = uz.uz_frees;
+ mtp->mt_failures = uz.uz_fails;
+ if (kz.uk_flags & UMA_ZFLAG_INTERNAL)
+ goto skip_percpu;
+ for (i = 0; i < mp_maxid + 1; i++) {
+ if ((all_cpus & (1 << i)) == 0)
+ continue;
+ ucp = &ucp_array[i];
+ mtp->mt_numallocs += ucp->uc_allocs;
+ mtp->mt_numfrees += ucp->uc_frees;
+
+ if (ucp->uc_allocbucket != NULL) {
+ ret = kread(kvm, ucp->uc_allocbucket,
+ &ub, sizeof(ub), 0);
+ if (ret != 0) {
+ free(ucp_array);
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+ mtp->mt_free += ub.ub_cnt;
+ }
+ if (ucp->uc_freebucket != NULL) {
+ ret = kread(kvm, ucp->uc_freebucket,
+ &ub, sizeof(ub), 0);
+ if (ret != 0) {
+ free(ucp_array);
+ _memstat_mtl_empty(list);
+ list->mtl_error = ret;
+ return (-1);
+ }
+ mtp->mt_free += ub.ub_cnt;
+ }
+ }
+skip_percpu:
+ mtp->mt_size = kz.uk_size;
+ mtp->mt_memalloced = mtp->mt_numallocs * mtp->mt_size;
+ mtp->mt_memfreed = mtp->mt_numfrees * mtp->mt_size;
+ mtp->mt_bytes = mtp->mt_memalloced - mtp->mt_memfreed;
+ if (kz.uk_ppera > 1)
+ mtp->mt_countlimit = kz.uk_maxpages /
+ kz.uk_ipers;
+ else
+ mtp->mt_countlimit = kz.uk_maxpages *
+ kz.uk_ipers;
+ mtp->mt_byteslimit = mtp->mt_countlimit * mtp->mt_size;
+ mtp->mt_count = mtp->mt_numallocs - mtp->mt_numfrees;
+ for (ubp = LIST_FIRST(&uz.uz_full_bucket); ubp !=
+ NULL; ubp = LIST_NEXT(&ub, ub_link)) {
+ ret = kread(kvm, ubp, &ub, sizeof(ub), 0);
+ mtp->mt_zonefree += ub.ub_cnt;
+ }
+ if (!((kz.uk_flags & UMA_ZONE_SECONDARY) &&
+ LIST_FIRST(&kz.uk_zones) != uzp)) {
+ mtp->mt_kegfree = kz.uk_free;
+ mtp->mt_free += mtp->mt_kegfree;
+ }
+ mtp->mt_free += mtp->mt_zonefree;
+ }
+ }
+ free(ucp_array);
+ return (0);
+}
+#endif
diff --git a/freebsd/lib/libutil/expand_number.c b/freebsd/lib/libutil/expand_number.c
new file mode 100644
index 00000000..4c8d6f5b
--- /dev/null
+++ b/freebsd/lib/libutil/expand_number.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2007 Eric Anderson <anderson@FreeBSD.org>
+ * Copyright (c) 2007 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <libutil.h>
+#include <stdint.h>
+
+/*
+ * Convert an expression of the following forms to a int64_t.
+ * 1) A positive decimal number.
+ * 2) A positive decimal number followed by a 'b' or 'B' (mult by 1).
+ * 3) A positive decimal number followed by a 'k' or 'K' (mult by 1 << 10).
+ * 4) A positive decimal number followed by a 'm' or 'M' (mult by 1 << 20).
+ * 5) A positive decimal number followed by a 'g' or 'G' (mult by 1 << 30).
+ * 6) A positive decimal number followed by a 't' or 'T' (mult by 1 << 40).
+ * 7) A positive decimal number followed by a 'p' or 'P' (mult by 1 << 50).
+ * 8) A positive decimal number followed by a 'e' or 'E' (mult by 1 << 60).
+ */
+int
+expand_number(const char *buf, int64_t *num)
+{
+ static const char unit[] = "bkmgtpe";
+ char *endptr, s;
+ int64_t number;
+ int i;
+
+ number = strtoimax(buf, &endptr, 0);
+
+ if (endptr == buf) {
+ /* No valid digits. */
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (*endptr == '\0') {
+ /* No unit. */
+ *num = number;
+ return (0);
+ }
+
+ s = tolower(*endptr);
+ switch (s) {
+ case 'b':
+ case 'k':
+ case 'm':
+ case 'g':
+ case 't':
+ case 'p':
+ case 'e':
+ break;
+ default:
+ /* Unrecognized unit. */
+ errno = EINVAL;
+ return (-1);
+ }
+
+ for (i = 0; unit[i] != '\0'; i++) {
+ if (s == unit[i])
+ break;
+ if ((number < 0 && (number << 10) > number) ||
+ (number >= 0 && (number << 10) < number)) {
+ errno = ERANGE;
+ return (-1);
+ }
+ number <<= 10;
+ }
+
+ *num = number;
+ return (0);
+}
diff --git a/freebsd/lib/libutil/humanize_number.c b/freebsd/lib/libutil/humanize_number.c
new file mode 100644
index 00000000..de985870
--- /dev/null
+++ b/freebsd/lib/libutil/humanize_number.c
@@ -0,0 +1,146 @@
+/* $NetBSD: humanize_number.c,v 1.14 2008/04/28 20:22:59 martin Exp $ */
+
+/*
+ * Copyright (c) 1997, 1998, 1999, 2002 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center, by Luke Mewburn and by Tomas Svensson.
+ *
+ * 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <libutil.h>
+
+int
+humanize_number(char *buf, size_t len, int64_t bytes,
+ const char *suffix, int scale, int flags)
+{
+ const char *prefixes, *sep;
+ int b, i, r, maxscale, s1, s2, sign;
+ int64_t divisor, max;
+ size_t baselen;
+
+ assert(buf != NULL);
+ assert(suffix != NULL);
+ assert(scale >= 0);
+
+ if (flags & HN_DIVISOR_1000) {
+ /* SI for decimal multiplies */
+ divisor = 1000;
+ if (flags & HN_B)
+ prefixes = "B\0k\0M\0G\0T\0P\0E";
+ else
+ prefixes = "\0\0k\0M\0G\0T\0P\0E";
+ } else {
+ /*
+ * binary multiplies
+ * XXX IEC 60027-2 recommends Ki, Mi, Gi...
+ */
+ divisor = 1024;
+ if (flags & HN_B)
+ prefixes = "B\0K\0M\0G\0T\0P\0E";
+ else
+ prefixes = "\0\0K\0M\0G\0T\0P\0E";
+ }
+
+#define SCALE2PREFIX(scale) (&prefixes[(scale) << 1])
+ maxscale = 7;
+
+ if (scale >= maxscale &&
+ (scale & (HN_AUTOSCALE | HN_GETSCALE)) == 0)
+ return (-1);
+
+ if (buf == NULL || suffix == NULL)
+ return (-1);
+
+ if (len > 0)
+ buf[0] = '\0';
+ if (bytes < 0) {
+ sign = -1;
+ bytes *= -100;
+ baselen = 3; /* sign, digit, prefix */
+ } else {
+ sign = 1;
+ bytes *= 100;
+ baselen = 2; /* digit, prefix */
+ }
+ if (flags & HN_NOSPACE)
+ sep = "";
+ else {
+ sep = " ";
+ baselen++;
+ }
+ baselen += strlen(suffix);
+
+ /* Check if enough room for `x y' + suffix + `\0' */
+ if (len < baselen + 1)
+ return (-1);
+
+ if (scale & (HN_AUTOSCALE | HN_GETSCALE)) {
+ /* See if there is additional columns can be used. */
+ for (max = 100, i = len - baselen; i-- > 0;)
+ max *= 10;
+
+ /*
+ * Divide the number until it fits the given column.
+ * If there will be an overflow by the rounding below,
+ * divide once more.
+ */
+ for (i = 0; bytes >= max - 50 && i < maxscale; i++)
+ bytes /= divisor;
+
+ if (scale & HN_GETSCALE)
+ return (i);
+ } else
+ for (i = 0; i < scale && i < maxscale; i++)
+ bytes /= divisor;
+
+ /* If a value <= 9.9 after rounding and ... */
+ if (bytes < 995 && i > 0 && flags & HN_DECIMAL) {
+ /* baselen + \0 + .N */
+ if (len < baselen + 1 + 2)
+ return (-1);
+ b = ((int)bytes + 5) / 10;
+ s1 = b / 10;
+ s2 = b % 10;
+ r = snprintf(buf, len, "%d%s%d%s%s%s",
+ sign * s1, localeconv()->decimal_point, s2,
+ sep, SCALE2PREFIX(i), suffix);
+ } else
+ r = snprintf(buf, len, "%" PRId64 "%s%s%s",
+ sign * ((bytes + 50) / 100),
+ sep, SCALE2PREFIX(i), suffix);
+
+ return (r);
+}
diff --git a/freebsd/lib/libutil/libutil.h b/freebsd/lib/libutil/libutil.h
new file mode 100644
index 00000000..3187fb37
--- /dev/null
+++ b/freebsd/lib/libutil/libutil.h
@@ -0,0 +1,188 @@
+/*
+ * Copyright (c) 1996 Peter Wemm <peter@FreeBSD.org>.
+ * All rights reserved.
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * ThinkSec AS and NAI Labs, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, is 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 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 _LIBUTIL_H_
+#define _LIBUTIL_H_
+
+#define PROPERTY_MAX_NAME 64
+#define PROPERTY_MAX_VALUE 512
+
+/* for properties.c */
+typedef struct _property {
+ struct _property *next;
+ char *name;
+ char *value;
+} *properties;
+
+#ifdef _SYS_PARAM_H_
+/* for pidfile.c */
+struct pidfh {
+ int pf_fd;
+ char pf_path[MAXPATHLEN + 1];
+ __dev_t pf_dev;
+ ino_t pf_ino;
+};
+#endif
+
+/* Avoid pulling in all the include files for no need */
+struct termios;
+struct winsize;
+struct utmp;
+struct in_addr;
+struct kinfo_file;
+struct kinfo_vmentry;
+
+__BEGIN_DECLS
+void clean_environment(const char * const *_white,
+ const char * const *_more_white);
+int extattr_namespace_to_string(int _attrnamespace, char **_string);
+int extattr_string_to_namespace(const char *_string, int *_attrnamespace);
+int flopen(const char *_path, int _flags, ...);
+void hexdump(const void *ptr, int length, const char *hdr, int flags);
+void login(struct utmp *_ut);
+int login_tty(int _fd);
+int logout(const char *_line);
+void logwtmp(const char *_line, const char *_name, const char *_host);
+void trimdomain(char *_fullhost, int _hostsize);
+int openpty(int *_amaster, int *_aslave, char *_name,
+ struct termios *_termp, struct winsize *_winp);
+int forkpty(int *_amaster, char *_name,
+ struct termios *_termp, struct winsize *_winp);
+int humanize_number(char *_buf, size_t _len, int64_t _number,
+ const char *_suffix, int _scale, int _flags);
+int expand_number(const char *_buf, int64_t *_num);
+const char *uu_lockerr(int _uu_lockresult);
+int uu_lock(const char *_ttyname);
+int uu_unlock(const char *_ttyname);
+int uu_lock_txfr(const char *_ttyname, pid_t _pid);
+int _secure_path(const char *_path, uid_t _uid, gid_t _gid);
+properties properties_read(int fd);
+void properties_free(properties list);
+char *property_find(properties list, const char *name);
+char *auth_getval(const char *name);
+int realhostname(char *host, size_t hsize, const struct in_addr *ip);
+struct sockaddr;
+int realhostname_sa(char *host, size_t hsize, struct sockaddr *addr,
+ int addrlen);
+
+int kld_isloaded(const char *name);
+int kld_load(const char *name);
+struct kinfo_file *
+ kinfo_getfile(pid_t _pid, int *_cntp);
+struct kinfo_vmentry *
+ kinfo_getvmmap(pid_t _pid, int *_cntp);
+
+#ifdef _STDIO_H_ /* avoid adding new includes */
+char *fparseln(FILE *, size_t *, size_t *, const char[3], int);
+#endif
+
+#ifdef _PWD_H_
+int pw_copy(int _ffd, int _tfd, const struct passwd *_pw, struct passwd *_old_pw);
+struct passwd *pw_dup(const struct passwd *_pw);
+int pw_edit(int _notsetuid);
+int pw_equal(const struct passwd *_pw1, const struct passwd *_pw2);
+void pw_fini(void);
+int pw_init(const char *_dir, const char *_master);
+char *pw_make(const struct passwd *_pw);
+int pw_mkdb(const char *_user);
+int pw_lock(void);
+struct passwd *pw_scan(const char *_line, int _flags);
+const char *pw_tempname(void);
+int pw_tmp(int _mfd);
+#endif
+
+#ifdef _GRP_H_
+int gr_equal(const struct group *gr1, const struct group *gr2);
+char *gr_make(const struct group *gr);
+struct group *gr_dup(const struct group *gr);
+struct group *gr_scan(const char *line);
+#endif
+
+#ifdef _SYS_PARAM_H_
+struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
+int pidfile_write(struct pidfh *pfh);
+int pidfile_close(struct pidfh *pfh);
+int pidfile_remove(struct pidfh *pfh);
+#endif
+
+__END_DECLS
+
+#define UU_LOCK_INUSE (1)
+#define UU_LOCK_OK (0)
+#define UU_LOCK_OPEN_ERR (-1)
+#define UU_LOCK_READ_ERR (-2)
+#define UU_LOCK_CREAT_ERR (-3)
+#define UU_LOCK_WRITE_ERR (-4)
+#define UU_LOCK_LINK_ERR (-5)
+#define UU_LOCK_TRY_ERR (-6)
+#define UU_LOCK_OWNER_ERR (-7)
+
+/* return values from realhostname() */
+#define HOSTNAME_FOUND (0)
+#define HOSTNAME_INCORRECTNAME (1)
+#define HOSTNAME_INVALIDADDR (2)
+#define HOSTNAME_INVALIDNAME (3)
+
+/* fparseln(3) */
+#define FPARSELN_UNESCESC 0x01
+#define FPARSELN_UNESCCONT 0x02
+#define FPARSELN_UNESCCOMM 0x04
+#define FPARSELN_UNESCREST 0x08
+#define FPARSELN_UNESCALL 0x0f
+
+/* pw_scan() */
+#define PWSCAN_MASTER 0x01
+#define PWSCAN_WARN 0x02
+
+/* humanize_number(3) */
+#define HN_DECIMAL 0x01
+#define HN_NOSPACE 0x02
+#define HN_B 0x04
+#define HN_DIVISOR_1000 0x08
+
+#define HN_GETSCALE 0x10
+#define HN_AUTOSCALE 0x20
+
+/* hexdump(3) */
+#define HD_COLUMN_MASK 0xff
+#define HD_DELIM_MASK 0xff00
+#define HD_OMIT_COUNT (1 << 16)
+#define HD_OMIT_HEX (1 << 17)
+#define HD_OMIT_CHARS (1 << 18)
+
+#endif /* !_LIBUTIL_H_ */
diff --git a/freebsd/lib/libutil/trimdomain.c b/freebsd/lib/libutil/trimdomain.c
new file mode 100644
index 00000000..7ca6ab69
--- /dev/null
+++ b/freebsd/lib/libutil/trimdomain.c
@@ -0,0 +1,118 @@
+#ifdef __rtems__
+#include "port_before.h"
+#endif
+/*-
+ * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org>
+ * Based on original work by Atsushi Murai <amurai@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.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <libutil.h>
+#include <string.h>
+#include <unistd.h>
+
+static int isDISP(const char *);
+
+/*-
+ * Trim the current domain name from fullhost, but only if the result
+ * is less than or equal to hostsize in length.
+ *
+ * This function understands $DISPLAY type fullhosts.
+ *
+ * For example:
+ *
+ * trimdomain("abcde.my.domain", 5) -> "abcde"
+ * trimdomain("abcde.my.domain", 4) -> "abcde.my.domain"
+ * trimdomain("abcde.my.domain:0.0", 9) -> "abcde:0.0"
+ * trimdomain("abcde.my.domain:0.0", 8) -> "abcde.my.domain:0.0"
+ */
+void
+trimdomain(char *fullhost, int hostsize)
+{
+ static size_t dlen;
+ static int first = 1;
+ static char domain[MAXHOSTNAMELEN];
+ char *end, *s;
+ size_t len;
+
+ if (first) {
+ /* XXX: Should we assume that our domain is this persistent ? */
+ first = 0;
+ if (gethostname(domain, sizeof(domain) - 1) == 0 &&
+ (s = strchr(domain, '.')) != NULL)
+ memmove(domain, s + 1, strlen(s + 1) + 1);
+ else
+ domain[0] = '\0';
+ dlen = strlen(domain);
+ }
+
+ if (domain[0] == '\0')
+ return;
+
+ s = fullhost;
+ end = s + hostsize + 1;
+ if ((s = memchr(s, '.', (size_t)(end - s))) != NULL) {
+ if (strncasecmp(s + 1, domain, dlen) == 0) {
+ if (s[dlen + 1] == '\0') {
+ /* Found -- lose the domain. */
+ *s = '\0';
+ } else if (s[dlen + 1] == ':' &&
+ isDISP(s + dlen + 2) &&
+ (len = strlen(s + dlen + 1)) < (size_t)(end - s)) {
+ /* Found -- shuffle the DISPLAY back. */
+ memmove(s, s + dlen + 1, len + 1);
+ }
+ }
+ }
+}
+
+/*
+ * Is the given string NN or NN.NN where ``NN'' is an all-numeric string ?
+ */
+static int
+isDISP(const char *disp)
+{
+ size_t w;
+ int res;
+
+ w = strspn(disp, "0123456789");
+ res = 0;
+ if (w > 0) {
+ if (disp[w] == '\0')
+ res = 1; /* NN */
+ else if (disp[w] == '.') {
+ disp += w + 1;
+ w = strspn(disp, "0123456789");
+ if (w > 0 && disp[w] == '\0')
+ res = 1; /* NN.NN */
+ }
+ }
+ return (res);
+}
diff --git a/freebsd/local/bus_if.c b/freebsd/local/bus_if.c
deleted file mode 100644
index 10f9ef46..00000000
--- a/freebsd/local/bus_if.c
+++ /dev/null
@@ -1,273 +0,0 @@
-#include <freebsd/machine/rtems-bsd-config.h>
-
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * kern/bus_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-#include <freebsd/sys/param.h>
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/kernel.h>
-#include <freebsd/sys/kobj.h>
-#include <freebsd/sys/types.h>
-#include <freebsd/sys/systm.h>
-#include <freebsd/sys/bus.h>
-#include <freebsd/local/bus_if.h>
-
-
-static struct resource *
-null_alloc_resource(device_t dev, device_t child,
- int type, int *rid, u_long start, u_long end,
- u_long count, u_int flags)
-{
- return (0);
-}
-
-static int
-null_remap_intr(device_t bus, device_t dev, u_int irq)
-{
-
- if (dev != NULL)
- return (BUS_REMAP_INTR(dev, NULL, irq));
- return (ENXIO);
-}
-
-static device_t
-null_add_child(device_t bus, int order, const char *name,
- int unit)
-{
-
- panic("bus_add_child is not implemented");
-}
-
-struct kobj_method bus_print_child_method_default = {
- &bus_print_child_desc, (kobjop_t) bus_generic_print_child
-};
-
-struct kobjop_desc bus_print_child_desc = {
- 0, &bus_print_child_method_default
-};
-
-struct kobj_method bus_probe_nomatch_method_default = {
- &bus_probe_nomatch_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_probe_nomatch_desc = {
- 0, &bus_probe_nomatch_method_default
-};
-
-struct kobj_method bus_read_ivar_method_default = {
- &bus_read_ivar_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_read_ivar_desc = {
- 0, &bus_read_ivar_method_default
-};
-
-struct kobj_method bus_write_ivar_method_default = {
- &bus_write_ivar_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_write_ivar_desc = {
- 0, &bus_write_ivar_method_default
-};
-
-struct kobj_method bus_child_detached_method_default = {
- &bus_child_detached_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_child_detached_desc = {
- 0, &bus_child_detached_method_default
-};
-
-struct kobj_method bus_driver_added_method_default = {
- &bus_driver_added_desc, (kobjop_t) bus_generic_driver_added
-};
-
-struct kobjop_desc bus_driver_added_desc = {
- 0, &bus_driver_added_method_default
-};
-
-struct kobj_method bus_add_child_method_default = {
- &bus_add_child_desc, (kobjop_t) null_add_child
-};
-
-struct kobjop_desc bus_add_child_desc = {
- 0, &bus_add_child_method_default
-};
-
-struct kobj_method bus_alloc_resource_method_default = {
- &bus_alloc_resource_desc, (kobjop_t) null_alloc_resource
-};
-
-struct kobjop_desc bus_alloc_resource_desc = {
- 0, &bus_alloc_resource_method_default
-};
-
-struct kobj_method bus_activate_resource_method_default = {
- &bus_activate_resource_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_activate_resource_desc = {
- 0, &bus_activate_resource_method_default
-};
-
-struct kobj_method bus_deactivate_resource_method_default = {
- &bus_deactivate_resource_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_deactivate_resource_desc = {
- 0, &bus_deactivate_resource_method_default
-};
-
-struct kobj_method bus_release_resource_method_default = {
- &bus_release_resource_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_release_resource_desc = {
- 0, &bus_release_resource_method_default
-};
-
-struct kobj_method bus_setup_intr_method_default = {
- &bus_setup_intr_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_setup_intr_desc = {
- 0, &bus_setup_intr_method_default
-};
-
-struct kobj_method bus_teardown_intr_method_default = {
- &bus_teardown_intr_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_teardown_intr_desc = {
- 0, &bus_teardown_intr_method_default
-};
-
-struct kobj_method bus_set_resource_method_default = {
- &bus_set_resource_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_set_resource_desc = {
- 0, &bus_set_resource_method_default
-};
-
-struct kobj_method bus_get_resource_method_default = {
- &bus_get_resource_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_get_resource_desc = {
- 0, &bus_get_resource_method_default
-};
-
-struct kobj_method bus_delete_resource_method_default = {
- &bus_delete_resource_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_delete_resource_desc = {
- 0, &bus_delete_resource_method_default
-};
-
-struct kobj_method bus_get_resource_list_method_default = {
- &bus_get_resource_list_desc, (kobjop_t) bus_generic_get_resource_list
-};
-
-struct kobjop_desc bus_get_resource_list_desc = {
- 0, &bus_get_resource_list_method_default
-};
-
-struct kobj_method bus_child_present_method_default = {
- &bus_child_present_desc, (kobjop_t) bus_generic_child_present
-};
-
-struct kobjop_desc bus_child_present_desc = {
- 0, &bus_child_present_method_default
-};
-
-struct kobj_method bus_child_pnpinfo_str_method_default = {
- &bus_child_pnpinfo_str_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_child_pnpinfo_str_desc = {
- 0, &bus_child_pnpinfo_str_method_default
-};
-
-struct kobj_method bus_child_location_str_method_default = {
- &bus_child_location_str_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_child_location_str_desc = {
- 0, &bus_child_location_str_method_default
-};
-
-struct kobj_method bus_bind_intr_method_default = {
- &bus_bind_intr_desc, (kobjop_t) bus_generic_bind_intr
-};
-
-struct kobjop_desc bus_bind_intr_desc = {
- 0, &bus_bind_intr_method_default
-};
-
-struct kobj_method bus_config_intr_method_default = {
- &bus_config_intr_desc, (kobjop_t) bus_generic_config_intr
-};
-
-struct kobjop_desc bus_config_intr_desc = {
- 0, &bus_config_intr_method_default
-};
-
-struct kobj_method bus_describe_intr_method_default = {
- &bus_describe_intr_desc, (kobjop_t) bus_generic_describe_intr
-};
-
-struct kobjop_desc bus_describe_intr_desc = {
- 0, &bus_describe_intr_method_default
-};
-
-struct kobj_method bus_hinted_child_method_default = {
- &bus_hinted_child_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_hinted_child_desc = {
- 0, &bus_hinted_child_method_default
-};
-
-struct kobj_method bus_get_dma_tag_method_default = {
- &bus_get_dma_tag_desc, (kobjop_t) bus_generic_get_dma_tag
-};
-
-struct kobjop_desc bus_get_dma_tag_desc = {
- 0, &bus_get_dma_tag_method_default
-};
-
-struct kobj_method bus_hint_device_unit_method_default = {
- &bus_hint_device_unit_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc bus_hint_device_unit_desc = {
- 0, &bus_hint_device_unit_method_default
-};
-
-struct kobj_method bus_new_pass_method_default = {
- &bus_new_pass_desc, (kobjop_t) bus_generic_new_pass
-};
-
-struct kobjop_desc bus_new_pass_desc = {
- 0, &bus_new_pass_method_default
-};
-
-struct kobj_method bus_remap_intr_method_default = {
- &bus_remap_intr_desc, (kobjop_t) null_remap_intr
-};
-
-struct kobjop_desc bus_remap_intr_desc = {
- 0, &bus_remap_intr_method_default
-};
-
diff --git a/freebsd/local/bus_if.h b/freebsd/local/bus_if.h
deleted file mode 100644
index 6a54d605..00000000
--- a/freebsd/local/bus_if.h
+++ /dev/null
@@ -1,786 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * kern/bus_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-/**
- * @defgroup BUS bus - KObj methods for drivers of devices with children
- * @brief A set of methods required device drivers that support
- * child devices.
- * @{
- */
-
-#ifndef _bus_if_h_
-#define _bus_if_h_
-
-/** @brief Unique descriptor for the BUS_PRINT_CHILD() method */
-extern struct kobjop_desc bus_print_child_desc;
-/** @brief A function implementing the BUS_PRINT_CHILD() method */
-typedef int bus_print_child_t(device_t _dev, device_t _child);
-/**
- * @brief Print a description of a child device
- *
- * This is called from system code which prints out a description of a
- * device. It should describe the attachment that the child has with
- * the parent. For instance the TurboLaser bus prints which node the
- * device is attached to. See bus_generic_print_child() for more
- * information.
- *
- * @param _dev the device whose child is being printed
- * @param _child the child device to describe
- *
- * @returns the number of characters output.
- */
-
-static __inline int BUS_PRINT_CHILD(device_t _dev, device_t _child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_print_child);
- return ((bus_print_child_t *) _m)(_dev, _child);
-}
-
-/** @brief Unique descriptor for the BUS_PROBE_NOMATCH() method */
-extern struct kobjop_desc bus_probe_nomatch_desc;
-/** @brief A function implementing the BUS_PROBE_NOMATCH() method */
-typedef void bus_probe_nomatch_t(device_t _dev, device_t _child);
-/**
- * @brief Print a notification about an unprobed child device.
- *
- * Called for each child device that did not succeed in probing for a
- * driver.
- *
- * @param _dev the device whose child was being probed
- * @param _child the child device which failed to probe
- */
-
-static __inline void BUS_PROBE_NOMATCH(device_t _dev, device_t _child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_probe_nomatch);
- ((bus_probe_nomatch_t *) _m)(_dev, _child);
-}
-
-/** @brief Unique descriptor for the BUS_READ_IVAR() method */
-extern struct kobjop_desc bus_read_ivar_desc;
-/** @brief A function implementing the BUS_READ_IVAR() method */
-typedef int bus_read_ivar_t(device_t _dev, device_t _child, int _index,
- uintptr_t *_result);
-/**
- * @brief Read the value of a bus-specific attribute of a device
- *
- * This method, along with BUS_WRITE_IVAR() manages a bus-specific set
- * of instance variables of a child device. The intention is that
- * each different type of bus defines a set of appropriate instance
- * variables (such as ports and irqs for ISA bus etc.)
- *
- * This information could be given to the child device as a struct but
- * that makes it hard for a bus to add or remove variables without
- * forcing an edit and recompile for all drivers which may not be
- * possible for vendor supplied binary drivers.
- *
- * This method copies the value of an instance variable to the
- * location specified by @p *_result.
- *
- * @param _dev the device whose child was being examined
- * @param _child the child device whose instance variable is
- * being read
- * @param _index the instance variable to read
- * @param _result a loction to recieve the instance variable
- * value
- *
- * @retval 0 success
- * @retval ENOENT no such instance variable is supported by @p
- * _dev
- */
-
-static __inline int BUS_READ_IVAR(device_t _dev, device_t _child, int _index,
- uintptr_t *_result)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_read_ivar);
- return ((bus_read_ivar_t *) _m)(_dev, _child, _index, _result);
-}
-
-/** @brief Unique descriptor for the BUS_WRITE_IVAR() method */
-extern struct kobjop_desc bus_write_ivar_desc;
-/** @brief A function implementing the BUS_WRITE_IVAR() method */
-typedef int bus_write_ivar_t(device_t _dev, device_t _child, int _indx,
- uintptr_t _value);
-/**
- * @brief Write the value of a bus-specific attribute of a device
- *
- * This method sets the value of an instance variable to @p _value.
- *
- * @param _dev the device whose child was being updated
- * @param _child the child device whose instance variable is
- * being written
- * @param _index the instance variable to write
- * @param _value the value to write to that instance variable
- *
- * @retval 0 success
- * @retval ENOENT no such instance variable is supported by @p
- * _dev
- * @retval EINVAL the instance variable was recognised but
- * contains a read-only value
- */
-
-static __inline int BUS_WRITE_IVAR(device_t _dev, device_t _child, int _indx,
- uintptr_t _value)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_write_ivar);
- return ((bus_write_ivar_t *) _m)(_dev, _child, _indx, _value);
-}
-
-/** @brief Unique descriptor for the BUS_CHILD_DETACHED() method */
-extern struct kobjop_desc bus_child_detached_desc;
-/** @brief A function implementing the BUS_CHILD_DETACHED() method */
-typedef void bus_child_detached_t(device_t _dev, device_t _child);
-/**
- * @brief Notify a bus that a child was detached
- *
- * Called after the child's DEVICE_DETACH() method to allow the parent
- * to reclaim any resources allocated on behalf of the child.
- *
- * @param _dev the device whose child changed state
- * @param _child the child device which changed state
- */
-
-static __inline void BUS_CHILD_DETACHED(device_t _dev, device_t _child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_child_detached);
- ((bus_child_detached_t *) _m)(_dev, _child);
-}
-
-/** @brief Unique descriptor for the BUS_DRIVER_ADDED() method */
-extern struct kobjop_desc bus_driver_added_desc;
-/** @brief A function implementing the BUS_DRIVER_ADDED() method */
-typedef void bus_driver_added_t(device_t _dev, driver_t *_driver);
-/**
- * @brief Notify a bus that a new driver was added
- *
- * Called when a new driver is added to the devclass which owns this
- * bus. The generic implementation of this method attempts to probe and
- * attach any un-matched children of the bus.
- *
- * @param _dev the device whose devclass had a new driver
- * added to it
- * @param _driver the new driver which was added
- */
-
-static __inline void BUS_DRIVER_ADDED(device_t _dev, driver_t *_driver)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_driver_added);
- ((bus_driver_added_t *) _m)(_dev, _driver);
-}
-
-/** @brief Unique descriptor for the BUS_ADD_CHILD() method */
-extern struct kobjop_desc bus_add_child_desc;
-/** @brief A function implementing the BUS_ADD_CHILD() method */
-typedef device_t bus_add_child_t(device_t _dev, u_int _order, const char *_name,
- int _unit);
-/**
- * @brief Create a new child device
- *
- * For busses which use use drivers supporting DEVICE_IDENTIFY() to
- * enumerate their devices, this method is used to create new
- * device instances. The new device will be added after the last
- * existing child with the same order.
- *
- * @param _dev the bus device which will be the parent of the
- * new child device
- * @param _order a value which is used to partially sort the
- * children of @p _dev - devices created using
- * lower values of @p _order appear first in @p
- * _dev's list of children
- * @param _name devclass name for new device or @c NULL if not
- * specified
- * @param _unit unit number for new device or @c -1 if not
- * specified
- */
-
-static __inline device_t BUS_ADD_CHILD(device_t _dev, u_int _order,
- const char *_name, int _unit)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_add_child);
- return ((bus_add_child_t *) _m)(_dev, _order, _name, _unit);
-}
-
-/** @brief Unique descriptor for the BUS_ALLOC_RESOURCE() method */
-extern struct kobjop_desc bus_alloc_resource_desc;
-/** @brief A function implementing the BUS_ALLOC_RESOURCE() method */
-typedef struct resource * bus_alloc_resource_t(device_t _dev, device_t _child,
- int _type, int *_rid,
- u_long _start, u_long _end,
- u_long _count, u_int _flags);
-/**
- * @brief Allocate a system resource
- *
- * This method is called by child devices of a bus to allocate resources.
- * The types are defined in <machine/resource.h>; the meaning of the
- * resource-ID field varies from bus to bus (but @p *rid == 0 is always
- * valid if the resource type is). If a resource was allocated and the
- * caller did not use the RF_ACTIVE to specify that it should be
- * activated immediately, the caller is responsible for calling
- * BUS_ACTIVATE_RESOURCE() when it actually uses the resource.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which is requesting an allocation
- * @param _type the type of resource to allocate
- * @param _rid a pointer to the resource identifier
- * @param _start hint at the start of the resource range - pass
- * @c 0UL for any start address
- * @param _end hint at the end of the resource range - pass
- * @c ~0UL for any end address
- * @param _count hint at the size of range required - pass @c 1
- * for any size
- * @param _flags any extra flags to control the resource
- * allocation - see @c RF_XXX flags in
- * <sys/rman.h> for details
- *
- * @returns the resource which was allocated or @c NULL if no
- * resource could be allocated
- */
-
-static __inline struct resource * BUS_ALLOC_RESOURCE(device_t _dev,
- device_t _child, int _type,
- int *_rid, u_long _start,
- u_long _end, u_long _count,
- u_int _flags)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_alloc_resource);
- return ((bus_alloc_resource_t *) _m)(_dev, _child, _type, _rid, _start, _end, _count, _flags);
-}
-
-/** @brief Unique descriptor for the BUS_ACTIVATE_RESOURCE() method */
-extern struct kobjop_desc bus_activate_resource_desc;
-/** @brief A function implementing the BUS_ACTIVATE_RESOURCE() method */
-typedef int bus_activate_resource_t(device_t _dev, device_t _child, int _type,
- int _rid, struct resource *_r);
-/**
- * @brief Activate a resource
- *
- * Activate a resource previously allocated with
- * BUS_ALLOC_RESOURCE(). This may for instance map a memory region
- * into the kernel's virtual address space.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which allocated the resource
- * @param _type the type of resource
- * @param _rid the resource identifier
- * @param _r the resource to activate
- */
-
-static __inline int BUS_ACTIVATE_RESOURCE(device_t _dev, device_t _child,
- int _type, int _rid,
- struct resource *_r)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_activate_resource);
- return ((bus_activate_resource_t *) _m)(_dev, _child, _type, _rid, _r);
-}
-
-/** @brief Unique descriptor for the BUS_DEACTIVATE_RESOURCE() method */
-extern struct kobjop_desc bus_deactivate_resource_desc;
-/** @brief A function implementing the BUS_DEACTIVATE_RESOURCE() method */
-typedef int bus_deactivate_resource_t(device_t _dev, device_t _child, int _type,
- int _rid, struct resource *_r);
-/**
- * @brief Deactivate a resource
- *
- * Deactivate a resource previously allocated with
- * BUS_ALLOC_RESOURCE(). This may for instance unmap a memory region
- * from the kernel's virtual address space.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which allocated the resource
- * @param _type the type of resource
- * @param _rid the resource identifier
- * @param _r the resource to deactivate
- */
-
-static __inline int BUS_DEACTIVATE_RESOURCE(device_t _dev, device_t _child,
- int _type, int _rid,
- struct resource *_r)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_deactivate_resource);
- return ((bus_deactivate_resource_t *) _m)(_dev, _child, _type, _rid, _r);
-}
-
-/** @brief Unique descriptor for the BUS_RELEASE_RESOURCE() method */
-extern struct kobjop_desc bus_release_resource_desc;
-/** @brief A function implementing the BUS_RELEASE_RESOURCE() method */
-typedef int bus_release_resource_t(device_t _dev, device_t _child, int _type,
- int _rid, struct resource *_res);
-/**
- * @brief Release a resource
- *
- * Free a resource allocated by the BUS_ALLOC_RESOURCE. The @p _rid
- * value must be the same as the one returned by BUS_ALLOC_RESOURCE()
- * (which is not necessarily the same as the one the client passed).
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which allocated the resource
- * @param _type the type of resource
- * @param _rid the resource identifier
- * @param _r the resource to release
- */
-
-static __inline int BUS_RELEASE_RESOURCE(device_t _dev, device_t _child,
- int _type, int _rid,
- struct resource *_res)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_release_resource);
- return ((bus_release_resource_t *) _m)(_dev, _child, _type, _rid, _res);
-}
-
-/** @brief Unique descriptor for the BUS_SETUP_INTR() method */
-extern struct kobjop_desc bus_setup_intr_desc;
-/** @brief A function implementing the BUS_SETUP_INTR() method */
-typedef int bus_setup_intr_t(device_t _dev, device_t _child,
- struct resource *_irq, int _flags,
- driver_filter_t *_filter, driver_intr_t *_intr,
- void *_arg, void **_cookiep);
-/**
- * @brief Install an interrupt handler
- *
- * This method is used to associate an interrupt handler function with
- * an irq resource. When the interrupt triggers, the function @p _intr
- * will be called with the value of @p _arg as its single
- * argument. The value returned in @p *_cookiep is used to cancel the
- * interrupt handler - the caller should save this value to use in a
- * future call to BUS_TEARDOWN_INTR().
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which allocated the resource
- * @param _irq the resource representing the interrupt
- * @param _flags a set of bits from enum intr_type specifying
- * the class of interrupt
- * @param _intr the function to call when the interrupt
- * triggers
- * @param _arg a value to use as the single argument in calls
- * to @p _intr
- * @param _cookiep a pointer to a location to recieve a cookie
- * value that may be used to remove the interrupt
- * handler
- */
-
-static __inline int BUS_SETUP_INTR(device_t _dev, device_t _child,
- struct resource *_irq, int _flags,
- driver_filter_t *_filter,
- driver_intr_t *_intr, void *_arg,
- void **_cookiep)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_setup_intr);
- return ((bus_setup_intr_t *) _m)(_dev, _child, _irq, _flags, _filter, _intr, _arg, _cookiep);
-}
-
-/** @brief Unique descriptor for the BUS_TEARDOWN_INTR() method */
-extern struct kobjop_desc bus_teardown_intr_desc;
-/** @brief A function implementing the BUS_TEARDOWN_INTR() method */
-typedef int bus_teardown_intr_t(device_t _dev, device_t _child,
- struct resource *_irq, void *_cookie);
-/**
- * @brief Uninstall an interrupt handler
- *
- * This method is used to disassociate an interrupt handler function
- * with an irq resource. The value of @p _cookie must be the value
- * returned from a previous call to BUS_SETUP_INTR().
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which allocated the resource
- * @param _irq the resource representing the interrupt
- * @param _cookie the cookie value returned when the interrupt
- * was originally registered
- */
-
-static __inline int BUS_TEARDOWN_INTR(device_t _dev, device_t _child,
- struct resource *_irq, void *_cookie)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_teardown_intr);
- return ((bus_teardown_intr_t *) _m)(_dev, _child, _irq, _cookie);
-}
-
-/** @brief Unique descriptor for the BUS_SET_RESOURCE() method */
-extern struct kobjop_desc bus_set_resource_desc;
-/** @brief A function implementing the BUS_SET_RESOURCE() method */
-typedef int bus_set_resource_t(device_t _dev, device_t _child, int _type,
- int _rid, u_long _start, u_long _count);
-/**
- * @brief Define a resource which can be allocated with
- * BUS_ALLOC_RESOURCE().
- *
- * This method is used by some busses (typically ISA) to allow a
- * driver to describe a resource range that it would like to
- * allocate. The resource defined by @p _type and @p _rid is defined
- * to start at @p _start and to include @p _count indices in its
- * range.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which owns the resource
- * @param _type the type of resource
- * @param _rid the resource identifier
- * @param _start the start of the resource range
- * @param _count the size of the resource range
- */
-
-static __inline int BUS_SET_RESOURCE(device_t _dev, device_t _child, int _type,
- int _rid, u_long _start, u_long _count)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_set_resource);
- return ((bus_set_resource_t *) _m)(_dev, _child, _type, _rid, _start, _count);
-}
-
-/** @brief Unique descriptor for the BUS_GET_RESOURCE() method */
-extern struct kobjop_desc bus_get_resource_desc;
-/** @brief A function implementing the BUS_GET_RESOURCE() method */
-typedef int bus_get_resource_t(device_t _dev, device_t _child, int _type,
- int _rid, u_long *_startp, u_long *_countp);
-/**
- * @brief Describe a resource
- *
- * This method allows a driver to examine the range used for a given
- * resource without actually allocating it.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which owns the resource
- * @param _type the type of resource
- * @param _rid the resource identifier
- * @param _start the address of a location to recieve the start
- * index of the resource range
- * @param _count the address of a location to recieve the size
- * of the resource range
- */
-
-static __inline int BUS_GET_RESOURCE(device_t _dev, device_t _child, int _type,
- int _rid, u_long *_startp, u_long *_countp)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_get_resource);
- return ((bus_get_resource_t *) _m)(_dev, _child, _type, _rid, _startp, _countp);
-}
-
-/** @brief Unique descriptor for the BUS_DELETE_RESOURCE() method */
-extern struct kobjop_desc bus_delete_resource_desc;
-/** @brief A function implementing the BUS_DELETE_RESOURCE() method */
-typedef void bus_delete_resource_t(device_t _dev, device_t _child, int _type,
- int _rid);
-/**
- * @brief Delete a resource.
- *
- * Use this to delete a resource (possibly one previously added with
- * BUS_SET_RESOURCE()).
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which owns the resource
- * @param _type the type of resource
- * @param _rid the resource identifier
- */
-
-static __inline void BUS_DELETE_RESOURCE(device_t _dev, device_t _child,
- int _type, int _rid)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_delete_resource);
- ((bus_delete_resource_t *) _m)(_dev, _child, _type, _rid);
-}
-
-/** @brief Unique descriptor for the BUS_GET_RESOURCE_LIST() method */
-extern struct kobjop_desc bus_get_resource_list_desc;
-/** @brief A function implementing the BUS_GET_RESOURCE_LIST() method */
-typedef struct resource_list * bus_get_resource_list_t(device_t _dev,
- device_t _child);
-/**
- * @brief Return a struct resource_list.
- *
- * Used by drivers which use bus_generic_rl_alloc_resource() etc. to
- * implement their resource handling. It should return the resource
- * list of the given child device.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which owns the resource list
- */
-
-static __inline struct resource_list * BUS_GET_RESOURCE_LIST(device_t _dev,
- device_t _child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_get_resource_list);
- return ((bus_get_resource_list_t *) _m)(_dev, _child);
-}
-
-/** @brief Unique descriptor for the BUS_CHILD_PRESENT() method */
-extern struct kobjop_desc bus_child_present_desc;
-/** @brief A function implementing the BUS_CHILD_PRESENT() method */
-typedef int bus_child_present_t(device_t _dev, device_t _child);
-/**
- * @brief Is the hardware described by @p _child still attached to the
- * system?
- *
- * This method should return 0 if the device is not present. It
- * should return -1 if it is present. Any errors in determining
- * should be returned as a normal errno value. Client drivers are to
- * assume that the device is present, even if there is an error
- * determining if it is there. Busses are to try to avoid returning
- * errors, but newcard will return an error if the device fails to
- * implement this method.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which is being examined
- */
-
-static __inline int BUS_CHILD_PRESENT(device_t _dev, device_t _child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_child_present);
- return ((bus_child_present_t *) _m)(_dev, _child);
-}
-
-/** @brief Unique descriptor for the BUS_CHILD_PNPINFO_STR() method */
-extern struct kobjop_desc bus_child_pnpinfo_str_desc;
-/** @brief A function implementing the BUS_CHILD_PNPINFO_STR() method */
-typedef int bus_child_pnpinfo_str_t(device_t _dev, device_t _child, char *_buf,
- size_t _buflen);
-/**
- * @brief Returns the pnp info for this device.
- *
- * Return it as a string. If the string is insufficient for the
- * storage, then return EOVERFLOW.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which is being examined
- * @param _buf the address of a buffer to receive the pnp
- * string
- * @param _buflen the size of the buffer pointed to by @p _buf
- */
-
-static __inline int BUS_CHILD_PNPINFO_STR(device_t _dev, device_t _child,
- char *_buf, size_t _buflen)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_child_pnpinfo_str);
- return ((bus_child_pnpinfo_str_t *) _m)(_dev, _child, _buf, _buflen);
-}
-
-/** @brief Unique descriptor for the BUS_CHILD_LOCATION_STR() method */
-extern struct kobjop_desc bus_child_location_str_desc;
-/** @brief A function implementing the BUS_CHILD_LOCATION_STR() method */
-typedef int bus_child_location_str_t(device_t _dev, device_t _child, char *_buf,
- size_t _buflen);
-/**
- * @brief Returns the location for this device.
- *
- * Return it as a string. If the string is insufficient for the
- * storage, then return EOVERFLOW.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which is being examined
- * @param _buf the address of a buffer to receive the location
- * string
- * @param _buflen the size of the buffer pointed to by @p _buf
- */
-
-static __inline int BUS_CHILD_LOCATION_STR(device_t _dev, device_t _child,
- char *_buf, size_t _buflen)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_child_location_str);
- return ((bus_child_location_str_t *) _m)(_dev, _child, _buf, _buflen);
-}
-
-/** @brief Unique descriptor for the BUS_BIND_INTR() method */
-extern struct kobjop_desc bus_bind_intr_desc;
-/** @brief A function implementing the BUS_BIND_INTR() method */
-typedef int bus_bind_intr_t(device_t _dev, device_t _child,
- struct resource *_irq, int _cpu);
-/**
- * @brief Allow drivers to request that an interrupt be bound to a specific
- * CPU.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which allocated the resource
- * @param _irq the resource representing the interrupt
- * @param _cpu the CPU to bind the interrupt to
- */
-
-static __inline int BUS_BIND_INTR(device_t _dev, device_t _child,
- struct resource *_irq, int _cpu)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_bind_intr);
- return ((bus_bind_intr_t *) _m)(_dev, _child, _irq, _cpu);
-}
-
-/** @brief Unique descriptor for the BUS_CONFIG_INTR() method */
-extern struct kobjop_desc bus_config_intr_desc;
-/** @brief A function implementing the BUS_CONFIG_INTR() method */
-typedef int bus_config_intr_t(device_t _dev, int _irq, enum intr_trigger _trig,
- enum intr_polarity _pol);
-/**
- * @brief Allow (bus) drivers to specify the trigger mode and polarity
- * of the specified interrupt.
- *
- * @param _dev the bus device
- * @param _irq the interrupt number to modify
- * @param _trig the trigger mode required
- * @param _pol the interrupt polarity required
- */
-
-static __inline int BUS_CONFIG_INTR(device_t _dev, int _irq,
- enum intr_trigger _trig,
- enum intr_polarity _pol)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_config_intr);
- return ((bus_config_intr_t *) _m)(_dev, _irq, _trig, _pol);
-}
-
-/** @brief Unique descriptor for the BUS_DESCRIBE_INTR() method */
-extern struct kobjop_desc bus_describe_intr_desc;
-/** @brief A function implementing the BUS_DESCRIBE_INTR() method */
-typedef int bus_describe_intr_t(device_t _dev, device_t _child,
- struct resource *_irq, void *_cookie,
- const char *_descr);
-/**
- * @brief Allow drivers to associate a description with an active
- * interrupt handler.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device which allocated the resource
- * @param _irq the resource representing the interrupt
- * @param _cookie the cookie value returned when the interrupt
- * was originally registered
- * @param _descr the description to associate with the interrupt
- */
-
-static __inline int BUS_DESCRIBE_INTR(device_t _dev, device_t _child,
- struct resource *_irq, void *_cookie,
- const char *_descr)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_describe_intr);
- return ((bus_describe_intr_t *) _m)(_dev, _child, _irq, _cookie, _descr);
-}
-
-/** @brief Unique descriptor for the BUS_HINTED_CHILD() method */
-extern struct kobjop_desc bus_hinted_child_desc;
-/** @brief A function implementing the BUS_HINTED_CHILD() method */
-typedef void bus_hinted_child_t(device_t _dev, const char *_dname, int _dunit);
-/**
- * @brief Notify a (bus) driver about a child that the hints mechanism
- * believes it has discovered.
- *
- * The bus is responsible for then adding the child in the right order
- * and discovering other things about the child. The bus driver is
- * free to ignore this hint, to do special things, etc. It is all up
- * to the bus driver to interpret.
- *
- * This method is only called in response to the parent bus asking for
- * hinted devices to be enumerated.
- *
- * @param _dev the bus device
- * @param _dname the name of the device w/o unit numbers
- * @param _dunit the unit number of the device
- */
-
-static __inline void BUS_HINTED_CHILD(device_t _dev, const char *_dname,
- int _dunit)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_hinted_child);
- ((bus_hinted_child_t *) _m)(_dev, _dname, _dunit);
-}
-
-/** @brief Unique descriptor for the BUS_GET_DMA_TAG() method */
-extern struct kobjop_desc bus_get_dma_tag_desc;
-/** @brief A function implementing the BUS_GET_DMA_TAG() method */
-typedef bus_dma_tag_t bus_get_dma_tag_t(device_t _dev, device_t _child);
-/**
- * @brief Returns bus_dma_tag_t for use w/ devices on the bus.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device to which the tag will belong
- */
-
-static __inline bus_dma_tag_t BUS_GET_DMA_TAG(device_t _dev, device_t _child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_get_dma_tag);
- return ((bus_get_dma_tag_t *) _m)(_dev, _child);
-}
-
-/** @brief Unique descriptor for the BUS_HINT_DEVICE_UNIT() method */
-extern struct kobjop_desc bus_hint_device_unit_desc;
-/** @brief A function implementing the BUS_HINT_DEVICE_UNIT() method */
-typedef void bus_hint_device_unit_t(device_t _dev, device_t _child,
- const char *_name, int *_unitp);
-/**
- * @brief Allow the bus to determine the unit number of a device.
- *
- * @param _dev the parent device of @p _child
- * @param _child the device whose unit is to be wired
- * @param _name the name of the device's new devclass
- * @param _unitp a pointer to the device's new unit value
- */
-
-static __inline void BUS_HINT_DEVICE_UNIT(device_t _dev, device_t _child,
- const char *_name, int *_unitp)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_hint_device_unit);
- ((bus_hint_device_unit_t *) _m)(_dev, _child, _name, _unitp);
-}
-
-/** @brief Unique descriptor for the BUS_NEW_PASS() method */
-extern struct kobjop_desc bus_new_pass_desc;
-/** @brief A function implementing the BUS_NEW_PASS() method */
-typedef void bus_new_pass_t(device_t _dev);
-/**
- * @brief Notify a bus that the bus pass level has been changed
- *
- * @param _dev the bus device
- */
-
-static __inline void BUS_NEW_PASS(device_t _dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_new_pass);
- ((bus_new_pass_t *) _m)(_dev);
-}
-
-/** @brief Unique descriptor for the BUS_REMAP_INTR() method */
-extern struct kobjop_desc bus_remap_intr_desc;
-/** @brief A function implementing the BUS_REMAP_INTR() method */
-typedef int bus_remap_intr_t(device_t _dev, device_t _child, u_int _irq);
-/**
- * @brief Notify a bus that specified child's IRQ should be remapped.
- *
- * @param _dev the bus device
- * @param _child the child device
- * @param _irq the irq number
- */
-
-static __inline int BUS_REMAP_INTR(device_t _dev, device_t _child, u_int _irq)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)_dev)->ops,bus_remap_intr);
- return ((bus_remap_intr_t *) _m)(_dev, _child, _irq);
-}
-
-#endif /* _bus_if_h_ */
diff --git a/freebsd/local/cryptodev_if.c b/freebsd/local/cryptodev_if.c
deleted file mode 100644
index d4875e46..00000000
--- a/freebsd/local/cryptodev_if.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include <freebsd/machine/rtems-bsd-config.h>
-
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * opencrypto/cryptodev_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-#include <freebsd/sys/param.h>
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/kernel.h>
-#include <freebsd/sys/kobj.h>
-#include <freebsd/sys/malloc.h>
-#include <freebsd/opencrypto/cryptodev.h>
-#include <freebsd/local/cryptodev_if.h>
-
-struct kobj_method cryptodev_newsession_method_default = {
- &cryptodev_newsession_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc cryptodev_newsession_desc = {
- 0, &cryptodev_newsession_method_default
-};
-
-struct kobj_method cryptodev_freesession_method_default = {
- &cryptodev_freesession_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc cryptodev_freesession_desc = {
- 0, &cryptodev_freesession_method_default
-};
-
-struct kobj_method cryptodev_process_method_default = {
- &cryptodev_process_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc cryptodev_process_desc = {
- 0, &cryptodev_process_method_default
-};
-
-struct kobj_method cryptodev_kprocess_method_default = {
- &cryptodev_kprocess_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc cryptodev_kprocess_desc = {
- 0, &cryptodev_kprocess_method_default
-};
-
diff --git a/freebsd/local/cryptodev_if.h b/freebsd/local/cryptodev_if.h
deleted file mode 100644
index 752527ed..00000000
--- a/freebsd/local/cryptodev_if.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * opencrypto/cryptodev_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-
-#ifndef _cryptodev_if_h_
-#define _cryptodev_if_h_
-
-/** @brief Unique descriptor for the CRYPTODEV_NEWSESSION() method */
-extern struct kobjop_desc cryptodev_newsession_desc;
-/** @brief A function implementing the CRYPTODEV_NEWSESSION() method */
-typedef int cryptodev_newsession_t(device_t dev, uint32_t *sid,
- struct cryptoini *cri);
-
-static __inline int CRYPTODEV_NEWSESSION(device_t dev, uint32_t *sid,
- struct cryptoini *cri)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_newsession);
- return ((cryptodev_newsession_t *) _m)(dev, sid, cri);
-}
-
-/** @brief Unique descriptor for the CRYPTODEV_FREESESSION() method */
-extern struct kobjop_desc cryptodev_freesession_desc;
-/** @brief A function implementing the CRYPTODEV_FREESESSION() method */
-typedef int cryptodev_freesession_t(device_t dev, uint64_t sid);
-
-static __inline int CRYPTODEV_FREESESSION(device_t dev, uint64_t sid)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_freesession);
- return ((cryptodev_freesession_t *) _m)(dev, sid);
-}
-
-/** @brief Unique descriptor for the CRYPTODEV_PROCESS() method */
-extern struct kobjop_desc cryptodev_process_desc;
-/** @brief A function implementing the CRYPTODEV_PROCESS() method */
-typedef int cryptodev_process_t(device_t dev, struct cryptop *op, int flags);
-
-static __inline int CRYPTODEV_PROCESS(device_t dev, struct cryptop *op,
- int flags)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_process);
- return ((cryptodev_process_t *) _m)(dev, op, flags);
-}
-
-/** @brief Unique descriptor for the CRYPTODEV_KPROCESS() method */
-extern struct kobjop_desc cryptodev_kprocess_desc;
-/** @brief A function implementing the CRYPTODEV_KPROCESS() method */
-typedef int cryptodev_kprocess_t(device_t dev, struct cryptkop *op, int flags);
-
-static __inline int CRYPTODEV_KPROCESS(device_t dev, struct cryptkop *op,
- int flags)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,cryptodev_kprocess);
- return ((cryptodev_kprocess_t *) _m)(dev, op, flags);
-}
-
-#endif /* _cryptodev_if_h_ */
diff --git a/freebsd/local/device_if.c b/freebsd/local/device_if.c
deleted file mode 100644
index e6f3189a..00000000
--- a/freebsd/local/device_if.c
+++ /dev/null
@@ -1,106 +0,0 @@
-#include <freebsd/machine/rtems-bsd-config.h>
-
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * kern/device_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-#include <freebsd/sys/param.h>
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/kernel.h>
-#include <freebsd/sys/kobj.h>
-#include <freebsd/sys/bus.h>
-#include <freebsd/local/device_if.h>
-
-
-static int null_shutdown(device_t dev)
-{
- return 0;
-}
-
-static int null_suspend(device_t dev)
-{
- return 0;
-}
-
-static int null_resume(device_t dev)
-{
- return 0;
-}
-
-static int null_quiesce(device_t dev)
-{
- return EOPNOTSUPP;
-}
-
-struct kobj_method device_probe_method_default = {
- &device_probe_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc device_probe_desc = {
- 0, &device_probe_method_default
-};
-
-struct kobj_method device_identify_method_default = {
- &device_identify_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc device_identify_desc = {
- 0, &device_identify_method_default
-};
-
-struct kobj_method device_attach_method_default = {
- &device_attach_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc device_attach_desc = {
- 0, &device_attach_method_default
-};
-
-struct kobj_method device_detach_method_default = {
- &device_detach_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc device_detach_desc = {
- 0, &device_detach_method_default
-};
-
-struct kobj_method device_shutdown_method_default = {
- &device_shutdown_desc, (kobjop_t) null_shutdown
-};
-
-struct kobjop_desc device_shutdown_desc = {
- 0, &device_shutdown_method_default
-};
-
-struct kobj_method device_suspend_method_default = {
- &device_suspend_desc, (kobjop_t) null_suspend
-};
-
-struct kobjop_desc device_suspend_desc = {
- 0, &device_suspend_method_default
-};
-
-struct kobj_method device_resume_method_default = {
- &device_resume_desc, (kobjop_t) null_resume
-};
-
-struct kobjop_desc device_resume_desc = {
- 0, &device_resume_method_default
-};
-
-struct kobj_method device_quiesce_method_default = {
- &device_quiesce_desc, (kobjop_t) null_quiesce
-};
-
-struct kobjop_desc device_quiesce_desc = {
- 0, &device_quiesce_method_default
-};
-
diff --git a/freebsd/local/device_if.h b/freebsd/local/device_if.h
deleted file mode 100644
index 47339eb3..00000000
--- a/freebsd/local/device_if.h
+++ /dev/null
@@ -1,340 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * kern/device_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-/**
- * @defgroup DEVICE device - KObj methods for all device drivers
- * @brief A basic set of methods required for all device drivers.
- *
- * The device interface is used to match devices to drivers during
- * autoconfiguration and provides methods to allow drivers to handle
- * system-wide events such as suspend, resume or shutdown.
- * @{
- */
-
-#ifndef _device_if_h_
-#define _device_if_h_
-
-/** @brief Unique descriptor for the DEVICE_PROBE() method */
-extern struct kobjop_desc device_probe_desc;
-/** @brief A function implementing the DEVICE_PROBE() method */
-typedef int device_probe_t(device_t dev);
-/**
- * @brief Probe to see if a device matches a driver.
- *
- * Users should not call this method directly. Normally, this
- * is called via device_probe_and_attach() to select a driver
- * calling the DEVICE_PROBE() of all candidate drivers and attach
- * the winning driver (if any) to the device.
- *
- * This function is used to match devices to device drivers.
- * Typically, the driver will examine the device to see if
- * it is suitable for this driver. This might include checking
- * the values of various device instance variables or reading
- * hardware registers.
- *
- * In some cases, there may be more than one driver available
- * which can be used for a device (for instance there might
- * be a generic driver which works for a set of many types of
- * device and a more specific driver which works for a subset
- * of devices). Because of this, a driver should not assume
- * that it will be the driver that attaches to the device even
- * if it returns a success status from DEVICE_PROBE(). In particular,
- * a driver must free any resources which it allocated during
- * the probe before returning. The return value of DEVICE_PROBE()
- * is used to elect which driver is used - the driver which returns
- * the largest non-error value wins the election and attaches to
- * the device.
- *
- * If a driver matches the hardware, it should set the device
- * description string using device_set_desc() or
- * device_set_desc_copy(). This string is
- * used to generate an informative message when DEVICE_ATTACH()
- * is called.
- *
- * As a special case, if a driver returns zero, the driver election
- * is cut short and that driver will attach to the device
- * immediately.
- *
- * For example, a probe method for a pci device driver might look
- * like this:
- *
- * @code
- * int foo_probe(device_t dev)
- * {
- * if (pci_get_vendor(dev) == FOOVENDOR &&
- * pci_get_device(dev) == FOODEVICE) {
- * device_set_desc(dev, "Foo device");
- * return (0);
- * }
- * return (ENXIO);
- * }
- * @endcode
- *
- * To include this method in a device driver, use a line like this
- * in the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_probe, foo_probe)
- * @endcode
- *
- * @param dev the device to probe
- *
- * @retval 0 if the driver strongly matches this device
- * @retval negative if the driver can match this device - the
- * least negative value is used to select the
- * driver
- * @retval ENXIO if the driver does not match the device
- * @retval positive if some kind of error was detected during
- * the probe, a regular unix error code should
- * be returned to indicate the type of error
- * @see DEVICE_ATTACH(), pci_get_vendor(), pci_get_device()
- */
-
-static __inline int DEVICE_PROBE(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,device_probe);
- return ((device_probe_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the DEVICE_IDENTIFY() method */
-extern struct kobjop_desc device_identify_desc;
-/** @brief A function implementing the DEVICE_IDENTIFY() method */
-typedef void device_identify_t(driver_t *driver, device_t parent);
-/**
- * @brief Allow a device driver to detect devices not otherwise enumerated.
- *
- * The DEVICE_IDENTIFY() method is used by some drivers (e.g. the ISA
- * bus driver) to help populate the bus device with a useful set of
- * child devices, normally by calling the BUS_ADD_CHILD() method of
- * the parent device. For instance, the ISA bus driver uses several
- * special drivers, including the isahint driver and the pnp driver to
- * create child devices based on configuration hints and PnP bus
- * probes respectively.
- *
- * Many bus drivers which support true plug-and-play do not need to
- * use this method at all since child devices can be discovered
- * automatically without help from child drivers.
- *
- * To include this method in a device driver, use a line like this
- * in the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_identify, foo_identify)
- * @endcode
- *
- * @param driver the driver whose identify method is being called
- * @param parent the parent device to use when adding new children
- */
-
-static __inline void DEVICE_IDENTIFY(driver_t *driver, device_t parent)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(driver->ops,device_identify);
- ((device_identify_t *) _m)(driver, parent);
-}
-
-/** @brief Unique descriptor for the DEVICE_ATTACH() method */
-extern struct kobjop_desc device_attach_desc;
-/** @brief A function implementing the DEVICE_ATTACH() method */
-typedef int device_attach_t(device_t dev);
-/**
- * @brief Attach a device to a device driver
- *
- * Normally only called via device_probe_and_attach(), this is called
- * when a driver has succeeded in probing against a device.
- * This method should initialise the hardware and allocate other
- * system resources (e.g. devfs entries) as required.
- *
- * To include this method in a device driver, use a line like this
- * in the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_attach, foo_attach)
- * @endcode
- *
- * @param dev the device to probe
- *
- * @retval 0 success
- * @retval non-zero if some kind of error was detected during
- * the attach, a regular unix error code should
- * be returned to indicate the type of error
- * @see DEVICE_PROBE()
- */
-
-static __inline int DEVICE_ATTACH(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,device_attach);
- return ((device_attach_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the DEVICE_DETACH() method */
-extern struct kobjop_desc device_detach_desc;
-/** @brief A function implementing the DEVICE_DETACH() method */
-typedef int device_detach_t(device_t dev);
-/**
- * @brief Detach a driver from a device.
- *
- * This can be called if the user is replacing the
- * driver software or if a device is about to be physically removed
- * from the system (e.g. for removable hardware such as USB or PCCARD).
- *
- * To include this method in a device driver, use a line like this
- * in the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_detach, foo_detach)
- * @endcode
- *
- * @param dev the device to detach
- *
- * @retval 0 success
- * @retval non-zero the detach could not be performed, e.g. if the
- * driver does not support detaching.
- *
- * @see DEVICE_ATTACH()
- */
-
-static __inline int DEVICE_DETACH(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,device_detach);
- return ((device_detach_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the DEVICE_SHUTDOWN() method */
-extern struct kobjop_desc device_shutdown_desc;
-/** @brief A function implementing the DEVICE_SHUTDOWN() method */
-typedef int device_shutdown_t(device_t dev);
-/**
- * @brief Called during system shutdown.
- *
- * This method allows drivers to detect when the system is being shut down.
- * Some drivers need to use this to place their hardware in a consistent
- * state before rebooting the computer.
- *
- * To include this method in a device driver, use a line like this
- * in the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_shutdown, foo_shutdown)
- * @endcode
- */
-
-static __inline int DEVICE_SHUTDOWN(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,device_shutdown);
- return ((device_shutdown_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the DEVICE_SUSPEND() method */
-extern struct kobjop_desc device_suspend_desc;
-/** @brief A function implementing the DEVICE_SUSPEND() method */
-typedef int device_suspend_t(device_t dev);
-/**
- * @brief This is called by the power-management subsystem when a
- * suspend has been requested by the user or by some automatic
- * mechanism.
- *
- * This gives drivers a chance to veto the suspend or save their
- * configuration before power is removed.
- *
- * To include this method in a device driver, use a line like this in
- * the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_suspend, foo_suspend)
- * @endcode
- *
- * @param dev the device being suspended
- *
- * @retval 0 success
- * @retval non-zero an error occurred while attempting to prepare the
- * device for suspension
- *
- * @see DEVICE_RESUME()
- */
-
-static __inline int DEVICE_SUSPEND(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,device_suspend);
- return ((device_suspend_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the DEVICE_RESUME() method */
-extern struct kobjop_desc device_resume_desc;
-/** @brief A function implementing the DEVICE_RESUME() method */
-typedef int device_resume_t(device_t dev);
-/**
- * @brief This is called when the system resumes after a suspend.
- *
- * To include this method in a device driver, use a line like this
- * in the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_resume, foo_resume)
- * @endcode
- *
- * @param dev the device being resumed
- *
- * @retval 0 success
- * @retval non-zero an error occurred while attempting to restore the
- * device from suspension
- *
- * @see DEVICE_SUSPEND()
- */
-
-static __inline int DEVICE_RESUME(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,device_resume);
- return ((device_resume_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the DEVICE_QUIESCE() method */
-extern struct kobjop_desc device_quiesce_desc;
-/** @brief A function implementing the DEVICE_QUIESCE() method */
-typedef int device_quiesce_t(device_t dev);
-/**
- * @brief This is called when the driver is asked to quiesce itself.
- *
- * The driver should arrange for the orderly shutdown of this device.
- * All further access to the device should be curtailed. Soon there
- * will be a request to detach, but there won't necessarily be one.
- *
- * To include this method in a device driver, use a line like this
- * in the driver's method list:
- *
- * @code
- * KOBJMETHOD(device_quiesce, foo_quiesce)
- * @endcode
- *
- * @param dev the device being quiesced
- *
- * @retval 0 success
- * @retval non-zero an error occurred while attempting to quiesce the
- * device
- *
- * @see DEVICE_DETACH()
- */
-
-static __inline int DEVICE_QUIESCE(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,device_quiesce);
- return ((device_quiesce_t *) _m)(dev);
-}
-
-#endif /* _device_if_h_ */
diff --git a/freebsd/local/linker_if.h b/freebsd/local/linker_if.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/local/linker_if.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/local/miibus_if.c b/freebsd/local/miibus_if.c
deleted file mode 100644
index 2f5127e8..00000000
--- a/freebsd/local/miibus_if.c
+++ /dev/null
@@ -1,61 +0,0 @@
-#include <freebsd/machine/rtems-bsd-config.h>
-
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/mii/miibus_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-#include <freebsd/sys/param.h>
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/kernel.h>
-#include <freebsd/sys/kobj.h>
-#include <freebsd/sys/bus.h>
-#include <freebsd/local/miibus_if.h>
-
-struct kobj_method miibus_readreg_method_default = {
- &miibus_readreg_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc miibus_readreg_desc = {
- 0, &miibus_readreg_method_default
-};
-
-struct kobj_method miibus_writereg_method_default = {
- &miibus_writereg_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc miibus_writereg_desc = {
- 0, &miibus_writereg_method_default
-};
-
-struct kobj_method miibus_statchg_method_default = {
- &miibus_statchg_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc miibus_statchg_desc = {
- 0, &miibus_statchg_method_default
-};
-
-struct kobj_method miibus_linkchg_method_default = {
- &miibus_linkchg_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc miibus_linkchg_desc = {
- 0, &miibus_linkchg_method_default
-};
-
-struct kobj_method miibus_mediainit_method_default = {
- &miibus_mediainit_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc miibus_mediainit_desc = {
- 0, &miibus_mediainit_method_default
-};
-
diff --git a/freebsd/local/miibus_if.h b/freebsd/local/miibus_if.h
deleted file mode 100644
index ec35ca19..00000000
--- a/freebsd/local/miibus_if.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/mii/miibus_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-
-#ifndef _miibus_if_h_
-#define _miibus_if_h_
-
-/** @brief Unique descriptor for the MIIBUS_READREG() method */
-extern struct kobjop_desc miibus_readreg_desc;
-/** @brief A function implementing the MIIBUS_READREG() method */
-typedef int miibus_readreg_t(device_t dev, int phy, int reg);
-
-static __inline int MIIBUS_READREG(device_t dev, int phy, int reg)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,miibus_readreg);
- return ((miibus_readreg_t *) _m)(dev, phy, reg);
-}
-
-/** @brief Unique descriptor for the MIIBUS_WRITEREG() method */
-extern struct kobjop_desc miibus_writereg_desc;
-/** @brief A function implementing the MIIBUS_WRITEREG() method */
-typedef int miibus_writereg_t(device_t dev, int phy, int reg, int val);
-
-static __inline int MIIBUS_WRITEREG(device_t dev, int phy, int reg, int val)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,miibus_writereg);
- return ((miibus_writereg_t *) _m)(dev, phy, reg, val);
-}
-
-/** @brief Unique descriptor for the MIIBUS_STATCHG() method */
-extern struct kobjop_desc miibus_statchg_desc;
-/** @brief A function implementing the MIIBUS_STATCHG() method */
-typedef void miibus_statchg_t(device_t dev);
-
-static __inline void MIIBUS_STATCHG(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,miibus_statchg);
- ((miibus_statchg_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the MIIBUS_LINKCHG() method */
-extern struct kobjop_desc miibus_linkchg_desc;
-/** @brief A function implementing the MIIBUS_LINKCHG() method */
-typedef void miibus_linkchg_t(device_t dev);
-
-static __inline void MIIBUS_LINKCHG(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,miibus_linkchg);
- ((miibus_linkchg_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the MIIBUS_MEDIAINIT() method */
-extern struct kobjop_desc miibus_mediainit_desc;
-/** @brief A function implementing the MIIBUS_MEDIAINIT() method */
-typedef void miibus_mediainit_t(device_t dev);
-
-static __inline void MIIBUS_MEDIAINIT(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,miibus_mediainit);
- ((miibus_mediainit_t *) _m)(dev);
-}
-
-#endif /* _miibus_if_h_ */
diff --git a/freebsd/local/miidevs.h b/freebsd/local/miidevs.h
deleted file mode 100644
index ee8f4327..00000000
--- a/freebsd/local/miidevs.h
+++ /dev/null
@@ -1,376 +0,0 @@
-/* $FreeBSD$ */
-
-/*
- * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
- *
- * generated from:
- * FreeBSD
- */
-/*$NetBSD: miidevs,v 1.6 1999/05/14 11:37:30 drochner Exp $*/
-
-/*-
- * Copyright (c) 1998, 1999 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
- * NASA Ames Research Center.
- *
- * 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.
- */
-
-/*
- * List of known MII OUIs.
- * For a complete list see http://standards.ieee.org/regauth/oui/
- *
- * XXX Vendors do obviously not agree how OUIs (18 bit) are mapped
- * to the 16 bits available in the id registers. The MII_OUI() macro
- * in "mii.h" reflects the most obvious way. If a vendor uses a
- * different mapping, an "xx" prefixed OUI is defined here which is
- * mangled accordingly to compensate.
- */
-
-#define MII_OUI_AGERE 0x00a0bc /* Agere Systems */
-#define MII_OUI_ALTIMA 0x0010a9 /* Altima Communications */
-#define MII_OUI_AMD 0x00001a /* Advanced Micro Devices */
-#define MII_OUI_ASIX 0x00602e /* Asix Semiconductor */
-#define MII_OUI_ATHEROS 0x001374 /* Atheros Communications */
-#define MII_OUI_BROADCOM 0x001018 /* Broadcom Corporation */
-#define MII_OUI_BROADCOM2 0x000af7 /* Broadcom Corporation */
-#define MII_OUI_CICADA 0x0003F1 /* Cicada Semiconductor */
-#define MII_OUI_DAVICOM 0x00606e /* Davicom Semiconductor */
-#define MII_OUI_ICPLUS 0x0090c3 /* IC Plus Corp. */
-#define MII_OUI_ICS 0x00a0be /* Integrated Circuit Systems */
-#define MII_OUI_INTEL 0x00aa00 /* Intel */
-#define MII_OUI_JATO 0x00e083 /* Jato Technologies */
-#define MII_OUI_JMICRON 0x001b8c /* JMicron Technologies */
-#define MII_OUI_LEVEL1 0x00207b /* Level 1 */
-#define MII_OUI_NATSEMI 0x080017 /* National Semiconductor */
-#define MII_OUI_QUALSEMI 0x006051 /* Quality Semiconductor */
-#define MII_OUI_REALTEK 0x000020 /* RealTek Semicondctor */
-#define MII_OUI_SEEQ 0x00a07d /* Seeq */
-#define MII_OUI_SIS 0x00e006 /* Silicon Integrated Systems */
-#define MII_OUI_SMSC 0x0005be /* SMSC */
-#define MII_OUI_TDK 0x00c039 /* TDK */
-#define MII_OUI_TI 0x080028 /* Texas Instruments */
-#define MII_OUI_VITESSE 0x0001c1 /* Vitesse Semiconductor */
-#define MII_OUI_XAQTI 0x00e0ae /* XaQti Corp. */
-#define MII_OUI_MARVELL 0x005043 /* Marvell Semiconductor */
-#define MII_OUI_xxMARVELL 0x000ac2 /* Marvell Semiconductor */
-
-/* in the 79c873, AMD uses another OUI (which matches Davicom!) */
-#define MII_OUI_xxAMD 0x00606e /* Advanced Micro Devices */
-
-/* Intel 82553 A/B steppings */
-#define MII_OUI_xxINTEL 0x00f800 /* Intel */
-
-/* some vendors have the bits swapped within bytes
- (ie, ordered as on the wire) */
-#define MII_OUI_xxALTIMA 0x000895 /* Altima Communications */
-#define MII_OUI_xxBROADCOM 0x000818 /* Broadcom Corporation */
-#define MII_OUI_xxBROADCOM_ALT1 0x0050ef /* Broadcom Corporation */
-#define MII_OUI_xxBROADCOM_ALT2 0x00d897 /* Broadcom Corporation */
-#define MII_OUI_xxICS 0x00057d /* Integrated Circuit Systems */
-#define MII_OUI_xxSEEQ 0x0005be /* Seeq */
-#define MII_OUI_xxSIS 0x000760 /* Silicon Integrated Systems */
-#define MII_OUI_xxTI 0x100014 /* Texas Instruments */
-#define MII_OUI_xxXAQTI 0x350700 /* XaQti Corp. */
-
-/* Level 1 is completely different - from right to left.
- (Two bits get lost in the third OUI byte.) */
-#define MII_OUI_xxLEVEL1 0x1e0400 /* Level 1 */
-
-/* Don't know what's going on here. */
-#define MII_OUI_xxDAVICOM 0x006040 /* Davicom Semiconductor */
-
-/* This is the OUI of the gigE PHY in the RealTek 8169S/8110S/8211B chips */
-#define MII_OUI_xxREALTEK 0x000732 /* */
-
-/*
- * List of known models. Grouped by oui.
- */
-
-/* Agere Systems PHYs */
-#define MII_MODEL_AGERE_ET1011 0x0001
-#define MII_STR_AGERE_ET1011 "ET1011 10/100/1000baseT PHY"
-#define MII_MODEL_AGERE_ET1011C 0x0004
-#define MII_STR_AGERE_ET1011C "ET1011C 10/100/1000baseT PHY"
-
-/* Altima Communications PHYs */
-#define MII_MODEL_xxALTIMA_AC101 0x0021
-#define MII_STR_xxALTIMA_AC101 "AC101 10/100 media interface"
-#define MII_MODEL_xxALTIMA_AC101L 0x0012
-#define MII_STR_xxALTIMA_AC101L "AC101L 10/100 media interface"
-#define MII_MODEL_xxALTIMA_ACXXX 0x0001
-#define MII_STR_xxALTIMA_ACXXX "ACXXX 10/100 media interface"
-
-/* Advanced Micro Devices PHYs */
-#define MII_MODEL_AMD_79c973phy 0x0036
-#define MII_STR_AMD_79c973phy "Am79c973 internal PHY"
-#define MII_MODEL_AMD_79c978 0x0039
-#define MII_STR_AMD_79c978 "Am79c978 HomePNA PHY"
-#define MII_MODEL_xxAMD_79C873 0x0000
-#define MII_STR_xxAMD_79C873 "Am79C873/DM9101 10/100 media interface"
-
-/* Asix semiconductor PHYs. */
-#define MII_MODEL_ASIX_AX88X9X 0x0031
-#define MII_STR_ASIX_AX88X9X "Ax88x9x internal PHY"
-
-/* Atheros Communications/Attansic PHYs. */
-#define MII_MODEL_ATHEROS_F1 0x0001
-#define MII_STR_ATHEROS_F1 "Atheros F1 10/100/1000 PHY"
-#define MII_MODEL_ATHEROS_F2 0x0002
-#define MII_STR_ATHEROS_F2 "Atheros F2 10/100 PHY"
-#define MII_MODEL_ATHEROS_F1_7 0x0007
-#define MII_STR_ATHEROS_F1_7 "Atheros F1 10/100/1000 PHY"
-
-/* Broadcom Corp. PHYs. */
-#define MII_MODEL_BROADCOM_3C905B 0x0012
-#define MII_STR_BROADCOM_3C905B "3c905B 10/100 internal PHY"
-#define MII_MODEL_BROADCOM_3C905C 0x0017
-#define MII_STR_BROADCOM_3C905C "3c905C 10/100 internal PHY"
-#define MII_MODEL_BROADCOM_BCM5201 0x0021
-#define MII_STR_BROADCOM_BCM5201 "BCM5201 10/100baseTX PHY"
-#define MII_MODEL_BROADCOM_BCM5214 0x0028
-#define MII_STR_BROADCOM_BCM5214 "BCM5214 Quad 10/100 PHY"
-#define MII_MODEL_BROADCOM_BCM5221 0x001e
-#define MII_STR_BROADCOM_BCM5221 "BCM5221 10/100baseTX PHY"
-#define MII_MODEL_BROADCOM_BCM5222 0x0032
-#define MII_STR_BROADCOM_BCM5222 "BCM5222 Dual 10/100 PHY"
-#define MII_MODEL_BROADCOM_BCM4401 0x0036
-#define MII_STR_BROADCOM_BCM4401 "BCM4401 10/100baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5400 0x0004
-#define MII_STR_xxBROADCOM_BCM5400 "Broadcom 1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5401 0x0005
-#define MII_STR_xxBROADCOM_BCM5401 "BCM5401 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5411 0x0007
-#define MII_STR_xxBROADCOM_BCM5411 "BCM5411 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5754 0x000e
-#define MII_STR_xxBROADCOM_BCM5754 "BCM5754 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5752 0x0010
-#define MII_STR_xxBROADCOM_BCM5752 "BCM5752 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5701 0x0011
-#define MII_STR_xxBROADCOM_BCM5701 "BCM5701 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5706 0x0015
-#define MII_STR_xxBROADCOM_BCM5706 "BCM5706 10/100/1000baseTX/SX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5703 0x0016
-#define MII_STR_xxBROADCOM_BCM5703 "BCM5703 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5704 0x0019
-#define MII_STR_xxBROADCOM_BCM5704 "BCM5704 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5705 0x001a
-#define MII_STR_xxBROADCOM_BCM5705 "BCM5705 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5750 0x0018
-#define MII_STR_xxBROADCOM_BCM5750 "BCM5750 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM54K2 0x002e
-#define MII_STR_xxBROADCOM_BCM54K2 "BCM54K2 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5714 0x0034
-#define MII_STR_xxBROADCOM_BCM5714 "BCM5714 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5780 0x0035
-#define MII_STR_xxBROADCOM_BCM5780 "BCM5780 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_BCM5708C 0x0036
-#define MII_STR_xxBROADCOM_BCM5708C "BCM5708C 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5755 0x000c
-#define MII_STR_xxBROADCOM_ALT1_BCM5755 "BCM5755 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5787 0x000e
-#define MII_STR_xxBROADCOM_ALT1_BCM5787 "BCM5787 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5708S 0x0015
-#define MII_STR_xxBROADCOM_ALT1_BCM5708S "BCM5708S 1000/2500BaseSX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5709CAX 0x002c
-#define MII_STR_xxBROADCOM_ALT1_BCM5709CAX "BCM5709C(AX) 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5722 0x002d
-#define MII_STR_xxBROADCOM_ALT1_BCM5722 "BCM5722 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5784 0x003a
-#define MII_STR_xxBROADCOM_ALT1_BCM5784 "BCM5784 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5709C 0x003c
-#define MII_STR_xxBROADCOM_ALT1_BCM5709C "BCM5709C 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5761 0x003d
-#define MII_STR_xxBROADCOM_ALT1_BCM5761 "BCM5761 10/100/1000baseTX PHY"
-#define MII_MODEL_xxBROADCOM_ALT1_BCM5709S 0x003f
-#define MII_STR_xxBROADCOM_ALT1_BCM5709S "BCM5709S 1000/2500baseSX PHY"
-#define MII_MODEL_xxBROADCOM_ALT2_BCM5717C 0x0020
-#define MII_STR_xxBROADCOM_ALT2_BCM5717C "BCM5717C 10/100/1000baseTX PHY"
-#define MII_MODEL_BROADCOM2_BCM5906 0x0004
-#define MII_STR_BROADCOM2_BCM5906 "BCM5906 10/100baseTX PHY"
-
-/* Cicada Semiconductor PHYs (now owned by Vitesse?) */
-#define MII_MODEL_CICADA_CS8201 0x0001
-#define MII_STR_CICADA_CS8201 "Cicada CS8201 10/100/1000TX PHY"
-#define MII_MODEL_CICADA_CS8204 0x0004
-#define MII_STR_CICADA_CS8204 "Cicada CS8204 10/100/1000TX PHY"
-#define MII_MODEL_CICADA_VSC8211 0x000b
-#define MII_STR_CICADA_VSC8211 "Cicada VSC8211 10/100/1000TX PHY"
-#define MII_MODEL_CICADA_CS8201A 0x0020
-#define MII_STR_CICADA_CS8201A "Cicada CS8201 10/100/1000TX PHY"
-#define MII_MODEL_CICADA_CS8201B 0x0021
-#define MII_STR_CICADA_CS8201B "Cicada CS8201 10/100/1000TX PHY"
-#define MII_MODEL_CICADA_CS8244 0x002c
-#define MII_STR_CICADA_CS8244 "Cicada CS8244 10/100/1000TX PHY"
-#define MII_MODEL_VITESSE_VSC8601 0x0002
-#define MII_STR_VITESSE_VSC8601 "Vitesse VSC8601 10/100/1000TX PHY"
-
-/* Davicom Semiconductor PHYs */
-#define MII_MODEL_DAVICOM_DM9102 0x0004
-#define MII_STR_DAVICOM_DM9102 "DM9102 10/100 media interface"
-#define MII_MODEL_xxDAVICOM_DM9101 0x0000
-#define MII_STR_xxDAVICOM_DM9101 "DM9101 10/100 media interface"
-
-/* Integrated Circuit Systems PHYs */
-#define MII_MODEL_xxICS_1889 0x0001
-#define MII_STR_xxICS_1889 "ICS1889 10/100 media interface"
-#define MII_MODEL_xxICS_1890 0x0002
-#define MII_STR_xxICS_1890 "ICS1890 10/100 media interface"
-#define MII_MODEL_xxICS_1892 0x0003
-#define MII_STR_xxICS_1892 "ICS1892 10/100 media interface"
-#define MII_MODEL_xxICS_1893 0x0004
-#define MII_STR_xxICS_1893 "ICS1893 10/100 media interface"
-
-/* IC Plus Corp. PHYs */
-#define MII_MODEL_ICPLUS_IP101 0x0005
-#define MII_STR_ICPLUS_IP101 "IC Plus 10/100 PHY"
-#define MII_MODEL_ICPLUS_IP1000A 0x0008
-#define MII_STR_ICPLUS_IP1000A "IC Plus 10/100/1000 media interface"
-#define MII_MODEL_ICPLUS_IP1001 0x0019
-#define MII_STR_ICPLUS_IP1001 "IC Plus IP1001 10/100/1000 media interface"
-
-/* Intel PHYs */
-#define MII_MODEL_xxINTEL_I82553AB 0x0000
-#define MII_STR_xxINTEL_I82553AB "i83553 10/100 media interface"
-#define MII_MODEL_INTEL_I82555 0x0015
-#define MII_STR_INTEL_I82555 "i82555 10/100 media interface"
-#define MII_MODEL_INTEL_I82562EM 0x0032
-#define MII_STR_INTEL_I82562EM "i82562EM 10/100 media interface"
-#define MII_MODEL_INTEL_I82562ET 0x0033
-#define MII_STR_INTEL_I82562ET "i82562ET 10/100 media interface"
-#define MII_MODEL_INTEL_I82553C 0x0035
-#define MII_STR_INTEL_I82553C "i82553 10/100 media interface"
-
-/* Jato Technologies PHYs */
-#define MII_MODEL_JATO_BASEX 0x0000
-#define MII_STR_JATO_BASEX "Jato 1000baseX media interface"
-
-/* JMicron Technologies PHYs */
-#define MII_MODEL_JMICRON_JMP211 0x0021
-#define MII_STR_JMICRON_JMP211 "JMP211 10/100/1000 media interface"
-#define MII_MODEL_JMICRON_JMP202 0x0022
-#define MII_STR_JMICRON_JMP202 "JMP202 10/100 media interface"
-
-/* Level 1 PHYs */
-#define MII_MODEL_xxLEVEL1_LXT970 0x0000
-#define MII_STR_xxLEVEL1_LXT970 "LXT970 10/100 media interface"
-
-/* National Semiconductor PHYs */
-#define MII_MODEL_NATSEMI_DP83840 0x0000
-#define MII_STR_NATSEMI_DP83840 "DP83840 10/100 media interface"
-#define MII_MODEL_NATSEMI_DP83843 0x0001
-#define MII_STR_NATSEMI_DP83843 "DP83843 10/100 media interface"
-#define MII_MODEL_NATSEMI_DP83815 0x0002
-#define MII_STR_NATSEMI_DP83815 "DP83815 10/100 media interface"
-#define MII_MODEL_NATSEMI_DP83847 0x0003
-#define MII_STR_NATSEMI_DP83847 "DP83847 10/100 media interface"
-#define MII_MODEL_NATSEMI_DP83891 0x0005
-#define MII_STR_NATSEMI_DP83891 "DP83891 10/100/1000 media interface"
-#define MII_MODEL_NATSEMI_DP83861 0x0006
-#define MII_STR_NATSEMI_DP83861 "DP83861 10/100/1000 media interface"
-#define MII_MODEL_NATSEMI_DP83865 0x0007
-#define MII_STR_NATSEMI_DP83865 "DP83865 10/100/1000 media interface"
-
-/* Quality Semiconductor PHYs */
-#define MII_MODEL_QUALSEMI_QS6612 0x0000
-#define MII_STR_QUALSEMI_QS6612 "QS6612 10/100 media interface"
-
-/* RealTek Semiconductor PHYs */
-#define MII_MODEL_REALTEK_RTL8201L 0x0020
-#define MII_STR_REALTEK_RTL8201L "RTL8201L 10/100 media interface"
-#define MII_MODEL_xxREALTEK_RTL8305SC 0x0005
-#define MII_STR_xxREALTEK_RTL8305SC "RTL8305SC 10/100 802.1q switch"
-#define MII_MODEL_xxREALTEK_RTL8169S 0x0011
-#define MII_STR_xxREALTEK_RTL8169S "RTL8169S/8110S/8211B media interface"
-
-/* Seeq PHYs */
-#define MII_MODEL_xxSEEQ_80220 0x0003
-#define MII_STR_xxSEEQ_80220 "Seeq 80220 10/100 media interface"
-#define MII_MODEL_xxSEEQ_84220 0x0004
-#define MII_STR_xxSEEQ_84220 "Seeq 84220 10/100 media interface"
-
-/* Silicon Integrated Systems PHYs */
-#define MII_MODEL_xxSIS_900 0x0000
-#define MII_STR_xxSIS_900 "SiS 900 10/100 media interface"
-
-/* SMSC PHYs */
-#define MII_MODEL_SMSC_LAN83C183 0x0004
-#define MII_STR_SMSC_LAN83C183 "SMSC LAN83C183 10/100 media interface"
-
-/* TDK */
-#define MII_MODEL_TDK_78Q2120 0x0014
-#define MII_STR_TDK_78Q2120 "TDK 78Q2120 media interface"
-
-/* Texas Instruments PHYs */
-#define MII_MODEL_xxTI_TLAN10T 0x0001
-#define MII_STR_xxTI_TLAN10T "ThunderLAN 10baseT media interface"
-#define MII_MODEL_xxTI_100VGPMI 0x0002
-#define MII_STR_xxTI_100VGPMI "ThunderLAN 100VG-AnyLan media interface"
-
-/* XaQti Corp. PHYs. */
-#define MII_MODEL_XAQTI_XMACII 0x0000
-#define MII_STR_XAQTI_XMACII "XaQti Corp. XMAC II gigabit interface"
-
-/* Marvell Semiconductor PHYs */
-#define MII_MODEL_MARVELL_E1000 0x0000
-#define MII_STR_MARVELL_E1000 "Marvell 88E1000 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1011 0x0002
-#define MII_STR_MARVELL_E1011 "Marvell 88E1011 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1000_3 0x0003
-#define MII_STR_MARVELL_E1000_3 "Marvell 88E1000 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1000S 0x0004
-#define MII_STR_MARVELL_E1000S "Marvell 88E1000S Gigabit PHY"
-#define MII_MODEL_MARVELL_E1000_5 0x0005
-#define MII_STR_MARVELL_E1000_5 "Marvell 88E1000 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1101 0x0006
-#define MII_STR_MARVELL_E1101 "Marvell 88E1101 Gigabit PHY"
-#define MII_MODEL_MARVELL_E3082 0x0008
-#define MII_STR_MARVELL_E3082 "Marvell 88E3082 10/100 Fast Ethernet PHY"
-#define MII_MODEL_MARVELL_E1112 0x0009
-#define MII_STR_MARVELL_E1112 "Marvell 88E1112 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1149 0x000b
-#define MII_STR_MARVELL_E1149 "Marvell 88E1149 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1111 0x000c
-#define MII_STR_MARVELL_E1111 "Marvell 88E1111 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1116 0x0021
-#define MII_STR_MARVELL_E1116 "Marvell 88E1116 Gigabit PHY"
-#define MII_MODEL_MARVELL_E1116R 0x0024
-#define MII_STR_MARVELL_E1116R "Marvell 88E1116R Gigabit PHY"
-#define MII_MODEL_MARVELL_E1118 0x0022
-#define MII_STR_MARVELL_E1118 "Marvell 88E1118 Gigabit PHY"
-#define MII_MODEL_MARVELL_E3016 0x0026
-#define MII_STR_MARVELL_E3016 "Marvell 88E3016 10/100 Fast Ethernet PHY"
-#define MII_MODEL_MARVELL_PHYG65G 0x0027
-#define MII_STR_MARVELL_PHYG65G "Marvell PHYG65G Gigabit PHY"
-#define MII_MODEL_xxMARVELL_E1000 0x0005
-#define MII_STR_xxMARVELL_E1000 "Marvell 88E1000 Gigabit PHY"
-#define MII_MODEL_xxMARVELL_E1011 0x0002
-#define MII_STR_xxMARVELL_E1011 "Marvell 88E1011 Gigabit PHY"
-#define MII_MODEL_xxMARVELL_E1000_3 0x0003
-#define MII_STR_xxMARVELL_E1000_3 "Marvell 88E1000 Gigabit PHY"
-#define MII_MODEL_xxMARVELL_E1000_5 0x0005
-#define MII_STR_xxMARVELL_E1000_5 "Marvell 88E1000 Gigabit PHY"
-#define MII_MODEL_xxMARVELL_E1111 0x000c
-#define MII_STR_xxMARVELL_E1111 "Marvell 88E1111 Gigabit PHY"
diff --git a/freebsd/local/opt_atalk.h b/freebsd/local/opt_atalk.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_atalk.h
+++ /dev/null
diff --git a/freebsd/local/opt_bce.h b/freebsd/local/opt_bce.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/local/opt_bce.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/local/opt_bootp.h b/freebsd/local/opt_bootp.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_bootp.h
+++ /dev/null
diff --git a/freebsd/local/opt_bpf.h b/freebsd/local/opt_bpf.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_bpf.h
+++ /dev/null
diff --git a/freebsd/local/opt_bus.h b/freebsd/local/opt_bus.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_bus.h
+++ /dev/null
diff --git a/freebsd/local/opt_cam.h b/freebsd/local/opt_cam.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_cam.h
+++ /dev/null
diff --git a/freebsd/local/opt_carp.h b/freebsd/local/opt_carp.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_carp.h
+++ /dev/null
diff --git a/freebsd/local/opt_compat.h b/freebsd/local/opt_compat.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_compat.h
+++ /dev/null
diff --git a/freebsd/local/opt_config.h b/freebsd/local/opt_config.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_config.h
+++ /dev/null
diff --git a/freebsd/local/opt_cpu.h b/freebsd/local/opt_cpu.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_cpu.h
+++ /dev/null
diff --git a/freebsd/local/opt_ddb.h b/freebsd/local/opt_ddb.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ddb.h
+++ /dev/null
diff --git a/freebsd/local/opt_device_polling.h b/freebsd/local/opt_device_polling.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_device_polling.h
+++ /dev/null
diff --git a/freebsd/local/opt_ef.h b/freebsd/local/opt_ef.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ef.h
+++ /dev/null
diff --git a/freebsd/local/opt_enc.h b/freebsd/local/opt_enc.h
deleted file mode 100644
index a06aab6c..00000000
--- a/freebsd/local/opt_enc.h
+++ /dev/null
@@ -1 +0,0 @@
-#define DEV_ENC 1
diff --git a/freebsd/local/opt_hwpmc_hooks.h b/freebsd/local/opt_hwpmc_hooks.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_hwpmc_hooks.h
+++ /dev/null
diff --git a/freebsd/local/opt_inet.h b/freebsd/local/opt_inet.h
deleted file mode 100644
index fdf70095..00000000
--- a/freebsd/local/opt_inet.h
+++ /dev/null
@@ -1 +0,0 @@
-#define INET 1
diff --git a/freebsd/local/opt_inet6.h b/freebsd/local/opt_inet6.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_inet6.h
+++ /dev/null
diff --git a/freebsd/local/opt_init_path.h b/freebsd/local/opt_init_path.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_init_path.h
+++ /dev/null
diff --git a/freebsd/local/opt_ipdivert.h b/freebsd/local/opt_ipdivert.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ipdivert.h
+++ /dev/null
diff --git a/freebsd/local/opt_ipdn.h b/freebsd/local/opt_ipdn.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ipdn.h
+++ /dev/null
diff --git a/freebsd/local/opt_ipfw.h b/freebsd/local/opt_ipfw.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ipfw.h
+++ /dev/null
diff --git a/freebsd/local/opt_ipsec.h b/freebsd/local/opt_ipsec.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ipsec.h
+++ /dev/null
diff --git a/freebsd/local/opt_ipstealth.h b/freebsd/local/opt_ipstealth.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ipstealth.h
+++ /dev/null
diff --git a/freebsd/local/opt_ipx.h b/freebsd/local/opt_ipx.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ipx.h
+++ /dev/null
diff --git a/freebsd/local/opt_kdb.h b/freebsd/local/opt_kdb.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_kdb.h
+++ /dev/null
diff --git a/freebsd/local/opt_kdtrace.h b/freebsd/local/opt_kdtrace.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_kdtrace.h
+++ /dev/null
diff --git a/freebsd/local/opt_ktrace.h b/freebsd/local/opt_ktrace.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_ktrace.h
+++ /dev/null
diff --git a/freebsd/local/opt_mbuf_profiling.h b/freebsd/local/opt_mbuf_profiling.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_mbuf_profiling.h
+++ /dev/null
diff --git a/freebsd/local/opt_mbuf_stress_test.h b/freebsd/local/opt_mbuf_stress_test.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_mbuf_stress_test.h
+++ /dev/null
diff --git a/freebsd/local/opt_mpath.h b/freebsd/local/opt_mpath.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_mpath.h
+++ /dev/null
diff --git a/freebsd/local/opt_mrouting.h b/freebsd/local/opt_mrouting.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_mrouting.h
+++ /dev/null
diff --git a/freebsd/local/opt_natm.h b/freebsd/local/opt_natm.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_natm.h
+++ /dev/null
diff --git a/freebsd/local/opt_netgraph.h b/freebsd/local/opt_netgraph.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_netgraph.h
+++ /dev/null
diff --git a/freebsd/local/opt_ntp.h b/freebsd/local/opt_ntp.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/local/opt_ntp.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/local/opt_param.h b/freebsd/local/opt_param.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_param.h
+++ /dev/null
diff --git a/freebsd/local/opt_pf.h b/freebsd/local/opt_pf.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_pf.h
+++ /dev/null
diff --git a/freebsd/local/opt_posix.h b/freebsd/local/opt_posix.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_posix.h
+++ /dev/null
diff --git a/freebsd/local/opt_printf.h b/freebsd/local/opt_printf.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_printf.h
+++ /dev/null
diff --git a/freebsd/local/opt_route.h b/freebsd/local/opt_route.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_route.h
+++ /dev/null
diff --git a/freebsd/local/opt_scsi.h b/freebsd/local/opt_scsi.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_scsi.h
+++ /dev/null
diff --git a/freebsd/local/opt_sctp.h b/freebsd/local/opt_sctp.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_sctp.h
+++ /dev/null
diff --git a/freebsd/local/opt_tcpdebug.h b/freebsd/local/opt_tcpdebug.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_tcpdebug.h
+++ /dev/null
diff --git a/freebsd/local/opt_tdma.h b/freebsd/local/opt_tdma.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_tdma.h
+++ /dev/null
diff --git a/freebsd/local/opt_usb.h b/freebsd/local/opt_usb.h
deleted file mode 100644
index f9643174..00000000
--- a/freebsd/local/opt_usb.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#define USB_HAVE_CONDVAR 1
-
-#define USB_HAVE_UGEN 0
-
-#define USB_HAVE_BUSDMA 1
-
-#define USB_HAVE_COMPAT_LINUX 0
-
-#define USB_HAVE_USER_IO 0
-
-#define USB_HAVE_MBUF 0
-
-#undef USB_VERBOSE
-
-#define USB_DEBUG 0
-
-#define USB_HAVE_TT_SUPPORT 1
-
-#define USB_HAVE_POWERD 1
diff --git a/freebsd/local/opt_vlan.h b/freebsd/local/opt_vlan.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_vlan.h
+++ /dev/null
diff --git a/freebsd/local/opt_wlan.h b/freebsd/local/opt_wlan.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_wlan.h
+++ /dev/null
diff --git a/freebsd/local/opt_zero.h b/freebsd/local/opt_zero.h
deleted file mode 100644
index e69de29b..00000000
--- a/freebsd/local/opt_zero.h
+++ /dev/null
diff --git a/freebsd/local/pci_if.c b/freebsd/local/pci_if.c
deleted file mode 100644
index 257e890b..00000000
--- a/freebsd/local/pci_if.c
+++ /dev/null
@@ -1,172 +0,0 @@
-#include <freebsd/machine/rtems-bsd-config.h>
-
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/pci/pci_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-#include <freebsd/sys/param.h>
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/kernel.h>
-#include <freebsd/sys/kobj.h>
-#include <freebsd/sys/bus.h>
-#include <freebsd/local/pci_if.h>
-
-
-static int
-null_msi_count(device_t dev, device_t child)
-{
- return (0);
-}
-
-struct kobj_method pci_read_config_method_default = {
- &pci_read_config_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_read_config_desc = {
- 0, &pci_read_config_method_default
-};
-
-struct kobj_method pci_write_config_method_default = {
- &pci_write_config_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_write_config_desc = {
- 0, &pci_write_config_method_default
-};
-
-struct kobj_method pci_get_powerstate_method_default = {
- &pci_get_powerstate_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_get_powerstate_desc = {
- 0, &pci_get_powerstate_method_default
-};
-
-struct kobj_method pci_set_powerstate_method_default = {
- &pci_set_powerstate_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_set_powerstate_desc = {
- 0, &pci_set_powerstate_method_default
-};
-
-struct kobj_method pci_get_vpd_ident_method_default = {
- &pci_get_vpd_ident_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_get_vpd_ident_desc = {
- 0, &pci_get_vpd_ident_method_default
-};
-
-struct kobj_method pci_get_vpd_readonly_method_default = {
- &pci_get_vpd_readonly_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_get_vpd_readonly_desc = {
- 0, &pci_get_vpd_readonly_method_default
-};
-
-struct kobj_method pci_enable_busmaster_method_default = {
- &pci_enable_busmaster_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_enable_busmaster_desc = {
- 0, &pci_enable_busmaster_method_default
-};
-
-struct kobj_method pci_disable_busmaster_method_default = {
- &pci_disable_busmaster_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_disable_busmaster_desc = {
- 0, &pci_disable_busmaster_method_default
-};
-
-struct kobj_method pci_enable_io_method_default = {
- &pci_enable_io_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_enable_io_desc = {
- 0, &pci_enable_io_method_default
-};
-
-struct kobj_method pci_disable_io_method_default = {
- &pci_disable_io_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_disable_io_desc = {
- 0, &pci_disable_io_method_default
-};
-
-struct kobj_method pci_assign_interrupt_method_default = {
- &pci_assign_interrupt_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_assign_interrupt_desc = {
- 0, &pci_assign_interrupt_method_default
-};
-
-struct kobj_method pci_find_extcap_method_default = {
- &pci_find_extcap_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_find_extcap_desc = {
- 0, &pci_find_extcap_method_default
-};
-
-struct kobj_method pci_alloc_msi_method_default = {
- &pci_alloc_msi_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_alloc_msi_desc = {
- 0, &pci_alloc_msi_method_default
-};
-
-struct kobj_method pci_alloc_msix_method_default = {
- &pci_alloc_msix_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_alloc_msix_desc = {
- 0, &pci_alloc_msix_method_default
-};
-
-struct kobj_method pci_remap_msix_method_default = {
- &pci_remap_msix_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_remap_msix_desc = {
- 0, &pci_remap_msix_method_default
-};
-
-struct kobj_method pci_release_msi_method_default = {
- &pci_release_msi_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pci_release_msi_desc = {
- 0, &pci_release_msi_method_default
-};
-
-struct kobj_method pci_msi_count_method_default = {
- &pci_msi_count_desc, (kobjop_t) null_msi_count
-};
-
-struct kobjop_desc pci_msi_count_desc = {
- 0, &pci_msi_count_method_default
-};
-
-struct kobj_method pci_msix_count_method_default = {
- &pci_msix_count_desc, (kobjop_t) null_msi_count
-};
-
-struct kobjop_desc pci_msix_count_desc = {
- 0, &pci_msix_count_method_default
-};
-
diff --git a/freebsd/local/pci_if.h b/freebsd/local/pci_if.h
deleted file mode 100644
index c2028bf8..00000000
--- a/freebsd/local/pci_if.h
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/pci/pci_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-
-#ifndef _pci_if_h_
-#define _pci_if_h_
-
-/** @brief Unique descriptor for the PCI_READ_CONFIG() method */
-extern struct kobjop_desc pci_read_config_desc;
-/** @brief A function implementing the PCI_READ_CONFIG() method */
-typedef u_int32_t pci_read_config_t(device_t dev, device_t child, int reg,
- int width);
-
-static __inline u_int32_t PCI_READ_CONFIG(device_t dev, device_t child, int reg,
- int width)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_read_config);
- return ((pci_read_config_t *) _m)(dev, child, reg, width);
-}
-
-/** @brief Unique descriptor for the PCI_WRITE_CONFIG() method */
-extern struct kobjop_desc pci_write_config_desc;
-/** @brief A function implementing the PCI_WRITE_CONFIG() method */
-typedef void pci_write_config_t(device_t dev, device_t child, int reg,
- u_int32_t val, int width);
-
-static __inline void PCI_WRITE_CONFIG(device_t dev, device_t child, int reg,
- u_int32_t val, int width)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_write_config);
- ((pci_write_config_t *) _m)(dev, child, reg, val, width);
-}
-
-/** @brief Unique descriptor for the PCI_GET_POWERSTATE() method */
-extern struct kobjop_desc pci_get_powerstate_desc;
-/** @brief A function implementing the PCI_GET_POWERSTATE() method */
-typedef int pci_get_powerstate_t(device_t dev, device_t child);
-
-static __inline int PCI_GET_POWERSTATE(device_t dev, device_t child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_get_powerstate);
- return ((pci_get_powerstate_t *) _m)(dev, child);
-}
-
-/** @brief Unique descriptor for the PCI_SET_POWERSTATE() method */
-extern struct kobjop_desc pci_set_powerstate_desc;
-/** @brief A function implementing the PCI_SET_POWERSTATE() method */
-typedef int pci_set_powerstate_t(device_t dev, device_t child, int state);
-
-static __inline int PCI_SET_POWERSTATE(device_t dev, device_t child, int state)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_set_powerstate);
- return ((pci_set_powerstate_t *) _m)(dev, child, state);
-}
-
-/** @brief Unique descriptor for the PCI_GET_VPD_IDENT() method */
-extern struct kobjop_desc pci_get_vpd_ident_desc;
-/** @brief A function implementing the PCI_GET_VPD_IDENT() method */
-typedef int pci_get_vpd_ident_t(device_t dev, device_t child,
- const char **identptr);
-
-static __inline int PCI_GET_VPD_IDENT(device_t dev, device_t child,
- const char **identptr)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_get_vpd_ident);
- return ((pci_get_vpd_ident_t *) _m)(dev, child, identptr);
-}
-
-/** @brief Unique descriptor for the PCI_GET_VPD_READONLY() method */
-extern struct kobjop_desc pci_get_vpd_readonly_desc;
-/** @brief A function implementing the PCI_GET_VPD_READONLY() method */
-typedef int pci_get_vpd_readonly_t(device_t dev, device_t child, const char *kw,
- const char **vptr);
-
-static __inline int PCI_GET_VPD_READONLY(device_t dev, device_t child,
- const char *kw, const char **vptr)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_get_vpd_readonly);
- return ((pci_get_vpd_readonly_t *) _m)(dev, child, kw, vptr);
-}
-
-/** @brief Unique descriptor for the PCI_ENABLE_BUSMASTER() method */
-extern struct kobjop_desc pci_enable_busmaster_desc;
-/** @brief A function implementing the PCI_ENABLE_BUSMASTER() method */
-typedef int pci_enable_busmaster_t(device_t dev, device_t child);
-
-static __inline int PCI_ENABLE_BUSMASTER(device_t dev, device_t child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_enable_busmaster);
- return ((pci_enable_busmaster_t *) _m)(dev, child);
-}
-
-/** @brief Unique descriptor for the PCI_DISABLE_BUSMASTER() method */
-extern struct kobjop_desc pci_disable_busmaster_desc;
-/** @brief A function implementing the PCI_DISABLE_BUSMASTER() method */
-typedef int pci_disable_busmaster_t(device_t dev, device_t child);
-
-static __inline int PCI_DISABLE_BUSMASTER(device_t dev, device_t child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_disable_busmaster);
- return ((pci_disable_busmaster_t *) _m)(dev, child);
-}
-
-/** @brief Unique descriptor for the PCI_ENABLE_IO() method */
-extern struct kobjop_desc pci_enable_io_desc;
-/** @brief A function implementing the PCI_ENABLE_IO() method */
-typedef int pci_enable_io_t(device_t dev, device_t child, int space);
-
-static __inline int PCI_ENABLE_IO(device_t dev, device_t child, int space)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_enable_io);
- return ((pci_enable_io_t *) _m)(dev, child, space);
-}
-
-/** @brief Unique descriptor for the PCI_DISABLE_IO() method */
-extern struct kobjop_desc pci_disable_io_desc;
-/** @brief A function implementing the PCI_DISABLE_IO() method */
-typedef int pci_disable_io_t(device_t dev, device_t child, int space);
-
-static __inline int PCI_DISABLE_IO(device_t dev, device_t child, int space)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_disable_io);
- return ((pci_disable_io_t *) _m)(dev, child, space);
-}
-
-/** @brief Unique descriptor for the PCI_ASSIGN_INTERRUPT() method */
-extern struct kobjop_desc pci_assign_interrupt_desc;
-/** @brief A function implementing the PCI_ASSIGN_INTERRUPT() method */
-typedef int pci_assign_interrupt_t(device_t dev, device_t child);
-
-static __inline int PCI_ASSIGN_INTERRUPT(device_t dev, device_t child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_assign_interrupt);
- return ((pci_assign_interrupt_t *) _m)(dev, child);
-}
-
-/** @brief Unique descriptor for the PCI_FIND_EXTCAP() method */
-extern struct kobjop_desc pci_find_extcap_desc;
-/** @brief A function implementing the PCI_FIND_EXTCAP() method */
-typedef int pci_find_extcap_t(device_t dev, device_t child, int capability,
- int *capreg);
-
-static __inline int PCI_FIND_EXTCAP(device_t dev, device_t child,
- int capability, int *capreg)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_find_extcap);
- return ((pci_find_extcap_t *) _m)(dev, child, capability, capreg);
-}
-
-/** @brief Unique descriptor for the PCI_ALLOC_MSI() method */
-extern struct kobjop_desc pci_alloc_msi_desc;
-/** @brief A function implementing the PCI_ALLOC_MSI() method */
-typedef int pci_alloc_msi_t(device_t dev, device_t child, int *count);
-
-static __inline int PCI_ALLOC_MSI(device_t dev, device_t child, int *count)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_alloc_msi);
- return ((pci_alloc_msi_t *) _m)(dev, child, count);
-}
-
-/** @brief Unique descriptor for the PCI_ALLOC_MSIX() method */
-extern struct kobjop_desc pci_alloc_msix_desc;
-/** @brief A function implementing the PCI_ALLOC_MSIX() method */
-typedef int pci_alloc_msix_t(device_t dev, device_t child, int *count);
-
-static __inline int PCI_ALLOC_MSIX(device_t dev, device_t child, int *count)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_alloc_msix);
- return ((pci_alloc_msix_t *) _m)(dev, child, count);
-}
-
-/** @brief Unique descriptor for the PCI_REMAP_MSIX() method */
-extern struct kobjop_desc pci_remap_msix_desc;
-/** @brief A function implementing the PCI_REMAP_MSIX() method */
-typedef int pci_remap_msix_t(device_t dev, device_t child, int count,
- const u_int *vectors);
-
-static __inline int PCI_REMAP_MSIX(device_t dev, device_t child, int count,
- const u_int *vectors)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_remap_msix);
- return ((pci_remap_msix_t *) _m)(dev, child, count, vectors);
-}
-
-/** @brief Unique descriptor for the PCI_RELEASE_MSI() method */
-extern struct kobjop_desc pci_release_msi_desc;
-/** @brief A function implementing the PCI_RELEASE_MSI() method */
-typedef int pci_release_msi_t(device_t dev, device_t child);
-
-static __inline int PCI_RELEASE_MSI(device_t dev, device_t child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_release_msi);
- return ((pci_release_msi_t *) _m)(dev, child);
-}
-
-/** @brief Unique descriptor for the PCI_MSI_COUNT() method */
-extern struct kobjop_desc pci_msi_count_desc;
-/** @brief A function implementing the PCI_MSI_COUNT() method */
-typedef int pci_msi_count_t(device_t dev, device_t child);
-
-static __inline int PCI_MSI_COUNT(device_t dev, device_t child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_msi_count);
- return ((pci_msi_count_t *) _m)(dev, child);
-}
-
-/** @brief Unique descriptor for the PCI_MSIX_COUNT() method */
-extern struct kobjop_desc pci_msix_count_desc;
-/** @brief A function implementing the PCI_MSIX_COUNT() method */
-typedef int pci_msix_count_t(device_t dev, device_t child);
-
-static __inline int PCI_MSIX_COUNT(device_t dev, device_t child)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pci_msix_count);
- return ((pci_msix_count_t *) _m)(dev, child);
-}
-
-#endif /* _pci_if_h_ */
diff --git a/freebsd/local/pcib_if.c b/freebsd/local/pcib_if.c
deleted file mode 100644
index cc460893..00000000
--- a/freebsd/local/pcib_if.c
+++ /dev/null
@@ -1,101 +0,0 @@
-#include <freebsd/machine/rtems-bsd-config.h>
-
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/pci/pcib_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-#include <freebsd/sys/param.h>
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/kernel.h>
-#include <freebsd/sys/kobj.h>
-#include <freebsd/sys/bus.h>
-#include <freebsd/dev/pci/pcivar.h>
-#include <freebsd/local/pcib_if.h>
-
-
-static int
-null_route_interrupt(device_t pcib, device_t dev, int pin)
-{
- return (PCI_INVALID_IRQ);
-}
-
-struct kobj_method pcib_maxslots_method_default = {
- &pcib_maxslots_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_maxslots_desc = {
- 0, &pcib_maxslots_method_default
-};
-
-struct kobj_method pcib_read_config_method_default = {
- &pcib_read_config_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_read_config_desc = {
- 0, &pcib_read_config_method_default
-};
-
-struct kobj_method pcib_write_config_method_default = {
- &pcib_write_config_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_write_config_desc = {
- 0, &pcib_write_config_method_default
-};
-
-struct kobj_method pcib_route_interrupt_method_default = {
- &pcib_route_interrupt_desc, (kobjop_t) null_route_interrupt
-};
-
-struct kobjop_desc pcib_route_interrupt_desc = {
- 0, &pcib_route_interrupt_method_default
-};
-
-struct kobj_method pcib_alloc_msi_method_default = {
- &pcib_alloc_msi_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_alloc_msi_desc = {
- 0, &pcib_alloc_msi_method_default
-};
-
-struct kobj_method pcib_release_msi_method_default = {
- &pcib_release_msi_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_release_msi_desc = {
- 0, &pcib_release_msi_method_default
-};
-
-struct kobj_method pcib_alloc_msix_method_default = {
- &pcib_alloc_msix_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_alloc_msix_desc = {
- 0, &pcib_alloc_msix_method_default
-};
-
-struct kobj_method pcib_release_msix_method_default = {
- &pcib_release_msix_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_release_msix_desc = {
- 0, &pcib_release_msix_method_default
-};
-
-struct kobj_method pcib_map_msi_method_default = {
- &pcib_map_msi_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc pcib_map_msi_desc = {
- 0, &pcib_map_msi_method_default
-};
-
diff --git a/freebsd/local/pcib_if.h b/freebsd/local/pcib_if.h
deleted file mode 100644
index ad659176..00000000
--- a/freebsd/local/pcib_if.h
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/pci/pcib_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-
-#ifndef _pcib_if_h_
-#define _pcib_if_h_
-
-/** @brief Unique descriptor for the PCIB_MAXSLOTS() method */
-extern struct kobjop_desc pcib_maxslots_desc;
-/** @brief A function implementing the PCIB_MAXSLOTS() method */
-typedef int pcib_maxslots_t(device_t dev);
-
-static __inline int PCIB_MAXSLOTS(device_t dev)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pcib_maxslots);
- return ((pcib_maxslots_t *) _m)(dev);
-}
-
-/** @brief Unique descriptor for the PCIB_READ_CONFIG() method */
-extern struct kobjop_desc pcib_read_config_desc;
-/** @brief A function implementing the PCIB_READ_CONFIG() method */
-typedef u_int32_t pcib_read_config_t(device_t dev, u_int bus, u_int slot,
- u_int func, u_int reg, int width);
-
-static __inline u_int32_t PCIB_READ_CONFIG(device_t dev, u_int bus, u_int slot,
- u_int func, u_int reg, int width)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pcib_read_config);
- return ((pcib_read_config_t *) _m)(dev, bus, slot, func, reg, width);
-}
-
-/** @brief Unique descriptor for the PCIB_WRITE_CONFIG() method */
-extern struct kobjop_desc pcib_write_config_desc;
-/** @brief A function implementing the PCIB_WRITE_CONFIG() method */
-typedef void pcib_write_config_t(device_t dev, u_int bus, u_int slot,
- u_int func, u_int reg, u_int32_t value,
- int width);
-
-static __inline void PCIB_WRITE_CONFIG(device_t dev, u_int bus, u_int slot,
- u_int func, u_int reg, u_int32_t value,
- int width)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,pcib_write_config);
- ((pcib_write_config_t *) _m)(dev, bus, slot, func, reg, value, width);
-}
-
-/** @brief Unique descriptor for the PCIB_ROUTE_INTERRUPT() method */
-extern struct kobjop_desc pcib_route_interrupt_desc;
-/** @brief A function implementing the PCIB_ROUTE_INTERRUPT() method */
-typedef int pcib_route_interrupt_t(device_t pcib, device_t dev, int pin);
-
-static __inline int PCIB_ROUTE_INTERRUPT(device_t pcib, device_t dev, int pin)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)pcib)->ops,pcib_route_interrupt);
- return ((pcib_route_interrupt_t *) _m)(pcib, dev, pin);
-}
-
-/** @brief Unique descriptor for the PCIB_ALLOC_MSI() method */
-extern struct kobjop_desc pcib_alloc_msi_desc;
-/** @brief A function implementing the PCIB_ALLOC_MSI() method */
-typedef int pcib_alloc_msi_t(device_t pcib, device_t dev, int count,
- int maxcount, int *irqs);
-
-static __inline int PCIB_ALLOC_MSI(device_t pcib, device_t dev, int count,
- int maxcount, int *irqs)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)pcib)->ops,pcib_alloc_msi);
- return ((pcib_alloc_msi_t *) _m)(pcib, dev, count, maxcount, irqs);
-}
-
-/** @brief Unique descriptor for the PCIB_RELEASE_MSI() method */
-extern struct kobjop_desc pcib_release_msi_desc;
-/** @brief A function implementing the PCIB_RELEASE_MSI() method */
-typedef int pcib_release_msi_t(device_t pcib, device_t dev, int count,
- int *irqs);
-
-static __inline int PCIB_RELEASE_MSI(device_t pcib, device_t dev, int count,
- int *irqs)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)pcib)->ops,pcib_release_msi);
- return ((pcib_release_msi_t *) _m)(pcib, dev, count, irqs);
-}
-
-/** @brief Unique descriptor for the PCIB_ALLOC_MSIX() method */
-extern struct kobjop_desc pcib_alloc_msix_desc;
-/** @brief A function implementing the PCIB_ALLOC_MSIX() method */
-typedef int pcib_alloc_msix_t(device_t pcib, device_t dev, int *irq);
-
-static __inline int PCIB_ALLOC_MSIX(device_t pcib, device_t dev, int *irq)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)pcib)->ops,pcib_alloc_msix);
- return ((pcib_alloc_msix_t *) _m)(pcib, dev, irq);
-}
-
-/** @brief Unique descriptor for the PCIB_RELEASE_MSIX() method */
-extern struct kobjop_desc pcib_release_msix_desc;
-/** @brief A function implementing the PCIB_RELEASE_MSIX() method */
-typedef int pcib_release_msix_t(device_t pcib, device_t dev, int irq);
-
-static __inline int PCIB_RELEASE_MSIX(device_t pcib, device_t dev, int irq)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)pcib)->ops,pcib_release_msix);
- return ((pcib_release_msix_t *) _m)(pcib, dev, irq);
-}
-
-/** @brief Unique descriptor for the PCIB_MAP_MSI() method */
-extern struct kobjop_desc pcib_map_msi_desc;
-/** @brief A function implementing the PCIB_MAP_MSI() method */
-typedef int pcib_map_msi_t(device_t pcib, device_t dev, int irq, uint64_t *addr,
- uint32_t *data);
-
-static __inline int PCIB_MAP_MSI(device_t pcib, device_t dev, int irq,
- uint64_t *addr, uint32_t *data)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)pcib)->ops,pcib_map_msi);
- return ((pcib_map_msi_t *) _m)(pcib, dev, irq, addr, data);
-}
-
-#endif /* _pcib_if_h_ */
diff --git a/freebsd/local/usb_if.c b/freebsd/local/usb_if.c
deleted file mode 100644
index db9b2670..00000000
--- a/freebsd/local/usb_if.c
+++ /dev/null
@@ -1,29 +0,0 @@
-#include <freebsd/machine/rtems-bsd-config.h>
-
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/usb/usb_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-#include <freebsd/sys/param.h>
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/kernel.h>
-#include <freebsd/sys/kobj.h>
-#include <freebsd/sys/bus.h>
-#include <freebsd/local/usb_if.h>
-
-struct kobj_method usb_handle_request_method_default = {
- &usb_handle_request_desc, (kobjop_t) kobj_error_method
-};
-
-struct kobjop_desc usb_handle_request_desc = {
- 0, &usb_handle_request_method_default
-};
-
diff --git a/freebsd/local/usb_if.h b/freebsd/local/usb_if.h
deleted file mode 100644
index 6f4a15a3..00000000
--- a/freebsd/local/usb_if.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from source file
- * dev/usb/usb_if.m
- * with
- * makeobjops.awk
- *
- * See the source file for legal information
- */
-
-
-#ifndef _usb_if_h_
-#define _usb_if_h_
-
-/** @brief Unique descriptor for the USB_HANDLE_REQUEST() method */
-extern struct kobjop_desc usb_handle_request_desc;
-/** @brief A function implementing the USB_HANDLE_REQUEST() method */
-typedef int usb_handle_request_t(device_t dev, const void *req,
- /* pointer to the device request */ void **pptr, /* data pointer */ uint16_t *plen, /* maximum transfer length */ uint16_t offset, /* data offset */ uint8_t *pstate);
-
-static __inline int USB_HANDLE_REQUEST(device_t dev, const void *req,
- /* pointer to the device request */ void **pptr, /* data pointer */ uint16_t *plen, /* maximum transfer length */ uint16_t offset, /* data offset */ uint8_t *pstate)
-{
- kobjop_t _m;
- KOBJOPLOOKUP(((kobj_t)dev)->ops,usb_handle_request);
- return ((usb_handle_request_t *) _m)(dev, req, pptr, plen, offset, pstate);
-}
-
-#endif /* _usb_if_h_ */
diff --git a/freebsd/local/usbdevs.h b/freebsd/local/usbdevs.h
deleted file mode 100644
index 79bee891..00000000
--- a/freebsd/local/usbdevs.h
+++ /dev/null
@@ -1,3433 +0,0 @@
-/* ??? */
-
-/*
- * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
- *
- * generated from:
- * FreeBSD
- */
-/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
-
-/*-
- * Copyright (c) 1998-2004 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.
- *
- * 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.
- */
-
-/*
- * List of known USB vendors
- *
- * USB.org publishes a VID list of USB-IF member companies at
- * http://www.usb.org/developers/tools
- * Note that it does not show companies that have obtained a Vendor ID
- * without becoming full members.
- *
- * Please note that these IDs do not do anything. Adding an ID here and
- * regenerating the usbdevs.h and usbdevs_data.h only makes a symbolic name
- * available to the source code and does not change any functionality, nor
- * does it make your device available to a specific driver.
- * It will however make the descriptive string available if a device does not
- * provide the string itself.
- *
- * After adding a vendor ID VNDR and a product ID PRDCT you will have the
- * following extra defines:
- * #define USB_VENDOR_VNDR 0x????
- * #define USB_PRODUCT_VNDR_PRDCT 0x????
- *
- * You may have to add these defines to the respective probe routines to
- * make the device recognised by the appropriate device driver.
- */
-
-#define USB_VENDOR_UNKNOWN1 0x0053 /* Unknown vendor */
-#define USB_VENDOR_UNKNOWN2 0x0105 /* Unknown vendor */
-#define USB_VENDOR_EGALAX2 0x0123 /* eGalax, Inc. */
-#define USB_VENDOR_CHIPSBANK 0x0204 /* Chipsbank Microelectronics Co. */
-#define USB_VENDOR_HUMAX 0x02ad /* HUMAX */
-#define USB_VENDOR_LTS 0x0386 /* LTS */
-#define USB_VENDOR_BWCT 0x03da /* Bernd Walter Computer Technology */
-#define USB_VENDOR_AOX 0x03e8 /* AOX */
-#define USB_VENDOR_THESYS 0x03e9 /* Thesys */
-#define USB_VENDOR_DATABROADCAST 0x03ea /* Data Broadcasting */
-#define USB_VENDOR_ATMEL 0x03eb /* Atmel */
-#define USB_VENDOR_IWATSU 0x03ec /* Iwatsu America */
-#define USB_VENDOR_MITSUMI 0x03ee /* Mitsumi */
-#define USB_VENDOR_HP 0x03f0 /* Hewlett Packard */
-#define USB_VENDOR_GENOA 0x03f1 /* Genoa */
-#define USB_VENDOR_OAK 0x03f2 /* Oak */
-#define USB_VENDOR_ADAPTEC 0x03f3 /* Adaptec */
-#define USB_VENDOR_DIEBOLD 0x03f4 /* Diebold */
-#define USB_VENDOR_SIEMENSELECTRO 0x03f5 /* Siemens Electromechanical */
-#define USB_VENDOR_EPSONIMAGING 0x03f8 /* Epson Imaging */
-#define USB_VENDOR_KEYTRONIC 0x03f9 /* KeyTronic */
-#define USB_VENDOR_OPTI 0x03fb /* OPTi */
-#define USB_VENDOR_ELITEGROUP 0x03fc /* Elitegroup */
-#define USB_VENDOR_XILINX 0x03fd /* Xilinx */
-#define USB_VENDOR_FARALLON 0x03fe /* Farallon Communications */
-#define USB_VENDOR_NATIONAL 0x0400 /* National Semiconductor */
-#define USB_VENDOR_NATIONALREG 0x0401 /* National Registry */
-#define USB_VENDOR_ACERLABS 0x0402 /* Acer Labs */
-#define USB_VENDOR_FTDI 0x0403 /* Future Technology Devices */
-#define USB_VENDOR_NCR 0x0404 /* NCR */
-#define USB_VENDOR_SYNOPSYS2 0x0405 /* Synopsys */
-#define USB_VENDOR_FUJITSUICL 0x0406 /* Fujitsu-ICL */
-#define USB_VENDOR_FUJITSU2 0x0407 /* Fujitsu Personal Systems */
-#define USB_VENDOR_QUANTA 0x0408 /* Quanta */
-#define USB_VENDOR_NEC 0x0409 /* NEC */
-#define USB_VENDOR_KODAK 0x040a /* Eastman Kodak */
-#define USB_VENDOR_WELTREND 0x040b /* Weltrend */
-#define USB_VENDOR_VIA 0x040d /* VIA */
-#define USB_VENDOR_MCCI 0x040e /* MCCI */
-#define USB_VENDOR_MELCO 0x0411 /* Melco */
-#define USB_VENDOR_LEADTEK 0x0413 /* Leadtek */
-#define USB_VENDOR_WINBOND 0x0416 /* Winbond */
-#define USB_VENDOR_PHOENIX 0x041a /* Phoenix */
-#define USB_VENDOR_CREATIVE 0x041e /* Creative Labs */
-#define USB_VENDOR_NOKIA 0x0421 /* Nokia */
-#define USB_VENDOR_ADI 0x0422 /* ADI Systems */
-#define USB_VENDOR_CATC 0x0423 /* Computer Access Technology */
-#define USB_VENDOR_SMC2 0x0424 /* Standard Microsystems */
-#define USB_VENDOR_MOTOROLA_HK 0x0425 /* Motorola HK */
-#define USB_VENDOR_GRAVIS 0x0428 /* Advanced Gravis Computer */
-#define USB_VENDOR_CIRRUSLOGIC 0x0429 /* Cirrus Logic */
-#define USB_VENDOR_INNOVATIVE 0x042c /* Innovative Semiconductors */
-#define USB_VENDOR_MOLEX 0x042f /* Molex */
-#define USB_VENDOR_SUN 0x0430 /* Sun Microsystems */
-#define USB_VENDOR_UNISYS 0x0432 /* Unisys */
-#define USB_VENDOR_TAUGA 0x0436 /* Taugagreining HF */
-#define USB_VENDOR_AMD 0x0438 /* Advanced Micro Devices */
-#define USB_VENDOR_LEXMARK 0x043d /* Lexmark International */
-#define USB_VENDOR_LG 0x043e /* LG Electronics */
-#define USB_VENDOR_NANAO 0x0440 /* NANAO */
-#define USB_VENDOR_GATEWAY 0x0443 /* Gateway 2000 */
-#define USB_VENDOR_NMB 0x0446 /* NMB */
-#define USB_VENDOR_ALPS 0x044e /* Alps Electric */
-#define USB_VENDOR_THRUST 0x044f /* Thrustmaster */
-#define USB_VENDOR_TI 0x0451 /* Texas Instruments */
-#define USB_VENDOR_ANALOGDEVICES 0x0456 /* Analog Devices */
-#define USB_VENDOR_SIS 0x0457 /* Silicon Integrated Systems Corp. */
-#define USB_VENDOR_KYE 0x0458 /* KYE Systems */
-#define USB_VENDOR_DIAMOND2 0x045a /* Diamond (Supra) */
-#define USB_VENDOR_RENESAS 0x045b /* Renesas */
-#define USB_VENDOR_MICROSOFT 0x045e /* Microsoft */
-#define USB_VENDOR_PRIMAX 0x0461 /* Primax Electronics */
-#define USB_VENDOR_MGE 0x0463 /* MGE UPS Systems */
-#define USB_VENDOR_AMP 0x0464 /* AMP */
-#define USB_VENDOR_CHERRY 0x046a /* Cherry Mikroschalter */
-#define USB_VENDOR_MEGATRENDS 0x046b /* American Megatrends */
-#define USB_VENDOR_LOGITECH 0x046d /* Logitech */
-#define USB_VENDOR_BTC 0x046e /* Behavior Tech. Computer */
-#define USB_VENDOR_PHILIPS 0x0471 /* Philips */
-#define USB_VENDOR_SUN2 0x0472 /* Sun Microsystems (offical) */
-#define USB_VENDOR_SANYO 0x0474 /* Sanyo Electric */
-#define USB_VENDOR_SEAGATE 0x0477 /* Seagate */
-#define USB_VENDOR_CONNECTIX 0x0478 /* Connectix */
-#define USB_VENDOR_SEMTECH 0x047a /* Semtech */
-#define USB_VENDOR_KENSINGTON 0x047d /* Kensington */
-#define USB_VENDOR_LUCENT 0x047e /* Lucent */
-#define USB_VENDOR_PLANTRONICS 0x047f /* Plantronics */
-#define USB_VENDOR_KYOCERA 0x0482 /* Kyocera Wireless Corp. */
-#define USB_VENDOR_STMICRO 0x0483 /* STMicroelectronics */
-#define USB_VENDOR_FOXCONN 0x0489 /* Foxconn */
-#define USB_VENDOR_MEIZU 0x0492 /* Meizu Electronics */
-#define USB_VENDOR_YAMAHA 0x0499 /* YAMAHA */
-#define USB_VENDOR_COMPAQ 0x049f /* Compaq */
-#define USB_VENDOR_HITACHI 0x04a4 /* Hitachi */
-#define USB_VENDOR_ACERP 0x04a5 /* Acer Peripherals */
-#define USB_VENDOR_DAVICOM 0x04a6 /* Davicom */
-#define USB_VENDOR_VISIONEER 0x04a7 /* Visioneer */
-#define USB_VENDOR_CANON 0x04a9 /* Canon */
-#define USB_VENDOR_NIKON 0x04b0 /* Nikon */
-#define USB_VENDOR_PAN 0x04b1 /* Pan International */
-#define USB_VENDOR_IBM 0x04b3 /* IBM */
-#define USB_VENDOR_CYPRESS 0x04b4 /* Cypress Semiconductor */
-#define USB_VENDOR_ROHM 0x04b5 /* ROHM */
-#define USB_VENDOR_COMPAL 0x04b7 /* Compal */
-#define USB_VENDOR_EPSON 0x04b8 /* Seiko Epson */
-#define USB_VENDOR_RAINBOW 0x04b9 /* Rainbow Technologies */
-#define USB_VENDOR_IODATA 0x04bb /* I-O Data */
-#define USB_VENDOR_TDK 0x04bf /* TDK */
-#define USB_VENDOR_3COMUSR 0x04c1 /* U.S. Robotics */
-#define USB_VENDOR_METHODE 0x04c2 /* Methode Electronics Far East */
-#define USB_VENDOR_MAXISWITCH 0x04c3 /* Maxi Switch */
-#define USB_VENDOR_LOCKHEEDMER 0x04c4 /* Lockheed Martin Energy Research */
-#define USB_VENDOR_FUJITSU 0x04c5 /* Fujitsu */
-#define USB_VENDOR_TOSHIBAAM 0x04c6 /* Toshiba America */
-#define USB_VENDOR_MICROMACRO 0x04c7 /* Micro Macro Technologies */
-#define USB_VENDOR_KONICA 0x04c8 /* Konica */
-#define USB_VENDOR_LITEON 0x04ca /* Lite-On Technology */
-#define USB_VENDOR_FUJIPHOTO 0x04cb /* Fuji Photo Film */
-#define USB_VENDOR_PHILIPSSEMI 0x04cc /* Philips Semiconductors */
-#define USB_VENDOR_TATUNG 0x04cd /* Tatung Co. Of America */
-#define USB_VENDOR_SCANLOGIC 0x04ce /* ScanLogic */
-#define USB_VENDOR_MYSON 0x04cf /* Myson Technology */
-#define USB_VENDOR_DIGI2 0x04d0 /* Digi */
-#define USB_VENDOR_ITTCANON 0x04d1 /* ITT Canon */
-#define USB_VENDOR_ALTEC 0x04d2 /* Altec Lansing */
-#define USB_VENDOR_LSI 0x04d4 /* LSI */
-#define USB_VENDOR_MENTORGRAPHICS 0x04d6 /* Mentor Graphics */
-#define USB_VENDOR_ITUNERNET 0x04d8 /* I-Tuner Networks */
-#define USB_VENDOR_HOLTEK 0x04d9 /* Holtek Semiconductor, Inc. */
-#define USB_VENDOR_PANASONIC 0x04da /* Panasonic (Matsushita) */
-#define USB_VENDOR_HUANHSIN 0x04dc /* Huan Hsin */
-#define USB_VENDOR_SHARP 0x04dd /* Sharp */
-#define USB_VENDOR_IIYAMA 0x04e1 /* Iiyama */
-#define USB_VENDOR_SHUTTLE 0x04e6 /* Shuttle Technology */
-#define USB_VENDOR_ELO 0x04e7 /* Elo TouchSystems */
-#define USB_VENDOR_SAMSUNG 0x04e8 /* Samsung Electronics */
-#define USB_VENDOR_NORTHSTAR 0x04eb /* Northstar */
-#define USB_VENDOR_TOKYOELECTRON 0x04ec /* Tokyo Electron */
-#define USB_VENDOR_ANNABOOKS 0x04ed /* Annabooks */
-#define USB_VENDOR_JVC 0x04f1 /* JVC */
-#define USB_VENDOR_CHICONY 0x04f2 /* Chicony Electronics */
-#define USB_VENDOR_ELAN 0x04f3 /* Elan */
-#define USB_VENDOR_NEWNEX 0x04f7 /* Newnex */
-#define USB_VENDOR_BROTHER 0x04f9 /* Brother Industries */
-#define USB_VENDOR_DALLAS 0x04fa /* Dallas Semiconductor */
-#define USB_VENDOR_AIPTEK2 0x04fc /* AIPTEK International */
-#define USB_VENDOR_PFU 0x04fe /* PFU */
-#define USB_VENDOR_FUJIKURA 0x0501 /* Fujikura/DDK */
-#define USB_VENDOR_ACER 0x0502 /* Acer */
-#define USB_VENDOR_3COM 0x0506 /* 3Com */
-#define USB_VENDOR_HOSIDEN 0x0507 /* Hosiden Corporation */
-#define USB_VENDOR_AZTECH 0x0509 /* Aztech Systems */
-#define USB_VENDOR_BELKIN 0x050d /* Belkin Components */
-#define USB_VENDOR_KAWATSU 0x050f /* Kawatsu Semiconductor */
-#define USB_VENDOR_FCI 0x0514 /* FCI */
-#define USB_VENDOR_LONGWELL 0x0516 /* Longwell */
-#define USB_VENDOR_COMPOSITE 0x0518 /* Composite */
-#define USB_VENDOR_STAR 0x0519 /* Star Micronics */
-#define USB_VENDOR_APC 0x051d /* American Power Conversion */
-#define USB_VENDOR_SCIATLANTA 0x051e /* Scientific Atlanta */
-#define USB_VENDOR_TSM 0x0520 /* TSM */
-#define USB_VENDOR_CONNECTEK 0x0522 /* Advanced Connectek USA */
-#define USB_VENDOR_NETCHIP 0x0525 /* NetChip Technology */
-#define USB_VENDOR_ALTRA 0x0527 /* ALTRA */
-#define USB_VENDOR_ATI 0x0528 /* ATI Technologies */
-#define USB_VENDOR_AKS 0x0529 /* Aladdin Knowledge Systems */
-#define USB_VENDOR_TEKOM 0x052b /* Tekom */
-#define USB_VENDOR_CANONDEV 0x052c /* Canon */
-#define USB_VENDOR_WACOMTECH 0x0531 /* Wacom */
-#define USB_VENDOR_INVENTEC 0x0537 /* Inventec */
-#define USB_VENDOR_SHYHSHIUN 0x0539 /* Shyh Shiun Terminals */
-#define USB_VENDOR_PREHWERKE 0x053a /* Preh Werke Gmbh & Co. KG */
-#define USB_VENDOR_SYNOPSYS 0x053f /* Synopsys */
-#define USB_VENDOR_UNIACCESS 0x0540 /* Universal Access */
-#define USB_VENDOR_VIEWSONIC 0x0543 /* ViewSonic */
-#define USB_VENDOR_XIRLINK 0x0545 /* Xirlink */
-#define USB_VENDOR_ANCHOR 0x0547 /* Anchor Chips */
-#define USB_VENDOR_SONY 0x054c /* Sony */
-#define USB_VENDOR_FUJIXEROX 0x0550 /* Fuji Xerox */
-#define USB_VENDOR_VISION 0x0553 /* VLSI Vision */
-#define USB_VENDOR_ASAHIKASEI 0x0556 /* Asahi Kasei Microsystems */
-#define USB_VENDOR_ATEN 0x0557 /* ATEN International */
-#define USB_VENDOR_SAMSUNG2 0x055d /* Samsung Electronics */
-#define USB_VENDOR_MUSTEK 0x055f /* Mustek Systems */
-#define USB_VENDOR_TELEX 0x0562 /* Telex Communications */
-#define USB_VENDOR_CHINON 0x0564 /* Chinon */
-#define USB_VENDOR_PERACOM 0x0565 /* Peracom Networks */
-#define USB_VENDOR_ALCOR2 0x0566 /* Alcor Micro */
-#define USB_VENDOR_XYRATEX 0x0567 /* Xyratex */
-#define USB_VENDOR_WACOM 0x056a /* WACOM */
-#define USB_VENDOR_ETEK 0x056c /* e-TEK Labs */
-#define USB_VENDOR_EIZO 0x056d /* EIZO */
-#define USB_VENDOR_ELECOM 0x056e /* Elecom */
-#define USB_VENDOR_CONEXANT 0x0572 /* Conexant */
-#define USB_VENDOR_HAUPPAUGE 0x0573 /* Hauppauge Computer Works */
-#define USB_VENDOR_BAFO 0x0576 /* BAFO/Quality Computer Accessories */
-#define USB_VENDOR_YEDATA 0x057b /* Y-E Data */
-#define USB_VENDOR_AVM 0x057c /* AVM */
-#define USB_VENDOR_QUICKSHOT 0x057f /* Quickshot */
-#define USB_VENDOR_ROLAND 0x0582 /* Roland */
-#define USB_VENDOR_ROCKFIRE 0x0583 /* Rockfire */
-#define USB_VENDOR_RATOC 0x0584 /* RATOC Systems */
-#define USB_VENDOR_ZYXEL 0x0586 /* ZyXEL Communication */
-#define USB_VENDOR_INFINEON 0x058b /* Infineon */
-#define USB_VENDOR_MICREL 0x058d /* Micrel */
-#define USB_VENDOR_ALCOR 0x058f /* Alcor Micro */
-#define USB_VENDOR_OMRON 0x0590 /* OMRON */
-#define USB_VENDOR_ZORAN 0x0595 /* Zoran Microelectronics */
-#define USB_VENDOR_NIIGATA 0x0598 /* Niigata */
-#define USB_VENDOR_IOMEGA 0x059b /* Iomega */
-#define USB_VENDOR_ATREND 0x059c /* A-Trend Technology */
-#define USB_VENDOR_AID 0x059d /* Advanced Input Devices */
-#define USB_VENDOR_LACIE 0x059f /* LaCie */
-#define USB_VENDOR_FUJIFILM 0x05a2 /* Fuji Film */
-#define USB_VENDOR_ARC 0x05a3 /* ARC */
-#define USB_VENDOR_ORTEK 0x05a4 /* Ortek */
-#define USB_VENDOR_CISCOLINKSYS3 0x05a6 /* Cisco-Linksys */
-#define USB_VENDOR_BOSE 0x05a7 /* Bose */
-#define USB_VENDOR_OMNIVISION 0x05a9 /* OmniVision */
-#define USB_VENDOR_INSYSTEM 0x05ab /* In-System Design */
-#define USB_VENDOR_APPLE 0x05ac /* Apple Computer */
-#define USB_VENDOR_YCCABLE 0x05ad /* Y.C. Cable */
-#define USB_VENDOR_DIGITALPERSONA 0x05ba /* DigitalPersona */
-#define USB_VENDOR_3G 0x05bc /* 3G Green Green Globe */
-#define USB_VENDOR_RAFI 0x05bd /* RAFI */
-#define USB_VENDOR_TYCO 0x05be /* Tyco */
-#define USB_VENDOR_KAWASAKI 0x05c1 /* Kawasaki */
-#define USB_VENDOR_DIGI 0x05c5 /* Digi International */
-#define USB_VENDOR_QUALCOMM2 0x05c6 /* Qualcomm */
-#define USB_VENDOR_QTRONIX 0x05c7 /* Qtronix */
-#define USB_VENDOR_FOXLINK 0x05c8 /* Foxlink */
-#define USB_VENDOR_RICOH 0x05ca /* Ricoh */
-#define USB_VENDOR_ELSA 0x05cc /* ELSA */
-#define USB_VENDOR_SCIWORX 0x05ce /* sci-worx */
-#define USB_VENDOR_BRAINBOXES 0x05d1 /* Brainboxes Limited */
-#define USB_VENDOR_ULTIMA 0x05d8 /* Ultima */
-#define USB_VENDOR_AXIOHM 0x05d9 /* Axiohm Transaction Solutions */
-#define USB_VENDOR_MICROTEK 0x05da /* Microtek */
-#define USB_VENDOR_SUNTAC 0x05db /* SUN Corporation */
-#define USB_VENDOR_LEXAR 0x05dc /* Lexar Media */
-#define USB_VENDOR_ADDTRON 0x05dd /* Addtron */
-#define USB_VENDOR_SYMBOL 0x05e0 /* Symbol Technologies */
-#define USB_VENDOR_SYNTEK 0x05e1 /* Syntek */
-#define USB_VENDOR_GENESYS 0x05e3 /* Genesys Logic */
-#define USB_VENDOR_FUJI 0x05e5 /* Fuji Electric */
-#define USB_VENDOR_KEITHLEY 0x05e6 /* Keithley Instruments */
-#define USB_VENDOR_EIZONANAO 0x05e7 /* EIZO Nanao */
-#define USB_VENDOR_KLSI 0x05e9 /* Kawasaki LSI */
-#define USB_VENDOR_FFC 0x05eb /* FFC */
-#define USB_VENDOR_ANKO 0x05ef /* Anko Electronic */
-#define USB_VENDOR_PIENGINEERING 0x05f3 /* P.I. Engineering */
-#define USB_VENDOR_AOC 0x05f6 /* AOC International */
-#define USB_VENDOR_CHIC 0x05fe /* Chic Technology */
-#define USB_VENDOR_BARCO 0x0600 /* Barco Display Systems */
-#define USB_VENDOR_BRIDGE 0x0607 /* Bridge Information */
-#define USB_VENDOR_SOLIDYEAR 0x060b /* Solid Year */
-#define USB_VENDOR_BIORAD 0x0614 /* Bio-Rad Laboratories */
-#define USB_VENDOR_MACALLY 0x0618 /* Macally */
-#define USB_VENDOR_ACTLABS 0x061c /* Act Labs */
-#define USB_VENDOR_ALARIS 0x0620 /* Alaris */
-#define USB_VENDOR_APEX 0x0624 /* Apex */
-#define USB_VENDOR_CREATIVE3 0x062a /* Creative Labs */
-#define USB_VENDOR_VIVITAR 0x0636 /* Vivitar */
-#define USB_VENDOR_GUNZE 0x0637 /* Gunze Electronics USA */
-#define USB_VENDOR_AVISION 0x0638 /* Avision */
-#define USB_VENDOR_TEAC 0x0644 /* TEAC */
-#define USB_VENDOR_SGI 0x065e /* Silicon Graphics */
-#define USB_VENDOR_SANWASUPPLY 0x0663 /* Sanwa Supply */
-#define USB_VENDOR_MEGATEC 0x0665 /* Megatec */
-#define USB_VENDOR_LINKSYS 0x066b /* Linksys */
-#define USB_VENDOR_ACERSA 0x066e /* Acer Semiconductor America */
-#define USB_VENDOR_SIGMATEL 0x066f /* Sigmatel */
-#define USB_VENDOR_DRAYTEK 0x0675 /* DrayTek */
-#define USB_VENDOR_AIWA 0x0677 /* Aiwa */
-#define USB_VENDOR_ACARD 0x0678 /* ACARD Technology */
-#define USB_VENDOR_PROLIFIC 0x067b /* Prolific Technology */
-#define USB_VENDOR_SIEMENS 0x067c /* Siemens */
-#define USB_VENDOR_AVANCELOGIC 0x0680 /* Avance Logic */
-#define USB_VENDOR_SIEMENS2 0x0681 /* Siemens */
-#define USB_VENDOR_MINOLTA 0x0686 /* Minolta */
-#define USB_VENDOR_CHPRODUCTS 0x068e /* CH Products */
-#define USB_VENDOR_HAGIWARA 0x0693 /* Hagiwara Sys-Com */
-#define USB_VENDOR_CTX 0x0698 /* Chuntex */
-#define USB_VENDOR_ASKEY 0x069a /* Askey Computer */
-#define USB_VENDOR_SAITEK 0x06a3 /* Saitek */
-#define USB_VENDOR_ALCATELT 0x06b9 /* Alcatel Telecom */
-#define USB_VENDOR_AGFA 0x06bd /* AGFA-Gevaert */
-#define USB_VENDOR_ASIAMD 0x06be /* Asia Microelectronic Development */
-#define USB_VENDOR_BIZLINK 0x06c4 /* Bizlink International */
-#define USB_VENDOR_KEYSPAN 0x06cd /* Keyspan / InnoSys Inc. */
-#define USB_VENDOR_AASHIMA 0x06d6 /* Aashima Technology */
-#define USB_VENDOR_LIEBERT 0x06da /* Liebert */
-#define USB_VENDOR_MULTITECH 0x06e0 /* MultiTech */
-#define USB_VENDOR_ADS 0x06e1 /* ADS Technologies */
-#define USB_VENDOR_ALCATELM 0x06e4 /* Alcatel Microelectronics */
-#define USB_VENDOR_SIRIUS 0x06ea /* Sirius Technologies */
-#define USB_VENDOR_GUILLEMOT 0x06f8 /* Guillemot */
-#define USB_VENDOR_BOSTON 0x06fd /* Boston Acoustics */
-#define USB_VENDOR_SMC 0x0707 /* Standard Microsystems */
-#define USB_VENDOR_PUTERCOM 0x0708 /* Putercom */
-#define USB_VENDOR_MCT 0x0711 /* MCT */
-#define USB_VENDOR_IMATION 0x0718 /* Imation */
-#define USB_VENDOR_TECLAST 0x071b /* Teclast */
-#define USB_VENDOR_SONYERICSSON 0x0731 /* Sony Ericsson */
-#define USB_VENDOR_EICON 0x0734 /* Eicon Networks */
-#define USB_VENDOR_SYNTECH 0x0745 /* Syntech Information */
-#define USB_VENDOR_DIGITALSTREAM 0x074e /* Digital Stream */
-#define USB_VENDOR_AUREAL 0x0755 /* Aureal Semiconductor */
-#define USB_VENDOR_MIDIMAN 0x0763 /* Midiman */
-#define USB_VENDOR_CYBERPOWER 0x0764 /* Cyber Power Systems, Inc. */
-#define USB_VENDOR_SURECOM 0x0769 /* Surecom Technology */
-#define USB_VENDOR_HIDGLOBAL 0x076b /* HID Global */
-#define USB_VENDOR_LINKSYS2 0x077b /* Linksys */
-#define USB_VENDOR_GRIFFIN 0x077d /* Griffin Technology */
-#define USB_VENDOR_SANDISK 0x0781 /* SanDisk */
-#define USB_VENDOR_JENOPTIK 0x0784 /* Jenoptik */
-#define USB_VENDOR_LOGITEC 0x0789 /* Logitec */
-#define USB_VENDOR_NOKIA2 0x078b /* Nokia */
-#define USB_VENDOR_BRIMAX 0x078e /* Brimax */
-#define USB_VENDOR_AXIS 0x0792 /* Axis Communications */
-#define USB_VENDOR_ABL 0x0794 /* ABL Electronics */
-#define USB_VENDOR_SAGEM 0x079b /* Sagem */
-#define USB_VENDOR_SUNCOMM 0x079c /* Sun Communications, Inc. */
-#define USB_VENDOR_ALFADATA 0x079d /* Alfadata Computer */
-#define USB_VENDOR_NATIONALTECH 0x07a2 /* National Technical Systems */
-#define USB_VENDOR_ONNTO 0x07a3 /* Onnto */
-#define USB_VENDOR_BE 0x07a4 /* Be */
-#define USB_VENDOR_ADMTEK 0x07a6 /* ADMtek */
-#define USB_VENDOR_COREGA 0x07aa /* Corega */
-#define USB_VENDOR_FREECOM 0x07ab /* Freecom */
-#define USB_VENDOR_MICROTECH 0x07af /* Microtech */
-#define USB_VENDOR_GENERALINSTMNTS 0x07b2 /* General Instruments (Motorola) */
-#define USB_VENDOR_OLYMPUS 0x07b4 /* Olympus */
-#define USB_VENDOR_ABOCOM 0x07b8 /* AboCom Systems */
-#define USB_VENDOR_KEISOKUGIKEN 0x07c1 /* Keisokugiken */
-#define USB_VENDOR_ONSPEC 0x07c4 /* OnSpec */
-#define USB_VENDOR_APG 0x07c5 /* APG Cash Drawer */
-#define USB_VENDOR_BUG 0x07c8 /* B.U.G. */
-#define USB_VENDOR_ALLIEDTELESYN 0x07c9 /* Allied Telesyn International */
-#define USB_VENDOR_AVERMEDIA 0x07ca /* AVerMedia Technologies */
-#define USB_VENDOR_SIIG 0x07cc /* SIIG */
-#define USB_VENDOR_CASIO 0x07cf /* CASIO */
-#define USB_VENDOR_DLINK2 0x07d1 /* D-Link */
-#define USB_VENDOR_APTIO 0x07d2 /* Aptio Products */
-#define USB_VENDOR_ARASAN 0x07da /* Arasan Chip Systems */
-#define USB_VENDOR_ALLIEDCABLE 0x07e6 /* Allied Cable */
-#define USB_VENDOR_STSN 0x07ef /* STSN */
-#define USB_VENDOR_CENTURY 0x07f7 /* Century Corp */
-#define USB_VENDOR_NEWLINK 0x07ff /* NEWlink */
-#define USB_VENDOR_ZOOM 0x0803 /* Zoom Telephonics */
-#define USB_VENDOR_PCS 0x0810 /* Personal Communication Systems */
-#define USB_VENDOR_ALPHASMART 0x081e /* AlphaSmart, Inc. */
-#define USB_VENDOR_BROADLOGIC 0x0827 /* BroadLogic */
-#define USB_VENDOR_HANDSPRING 0x082d /* Handspring */
-#define USB_VENDOR_PALM 0x0830 /* Palm Computing */
-#define USB_VENDOR_SOURCENEXT 0x0833 /* SOURCENEXT */
-#define USB_VENDOR_ACTIONSTAR 0x0835 /* Action Star Enterprise */
-#define USB_VENDOR_SAMSUNG_TECHWIN 0x0839 /* Samsung Techwin */
-#define USB_VENDOR_ACCTON 0x083a /* Accton Technology */
-#define USB_VENDOR_DIAMOND 0x0841 /* Diamond */
-#define USB_VENDOR_NETGEAR 0x0846 /* BayNETGEAR */
-#define USB_VENDOR_TOPRE 0x0853 /* Topre Corporation */
-#define USB_VENDOR_ACTIVEWIRE 0x0854 /* ActiveWire */
-#define USB_VENDOR_BBELECTRONICS 0x0856 /* B&B Electronics */
-#define USB_VENDOR_PORTGEAR 0x085a /* PortGear */
-#define USB_VENDOR_NETGEAR2 0x0864 /* Netgear */
-#define USB_VENDOR_SYSTEMTALKS 0x086e /* System Talks */
-#define USB_VENDOR_METRICOM 0x0870 /* Metricom */
-#define USB_VENDOR_ADESSOKBTEK 0x087c /* ADESSO/Kbtek America */
-#define USB_VENDOR_JATON 0x087d /* Jaton */
-#define USB_VENDOR_APT 0x0880 /* APT Technologies */
-#define USB_VENDOR_BOCARESEARCH 0x0885 /* Boca Research */
-#define USB_VENDOR_ANDREA 0x08a8 /* Andrea Electronics */
-#define USB_VENDOR_BURRBROWN 0x08bb /* Burr-Brown Japan */
-#define USB_VENDOR_2WIRE 0x08c8 /* 2Wire */
-#define USB_VENDOR_AIPTEK 0x08ca /* AIPTEK International */
-#define USB_VENDOR_SMARTBRIDGES 0x08d1 /* SmartBridges */
-#define USB_VENDOR_FUJITSUSIEMENS 0x08d4 /* Fujitsu-Siemens */
-#define USB_VENDOR_BILLIONTON 0x08dd /* Billionton Systems */
-#define USB_VENDOR_GEMALTO 0x08e6 /* Gemalto SA */
-#define USB_VENDOR_EXTENDED 0x08e9 /* Extended Systems */
-#define USB_VENDOR_MSYSTEMS 0x08ec /* M-Systems */
-#define USB_VENDOR_DIGIANSWER 0x08fd /* Digianswer */
-#define USB_VENDOR_AUTHENTEC 0x08ff /* AuthenTec */
-#define USB_VENDOR_AUDIOTECHNICA 0x0909 /* Audio-Technica */
-#define USB_VENDOR_TRUMPION 0x090a /* Trumpion Microelectronics */
-#define USB_VENDOR_FEIYA 0x090c /* Feiya */
-#define USB_VENDOR_ALATION 0x0910 /* Alation Systems */
-#define USB_VENDOR_GLOBESPAN 0x0915 /* Globespan */
-#define USB_VENDOR_CONCORDCAMERA 0x0919 /* Concord Camera */
-#define USB_VENDOR_GARMIN 0x091e /* Garmin International */
-#define USB_VENDOR_GOHUBS 0x0921 /* GoHubs */
-#define USB_VENDOR_XEROX 0x0924 /* Xerox */
-#define USB_VENDOR_BIOMETRIC 0x0929 /* American Biometric Company */
-#define USB_VENDOR_TOSHIBA 0x0930 /* Toshiba */
-#define USB_VENDOR_PLEXTOR 0x093b /* Plextor */
-#define USB_VENDOR_INTREPIDCS 0x093c /* Intrepid */
-#define USB_VENDOR_YANO 0x094f /* Yano */
-#define USB_VENDOR_KINGSTON 0x0951 /* Kingston Technology */
-#define USB_VENDOR_BLUEWATER 0x0956 /* BlueWater Systems */
-#define USB_VENDOR_AGILENT 0x0957 /* Agilent Technologies */
-#define USB_VENDOR_GUDE 0x0959 /* Gude ADS */
-#define USB_VENDOR_PORTSMITH 0x095a /* Portsmith */
-#define USB_VENDOR_ACERW 0x0967 /* Acer */
-#define USB_VENDOR_ADIRONDACK 0x0976 /* Adirondack Wire & Cable */
-#define USB_VENDOR_BECKHOFF 0x0978 /* Beckhoff */
-#define USB_VENDOR_MINDSATWORK 0x097a /* Minds At Work */
-#define USB_VENDOR_POINTCHIPS 0x09a6 /* PointChips */
-#define USB_VENDOR_INTERSIL 0x09aa /* Intersil */
-#define USB_VENDOR_ALTIUS 0x09b3 /* Altius Solutions */
-#define USB_VENDOR_ARRIS 0x09c1 /* Arris Interactive */
-#define USB_VENDOR_ACTIVCARD 0x09c3 /* ACTIVCARD */
-#define USB_VENDOR_ACTISYS 0x09c4 /* ACTiSYS */
-#define USB_VENDOR_NOVATEL2 0x09d7 /* Novatel Wireless */
-#define USB_VENDOR_AFOURTECH 0x09da /* A-FOUR TECH */
-#define USB_VENDOR_AIMEX 0x09dc /* AIMEX */
-#define USB_VENDOR_ADDONICS 0x09df /* Addonics Technologies */
-#define USB_VENDOR_AKAI 0x09e8 /* AKAI professional M.I. */
-#define USB_VENDOR_ARESCOM 0x09f5 /* ARESCOM */
-#define USB_VENDOR_BAY 0x09f9 /* Bay Associates */
-#define USB_VENDOR_ALTERA 0x09fb /* Altera */
-#define USB_VENDOR_CSR 0x0a12 /* Cambridge Silicon Radio */
-#define USB_VENDOR_TREK 0x0a16 /* Trek Technology */
-#define USB_VENDOR_ASAHIOPTICAL 0x0a17 /* Asahi Optical */
-#define USB_VENDOR_BOCASYSTEMS 0x0a43 /* Boca Systems */
-#define USB_VENDOR_SHANTOU 0x0a46 /* ShanTou */
-#define USB_VENDOR_MEDIAGEAR 0x0a48 /* MediaGear */
-#define USB_VENDOR_BROADCOM 0x0a5c /* Broadcom */
-#define USB_VENDOR_GREENHOUSE 0x0a6b /* GREENHOUSE */
-#define USB_VENDOR_GEOCAST 0x0a79 /* Geocast Network Systems */
-#define USB_VENDOR_IDQUANTIQUE 0x0aba /* id Quantique */
-#define USB_VENDOR_ZYDAS 0x0ace /* Zydas Technology Corporation */
-#define USB_VENDOR_NEODIO 0x0aec /* Neodio */
-#define USB_VENDOR_OPTION 0x0af0 /* Option N.V. */
-#define USB_VENDOR_ASUS 0x0b05 /* ASUSTeK Computer */
-#define USB_VENDOR_TODOS 0x0b0c /* Todos Data System */
-#define USB_VENDOR_SIIG2 0x0b39 /* SIIG */
-#define USB_VENDOR_TEKRAM 0x0b3b /* Tekram Technology */
-#define USB_VENDOR_HAL 0x0b41 /* HAL Corporation */
-#define USB_VENDOR_EMS 0x0b43 /* EMS Production */
-#define USB_VENDOR_NEC2 0x0b62 /* NEC */
-#define USB_VENDOR_ADLINK 0x0b63 /* ADLINK Technoligy, Inc. */
-#define USB_VENDOR_ATI2 0x0b6f /* ATI */
-#define USB_VENDOR_ZEEVO 0x0b7a /* Zeevo, Inc. */
-#define USB_VENDOR_KURUSUGAWA 0x0b7e /* Kurusugawa Electronics, Inc. */
-#define USB_VENDOR_SMART 0x0b8c /* Smart Technologies */
-#define USB_VENDOR_ASIX 0x0b95 /* ASIX Electronics */
-#define USB_VENDOR_O2MICRO 0x0b97 /* O2 Micro, Inc. */
-#define USB_VENDOR_USR 0x0baf /* U.S. Robotics */
-#define USB_VENDOR_AMBIT 0x0bb2 /* Ambit Microsystems */
-#define USB_VENDOR_HTC 0x0bb4 /* HTC */
-#define USB_VENDOR_REALTEK 0x0bda /* Realtek */
-#define USB_VENDOR_MEI 0x0bed /* MEI */
-#define USB_VENDOR_ADDONICS2 0x0bf6 /* Addonics Technology */
-#define USB_VENDOR_FSC 0x0bf8 /* Fujitsu Siemens Computers */
-#define USB_VENDOR_AGATE 0x0c08 /* Agate Technologies */
-#define USB_VENDOR_DMI 0x0c0b /* DMI */
-#define USB_VENDOR_CHICONY2 0x0c45 /* Chicony */
-#define USB_VENDOR_REINERSCT 0x0c4b /* Reiner-SCT */
-#define USB_VENDOR_SEALEVEL 0x0c52 /* Sealevel System */
-#define USB_VENDOR_LUWEN 0x0c76 /* Luwen */
-#define USB_VENDOR_KYOCERA2 0x0c88 /* Kyocera Wireless Corp. */
-#define USB_VENDOR_ZCOM 0x0cde /* Z-Com */
-#define USB_VENDOR_ATHEROS2 0x0cf3 /* Atheros Communications */
-#define USB_VENDOR_TANGTOP 0x0d3d /* Tangtop */
-#define USB_VENDOR_SMC3 0x0d5c /* Standard Microsystems */
-#define USB_VENDOR_ADDON 0x0d7d /* Add-on Technology */
-#define USB_VENDOR_ACDC 0x0d7e /* American Computer & Digital Components */
-#define USB_VENDOR_CMEDIA 0x0d8c /* CMEDIA */
-#define USB_VENDOR_CONCEPTRONIC 0x0d8e /* Conceptronic */
-#define USB_VENDOR_SKANHEX 0x0d96 /* Skanhex Technology, Inc. */
-#define USB_VENDOR_MSI 0x0db0 /* Micro Star International */
-#define USB_VENDOR_ELCON 0x0db7 /* ELCON Systemtechnik */
-#define USB_VENDOR_NETAC 0x0dd8 /* Netac */
-#define USB_VENDOR_SITECOMEU 0x0df6 /* Sitecom Europe */
-#define USB_VENDOR_MOBILEACTION 0x0df7 /* Mobile Action */
-#define USB_VENDOR_AMIGO 0x0e0b /* Amigo Technology */
-#define USB_VENDOR_SPEEDDRAGON 0x0e55 /* Speed Dragon Multimedia */
-#define USB_VENDOR_HAWKING 0x0e66 /* Hawking */
-#define USB_VENDOR_FOSSIL 0x0e67 /* Fossil, Inc */
-#define USB_VENDOR_GMATE 0x0e7e /* G.Mate, Inc */
-#define USB_VENDOR_OTI 0x0ea0 /* Ours Technology */
-#define USB_VENDOR_YISO 0x0eab /* Yiso Wireless Co. */
-#define USB_VENDOR_PILOTECH 0x0eaf /* Pilotech */
-#define USB_VENDOR_NOVATECH 0x0eb0 /* NovaTech */
-#define USB_VENDOR_ITEGNO 0x0eba /* iTegno */
-#define USB_VENDOR_WINMAXGROUP 0x0ed1 /* WinMaxGroup */
-#define USB_VENDOR_TOD 0x0ede /* TOD */
-#define USB_VENDOR_EGALAX 0x0eef /* eGalax, Inc. */
-#define USB_VENDOR_AIRPRIME 0x0f3d /* AirPrime, Inc. */
-#define USB_VENDOR_MICROTUNE 0x0f4d /* Microtune */
-#define USB_VENDOR_VTECH 0x0f88 /* VTech */
-#define USB_VENDOR_FALCOM 0x0f94 /* Falcom Wireless Communications GmbH */
-#define USB_VENDOR_RIM 0x0fca /* Research In Motion */
-#define USB_VENDOR_DYNASTREAM 0x0fcf /* Dynastream Innovations */
-#define USB_VENDOR_QUALCOMM 0x1004 /* Qualcomm */
-#define USB_VENDOR_APACER 0x1005 /* Apacer */
-#define USB_VENDOR_MOTOROLA4 0x100d /* Motorola */
-#define USB_VENDOR_AIRPLUS 0x1011 /* Airplus */
-#define USB_VENDOR_DESKNOTE 0x1019 /* Desknote */
-#define USB_VENDOR_GIGABYTE 0x1044 /* GIGABYTE */
-#define USB_VENDOR_WESTERN 0x1058 /* Western Digital */
-#define USB_VENDOR_MOTOROLA 0x1063 /* Motorola */
-#define USB_VENDOR_CCYU 0x1065 /* CCYU Technology */
-#define USB_VENDOR_CURITEL 0x106c /* Curitel Communications Inc */
-#define USB_VENDOR_SILABS2 0x10a6 /* SILABS2 */
-#define USB_VENDOR_USI 0x10ab /* USI */
-#define USB_VENDOR_PLX 0x10b5 /* PLX */
-#define USB_VENDOR_ASANTE 0x10bd /* Asante */
-#define USB_VENDOR_SILABS 0x10c4 /* Silicon Labs */
-#define USB_VENDOR_SILABS3 0x10c5 /* Silicon Labs */
-#define USB_VENDOR_SILABS4 0x10ce /* Silicon Labs */
-#define USB_VENDOR_ACTIONS 0x10d6 /* Actions */
-#define USB_VENDOR_ANALOG 0x1110 /* Analog Devices */
-#define USB_VENDOR_TENX 0x1130 /* Ten X Technology, Inc. */
-#define USB_VENDOR_ISSC 0x1131 /* Integrated System Solution Corp. */
-#define USB_VENDOR_JRC 0x1145 /* Japan Radio Company */
-#define USB_VENDOR_SPHAIRON 0x114b /* Sphairon Access Systems GmbH */
-#define USB_VENDOR_DELORME 0x1163 /* DeLorme */
-#define USB_VENDOR_SERVERWORKS 0x1166 /* ServerWorks */
-#define USB_VENDOR_DLINK3 0x1186 /* Dlink */
-#define USB_VENDOR_ACERCM 0x1189 /* Acer Communications & Multimedia */
-#define USB_VENDOR_SIERRA 0x1199 /* Sierra Wireless */
-#define USB_VENDOR_SANWA 0x11ad /* Sanwa Electric Instrument Co., Ltd. */
-#define USB_VENDOR_TOPFIELD 0x11db /* Topfield Co., Ltd */
-#define USB_VENDOR_SIEMENS3 0x11f5 /* Siemens */
-#define USB_VENDOR_NETINDEX 0x11f6 /* NetIndex */
-#define USB_VENDOR_ALCATEL 0x11f7 /* Alcatel */
-#define USB_VENDOR_UNKNOWN3 0x1233 /* Unknown vendor */
-#define USB_VENDOR_TSUNAMI 0x1241 /* Tsunami */
-#define USB_VENDOR_PHEENET 0x124a /* Pheenet */
-#define USB_VENDOR_TARGUS 0x1267 /* Targus */
-#define USB_VENDOR_TWINMOS 0x126f /* TwinMOS */
-#define USB_VENDOR_TENDA 0x1286 /* Tenda */
-#define USB_VENDOR_CREATIVE2 0x1292 /* Creative Labs */
-#define USB_VENDOR_BELKIN2 0x1293 /* Belkin Components */
-#define USB_VENDOR_CYBERTAN 0x129b /* CyberTAN Technology */
-#define USB_VENDOR_HUAWEI 0x12d1 /* Huawei Technologies */
-#define USB_VENDOR_ARANEUS 0x12d8 /* Araneus Information Systems */
-#define USB_VENDOR_TAPWAVE 0x12ef /* Tapwave */
-#define USB_VENDOR_AINCOMM 0x12fd /* Aincomm */
-#define USB_VENDOR_MOBILITY 0x1342 /* Mobility */
-#define USB_VENDOR_DICKSMITH 0x1371 /* Dick Smith Electronics */
-#define USB_VENDOR_NETGEAR3 0x1385 /* Netgear */
-#define USB_VENDOR_BALTECH 0x13ad /* Baltech */
-#define USB_VENDOR_CISCOLINKSYS 0x13b1 /* Cisco-Linksys */
-#define USB_VENDOR_SHARK 0x13d2 /* Shark */
-#define USB_VENDOR_AZUREWAVE 0x13d3 /* AsureWave */
-#define USB_VENDOR_EMTEC 0x13fe /* Emtec */
-#define USB_VENDOR_NOVATEL 0x1410 /* Novatel Wireless */
-#define USB_VENDOR_MERLIN 0x1416 /* Merlin */
-#define USB_VENDOR_WISTRONNEWEB 0x1435 /* Wistron NeWeb */
-#define USB_VENDOR_RADIOSHACK 0x1453 /* Radio Shack */
-#define USB_VENDOR_HUAWEI3COM 0x1472 /* Huawei-3Com */
-#define USB_VENDOR_ABOCOM2 0x1482 /* AboCom Systems */
-#define USB_VENDOR_SILICOM 0x1485 /* Silicom */
-#define USB_VENDOR_RALINK 0x148f /* Ralink Technology */
-#define USB_VENDOR_IMAGINATION 0x149a /* Imagination Technologies */
-#define USB_VENDOR_CONCEPTRONIC2 0x14b2 /* Conceptronic */
-#define USB_VENDOR_SUPERTOP 0x14cd /* Super Top */
-#define USB_VENDOR_PLANEX3 0x14ea /* Planex Communications */
-#define USB_VENDOR_SILICONPORTALS 0x1527 /* Silicon Portals */
-#define USB_VENDOR_UBIQUAM 0x1529 /* UBIQUAM Co., Ltd. */
-#define USB_VENDOR_JMICRON 0x152d /* JMicron */
-#define USB_VENDOR_UBLOX 0x1546 /* U-blox */
-#define USB_VENDOR_PNY 0x154b /* PNY */
-#define USB_VENDOR_OWEN 0x1555 /* Owen */
-#define USB_VENDOR_OQO 0x1557 /* OQO */
-#define USB_VENDOR_UMEDIA 0x157e /* U-MEDIA Communications */
-#define USB_VENDOR_FIBERLINE 0x1582 /* Fiberline */
-#define USB_VENDOR_SPARKLAN 0x15a9 /* SparkLAN */
-#define USB_VENDOR_AMIT2 0x15c5 /* AMIT */
-#define USB_VENDOR_SOHOWARE 0x15e8 /* SOHOware */
-#define USB_VENDOR_UMAX 0x1606 /* UMAX Data Systems */
-#define USB_VENDOR_INSIDEOUT 0x1608 /* Inside Out Networks */
-#define USB_VENDOR_AMOI 0x1614 /* Amoi Electronics */
-#define USB_VENDOR_GOODWAY 0x1631 /* Good Way Technology */
-#define USB_VENDOR_ENTREGA 0x1645 /* Entrega */
-#define USB_VENDOR_ACTIONTEC 0x1668 /* Actiontec Electronics */
-#define USB_VENDOR_CLIPSAL 0x166a /* Clipsal */
-#define USB_VENDOR_CISCOLINKSYS2 0x167b /* Cisco-Linksys */
-#define USB_VENDOR_ATHEROS 0x168c /* Atheros Communications */
-#define USB_VENDOR_GIGASET 0x1690 /* Gigaset */
-#define USB_VENDOR_GLOBALSUN 0x16ab /* Global Sun Technology */
-#define USB_VENDOR_ANYDATA 0x16d5 /* AnyDATA Corporation */
-#define USB_VENDOR_JABLOTRON 0x16d6 /* Jablotron */
-#define USB_VENDOR_CMOTECH 0x16d8 /* C-motech */
-#define USB_VENDOR_AXESSTEL 0x1726 /* Axesstel Co., Ltd. */
-#define USB_VENDOR_LINKSYS4 0x1737 /* Linksys */
-#define USB_VENDOR_SENAO 0x1740 /* Senao */
-#define USB_VENDOR_ASUS2 0x1761 /* ASUS */
-#define USB_VENDOR_SWEEX2 0x177f /* Sweex */
-#define USB_VENDOR_METAGEEK 0x1781 /* MetaGeek */
-#define USB_VENDOR_WAVESENSE 0x17f4 /* WaveSense */
-#define USB_VENDOR_VAISALA 0x1843 /* Vaisala */
-#define USB_VENDOR_AMIT 0x18c5 /* AMIT */
-#define USB_VENDOR_GOOGLE 0x18d1 /* Google */
-#define USB_VENDOR_QCOM 0x18e8 /* Qcom */
-#define USB_VENDOR_ELV 0x18ef /* ELV */
-#define USB_VENDOR_LINKSYS3 0x1915 /* Linksys */
-#define USB_VENDOR_QUALCOMMINC 0x19d2 /* Qualcomm, Incorporated */
-#define USB_VENDOR_WCH2 0x1a86 /* QinHeng Electronics */
-#define USB_VENDOR_STELERA 0x1a8d /* Stelera Wireless */
-#define USB_VENDOR_MATRIXORBITAL 0x1b3d /* Matrix Orbital */
-#define USB_VENDOR_OVISLINK 0x1b75 /* OvisLink */
-#define USB_VENDOR_TCTMOBILE 0x1bbb /* TCT Mobile */
-#define USB_VENDOR_TELIT 0x1bc7 /* Telit */
-#define USB_VENDOR_LONGCHEER 0x1c9e /* Longcheer Holdings, Ltd. */
-#define USB_VENDOR_MPMAN 0x1cae /* MpMan */
-#define USB_VENDOR_DRESDENELEKTRONIK 0x1cf1 /* dresden elektronik */
-#define USB_VENDOR_NEOTEL 0x1d09 /* Neotel */
-#define USB_VENDOR_PEGATRON 0x1d4d /* Pegatron */
-#define USB_VENDOR_QISDA 0x1da5 /* Qisda */
-#define USB_VENDOR_METAGEEK2 0x1dd5 /* MetaGeek */
-#define USB_VENDOR_ALINK 0x1e0e /* Alink */
-#define USB_VENDOR_AIRTIES 0x1eda /* AirTies */
-#define USB_VENDOR_DLINK 0x2001 /* D-Link */
-#define USB_VENDOR_PLANEX2 0x2019 /* Planex Communications */
-#define USB_VENDOR_HAUPPAUGE2 0x2040 /* Hauppauge Computer Works */
-#define USB_VENDOR_TLAYTECH 0x20b9 /* Tlay Tech */
-#define USB_VENDOR_ENCORE 0x203d /* Encore */
-#define USB_VENDOR_PARA 0x20b8 /* PARA Industrial */
-#define USB_VENDOR_ERICSSON 0x2282 /* Ericsson */
-#define USB_VENDOR_MOTOROLA2 0x22b8 /* Motorola */
-#define USB_VENDOR_TRIPPLITE 0x2478 /* Tripp-Lite */
-#define USB_VENDOR_HIROSE 0x2631 /* Hirose Electric */
-#define USB_VENDOR_NHJ 0x2770 /* NHJ */
-#define USB_VENDOR_PLANEX 0x2c02 /* Planex Communications */
-#define USB_VENDOR_VIDZMEDIA 0x3275 /* VidzMedia Pte Ltd */
-#define USB_VENDOR_AEI 0x3334 /* AEI */
-#define USB_VENDOR_HANK 0x3353 /* Hank Connection */
-#define USB_VENDOR_PQI 0x3538 /* PQI */
-#define USB_VENDOR_DAISY 0x3579 /* Daisy Technology */
-#define USB_VENDOR_NI 0x3923 /* National Instruments */
-#define USB_VENDOR_MICRONET 0x3980 /* Micronet Communications */
-#define USB_VENDOR_IODATA2 0x40bb /* I-O Data */
-#define USB_VENDOR_IRIVER 0x4102 /* iRiver */
-#define USB_VENDOR_DELL 0x413c /* Dell */
-#define USB_VENDOR_WCH 0x4348 /* QinHeng Electronics */
-#define USB_VENDOR_ACEECA 0x4766 /* Aceeca */
-#define USB_VENDOR_AVERATEC 0x50c2 /* Averatec */
-#define USB_VENDOR_SWEEX 0x5173 /* Sweex */
-#define USB_VENDOR_PROLIFIC2 0x5372 /* Prolific Technologies */
-#define USB_VENDOR_ONSPEC2 0x55aa /* OnSpec Electronic Inc. */
-#define USB_VENDOR_ZINWELL 0x5a57 /* Zinwell */
-#define USB_VENDOR_SITECOM 0x6189 /* Sitecom */
-#define USB_VENDOR_ARKMICRO 0x6547 /* Arkmicro Technologies Inc. */
-#define USB_VENDOR_3COM2 0x6891 /* 3Com */
-#define USB_VENDOR_EDIMAX 0x7392 /* Edimax */
-#define USB_VENDOR_INTEL 0x8086 /* Intel */
-#define USB_VENDOR_INTEL2 0x8087 /* Intel */
-#define USB_VENDOR_ALLWIN 0x8516 /* ALLWIN Tech */
-#define USB_VENDOR_SITECOM2 0x9016 /* Sitecom */
-#define USB_VENDOR_MOSCHIP 0x9710 /* MosChip Semiconductor */
-#define USB_VENDOR_MARVELL 0x9e88 /* Marvell Technology Group Ltd. */
-#define USB_VENDOR_3COM3 0xa727 /* 3Com */
-#define USB_VENDOR_DATAAPEX 0xdaae /* DataApex */
-#define USB_VENDOR_HP2 0xf003 /* Hewlett Packard */
-#define USB_VENDOR_USRP 0xfffe /* GNU Radio USRP */
-
-/*
- * List of known products. Grouped by vendor.
- */
-
-/* 3Com products */
-#define USB_PRODUCT_3COM_HOMECONN 0x009d /* HomeConnect Camera */
-#define USB_PRODUCT_3COM_3CREB96 0x00a0 /* Bluetooth USB Adapter */
-#define USB_PRODUCT_3COM_3C19250 0x03e8 /* 3C19250 Ethernet Adapter */
-#define USB_PRODUCT_3COM_3CRSHEW696 0x0a01 /* 3CRSHEW696 Wireless Adapter */
-#define USB_PRODUCT_3COM_3C460 0x11f8 /* HomeConnect 3C460 */
-#define USB_PRODUCT_3COM_USR56K 0x3021 /* U.S.Robotics 56000 Voice FaxModem Pro */
-#define USB_PRODUCT_3COM_3C460B 0x4601 /* HomeConnect 3C460B */
-#define USB_PRODUCT_3COM2_3CRUSB10075 0xa727 /* 3CRUSB10075 */
-#define USB_PRODUCT_3COM3_AR5523_1 0x6893 /* AR5523 */
-#define USB_PRODUCT_3COM3_AR5523_2 0x6895 /* AR5523 */
-#define USB_PRODUCT_3COM3_AR5523_3 0x6897 /* AR5523 */
-
-#define USB_PRODUCT_3COMUSR_OFFICECONN 0x0082 /* 3Com OfficeConnect Analog Modem */
-#define USB_PRODUCT_3COMUSR_USRISDN 0x008f /* 3Com U.S. Robotics Pro ISDN TA */
-#define USB_PRODUCT_3COMUSR_HOMECONN 0x009d /* 3Com HomeConnect Camera */
-#define USB_PRODUCT_3COMUSR_USR56K 0x3021 /* U.S. Robotics 56000 Voice FaxModem Pro */
-
-/* AboCom products */
-#define USB_PRODUCT_ABOCOM_XX1 0x110c /* XX1 */
-#define USB_PRODUCT_ABOCOM_XX2 0x200c /* XX2 */
-#define USB_PRODUCT_ABOCOM_RT2770 0x2770 /* RT2770 */
-#define USB_PRODUCT_ABOCOM_RT2870 0x2870 /* RT2870 */
-#define USB_PRODUCT_ABOCOM_RT3070 0x3070 /* RT3070 */
-#define USB_PRODUCT_ABOCOM_RT3071 0x3071 /* RT3071 */
-#define USB_PRODUCT_ABOCOM_RT3072 0x3072 /* RT3072 */
-#define USB_PRODUCT_ABOCOM2_RT2870_1 0x3c09 /* RT2870 */
-#define USB_PRODUCT_ABOCOM_URE450 0x4000 /* URE450 Ethernet Adapter */
-#define USB_PRODUCT_ABOCOM_UFE1000 0x4002 /* UFE1000 Fast Ethernet Adapter */
-#define USB_PRODUCT_ABOCOM_DSB650TX_PNA 0x4003 /* 1/10/100 Ethernet Adapter */
-#define USB_PRODUCT_ABOCOM_XX4 0x4004 /* XX4 */
-#define USB_PRODUCT_ABOCOM_XX5 0x4007 /* XX5 */
-#define USB_PRODUCT_ABOCOM_XX6 0x400b /* XX6 */
-#define USB_PRODUCT_ABOCOM_XX7 0x400c /* XX7 */
-#define USB_PRODUCT_ABOCOM_RTL8151 0x401a /* RTL8151 */
-#define USB_PRODUCT_ABOCOM_XX8 0x4102 /* XX8 */
-#define USB_PRODUCT_ABOCOM_XX9 0x4104 /* XX9 */
-#define USB_PRODUCT_ABOCOM_UF200 0x420a /* UF200 Ethernet */
-#define USB_PRODUCT_ABOCOM_WL54 0x6001 /* WL54 */
-#define USB_PRODUCT_ABOCOM_XX10 0xabc1 /* XX10 */
-#define USB_PRODUCT_ABOCOM_BWU613 0xb000 /* BWU613 */
-#define USB_PRODUCT_ABOCOM_HWU54DM 0xb21b /* HWU54DM */
-#define USB_PRODUCT_ABOCOM_RT2573_2 0xb21c /* RT2573 */
-#define USB_PRODUCT_ABOCOM_RT2573_3 0xb21d /* RT2573 */
-#define USB_PRODUCT_ABOCOM_RT2573_4 0xb21e /* RT2573 */
-#define USB_PRODUCT_ABOCOM_WUG2700 0xb21f /* WUG2700 */
-
-/* Accton products */
-#define USB_PRODUCT_ACCTON_USB320_EC 0x1046 /* USB320-EC Ethernet Adapter */
-#define USB_PRODUCT_ACCTON_2664W 0x3501 /* 2664W */
-#define USB_PRODUCT_ACCTON_111 0x3503 /* T-Sinus 111 Wireless Adapter */
-#define USB_PRODUCT_ACCTON_SMCWUSBG_NF 0x4505 /* SMCWUSB-G (no firmware) */
-#define USB_PRODUCT_ACCTON_SMCWUSBG 0x4506 /* SMCWUSB-G */
-#define USB_PRODUCT_ACCTON_SMCWUSBTG2_NF 0x4507 /* SMCWUSBT-G2 (no firmware) */
-#define USB_PRODUCT_ACCTON_SMCWUSBTG2 0x4508 /* SMCWUSBT-G2 */
-#define USB_PRODUCT_ACCTON_PRISM_GT 0x4521 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_ACCTON_SS1001 0x5046 /* SpeedStream Ethernet Adapter */
-#define USB_PRODUCT_ACCTON_RT2870_2 0x6618 /* RT2870 */
-#define USB_PRODUCT_ACCTON_RT3070 0x7511 /* RT3070 */
-#define USB_PRODUCT_ACCTON_RT2770 0x7512 /* RT2770 */
-#define USB_PRODUCT_ACCTON_RT2870_3 0x7522 /* RT2870 */
-#define USB_PRODUCT_ACCTON_RT2870_5 0x8522 /* RT2870 */
-#define USB_PRODUCT_ACCTON_RT3070_4 0xa512 /* RT3070 */
-#define USB_PRODUCT_ACCTON_RT2870_4 0xa618 /* RT2870 */
-#define USB_PRODUCT_ACCTON_RT3070_1 0xa701 /* RT3070 */
-#define USB_PRODUCT_ACCTON_RT3070_2 0xa702 /* RT3070 */
-#define USB_PRODUCT_ACCTON_RT2870_1 0xb522 /* RT2870 */
-#define USB_PRODUCT_ACCTON_RT3070_3 0xc522 /* RT3070 */
-#define USB_PRODUCT_ACCTON_RT3070_5 0xd522 /* RT3070 */
-#define USB_PRODUCT_ACCTON_ZD1211B 0xe501 /* ZD1211B */
-
-/* Aceeca products */
-#define USB_PRODUCT_ACEECA_MEZ1000 0x0001 /* MEZ1000 RDA */
-
-/* Acer Communications & Multimedia (oemd by Surecom) */
-#define USB_PRODUCT_ACERCM_EP1427X2 0x0893 /* EP-1427X-2 Ethernet Adapter */
-
-/* Acer Labs products */
-#define USB_PRODUCT_ACERLABS_M5632 0x5632 /* USB 2.0 Data Link */
-
-/* Acer Peripherals, Inc. products */
-#define USB_PRODUCT_ACERP_ACERSCAN_C310U 0x12a6 /* Acerscan C310U */
-#define USB_PRODUCT_ACERP_ACERSCAN_320U 0x2022 /* Acerscan 320U */
-#define USB_PRODUCT_ACERP_ACERSCAN_640U 0x2040 /* Acerscan 640U */
-#define USB_PRODUCT_ACERP_ACERSCAN_620U 0x2060 /* Acerscan 620U */
-#define USB_PRODUCT_ACERP_ACERSCAN_4300U 0x20b0 /* Benq 3300U/4300U */
-#define USB_PRODUCT_ACERP_ACERSCAN_640BT 0x20be /* Acerscan 640BT */
-#define USB_PRODUCT_ACERP_ACERSCAN_1240U 0x20c0 /* Acerscan 1240U */
-#define USB_PRODUCT_ACERP_S81 0x4027 /* BenQ S81 phone */
-#define USB_PRODUCT_ACERP_H10 0x4068 /* AWL400 Wireless Adapter */
-#define USB_PRODUCT_ACERP_ATAPI 0x6003 /* ATA/ATAPI Adapter */
-#define USB_PRODUCT_ACERP_AWL300 0x9000 /* AWL300 Wireless Adapter */
-#define USB_PRODUCT_ACERP_AWL400 0x9001 /* AWL400 Wireless Adapter */
-
-/* Acer Warp products */
-#define USB_PRODUCT_ACERW_WARPLINK 0x0204 /* Warplink */
-
-/* Actions products */
-#define USB_PRODUCT_ACTIONS_MP4 0x1101 /* Actions MP4 Player */
-
-/* Actiontec, Inc. products */
-#define USB_PRODUCT_ACTIONTEC_PRISM_25 0x0408 /* Prism2.5 Wireless Adapter */
-#define USB_PRODUCT_ACTIONTEC_PRISM_25A 0x0421 /* Prism2.5 Wireless Adapter A */
-#define USB_PRODUCT_ACTIONTEC_FREELAN 0x6106 /* ROPEX FreeLan 802.11b */
-#define USB_PRODUCT_ACTIONTEC_UAT1 0x7605 /* UAT1 Wireless Ethernet Adapter */
-
-/* ACTiSYS products */
-#define USB_PRODUCT_ACTISYS_IR2000U 0x0011 /* ACT-IR2000U FIR */
-
-/* ActiveWire, Inc. products */
-#define USB_PRODUCT_ACTIVEWIRE_IOBOARD 0x0100 /* I/O Board */
-#define USB_PRODUCT_ACTIVEWIRE_IOBOARD_FW1 0x0101 /* I/O Board, rev. 1 firmware */
-
-/* Adaptec products */
-#define USB_PRODUCT_ADAPTEC_AWN8020 0x0020 /* AWN-8020 WLAN */
-
-/* Addtron products */
-#define USB_PRODUCT_ADDTRON_AWU120 0xff31 /* AWU-120 */
-
-/* ADLINK Texhnology products */
-#define USB_PRODUCT_ADLINK_ND6530 0x6530 /* ND-6530 USB-Serial */
-
-/* ADMtek products */
-#define USB_PRODUCT_ADMTEK_PEGASUSII_4 0x07c2 /* AN986A Ethernet */
-#define USB_PRODUCT_ADMTEK_PEGASUS 0x0986 /* AN986 Ethernet */
-#define USB_PRODUCT_ADMTEK_PEGASUSII 0x8511 /* AN8511 Ethernet */
-#define USB_PRODUCT_ADMTEK_PEGASUSII_2 0x8513 /* AN8513 Ethernet */
-#define USB_PRODUCT_ADMTEK_PEGASUSII_3 0x8515 /* AN8515 Ethernet */
-
-/* ADDON products */
-/* PNY OEMs these */
-#define USB_PRODUCT_ADDON_ATTACHE 0x1300 /* USB 2.0 Flash Drive */
-#define USB_PRODUCT_ADDON_ATTACHE 0x1300 /* USB 2.0 Flash Drive */
-#define USB_PRODUCT_ADDON_A256MB 0x1400 /* Attache 256MB USB 2.0 Flash Drive */
-#define USB_PRODUCT_ADDON_DISKPRO512 0x1420 /* USB 2.0 Flash Drive (DANE-ELEC zMate 512MB USB flash drive) */
-
-/* Addonics products */
-#define USB_PRODUCT_ADDONICS2_CABLE_205 0xa001 /* Cable 205 */
-
-/* ADS products */
-#define USB_PRODUCT_ADS_UBS10BT 0x0008 /* UBS-10BT Ethernet */
-#define USB_PRODUCT_ADS_UBS10BTX 0x0009 /* UBS-10BT Ethernet */
-
-/* AEI products */
-#define USB_PRODUCT_AEI_FASTETHERNET 0x1701 /* Fast Ethernet */
-
-/* Agate Technologies products */
-#define USB_PRODUCT_AGATE_QDRIVE 0x0378 /* Q-Drive */
-
-/* AGFA products */
-#define USB_PRODUCT_AGFA_SNAPSCAN1212U 0x0001 /* SnapScan 1212U */
-#define USB_PRODUCT_AGFA_SNAPSCAN1236U 0x0002 /* SnapScan 1236U */
-#define USB_PRODUCT_AGFA_SNAPSCANTOUCH 0x0100 /* SnapScan Touch */
-#define USB_PRODUCT_AGFA_SNAPSCAN1212U2 0x2061 /* SnapScan 1212U */
-#define USB_PRODUCT_AGFA_SNAPSCANE40 0x208d /* SnapScan e40 */
-#define USB_PRODUCT_AGFA_SNAPSCANE50 0x208f /* SnapScan e50 */
-#define USB_PRODUCT_AGFA_SNAPSCANE20 0x2091 /* SnapScan e20 */
-#define USB_PRODUCT_AGFA_SNAPSCANE25 0x2095 /* SnapScan e25 */
-#define USB_PRODUCT_AGFA_SNAPSCANE26 0x2097 /* SnapScan e26 */
-#define USB_PRODUCT_AGFA_SNAPSCANE52 0x20fd /* SnapScan e52 */
-
-/* Ain Communication Technology products */
-#define USB_PRODUCT_AINCOMM_AWU2000B 0x1001 /* AWU2000B Wireless Adapter */
-
-/* AIPTEK products */
-#define USB_PRODUCT_AIPTEK_POCKETCAM3M 0x2011 /* PocketCAM 3Mega */
-#define USB_PRODUCT_AIPTEK2_PENCAM_MEGA_1_3 0x504a /* PenCam Mega 1.3 */
-#define USB_PRODUCT_AIPTEK2_SUNPLUS_TECH 0x0c15 /* Sunplus Technology Inc. */
-
-/* AirPlis products */
-#define USB_PRODUCT_AIRPLUS_MCD650 0x3198 /* MCD650 modem */
-
-/* AirPrime products */
-#define USB_PRODUCT_AIRPRIME_PC5220 0x0112 /* CDMA Wireless PC Card */
-
-/* AirTies products */
-#define USB_PRODUCT_AIRTIES_RT3070 0x2310 /* RT3070 */
-
-/* AKS products */
-#define USB_PRODUCT_AKS_USBHASP 0x0001 /* USB-HASP 0.06 */
-
-/* Alcatel products */
-#define USB_PRODUCT_ALCATEL_OT535 0x02df /* One Touch 535/735 */
-
-/* Alcor Micro, Inc. products */
-#define USB_PRODUCT_ALCOR2_KBD_HUB 0x2802 /* Kbd Hub */
-
-#define USB_PRODUCT_ALCOR_SDCR_6335 0x6335 /* SD/MMC Card Reader */
-#define USB_PRODUCT_ALCOR_SDCR_6362 0x6362 /* SD/MMC Card Reader */
-#define USB_PRODUCT_ALCOR_TRANSCEND 0x6387 /* Transcend JetFlash Drive */
-#define USB_PRODUCT_ALCOR_MA_KBD_HUB 0x9213 /* MacAlly Kbd Hub */
-#define USB_PRODUCT_ALCOR_AU9814 0x9215 /* AU9814 Hub */
-#define USB_PRODUCT_ALCOR_UMCR_9361 0x9361 /* USB Multimedia Card Reader */
-#define USB_PRODUCT_ALCOR_SM_KBD 0x9410 /* MicroConnectors/StrongMan Keyboard */
-#define USB_PRODUCT_ALCOR_NEC_KBD_HUB 0x9472 /* NEC Kbd Hub */
-#define USB_PRODUCT_ALCOR_AU9720 0x9720 /* USB2 - RS-232 */
-#define USB_PRODUCT_ALCOR_AU6390 0x6390 /* AU6390 USB-IDE converter */
-
-/* Alink products */
-#define USB_PRODUCT_ALINK_DWM652U5 0xce16 /* DWM-652 */
-#define USB_PRODUCT_ALINK_3G 0x9000 /* 3G modem */
-#define USB_PRODUCT_ALINK_3GU 0x9200 /* 3G modem */
-
-/* Altec Lansing products */
-#define USB_PRODUCT_ALTEC_ADA70 0x0070 /* ADA70 Speakers */
-#define USB_PRODUCT_ALTEC_ASC495 0xff05 /* ASC495 Speakers */
-
-/* Allied Telesyn International products */
-#define USB_PRODUCT_ALLIEDTELESYN_ATUSB100 0xb100 /* AT-USB100 */
-
-/* ALLWIN Tech products */
-#define USB_PRODUCT_ALLWIN_RT2070 0x2070 /* RT2070 */
-#define USB_PRODUCT_ALLWIN_RT2770 0x2770 /* RT2770 */
-#define USB_PRODUCT_ALLWIN_RT2870 0x2870 /* RT2870 */
-#define USB_PRODUCT_ALLWIN_RT3070 0x3070 /* RT3070 */
-#define USB_PRODUCT_ALLWIN_RT3071 0x3071 /* RT3071 */
-#define USB_PRODUCT_ALLWIN_RT3072 0x3072 /* RT3072 */
-#define USB_PRODUCT_ALLWIN_RT3572 0x3572 /* RT3572 */
-
-/* AlphaSmart, Inc. products */
-#define USB_PRODUCT_ALPHASMART_DANA_KB 0xdbac /* AlphaSmart Dana Keyboard */
-#define USB_PRODUCT_ALPHASMART_DANA_SYNC 0xdf00 /* AlphaSmart Dana HotSync */
-
-/* Amoi products */
-#define USB_PRODUCT_AMOI_H01 0x0800 /* H01 3G modem */
-#define USB_PRODUCT_AMOI_H01A 0x7002 /* H01A 3G modem */
-#define USB_PRODUCT_AMOI_H02 0x0802 /* H02 3G modem */
-
-/* American Power Conversion products */
-#define USB_PRODUCT_APC_UPS 0x0002 /* Uninterruptible Power Supply */
-
-/* Ambit Microsystems products */
-#define USB_PRODUCT_AMBIT_WLAN 0x0302 /* WLAN */
-#define USB_PRODUCT_AMBIT_NTL_250 0x6098 /* NTL 250 cable modem */
-
-/* Apacer products */
-#define USB_PRODUCT_APACER_HT202 0xb113 /* USB 2.0 Flash Drive */
-
-/* American Power Conversion products */
-#define USB_PRODUCT_APC_UPS 0x0002 /* Uninterruptible Power Supply */
-
-/* Amigo Technology products */
-#define USB_PRODUCT_AMIGO_RT2870_1 0x9031 /* RT2870 */
-#define USB_PRODUCT_AMIGO_RT2870_2 0x9041 /* RT2870 */
-
-/* AMIT products */
-#define USB_PRODUCT_AMIT_CGWLUSB2GO 0x0002 /* CG-WLUSB2GO */
-#define USB_PRODUCT_AMIT_CGWLUSB2GNR 0x0008 /* CG-WLUSB2GNR */
-#define USB_PRODUCT_AMIT_RT2870_1 0x0012 /* RT2870 */
-
-/* AMIT(2) products */
-#define USB_PRODUCT_AMIT2_RT2870 0x0008 /* RT2870 */
-
-/* Anchor products */
-#define USB_PRODUCT_ANCHOR_SERIAL 0x2008 /* Serial */
-#define USB_PRODUCT_ANCHOR_EZUSB 0x2131 /* EZUSB */
-#define USB_PRODUCT_ANCHOR_EZLINK 0x2720 /* EZLINK */
-
-/* AnyData products */
-#define USB_PRODUCT_ANYDATA_ADU_620UW 0x6202 /* CDMA 2000 EV-DO USB Modem */
-#define USB_PRODUCT_ANYDATA_ADU_E100X 0x6501 /* CDMA 2000 1xRTT/EV-DO USB Modem */
-#define USB_PRODUCT_ANYDATA_ADU_500A 0x6502 /* CDMA 2000 EV-DO USB Modem */
-
-/* AOX, Inc. products */
-#define USB_PRODUCT_AOX_USB101 0x0008 /* Ethernet */
-
-/* American Power Conversion products */
-#define USB_PRODUCT_APC_UPS 0x0002 /* Uninterruptible Power Supply */
-
-/* Apple Computer products */
-#define USB_PRODUCT_APPLE_IMAC_KBD 0x0201 /* USB iMac Keyboard */
-#define USB_PRODUCT_APPLE_KBD 0x0202 /* USB Keyboard M2452 */
-#define USB_PRODUCT_APPLE_EXT_KBD 0x020c /* Apple Extended USB Keyboard */
-#define USB_PRODUCT_APPLE_KBD_TP_ANSI 0x0223 /* Apple Internal Keyboard/Trackpad (Wellspring/ANSI) */
-#define USB_PRODUCT_APPLE_KBD_TP_ISO 0x0224 /* Apple Internal Keyboard/Trackpad (Wellspring/ISO) */
-#define USB_PRODUCT_APPLE_KBD_TP_JIS 0x0225 /* Apple Internal Keyboard/Trackpad (Wellspring/JIS) */
-#define USB_PRODUCT_APPLE_KBD_TP_ANSI2 0x0230 /* Apple Internal Keyboard/Trackpad (Wellspring2/ANSI) */
-#define USB_PRODUCT_APPLE_KBD_TP_ISO2 0x0231 /* Apple Internal Keyboard/Trackpad (Wellspring2/ISO) */
-#define USB_PRODUCT_APPLE_KBD_TP_JIS2 0x0232 /* Apple Internal Keyboard/Trackpad (Wellspring2/JIS) */
-#define USB_PRODUCT_APPLE_MOUSE 0x0301 /* Mouse M4848 */
-#define USB_PRODUCT_APPLE_OPTMOUSE 0x0302 /* Optical mouse */
-#define USB_PRODUCT_APPLE_MIGHTYMOUSE 0x0304 /* Mighty Mouse */
-#define USB_PRODUCT_APPLE_KBD_HUB 0x1001 /* Hub in Apple USB Keyboard */
-#define USB_PRODUCT_APPLE_EXT_KBD_HUB 0x1003 /* Hub in Apple Extended USB Keyboard */
-#define USB_PRODUCT_APPLE_SPEAKERS 0x1101 /* Speakers */
-#define USB_PRODUCT_APPLE_IPOD 0x1201 /* iPod */
-#define USB_PRODUCT_APPLE_IPOD2G 0x1202 /* iPod 2G */
-#define USB_PRODUCT_APPLE_IPOD3G 0x1203 /* iPod 3G */
-#define USB_PRODUCT_APPLE_IPOD_04 0x1204 /* iPod '04' */
-#define USB_PRODUCT_APPLE_IPODMINI 0x1205 /* iPod Mini */
-#define USB_PRODUCT_APPLE_IPOD_06 0x1206 /* iPod '06' */
-#define USB_PRODUCT_APPLE_IPOD_07 0x1207 /* iPod '07' */
-#define USB_PRODUCT_APPLE_IPOD_08 0x1208 /* iPod '08' */
-#define USB_PRODUCT_APPLE_IPODVIDEO 0x1209 /* iPod Video */
-#define USB_PRODUCT_APPLE_IPODNANO 0x120a /* iPod Nano */
-#define USB_PRODUCT_APPLE_IPHONE 0x1290 /* iPhone */
-#define USB_PRODUCT_APPLE_IPOD_TOUCH 0x1291 /* iPod Touch */
-#define USB_PRODUCT_APPLE_IPHONE_3G 0x1292 /* iPhone 3G */
-#define USB_PRODUCT_APPLE_IPHONE_3GS 0x1294 /* iPhone 3GS */
-#define USB_PRODUCT_APPLE_IPHONE_4 0x1297 /* iPhone 4 */
-#define USB_PRODUCT_APPLE_IPAD 0x129a /* iPad */
-#define USB_PRODUCT_APPLE_ETHERNET 0x1402 /* Ethernet A1277 */
-
-/* Arkmicro Technologies */
-#define USB_PRODUCT_ARKMICRO_ARK3116 0x0232 /* ARK3116 Serial */
-
-/* Asahi Optical products */
-#define USB_PRODUCT_ASAHIOPTICAL_OPTIO230 0x0004 /* Digital camera */
-#define USB_PRODUCT_ASAHIOPTICAL_OPTIO330 0x0006 /* Digital camera */
-
-/* Asante products */
-#define USB_PRODUCT_ASANTE_EA 0x1427 /* Ethernet */
-
-/* ASIX Electronics products */
-#define USB_PRODUCT_ASIX_AX88172 0x1720 /* 10/100 Ethernet */
-#define USB_PRODUCT_ASIX_AX88178 0x1780 /* AX88178 */
-#define USB_PRODUCT_ASIX_AX88772 0x7720 /* AX88772 */
-#define USB_PRODUCT_ASIX_AX88772A 0x772a /* AX88772A USB 2.0 10/100 Ethernet */
-
-/* ASUS products */
-#define USB_PRODUCT_ASUS2_USBN11 0x0b05 /* USB-N11 */
-#define USB_PRODUCT_ASUS_WL167G 0x1707 /* WL-167g Wireless Adapter */
-#define USB_PRODUCT_ASUS_WL159G 0x170c /* WL-159g */
-#define USB_PRODUCT_ASUS_A9T_WIFI 0x171b /* A9T wireless */
-#define USB_PRODUCT_ASUS_P5B_WIFI 0x171d /* P5B wireless */
-#define USB_PRODUCT_ASUS_RT2573_1 0x1723 /* RT2573 */
-#define USB_PRODUCT_ASUS_RT2573_2 0x1724 /* RT2573 */
-#define USB_PRODUCT_ASUS_LCM 0x1726 /* LCM display */
-#define USB_PRODUCT_ASUS_RT2870_1 0x1731 /* RT2870 */
-#define USB_PRODUCT_ASUS_RT2870_2 0x1732 /* RT2870 */
-#define USB_PRODUCT_ASUS_RT2870_3 0x1742 /* RT2870 */
-#define USB_PRODUCT_ASUS_RT2870_4 0x1760 /* RT2870 */
-#define USB_PRODUCT_ASUS_RT2870_5 0x1761 /* RT2870 */
-#define USB_PRODUCT_ASUS_USBN13 0x1784 /* USB-N13 */
-#define USB_PRODUCT_ASUS_RT3070_1 0x1790 /* RT3070 */
-#define USB_PRODUCT_ASUS_A730W 0x4202 /* ASUS MyPal A730W */
-#define USB_PRODUCT_ASUS_P535 0x420f /* ASUS P535 PDA */
-#define USB_PRODUCT_ASUS_GMSC 0x422f /* ASUS Generic Mass Storage */
-#define USB_PRODUCT_ASUS_RT2570 0x1706 /* RT2500USB Wireless Adapter */
-
-/* ATen products */
-#define USB_PRODUCT_ATEN_UC1284 0x2001 /* Parallel printer */
-#define USB_PRODUCT_ATEN_UC10T 0x2002 /* 10Mbps Ethernet */
-#define USB_PRODUCT_ATEN_UC110T 0x2007 /* UC-110T Ethernet */
-#define USB_PRODUCT_ATEN_UC232A 0x2008 /* Serial */
-#define USB_PRODUCT_ATEN_UC210T 0x2009 /* UC-210T Ethernet */
-#define USB_PRODUCT_ATEN_DSB650C 0x4000 /* DSB-650C */
-
-/* Atheros Communications products */
-#define USB_PRODUCT_ATHEROS_AR5523 0x0001 /* AR5523 */
-#define USB_PRODUCT_ATHEROS_AR5523_NF 0x0002 /* AR5523 (no firmware) */
-#define USB_PRODUCT_ATHEROS2_AR5523_1 0x0001 /* AR5523 */
-#define USB_PRODUCT_ATHEROS2_AR5523_1_NF 0x0002 /* AR5523 (no firmware) */
-#define USB_PRODUCT_ATHEROS2_AR5523_2 0x0003 /* AR5523 */
-#define USB_PRODUCT_ATHEROS2_AR5523_2_NF 0x0004 /* AR5523 (no firmware) */
-#define USB_PRODUCT_ATHEROS2_AR5523_3 0x0005 /* AR5523 */
-#define USB_PRODUCT_ATHEROS2_AR5523_3_NF 0x0006 /* AR5523 (no firmware) */
-
-/* Atmel Comp. products */
-#define USB_PRODUCT_ATMEL_STK541 0x2109 /* Zigbee Controller */
-#define USB_PRODUCT_ATMEL_UHB124 0x3301 /* UHB124 hub */
-#define USB_PRODUCT_ATMEL_DWL120 0x7603 /* DWL-120 Wireless Adapter */
-#define USB_PRODUCT_ATMEL_BW002 0x7605 /* BW002 Wireless Adapter */
-#define USB_PRODUCT_ATMEL_WL1130USB 0x7613 /* WL-1130 USB */
-#define USB_PRODUCT_ATMEL_AT76C505A 0x7614 /* AT76c505a Wireless Adapter */
-
-/* AuthenTec products */
-#define USB_PRODUCT_AUTHENTEC_AES1610 0x1600 /* AES1610 Fingerprint Sensor */
-
-/* Avision products */
-#define USB_PRODUCT_AVISION_1200U 0x0268 /* 1200U scanner */
-
-/* Axesstel products */
-#define USB_PRODUCT_AXESSTEL_DATAMODEM 0x1000 /* Data Modem */
-
-/* AsureWave products */
-#define USB_PRODUCT_AZUREWAVE_RT2870_1 0x3247 /* RT2870 */
-#define USB_PRODUCT_AZUREWAVE_RT2870_2 0x3262 /* RT2870 */
-#define USB_PRODUCT_AZUREWAVE_RT3070_1 0x3273 /* RT3070 */
-#define USB_PRODUCT_AZUREWAVE_RT3070_2 0x3284 /* RT3070 */
-#define USB_PRODUCT_AZUREWAVE_RT3070_3 0x3305 /* RT3070 */
-
-/* Baltech products */
-#define USB_PRODUCT_BALTECH_CARDREADER 0x9999 /* Card reader */
-
-/* B&B Electronics products */
-#define USB_PRODUCT_BBELECTRONICS_USOTL4 0xAC01 /* RS-422/485 */
-
-/* Belkin products */
-/*product BELKIN F5U111 0x???? F5U111 Ethernet*/
-#define USB_PRODUCT_BELKIN_F5D6050 0x0050 /* F5D6050 802.11b Wireless Adapter */
-#define USB_PRODUCT_BELKIN_FBT001V 0x0081 /* FBT001v2 Bluetooth */
-#define USB_PRODUCT_BELKIN_FBT003V 0x0084 /* FBT003v2 Bluetooth */
-#define USB_PRODUCT_BELKIN_F5U103 0x0103 /* F5U103 Serial */
-#define USB_PRODUCT_BELKIN_F5U109 0x0109 /* F5U109 Serial */
-#define USB_PRODUCT_BELKIN_USB2SCSI 0x0115 /* USB to SCSI */
-#define USB_PRODUCT_BELKIN_F8T012 0x0121 /* F8T012xx1 Bluetooth USB Adapter */
-#define USB_PRODUCT_BELKIN_USB2LAN 0x0121 /* USB to LAN */
-#define USB_PRODUCT_BELKIN_F5U208 0x0208 /* F5U208 VideoBus II */
-#define USB_PRODUCT_BELKIN_F5U237 0x0237 /* F5U237 USB 2.0 7-Port Hub */
-#define USB_PRODUCT_BELKIN_F5U257 0x0257 /* F5U257 Serial */
-#define USB_PRODUCT_BELKIN_F5U409 0x0409 /* F5U409 Serial */
-#define USB_PRODUCT_BELKIN_F6C550AVR 0x0551 /* F6C550-AVR UPS */
-#define USB_PRODUCT_BELKIN_F5U120 0x1203 /* F5U120-PC Hub */
-#define USB_PRODUCT_BELKIN_ZD1211B 0x4050 /* ZD1211B */
-#define USB_PRODUCT_BELKIN_F5D5055 0x5055 /* F5D5055 */
-#define USB_PRODUCT_BELKIN_F5D7050 0x7050 /* F5D7050 Wireless Adapter */
-#define USB_PRODUCT_BELKIN_F5D7051 0x7051 /* F5D7051 54g USB Network Adapter */
-#define USB_PRODUCT_BELKIN_F5D7050A 0x705a /* F5D7050A Wireless Adapter */
-/* Also sold as 'Ativa 802.11g wireless card' */
-#define USB_PRODUCT_BELKIN_F5D7050_V4000 0x705c /* F5D7050 v4000 Wireless Adapter */
-#define USB_PRODUCT_BELKIN_F5D7050E 0x705e /* F5D7050E Wireless Adapter */
-#define USB_PRODUCT_BELKIN_RT2870_1 0x8053 /* RT2870 */
-#define USB_PRODUCT_BELKIN_RT2870_2 0x805c /* RT2870 */
-#define USB_PRODUCT_BELKIN_F5D8053V3 0x815c /* F5D8053 v3 */
-#define USB_PRODUCT_BELKIN_F5D8055 0x825a /* F5D8055 */
-#define USB_PRODUCT_BELKIN_F5D9050V3 0x905b /* F5D9050 ver 3 Wireless Adapter */
-#define USB_PRODUCT_BELKIN2_F5U002 0x0002 /* F5U002 Parallel printer */
-#define USB_PRODUCT_BELKIN_F6D4050V1 0x935a /* F6D4050 v1 */
-
-/* Billionton products */
-#define USB_PRODUCT_BILLIONTON_USB100 0x0986 /* USB100N 10/100 FastEthernet */
-#define USB_PRODUCT_BILLIONTON_USBLP100 0x0987 /* USB100LP */
-#define USB_PRODUCT_BILLIONTON_USBEL100 0x0988 /* USB100EL */
-#define USB_PRODUCT_BILLIONTON_USBE100 0x8511 /* USBE100 */
-#define USB_PRODUCT_BILLIONTON_USB2AR 0x90ff /* USB2AR Ethernet */
-
-/* Broadcom products */
-#define USB_PRODUCT_BROADCOM_BCM2033 0x2033 /* BCM2033 Bluetooth USB dongle */
-
-/* Brother Industries products */
-#define USB_PRODUCT_BROTHER_HL1050 0x0002 /* HL-1050 laser printer */
-#define USB_PRODUCT_BROTHER_MFC8600_9650 0x0100 /* MFC8600/9650 multifunction device */
-
-/* Behavior Technology Computer products */
-#define USB_PRODUCT_BTC_BTC6100 0x5550 /* 6100C Keyboard */
-#define USB_PRODUCT_BTC_BTC7932 0x6782 /* Keyboard with mouse port */
-
-/* Canon, Inc. products */
-#define USB_PRODUCT_CANON_N656U 0x2206 /* CanoScan N656U */
-#define USB_PRODUCT_CANON_N1220U 0x2207 /* CanoScan N1220U */
-#define USB_PRODUCT_CANON_D660U 0x2208 /* CanoScan D660U */
-#define USB_PRODUCT_CANON_N676U 0x220d /* CanoScan N676U */
-#define USB_PRODUCT_CANON_N1240U 0x220e /* CanoScan N1240U */
-#define USB_PRODUCT_CANON_LIDE25 0x2220 /* CanoScan LIDE 25 */
-#define USB_PRODUCT_CANON_S10 0x3041 /* PowerShot S10 */
-#define USB_PRODUCT_CANON_S100 0x3045 /* PowerShot S100 */
-#define USB_PRODUCT_CANON_S200 0x3065 /* PowerShot S200 */
-#define USB_PRODUCT_CANON_REBELXT 0x30ef /* Digital Rebel XT */
-
-/* CATC products */
-#define USB_PRODUCT_CATC_NETMATE 0x000a /* Netmate Ethernet */
-#define USB_PRODUCT_CATC_NETMATE2 0x000c /* Netmate2 Ethernet */
-#define USB_PRODUCT_CATC_CHIEF 0x000d /* USB Chief Bus & Protocol Analyzer */
-#define USB_PRODUCT_CATC_ANDROMEDA 0x1237 /* Andromeda hub */
-
-/* CASIO products */
-#define USB_PRODUCT_CASIO_QV_DIGICAM 0x1001 /* QV DigiCam */
-#define USB_PRODUCT_CASIO_EXS880 0x1105 /* Exilim EX-S880 */
-#define USB_PRODUCT_CASIO_BE300 0x2002 /* BE-300 PDA */
-#define USB_PRODUCT_CASIO_NAMELAND 0x4001 /* CASIO Nameland EZ-USB */
-
-/* CCYU products */
-#define USB_PRODUCT_CCYU_ED1064 0x2136 /* EasyDisk ED1064 */
-
-/* Century products */
-#define USB_PRODUCT_CENTURY_EX35QUAT 0x011e /* Century USB Disk Enclosure */
-#define USB_PRODUCT_CENTURY_EX35SW4_SB4 0x011f /* Century USB Disk Enclosure */
-
-/* Cherry products */
-#define USB_PRODUCT_CHERRY_MY3000KBD 0x0001 /* My3000 keyboard */
-#define USB_PRODUCT_CHERRY_MY3000HUB 0x0003 /* My3000 hub */
-#define USB_PRODUCT_CHERRY_CYBOARD 0x0004 /* CyBoard Keyboard */
-
-/* Chic Technology products */
-#define USB_PRODUCT_CHIC_MOUSE1 0x0001 /* mouse */
-#define USB_PRODUCT_CHIC_CYPRESS 0x0003 /* Cypress USB Mouse */
-
-/* Chicony products */
-#define USB_PRODUCT_CHICONY_KB8933 0x0001 /* KB-8933 keyboard */
-#define USB_PRODUCT_CHICONY_KU0325 0x0116 /* KU-0325 keyboard */
-#define USB_PRODUCT_CHICONY_CNF7129 0xb071 /* Notebook Web Camera */
-#define USB_PRODUCT_CHICONY2_TWINKLECAM 0x600d /* TwinkleCam USB camera */
-
-/* CH Products */
-#define USB_PRODUCT_CHPRODUCTS_PROTHROTTLE 0x00f1 /* Pro Throttle */
-#define USB_PRODUCT_CHPRODUCTS_PROPEDALS 0x00f2 /* Pro Pedals */
-#define USB_PRODUCT_CHPRODUCTS_FIGHTERSTICK 0x00f3 /* Fighterstick */
-#define USB_PRODUCT_CHPRODUCTS_FLIGHTYOKE 0x00ff /* Flight Sim Yoke */
-
-/* Cisco-Linksys products */
-#define USB_PRODUCT_CISCOLINKSYS_WUSB54AG 0x000c /* WUSB54AG Wireless Adapter */
-#define USB_PRODUCT_CISCOLINKSYS_WUSB54G 0x000d /* WUSB54G Wireless Adapter */
-#define USB_PRODUCT_CISCOLINKSYS_WUSB54GP 0x0011 /* WUSB54GP Wireless Adapter */
-#define USB_PRODUCT_CISCOLINKSYS_USB200MV2 0x0018 /* USB200M v2 */
-#define USB_PRODUCT_CISCOLINKSYS_HU200TS 0x001a /* HU200TS Wireless Adapter */
-#define USB_PRODUCT_CISCOLINKSYS_WUSB54GC 0x0020 /* WUSB54GC */
-#define USB_PRODUCT_CISCOLINKSYS_WUSB54GR 0x0023 /* WUSB54GR */
-#define USB_PRODUCT_CISCOLINKSYS_WUSBF54G 0x0024 /* WUSBF54G */
-#define USB_PRODUCT_CISCOLINKSYS2_RT3070 0x4001 /* RT3070 */
-#define USB_PRODUCT_CISCOLINKSYS3_RT3070 0x0101 /* RT3070 */
-
-/* Clipsal products */
-#define USB_PRODUCT_CLIPSAL_5500PCU 0x0303 /* 5500PCU C-Bus */
-
-/* CMOTECH products */
-#define USB_PRODUCT_CMOTECH_CNU510 0x5141 /* CDMA Technologies USB modem */
-#define USB_PRODUCT_CMOTECH_CNU550 0x5543 /* CDMA 2000 1xRTT/1xEVDO USB modem */
-#define USB_PRODUCT_CMOTECH_CGU628 0x6006 /* CGU-628 */
-#define USB_PRODUCT_CMOTECH_CDMA_MODEM1 0x6280 /* CDMA Technologies USB modem */
-#define USB_PRODUCT_CMOTECH_DISK 0xf000 /* disk mode */
-
-/* Compaq products */
-#define USB_PRODUCT_COMPAQ_IPAQPOCKETPC 0x0003 /* iPAQ PocketPC */
-#define USB_PRODUCT_COMPAQ_PJB100 0x504a /* Personal Jukebox PJB100 */
-#define USB_PRODUCT_COMPAQ_IPAQLINUX 0x505a /* iPAQ Linux */
-
-/* Composite Corp products looks the same as "TANGTOP" */
-#define USB_PRODUCT_COMPOSITE_USBPS2 0x0001 /* USB to PS2 Adaptor */
-
-/* Conceptronic products */
-#define USB_PRODUCT_CONCEPTRONIC_PRISM_GT 0x3762 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_CONCEPTRONIC_C11U 0x7100 /* C11U */
-#define USB_PRODUCT_CONCEPTRONIC_WL210 0x7110 /* WL-210 */
-#define USB_PRODUCT_CONCEPTRONIC_AR5523_1 0x7801 /* AR5523 */
-#define USB_PRODUCT_CONCEPTRONIC_AR5523_1_NF 0x7802 /* AR5523 (no firmware) */
-#define USB_PRODUCT_CONCEPTRONIC_AR5523_2 0x7811 /* AR5523 */
-#define USB_PRODUCT_CONCEPTRONIC_AR5523_2_NF 0x7812 /* AR5523 (no firmware) */
-#define USB_PRODUCT_CONCEPTRONIC2_C54RU 0x3c02 /* C54RU WLAN */
-#define USB_PRODUCT_CONCEPTRONIC2_C54RU2 0x3c22 /* C54RU */
-#define USB_PRODUCT_CONCEPTRONIC2_RT3070_1 0x3c08 /* RT3070 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT3070_2 0x3c11 /* RT3070 */
-#define USB_PRODUCT_CONCEPTRONIC2_VIGORN61 0x3c25 /* VIGORN61 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_1 0x3c06 /* RT2870 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_2 0x3c07 /* RT2870 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_7 0x3c09 /* RT2870 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_8 0x3c12 /* RT2870 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_3 0x3c23 /* RT2870 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_4 0x3c25 /* RT2870 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_5 0x3c27 /* RT2870 */
-#define USB_PRODUCT_CONCEPTRONIC2_RT2870_6 0x3c28 /* RT2870 */
-
-/* Connectix products */
-#define USB_PRODUCT_CONNECTIX_QUICKCAM 0x0001 /* QuickCam */
-
-/* Corega products */
-#define USB_PRODUCT_COREGA_ETHER_USB_T 0x0001 /* Ether USB-T */
-#define USB_PRODUCT_COREGA_FETHER_USB_TX 0x0004 /* FEther USB-TX */
-#define USB_PRODUCT_COREGA_WLAN_USB_USB_11 0x000c /* WirelessLAN USB-11 */
-#define USB_PRODUCT_COREGA_FETHER_USB_TXS 0x000d /* FEther USB-TXS */
-#define USB_PRODUCT_COREGA_WLANUSB 0x0012 /* Wireless LAN Stick-11 */
-#define USB_PRODUCT_COREGA_FETHER_USB2_TX 0x0017 /* FEther USB2-TX */
-#define USB_PRODUCT_COREGA_WLUSB_11_KEY 0x001a /* ULUSB-11 Key */
-#define USB_PRODUCT_COREGA_CGUSBRS232R 0x002a /* CG-USBRS232R */
-#define USB_PRODUCT_COREGA_CGWLUSB2GL 0x002d /* CG-WLUSB2GL */
-#define USB_PRODUCT_COREGA_CGWLUSB2GPX 0x002e /* CG-WLUSB2GPX */
-#define USB_PRODUCT_COREGA_RT2870_1 0x002f /* RT2870 */
-#define USB_PRODUCT_COREGA_RT2870_2 0x003c /* RT2870 */
-#define USB_PRODUCT_COREGA_RT2870_3 0x003f /* RT2870 */
-#define USB_PRODUCT_COREGA_RT3070 0x0041 /* RT3070 */
-#define USB_PRODUCT_COREGA_CGWLUSB300GNM 0x0042 /* CG-WLUSB300GNM */
-
-#define USB_PRODUCT_COREGA_WLUSB_11_STICK 0x7613 /* WLAN USB Stick 11 */
-#define USB_PRODUCT_COREGA_FETHER_USB_TXC 0x9601 /* FEther USB-TXC */
-
-/* Creative products */
-#define USB_PRODUCT_CREATIVE_NOMAD_II 0x1002 /* Nomad II MP3 player */
-#define USB_PRODUCT_CREATIVE_NOMAD_IIMG 0x4004 /* Nomad II MG */
-#define USB_PRODUCT_CREATIVE_NOMAD 0x4106 /* Nomad */
-#define USB_PRODUCT_CREATIVE2_VOIP_BLASTER 0x0258 /* Voip Blaster */
-#define USB_PRODUCT_CREATIVE3_OPTICAL_MOUSE 0x0001 /* Notebook Optical Mouse */
-
-/* Cambridge Silicon Radio Ltd. products */
-#define USB_PRODUCT_CSR_BT_DONGLE 0x0001 /* Bluetooth USB dongle */
-#define USB_PRODUCT_CSR_CSRDFU 0xffff /* USB Bluetooth Device in DFU State */
-
-/* Chipsbank Microelectronics Co., Ltd */
-#define USB_PRODUCT_CHIPSBANK_USBMEMSTICK 0x6025 /* CBM2080 Flash drive controller */
-#define USB_PRODUCT_CHIPSBANK_USBMEMSTICK1 0x6026 /* CBM1180 Flash drive controller */
-
-/* CTX products */
-#define USB_PRODUCT_CTX_EX1300 0x9999 /* Ex1300 hub */
-
-/* Curitel products */
-#define USB_PRODUCT_CURITEL_HX550C 0x1101 /* CDMA 2000 1xRTT USB modem (HX-550C) */
-#define USB_PRODUCT_CURITEL_HX57XB 0x2101 /* CDMA 2000 1xRTT USB modem (HX-570/575B/PR-600) */
-#define USB_PRODUCT_CURITEL_PC5740 0x3701 /* Broadband Wireless modem */
-#define USB_PRODUCT_CURITEL_UM175 0x3714 /* EVDO modem */
-
-/* CyberPower products */
-#define USB_PRODUCT_CYBERPOWER_1500CAVRLCD 0x0501 /* 1500CAVRLCD */
-
-/* CyberTAN Technology products */
-#define USB_PRODUCT_CYBERTAN_TG54USB 0x1666 /* TG54USB */
-#define USB_PRODUCT_CYBERTAN_RT2870 0x1828 /* RT2870 */
-
-/* Cypress Semiconductor products */
-#define USB_PRODUCT_CYPRESS_MOUSE 0x0001 /* mouse */
-#define USB_PRODUCT_CYPRESS_THERMO 0x0002 /* thermometer */
-#define USB_PRODUCT_CYPRESS_WISPY1A 0x0bad /* MetaGeek Wi-Spy */
-#define USB_PRODUCT_CYPRESS_KBDHUB 0x0101 /* Keyboard/Hub */
-#define USB_PRODUCT_CYPRESS_FMRADIO 0x1002 /* FM Radio */
-#define USB_PRODUCT_CYPRESS_IKARILASER 0x121f /* Ikari Laser SteelSeries ApS */
-
-#define USB_PRODUCT_CYPRESS_USBRS232 0x5500 /* USB-RS232 Interface */
-#define USB_PRODUCT_CYPRESS_SLIM_HUB 0x6560 /* Slim Hub */
-#define USB_PRODUCT_CYPRESS_XX6830XX 0x6830 /* PATA Storage Device */
-#define USB_PRODUCT_CYPRESS_SILVERSHIELD 0xfd13 /* Gembird Silver Shield PM */
-
-/* Daisy Technology products */
-#define USB_PRODUCT_DAISY_DMC 0x6901 /* USB MultiMedia Reader */
-
-/* Dallas Semiconductor products */
-#define USB_PRODUCT_DALLAS_J6502 0x4201 /* J-6502 speakers */
-
-/* DataApex products */
-#define USB_PRODUCT_DATAAPEX_MULTICOM 0xead6 /* MultiCom */
-
-/* Dell products */
-#define USB_PRODUCT_DELL_PORT 0x0058 /* Port Replicator */
-#define USB_PRODUCT_DELL_AIO926 0x5115 /* Photo AIO Printer 926 */
-#define USB_PRODUCT_DELL_BC02 0x8000 /* BC02 Bluetooth USB Adapter */
-#define USB_PRODUCT_DELL_PRISM_GT_1 0x8102 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_DELL_TM350 0x8103 /* TrueMobile 350 Bluetooth USB Adapter */
-#define USB_PRODUCT_DELL_PRISM_GT_2 0x8104 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_DELL_U5700 0x8114 /* Dell 5700 3G */
-#define USB_PRODUCT_DELL_U5500 0x8115 /* Dell 5500 3G */
-#define USB_PRODUCT_DELL_U5505 0x8116 /* Dell 5505 3G */
-#define USB_PRODUCT_DELL_U5700_2 0x8117 /* Dell 5700 3G */
-#define USB_PRODUCT_DELL_U5510 0x8118 /* Dell 5510 3G */
-#define USB_PRODUCT_DELL_U5700_3 0x8128 /* Dell 5700 3G */
-#define USB_PRODUCT_DELL_U5700_4 0x8129 /* Dell 5700 3G */
-#define USB_PRODUCT_DELL_U5720 0x8133 /* Dell 5720 3G */
-#define USB_PRODUCT_DELL_U5720_2 0x8134 /* Dell 5720 3G */
-#define USB_PRODUCT_DELL_U740 0x8135 /* Dell U740 CDMA */
-#define USB_PRODUCT_DELL_U5520 0x8136 /* Dell 5520 3G */
-#define USB_PRODUCT_DELL_U5520_2 0x8137 /* Dell 5520 3G */
-#define USB_PRODUCT_DELL_U5520_3 0x8138 /* Dell 5520 3G */
-#define USB_PRODUCT_DELL_U5730 0x8180 /* Dell 5730 3G */
-#define USB_PRODUCT_DELL_U5730_2 0x8181 /* Dell 5730 3G */
-#define USB_PRODUCT_DELL_U5730_3 0x8182 /* Dell 5730 3G */
-#define USB_PRODUCT_DELL_DW700 0x9500 /* Dell DW700 GPS */
-
-/* Delorme Paublishing products */
-#define USB_PRODUCT_DELORME_EARTHMATE 0x0100 /* Earthmate GPS */
-
-/* Desknote products */
-#define USB_PRODUCT_DESKNOTE_UCR_61S2B 0x0c55 /* UCR-61S2B */
-
-/* Diamond products */
-#define USB_PRODUCT_DIAMOND_RIO500USB 0x0001 /* Rio 500 USB */
-
-/* Dick Smith Electronics (really C-Net) products */
-#define USB_PRODUCT_DICKSMITH_RT2573 0x9022 /* RT2573 */
-#define USB_PRODUCT_DICKSMITH_CWD854F 0x9032 /* C-Net CWD-854 rev F */
-
-/* Digi International products */
-#define USB_PRODUCT_DIGI_ACCELEPORT2 0x0002 /* AccelePort USB 2 */
-#define USB_PRODUCT_DIGI_ACCELEPORT4 0x0004 /* AccelePort USB 4 */
-#define USB_PRODUCT_DIGI_ACCELEPORT8 0x0008 /* AccelePort USB 8 */
-
-/* Digianswer A/S products */
-#define USB_PRODUCT_DIGIANSWER_ZIGBEE802154 0x000a /* ZigBee/802.15.4 MAC */
-
-/* D-Link products */
-/*product DLINK DSBS25 0x0100 DSB-S25 serial*/
-#define USB_PRODUCT_DLINK_DUBE100 0x1a00 /* 10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DSB650TX4 0x200c /* 10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DWL120E 0x3200 /* DWL-120 rev E */
-#define USB_PRODUCT_DLINK_DWL122 0x3700 /* DWL-122 */
-#define USB_PRODUCT_DLINK_DWLG120 0x3701 /* DWL-G120 */
-#define USB_PRODUCT_DLINK_DWL120F 0x3702 /* DWL-120 rev F */
-#define USB_PRODUCT_DLINK_DWLAG132 0x3a00 /* DWL-AG132 */
-#define USB_PRODUCT_DLINK_DWLAG132_NF 0x3a01 /* DWL-AG132 (no firmware) */
-#define USB_PRODUCT_DLINK_DWLG132 0x3a02 /* DWL-G132 */
-#define USB_PRODUCT_DLINK_DWLG132_NF 0x3a03 /* DWL-G132 (no firmware) */
-#define USB_PRODUCT_DLINK_DWLAG122 0x3a04 /* DWL-AG122 */
-#define USB_PRODUCT_DLINK_DWLAG122_NF 0x3a05 /* DWL-AG122 (no firmware) */
-#define USB_PRODUCT_DLINK_DWLG122 0x3c00 /* DWL-G122 b1 Wireless Adapter */
-#define USB_PRODUCT_DLINK_DUBE100B1 0x3c05 /* DUB-E100 rev B1 */
-#define USB_PRODUCT_DLINK_RT2870 0x3c09 /* RT2870 */
-#define USB_PRODUCT_DLINK_RT3072 0x3c0a /* RT3072 */
-#define USB_PRODUCT_DLINK_DSB650C 0x4000 /* 10Mbps Ethernet */
-#define USB_PRODUCT_DLINK_DSB650TX1 0x4001 /* 10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DSB650TX 0x4002 /* 10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DSB650TX_PNA 0x4003 /* 1/10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DSB650TX3 0x400b /* 10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DSB650TX2 0x4102 /* 10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DSB650 0xabc1 /* 10/100 Ethernet */
-#define USB_PRODUCT_DLINK_DUBH7 0xf103 /* DUB-H7 USB 2.0 7-Port Hub */
-#define USB_PRODUCT_DLINK2_DWA120 0x3a0c /* DWA-120 */
-#define USB_PRODUCT_DLINK2_DWA120_NF 0x3a0d /* DWA-120 (no firmware) */
-#define USB_PRODUCT_DLINK2_DWLG122C1 0x3c03 /* DWL-G122 c1 */
-#define USB_PRODUCT_DLINK2_WUA1340 0x3c04 /* WUA-1340 */
-#define USB_PRODUCT_DLINK2_DWA111 0x3c06 /* DWA-111 */
-#define USB_PRODUCT_DLINK2_RT2870_1 0x3c09 /* RT2870 */
-#define USB_PRODUCT_DLINK2_DWA110 0x3c07 /* DWA-110 */
-#define USB_PRODUCT_DLINK2_RT3072 0x3c0a /* RT3072 */
-#define USB_PRODUCT_DLINK2_RT3072_1 0x3c0b /* RT3072 */
-#define USB_PRODUCT_DLINK2_RT3070_1 0x3c0d /* RT3070 */
-#define USB_PRODUCT_DLINK2_RT3070_2 0x3c0e /* RT3070 */
-#define USB_PRODUCT_DLINK2_RT3070_3 0x3c0f /* RT3070 */
-#define USB_PRODUCT_DLINK2_RT2870_2 0x3c11 /* RT2870 */
-#define USB_PRODUCT_DLINK2_DWA130 0x3c13 /* DWA-130 */
-#define USB_PRODUCT_DLINK2_RT3070_4 0x3c15 /* RT3070 */
-#define USB_PRODUCT_DLINK2_RT3070_5 0x3c16 /* RT3070 */
-#define USB_PRODUCT_DLINK3_DWM652 0x3e04 /* DWM-652 */
-
-/* DMI products */
-#define USB_PRODUCT_DMI_CFSM_RW 0xa109 /* CF/SM Reader/Writer */
-#define USB_PRODUCT_DMI_DISK 0x2bcf /* Generic Disk */
-
-/* DrayTek products */
-#define USB_PRODUCT_DRAYTEK_VIGOR550 0x0550 /* Vigor550 */
-
-/* dresden elektronik products */
-#define USB_PRODUCT_DRESDENELEKTRONIK_SENSORTERMINALBOARD 0x0001 /* SensorTerminalBoard */
-#define USB_PRODUCT_DRESDENELEKTRONIK_WIRELESSHANDHELDTERMINAL 0x0004 /* Wireless Handheld Terminal */
-
-/* Dynastream Innovations */
-#define USB_PRODUCT_DYNASTREAM_ANTDEVBOARD 0x1003 /* ANT dev board */
-#define USB_PRODUCT_DYNASTREAM_ANT2USB 0x1004 /* ANT2USB */
-#define USB_PRODUCT_DYNASTREAM_ANTDEVBOARD2 0x1006 /* ANT dev board */
-
-/* Edimax products */
-#define USB_PRODUCT_EDIMAX_EW7318USG 0x7318 /* USB Wireless dongle */
-#define USB_PRODUCT_EDIMAX_RT2870_1 0x7711 /* RT2870 */
-#define USB_PRODUCT_EDIMAX_EW7717 0x7717 /* EW-7717 */
-#define USB_PRODUCT_EDIMAX_EW7718 0x7718 /* EW-7718 */
-
-/* eGalax Products */
-#define USB_PRODUCT_EGALAX_TPANEL 0x0001 /* Touch Panel */
-#define USB_PRODUCT_EGALAX_TPANEL2 0x0002 /* Touch Panel */
-#define USB_PRODUCT_EGALAX2_TPANEL 0x0001 /* Touch Panel */
-
-/* Eicon Networks */
-#define USB_PRODUCT_EICON_DIVA852 0x4905 /* Diva 852 ISDN TA */
-
-/* EIZO products */
-#define USB_PRODUCT_EIZO_HUB 0x0000 /* hub */
-#define USB_PRODUCT_EIZO_MONITOR 0x0001 /* monitor */
-
-/* ELCON Systemtechnik products */
-#define USB_PRODUCT_ELCON_PLAN 0x0002 /* Goldpfeil P-LAN */
-
-/* Elecom products */
-#define USB_PRODUCT_ELECOM_MOUSE29UO 0x0002 /* mouse 29UO */
-#define USB_PRODUCT_ELECOM_LDUSBTX0 0x200c /* LD-USB/TX */
-#define USB_PRODUCT_ELECOM_LDUSBTX1 0x4002 /* LD-USB/TX */
-#define USB_PRODUCT_ELECOM_LDUSBLTX 0x4005 /* LD-USBL/TX */
-#define USB_PRODUCT_ELECOM_LDUSBTX2 0x400b /* LD-USB/TX */
-#define USB_PRODUCT_ELECOM_LDUSB20 0x4010 /* LD-USB20 */
-#define USB_PRODUCT_ELECOM_UCSGT 0x5003 /* UC-SGT */
-#define USB_PRODUCT_ELECOM_UCSGT0 0x5004 /* UC-SGT */
-#define USB_PRODUCT_ELECOM_LDUSBTX3 0xabc1 /* LD-USB/TX */
-
-/* Elsa products */
-#define USB_PRODUCT_ELSA_MODEM1 0x2265 /* ELSA Modem Board */
-#define USB_PRODUCT_ELSA_USB2ETHERNET 0x3000 /* Microlink USB2Ethernet */
-
-/* ELV products */
-#define USB_PRODUCT_ELV_USBI2C 0xe00f /* USB-I2C interface */
-
-/* EMS products */
-#define USB_PRODUCT_EMS_DUAL_SHOOTER 0x0003 /* PSX gun controller converter */
-
-/* Encore products */
-#define USB_PRODUCT_ENCORE_RT3070_1 0x1480 /* RT3070 */
-#define USB_PRODUCT_ENCORE_RT3070_2 0x14a1 /* RT3070 */
-#define USB_PRODUCT_ENCORE_RT3070_3 0x14a9 /* RT3070 */
-
-/* Entrega products */
-#define USB_PRODUCT_ENTREGA_1S 0x0001 /* 1S serial */
-#define USB_PRODUCT_ENTREGA_2S 0x0002 /* 2S serial */
-#define USB_PRODUCT_ENTREGA_1S25 0x0003 /* 1S25 serial */
-#define USB_PRODUCT_ENTREGA_4S 0x0004 /* 4S serial */
-#define USB_PRODUCT_ENTREGA_E45 0x0005 /* E45 Ethernet */
-#define USB_PRODUCT_ENTREGA_CENTRONICS 0x0006 /* Parallel Port */
-#define USB_PRODUCT_ENTREGA_XX1 0x0008 /* Ethernet */
-#define USB_PRODUCT_ENTREGA_1S9 0x0093 /* 1S9 serial */
-#define USB_PRODUCT_ENTREGA_EZUSB 0x8000 /* EZ-USB */
-/*product ENTREGA SERIAL 0x8001 DB25 Serial*/
-#define USB_PRODUCT_ENTREGA_2U4S 0x8004 /* 2U4S serial/usb hub */
-#define USB_PRODUCT_ENTREGA_XX2 0x8005 /* Ethernet */
-/*product ENTREGA SERIAL_DB9 0x8093 DB9 Serial*/
-
-/* Epson products */
-#define USB_PRODUCT_EPSON_PRINTER1 0x0001 /* USB Printer */
-#define USB_PRODUCT_EPSON_PRINTER2 0x0002 /* ISD USB Smart Cable for Mac */
-#define USB_PRODUCT_EPSON_PRINTER3 0x0003 /* ISD USB Smart Cable */
-#define USB_PRODUCT_EPSON_PRINTER5 0x0005 /* USB Printer */
-#define USB_PRODUCT_EPSON_636 0x0101 /* Perfection 636U / 636Photo scanner */
-#define USB_PRODUCT_EPSON_610 0x0103 /* Perfection 610 scanner */
-#define USB_PRODUCT_EPSON_1200 0x0104 /* Perfection 1200U / 1200Photo scanner */
-#define USB_PRODUCT_EPSON_1600 0x0107 /* Expression 1600 scanner */
-#define USB_PRODUCT_EPSON_1640 0x010a /* Perfection 1640SU scanner */
-#define USB_PRODUCT_EPSON_1240 0x010b /* Perfection 1240U / 1240Photo scanner */
-#define USB_PRODUCT_EPSON_640U 0x010c /* Perfection 640U scanner */
-#define USB_PRODUCT_EPSON_1250 0x010f /* Perfection 1250U / 1250Photo scanner */
-#define USB_PRODUCT_EPSON_1650 0x0110 /* Perfection 1650 scanner */
-#define USB_PRODUCT_EPSON_GT9700F 0x0112 /* GT-9700F scanner */
-#define USB_PRODUCT_EPSON_GT9300UF 0x011b /* GT-9300UF scanner */
-#define USB_PRODUCT_EPSON_3200 0x011c /* Perfection 3200 scanner */
-#define USB_PRODUCT_EPSON_1260 0x011d /* Perfection 1260 scanner */
-#define USB_PRODUCT_EPSON_1660 0x011e /* Perfection 1660 scanner */
-#define USB_PRODUCT_EPSON_1670 0x011f /* Perfection 1670 scanner */
-#define USB_PRODUCT_EPSON_1270 0x0120 /* Perfection 1270 scanner */
-#define USB_PRODUCT_EPSON_2480 0x0121 /* Perfection 2480 scanner */
-#define USB_PRODUCT_EPSON_3590 0x0122 /* Perfection 3590 scanner */
-#define USB_PRODUCT_EPSON_4990 0x012a /* Perfection 4990 Photo scanner */
-#define USB_PRODUCT_EPSON_CRESSI_EDY 0x0521 /* Cressi Edy diving computer */
-#define USB_PRODUCT_EPSON_STYLUS_875DC 0x0601 /* Stylus Photo 875DC Card Reader */
-#define USB_PRODUCT_EPSON_STYLUS_895 0x0602 /* Stylus Photo 895 Card Reader */
-#define USB_PRODUCT_EPSON_CX5400 0x0808 /* CX5400 scanner */
-#define USB_PRODUCT_EPSON_3500 0x080e /* CX-3500/3600/3650 MFP */
-#define USB_PRODUCT_EPSON_RX425 0x080f /* Stylus Photo RX425 scanner */
-#define USB_PRODUCT_EPSON_DX3800 0x0818 /* CX3700/CX3800/DX38x0 MFP scanner */
-#define USB_PRODUCT_EPSON_4800 0x0819 /* CX4700/CX4800/DX48x0 MFP scanner */
-#define USB_PRODUCT_EPSON_4200 0x0820 /* CX4100/CX4200/DX4200 MFP scanner */
-#define USB_PRODUCT_EPSON_5000 0x082b /* CX4900/CX5000/DX50x0 MFP scanner */
-#define USB_PRODUCT_EPSON_6000 0x082e /* CX5900/CX6000/DX60x0 MFP scanner */
-#define USB_PRODUCT_EPSON_DX4000 0x082f /* DX4000 MFP scanner */
-#define USB_PRODUCT_EPSON_DX7400 0x0838 /* CX7300/CX7400/DX7400 MFP scanner */
-#define USB_PRODUCT_EPSON_DX8400 0x0839 /* CX8300/CX8400/DX8400 MFP scanner */
-#define USB_PRODUCT_EPSON_SX100 0x0841 /* SX100/NX100 MFP scanner */
-#define USB_PRODUCT_EPSON_NX300 0x0848 /* NX300 MFP scanner */
-#define USB_PRODUCT_EPSON_SX200 0x0849 /* SX200/SX205 MFP scanner */
-#define USB_PRODUCT_EPSON_SX400 0x084a /* SX400/NX400/TX400 MFP scanner */
-
-/* e-TEK Labs products */
-#define USB_PRODUCT_ETEK_1COM 0x8007 /* Serial */
-
-/* Extended Systems products */
-#define USB_PRODUCT_EXTENDED_XTNDACCESS 0x0100 /* XTNDAccess IrDA */
-
-/* FEIYA products */
-#define USB_PRODUCT_FEIYA_5IN1 0x1132 /* 5-in-1 Card Reader */
-
-/* Fiberline */
-#define USB_PRODUCT_FIBERLINE_WL430U 0x6003 /* WL-430U */
-
-/* Fossil, Inc products */
-#define USB_PRODUCT_FOSSIL_WRISTPDA 0x0002 /* Wrist PDA */
-
-/* Foxconn products */
-#define USB_PRODUCT_FOXCONN_PIRELLI_DP_L10 0xe000 /* Pirelli DP-L10 */
-
-/* Freecom products */
-#define USB_PRODUCT_FREECOM_DVD 0xfc01 /* DVD drive */
-#define USB_PRODUCT_FREECOM_HDD 0xfc05 /* Classic SL Hard Drive */
-
-/* Fujitsu Siemens Computers products */
-#define USB_PRODUCT_FSC_E5400 0x1009 /* PrismGT USB 2.0 WLAN */
-
-/* Future Technology Devices products */
-#define USB_PRODUCT_FTDI_SERIAL_8U100AX 0x8372 /* 8U100AX Serial */
-#define USB_PRODUCT_FTDI_SERIAL_8U232AM 0x6001 /* 8U232AM Serial */
-#define USB_PRODUCT_FTDI_SERIAL_8U232AM4 0x6004 /* 8U232AM Serial */
-#define USB_PRODUCT_FTDI_SERIAL_2232C 0x6010 /* FT2232C Dual port Serial */
-#define USB_PRODUCT_FTDI_SERIAL_2232D 0x9e90 /* FT2232D Dual port Serial */
-#define USB_PRODUCT_FTDI_SERIAL_4232H 0x6011 /* FT4232H Quad port Serial */
-/* Gude Analog- und Digitalsysteme products also uses FTDI's id: */
-#define USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M 0xcc48 /* OpenPort 1.3 Mitsubishi */
-#define USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13S 0xcc49 /* OpenPort 1.3 Subaru */
-#define USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13U 0xcc4a /* OpenPort 1.3 Universal */
-#define USB_PRODUCT_FTDI_GAMMASCOUT 0xd678 /* Gamma-Scout */
-#define USB_PRODUCT_FTDI_KBS 0xe6c8 /* Pyramid KBS USB LCD */
-#define USB_PRODUCT_FTDI_EISCOU 0xe888 /* Expert ISDN Control USB */
-#define USB_PRODUCT_FTDI_UOPTBR 0xe889 /* USB-RS232 OptoBridge */
-#define USB_PRODUCT_FTDI_EMCU2D 0xe88a /* Expert mouseCLOCK USB II */
-#define USB_PRODUCT_FTDI_PCMSFU 0xe88b /* Precision Clock MSF USB */
-#define USB_PRODUCT_FTDI_EMCU2H 0xe88c /* Expert mouseCLOCK USB II HBG */
-#define USB_PRODUCT_FTDI_MAXSTREAM 0xee18 /* Maxstream PKG-U */
-#define USB_PRODUCT_FTDI_USB_UIRT 0xf850 /* USB-UIRT */
-#define USB_PRODUCT_FTDI_USBSERIAL 0xfa00 /* Matrix Orbital USB Serial */
-#define USB_PRODUCT_FTDI_MX2_3 0xfa01 /* Matrix Orbital MX2 or MX3 */
-#define USB_PRODUCT_FTDI_MX4_5 0xfa02 /* Matrix Orbital MX4 or MX5 */
-#define USB_PRODUCT_FTDI_LK202 0xfa03 /* Matrix Orbital VK/LK202 Family */
-#define USB_PRODUCT_FTDI_LK204 0xfa04 /* Matrix Orbital VK/LK204 Family */
-#define USB_PRODUCT_FTDI_CFA_632 0xfc08 /* Crystalfontz CFA-632 USB LCD */
-#define USB_PRODUCT_FTDI_CFA_634 0xfc09 /* Crystalfontz CFA-634 USB LCD */
-#define USB_PRODUCT_FTDI_CFA_633 0xfc0b /* Crystalfontz CFA-633 USB LCD */
-#define USB_PRODUCT_FTDI_CFA_631 0xfc0c /* Crystalfontz CFA-631 USB LCD */
-#define USB_PRODUCT_FTDI_CFA_635 0xfc0d /* Crystalfontz CFA-635 USB LCD */
-#define USB_PRODUCT_FTDI_SEMC_DSS20 0xfc82 /* SEMC DSS-20 SyncStation */
-/* Commerzielle und Technische Informationssysteme GmbH products */
-#define USB_PRODUCT_FTDI_CTI_USB_NANO_485 0xf60b /* CTI USB-Nano 485 */
-#define USB_PRODUCT_FTDI_CTI_USB_MINI_485 0xf608 /* CTI USB-Mini 485 */
-
-/* Fuji photo products */
-#define USB_PRODUCT_FUJIPHOTO_MASS0100 0x0100 /* Mass Storage */
-
-/* Fujitsu protducts */
-#define USB_PRODUCT_FUJITSU_AH_F401U 0x105b /* AH-F401U Air H device */
-
-/* Fujitsu-Siemens protducts */
-#define USB_PRODUCT_FUJITSUSIEMENS_SCR 0x0009 /* Fujitsu-Siemens SCR USB Reader */
-
-/* Garmin products */
-#define USB_PRODUCT_GARMIN_IQUE_3600 0x0004 /* iQue 3600 */
-
-/* Gemalto products */
-#define USB_PRODUCT_GEMALTO_PROXPU 0x5501 /* Prox-PU/CU */
-
-/* General Instruments (Motorola) products */
-#define USB_PRODUCT_GENERALINSTMNTS_SB5100 0x5100 /* SURFboard SB5100 Cable modem */
-
-/* Genesys Logic products */
-#define USB_PRODUCT_GENESYS_GL620USB 0x0501 /* GL620USB Host-Host interface */
-#define USB_PRODUCT_GENESYS_GL650 0x0604 /* GL650 HUB */
-#define USB_PRODUCT_GENESYS_GL606 0x0606 /* USB 2.0 HUB */
-#define USB_PRODUCT_GENESYS_GL641USB 0x0700 /* GL641USB CompactFlash Card Reader */
-#define USB_PRODUCT_GENESYS_GL641USB2IDE_2 0x0701 /* GL641USB USB-IDE Bridge No 2 */
-#define USB_PRODUCT_GENESYS_GL641USB2IDE 0x0702 /* GL641USB USB-IDE Bridge */
-#define USB_PRODUCT_GENESYS_GL641USB_2 0x0760 /* GL641USB 6-in-1 Card Reader */
-
-/* GIGABYTE products */
-#define USB_PRODUCT_GIGABYTE_GN54G 0x8001 /* GN-54G */
-#define USB_PRODUCT_GIGABYTE_GNBR402W 0x8002 /* GN-BR402W */
-#define USB_PRODUCT_GIGABYTE_GNWLBM101 0x8003 /* GN-WLBM101 */
-#define USB_PRODUCT_GIGABYTE_GNWBKG 0x8007 /* GN-WBKG */
-#define USB_PRODUCT_GIGABYTE_GNWB01GS 0x8008 /* GN-WB01GS */
-#define USB_PRODUCT_GIGABYTE_GNWI05GS 0x800a /* GN-WI05GS */
-
-/* Gigaset products */
-#define USB_PRODUCT_GIGASET_WLAN 0x0701 /* WLAN */
-#define USB_PRODUCT_GIGASET_SMCWUSBTG 0x0710 /* SMCWUSBT-G */
-#define USB_PRODUCT_GIGASET_SMCWUSBTG_NF 0x0711 /* SMCWUSBT-G (no firmware) */
-#define USB_PRODUCT_GIGASET_AR5523 0x0712 /* AR5523 */
-#define USB_PRODUCT_GIGASET_AR5523_NF 0x0713 /* AR5523 (no firmware) */
-#define USB_PRODUCT_GIGASET_RT2573 0x0722 /* RT2573 */
-#define USB_PRODUCT_GIGASET_RT3070_1 0x0740 /* RT3070 */
-#define USB_PRODUCT_GIGASET_RT3070_2 0x0744 /* RT3070 */
-#define USB_PRODUCT_GIGABYTE_RT2870_1 0x800b /* RT2870 */
-#define USB_PRODUCT_GIGABYTE_GNWB31N 0x800c /* GN-WB31N */
-#define USB_PRODUCT_GIGABYTE_GNWB32L 0x800d /* GN-WB32L */
-
-/* Global Sun Technology product */
-#define USB_PRODUCT_GLOBALSUN_AR5523_1 0x7801 /* AR5523 */
-#define USB_PRODUCT_GLOBALSUN_AR5523_1_NF 0x7802 /* AR5523 (no firmware) */
-#define USB_PRODUCT_GLOBALSUN_AR5523_2 0x7811 /* AR5523 */
-#define USB_PRODUCT_GLOBALSUN_AR5523_2_NF 0x7812 /* AR5523 (no firmware) */
-
-/* Globespan products */
-#define USB_PRODUCT_GLOBESPAN_PRISM_GT_1 0x2000 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_GLOBESPAN_PRISM_GT_2 0x2002 /* PrismGT USB 2.0 WLAN */
-
-/* G.Mate, Inc products */
-#define USB_PRODUCT_GMATE_YP3X00 0x1001 /* YP3X00 PDA */
-
-/* GoHubs products */
-#define USB_PRODUCT_GOHUBS_GOCOM232 0x1001 /* GoCOM232 Serial */
-
-/* Good Way Technology products */
-#define USB_PRODUCT_GOODWAY_GWUSB2E 0x6200 /* GWUSB2E */
-#define USB_PRODUCT_GOODWAY_RT2573 0xc019 /* RT2573 */
-
-/* Google products */
-#define USB_PRODUCT_GOOGLE_NEXUSONE 0x4e11 /* Nexus One */
-
-/* Gravis products */
-#define USB_PRODUCT_GRAVIS_GAMEPADPRO 0x4001 /* GamePad Pro */
-
-/* GREENHOUSE products */
-#define USB_PRODUCT_GREENHOUSE_KANA21 0x0001 /* CF-writer with MP3 */
-
-/* Griffin Technology */
-#define USB_PRODUCT_GRIFFIN_IMATE 0x0405 /* iMate, ADB Adapter */
-
-/* Guillemot Corporation */
-#define USB_PRODUCT_GUILLEMOT_DALEADER 0xa300 /* DA Leader */
-#define USB_PRODUCT_GUILLEMOT_HWGUSB254 0xe000 /* HWGUSB2-54 WLAN */
-#define USB_PRODUCT_GUILLEMOT_HWGUSB254LB 0xe010 /* HWGUSB2-54-LB */
-#define USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP 0xe020 /* HWGUSB2-54V2-AP */
-#define USB_PRODUCT_GUILLEMOT_HWNU300 0xe030 /* HWNU-300 */
-
-/* Hagiwara products */
-#define USB_PRODUCT_HAGIWARA_FGSM 0x0002 /* FlashGate SmartMedia Card Reader */
-#define USB_PRODUCT_HAGIWARA_FGCF 0x0003 /* FlashGate CompactFlash Card Reader */
-#define USB_PRODUCT_HAGIWARA_FG 0x0005 /* FlashGate */
-
-/* HAL Corporation products */
-#define USB_PRODUCT_HAL_IMR001 0x0011 /* Crossam2+USB IR commander */
-
-/* Handspring, Inc. */
-#define USB_PRODUCT_HANDSPRING_VISOR 0x0100 /* Handspring Visor */
-#define USB_PRODUCT_HANDSPRING_TREO 0x0200 /* Handspring Treo */
-#define USB_PRODUCT_HANDSPRING_TREO600 0x0300 /* Handspring Treo 600 */
-
-/* Hauppauge Computer Works */
-#define USB_PRODUCT_HAUPPAUGE_WINTV_USB_FM 0x4d12 /* WinTV USB FM */
-#define USB_PRODUCT_HAUPPAUGE2_NOVAT500 0x9580 /* NovaT 500Stick */
-
-/* Hawking Technologies products */
-#define USB_PRODUCT_HAWKING_RT2870_1 0x0001 /* RT2870 */
-#define USB_PRODUCT_HAWKING_RT2870_2 0x0003 /* RT2870 */
-#define USB_PRODUCT_HAWKING_HWUN2 0x0009 /* HWUN2 */
-#define USB_PRODUCT_HAWKING_RT3070 0x000b /* RT3070 */
-#define USB_PRODUCT_HAWKING_UF100 0x400c /* 10/100 USB Ethernet */
-
-/* HID Global GmbH products */
-#define USB_PRODUCT_HIDGLOBAL_CM2020 0x0596 /* Omnikey Cardman 2020 */
-#define USB_PRODUCT_HIDGLOBAL_CM6020 0x1784 /* Omnikey Cardman 6020 */
-
-/* Hitachi, Ltd. products */
-#define USB_PRODUCT_HITACHI_DVDCAM_DZ_MV100A 0x0004 /* DVD-CAM DZ-MV100A Camcorder */
-#define USB_PRODUCT_HITACHI_DVDCAM_USB 0x001e /* DVDCAM USB HS Interface */
-
-/* HP products */
-#define USB_PRODUCT_HP_895C 0x0004 /* DeskJet 895C */
-#define USB_PRODUCT_HP_4100C 0x0101 /* Scanjet 4100C */
-#define USB_PRODUCT_HP_S20 0x0102 /* Photosmart S20 */
-#define USB_PRODUCT_HP_880C 0x0104 /* DeskJet 880C */
-#define USB_PRODUCT_HP_4200C 0x0105 /* ScanJet 4200C */
-#define USB_PRODUCT_HP_CDWRITERPLUS 0x0107 /* CD-Writer Plus */
-#define USB_PRODUCT_HP_KBDHUB 0x010c /* Multimedia Keyboard Hub */
-#define USB_PRODUCT_HP_G55XI 0x0111 /* OfficeJet G55xi */
-#define USB_PRODUCT_HP_HN210W 0x011c /* HN210W 802.11b WLAN */
-#define USB_PRODUCT_HP_49GPLUS 0x0121 /* 49g+ graphing calculator */
-#define USB_PRODUCT_HP_6200C 0x0201 /* ScanJet 6200C */
-#define USB_PRODUCT_HP_S20b 0x0202 /* PhotoSmart S20 */
-#define USB_PRODUCT_HP_815C 0x0204 /* DeskJet 815C */
-#define USB_PRODUCT_HP_3300C 0x0205 /* ScanJet 3300C */
-#define USB_PRODUCT_HP_CDW8200 0x0207 /* CD-Writer Plus 8200e */
-#define USB_PRODUCT_HP_MMKEYB 0x020c /* Multimedia keyboard */
-#define USB_PRODUCT_HP_1220C 0x0212 /* DeskJet 1220C */
-#define USB_PRODUCT_HP_810C 0x0304 /* DeskJet 810C/812C */
-#define USB_PRODUCT_HP_4300C 0x0305 /* Scanjet 4300C */
-#define USB_PRODUCT_HP_CDW4E 0x0307 /* CD-Writer+ CD-4e */
-#define USB_PRODUCT_HP_G85XI 0x0311 /* OfficeJet G85xi */
-#define USB_PRODUCT_HP_1200 0x0317 /* LaserJet 1200 */
-#define USB_PRODUCT_HP_5200C 0x0401 /* Scanjet 5200C */
-#define USB_PRODUCT_HP_830C 0x0404 /* DeskJet 830C */
-#define USB_PRODUCT_HP_3400CSE 0x0405 /* ScanJet 3400cse */
-#define USB_PRODUCT_HP_6300C 0x0601 /* Scanjet 6300C */
-#define USB_PRODUCT_HP_840C 0x0604 /* DeskJet 840c */
-#define USB_PRODUCT_HP_2200C 0x0605 /* ScanJet 2200C */
-#define USB_PRODUCT_HP_5300C 0x0701 /* Scanjet 5300C */
-#define USB_PRODUCT_HP_4400C 0x0705 /* Scanjet 4400C */
-#define USB_PRODUCT_HP_4470C 0x0805 /* Scanjet 4470C */
-#define USB_PRODUCT_HP_82x0C 0x0b01 /* Scanjet 82x0C */
-#define USB_PRODUCT_HP_2300D 0x0b17 /* Laserjet 2300d */
-#define USB_PRODUCT_HP_970CSE 0x1004 /* Deskjet 970Cse */
-#define USB_PRODUCT_HP_5400C 0x1005 /* Scanjet 5400C */
-#define USB_PRODUCT_HP_2215 0x1016 /* iPAQ 22xx/Jornada 548 */
-#define USB_PRODUCT_HP_568J 0x1116 /* Jornada 568 */
-#define USB_PRODUCT_HP_930C 0x1204 /* DeskJet 930c */
-#define USB_PRODUCT_HP_P2000U 0x1801 /* Inkjet P-2000U */
-#define USB_PRODUCT_HP_HS2300 0x1e1d /* HS2300 HSDPA (aka MC8775) */
-#define USB_PRODUCT_HP_640C 0x2004 /* DeskJet 640c */
-#define USB_PRODUCT_HP_4670V 0x3005 /* ScanJet 4670v */
-#define USB_PRODUCT_HP_P1100 0x3102 /* Photosmart P1100 */
-#define USB_PRODUCT_HP_LD220 0x3524 /* LD220 POS Display */
-#define USB_PRODUCT_HP_OJ4215 0x3d11 /* OfficeJet 4215 */
-#define USB_PRODUCT_HP_HN210E 0x811c /* Ethernet HN210E */
-#define USB_PRODUCT_HP2_C500 0x6002 /* PhotoSmart C500 */
-#define USB_PRODUCT_HP_EV2200 0x1b1d /* ev2200 HSDPA (aka MC5720) */
-#define USB_PRODUCT_HP_HS2300 0x1e1d /* hs2300 HSDPA (aka MC8775) */
-
-/* HTC products */
-#define USB_PRODUCT_HTC_WINMOBILE 0x00ce /* HTC USB Sync */
-#define USB_PRODUCT_HTC_PPC6700MODEM 0x00cf /* PPC6700 Modem */
-#define USB_PRODUCT_HTC_SMARTPHONE 0x0a51 /* SmartPhone USB Sync */
-#define USB_PRODUCT_HTC_WIZARD 0x0bce /* HTC Wizard USB Sync */
-#define USB_PRODUCT_HTC_LEGENDSYNC 0x0c97 /* HTC Legend USB Sync */
-#define USB_PRODUCT_HTC_LEGEND 0x0ff9 /* HTC Legend */
-#define USB_PRODUCT_HTC_LEGENDINTERNET 0x0ffe /* HTC Legend Internet Sharing */
-
-/* HUAWEI products */
-#define USB_PRODUCT_HUAWEI_MOBILE 0x1001 /* Huawei Mobile */
-#define USB_PRODUCT_HUAWEI_E220 0x1003 /* HSDPA modem */
-#define USB_PRODUCT_HUAWEI_E220BIS 0x1004 /* HSDPA modem */
-#define USB_PRODUCT_HUAWEI_E1401 0x1401 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1402 0x1402 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1403 0x1403 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1404 0x1404 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1405 0x1405 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1406 0x1406 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1407 0x1407 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1408 0x1408 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1409 0x1409 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E140A 0x140a /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E140B 0x140b /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E180V 0x140c /* E180V */
-#define USB_PRODUCT_HUAWEI_E140D 0x140d /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E140E 0x140e /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E140F 0x140f /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1410 0x1410 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1411 0x1411 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1412 0x1412 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1413 0x1413 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1414 0x1414 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1415 0x1415 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1416 0x1416 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1417 0x1417 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1418 0x1418 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1419 0x1419 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E141A 0x141a /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E141B 0x141b /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E141C 0x141c /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E141D 0x141d /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E141E 0x141e /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E141F 0x141f /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1420 0x1420 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1421 0x1421 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1422 0x1422 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1423 0x1423 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1424 0x1424 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1425 0x1425 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1426 0x1426 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1427 0x1427 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1428 0x1428 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1429 0x1429 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E142A 0x142a /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E142B 0x142b /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E142C 0x142c /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E142D 0x142d /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E142E 0x142e /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E142F 0x142f /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1430 0x1430 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1431 0x1431 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1432 0x1432 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1433 0x1433 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1434 0x1434 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1435 0x1435 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1436 0x1436 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1437 0x1437 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1438 0x1438 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1439 0x1439 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E143A 0x143a /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E143B 0x143b /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E143C 0x143c /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E143D 0x143d /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E143E 0x143e /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E143F 0x143f /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1752 0x1446 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_K3765 0x1465 /* 3G modem */
-#define USB_PRODUCT_HUAWEI_E1820 0x14ac /* E1820 HSPA+ USB Slider */
-#define USB_PRODUCT_HUAWEI_K3765_INIT 0x1520 /* K3765 Initial */
-
-/* HUAWEI 3com products */
-#define USB_PRODUCT_HUAWEI3COM_WUB320G 0x0009 /* Aolynk WUB320g */
-
-/* IBM Corporation */
-#define USB_PRODUCT_IBM_USBCDROMDRIVE 0x4427 /* USB CD-ROM Drive */
-
-/* Imagination Technologies products */
-#define USB_PRODUCT_IMAGINATION_DBX1 0x2107 /* DBX1 DSP core */
-
-/* Inside Out Networks products */
-#define USB_PRODUCT_INSIDEOUT_EDGEPORT4 0x0001 /* EdgePort/4 serial ports */
-
-/* In-System products */
-#define USB_PRODUCT_INSYSTEM_F5U002 0x0002 /* Parallel printer */
-#define USB_PRODUCT_INSYSTEM_ATAPI 0x0031 /* ATAPI Adapter */
-#define USB_PRODUCT_INSYSTEM_ISD110 0x0200 /* IDE Adapter ISD110 */
-#define USB_PRODUCT_INSYSTEM_ISD105 0x0202 /* IDE Adapter ISD105 */
-#define USB_PRODUCT_INSYSTEM_USBCABLE 0x081a /* USB cable */
-#define USB_PRODUCT_INSYSTEM_STORAGE_V2 0x5701 /* USB Storage Adapter V2 */
-
-/* Intel products */
-#define USB_PRODUCT_INTEL_EASYPC_CAMERA 0x0110 /* Easy PC Camera */
-#define USB_PRODUCT_INTEL_TESTBOARD 0x9890 /* 82930 test board */
-#define USB_PRODUCT_INTEL2_IRMH 0x0020 /* Integrated Rate Matching Hub */
-
-/* Intersil products */
-#define USB_PRODUCT_INTERSIL_PRISM_GT 0x1000 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_INTERSIL_PRISM_2X 0x3642 /* Prism2.x or Atmel WLAN */
-
-/* Interpid Control Systems products */
-#define USB_PRODUCT_INTREPIDCS_VALUECAN 0x0601 /* ValueCAN CAN bus interface */
-#define USB_PRODUCT_INTREPIDCS_NEOVI 0x0701 /* NeoVI Blue vehicle bus interface */
-
-/* I/O DATA products */
-#define USB_PRODUCT_IODATA_IU_CD2 0x0204 /* DVD Multi-plus unit iU-CD2 */
-#define USB_PRODUCT_IODATA_DVR_UEH8 0x0206 /* DVD Multi-plus unit DVR-UEH8 */
-#define USB_PRODUCT_IODATA_USBSSMRW 0x0314 /* USB-SSMRW SD-card */
-#define USB_PRODUCT_IODATA_USBSDRW 0x031e /* USB-SDRW SD-card */
-#define USB_PRODUCT_IODATA_USBETT 0x0901 /* USB ETT */
-#define USB_PRODUCT_IODATA_USBETTX 0x0904 /* USB ETTX */
-#define USB_PRODUCT_IODATA_USBETTXS 0x0913 /* USB ETTX */
-#define USB_PRODUCT_IODATA_USBWNB11A 0x0919 /* USB WN-B11 */
-#define USB_PRODUCT_IODATA_USBWNB11 0x0922 /* USB Airport WN-B11 */
-#define USB_PRODUCT_IODATA_ETGUS2 0x0930 /* ETG-US2 */
-#define USB_PRODUCT_IODATA_RT3072_1 0x0944 /* RT3072 */
-#define USB_PRODUCT_IODATA_RT3072_2 0x0945 /* RT3072 */
-#define USB_PRODUCT_IODATA_RT3072_3 0x0947 /* RT3072 */
-#define USB_PRODUCT_IODATA_RT3072_4 0x0948 /* RT3072 */
-#define USB_PRODUCT_IODATA_USBRSAQ 0x0a03 /* Serial USB-RSAQ1 */
-#define USB_PRODUCT_IODATA_USBRSAQ5 0x0a0e /* Serial USB-RSAQ5 */
-#define USB_PRODUCT_IODATA2_USB2SC 0x0a09 /* USB2.0-SCSI Bridge USB2-SC */
-
-/* Iomega products */
-#define USB_PRODUCT_IOMEGA_ZIP100 0x0001 /* Zip 100 */
-#define USB_PRODUCT_IOMEGA_ZIP250 0x0030 /* Zip 250 */
-
-/* Integrated System Solution Corp. products */
-#define USB_PRODUCT_ISSC_ISSCBTA 0x1001 /* Bluetooth USB Adapter */
-
-/* iTegno products */
-#define USB_PRODUCT_ITEGNO_WM1080A 0x1080 /* WM1080A GSM/GPRS modem */
-#define USB_PRODUCT_ITEGNO_WM2080A 0x2080 /* WM2080A CDMA modem */
-
-/* Ituner networks products */
-#define USB_PRODUCT_ITUNERNET_USBLCD2X20 0x0002 /* USB-LCD 2x20 */
-#define USB_PRODUCT_ITUNERNET_USBLCD4X20 0xc001 /* USB-LCD 4x20 */
-
-/* Jablotron products */
-#define USB_PRODUCT_JABLOTRON_PC60B 0x0001 /* PC-60B */
-
-/* Jaton products */
-#define USB_PRODUCT_JATON_EDA 0x5704 /* Ethernet */
-
-/* JMicron products */
-#define USB_PRODUCT_JMICRON_JM20336 0x2336 /* USB to SATA Bridge */
-#define USB_PRODUCT_JMICRON_JM20337 0x2338 /* USB to ATA/ATAPI Bridge */
-
-/* JVC products */
-#define USB_PRODUCT_JVC_GR_DX95 0x000a /* GR-DX95 */
-#define USB_PRODUCT_JVC_MP_PRX1 0x3008 /* MP-PRX1 Ethernet */
-
-/* JRC products */
-#define USB_PRODUCT_JRC_AH_J3001V_J3002V 0x0001 /* AirH PHONE AH-J3001V/J3002V */
-
-/* Kawatsu products */
-#define USB_PRODUCT_KAWATSU_MH4000P 0x0003 /* MiniHub 4000P */
-
-/* Keisokugiken Corp. products */
-#define USB_PRODUCT_KEISOKUGIKEN_USBDAQ 0x0068 /* HKS-0200 USBDAQ */
-
-/* Kensington products */
-#define USB_PRODUCT_KENSINGTON_ORBIT 0x1003 /* Orbit USB/PS2 trackball */
-#define USB_PRODUCT_KENSINGTON_TURBOBALL 0x1005 /* TurboBall */
-
-/* Keyspan products */
-#define USB_PRODUCT_KEYSPAN_USA28_NF 0x0101 /* USA-28 serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA28X_NF 0x0102 /* USA-28X serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA19_NF 0x0103 /* USA-19 serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA18_NF 0x0104 /* USA-18 serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA18X_NF 0x0105 /* USA-18X serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA19W_NF 0x0106 /* USA-19W serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA19 0x0107 /* USA-19 serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA19W 0x0108 /* USA-19W serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA49W_NF 0x0109 /* USA-49W serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA49W 0x010a /* USA-49W serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA19QI_NF 0x010b /* USA-19QI serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA19QI 0x010c /* USA-19QI serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA19Q_NF 0x010d /* USA-19Q serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA19Q 0x010e /* USA-19Q serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA28 0x010f /* USA-28 serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA28XXB 0x0110 /* USA-28X/XB serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA18 0x0111 /* USA-18 serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA18X 0x0112 /* USA-18X serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA28XB_NF 0x0113 /* USA-28XB serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA28XA_NF 0x0114 /* USA-28XB serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA28XA 0x0115 /* USA-28XA serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA18XA_NF 0x0116 /* USA-18XA serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA18XA 0x0117 /* USA-18XA serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA19QW_NF 0x0118 /* USA-19WQ serial Adapter (no firmware) */
-#define USB_PRODUCT_KEYSPAN_USA19QW 0x0119 /* USA-19WQ serial Adapter */
-#define USB_PRODUCT_KEYSPAN_USA19HA 0x0121 /* USA-19HS serial Adapter */
-#define USB_PRODUCT_KEYSPAN_UIA10 0x0201 /* UIA-10 remote control */
-#define USB_PRODUCT_KEYSPAN_UIA11 0x0202 /* UIA-11 remote control */
-
-/* Kingston products */
-#define USB_PRODUCT_KINGSTON_XX1 0x0008 /* Ethernet */
-#define USB_PRODUCT_KINGSTON_KNU101TX 0x000a /* KNU101TX USB Ethernet */
-
-/* Kawasaki products */
-#define USB_PRODUCT_KLSI_DUH3E10BT 0x0008 /* USB Ethernet */
-#define USB_PRODUCT_KLSI_DUH3E10BTN 0x0009 /* USB Ethernet */
-
-/* Kodak products */
-#define USB_PRODUCT_KODAK_DC220 0x0100 /* Digital Science DC220 */
-#define USB_PRODUCT_KODAK_DC260 0x0110 /* Digital Science DC260 */
-#define USB_PRODUCT_KODAK_DC265 0x0111 /* Digital Science DC265 */
-#define USB_PRODUCT_KODAK_DC290 0x0112 /* Digital Science DC290 */
-#define USB_PRODUCT_KODAK_DC240 0x0120 /* Digital Science DC240 */
-#define USB_PRODUCT_KODAK_DC280 0x0130 /* Digital Science DC280 */
-
-/* Konica Corp. Products */
-#define USB_PRODUCT_KONICA_CAMERA 0x0720 /* Digital Color Camera */
-
-/* KYE products */
-#define USB_PRODUCT_KYE_NICHE 0x0001 /* Niche mouse */
-#define USB_PRODUCT_KYE_NETSCROLL 0x0003 /* Genius NetScroll mouse */
-#define USB_PRODUCT_KYE_FLIGHT2000 0x1004 /* Flight 2000 joystick */
-#define USB_PRODUCT_KYE_VIVIDPRO 0x2001 /* ColorPage Vivid-Pro scanner */
-
-/* Kyocera products */
-#define USB_PRODUCT_KYOCERA_FINECAM_S3X 0x0100 /* Finecam S3x */
-#define USB_PRODUCT_KYOCERA_FINECAM_S4 0x0101 /* Finecam S4 */
-#define USB_PRODUCT_KYOCERA_FINECAM_S5 0x0103 /* Finecam S5 */
-#define USB_PRODUCT_KYOCERA_FINECAM_L3 0x0105 /* Finecam L3 */
-#define USB_PRODUCT_KYOCERA_AHK3001V 0x0203 /* AH-K3001V */
-#define USB_PRODUCT_KYOCERA2_CDMA_MSM_K 0x17da /* Qualcomm Kyocera CDMA Technologies MSM */
-#define USB_PRODUCT_KYOCERA2_KPC680 0x180a /* Qualcomm Kyocera CDMA Technologies MSM */
-
-/* LaCie products */
-#define USB_PRODUCT_LACIE_HD 0xa601 /* Hard Disk */
-#define USB_PRODUCT_LACIE_CDRW 0xa602 /* CD R/W */
-
-/* Leadtek products */
-#define USB_PRODUCT_LEADTEK_9531 0x2101 /* 9531 GPS */
-
-/* Lexar products */
-#define USB_PRODUCT_LEXAR_JUMPSHOT 0x0001 /* jumpSHOT CompactFlash Reader */
-#define USB_PRODUCT_LEXAR_CF_READER 0xb002 /* USB CF Reader */
-
-/* Lexmark products */
-#define USB_PRODUCT_LEXMARK_S2450 0x0009 /* Optra S 2450 */
-
-/* Liebert products */
-#define USB_PRODUCT_LIEBERT_POWERSURE_PXT 0xffff /* PowerSure Personal XT */
-
-/* Linksys products */
-#define USB_PRODUCT_LINKSYS_MAUSB2 0x0105 /* Camedia MAUSB-2 */
-#define USB_PRODUCT_LINKSYS_USB10TX1 0x200c /* USB10TX */
-#define USB_PRODUCT_LINKSYS_USB10T 0x2202 /* USB10T Ethernet */
-#define USB_PRODUCT_LINKSYS_USB100TX 0x2203 /* USB100TX Ethernet */
-#define USB_PRODUCT_LINKSYS_USB100H1 0x2204 /* USB100H1 Ethernet/HPNA */
-#define USB_PRODUCT_LINKSYS_USB10TA 0x2206 /* USB10TA Ethernet */
-#define USB_PRODUCT_LINKSYS_USB10TX2 0x400b /* USB10TX */
-#define USB_PRODUCT_LINKSYS2_WUSB11 0x2219 /* WUSB11 Wireless Adapter */
-#define USB_PRODUCT_LINKSYS2_USB200M 0x2226 /* USB 2.0 10/100 Ethernet */
-#define USB_PRODUCT_LINKSYS3_WUSB11v28 0x2233 /* WUSB11 v2.8 Wireless Adapter */
-#define USB_PRODUCT_LINKSYS4_USB1000 0x0039 /* USB1000 */
-#define USB_PRODUCT_LINKSYS4_WUSB100 0x0070 /* WUSB100 */
-#define USB_PRODUCT_LINKSYS4_WUSB600N 0x0071 /* WUSB600N */
-#define USB_PRODUCT_LINKSYS4_WUSB54GCV2 0x0073 /* WUSB54GC v2 */
-#define USB_PRODUCT_LINKSYS4_WUSB54GCV3 0x0077 /* WUSB54GC v3 */
-#define USB_PRODUCT_LINKSYS4_RT3070 0x0078 /* RT3070 */
-#define USB_PRODUCT_LINKSYS4_WUSB600NV2 0x0079 /* WUSB600N v2 */
-
-/* Logitech products */
-#define USB_PRODUCT_LOGITECH_M2452 0x0203 /* M2452 keyboard */
-#define USB_PRODUCT_LOGITECH_M4848 0x0301 /* M4848 mouse */
-#define USB_PRODUCT_LOGITECH_PAGESCAN 0x040f /* PageScan */
-#define USB_PRODUCT_LOGITECH_QUICKCAMWEB 0x0801 /* QuickCam Web */
-#define USB_PRODUCT_LOGITECH_QUICKCAMPRO 0x0810 /* QuickCam Pro */
-#define USB_PRODUCT_LOGITECH_QUICKCAMEXP 0x0840 /* QuickCam Express */
-#define USB_PRODUCT_LOGITECH_QUICKCAM 0x0850 /* QuickCam */
-#define USB_PRODUCT_LOGITECH_QUICKCAMPRO3 0x0990 /* QuickCam Pro 9000 */
-#define USB_PRODUCT_LOGITECH_N43 0xc000 /* N43 */
-#define USB_PRODUCT_LOGITECH_N48 0xc001 /* N48 mouse */
-#define USB_PRODUCT_LOGITECH_MBA47 0xc002 /* M-BA47 mouse */
-#define USB_PRODUCT_LOGITECH_WMMOUSE 0xc004 /* WingMan Gaming Mouse */
-#define USB_PRODUCT_LOGITECH_BD58 0xc00c /* BD58 mouse */
-#define USB_PRODUCT_LOGITECH_UN58A 0xc030 /* iFeel Mouse */
-#define USB_PRODUCT_LOGITECH_UN53B 0xc032 /* iFeel MouseMan */
-#define USB_PRODUCT_LOGITECH_WMPAD 0xc208 /* WingMan GamePad Extreme */
-#define USB_PRODUCT_LOGITECH_WMRPAD 0xc20a /* WingMan RumblePad */
-#define USB_PRODUCT_LOGITECH_WMJOY 0xc281 /* WingMan Force joystick */
-#define USB_PRODUCT_LOGITECH_BB13 0xc401 /* USB-PS/2 Trackball */
-#define USB_PRODUCT_LOGITECH_RK53 0xc501 /* Cordless mouse */
-#define USB_PRODUCT_LOGITECH_RB6 0xc503 /* Cordless keyboard */
-#define USB_PRODUCT_LOGITECH_MX700 0xc506 /* Cordless optical mouse */
-#define USB_PRODUCT_LOGITECH_QUICKCAMPRO2 0xd001 /* QuickCam Pro */
-
-/* Logitec Corp. products */
-#define USB_PRODUCT_LOGITEC_LDR_H443SU2 0x0033 /* DVD Multi-plus unit LDR-H443SU2 */
-#define USB_PRODUCT_LOGITEC_LDR_H443U2 0x00b3 /* DVD Multi-plus unit LDR-H443U2 */
-#define USB_PRODUCT_LOGITEC_LAN_GTJU2A 0x0160 /* LAN-GTJ/U2A Ethernet */
-#define USB_PRODUCT_LOGITEC_RT2870_1 0x0162 /* RT2870 */
-#define USB_PRODUCT_LOGITEC_RT2870_2 0x0163 /* RT2870 */
-#define USB_PRODUCT_LOGITEC_RT2870_3 0x0164 /* RT2870 */
-
-/* Longcheer Holdings, Ltd. products */
-#define USB_PRODUCT_LONGCHEER_WM66 0x6061 /* Longcheer WM66 HSDPA */
-#define USB_PRODUCT_LONGCHEER_W14 0x9603 /* Mobilcom W14 */
-#define USB_PRODUCT_LONGCHEER_DISK 0xf000 /* Driver disk */
-
-
-/* Lucent products */
-#define USB_PRODUCT_LUCENT_EVALKIT 0x1001 /* USS-720 evaluation kit */
-
-/* Luwen products */
-#define USB_PRODUCT_LUWEN_EASYDISK 0x0005 /* EasyDisc */
-
-/* Macally products */
-#define USB_PRODUCT_MACALLY_MOUSE1 0x0101 /* mouse */
-
-/* Marvell Technology Group, Ltd. products */
-#define USB_PRODUCT_MARVELL_SHEEVAPLUG 0x9e8f /* SheevaPlug serial interface */
-
-/* Matrix Orbital products */
-#define USB_PRODUCT_MATRIXORBITAL_MOUA 0x0153 /* Martrix Orbital MOU-Axxxx LCD displays */
-
-/* MCT Corp. */
-#define USB_PRODUCT_MCT_HUB0100 0x0100 /* Hub */
-#define USB_PRODUCT_MCT_DU_H3SP_USB232 0x0200 /* D-Link DU-H3SP USB BAY Hub */
-#define USB_PRODUCT_MCT_USB232 0x0210 /* USB-232 Interface */
-#define USB_PRODUCT_MCT_SITECOM_USB232 0x0230 /* Sitecom USB-232 Products */
-
-/* Meizu Electronics */
-#define USB_PRODUCT_MEIZU_M6_SL 0x0140 /* MiniPlayer M6 (SL) */
-
-/* Melco, Inc products */
-#define USB_PRODUCT_MELCO_LUATX1 0x0001 /* LUA-TX Ethernet */
-#define USB_PRODUCT_MELCO_LUATX5 0x0005 /* LUA-TX Ethernet */
-#define USB_PRODUCT_MELCO_LUA2TX5 0x0009 /* LUA2-TX Ethernet */
-#define USB_PRODUCT_MELCO_LUAKTX 0x0012 /* LUA-KTX Ethernet */
-#define USB_PRODUCT_MELCO_DUBPXXG 0x001c /* DUB-PxxG */
-#define USB_PRODUCT_MELCO_LUAU2KTX 0x003d /* LUA-U2-KTX Ethernet */
-#define USB_PRODUCT_MELCO_KG54YB 0x005e /* WLI-U2-KG54-YB WLAN */
-#define USB_PRODUCT_MELCO_KG54 0x0066 /* WLI-U2-KG54 WLAN */
-#define USB_PRODUCT_MELCO_KG54AI 0x0067 /* WLI-U2-KG54-AI WLAN */
-#define USB_PRODUCT_MELCO_LUA3U2AGT 0x006e /* LUA3-U2-AGT */
-#define USB_PRODUCT_MELCO_NINWIFI 0x008b /* Nintendo Wi-Fi */
-#define USB_PRODUCT_MELCO_PCOPRS1 0x00b3 /* PC-OP-RS1 RemoteStation */
-#define USB_PRODUCT_MELCO_SG54HP 0x00d8 /* WLI-U2-SG54HP */
-#define USB_PRODUCT_MELCO_G54HP 0x00d9 /* WLI-U2-G54HP */
-#define USB_PRODUCT_MELCO_KG54L 0x00da /* WLI-U2-KG54L */
-#define USB_PRODUCT_MELCO_WLIUCG300N 0x00e8 /* WLI-UC-G300N */
-#define USB_PRODUCT_MELCO_SG54HG 0x00f4 /* WLI-U2-SG54HG */
-#define USB_PRODUCT_MELCO_WLRUCG 0x0116 /* WLR-UC-G */
-#define USB_PRODUCT_MELCO_WLRUCGAOSS 0x0119 /* WLR-UC-G-AOSS */
-#define USB_PRODUCT_MELCO_WLIUCAG300N 0x012e /* WLI-UC-AG300N */
-#define USB_PRODUCT_MELCO_RT2870_1 0x0148 /* RT2870 */
-#define USB_PRODUCT_MELCO_RT2870_2 0x0150 /* RT2870 */
-#define USB_PRODUCT_MELCO_WLIUCGN 0x015d /* WLI-UC-GN */
-
-/* Merlin products */
-#define USB_PRODUCT_MERLIN_V620 0x1110 /* Merlin V620 */
-
-/* MetaGeek products */
-#define USB_PRODUCT_METAGEEK_WISPY1B 0x083e /* MetaGeek Wi-Spy */
-#define USB_PRODUCT_METAGEEK_WISPY24X 0x083f /* MetaGeek Wi-Spy 2.4x */
-#define USB_PRODUCT_METAGEEK2_WISPYDBX 0x5000 /* MetaGeek Wi-Spy DBx */
-
-/* Metricom products */
-#define USB_PRODUCT_METRICOM_RICOCHET_GS 0x0001 /* Ricochet GS */
-
-/* MGE UPS Systems */
-#define USB_PRODUCT_MGE_UPS1 0x0001 /* MGE UPS SYSTEMS PROTECTIONCENTER 1 */
-#define USB_PRODUCT_MGE_UPS2 0xffff /* MGE UPS SYSTEMS PROTECTIONCENTER 2 */
-
-/* MEI products */
-#define USB_PRODUCT_MEI_CASHFLOW_SC 0x1100 /* Cashflow-SC Cash Acceptor */
-#define USB_PRODUCT_MEI_S2000 0x1101 /* Seies 2000 Combo Acceptor */
-
-/* Micro Star International products */
-#define USB_PRODUCT_MSI_BT_DONGLE 0x1967 /* Bluetooth USB dongle */
-#define USB_PRODUCT_MSI_RT3070_1 0x3820 /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_2 0x3821 /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_8 0x3822 /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_3 0x3870 /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_9 0x3871 /* RT3070 */
-#define USB_PRODUCT_MSI_UB11B 0x6823 /* UB11B */
-#define USB_PRODUCT_MSI_RT2570 0x6861 /* RT2570 */
-#define USB_PRODUCT_MSI_RT2570_2 0x6865 /* RT2570 */
-#define USB_PRODUCT_MSI_RT2570_3 0x6869 /* RT2570 */
-#define USB_PRODUCT_MSI_RT2573_1 0x6874 /* RT2573 */
-#define USB_PRODUCT_MSI_RT2573_2 0x6877 /* RT2573 */
-#define USB_PRODUCT_MSI_RT3070_4 0x6899 /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_5 0x821a /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_10 0x822a /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_6 0x870a /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_11 0x871a /* RT3070 */
-#define USB_PRODUCT_MSI_RT3070_7 0x899a /* RT3070 */
-#define USB_PRODUCT_MSI_RT2573_3 0xa861 /* RT2573 */
-#define USB_PRODUCT_MSI_RT2573_4 0xa874 /* RT2573 */
-
-/* Microsoft products */
-#define USB_PRODUCT_MICROSOFT_SIDEPREC 0x0008 /* SideWinder Precision Pro */
-#define USB_PRODUCT_MICROSOFT_INTELLIMOUSE 0x0009 /* IntelliMouse */
-#define USB_PRODUCT_MICROSOFT_NATURALKBD 0x000b /* Natural Keyboard Elite */
-#define USB_PRODUCT_MICROSOFT_DDS80 0x0014 /* Digital Sound System 80 */
-#define USB_PRODUCT_MICROSOFT_SIDEWINDER 0x001a /* Sidewinder Precision Racing Wheel */
-#define USB_PRODUCT_MICROSOFT_INETPRO 0x001c /* Internet Keyboard Pro */
-#define USB_PRODUCT_MICROSOFT_TBEXPLORER 0x0024 /* Trackball Explorer */
-#define USB_PRODUCT_MICROSOFT_INTELLIEYE 0x0025 /* IntelliEye mouse */
-#define USB_PRODUCT_MICROSOFT_INETPRO2 0x002b /* Internet Keyboard Pro */
-#define USB_PRODUCT_MICROSOFT_INTELLIMOUSE5 0x0039 /* IntelliMouse 1.1 5-Button Mouse */
-#define USB_PRODUCT_MICROSOFT_WHEELMOUSE 0x0040 /* Wheel Mouse Optical */
-#define USB_PRODUCT_MICROSOFT_MN510 0x006e /* MN510 Wireless */
-#define USB_PRODUCT_MICROSOFT_700WX 0x0079 /* Palm 700WX */
-#define USB_PRODUCT_MICROSOFT_MN110 0x007a /* 10/100 USB NIC */
-#define USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE 0x008c /* Wireless Optical IntelliMouse */
-#define USB_PRODUCT_MICROSOFT_WLNOTEBOOK 0x00b9 /* Wireless Optical Mouse (Model 1023) */
-#define USB_PRODUCT_MICROSOFT_COMFORT3000 0x00d1 /* Comfort Optical Mouse 3000 (Model 1043) */
-#define USB_PRODUCT_MICROSOFT_WLNOTEBOOK3 0x00d2 /* Wireless Optical Mouse 3000 (Model 1049) */
-#define USB_PRODUCT_MICROSOFT_NATURAL4000 0x00db /* Natural Ergonomic Keyboard 4000 */
-#define USB_PRODUCT_MICROSOFT_WLNOTEBOOK2 0x00e1 /* Wireless Optical Mouse 3000 (Model 1056) */
-#define USB_PRODUCT_MICROSOFT_XBOX360 0x0292 /* XBOX 360 WLAN */
-
-/* Microtech products */
-#define USB_PRODUCT_MICROTECH_SCSIDB25 0x0004 /* USB-SCSI-DB25 */
-#define USB_PRODUCT_MICROTECH_SCSIHD50 0x0005 /* USB-SCSI-HD50 */
-#define USB_PRODUCT_MICROTECH_DPCM 0x0006 /* USB CameraMate */
-#define USB_PRODUCT_MICROTECH_FREECOM 0xfc01 /* Freecom USB-IDE */
-
-/* Microtek products */
-#define USB_PRODUCT_MICROTEK_336CX 0x0094 /* Phantom 336CX - C3 scanner */
-#define USB_PRODUCT_MICROTEK_X6U 0x0099 /* ScanMaker X6 - X6U */
-#define USB_PRODUCT_MICROTEK_C6 0x009a /* Phantom C6 scanner */
-#define USB_PRODUCT_MICROTEK_336CX2 0x00a0 /* Phantom 336CX - C3 scanner */
-#define USB_PRODUCT_MICROTEK_V6USL 0x00a3 /* ScanMaker V6USL */
-#define USB_PRODUCT_MICROTEK_V6USL2 0x80a3 /* ScanMaker V6USL */
-#define USB_PRODUCT_MICROTEK_V6UL 0x80ac /* ScanMaker V6UL */
-
-/* Microtune, Inc. products */
-#define USB_PRODUCT_MICROTUNE_BT_DONGLE 0x1000 /* Bluetooth USB dongle */
-
-/* Midiman products */
-#define USB_PRODUCT_MIDIMAN_MIDISPORT2X2 0x1001 /* Midisport 2x2 */
-
-/* MindsAtWork products */
-#define USB_PRODUCT_MINDSATWORK_WALLET 0x0001 /* Digital Wallet */
-
-/* Minolta Co., Ltd. */
-#define USB_PRODUCT_MINOLTA_2300 0x4001 /* Dimage 2300 */
-#define USB_PRODUCT_MINOLTA_S304 0x4007 /* Dimage S304 */
-#define USB_PRODUCT_MINOLTA_X 0x4009 /* Dimage X */
-#define USB_PRODUCT_MINOLTA_5400 0x400e /* Dimage 5400 */
-#define USB_PRODUCT_MINOLTA_F300 0x4011 /* Dimage F300 */
-#define USB_PRODUCT_MINOLTA_E223 0x4017 /* Dimage E223 */
-
-/* Mitsumi products */
-#define USB_PRODUCT_MITSUMI_CDRRW 0x0000 /* CD-R/RW Drive */
-#define USB_PRODUCT_MITSUMI_BT_DONGLE 0x641f /* Bluetooth USB dongle */
-#define USB_PRODUCT_MITSUMI_FDD 0x6901 /* USB FDD */
-
-/* Mobile Action products */
-#define USB_PRODUCT_MOBILEACTION_MA620 0x0620 /* MA-620 Infrared Adapter */
-
-/* Mobility products */
-#define USB_PRODUCT_MOBILITY_EA 0x0204 /* Ethernet */
-#define USB_PRODUCT_MOBILITY_EASIDOCK 0x0304 /* EasiDock Ethernet */
-
-/* MosChip products */
-#define USB_PRODUCT_MOSCHIP_MCS7703 0x7703 /* MCS7703 Serial Port Adapter */
-#define USB_PRODUCT_MOSCHIP_MCS7830 0x7830 /* MCS7830 Ethernet */
-
-/* Motorola products */
-#define USB_PRODUCT_MOTOROLA_MC141555 0x1555 /* MC141555 hub controller */
-#define USB_PRODUCT_MOTOROLA_SB4100 0x4100 /* SB4100 USB Cable Modem */
-#define USB_PRODUCT_MOTOROLA2_T720C 0x2822 /* T720c */
-#define USB_PRODUCT_MOTOROLA2_A41XV32X 0x2a22 /* A41x/V32x Mobile Phones */
-#define USB_PRODUCT_MOTOROLA2_E398 0x4810 /* E398 Mobile Phone */
-#define USB_PRODUCT_MOTOROLA2_USBLAN 0x600c /* USBLAN */
-#define USB_PRODUCT_MOTOROLA2_USBLAN2 0x6027 /* USBLAN */
-#define USB_PRODUCT_MOTOROLA4_RT2770 0x9031 /* RT2770 */
-#define USB_PRODUCT_MOTOROLA4_RT3070 0x9032 /* RT3070 */
-
-/* MultiTech products */
-#define USB_PRODUCT_MULTITECH_ATLAS 0xf101 /* MT5634ZBA-USB modem */
-
-/* Mustek products */
-#define USB_PRODUCT_MUSTEK_1200CU 0x0001 /* 1200 CU scanner */
-#define USB_PRODUCT_MUSTEK_600CU 0x0002 /* 600 CU scanner */
-#define USB_PRODUCT_MUSTEK_1200USB 0x0003 /* 1200 USB scanner */
-#define USB_PRODUCT_MUSTEK_1200UB 0x0006 /* 1200 UB scanner */
-#define USB_PRODUCT_MUSTEK_1200USBPLUS 0x0007 /* 1200 USB Plus scanner */
-#define USB_PRODUCT_MUSTEK_1200CUPLUS 0x0008 /* 1200 CU Plus scanner */
-#define USB_PRODUCT_MUSTEK_BEARPAW1200F 0x0010 /* BearPaw 1200F scanner */
-#define USB_PRODUCT_MUSTEK_BEARPAW2400TA 0x0218 /* BearPaw 2400TA scanner */
-#define USB_PRODUCT_MUSTEK_BEARPAW1200TA 0x021e /* BearPaw 1200TA scanner */
-#define USB_PRODUCT_MUSTEK_600USB 0x0873 /* 600 USB scanner */
-#define USB_PRODUCT_MUSTEK_MDC800 0xa800 /* MDC-800 digital camera */
-
-/* M-Systems products */
-#define USB_PRODUCT_MSYSTEMS_DISKONKEY 0x0010 /* DiskOnKey */
-#define USB_PRODUCT_MSYSTEMS_DISKONKEY2 0x0011 /* DiskOnKey */
-
-/* Myson products */
-#define USB_PRODUCT_MYSON_HEDEN_8813 0x8813 /* USB-IDE */
-#define USB_PRODUCT_MYSON_HEDEN 0x8818 /* USB-IDE */
-#define USB_PRODUCT_MYSON_HUBREADER 0x8819 /* COMBO Card reader with USB HUB */
-#define USB_PRODUCT_MYSON_STARREADER 0x9920 /* USB flash card adapter */
-
-/* National Semiconductor */
-#define USB_PRODUCT_NATIONAL_BEARPAW1200 0x1000 /* BearPaw 1200 */
-#define USB_PRODUCT_NATIONAL_BEARPAW2400 0x1001 /* BearPaw 2400 */
-
-/* NEC products */
-#define USB_PRODUCT_NEC_HUB_0050 0x0050 /* USB 2.0 7-Port Hub */
-#define USB_PRODUCT_NEC_HUB_005A 0x005a /* USB 2.0 4-Port Hub */
-#define USB_PRODUCT_NEC_HUB 0x55aa /* hub */
-#define USB_PRODUCT_NEC_HUB_B 0x55ab /* hub */
-
-/* NEODIO products */
-#define USB_PRODUCT_NEODIO_ND3260 0x3260 /* 8-in-1 Multi-format Flash Controller */
-#define USB_PRODUCT_NEODIO_ND5010 0x5010 /* Multi-format Flash Controller */
-
-/* Neotel products */
-#define USB_PRODUCT_NEOTEL_PRIME 0x4000 /* Prime USB modem */
-
-/* Netac products */
-#define USB_PRODUCT_NETAC_CF_CARD 0x1060 /* USB-CF-Card */
-#define USB_PRODUCT_NETAC_ONLYDISK 0x0003 /* OnlyDisk */
-
-/* NetChip Technology Products */
-#define USB_PRODUCT_NETCHIP_TURBOCONNECT 0x1080 /* Turbo-Connect */
-#define USB_PRODUCT_NETCHIP_CLIK_40 0xa140 /* USB Clik! 40 */
-#define USB_PRODUCT_NETCHIP_ETHERNETGADGET 0xa4a2 /* Linux Ethernet/RNDIS gadget on pxa210/25x/26x */
-
-/* Netgear products */
-#define USB_PRODUCT_NETGEAR_EA101 0x1001 /* Ethernet */
-#define USB_PRODUCT_NETGEAR_EA101X 0x1002 /* Ethernet */
-#define USB_PRODUCT_NETGEAR_FA101 0x1020 /* Ethernet 10/100, USB1.1 */
-#define USB_PRODUCT_NETGEAR_FA120 0x1040 /* USB 2.0 Ethernet */
-#define USB_PRODUCT_NETGEAR_WG111V2_2 0x4240 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_NETGEAR_WG111V3 0x4260 /* WG111v3 */
-#define USB_PRODUCT_NETGEAR_WG111U 0x4300 /* WG111U */
-#define USB_PRODUCT_NETGEAR_WG111U_NF 0x4301 /* WG111U (no firmware) */
-#define USB_PRODUCT_NETGEAR_WG111V2 0x6a00 /* WG111V2 */
-#define USB_PRODUCT_NETGEAR2_MA101 0x4100 /* MA101 */
-#define USB_PRODUCT_NETGEAR2_MA101B 0x4102 /* MA101 Rev B */
-#define USB_PRODUCT_NETGEAR3_WG111T 0x4250 /* WG111T */
-#define USB_PRODUCT_NETGEAR3_WG111T_NF 0x4251 /* WG111T (no firmware) */
-#define USB_PRODUCT_NETGEAR3_WPN111 0x5f00 /* WPN111 */
-#define USB_PRODUCT_NETGEAR3_WPN111_NF 0x5f01 /* WPN111 (no firmware) */
-#define USB_PRODUCT_NETGEAR3_WPN111_2 0x5f02 /* WPN111 */
-
-/* NetIndex products */
-#define USB_PRODUCT_NETINDEX_WS002IN 0x2001 /* Willcom WS002IN */
-
-/* NEWlink */
-#define USB_PRODUCT_NEWLINK_USB2IDEBRIDGE 0x00ff /* USB 2.0 Hard Drive Enclosure */
-
-/* Nikon products */
-#define USB_PRODUCT_NIKON_E990 0x0102 /* Digital Camera E990 */
-#define USB_PRODUCT_NIKON_LS40 0x4000 /* CoolScan LS40 ED */
-#define USB_PRODUCT_NIKON_D300 0x041a /* Digital Camera D300 */
-
-/* NovaTech Products */
-#define USB_PRODUCT_NOVATECH_NV902 0x9020 /* NovaTech NV-902W */
-#define USB_PRODUCT_NOVATECH_RT2573 0x9021 /* RT2573 */
-
-/* Nokia products */
-#define USB_PRODUCT_NOKIA_N958GB 0x0070 /* Nokia N95 8GBc */
-#define USB_PRODUCT_NOKIA2_CA42 0x1234 /* CA-42 cable */
-
-/* Novatel Wireless products */
-#define USB_PRODUCT_NOVATEL_V640 0x1100 /* Merlin V620 */
-#define USB_PRODUCT_NOVATEL_CDMA_MODEM 0x1110 /* Novatel Wireless Merlin CDMA */
-#define USB_PRODUCT_NOVATEL_V620 0x1110 /* Merlin V620 */
-#define USB_PRODUCT_NOVATEL_V740 0x1120 /* Merlin V740 */
-#define USB_PRODUCT_NOVATEL_V720 0x1130 /* Merlin V720 */
-#define USB_PRODUCT_NOVATEL_U740 0x1400 /* Merlin U740 */
-#define USB_PRODUCT_NOVATEL_U740_2 0x1410 /* Merlin U740 */
-#define USB_PRODUCT_NOVATEL_U870 0x1420 /* Merlin U870 */
-#define USB_PRODUCT_NOVATEL_XU870 0x1430 /* Merlin XU870 */
-#define USB_PRODUCT_NOVATEL_X950D 0x1450 /* Merlin X950D */
-#define USB_PRODUCT_NOVATEL_ES620 0x2100 /* Expedite ES620 */
-#define USB_PRODUCT_NOVATEL_E725 0x2120 /* Expedite E725 */
-#define USB_PRODUCT_NOVATEL_ES620_2 0x2130 /* Expedite ES620 */
-#define USB_PRODUCT_NOVATEL_ES620 0x2100 /* ES620 CDMA */
-#define USB_PRODUCT_NOVATEL_U720 0x2110 /* Merlin U720 */
-#define USB_PRODUCT_NOVATEL_EU730 0x2400 /* Expedite EU730 */
-#define USB_PRODUCT_NOVATEL_EU740 0x2410 /* Expedite EU740 */
-#define USB_PRODUCT_NOVATEL_EU870D 0x2420 /* Expedite EU870D */
-#define USB_PRODUCT_NOVATEL_U727 0x4100 /* Merlin U727 CDMA */
-#define USB_PRODUCT_NOVATEL_MC950D 0x4400 /* Novatel MC950D HSUPA */
-#define USB_PRODUCT_NOVATEL_ZEROCD 0x5010 /* Novatel ZeroCD */
-#define USB_PRODUCT_NOVATEL_ZEROCD2 0x5030 /* Novatel ZeroCD */
-#define USB_PRODUCT_NOVATEL_U727_2 0x5100 /* Merlin U727 CDMA */
-#define USB_PRODUCT_NOVATEL_U760 0x6000 /* Novatel U760 */
-#define USB_PRODUCT_NOVATEL_MC760 0x6002 /* Novatel MC760 */
-#define USB_PRODUCT_NOVATEL2_FLEXPACKGPS 0x0100 /* NovAtel FlexPack GPS receiver */
-
-/* Merlin products */
-#define USB_PRODUCT_MERLIN_V620 0x1110 /* Merlin V620 */
-
-/* O2Micro products */
-#define USB_PRODUCT_O2MICRO_OZ776_HUB 0x7761 /* OZ776 hub */
-#define USB_PRODUCT_O2MICRO_OZ776_CCID_SC 0x7772 /* OZ776 CCID SC Reader */
-
-/* Olympus products */
-#define USB_PRODUCT_OLYMPUS_C1 0x0102 /* C-1 Digital Camera */
-#define USB_PRODUCT_OLYMPUS_C700 0x0105 /* C-700 Ultra Zoom */
-
-/* OmniVision Technologies, Inc. products */
-#define USB_PRODUCT_OMNIVISION_OV511 0x0511 /* OV511 Camera */
-#define USB_PRODUCT_OMNIVISION_OV511PLUS 0xa511 /* OV511+ Camera */
-
-/* OnSpec Electronic, Inc. */
-#define USB_PRODUCT_ONSPEC_SDS_HOTFIND_D 0x0400 /* SDS-infrared.com Hotfind-D Infrared Camera */
-#define USB_PRODUCT_ONSPEC_MDCFE_B_CF_READER 0xa000 /* MDCFE-B USB CF Reader */
-#define USB_PRODUCT_ONSPEC_CFMS_RW 0xa001 /* SIIG/Datafab Memory Stick+CF Reader/Writer */
-#define USB_PRODUCT_ONSPEC_READER 0xa003 /* Datafab-based Reader */
-#define USB_PRODUCT_ONSPEC_CFSM_READER 0xa005 /* PNY/Datafab CF+SM Reader */
-#define USB_PRODUCT_ONSPEC_CFSM_READER2 0xa006 /* Simple Tech/Datafab CF+SM Reader */
-#define USB_PRODUCT_ONSPEC_MDSM_B_READER 0xa103 /* MDSM-B reader */
-#define USB_PRODUCT_ONSPEC_CFSM_COMBO 0xa109 /* USB to CF + SM Combo (LC1) */
-#define USB_PRODUCT_ONSPEC_UCF100 0xa400 /* FlashLink UCF-100 CompactFlash Reader */
-#define USB_PRODUCT_ONSPEC2_IMAGEMATE_SDDR55 0xa103 /* ImageMate SDDR55 */
-
-/* Option products */
-#define USB_PRODUCT_OPTION_VODAFONEMC3G 0x5000 /* Vodafone Mobile Connect 3G datacard */
-#define USB_PRODUCT_OPTION_GT3G 0x6000 /* GlobeTrotter 3G datacard */
-#define USB_PRODUCT_OPTION_GT3GQUAD 0x6300 /* GlobeTrotter 3G QUAD datacard */
-#define USB_PRODUCT_OPTION_GT3GPLUS 0x6600 /* GlobeTrotter 3G+ datacard */
-#define USB_PRODUCT_OPTION_GTICON322 0xd033 /* GlobeTrotter Icon322 storage */
-#define USB_PRODUCT_OPTION_GTMAX36 0x6701 /* GlobeTrotter Max 3.6 Modem */
-#define USB_PRODUCT_OPTION_GTHSDPA 0x6971 /* GlobeTrotter HSDPA */
-#define USB_PRODUCT_OPTION_GTMAXHSUPA 0x7001 /* GlobeTrotter HSUPA */
-#define USB_PRODUCT_OPTION_GTMAXHSUPAE 0x6901 /* GlobeTrotter HSUPA PCIe */
-#define USB_PRODUCT_OPTION_GTMAX380HSUPAE 0x7211 /* GlobeTrotter 380HSUPA PCIe */
-#define USB_PRODUCT_OPTION_GT3G_1 0x6050 /* 3G modem */
-#define USB_PRODUCT_OPTION_GT3G_2 0x6100 /* 3G modem */
-#define USB_PRODUCT_OPTION_GT3G_3 0x6150 /* 3G modem */
-#define USB_PRODUCT_OPTION_GT3G_4 0x6200 /* 3G modem */
-#define USB_PRODUCT_OPTION_GT3G_5 0x6250 /* 3G modem */
-#define USB_PRODUCT_OPTION_GT3G_6 0x6350 /* 3G modem */
-#define USB_PRODUCT_OPTION_E6500 0x6500 /* 3G modem */
-#define USB_PRODUCT_OPTION_E6501 0x6501 /* 3G modem */
-#define USB_PRODUCT_OPTION_E6601 0x6601 /* 3G modem */
-#define USB_PRODUCT_OPTION_E6721 0x6721 /* 3G modem */
-#define USB_PRODUCT_OPTION_E6741 0x6741 /* 3G modem */
-#define USB_PRODUCT_OPTION_E6761 0x6761 /* 3G modem */
-#define USB_PRODUCT_OPTION_E6800 0x6800 /* 3G modem */
-#define USB_PRODUCT_OPTION_E7021 0x7021 /* 3G modem */
-#define USB_PRODUCT_OPTION_E7041 0x7041 /* 3G modem */
-#define USB_PRODUCT_OPTION_E7061 0x7061 /* 3G modem */
-#define USB_PRODUCT_OPTION_E7100 0x7100 /* 3G modem */
-#define USB_PRODUCT_OPTION_GTM380 0x7201 /* 3G modem */
-#define USB_PRODUCT_OPTION_GE40X 0x7601 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_GSICON72 0x6911 /* GlobeSurfer iCON */
-#define USB_PRODUCT_OPTION_GSICONHSUPA 0x7251 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_ICON401 0x7401 /* GlobeSurfer iCON 401 */
-#define USB_PRODUCT_OPTION_GTHSUPA 0x7011 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_GMT382 0x7501 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_GE40X_1 0x7301 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_GE40X_2 0x7361 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_GE40X_3 0x7381 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_ICONEDGE 0xc031 /* GlobeSurfer iCON EDGE */
-#define USB_PRODUCT_OPTION_MODHSXPA 0xd013 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_ICON321 0xd031 /* Globetrotter HSUPA */
-#define USB_PRODUCT_OPTION_ICON505 0xd055 /* Globetrotter iCON 505 */
-#define USB_PRODUCT_OPTION_ICON452 0x7901 /* Globetrotter iCON 452 */
-
-/* OvisLink product */
-#define USB_PRODUCT_OVISLINK_RT3072 0x3072 /* RT3072 */
-
-/* OQO */
-#define USB_PRODUCT_OQO_WIFI01 0x0002 /* model 01 WiFi interface */
-#define USB_PRODUCT_OQO_BT01 0x0003 /* model 01 Bluetooth interface */
-#define USB_PRODUCT_OQO_ETHER01PLUS 0x7720 /* model 01+ Ethernet */
-#define USB_PRODUCT_OQO_ETHER01 0x8150 /* model 01 Ethernet interface */
-
-/* Ours Technology Inc. */
-#define USB_PRODUCT_OTI_DKU5 0x6858 /* DKU-5 Serial */
-
-/* Owen.ru products */
-#define USB_PRODUCT_OWEN_AC4 0x0004 /* AC4 USB-RS485 converter */
-
-/* Palm Computing, Inc. product */
-#define USB_PRODUCT_PALM_SERIAL 0x0080 /* USB Serial */
-#define USB_PRODUCT_PALM_M500 0x0001 /* Palm m500 */
-#define USB_PRODUCT_PALM_M505 0x0002 /* Palm m505 */
-#define USB_PRODUCT_PALM_M515 0x0003 /* Palm m515 */
-#define USB_PRODUCT_PALM_I705 0x0020 /* Palm i705 */
-#define USB_PRODUCT_PALM_TUNGSTEN_Z 0x0031 /* Palm Tungsten Z */
-#define USB_PRODUCT_PALM_M125 0x0040 /* Palm m125 */
-#define USB_PRODUCT_PALM_M130 0x0050 /* Palm m130 */
-#define USB_PRODUCT_PALM_TUNGSTEN_T 0x0060 /* Palm Tungsten T */
-#define USB_PRODUCT_PALM_ZIRE31 0x0061 /* Palm Zire 31 */
-#define USB_PRODUCT_PALM_ZIRE 0x0070 /* Palm Zire */
-
-/* Panasonic products */
-#define USB_PRODUCT_PANASONIC_LS120CAM 0x0901 /* LS-120 Camera */
-#define USB_PRODUCT_PANASONIC_KXL840AN 0x0d01 /* CD-R Drive KXL-840AN */
-#define USB_PRODUCT_PANASONIC_KXLRW32AN 0x0d09 /* CD-R Drive KXL-RW32AN */
-#define USB_PRODUCT_PANASONIC_KXLCB20AN 0x0d0a /* CD-R Drive KXL-CB20AN */
-#define USB_PRODUCT_PANASONIC_KXLCB35AN 0x0d0e /* DVD-ROM & CD-R/RW */
-#define USB_PRODUCT_PANASONIC_SDCAAE 0x1b00 /* MultiMediaCard */
-#define USB_PRODUCT_PANASONIC_TYTP50P6S 0x3900 /* TY-TP50P6-S 50in Touch Panel */
-
-/* PARA Industrial products */
-#define USB_PRODUCT_PARA_RT3070 0x8888 /* RT3070 */
-
-/* Pegatron products */
-#define USB_PRODUCT_PEGATRON_RT2870 0x0002 /* RT2870 */
-#define USB_PRODUCT_PEGATRON_RT3070 0x000c /* RT3070 */
-#define USB_PRODUCT_PEGATRON_RT3070_2 0x000e /* RT3070 */
-#define USB_PRODUCT_PEGATRON_RT3070_3 0x0010 /* RT3070 */
-
-/* Peracom products */
-#define USB_PRODUCT_PERACOM_SERIAL1 0x0001 /* Serial */
-#define USB_PRODUCT_PERACOM_ENET 0x0002 /* Ethernet */
-#define USB_PRODUCT_PERACOM_ENET3 0x0003 /* At Home Ethernet */
-#define USB_PRODUCT_PERACOM_ENET2 0x0005 /* Ethernet */
-
-/* Philips products */
-#define USB_PRODUCT_PHILIPS_DSS350 0x0101 /* DSS 350 Digital Speaker System */
-#define USB_PRODUCT_PHILIPS_DSS 0x0104 /* DSS XXX Digital Speaker System */
-#define USB_PRODUCT_PHILIPS_HUB 0x0201 /* hub */
-#define USB_PRODUCT_PHILIPS_PCA646VC 0x0303 /* PCA646VC PC Camera */
-#define USB_PRODUCT_PHILIPS_PCVC680K 0x0308 /* PCVC680K Vesta Pro PC Camera */
-#define USB_PRODUCT_PHILIPS_DSS150 0x0471 /* DSS 150 Digital Speaker System */
-#define USB_PRODUCT_PHILIPS_ACE1001 0x066a /* AKTAKOM ACE-1001 cable */
-#define USB_PRODUCT_PHILIPS_SPE3030CC 0x083a /* USB 2.0 External Disk */
-#define USB_PRODUCT_PHILIPS_SNU5600 0x1236 /* SNU5600 */
-#define USB_PRODUCT_PHILIPS_UM10016 0x1552 /* ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit */
-#define USB_PRODUCT_PHILIPS_DIVAUSB 0x1801 /* DIVA USB mp3 player */
-#define USB_PRODUCT_PHILIPS_RT2870 0x200f /* RT2870 */
-
-/* Philips Semiconductor products */
-#define USB_PRODUCT_PHILIPSSEMI_HUB1122 0x1122 /* HUB */
-
-/* Megatec */
-#define USB_PRODUCT_MEGATEC_UPS 0x5161 /* Phoenixtec protocol based UPS */
-
-/* P.I. Engineering products */
-#define USB_PRODUCT_PIENGINEERING_PS2USB 0x020b /* PS2 to Mac USB Adapter */
-
-/* Planex Communications products */
-#define USB_PRODUCT_PLANEX_GW_US11H 0x14ea /* GW-US11H WLAN */
-#define USB_PRODUCT_PLANEX2_GW_US11S 0x3220 /* GW-US11S WLAN */
-#define USB_PRODUCT_PLANEX2_GW_US54GXS 0x5303 /* GW-US54GXS WLAN */
-#define USB_PRODUCT_PLANEX2_GWUS54HP 0xab01 /* GW-US54HP */
-#define USB_PRODUCT_PLANEX2_GWUS300MINIS 0xab24 /* GW-US300MiniS */
-#define USB_PRODUCT_PLANEX2_RT3070 0xab25 /* RT3070 */
-#define USB_PRODUCT_PLANEX2_GWUS54MINI2 0xab50 /* GW-US54Mini2 */
-#define USB_PRODUCT_PLANEX2_GWUS54SG 0xc002 /* GW-US54SG */
-#define USB_PRODUCT_PLANEX2_GWUS54GZL 0xc007 /* GW-US54GZL */
-#define USB_PRODUCT_PLANEX2_GWUS54GD 0xed01 /* GW-US54GD */
-#define USB_PRODUCT_PLANEX2_GWUSMM 0xed02 /* GW-USMM */
-#define USB_PRODUCT_PLANEX2_RT2870 0xed06 /* RT2870 */
-#define USB_PRODUCT_PLANEX2_GWUSMICRON 0xed14 /* GW-USMicroN */
-#define USB_PRODUCT_PLANEX3_GWUS54GZ 0xab10 /* GW-US54GZ */
-#define USB_PRODUCT_PLANEX3_GU1000T 0xab11 /* GU-1000T */
-#define USB_PRODUCT_PLANEX3_GWUS54MINI 0xab13 /* GW-US54Mini */
-
-/* Plextor Corp. */
-#define USB_PRODUCT_PLEXTOR_40_12_40U 0x0011 /* PlexWriter 40/12/40U */
-
-/* PLX products */
-#define USB_PRODUCT_PLX_TESTBOARD 0x9060 /* test board */
-#define USB_PRODUCT_PLX_CA42 0xac70 /* CA-42 */
-
-/* PNY products */
-#define USB_PRODUCT_PNY_ATTACHE2 0x0010 /* USB 2.0 Flash Drive */
-
-/* PortGear products */
-#define USB_PRODUCT_PORTGEAR_EA8 0x0008 /* Ethernet */
-#define USB_PRODUCT_PORTGEAR_EA9 0x0009 /* Ethernet */
-
-/* Portsmith products */
-#define USB_PRODUCT_PORTSMITH_EEA 0x3003 /* Express Ethernet */
-
-/* Primax products */
-#define USB_PRODUCT_PRIMAX_G2X300 0x0300 /* G2-200 scanner */
-#define USB_PRODUCT_PRIMAX_G2E300 0x0301 /* G2E-300 scanner */
-#define USB_PRODUCT_PRIMAX_G2300 0x0302 /* G2-300 scanner */
-#define USB_PRODUCT_PRIMAX_G2E3002 0x0303 /* G2E-300 scanner */
-#define USB_PRODUCT_PRIMAX_9600 0x0340 /* Colorado USB 9600 scanner */
-#define USB_PRODUCT_PRIMAX_600U 0x0341 /* Colorado 600u scanner */
-#define USB_PRODUCT_PRIMAX_6200 0x0345 /* Visioneer 6200 scanner */
-#define USB_PRODUCT_PRIMAX_19200 0x0360 /* Colorado USB 19200 scanner */
-#define USB_PRODUCT_PRIMAX_1200U 0x0361 /* Colorado 1200u scanner */
-#define USB_PRODUCT_PRIMAX_G600 0x0380 /* G2-600 scanner */
-#define USB_PRODUCT_PRIMAX_636I 0x0381 /* ReadyScan 636i */
-#define USB_PRODUCT_PRIMAX_G2600 0x0382 /* G2-600 scanner */
-#define USB_PRODUCT_PRIMAX_G2E600 0x0383 /* G2E-600 scanner */
-#define USB_PRODUCT_PRIMAX_COMFORT 0x4d01 /* Comfort */
-#define USB_PRODUCT_PRIMAX_MOUSEINABOX 0x4d02 /* Mouse-in-a-Box */
-#define USB_PRODUCT_PRIMAX_PCGAUMS1 0x4d04 /* Sony PCGA-UMS1 */
-#define USB_PRODUCT_PRIMAX_HP_RH304AA 0x4d17 /* HP RH304AA mouse */
-
-/* Prolific products */
-#define USB_PRODUCT_PROLIFIC_PL2301 0x0000 /* PL2301 Host-Host interface */
-#define USB_PRODUCT_PROLIFIC_PL2302 0x0001 /* PL2302 Host-Host interface */
-#define USB_PRODUCT_PROLIFIC_RSAQ2 0x04bb /* PL2303 Serial (IODATA USB-RSAQ2) */
-#define USB_PRODUCT_PROLIFIC_ALLTRONIX_GPRS 0x0609 /* Alltronix ACM003U00 modem */
-#define USB_PRODUCT_PROLIFIC_ALDIGA_AL11U 0x0611 /* AlDiga AL-11U modem */
-#define USB_PRODUCT_PROLIFIC_MICROMAX_610U 0x0612 /* Micromax 610U */
-#define USB_PRODUCT_PROLIFIC_DCU11 0x1234 /* DCU-11 Phone Cable */
-#define USB_PRODUCT_PROLIFIC_PL2303 0x2303 /* PL2303 Serial (ATEN/IOGEAR UC232A) */
-#define USB_PRODUCT_PROLIFIC_PL2305 0x2305 /* Parallel printer */
-#define USB_PRODUCT_PROLIFIC_ATAPI4 0x2307 /* ATAPI-4 Controller */
-#define USB_PRODUCT_PROLIFIC_PL2501 0x2501 /* PL2501 Host-Host interface */
-#define USB_PRODUCT_PROLIFIC_PL2506 0x2506 /* PL2506 USB to IDE Bridge */
-#define USB_PRODUCT_PROLIFIC_HCR331 0x331a /* HCR331 Hybrid Card Reader */
-#define USB_PRODUCT_PROLIFIC_PHAROS 0xaaa0 /* Prolific Pharos */
-#define USB_PRODUCT_PROLIFIC_RSAQ3 0xaaa2 /* PL2303 Serial Adapter (IODATA USB-RSAQ3) */
-#define USB_PRODUCT_PROLIFIC2_PL2303 0x2303 /* PL2303 Serial Adapter */
-
-/* Putercom products */
-#define USB_PRODUCT_PUTERCOM_UPA100 0x047e /* USB-1284 BRIDGE */
-
-/* Qcom products */
-#define USB_PRODUCT_QCOM_RT2573 0x6196 /* RT2573 */
-#define USB_PRODUCT_QCOM_RT2573_2 0x6229 /* RT2573 */
-#define USB_PRODUCT_QCOM_RT2573_3 0x6238 /* RT2573 */
-#define USB_PRODUCT_QCOM_RT2870 0x6259 /* RT2870 */
-
-/* Qisda products */
-#define USB_PRODUCT_QISDA_H21_1 0x4512 /* 3G modem */
-#define USB_PRODUCT_QISDA_H21_2 0x4523 /* 3G modem */
-#define USB_PRODUCT_QISDA_H20_1 0x4515 /* 3G modem */
-#define USB_PRODUCT_QISDA_H20_2 0x4519 /* 3G modem */
-
-/* Qualcomm products */
-#define USB_PRODUCT_QUALCOMM_CDMA_MSM 0x6000 /* CDMA Technologies MSM phone */
-#define USB_PRODUCT_QUALCOMM2_MF330 0x6613 /* MF330 */
-#define USB_PRODUCT_QUALCOMM2_RWT_FCT 0x3100 /* RWT FCT-CDMA 2000 1xRTT modem */
-#define USB_PRODUCT_QUALCOMM2_CDMA_MSM 0x3196 /* CDMA Technologies MSM modem */
-#define USB_PRODUCT_QUALCOMM2_AC8700 0x6000 /* AC8700 */
-#define USB_PRODUCT_QUALCOMMINC_CDMA_MSM 0x0001 /* CDMA Technologies MSM modem */
-#define USB_PRODUCT_QUALCOMMINC_E0002 0x0002 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0003 0x0003 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0004 0x0004 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0005 0x0005 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0006 0x0006 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0007 0x0007 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0008 0x0008 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0009 0x0009 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E000A 0x000a /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E000B 0x000b /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E000C 0x000c /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E000D 0x000d /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E000E 0x000e /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E000F 0x000f /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0010 0x0010 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0011 0x0011 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0012 0x0012 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0013 0x0013 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0014 0x0014 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_MF628 0x0015 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_MF633R 0x0016 /* ZTE WCDMA modem */
-#define USB_PRODUCT_QUALCOMMINC_E0017 0x0017 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0018 0x0018 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0019 0x0019 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0020 0x0020 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0021 0x0021 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0022 0x0022 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0023 0x0023 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0024 0x0024 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0025 0x0025 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0026 0x0026 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0027 0x0027 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0028 0x0028 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0029 0x0029 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0030 0x0030 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_MF626 0x0031 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0032 0x0032 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0033 0x0033 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0037 0x0037 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0039 0x0039 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0042 0x0042 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0043 0x0043 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0048 0x0048 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0049 0x0049 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0051 0x0051 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0052 0x0052 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_ZTE_STOR2 0x0053 /* USB ZTE Storage */
-#define USB_PRODUCT_QUALCOMMINC_E0054 0x0054 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0055 0x0055 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0057 0x0057 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0058 0x0058 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0059 0x0059 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0060 0x0060 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0061 0x0061 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0062 0x0062 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0063 0x0063 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0064 0x0064 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0066 0x0066 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0069 0x0069 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0070 0x0070 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0073 0x0073 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0076 0x0076 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0078 0x0078 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0082 0x0082 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E0086 0x0086 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_ZTE_STOR 0x2000 /* USB ZTE Storage */
-#define USB_PRODUCT_QUALCOMMINC_E2002 0x2002 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_E2003 0x2003 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_AC8710 0xfff1 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_AC2726 0xfff5 /* 3G modem */
-#define USB_PRODUCT_QUALCOMMINC_AC8700 0xfffe /* CDMA 1xEVDO USB modem */
-
-/* Quanta products */
-#define USB_PRODUCT_QUANTA_RW6815_1 0x00ce /* HP iPAQ rw6815 */
-#define USB_PRODUCT_QUANTA_RT3070 0x0304 /* RT3070 */
-#define USB_PRODUCT_QUANTA_Q101_STOR 0x1000 /* USB Q101 Storage */
-#define USB_PRODUCT_QUANTA_Q101 0xea02 /* HSDPA modem */
-#define USB_PRODUCT_QUANTA_Q111 0xea03 /* HSDPA modem */
-#define USB_PRODUCT_QUANTA_GLX 0xea04 /* HSDPA modem */
-#define USB_PRODUCT_QUANTA_GKE 0xea05 /* HSDPA modem */
-#define USB_PRODUCT_QUANTA_GLE 0xea06 /* HSDPA modem */
-#define USB_PRODUCT_QUANTA_RW6815R 0xf003 /* HP iPAQ rw6815 RNDIS */
-
-/* Qtronix products */
-#define USB_PRODUCT_QTRONIX_980N 0x2011 /* Scorpion-980N keyboard */
-
-/* Quickshot products */
-#define USB_PRODUCT_QUICKSHOT_STRIKEPAD 0x6238 /* USB StrikePad */
-
-/* Radio Shack */
-#define USB_PRODUCT_RADIOSHACK_USBCABLE 0x4026 /* USB to Serial Cable */
-
-/* Rainbow Technologies products */
-#define USB_PRODUCT_RAINBOW_IKEY2000 0x1200 /* i-Key 2000 */
-
-/* Ralink Technology products */
-#define USB_PRODUCT_RALINK_RT2570 0x1706 /* RT2500USB Wireless Adapter */
-#define USB_PRODUCT_RALINK_RT2070 0x2070 /* RT2070 */
-#define USB_PRODUCT_RALINK_RT2570_2 0x2570 /* RT2500USB Wireless Adapter */
-#define USB_PRODUCT_RALINK_RT2573 0x2573 /* RT2501USB Wireless Adapter */
-#define USB_PRODUCT_RALINK_RT2671 0x2671 /* RT2601USB Wireless Adapter */
-#define USB_PRODUCT_RALINK_RT2770 0x2770 /* RT2770 */
-#define USB_PRODUCT_RALINK_RT2870 0x2870 /* RT2870 */
-#define USB_PRODUCT_RALINK_RT3070 0x3070 /* RT3070 */
-#define USB_PRODUCT_RALINK_RT3071 0x3071 /* RT3071 */
-#define USB_PRODUCT_RALINK_RT3072 0x3072 /* RT3072 */
-#define USB_PRODUCT_RALINK_RT3370 0x3370 /* RT3370 */
-#define USB_PRODUCT_RALINK_RT3572 0x3572 /* RT3572 */
-#define USB_PRODUCT_RALINK_RT8070 0x8070 /* RT8070 */
-#define USB_PRODUCT_RALINK_RT2570_3 0x9020 /* RT2500USB Wireless Adapter */
-#define USB_PRODUCT_RALINK_RT2573_2 0x9021 /* RT2501USB Wireless Adapter */
-
-/* RATOC Systems products */
-#define USB_PRODUCT_RATOC_REXUSB60 0xb000 /* USB serial adapter REX-USB60 */
-#define USB_PRODUCT_RATOC_REXUSB60F 0xb020 /* USB serial adapter REX-USB60F */
-
-/* ReakTek products */
-/* Green House and CompUSA OEM this part */
-#define USB_PRODUCT_REALTEK_USB20CRW 0x0158 /* USB20CRW Card Reader */
-#define USB_PRODUCT_REALTEK_USBKR100 0x8150 /* USBKR100 USB Ethernet */
-#define USB_PRODUCT_REALTEK_RTL8187 0x8187 /* RTL8187 Wireless Adapter */
-#define USB_PRODUCT_REALTEK_RTL8187B_0 0x8189 /* RTL8187B Wireless Adapter */
-#define USB_PRODUCT_REALTEK_RTL8187B_1 0x8197 /* RTL8187B Wireless Adapter */
-#define USB_PRODUCT_REALTEK_RTL8187B_2 0x8198 /* RTL8187B Wireless Adapter */
-
-/* Ricoh products */
-#define USB_PRODUCT_RICOH_VGPVCC2 0x1830 /* VGP-VCC2 Camera */
-#define USB_PRODUCT_RICOH_VGPVCC3 0x1832 /* VGP-VCC3 Camera */
-#define USB_PRODUCT_RICOH_VGPVCC2_2 0x1833 /* VGP-VCC2 Camera */
-#define USB_PRODUCT_RICOH_VGPVCC2_3 0x1834 /* VGP-VCC2 Camera */
-#define USB_PRODUCT_RICOH_VGPVCC7 0x183a /* VGP-VCC7 Camera */
-#define USB_PRODUCT_RICOH_VGPVCC8 0x183b /* VGP-VCC8 Camera */
-
-/* Reiner-SCT products */
-#define USB_PRODUCT_REINERSCT_CYBERJACK_ECOM 0x0100 /* e-com cyberJack */
-
-/* Roland products */
-#define USB_PRODUCT_ROLAND_UM1 0x0009 /* UM-1 MIDI I/F */
-#define USB_PRODUCT_ROLAND_UM880N 0x0014 /* EDIROL UM-880 MIDI I/F (native) */
-#define USB_PRODUCT_ROLAND_UM880G 0x0015 /* EDIROL UM-880 MIDI I/F (generic) */
-
-/* Rockfire products */
-#define USB_PRODUCT_ROCKFIRE_GAMEPAD 0x2033 /* gamepad 203USB */
-
-/* RATOC Systems products */
-#define USB_PRODUCT_RATOC_REXUSB60 0xb000 /* REX-USB60 */
-#define USB_PRODUCT_RATOC_REXUSB60F 0xb020 /* REX-USB60F */
-
-/* Sagem products */
-#define USB_PRODUCT_SAGEM_USBSERIAL 0x0027 /* USB-Serial Controller */
-#define USB_PRODUCT_SAGEM_XG760A 0x004a /* XG-760A */
-#define USB_PRODUCT_SAGEM_XG76NA 0x0062 /* XG-76NA */
-
-/* Samsung products */
-#define USB_PRODUCT_SAMSUNG_ML6060 0x3008 /* ML-6060 laser printer */
-#define USB_PRODUCT_SAMSUNG_YP_U2 0x5050 /* YP-U2 MP3 Player */
-#define USB_PRODUCT_SAMSUNG_YP_U4 0x5092 /* YP-U4 MP3 Player */
-#define USB_PRODUCT_SAMSUNG_I500 0x6601 /* I500 Palm USB Phone */
-#define USB_PRODUCT_SAMSUNG_I330 0x8001 /* I330 phone cradle */
-#define USB_PRODUCT_SAMSUNG2_RT2870_1 0x2018 /* RT2870 */
-
-/* Samsung Techwin products */
-#define USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410 0x000a /* Digimax 410 */
-
-/* SanDisk products */
-#define USB_PRODUCT_SANDISK_SDDR05A 0x0001 /* ImageMate SDDR-05a */
-#define USB_PRODUCT_SANDISK_SDDR31 0x0002 /* ImageMate SDDR-31 */
-#define USB_PRODUCT_SANDISK_SDDR05 0x0005 /* ImageMate SDDR-05 */
-#define USB_PRODUCT_SANDISK_SDDR12 0x0100 /* ImageMate SDDR-12 */
-#define USB_PRODUCT_SANDISK_SDDR09 0x0200 /* ImageMate SDDR-09 */
-#define USB_PRODUCT_SANDISK_SDDR75 0x0810 /* ImageMate SDDR-75 */
-#define USB_PRODUCT_SANDISK_SDCZ2_256 0x7104 /* Cruzer Mini 256MB */
-#define USB_PRODUCT_SANDISK_SDCZ4_128 0x7112 /* Cruzer Micro 128MB */
-#define USB_PRODUCT_SANDISK_SDCZ4_256 0x7113 /* Cruzer Micro 256MB */
-
-/* Sanwa Electric Instrument Co., Ltd. products */
-#define USB_PRODUCT_SANWA_KB_USB2 0x0701 /* KB-USB2 multimeter cable */
-
-/* Sanyo Electric products */
-#define USB_PRODUCT_SANYO_SCP4900 0x0701 /* Sanyo SCP-4900 USB Phone */
-
-/* ScanLogic products */
-#define USB_PRODUCT_SCANLOGIC_SL11R 0x0002 /* SL11R IDE Adapter */
-#define USB_PRODUCT_SCANLOGIC_336CX 0x0300 /* Phantom 336CX - C3 scanner */
-
-/* Senao products */
-#define USB_PRODUCT_SENAO_RT2870_3 0x0605 /* RT2870 */
-#define USB_PRODUCT_SENAO_RT2870_4 0x0615 /* RT2870 */
-#define USB_PRODUCT_SENAO_NUB8301 0x2000 /* NUB-8301 */
-#define USB_PRODUCT_SENAO_RT2870_1 0x9701 /* RT2870 */
-#define USB_PRODUCT_SENAO_RT2870_2 0x9702 /* RT2870 */
-#define USB_PRODUCT_SENAO_RT3070 0x9703 /* RT3070 */
-#define USB_PRODUCT_SENAO_RT3071 0x9705 /* RT3071 */
-#define USB_PRODUCT_SENAO_RT3072_1 0x9706 /* RT3072 */
-#define USB_PRODUCT_SENAO_RT3072_2 0x9707 /* RT3072 */
-#define USB_PRODUCT_SENAO_RT3072_3 0x9708 /* RT3072 */
-#define USB_PRODUCT_SENAO_RT3072_4 0x9709 /* RT3072 */
-#define USB_PRODUCT_SENAO_RT3072_5 0x9801 /* RT3072 */
-
-/* ShanTou products */
-#define USB_PRODUCT_SHANTOU_ST268 0x0268 /* ST268 */
-#define USB_PRODUCT_SHANTOU_DM9601 0x9601 /* DM 9601 */
-
-/* Shark products */
-#define USB_PRODUCT_SHARK_PA 0x0400 /* Pocket Adapter */
-
-/* Sharp products */
-#define USB_PRODUCT_SHARP_SL5500 0x8004 /* Zaurus SL-5500 PDA */
-#define USB_PRODUCT_SHARP_SLA300 0x8005 /* Zaurus SL-A300 PDA */
-#define USB_PRODUCT_SHARP_SL5600 0x8006 /* Zaurus SL-5600 PDA */
-#define USB_PRODUCT_SHARP_SLC700 0x8007 /* Zaurus SL-C700 PDA */
-#define USB_PRODUCT_SHARP_SLC750 0x9031 /* Zaurus SL-C750 PDA */
-#define USB_PRODUCT_SHARP_WZERO3ES 0x9123 /* W-ZERO3 ES Smartphone */
-#define USB_PRODUCT_SHARP_WZERO3ADES 0x91ac /* Advanced W-ZERO3 ES Smartphone */
-#define USB_PRODUCT_SHARP_WILLCOM03 0x9242 /* WILLCOM03 */
-
-/* Shuttle Technology products */
-#define USB_PRODUCT_SHUTTLE_EUSB 0x0001 /* E-USB Bridge */
-#define USB_PRODUCT_SHUTTLE_EUSCSI 0x0002 /* eUSCSI Bridge */
-#define USB_PRODUCT_SHUTTLE_SDDR09 0x0003 /* ImageMate SDDR09 */
-#define USB_PRODUCT_SHUTTLE_EUSBCFSM 0x0005 /* eUSB SmartMedia / CompactFlash Adapter */
-#define USB_PRODUCT_SHUTTLE_ZIOMMC 0x0006 /* eUSB MultiMediaCard Adapter */
-#define USB_PRODUCT_SHUTTLE_HIFD 0x0007 /* Sony Hifd */
-#define USB_PRODUCT_SHUTTLE_EUSBATAPI 0x0009 /* eUSB ATA/ATAPI Adapter */
-#define USB_PRODUCT_SHUTTLE_CF 0x000a /* eUSB CompactFlash Adapter */
-#define USB_PRODUCT_SHUTTLE_EUSCSI_B 0x000b /* eUSCSI Bridge */
-#define USB_PRODUCT_SHUTTLE_EUSCSI_C 0x000c /* eUSCSI Bridge */
-#define USB_PRODUCT_SHUTTLE_CDRW 0x0101 /* CD-RW Device */
-#define USB_PRODUCT_SHUTTLE_EUSBORCA 0x0325 /* eUSB ORCA Quad Reader */
-
-/* Siemens products */
-#define USB_PRODUCT_SIEMENS_SPEEDSTREAM 0x1001 /* SpeedStream */
-#define USB_PRODUCT_SIEMENS_SPEEDSTREAM22 0x1022 /* SpeedStream 1022 */
-#define USB_PRODUCT_SIEMENS2_WLL013 0x001b /* WLL013 */
-#define USB_PRODUCT_SIEMENS2_ES75 0x0034 /* GSM module MC35 */
-#define USB_PRODUCT_SIEMENS2_WL54G 0x3c06 /* 54g USB Network Adapter */
-#define USB_PRODUCT_SIEMENS3_SX1 0x0001 /* SX1 */
-#define USB_PRODUCT_SIEMENS3_X65 0x0003 /* X65 */
-#define USB_PRODUCT_SIEMENS3_X75 0x0004 /* X75 */
-#define USB_PRODUCT_SIEMENS3_EF81 0x0005 /* EF81 */
-
-/* Sierra Wireless products */
-#define USB_PRODUCT_SIERRA_EM5625 0x0017 /* EM5625 */
-#define USB_PRODUCT_SIERRA_MC5720_2 0x0018 /* MC5720 */
-#define USB_PRODUCT_SIERRA_MC5725 0x0020 /* MC5725 */
-#define USB_PRODUCT_SIERRA_AIRCARD580 0x0112 /* Sierra Wireless AirCard 580 */
-#define USB_PRODUCT_SIERRA_AIRCARD595 0x0019 /* Sierra Wireless AirCard 595 */
-#define USB_PRODUCT_SIERRA_AC595U 0x0120 /* Sierra Wireless AirCard 595U */
-#define USB_PRODUCT_SIERRA_AC597E 0x0021 /* Sierra Wireless AirCard 597E */
-#define USB_PRODUCT_SIERRA_EM5725 0x0022 /* EM5725 */
-#define USB_PRODUCT_SIERRA_C597 0x0023 /* Sierra Wireless Compass 597 */
-#define USB_PRODUCT_SIERRA_MC5727 0x0024 /* MC5727 */
-#define USB_PRODUCT_SIERRA_T598 0x0025 /* T598 */
-#define USB_PRODUCT_SIERRA_T11 0x0026 /* T11 */
-#define USB_PRODUCT_SIERRA_AC402 0x0027 /* AC402 */
-#define USB_PRODUCT_SIERRA_MC5728 0x0028 /* MC5728 */
-#define USB_PRODUCT_SIERRA_E0029 0x0029 /* E0029 */
-#define USB_PRODUCT_SIERRA_AIRCARD580 0x0112 /* Sierra Wireless AirCard 580 */
-#define USB_PRODUCT_SIERRA_AC595U 0x0120 /* Sierra Wireless AirCard 595U */
-#define USB_PRODUCT_SIERRA_MC5720 0x0218 /* MC5720 Wireless Modem */
-#define USB_PRODUCT_SIERRA_MINI5725 0x0220 /* Sierra Wireless miniPCI 5275 */
-#define USB_PRODUCT_SIERRA_MC5727_2 0x0224 /* MC5727 */
-#define USB_PRODUCT_SIERRA_MC8755_2 0x6802 /* MC8755 */
-#define USB_PRODUCT_SIERRA_MC8765 0x6803 /* MC8765 */
-#define USB_PRODUCT_SIERRA_MC8755 0x6804 /* MC8755 */
-#define USB_PRODUCT_SIERRA_MC8765_2 0x6805 /* MC8765 */
-#define USB_PRODUCT_SIERRA_MC8755_4 0x6808 /* MC8755 */
-#define USB_PRODUCT_SIERRA_MC8765_3 0x6809 /* MC8765 */
-#define USB_PRODUCT_SIERRA_AC875U 0x6812 /* AC875U HSDPA USB Modem */
-#define USB_PRODUCT_SIERRA_MC8755_3 0x6813 /* MC8755 HSDPA */
-#define USB_PRODUCT_SIERRA_MC8775_2 0x6815 /* MC8775 */
-#define USB_PRODUCT_SIERRA_MC8775 0x6816 /* MC8775 */
-#define USB_PRODUCT_SIERRA_AC875 0x6820 /* Sierra Wireless AirCard 875 */
-#define USB_PRODUCT_SIERRA_AC875U_2 0x6821 /* AC875U */
-#define USB_PRODUCT_SIERRA_AC875E 0x6822 /* AC875E */
-#define USB_PRODUCT_SIERRA_MC8780 0x6832 /* MC8780 */
-#define USB_PRODUCT_SIERRA_MC8781 0x6833 /* MC8781 */
-#define USB_PRODUCT_SIERRA_MC8780_2 0x6834 /* MC8780 */
-#define USB_PRODUCT_SIERRA_MC8781_2 0x6835 /* MC8781 */
-#define USB_PRODUCT_SIERRA_MC8780_3 0x6838 /* MC8780 */
-#define USB_PRODUCT_SIERRA_MC8781_3 0x6839 /* MC8781 */
-#define USB_PRODUCT_SIERRA_MC8785 0x683A /* MC8785 */
-#define USB_PRODUCT_SIERRA_MC8785_2 0x683B /* MC8785 */
-#define USB_PRODUCT_SIERRA_MC8790 0x683C /* MC8790 */
-#define USB_PRODUCT_SIERRA_MC8791 0x683D /* MC8791 */
-#define USB_PRODUCT_SIERRA_MC8792 0x683E /* MC8792 */
-#define USB_PRODUCT_SIERRA_AC880 0x6850 /* Sierra Wireless AirCard 880 */
-#define USB_PRODUCT_SIERRA_AC881 0x6851 /* Sierra Wireless AirCard 881 */
-#define USB_PRODUCT_SIERRA_AC880E 0x6852 /* Sierra Wireless AirCard 880E */
-#define USB_PRODUCT_SIERRA_AC881E 0x6853 /* Sierra Wireless AirCard 881E */
-#define USB_PRODUCT_SIERRA_AC880U 0x6855 /* Sierra Wireless AirCard 880U */
-#define USB_PRODUCT_SIERRA_AC881U 0x6856 /* Sierra Wireless AirCard 881U */
-#define USB_PRODUCT_SIERRA_AC885E 0x6859 /* AC885E */
-#define USB_PRODUCT_SIERRA_AC885E_2 0x685A /* AC885E */
-#define USB_PRODUCT_SIERRA_AC885U 0x6880 /* Sierra Wireless AirCard 885U */
-#define USB_PRODUCT_SIERRA_C888 0x6890 /* C888 */
-#define USB_PRODUCT_SIERRA_C22 0x6891 /* C22 */
-#define USB_PRODUCT_SIERRA_E6892 0x6892 /* E6892 */
-#define USB_PRODUCT_SIERRA_E6893 0x6893 /* E6893 */
-#define USB_PRODUCT_SIERRA_MC8700 0x68A3 /* MC8700 */
-#define USB_PRODUCT_SIERRA_AIRCARD875 0x6820 /* Aircard 875 HSDPA */
-#define USB_PRODUCT_SIERRA_TRUINSTALL 0x0fff /* Aircard Tru Installer */
-
-/* Sigmatel products */
-#define USB_PRODUCT_SIGMATEL_WBT_3052 0x4200 /* WBT-3052 IrDA/USB Bridge */
-#define USB_PRODUCT_SIGMATEL_I_BEAD100 0x8008 /* i-Bead 100 MP3 Player */
-
-/* SIIG products */
-/* Also: Omnidirectional Control Technology products */
-#define USB_PRODUCT_SIIG_DIGIFILMREADER 0x0004 /* DigiFilm-Combo Reader */
-#define USB_PRODUCT_SIIG_WINTERREADER 0x0330 /* WINTERREADER Reader */
-#define USB_PRODUCT_SIIG2_USBTOETHER 0x0109 /* USB TO Ethernet */
-#define USB_PRODUCT_SIIG2_US2308 0x0421 /* Serial */
-
-/* Silicom products */
-#define USB_PRODUCT_SILICOM_U2E 0x0001 /* U2E */
-#define USB_PRODUCT_SILICOM_GPE 0x0002 /* Psion Gold Port Ethernet */
-
-/* SI Labs */
-#define USB_PRODUCT_SILABS_VSTABI 0x0f91 /* Vstabi */
-#define USB_PRODUCT_SILABS_ARKHAM_DS101_M 0x1101 /* Arkham DS101 Monitor */
-#define USB_PRODUCT_SILABS_ARKHAM_DS101_A 0x1601 /* Arkham DS101 Adapter */
-#define USB_PRODUCT_SILABS_BSM7DUSB 0x800a /* BSM7-D-USB */
-#define USB_PRODUCT_SILABS_POLOLU 0x803b /* Pololu Serial */
-#define USB_PRODUCT_SILABS_CYGNAL_DEBUG 0x8044 /* Cygnal Debug Adapter */
-#define USB_PRODUCT_SILABS_SB_PARAMOUNT_ME 0x8043 /* Software Bisque Paramount ME */
-#define USB_PRODUCT_SILABS_SAEL 0x8053 /* SA-EL USB */
-#define USB_PRODUCT_SILABS_GSM2228 0x8054 /* Enfora GSM2228 USB */
-#define USB_PRODUCT_SILABS_ARGUSISP 0x8066 /* Argussoft ISP */
-#define USB_PRODUCT_SILABS_IMS_USB_RS422 0x806f /* IMS USB-RS422 */
-#define USB_PRODUCT_SILABS_CRUMB128 0x807a /* Crumb128 board */
-#define USB_PRODUCT_SILABS_DEGREE 0x80ca /* Degree Controls Inc */
-#define USB_PRODUCT_SILABS_TRACIENT 0x80dd /* Tracient RFID */
-#define USB_PRODUCT_SILABS_TRAQMATE 0x80ed /* Track Systems Traqmate */
-#define USB_PRODUCT_SILABS_SUUNTO 0x80f6 /* Suunto Sports Instrument */
-#define USB_PRODUCT_SILABS_ARYGON_MIFARE 0x8115 /* Arygon Mifare RFID reader */
-#define USB_PRODUCT_SILABS_BURNSIDE 0x813d /* Burnside Telecon Deskmobile */
-#define USB_PRODUCT_SILABS_TAMSMASTER 0x813f /* Tams Master Easy Control */
-#define USB_PRODUCT_SILABS_WMRBATT 0x814a /* WMR RIGblaster Plug&Play */
-#define USB_PRODUCT_SILABS_WMRRIGBLASTER 0x814a /* WMR RIGblaster Plug&Play */
-#define USB_PRODUCT_SILABS_WMRRIGTALK 0x814b /* WMR RIGtalk RT1 */
-#define USB_PRODUCT_SILABS_HELICOM 0x815e /* Helicomm IP-Link 1220-DVM */
-#define USB_PRODUCT_SILABS_AVIT_USB_TTL 0x818b /* AVIT Research USB-TTL */
-#define USB_PRODUCT_SILABS_MJS_TOSLINK 0x819f /* MJS USB-TOSLINk */
-#define USB_PRODUCT_SILABS_WAVIT 0x81a6 /* ThinkOptics WavIt */
-#define USB_PRODUCT_SILABS_MSD_DASHHAWK 0x81ac /* MSD DashHawk */
-#define USB_PRODUCT_SILABS_INSYS_MODEM 0x81ad /* INSYS Modem */
-#define USB_PRODUCT_SILABS_LIPOWSKY_JTAG 0x81c8 /* Lipowsky Baby-JTAG */
-#define USB_PRODUCT_SILABS_LIPOWSKY_LIN 0x81e2 /* Lipowsky Baby-LIN */
-#define USB_PRODUCT_SILABS_AEROCOMM 0x81e7 /* Aerocomm Radio */
-#define USB_PRODUCT_SILABS_ZEPHYR_BIO 0x81e8 /* Zephyr Bioharness */
-#define USB_PRODUCT_SILABS_EMS_C1007 0x81f2 /* EMS C1007 HF RFID controller */
-#define USB_PRODUCT_SILABS_LIPOWSKY_HARP 0x8218 /* Lipowsky HARP-1 */
-#define USB_PRODUCT_SILABS_C2_EDGE_MODEM 0x822b /* Commander 2 EDGE(GSM) Modem */
-#define USB_PRODUCT_SILABS_CYGNAL_GPS 0x826b /* Cygnal Fasttrax GPS */
-#define USB_PRODUCT_SILABS_TELEGESYS_ETRX2 0x8293 /* Telegesys ETRX2USB */
-#define USB_PRODUCT_SILABS_PROCYON_AVS 0x82f9 /* Procyon AVS */
-#define USB_PRODUCT_SILABS_MC35PU 0x8341 /* MC35pu */
-#define USB_PRODUCT_SILABS_CYGNAL 0x8382 /* Cygnal */
-#define USB_PRODUCT_SILABS_AMBER_AMB2560 0x83a8 /* Amber Wireless AMB2560 */
-#define USB_PRODUCT_SILABS_KYOCERA_GPS 0x8411 /* Kyocera GPS */
-#define USB_PRODUCT_SILABS_BEI_VCP 0x846e /* BEI USB Sensor (VCP) */
-#define USB_PRODUCT_SILABS_CP2102 0xea60 /* SILABS USB UART */
-#define USB_PRODUCT_SILABS_CP210X_2 0xea61 /* CP210x Serial */
-#define USB_PRODUCT_SILABS_INFINITY_MIC 0xea71 /* Infinity GPS-MIC-1 Radio Monophone */
-#define USB_PRODUCT_SILABS_USBSCOPE50 0xf001 /* USBscope50 */
-#define USB_PRODUCT_SILABS_USBWAVE12 0xf002 /* USBwave12 */
-#define USB_PRODUCT_SILABS_USBPULSE100 0xf003 /* USBpulse100 */
-#define USB_PRODUCT_SILABS_USBCOUNT50 0xf004 /* USBcount50 */
-#define USB_PRODUCT_SILABS2_DCU11CLONE 0xaa26 /* DCU-11 clone */
-#define USB_PRODUCT_SILABS3_GPRS_MODEM 0xea61 /* GPRS Modem */
-#define USB_PRODUCT_SILABS4_100EU_MODEM 0xea61 /* GPRS Modem 100EU */
-
-/* Silicon Portals Inc. */
-#define USB_PRODUCT_SILICONPORTALS_YAPPH_NF 0x0200 /* YAP Phone (no firmware) */
-#define USB_PRODUCT_SILICONPORTALS_YAPPHONE 0x0201 /* YAP Phone */
-
-/* Sirius Technologies products */
-#define USB_PRODUCT_SIRIUS_ROADSTER 0x0001 /* NetComm Roadster II 56 USB */
-
-/* Sitecom products */
-#define USB_PRODUCT_SITECOM_LN029 0x182d /* USB 2.0 Ethernet */
-#define USB_PRODUCT_SITECOM_SERIAL 0x2068 /* USB to serial cable (v2) */
-#define USB_PRODUCT_SITECOM2_WL022 0x182d /* WL-022 */
-
-/* Sitecom Europe products */
-#define USB_PRODUCT_SITECOMEU_RT2870_1 0x0017 /* RT2870 */
-#define USB_PRODUCT_SITECOMEU_WL168V1 0x000d /* WL-168 v1 */
-#define USB_PRODUCT_SITECOMEU_WL168V4 0x0028 /* WL-168 v4 */
-#define USB_PRODUCT_SITECOMEU_RT2870_2 0x002b /* RT2870 */
-#define USB_PRODUCT_SITECOMEU_RT2870_3 0x002c /* RT2870 */
-#define USB_PRODUCT_SITECOMEU_RT2870_4 0x002d /* RT2870 */
-#define USB_PRODUCT_SITECOMEU_RT2770 0x0039 /* RT2770 */
-#define USB_PRODUCT_SITECOMEU_RT3070_2 0x003b /* RT3070 */
-#define USB_PRODUCT_SITECOMEU_RT3070_3 0x003c /* RT3070 */
-#define USB_PRODUCT_SITECOMEU_RT3070_4 0x003d /* RT3070 */
-#define USB_PRODUCT_SITECOMEU_RT3070 0x003e /* RT3070 */
-#define USB_PRODUCT_SITECOMEU_WL608 0x003f /* WL-608 */
-#define USB_PRODUCT_SITECOMEU_RT3071 0x0040 /* RT3071 */
-#define USB_PRODUCT_SITECOMEU_RT3072_1 0x0041 /* RT3072 */
-#define USB_PRODUCT_SITECOMEU_RT3072_2 0x0042 /* RT3072 */
-#define USB_PRODUCT_SITECOMEU_RT3072_3 0x0047 /* RT3072 */
-#define USB_PRODUCT_SITECOMEU_RT3072_4 0x0048 /* RT3072 */
-#define USB_PRODUCT_SITECOMEU_RT3072_5 0x004a /* RT3072 */
-#define USB_PRODUCT_SITECOMEU_RT3072_6 0x004d /* RT3072 */
-#define USB_PRODUCT_SITECOMEU_LN028 0x061c /* LN-028 */
-#define USB_PRODUCT_SITECOMEU_WL113 0x9071 /* WL-113 */
-#define USB_PRODUCT_SITECOMEU_ZD1211B 0x9075 /* ZD1211B */
-#define USB_PRODUCT_SITECOMEU_WL172 0x90ac /* WL-172 */
-#define USB_PRODUCT_SITECOMEU_WL113R2 0x9712 /* WL-113 rev 2 */
-
-/* Skanhex Technology products */
-#define USB_PRODUCT_SKANHEX_MD_7425 0x410a /* MD 7425 Camera */
-#define USB_PRODUCT_SKANHEX_SX_520Z 0x5200 /* SX 520z Camera */
-
-/* Smart Technologies products */
-#define USB_PRODUCT_SMART_PL2303 0x2303 /* Serial adapter */
-
-/* SmartBridges products */
-#define USB_PRODUCT_SMARTBRIDGES_SMARTLINK 0x0001 /* SmartLink USB Ethernet */
-#define USB_PRODUCT_SMARTBRIDGES_SMARTNIC 0x0003 /* smartNIC 2 PnP Ethernet */
-
-/* SMC products */
-#define USB_PRODUCT_SMC_2102USB 0x0100 /* 10Mbps Ethernet */
-#define USB_PRODUCT_SMC_2202USB 0x0200 /* 10/100 Ethernet */
-#define USB_PRODUCT_SMC_2206USB 0x0201 /* EZ Connect USB Ethernet */
-#define USB_PRODUCT_SMC_2862WG 0xee13 /* EZ Connect Wireless Adapter */
-#define USB_PRODUCT_SMC2_2020HUB 0x2020 /* USB Hub */
-#define USB_PRODUCT_SMC2_2514HUB 0x2514 /* USB Hub */
-#define USB_PRODUCT_SMC3_2662WUSB 0xa002 /* 2662W-AR Wireless */
-
-/* SOHOware products */
-#define USB_PRODUCT_SOHOWARE_NUB100 0x9100 /* 10/100 USB Ethernet */
-#define USB_PRODUCT_SOHOWARE_NUB110 0x9110 /* 10/100 USB Ethernet */
-
-/* SOLID YEAR products */
-#define USB_PRODUCT_SOLIDYEAR_KEYBOARD 0x2101 /* Solid Year USB keyboard */
-
-/* SONY products */
-#define USB_PRODUCT_SONY_DSC 0x0010 /* DSC cameras */
-#define USB_PRODUCT_SONY_MS_NW_MS7 0x0025 /* Memorystick NW-MS7 */
-#define USB_PRODUCT_SONY_PORTABLE_HDD_V2 0x002b /* Portable USB Harddrive V2 */
-#define USB_PRODUCT_SONY_MSACUS1 0x002d /* Memorystick MSAC-US1 */
-#define USB_PRODUCT_SONY_HANDYCAM 0x002e /* Handycam */
-#define USB_PRODUCT_SONY_MSC 0x0032 /* MSC memory stick slot */
-#define USB_PRODUCT_SONY_CLIE_35 0x0038 /* Sony Clie v3.5 */
-#define USB_PRODUCT_SONY_MS_PEG_N760C 0x0058 /* PEG N760c Memorystick */
-#define USB_PRODUCT_SONY_CLIE_40 0x0066 /* Sony Clie v4.0 */
-#define USB_PRODUCT_SONY_MS_MSC_U03 0x0069 /* Memorystick MSC-U03 */
-#define USB_PRODUCT_SONY_CLIE_40_MS 0x006d /* Sony Clie v4.0 Memory Stick slot */
-#define USB_PRODUCT_SONY_CLIE_S360 0x0095 /* Sony Clie s360 */
-#define USB_PRODUCT_SONY_CLIE_41_MS 0x0099 /* Sony Clie v4.1 Memory Stick slot */
-#define USB_PRODUCT_SONY_CLIE_41 0x009a /* Sony Clie v4.1 */
-#define USB_PRODUCT_SONY_CLIE_NX60 0x00da /* Sony Clie nx60 */
-#define USB_PRODUCT_SONY_CLIE_TH55 0x0144 /* Sony Clie th55 */
-#define USB_PRODUCT_SONY_CLIE_TJ37 0x0169 /* Sony Clie tj37 */
-#define USB_PRODUCT_SONY_RF_RECEIVER 0x01db /* Sony RF mouse/kbd Receiver VGP-WRC1 */
-#define USB_PRODUCT_SONY_QN3 0x0437 /* Sony QN3 CMD-Jxx phone cable */
-
-/* Sony Ericsson products */
-#define USB_PRODUCT_SONYERICSSON_DCU10 0x0528 /* DCU-10 Phone Data Cable */
-#define USB_PRODUCT_SONYERICSSON_DATAPILOT 0x2003 /* Datapilot Phone Cable */
-
-/* SOURCENEXT products */
-#define USB_PRODUCT_SOURCENEXT_KEIKAI8 0x039f /* KeikaiDenwa 8 */
-#define USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG 0x012e /* KeikaiDenwa 8 with charger */
-
-/* SparkLAN products */
-#define USB_PRODUCT_SPARKLAN_RT2573 0x0004 /* RT2573 */
-#define USB_PRODUCT_SPARKLAN_RT2870_1 0x0006 /* RT2870 */
-#define USB_PRODUCT_SPARKLAN_RT3070 0x0010 /* RT3070 */
-
-/* Speed Dragon Multimedia products */
-#define USB_PRODUCT_SPEEDDRAGON_MS3303H 0x110b /* MS3303H Serial */
-
-/* Sphairon Access Systems GmbH products */
-#define USB_PRODUCT_SPHAIRON_UB801R 0x0110 /* UB801R */
-
-/* Stelera Wireless products */
-#define USB_PRODUCT_STELERA_ZEROCD 0x1000 /* Zerocd Installer */
-#define USB_PRODUCT_STELERA_C105 0x1002 /* Stelera/Bandrish C105 USB */
-#define USB_PRODUCT_STELERA_E1003 0x1003 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1004 0x1004 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1005 0x1005 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1006 0x1006 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1007 0x1007 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1008 0x1008 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1009 0x1009 /* 3G modem */
-#define USB_PRODUCT_STELERA_E100A 0x100a /* 3G modem */
-#define USB_PRODUCT_STELERA_E100B 0x100b /* 3G modem */
-#define USB_PRODUCT_STELERA_E100C 0x100c /* 3G modem */
-#define USB_PRODUCT_STELERA_E100D 0x100d /* 3G modem */
-#define USB_PRODUCT_STELERA_E100E 0x100e /* 3G modem */
-#define USB_PRODUCT_STELERA_E100F 0x100f /* 3G modem */
-#define USB_PRODUCT_STELERA_E1010 0x1010 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1011 0x1011 /* 3G modem */
-#define USB_PRODUCT_STELERA_E1012 0x1012 /* 3G modem */
-
-/* MpMan products */
-#define USB_PRODUCT_MPMAN_MPF400_1 0x36d0 /* MPF400 Music Player 1Go */
-#define USB_PRODUCT_MPMAN_MPF400_2 0x25a8 /* MPF400 Music Player 2Go */
-
-/* STMicroelectronics products */
-#define USB_PRODUCT_STMICRO_BIOCPU 0x2016 /* Biometric Coprocessor */
-#define USB_PRODUCT_STMICRO_COMMUNICATOR 0x7554 /* USB Communicator */
-
-/* STSN products */
-#define USB_PRODUCT_STSN_STSN0001 0x0001 /* Internet Access Device */
-
-/* SUN Corporation products */
-#define USB_PRODUCT_SUNTAC_DS96L 0x0003 /* SUNTAC U-Cable type D2 */
-#define USB_PRODUCT_SUNTAC_PS64P1 0x0005 /* SUNTAC U-Cable type P1 */
-#define USB_PRODUCT_SUNTAC_VS10U 0x0009 /* SUNTAC Slipper U */
-#define USB_PRODUCT_SUNTAC_IS96U 0x000a /* SUNTAC Ir-Trinity */
-#define USB_PRODUCT_SUNTAC_AS64LX 0x000b /* SUNTAC U-Cable type A3 */
-#define USB_PRODUCT_SUNTAC_AS144L4 0x0011 /* SUNTAC U-Cable type A4 */
-
-/* Sun Microsystems products */
-#define USB_PRODUCT_SUN_KEYBOARD_TYPE_6 0x0005 /* Type 6 USB keyboard */
-#define USB_PRODUCT_SUN_KEYBOARD_TYPE_7 0x00a2 /* Type 7 USB keyboard */
-/* XXX The above is a North American PC style keyboard possibly */
-#define USB_PRODUCT_SUN_MOUSE 0x0100 /* Type 6 USB mouse */
-#define USB_PRODUCT_SUN_KBD_HUB 0x100e /* Kbd Hub */
-
-/* Super Top products */
-#define USB_PRODUCT_SUPERTOP_IDE 0x6600 /* USB-IDE */
-
-/* Syntech products */
-#define USB_PRODUCT_SYNTECH_CPT8001C 0x0001 /* CPT-8001C Barcode scanner */
-#define USB_PRODUCT_SYNTECH_CYPHERLAB100 0x1000 /* CipherLab USB Barcode Scanner */
-
-/* Teclast products */
-#define USB_PRODUCT_TECLAST_TLC300 0x3203 /* USB Media Player */
-
-/* Supra products */
-#define USB_PRODUCT_DIAMOND2_SUPRAEXPRESS56K 0x07da /* Supra Express 56K modem */
-#define USB_PRODUCT_DIAMOND2_SUPRA2890 0x0b4a /* SupraMax 2890 56K Modem */
-#define USB_PRODUCT_DIAMOND2_RIO600USB 0x5001 /* Rio 600 USB */
-#define USB_PRODUCT_DIAMOND2_RIO800USB 0x5002 /* Rio 800 USB */
-
-/* Surecom Technology products */
-#define USB_PRODUCT_SURECOM_EP9001G2A 0x11f2 /* EP-9001-G rev 2A */
-#define USB_PRODUCT_SURECOM_RT2570 0x11f3 /* RT2570 */
-#define USB_PRODUCT_SURECOM_RT2573 0x31f3 /* RT2573 */
-
-/* Sweex products */
-#define USB_PRODUCT_SWEEX_ZD1211 0x1809 /* ZD1211 */
-#define USB_PRODUCT_SWEEX2_LW153 0x0153 /* LW153 */
-#define USB_PRODUCT_SWEEX2_LW303 0x0302 /* LW303 */
-#define USB_PRODUCT_SWEEX2_LW313 0x0313 /* LW313 */
-
-/* System TALKS, Inc. */
-#define USB_PRODUCT_SYSTEMTALKS_SGCX2UL 0x1920 /* SGC-X2UL */
-
-/* Tapwave products */
-#define USB_PRODUCT_TAPWAVE_ZODIAC 0x0100 /* Zodiac */
-
-/* Taugagreining products */
-#define USB_PRODUCT_TAUGA_CAMERAMATE 0x0005 /* CameraMate (DPCM_USB) */
-
-/* TCTMobile products */
-#define USB_PRODUCT_TCTMOBILE_X060S 0x0000 /* X060S 3G modem */
-#define USB_PRODUCT_TCTMOBILE_X080S 0xf000 /* X080S 3G modem */
-
-/* TDK products */
-#define USB_PRODUCT_TDK_UPA9664 0x0115 /* USB-PDC Adapter UPA9664 */
-#define USB_PRODUCT_TDK_UCA1464 0x0116 /* USB-cdmaOne Adapter UCA1464 */
-#define USB_PRODUCT_TDK_UHA6400 0x0117 /* USB-PHS Adapter UHA6400 */
-#define USB_PRODUCT_TDK_UPA6400 0x0118 /* USB-PHS Adapter UPA6400 */
-#define USB_PRODUCT_TDK_BT_DONGLE 0x0309 /* Bluetooth USB dongle */
-
-/* TEAC products */
-#define USB_PRODUCT_TEAC_FD05PUB 0x0000 /* FD-05PUB floppy */
-
-/* Tekram Technology products */
-#define USB_PRODUCT_TEKRAM_QUICKWLAN 0x1630 /* QuickWLAN */
-#define USB_PRODUCT_TEKRAM_ZD1211_1 0x5630 /* ZD1211 */
-#define USB_PRODUCT_TEKRAM_ZD1211_2 0x6630 /* ZD1211 */
-
-/* Telex Communications products */
-#define USB_PRODUCT_TELEX_MIC1 0x0001 /* Enhanced USB Microphone */
-
-/* Telit products */
-#define USB_PRODUCT_TELIT_UC864E 0x1003 /* UC864E 3G modem */
-#define USB_PRODUCT_TELIT_UC864G 0x1004 /* UC864G 3G modem */
-
-/* Ten X Technology, Inc. */
-#define USB_PRODUCT_TENX_UAUDIO0 0xf211 /* USB audio headset */
-
-/* Texas Intel products */
-#define USB_PRODUCT_TI_UTUSB41 0x1446 /* UT-USB41 hub */
-#define USB_PRODUCT_TI_TUSB2046 0x2046 /* TUSB2046 hub */
-
-/* Thrustmaster products */
-#define USB_PRODUCT_THRUST_FUSION_PAD 0xa0a3 /* Fusion Digital Gamepad */
-
-/* TLayTech products */
-#define USB_PRODUCT_TLAYTECH_TEU800 0x1682 /* TEU800 3G modem */
-
-/* Topre Corporation products */
-#define USB_PRODUCT_TOPRE_HHKB 0x0100 /* HHKB Professional */
-
-/* Toshiba Corporation products */
-#define USB_PRODUCT_TOSHIBA_POCKETPC_E740 0x0706 /* PocketPC e740 */
-#define USB_PRODUCT_TOSHIBA_RT3070 0x0a07 /* RT3070 */
-#define USB_PRODUCT_TOSHIBA_G450 0x0d45 /* G450 modem */
-#define USB_PRODUCT_TOSHIBA_HSDPA 0x1302 /* G450 modem */
-
-/* Trek Technology products */
-#define USB_PRODUCT_TREK_THUMBDRIVE 0x1111 /* ThumbDrive */
-#define USB_PRODUCT_TREK_MEMKEY 0x8888 /* IBM USB Memory Key */
-#define USB_PRODUCT_TREK_THUMBDRIVE_8MB 0x9988 /* ThumbDrive_8MB */
-
-/* Tripp-Lite products */
-#define USB_PRODUCT_TRIPPLITE_U209 0x2008 /* Serial */
-
-/* Trumpion products */
-#define USB_PRODUCT_TRUMPION_T33520 0x1001 /* T33520 USB Flash Card Controller */
-#define USB_PRODUCT_TRUMPION_C3310 0x1100 /* Comotron C3310 MP3 player */
-#define USB_PRODUCT_TRUMPION_MP3 0x1200 /* MP3 player */
-
-/* TwinMOS */
-#define USB_PRODUCT_TWINMOS_G240 0xa006 /* G240 */
-#define USB_PRODUCT_TWINMOS_MDIV 0x1325 /* Memory Disk IV */
-
-/* Ubiquam products */
-#define USB_PRODUCT_UBIQUAM_UALL 0x3100 /* CDMA 1xRTT USB Modem (U-100/105/200/300/520) */
-
-/* Ultima products */
-#define USB_PRODUCT_ULTIMA_1200UBPLUS 0x4002 /* 1200 UB Plus scanner */
-
-/* UMAX products */
-#define USB_PRODUCT_UMAX_ASTRA1236U 0x0002 /* Astra 1236U Scanner */
-#define USB_PRODUCT_UMAX_ASTRA1220U 0x0010 /* Astra 1220U Scanner */
-#define USB_PRODUCT_UMAX_ASTRA2000U 0x0030 /* Astra 2000U Scanner */
-#define USB_PRODUCT_UMAX_ASTRA2100U 0x0130 /* Astra 2100U Scanner */
-#define USB_PRODUCT_UMAX_ASTRA2200U 0x0230 /* Astra 2200U Scanner */
-#define USB_PRODUCT_UMAX_ASTRA3400 0x0060 /* Astra 3400 Scanner */
-
-/* U-MEDIA Communications products */
-#define USB_PRODUCT_UMEDIA_TEW444UBEU 0x3006 /* TEW-444UB EU */
-#define USB_PRODUCT_UMEDIA_TEW444UBEU_NF 0x3007 /* TEW-444UB EU (no firmware) */
-#define USB_PRODUCT_UMEDIA_TEW429UB_A 0x300a /* TEW-429UB_A */
-#define USB_PRODUCT_UMEDIA_TEW429UB 0x300b /* TEW-429UB */
-#define USB_PRODUCT_UMEDIA_TEW429UBC1 0x300d /* TEW-429UB C1 */
-#define USB_PRODUCT_UMEDIA_RT2870_1 0x300e /* RT2870 */
-#define USB_PRODUCT_UMEDIA_ALL0298V2 0x3204 /* ALL0298 v2 */
-#define USB_PRODUCT_UMEDIA_AR5523_2 0x3205 /* AR5523 */
-#define USB_PRODUCT_UMEDIA_AR5523_2_NF 0x3206 /* AR5523 (no firmware) */
-
-/* Universal Access products */
-#define USB_PRODUCT_UNIACCESS_PANACHE 0x0101 /* Panache Surf USB ISDN Adapter */
-
-/* USI products */
-#define USB_PRODUCT_USI_MC60 0x10c5 /* MC60 Serial */
-
-/* U.S. Robotics products */
-#define USB_PRODUCT_USR_USR5422 0x0118 /* USR5422 WLAN */
-#define USB_PRODUCT_USR_USR5423 0x0121 /* USR5423 WLAN */
-
-/* VIA Technologies products */
-#define USB_PRODUCT_VIA_USB2IDEBRIDGE 0x6204 /* USB 2.0 IDE Bridge */
-
-/* Vaisala products */
-#define USB_PRODUCT_VAISALA_CABLE 0x0200 /* USB Interface cable */
-
-/* VidzMedia products */
-#define USB_PRODUCT_VIDZMEDIA_MONSTERTV 0x4fb1 /* MonsterTV P2H */
-
-/* Vision products */
-#define USB_PRODUCT_VISION_VC6452V002 0x0002 /* CPiA Camera */
-
-/* Visioneer products */
-#define USB_PRODUCT_VISIONEER_7600 0x0211 /* OneTouch 7600 */
-#define USB_PRODUCT_VISIONEER_5300 0x0221 /* OneTouch 5300 */
-#define USB_PRODUCT_VISIONEER_3000 0x0224 /* Scanport 3000 */
-#define USB_PRODUCT_VISIONEER_6100 0x0231 /* OneTouch 6100 */
-#define USB_PRODUCT_VISIONEER_6200 0x0311 /* OneTouch 6200 */
-#define USB_PRODUCT_VISIONEER_8100 0x0321 /* OneTouch 8100 */
-#define USB_PRODUCT_VISIONEER_8600 0x0331 /* OneTouch 8600 */
-
-/* Vivitar products */
-#define USB_PRODUCT_VIVITAR_35XX 0x0003 /* Vivicam 35Xx */
-
-/* VTech products */
-#define USB_PRODUCT_VTECH_RT2570 0x3012 /* RT2570 */
-#define USB_PRODUCT_VTECH_ZD1211B 0x3014 /* ZD1211B */
-
-/* Wacom products */
-#define USB_PRODUCT_WACOM_CT0405U 0x0000 /* CT-0405-U Tablet */
-#define USB_PRODUCT_WACOM_GRAPHIRE 0x0010 /* Graphire */
-#define USB_PRODUCT_WACOM_GRAPHIRE3_4X5 0x0013 /* Graphire 3 4x5 */
-#define USB_PRODUCT_WACOM_INTUOSA5 0x0021 /* Intuos A5 */
-#define USB_PRODUCT_WACOM_GD0912U 0x0022 /* Intuos 9x12 Graphics Tablet */
-
-/* WaveSense products */
-#define USB_PRODUCT_WAVESENSE_JAZZ 0xaaaa /* Jazz blood glucose meter */
-
-/* WCH products */
-#define USB_PRODUCT_WCH_CH341SER 0x5523 /* CH341/CH340 USB-Serial Bridge */
-#define USB_PRODUCT_WCH2_CH341SER 0x7523 /* CH341/CH340 USB-Serial Bridge */
-
-/* Western Digital products */
-#define USB_PRODUCT_WESTERN_COMBO 0x0200 /* Firewire USB Combo */
-#define USB_PRODUCT_WESTERN_EXTHDD 0x0400 /* External HDD */
-#define USB_PRODUCT_WESTERN_HUB 0x0500 /* USB HUB */
-#define USB_PRODUCT_WESTERN_MYBOOK 0x0901 /* MyBook External HDD */
-#define USB_PRODUCT_WESTERN_MYPASSWORD 0x0704 /* MyPassword External HDD */
-
-/* Windbond Electronics */
-#define USB_PRODUCT_WINBOND_UH104 0x5518 /* 4-port USB Hub */
-
-/* WinMaxGroup products */
-#define USB_PRODUCT_WINMAXGROUP_FLASH64MC 0x6660 /* USB Flash Disk 64M-C */
-
-/* Wistron NeWeb products */
-#define USB_PRODUCT_WISTRONNEWEB_UR045G 0x0427 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_WISTRONNEWEB_UR055G 0x0711 /* UR055G */
-#define USB_PRODUCT_WISTRONNEWEB_AR5523_1 0x0826 /* AR5523 */
-#define USB_PRODUCT_WISTRONNEWEB_AR5523_1_NF 0x0827 /* AR5523 (no firmware) */
-#define USB_PRODUCT_WISTRONNEWEB_AR5523_2 0x082a /* AR5523 */
-#define USB_PRODUCT_WISTRONNEWEB_AR5523_2_NF 0x0829 /* AR5523 (no firmware) */
-
-/* Xerox products */
-#define USB_PRODUCT_XEROX_WCM15 0xffef /* WorkCenter M15 */
-
-/* Xirlink products */
-#define USB_PRODUCT_XIRLINK_PCCAM 0x8080 /* IBM PC Camera */
-
-/* Xyratex products */
-#define USB_PRODUCT_XYRATEX_PRISM_GT_1 0x2000 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_XYRATEX_PRISM_GT_2 0x2002 /* PrismGT USB 2.0 WLAN */
-
-/* Yamaha products */
-#define USB_PRODUCT_YAMAHA_UX256 0x1000 /* UX256 MIDI I/F */
-#define USB_PRODUCT_YAMAHA_UX96 0x1008 /* UX96 MIDI I/F */
-#define USB_PRODUCT_YAMAHA_RTA54I 0x4000 /* NetVolante RTA54i Broadband&ISDN Router */
-#define USB_PRODUCT_YAMAHA_RTA55I 0x4004 /* NetVolante RTA55i Broadband VoIP Router */
-#define USB_PRODUCT_YAMAHA_RTW65B 0x4001 /* NetVolante RTW65b Broadband Wireless Router */
-#define USB_PRODUCT_YAMAHA_RTW65I 0x4002 /* NetVolante RTW65i Broadband&ISDN Wireless Router */
-
-/* Yano products */
-#define USB_PRODUCT_YANO_U640MO 0x0101 /* U640MO-03 */
-#define USB_PRODUCT_YANO_FW800HD 0x05fc /* METALWEAR-HDD */
-
-/* Y.C. Cable products */
-#define USB_PRODUCT_YCCABLE_PL2303 0x0fba /* PL2303 Serial */
-
-/* Y-E Data products */
-#define USB_PRODUCT_YEDATA_FLASHBUSTERU 0x0000 /* Flashbuster-U */
-
-/* Yiso Wireless Co. products */
-#define USB_PRODUCT_YISO_C893 0xc893 /* CDMA 2000 1xEVDO PC Card */
-
-/* Z-Com products */
-#define USB_PRODUCT_ZCOM_M4Y750 0x0001 /* M4Y-750 */
-#define USB_PRODUCT_ZCOM_XI725 0x0002 /* XI-725/726 */
-#define USB_PRODUCT_ZCOM_XI735 0x0005 /* XI-735 */
-#define USB_PRODUCT_ZCOM_XG703A 0x0008 /* PrismGT USB 2.0 WLAN */
-#define USB_PRODUCT_ZCOM_ZD1211 0x0011 /* ZD1211 */
-#define USB_PRODUCT_ZCOM_AR5523 0x0012 /* AR5523 */
-#define USB_PRODUCT_ZCOM_AR5523_NF 0x0013 /* AR5523 driver (no firmware) */
-#define USB_PRODUCT_ZCOM_XM142 0x0015 /* XM-142 */
-#define USB_PRODUCT_ZCOM_ZD1211B 0x001a /* ZD1211B */
-#define USB_PRODUCT_ZCOM_RT2870_1 0x0022 /* RT2870 */
-#define USB_PRODUCT_ZCOM_RT2870_2 0x0025 /* RT2870 */
-
-/* Zinwell products */
-#define USB_PRODUCT_ZINWELL_RT2570 0x0260 /* RT2570 */
-#define USB_PRODUCT_ZINWELL_RT2870_1 0x0280 /* RT2870 */
-#define USB_PRODUCT_ZINWELL_RT2870_2 0x0282 /* RT2870 */
-#define USB_PRODUCT_ZINWELL_RT3072_1 0x0283 /* RT3072 */
-#define USB_PRODUCT_ZINWELL_RT3072_2 0x0284 /* RT3072 */
-#define USB_PRODUCT_ZINWELL_RT3070 0x5257 /* RT3070 */
-
-/* Zoom Telephonics, Inc. products */
-#define USB_PRODUCT_ZOOM_2986L 0x9700 /* 2986L Fax modem */
-
-/* Zoran Microelectronics products */
-#define USB_PRODUCT_ZORAN_EX20DSC 0x4343 /* Digital Camera EX-20 DSC */
-
-/* Zydas Technology Corporation products */
-#define USB_PRODUCT_ZYDAS_ZD1211 0x1211 /* ZD1211 WLAN abg */
-#define USB_PRODUCT_ZYDAS_ZD1211B 0x1215 /* ZD1211B */
-
-/* ZyXEL Communication Co. products */
-#define USB_PRODUCT_ZYXEL_OMNI56K 0x1500 /* Omni 56K Plus */
-#define USB_PRODUCT_ZYXEL_980N 0x2011 /* Scorpion-980N keyboard */
-#define USB_PRODUCT_ZYXEL_ZYAIRG220 0x3401 /* ZyAIR G-220 */
-#define USB_PRODUCT_ZYXEL_G200V2 0x3407 /* G-200 v2 */
-#define USB_PRODUCT_ZYXEL_AG225H 0x3409 /* AG-225H */
-#define USB_PRODUCT_ZYXEL_M202 0x340a /* M-202 */
-#define USB_PRODUCT_ZYXEL_G220V2 0x340f /* G-220 v2 */
-#define USB_PRODUCT_ZYXEL_G202 0x3410 /* G-202 */
-#define USB_PRODUCT_ZYXEL_RT2870_1 0x3416 /* RT2870 */
-#define USB_PRODUCT_ZYXEL_RT2870_2 0x341a /* RT2870 */
diff --git a/freebsd/local/usbdevs_data.h b/freebsd/local/usbdevs_data.h
deleted file mode 100644
index 6bd20f55..00000000
--- a/freebsd/local/usbdevs_data.h
+++ /dev/null
@@ -1,15530 +0,0 @@
-/* ??? */
-
-/*
- * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.
- *
- * generated from:
- * FreeBSD
- */
-/* $NetBSD: usbdevs,v 1.392 2004/12/29 08:38:44 imp Exp $ */
-
-/*-
- * Copyright (c) 1998-2004 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.
- *
- * 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.
- */
-
-const struct usb_knowndev usb_knowndevs[] = {
- {
- USB_VENDOR_3COM, USB_PRODUCT_3COM_HOMECONN,
- 0,
- "3Com",
- "HomeConnect Camera",
- },
- {
- USB_VENDOR_3COM, USB_PRODUCT_3COM_3CREB96,
- 0,
- "3Com",
- "Bluetooth USB Adapter",
- },
- {
- USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250,
- 0,
- "3Com",
- "3C19250 Ethernet Adapter",
- },
- {
- USB_VENDOR_3COM, USB_PRODUCT_3COM_3CRSHEW696,
- 0,
- "3Com",
- "3CRSHEW696 Wireless Adapter",
- },
- {
- USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460,
- 0,
- "3Com",
- "HomeConnect 3C460",
- },
- {
- USB_VENDOR_3COM, USB_PRODUCT_3COM_USR56K,
- 0,
- "3Com",
- "U.S.Robotics 56000 Voice FaxModem Pro",
- },
- {
- USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460B,
- 0,
- "3Com",
- "HomeConnect 3C460B",
- },
- {
- USB_VENDOR_3COM2, USB_PRODUCT_3COM2_3CRUSB10075,
- 0,
- "3Com",
- "3CRUSB10075",
- },
- {
- USB_VENDOR_3COM3, USB_PRODUCT_3COM3_AR5523_1,
- 0,
- "3Com",
- "AR5523",
- },
- {
- USB_VENDOR_3COM3, USB_PRODUCT_3COM3_AR5523_2,
- 0,
- "3Com",
- "AR5523",
- },
- {
- USB_VENDOR_3COM3, USB_PRODUCT_3COM3_AR5523_3,
- 0,
- "3Com",
- "AR5523",
- },
- {
- USB_VENDOR_3COMUSR, USB_PRODUCT_3COMUSR_OFFICECONN,
- 0,
- "U.S. Robotics",
- "3Com OfficeConnect Analog Modem",
- },
- {
- USB_VENDOR_3COMUSR, USB_PRODUCT_3COMUSR_USRISDN,
- 0,
- "U.S. Robotics",
- "3Com U.S. Robotics Pro ISDN TA",
- },
- {
- USB_VENDOR_3COMUSR, USB_PRODUCT_3COMUSR_HOMECONN,
- 0,
- "U.S. Robotics",
- "3Com HomeConnect Camera",
- },
- {
- USB_VENDOR_3COMUSR, USB_PRODUCT_3COMUSR_USR56K,
- 0,
- "U.S. Robotics",
- "U.S. Robotics 56000 Voice FaxModem Pro",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX1,
- 0,
- "AboCom Systems",
- "XX1",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX2,
- 0,
- "AboCom Systems",
- "XX2",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2770,
- 0,
- "AboCom Systems",
- "RT2770",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2870,
- 0,
- "AboCom Systems",
- "RT2870",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT3070,
- 0,
- "AboCom Systems",
- "RT3070",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT3071,
- 0,
- "AboCom Systems",
- "RT3071",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT3072,
- 0,
- "AboCom Systems",
- "RT3072",
- },
- {
- USB_VENDOR_ABOCOM2, USB_PRODUCT_ABOCOM2_RT2870_1,
- 0,
- "AboCom Systems",
- "RT2870",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_URE450,
- 0,
- "AboCom Systems",
- "URE450 Ethernet Adapter",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UFE1000,
- 0,
- "AboCom Systems",
- "UFE1000 Fast Ethernet Adapter",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_DSB650TX_PNA,
- 0,
- "AboCom Systems",
- "1/10/100 Ethernet Adapter",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX4,
- 0,
- "AboCom Systems",
- "XX4",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX5,
- 0,
- "AboCom Systems",
- "XX5",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX6,
- 0,
- "AboCom Systems",
- "XX6",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX7,
- 0,
- "AboCom Systems",
- "XX7",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RTL8151,
- 0,
- "AboCom Systems",
- "RTL8151",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX8,
- 0,
- "AboCom Systems",
- "XX8",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX9,
- 0,
- "AboCom Systems",
- "XX9",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_UF200,
- 0,
- "AboCom Systems",
- "UF200 Ethernet",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WL54,
- 0,
- "AboCom Systems",
- "WL54",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_XX10,
- 0,
- "AboCom Systems",
- "XX10",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_BWU613,
- 0,
- "AboCom Systems",
- "BWU613",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_HWU54DM,
- 0,
- "AboCom Systems",
- "HWU54DM",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_2,
- 0,
- "AboCom Systems",
- "RT2573",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_3,
- 0,
- "AboCom Systems",
- "RT2573",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_RT2573_4,
- 0,
- "AboCom Systems",
- "RT2573",
- },
- {
- USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_WUG2700,
- 0,
- "AboCom Systems",
- "WUG2700",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_USB320_EC,
- 0,
- "Accton Technology",
- "USB320-EC Ethernet Adapter",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_2664W,
- 0,
- "Accton Technology",
- "2664W",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_111,
- 0,
- "Accton Technology",
- "T-Sinus 111 Wireless Adapter",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SMCWUSBG_NF,
- 0,
- "Accton Technology",
- "SMCWUSB-G (no firmware)",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SMCWUSBG,
- 0,
- "Accton Technology",
- "SMCWUSB-G",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SMCWUSBTG2_NF,
- 0,
- "Accton Technology",
- "SMCWUSBT-G2 (no firmware)",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SMCWUSBTG2,
- 0,
- "Accton Technology",
- "SMCWUSBT-G2",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_PRISM_GT,
- 0,
- "Accton Technology",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_SS1001,
- 0,
- "Accton Technology",
- "SpeedStream Ethernet Adapter",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT2870_2,
- 0,
- "Accton Technology",
- "RT2870",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT3070,
- 0,
- "Accton Technology",
- "RT3070",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT2770,
- 0,
- "Accton Technology",
- "RT2770",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT2870_3,
- 0,
- "Accton Technology",
- "RT2870",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT2870_5,
- 0,
- "Accton Technology",
- "RT2870",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT3070_4,
- 0,
- "Accton Technology",
- "RT3070",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT2870_4,
- 0,
- "Accton Technology",
- "RT2870",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT3070_1,
- 0,
- "Accton Technology",
- "RT3070",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT3070_2,
- 0,
- "Accton Technology",
- "RT3070",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT2870_1,
- 0,
- "Accton Technology",
- "RT2870",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT3070_3,
- 0,
- "Accton Technology",
- "RT3070",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_RT3070_5,
- 0,
- "Accton Technology",
- "RT3070",
- },
- {
- USB_VENDOR_ACCTON, USB_PRODUCT_ACCTON_ZD1211B,
- 0,
- "Accton Technology",
- "ZD1211B",
- },
- {
- USB_VENDOR_ACEECA, USB_PRODUCT_ACEECA_MEZ1000,
- 0,
- "Aceeca",
- "MEZ1000 RDA",
- },
- {
- USB_VENDOR_ACERCM, USB_PRODUCT_ACERCM_EP1427X2,
- 0,
- "Acer Communications & Multimedia",
- "EP-1427X-2 Ethernet Adapter",
- },
- {
- USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632,
- 0,
- "Acer Labs",
- "USB 2.0 Data Link",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_C310U,
- 0,
- "Acer Peripherals",
- "Acerscan C310U",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_320U,
- 0,
- "Acer Peripherals",
- "Acerscan 320U",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640U,
- 0,
- "Acer Peripherals",
- "Acerscan 640U",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_620U,
- 0,
- "Acer Peripherals",
- "Acerscan 620U",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_4300U,
- 0,
- "Acer Peripherals",
- "Benq 3300U/4300U",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_640BT,
- 0,
- "Acer Peripherals",
- "Acerscan 640BT",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ACERSCAN_1240U,
- 0,
- "Acer Peripherals",
- "Acerscan 1240U",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_S81,
- 0,
- "Acer Peripherals",
- "BenQ S81 phone",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_H10,
- 0,
- "Acer Peripherals",
- "AWL400 Wireless Adapter",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_ATAPI,
- 0,
- "Acer Peripherals",
- "ATA/ATAPI Adapter",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_AWL300,
- 0,
- "Acer Peripherals",
- "AWL300 Wireless Adapter",
- },
- {
- USB_VENDOR_ACERP, USB_PRODUCT_ACERP_AWL400,
- 0,
- "Acer Peripherals",
- "AWL400 Wireless Adapter",
- },
- {
- USB_VENDOR_ACERW, USB_PRODUCT_ACERW_WARPLINK,
- 0,
- "Acer",
- "Warplink",
- },
- {
- USB_VENDOR_ACTIONS, USB_PRODUCT_ACTIONS_MP4,
- 0,
- "Actions",
- "Actions MP4 Player",
- },
- {
- USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_PRISM_25,
- 0,
- "Actiontec Electronics",
- "Prism2.5 Wireless Adapter",
- },
- {
- USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_PRISM_25A,
- 0,
- "Actiontec Electronics",
- "Prism2.5 Wireless Adapter A",
- },
- {
- USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_FREELAN,
- 0,
- "Actiontec Electronics",
- "ROPEX FreeLan 802.11b",
- },
- {
- USB_VENDOR_ACTIONTEC, USB_PRODUCT_ACTIONTEC_UAT1,
- 0,
- "Actiontec Electronics",
- "UAT1 Wireless Ethernet Adapter",
- },
- {
- USB_VENDOR_ACTISYS, USB_PRODUCT_ACTISYS_IR2000U,
- 0,
- "ACTiSYS",
- "ACT-IR2000U FIR",
- },
- {
- USB_VENDOR_ACTIVEWIRE, USB_PRODUCT_ACTIVEWIRE_IOBOARD,
- 0,
- "ActiveWire",
- "I/O Board",
- },
- {
- USB_VENDOR_ACTIVEWIRE, USB_PRODUCT_ACTIVEWIRE_IOBOARD_FW1,
- 0,
- "ActiveWire",
- "I/O Board, rev. 1 firmware",
- },
- {
- USB_VENDOR_ADAPTEC, USB_PRODUCT_ADAPTEC_AWN8020,
- 0,
- "Adaptec",
- "AWN-8020 WLAN",
- },
- {
- USB_VENDOR_ADDTRON, USB_PRODUCT_ADDTRON_AWU120,
- 0,
- "Addtron",
- "AWU-120",
- },
- {
- USB_VENDOR_ADLINK, USB_PRODUCT_ADLINK_ND6530,
- 0,
- "ADLINK Technoligy, Inc.",
- "ND-6530 USB-Serial",
- },
- {
- USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_4,
- 0,
- "ADMtek",
- "AN986A Ethernet",
- },
- {
- USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUS,
- 0,
- "ADMtek",
- "AN986 Ethernet",
- },
- {
- USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII,
- 0,
- "ADMtek",
- "AN8511 Ethernet",
- },
- {
- USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_2,
- 0,
- "ADMtek",
- "AN8513 Ethernet",
- },
- {
- USB_VENDOR_ADMTEK, USB_PRODUCT_ADMTEK_PEGASUSII_3,
- 0,
- "ADMtek",
- "AN8515 Ethernet",
- },
- {
- USB_VENDOR_ADDON, USB_PRODUCT_ADDON_ATTACHE,
- 0,
- "Add-on Technology",
- "USB 2.0 Flash Drive",
- },
- {
- USB_VENDOR_ADDON, USB_PRODUCT_ADDON_ATTACHE,
- 0,
- "Add-on Technology",
- "USB 2.0 Flash Drive",
- },
- {
- USB_VENDOR_ADDON, USB_PRODUCT_ADDON_A256MB,
- 0,
- "Add-on Technology",
- "Attache 256MB USB 2.0 Flash Drive",
- },
- {
- USB_VENDOR_ADDON, USB_PRODUCT_ADDON_DISKPRO512,
- 0,
- "Add-on Technology",
- "USB 2.0 Flash Drive (DANE-ELEC zMate 512MB USB flash drive)",
- },
- {
- USB_VENDOR_ADDONICS2, USB_PRODUCT_ADDONICS2_CABLE_205,
- 0,
- "Addonics Technology",
- "Cable 205",
- },
- {
- USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT,
- 0,
- "ADS Technologies",
- "UBS-10BT Ethernet",
- },
- {
- USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BTX,
- 0,
- "ADS Technologies",
- "UBS-10BT Ethernet",
- },
- {
- USB_VENDOR_AEI, USB_PRODUCT_AEI_FASTETHERNET,
- 0,
- "AEI",
- "Fast Ethernet",
- },
- {
- USB_VENDOR_AGATE, USB_PRODUCT_AGATE_QDRIVE,
- 0,
- "Agate Technologies",
- "Q-Drive",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U,
- 0,
- "AGFA-Gevaert",
- "SnapScan 1212U",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1236U,
- 0,
- "AGFA-Gevaert",
- "SnapScan 1236U",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANTOUCH,
- 0,
- "AGFA-Gevaert",
- "SnapScan Touch",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCAN1212U2,
- 0,
- "AGFA-Gevaert",
- "SnapScan 1212U",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE40,
- 0,
- "AGFA-Gevaert",
- "SnapScan e40",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE50,
- 0,
- "AGFA-Gevaert",
- "SnapScan e50",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE20,
- 0,
- "AGFA-Gevaert",
- "SnapScan e20",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE25,
- 0,
- "AGFA-Gevaert",
- "SnapScan e25",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE26,
- 0,
- "AGFA-Gevaert",
- "SnapScan e26",
- },
- {
- USB_VENDOR_AGFA, USB_PRODUCT_AGFA_SNAPSCANE52,
- 0,
- "AGFA-Gevaert",
- "SnapScan e52",
- },
- {
- USB_VENDOR_AINCOMM, USB_PRODUCT_AINCOMM_AWU2000B,
- 0,
- "Aincomm",
- "AWU2000B Wireless Adapter",
- },
- {
- USB_VENDOR_AIPTEK, USB_PRODUCT_AIPTEK_POCKETCAM3M,
- 0,
- "AIPTEK International",
- "PocketCAM 3Mega",
- },
- {
- USB_VENDOR_AIPTEK2, USB_PRODUCT_AIPTEK2_PENCAM_MEGA_1_3,
- 0,
- "AIPTEK International",
- "PenCam Mega 1.3",
- },
- {
- USB_VENDOR_AIPTEK2, USB_PRODUCT_AIPTEK2_SUNPLUS_TECH,
- 0,
- "AIPTEK International",
- "Sunplus Technology Inc.",
- },
- {
- USB_VENDOR_AIRPLUS, USB_PRODUCT_AIRPLUS_MCD650,
- 0,
- "Airplus",
- "MCD650 modem",
- },
- {
- USB_VENDOR_AIRPRIME, USB_PRODUCT_AIRPRIME_PC5220,
- 0,
- "AirPrime, Inc.",
- "CDMA Wireless PC Card",
- },
- {
- USB_VENDOR_AIRTIES, USB_PRODUCT_AIRTIES_RT3070,
- 0,
- "AirTies",
- "RT3070",
- },
- {
- USB_VENDOR_AKS, USB_PRODUCT_AKS_USBHASP,
- 0,
- "Aladdin Knowledge Systems",
- "USB-HASP 0.06",
- },
- {
- USB_VENDOR_ALCATEL, USB_PRODUCT_ALCATEL_OT535,
- 0,
- "Alcatel",
- "One Touch 535/735",
- },
- {
- USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB,
- 0,
- "Alcor Micro",
- "Kbd Hub",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SDCR_6335,
- 0,
- "Alcor Micro",
- "SD/MMC Card Reader",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SDCR_6362,
- 0,
- "Alcor Micro",
- "SD/MMC Card Reader",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_TRANSCEND,
- 0,
- "Alcor Micro",
- "Transcend JetFlash Drive",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_MA_KBD_HUB,
- 0,
- "Alcor Micro",
- "MacAlly Kbd Hub",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_AU9814,
- 0,
- "Alcor Micro",
- "AU9814 Hub",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_UMCR_9361,
- 0,
- "Alcor Micro",
- "USB Multimedia Card Reader",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_SM_KBD,
- 0,
- "Alcor Micro",
- "MicroConnectors/StrongMan Keyboard",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_NEC_KBD_HUB,
- 0,
- "Alcor Micro",
- "NEC Kbd Hub",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_AU9720,
- 0,
- "Alcor Micro",
- "USB2 - RS-232",
- },
- {
- USB_VENDOR_ALCOR, USB_PRODUCT_ALCOR_AU6390,
- 0,
- "Alcor Micro",
- "AU6390 USB-IDE converter",
- },
- {
- USB_VENDOR_ALINK, USB_PRODUCT_ALINK_DWM652U5,
- 0,
- "Alink",
- "DWM-652",
- },
- {
- USB_VENDOR_ALINK, USB_PRODUCT_ALINK_3G,
- 0,
- "Alink",
- "3G modem",
- },
- {
- USB_VENDOR_ALINK, USB_PRODUCT_ALINK_3GU,
- 0,
- "Alink",
- "3G modem",
- },
- {
- USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70,
- 0,
- "Altec Lansing",
- "ADA70 Speakers",
- },
- {
- USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495,
- 0,
- "Altec Lansing",
- "ASC495 Speakers",
- },
- {
- USB_VENDOR_ALLIEDTELESYN, USB_PRODUCT_ALLIEDTELESYN_ATUSB100,
- 0,
- "Allied Telesyn International",
- "AT-USB100",
- },
- {
- USB_VENDOR_ALLWIN, USB_PRODUCT_ALLWIN_RT2070,
- 0,
- "ALLWIN Tech",
- "RT2070",
- },
- {
- USB_VENDOR_ALLWIN, USB_PRODUCT_ALLWIN_RT2770,
- 0,
- "ALLWIN Tech",
- "RT2770",
- },
- {
- USB_VENDOR_ALLWIN, USB_PRODUCT_ALLWIN_RT2870,
- 0,
- "ALLWIN Tech",
- "RT2870",
- },
- {
- USB_VENDOR_ALLWIN, USB_PRODUCT_ALLWIN_RT3070,
- 0,
- "ALLWIN Tech",
- "RT3070",
- },
- {
- USB_VENDOR_ALLWIN, USB_PRODUCT_ALLWIN_RT3071,
- 0,
- "ALLWIN Tech",
- "RT3071",
- },
- {
- USB_VENDOR_ALLWIN, USB_PRODUCT_ALLWIN_RT3072,
- 0,
- "ALLWIN Tech",
- "RT3072",
- },
- {
- USB_VENDOR_ALLWIN, USB_PRODUCT_ALLWIN_RT3572,
- 0,
- "ALLWIN Tech",
- "RT3572",
- },
- {
- USB_VENDOR_ALPHASMART, USB_PRODUCT_ALPHASMART_DANA_KB,
- 0,
- "AlphaSmart, Inc.",
- "AlphaSmart Dana Keyboard",
- },
- {
- USB_VENDOR_ALPHASMART, USB_PRODUCT_ALPHASMART_DANA_SYNC,
- 0,
- "AlphaSmart, Inc.",
- "AlphaSmart Dana HotSync",
- },
- {
- USB_VENDOR_AMOI, USB_PRODUCT_AMOI_H01,
- 0,
- "Amoi Electronics",
- "H01 3G modem",
- },
- {
- USB_VENDOR_AMOI, USB_PRODUCT_AMOI_H01A,
- 0,
- "Amoi Electronics",
- "H01A 3G modem",
- },
- {
- USB_VENDOR_AMOI, USB_PRODUCT_AMOI_H02,
- 0,
- "Amoi Electronics",
- "H02 3G modem",
- },
- {
- USB_VENDOR_APC, USB_PRODUCT_APC_UPS,
- 0,
- "American Power Conversion",
- "Uninterruptible Power Supply",
- },
- {
- USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_WLAN,
- 0,
- "Ambit Microsystems",
- "WLAN",
- },
- {
- USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250,
- 0,
- "Ambit Microsystems",
- "NTL 250 cable modem",
- },
- {
- USB_VENDOR_APACER, USB_PRODUCT_APACER_HT202,
- 0,
- "Apacer",
- "USB 2.0 Flash Drive",
- },
- {
- USB_VENDOR_APC, USB_PRODUCT_APC_UPS,
- 0,
- "American Power Conversion",
- "Uninterruptible Power Supply",
- },
- {
- USB_VENDOR_AMIGO, USB_PRODUCT_AMIGO_RT2870_1,
- 0,
- "Amigo Technology",
- "RT2870",
- },
- {
- USB_VENDOR_AMIGO, USB_PRODUCT_AMIGO_RT2870_2,
- 0,
- "Amigo Technology",
- "RT2870",
- },
- {
- USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GO,
- 0,
- "AMIT",
- "CG-WLUSB2GO",
- },
- {
- USB_VENDOR_AMIT, USB_PRODUCT_AMIT_CGWLUSB2GNR,
- 0,
- "AMIT",
- "CG-WLUSB2GNR",
- },
- {
- USB_VENDOR_AMIT, USB_PRODUCT_AMIT_RT2870_1,
- 0,
- "AMIT",
- "RT2870",
- },
- {
- USB_VENDOR_AMIT2, USB_PRODUCT_AMIT2_RT2870,
- 0,
- "AMIT",
- "RT2870",
- },
- {
- USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_SERIAL,
- 0,
- "Anchor Chips",
- "Serial",
- },
- {
- USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_EZUSB,
- 0,
- "Anchor Chips",
- "EZUSB",
- },
- {
- USB_VENDOR_ANCHOR, USB_PRODUCT_ANCHOR_EZLINK,
- 0,
- "Anchor Chips",
- "EZLINK",
- },
- {
- USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_620UW,
- 0,
- "AnyDATA Corporation",
- "CDMA 2000 EV-DO USB Modem",
- },
- {
- USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_E100X,
- 0,
- "AnyDATA Corporation",
- "CDMA 2000 1xRTT/EV-DO USB Modem",
- },
- {
- USB_VENDOR_ANYDATA, USB_PRODUCT_ANYDATA_ADU_500A,
- 0,
- "AnyDATA Corporation",
- "CDMA 2000 EV-DO USB Modem",
- },
- {
- USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101,
- 0,
- "AOX",
- "Ethernet",
- },
- {
- USB_VENDOR_APC, USB_PRODUCT_APC_UPS,
- 0,
- "American Power Conversion",
- "Uninterruptible Power Supply",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IMAC_KBD,
- 0,
- "Apple Computer",
- "USB iMac Keyboard",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD,
- 0,
- "Apple Computer",
- "USB Keyboard M2452",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_EXT_KBD,
- 0,
- "Apple Computer",
- "Apple Extended USB Keyboard",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD_TP_ANSI,
- 0,
- "Apple Computer",
- "Apple Internal Keyboard/Trackpad (Wellspring/ANSI)",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD_TP_ISO,
- 0,
- "Apple Computer",
- "Apple Internal Keyboard/Trackpad (Wellspring/ISO)",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD_TP_JIS,
- 0,
- "Apple Computer",
- "Apple Internal Keyboard/Trackpad (Wellspring/JIS)",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD_TP_ANSI2,
- 0,
- "Apple Computer",
- "Apple Internal Keyboard/Trackpad (Wellspring2/ANSI)",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD_TP_ISO2,
- 0,
- "Apple Computer",
- "Apple Internal Keyboard/Trackpad (Wellspring2/ISO)",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD_TP_JIS2,
- 0,
- "Apple Computer",
- "Apple Internal Keyboard/Trackpad (Wellspring2/JIS)",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_MOUSE,
- 0,
- "Apple Computer",
- "Mouse M4848",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_OPTMOUSE,
- 0,
- "Apple Computer",
- "Optical mouse",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_MIGHTYMOUSE,
- 0,
- "Apple Computer",
- "Mighty Mouse",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_KBD_HUB,
- 0,
- "Apple Computer",
- "Hub in Apple USB Keyboard",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_EXT_KBD_HUB,
- 0,
- "Apple Computer",
- "Hub in Apple Extended USB Keyboard",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_SPEAKERS,
- 0,
- "Apple Computer",
- "Speakers",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD,
- 0,
- "Apple Computer",
- "iPod",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD2G,
- 0,
- "Apple Computer",
- "iPod 2G",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD3G,
- 0,
- "Apple Computer",
- "iPod 3G",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_04,
- 0,
- "Apple Computer",
- "iPod '04'",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPODMINI,
- 0,
- "Apple Computer",
- "iPod Mini",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_06,
- 0,
- "Apple Computer",
- "iPod '06'",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_07,
- 0,
- "Apple Computer",
- "iPod '07'",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_08,
- 0,
- "Apple Computer",
- "iPod '08'",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPODVIDEO,
- 0,
- "Apple Computer",
- "iPod Video",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPODNANO,
- 0,
- "Apple Computer",
- "iPod Nano",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE,
- 0,
- "Apple Computer",
- "iPhone",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH,
- 0,
- "Apple Computer",
- "iPod Touch",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G,
- 0,
- "Apple Computer",
- "iPhone 3G",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS,
- 0,
- "Apple Computer",
- "iPhone 3GS",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4,
- 0,
- "Apple Computer",
- "iPhone 4",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPAD,
- 0,
- "Apple Computer",
- "iPad",
- },
- {
- USB_VENDOR_APPLE, USB_PRODUCT_APPLE_ETHERNET,
- 0,
- "Apple Computer",
- "Ethernet A1277",
- },
- {
- USB_VENDOR_ARKMICRO, USB_PRODUCT_ARKMICRO_ARK3116,
- 0,
- "Arkmicro Technologies Inc.",
- "ARK3116 Serial",
- },
- {
- USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO230,
- 0,
- "Asahi Optical",
- "Digital camera",
- },
- {
- USB_VENDOR_ASAHIOPTICAL, USB_PRODUCT_ASAHIOPTICAL_OPTIO330,
- 0,
- "Asahi Optical",
- "Digital camera",
- },
- {
- USB_VENDOR_ASANTE, USB_PRODUCT_ASANTE_EA,
- 0,
- "Asante",
- "Ethernet",
- },
- {
- USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88172,
- 0,
- "ASIX Electronics",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88178,
- 0,
- "ASIX Electronics",
- "AX88178",
- },
- {
- USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772,
- 0,
- "ASIX Electronics",
- "AX88772",
- },
- {
- USB_VENDOR_ASIX, USB_PRODUCT_ASIX_AX88772A,
- 0,
- "ASIX Electronics",
- "AX88772A USB 2.0 10/100 Ethernet",
- },
- {
- USB_VENDOR_ASUS2, USB_PRODUCT_ASUS2_USBN11,
- 0,
- "ASUS",
- "USB-N11",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL167G,
- 0,
- "ASUSTeK Computer",
- "WL-167g Wireless Adapter",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_WL159G,
- 0,
- "ASUSTeK Computer",
- "WL-159g",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_A9T_WIFI,
- 0,
- "ASUSTeK Computer",
- "A9T wireless",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_P5B_WIFI,
- 0,
- "ASUSTeK Computer",
- "P5B wireless",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_1,
- 0,
- "ASUSTeK Computer",
- "RT2573",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2573_2,
- 0,
- "ASUSTeK Computer",
- "RT2573",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM,
- 0,
- "ASUSTeK Computer",
- "LCM display",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2870_1,
- 0,
- "ASUSTeK Computer",
- "RT2870",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2870_2,
- 0,
- "ASUSTeK Computer",
- "RT2870",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2870_3,
- 0,
- "ASUSTeK Computer",
- "RT2870",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2870_4,
- 0,
- "ASUSTeK Computer",
- "RT2870",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2870_5,
- 0,
- "ASUSTeK Computer",
- "RT2870",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_USBN13,
- 0,
- "ASUSTeK Computer",
- "USB-N13",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT3070_1,
- 0,
- "ASUSTeK Computer",
- "RT3070",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_A730W,
- 0,
- "ASUSTeK Computer",
- "ASUS MyPal A730W",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_P535,
- 0,
- "ASUSTeK Computer",
- "ASUS P535 PDA",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_GMSC,
- 0,
- "ASUSTeK Computer",
- "ASUS Generic Mass Storage",
- },
- {
- USB_VENDOR_ASUS, USB_PRODUCT_ASUS_RT2570,
- 0,
- "ASUSTeK Computer",
- "RT2500USB Wireless Adapter",
- },
- {
- USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC1284,
- 0,
- "ATEN International",
- "Parallel printer",
- },
- {
- USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T,
- 0,
- "ATEN International",
- "10Mbps Ethernet",
- },
- {
- USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC110T,
- 0,
- "ATEN International",
- "UC-110T Ethernet",
- },
- {
- USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC232A,
- 0,
- "ATEN International",
- "Serial",
- },
- {
- USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC210T,
- 0,
- "ATEN International",
- "UC-210T Ethernet",
- },
- {
- USB_VENDOR_ATEN, USB_PRODUCT_ATEN_DSB650C,
- 0,
- "ATEN International",
- "DSB-650C",
- },
- {
- USB_VENDOR_ATHEROS, USB_PRODUCT_ATHEROS_AR5523,
- 0,
- "Atheros Communications",
- "AR5523",
- },
- {
- USB_VENDOR_ATHEROS, USB_PRODUCT_ATHEROS_AR5523_NF,
- 0,
- "Atheros Communications",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR5523_1,
- 0,
- "Atheros Communications",
- "AR5523",
- },
- {
- USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR5523_1_NF,
- 0,
- "Atheros Communications",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR5523_2,
- 0,
- "Atheros Communications",
- "AR5523",
- },
- {
- USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR5523_2_NF,
- 0,
- "Atheros Communications",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR5523_3,
- 0,
- "Atheros Communications",
- "AR5523",
- },
- {
- USB_VENDOR_ATHEROS2, USB_PRODUCT_ATHEROS2_AR5523_3_NF,
- 0,
- "Atheros Communications",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_STK541,
- 0,
- "Atmel",
- "Zigbee Controller",
- },
- {
- USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_UHB124,
- 0,
- "Atmel",
- "UHB124 hub",
- },
- {
- USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_DWL120,
- 0,
- "Atmel",
- "DWL-120 Wireless Adapter",
- },
- {
- USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_BW002,
- 0,
- "Atmel",
- "BW002 Wireless Adapter",
- },
- {
- USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_WL1130USB,
- 0,
- "Atmel",
- "WL-1130 USB",
- },
- {
- USB_VENDOR_ATMEL, USB_PRODUCT_ATMEL_AT76C505A,
- 0,
- "Atmel",
- "AT76c505a Wireless Adapter",
- },
- {
- USB_VENDOR_AUTHENTEC, USB_PRODUCT_AUTHENTEC_AES1610,
- 0,
- "AuthenTec",
- "AES1610 Fingerprint Sensor",
- },
- {
- USB_VENDOR_AVISION, USB_PRODUCT_AVISION_1200U,
- 0,
- "Avision",
- "1200U scanner",
- },
- {
- USB_VENDOR_AXESSTEL, USB_PRODUCT_AXESSTEL_DATAMODEM,
- 0,
- "Axesstel Co., Ltd.",
- "Data Modem",
- },
- {
- USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RT2870_1,
- 0,
- "AsureWave",
- "RT2870",
- },
- {
- USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RT2870_2,
- 0,
- "AsureWave",
- "RT2870",
- },
- {
- USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RT3070_1,
- 0,
- "AsureWave",
- "RT3070",
- },
- {
- USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RT3070_2,
- 0,
- "AsureWave",
- "RT3070",
- },
- {
- USB_VENDOR_AZUREWAVE, USB_PRODUCT_AZUREWAVE_RT3070_3,
- 0,
- "AsureWave",
- "RT3070",
- },
- {
- USB_VENDOR_BALTECH, USB_PRODUCT_BALTECH_CARDREADER,
- 0,
- "Baltech",
- "Card reader",
- },
- {
- USB_VENDOR_BBELECTRONICS, USB_PRODUCT_BBELECTRONICS_USOTL4,
- 0,
- "B&B Electronics",
- "RS-422/485",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D6050,
- 0,
- "Belkin Components",
- "F5D6050 802.11b Wireless Adapter",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_FBT001V,
- 0,
- "Belkin Components",
- "FBT001v2 Bluetooth",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_FBT003V,
- 0,
- "Belkin Components",
- "FBT003v2 Bluetooth",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U103,
- 0,
- "Belkin Components",
- "F5U103 Serial",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U109,
- 0,
- "Belkin Components",
- "F5U109 Serial",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2SCSI,
- 0,
- "Belkin Components",
- "USB to SCSI",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F8T012,
- 0,
- "Belkin Components",
- "F8T012xx1 Bluetooth USB Adapter",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_USB2LAN,
- 0,
- "Belkin Components",
- "USB to LAN",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U208,
- 0,
- "Belkin Components",
- "F5U208 VideoBus II",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U237,
- 0,
- "Belkin Components",
- "F5U237 USB 2.0 7-Port Hub",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U257,
- 0,
- "Belkin Components",
- "F5U257 Serial",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U409,
- 0,
- "Belkin Components",
- "F5U409 Serial",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR,
- 0,
- "Belkin Components",
- "F6C550-AVR UPS",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U120,
- 0,
- "Belkin Components",
- "F5U120-PC Hub",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_ZD1211B,
- 0,
- "Belkin Components",
- "ZD1211B",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D5055,
- 0,
- "Belkin Components",
- "F5D5055",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050,
- 0,
- "Belkin Components",
- "F5D7050 Wireless Adapter",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7051,
- 0,
- "Belkin Components",
- "F5D7051 54g USB Network Adapter",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050A,
- 0,
- "Belkin Components",
- "F5D7050A Wireless Adapter",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050_V4000,
- 0,
- "Belkin Components",
- "F5D7050 v4000 Wireless Adapter",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D7050E,
- 0,
- "Belkin Components",
- "F5D7050E Wireless Adapter",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RT2870_1,
- 0,
- "Belkin Components",
- "RT2870",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_RT2870_2,
- 0,
- "Belkin Components",
- "RT2870",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D8053V3,
- 0,
- "Belkin Components",
- "F5D8053 v3",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D8055,
- 0,
- "Belkin Components",
- "F5D8055",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5D9050V3,
- 0,
- "Belkin Components",
- "F5D9050 ver 3 Wireless Adapter",
- },
- {
- USB_VENDOR_BELKIN2, USB_PRODUCT_BELKIN2_F5U002,
- 0,
- "Belkin Components",
- "F5U002 Parallel printer",
- },
- {
- USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6D4050V1,
- 0,
- "Belkin Components",
- "F6D4050 v1",
- },
- {
- USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB100,
- 0,
- "Billionton Systems",
- "USB100N 10/100 FastEthernet",
- },
- {
- USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBLP100,
- 0,
- "Billionton Systems",
- "USB100LP",
- },
- {
- USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBEL100,
- 0,
- "Billionton Systems",
- "USB100EL",
- },
- {
- USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USBE100,
- 0,
- "Billionton Systems",
- "USBE100",
- },
- {
- USB_VENDOR_BILLIONTON, USB_PRODUCT_BILLIONTON_USB2AR,
- 0,
- "Billionton Systems",
- "USB2AR Ethernet",
- },
- {
- USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033,
- 0,
- "Broadcom",
- "BCM2033 Bluetooth USB dongle",
- },
- {
- USB_VENDOR_BROTHER, USB_PRODUCT_BROTHER_HL1050,
- 0,
- "Brother Industries",
- "HL-1050 laser printer",
- },
- {
- USB_VENDOR_BROTHER, USB_PRODUCT_BROTHER_MFC8600_9650,
- 0,
- "Brother Industries",
- "MFC8600/9650 multifunction device",
- },
- {
- USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC6100,
- 0,
- "Behavior Tech. Computer",
- "6100C Keyboard",
- },
- {
- USB_VENDOR_BTC, USB_PRODUCT_BTC_BTC7932,
- 0,
- "Behavior Tech. Computer",
- "Keyboard with mouse port",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_N656U,
- 0,
- "Canon",
- "CanoScan N656U",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_N1220U,
- 0,
- "Canon",
- "CanoScan N1220U",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_D660U,
- 0,
- "Canon",
- "CanoScan D660U",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_N676U,
- 0,
- "Canon",
- "CanoScan N676U",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_N1240U,
- 0,
- "Canon",
- "CanoScan N1240U",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_LIDE25,
- 0,
- "Canon",
- "CanoScan LIDE 25",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_S10,
- 0,
- "Canon",
- "PowerShot S10",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_S100,
- 0,
- "Canon",
- "PowerShot S100",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_S200,
- 0,
- "Canon",
- "PowerShot S200",
- },
- {
- USB_VENDOR_CANON, USB_PRODUCT_CANON_REBELXT,
- 0,
- "Canon",
- "Digital Rebel XT",
- },
- {
- USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE,
- 0,
- "Computer Access Technology",
- "Netmate Ethernet",
- },
- {
- USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2,
- 0,
- "Computer Access Technology",
- "Netmate2 Ethernet",
- },
- {
- USB_VENDOR_CATC, USB_PRODUCT_CATC_CHIEF,
- 0,
- "Computer Access Technology",
- "USB Chief Bus & Protocol Analyzer",
- },
- {
- USB_VENDOR_CATC, USB_PRODUCT_CATC_ANDROMEDA,
- 0,
- "Computer Access Technology",
- "Andromeda hub",
- },
- {
- USB_VENDOR_CASIO, USB_PRODUCT_CASIO_QV_DIGICAM,
- 0,
- "CASIO",
- "QV DigiCam",
- },
- {
- USB_VENDOR_CASIO, USB_PRODUCT_CASIO_EXS880,
- 0,
- "CASIO",
- "Exilim EX-S880",
- },
- {
- USB_VENDOR_CASIO, USB_PRODUCT_CASIO_BE300,
- 0,
- "CASIO",
- "BE-300 PDA",
- },
- {
- USB_VENDOR_CASIO, USB_PRODUCT_CASIO_NAMELAND,
- 0,
- "CASIO",
- "CASIO Nameland EZ-USB",
- },
- {
- USB_VENDOR_CCYU, USB_PRODUCT_CCYU_ED1064,
- 0,
- "CCYU Technology",
- "EasyDisk ED1064",
- },
- {
- USB_VENDOR_CENTURY, USB_PRODUCT_CENTURY_EX35QUAT,
- 0,
- "Century Corp",
- "Century USB Disk Enclosure",
- },
- {
- USB_VENDOR_CENTURY, USB_PRODUCT_CENTURY_EX35SW4_SB4,
- 0,
- "Century Corp",
- "Century USB Disk Enclosure",
- },
- {
- USB_VENDOR_CHERRY, USB_PRODUCT_CHERRY_MY3000KBD,
- 0,
- "Cherry Mikroschalter",
- "My3000 keyboard",
- },
- {
- USB_VENDOR_CHERRY, USB_PRODUCT_CHERRY_MY3000HUB,
- 0,
- "Cherry Mikroschalter",
- "My3000 hub",
- },
- {
- USB_VENDOR_CHERRY, USB_PRODUCT_CHERRY_CYBOARD,
- 0,
- "Cherry Mikroschalter",
- "CyBoard Keyboard",
- },
- {
- USB_VENDOR_CHIC, USB_PRODUCT_CHIC_MOUSE1,
- 0,
- "Chic Technology",
- "mouse",
- },
- {
- USB_VENDOR_CHIC, USB_PRODUCT_CHIC_CYPRESS,
- 0,
- "Chic Technology",
- "Cypress USB Mouse",
- },
- {
- USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_KB8933,
- 0,
- "Chicony Electronics",
- "KB-8933 keyboard",
- },
- {
- USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_KU0325,
- 0,
- "Chicony Electronics",
- "KU-0325 keyboard",
- },
- {
- USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_CNF7129,
- 0,
- "Chicony Electronics",
- "Notebook Web Camera",
- },
- {
- USB_VENDOR_CHICONY2, USB_PRODUCT_CHICONY2_TWINKLECAM,
- 0,
- "Chicony",
- "TwinkleCam USB camera",
- },
- {
- USB_VENDOR_CHPRODUCTS, USB_PRODUCT_CHPRODUCTS_PROTHROTTLE,
- 0,
- "CH Products",
- "Pro Throttle",
- },
- {
- USB_VENDOR_CHPRODUCTS, USB_PRODUCT_CHPRODUCTS_PROPEDALS,
- 0,
- "CH Products",
- "Pro Pedals",
- },
- {
- USB_VENDOR_CHPRODUCTS, USB_PRODUCT_CHPRODUCTS_FIGHTERSTICK,
- 0,
- "CH Products",
- "Fighterstick",
- },
- {
- USB_VENDOR_CHPRODUCTS, USB_PRODUCT_CHPRODUCTS_FLIGHTYOKE,
- 0,
- "CH Products",
- "Flight Sim Yoke",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54AG,
- 0,
- "Cisco-Linksys",
- "WUSB54AG Wireless Adapter",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54G,
- 0,
- "Cisco-Linksys",
- "WUSB54G Wireless Adapter",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GP,
- 0,
- "Cisco-Linksys",
- "WUSB54GP Wireless Adapter",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_USB200MV2,
- 0,
- "Cisco-Linksys",
- "USB200M v2",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_HU200TS,
- 0,
- "Cisco-Linksys",
- "HU200TS Wireless Adapter",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GC,
- 0,
- "Cisco-Linksys",
- "WUSB54GC",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSB54GR,
- 0,
- "Cisco-Linksys",
- "WUSB54GR",
- },
- {
- USB_VENDOR_CISCOLINKSYS, USB_PRODUCT_CISCOLINKSYS_WUSBF54G,
- 0,
- "Cisco-Linksys",
- "WUSBF54G",
- },
- {
- USB_VENDOR_CISCOLINKSYS2, USB_PRODUCT_CISCOLINKSYS2_RT3070,
- 0,
- "Cisco-Linksys",
- "RT3070",
- },
- {
- USB_VENDOR_CISCOLINKSYS3, USB_PRODUCT_CISCOLINKSYS3_RT3070,
- 0,
- "Cisco-Linksys",
- "RT3070",
- },
- {
- USB_VENDOR_CLIPSAL, USB_PRODUCT_CLIPSAL_5500PCU,
- 0,
- "Clipsal",
- "5500PCU C-Bus",
- },
- {
- USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CNU510,
- 0,
- "C-motech",
- "CDMA Technologies USB modem",
- },
- {
- USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CNU550,
- 0,
- "C-motech",
- "CDMA 2000 1xRTT/1xEVDO USB modem",
- },
- {
- USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CGU628,
- 0,
- "C-motech",
- "CGU-628",
- },
- {
- USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_CDMA_MODEM1,
- 0,
- "C-motech",
- "CDMA Technologies USB modem",
- },
- {
- USB_VENDOR_CMOTECH, USB_PRODUCT_CMOTECH_DISK,
- 0,
- "C-motech",
- "disk mode",
- },
- {
- USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQPOCKETPC,
- 0,
- "Compaq",
- "iPAQ PocketPC",
- },
- {
- USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_PJB100,
- 0,
- "Compaq",
- "Personal Jukebox PJB100",
- },
- {
- USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX,
- 0,
- "Compaq",
- "iPAQ Linux",
- },
- {
- USB_VENDOR_COMPOSITE, USB_PRODUCT_COMPOSITE_USBPS2,
- 0,
- "Composite",
- "USB to PS2 Adaptor",
- },
- {
- USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_PRISM_GT,
- 0,
- "Conceptronic",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_C11U,
- 0,
- "Conceptronic",
- "C11U",
- },
- {
- USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_WL210,
- 0,
- "Conceptronic",
- "WL-210",
- },
- {
- USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_AR5523_1,
- 0,
- "Conceptronic",
- "AR5523",
- },
- {
- USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_AR5523_1_NF,
- 0,
- "Conceptronic",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_AR5523_2,
- 0,
- "Conceptronic",
- "AR5523",
- },
- {
- USB_VENDOR_CONCEPTRONIC, USB_PRODUCT_CONCEPTRONIC_AR5523_2_NF,
- 0,
- "Conceptronic",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU,
- 0,
- "Conceptronic",
- "C54RU WLAN",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_C54RU2,
- 0,
- "Conceptronic",
- "C54RU",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT3070_1,
- 0,
- "Conceptronic",
- "RT3070",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT3070_2,
- 0,
- "Conceptronic",
- "RT3070",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_VIGORN61,
- 0,
- "Conceptronic",
- "VIGORN61",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_1,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_2,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_7,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_8,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_3,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_4,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_5,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONCEPTRONIC2, USB_PRODUCT_CONCEPTRONIC2_RT2870_6,
- 0,
- "Conceptronic",
- "RT2870",
- },
- {
- USB_VENDOR_CONNECTIX, USB_PRODUCT_CONNECTIX_QUICKCAM,
- 0,
- "Connectix",
- "QuickCam",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T,
- 0,
- "Corega",
- "Ether USB-T",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TX,
- 0,
- "Corega",
- "FEther USB-TX",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLAN_USB_USB_11,
- 0,
- "Corega",
- "WirelessLAN USB-11",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXS,
- 0,
- "Corega",
- "FEther USB-TXS",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLANUSB,
- 0,
- "Corega",
- "Wireless LAN Stick-11",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB2_TX,
- 0,
- "Corega",
- "FEther USB2-TX",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLUSB_11_KEY,
- 0,
- "Corega",
- "ULUSB-11 Key",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGUSBRS232R,
- 0,
- "Corega",
- "CG-USBRS232R",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GL,
- 0,
- "Corega",
- "CG-WLUSB2GL",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB2GPX,
- 0,
- "Corega",
- "CG-WLUSB2GPX",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_RT2870_1,
- 0,
- "Corega",
- "RT2870",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_RT2870_2,
- 0,
- "Corega",
- "RT2870",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_RT2870_3,
- 0,
- "Corega",
- "RT2870",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_RT3070,
- 0,
- "Corega",
- "RT3070",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_CGWLUSB300GNM,
- 0,
- "Corega",
- "CG-WLUSB300GNM",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_WLUSB_11_STICK,
- 0,
- "Corega",
- "WLAN USB Stick 11",
- },
- {
- USB_VENDOR_COREGA, USB_PRODUCT_COREGA_FETHER_USB_TXC,
- 0,
- "Corega",
- "FEther USB-TXC",
- },
- {
- USB_VENDOR_CREATIVE, USB_PRODUCT_CREATIVE_NOMAD_II,
- 0,
- "Creative Labs",
- "Nomad II MP3 player",
- },
- {
- USB_VENDOR_CREATIVE, USB_PRODUCT_CREATIVE_NOMAD_IIMG,
- 0,
- "Creative Labs",
- "Nomad II MG",
- },
- {
- USB_VENDOR_CREATIVE, USB_PRODUCT_CREATIVE_NOMAD,
- 0,
- "Creative Labs",
- "Nomad",
- },
- {
- USB_VENDOR_CREATIVE2, USB_PRODUCT_CREATIVE2_VOIP_BLASTER,
- 0,
- "Creative Labs",
- "Voip Blaster",
- },
- {
- USB_VENDOR_CREATIVE3, USB_PRODUCT_CREATIVE3_OPTICAL_MOUSE,
- 0,
- "Creative Labs",
- "Notebook Optical Mouse",
- },
- {
- USB_VENDOR_CSR, USB_PRODUCT_CSR_BT_DONGLE,
- 0,
- "Cambridge Silicon Radio",
- "Bluetooth USB dongle",
- },
- {
- USB_VENDOR_CSR, USB_PRODUCT_CSR_CSRDFU,
- 0,
- "Cambridge Silicon Radio",
- "USB Bluetooth Device in DFU State",
- },
- {
- USB_VENDOR_CHIPSBANK, USB_PRODUCT_CHIPSBANK_USBMEMSTICK,
- 0,
- "Chipsbank Microelectronics Co.",
- "CBM2080 Flash drive controller",
- },
- {
- USB_VENDOR_CHIPSBANK, USB_PRODUCT_CHIPSBANK_USBMEMSTICK1,
- 0,
- "Chipsbank Microelectronics Co.",
- "CBM1180 Flash drive controller",
- },
- {
- USB_VENDOR_CTX, USB_PRODUCT_CTX_EX1300,
- 0,
- "Chuntex",
- "Ex1300 hub",
- },
- {
- USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_HX550C,
- 0,
- "Curitel Communications Inc",
- "CDMA 2000 1xRTT USB modem (HX-550C)",
- },
- {
- USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_HX57XB,
- 0,
- "Curitel Communications Inc",
- "CDMA 2000 1xRTT USB modem (HX-570/575B/PR-600)",
- },
- {
- USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_PC5740,
- 0,
- "Curitel Communications Inc",
- "Broadband Wireless modem",
- },
- {
- USB_VENDOR_CURITEL, USB_PRODUCT_CURITEL_UM175,
- 0,
- "Curitel Communications Inc",
- "EVDO modem",
- },
- {
- USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_1500CAVRLCD,
- 0,
- "Cyber Power Systems, Inc.",
- "1500CAVRLCD",
- },
- {
- USB_VENDOR_CYBERTAN, USB_PRODUCT_CYBERTAN_TG54USB,
- 0,
- "CyberTAN Technology",
- "TG54USB",
- },
- {
- USB_VENDOR_CYBERTAN, USB_PRODUCT_CYBERTAN_RT2870,
- 0,
- "CyberTAN Technology",
- "RT2870",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_MOUSE,
- 0,
- "Cypress Semiconductor",
- "mouse",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_THERMO,
- 0,
- "Cypress Semiconductor",
- "thermometer",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A,
- 0,
- "Cypress Semiconductor",
- "MetaGeek Wi-Spy",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_KBDHUB,
- 0,
- "Cypress Semiconductor",
- "Keyboard/Hub",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_FMRADIO,
- 0,
- "Cypress Semiconductor",
- "FM Radio",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_IKARILASER,
- 0,
- "Cypress Semiconductor",
- "Ikari Laser SteelSeries ApS",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_USBRS232,
- 0,
- "Cypress Semiconductor",
- "USB-RS232 Interface",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_SLIM_HUB,
- 0,
- "Cypress Semiconductor",
- "Slim Hub",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_XX6830XX,
- 0,
- "Cypress Semiconductor",
- "PATA Storage Device",
- },
- {
- USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_SILVERSHIELD,
- 0,
- "Cypress Semiconductor",
- "Gembird Silver Shield PM",
- },
- {
- USB_VENDOR_DAISY, USB_PRODUCT_DAISY_DMC,
- 0,
- "Daisy Technology",
- "USB MultiMedia Reader",
- },
- {
- USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,
- 0,
- "Dallas Semiconductor",
- "J-6502 speakers",
- },
- {
- USB_VENDOR_DATAAPEX, USB_PRODUCT_DATAAPEX_MULTICOM,
- 0,
- "DataApex",
- "MultiCom",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_PORT,
- 0,
- "Dell",
- "Port Replicator",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_AIO926,
- 0,
- "Dell",
- "Photo AIO Printer 926",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_BC02,
- 0,
- "Dell",
- "BC02 Bluetooth USB Adapter",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_PRISM_GT_1,
- 0,
- "Dell",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_TM350,
- 0,
- "Dell",
- "TrueMobile 350 Bluetooth USB Adapter",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_PRISM_GT_2,
- 0,
- "Dell",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5700,
- 0,
- "Dell",
- "Dell 5700 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5500,
- 0,
- "Dell",
- "Dell 5500 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5505,
- 0,
- "Dell",
- "Dell 5505 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5700_2,
- 0,
- "Dell",
- "Dell 5700 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5510,
- 0,
- "Dell",
- "Dell 5510 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5700_3,
- 0,
- "Dell",
- "Dell 5700 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5700_4,
- 0,
- "Dell",
- "Dell 5700 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5720,
- 0,
- "Dell",
- "Dell 5720 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5720_2,
- 0,
- "Dell",
- "Dell 5720 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U740,
- 0,
- "Dell",
- "Dell U740 CDMA",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5520,
- 0,
- "Dell",
- "Dell 5520 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5520_2,
- 0,
- "Dell",
- "Dell 5520 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5520_3,
- 0,
- "Dell",
- "Dell 5520 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5730,
- 0,
- "Dell",
- "Dell 5730 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5730_2,
- 0,
- "Dell",
- "Dell 5730 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_U5730_3,
- 0,
- "Dell",
- "Dell 5730 3G",
- },
- {
- USB_VENDOR_DELL, USB_PRODUCT_DELL_DW700,
- 0,
- "Dell",
- "Dell DW700 GPS",
- },
- {
- USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE,
- 0,
- "DeLorme",
- "Earthmate GPS",
- },
- {
- USB_VENDOR_DESKNOTE, USB_PRODUCT_DESKNOTE_UCR_61S2B,
- 0,
- "Desknote",
- "UCR-61S2B",
- },
- {
- USB_VENDOR_DIAMOND, USB_PRODUCT_DIAMOND_RIO500USB,
- 0,
- "Diamond",
- "Rio 500 USB",
- },
- {
- USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_RT2573,
- 0,
- "Dick Smith Electronics",
- "RT2573",
- },
- {
- USB_VENDOR_DICKSMITH, USB_PRODUCT_DICKSMITH_CWD854F,
- 0,
- "Dick Smith Electronics",
- "C-Net CWD-854 rev F",
- },
- {
- USB_VENDOR_DIGI, USB_PRODUCT_DIGI_ACCELEPORT2,
- 0,
- "Digi International",
- "AccelePort USB 2",
- },
- {
- USB_VENDOR_DIGI, USB_PRODUCT_DIGI_ACCELEPORT4,
- 0,
- "Digi International",
- "AccelePort USB 4",
- },
- {
- USB_VENDOR_DIGI, USB_PRODUCT_DIGI_ACCELEPORT8,
- 0,
- "Digi International",
- "AccelePort USB 8",
- },
- {
- USB_VENDOR_DIGIANSWER, USB_PRODUCT_DIGIANSWER_ZIGBEE802154,
- 0,
- "Digianswer",
- "ZigBee/802.15.4 MAC",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100,
- 0,
- "D-Link",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX4,
- 0,
- "D-Link",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL120E,
- 0,
- "D-Link",
- "DWL-120 rev E",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL122,
- 0,
- "D-Link",
- "DWL-122",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG120,
- 0,
- "D-Link",
- "DWL-G120",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWL120F,
- 0,
- "D-Link",
- "DWL-120 rev F",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLAG132,
- 0,
- "D-Link",
- "DWL-AG132",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLAG132_NF,
- 0,
- "D-Link",
- "DWL-AG132 (no firmware)",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG132,
- 0,
- "D-Link",
- "DWL-G132",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG132_NF,
- 0,
- "D-Link",
- "DWL-G132 (no firmware)",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLAG122,
- 0,
- "D-Link",
- "DWL-AG122",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLAG122_NF,
- 0,
- "D-Link",
- "DWL-AG122 (no firmware)",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DWLG122,
- 0,
- "D-Link",
- "DWL-G122 b1 Wireless Adapter",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBE100B1,
- 0,
- "D-Link",
- "DUB-E100 rev B1",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RT2870,
- 0,
- "D-Link",
- "RT2870",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_RT3072,
- 0,
- "D-Link",
- "RT3072",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C,
- 0,
- "D-Link",
- "10Mbps Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX1,
- 0,
- "D-Link",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX,
- 0,
- "D-Link",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX_PNA,
- 0,
- "D-Link",
- "1/10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX3,
- 0,
- "D-Link",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650TX2,
- 0,
- "D-Link",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650,
- 0,
- "D-Link",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DUBH7,
- 0,
- "D-Link",
- "DUB-H7 USB 2.0 7-Port Hub",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA120,
- 0,
- "D-Link",
- "DWA-120",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA120_NF,
- 0,
- "D-Link",
- "DWA-120 (no firmware)",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWLG122C1,
- 0,
- "D-Link",
- "DWL-G122 c1",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_WUA1340,
- 0,
- "D-Link",
- "WUA-1340",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA111,
- 0,
- "D-Link",
- "DWA-111",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT2870_1,
- 0,
- "D-Link",
- "RT2870",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA110,
- 0,
- "D-Link",
- "DWA-110",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT3072,
- 0,
- "D-Link",
- "RT3072",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT3072_1,
- 0,
- "D-Link",
- "RT3072",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT3070_1,
- 0,
- "D-Link",
- "RT3070",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT3070_2,
- 0,
- "D-Link",
- "RT3070",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT3070_3,
- 0,
- "D-Link",
- "RT3070",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT2870_2,
- 0,
- "D-Link",
- "RT2870",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_DWA130,
- 0,
- "D-Link",
- "DWA-130",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT3070_4,
- 0,
- "D-Link",
- "RT3070",
- },
- {
- USB_VENDOR_DLINK2, USB_PRODUCT_DLINK2_RT3070_5,
- 0,
- "D-Link",
- "RT3070",
- },
- {
- USB_VENDOR_DLINK3, USB_PRODUCT_DLINK3_DWM652,
- 0,
- "Dlink",
- "DWM-652",
- },
- {
- USB_VENDOR_DMI, USB_PRODUCT_DMI_CFSM_RW,
- 0,
- "DMI",
- "CF/SM Reader/Writer",
- },
- {
- USB_VENDOR_DMI, USB_PRODUCT_DMI_DISK,
- 0,
- "DMI",
- "Generic Disk",
- },
- {
- USB_VENDOR_DRAYTEK, USB_PRODUCT_DRAYTEK_VIGOR550,
- 0,
- "DrayTek",
- "Vigor550",
- },
- {
- USB_VENDOR_DRESDENELEKTRONIK, USB_PRODUCT_DRESDENELEKTRONIK_SENSORTERMINALBOARD,
- 0,
- "dresden elektronik",
- "SensorTerminalBoard",
- },
- {
- USB_VENDOR_DRESDENELEKTRONIK, USB_PRODUCT_DRESDENELEKTRONIK_WIRELESSHANDHELDTERMINAL,
- 0,
- "dresden elektronik",
- "Wireless Handheld Terminal",
- },
- {
- USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANTDEVBOARD,
- 0,
- "Dynastream Innovations",
- "ANT dev board",
- },
- {
- USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANT2USB,
- 0,
- "Dynastream Innovations",
- "ANT2USB",
- },
- {
- USB_VENDOR_DYNASTREAM, USB_PRODUCT_DYNASTREAM_ANTDEVBOARD2,
- 0,
- "Dynastream Innovations",
- "ANT dev board",
- },
- {
- USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_EW7318USG,
- 0,
- "Edimax",
- "USB Wireless dongle",
- },
- {
- USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_RT2870_1,
- 0,
- "Edimax",
- "RT2870",
- },
- {
- USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_EW7717,
- 0,
- "Edimax",
- "EW-7717",
- },
- {
- USB_VENDOR_EDIMAX, USB_PRODUCT_EDIMAX_EW7718,
- 0,
- "Edimax",
- "EW-7718",
- },
- {
- USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL,
- 0,
- "eGalax, Inc.",
- "Touch Panel",
- },
- {
- USB_VENDOR_EGALAX, USB_PRODUCT_EGALAX_TPANEL2,
- 0,
- "eGalax, Inc.",
- "Touch Panel",
- },
- {
- USB_VENDOR_EGALAX2, USB_PRODUCT_EGALAX2_TPANEL,
- 0,
- "eGalax, Inc.",
- "Touch Panel",
- },
- {
- USB_VENDOR_EICON, USB_PRODUCT_EICON_DIVA852,
- 0,
- "Eicon Networks",
- "Diva 852 ISDN TA",
- },
- {
- USB_VENDOR_EIZO, USB_PRODUCT_EIZO_HUB,
- 0,
- "EIZO",
- "hub",
- },
- {
- USB_VENDOR_EIZO, USB_PRODUCT_EIZO_MONITOR,
- 0,
- "EIZO",
- "monitor",
- },
- {
- USB_VENDOR_ELCON, USB_PRODUCT_ELCON_PLAN,
- 0,
- "ELCON Systemtechnik",
- "Goldpfeil P-LAN",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_MOUSE29UO,
- 0,
- "Elecom",
- "mouse 29UO",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX0,
- 0,
- "Elecom",
- "LD-USB/TX",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX1,
- 0,
- "Elecom",
- "LD-USB/TX",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBLTX,
- 0,
- "Elecom",
- "LD-USBL/TX",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX2,
- 0,
- "Elecom",
- "LD-USB/TX",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSB20,
- 0,
- "Elecom",
- "LD-USB20",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT,
- 0,
- "Elecom",
- "UC-SGT",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_UCSGT0,
- 0,
- "Elecom",
- "UC-SGT",
- },
- {
- USB_VENDOR_ELECOM, USB_PRODUCT_ELECOM_LDUSBTX3,
- 0,
- "Elecom",
- "LD-USB/TX",
- },
- {
- USB_VENDOR_ELSA, USB_PRODUCT_ELSA_MODEM1,
- 0,
- "ELSA",
- "ELSA Modem Board",
- },
- {
- USB_VENDOR_ELSA, USB_PRODUCT_ELSA_USB2ETHERNET,
- 0,
- "ELSA",
- "Microlink USB2Ethernet",
- },
- {
- USB_VENDOR_ELV, USB_PRODUCT_ELV_USBI2C,
- 0,
- "ELV",
- "USB-I2C interface",
- },
- {
- USB_VENDOR_EMS, USB_PRODUCT_EMS_DUAL_SHOOTER,
- 0,
- "EMS Production",
- "PSX gun controller converter",
- },
- {
- USB_VENDOR_ENCORE, USB_PRODUCT_ENCORE_RT3070_1,
- 0,
- "Encore",
- "RT3070",
- },
- {
- USB_VENDOR_ENCORE, USB_PRODUCT_ENCORE_RT3070_2,
- 0,
- "Encore",
- "RT3070",
- },
- {
- USB_VENDOR_ENCORE, USB_PRODUCT_ENCORE_RT3070_3,
- 0,
- "Encore",
- "RT3070",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_1S,
- 0,
- "Entrega",
- "1S serial",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_2S,
- 0,
- "Entrega",
- "2S serial",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_1S25,
- 0,
- "Entrega",
- "1S25 serial",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_4S,
- 0,
- "Entrega",
- "4S serial",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45,
- 0,
- "Entrega",
- "E45 Ethernet",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_CENTRONICS,
- 0,
- "Entrega",
- "Parallel Port",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX1,
- 0,
- "Entrega",
- "Ethernet",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_1S9,
- 0,
- "Entrega",
- "1S9 serial",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_EZUSB,
- 0,
- "Entrega",
- "EZ-USB",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_2U4S,
- 0,
- "Entrega",
- "2U4S serial/usb hub",
- },
- {
- USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX2,
- 0,
- "Entrega",
- "Ethernet",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_PRINTER1,
- 0,
- "Seiko Epson",
- "USB Printer",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_PRINTER2,
- 0,
- "Seiko Epson",
- "ISD USB Smart Cable for Mac",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_PRINTER3,
- 0,
- "Seiko Epson",
- "ISD USB Smart Cable",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_PRINTER5,
- 0,
- "Seiko Epson",
- "USB Printer",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_636,
- 0,
- "Seiko Epson",
- "Perfection 636U / 636Photo scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_610,
- 0,
- "Seiko Epson",
- "Perfection 610 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1200,
- 0,
- "Seiko Epson",
- "Perfection 1200U / 1200Photo scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1600,
- 0,
- "Seiko Epson",
- "Expression 1600 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1640,
- 0,
- "Seiko Epson",
- "Perfection 1640SU scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1240,
- 0,
- "Seiko Epson",
- "Perfection 1240U / 1240Photo scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_640U,
- 0,
- "Seiko Epson",
- "Perfection 640U scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1250,
- 0,
- "Seiko Epson",
- "Perfection 1250U / 1250Photo scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1650,
- 0,
- "Seiko Epson",
- "Perfection 1650 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9700F,
- 0,
- "Seiko Epson",
- "GT-9700F scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_GT9300UF,
- 0,
- "Seiko Epson",
- "GT-9300UF scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3200,
- 0,
- "Seiko Epson",
- "Perfection 3200 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1260,
- 0,
- "Seiko Epson",
- "Perfection 1260 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1660,
- 0,
- "Seiko Epson",
- "Perfection 1660 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1670,
- 0,
- "Seiko Epson",
- "Perfection 1670 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_1270,
- 0,
- "Seiko Epson",
- "Perfection 1270 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_2480,
- 0,
- "Seiko Epson",
- "Perfection 2480 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3590,
- 0,
- "Seiko Epson",
- "Perfection 3590 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4990,
- 0,
- "Seiko Epson",
- "Perfection 4990 Photo scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_CRESSI_EDY,
- 0,
- "Seiko Epson",
- "Cressi Edy diving computer",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_875DC,
- 0,
- "Seiko Epson",
- "Stylus Photo 875DC Card Reader",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_STYLUS_895,
- 0,
- "Seiko Epson",
- "Stylus Photo 895 Card Reader",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_CX5400,
- 0,
- "Seiko Epson",
- "CX5400 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_3500,
- 0,
- "Seiko Epson",
- "CX-3500/3600/3650 MFP",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_RX425,
- 0,
- "Seiko Epson",
- "Stylus Photo RX425 scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX3800,
- 0,
- "Seiko Epson",
- "CX3700/CX3800/DX38x0 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4800,
- 0,
- "Seiko Epson",
- "CX4700/CX4800/DX48x0 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_4200,
- 0,
- "Seiko Epson",
- "CX4100/CX4200/DX4200 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_5000,
- 0,
- "Seiko Epson",
- "CX4900/CX5000/DX50x0 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_6000,
- 0,
- "Seiko Epson",
- "CX5900/CX6000/DX60x0 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX4000,
- 0,
- "Seiko Epson",
- "DX4000 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX7400,
- 0,
- "Seiko Epson",
- "CX7300/CX7400/DX7400 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_DX8400,
- 0,
- "Seiko Epson",
- "CX8300/CX8400/DX8400 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_SX100,
- 0,
- "Seiko Epson",
- "SX100/NX100 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_NX300,
- 0,
- "Seiko Epson",
- "NX300 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_SX200,
- 0,
- "Seiko Epson",
- "SX200/SX205 MFP scanner",
- },
- {
- USB_VENDOR_EPSON, USB_PRODUCT_EPSON_SX400,
- 0,
- "Seiko Epson",
- "SX400/NX400/TX400 MFP scanner",
- },
- {
- USB_VENDOR_ETEK, USB_PRODUCT_ETEK_1COM,
- 0,
- "e-TEK Labs",
- "Serial",
- },
- {
- USB_VENDOR_EXTENDED, USB_PRODUCT_EXTENDED_XTNDACCESS,
- 0,
- "Extended Systems",
- "XTNDAccess IrDA",
- },
- {
- USB_VENDOR_FEIYA, USB_PRODUCT_FEIYA_5IN1,
- 0,
- "Feiya",
- "5-in-1 Card Reader",
- },
- {
- USB_VENDOR_FIBERLINE, USB_PRODUCT_FIBERLINE_WL430U,
- 0,
- "Fiberline",
- "WL-430U",
- },
- {
- USB_VENDOR_FOSSIL, USB_PRODUCT_FOSSIL_WRISTPDA,
- 0,
- "Fossil, Inc",
- "Wrist PDA",
- },
- {
- USB_VENDOR_FOXCONN, USB_PRODUCT_FOXCONN_PIRELLI_DP_L10,
- 0,
- "Foxconn",
- "Pirelli DP-L10",
- },
- {
- USB_VENDOR_FREECOM, USB_PRODUCT_FREECOM_DVD,
- 0,
- "Freecom",
- "DVD drive",
- },
- {
- USB_VENDOR_FREECOM, USB_PRODUCT_FREECOM_HDD,
- 0,
- "Freecom",
- "Classic SL Hard Drive",
- },
- {
- USB_VENDOR_FSC, USB_PRODUCT_FSC_E5400,
- 0,
- "Fujitsu Siemens Computers",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_8U100AX,
- 0,
- "Future Technology Devices",
- "8U100AX Serial",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_8U232AM,
- 0,
- "Future Technology Devices",
- "8U232AM Serial",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_8U232AM4,
- 0,
- "Future Technology Devices",
- "8U232AM Serial",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_2232C,
- 0,
- "Future Technology Devices",
- "FT2232C Dual port Serial",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_2232D,
- 0,
- "Future Technology Devices",
- "FT2232D Dual port Serial",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SERIAL_4232H,
- 0,
- "Future Technology Devices",
- "FT4232H Quad port Serial",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13M,
- 0,
- "Future Technology Devices",
- "OpenPort 1.3 Mitsubishi",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13S,
- 0,
- "Future Technology Devices",
- "OpenPort 1.3 Subaru",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_TACTRIX_OPENPORT_13U,
- 0,
- "Future Technology Devices",
- "OpenPort 1.3 Universal",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_GAMMASCOUT,
- 0,
- "Future Technology Devices",
- "Gamma-Scout",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_KBS,
- 0,
- "Future Technology Devices",
- "Pyramid KBS USB LCD",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_EISCOU,
- 0,
- "Future Technology Devices",
- "Expert ISDN Control USB",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_UOPTBR,
- 0,
- "Future Technology Devices",
- "USB-RS232 OptoBridge",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_EMCU2D,
- 0,
- "Future Technology Devices",
- "Expert mouseCLOCK USB II",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_PCMSFU,
- 0,
- "Future Technology Devices",
- "Precision Clock MSF USB",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_EMCU2H,
- 0,
- "Future Technology Devices",
- "Expert mouseCLOCK USB II HBG",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MAXSTREAM,
- 0,
- "Future Technology Devices",
- "Maxstream PKG-U",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_USB_UIRT,
- 0,
- "Future Technology Devices",
- "USB-UIRT",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_USBSERIAL,
- 0,
- "Future Technology Devices",
- "Matrix Orbital USB Serial",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MX2_3,
- 0,
- "Future Technology Devices",
- "Matrix Orbital MX2 or MX3",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_MX4_5,
- 0,
- "Future Technology Devices",
- "Matrix Orbital MX4 or MX5",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_LK202,
- 0,
- "Future Technology Devices",
- "Matrix Orbital VK/LK202 Family",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_LK204,
- 0,
- "Future Technology Devices",
- "Matrix Orbital VK/LK204 Family",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CFA_632,
- 0,
- "Future Technology Devices",
- "Crystalfontz CFA-632 USB LCD",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CFA_634,
- 0,
- "Future Technology Devices",
- "Crystalfontz CFA-634 USB LCD",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CFA_633,
- 0,
- "Future Technology Devices",
- "Crystalfontz CFA-633 USB LCD",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CFA_631,
- 0,
- "Future Technology Devices",
- "Crystalfontz CFA-631 USB LCD",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CFA_635,
- 0,
- "Future Technology Devices",
- "Crystalfontz CFA-635 USB LCD",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_SEMC_DSS20,
- 0,
- "Future Technology Devices",
- "SEMC DSS-20 SyncStation",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CTI_USB_NANO_485,
- 0,
- "Future Technology Devices",
- "CTI USB-Nano 485",
- },
- {
- USB_VENDOR_FTDI, USB_PRODUCT_FTDI_CTI_USB_MINI_485,
- 0,
- "Future Technology Devices",
- "CTI USB-Mini 485",
- },
- {
- USB_VENDOR_FUJIPHOTO, USB_PRODUCT_FUJIPHOTO_MASS0100,
- 0,
- "Fuji Photo Film",
- "Mass Storage",
- },
- {
- USB_VENDOR_FUJITSU, USB_PRODUCT_FUJITSU_AH_F401U,
- 0,
- "Fujitsu",
- "AH-F401U Air H device",
- },
- {
- USB_VENDOR_FUJITSUSIEMENS, USB_PRODUCT_FUJITSUSIEMENS_SCR,
- 0,
- "Fujitsu-Siemens",
- "Fujitsu-Siemens SCR USB Reader",
- },
- {
- USB_VENDOR_GARMIN, USB_PRODUCT_GARMIN_IQUE_3600,
- 0,
- "Garmin International",
- "iQue 3600",
- },
- {
- USB_VENDOR_GEMALTO, USB_PRODUCT_GEMALTO_PROXPU,
- 0,
- "Gemalto SA",
- "Prox-PU/CU",
- },
- {
- USB_VENDOR_GENERALINSTMNTS, USB_PRODUCT_GENERALINSTMNTS_SB5100,
- 0,
- "General Instruments (Motorola)",
- "SURFboard SB5100 Cable modem",
- },
- {
- USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL620USB,
- 0,
- "Genesys Logic",
- "GL620USB Host-Host interface",
- },
- {
- USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL650,
- 0,
- "Genesys Logic",
- "GL650 HUB",
- },
- {
- USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL606,
- 0,
- "Genesys Logic",
- "USB 2.0 HUB",
- },
- {
- USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB,
- 0,
- "Genesys Logic",
- "GL641USB CompactFlash Card Reader",
- },
- {
- USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE_2,
- 0,
- "Genesys Logic",
- "GL641USB USB-IDE Bridge No 2",
- },
- {
- USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB2IDE,
- 0,
- "Genesys Logic",
- "GL641USB USB-IDE Bridge",
- },
- {
- USB_VENDOR_GENESYS, USB_PRODUCT_GENESYS_GL641USB_2,
- 0,
- "Genesys Logic",
- "GL641USB 6-in-1 Card Reader",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GN54G,
- 0,
- "GIGABYTE",
- "GN-54G",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNBR402W,
- 0,
- "GIGABYTE",
- "GN-BR402W",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWLBM101,
- 0,
- "GIGABYTE",
- "GN-WLBM101",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWBKG,
- 0,
- "GIGABYTE",
- "GN-WBKG",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB01GS,
- 0,
- "GIGABYTE",
- "GN-WB01GS",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWI05GS,
- 0,
- "GIGABYTE",
- "GN-WI05GS",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_WLAN,
- 0,
- "Gigaset",
- "WLAN",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_SMCWUSBTG,
- 0,
- "Gigaset",
- "SMCWUSBT-G",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_SMCWUSBTG_NF,
- 0,
- "Gigaset",
- "SMCWUSBT-G (no firmware)",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_AR5523,
- 0,
- "Gigaset",
- "AR5523",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_AR5523_NF,
- 0,
- "Gigaset",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT2573,
- 0,
- "Gigaset",
- "RT2573",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT3070_1,
- 0,
- "Gigaset",
- "RT3070",
- },
- {
- USB_VENDOR_GIGASET, USB_PRODUCT_GIGASET_RT3070_2,
- 0,
- "Gigaset",
- "RT3070",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_RT2870_1,
- 0,
- "GIGABYTE",
- "RT2870",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB31N,
- 0,
- "GIGABYTE",
- "GN-WB31N",
- },
- {
- USB_VENDOR_GIGABYTE, USB_PRODUCT_GIGABYTE_GNWB32L,
- 0,
- "GIGABYTE",
- "GN-WB32L",
- },
- {
- USB_VENDOR_GLOBALSUN, USB_PRODUCT_GLOBALSUN_AR5523_1,
- 0,
- "Global Sun Technology",
- "AR5523",
- },
- {
- USB_VENDOR_GLOBALSUN, USB_PRODUCT_GLOBALSUN_AR5523_1_NF,
- 0,
- "Global Sun Technology",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_GLOBALSUN, USB_PRODUCT_GLOBALSUN_AR5523_2,
- 0,
- "Global Sun Technology",
- "AR5523",
- },
- {
- USB_VENDOR_GLOBALSUN, USB_PRODUCT_GLOBALSUN_AR5523_2_NF,
- 0,
- "Global Sun Technology",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_PRISM_GT_1,
- 0,
- "Globespan",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_GLOBESPAN, USB_PRODUCT_GLOBESPAN_PRISM_GT_2,
- 0,
- "Globespan",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00,
- 0,
- "G.Mate, Inc",
- "YP3X00 PDA",
- },
- {
- USB_VENDOR_GOHUBS, USB_PRODUCT_GOHUBS_GOCOM232,
- 0,
- "GoHubs",
- "GoCOM232 Serial",
- },
- {
- USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_GWUSB2E,
- 0,
- "Good Way Technology",
- "GWUSB2E",
- },
- {
- USB_VENDOR_GOODWAY, USB_PRODUCT_GOODWAY_RT2573,
- 0,
- "Good Way Technology",
- "RT2573",
- },
- {
- USB_VENDOR_GOOGLE, USB_PRODUCT_GOOGLE_NEXUSONE,
- 0,
- "Google",
- "Nexus One",
- },
- {
- USB_VENDOR_GRAVIS, USB_PRODUCT_GRAVIS_GAMEPADPRO,
- 0,
- "Advanced Gravis Computer",
- "GamePad Pro",
- },
- {
- USB_VENDOR_GREENHOUSE, USB_PRODUCT_GREENHOUSE_KANA21,
- 0,
- "GREENHOUSE",
- "CF-writer with MP3",
- },
- {
- USB_VENDOR_GRIFFIN, USB_PRODUCT_GRIFFIN_IMATE,
- 0,
- "Griffin Technology",
- "iMate, ADB Adapter",
- },
- {
- USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_DALEADER,
- 0,
- "Guillemot",
- "DA Leader",
- },
- {
- USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254,
- 0,
- "Guillemot",
- "HWGUSB2-54 WLAN",
- },
- {
- USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254LB,
- 0,
- "Guillemot",
- "HWGUSB2-54-LB",
- },
- {
- USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWGUSB254V2AP,
- 0,
- "Guillemot",
- "HWGUSB2-54V2-AP",
- },
- {
- USB_VENDOR_GUILLEMOT, USB_PRODUCT_GUILLEMOT_HWNU300,
- 0,
- "Guillemot",
- "HWNU-300",
- },
- {
- USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FGSM,
- 0,
- "Hagiwara Sys-Com",
- "FlashGate SmartMedia Card Reader",
- },
- {
- USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FGCF,
- 0,
- "Hagiwara Sys-Com",
- "FlashGate CompactFlash Card Reader",
- },
- {
- USB_VENDOR_HAGIWARA, USB_PRODUCT_HAGIWARA_FG,
- 0,
- "Hagiwara Sys-Com",
- "FlashGate",
- },
- {
- USB_VENDOR_HAL, USB_PRODUCT_HAL_IMR001,
- 0,
- "HAL Corporation",
- "Crossam2+USB IR commander",
- },
- {
- USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_VISOR,
- 0,
- "Handspring",
- "Handspring Visor",
- },
- {
- USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO,
- 0,
- "Handspring",
- "Handspring Treo",
- },
- {
- USB_VENDOR_HANDSPRING, USB_PRODUCT_HANDSPRING_TREO600,
- 0,
- "Handspring",
- "Handspring Treo 600",
- },
- {
- USB_VENDOR_HAUPPAUGE, USB_PRODUCT_HAUPPAUGE_WINTV_USB_FM,
- 0,
- "Hauppauge Computer Works",
- "WinTV USB FM",
- },
- {
- USB_VENDOR_HAUPPAUGE2, USB_PRODUCT_HAUPPAUGE2_NOVAT500,
- 0,
- "Hauppauge Computer Works",
- "NovaT 500Stick",
- },
- {
- USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_RT2870_1,
- 0,
- "Hawking",
- "RT2870",
- },
- {
- USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_RT2870_2,
- 0,
- "Hawking",
- "RT2870",
- },
- {
- USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_HWUN2,
- 0,
- "Hawking",
- "HWUN2",
- },
- {
- USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_RT3070,
- 0,
- "Hawking",
- "RT3070",
- },
- {
- USB_VENDOR_HAWKING, USB_PRODUCT_HAWKING_UF100,
- 0,
- "Hawking",
- "10/100 USB Ethernet",
- },
- {
- USB_VENDOR_HIDGLOBAL, USB_PRODUCT_HIDGLOBAL_CM2020,
- 0,
- "HID Global",
- "Omnikey Cardman 2020",
- },
- {
- USB_VENDOR_HIDGLOBAL, USB_PRODUCT_HIDGLOBAL_CM6020,
- 0,
- "HID Global",
- "Omnikey Cardman 6020",
- },
- {
- USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_DZ_MV100A,
- 0,
- "Hitachi",
- "DVD-CAM DZ-MV100A Camcorder",
- },
- {
- USB_VENDOR_HITACHI, USB_PRODUCT_HITACHI_DVDCAM_USB,
- 0,
- "Hitachi",
- "DVDCAM USB HS Interface",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_895C,
- 0,
- "Hewlett Packard",
- "DeskJet 895C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_4100C,
- 0,
- "Hewlett Packard",
- "Scanjet 4100C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_S20,
- 0,
- "Hewlett Packard",
- "Photosmart S20",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_880C,
- 0,
- "Hewlett Packard",
- "DeskJet 880C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_4200C,
- 0,
- "Hewlett Packard",
- "ScanJet 4200C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_CDWRITERPLUS,
- 0,
- "Hewlett Packard",
- "CD-Writer Plus",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_KBDHUB,
- 0,
- "Hewlett Packard",
- "Multimedia Keyboard Hub",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_G55XI,
- 0,
- "Hewlett Packard",
- "OfficeJet G55xi",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_HN210W,
- 0,
- "Hewlett Packard",
- "HN210W 802.11b WLAN",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_49GPLUS,
- 0,
- "Hewlett Packard",
- "49g+ graphing calculator",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_6200C,
- 0,
- "Hewlett Packard",
- "ScanJet 6200C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_S20b,
- 0,
- "Hewlett Packard",
- "PhotoSmart S20",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_815C,
- 0,
- "Hewlett Packard",
- "DeskJet 815C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_3300C,
- 0,
- "Hewlett Packard",
- "ScanJet 3300C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_CDW8200,
- 0,
- "Hewlett Packard",
- "CD-Writer Plus 8200e",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_MMKEYB,
- 0,
- "Hewlett Packard",
- "Multimedia keyboard",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_1220C,
- 0,
- "Hewlett Packard",
- "DeskJet 1220C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_810C,
- 0,
- "Hewlett Packard",
- "DeskJet 810C/812C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_4300C,
- 0,
- "Hewlett Packard",
- "Scanjet 4300C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_CDW4E,
- 0,
- "Hewlett Packard",
- "CD-Writer+ CD-4e",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_G85XI,
- 0,
- "Hewlett Packard",
- "OfficeJet G85xi",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_1200,
- 0,
- "Hewlett Packard",
- "LaserJet 1200",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_5200C,
- 0,
- "Hewlett Packard",
- "Scanjet 5200C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_830C,
- 0,
- "Hewlett Packard",
- "DeskJet 830C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_3400CSE,
- 0,
- "Hewlett Packard",
- "ScanJet 3400cse",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_6300C,
- 0,
- "Hewlett Packard",
- "Scanjet 6300C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_840C,
- 0,
- "Hewlett Packard",
- "DeskJet 840c",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_2200C,
- 0,
- "Hewlett Packard",
- "ScanJet 2200C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_5300C,
- 0,
- "Hewlett Packard",
- "Scanjet 5300C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_4400C,
- 0,
- "Hewlett Packard",
- "Scanjet 4400C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_4470C,
- 0,
- "Hewlett Packard",
- "Scanjet 4470C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_82x0C,
- 0,
- "Hewlett Packard",
- "Scanjet 82x0C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_2300D,
- 0,
- "Hewlett Packard",
- "Laserjet 2300d",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_970CSE,
- 0,
- "Hewlett Packard",
- "Deskjet 970Cse",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_5400C,
- 0,
- "Hewlett Packard",
- "Scanjet 5400C",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_2215,
- 0,
- "Hewlett Packard",
- "iPAQ 22xx/Jornada 548",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_568J,
- 0,
- "Hewlett Packard",
- "Jornada 568",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_930C,
- 0,
- "Hewlett Packard",
- "DeskJet 930c",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_P2000U,
- 0,
- "Hewlett Packard",
- "Inkjet P-2000U",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_HS2300,
- 0,
- "Hewlett Packard",
- "HS2300 HSDPA (aka MC8775)",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_640C,
- 0,
- "Hewlett Packard",
- "DeskJet 640c",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_4670V,
- 0,
- "Hewlett Packard",
- "ScanJet 4670v",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_P1100,
- 0,
- "Hewlett Packard",
- "Photosmart P1100",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_LD220,
- 0,
- "Hewlett Packard",
- "LD220 POS Display",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_OJ4215,
- 0,
- "Hewlett Packard",
- "OfficeJet 4215",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_HN210E,
- 0,
- "Hewlett Packard",
- "Ethernet HN210E",
- },
- {
- USB_VENDOR_HP2, USB_PRODUCT_HP2_C500,
- 0,
- "Hewlett Packard",
- "PhotoSmart C500",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_EV2200,
- 0,
- "Hewlett Packard",
- "ev2200 HSDPA (aka MC5720)",
- },
- {
- USB_VENDOR_HP, USB_PRODUCT_HP_HS2300,
- 0,
- "Hewlett Packard",
- "hs2300 HSDPA (aka MC8775)",
- },
- {
- USB_VENDOR_HTC, USB_PRODUCT_HTC_WINMOBILE,
- 0,
- "HTC",
- "HTC USB Sync",
- },
- {
- USB_VENDOR_HTC, USB_PRODUCT_HTC_PPC6700MODEM,
- 0,
- "HTC",
- "PPC6700 Modem",
- },
- {
- USB_VENDOR_HTC, USB_PRODUCT_HTC_SMARTPHONE,
- 0,
- "HTC",
- "SmartPhone USB Sync",
- },
- {
- USB_VENDOR_HTC, USB_PRODUCT_HTC_WIZARD,
- 0,
- "HTC",
- "HTC Wizard USB Sync",
- },
- {
- USB_VENDOR_HTC, USB_PRODUCT_HTC_LEGENDSYNC,
- 0,
- "HTC",
- "HTC Legend USB Sync",
- },
- {
- USB_VENDOR_HTC, USB_PRODUCT_HTC_LEGEND,
- 0,
- "HTC",
- "HTC Legend",
- },
- {
- USB_VENDOR_HTC, USB_PRODUCT_HTC_LEGENDINTERNET,
- 0,
- "HTC",
- "HTC Legend Internet Sharing",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_MOBILE,
- 0,
- "Huawei Technologies",
- "Huawei Mobile",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220,
- 0,
- "Huawei Technologies",
- "HSDPA modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E220BIS,
- 0,
- "Huawei Technologies",
- "HSDPA modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1401,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1402,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1403,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1404,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1405,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1406,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1407,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1408,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1409,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E140A,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E140B,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E180V,
- 0,
- "Huawei Technologies",
- "E180V",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E140D,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E140E,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E140F,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1410,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1411,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1412,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1413,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1414,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1415,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1416,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1417,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1418,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1419,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E141A,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E141B,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E141C,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E141D,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E141E,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E141F,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1420,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1421,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1422,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1423,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1424,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1425,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1426,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1427,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1428,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1429,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E142A,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E142B,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E142C,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E142D,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E142E,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E142F,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1430,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1431,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1432,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1433,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1434,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1435,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1436,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1437,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1438,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1439,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E143A,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E143B,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E143C,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E143D,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E143E,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E143F,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1752,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3765,
- 0,
- "Huawei Technologies",
- "3G modem",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_E1820,
- 0,
- "Huawei Technologies",
- "E1820 HSPA+ USB Slider",
- },
- {
- USB_VENDOR_HUAWEI, USB_PRODUCT_HUAWEI_K3765_INIT,
- 0,
- "Huawei Technologies",
- "K3765 Initial",
- },
- {
- USB_VENDOR_HUAWEI3COM, USB_PRODUCT_HUAWEI3COM_WUB320G,
- 0,
- "Huawei-3Com",
- "Aolynk WUB320g",
- },
- {
- USB_VENDOR_IBM, USB_PRODUCT_IBM_USBCDROMDRIVE,
- 0,
- "IBM",
- "USB CD-ROM Drive",
- },
- {
- USB_VENDOR_IMAGINATION, USB_PRODUCT_IMAGINATION_DBX1,
- 0,
- "Imagination Technologies",
- "DBX1 DSP core",
- },
- {
- USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4,
- 0,
- "Inside Out Networks",
- "EdgePort/4 serial ports",
- },
- {
- USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_F5U002,
- 0,
- "In-System Design",
- "Parallel printer",
- },
- {
- USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ATAPI,
- 0,
- "In-System Design",
- "ATAPI Adapter",
- },
- {
- USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ISD110,
- 0,
- "In-System Design",
- "IDE Adapter ISD110",
- },
- {
- USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_ISD105,
- 0,
- "In-System Design",
- "IDE Adapter ISD105",
- },
- {
- USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_USBCABLE,
- 0,
- "In-System Design",
- "USB cable",
- },
- {
- USB_VENDOR_INSYSTEM, USB_PRODUCT_INSYSTEM_STORAGE_V2,
- 0,
- "In-System Design",
- "USB Storage Adapter V2",
- },
- {
- USB_VENDOR_INTEL, USB_PRODUCT_INTEL_EASYPC_CAMERA,
- 0,
- "Intel",
- "Easy PC Camera",
- },
- {
- USB_VENDOR_INTEL, USB_PRODUCT_INTEL_TESTBOARD,
- 0,
- "Intel",
- "82930 test board",
- },
- {
- USB_VENDOR_INTEL2, USB_PRODUCT_INTEL2_IRMH,
- 0,
- "Intel",
- "Integrated Rate Matching Hub",
- },
- {
- USB_VENDOR_INTERSIL, USB_PRODUCT_INTERSIL_PRISM_GT,
- 0,
- "Intersil",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_INTERSIL, USB_PRODUCT_INTERSIL_PRISM_2X,
- 0,
- "Intersil",
- "Prism2.x or Atmel WLAN",
- },
- {
- USB_VENDOR_INTREPIDCS, USB_PRODUCT_INTREPIDCS_VALUECAN,
- 0,
- "Intrepid",
- "ValueCAN CAN bus interface",
- },
- {
- USB_VENDOR_INTREPIDCS, USB_PRODUCT_INTREPIDCS_NEOVI,
- 0,
- "Intrepid",
- "NeoVI Blue vehicle bus interface",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_IU_CD2,
- 0,
- "I-O Data",
- "DVD Multi-plus unit iU-CD2",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_DVR_UEH8,
- 0,
- "I-O Data",
- "DVD Multi-plus unit DVR-UEH8",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBSSMRW,
- 0,
- "I-O Data",
- "USB-SSMRW SD-card",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBSDRW,
- 0,
- "I-O Data",
- "USB-SDRW SD-card",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETT,
- 0,
- "I-O Data",
- "USB ETT",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTX,
- 0,
- "I-O Data",
- "USB ETTX",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETTXS,
- 0,
- "I-O Data",
- "USB ETTX",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBWNB11A,
- 0,
- "I-O Data",
- "USB WN-B11",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBWNB11,
- 0,
- "I-O Data",
- "USB Airport WN-B11",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_ETGUS2,
- 0,
- "I-O Data",
- "ETG-US2",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_RT3072_1,
- 0,
- "I-O Data",
- "RT3072",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_RT3072_2,
- 0,
- "I-O Data",
- "RT3072",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_RT3072_3,
- 0,
- "I-O Data",
- "RT3072",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_RT3072_4,
- 0,
- "I-O Data",
- "RT3072",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ,
- 0,
- "I-O Data",
- "Serial USB-RSAQ1",
- },
- {
- USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBRSAQ5,
- 0,
- "I-O Data",
- "Serial USB-RSAQ5",
- },
- {
- USB_VENDOR_IODATA2, USB_PRODUCT_IODATA2_USB2SC,
- 0,
- "I-O Data",
- "USB2.0-SCSI Bridge USB2-SC",
- },
- {
- USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP100,
- 0,
- "Iomega",
- "Zip 100",
- },
- {
- USB_VENDOR_IOMEGA, USB_PRODUCT_IOMEGA_ZIP250,
- 0,
- "Iomega",
- "Zip 250",
- },
- {
- USB_VENDOR_ISSC, USB_PRODUCT_ISSC_ISSCBTA,
- 0,
- "Integrated System Solution Corp.",
- "Bluetooth USB Adapter",
- },
- {
- USB_VENDOR_ITEGNO, USB_PRODUCT_ITEGNO_WM1080A,
- 0,
- "iTegno",
- "WM1080A GSM/GPRS modem",
- },
- {
- USB_VENDOR_ITEGNO, USB_PRODUCT_ITEGNO_WM2080A,
- 0,
- "iTegno",
- "WM2080A CDMA modem",
- },
- {
- USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20,
- 0,
- "I-Tuner Networks",
- "USB-LCD 2x20",
- },
- {
- USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD4X20,
- 0,
- "I-Tuner Networks",
- "USB-LCD 4x20",
- },
- {
- USB_VENDOR_JABLOTRON, USB_PRODUCT_JABLOTRON_PC60B,
- 0,
- "Jablotron",
- "PC-60B",
- },
- {
- USB_VENDOR_JATON, USB_PRODUCT_JATON_EDA,
- 0,
- "Jaton",
- "Ethernet",
- },
- {
- USB_VENDOR_JMICRON, USB_PRODUCT_JMICRON_JM20336,
- 0,
- "JMicron",
- "USB to SATA Bridge",
- },
- {
- USB_VENDOR_JMICRON, USB_PRODUCT_JMICRON_JM20337,
- 0,
- "JMicron",
- "USB to ATA/ATAPI Bridge",
- },
- {
- USB_VENDOR_JVC, USB_PRODUCT_JVC_GR_DX95,
- 0,
- "JVC",
- "GR-DX95",
- },
- {
- USB_VENDOR_JVC, USB_PRODUCT_JVC_MP_PRX1,
- 0,
- "JVC",
- "MP-PRX1 Ethernet",
- },
- {
- USB_VENDOR_JRC, USB_PRODUCT_JRC_AH_J3001V_J3002V,
- 0,
- "Japan Radio Company",
- "AirH PHONE AH-J3001V/J3002V",
- },
- {
- USB_VENDOR_KAWATSU, USB_PRODUCT_KAWATSU_MH4000P,
- 0,
- "Kawatsu Semiconductor",
- "MiniHub 4000P",
- },
- {
- USB_VENDOR_KEISOKUGIKEN, USB_PRODUCT_KEISOKUGIKEN_USBDAQ,
- 0,
- "Keisokugiken",
- "HKS-0200 USBDAQ",
- },
- {
- USB_VENDOR_KENSINGTON, USB_PRODUCT_KENSINGTON_ORBIT,
- 0,
- "Kensington",
- "Orbit USB/PS2 trackball",
- },
- {
- USB_VENDOR_KENSINGTON, USB_PRODUCT_KENSINGTON_TURBOBALL,
- 0,
- "Kensington",
- "TurboBall",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-28 serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28X_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-28X serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19 serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA18_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-18 serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA18X_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-18X serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19W_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19W serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19 serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19W,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19W serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA49W_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-49W serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA49W,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-49W serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19QI_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19QI serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19QI,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19QI serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19Q_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19Q serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19Q,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19Q serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-28 serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28XXB,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-28X/XB serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA18,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-18 serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA18X,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-18X serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28XB_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-28XB serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28XA_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-28XB serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA28XA,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-28XA serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA18XA_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-18XA serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA18XA,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-18XA serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19QW_NF,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19WQ serial Adapter (no firmware)",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19QW,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19WQ serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_USA19HA,
- 0,
- "Keyspan / InnoSys Inc.",
- "USA-19HS serial Adapter",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_UIA10,
- 0,
- "Keyspan / InnoSys Inc.",
- "UIA-10 remote control",
- },
- {
- USB_VENDOR_KEYSPAN, USB_PRODUCT_KEYSPAN_UIA11,
- 0,
- "Keyspan / InnoSys Inc.",
- "UIA-11 remote control",
- },
- {
- USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_XX1,
- 0,
- "Kingston Technology",
- "Ethernet",
- },
- {
- USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_KNU101TX,
- 0,
- "Kingston Technology",
- "KNU101TX USB Ethernet",
- },
- {
- USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BT,
- 0,
- "Kawasaki LSI",
- "USB Ethernet",
- },
- {
- USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BTN,
- 0,
- "Kawasaki LSI",
- "USB Ethernet",
- },
- {
- USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC220,
- 0,
- "Eastman Kodak",
- "Digital Science DC220",
- },
- {
- USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC260,
- 0,
- "Eastman Kodak",
- "Digital Science DC260",
- },
- {
- USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC265,
- 0,
- "Eastman Kodak",
- "Digital Science DC265",
- },
- {
- USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC290,
- 0,
- "Eastman Kodak",
- "Digital Science DC290",
- },
- {
- USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC240,
- 0,
- "Eastman Kodak",
- "Digital Science DC240",
- },
- {
- USB_VENDOR_KODAK, USB_PRODUCT_KODAK_DC280,
- 0,
- "Eastman Kodak",
- "Digital Science DC280",
- },
- {
- USB_VENDOR_KONICA, USB_PRODUCT_KONICA_CAMERA,
- 0,
- "Konica",
- "Digital Color Camera",
- },
- {
- USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE,
- 0,
- "KYE Systems",
- "Niche mouse",
- },
- {
- USB_VENDOR_KYE, USB_PRODUCT_KYE_NETSCROLL,
- 0,
- "KYE Systems",
- "Genius NetScroll mouse",
- },
- {
- USB_VENDOR_KYE, USB_PRODUCT_KYE_FLIGHT2000,
- 0,
- "KYE Systems",
- "Flight 2000 joystick",
- },
- {
- USB_VENDOR_KYE, USB_PRODUCT_KYE_VIVIDPRO,
- 0,
- "KYE Systems",
- "ColorPage Vivid-Pro scanner",
- },
- {
- USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S3X,
- 0,
- "Kyocera Wireless Corp.",
- "Finecam S3x",
- },
- {
- USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S4,
- 0,
- "Kyocera Wireless Corp.",
- "Finecam S4",
- },
- {
- USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_S5,
- 0,
- "Kyocera Wireless Corp.",
- "Finecam S5",
- },
- {
- USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_FINECAM_L3,
- 0,
- "Kyocera Wireless Corp.",
- "Finecam L3",
- },
- {
- USB_VENDOR_KYOCERA, USB_PRODUCT_KYOCERA_AHK3001V,
- 0,
- "Kyocera Wireless Corp.",
- "AH-K3001V",
- },
- {
- USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_CDMA_MSM_K,
- 0,
- "Kyocera Wireless Corp.",
- "Qualcomm Kyocera CDMA Technologies MSM",
- },
- {
- USB_VENDOR_KYOCERA2, USB_PRODUCT_KYOCERA2_KPC680,
- 0,
- "Kyocera Wireless Corp.",
- "Qualcomm Kyocera CDMA Technologies MSM",
- },
- {
- USB_VENDOR_LACIE, USB_PRODUCT_LACIE_HD,
- 0,
- "LaCie",
- "Hard Disk",
- },
- {
- USB_VENDOR_LACIE, USB_PRODUCT_LACIE_CDRW,
- 0,
- "LaCie",
- "CD R/W",
- },
- {
- USB_VENDOR_LEADTEK, USB_PRODUCT_LEADTEK_9531,
- 0,
- "Leadtek",
- "9531 GPS",
- },
- {
- USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_JUMPSHOT,
- 0,
- "Lexar Media",
- "jumpSHOT CompactFlash Reader",
- },
- {
- USB_VENDOR_LEXAR, USB_PRODUCT_LEXAR_CF_READER,
- 0,
- "Lexar Media",
- "USB CF Reader",
- },
- {
- USB_VENDOR_LEXMARK, USB_PRODUCT_LEXMARK_S2450,
- 0,
- "Lexmark International",
- "Optra S 2450",
- },
- {
- USB_VENDOR_LIEBERT, USB_PRODUCT_LIEBERT_POWERSURE_PXT,
- 0,
- "Liebert",
- "PowerSure Personal XT",
- },
- {
- USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_MAUSB2,
- 0,
- "Linksys",
- "Camedia MAUSB-2",
- },
- {
- USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX1,
- 0,
- "Linksys",
- "USB10TX",
- },
- {
- USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T,
- 0,
- "Linksys",
- "USB10T Ethernet",
- },
- {
- USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100TX,
- 0,
- "Linksys",
- "USB100TX Ethernet",
- },
- {
- USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB100H1,
- 0,
- "Linksys",
- "USB100H1 Ethernet/HPNA",
- },
- {
- USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TA,
- 0,
- "Linksys",
- "USB10TA Ethernet",
- },
- {
- USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10TX2,
- 0,
- "Linksys",
- "USB10TX",
- },
- {
- USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_WUSB11,
- 0,
- "Linksys",
- "WUSB11 Wireless Adapter",
- },
- {
- USB_VENDOR_LINKSYS2, USB_PRODUCT_LINKSYS2_USB200M,
- 0,
- "Linksys",
- "USB 2.0 10/100 Ethernet",
- },
- {
- USB_VENDOR_LINKSYS3, USB_PRODUCT_LINKSYS3_WUSB11v28,
- 0,
- "Linksys",
- "WUSB11 v2.8 Wireless Adapter",
- },
- {
- USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_USB1000,
- 0,
- "Linksys",
- "USB1000",
- },
- {
- USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB100,
- 0,
- "Linksys",
- "WUSB100",
- },
- {
- USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB600N,
- 0,
- "Linksys",
- "WUSB600N",
- },
- {
- USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB54GCV2,
- 0,
- "Linksys",
- "WUSB54GC v2",
- },
- {
- USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB54GCV3,
- 0,
- "Linksys",
- "WUSB54GC v3",
- },
- {
- USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_RT3070,
- 0,
- "Linksys",
- "RT3070",
- },
- {
- USB_VENDOR_LINKSYS4, USB_PRODUCT_LINKSYS4_WUSB600NV2,
- 0,
- "Linksys",
- "WUSB600N v2",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_M2452,
- 0,
- "Logitech",
- "M2452 keyboard",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_M4848,
- 0,
- "Logitech",
- "M4848 mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_PAGESCAN,
- 0,
- "Logitech",
- "PageScan",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMWEB,
- 0,
- "Logitech",
- "QuickCam Web",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRO,
- 0,
- "Logitech",
- "QuickCam Pro",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMEXP,
- 0,
- "Logitech",
- "QuickCam Express",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAM,
- 0,
- "Logitech",
- "QuickCam",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRO3,
- 0,
- "Logitech",
- "QuickCam Pro 9000",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_N43,
- 0,
- "Logitech",
- "N43",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_N48,
- 0,
- "Logitech",
- "N48 mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_MBA47,
- 0,
- "Logitech",
- "M-BA47 mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WMMOUSE,
- 0,
- "Logitech",
- "WingMan Gaming Mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_BD58,
- 0,
- "Logitech",
- "BD58 mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN58A,
- 0,
- "Logitech",
- "iFeel Mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B,
- 0,
- "Logitech",
- "iFeel MouseMan",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WMPAD,
- 0,
- "Logitech",
- "WingMan GamePad Extreme",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WMRPAD,
- 0,
- "Logitech",
- "WingMan RumblePad",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_WMJOY,
- 0,
- "Logitech",
- "WingMan Force joystick",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_BB13,
- 0,
- "Logitech",
- "USB-PS/2 Trackball",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_RK53,
- 0,
- "Logitech",
- "Cordless mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_RB6,
- 0,
- "Logitech",
- "Cordless keyboard",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_MX700,
- 0,
- "Logitech",
- "Cordless optical mouse",
- },
- {
- USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRO2,
- 0,
- "Logitech",
- "QuickCam Pro",
- },
- {
- USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443SU2,
- 0,
- "Logitec",
- "DVD Multi-plus unit LDR-H443SU2",
- },
- {
- USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LDR_H443U2,
- 0,
- "Logitec",
- "DVD Multi-plus unit LDR-H443U2",
- },
- {
- USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_LAN_GTJU2A,
- 0,
- "Logitec",
- "LAN-GTJ/U2A Ethernet",
- },
- {
- USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_RT2870_1,
- 0,
- "Logitec",
- "RT2870",
- },
- {
- USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_RT2870_2,
- 0,
- "Logitec",
- "RT2870",
- },
- {
- USB_VENDOR_LOGITEC, USB_PRODUCT_LOGITEC_RT2870_3,
- 0,
- "Logitec",
- "RT2870",
- },
- {
- USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_WM66,
- 0,
- "Longcheer Holdings, Ltd.",
- "Longcheer WM66 HSDPA",
- },
- {
- USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_W14,
- 0,
- "Longcheer Holdings, Ltd.",
- "Mobilcom W14",
- },
- {
- USB_VENDOR_LONGCHEER, USB_PRODUCT_LONGCHEER_DISK,
- 0,
- "Longcheer Holdings, Ltd.",
- "Driver disk",
- },
- {
- USB_VENDOR_LUCENT, USB_PRODUCT_LUCENT_EVALKIT,
- 0,
- "Lucent",
- "USS-720 evaluation kit",
- },
- {
- USB_VENDOR_LUWEN, USB_PRODUCT_LUWEN_EASYDISK,
- 0,
- "Luwen",
- "EasyDisc",
- },
- {
- USB_VENDOR_MACALLY, USB_PRODUCT_MACALLY_MOUSE1,
- 0,
- "Macally",
- "mouse",
- },
- {
- USB_VENDOR_MARVELL, USB_PRODUCT_MARVELL_SHEEVAPLUG,
- 0,
- "Marvell Technology Group Ltd.",
- "SheevaPlug serial interface",
- },
- {
- USB_VENDOR_MATRIXORBITAL, USB_PRODUCT_MATRIXORBITAL_MOUA,
- 0,
- "Matrix Orbital",
- "Martrix Orbital MOU-Axxxx LCD displays",
- },
- {
- USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100,
- 0,
- "MCT",
- "Hub",
- },
- {
- USB_VENDOR_MCT, USB_PRODUCT_MCT_DU_H3SP_USB232,
- 0,
- "MCT",
- "D-Link DU-H3SP USB BAY Hub",
- },
- {
- USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232,
- 0,
- "MCT",
- "USB-232 Interface",
- },
- {
- USB_VENDOR_MCT, USB_PRODUCT_MCT_SITECOM_USB232,
- 0,
- "MCT",
- "Sitecom USB-232 Products",
- },
- {
- USB_VENDOR_MEIZU, USB_PRODUCT_MEIZU_M6_SL,
- 0,
- "Meizu Electronics",
- "MiniPlayer M6 (SL)",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX1,
- 0,
- "Melco",
- "LUA-TX Ethernet",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUATX5,
- 0,
- "Melco",
- "LUA-TX Ethernet",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUA2TX5,
- 0,
- "Melco",
- "LUA2-TX Ethernet",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAKTX,
- 0,
- "Melco",
- "LUA-KTX Ethernet",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_DUBPXXG,
- 0,
- "Melco",
- "DUB-PxxG",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUAU2KTX,
- 0,
- "Melco",
- "LUA-U2-KTX Ethernet",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54YB,
- 0,
- "Melco",
- "WLI-U2-KG54-YB WLAN",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54,
- 0,
- "Melco",
- "WLI-U2-KG54 WLAN",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54AI,
- 0,
- "Melco",
- "WLI-U2-KG54-AI WLAN",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_LUA3U2AGT,
- 0,
- "Melco",
- "LUA3-U2-AGT",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_NINWIFI,
- 0,
- "Melco",
- "Nintendo Wi-Fi",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_PCOPRS1,
- 0,
- "Melco",
- "PC-OP-RS1 RemoteStation",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HP,
- 0,
- "Melco",
- "WLI-U2-SG54HP",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_G54HP,
- 0,
- "Melco",
- "WLI-U2-G54HP",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_KG54L,
- 0,
- "Melco",
- "WLI-U2-KG54L",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLIUCG300N,
- 0,
- "Melco",
- "WLI-UC-G300N",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_SG54HG,
- 0,
- "Melco",
- "WLI-U2-SG54HG",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLRUCG,
- 0,
- "Melco",
- "WLR-UC-G",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLRUCGAOSS,
- 0,
- "Melco",
- "WLR-UC-G-AOSS",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLIUCAG300N,
- 0,
- "Melco",
- "WLI-UC-AG300N",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_RT2870_1,
- 0,
- "Melco",
- "RT2870",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_RT2870_2,
- 0,
- "Melco",
- "RT2870",
- },
- {
- USB_VENDOR_MELCO, USB_PRODUCT_MELCO_WLIUCGN,
- 0,
- "Melco",
- "WLI-UC-GN",
- },
- {
- USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620,
- 0,
- "Merlin",
- "Merlin V620",
- },
- {
- USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B,
- 0,
- "MetaGeek",
- "MetaGeek Wi-Spy",
- },
- {
- USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X,
- 0,
- "MetaGeek",
- "MetaGeek Wi-Spy 2.4x",
- },
- {
- USB_VENDOR_METAGEEK2, USB_PRODUCT_METAGEEK2_WISPYDBX,
- 0,
- "MetaGeek",
- "MetaGeek Wi-Spy DBx",
- },
- {
- USB_VENDOR_METRICOM, USB_PRODUCT_METRICOM_RICOCHET_GS,
- 0,
- "Metricom",
- "Ricochet GS",
- },
- {
- USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1,
- 0,
- "MGE UPS Systems",
- "MGE UPS SYSTEMS PROTECTIONCENTER 1",
- },
- {
- USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2,
- 0,
- "MGE UPS Systems",
- "MGE UPS SYSTEMS PROTECTIONCENTER 2",
- },
- {
- USB_VENDOR_MEI, USB_PRODUCT_MEI_CASHFLOW_SC,
- 0,
- "MEI",
- "Cashflow-SC Cash Acceptor",
- },
- {
- USB_VENDOR_MEI, USB_PRODUCT_MEI_S2000,
- 0,
- "MEI",
- "Seies 2000 Combo Acceptor",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_BT_DONGLE,
- 0,
- "Micro Star International",
- "Bluetooth USB dongle",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_1,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_2,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_8,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_3,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_9,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_UB11B,
- 0,
- "Micro Star International",
- "UB11B",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570,
- 0,
- "Micro Star International",
- "RT2570",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_2,
- 0,
- "Micro Star International",
- "RT2570",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2570_3,
- 0,
- "Micro Star International",
- "RT2570",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_1,
- 0,
- "Micro Star International",
- "RT2573",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_2,
- 0,
- "Micro Star International",
- "RT2573",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_4,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_5,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_10,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_6,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_11,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT3070_7,
- 0,
- "Micro Star International",
- "RT3070",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_3,
- 0,
- "Micro Star International",
- "RT2573",
- },
- {
- USB_VENDOR_MSI, USB_PRODUCT_MSI_RT2573_4,
- 0,
- "Micro Star International",
- "RT2573",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_SIDEPREC,
- 0,
- "Microsoft",
- "SideWinder Precision Pro",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_INTELLIMOUSE,
- 0,
- "Microsoft",
- "IntelliMouse",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_NATURALKBD,
- 0,
- "Microsoft",
- "Natural Keyboard Elite",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_DDS80,
- 0,
- "Microsoft",
- "Digital Sound System 80",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_SIDEWINDER,
- 0,
- "Microsoft",
- "Sidewinder Precision Racing Wheel",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_INETPRO,
- 0,
- "Microsoft",
- "Internet Keyboard Pro",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_TBEXPLORER,
- 0,
- "Microsoft",
- "Trackball Explorer",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_INTELLIEYE,
- 0,
- "Microsoft",
- "IntelliEye mouse",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_INETPRO2,
- 0,
- "Microsoft",
- "Internet Keyboard Pro",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_INTELLIMOUSE5,
- 0,
- "Microsoft",
- "IntelliMouse 1.1 5-Button Mouse",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WHEELMOUSE,
- 0,
- "Microsoft",
- "Wheel Mouse Optical",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_MN510,
- 0,
- "Microsoft",
- "MN510 Wireless",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_700WX,
- 0,
- "Microsoft",
- "Palm 700WX",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_MN110,
- 0,
- "Microsoft",
- "10/100 USB NIC",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE,
- 0,
- "Microsoft",
- "Wireless Optical IntelliMouse",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK,
- 0,
- "Microsoft",
- "Wireless Optical Mouse (Model 1023)",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_COMFORT3000,
- 0,
- "Microsoft",
- "Comfort Optical Mouse 3000 (Model 1043)",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK3,
- 0,
- "Microsoft",
- "Wireless Optical Mouse 3000 (Model 1049)",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_NATURAL4000,
- 0,
- "Microsoft",
- "Natural Ergonomic Keyboard 4000",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLNOTEBOOK2,
- 0,
- "Microsoft",
- "Wireless Optical Mouse 3000 (Model 1056)",
- },
- {
- USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_XBOX360,
- 0,
- "Microsoft",
- "XBOX 360 WLAN",
- },
- {
- USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIDB25,
- 0,
- "Microtech",
- "USB-SCSI-DB25",
- },
- {
- USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_SCSIHD50,
- 0,
- "Microtech",
- "USB-SCSI-HD50",
- },
- {
- USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_DPCM,
- 0,
- "Microtech",
- "USB CameraMate",
- },
- {
- USB_VENDOR_MICROTECH, USB_PRODUCT_MICROTECH_FREECOM,
- 0,
- "Microtech",
- "Freecom USB-IDE",
- },
- {
- USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX,
- 0,
- "Microtek",
- "Phantom 336CX - C3 scanner",
- },
- {
- USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_X6U,
- 0,
- "Microtek",
- "ScanMaker X6 - X6U",
- },
- {
- USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_C6,
- 0,
- "Microtek",
- "Phantom C6 scanner",
- },
- {
- USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_336CX2,
- 0,
- "Microtek",
- "Phantom 336CX - C3 scanner",
- },
- {
- USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL,
- 0,
- "Microtek",
- "ScanMaker V6USL",
- },
- {
- USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6USL2,
- 0,
- "Microtek",
- "ScanMaker V6USL",
- },
- {
- USB_VENDOR_MICROTEK, USB_PRODUCT_MICROTEK_V6UL,
- 0,
- "Microtek",
- "ScanMaker V6UL",
- },
- {
- USB_VENDOR_MICROTUNE, USB_PRODUCT_MICROTUNE_BT_DONGLE,
- 0,
- "Microtune",
- "Bluetooth USB dongle",
- },
- {
- USB_VENDOR_MIDIMAN, USB_PRODUCT_MIDIMAN_MIDISPORT2X2,
- 0,
- "Midiman",
- "Midisport 2x2",
- },
- {
- USB_VENDOR_MINDSATWORK, USB_PRODUCT_MINDSATWORK_WALLET,
- 0,
- "Minds At Work",
- "Digital Wallet",
- },
- {
- USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_2300,
- 0,
- "Minolta",
- "Dimage 2300",
- },
- {
- USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_S304,
- 0,
- "Minolta",
- "Dimage S304",
- },
- {
- USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_X,
- 0,
- "Minolta",
- "Dimage X",
- },
- {
- USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_5400,
- 0,
- "Minolta",
- "Dimage 5400",
- },
- {
- USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_F300,
- 0,
- "Minolta",
- "Dimage F300",
- },
- {
- USB_VENDOR_MINOLTA, USB_PRODUCT_MINOLTA_E223,
- 0,
- "Minolta",
- "Dimage E223",
- },
- {
- USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_CDRRW,
- 0,
- "Mitsumi",
- "CD-R/RW Drive",
- },
- {
- USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_BT_DONGLE,
- 0,
- "Mitsumi",
- "Bluetooth USB dongle",
- },
- {
- USB_VENDOR_MITSUMI, USB_PRODUCT_MITSUMI_FDD,
- 0,
- "Mitsumi",
- "USB FDD",
- },
- {
- USB_VENDOR_MOBILEACTION, USB_PRODUCT_MOBILEACTION_MA620,
- 0,
- "Mobile Action",
- "MA-620 Infrared Adapter",
- },
- {
- USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_EA,
- 0,
- "Mobility",
- "Ethernet",
- },
- {
- USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_EASIDOCK,
- 0,
- "Mobility",
- "EasiDock Ethernet",
- },
- {
- USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7703,
- 0,
- "MosChip Semiconductor",
- "MCS7703 Serial Port Adapter",
- },
- {
- USB_VENDOR_MOSCHIP, USB_PRODUCT_MOSCHIP_MCS7830,
- 0,
- "MosChip Semiconductor",
- "MCS7830 Ethernet",
- },
- {
- USB_VENDOR_MOTOROLA, USB_PRODUCT_MOTOROLA_MC141555,
- 0,
- "Motorola",
- "MC141555 hub controller",
- },
- {
- USB_VENDOR_MOTOROLA, USB_PRODUCT_MOTOROLA_SB4100,
- 0,
- "Motorola",
- "SB4100 USB Cable Modem",
- },
- {
- USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_T720C,
- 0,
- "Motorola",
- "T720c",
- },
- {
- USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_A41XV32X,
- 0,
- "Motorola",
- "A41x/V32x Mobile Phones",
- },
- {
- USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_E398,
- 0,
- "Motorola",
- "E398 Mobile Phone",
- },
- {
- USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN,
- 0,
- "Motorola",
- "USBLAN",
- },
- {
- USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2,
- 0,
- "Motorola",
- "USBLAN",
- },
- {
- USB_VENDOR_MOTOROLA4, USB_PRODUCT_MOTOROLA4_RT2770,
- 0,
- "Motorola",
- "RT2770",
- },
- {
- USB_VENDOR_MOTOROLA4, USB_PRODUCT_MOTOROLA4_RT3070,
- 0,
- "Motorola",
- "RT3070",
- },
- {
- USB_VENDOR_MULTITECH, USB_PRODUCT_MULTITECH_ATLAS,
- 0,
- "MultiTech",
- "MT5634ZBA-USB modem",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CU,
- 0,
- "Mustek Systems",
- "1200 CU scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_600CU,
- 0,
- "Mustek Systems",
- "600 CU scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200USB,
- 0,
- "Mustek Systems",
- "1200 USB scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200UB,
- 0,
- "Mustek Systems",
- "1200 UB scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200USBPLUS,
- 0,
- "Mustek Systems",
- "1200 USB Plus scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_1200CUPLUS,
- 0,
- "Mustek Systems",
- "1200 CU Plus scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW1200F,
- 0,
- "Mustek Systems",
- "BearPaw 1200F scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW2400TA,
- 0,
- "Mustek Systems",
- "BearPaw 2400TA scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_BEARPAW1200TA,
- 0,
- "Mustek Systems",
- "BearPaw 1200TA scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_600USB,
- 0,
- "Mustek Systems",
- "600 USB scanner",
- },
- {
- USB_VENDOR_MUSTEK, USB_PRODUCT_MUSTEK_MDC800,
- 0,
- "Mustek Systems",
- "MDC-800 digital camera",
- },
- {
- USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY,
- 0,
- "M-Systems",
- "DiskOnKey",
- },
- {
- USB_VENDOR_MSYSTEMS, USB_PRODUCT_MSYSTEMS_DISKONKEY2,
- 0,
- "M-Systems",
- "DiskOnKey",
- },
- {
- USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN_8813,
- 0,
- "Myson Technology",
- "USB-IDE",
- },
- {
- USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HEDEN,
- 0,
- "Myson Technology",
- "USB-IDE",
- },
- {
- USB_VENDOR_MYSON, USB_PRODUCT_MYSON_HUBREADER,
- 0,
- "Myson Technology",
- "COMBO Card reader with USB HUB",
- },
- {
- USB_VENDOR_MYSON, USB_PRODUCT_MYSON_STARREADER,
- 0,
- "Myson Technology",
- "USB flash card adapter",
- },
- {
- USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW1200,
- 0,
- "National Semiconductor",
- "BearPaw 1200",
- },
- {
- USB_VENDOR_NATIONAL, USB_PRODUCT_NATIONAL_BEARPAW2400,
- 0,
- "National Semiconductor",
- "BearPaw 2400",
- },
- {
- USB_VENDOR_NEC, USB_PRODUCT_NEC_HUB_0050,
- 0,
- "NEC",
- "USB 2.0 7-Port Hub",
- },
- {
- USB_VENDOR_NEC, USB_PRODUCT_NEC_HUB_005A,
- 0,
- "NEC",
- "USB 2.0 4-Port Hub",
- },
- {
- USB_VENDOR_NEC, USB_PRODUCT_NEC_HUB,
- 0,
- "NEC",
- "hub",
- },
- {
- USB_VENDOR_NEC, USB_PRODUCT_NEC_HUB_B,
- 0,
- "NEC",
- "hub",
- },
- {
- USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND3260,
- 0,
- "Neodio",
- "8-in-1 Multi-format Flash Controller",
- },
- {
- USB_VENDOR_NEODIO, USB_PRODUCT_NEODIO_ND5010,
- 0,
- "Neodio",
- "Multi-format Flash Controller",
- },
- {
- USB_VENDOR_NEOTEL, USB_PRODUCT_NEOTEL_PRIME,
- 0,
- "Neotel",
- "Prime USB modem",
- },
- {
- USB_VENDOR_NETAC, USB_PRODUCT_NETAC_CF_CARD,
- 0,
- "Netac",
- "USB-CF-Card",
- },
- {
- USB_VENDOR_NETAC, USB_PRODUCT_NETAC_ONLYDISK,
- 0,
- "Netac",
- "OnlyDisk",
- },
- {
- USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_TURBOCONNECT,
- 0,
- "NetChip Technology",
- "Turbo-Connect",
- },
- {
- USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_CLIK_40,
- 0,
- "NetChip Technology",
- "USB Clik! 40",
- },
- {
- USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET,
- 0,
- "NetChip Technology",
- "Linux Ethernet/RNDIS gadget on pxa210/25x/26x",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101,
- 0,
- "BayNETGEAR",
- "Ethernet",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101X,
- 0,
- "BayNETGEAR",
- "Ethernet",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA101,
- 0,
- "BayNETGEAR",
- "Ethernet 10/100, USB1.1",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_FA120,
- 0,
- "BayNETGEAR",
- "USB 2.0 Ethernet",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WG111V2_2,
- 0,
- "BayNETGEAR",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WG111V3,
- 0,
- "BayNETGEAR",
- "WG111v3",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WG111U,
- 0,
- "BayNETGEAR",
- "WG111U",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WG111U_NF,
- 0,
- "BayNETGEAR",
- "WG111U (no firmware)",
- },
- {
- USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_WG111V2,
- 0,
- "BayNETGEAR",
- "WG111V2",
- },
- {
- USB_VENDOR_NETGEAR2, USB_PRODUCT_NETGEAR2_MA101,
- 0,
- "Netgear",
- "MA101",
- },
- {
- USB_VENDOR_NETGEAR2, USB_PRODUCT_NETGEAR2_MA101B,
- 0,
- "Netgear",
- "MA101 Rev B",
- },
- {
- USB_VENDOR_NETGEAR3, USB_PRODUCT_NETGEAR3_WG111T,
- 0,
- "Netgear",
- "WG111T",
- },
- {
- USB_VENDOR_NETGEAR3, USB_PRODUCT_NETGEAR3_WG111T_NF,
- 0,
- "Netgear",
- "WG111T (no firmware)",
- },
- {
- USB_VENDOR_NETGEAR3, USB_PRODUCT_NETGEAR3_WPN111,
- 0,
- "Netgear",
- "WPN111",
- },
- {
- USB_VENDOR_NETGEAR3, USB_PRODUCT_NETGEAR3_WPN111_NF,
- 0,
- "Netgear",
- "WPN111 (no firmware)",
- },
- {
- USB_VENDOR_NETGEAR3, USB_PRODUCT_NETGEAR3_WPN111_2,
- 0,
- "Netgear",
- "WPN111",
- },
- {
- USB_VENDOR_NETINDEX, USB_PRODUCT_NETINDEX_WS002IN,
- 0,
- "NetIndex",
- "Willcom WS002IN",
- },
- {
- USB_VENDOR_NEWLINK, USB_PRODUCT_NEWLINK_USB2IDEBRIDGE,
- 0,
- "NEWlink",
- "USB 2.0 Hard Drive Enclosure",
- },
- {
- USB_VENDOR_NIKON, USB_PRODUCT_NIKON_E990,
- 0,
- "Nikon",
- "Digital Camera E990",
- },
- {
- USB_VENDOR_NIKON, USB_PRODUCT_NIKON_LS40,
- 0,
- "Nikon",
- "CoolScan LS40 ED",
- },
- {
- USB_VENDOR_NIKON, USB_PRODUCT_NIKON_D300,
- 0,
- "Nikon",
- "Digital Camera D300",
- },
- {
- USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_NV902,
- 0,
- "NovaTech",
- "NovaTech NV-902W",
- },
- {
- USB_VENDOR_NOVATECH, USB_PRODUCT_NOVATECH_RT2573,
- 0,
- "NovaTech",
- "RT2573",
- },
- {
- USB_VENDOR_NOKIA, USB_PRODUCT_NOKIA_N958GB,
- 0,
- "Nokia",
- "Nokia N95 8GBc",
- },
- {
- USB_VENDOR_NOKIA2, USB_PRODUCT_NOKIA2_CA42,
- 0,
- "Nokia",
- "CA-42 cable",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V640,
- 0,
- "Novatel Wireless",
- "Merlin V620",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_CDMA_MODEM,
- 0,
- "Novatel Wireless",
- "Novatel Wireless Merlin CDMA",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V620,
- 0,
- "Novatel Wireless",
- "Merlin V620",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V740,
- 0,
- "Novatel Wireless",
- "Merlin V740",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_V720,
- 0,
- "Novatel Wireless",
- "Merlin V720",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740,
- 0,
- "Novatel Wireless",
- "Merlin U740",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U740_2,
- 0,
- "Novatel Wireless",
- "Merlin U740",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U870,
- 0,
- "Novatel Wireless",
- "Merlin U870",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_XU870,
- 0,
- "Novatel Wireless",
- "Merlin XU870",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_X950D,
- 0,
- "Novatel Wireless",
- "Merlin X950D",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620,
- 0,
- "Novatel Wireless",
- "Expedite ES620",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_E725,
- 0,
- "Novatel Wireless",
- "Expedite E725",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620_2,
- 0,
- "Novatel Wireless",
- "Expedite ES620",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ES620,
- 0,
- "Novatel Wireless",
- "ES620 CDMA",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U720,
- 0,
- "Novatel Wireless",
- "Merlin U720",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_EU730,
- 0,
- "Novatel Wireless",
- "Expedite EU730",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_EU740,
- 0,
- "Novatel Wireless",
- "Expedite EU740",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_EU870D,
- 0,
- "Novatel Wireless",
- "Expedite EU870D",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727,
- 0,
- "Novatel Wireless",
- "Merlin U727 CDMA",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC950D,
- 0,
- "Novatel Wireless",
- "Novatel MC950D HSUPA",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD,
- 0,
- "Novatel Wireless",
- "Novatel ZeroCD",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_ZEROCD2,
- 0,
- "Novatel Wireless",
- "Novatel ZeroCD",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U727_2,
- 0,
- "Novatel Wireless",
- "Merlin U727 CDMA",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_U760,
- 0,
- "Novatel Wireless",
- "Novatel U760",
- },
- {
- USB_VENDOR_NOVATEL, USB_PRODUCT_NOVATEL_MC760,
- 0,
- "Novatel Wireless",
- "Novatel MC760",
- },
- {
- USB_VENDOR_NOVATEL2, USB_PRODUCT_NOVATEL2_FLEXPACKGPS,
- 0,
- "Novatel Wireless",
- "NovAtel FlexPack GPS receiver",
- },
- {
- USB_VENDOR_MERLIN, USB_PRODUCT_MERLIN_V620,
- 0,
- "Merlin",
- "Merlin V620",
- },
- {
- USB_VENDOR_O2MICRO, USB_PRODUCT_O2MICRO_OZ776_HUB,
- 0,
- "O2 Micro, Inc.",
- "OZ776 hub",
- },
- {
- USB_VENDOR_O2MICRO, USB_PRODUCT_O2MICRO_OZ776_CCID_SC,
- 0,
- "O2 Micro, Inc.",
- "OZ776 CCID SC Reader",
- },
- {
- USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C1,
- 0,
- "Olympus",
- "C-1 Digital Camera",
- },
- {
- USB_VENDOR_OLYMPUS, USB_PRODUCT_OLYMPUS_C700,
- 0,
- "Olympus",
- "C-700 Ultra Zoom",
- },
- {
- USB_VENDOR_OMNIVISION, USB_PRODUCT_OMNIVISION_OV511,
- 0,
- "OmniVision",
- "OV511 Camera",
- },
- {
- USB_VENDOR_OMNIVISION, USB_PRODUCT_OMNIVISION_OV511PLUS,
- 0,
- "OmniVision",
- "OV511+ Camera",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_SDS_HOTFIND_D,
- 0,
- "OnSpec",
- "SDS-infrared.com Hotfind-D Infrared Camera",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDCFE_B_CF_READER,
- 0,
- "OnSpec",
- "MDCFE-B USB CF Reader",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFMS_RW,
- 0,
- "OnSpec",
- "SIIG/Datafab Memory Stick+CF Reader/Writer",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_READER,
- 0,
- "OnSpec",
- "Datafab-based Reader",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER,
- 0,
- "OnSpec",
- "PNY/Datafab CF+SM Reader",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_READER2,
- 0,
- "OnSpec",
- "Simple Tech/Datafab CF+SM Reader",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_MDSM_B_READER,
- 0,
- "OnSpec",
- "MDSM-B reader",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_CFSM_COMBO,
- 0,
- "OnSpec",
- "USB to CF + SM Combo (LC1)",
- },
- {
- USB_VENDOR_ONSPEC, USB_PRODUCT_ONSPEC_UCF100,
- 0,
- "OnSpec",
- "FlashLink UCF-100 CompactFlash Reader",
- },
- {
- USB_VENDOR_ONSPEC2, USB_PRODUCT_ONSPEC2_IMAGEMATE_SDDR55,
- 0,
- "OnSpec Electronic Inc.",
- "ImageMate SDDR55",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_VODAFONEMC3G,
- 0,
- "Option N.V.",
- "Vodafone Mobile Connect 3G datacard",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G,
- 0,
- "Option N.V.",
- "GlobeTrotter 3G datacard",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GQUAD,
- 0,
- "Option N.V.",
- "GlobeTrotter 3G QUAD datacard",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3GPLUS,
- 0,
- "Option N.V.",
- "GlobeTrotter 3G+ datacard",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTICON322,
- 0,
- "Option N.V.",
- "GlobeTrotter Icon322 storage",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX36,
- 0,
- "Option N.V.",
- "GlobeTrotter Max 3.6 Modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTHSDPA,
- 0,
- "Option N.V.",
- "GlobeTrotter HSDPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAXHSUPA,
- 0,
- "Option N.V.",
- "GlobeTrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAXHSUPAE,
- 0,
- "Option N.V.",
- "GlobeTrotter HSUPA PCIe",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTMAX380HSUPAE,
- 0,
- "Option N.V.",
- "GlobeTrotter 380HSUPA PCIe",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G_1,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G_2,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G_3,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G_4,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G_5,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GT3G_6,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E6500,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E6501,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E6601,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E6721,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E6741,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E6761,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E6800,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E7021,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E7041,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E7061,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_E7100,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTM380,
- 0,
- "Option N.V.",
- "3G modem",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GE40X,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GSICON72,
- 0,
- "Option N.V.",
- "GlobeSurfer iCON",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GSICONHSUPA,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_ICON401,
- 0,
- "Option N.V.",
- "GlobeSurfer iCON 401",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GTHSUPA,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GMT382,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GE40X_1,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GE40X_2,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_GE40X_3,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_ICONEDGE,
- 0,
- "Option N.V.",
- "GlobeSurfer iCON EDGE",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_MODHSXPA,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_ICON321,
- 0,
- "Option N.V.",
- "Globetrotter HSUPA",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_ICON505,
- 0,
- "Option N.V.",
- "Globetrotter iCON 505",
- },
- {
- USB_VENDOR_OPTION, USB_PRODUCT_OPTION_ICON452,
- 0,
- "Option N.V.",
- "Globetrotter iCON 452",
- },
- {
- USB_VENDOR_OVISLINK, USB_PRODUCT_OVISLINK_RT3072,
- 0,
- "OvisLink",
- "RT3072",
- },
- {
- USB_VENDOR_OQO, USB_PRODUCT_OQO_WIFI01,
- 0,
- "OQO",
- "model 01 WiFi interface",
- },
- {
- USB_VENDOR_OQO, USB_PRODUCT_OQO_BT01,
- 0,
- "OQO",
- "model 01 Bluetooth interface",
- },
- {
- USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01PLUS,
- 0,
- "OQO",
- "model 01+ Ethernet",
- },
- {
- USB_VENDOR_OQO, USB_PRODUCT_OQO_ETHER01,
- 0,
- "OQO",
- "model 01 Ethernet interface",
- },
- {
- USB_VENDOR_OTI, USB_PRODUCT_OTI_DKU5,
- 0,
- "Ours Technology",
- "DKU-5 Serial",
- },
- {
- USB_VENDOR_OWEN, USB_PRODUCT_OWEN_AC4,
- 0,
- "Owen",
- "AC4 USB-RS485 converter",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_SERIAL,
- 0,
- "Palm Computing",
- "USB Serial",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_M500,
- 0,
- "Palm Computing",
- "Palm m500",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_M505,
- 0,
- "Palm Computing",
- "Palm m505",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_M515,
- 0,
- "Palm Computing",
- "Palm m515",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_I705,
- 0,
- "Palm Computing",
- "Palm i705",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_Z,
- 0,
- "Palm Computing",
- "Palm Tungsten Z",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_M125,
- 0,
- "Palm Computing",
- "Palm m125",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_M130,
- 0,
- "Palm Computing",
- "Palm m130",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_TUNGSTEN_T,
- 0,
- "Palm Computing",
- "Palm Tungsten T",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE31,
- 0,
- "Palm Computing",
- "Palm Zire 31",
- },
- {
- USB_VENDOR_PALM, USB_PRODUCT_PALM_ZIRE,
- 0,
- "Palm Computing",
- "Palm Zire",
- },
- {
- USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_LS120CAM,
- 0,
- "Panasonic (Matsushita)",
- "LS-120 Camera",
- },
- {
- USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXL840AN,
- 0,
- "Panasonic (Matsushita)",
- "CD-R Drive KXL-840AN",
- },
- {
- USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLRW32AN,
- 0,
- "Panasonic (Matsushita)",
- "CD-R Drive KXL-RW32AN",
- },
- {
- USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB20AN,
- 0,
- "Panasonic (Matsushita)",
- "CD-R Drive KXL-CB20AN",
- },
- {
- USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_KXLCB35AN,
- 0,
- "Panasonic (Matsushita)",
- "DVD-ROM & CD-R/RW",
- },
- {
- USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_SDCAAE,
- 0,
- "Panasonic (Matsushita)",
- "MultiMediaCard",
- },
- {
- USB_VENDOR_PANASONIC, USB_PRODUCT_PANASONIC_TYTP50P6S,
- 0,
- "Panasonic (Matsushita)",
- "TY-TP50P6-S 50in Touch Panel",
- },
- {
- USB_VENDOR_PARA, USB_PRODUCT_PARA_RT3070,
- 0,
- "PARA Industrial",
- "RT3070",
- },
- {
- USB_VENDOR_PEGATRON, USB_PRODUCT_PEGATRON_RT2870,
- 0,
- "Pegatron",
- "RT2870",
- },
- {
- USB_VENDOR_PEGATRON, USB_PRODUCT_PEGATRON_RT3070,
- 0,
- "Pegatron",
- "RT3070",
- },
- {
- USB_VENDOR_PEGATRON, USB_PRODUCT_PEGATRON_RT3070_2,
- 0,
- "Pegatron",
- "RT3070",
- },
- {
- USB_VENDOR_PEGATRON, USB_PRODUCT_PEGATRON_RT3070_3,
- 0,
- "Pegatron",
- "RT3070",
- },
- {
- USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_SERIAL1,
- 0,
- "Peracom Networks",
- "Serial",
- },
- {
- USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET,
- 0,
- "Peracom Networks",
- "Ethernet",
- },
- {
- USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET3,
- 0,
- "Peracom Networks",
- "At Home Ethernet",
- },
- {
- USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2,
- 0,
- "Peracom Networks",
- "Ethernet",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DSS350,
- 0,
- "Philips",
- "DSS 350 Digital Speaker System",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DSS,
- 0,
- "Philips",
- "DSS XXX Digital Speaker System",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_HUB,
- 0,
- "Philips",
- "hub",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_PCA646VC,
- 0,
- "Philips",
- "PCA646VC PC Camera",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_PCVC680K,
- 0,
- "Philips",
- "PCVC680K Vesta Pro PC Camera",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DSS150,
- 0,
- "Philips",
- "DSS 150 Digital Speaker System",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_ACE1001,
- 0,
- "Philips",
- "AKTAKOM ACE-1001 cable",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SPE3030CC,
- 0,
- "Philips",
- "USB 2.0 External Disk",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_SNU5600,
- 0,
- "Philips",
- "SNU5600",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_UM10016,
- 0,
- "Philips",
- "ISP 1581 Hi-Speed USB MPEG2 Encoder Reference Kit",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_DIVAUSB,
- 0,
- "Philips",
- "DIVA USB mp3 player",
- },
- {
- USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_RT2870,
- 0,
- "Philips",
- "RT2870",
- },
- {
- USB_VENDOR_PHILIPSSEMI, USB_PRODUCT_PHILIPSSEMI_HUB1122,
- 0,
- "Philips Semiconductors",
- "HUB",
- },
- {
- USB_VENDOR_MEGATEC, USB_PRODUCT_MEGATEC_UPS,
- 0,
- "Megatec",
- "Phoenixtec protocol based UPS",
- },
- {
- USB_VENDOR_PIENGINEERING, USB_PRODUCT_PIENGINEERING_PS2USB,
- 0,
- "P.I. Engineering",
- "PS2 to Mac USB Adapter",
- },
- {
- USB_VENDOR_PLANEX, USB_PRODUCT_PLANEX_GW_US11H,
- 0,
- "Planex Communications",
- "GW-US11H WLAN",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GW_US11S,
- 0,
- "Planex Communications",
- "GW-US11S WLAN",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GW_US54GXS,
- 0,
- "Planex Communications",
- "GW-US54GXS WLAN",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54HP,
- 0,
- "Planex Communications",
- "GW-US54HP",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS300MINIS,
- 0,
- "Planex Communications",
- "GW-US300MiniS",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RT3070,
- 0,
- "Planex Communications",
- "RT3070",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54MINI2,
- 0,
- "Planex Communications",
- "GW-US54Mini2",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54SG,
- 0,
- "Planex Communications",
- "GW-US54SG",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GZL,
- 0,
- "Planex Communications",
- "GW-US54GZL",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUS54GD,
- 0,
- "Planex Communications",
- "GW-US54GD",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMM,
- 0,
- "Planex Communications",
- "GW-USMM",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_RT2870,
- 0,
- "Planex Communications",
- "RT2870",
- },
- {
- USB_VENDOR_PLANEX2, USB_PRODUCT_PLANEX2_GWUSMICRON,
- 0,
- "Planex Communications",
- "GW-USMicroN",
- },
- {
- USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54GZ,
- 0,
- "Planex Communications",
- "GW-US54GZ",
- },
- {
- USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GU1000T,
- 0,
- "Planex Communications",
- "GU-1000T",
- },
- {
- USB_VENDOR_PLANEX3, USB_PRODUCT_PLANEX3_GWUS54MINI,
- 0,
- "Planex Communications",
- "GW-US54Mini",
- },
- {
- USB_VENDOR_PLEXTOR, USB_PRODUCT_PLEXTOR_40_12_40U,
- 0,
- "Plextor",
- "PlexWriter 40/12/40U",
- },
- {
- USB_VENDOR_PLX, USB_PRODUCT_PLX_TESTBOARD,
- 0,
- "PLX",
- "test board",
- },
- {
- USB_VENDOR_PLX, USB_PRODUCT_PLX_CA42,
- 0,
- "PLX",
- "CA-42",
- },
- {
- USB_VENDOR_PNY, USB_PRODUCT_PNY_ATTACHE2,
- 0,
- "PNY",
- "USB 2.0 Flash Drive",
- },
- {
- USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA8,
- 0,
- "PortGear",
- "Ethernet",
- },
- {
- USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA9,
- 0,
- "PortGear",
- "Ethernet",
- },
- {
- USB_VENDOR_PORTSMITH, USB_PRODUCT_PORTSMITH_EEA,
- 0,
- "Portsmith",
- "Express Ethernet",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2X300,
- 0,
- "Primax Electronics",
- "G2-200 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E300,
- 0,
- "Primax Electronics",
- "G2E-300 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2300,
- 0,
- "Primax Electronics",
- "G2-300 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E3002,
- 0,
- "Primax Electronics",
- "G2E-300 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_9600,
- 0,
- "Primax Electronics",
- "Colorado USB 9600 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_600U,
- 0,
- "Primax Electronics",
- "Colorado 600u scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_6200,
- 0,
- "Primax Electronics",
- "Visioneer 6200 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_19200,
- 0,
- "Primax Electronics",
- "Colorado USB 19200 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_1200U,
- 0,
- "Primax Electronics",
- "Colorado 1200u scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G600,
- 0,
- "Primax Electronics",
- "G2-600 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_636I,
- 0,
- "Primax Electronics",
- "ReadyScan 636i",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2600,
- 0,
- "Primax Electronics",
- "G2-600 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_G2E600,
- 0,
- "Primax Electronics",
- "G2E-600 scanner",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_COMFORT,
- 0,
- "Primax Electronics",
- "Comfort",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_MOUSEINABOX,
- 0,
- "Primax Electronics",
- "Mouse-in-a-Box",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_PCGAUMS1,
- 0,
- "Primax Electronics",
- "Sony PCGA-UMS1",
- },
- {
- USB_VENDOR_PRIMAX, USB_PRODUCT_PRIMAX_HP_RH304AA,
- 0,
- "Primax Electronics",
- "HP RH304AA mouse",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301,
- 0,
- "Prolific Technology",
- "PL2301 Host-Host interface",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302,
- 0,
- "Prolific Technology",
- "PL2302 Host-Host interface",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ2,
- 0,
- "Prolific Technology",
- "PL2303 Serial (IODATA USB-RSAQ2)",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_ALLTRONIX_GPRS,
- 0,
- "Prolific Technology",
- "Alltronix ACM003U00 modem",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_ALDIGA_AL11U,
- 0,
- "Prolific Technology",
- "AlDiga AL-11U modem",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_MICROMAX_610U,
- 0,
- "Prolific Technology",
- "Micromax 610U",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_DCU11,
- 0,
- "Prolific Technology",
- "DCU-11 Phone Cable",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2303,
- 0,
- "Prolific Technology",
- "PL2303 Serial (ATEN/IOGEAR UC232A)",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2305,
- 0,
- "Prolific Technology",
- "Parallel printer",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_ATAPI4,
- 0,
- "Prolific Technology",
- "ATAPI-4 Controller",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501,
- 0,
- "Prolific Technology",
- "PL2501 Host-Host interface",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2506,
- 0,
- "Prolific Technology",
- "PL2506 USB to IDE Bridge",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_HCR331,
- 0,
- "Prolific Technology",
- "HCR331 Hybrid Card Reader",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PHAROS,
- 0,
- "Prolific Technology",
- "Prolific Pharos",
- },
- {
- USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_RSAQ3,
- 0,
- "Prolific Technology",
- "PL2303 Serial Adapter (IODATA USB-RSAQ3)",
- },
- {
- USB_VENDOR_PROLIFIC2, USB_PRODUCT_PROLIFIC2_PL2303,
- 0,
- "Prolific Technologies",
- "PL2303 Serial Adapter",
- },
- {
- USB_VENDOR_PUTERCOM, USB_PRODUCT_PUTERCOM_UPA100,
- 0,
- "Putercom",
- "USB-1284 BRIDGE",
- },
- {
- USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573,
- 0,
- "Qcom",
- "RT2573",
- },
- {
- USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_2,
- 0,
- "Qcom",
- "RT2573",
- },
- {
- USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2573_3,
- 0,
- "Qcom",
- "RT2573",
- },
- {
- USB_VENDOR_QCOM, USB_PRODUCT_QCOM_RT2870,
- 0,
- "Qcom",
- "RT2870",
- },
- {
- USB_VENDOR_QISDA, USB_PRODUCT_QISDA_H21_1,
- 0,
- "Qisda",
- "3G modem",
- },
- {
- USB_VENDOR_QISDA, USB_PRODUCT_QISDA_H21_2,
- 0,
- "Qisda",
- "3G modem",
- },
- {
- USB_VENDOR_QISDA, USB_PRODUCT_QISDA_H20_1,
- 0,
- "Qisda",
- "3G modem",
- },
- {
- USB_VENDOR_QISDA, USB_PRODUCT_QISDA_H20_2,
- 0,
- "Qisda",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMM, USB_PRODUCT_QUALCOMM_CDMA_MSM,
- 0,
- "Qualcomm",
- "CDMA Technologies MSM phone",
- },
- {
- USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_MF330,
- 0,
- "Qualcomm",
- "MF330",
- },
- {
- USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_RWT_FCT,
- 0,
- "Qualcomm",
- "RWT FCT-CDMA 2000 1xRTT modem",
- },
- {
- USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_CDMA_MSM,
- 0,
- "Qualcomm",
- "CDMA Technologies MSM modem",
- },
- {
- USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_AC8700,
- 0,
- "Qualcomm",
- "AC8700",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_CDMA_MSM,
- 0,
- "Qualcomm, Incorporated",
- "CDMA Technologies MSM modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0002,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0003,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0004,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0005,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0006,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0007,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0008,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0009,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E000A,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E000B,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E000C,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E000D,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E000E,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E000F,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0010,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0011,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0012,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0013,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0014,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_MF628,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_MF633R,
- 0,
- "Qualcomm, Incorporated",
- "ZTE WCDMA modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0017,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0018,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0019,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0020,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0021,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0022,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0023,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0024,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0025,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0026,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0027,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0028,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0029,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0030,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_MF626,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0032,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0033,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0037,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0039,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0042,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0043,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0048,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0049,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0051,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0052,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR2,
- 0,
- "Qualcomm, Incorporated",
- "USB ZTE Storage",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0054,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0055,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0057,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0058,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0059,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0060,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0061,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0062,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0063,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0064,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0066,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0069,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0070,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0073,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0076,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0078,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0082,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E0086,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_ZTE_STOR,
- 0,
- "Qualcomm, Incorporated",
- "USB ZTE Storage",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E2002,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_E2003,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_AC8710,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_AC2726,
- 0,
- "Qualcomm, Incorporated",
- "3G modem",
- },
- {
- USB_VENDOR_QUALCOMMINC, USB_PRODUCT_QUALCOMMINC_AC8700,
- 0,
- "Qualcomm, Incorporated",
- "CDMA 1xEVDO USB modem",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_RW6815_1,
- 0,
- "Quanta",
- "HP iPAQ rw6815",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_RT3070,
- 0,
- "Quanta",
- "RT3070",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_Q101_STOR,
- 0,
- "Quanta",
- "USB Q101 Storage",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_Q101,
- 0,
- "Quanta",
- "HSDPA modem",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_Q111,
- 0,
- "Quanta",
- "HSDPA modem",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_GLX,
- 0,
- "Quanta",
- "HSDPA modem",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_GKE,
- 0,
- "Quanta",
- "HSDPA modem",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_GLE,
- 0,
- "Quanta",
- "HSDPA modem",
- },
- {
- USB_VENDOR_QUANTA, USB_PRODUCT_QUANTA_RW6815R,
- 0,
- "Quanta",
- "HP iPAQ rw6815 RNDIS",
- },
- {
- USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N,
- 0,
- "Qtronix",
- "Scorpion-980N keyboard",
- },
- {
- USB_VENDOR_QUICKSHOT, USB_PRODUCT_QUICKSHOT_STRIKEPAD,
- 0,
- "Quickshot",
- "USB StrikePad",
- },
- {
- USB_VENDOR_RADIOSHACK, USB_PRODUCT_RADIOSHACK_USBCABLE,
- 0,
- "Radio Shack",
- "USB to Serial Cable",
- },
- {
- USB_VENDOR_RAINBOW, USB_PRODUCT_RAINBOW_IKEY2000,
- 0,
- "Rainbow Technologies",
- "i-Key 2000",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570,
- 0,
- "Ralink Technology",
- "RT2500USB Wireless Adapter",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2070,
- 0,
- "Ralink Technology",
- "RT2070",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_2,
- 0,
- "Ralink Technology",
- "RT2500USB Wireless Adapter",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573,
- 0,
- "Ralink Technology",
- "RT2501USB Wireless Adapter",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2671,
- 0,
- "Ralink Technology",
- "RT2601USB Wireless Adapter",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2770,
- 0,
- "Ralink Technology",
- "RT2770",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2870,
- 0,
- "Ralink Technology",
- "RT2870",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT3070,
- 0,
- "Ralink Technology",
- "RT3070",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT3071,
- 0,
- "Ralink Technology",
- "RT3071",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT3072,
- 0,
- "Ralink Technology",
- "RT3072",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT3370,
- 0,
- "Ralink Technology",
- "RT3370",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT3572,
- 0,
- "Ralink Technology",
- "RT3572",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT8070,
- 0,
- "Ralink Technology",
- "RT8070",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2570_3,
- 0,
- "Ralink Technology",
- "RT2500USB Wireless Adapter",
- },
- {
- USB_VENDOR_RALINK, USB_PRODUCT_RALINK_RT2573_2,
- 0,
- "Ralink Technology",
- "RT2501USB Wireless Adapter",
- },
- {
- USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60,
- 0,
- "RATOC Systems",
- "USB serial adapter REX-USB60",
- },
- {
- USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60F,
- 0,
- "RATOC Systems",
- "USB serial adapter REX-USB60F",
- },
- {
- USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USB20CRW,
- 0,
- "Realtek",
- "USB20CRW Card Reader",
- },
- {
- USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_USBKR100,
- 0,
- "Realtek",
- "USBKR100 USB Ethernet",
- },
- {
- USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8187,
- 0,
- "Realtek",
- "RTL8187 Wireless Adapter",
- },
- {
- USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8187B_0,
- 0,
- "Realtek",
- "RTL8187B Wireless Adapter",
- },
- {
- USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8187B_1,
- 0,
- "Realtek",
- "RTL8187B Wireless Adapter",
- },
- {
- USB_VENDOR_REALTEK, USB_PRODUCT_REALTEK_RTL8187B_2,
- 0,
- "Realtek",
- "RTL8187B Wireless Adapter",
- },
- {
- USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC2,
- 0,
- "Ricoh",
- "VGP-VCC2 Camera",
- },
- {
- USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC3,
- 0,
- "Ricoh",
- "VGP-VCC3 Camera",
- },
- {
- USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC2_2,
- 0,
- "Ricoh",
- "VGP-VCC2 Camera",
- },
- {
- USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC2_3,
- 0,
- "Ricoh",
- "VGP-VCC2 Camera",
- },
- {
- USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC7,
- 0,
- "Ricoh",
- "VGP-VCC7 Camera",
- },
- {
- USB_VENDOR_RICOH, USB_PRODUCT_RICOH_VGPVCC8,
- 0,
- "Ricoh",
- "VGP-VCC8 Camera",
- },
- {
- USB_VENDOR_REINERSCT, USB_PRODUCT_REINERSCT_CYBERJACK_ECOM,
- 0,
- "Reiner-SCT",
- "e-com cyberJack",
- },
- {
- USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM1,
- 0,
- "Roland",
- "UM-1 MIDI I/F",
- },
- {
- USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM880N,
- 0,
- "Roland",
- "EDIROL UM-880 MIDI I/F (native)",
- },
- {
- USB_VENDOR_ROLAND, USB_PRODUCT_ROLAND_UM880G,
- 0,
- "Roland",
- "EDIROL UM-880 MIDI I/F (generic)",
- },
- {
- USB_VENDOR_ROCKFIRE, USB_PRODUCT_ROCKFIRE_GAMEPAD,
- 0,
- "Rockfire",
- "gamepad 203USB",
- },
- {
- USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60,
- 0,
- "RATOC Systems",
- "REX-USB60",
- },
- {
- USB_VENDOR_RATOC, USB_PRODUCT_RATOC_REXUSB60F,
- 0,
- "RATOC Systems",
- "REX-USB60F",
- },
- {
- USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_USBSERIAL,
- 0,
- "Sagem",
- "USB-Serial Controller",
- },
- {
- USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG760A,
- 0,
- "Sagem",
- "XG-760A",
- },
- {
- USB_VENDOR_SAGEM, USB_PRODUCT_SAGEM_XG76NA,
- 0,
- "Sagem",
- "XG-76NA",
- },
- {
- USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_ML6060,
- 0,
- "Samsung Electronics",
- "ML-6060 laser printer",
- },
- {
- USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_YP_U2,
- 0,
- "Samsung Electronics",
- "YP-U2 MP3 Player",
- },
- {
- USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_YP_U4,
- 0,
- "Samsung Electronics",
- "YP-U4 MP3 Player",
- },
- {
- USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_I500,
- 0,
- "Samsung Electronics",
- "I500 Palm USB Phone",
- },
- {
- USB_VENDOR_SAMSUNG, USB_PRODUCT_SAMSUNG_I330,
- 0,
- "Samsung Electronics",
- "I330 phone cradle",
- },
- {
- USB_VENDOR_SAMSUNG2, USB_PRODUCT_SAMSUNG2_RT2870_1,
- 0,
- "Samsung Electronics",
- "RT2870",
- },
- {
- USB_VENDOR_SAMSUNG_TECHWIN, USB_PRODUCT_SAMSUNG_TECHWIN_DIGIMAX_410,
- 0,
- "Samsung Techwin",
- "Digimax 410",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR05A,
- 0,
- "SanDisk",
- "ImageMate SDDR-05a",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR31,
- 0,
- "SanDisk",
- "ImageMate SDDR-31",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR05,
- 0,
- "SanDisk",
- "ImageMate SDDR-05",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR12,
- 0,
- "SanDisk",
- "ImageMate SDDR-12",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR09,
- 0,
- "SanDisk",
- "ImageMate SDDR-09",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDDR75,
- 0,
- "SanDisk",
- "ImageMate SDDR-75",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ2_256,
- 0,
- "SanDisk",
- "Cruzer Mini 256MB",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_128,
- 0,
- "SanDisk",
- "Cruzer Micro 128MB",
- },
- {
- USB_VENDOR_SANDISK, USB_PRODUCT_SANDISK_SDCZ4_256,
- 0,
- "SanDisk",
- "Cruzer Micro 256MB",
- },
- {
- USB_VENDOR_SANWA, USB_PRODUCT_SANWA_KB_USB2,
- 0,
- "Sanwa Electric Instrument Co., Ltd.",
- "KB-USB2 multimeter cable",
- },
- {
- USB_VENDOR_SANYO, USB_PRODUCT_SANYO_SCP4900,
- 0,
- "Sanyo Electric",
- "Sanyo SCP-4900 USB Phone",
- },
- {
- USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_SL11R,
- 0,
- "ScanLogic",
- "SL11R IDE Adapter",
- },
- {
- USB_VENDOR_SCANLOGIC, USB_PRODUCT_SCANLOGIC_336CX,
- 0,
- "ScanLogic",
- "Phantom 336CX - C3 scanner",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT2870_3,
- 0,
- "Senao",
- "RT2870",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT2870_4,
- 0,
- "Senao",
- "RT2870",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_NUB8301,
- 0,
- "Senao",
- "NUB-8301",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT2870_1,
- 0,
- "Senao",
- "RT2870",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT2870_2,
- 0,
- "Senao",
- "RT2870",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT3070,
- 0,
- "Senao",
- "RT3070",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT3071,
- 0,
- "Senao",
- "RT3071",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT3072_1,
- 0,
- "Senao",
- "RT3072",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT3072_2,
- 0,
- "Senao",
- "RT3072",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT3072_3,
- 0,
- "Senao",
- "RT3072",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT3072_4,
- 0,
- "Senao",
- "RT3072",
- },
- {
- USB_VENDOR_SENAO, USB_PRODUCT_SENAO_RT3072_5,
- 0,
- "Senao",
- "RT3072",
- },
- {
- USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_ST268,
- 0,
- "ShanTou",
- "ST268",
- },
- {
- USB_VENDOR_SHANTOU, USB_PRODUCT_SHANTOU_DM9601,
- 0,
- "ShanTou",
- "DM 9601",
- },
- {
- USB_VENDOR_SHARK, USB_PRODUCT_SHARK_PA,
- 0,
- "Shark",
- "Pocket Adapter",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500,
- 0,
- "Sharp",
- "Zaurus SL-5500 PDA",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300,
- 0,
- "Sharp",
- "Zaurus SL-A300 PDA",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600,
- 0,
- "Sharp",
- "Zaurus SL-5600 PDA",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700,
- 0,
- "Sharp",
- "Zaurus SL-C700 PDA",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750,
- 0,
- "Sharp",
- "Zaurus SL-C750 PDA",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_WZERO3ES,
- 0,
- "Sharp",
- "W-ZERO3 ES Smartphone",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_WZERO3ADES,
- 0,
- "Sharp",
- "Advanced W-ZERO3 ES Smartphone",
- },
- {
- USB_VENDOR_SHARP, USB_PRODUCT_SHARP_WILLCOM03,
- 0,
- "Sharp",
- "WILLCOM03",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSB,
- 0,
- "Shuttle Technology",
- "E-USB Bridge",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSCSI,
- 0,
- "Shuttle Technology",
- "eUSCSI Bridge",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_SDDR09,
- 0,
- "Shuttle Technology",
- "ImageMate SDDR09",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBCFSM,
- 0,
- "Shuttle Technology",
- "eUSB SmartMedia / CompactFlash Adapter",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_ZIOMMC,
- 0,
- "Shuttle Technology",
- "eUSB MultiMediaCard Adapter",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_HIFD,
- 0,
- "Shuttle Technology",
- "Sony Hifd",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBATAPI,
- 0,
- "Shuttle Technology",
- "eUSB ATA/ATAPI Adapter",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CF,
- 0,
- "Shuttle Technology",
- "eUSB CompactFlash Adapter",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSCSI_B,
- 0,
- "Shuttle Technology",
- "eUSCSI Bridge",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSCSI_C,
- 0,
- "Shuttle Technology",
- "eUSCSI Bridge",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_CDRW,
- 0,
- "Shuttle Technology",
- "CD-RW Device",
- },
- {
- USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_EUSBORCA,
- 0,
- "Shuttle Technology",
- "eUSB ORCA Quad Reader",
- },
- {
- USB_VENDOR_SIEMENS, USB_PRODUCT_SIEMENS_SPEEDSTREAM,
- 0,
- "Siemens",
- "SpeedStream",
- },
- {
- USB_VENDOR_SIEMENS, USB_PRODUCT_SIEMENS_SPEEDSTREAM22,
- 0,
- "Siemens",
- "SpeedStream 1022",
- },
- {
- USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_WLL013,
- 0,
- "Siemens",
- "WLL013",
- },
- {
- USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_ES75,
- 0,
- "Siemens",
- "GSM module MC35",
- },
- {
- USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_WL54G,
- 0,
- "Siemens",
- "54g USB Network Adapter",
- },
- {
- USB_VENDOR_SIEMENS3, USB_PRODUCT_SIEMENS3_SX1,
- 0,
- "Siemens",
- "SX1",
- },
- {
- USB_VENDOR_SIEMENS3, USB_PRODUCT_SIEMENS3_X65,
- 0,
- "Siemens",
- "X65",
- },
- {
- USB_VENDOR_SIEMENS3, USB_PRODUCT_SIEMENS3_X75,
- 0,
- "Siemens",
- "X75",
- },
- {
- USB_VENDOR_SIEMENS3, USB_PRODUCT_SIEMENS3_EF81,
- 0,
- "Siemens",
- "EF81",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5625,
- 0,
- "Sierra Wireless",
- "EM5625",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720_2,
- 0,
- "Sierra Wireless",
- "MC5720",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5725,
- 0,
- "Sierra Wireless",
- "MC5725",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 580",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD595,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 595",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 595U",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC597E,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 597E",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_EM5725,
- 0,
- "Sierra Wireless",
- "EM5725",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C597,
- 0,
- "Sierra Wireless",
- "Sierra Wireless Compass 597",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5727,
- 0,
- "Sierra Wireless",
- "MC5727",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_T598,
- 0,
- "Sierra Wireless",
- "T598",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_T11,
- 0,
- "Sierra Wireless",
- "T11",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC402,
- 0,
- "Sierra Wireless",
- "AC402",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5728,
- 0,
- "Sierra Wireless",
- "MC5728",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_E0029,
- 0,
- "Sierra Wireless",
- "E0029",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD580,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 580",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC595U,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 595U",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5720,
- 0,
- "Sierra Wireless",
- "MC5720 Wireless Modem",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MINI5725,
- 0,
- "Sierra Wireless",
- "Sierra Wireless miniPCI 5275",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC5727_2,
- 0,
- "Sierra Wireless",
- "MC5727",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_2,
- 0,
- "Sierra Wireless",
- "MC8755",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765,
- 0,
- "Sierra Wireless",
- "MC8765",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755,
- 0,
- "Sierra Wireless",
- "MC8755",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765_2,
- 0,
- "Sierra Wireless",
- "MC8765",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_4,
- 0,
- "Sierra Wireless",
- "MC8755",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8765_3,
- 0,
- "Sierra Wireless",
- "MC8765",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U,
- 0,
- "Sierra Wireless",
- "AC875U HSDPA USB Modem",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8755_3,
- 0,
- "Sierra Wireless",
- "MC8755 HSDPA",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775_2,
- 0,
- "Sierra Wireless",
- "MC8775",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8775,
- 0,
- "Sierra Wireless",
- "MC8775",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 875",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875U_2,
- 0,
- "Sierra Wireless",
- "AC875U",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC875E,
- 0,
- "Sierra Wireless",
- "AC875E",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780,
- 0,
- "Sierra Wireless",
- "MC8780",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781,
- 0,
- "Sierra Wireless",
- "MC8781",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780_2,
- 0,
- "Sierra Wireless",
- "MC8780",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781_2,
- 0,
- "Sierra Wireless",
- "MC8781",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8780_3,
- 0,
- "Sierra Wireless",
- "MC8780",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8781_3,
- 0,
- "Sierra Wireless",
- "MC8781",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8785,
- 0,
- "Sierra Wireless",
- "MC8785",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8785_2,
- 0,
- "Sierra Wireless",
- "MC8785",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8790,
- 0,
- "Sierra Wireless",
- "MC8790",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8791,
- 0,
- "Sierra Wireless",
- "MC8791",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8792,
- 0,
- "Sierra Wireless",
- "MC8792",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 880",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 881",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880E,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 880E",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881E,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 881E",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC880U,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 880U",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC881U,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 881U",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC885E,
- 0,
- "Sierra Wireless",
- "AC885E",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC885E_2,
- 0,
- "Sierra Wireless",
- "AC885E",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AC885U,
- 0,
- "Sierra Wireless",
- "Sierra Wireless AirCard 885U",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C888,
- 0,
- "Sierra Wireless",
- "C888",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_C22,
- 0,
- "Sierra Wireless",
- "C22",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_E6892,
- 0,
- "Sierra Wireless",
- "E6892",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_E6893,
- 0,
- "Sierra Wireless",
- "E6893",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_MC8700,
- 0,
- "Sierra Wireless",
- "MC8700",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_AIRCARD875,
- 0,
- "Sierra Wireless",
- "Aircard 875 HSDPA",
- },
- {
- USB_VENDOR_SIERRA, USB_PRODUCT_SIERRA_TRUINSTALL,
- 0,
- "Sierra Wireless",
- "Aircard Tru Installer",
- },
- {
- USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_WBT_3052,
- 0,
- "Sigmatel",
- "WBT-3052 IrDA/USB Bridge",
- },
- {
- USB_VENDOR_SIGMATEL, USB_PRODUCT_SIGMATEL_I_BEAD100,
- 0,
- "Sigmatel",
- "i-Bead 100 MP3 Player",
- },
- {
- USB_VENDOR_SIIG, USB_PRODUCT_SIIG_DIGIFILMREADER,
- 0,
- "SIIG",
- "DigiFilm-Combo Reader",
- },
- {
- USB_VENDOR_SIIG, USB_PRODUCT_SIIG_WINTERREADER,
- 0,
- "SIIG",
- "WINTERREADER Reader",
- },
- {
- USB_VENDOR_SIIG2, USB_PRODUCT_SIIG2_USBTOETHER,
- 0,
- "SIIG",
- "USB TO Ethernet",
- },
- {
- USB_VENDOR_SIIG2, USB_PRODUCT_SIIG2_US2308,
- 0,
- "SIIG",
- "Serial",
- },
- {
- USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_U2E,
- 0,
- "Silicom",
- "U2E",
- },
- {
- USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_GPE,
- 0,
- "Silicom",
- "Psion Gold Port Ethernet",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_VSTABI,
- 0,
- "Silicon Labs",
- "Vstabi",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARKHAM_DS101_M,
- 0,
- "Silicon Labs",
- "Arkham DS101 Monitor",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARKHAM_DS101_A,
- 0,
- "Silicon Labs",
- "Arkham DS101 Adapter",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BSM7DUSB,
- 0,
- "Silicon Labs",
- "BSM7-D-USB",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_POLOLU,
- 0,
- "Silicon Labs",
- "Pololu Serial",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CYGNAL_DEBUG,
- 0,
- "Silicon Labs",
- "Cygnal Debug Adapter",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SB_PARAMOUNT_ME,
- 0,
- "Silicon Labs",
- "Software Bisque Paramount ME",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SAEL,
- 0,
- "Silicon Labs",
- "SA-EL USB",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_GSM2228,
- 0,
- "Silicon Labs",
- "Enfora GSM2228 USB",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARGUSISP,
- 0,
- "Silicon Labs",
- "Argussoft ISP",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_IMS_USB_RS422,
- 0,
- "Silicon Labs",
- "IMS USB-RS422",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CRUMB128,
- 0,
- "Silicon Labs",
- "Crumb128 board",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_DEGREE,
- 0,
- "Silicon Labs",
- "Degree Controls Inc",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TRACIENT,
- 0,
- "Silicon Labs",
- "Tracient RFID",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TRAQMATE,
- 0,
- "Silicon Labs",
- "Track Systems Traqmate",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_SUUNTO,
- 0,
- "Silicon Labs",
- "Suunto Sports Instrument",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ARYGON_MIFARE,
- 0,
- "Silicon Labs",
- "Arygon Mifare RFID reader",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BURNSIDE,
- 0,
- "Silicon Labs",
- "Burnside Telecon Deskmobile",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TAMSMASTER,
- 0,
- "Silicon Labs",
- "Tams Master Easy Control",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_WMRBATT,
- 0,
- "Silicon Labs",
- "WMR RIGblaster Plug&Play",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_WMRRIGBLASTER,
- 0,
- "Silicon Labs",
- "WMR RIGblaster Plug&Play",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_WMRRIGTALK,
- 0,
- "Silicon Labs",
- "WMR RIGtalk RT1",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_HELICOM,
- 0,
- "Silicon Labs",
- "Helicomm IP-Link 1220-DVM",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AVIT_USB_TTL,
- 0,
- "Silicon Labs",
- "AVIT Research USB-TTL",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_MJS_TOSLINK,
- 0,
- "Silicon Labs",
- "MJS USB-TOSLINk",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_WAVIT,
- 0,
- "Silicon Labs",
- "ThinkOptics WavIt",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_MSD_DASHHAWK,
- 0,
- "Silicon Labs",
- "MSD DashHawk",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_INSYS_MODEM,
- 0,
- "Silicon Labs",
- "INSYS Modem",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_JTAG,
- 0,
- "Silicon Labs",
- "Lipowsky Baby-JTAG",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_LIN,
- 0,
- "Silicon Labs",
- "Lipowsky Baby-LIN",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AEROCOMM,
- 0,
- "Silicon Labs",
- "Aerocomm Radio",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_ZEPHYR_BIO,
- 0,
- "Silicon Labs",
- "Zephyr Bioharness",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_EMS_C1007,
- 0,
- "Silicon Labs",
- "EMS C1007 HF RFID controller",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_LIPOWSKY_HARP,
- 0,
- "Silicon Labs",
- "Lipowsky HARP-1",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_C2_EDGE_MODEM,
- 0,
- "Silicon Labs",
- "Commander 2 EDGE(GSM) Modem",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CYGNAL_GPS,
- 0,
- "Silicon Labs",
- "Cygnal Fasttrax GPS",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_TELEGESYS_ETRX2,
- 0,
- "Silicon Labs",
- "Telegesys ETRX2USB",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_PROCYON_AVS,
- 0,
- "Silicon Labs",
- "Procyon AVS",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_MC35PU,
- 0,
- "Silicon Labs",
- "MC35pu",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CYGNAL,
- 0,
- "Silicon Labs",
- "Cygnal",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_AMBER_AMB2560,
- 0,
- "Silicon Labs",
- "Amber Wireless AMB2560",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_KYOCERA_GPS,
- 0,
- "Silicon Labs",
- "Kyocera GPS",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_BEI_VCP,
- 0,
- "Silicon Labs",
- "BEI USB Sensor (VCP)",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP2102,
- 0,
- "Silicon Labs",
- "SILABS USB UART",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_CP210X_2,
- 0,
- "Silicon Labs",
- "CP210x Serial",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_INFINITY_MIC,
- 0,
- "Silicon Labs",
- "Infinity GPS-MIC-1 Radio Monophone",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_USBSCOPE50,
- 0,
- "Silicon Labs",
- "USBscope50",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_USBWAVE12,
- 0,
- "Silicon Labs",
- "USBwave12",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_USBPULSE100,
- 0,
- "Silicon Labs",
- "USBpulse100",
- },
- {
- USB_VENDOR_SILABS, USB_PRODUCT_SILABS_USBCOUNT50,
- 0,
- "Silicon Labs",
- "USBcount50",
- },
- {
- USB_VENDOR_SILABS2, USB_PRODUCT_SILABS2_DCU11CLONE,
- 0,
- "SILABS2",
- "DCU-11 clone",
- },
- {
- USB_VENDOR_SILABS3, USB_PRODUCT_SILABS3_GPRS_MODEM,
- 0,
- "Silicon Labs",
- "GPRS Modem",
- },
- {
- USB_VENDOR_SILABS4, USB_PRODUCT_SILABS4_100EU_MODEM,
- 0,
- "Silicon Labs",
- "GPRS Modem 100EU",
- },
- {
- USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPH_NF,
- 0,
- "Silicon Portals",
- "YAP Phone (no firmware)",
- },
- {
- USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE,
- 0,
- "Silicon Portals",
- "YAP Phone",
- },
- {
- USB_VENDOR_SIRIUS, USB_PRODUCT_SIRIUS_ROADSTER,
- 0,
- "Sirius Technologies",
- "NetComm Roadster II 56 USB",
- },
- {
- USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_LN029,
- 0,
- "Sitecom",
- "USB 2.0 Ethernet",
- },
- {
- USB_VENDOR_SITECOM, USB_PRODUCT_SITECOM_SERIAL,
- 0,
- "Sitecom",
- "USB to serial cable (v2)",
- },
- {
- USB_VENDOR_SITECOM2, USB_PRODUCT_SITECOM2_WL022,
- 0,
- "Sitecom",
- "WL-022",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT2870_1,
- 0,
- "Sitecom Europe",
- "RT2870",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL168V1,
- 0,
- "Sitecom Europe",
- "WL-168 v1",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL168V4,
- 0,
- "Sitecom Europe",
- "WL-168 v4",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT2870_2,
- 0,
- "Sitecom Europe",
- "RT2870",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT2870_3,
- 0,
- "Sitecom Europe",
- "RT2870",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT2870_4,
- 0,
- "Sitecom Europe",
- "RT2870",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT2770,
- 0,
- "Sitecom Europe",
- "RT2770",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3070_2,
- 0,
- "Sitecom Europe",
- "RT3070",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3070_3,
- 0,
- "Sitecom Europe",
- "RT3070",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3070_4,
- 0,
- "Sitecom Europe",
- "RT3070",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3070,
- 0,
- "Sitecom Europe",
- "RT3070",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL608,
- 0,
- "Sitecom Europe",
- "WL-608",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3071,
- 0,
- "Sitecom Europe",
- "RT3071",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3072_1,
- 0,
- "Sitecom Europe",
- "RT3072",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3072_2,
- 0,
- "Sitecom Europe",
- "RT3072",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3072_3,
- 0,
- "Sitecom Europe",
- "RT3072",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3072_4,
- 0,
- "Sitecom Europe",
- "RT3072",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3072_5,
- 0,
- "Sitecom Europe",
- "RT3072",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_RT3072_6,
- 0,
- "Sitecom Europe",
- "RT3072",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_LN028,
- 0,
- "Sitecom Europe",
- "LN-028",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113,
- 0,
- "Sitecom Europe",
- "WL-113",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_ZD1211B,
- 0,
- "Sitecom Europe",
- "ZD1211B",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL172,
- 0,
- "Sitecom Europe",
- "WL-172",
- },
- {
- USB_VENDOR_SITECOMEU, USB_PRODUCT_SITECOMEU_WL113R2,
- 0,
- "Sitecom Europe",
- "WL-113 rev 2",
- },
- {
- USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_MD_7425,
- 0,
- "Skanhex Technology, Inc.",
- "MD 7425 Camera",
- },
- {
- USB_VENDOR_SKANHEX, USB_PRODUCT_SKANHEX_SX_520Z,
- 0,
- "Skanhex Technology, Inc.",
- "SX 520z Camera",
- },
- {
- USB_VENDOR_SMART, USB_PRODUCT_SMART_PL2303,
- 0,
- "Smart Technologies",
- "Serial adapter",
- },
- {
- USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK,
- 0,
- "SmartBridges",
- "SmartLink USB Ethernet",
- },
- {
- USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTNIC,
- 0,
- "SmartBridges",
- "smartNIC 2 PnP Ethernet",
- },
- {
- USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB,
- 0,
- "Standard Microsystems",
- "10Mbps Ethernet",
- },
- {
- USB_VENDOR_SMC, USB_PRODUCT_SMC_2202USB,
- 0,
- "Standard Microsystems",
- "10/100 Ethernet",
- },
- {
- USB_VENDOR_SMC, USB_PRODUCT_SMC_2206USB,
- 0,
- "Standard Microsystems",
- "EZ Connect USB Ethernet",
- },
- {
- USB_VENDOR_SMC, USB_PRODUCT_SMC_2862WG,
- 0,
- "Standard Microsystems",
- "EZ Connect Wireless Adapter",
- },
- {
- USB_VENDOR_SMC2, USB_PRODUCT_SMC2_2020HUB,
- 0,
- "Standard Microsystems",
- "USB Hub",
- },
- {
- USB_VENDOR_SMC2, USB_PRODUCT_SMC2_2514HUB,
- 0,
- "Standard Microsystems",
- "USB Hub",
- },
- {
- USB_VENDOR_SMC3, USB_PRODUCT_SMC3_2662WUSB,
- 0,
- "Standard Microsystems",
- "2662W-AR Wireless",
- },
- {
- USB_VENDOR_SOHOWARE, USB_PRODUCT_SOHOWARE_NUB100,
- 0,
- "SOHOware",
- "10/100 USB Ethernet",
- },
- {
- USB_VENDOR_SOHOWARE, USB_PRODUCT_SOHOWARE_NUB110,
- 0,
- "SOHOware",
- "10/100 USB Ethernet",
- },
- {
- USB_VENDOR_SOLIDYEAR, USB_PRODUCT_SOLIDYEAR_KEYBOARD,
- 0,
- "Solid Year",
- "Solid Year USB keyboard",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_DSC,
- 0,
- "Sony",
- "DSC cameras",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_NW_MS7,
- 0,
- "Sony",
- "Memorystick NW-MS7",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_PORTABLE_HDD_V2,
- 0,
- "Sony",
- "Portable USB Harddrive V2",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_MSACUS1,
- 0,
- "Sony",
- "Memorystick MSAC-US1",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_HANDYCAM,
- 0,
- "Sony",
- "Handycam",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_MSC,
- 0,
- "Sony",
- "MSC memory stick slot",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_35,
- 0,
- "Sony",
- "Sony Clie v3.5",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_PEG_N760C,
- 0,
- "Sony",
- "PEG N760c Memorystick",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40,
- 0,
- "Sony",
- "Sony Clie v4.0",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_MS_MSC_U03,
- 0,
- "Sony",
- "Memorystick MSC-U03",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_40_MS,
- 0,
- "Sony",
- "Sony Clie v4.0 Memory Stick slot",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_S360,
- 0,
- "Sony",
- "Sony Clie s360",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41_MS,
- 0,
- "Sony",
- "Sony Clie v4.1 Memory Stick slot",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_41,
- 0,
- "Sony",
- "Sony Clie v4.1",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_NX60,
- 0,
- "Sony",
- "Sony Clie nx60",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TH55,
- 0,
- "Sony",
- "Sony Clie th55",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_CLIE_TJ37,
- 0,
- "Sony",
- "Sony Clie tj37",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_RF_RECEIVER,
- 0,
- "Sony",
- "Sony RF mouse/kbd Receiver VGP-WRC1",
- },
- {
- USB_VENDOR_SONY, USB_PRODUCT_SONY_QN3,
- 0,
- "Sony",
- "Sony QN3 CMD-Jxx phone cable",
- },
- {
- USB_VENDOR_SONYERICSSON, USB_PRODUCT_SONYERICSSON_DCU10,
- 0,
- "Sony Ericsson",
- "DCU-10 Phone Data Cable",
- },
- {
- USB_VENDOR_SONYERICSSON, USB_PRODUCT_SONYERICSSON_DATAPILOT,
- 0,
- "Sony Ericsson",
- "Datapilot Phone Cable",
- },
- {
- USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8,
- 0,
- "SOURCENEXT",
- "KeikaiDenwa 8",
- },
- {
- USB_VENDOR_SOURCENEXT, USB_PRODUCT_SOURCENEXT_KEIKAI8_CHG,
- 0,
- "SOURCENEXT",
- "KeikaiDenwa 8 with charger",
- },
- {
- USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2573,
- 0,
- "SparkLAN",
- "RT2573",
- },
- {
- USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT2870_1,
- 0,
- "SparkLAN",
- "RT2870",
- },
- {
- USB_VENDOR_SPARKLAN, USB_PRODUCT_SPARKLAN_RT3070,
- 0,
- "SparkLAN",
- "RT3070",
- },
- {
- USB_VENDOR_SPEEDDRAGON, USB_PRODUCT_SPEEDDRAGON_MS3303H,
- 0,
- "Speed Dragon Multimedia",
- "MS3303H Serial",
- },
- {
- USB_VENDOR_SPHAIRON, USB_PRODUCT_SPHAIRON_UB801R,
- 0,
- "Sphairon Access Systems GmbH",
- "UB801R",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_ZEROCD,
- 0,
- "Stelera Wireless",
- "Zerocd Installer",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_C105,
- 0,
- "Stelera Wireless",
- "Stelera/Bandrish C105 USB",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1003,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1004,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1005,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1006,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1007,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1008,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1009,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E100A,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E100B,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E100C,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E100D,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E100E,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E100F,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1010,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1011,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_STELERA, USB_PRODUCT_STELERA_E1012,
- 0,
- "Stelera Wireless",
- "3G modem",
- },
- {
- USB_VENDOR_MPMAN, USB_PRODUCT_MPMAN_MPF400_1,
- 0,
- "MpMan",
- "MPF400 Music Player 1Go",
- },
- {
- USB_VENDOR_MPMAN, USB_PRODUCT_MPMAN_MPF400_2,
- 0,
- "MpMan",
- "MPF400 Music Player 2Go",
- },
- {
- USB_VENDOR_STMICRO, USB_PRODUCT_STMICRO_BIOCPU,
- 0,
- "STMicroelectronics",
- "Biometric Coprocessor",
- },
- {
- USB_VENDOR_STMICRO, USB_PRODUCT_STMICRO_COMMUNICATOR,
- 0,
- "STMicroelectronics",
- "USB Communicator",
- },
- {
- USB_VENDOR_STSN, USB_PRODUCT_STSN_STSN0001,
- 0,
- "STSN",
- "Internet Access Device",
- },
- {
- USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_DS96L,
- 0,
- "SUN Corporation",
- "SUNTAC U-Cable type D2",
- },
- {
- USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_PS64P1,
- 0,
- "SUN Corporation",
- "SUNTAC U-Cable type P1",
- },
- {
- USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_VS10U,
- 0,
- "SUN Corporation",
- "SUNTAC Slipper U",
- },
- {
- USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_IS96U,
- 0,
- "SUN Corporation",
- "SUNTAC Ir-Trinity",
- },
- {
- USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS64LX,
- 0,
- "SUN Corporation",
- "SUNTAC U-Cable type A3",
- },
- {
- USB_VENDOR_SUNTAC, USB_PRODUCT_SUNTAC_AS144L4,
- 0,
- "SUN Corporation",
- "SUNTAC U-Cable type A4",
- },
- {
- USB_VENDOR_SUN, USB_PRODUCT_SUN_KEYBOARD_TYPE_6,
- 0,
- "Sun Microsystems",
- "Type 6 USB keyboard",
- },
- {
- USB_VENDOR_SUN, USB_PRODUCT_SUN_KEYBOARD_TYPE_7,
- 0,
- "Sun Microsystems",
- "Type 7 USB keyboard",
- },
- {
- USB_VENDOR_SUN, USB_PRODUCT_SUN_MOUSE,
- 0,
- "Sun Microsystems",
- "Type 6 USB mouse",
- },
- {
- USB_VENDOR_SUN, USB_PRODUCT_SUN_KBD_HUB,
- 0,
- "Sun Microsystems",
- "Kbd Hub",
- },
- {
- USB_VENDOR_SUPERTOP, USB_PRODUCT_SUPERTOP_IDE,
- 0,
- "Super Top",
- "USB-IDE",
- },
- {
- USB_VENDOR_SYNTECH, USB_PRODUCT_SYNTECH_CPT8001C,
- 0,
- "Syntech Information",
- "CPT-8001C Barcode scanner",
- },
- {
- USB_VENDOR_SYNTECH, USB_PRODUCT_SYNTECH_CYPHERLAB100,
- 0,
- "Syntech Information",
- "CipherLab USB Barcode Scanner",
- },
- {
- USB_VENDOR_TECLAST, USB_PRODUCT_TECLAST_TLC300,
- 0,
- "Teclast",
- "USB Media Player",
- },
- {
- USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_SUPRAEXPRESS56K,
- 0,
- "Diamond (Supra)",
- "Supra Express 56K modem",
- },
- {
- USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_SUPRA2890,
- 0,
- "Diamond (Supra)",
- "SupraMax 2890 56K Modem",
- },
- {
- USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO600USB,
- 0,
- "Diamond (Supra)",
- "Rio 600 USB",
- },
- {
- USB_VENDOR_DIAMOND2, USB_PRODUCT_DIAMOND2_RIO800USB,
- 0,
- "Diamond (Supra)",
- "Rio 800 USB",
- },
- {
- USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_EP9001G2A,
- 0,
- "Surecom Technology",
- "EP-9001-G rev 2A",
- },
- {
- USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2570,
- 0,
- "Surecom Technology",
- "RT2570",
- },
- {
- USB_VENDOR_SURECOM, USB_PRODUCT_SURECOM_RT2573,
- 0,
- "Surecom Technology",
- "RT2573",
- },
- {
- USB_VENDOR_SWEEX, USB_PRODUCT_SWEEX_ZD1211,
- 0,
- "Sweex",
- "ZD1211",
- },
- {
- USB_VENDOR_SWEEX2, USB_PRODUCT_SWEEX2_LW153,
- 0,
- "Sweex",
- "LW153",
- },
- {
- USB_VENDOR_SWEEX2, USB_PRODUCT_SWEEX2_LW303,
- 0,
- "Sweex",
- "LW303",
- },
- {
- USB_VENDOR_SWEEX2, USB_PRODUCT_SWEEX2_LW313,
- 0,
- "Sweex",
- "LW313",
- },
- {
- USB_VENDOR_SYSTEMTALKS, USB_PRODUCT_SYSTEMTALKS_SGCX2UL,
- 0,
- "System Talks",
- "SGC-X2UL",
- },
- {
- USB_VENDOR_TAPWAVE, USB_PRODUCT_TAPWAVE_ZODIAC,
- 0,
- "Tapwave",
- "Zodiac",
- },
- {
- USB_VENDOR_TAUGA, USB_PRODUCT_TAUGA_CAMERAMATE,
- 0,
- "Taugagreining HF",
- "CameraMate (DPCM_USB)",
- },
- {
- USB_VENDOR_TCTMOBILE, USB_PRODUCT_TCTMOBILE_X060S,
- 0,
- "TCT Mobile",
- "X060S 3G modem",
- },
- {
- USB_VENDOR_TCTMOBILE, USB_PRODUCT_TCTMOBILE_X080S,
- 0,
- "TCT Mobile",
- "X080S 3G modem",
- },
- {
- USB_VENDOR_TDK, USB_PRODUCT_TDK_UPA9664,
- 0,
- "TDK",
- "USB-PDC Adapter UPA9664",
- },
- {
- USB_VENDOR_TDK, USB_PRODUCT_TDK_UCA1464,
- 0,
- "TDK",
- "USB-cdmaOne Adapter UCA1464",
- },
- {
- USB_VENDOR_TDK, USB_PRODUCT_TDK_UHA6400,
- 0,
- "TDK",
- "USB-PHS Adapter UHA6400",
- },
- {
- USB_VENDOR_TDK, USB_PRODUCT_TDK_UPA6400,
- 0,
- "TDK",
- "USB-PHS Adapter UPA6400",
- },
- {
- USB_VENDOR_TDK, USB_PRODUCT_TDK_BT_DONGLE,
- 0,
- "TDK",
- "Bluetooth USB dongle",
- },
- {
- USB_VENDOR_TEAC, USB_PRODUCT_TEAC_FD05PUB,
- 0,
- "TEAC",
- "FD-05PUB floppy",
- },
- {
- USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_QUICKWLAN,
- 0,
- "Tekram Technology",
- "QuickWLAN",
- },
- {
- USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_1,
- 0,
- "Tekram Technology",
- "ZD1211",
- },
- {
- USB_VENDOR_TEKRAM, USB_PRODUCT_TEKRAM_ZD1211_2,
- 0,
- "Tekram Technology",
- "ZD1211",
- },
- {
- USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1,
- 0,
- "Telex Communications",
- "Enhanced USB Microphone",
- },
- {
- USB_VENDOR_TELIT, USB_PRODUCT_TELIT_UC864E,
- 0,
- "Telit",
- "UC864E 3G modem",
- },
- {
- USB_VENDOR_TELIT, USB_PRODUCT_TELIT_UC864G,
- 0,
- "Telit",
- "UC864G 3G modem",
- },
- {
- USB_VENDOR_TENX, USB_PRODUCT_TENX_UAUDIO0,
- 0,
- "Ten X Technology, Inc.",
- "USB audio headset",
- },
- {
- USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41,
- 0,
- "Texas Instruments",
- "UT-USB41 hub",
- },
- {
- USB_VENDOR_TI, USB_PRODUCT_TI_TUSB2046,
- 0,
- "Texas Instruments",
- "TUSB2046 hub",
- },
- {
- USB_VENDOR_THRUST, USB_PRODUCT_THRUST_FUSION_PAD,
- 0,
- "Thrustmaster",
- "Fusion Digital Gamepad",
- },
- {
- USB_VENDOR_TLAYTECH, USB_PRODUCT_TLAYTECH_TEU800,
- 0,
- "Tlay Tech",
- "TEU800 3G modem",
- },
- {
- USB_VENDOR_TOPRE, USB_PRODUCT_TOPRE_HHKB,
- 0,
- "Topre Corporation",
- "HHKB Professional",
- },
- {
- USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_POCKETPC_E740,
- 0,
- "Toshiba",
- "PocketPC e740",
- },
- {
- USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_RT3070,
- 0,
- "Toshiba",
- "RT3070",
- },
- {
- USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_G450,
- 0,
- "Toshiba",
- "G450 modem",
- },
- {
- USB_VENDOR_TOSHIBA, USB_PRODUCT_TOSHIBA_HSDPA,
- 0,
- "Toshiba",
- "G450 modem",
- },
- {
- USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE,
- 0,
- "Trek Technology",
- "ThumbDrive",
- },
- {
- USB_VENDOR_TREK, USB_PRODUCT_TREK_MEMKEY,
- 0,
- "Trek Technology",
- "IBM USB Memory Key",
- },
- {
- USB_VENDOR_TREK, USB_PRODUCT_TREK_THUMBDRIVE_8MB,
- 0,
- "Trek Technology",
- "ThumbDrive_8MB",
- },
- {
- USB_VENDOR_TRIPPLITE, USB_PRODUCT_TRIPPLITE_U209,
- 0,
- "Tripp-Lite",
- "Serial",
- },
- {
- USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_T33520,
- 0,
- "Trumpion Microelectronics",
- "T33520 USB Flash Card Controller",
- },
- {
- USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_C3310,
- 0,
- "Trumpion Microelectronics",
- "Comotron C3310 MP3 player",
- },
- {
- USB_VENDOR_TRUMPION, USB_PRODUCT_TRUMPION_MP3,
- 0,
- "Trumpion Microelectronics",
- "MP3 player",
- },
- {
- USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_G240,
- 0,
- "TwinMOS",
- "G240",
- },
- {
- USB_VENDOR_TWINMOS, USB_PRODUCT_TWINMOS_MDIV,
- 0,
- "TwinMOS",
- "Memory Disk IV",
- },
- {
- USB_VENDOR_UBIQUAM, USB_PRODUCT_UBIQUAM_UALL,
- 0,
- "UBIQUAM Co., Ltd.",
- "CDMA 1xRTT USB Modem (U-100/105/200/300/520)",
- },
- {
- USB_VENDOR_ULTIMA, USB_PRODUCT_ULTIMA_1200UBPLUS,
- 0,
- "Ultima",
- "1200 UB Plus scanner",
- },
- {
- USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1236U,
- 0,
- "UMAX Data Systems",
- "Astra 1236U Scanner",
- },
- {
- USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA1220U,
- 0,
- "UMAX Data Systems",
- "Astra 1220U Scanner",
- },
- {
- USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2000U,
- 0,
- "UMAX Data Systems",
- "Astra 2000U Scanner",
- },
- {
- USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2100U,
- 0,
- "UMAX Data Systems",
- "Astra 2100U Scanner",
- },
- {
- USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA2200U,
- 0,
- "UMAX Data Systems",
- "Astra 2200U Scanner",
- },
- {
- USB_VENDOR_UMAX, USB_PRODUCT_UMAX_ASTRA3400,
- 0,
- "UMAX Data Systems",
- "Astra 3400 Scanner",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW444UBEU,
- 0,
- "U-MEDIA Communications",
- "TEW-444UB EU",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW444UBEU_NF,
- 0,
- "U-MEDIA Communications",
- "TEW-444UB EU (no firmware)",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB_A,
- 0,
- "U-MEDIA Communications",
- "TEW-429UB_A",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UB,
- 0,
- "U-MEDIA Communications",
- "TEW-429UB",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_TEW429UBC1,
- 0,
- "U-MEDIA Communications",
- "TEW-429UB C1",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_RT2870_1,
- 0,
- "U-MEDIA Communications",
- "RT2870",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_ALL0298V2,
- 0,
- "U-MEDIA Communications",
- "ALL0298 v2",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_AR5523_2,
- 0,
- "U-MEDIA Communications",
- "AR5523",
- },
- {
- USB_VENDOR_UMEDIA, USB_PRODUCT_UMEDIA_AR5523_2_NF,
- 0,
- "U-MEDIA Communications",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_UNIACCESS, USB_PRODUCT_UNIACCESS_PANACHE,
- 0,
- "Universal Access",
- "Panache Surf USB ISDN Adapter",
- },
- {
- USB_VENDOR_USI, USB_PRODUCT_USI_MC60,
- 0,
- "USI",
- "MC60 Serial",
- },
- {
- USB_VENDOR_USR, USB_PRODUCT_USR_USR5422,
- 0,
- "U.S. Robotics",
- "USR5422 WLAN",
- },
- {
- USB_VENDOR_USR, USB_PRODUCT_USR_USR5423,
- 0,
- "U.S. Robotics",
- "USR5423 WLAN",
- },
- {
- USB_VENDOR_VIA, USB_PRODUCT_VIA_USB2IDEBRIDGE,
- 0,
- "VIA",
- "USB 2.0 IDE Bridge",
- },
- {
- USB_VENDOR_VAISALA, USB_PRODUCT_VAISALA_CABLE,
- 0,
- "Vaisala",
- "USB Interface cable",
- },
- {
- USB_VENDOR_VIDZMEDIA, USB_PRODUCT_VIDZMEDIA_MONSTERTV,
- 0,
- "VidzMedia Pte Ltd",
- "MonsterTV P2H",
- },
- {
- USB_VENDOR_VISION, USB_PRODUCT_VISION_VC6452V002,
- 0,
- "VLSI Vision",
- "CPiA Camera",
- },
- {
- USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_7600,
- 0,
- "Visioneer",
- "OneTouch 7600",
- },
- {
- USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_5300,
- 0,
- "Visioneer",
- "OneTouch 5300",
- },
- {
- USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_3000,
- 0,
- "Visioneer",
- "Scanport 3000",
- },
- {
- USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6100,
- 0,
- "Visioneer",
- "OneTouch 6100",
- },
- {
- USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_6200,
- 0,
- "Visioneer",
- "OneTouch 6200",
- },
- {
- USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8100,
- 0,
- "Visioneer",
- "OneTouch 8100",
- },
- {
- USB_VENDOR_VISIONEER, USB_PRODUCT_VISIONEER_8600,
- 0,
- "Visioneer",
- "OneTouch 8600",
- },
- {
- USB_VENDOR_VIVITAR, USB_PRODUCT_VIVITAR_35XX,
- 0,
- "Vivitar",
- "Vivicam 35Xx",
- },
- {
- USB_VENDOR_VTECH, USB_PRODUCT_VTECH_RT2570,
- 0,
- "VTech",
- "RT2570",
- },
- {
- USB_VENDOR_VTECH, USB_PRODUCT_VTECH_ZD1211B,
- 0,
- "VTech",
- "ZD1211B",
- },
- {
- USB_VENDOR_WACOM, USB_PRODUCT_WACOM_CT0405U,
- 0,
- "WACOM",
- "CT-0405-U Tablet",
- },
- {
- USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE,
- 0,
- "WACOM",
- "Graphire",
- },
- {
- USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GRAPHIRE3_4X5,
- 0,
- "WACOM",
- "Graphire 3 4x5",
- },
- {
- USB_VENDOR_WACOM, USB_PRODUCT_WACOM_INTUOSA5,
- 0,
- "WACOM",
- "Intuos A5",
- },
- {
- USB_VENDOR_WACOM, USB_PRODUCT_WACOM_GD0912U,
- 0,
- "WACOM",
- "Intuos 9x12 Graphics Tablet",
- },
- {
- USB_VENDOR_WAVESENSE, USB_PRODUCT_WAVESENSE_JAZZ,
- 0,
- "WaveSense",
- "Jazz blood glucose meter",
- },
- {
- USB_VENDOR_WCH, USB_PRODUCT_WCH_CH341SER,
- 0,
- "QinHeng Electronics",
- "CH341/CH340 USB-Serial Bridge",
- },
- {
- USB_VENDOR_WCH2, USB_PRODUCT_WCH2_CH341SER,
- 0,
- "QinHeng Electronics",
- "CH341/CH340 USB-Serial Bridge",
- },
- {
- USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_COMBO,
- 0,
- "Western Digital",
- "Firewire USB Combo",
- },
- {
- USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_EXTHDD,
- 0,
- "Western Digital",
- "External HDD",
- },
- {
- USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_HUB,
- 0,
- "Western Digital",
- "USB HUB",
- },
- {
- USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_MYBOOK,
- 0,
- "Western Digital",
- "MyBook External HDD",
- },
- {
- USB_VENDOR_WESTERN, USB_PRODUCT_WESTERN_MYPASSWORD,
- 0,
- "Western Digital",
- "MyPassword External HDD",
- },
- {
- USB_VENDOR_WINBOND, USB_PRODUCT_WINBOND_UH104,
- 0,
- "Winbond",
- "4-port USB Hub",
- },
- {
- USB_VENDOR_WINMAXGROUP, USB_PRODUCT_WINMAXGROUP_FLASH64MC,
- 0,
- "WinMaxGroup",
- "USB Flash Disk 64M-C",
- },
- {
- USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR045G,
- 0,
- "Wistron NeWeb",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_UR055G,
- 0,
- "Wistron NeWeb",
- "UR055G",
- },
- {
- USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_AR5523_1,
- 0,
- "Wistron NeWeb",
- "AR5523",
- },
- {
- USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_AR5523_1_NF,
- 0,
- "Wistron NeWeb",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_AR5523_2,
- 0,
- "Wistron NeWeb",
- "AR5523",
- },
- {
- USB_VENDOR_WISTRONNEWEB, USB_PRODUCT_WISTRONNEWEB_AR5523_2_NF,
- 0,
- "Wistron NeWeb",
- "AR5523 (no firmware)",
- },
- {
- USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15,
- 0,
- "Xerox",
- "WorkCenter M15",
- },
- {
- USB_VENDOR_XIRLINK, USB_PRODUCT_XIRLINK_PCCAM,
- 0,
- "Xirlink",
- "IBM PC Camera",
- },
- {
- USB_VENDOR_XYRATEX, USB_PRODUCT_XYRATEX_PRISM_GT_1,
- 0,
- "Xyratex",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_XYRATEX, USB_PRODUCT_XYRATEX_PRISM_GT_2,
- 0,
- "Xyratex",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_UX256,
- 0,
- "YAMAHA",
- "UX256 MIDI I/F",
- },
- {
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_UX96,
- 0,
- "YAMAHA",
- "UX96 MIDI I/F",
- },
- {
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTA54I,
- 0,
- "YAMAHA",
- "NetVolante RTA54i Broadband&ISDN Router",
- },
- {
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTA55I,
- 0,
- "YAMAHA",
- "NetVolante RTA55i Broadband VoIP Router",
- },
- {
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTW65B,
- 0,
- "YAMAHA",
- "NetVolante RTW65b Broadband Wireless Router",
- },
- {
- USB_VENDOR_YAMAHA, USB_PRODUCT_YAMAHA_RTW65I,
- 0,
- "YAMAHA",
- "NetVolante RTW65i Broadband&ISDN Wireless Router",
- },
- {
- USB_VENDOR_YANO, USB_PRODUCT_YANO_U640MO,
- 0,
- "Yano",
- "U640MO-03",
- },
- {
- USB_VENDOR_YANO, USB_PRODUCT_YANO_FW800HD,
- 0,
- "Yano",
- "METALWEAR-HDD",
- },
- {
- USB_VENDOR_YCCABLE, USB_PRODUCT_YCCABLE_PL2303,
- 0,
- "Y.C. Cable",
- "PL2303 Serial",
- },
- {
- USB_VENDOR_YEDATA, USB_PRODUCT_YEDATA_FLASHBUSTERU,
- 0,
- "Y-E Data",
- "Flashbuster-U",
- },
- {
- USB_VENDOR_YISO, USB_PRODUCT_YISO_C893,
- 0,
- "Yiso Wireless Co.",
- "CDMA 2000 1xEVDO PC Card",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_M4Y750,
- 0,
- "Z-Com",
- "M4Y-750",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XI725,
- 0,
- "Z-Com",
- "XI-725/726",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XI735,
- 0,
- "Z-Com",
- "XI-735",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XG703A,
- 0,
- "Z-Com",
- "PrismGT USB 2.0 WLAN",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211,
- 0,
- "Z-Com",
- "ZD1211",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_AR5523,
- 0,
- "Z-Com",
- "AR5523",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_AR5523_NF,
- 0,
- "Z-Com",
- "AR5523 driver (no firmware)",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_XM142,
- 0,
- "Z-Com",
- "XM-142",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_ZD1211B,
- 0,
- "Z-Com",
- "ZD1211B",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_RT2870_1,
- 0,
- "Z-Com",
- "RT2870",
- },
- {
- USB_VENDOR_ZCOM, USB_PRODUCT_ZCOM_RT2870_2,
- 0,
- "Z-Com",
- "RT2870",
- },
- {
- USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2570,
- 0,
- "Zinwell",
- "RT2570",
- },
- {
- USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2870_1,
- 0,
- "Zinwell",
- "RT2870",
- },
- {
- USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT2870_2,
- 0,
- "Zinwell",
- "RT2870",
- },
- {
- USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT3072_1,
- 0,
- "Zinwell",
- "RT3072",
- },
- {
- USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT3072_2,
- 0,
- "Zinwell",
- "RT3072",
- },
- {
- USB_VENDOR_ZINWELL, USB_PRODUCT_ZINWELL_RT3070,
- 0,
- "Zinwell",
- "RT3070",
- },
- {
- USB_VENDOR_ZOOM, USB_PRODUCT_ZOOM_2986L,
- 0,
- "Zoom Telephonics",
- "2986L Fax modem",
- },
- {
- USB_VENDOR_ZORAN, USB_PRODUCT_ZORAN_EX20DSC,
- 0,
- "Zoran Microelectronics",
- "Digital Camera EX-20 DSC",
- },
- {
- USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211,
- 0,
- "Zydas Technology Corporation",
- "ZD1211 WLAN abg",
- },
- {
- USB_VENDOR_ZYDAS, USB_PRODUCT_ZYDAS_ZD1211B,
- 0,
- "Zydas Technology Corporation",
- "ZD1211B",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_OMNI56K,
- 0,
- "ZyXEL Communication",
- "Omni 56K Plus",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_980N,
- 0,
- "ZyXEL Communication",
- "Scorpion-980N keyboard",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_ZYAIRG220,
- 0,
- "ZyXEL Communication",
- "ZyAIR G-220",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G200V2,
- 0,
- "ZyXEL Communication",
- "G-200 v2",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_AG225H,
- 0,
- "ZyXEL Communication",
- "AG-225H",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_M202,
- 0,
- "ZyXEL Communication",
- "M-202",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G220V2,
- 0,
- "ZyXEL Communication",
- "G-220 v2",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_G202,
- 0,
- "ZyXEL Communication",
- "G-202",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RT2870_1,
- 0,
- "ZyXEL Communication",
- "RT2870",
- },
- {
- USB_VENDOR_ZYXEL, USB_PRODUCT_ZYXEL_RT2870_2,
- 0,
- "ZyXEL Communication",
- "RT2870",
- },
- {
- USB_VENDOR_UNKNOWN1, 0,
- USB_KNOWNDEV_NOPROD,
- "Unknown vendor",
- NULL,
- },
- {
- USB_VENDOR_UNKNOWN2, 0,
- USB_KNOWNDEV_NOPROD,
- "Unknown vendor",
- NULL,
- },
- {
- USB_VENDOR_EGALAX2, 0,
- USB_KNOWNDEV_NOPROD,
- "eGalax, Inc.",
- NULL,
- },
- {
- USB_VENDOR_CHIPSBANK, 0,
- USB_KNOWNDEV_NOPROD,
- "Chipsbank Microelectronics Co.",
- NULL,
- },
- {
- USB_VENDOR_HUMAX, 0,
- USB_KNOWNDEV_NOPROD,
- "HUMAX",
- NULL,
- },
- {
- USB_VENDOR_LTS, 0,
- USB_KNOWNDEV_NOPROD,
- "LTS",
- NULL,
- },
- {
- USB_VENDOR_BWCT, 0,
- USB_KNOWNDEV_NOPROD,
- "Bernd Walter Computer Technology",
- NULL,
- },
- {
- USB_VENDOR_AOX, 0,
- USB_KNOWNDEV_NOPROD,
- "AOX",
- NULL,
- },
- {
- USB_VENDOR_THESYS, 0,
- USB_KNOWNDEV_NOPROD,
- "Thesys",
- NULL,
- },
- {
- USB_VENDOR_DATABROADCAST, 0,
- USB_KNOWNDEV_NOPROD,
- "Data Broadcasting",
- NULL,
- },
- {
- USB_VENDOR_ATMEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Atmel",
- NULL,
- },
- {
- USB_VENDOR_IWATSU, 0,
- USB_KNOWNDEV_NOPROD,
- "Iwatsu America",
- NULL,
- },
- {
- USB_VENDOR_MITSUMI, 0,
- USB_KNOWNDEV_NOPROD,
- "Mitsumi",
- NULL,
- },
- {
- USB_VENDOR_HP, 0,
- USB_KNOWNDEV_NOPROD,
- "Hewlett Packard",
- NULL,
- },
- {
- USB_VENDOR_GENOA, 0,
- USB_KNOWNDEV_NOPROD,
- "Genoa",
- NULL,
- },
- {
- USB_VENDOR_OAK, 0,
- USB_KNOWNDEV_NOPROD,
- "Oak",
- NULL,
- },
- {
- USB_VENDOR_ADAPTEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Adaptec",
- NULL,
- },
- {
- USB_VENDOR_DIEBOLD, 0,
- USB_KNOWNDEV_NOPROD,
- "Diebold",
- NULL,
- },
- {
- USB_VENDOR_SIEMENSELECTRO, 0,
- USB_KNOWNDEV_NOPROD,
- "Siemens Electromechanical",
- NULL,
- },
- {
- USB_VENDOR_EPSONIMAGING, 0,
- USB_KNOWNDEV_NOPROD,
- "Epson Imaging",
- NULL,
- },
- {
- USB_VENDOR_KEYTRONIC, 0,
- USB_KNOWNDEV_NOPROD,
- "KeyTronic",
- NULL,
- },
- {
- USB_VENDOR_OPTI, 0,
- USB_KNOWNDEV_NOPROD,
- "OPTi",
- NULL,
- },
- {
- USB_VENDOR_ELITEGROUP, 0,
- USB_KNOWNDEV_NOPROD,
- "Elitegroup",
- NULL,
- },
- {
- USB_VENDOR_XILINX, 0,
- USB_KNOWNDEV_NOPROD,
- "Xilinx",
- NULL,
- },
- {
- USB_VENDOR_FARALLON, 0,
- USB_KNOWNDEV_NOPROD,
- "Farallon Communications",
- NULL,
- },
- {
- USB_VENDOR_NATIONAL, 0,
- USB_KNOWNDEV_NOPROD,
- "National Semiconductor",
- NULL,
- },
- {
- USB_VENDOR_NATIONALREG, 0,
- USB_KNOWNDEV_NOPROD,
- "National Registry",
- NULL,
- },
- {
- USB_VENDOR_ACERLABS, 0,
- USB_KNOWNDEV_NOPROD,
- "Acer Labs",
- NULL,
- },
- {
- USB_VENDOR_FTDI, 0,
- USB_KNOWNDEV_NOPROD,
- "Future Technology Devices",
- NULL,
- },
- {
- USB_VENDOR_NCR, 0,
- USB_KNOWNDEV_NOPROD,
- "NCR",
- NULL,
- },
- {
- USB_VENDOR_SYNOPSYS2, 0,
- USB_KNOWNDEV_NOPROD,
- "Synopsys",
- NULL,
- },
- {
- USB_VENDOR_FUJITSUICL, 0,
- USB_KNOWNDEV_NOPROD,
- "Fujitsu-ICL",
- NULL,
- },
- {
- USB_VENDOR_FUJITSU2, 0,
- USB_KNOWNDEV_NOPROD,
- "Fujitsu Personal Systems",
- NULL,
- },
- {
- USB_VENDOR_QUANTA, 0,
- USB_KNOWNDEV_NOPROD,
- "Quanta",
- NULL,
- },
- {
- USB_VENDOR_NEC, 0,
- USB_KNOWNDEV_NOPROD,
- "NEC",
- NULL,
- },
- {
- USB_VENDOR_KODAK, 0,
- USB_KNOWNDEV_NOPROD,
- "Eastman Kodak",
- NULL,
- },
- {
- USB_VENDOR_WELTREND, 0,
- USB_KNOWNDEV_NOPROD,
- "Weltrend",
- NULL,
- },
- {
- USB_VENDOR_VIA, 0,
- USB_KNOWNDEV_NOPROD,
- "VIA",
- NULL,
- },
- {
- USB_VENDOR_MCCI, 0,
- USB_KNOWNDEV_NOPROD,
- "MCCI",
- NULL,
- },
- {
- USB_VENDOR_MELCO, 0,
- USB_KNOWNDEV_NOPROD,
- "Melco",
- NULL,
- },
- {
- USB_VENDOR_LEADTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Leadtek",
- NULL,
- },
- {
- USB_VENDOR_WINBOND, 0,
- USB_KNOWNDEV_NOPROD,
- "Winbond",
- NULL,
- },
- {
- USB_VENDOR_PHOENIX, 0,
- USB_KNOWNDEV_NOPROD,
- "Phoenix",
- NULL,
- },
- {
- USB_VENDOR_CREATIVE, 0,
- USB_KNOWNDEV_NOPROD,
- "Creative Labs",
- NULL,
- },
- {
- USB_VENDOR_NOKIA, 0,
- USB_KNOWNDEV_NOPROD,
- "Nokia",
- NULL,
- },
- {
- USB_VENDOR_ADI, 0,
- USB_KNOWNDEV_NOPROD,
- "ADI Systems",
- NULL,
- },
- {
- USB_VENDOR_CATC, 0,
- USB_KNOWNDEV_NOPROD,
- "Computer Access Technology",
- NULL,
- },
- {
- USB_VENDOR_SMC2, 0,
- USB_KNOWNDEV_NOPROD,
- "Standard Microsystems",
- NULL,
- },
- {
- USB_VENDOR_MOTOROLA_HK, 0,
- USB_KNOWNDEV_NOPROD,
- "Motorola HK",
- NULL,
- },
- {
- USB_VENDOR_GRAVIS, 0,
- USB_KNOWNDEV_NOPROD,
- "Advanced Gravis Computer",
- NULL,
- },
- {
- USB_VENDOR_CIRRUSLOGIC, 0,
- USB_KNOWNDEV_NOPROD,
- "Cirrus Logic",
- NULL,
- },
- {
- USB_VENDOR_INNOVATIVE, 0,
- USB_KNOWNDEV_NOPROD,
- "Innovative Semiconductors",
- NULL,
- },
- {
- USB_VENDOR_MOLEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Molex",
- NULL,
- },
- {
- USB_VENDOR_SUN, 0,
- USB_KNOWNDEV_NOPROD,
- "Sun Microsystems",
- NULL,
- },
- {
- USB_VENDOR_UNISYS, 0,
- USB_KNOWNDEV_NOPROD,
- "Unisys",
- NULL,
- },
- {
- USB_VENDOR_TAUGA, 0,
- USB_KNOWNDEV_NOPROD,
- "Taugagreining HF",
- NULL,
- },
- {
- USB_VENDOR_AMD, 0,
- USB_KNOWNDEV_NOPROD,
- "Advanced Micro Devices",
- NULL,
- },
- {
- USB_VENDOR_LEXMARK, 0,
- USB_KNOWNDEV_NOPROD,
- "Lexmark International",
- NULL,
- },
- {
- USB_VENDOR_LG, 0,
- USB_KNOWNDEV_NOPROD,
- "LG Electronics",
- NULL,
- },
- {
- USB_VENDOR_NANAO, 0,
- USB_KNOWNDEV_NOPROD,
- "NANAO",
- NULL,
- },
- {
- USB_VENDOR_GATEWAY, 0,
- USB_KNOWNDEV_NOPROD,
- "Gateway 2000",
- NULL,
- },
- {
- USB_VENDOR_NMB, 0,
- USB_KNOWNDEV_NOPROD,
- "NMB",
- NULL,
- },
- {
- USB_VENDOR_ALPS, 0,
- USB_KNOWNDEV_NOPROD,
- "Alps Electric",
- NULL,
- },
- {
- USB_VENDOR_THRUST, 0,
- USB_KNOWNDEV_NOPROD,
- "Thrustmaster",
- NULL,
- },
- {
- USB_VENDOR_TI, 0,
- USB_KNOWNDEV_NOPROD,
- "Texas Instruments",
- NULL,
- },
- {
- USB_VENDOR_ANALOGDEVICES, 0,
- USB_KNOWNDEV_NOPROD,
- "Analog Devices",
- NULL,
- },
- {
- USB_VENDOR_SIS, 0,
- USB_KNOWNDEV_NOPROD,
- "Silicon Integrated Systems Corp.",
- NULL,
- },
- {
- USB_VENDOR_KYE, 0,
- USB_KNOWNDEV_NOPROD,
- "KYE Systems",
- NULL,
- },
- {
- USB_VENDOR_DIAMOND2, 0,
- USB_KNOWNDEV_NOPROD,
- "Diamond (Supra)",
- NULL,
- },
- {
- USB_VENDOR_RENESAS, 0,
- USB_KNOWNDEV_NOPROD,
- "Renesas",
- NULL,
- },
- {
- USB_VENDOR_MICROSOFT, 0,
- USB_KNOWNDEV_NOPROD,
- "Microsoft",
- NULL,
- },
- {
- USB_VENDOR_PRIMAX, 0,
- USB_KNOWNDEV_NOPROD,
- "Primax Electronics",
- NULL,
- },
- {
- USB_VENDOR_MGE, 0,
- USB_KNOWNDEV_NOPROD,
- "MGE UPS Systems",
- NULL,
- },
- {
- USB_VENDOR_AMP, 0,
- USB_KNOWNDEV_NOPROD,
- "AMP",
- NULL,
- },
- {
- USB_VENDOR_CHERRY, 0,
- USB_KNOWNDEV_NOPROD,
- "Cherry Mikroschalter",
- NULL,
- },
- {
- USB_VENDOR_MEGATRENDS, 0,
- USB_KNOWNDEV_NOPROD,
- "American Megatrends",
- NULL,
- },
- {
- USB_VENDOR_LOGITECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Logitech",
- NULL,
- },
- {
- USB_VENDOR_BTC, 0,
- USB_KNOWNDEV_NOPROD,
- "Behavior Tech. Computer",
- NULL,
- },
- {
- USB_VENDOR_PHILIPS, 0,
- USB_KNOWNDEV_NOPROD,
- "Philips",
- NULL,
- },
- {
- USB_VENDOR_SUN2, 0,
- USB_KNOWNDEV_NOPROD,
- "Sun Microsystems (offical)",
- NULL,
- },
- {
- USB_VENDOR_SANYO, 0,
- USB_KNOWNDEV_NOPROD,
- "Sanyo Electric",
- NULL,
- },
- {
- USB_VENDOR_SEAGATE, 0,
- USB_KNOWNDEV_NOPROD,
- "Seagate",
- NULL,
- },
- {
- USB_VENDOR_CONNECTIX, 0,
- USB_KNOWNDEV_NOPROD,
- "Connectix",
- NULL,
- },
- {
- USB_VENDOR_SEMTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Semtech",
- NULL,
- },
- {
- USB_VENDOR_KENSINGTON, 0,
- USB_KNOWNDEV_NOPROD,
- "Kensington",
- NULL,
- },
- {
- USB_VENDOR_LUCENT, 0,
- USB_KNOWNDEV_NOPROD,
- "Lucent",
- NULL,
- },
- {
- USB_VENDOR_PLANTRONICS, 0,
- USB_KNOWNDEV_NOPROD,
- "Plantronics",
- NULL,
- },
- {
- USB_VENDOR_KYOCERA, 0,
- USB_KNOWNDEV_NOPROD,
- "Kyocera Wireless Corp.",
- NULL,
- },
- {
- USB_VENDOR_STMICRO, 0,
- USB_KNOWNDEV_NOPROD,
- "STMicroelectronics",
- NULL,
- },
- {
- USB_VENDOR_FOXCONN, 0,
- USB_KNOWNDEV_NOPROD,
- "Foxconn",
- NULL,
- },
- {
- USB_VENDOR_MEIZU, 0,
- USB_KNOWNDEV_NOPROD,
- "Meizu Electronics",
- NULL,
- },
- {
- USB_VENDOR_YAMAHA, 0,
- USB_KNOWNDEV_NOPROD,
- "YAMAHA",
- NULL,
- },
- {
- USB_VENDOR_COMPAQ, 0,
- USB_KNOWNDEV_NOPROD,
- "Compaq",
- NULL,
- },
- {
- USB_VENDOR_HITACHI, 0,
- USB_KNOWNDEV_NOPROD,
- "Hitachi",
- NULL,
- },
- {
- USB_VENDOR_ACERP, 0,
- USB_KNOWNDEV_NOPROD,
- "Acer Peripherals",
- NULL,
- },
- {
- USB_VENDOR_DAVICOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Davicom",
- NULL,
- },
- {
- USB_VENDOR_VISIONEER, 0,
- USB_KNOWNDEV_NOPROD,
- "Visioneer",
- NULL,
- },
- {
- USB_VENDOR_CANON, 0,
- USB_KNOWNDEV_NOPROD,
- "Canon",
- NULL,
- },
- {
- USB_VENDOR_NIKON, 0,
- USB_KNOWNDEV_NOPROD,
- "Nikon",
- NULL,
- },
- {
- USB_VENDOR_PAN, 0,
- USB_KNOWNDEV_NOPROD,
- "Pan International",
- NULL,
- },
- {
- USB_VENDOR_IBM, 0,
- USB_KNOWNDEV_NOPROD,
- "IBM",
- NULL,
- },
- {
- USB_VENDOR_CYPRESS, 0,
- USB_KNOWNDEV_NOPROD,
- "Cypress Semiconductor",
- NULL,
- },
- {
- USB_VENDOR_ROHM, 0,
- USB_KNOWNDEV_NOPROD,
- "ROHM",
- NULL,
- },
- {
- USB_VENDOR_COMPAL, 0,
- USB_KNOWNDEV_NOPROD,
- "Compal",
- NULL,
- },
- {
- USB_VENDOR_EPSON, 0,
- USB_KNOWNDEV_NOPROD,
- "Seiko Epson",
- NULL,
- },
- {
- USB_VENDOR_RAINBOW, 0,
- USB_KNOWNDEV_NOPROD,
- "Rainbow Technologies",
- NULL,
- },
- {
- USB_VENDOR_IODATA, 0,
- USB_KNOWNDEV_NOPROD,
- "I-O Data",
- NULL,
- },
- {
- USB_VENDOR_TDK, 0,
- USB_KNOWNDEV_NOPROD,
- "TDK",
- NULL,
- },
- {
- USB_VENDOR_3COMUSR, 0,
- USB_KNOWNDEV_NOPROD,
- "U.S. Robotics",
- NULL,
- },
- {
- USB_VENDOR_METHODE, 0,
- USB_KNOWNDEV_NOPROD,
- "Methode Electronics Far East",
- NULL,
- },
- {
- USB_VENDOR_MAXISWITCH, 0,
- USB_KNOWNDEV_NOPROD,
- "Maxi Switch",
- NULL,
- },
- {
- USB_VENDOR_LOCKHEEDMER, 0,
- USB_KNOWNDEV_NOPROD,
- "Lockheed Martin Energy Research",
- NULL,
- },
- {
- USB_VENDOR_FUJITSU, 0,
- USB_KNOWNDEV_NOPROD,
- "Fujitsu",
- NULL,
- },
- {
- USB_VENDOR_TOSHIBAAM, 0,
- USB_KNOWNDEV_NOPROD,
- "Toshiba America",
- NULL,
- },
- {
- USB_VENDOR_MICROMACRO, 0,
- USB_KNOWNDEV_NOPROD,
- "Micro Macro Technologies",
- NULL,
- },
- {
- USB_VENDOR_KONICA, 0,
- USB_KNOWNDEV_NOPROD,
- "Konica",
- NULL,
- },
- {
- USB_VENDOR_LITEON, 0,
- USB_KNOWNDEV_NOPROD,
- "Lite-On Technology",
- NULL,
- },
- {
- USB_VENDOR_FUJIPHOTO, 0,
- USB_KNOWNDEV_NOPROD,
- "Fuji Photo Film",
- NULL,
- },
- {
- USB_VENDOR_PHILIPSSEMI, 0,
- USB_KNOWNDEV_NOPROD,
- "Philips Semiconductors",
- NULL,
- },
- {
- USB_VENDOR_TATUNG, 0,
- USB_KNOWNDEV_NOPROD,
- "Tatung Co. Of America",
- NULL,
- },
- {
- USB_VENDOR_SCANLOGIC, 0,
- USB_KNOWNDEV_NOPROD,
- "ScanLogic",
- NULL,
- },
- {
- USB_VENDOR_MYSON, 0,
- USB_KNOWNDEV_NOPROD,
- "Myson Technology",
- NULL,
- },
- {
- USB_VENDOR_DIGI2, 0,
- USB_KNOWNDEV_NOPROD,
- "Digi",
- NULL,
- },
- {
- USB_VENDOR_ITTCANON, 0,
- USB_KNOWNDEV_NOPROD,
- "ITT Canon",
- NULL,
- },
- {
- USB_VENDOR_ALTEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Altec Lansing",
- NULL,
- },
- {
- USB_VENDOR_LSI, 0,
- USB_KNOWNDEV_NOPROD,
- "LSI",
- NULL,
- },
- {
- USB_VENDOR_MENTORGRAPHICS, 0,
- USB_KNOWNDEV_NOPROD,
- "Mentor Graphics",
- NULL,
- },
- {
- USB_VENDOR_ITUNERNET, 0,
- USB_KNOWNDEV_NOPROD,
- "I-Tuner Networks",
- NULL,
- },
- {
- USB_VENDOR_HOLTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Holtek Semiconductor, Inc.",
- NULL,
- },
- {
- USB_VENDOR_PANASONIC, 0,
- USB_KNOWNDEV_NOPROD,
- "Panasonic (Matsushita)",
- NULL,
- },
- {
- USB_VENDOR_HUANHSIN, 0,
- USB_KNOWNDEV_NOPROD,
- "Huan Hsin",
- NULL,
- },
- {
- USB_VENDOR_SHARP, 0,
- USB_KNOWNDEV_NOPROD,
- "Sharp",
- NULL,
- },
- {
- USB_VENDOR_IIYAMA, 0,
- USB_KNOWNDEV_NOPROD,
- "Iiyama",
- NULL,
- },
- {
- USB_VENDOR_SHUTTLE, 0,
- USB_KNOWNDEV_NOPROD,
- "Shuttle Technology",
- NULL,
- },
- {
- USB_VENDOR_ELO, 0,
- USB_KNOWNDEV_NOPROD,
- "Elo TouchSystems",
- NULL,
- },
- {
- USB_VENDOR_SAMSUNG, 0,
- USB_KNOWNDEV_NOPROD,
- "Samsung Electronics",
- NULL,
- },
- {
- USB_VENDOR_NORTHSTAR, 0,
- USB_KNOWNDEV_NOPROD,
- "Northstar",
- NULL,
- },
- {
- USB_VENDOR_TOKYOELECTRON, 0,
- USB_KNOWNDEV_NOPROD,
- "Tokyo Electron",
- NULL,
- },
- {
- USB_VENDOR_ANNABOOKS, 0,
- USB_KNOWNDEV_NOPROD,
- "Annabooks",
- NULL,
- },
- {
- USB_VENDOR_JVC, 0,
- USB_KNOWNDEV_NOPROD,
- "JVC",
- NULL,
- },
- {
- USB_VENDOR_CHICONY, 0,
- USB_KNOWNDEV_NOPROD,
- "Chicony Electronics",
- NULL,
- },
- {
- USB_VENDOR_ELAN, 0,
- USB_KNOWNDEV_NOPROD,
- "Elan",
- NULL,
- },
- {
- USB_VENDOR_NEWNEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Newnex",
- NULL,
- },
- {
- USB_VENDOR_BROTHER, 0,
- USB_KNOWNDEV_NOPROD,
- "Brother Industries",
- NULL,
- },
- {
- USB_VENDOR_DALLAS, 0,
- USB_KNOWNDEV_NOPROD,
- "Dallas Semiconductor",
- NULL,
- },
- {
- USB_VENDOR_AIPTEK2, 0,
- USB_KNOWNDEV_NOPROD,
- "AIPTEK International",
- NULL,
- },
- {
- USB_VENDOR_PFU, 0,
- USB_KNOWNDEV_NOPROD,
- "PFU",
- NULL,
- },
- {
- USB_VENDOR_FUJIKURA, 0,
- USB_KNOWNDEV_NOPROD,
- "Fujikura/DDK",
- NULL,
- },
- {
- USB_VENDOR_ACER, 0,
- USB_KNOWNDEV_NOPROD,
- "Acer",
- NULL,
- },
- {
- USB_VENDOR_3COM, 0,
- USB_KNOWNDEV_NOPROD,
- "3Com",
- NULL,
- },
- {
- USB_VENDOR_HOSIDEN, 0,
- USB_KNOWNDEV_NOPROD,
- "Hosiden Corporation",
- NULL,
- },
- {
- USB_VENDOR_AZTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Aztech Systems",
- NULL,
- },
- {
- USB_VENDOR_BELKIN, 0,
- USB_KNOWNDEV_NOPROD,
- "Belkin Components",
- NULL,
- },
- {
- USB_VENDOR_KAWATSU, 0,
- USB_KNOWNDEV_NOPROD,
- "Kawatsu Semiconductor",
- NULL,
- },
- {
- USB_VENDOR_FCI, 0,
- USB_KNOWNDEV_NOPROD,
- "FCI",
- NULL,
- },
- {
- USB_VENDOR_LONGWELL, 0,
- USB_KNOWNDEV_NOPROD,
- "Longwell",
- NULL,
- },
- {
- USB_VENDOR_COMPOSITE, 0,
- USB_KNOWNDEV_NOPROD,
- "Composite",
- NULL,
- },
- {
- USB_VENDOR_STAR, 0,
- USB_KNOWNDEV_NOPROD,
- "Star Micronics",
- NULL,
- },
- {
- USB_VENDOR_APC, 0,
- USB_KNOWNDEV_NOPROD,
- "American Power Conversion",
- NULL,
- },
- {
- USB_VENDOR_SCIATLANTA, 0,
- USB_KNOWNDEV_NOPROD,
- "Scientific Atlanta",
- NULL,
- },
- {
- USB_VENDOR_TSM, 0,
- USB_KNOWNDEV_NOPROD,
- "TSM",
- NULL,
- },
- {
- USB_VENDOR_CONNECTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Advanced Connectek USA",
- NULL,
- },
- {
- USB_VENDOR_NETCHIP, 0,
- USB_KNOWNDEV_NOPROD,
- "NetChip Technology",
- NULL,
- },
- {
- USB_VENDOR_ALTRA, 0,
- USB_KNOWNDEV_NOPROD,
- "ALTRA",
- NULL,
- },
- {
- USB_VENDOR_ATI, 0,
- USB_KNOWNDEV_NOPROD,
- "ATI Technologies",
- NULL,
- },
- {
- USB_VENDOR_AKS, 0,
- USB_KNOWNDEV_NOPROD,
- "Aladdin Knowledge Systems",
- NULL,
- },
- {
- USB_VENDOR_TEKOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Tekom",
- NULL,
- },
- {
- USB_VENDOR_CANONDEV, 0,
- USB_KNOWNDEV_NOPROD,
- "Canon",
- NULL,
- },
- {
- USB_VENDOR_WACOMTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Wacom",
- NULL,
- },
- {
- USB_VENDOR_INVENTEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Inventec",
- NULL,
- },
- {
- USB_VENDOR_SHYHSHIUN, 0,
- USB_KNOWNDEV_NOPROD,
- "Shyh Shiun Terminals",
- NULL,
- },
- {
- USB_VENDOR_PREHWERKE, 0,
- USB_KNOWNDEV_NOPROD,
- "Preh Werke Gmbh & Co. KG",
- NULL,
- },
- {
- USB_VENDOR_SYNOPSYS, 0,
- USB_KNOWNDEV_NOPROD,
- "Synopsys",
- NULL,
- },
- {
- USB_VENDOR_UNIACCESS, 0,
- USB_KNOWNDEV_NOPROD,
- "Universal Access",
- NULL,
- },
- {
- USB_VENDOR_VIEWSONIC, 0,
- USB_KNOWNDEV_NOPROD,
- "ViewSonic",
- NULL,
- },
- {
- USB_VENDOR_XIRLINK, 0,
- USB_KNOWNDEV_NOPROD,
- "Xirlink",
- NULL,
- },
- {
- USB_VENDOR_ANCHOR, 0,
- USB_KNOWNDEV_NOPROD,
- "Anchor Chips",
- NULL,
- },
- {
- USB_VENDOR_SONY, 0,
- USB_KNOWNDEV_NOPROD,
- "Sony",
- NULL,
- },
- {
- USB_VENDOR_FUJIXEROX, 0,
- USB_KNOWNDEV_NOPROD,
- "Fuji Xerox",
- NULL,
- },
- {
- USB_VENDOR_VISION, 0,
- USB_KNOWNDEV_NOPROD,
- "VLSI Vision",
- NULL,
- },
- {
- USB_VENDOR_ASAHIKASEI, 0,
- USB_KNOWNDEV_NOPROD,
- "Asahi Kasei Microsystems",
- NULL,
- },
- {
- USB_VENDOR_ATEN, 0,
- USB_KNOWNDEV_NOPROD,
- "ATEN International",
- NULL,
- },
- {
- USB_VENDOR_SAMSUNG2, 0,
- USB_KNOWNDEV_NOPROD,
- "Samsung Electronics",
- NULL,
- },
- {
- USB_VENDOR_MUSTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Mustek Systems",
- NULL,
- },
- {
- USB_VENDOR_TELEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Telex Communications",
- NULL,
- },
- {
- USB_VENDOR_CHINON, 0,
- USB_KNOWNDEV_NOPROD,
- "Chinon",
- NULL,
- },
- {
- USB_VENDOR_PERACOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Peracom Networks",
- NULL,
- },
- {
- USB_VENDOR_ALCOR2, 0,
- USB_KNOWNDEV_NOPROD,
- "Alcor Micro",
- NULL,
- },
- {
- USB_VENDOR_XYRATEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Xyratex",
- NULL,
- },
- {
- USB_VENDOR_WACOM, 0,
- USB_KNOWNDEV_NOPROD,
- "WACOM",
- NULL,
- },
- {
- USB_VENDOR_ETEK, 0,
- USB_KNOWNDEV_NOPROD,
- "e-TEK Labs",
- NULL,
- },
- {
- USB_VENDOR_EIZO, 0,
- USB_KNOWNDEV_NOPROD,
- "EIZO",
- NULL,
- },
- {
- USB_VENDOR_ELECOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Elecom",
- NULL,
- },
- {
- USB_VENDOR_CONEXANT, 0,
- USB_KNOWNDEV_NOPROD,
- "Conexant",
- NULL,
- },
- {
- USB_VENDOR_HAUPPAUGE, 0,
- USB_KNOWNDEV_NOPROD,
- "Hauppauge Computer Works",
- NULL,
- },
- {
- USB_VENDOR_BAFO, 0,
- USB_KNOWNDEV_NOPROD,
- "BAFO/Quality Computer Accessories",
- NULL,
- },
- {
- USB_VENDOR_YEDATA, 0,
- USB_KNOWNDEV_NOPROD,
- "Y-E Data",
- NULL,
- },
- {
- USB_VENDOR_AVM, 0,
- USB_KNOWNDEV_NOPROD,
- "AVM",
- NULL,
- },
- {
- USB_VENDOR_QUICKSHOT, 0,
- USB_KNOWNDEV_NOPROD,
- "Quickshot",
- NULL,
- },
- {
- USB_VENDOR_ROLAND, 0,
- USB_KNOWNDEV_NOPROD,
- "Roland",
- NULL,
- },
- {
- USB_VENDOR_ROCKFIRE, 0,
- USB_KNOWNDEV_NOPROD,
- "Rockfire",
- NULL,
- },
- {
- USB_VENDOR_RATOC, 0,
- USB_KNOWNDEV_NOPROD,
- "RATOC Systems",
- NULL,
- },
- {
- USB_VENDOR_ZYXEL, 0,
- USB_KNOWNDEV_NOPROD,
- "ZyXEL Communication",
- NULL,
- },
- {
- USB_VENDOR_INFINEON, 0,
- USB_KNOWNDEV_NOPROD,
- "Infineon",
- NULL,
- },
- {
- USB_VENDOR_MICREL, 0,
- USB_KNOWNDEV_NOPROD,
- "Micrel",
- NULL,
- },
- {
- USB_VENDOR_ALCOR, 0,
- USB_KNOWNDEV_NOPROD,
- "Alcor Micro",
- NULL,
- },
- {
- USB_VENDOR_OMRON, 0,
- USB_KNOWNDEV_NOPROD,
- "OMRON",
- NULL,
- },
- {
- USB_VENDOR_ZORAN, 0,
- USB_KNOWNDEV_NOPROD,
- "Zoran Microelectronics",
- NULL,
- },
- {
- USB_VENDOR_NIIGATA, 0,
- USB_KNOWNDEV_NOPROD,
- "Niigata",
- NULL,
- },
- {
- USB_VENDOR_IOMEGA, 0,
- USB_KNOWNDEV_NOPROD,
- "Iomega",
- NULL,
- },
- {
- USB_VENDOR_ATREND, 0,
- USB_KNOWNDEV_NOPROD,
- "A-Trend Technology",
- NULL,
- },
- {
- USB_VENDOR_AID, 0,
- USB_KNOWNDEV_NOPROD,
- "Advanced Input Devices",
- NULL,
- },
- {
- USB_VENDOR_LACIE, 0,
- USB_KNOWNDEV_NOPROD,
- "LaCie",
- NULL,
- },
- {
- USB_VENDOR_FUJIFILM, 0,
- USB_KNOWNDEV_NOPROD,
- "Fuji Film",
- NULL,
- },
- {
- USB_VENDOR_ARC, 0,
- USB_KNOWNDEV_NOPROD,
- "ARC",
- NULL,
- },
- {
- USB_VENDOR_ORTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Ortek",
- NULL,
- },
- {
- USB_VENDOR_CISCOLINKSYS3, 0,
- USB_KNOWNDEV_NOPROD,
- "Cisco-Linksys",
- NULL,
- },
- {
- USB_VENDOR_BOSE, 0,
- USB_KNOWNDEV_NOPROD,
- "Bose",
- NULL,
- },
- {
- USB_VENDOR_OMNIVISION, 0,
- USB_KNOWNDEV_NOPROD,
- "OmniVision",
- NULL,
- },
- {
- USB_VENDOR_INSYSTEM, 0,
- USB_KNOWNDEV_NOPROD,
- "In-System Design",
- NULL,
- },
- {
- USB_VENDOR_APPLE, 0,
- USB_KNOWNDEV_NOPROD,
- "Apple Computer",
- NULL,
- },
- {
- USB_VENDOR_YCCABLE, 0,
- USB_KNOWNDEV_NOPROD,
- "Y.C. Cable",
- NULL,
- },
- {
- USB_VENDOR_DIGITALPERSONA, 0,
- USB_KNOWNDEV_NOPROD,
- "DigitalPersona",
- NULL,
- },
- {
- USB_VENDOR_3G, 0,
- USB_KNOWNDEV_NOPROD,
- "3G Green Green Globe",
- NULL,
- },
- {
- USB_VENDOR_RAFI, 0,
- USB_KNOWNDEV_NOPROD,
- "RAFI",
- NULL,
- },
- {
- USB_VENDOR_TYCO, 0,
- USB_KNOWNDEV_NOPROD,
- "Tyco",
- NULL,
- },
- {
- USB_VENDOR_KAWASAKI, 0,
- USB_KNOWNDEV_NOPROD,
- "Kawasaki",
- NULL,
- },
- {
- USB_VENDOR_DIGI, 0,
- USB_KNOWNDEV_NOPROD,
- "Digi International",
- NULL,
- },
- {
- USB_VENDOR_QUALCOMM2, 0,
- USB_KNOWNDEV_NOPROD,
- "Qualcomm",
- NULL,
- },
- {
- USB_VENDOR_QTRONIX, 0,
- USB_KNOWNDEV_NOPROD,
- "Qtronix",
- NULL,
- },
- {
- USB_VENDOR_FOXLINK, 0,
- USB_KNOWNDEV_NOPROD,
- "Foxlink",
- NULL,
- },
- {
- USB_VENDOR_RICOH, 0,
- USB_KNOWNDEV_NOPROD,
- "Ricoh",
- NULL,
- },
- {
- USB_VENDOR_ELSA, 0,
- USB_KNOWNDEV_NOPROD,
- "ELSA",
- NULL,
- },
- {
- USB_VENDOR_SCIWORX, 0,
- USB_KNOWNDEV_NOPROD,
- "sci-worx",
- NULL,
- },
- {
- USB_VENDOR_BRAINBOXES, 0,
- USB_KNOWNDEV_NOPROD,
- "Brainboxes Limited",
- NULL,
- },
- {
- USB_VENDOR_ULTIMA, 0,
- USB_KNOWNDEV_NOPROD,
- "Ultima",
- NULL,
- },
- {
- USB_VENDOR_AXIOHM, 0,
- USB_KNOWNDEV_NOPROD,
- "Axiohm Transaction Solutions",
- NULL,
- },
- {
- USB_VENDOR_MICROTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Microtek",
- NULL,
- },
- {
- USB_VENDOR_SUNTAC, 0,
- USB_KNOWNDEV_NOPROD,
- "SUN Corporation",
- NULL,
- },
- {
- USB_VENDOR_LEXAR, 0,
- USB_KNOWNDEV_NOPROD,
- "Lexar Media",
- NULL,
- },
- {
- USB_VENDOR_ADDTRON, 0,
- USB_KNOWNDEV_NOPROD,
- "Addtron",
- NULL,
- },
- {
- USB_VENDOR_SYMBOL, 0,
- USB_KNOWNDEV_NOPROD,
- "Symbol Technologies",
- NULL,
- },
- {
- USB_VENDOR_SYNTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Syntek",
- NULL,
- },
- {
- USB_VENDOR_GENESYS, 0,
- USB_KNOWNDEV_NOPROD,
- "Genesys Logic",
- NULL,
- },
- {
- USB_VENDOR_FUJI, 0,
- USB_KNOWNDEV_NOPROD,
- "Fuji Electric",
- NULL,
- },
- {
- USB_VENDOR_KEITHLEY, 0,
- USB_KNOWNDEV_NOPROD,
- "Keithley Instruments",
- NULL,
- },
- {
- USB_VENDOR_EIZONANAO, 0,
- USB_KNOWNDEV_NOPROD,
- "EIZO Nanao",
- NULL,
- },
- {
- USB_VENDOR_KLSI, 0,
- USB_KNOWNDEV_NOPROD,
- "Kawasaki LSI",
- NULL,
- },
- {
- USB_VENDOR_FFC, 0,
- USB_KNOWNDEV_NOPROD,
- "FFC",
- NULL,
- },
- {
- USB_VENDOR_ANKO, 0,
- USB_KNOWNDEV_NOPROD,
- "Anko Electronic",
- NULL,
- },
- {
- USB_VENDOR_PIENGINEERING, 0,
- USB_KNOWNDEV_NOPROD,
- "P.I. Engineering",
- NULL,
- },
- {
- USB_VENDOR_AOC, 0,
- USB_KNOWNDEV_NOPROD,
- "AOC International",
- NULL,
- },
- {
- USB_VENDOR_CHIC, 0,
- USB_KNOWNDEV_NOPROD,
- "Chic Technology",
- NULL,
- },
- {
- USB_VENDOR_BARCO, 0,
- USB_KNOWNDEV_NOPROD,
- "Barco Display Systems",
- NULL,
- },
- {
- USB_VENDOR_BRIDGE, 0,
- USB_KNOWNDEV_NOPROD,
- "Bridge Information",
- NULL,
- },
- {
- USB_VENDOR_SOLIDYEAR, 0,
- USB_KNOWNDEV_NOPROD,
- "Solid Year",
- NULL,
- },
- {
- USB_VENDOR_BIORAD, 0,
- USB_KNOWNDEV_NOPROD,
- "Bio-Rad Laboratories",
- NULL,
- },
- {
- USB_VENDOR_MACALLY, 0,
- USB_KNOWNDEV_NOPROD,
- "Macally",
- NULL,
- },
- {
- USB_VENDOR_ACTLABS, 0,
- USB_KNOWNDEV_NOPROD,
- "Act Labs",
- NULL,
- },
- {
- USB_VENDOR_ALARIS, 0,
- USB_KNOWNDEV_NOPROD,
- "Alaris",
- NULL,
- },
- {
- USB_VENDOR_APEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Apex",
- NULL,
- },
- {
- USB_VENDOR_CREATIVE3, 0,
- USB_KNOWNDEV_NOPROD,
- "Creative Labs",
- NULL,
- },
- {
- USB_VENDOR_VIVITAR, 0,
- USB_KNOWNDEV_NOPROD,
- "Vivitar",
- NULL,
- },
- {
- USB_VENDOR_GUNZE, 0,
- USB_KNOWNDEV_NOPROD,
- "Gunze Electronics USA",
- NULL,
- },
- {
- USB_VENDOR_AVISION, 0,
- USB_KNOWNDEV_NOPROD,
- "Avision",
- NULL,
- },
- {
- USB_VENDOR_TEAC, 0,
- USB_KNOWNDEV_NOPROD,
- "TEAC",
- NULL,
- },
- {
- USB_VENDOR_SGI, 0,
- USB_KNOWNDEV_NOPROD,
- "Silicon Graphics",
- NULL,
- },
- {
- USB_VENDOR_SANWASUPPLY, 0,
- USB_KNOWNDEV_NOPROD,
- "Sanwa Supply",
- NULL,
- },
- {
- USB_VENDOR_MEGATEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Megatec",
- NULL,
- },
- {
- USB_VENDOR_LINKSYS, 0,
- USB_KNOWNDEV_NOPROD,
- "Linksys",
- NULL,
- },
- {
- USB_VENDOR_ACERSA, 0,
- USB_KNOWNDEV_NOPROD,
- "Acer Semiconductor America",
- NULL,
- },
- {
- USB_VENDOR_SIGMATEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Sigmatel",
- NULL,
- },
- {
- USB_VENDOR_DRAYTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "DrayTek",
- NULL,
- },
- {
- USB_VENDOR_AIWA, 0,
- USB_KNOWNDEV_NOPROD,
- "Aiwa",
- NULL,
- },
- {
- USB_VENDOR_ACARD, 0,
- USB_KNOWNDEV_NOPROD,
- "ACARD Technology",
- NULL,
- },
- {
- USB_VENDOR_PROLIFIC, 0,
- USB_KNOWNDEV_NOPROD,
- "Prolific Technology",
- NULL,
- },
- {
- USB_VENDOR_SIEMENS, 0,
- USB_KNOWNDEV_NOPROD,
- "Siemens",
- NULL,
- },
- {
- USB_VENDOR_AVANCELOGIC, 0,
- USB_KNOWNDEV_NOPROD,
- "Avance Logic",
- NULL,
- },
- {
- USB_VENDOR_SIEMENS2, 0,
- USB_KNOWNDEV_NOPROD,
- "Siemens",
- NULL,
- },
- {
- USB_VENDOR_MINOLTA, 0,
- USB_KNOWNDEV_NOPROD,
- "Minolta",
- NULL,
- },
- {
- USB_VENDOR_CHPRODUCTS, 0,
- USB_KNOWNDEV_NOPROD,
- "CH Products",
- NULL,
- },
- {
- USB_VENDOR_HAGIWARA, 0,
- USB_KNOWNDEV_NOPROD,
- "Hagiwara Sys-Com",
- NULL,
- },
- {
- USB_VENDOR_CTX, 0,
- USB_KNOWNDEV_NOPROD,
- "Chuntex",
- NULL,
- },
- {
- USB_VENDOR_ASKEY, 0,
- USB_KNOWNDEV_NOPROD,
- "Askey Computer",
- NULL,
- },
- {
- USB_VENDOR_SAITEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Saitek",
- NULL,
- },
- {
- USB_VENDOR_ALCATELT, 0,
- USB_KNOWNDEV_NOPROD,
- "Alcatel Telecom",
- NULL,
- },
- {
- USB_VENDOR_AGFA, 0,
- USB_KNOWNDEV_NOPROD,
- "AGFA-Gevaert",
- NULL,
- },
- {
- USB_VENDOR_ASIAMD, 0,
- USB_KNOWNDEV_NOPROD,
- "Asia Microelectronic Development",
- NULL,
- },
- {
- USB_VENDOR_BIZLINK, 0,
- USB_KNOWNDEV_NOPROD,
- "Bizlink International",
- NULL,
- },
- {
- USB_VENDOR_KEYSPAN, 0,
- USB_KNOWNDEV_NOPROD,
- "Keyspan / InnoSys Inc.",
- NULL,
- },
- {
- USB_VENDOR_AASHIMA, 0,
- USB_KNOWNDEV_NOPROD,
- "Aashima Technology",
- NULL,
- },
- {
- USB_VENDOR_LIEBERT, 0,
- USB_KNOWNDEV_NOPROD,
- "Liebert",
- NULL,
- },
- {
- USB_VENDOR_MULTITECH, 0,
- USB_KNOWNDEV_NOPROD,
- "MultiTech",
- NULL,
- },
- {
- USB_VENDOR_ADS, 0,
- USB_KNOWNDEV_NOPROD,
- "ADS Technologies",
- NULL,
- },
- {
- USB_VENDOR_ALCATELM, 0,
- USB_KNOWNDEV_NOPROD,
- "Alcatel Microelectronics",
- NULL,
- },
- {
- USB_VENDOR_SIRIUS, 0,
- USB_KNOWNDEV_NOPROD,
- "Sirius Technologies",
- NULL,
- },
- {
- USB_VENDOR_GUILLEMOT, 0,
- USB_KNOWNDEV_NOPROD,
- "Guillemot",
- NULL,
- },
- {
- USB_VENDOR_BOSTON, 0,
- USB_KNOWNDEV_NOPROD,
- "Boston Acoustics",
- NULL,
- },
- {
- USB_VENDOR_SMC, 0,
- USB_KNOWNDEV_NOPROD,
- "Standard Microsystems",
- NULL,
- },
- {
- USB_VENDOR_PUTERCOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Putercom",
- NULL,
- },
- {
- USB_VENDOR_MCT, 0,
- USB_KNOWNDEV_NOPROD,
- "MCT",
- NULL,
- },
- {
- USB_VENDOR_IMATION, 0,
- USB_KNOWNDEV_NOPROD,
- "Imation",
- NULL,
- },
- {
- USB_VENDOR_TECLAST, 0,
- USB_KNOWNDEV_NOPROD,
- "Teclast",
- NULL,
- },
- {
- USB_VENDOR_SONYERICSSON, 0,
- USB_KNOWNDEV_NOPROD,
- "Sony Ericsson",
- NULL,
- },
- {
- USB_VENDOR_EICON, 0,
- USB_KNOWNDEV_NOPROD,
- "Eicon Networks",
- NULL,
- },
- {
- USB_VENDOR_SYNTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Syntech Information",
- NULL,
- },
- {
- USB_VENDOR_DIGITALSTREAM, 0,
- USB_KNOWNDEV_NOPROD,
- "Digital Stream",
- NULL,
- },
- {
- USB_VENDOR_AUREAL, 0,
- USB_KNOWNDEV_NOPROD,
- "Aureal Semiconductor",
- NULL,
- },
- {
- USB_VENDOR_MIDIMAN, 0,
- USB_KNOWNDEV_NOPROD,
- "Midiman",
- NULL,
- },
- {
- USB_VENDOR_CYBERPOWER, 0,
- USB_KNOWNDEV_NOPROD,
- "Cyber Power Systems, Inc.",
- NULL,
- },
- {
- USB_VENDOR_SURECOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Surecom Technology",
- NULL,
- },
- {
- USB_VENDOR_HIDGLOBAL, 0,
- USB_KNOWNDEV_NOPROD,
- "HID Global",
- NULL,
- },
- {
- USB_VENDOR_LINKSYS2, 0,
- USB_KNOWNDEV_NOPROD,
- "Linksys",
- NULL,
- },
- {
- USB_VENDOR_GRIFFIN, 0,
- USB_KNOWNDEV_NOPROD,
- "Griffin Technology",
- NULL,
- },
- {
- USB_VENDOR_SANDISK, 0,
- USB_KNOWNDEV_NOPROD,
- "SanDisk",
- NULL,
- },
- {
- USB_VENDOR_JENOPTIK, 0,
- USB_KNOWNDEV_NOPROD,
- "Jenoptik",
- NULL,
- },
- {
- USB_VENDOR_LOGITEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Logitec",
- NULL,
- },
- {
- USB_VENDOR_NOKIA2, 0,
- USB_KNOWNDEV_NOPROD,
- "Nokia",
- NULL,
- },
- {
- USB_VENDOR_BRIMAX, 0,
- USB_KNOWNDEV_NOPROD,
- "Brimax",
- NULL,
- },
- {
- USB_VENDOR_AXIS, 0,
- USB_KNOWNDEV_NOPROD,
- "Axis Communications",
- NULL,
- },
- {
- USB_VENDOR_ABL, 0,
- USB_KNOWNDEV_NOPROD,
- "ABL Electronics",
- NULL,
- },
- {
- USB_VENDOR_SAGEM, 0,
- USB_KNOWNDEV_NOPROD,
- "Sagem",
- NULL,
- },
- {
- USB_VENDOR_SUNCOMM, 0,
- USB_KNOWNDEV_NOPROD,
- "Sun Communications, Inc.",
- NULL,
- },
- {
- USB_VENDOR_ALFADATA, 0,
- USB_KNOWNDEV_NOPROD,
- "Alfadata Computer",
- NULL,
- },
- {
- USB_VENDOR_NATIONALTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "National Technical Systems",
- NULL,
- },
- {
- USB_VENDOR_ONNTO, 0,
- USB_KNOWNDEV_NOPROD,
- "Onnto",
- NULL,
- },
- {
- USB_VENDOR_BE, 0,
- USB_KNOWNDEV_NOPROD,
- "Be",
- NULL,
- },
- {
- USB_VENDOR_ADMTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "ADMtek",
- NULL,
- },
- {
- USB_VENDOR_COREGA, 0,
- USB_KNOWNDEV_NOPROD,
- "Corega",
- NULL,
- },
- {
- USB_VENDOR_FREECOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Freecom",
- NULL,
- },
- {
- USB_VENDOR_MICROTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Microtech",
- NULL,
- },
- {
- USB_VENDOR_GENERALINSTMNTS, 0,
- USB_KNOWNDEV_NOPROD,
- "General Instruments (Motorola)",
- NULL,
- },
- {
- USB_VENDOR_OLYMPUS, 0,
- USB_KNOWNDEV_NOPROD,
- "Olympus",
- NULL,
- },
- {
- USB_VENDOR_ABOCOM, 0,
- USB_KNOWNDEV_NOPROD,
- "AboCom Systems",
- NULL,
- },
- {
- USB_VENDOR_KEISOKUGIKEN, 0,
- USB_KNOWNDEV_NOPROD,
- "Keisokugiken",
- NULL,
- },
- {
- USB_VENDOR_ONSPEC, 0,
- USB_KNOWNDEV_NOPROD,
- "OnSpec",
- NULL,
- },
- {
- USB_VENDOR_APG, 0,
- USB_KNOWNDEV_NOPROD,
- "APG Cash Drawer",
- NULL,
- },
- {
- USB_VENDOR_BUG, 0,
- USB_KNOWNDEV_NOPROD,
- "B.U.G.",
- NULL,
- },
- {
- USB_VENDOR_ALLIEDTELESYN, 0,
- USB_KNOWNDEV_NOPROD,
- "Allied Telesyn International",
- NULL,
- },
- {
- USB_VENDOR_AVERMEDIA, 0,
- USB_KNOWNDEV_NOPROD,
- "AVerMedia Technologies",
- NULL,
- },
- {
- USB_VENDOR_SIIG, 0,
- USB_KNOWNDEV_NOPROD,
- "SIIG",
- NULL,
- },
- {
- USB_VENDOR_CASIO, 0,
- USB_KNOWNDEV_NOPROD,
- "CASIO",
- NULL,
- },
- {
- USB_VENDOR_DLINK2, 0,
- USB_KNOWNDEV_NOPROD,
- "D-Link",
- NULL,
- },
- {
- USB_VENDOR_APTIO, 0,
- USB_KNOWNDEV_NOPROD,
- "Aptio Products",
- NULL,
- },
- {
- USB_VENDOR_ARASAN, 0,
- USB_KNOWNDEV_NOPROD,
- "Arasan Chip Systems",
- NULL,
- },
- {
- USB_VENDOR_ALLIEDCABLE, 0,
- USB_KNOWNDEV_NOPROD,
- "Allied Cable",
- NULL,
- },
- {
- USB_VENDOR_STSN, 0,
- USB_KNOWNDEV_NOPROD,
- "STSN",
- NULL,
- },
- {
- USB_VENDOR_CENTURY, 0,
- USB_KNOWNDEV_NOPROD,
- "Century Corp",
- NULL,
- },
- {
- USB_VENDOR_NEWLINK, 0,
- USB_KNOWNDEV_NOPROD,
- "NEWlink",
- NULL,
- },
- {
- USB_VENDOR_ZOOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Zoom Telephonics",
- NULL,
- },
- {
- USB_VENDOR_PCS, 0,
- USB_KNOWNDEV_NOPROD,
- "Personal Communication Systems",
- NULL,
- },
- {
- USB_VENDOR_ALPHASMART, 0,
- USB_KNOWNDEV_NOPROD,
- "AlphaSmart, Inc.",
- NULL,
- },
- {
- USB_VENDOR_BROADLOGIC, 0,
- USB_KNOWNDEV_NOPROD,
- "BroadLogic",
- NULL,
- },
- {
- USB_VENDOR_HANDSPRING, 0,
- USB_KNOWNDEV_NOPROD,
- "Handspring",
- NULL,
- },
- {
- USB_VENDOR_PALM, 0,
- USB_KNOWNDEV_NOPROD,
- "Palm Computing",
- NULL,
- },
- {
- USB_VENDOR_SOURCENEXT, 0,
- USB_KNOWNDEV_NOPROD,
- "SOURCENEXT",
- NULL,
- },
- {
- USB_VENDOR_ACTIONSTAR, 0,
- USB_KNOWNDEV_NOPROD,
- "Action Star Enterprise",
- NULL,
- },
- {
- USB_VENDOR_SAMSUNG_TECHWIN, 0,
- USB_KNOWNDEV_NOPROD,
- "Samsung Techwin",
- NULL,
- },
- {
- USB_VENDOR_ACCTON, 0,
- USB_KNOWNDEV_NOPROD,
- "Accton Technology",
- NULL,
- },
- {
- USB_VENDOR_DIAMOND, 0,
- USB_KNOWNDEV_NOPROD,
- "Diamond",
- NULL,
- },
- {
- USB_VENDOR_NETGEAR, 0,
- USB_KNOWNDEV_NOPROD,
- "BayNETGEAR",
- NULL,
- },
- {
- USB_VENDOR_TOPRE, 0,
- USB_KNOWNDEV_NOPROD,
- "Topre Corporation",
- NULL,
- },
- {
- USB_VENDOR_ACTIVEWIRE, 0,
- USB_KNOWNDEV_NOPROD,
- "ActiveWire",
- NULL,
- },
- {
- USB_VENDOR_BBELECTRONICS, 0,
- USB_KNOWNDEV_NOPROD,
- "B&B Electronics",
- NULL,
- },
- {
- USB_VENDOR_PORTGEAR, 0,
- USB_KNOWNDEV_NOPROD,
- "PortGear",
- NULL,
- },
- {
- USB_VENDOR_NETGEAR2, 0,
- USB_KNOWNDEV_NOPROD,
- "Netgear",
- NULL,
- },
- {
- USB_VENDOR_SYSTEMTALKS, 0,
- USB_KNOWNDEV_NOPROD,
- "System Talks",
- NULL,
- },
- {
- USB_VENDOR_METRICOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Metricom",
- NULL,
- },
- {
- USB_VENDOR_ADESSOKBTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "ADESSO/Kbtek America",
- NULL,
- },
- {
- USB_VENDOR_JATON, 0,
- USB_KNOWNDEV_NOPROD,
- "Jaton",
- NULL,
- },
- {
- USB_VENDOR_APT, 0,
- USB_KNOWNDEV_NOPROD,
- "APT Technologies",
- NULL,
- },
- {
- USB_VENDOR_BOCARESEARCH, 0,
- USB_KNOWNDEV_NOPROD,
- "Boca Research",
- NULL,
- },
- {
- USB_VENDOR_ANDREA, 0,
- USB_KNOWNDEV_NOPROD,
- "Andrea Electronics",
- NULL,
- },
- {
- USB_VENDOR_BURRBROWN, 0,
- USB_KNOWNDEV_NOPROD,
- "Burr-Brown Japan",
- NULL,
- },
- {
- USB_VENDOR_2WIRE, 0,
- USB_KNOWNDEV_NOPROD,
- "2Wire",
- NULL,
- },
- {
- USB_VENDOR_AIPTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "AIPTEK International",
- NULL,
- },
- {
- USB_VENDOR_SMARTBRIDGES, 0,
- USB_KNOWNDEV_NOPROD,
- "SmartBridges",
- NULL,
- },
- {
- USB_VENDOR_FUJITSUSIEMENS, 0,
- USB_KNOWNDEV_NOPROD,
- "Fujitsu-Siemens",
- NULL,
- },
- {
- USB_VENDOR_BILLIONTON, 0,
- USB_KNOWNDEV_NOPROD,
- "Billionton Systems",
- NULL,
- },
- {
- USB_VENDOR_GEMALTO, 0,
- USB_KNOWNDEV_NOPROD,
- "Gemalto SA",
- NULL,
- },
- {
- USB_VENDOR_EXTENDED, 0,
- USB_KNOWNDEV_NOPROD,
- "Extended Systems",
- NULL,
- },
- {
- USB_VENDOR_MSYSTEMS, 0,
- USB_KNOWNDEV_NOPROD,
- "M-Systems",
- NULL,
- },
- {
- USB_VENDOR_DIGIANSWER, 0,
- USB_KNOWNDEV_NOPROD,
- "Digianswer",
- NULL,
- },
- {
- USB_VENDOR_AUTHENTEC, 0,
- USB_KNOWNDEV_NOPROD,
- "AuthenTec",
- NULL,
- },
- {
- USB_VENDOR_AUDIOTECHNICA, 0,
- USB_KNOWNDEV_NOPROD,
- "Audio-Technica",
- NULL,
- },
- {
- USB_VENDOR_TRUMPION, 0,
- USB_KNOWNDEV_NOPROD,
- "Trumpion Microelectronics",
- NULL,
- },
- {
- USB_VENDOR_FEIYA, 0,
- USB_KNOWNDEV_NOPROD,
- "Feiya",
- NULL,
- },
- {
- USB_VENDOR_ALATION, 0,
- USB_KNOWNDEV_NOPROD,
- "Alation Systems",
- NULL,
- },
- {
- USB_VENDOR_GLOBESPAN, 0,
- USB_KNOWNDEV_NOPROD,
- "Globespan",
- NULL,
- },
- {
- USB_VENDOR_CONCORDCAMERA, 0,
- USB_KNOWNDEV_NOPROD,
- "Concord Camera",
- NULL,
- },
- {
- USB_VENDOR_GARMIN, 0,
- USB_KNOWNDEV_NOPROD,
- "Garmin International",
- NULL,
- },
- {
- USB_VENDOR_GOHUBS, 0,
- USB_KNOWNDEV_NOPROD,
- "GoHubs",
- NULL,
- },
- {
- USB_VENDOR_XEROX, 0,
- USB_KNOWNDEV_NOPROD,
- "Xerox",
- NULL,
- },
- {
- USB_VENDOR_BIOMETRIC, 0,
- USB_KNOWNDEV_NOPROD,
- "American Biometric Company",
- NULL,
- },
- {
- USB_VENDOR_TOSHIBA, 0,
- USB_KNOWNDEV_NOPROD,
- "Toshiba",
- NULL,
- },
- {
- USB_VENDOR_PLEXTOR, 0,
- USB_KNOWNDEV_NOPROD,
- "Plextor",
- NULL,
- },
- {
- USB_VENDOR_INTREPIDCS, 0,
- USB_KNOWNDEV_NOPROD,
- "Intrepid",
- NULL,
- },
- {
- USB_VENDOR_YANO, 0,
- USB_KNOWNDEV_NOPROD,
- "Yano",
- NULL,
- },
- {
- USB_VENDOR_KINGSTON, 0,
- USB_KNOWNDEV_NOPROD,
- "Kingston Technology",
- NULL,
- },
- {
- USB_VENDOR_BLUEWATER, 0,
- USB_KNOWNDEV_NOPROD,
- "BlueWater Systems",
- NULL,
- },
- {
- USB_VENDOR_AGILENT, 0,
- USB_KNOWNDEV_NOPROD,
- "Agilent Technologies",
- NULL,
- },
- {
- USB_VENDOR_GUDE, 0,
- USB_KNOWNDEV_NOPROD,
- "Gude ADS",
- NULL,
- },
- {
- USB_VENDOR_PORTSMITH, 0,
- USB_KNOWNDEV_NOPROD,
- "Portsmith",
- NULL,
- },
- {
- USB_VENDOR_ACERW, 0,
- USB_KNOWNDEV_NOPROD,
- "Acer",
- NULL,
- },
- {
- USB_VENDOR_ADIRONDACK, 0,
- USB_KNOWNDEV_NOPROD,
- "Adirondack Wire & Cable",
- NULL,
- },
- {
- USB_VENDOR_BECKHOFF, 0,
- USB_KNOWNDEV_NOPROD,
- "Beckhoff",
- NULL,
- },
- {
- USB_VENDOR_MINDSATWORK, 0,
- USB_KNOWNDEV_NOPROD,
- "Minds At Work",
- NULL,
- },
- {
- USB_VENDOR_POINTCHIPS, 0,
- USB_KNOWNDEV_NOPROD,
- "PointChips",
- NULL,
- },
- {
- USB_VENDOR_INTERSIL, 0,
- USB_KNOWNDEV_NOPROD,
- "Intersil",
- NULL,
- },
- {
- USB_VENDOR_ALTIUS, 0,
- USB_KNOWNDEV_NOPROD,
- "Altius Solutions",
- NULL,
- },
- {
- USB_VENDOR_ARRIS, 0,
- USB_KNOWNDEV_NOPROD,
- "Arris Interactive",
- NULL,
- },
- {
- USB_VENDOR_ACTIVCARD, 0,
- USB_KNOWNDEV_NOPROD,
- "ACTIVCARD",
- NULL,
- },
- {
- USB_VENDOR_ACTISYS, 0,
- USB_KNOWNDEV_NOPROD,
- "ACTiSYS",
- NULL,
- },
- {
- USB_VENDOR_NOVATEL2, 0,
- USB_KNOWNDEV_NOPROD,
- "Novatel Wireless",
- NULL,
- },
- {
- USB_VENDOR_AFOURTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "A-FOUR TECH",
- NULL,
- },
- {
- USB_VENDOR_AIMEX, 0,
- USB_KNOWNDEV_NOPROD,
- "AIMEX",
- NULL,
- },
- {
- USB_VENDOR_ADDONICS, 0,
- USB_KNOWNDEV_NOPROD,
- "Addonics Technologies",
- NULL,
- },
- {
- USB_VENDOR_AKAI, 0,
- USB_KNOWNDEV_NOPROD,
- "AKAI professional M.I.",
- NULL,
- },
- {
- USB_VENDOR_ARESCOM, 0,
- USB_KNOWNDEV_NOPROD,
- "ARESCOM",
- NULL,
- },
- {
- USB_VENDOR_BAY, 0,
- USB_KNOWNDEV_NOPROD,
- "Bay Associates",
- NULL,
- },
- {
- USB_VENDOR_ALTERA, 0,
- USB_KNOWNDEV_NOPROD,
- "Altera",
- NULL,
- },
- {
- USB_VENDOR_CSR, 0,
- USB_KNOWNDEV_NOPROD,
- "Cambridge Silicon Radio",
- NULL,
- },
- {
- USB_VENDOR_TREK, 0,
- USB_KNOWNDEV_NOPROD,
- "Trek Technology",
- NULL,
- },
- {
- USB_VENDOR_ASAHIOPTICAL, 0,
- USB_KNOWNDEV_NOPROD,
- "Asahi Optical",
- NULL,
- },
- {
- USB_VENDOR_BOCASYSTEMS, 0,
- USB_KNOWNDEV_NOPROD,
- "Boca Systems",
- NULL,
- },
- {
- USB_VENDOR_SHANTOU, 0,
- USB_KNOWNDEV_NOPROD,
- "ShanTou",
- NULL,
- },
- {
- USB_VENDOR_MEDIAGEAR, 0,
- USB_KNOWNDEV_NOPROD,
- "MediaGear",
- NULL,
- },
- {
- USB_VENDOR_BROADCOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Broadcom",
- NULL,
- },
- {
- USB_VENDOR_GREENHOUSE, 0,
- USB_KNOWNDEV_NOPROD,
- "GREENHOUSE",
- NULL,
- },
- {
- USB_VENDOR_GEOCAST, 0,
- USB_KNOWNDEV_NOPROD,
- "Geocast Network Systems",
- NULL,
- },
- {
- USB_VENDOR_IDQUANTIQUE, 0,
- USB_KNOWNDEV_NOPROD,
- "id Quantique",
- NULL,
- },
- {
- USB_VENDOR_ZYDAS, 0,
- USB_KNOWNDEV_NOPROD,
- "Zydas Technology Corporation",
- NULL,
- },
- {
- USB_VENDOR_NEODIO, 0,
- USB_KNOWNDEV_NOPROD,
- "Neodio",
- NULL,
- },
- {
- USB_VENDOR_OPTION, 0,
- USB_KNOWNDEV_NOPROD,
- "Option N.V.",
- NULL,
- },
- {
- USB_VENDOR_ASUS, 0,
- USB_KNOWNDEV_NOPROD,
- "ASUSTeK Computer",
- NULL,
- },
- {
- USB_VENDOR_TODOS, 0,
- USB_KNOWNDEV_NOPROD,
- "Todos Data System",
- NULL,
- },
- {
- USB_VENDOR_SIIG2, 0,
- USB_KNOWNDEV_NOPROD,
- "SIIG",
- NULL,
- },
- {
- USB_VENDOR_TEKRAM, 0,
- USB_KNOWNDEV_NOPROD,
- "Tekram Technology",
- NULL,
- },
- {
- USB_VENDOR_HAL, 0,
- USB_KNOWNDEV_NOPROD,
- "HAL Corporation",
- NULL,
- },
- {
- USB_VENDOR_EMS, 0,
- USB_KNOWNDEV_NOPROD,
- "EMS Production",
- NULL,
- },
- {
- USB_VENDOR_NEC2, 0,
- USB_KNOWNDEV_NOPROD,
- "NEC",
- NULL,
- },
- {
- USB_VENDOR_ADLINK, 0,
- USB_KNOWNDEV_NOPROD,
- "ADLINK Technoligy, Inc.",
- NULL,
- },
- {
- USB_VENDOR_ATI2, 0,
- USB_KNOWNDEV_NOPROD,
- "ATI",
- NULL,
- },
- {
- USB_VENDOR_ZEEVO, 0,
- USB_KNOWNDEV_NOPROD,
- "Zeevo, Inc.",
- NULL,
- },
- {
- USB_VENDOR_KURUSUGAWA, 0,
- USB_KNOWNDEV_NOPROD,
- "Kurusugawa Electronics, Inc.",
- NULL,
- },
- {
- USB_VENDOR_SMART, 0,
- USB_KNOWNDEV_NOPROD,
- "Smart Technologies",
- NULL,
- },
- {
- USB_VENDOR_ASIX, 0,
- USB_KNOWNDEV_NOPROD,
- "ASIX Electronics",
- NULL,
- },
- {
- USB_VENDOR_O2MICRO, 0,
- USB_KNOWNDEV_NOPROD,
- "O2 Micro, Inc.",
- NULL,
- },
- {
- USB_VENDOR_USR, 0,
- USB_KNOWNDEV_NOPROD,
- "U.S. Robotics",
- NULL,
- },
- {
- USB_VENDOR_AMBIT, 0,
- USB_KNOWNDEV_NOPROD,
- "Ambit Microsystems",
- NULL,
- },
- {
- USB_VENDOR_HTC, 0,
- USB_KNOWNDEV_NOPROD,
- "HTC",
- NULL,
- },
- {
- USB_VENDOR_REALTEK, 0,
- USB_KNOWNDEV_NOPROD,
- "Realtek",
- NULL,
- },
- {
- USB_VENDOR_MEI, 0,
- USB_KNOWNDEV_NOPROD,
- "MEI",
- NULL,
- },
- {
- USB_VENDOR_ADDONICS2, 0,
- USB_KNOWNDEV_NOPROD,
- "Addonics Technology",
- NULL,
- },
- {
- USB_VENDOR_FSC, 0,
- USB_KNOWNDEV_NOPROD,
- "Fujitsu Siemens Computers",
- NULL,
- },
- {
- USB_VENDOR_AGATE, 0,
- USB_KNOWNDEV_NOPROD,
- "Agate Technologies",
- NULL,
- },
- {
- USB_VENDOR_DMI, 0,
- USB_KNOWNDEV_NOPROD,
- "DMI",
- NULL,
- },
- {
- USB_VENDOR_CHICONY2, 0,
- USB_KNOWNDEV_NOPROD,
- "Chicony",
- NULL,
- },
- {
- USB_VENDOR_REINERSCT, 0,
- USB_KNOWNDEV_NOPROD,
- "Reiner-SCT",
- NULL,
- },
- {
- USB_VENDOR_SEALEVEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Sealevel System",
- NULL,
- },
- {
- USB_VENDOR_LUWEN, 0,
- USB_KNOWNDEV_NOPROD,
- "Luwen",
- NULL,
- },
- {
- USB_VENDOR_KYOCERA2, 0,
- USB_KNOWNDEV_NOPROD,
- "Kyocera Wireless Corp.",
- NULL,
- },
- {
- USB_VENDOR_ZCOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Z-Com",
- NULL,
- },
- {
- USB_VENDOR_ATHEROS2, 0,
- USB_KNOWNDEV_NOPROD,
- "Atheros Communications",
- NULL,
- },
- {
- USB_VENDOR_TANGTOP, 0,
- USB_KNOWNDEV_NOPROD,
- "Tangtop",
- NULL,
- },
- {
- USB_VENDOR_SMC3, 0,
- USB_KNOWNDEV_NOPROD,
- "Standard Microsystems",
- NULL,
- },
- {
- USB_VENDOR_ADDON, 0,
- USB_KNOWNDEV_NOPROD,
- "Add-on Technology",
- NULL,
- },
- {
- USB_VENDOR_ACDC, 0,
- USB_KNOWNDEV_NOPROD,
- "American Computer & Digital Components",
- NULL,
- },
- {
- USB_VENDOR_CMEDIA, 0,
- USB_KNOWNDEV_NOPROD,
- "CMEDIA",
- NULL,
- },
- {
- USB_VENDOR_CONCEPTRONIC, 0,
- USB_KNOWNDEV_NOPROD,
- "Conceptronic",
- NULL,
- },
- {
- USB_VENDOR_SKANHEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Skanhex Technology, Inc.",
- NULL,
- },
- {
- USB_VENDOR_MSI, 0,
- USB_KNOWNDEV_NOPROD,
- "Micro Star International",
- NULL,
- },
- {
- USB_VENDOR_ELCON, 0,
- USB_KNOWNDEV_NOPROD,
- "ELCON Systemtechnik",
- NULL,
- },
- {
- USB_VENDOR_NETAC, 0,
- USB_KNOWNDEV_NOPROD,
- "Netac",
- NULL,
- },
- {
- USB_VENDOR_SITECOMEU, 0,
- USB_KNOWNDEV_NOPROD,
- "Sitecom Europe",
- NULL,
- },
- {
- USB_VENDOR_MOBILEACTION, 0,
- USB_KNOWNDEV_NOPROD,
- "Mobile Action",
- NULL,
- },
- {
- USB_VENDOR_AMIGO, 0,
- USB_KNOWNDEV_NOPROD,
- "Amigo Technology",
- NULL,
- },
- {
- USB_VENDOR_SPEEDDRAGON, 0,
- USB_KNOWNDEV_NOPROD,
- "Speed Dragon Multimedia",
- NULL,
- },
- {
- USB_VENDOR_HAWKING, 0,
- USB_KNOWNDEV_NOPROD,
- "Hawking",
- NULL,
- },
- {
- USB_VENDOR_FOSSIL, 0,
- USB_KNOWNDEV_NOPROD,
- "Fossil, Inc",
- NULL,
- },
- {
- USB_VENDOR_GMATE, 0,
- USB_KNOWNDEV_NOPROD,
- "G.Mate, Inc",
- NULL,
- },
- {
- USB_VENDOR_OTI, 0,
- USB_KNOWNDEV_NOPROD,
- "Ours Technology",
- NULL,
- },
- {
- USB_VENDOR_YISO, 0,
- USB_KNOWNDEV_NOPROD,
- "Yiso Wireless Co.",
- NULL,
- },
- {
- USB_VENDOR_PILOTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Pilotech",
- NULL,
- },
- {
- USB_VENDOR_NOVATECH, 0,
- USB_KNOWNDEV_NOPROD,
- "NovaTech",
- NULL,
- },
- {
- USB_VENDOR_ITEGNO, 0,
- USB_KNOWNDEV_NOPROD,
- "iTegno",
- NULL,
- },
- {
- USB_VENDOR_WINMAXGROUP, 0,
- USB_KNOWNDEV_NOPROD,
- "WinMaxGroup",
- NULL,
- },
- {
- USB_VENDOR_TOD, 0,
- USB_KNOWNDEV_NOPROD,
- "TOD",
- NULL,
- },
- {
- USB_VENDOR_EGALAX, 0,
- USB_KNOWNDEV_NOPROD,
- "eGalax, Inc.",
- NULL,
- },
- {
- USB_VENDOR_AIRPRIME, 0,
- USB_KNOWNDEV_NOPROD,
- "AirPrime, Inc.",
- NULL,
- },
- {
- USB_VENDOR_MICROTUNE, 0,
- USB_KNOWNDEV_NOPROD,
- "Microtune",
- NULL,
- },
- {
- USB_VENDOR_VTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "VTech",
- NULL,
- },
- {
- USB_VENDOR_FALCOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Falcom Wireless Communications GmbH",
- NULL,
- },
- {
- USB_VENDOR_RIM, 0,
- USB_KNOWNDEV_NOPROD,
- "Research In Motion",
- NULL,
- },
- {
- USB_VENDOR_DYNASTREAM, 0,
- USB_KNOWNDEV_NOPROD,
- "Dynastream Innovations",
- NULL,
- },
- {
- USB_VENDOR_QUALCOMM, 0,
- USB_KNOWNDEV_NOPROD,
- "Qualcomm",
- NULL,
- },
- {
- USB_VENDOR_APACER, 0,
- USB_KNOWNDEV_NOPROD,
- "Apacer",
- NULL,
- },
- {
- USB_VENDOR_MOTOROLA4, 0,
- USB_KNOWNDEV_NOPROD,
- "Motorola",
- NULL,
- },
- {
- USB_VENDOR_AIRPLUS, 0,
- USB_KNOWNDEV_NOPROD,
- "Airplus",
- NULL,
- },
- {
- USB_VENDOR_DESKNOTE, 0,
- USB_KNOWNDEV_NOPROD,
- "Desknote",
- NULL,
- },
- {
- USB_VENDOR_GIGABYTE, 0,
- USB_KNOWNDEV_NOPROD,
- "GIGABYTE",
- NULL,
- },
- {
- USB_VENDOR_WESTERN, 0,
- USB_KNOWNDEV_NOPROD,
- "Western Digital",
- NULL,
- },
- {
- USB_VENDOR_MOTOROLA, 0,
- USB_KNOWNDEV_NOPROD,
- "Motorola",
- NULL,
- },
- {
- USB_VENDOR_CCYU, 0,
- USB_KNOWNDEV_NOPROD,
- "CCYU Technology",
- NULL,
- },
- {
- USB_VENDOR_CURITEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Curitel Communications Inc",
- NULL,
- },
- {
- USB_VENDOR_SILABS2, 0,
- USB_KNOWNDEV_NOPROD,
- "SILABS2",
- NULL,
- },
- {
- USB_VENDOR_USI, 0,
- USB_KNOWNDEV_NOPROD,
- "USI",
- NULL,
- },
- {
- USB_VENDOR_PLX, 0,
- USB_KNOWNDEV_NOPROD,
- "PLX",
- NULL,
- },
- {
- USB_VENDOR_ASANTE, 0,
- USB_KNOWNDEV_NOPROD,
- "Asante",
- NULL,
- },
- {
- USB_VENDOR_SILABS, 0,
- USB_KNOWNDEV_NOPROD,
- "Silicon Labs",
- NULL,
- },
- {
- USB_VENDOR_SILABS3, 0,
- USB_KNOWNDEV_NOPROD,
- "Silicon Labs",
- NULL,
- },
- {
- USB_VENDOR_SILABS4, 0,
- USB_KNOWNDEV_NOPROD,
- "Silicon Labs",
- NULL,
- },
- {
- USB_VENDOR_ACTIONS, 0,
- USB_KNOWNDEV_NOPROD,
- "Actions",
- NULL,
- },
- {
- USB_VENDOR_ANALOG, 0,
- USB_KNOWNDEV_NOPROD,
- "Analog Devices",
- NULL,
- },
- {
- USB_VENDOR_TENX, 0,
- USB_KNOWNDEV_NOPROD,
- "Ten X Technology, Inc.",
- NULL,
- },
- {
- USB_VENDOR_ISSC, 0,
- USB_KNOWNDEV_NOPROD,
- "Integrated System Solution Corp.",
- NULL,
- },
- {
- USB_VENDOR_JRC, 0,
- USB_KNOWNDEV_NOPROD,
- "Japan Radio Company",
- NULL,
- },
- {
- USB_VENDOR_SPHAIRON, 0,
- USB_KNOWNDEV_NOPROD,
- "Sphairon Access Systems GmbH",
- NULL,
- },
- {
- USB_VENDOR_DELORME, 0,
- USB_KNOWNDEV_NOPROD,
- "DeLorme",
- NULL,
- },
- {
- USB_VENDOR_SERVERWORKS, 0,
- USB_KNOWNDEV_NOPROD,
- "ServerWorks",
- NULL,
- },
- {
- USB_VENDOR_DLINK3, 0,
- USB_KNOWNDEV_NOPROD,
- "Dlink",
- NULL,
- },
- {
- USB_VENDOR_ACERCM, 0,
- USB_KNOWNDEV_NOPROD,
- "Acer Communications & Multimedia",
- NULL,
- },
- {
- USB_VENDOR_SIERRA, 0,
- USB_KNOWNDEV_NOPROD,
- "Sierra Wireless",
- NULL,
- },
- {
- USB_VENDOR_SANWA, 0,
- USB_KNOWNDEV_NOPROD,
- "Sanwa Electric Instrument Co., Ltd.",
- NULL,
- },
- {
- USB_VENDOR_TOPFIELD, 0,
- USB_KNOWNDEV_NOPROD,
- "Topfield Co., Ltd",
- NULL,
- },
- {
- USB_VENDOR_SIEMENS3, 0,
- USB_KNOWNDEV_NOPROD,
- "Siemens",
- NULL,
- },
- {
- USB_VENDOR_NETINDEX, 0,
- USB_KNOWNDEV_NOPROD,
- "NetIndex",
- NULL,
- },
- {
- USB_VENDOR_ALCATEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Alcatel",
- NULL,
- },
- {
- USB_VENDOR_UNKNOWN3, 0,
- USB_KNOWNDEV_NOPROD,
- "Unknown vendor",
- NULL,
- },
- {
- USB_VENDOR_TSUNAMI, 0,
- USB_KNOWNDEV_NOPROD,
- "Tsunami",
- NULL,
- },
- {
- USB_VENDOR_PHEENET, 0,
- USB_KNOWNDEV_NOPROD,
- "Pheenet",
- NULL,
- },
- {
- USB_VENDOR_TARGUS, 0,
- USB_KNOWNDEV_NOPROD,
- "Targus",
- NULL,
- },
- {
- USB_VENDOR_TWINMOS, 0,
- USB_KNOWNDEV_NOPROD,
- "TwinMOS",
- NULL,
- },
- {
- USB_VENDOR_TENDA, 0,
- USB_KNOWNDEV_NOPROD,
- "Tenda",
- NULL,
- },
- {
- USB_VENDOR_CREATIVE2, 0,
- USB_KNOWNDEV_NOPROD,
- "Creative Labs",
- NULL,
- },
- {
- USB_VENDOR_BELKIN2, 0,
- USB_KNOWNDEV_NOPROD,
- "Belkin Components",
- NULL,
- },
- {
- USB_VENDOR_CYBERTAN, 0,
- USB_KNOWNDEV_NOPROD,
- "CyberTAN Technology",
- NULL,
- },
- {
- USB_VENDOR_HUAWEI, 0,
- USB_KNOWNDEV_NOPROD,
- "Huawei Technologies",
- NULL,
- },
- {
- USB_VENDOR_ARANEUS, 0,
- USB_KNOWNDEV_NOPROD,
- "Araneus Information Systems",
- NULL,
- },
- {
- USB_VENDOR_TAPWAVE, 0,
- USB_KNOWNDEV_NOPROD,
- "Tapwave",
- NULL,
- },
- {
- USB_VENDOR_AINCOMM, 0,
- USB_KNOWNDEV_NOPROD,
- "Aincomm",
- NULL,
- },
- {
- USB_VENDOR_MOBILITY, 0,
- USB_KNOWNDEV_NOPROD,
- "Mobility",
- NULL,
- },
- {
- USB_VENDOR_DICKSMITH, 0,
- USB_KNOWNDEV_NOPROD,
- "Dick Smith Electronics",
- NULL,
- },
- {
- USB_VENDOR_NETGEAR3, 0,
- USB_KNOWNDEV_NOPROD,
- "Netgear",
- NULL,
- },
- {
- USB_VENDOR_BALTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Baltech",
- NULL,
- },
- {
- USB_VENDOR_CISCOLINKSYS, 0,
- USB_KNOWNDEV_NOPROD,
- "Cisco-Linksys",
- NULL,
- },
- {
- USB_VENDOR_SHARK, 0,
- USB_KNOWNDEV_NOPROD,
- "Shark",
- NULL,
- },
- {
- USB_VENDOR_AZUREWAVE, 0,
- USB_KNOWNDEV_NOPROD,
- "AsureWave",
- NULL,
- },
- {
- USB_VENDOR_EMTEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Emtec",
- NULL,
- },
- {
- USB_VENDOR_NOVATEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Novatel Wireless",
- NULL,
- },
- {
- USB_VENDOR_MERLIN, 0,
- USB_KNOWNDEV_NOPROD,
- "Merlin",
- NULL,
- },
- {
- USB_VENDOR_WISTRONNEWEB, 0,
- USB_KNOWNDEV_NOPROD,
- "Wistron NeWeb",
- NULL,
- },
- {
- USB_VENDOR_RADIOSHACK, 0,
- USB_KNOWNDEV_NOPROD,
- "Radio Shack",
- NULL,
- },
- {
- USB_VENDOR_HUAWEI3COM, 0,
- USB_KNOWNDEV_NOPROD,
- "Huawei-3Com",
- NULL,
- },
- {
- USB_VENDOR_ABOCOM2, 0,
- USB_KNOWNDEV_NOPROD,
- "AboCom Systems",
- NULL,
- },
- {
- USB_VENDOR_SILICOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Silicom",
- NULL,
- },
- {
- USB_VENDOR_RALINK, 0,
- USB_KNOWNDEV_NOPROD,
- "Ralink Technology",
- NULL,
- },
- {
- USB_VENDOR_IMAGINATION, 0,
- USB_KNOWNDEV_NOPROD,
- "Imagination Technologies",
- NULL,
- },
- {
- USB_VENDOR_CONCEPTRONIC2, 0,
- USB_KNOWNDEV_NOPROD,
- "Conceptronic",
- NULL,
- },
- {
- USB_VENDOR_SUPERTOP, 0,
- USB_KNOWNDEV_NOPROD,
- "Super Top",
- NULL,
- },
- {
- USB_VENDOR_PLANEX3, 0,
- USB_KNOWNDEV_NOPROD,
- "Planex Communications",
- NULL,
- },
- {
- USB_VENDOR_SILICONPORTALS, 0,
- USB_KNOWNDEV_NOPROD,
- "Silicon Portals",
- NULL,
- },
- {
- USB_VENDOR_UBIQUAM, 0,
- USB_KNOWNDEV_NOPROD,
- "UBIQUAM Co., Ltd.",
- NULL,
- },
- {
- USB_VENDOR_JMICRON, 0,
- USB_KNOWNDEV_NOPROD,
- "JMicron",
- NULL,
- },
- {
- USB_VENDOR_UBLOX, 0,
- USB_KNOWNDEV_NOPROD,
- "U-blox",
- NULL,
- },
- {
- USB_VENDOR_PNY, 0,
- USB_KNOWNDEV_NOPROD,
- "PNY",
- NULL,
- },
- {
- USB_VENDOR_OWEN, 0,
- USB_KNOWNDEV_NOPROD,
- "Owen",
- NULL,
- },
- {
- USB_VENDOR_OQO, 0,
- USB_KNOWNDEV_NOPROD,
- "OQO",
- NULL,
- },
- {
- USB_VENDOR_UMEDIA, 0,
- USB_KNOWNDEV_NOPROD,
- "U-MEDIA Communications",
- NULL,
- },
- {
- USB_VENDOR_FIBERLINE, 0,
- USB_KNOWNDEV_NOPROD,
- "Fiberline",
- NULL,
- },
- {
- USB_VENDOR_SPARKLAN, 0,
- USB_KNOWNDEV_NOPROD,
- "SparkLAN",
- NULL,
- },
- {
- USB_VENDOR_AMIT2, 0,
- USB_KNOWNDEV_NOPROD,
- "AMIT",
- NULL,
- },
- {
- USB_VENDOR_SOHOWARE, 0,
- USB_KNOWNDEV_NOPROD,
- "SOHOware",
- NULL,
- },
- {
- USB_VENDOR_UMAX, 0,
- USB_KNOWNDEV_NOPROD,
- "UMAX Data Systems",
- NULL,
- },
- {
- USB_VENDOR_INSIDEOUT, 0,
- USB_KNOWNDEV_NOPROD,
- "Inside Out Networks",
- NULL,
- },
- {
- USB_VENDOR_AMOI, 0,
- USB_KNOWNDEV_NOPROD,
- "Amoi Electronics",
- NULL,
- },
- {
- USB_VENDOR_GOODWAY, 0,
- USB_KNOWNDEV_NOPROD,
- "Good Way Technology",
- NULL,
- },
- {
- USB_VENDOR_ENTREGA, 0,
- USB_KNOWNDEV_NOPROD,
- "Entrega",
- NULL,
- },
- {
- USB_VENDOR_ACTIONTEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Actiontec Electronics",
- NULL,
- },
- {
- USB_VENDOR_CLIPSAL, 0,
- USB_KNOWNDEV_NOPROD,
- "Clipsal",
- NULL,
- },
- {
- USB_VENDOR_CISCOLINKSYS2, 0,
- USB_KNOWNDEV_NOPROD,
- "Cisco-Linksys",
- NULL,
- },
- {
- USB_VENDOR_ATHEROS, 0,
- USB_KNOWNDEV_NOPROD,
- "Atheros Communications",
- NULL,
- },
- {
- USB_VENDOR_GIGASET, 0,
- USB_KNOWNDEV_NOPROD,
- "Gigaset",
- NULL,
- },
- {
- USB_VENDOR_GLOBALSUN, 0,
- USB_KNOWNDEV_NOPROD,
- "Global Sun Technology",
- NULL,
- },
- {
- USB_VENDOR_ANYDATA, 0,
- USB_KNOWNDEV_NOPROD,
- "AnyDATA Corporation",
- NULL,
- },
- {
- USB_VENDOR_JABLOTRON, 0,
- USB_KNOWNDEV_NOPROD,
- "Jablotron",
- NULL,
- },
- {
- USB_VENDOR_CMOTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "C-motech",
- NULL,
- },
- {
- USB_VENDOR_AXESSTEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Axesstel Co., Ltd.",
- NULL,
- },
- {
- USB_VENDOR_LINKSYS4, 0,
- USB_KNOWNDEV_NOPROD,
- "Linksys",
- NULL,
- },
- {
- USB_VENDOR_SENAO, 0,
- USB_KNOWNDEV_NOPROD,
- "Senao",
- NULL,
- },
- {
- USB_VENDOR_ASUS2, 0,
- USB_KNOWNDEV_NOPROD,
- "ASUS",
- NULL,
- },
- {
- USB_VENDOR_SWEEX2, 0,
- USB_KNOWNDEV_NOPROD,
- "Sweex",
- NULL,
- },
- {
- USB_VENDOR_METAGEEK, 0,
- USB_KNOWNDEV_NOPROD,
- "MetaGeek",
- NULL,
- },
- {
- USB_VENDOR_WAVESENSE, 0,
- USB_KNOWNDEV_NOPROD,
- "WaveSense",
- NULL,
- },
- {
- USB_VENDOR_VAISALA, 0,
- USB_KNOWNDEV_NOPROD,
- "Vaisala",
- NULL,
- },
- {
- USB_VENDOR_AMIT, 0,
- USB_KNOWNDEV_NOPROD,
- "AMIT",
- NULL,
- },
- {
- USB_VENDOR_GOOGLE, 0,
- USB_KNOWNDEV_NOPROD,
- "Google",
- NULL,
- },
- {
- USB_VENDOR_QCOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Qcom",
- NULL,
- },
- {
- USB_VENDOR_ELV, 0,
- USB_KNOWNDEV_NOPROD,
- "ELV",
- NULL,
- },
- {
- USB_VENDOR_LINKSYS3, 0,
- USB_KNOWNDEV_NOPROD,
- "Linksys",
- NULL,
- },
- {
- USB_VENDOR_QUALCOMMINC, 0,
- USB_KNOWNDEV_NOPROD,
- "Qualcomm, Incorporated",
- NULL,
- },
- {
- USB_VENDOR_WCH2, 0,
- USB_KNOWNDEV_NOPROD,
- "QinHeng Electronics",
- NULL,
- },
- {
- USB_VENDOR_STELERA, 0,
- USB_KNOWNDEV_NOPROD,
- "Stelera Wireless",
- NULL,
- },
- {
- USB_VENDOR_MATRIXORBITAL, 0,
- USB_KNOWNDEV_NOPROD,
- "Matrix Orbital",
- NULL,
- },
- {
- USB_VENDOR_OVISLINK, 0,
- USB_KNOWNDEV_NOPROD,
- "OvisLink",
- NULL,
- },
- {
- USB_VENDOR_TCTMOBILE, 0,
- USB_KNOWNDEV_NOPROD,
- "TCT Mobile",
- NULL,
- },
- {
- USB_VENDOR_TELIT, 0,
- USB_KNOWNDEV_NOPROD,
- "Telit",
- NULL,
- },
- {
- USB_VENDOR_LONGCHEER, 0,
- USB_KNOWNDEV_NOPROD,
- "Longcheer Holdings, Ltd.",
- NULL,
- },
- {
- USB_VENDOR_MPMAN, 0,
- USB_KNOWNDEV_NOPROD,
- "MpMan",
- NULL,
- },
- {
- USB_VENDOR_DRESDENELEKTRONIK, 0,
- USB_KNOWNDEV_NOPROD,
- "dresden elektronik",
- NULL,
- },
- {
- USB_VENDOR_NEOTEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Neotel",
- NULL,
- },
- {
- USB_VENDOR_PEGATRON, 0,
- USB_KNOWNDEV_NOPROD,
- "Pegatron",
- NULL,
- },
- {
- USB_VENDOR_QISDA, 0,
- USB_KNOWNDEV_NOPROD,
- "Qisda",
- NULL,
- },
- {
- USB_VENDOR_METAGEEK2, 0,
- USB_KNOWNDEV_NOPROD,
- "MetaGeek",
- NULL,
- },
- {
- USB_VENDOR_ALINK, 0,
- USB_KNOWNDEV_NOPROD,
- "Alink",
- NULL,
- },
- {
- USB_VENDOR_AIRTIES, 0,
- USB_KNOWNDEV_NOPROD,
- "AirTies",
- NULL,
- },
- {
- USB_VENDOR_DLINK, 0,
- USB_KNOWNDEV_NOPROD,
- "D-Link",
- NULL,
- },
- {
- USB_VENDOR_PLANEX2, 0,
- USB_KNOWNDEV_NOPROD,
- "Planex Communications",
- NULL,
- },
- {
- USB_VENDOR_HAUPPAUGE2, 0,
- USB_KNOWNDEV_NOPROD,
- "Hauppauge Computer Works",
- NULL,
- },
- {
- USB_VENDOR_TLAYTECH, 0,
- USB_KNOWNDEV_NOPROD,
- "Tlay Tech",
- NULL,
- },
- {
- USB_VENDOR_ENCORE, 0,
- USB_KNOWNDEV_NOPROD,
- "Encore",
- NULL,
- },
- {
- USB_VENDOR_PARA, 0,
- USB_KNOWNDEV_NOPROD,
- "PARA Industrial",
- NULL,
- },
- {
- USB_VENDOR_ERICSSON, 0,
- USB_KNOWNDEV_NOPROD,
- "Ericsson",
- NULL,
- },
- {
- USB_VENDOR_MOTOROLA2, 0,
- USB_KNOWNDEV_NOPROD,
- "Motorola",
- NULL,
- },
- {
- USB_VENDOR_TRIPPLITE, 0,
- USB_KNOWNDEV_NOPROD,
- "Tripp-Lite",
- NULL,
- },
- {
- USB_VENDOR_HIROSE, 0,
- USB_KNOWNDEV_NOPROD,
- "Hirose Electric",
- NULL,
- },
- {
- USB_VENDOR_NHJ, 0,
- USB_KNOWNDEV_NOPROD,
- "NHJ",
- NULL,
- },
- {
- USB_VENDOR_PLANEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Planex Communications",
- NULL,
- },
- {
- USB_VENDOR_VIDZMEDIA, 0,
- USB_KNOWNDEV_NOPROD,
- "VidzMedia Pte Ltd",
- NULL,
- },
- {
- USB_VENDOR_AEI, 0,
- USB_KNOWNDEV_NOPROD,
- "AEI",
- NULL,
- },
- {
- USB_VENDOR_HANK, 0,
- USB_KNOWNDEV_NOPROD,
- "Hank Connection",
- NULL,
- },
- {
- USB_VENDOR_PQI, 0,
- USB_KNOWNDEV_NOPROD,
- "PQI",
- NULL,
- },
- {
- USB_VENDOR_DAISY, 0,
- USB_KNOWNDEV_NOPROD,
- "Daisy Technology",
- NULL,
- },
- {
- USB_VENDOR_NI, 0,
- USB_KNOWNDEV_NOPROD,
- "National Instruments",
- NULL,
- },
- {
- USB_VENDOR_MICRONET, 0,
- USB_KNOWNDEV_NOPROD,
- "Micronet Communications",
- NULL,
- },
- {
- USB_VENDOR_IODATA2, 0,
- USB_KNOWNDEV_NOPROD,
- "I-O Data",
- NULL,
- },
- {
- USB_VENDOR_IRIVER, 0,
- USB_KNOWNDEV_NOPROD,
- "iRiver",
- NULL,
- },
- {
- USB_VENDOR_DELL, 0,
- USB_KNOWNDEV_NOPROD,
- "Dell",
- NULL,
- },
- {
- USB_VENDOR_WCH, 0,
- USB_KNOWNDEV_NOPROD,
- "QinHeng Electronics",
- NULL,
- },
- {
- USB_VENDOR_ACEECA, 0,
- USB_KNOWNDEV_NOPROD,
- "Aceeca",
- NULL,
- },
- {
- USB_VENDOR_AVERATEC, 0,
- USB_KNOWNDEV_NOPROD,
- "Averatec",
- NULL,
- },
- {
- USB_VENDOR_SWEEX, 0,
- USB_KNOWNDEV_NOPROD,
- "Sweex",
- NULL,
- },
- {
- USB_VENDOR_PROLIFIC2, 0,
- USB_KNOWNDEV_NOPROD,
- "Prolific Technologies",
- NULL,
- },
- {
- USB_VENDOR_ONSPEC2, 0,
- USB_KNOWNDEV_NOPROD,
- "OnSpec Electronic Inc.",
- NULL,
- },
- {
- USB_VENDOR_ZINWELL, 0,
- USB_KNOWNDEV_NOPROD,
- "Zinwell",
- NULL,
- },
- {
- USB_VENDOR_SITECOM, 0,
- USB_KNOWNDEV_NOPROD,
- "Sitecom",
- NULL,
- },
- {
- USB_VENDOR_ARKMICRO, 0,
- USB_KNOWNDEV_NOPROD,
- "Arkmicro Technologies Inc.",
- NULL,
- },
- {
- USB_VENDOR_3COM2, 0,
- USB_KNOWNDEV_NOPROD,
- "3Com",
- NULL,
- },
- {
- USB_VENDOR_EDIMAX, 0,
- USB_KNOWNDEV_NOPROD,
- "Edimax",
- NULL,
- },
- {
- USB_VENDOR_INTEL, 0,
- USB_KNOWNDEV_NOPROD,
- "Intel",
- NULL,
- },
- {
- USB_VENDOR_INTEL2, 0,
- USB_KNOWNDEV_NOPROD,
- "Intel",
- NULL,
- },
- {
- USB_VENDOR_ALLWIN, 0,
- USB_KNOWNDEV_NOPROD,
- "ALLWIN Tech",
- NULL,
- },
- {
- USB_VENDOR_SITECOM2, 0,
- USB_KNOWNDEV_NOPROD,
- "Sitecom",
- NULL,
- },
- {
- USB_VENDOR_MOSCHIP, 0,
- USB_KNOWNDEV_NOPROD,
- "MosChip Semiconductor",
- NULL,
- },
- {
- USB_VENDOR_MARVELL, 0,
- USB_KNOWNDEV_NOPROD,
- "Marvell Technology Group Ltd.",
- NULL,
- },
- {
- USB_VENDOR_3COM3, 0,
- USB_KNOWNDEV_NOPROD,
- "3Com",
- NULL,
- },
- {
- USB_VENDOR_DATAAPEX, 0,
- USB_KNOWNDEV_NOPROD,
- "DataApex",
- NULL,
- },
- {
- USB_VENDOR_HP2, 0,
- USB_KNOWNDEV_NOPROD,
- "Hewlett Packard",
- NULL,
- },
- {
- USB_VENDOR_USRP, 0,
- USB_KNOWNDEV_NOPROD,
- "GNU Radio USRP",
- NULL,
- },
- { 0, 0, 0, NULL, NULL, }
-};
diff --git a/freebsd/local/vnode_if.h b/freebsd/local/vnode_if.h
deleted file mode 100644
index c90e6c8e..00000000
--- a/freebsd/local/vnode_if.h
+++ /dev/null
@@ -1,1546 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from $FreeBSD$
- */
-
-extern struct vnodeop_desc vop_default_desc;
-#include <freebsd/local/vnode_if_typedef.h>
-#include <freebsd/local/vnode_if_newproto.h>
-struct vop_islocked_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
-};
-
-extern struct vnodeop_desc vop_islocked_desc;
-
-int VOP_ISLOCKED_AP(struct vop_islocked_args *);
-int VOP_ISLOCKED_APV(struct vop_vector *vop, struct vop_islocked_args *);
-
-static __inline int VOP_ISLOCKED(
- struct vnode *vp)
-{
- struct vop_islocked_args a;
-
- a.a_gen.a_desc = &vop_islocked_desc;
- a.a_vp = vp;
- return (VOP_ISLOCKED_APV(vp->v_op, &a));
-}
-
-struct vop_lookup_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_lookup_desc;
-
-int VOP_LOOKUP_AP(struct vop_lookup_args *);
-int VOP_LOOKUP_APV(struct vop_vector *vop, struct vop_lookup_args *);
-
-static __inline int VOP_LOOKUP(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp)
-{
- struct vop_lookup_args a;
-
- a.a_gen.a_desc = &vop_lookup_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- return (VOP_LOOKUP_APV(dvp->v_op, &a));
-}
-
-struct vop_cachedlookup_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_cachedlookup_desc;
-
-int VOP_CACHEDLOOKUP_AP(struct vop_cachedlookup_args *);
-int VOP_CACHEDLOOKUP_APV(struct vop_vector *vop, struct vop_cachedlookup_args *);
-
-static __inline int VOP_CACHEDLOOKUP(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp)
-{
- struct vop_cachedlookup_args a;
-
- a.a_gen.a_desc = &vop_cachedlookup_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- return (VOP_CACHEDLOOKUP_APV(dvp->v_op, &a));
-}
-
-struct vop_create_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-
-extern struct vnodeop_desc vop_create_desc;
-
-int VOP_CREATE_AP(struct vop_create_args *);
-int VOP_CREATE_APV(struct vop_vector *vop, struct vop_create_args *);
-
-static __inline int VOP_CREATE(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap)
-{
- struct vop_create_args a;
-
- a.a_gen.a_desc = &vop_create_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- return (VOP_CREATE_APV(dvp->v_op, &a));
-}
-
-struct vop_whiteout_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct componentname *a_cnp;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_whiteout_desc;
-
-int VOP_WHITEOUT_AP(struct vop_whiteout_args *);
-int VOP_WHITEOUT_APV(struct vop_vector *vop, struct vop_whiteout_args *);
-
-static __inline int VOP_WHITEOUT(
- struct vnode *dvp,
- struct componentname *cnp,
- int flags)
-{
- struct vop_whiteout_args a;
-
- a.a_gen.a_desc = &vop_whiteout_desc;
- a.a_dvp = dvp;
- a.a_cnp = cnp;
- a.a_flags = flags;
- return (VOP_WHITEOUT_APV(dvp->v_op, &a));
-}
-
-struct vop_mknod_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-
-extern struct vnodeop_desc vop_mknod_desc;
-
-int VOP_MKNOD_AP(struct vop_mknod_args *);
-int VOP_MKNOD_APV(struct vop_vector *vop, struct vop_mknod_args *);
-
-static __inline int VOP_MKNOD(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap)
-{
- struct vop_mknod_args a;
-
- a.a_gen.a_desc = &vop_mknod_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- return (VOP_MKNOD_APV(dvp->v_op, &a));
-}
-
-struct vop_open_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_mode;
- struct ucred *a_cred;
- struct thread *a_td;
- struct file *a_fp;
-};
-
-extern struct vnodeop_desc vop_open_desc;
-
-int VOP_OPEN_AP(struct vop_open_args *);
-int VOP_OPEN_APV(struct vop_vector *vop, struct vop_open_args *);
-
-static __inline int VOP_OPEN(
- struct vnode *vp,
- int mode,
- struct ucred *cred,
- struct thread *td,
- struct file *fp)
-{
- struct vop_open_args a;
-
- a.a_gen.a_desc = &vop_open_desc;
- a.a_vp = vp;
- a.a_mode = mode;
- a.a_cred = cred;
- a.a_td = td;
- a.a_fp = fp;
- return (VOP_OPEN_APV(vp->v_op, &a));
-}
-
-struct vop_close_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_close_desc;
-
-int VOP_CLOSE_AP(struct vop_close_args *);
-int VOP_CLOSE_APV(struct vop_vector *vop, struct vop_close_args *);
-
-static __inline int VOP_CLOSE(
- struct vnode *vp,
- int fflag,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_close_args a;
-
- a.a_gen.a_desc = &vop_close_desc;
- a.a_vp = vp;
- a.a_fflag = fflag;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_CLOSE_APV(vp->v_op, &a));
-}
-
-struct vop_access_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- accmode_t a_accmode;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_access_desc;
-
-int VOP_ACCESS_AP(struct vop_access_args *);
-int VOP_ACCESS_APV(struct vop_vector *vop, struct vop_access_args *);
-
-static __inline int VOP_ACCESS(
- struct vnode *vp,
- accmode_t accmode,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_access_args a;
-
- a.a_gen.a_desc = &vop_access_desc;
- a.a_vp = vp;
- a.a_accmode = accmode;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_ACCESS_APV(vp->v_op, &a));
-}
-
-struct vop_accessx_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- accmode_t a_accmode;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_accessx_desc;
-
-int VOP_ACCESSX_AP(struct vop_accessx_args *);
-int VOP_ACCESSX_APV(struct vop_vector *vop, struct vop_accessx_args *);
-
-static __inline int VOP_ACCESSX(
- struct vnode *vp,
- accmode_t accmode,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_accessx_args a;
-
- a.a_gen.a_desc = &vop_accessx_desc;
- a.a_vp = vp;
- a.a_accmode = accmode;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_ACCESSX_APV(vp->v_op, &a));
-}
-
-struct vop_getattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_getattr_desc;
-
-int VOP_GETATTR_AP(struct vop_getattr_args *);
-int VOP_GETATTR_APV(struct vop_vector *vop, struct vop_getattr_args *);
-
-static __inline int VOP_GETATTR(
- struct vnode *vp,
- struct vattr *vap,
- struct ucred *cred)
-{
- struct vop_getattr_args a;
-
- a.a_gen.a_desc = &vop_getattr_desc;
- a.a_vp = vp;
- a.a_vap = vap;
- a.a_cred = cred;
- return (VOP_GETATTR_APV(vp->v_op, &a));
-}
-
-struct vop_setattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct vattr *a_vap;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_setattr_desc;
-
-int VOP_SETATTR_AP(struct vop_setattr_args *);
-int VOP_SETATTR_APV(struct vop_vector *vop, struct vop_setattr_args *);
-
-static __inline int VOP_SETATTR(
- struct vnode *vp,
- struct vattr *vap,
- struct ucred *cred)
-{
- struct vop_setattr_args a;
-
- a.a_gen.a_desc = &vop_setattr_desc;
- a.a_vp = vp;
- a.a_vap = vap;
- a.a_cred = cred;
- return (VOP_SETATTR_APV(vp->v_op, &a));
-}
-
-struct vop_markatime_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
-};
-
-extern struct vnodeop_desc vop_markatime_desc;
-
-int VOP_MARKATIME_AP(struct vop_markatime_args *);
-int VOP_MARKATIME_APV(struct vop_vector *vop, struct vop_markatime_args *);
-
-static __inline int VOP_MARKATIME(
- struct vnode *vp)
-{
- struct vop_markatime_args a;
-
- a.a_gen.a_desc = &vop_markatime_desc;
- a.a_vp = vp;
- return (VOP_MARKATIME_APV(vp->v_op, &a));
-}
-
-struct vop_read_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_read_desc;
-
-int VOP_READ_AP(struct vop_read_args *);
-int VOP_READ_APV(struct vop_vector *vop, struct vop_read_args *);
-
-static __inline int VOP_READ(
- struct vnode *vp,
- struct uio *uio,
- int ioflag,
- struct ucred *cred)
-{
- struct vop_read_args a;
-
- a.a_gen.a_desc = &vop_read_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_ioflag = ioflag;
- a.a_cred = cred;
- return (VOP_READ_APV(vp->v_op, &a));
-}
-
-struct vop_write_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- int a_ioflag;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_write_desc;
-
-int VOP_WRITE_AP(struct vop_write_args *);
-int VOP_WRITE_APV(struct vop_vector *vop, struct vop_write_args *);
-
-static __inline int VOP_WRITE(
- struct vnode *vp,
- struct uio *uio,
- int ioflag,
- struct ucred *cred)
-{
- struct vop_write_args a;
-
- a.a_gen.a_desc = &vop_write_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_ioflag = ioflag;
- a.a_cred = cred;
- return (VOP_WRITE_APV(vp->v_op, &a));
-}
-
-struct vop_ioctl_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- u_long a_command;
- void *a_data;
- int a_fflag;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_ioctl_desc;
-
-int VOP_IOCTL_AP(struct vop_ioctl_args *);
-int VOP_IOCTL_APV(struct vop_vector *vop, struct vop_ioctl_args *);
-
-static __inline int VOP_IOCTL(
- struct vnode *vp,
- u_long command,
- void *data,
- int fflag,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_ioctl_args a;
-
- a.a_gen.a_desc = &vop_ioctl_desc;
- a.a_vp = vp;
- a.a_command = command;
- a.a_data = data;
- a.a_fflag = fflag;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_IOCTL_APV(vp->v_op, &a));
-}
-
-struct vop_poll_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_events;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_poll_desc;
-
-int VOP_POLL_AP(struct vop_poll_args *);
-int VOP_POLL_APV(struct vop_vector *vop, struct vop_poll_args *);
-
-static __inline int VOP_POLL(
- struct vnode *vp,
- int events,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_poll_args a;
-
- a.a_gen.a_desc = &vop_poll_desc;
- a.a_vp = vp;
- a.a_events = events;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_POLL_APV(vp->v_op, &a));
-}
-
-struct vop_kqfilter_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct knote *a_kn;
-};
-
-extern struct vnodeop_desc vop_kqfilter_desc;
-
-int VOP_KQFILTER_AP(struct vop_kqfilter_args *);
-int VOP_KQFILTER_APV(struct vop_vector *vop, struct vop_kqfilter_args *);
-
-static __inline int VOP_KQFILTER(
- struct vnode *vp,
- struct knote *kn)
-{
- struct vop_kqfilter_args a;
-
- a.a_gen.a_desc = &vop_kqfilter_desc;
- a.a_vp = vp;
- a.a_kn = kn;
- return (VOP_KQFILTER_APV(vp->v_op, &a));
-}
-
-struct vop_revoke_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_revoke_desc;
-
-int VOP_REVOKE_AP(struct vop_revoke_args *);
-int VOP_REVOKE_APV(struct vop_vector *vop, struct vop_revoke_args *);
-
-static __inline int VOP_REVOKE(
- struct vnode *vp,
- int flags)
-{
- struct vop_revoke_args a;
-
- a.a_gen.a_desc = &vop_revoke_desc;
- a.a_vp = vp;
- a.a_flags = flags;
- return (VOP_REVOKE_APV(vp->v_op, &a));
-}
-
-struct vop_fsync_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_waitfor;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_fsync_desc;
-
-int VOP_FSYNC_AP(struct vop_fsync_args *);
-int VOP_FSYNC_APV(struct vop_vector *vop, struct vop_fsync_args *);
-
-static __inline int VOP_FSYNC(
- struct vnode *vp,
- int waitfor,
- struct thread *td)
-{
- struct vop_fsync_args a;
-
- a.a_gen.a_desc = &vop_fsync_desc;
- a.a_vp = vp;
- a.a_waitfor = waitfor;
- a.a_td = td;
- return (VOP_FSYNC_APV(vp->v_op, &a));
-}
-
-struct vop_remove_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_remove_desc;
-
-int VOP_REMOVE_AP(struct vop_remove_args *);
-int VOP_REMOVE_APV(struct vop_vector *vop, struct vop_remove_args *);
-
-static __inline int VOP_REMOVE(
- struct vnode *dvp,
- struct vnode *vp,
- struct componentname *cnp)
-{
- struct vop_remove_args a;
-
- a.a_gen.a_desc = &vop_remove_desc;
- a.a_dvp = dvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- return (VOP_REMOVE_APV(dvp->v_op, &a));
-}
-
-struct vop_link_args {
- struct vop_generic_args a_gen;
- struct vnode *a_tdvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_link_desc;
-
-int VOP_LINK_AP(struct vop_link_args *);
-int VOP_LINK_APV(struct vop_vector *vop, struct vop_link_args *);
-
-static __inline int VOP_LINK(
- struct vnode *tdvp,
- struct vnode *vp,
- struct componentname *cnp)
-{
- struct vop_link_args a;
-
- a.a_gen.a_desc = &vop_link_desc;
- a.a_tdvp = tdvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- return (VOP_LINK_APV(tdvp->v_op, &a));
-}
-
-struct vop_rename_args {
- struct vop_generic_args a_gen;
- struct vnode *a_fdvp;
- struct vnode *a_fvp;
- struct componentname *a_fcnp;
- struct vnode *a_tdvp;
- struct vnode *a_tvp;
- struct componentname *a_tcnp;
-};
-
-extern struct vnodeop_desc vop_rename_desc;
-
-int VOP_RENAME_AP(struct vop_rename_args *);
-int VOP_RENAME_APV(struct vop_vector *vop, struct vop_rename_args *);
-
-static __inline int VOP_RENAME(
- struct vnode *fdvp,
- struct vnode *fvp,
- struct componentname *fcnp,
- struct vnode *tdvp,
- struct vnode *tvp,
- struct componentname *tcnp)
-{
- struct vop_rename_args a;
-
- a.a_gen.a_desc = &vop_rename_desc;
- a.a_fdvp = fdvp;
- a.a_fvp = fvp;
- a.a_fcnp = fcnp;
- a.a_tdvp = tdvp;
- a.a_tvp = tvp;
- a.a_tcnp = tcnp;
- return (VOP_RENAME_APV(fdvp->v_op, &a));
-}
-
-struct vop_mkdir_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
-};
-
-extern struct vnodeop_desc vop_mkdir_desc;
-
-int VOP_MKDIR_AP(struct vop_mkdir_args *);
-int VOP_MKDIR_APV(struct vop_vector *vop, struct vop_mkdir_args *);
-
-static __inline int VOP_MKDIR(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap)
-{
- struct vop_mkdir_args a;
-
- a.a_gen.a_desc = &vop_mkdir_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- return (VOP_MKDIR_APV(dvp->v_op, &a));
-}
-
-struct vop_rmdir_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode *a_vp;
- struct componentname *a_cnp;
-};
-
-extern struct vnodeop_desc vop_rmdir_desc;
-
-int VOP_RMDIR_AP(struct vop_rmdir_args *);
-int VOP_RMDIR_APV(struct vop_vector *vop, struct vop_rmdir_args *);
-
-static __inline int VOP_RMDIR(
- struct vnode *dvp,
- struct vnode *vp,
- struct componentname *cnp)
-{
- struct vop_rmdir_args a;
-
- a.a_gen.a_desc = &vop_rmdir_desc;
- a.a_dvp = dvp;
- a.a_vp = vp;
- a.a_cnp = cnp;
- return (VOP_RMDIR_APV(dvp->v_op, &a));
-}
-
-struct vop_symlink_args {
- struct vop_generic_args a_gen;
- struct vnode *a_dvp;
- struct vnode **a_vpp;
- struct componentname *a_cnp;
- struct vattr *a_vap;
- char *a_target;
-};
-
-extern struct vnodeop_desc vop_symlink_desc;
-
-int VOP_SYMLINK_AP(struct vop_symlink_args *);
-int VOP_SYMLINK_APV(struct vop_vector *vop, struct vop_symlink_args *);
-
-static __inline int VOP_SYMLINK(
- struct vnode *dvp,
- struct vnode **vpp,
- struct componentname *cnp,
- struct vattr *vap,
- char *target)
-{
- struct vop_symlink_args a;
-
- a.a_gen.a_desc = &vop_symlink_desc;
- a.a_dvp = dvp;
- a.a_vpp = vpp;
- a.a_cnp = cnp;
- a.a_vap = vap;
- a.a_target = target;
- return (VOP_SYMLINK_APV(dvp->v_op, &a));
-}
-
-struct vop_readdir_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
- int *a_eofflag;
- int *a_ncookies;
- u_long **a_cookies;
-};
-
-extern struct vnodeop_desc vop_readdir_desc;
-
-int VOP_READDIR_AP(struct vop_readdir_args *);
-int VOP_READDIR_APV(struct vop_vector *vop, struct vop_readdir_args *);
-
-static __inline int VOP_READDIR(
- struct vnode *vp,
- struct uio *uio,
- struct ucred *cred,
- int *eofflag,
- int *ncookies,
- u_long **cookies)
-{
- struct vop_readdir_args a;
-
- a.a_gen.a_desc = &vop_readdir_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_cred = cred;
- a.a_eofflag = eofflag;
- a.a_ncookies = ncookies;
- a.a_cookies = cookies;
- return (VOP_READDIR_APV(vp->v_op, &a));
-}
-
-struct vop_readlink_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct uio *a_uio;
- struct ucred *a_cred;
-};
-
-extern struct vnodeop_desc vop_readlink_desc;
-
-int VOP_READLINK_AP(struct vop_readlink_args *);
-int VOP_READLINK_APV(struct vop_vector *vop, struct vop_readlink_args *);
-
-static __inline int VOP_READLINK(
- struct vnode *vp,
- struct uio *uio,
- struct ucred *cred)
-{
- struct vop_readlink_args a;
-
- a.a_gen.a_desc = &vop_readlink_desc;
- a.a_vp = vp;
- a.a_uio = uio;
- a.a_cred = cred;
- return (VOP_READLINK_APV(vp->v_op, &a));
-}
-
-struct vop_inactive_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_inactive_desc;
-
-int VOP_INACTIVE_AP(struct vop_inactive_args *);
-int VOP_INACTIVE_APV(struct vop_vector *vop, struct vop_inactive_args *);
-
-static __inline int VOP_INACTIVE(
- struct vnode *vp,
- struct thread *td)
-{
- struct vop_inactive_args a;
-
- a.a_gen.a_desc = &vop_inactive_desc;
- a.a_vp = vp;
- a.a_td = td;
- return (VOP_INACTIVE_APV(vp->v_op, &a));
-}
-
-struct vop_reclaim_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_reclaim_desc;
-
-int VOP_RECLAIM_AP(struct vop_reclaim_args *);
-int VOP_RECLAIM_APV(struct vop_vector *vop, struct vop_reclaim_args *);
-
-static __inline int VOP_RECLAIM(
- struct vnode *vp,
- struct thread *td)
-{
- struct vop_reclaim_args a;
-
- a.a_gen.a_desc = &vop_reclaim_desc;
- a.a_vp = vp;
- a.a_td = td;
- return (VOP_RECLAIM_APV(vp->v_op, &a));
-}
-
-struct vop_lock1_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_flags;
- char *a_file;
- int a_line;
-};
-
-extern struct vnodeop_desc vop_lock1_desc;
-
-int VOP_LOCK1_AP(struct vop_lock1_args *);
-int VOP_LOCK1_APV(struct vop_vector *vop, struct vop_lock1_args *);
-
-static __inline int VOP_LOCK1(
- struct vnode *vp,
- int flags,
- char *file,
- int line)
-{
- struct vop_lock1_args a;
-
- a.a_gen.a_desc = &vop_lock1_desc;
- a.a_vp = vp;
- a.a_flags = flags;
- a.a_file = file;
- a.a_line = line;
- return (VOP_LOCK1_APV(vp->v_op, &a));
-}
-
-struct vop_unlock_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_unlock_desc;
-
-int VOP_UNLOCK_AP(struct vop_unlock_args *);
-int VOP_UNLOCK_APV(struct vop_vector *vop, struct vop_unlock_args *);
-
-static __inline int VOP_UNLOCK(
- struct vnode *vp,
- int flags)
-{
- struct vop_unlock_args a;
-
- a.a_gen.a_desc = &vop_unlock_desc;
- a.a_vp = vp;
- a.a_flags = flags;
- return (VOP_UNLOCK_APV(vp->v_op, &a));
-}
-
-struct vop_bmap_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- daddr_t a_bn;
- struct bufobj **a_bop;
- daddr_t *a_bnp;
- int *a_runp;
- int *a_runb;
-};
-
-extern struct vnodeop_desc vop_bmap_desc;
-
-int VOP_BMAP_AP(struct vop_bmap_args *);
-int VOP_BMAP_APV(struct vop_vector *vop, struct vop_bmap_args *);
-
-static __inline int VOP_BMAP(
- struct vnode *vp,
- daddr_t bn,
- struct bufobj **bop,
- daddr_t *bnp,
- int *runp,
- int *runb)
-{
- struct vop_bmap_args a;
-
- a.a_gen.a_desc = &vop_bmap_desc;
- a.a_vp = vp;
- a.a_bn = bn;
- a.a_bop = bop;
- a.a_bnp = bnp;
- a.a_runp = runp;
- a.a_runb = runb;
- return (VOP_BMAP_APV(vp->v_op, &a));
-}
-
-struct vop_strategy_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct buf *a_bp;
-};
-
-extern struct vnodeop_desc vop_strategy_desc;
-
-int VOP_STRATEGY_AP(struct vop_strategy_args *);
-int VOP_STRATEGY_APV(struct vop_vector *vop, struct vop_strategy_args *);
-
-static __inline int VOP_STRATEGY(
- struct vnode *vp,
- struct buf *bp)
-{
- struct vop_strategy_args a;
-
- a.a_gen.a_desc = &vop_strategy_desc;
- a.a_vp = vp;
- a.a_bp = bp;
- return (VOP_STRATEGY_APV(vp->v_op, &a));
-}
-
-struct vop_getwritemount_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct mount **a_mpp;
-};
-
-extern struct vnodeop_desc vop_getwritemount_desc;
-
-int VOP_GETWRITEMOUNT_AP(struct vop_getwritemount_args *);
-int VOP_GETWRITEMOUNT_APV(struct vop_vector *vop, struct vop_getwritemount_args *);
-
-static __inline int VOP_GETWRITEMOUNT(
- struct vnode *vp,
- struct mount **mpp)
-{
- struct vop_getwritemount_args a;
-
- a.a_gen.a_desc = &vop_getwritemount_desc;
- a.a_vp = vp;
- a.a_mpp = mpp;
- return (VOP_GETWRITEMOUNT_APV(vp->v_op, &a));
-}
-
-struct vop_print_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
-};
-
-extern struct vnodeop_desc vop_print_desc;
-
-int VOP_PRINT_AP(struct vop_print_args *);
-int VOP_PRINT_APV(struct vop_vector *vop, struct vop_print_args *);
-
-static __inline int VOP_PRINT(
- struct vnode *vp)
-{
- struct vop_print_args a;
-
- a.a_gen.a_desc = &vop_print_desc;
- a.a_vp = vp;
- return (VOP_PRINT_APV(vp->v_op, &a));
-}
-
-struct vop_pathconf_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_name;
- register_t *a_retval;
-};
-
-extern struct vnodeop_desc vop_pathconf_desc;
-
-int VOP_PATHCONF_AP(struct vop_pathconf_args *);
-int VOP_PATHCONF_APV(struct vop_vector *vop, struct vop_pathconf_args *);
-
-static __inline int VOP_PATHCONF(
- struct vnode *vp,
- int name,
- register_t *retval)
-{
- struct vop_pathconf_args a;
-
- a.a_gen.a_desc = &vop_pathconf_desc;
- a.a_vp = vp;
- a.a_name = name;
- a.a_retval = retval;
- return (VOP_PATHCONF_APV(vp->v_op, &a));
-}
-
-struct vop_advlock_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- void *a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
-};
-
-extern struct vnodeop_desc vop_advlock_desc;
-
-int VOP_ADVLOCK_AP(struct vop_advlock_args *);
-int VOP_ADVLOCK_APV(struct vop_vector *vop, struct vop_advlock_args *);
-
-static __inline int VOP_ADVLOCK(
- struct vnode *vp,
- void *id,
- int op,
- struct flock *fl,
- int flags)
-{
- struct vop_advlock_args a;
-
- a.a_gen.a_desc = &vop_advlock_desc;
- a.a_vp = vp;
- a.a_id = id;
- a.a_op = op;
- a.a_fl = fl;
- a.a_flags = flags;
- return (VOP_ADVLOCK_APV(vp->v_op, &a));
-}
-
-struct vop_advlockasync_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- void *a_id;
- int a_op;
- struct flock *a_fl;
- int a_flags;
- struct task *a_task;
- void **a_cookiep;
-};
-
-extern struct vnodeop_desc vop_advlockasync_desc;
-
-int VOP_ADVLOCKASYNC_AP(struct vop_advlockasync_args *);
-int VOP_ADVLOCKASYNC_APV(struct vop_vector *vop, struct vop_advlockasync_args *);
-
-static __inline int VOP_ADVLOCKASYNC(
- struct vnode *vp,
- void *id,
- int op,
- struct flock *fl,
- int flags,
- struct task *task,
- void **cookiep)
-{
- struct vop_advlockasync_args a;
-
- a.a_gen.a_desc = &vop_advlockasync_desc;
- a.a_vp = vp;
- a.a_id = id;
- a.a_op = op;
- a.a_fl = fl;
- a.a_flags = flags;
- a.a_task = task;
- a.a_cookiep = cookiep;
- return (VOP_ADVLOCKASYNC_APV(vp->v_op, &a));
-}
-
-struct vop_reallocblks_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct cluster_save *a_buflist;
-};
-
-extern struct vnodeop_desc vop_reallocblks_desc;
-
-int VOP_REALLOCBLKS_AP(struct vop_reallocblks_args *);
-int VOP_REALLOCBLKS_APV(struct vop_vector *vop, struct vop_reallocblks_args *);
-
-static __inline int VOP_REALLOCBLKS(
- struct vnode *vp,
- struct cluster_save *buflist)
-{
- struct vop_reallocblks_args a;
-
- a.a_gen.a_desc = &vop_reallocblks_desc;
- a.a_vp = vp;
- a.a_buflist = buflist;
- return (VOP_REALLOCBLKS_APV(vp->v_op, &a));
-}
-
-struct vop_getpages_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_reqpage;
- vm_ooffset_t a_offset;
-};
-
-extern struct vnodeop_desc vop_getpages_desc;
-
-int VOP_GETPAGES_AP(struct vop_getpages_args *);
-int VOP_GETPAGES_APV(struct vop_vector *vop, struct vop_getpages_args *);
-
-static __inline int VOP_GETPAGES(
- struct vnode *vp,
- vm_page_t *m,
- int count,
- int reqpage,
- vm_ooffset_t offset)
-{
- struct vop_getpages_args a;
-
- a.a_gen.a_desc = &vop_getpages_desc;
- a.a_vp = vp;
- a.a_m = m;
- a.a_count = count;
- a.a_reqpage = reqpage;
- a.a_offset = offset;
- return (VOP_GETPAGES_APV(vp->v_op, &a));
-}
-
-struct vop_putpages_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- vm_page_t *a_m;
- int a_count;
- int a_sync;
- int *a_rtvals;
- vm_ooffset_t a_offset;
-};
-
-extern struct vnodeop_desc vop_putpages_desc;
-
-int VOP_PUTPAGES_AP(struct vop_putpages_args *);
-int VOP_PUTPAGES_APV(struct vop_vector *vop, struct vop_putpages_args *);
-
-static __inline int VOP_PUTPAGES(
- struct vnode *vp,
- vm_page_t *m,
- int count,
- int sync,
- int *rtvals,
- vm_ooffset_t offset)
-{
- struct vop_putpages_args a;
-
- a.a_gen.a_desc = &vop_putpages_desc;
- a.a_vp = vp;
- a.a_m = m;
- a.a_count = count;
- a.a_sync = sync;
- a.a_rtvals = rtvals;
- a.a_offset = offset;
- return (VOP_PUTPAGES_APV(vp->v_op, &a));
-}
-
-struct vop_getacl_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_getacl_desc;
-
-int VOP_GETACL_AP(struct vop_getacl_args *);
-int VOP_GETACL_APV(struct vop_vector *vop, struct vop_getacl_args *);
-
-static __inline int VOP_GETACL(
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_getacl_args a;
-
- a.a_gen.a_desc = &vop_getacl_desc;
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_GETACL_APV(vp->v_op, &a));
-}
-
-struct vop_setacl_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_setacl_desc;
-
-int VOP_SETACL_AP(struct vop_setacl_args *);
-int VOP_SETACL_APV(struct vop_vector *vop, struct vop_setacl_args *);
-
-static __inline int VOP_SETACL(
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_setacl_args a;
-
- a.a_gen.a_desc = &vop_setacl_desc;
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_SETACL_APV(vp->v_op, &a));
-}
-
-struct vop_aclcheck_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- acl_type_t a_type;
- struct acl *a_aclp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_aclcheck_desc;
-
-int VOP_ACLCHECK_AP(struct vop_aclcheck_args *);
-int VOP_ACLCHECK_APV(struct vop_vector *vop, struct vop_aclcheck_args *);
-
-static __inline int VOP_ACLCHECK(
- struct vnode *vp,
- acl_type_t type,
- struct acl *aclp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_aclcheck_args a;
-
- a.a_gen.a_desc = &vop_aclcheck_desc;
- a.a_vp = vp;
- a.a_type = type;
- a.a_aclp = aclp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_ACLCHECK_APV(vp->v_op, &a));
-}
-
-struct vop_closeextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_commit;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_closeextattr_desc;
-
-int VOP_CLOSEEXTATTR_AP(struct vop_closeextattr_args *);
-int VOP_CLOSEEXTATTR_APV(struct vop_vector *vop, struct vop_closeextattr_args *);
-
-static __inline int VOP_CLOSEEXTATTR(
- struct vnode *vp,
- int commit,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_closeextattr_args a;
-
- a.a_gen.a_desc = &vop_closeextattr_desc;
- a.a_vp = vp;
- a.a_commit = commit;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_CLOSEEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_getextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- const char *a_name;
- struct uio *a_uio;
- size_t *a_size;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_getextattr_desc;
-
-int VOP_GETEXTATTR_AP(struct vop_getextattr_args *);
-int VOP_GETEXTATTR_APV(struct vop_vector *vop, struct vop_getextattr_args *);
-
-static __inline int VOP_GETEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- const char *name,
- struct uio *uio,
- size_t *size,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_getextattr_args a;
-
- a.a_gen.a_desc = &vop_getextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_name = name;
- a.a_uio = uio;
- a.a_size = size;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_GETEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_listextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- struct uio *a_uio;
- size_t *a_size;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_listextattr_desc;
-
-int VOP_LISTEXTATTR_AP(struct vop_listextattr_args *);
-int VOP_LISTEXTATTR_APV(struct vop_vector *vop, struct vop_listextattr_args *);
-
-static __inline int VOP_LISTEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- struct uio *uio,
- size_t *size,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_listextattr_args a;
-
- a.a_gen.a_desc = &vop_listextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_uio = uio;
- a.a_size = size;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_LISTEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_openextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_openextattr_desc;
-
-int VOP_OPENEXTATTR_AP(struct vop_openextattr_args *);
-int VOP_OPENEXTATTR_APV(struct vop_vector *vop, struct vop_openextattr_args *);
-
-static __inline int VOP_OPENEXTATTR(
- struct vnode *vp,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_openextattr_args a;
-
- a.a_gen.a_desc = &vop_openextattr_desc;
- a.a_vp = vp;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_OPENEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_deleteextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- const char *a_name;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_deleteextattr_desc;
-
-int VOP_DELETEEXTATTR_AP(struct vop_deleteextattr_args *);
-int VOP_DELETEEXTATTR_APV(struct vop_vector *vop, struct vop_deleteextattr_args *);
-
-static __inline int VOP_DELETEEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- const char *name,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_deleteextattr_args a;
-
- a.a_gen.a_desc = &vop_deleteextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_name = name;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_DELETEEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_setextattr_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- int a_attrnamespace;
- const char *a_name;
- struct uio *a_uio;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_setextattr_desc;
-
-int VOP_SETEXTATTR_AP(struct vop_setextattr_args *);
-int VOP_SETEXTATTR_APV(struct vop_vector *vop, struct vop_setextattr_args *);
-
-static __inline int VOP_SETEXTATTR(
- struct vnode *vp,
- int attrnamespace,
- const char *name,
- struct uio *uio,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_setextattr_args a;
-
- a.a_gen.a_desc = &vop_setextattr_desc;
- a.a_vp = vp;
- a.a_attrnamespace = attrnamespace;
- a.a_name = name;
- a.a_uio = uio;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_SETEXTATTR_APV(vp->v_op, &a));
-}
-
-struct vop_setlabel_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct label *a_label;
- struct ucred *a_cred;
- struct thread *a_td;
-};
-
-extern struct vnodeop_desc vop_setlabel_desc;
-
-int VOP_SETLABEL_AP(struct vop_setlabel_args *);
-int VOP_SETLABEL_APV(struct vop_vector *vop, struct vop_setlabel_args *);
-
-static __inline int VOP_SETLABEL(
- struct vnode *vp,
- struct label *label,
- struct ucred *cred,
- struct thread *td)
-{
- struct vop_setlabel_args a;
-
- a.a_gen.a_desc = &vop_setlabel_desc;
- a.a_vp = vp;
- a.a_label = label;
- a.a_cred = cred;
- a.a_td = td;
- return (VOP_SETLABEL_APV(vp->v_op, &a));
-}
-
-struct vop_vptofh_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct fid *a_fhp;
-};
-
-extern struct vnodeop_desc vop_vptofh_desc;
-
-int VOP_VPTOFH_AP(struct vop_vptofh_args *);
-int VOP_VPTOFH_APV(struct vop_vector *vop, struct vop_vptofh_args *);
-
-static __inline int VOP_VPTOFH(
- struct vnode *vp,
- struct fid *fhp)
-{
- struct vop_vptofh_args a;
-
- a.a_gen.a_desc = &vop_vptofh_desc;
- a.a_vp = vp;
- a.a_fhp = fhp;
- return (VOP_VPTOFH_APV(vp->v_op, &a));
-}
-
-struct vop_vptocnp_args {
- struct vop_generic_args a_gen;
- struct vnode *a_vp;
- struct vnode **a_vpp;
- struct ucred *a_cred;
- char *a_buf;
- int *a_buflen;
-};
-
-extern struct vnodeop_desc vop_vptocnp_desc;
-
-int VOP_VPTOCNP_AP(struct vop_vptocnp_args *);
-int VOP_VPTOCNP_APV(struct vop_vector *vop, struct vop_vptocnp_args *);
-
-static __inline int VOP_VPTOCNP(
- struct vnode *vp,
- struct vnode **vpp,
- struct ucred *cred,
- char *buf,
- int *buflen)
-{
- struct vop_vptocnp_args a;
-
- a.a_gen.a_desc = &vop_vptocnp_desc;
- a.a_vp = vp;
- a.a_vpp = vpp;
- a.a_cred = cred;
- a.a_buf = buf;
- a.a_buflen = buflen;
- return (VOP_VPTOCNP_APV(vp->v_op, &a));
-}
-
diff --git a/freebsd/local/vnode_if_newproto.h b/freebsd/local/vnode_if_newproto.h
deleted file mode 100644
index 4b888acd..00000000
--- a/freebsd/local/vnode_if_newproto.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from $FreeBSD$
- */
-
-
-struct vop_vector {
- struct vop_vector *vop_default;
- vop_bypass_t *vop_bypass;
- vop_islocked_t *vop_islocked;
- vop_lookup_t *vop_lookup;
- vop_cachedlookup_t *vop_cachedlookup;
- vop_create_t *vop_create;
- vop_whiteout_t *vop_whiteout;
- vop_mknod_t *vop_mknod;
- vop_open_t *vop_open;
- vop_close_t *vop_close;
- vop_access_t *vop_access;
- vop_accessx_t *vop_accessx;
- vop_getattr_t *vop_getattr;
- vop_setattr_t *vop_setattr;
- vop_markatime_t *vop_markatime;
- vop_read_t *vop_read;
- vop_write_t *vop_write;
- vop_ioctl_t *vop_ioctl;
- vop_poll_t *vop_poll;
- vop_kqfilter_t *vop_kqfilter;
- vop_revoke_t *vop_revoke;
- vop_fsync_t *vop_fsync;
- vop_remove_t *vop_remove;
- vop_link_t *vop_link;
- vop_rename_t *vop_rename;
- vop_mkdir_t *vop_mkdir;
- vop_rmdir_t *vop_rmdir;
- vop_symlink_t *vop_symlink;
- vop_readdir_t *vop_readdir;
- vop_readlink_t *vop_readlink;
- vop_inactive_t *vop_inactive;
- vop_reclaim_t *vop_reclaim;
- vop_lock1_t *vop_lock1;
- vop_unlock_t *vop_unlock;
- vop_bmap_t *vop_bmap;
- vop_strategy_t *vop_strategy;
- vop_getwritemount_t *vop_getwritemount;
- vop_print_t *vop_print;
- vop_pathconf_t *vop_pathconf;
- vop_advlock_t *vop_advlock;
- vop_advlockasync_t *vop_advlockasync;
- vop_reallocblks_t *vop_reallocblks;
- vop_getpages_t *vop_getpages;
- vop_putpages_t *vop_putpages;
- vop_getacl_t *vop_getacl;
- vop_setacl_t *vop_setacl;
- vop_aclcheck_t *vop_aclcheck;
- vop_closeextattr_t *vop_closeextattr;
- vop_getextattr_t *vop_getextattr;
- vop_listextattr_t *vop_listextattr;
- vop_openextattr_t *vop_openextattr;
- vop_deleteextattr_t *vop_deleteextattr;
- vop_setextattr_t *vop_setextattr;
- vop_setlabel_t *vop_setlabel;
- vop_vptofh_t *vop_vptofh;
- vop_vptocnp_t *vop_vptocnp;
-};
diff --git a/freebsd/local/vnode_if_typedef.h b/freebsd/local/vnode_if_typedef.h
deleted file mode 100644
index b7157011..00000000
--- a/freebsd/local/vnode_if_typedef.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * This file is produced automatically.
- * Do not modify anything in here by hand.
- *
- * Created from $FreeBSD$
- */
-
-
-struct vop_islocked_args;
-typedef int vop_islocked_t(struct vop_islocked_args *);
-
-struct vop_lookup_args;
-typedef int vop_lookup_t(struct vop_lookup_args *);
-
-struct vop_cachedlookup_args;
-typedef int vop_cachedlookup_t(struct vop_cachedlookup_args *);
-
-struct vop_create_args;
-typedef int vop_create_t(struct vop_create_args *);
-
-struct vop_whiteout_args;
-typedef int vop_whiteout_t(struct vop_whiteout_args *);
-
-struct vop_mknod_args;
-typedef int vop_mknod_t(struct vop_mknod_args *);
-
-struct vop_open_args;
-typedef int vop_open_t(struct vop_open_args *);
-
-struct vop_close_args;
-typedef int vop_close_t(struct vop_close_args *);
-
-struct vop_access_args;
-typedef int vop_access_t(struct vop_access_args *);
-
-struct vop_accessx_args;
-typedef int vop_accessx_t(struct vop_accessx_args *);
-
-struct vop_getattr_args;
-typedef int vop_getattr_t(struct vop_getattr_args *);
-
-struct vop_setattr_args;
-typedef int vop_setattr_t(struct vop_setattr_args *);
-
-struct vop_markatime_args;
-typedef int vop_markatime_t(struct vop_markatime_args *);
-
-struct vop_read_args;
-typedef int vop_read_t(struct vop_read_args *);
-
-struct vop_write_args;
-typedef int vop_write_t(struct vop_write_args *);
-
-struct vop_ioctl_args;
-typedef int vop_ioctl_t(struct vop_ioctl_args *);
-
-struct vop_poll_args;
-typedef int vop_poll_t(struct vop_poll_args *);
-
-struct vop_kqfilter_args;
-typedef int vop_kqfilter_t(struct vop_kqfilter_args *);
-
-struct vop_revoke_args;
-typedef int vop_revoke_t(struct vop_revoke_args *);
-
-struct vop_fsync_args;
-typedef int vop_fsync_t(struct vop_fsync_args *);
-
-struct vop_remove_args;
-typedef int vop_remove_t(struct vop_remove_args *);
-
-struct vop_link_args;
-typedef int vop_link_t(struct vop_link_args *);
-
-struct vop_rename_args;
-typedef int vop_rename_t(struct vop_rename_args *);
-
-struct vop_mkdir_args;
-typedef int vop_mkdir_t(struct vop_mkdir_args *);
-
-struct vop_rmdir_args;
-typedef int vop_rmdir_t(struct vop_rmdir_args *);
-
-struct vop_symlink_args;
-typedef int vop_symlink_t(struct vop_symlink_args *);
-
-struct vop_readdir_args;
-typedef int vop_readdir_t(struct vop_readdir_args *);
-
-struct vop_readlink_args;
-typedef int vop_readlink_t(struct vop_readlink_args *);
-
-struct vop_inactive_args;
-typedef int vop_inactive_t(struct vop_inactive_args *);
-
-struct vop_reclaim_args;
-typedef int vop_reclaim_t(struct vop_reclaim_args *);
-
-struct vop_lock1_args;
-typedef int vop_lock1_t(struct vop_lock1_args *);
-
-struct vop_unlock_args;
-typedef int vop_unlock_t(struct vop_unlock_args *);
-
-struct vop_bmap_args;
-typedef int vop_bmap_t(struct vop_bmap_args *);
-
-struct vop_strategy_args;
-typedef int vop_strategy_t(struct vop_strategy_args *);
-
-struct vop_getwritemount_args;
-typedef int vop_getwritemount_t(struct vop_getwritemount_args *);
-
-struct vop_print_args;
-typedef int vop_print_t(struct vop_print_args *);
-
-struct vop_pathconf_args;
-typedef int vop_pathconf_t(struct vop_pathconf_args *);
-
-struct vop_advlock_args;
-typedef int vop_advlock_t(struct vop_advlock_args *);
-
-struct vop_advlockasync_args;
-typedef int vop_advlockasync_t(struct vop_advlockasync_args *);
-
-struct vop_reallocblks_args;
-typedef int vop_reallocblks_t(struct vop_reallocblks_args *);
-
-struct vop_getpages_args;
-typedef int vop_getpages_t(struct vop_getpages_args *);
-
-struct vop_putpages_args;
-typedef int vop_putpages_t(struct vop_putpages_args *);
-
-struct vop_getacl_args;
-typedef int vop_getacl_t(struct vop_getacl_args *);
-
-struct vop_setacl_args;
-typedef int vop_setacl_t(struct vop_setacl_args *);
-
-struct vop_aclcheck_args;
-typedef int vop_aclcheck_t(struct vop_aclcheck_args *);
-
-struct vop_closeextattr_args;
-typedef int vop_closeextattr_t(struct vop_closeextattr_args *);
-
-struct vop_getextattr_args;
-typedef int vop_getextattr_t(struct vop_getextattr_args *);
-
-struct vop_listextattr_args;
-typedef int vop_listextattr_t(struct vop_listextattr_args *);
-
-struct vop_openextattr_args;
-typedef int vop_openextattr_t(struct vop_openextattr_args *);
-
-struct vop_deleteextattr_args;
-typedef int vop_deleteextattr_t(struct vop_deleteextattr_args *);
-
-struct vop_setextattr_args;
-typedef int vop_setextattr_t(struct vop_setextattr_args *);
-
-struct vop_setlabel_args;
-typedef int vop_setlabel_t(struct vop_setlabel_args *);
-
-struct vop_vptofh_args;
-typedef int vop_vptofh_t(struct vop_vptofh_args *);
-
-struct vop_vptocnp_args;
-typedef int vop_vptocnp_t(struct vop_vptocnp_args *);
-
diff --git a/freebsd/machine/elf.h b/freebsd/machine/elf.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/machine/elf.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/machine/pcb.h b/freebsd/machine/pcb.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/machine/pcb.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/machine/resource.h b/freebsd/machine/resource.h
deleted file mode 100644
index 9b143810..00000000
--- a/freebsd/machine/resource.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#ifndef _MACHINE_RESOURCE_H_
-#define _MACHINE_RESOURCE_H_ 1
-
-#define SYS_RES_IRQ 1 /* interrupt lines */
-#define SYS_RES_DRQ 2 /* isa dma lines */
-#define SYS_RES_MEMORY 3 /* i/o memory */
-#define SYS_RES_IOPORT 4 /* i/o ports */
-#define SYS_RES_GPIO 5 /* general purpose i/o */
-
-#endif /* !_MACHINE_RESOURCE_H_ */
diff --git a/freebsd/machine/smp.h b/freebsd/machine/smp.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/machine/smp.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/machine/vm.h b/freebsd/machine/vm.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/machine/vm.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/netgraph/ng_ipfw.h b/freebsd/netgraph/ng_ipfw.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/netgraph/ng_ipfw.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sbin/dhclient/alloc.c b/freebsd/sbin/dhclient/alloc.c
new file mode 100644
index 00000000..cd60ceca
--- /dev/null
+++ b/freebsd/sbin/dhclient/alloc.c
@@ -0,0 +1,79 @@
+/* $OpenBSD: alloc.c,v 1.9 2004/05/04 20:28:40 deraadt Exp $ */
+
+/* Memory allocation... */
+
+/*
+ * Copyright (c) 1995, 1996, 1998 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+struct string_list *
+new_string_list(size_t size)
+{
+ struct string_list *rval;
+
+ rval = calloc(1, sizeof(struct string_list) + size);
+ if (rval != NULL)
+ rval->string = ((char *)rval) + sizeof(struct string_list);
+ return (rval);
+}
+
+struct hash_table *
+new_hash_table(int count)
+{
+ struct hash_table *rval;
+
+ rval = calloc(1, sizeof(struct hash_table) -
+ (DEFAULT_HASH_SIZE * sizeof(struct hash_bucket *)) +
+ (count * sizeof(struct hash_bucket *)));
+ if (rval == NULL)
+ return (NULL);
+ rval->hash_count = count;
+ return (rval);
+}
+
+struct hash_bucket *
+new_hash_bucket(void)
+{
+ struct hash_bucket *rval = calloc(1, sizeof(struct hash_bucket));
+
+ return (rval);
+}
diff --git a/freebsd/sbin/dhclient/bpf.c b/freebsd/sbin/dhclient/bpf.c
new file mode 100644
index 00000000..7f87ddf5
--- /dev/null
+++ b/freebsd/sbin/dhclient/bpf.c
@@ -0,0 +1,416 @@
+/* $OpenBSD: bpf.c,v 1.13 2004/05/05 14:28:58 deraadt Exp $ */
+
+/* BPF socket interface code, originally contributed by Archie Cobbs. */
+
+/*
+ * Copyright (c) 1995, 1996, 1998, 1999
+ * The Internet Software Consortium. 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+#include <sys/ioctl.h>
+#include <sys/uio.h>
+
+#ifdef __rtems__
+#include <freebsd/net/bpf.h>
+#include <freebsd/netinet/in_systm.h>
+#else
+#include <net/bpf.h>
+#include <netinet/in_systm.h>
+#endif
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netinet/if_ether.h>
+
+#define BPF_FORMAT "/dev/bpf%d"
+
+/*
+ * Called by get_interface_list for each interface that's discovered.
+ * Opens a packet filter for each interface and adds it to the select
+ * mask.
+ */
+int
+if_register_bpf(struct interface_info *info)
+{
+ char filename[50];
+ int sock, b;
+
+ /* Open a BPF device */
+ for (b = 0; 1; b++) {
+ snprintf(filename, sizeof(filename), BPF_FORMAT, b);
+ sock = open(filename, O_RDWR, 0);
+ if (sock < 0) {
+ if (errno == EBUSY)
+ continue;
+ else
+ error("Can't find free bpf: %m");
+ } else
+ break;
+ }
+
+ /* Set the BPF device to point at this interface. */
+ if (ioctl(sock, BIOCSETIF, info->ifp) < 0)
+ error("Can't attach interface %s to bpf device %s: %m",
+ info->name, filename);
+
+ return (sock);
+}
+
+void
+if_register_send(struct interface_info *info)
+{
+ int sock, on = 1;
+
+ /*
+ * If we're using the bpf API for sending and receiving, we
+ * don't need to register this interface twice.
+ */
+ info->wfdesc = info->rfdesc;
+
+ /*
+ * Use raw socket for unicast send.
+ */
+ if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_UDP)) == -1)
+ error("socket(SOCK_RAW): %m");
+ if (setsockopt(sock, IPPROTO_IP, IP_HDRINCL, &on,
+ sizeof(on)) == -1)
+ error("setsockopt(IP_HDRINCL): %m");
+ info->ufdesc = sock;
+}
+
+/*
+ * Packet filter program...
+ *
+ * XXX: Changes to the filter program may require changes to the
+ * constant offsets used in if_register_send to patch the BPF program!
+ */
+struct bpf_insn dhcp_bpf_filter[] = {
+ /* Make sure this is an IP packet... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 8),
+
+ /* Make sure it's a UDP packet... */
+ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 6),
+
+ /* Make sure this isn't a fragment... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
+ BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 4, 0),
+
+ /* Get the IP header length... */
+ BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
+
+ /* Make sure it's to the right port... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1), /* patch */
+
+ /* If we passed all the tests, ask for the whole packet. */
+ BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+
+ /* Otherwise, drop it. */
+ BPF_STMT(BPF_RET+BPF_K, 0),
+};
+
+int dhcp_bpf_filter_len = sizeof(dhcp_bpf_filter) / sizeof(struct bpf_insn);
+
+/*
+ * Packet write filter program:
+ * 'ip and udp and src port bootps and dst port (bootps or bootpc)'
+ */
+struct bpf_insn dhcp_bpf_wfilter[] = {
+ BPF_STMT(BPF_LD + BPF_B + BPF_IND, 14),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, (IPVERSION << 4) + 5, 0, 12),
+
+ /* Make sure this is an IP packet... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 12),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, ETHERTYPE_IP, 0, 10),
+
+ /* Make sure it's a UDP packet... */
+ BPF_STMT(BPF_LD + BPF_B + BPF_ABS, 23),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, IPPROTO_UDP, 0, 8),
+
+ /* Make sure this isn't a fragment... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_ABS, 20),
+ BPF_JUMP(BPF_JMP + BPF_JSET + BPF_K, 0x1fff, 6, 0), /* patched */
+
+ /* Get the IP header length... */
+ BPF_STMT(BPF_LDX + BPF_B + BPF_MSH, 14),
+
+ /* Make sure it's from the right port... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 14),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 68, 0, 3),
+
+ /* Make sure it is to the right ports ... */
+ BPF_STMT(BPF_LD + BPF_H + BPF_IND, 16),
+ BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, 67, 0, 1),
+
+ /* If we passed all the tests, ask for the whole packet. */
+ BPF_STMT(BPF_RET+BPF_K, (u_int)-1),
+
+ /* Otherwise, drop it. */
+ BPF_STMT(BPF_RET+BPF_K, 0),
+};
+
+int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn);
+
+void
+if_register_receive(struct interface_info *info)
+{
+ struct bpf_version v;
+ struct bpf_program p;
+ int flag = 1, sz;
+
+ /* Open a BPF device and hang it on this interface... */
+ info->rfdesc = if_register_bpf(info);
+
+ /* Make sure the BPF version is in range... */
+ if (ioctl(info->rfdesc, BIOCVERSION, &v) < 0)
+ error("Can't get BPF version: %m");
+
+ if (v.bv_major != BPF_MAJOR_VERSION ||
+ v.bv_minor < BPF_MINOR_VERSION)
+ error("Kernel BPF version out of range - recompile dhcpd!");
+
+ /*
+ * Set immediate mode so that reads return as soon as a packet
+ * comes in, rather than waiting for the input buffer to fill
+ * with packets.
+ */
+ if (ioctl(info->rfdesc, BIOCIMMEDIATE, &flag) < 0)
+ error("Can't set immediate mode on bpf device: %m");
+
+ /* Get the required BPF buffer length from the kernel. */
+ if (ioctl(info->rfdesc, BIOCGBLEN, &sz) < 0)
+ error("Can't get bpf buffer length: %m");
+ info->rbuf_max = sz;
+ info->rbuf = malloc(info->rbuf_max);
+ if (!info->rbuf)
+ error("Can't allocate %lu bytes for bpf input buffer.",
+ (unsigned long)info->rbuf_max);
+ info->rbuf_offset = 0;
+ info->rbuf_len = 0;
+
+ /* Set up the bpf filter program structure. */
+ p.bf_len = dhcp_bpf_filter_len;
+ p.bf_insns = dhcp_bpf_filter;
+
+ /* Patch the server port into the BPF program...
+ *
+ * XXX: changes to filter program may require changes to the
+ * insn number(s) used below!
+ */
+ dhcp_bpf_filter[8].k = LOCAL_PORT;
+
+ if (ioctl(info->rfdesc, BIOCSETF, &p) < 0)
+ error("Can't install packet filter program: %m");
+
+ /* Set up the bpf write filter program structure. */
+ p.bf_len = dhcp_bpf_wfilter_len;
+ p.bf_insns = dhcp_bpf_wfilter;
+
+ if (dhcp_bpf_wfilter[7].k == 0x1fff)
+ dhcp_bpf_wfilter[7].k = htons(IP_MF|IP_OFFMASK);
+
+ if (ioctl(info->rfdesc, BIOCSETWF, &p) < 0)
+ error("Can't install write filter program: %m");
+
+ if (ioctl(info->rfdesc, BIOCLOCK, NULL) < 0)
+ error("Cannot lock bpf");
+}
+
+ssize_t
+send_packet(struct interface_info *interface, struct dhcp_packet *raw,
+ size_t len, struct in_addr from, struct sockaddr_in *to,
+ struct hardware *hto)
+{
+ unsigned char buf[256];
+ struct iovec iov[2];
+ struct msghdr msg;
+ int result, bufp = 0;
+
+ /* Assemble the headers... */
+ if (to->sin_addr.s_addr == INADDR_BROADCAST)
+ assemble_hw_header(interface, buf, &bufp, hto);
+ assemble_udp_ip_header(buf, &bufp, from.s_addr,
+ to->sin_addr.s_addr, to->sin_port, (unsigned char *)raw, len);
+
+ iov[0].iov_base = (char *)buf;
+ iov[0].iov_len = bufp;
+ iov[1].iov_base = (char *)raw;
+ iov[1].iov_len = len;
+
+ /* Fire it off */
+ if (to->sin_addr.s_addr == INADDR_BROADCAST)
+ result = writev(interface->wfdesc, iov, 2);
+ else {
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = (struct sockaddr *)to;
+ msg.msg_namelen = sizeof(*to);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 2;
+ result = sendmsg(interface->ufdesc, &msg, 0);
+ }
+
+ if (result < 0)
+ warning("send_packet: %m");
+ return (result);
+}
+
+ssize_t
+receive_packet(struct interface_info *interface, unsigned char *buf,
+ size_t len, struct sockaddr_in *from, struct hardware *hfrom)
+{
+ int length = 0, offset = 0;
+ struct bpf_hdr hdr;
+
+ /*
+ * All this complexity is because BPF doesn't guarantee that
+ * only one packet will be returned at a time. We're getting
+ * what we deserve, though - this is a terrible abuse of the BPF
+ * interface. Sigh.
+ */
+
+ /* Process packets until we get one we can return or until we've
+ * done a read and gotten nothing we can return...
+ */
+ do {
+ /* If the buffer is empty, fill it. */
+ if (interface->rbuf_offset >= interface->rbuf_len) {
+ length = read(interface->rfdesc, interface->rbuf,
+ interface->rbuf_max);
+ if (length <= 0)
+ return (length);
+ interface->rbuf_offset = 0;
+ interface->rbuf_len = length;
+ }
+
+ /*
+ * If there isn't room for a whole bpf header, something
+ * went wrong, but we'll ignore it and hope it goes
+ * away... XXX
+ */
+ if (interface->rbuf_len - interface->rbuf_offset <
+ sizeof(hdr)) {
+ interface->rbuf_offset = interface->rbuf_len;
+ continue;
+ }
+
+ /* Copy out a bpf header... */
+ memcpy(&hdr, &interface->rbuf[interface->rbuf_offset],
+ sizeof(hdr));
+
+ /*
+ * If the bpf header plus data doesn't fit in what's
+ * left of the buffer, stick head in sand yet again...
+ */
+ if (interface->rbuf_offset + hdr.bh_hdrlen + hdr.bh_caplen >
+ interface->rbuf_len) {
+ interface->rbuf_offset = interface->rbuf_len;
+ continue;
+ }
+
+ /* Skip over the BPF header... */
+ interface->rbuf_offset += hdr.bh_hdrlen;
+
+ /*
+ * If the captured data wasn't the whole packet, or if
+ * the packet won't fit in the input buffer, all we can
+ * do is drop it.
+ */
+ if (hdr.bh_caplen != hdr.bh_datalen) {
+ interface->rbuf_offset =
+ BPF_WORDALIGN(interface->rbuf_offset +
+ hdr.bh_caplen);
+ continue;
+ }
+
+ /* Decode the physical header... */
+ offset = decode_hw_header(interface->rbuf,
+ interface->rbuf_offset, hfrom);
+
+ /*
+ * If a physical layer checksum failed (dunno of any
+ * physical layer that supports this, but WTH), skip
+ * this packet.
+ */
+ if (offset < 0) {
+ interface->rbuf_offset =
+ BPF_WORDALIGN(interface->rbuf_offset +
+ hdr.bh_caplen);
+ continue;
+ }
+ interface->rbuf_offset += offset;
+ hdr.bh_caplen -= offset;
+
+ /* Decode the IP and UDP headers... */
+ offset = decode_udp_ip_header(interface->rbuf,
+ interface->rbuf_offset, from, NULL, hdr.bh_caplen);
+
+ /* If the IP or UDP checksum was bad, skip the packet... */
+ if (offset < 0) {
+ interface->rbuf_offset =
+ BPF_WORDALIGN(interface->rbuf_offset +
+ hdr.bh_caplen);
+ continue;
+ }
+ interface->rbuf_offset += offset;
+ hdr.bh_caplen -= offset;
+
+ /*
+ * If there's not enough room to stash the packet data,
+ * we have to skip it (this shouldn't happen in real
+ * life, though).
+ */
+ if (hdr.bh_caplen > len) {
+ interface->rbuf_offset =
+ BPF_WORDALIGN(interface->rbuf_offset +
+ hdr.bh_caplen);
+ continue;
+ }
+
+ /* Copy out the data in the packet... */
+ memcpy(buf, interface->rbuf + interface->rbuf_offset,
+ hdr.bh_caplen);
+ interface->rbuf_offset =
+ BPF_WORDALIGN(interface->rbuf_offset +
+ hdr.bh_caplen);
+ return (hdr.bh_caplen);
+ } while (!length);
+ return (0);
+}
diff --git a/freebsd/sbin/dhclient/clparse.c b/freebsd/sbin/dhclient/clparse.c
new file mode 100644
index 00000000..5d7084e7
--- /dev/null
+++ b/freebsd/sbin/dhclient/clparse.c
@@ -0,0 +1,943 @@
+/* $OpenBSD: clparse.c,v 1.18 2004/09/15 18:15:18 henning Exp $ */
+
+/* Parser for dhclient config and lease files... */
+
+/*
+ * Copyright (c) 1997 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+
+struct client_config top_level_config;
+struct interface_info *dummy_interfaces;
+extern struct interface_info *ifi;
+
+char client_script_name[] = "/sbin/dhclient-script";
+
+/*
+ * client-conf-file :== client-declarations EOF
+ * client-declarations :== <nil>
+ * | client-declaration
+ * | client-declarations client-declaration
+ */
+int
+read_client_conf(void)
+{
+ FILE *cfile;
+ char *val;
+ int token;
+ struct client_config *config;
+
+ new_parse(path_dhclient_conf);
+
+ /* Set up the initial dhcp option universe. */
+ initialize_universes();
+
+ /* Initialize the top level client configuration. */
+ memset(&top_level_config, 0, sizeof(top_level_config));
+
+ /* Set some defaults... */
+ top_level_config.timeout = 60;
+ top_level_config.select_interval = 0;
+ top_level_config.reboot_timeout = 10;
+ top_level_config.retry_interval = 300;
+ top_level_config.backoff_cutoff = 15;
+ top_level_config.initial_interval = 3;
+ top_level_config.bootp_policy = ACCEPT;
+ top_level_config.script_name = client_script_name;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_SUBNET_MASK;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_BROADCAST_ADDRESS;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_TIME_OFFSET;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_CLASSLESS_ROUTES;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_ROUTERS;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_DOMAIN_NAME;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] =
+ DHO_DOMAIN_NAME_SERVERS;
+ top_level_config.requested_options
+ [top_level_config.requested_option_count++] = DHO_HOST_NAME;
+
+ if ((cfile = fopen(path_dhclient_conf, "r")) != NULL) {
+ do {
+ token = peek_token(&val, cfile);
+ if (token == EOF)
+ break;
+ parse_client_statement(cfile, NULL, &top_level_config);
+ } while (1);
+ token = next_token(&val, cfile); /* Clear the peek buffer */
+ fclose(cfile);
+ }
+
+ /*
+ * Set up state and config structures for clients that don't
+ * have per-interface configuration declarations.
+ */
+ config = NULL;
+ if (!ifi->client) {
+ ifi->client = malloc(sizeof(struct client_state));
+ if (!ifi->client)
+ error("no memory for client state.");
+ memset(ifi->client, 0, sizeof(*(ifi->client)));
+ }
+ if (!ifi->client->config) {
+ if (!config) {
+ config = malloc(sizeof(struct client_config));
+ if (!config)
+ error("no memory for client config.");
+ memcpy(config, &top_level_config,
+ sizeof(top_level_config));
+ }
+ ifi->client->config = config;
+ }
+
+ return (!warnings_occurred);
+}
+
+/*
+ * lease-file :== client-lease-statements EOF
+ * client-lease-statements :== <nil>
+ * | client-lease-statements LEASE client-lease-statement
+ */
+void
+read_client_leases(void)
+{
+ FILE *cfile;
+ char *val;
+ int token;
+
+ new_parse(path_dhclient_db);
+
+ /* Open the lease file. If we can't open it, just return -
+ we can safely trust the server to remember our state. */
+ if ((cfile = fopen(path_dhclient_db, "r")) == NULL)
+ return;
+ do {
+ token = next_token(&val, cfile);
+ if (token == EOF)
+ break;
+ if (token != LEASE) {
+ warning("Corrupt lease file - possible data loss!");
+ skip_to_semi(cfile);
+ break;
+ } else
+ parse_client_lease_statement(cfile, 0);
+
+ } while (1);
+ fclose(cfile);
+}
+
+/*
+ * client-declaration :==
+ * SEND option-decl |
+ * DEFAULT option-decl |
+ * SUPERSEDE option-decl |
+ * PREPEND option-decl |
+ * APPEND option-decl |
+ * hardware-declaration |
+ * REQUEST option-list |
+ * REQUIRE option-list |
+ * TIMEOUT number |
+ * RETRY number |
+ * REBOOT number |
+ * SELECT_TIMEOUT number |
+ * SCRIPT string |
+ * interface-declaration |
+ * LEASE client-lease-statement |
+ * ALIAS client-lease-statement
+ */
+void
+parse_client_statement(FILE *cfile, struct interface_info *ip,
+ struct client_config *config)
+{
+ int token;
+ char *val;
+ struct option *option;
+
+ switch (next_token(&val, cfile)) {
+ case SEND:
+ parse_option_decl(cfile, &config->send_options[0]);
+ return;
+ case DEFAULT:
+ option = parse_option_decl(cfile, &config->defaults[0]);
+ if (option)
+ config->default_actions[option->code] = ACTION_DEFAULT;
+ return;
+ case SUPERSEDE:
+ option = parse_option_decl(cfile, &config->defaults[0]);
+ if (option)
+ config->default_actions[option->code] =
+ ACTION_SUPERSEDE;
+ return;
+ case APPEND:
+ option = parse_option_decl(cfile, &config->defaults[0]);
+ if (option)
+ config->default_actions[option->code] = ACTION_APPEND;
+ return;
+ case PREPEND:
+ option = parse_option_decl(cfile, &config->defaults[0]);
+ if (option)
+ config->default_actions[option->code] = ACTION_PREPEND;
+ return;
+ case MEDIA:
+ parse_string_list(cfile, &config->media, 1);
+ return;
+ case HARDWARE:
+ if (ip)
+ parse_hardware_param(cfile, &ip->hw_address);
+ else {
+ parse_warn("hardware address parameter %s",
+ "not allowed here.");
+ skip_to_semi(cfile);
+ }
+ return;
+ case REQUEST:
+ config->requested_option_count =
+ parse_option_list(cfile, config->requested_options);
+ return;
+ case REQUIRE:
+ memset(config->required_options, 0,
+ sizeof(config->required_options));
+ parse_option_list(cfile, config->required_options);
+ return;
+ case TIMEOUT:
+ parse_lease_time(cfile, &config->timeout);
+ return;
+ case RETRY:
+ parse_lease_time(cfile, &config->retry_interval);
+ return;
+ case SELECT_TIMEOUT:
+ parse_lease_time(cfile, &config->select_interval);
+ return;
+ case REBOOT:
+ parse_lease_time(cfile, &config->reboot_timeout);
+ return;
+ case BACKOFF_CUTOFF:
+ parse_lease_time(cfile, &config->backoff_cutoff);
+ return;
+ case INITIAL_INTERVAL:
+ parse_lease_time(cfile, &config->initial_interval);
+ return;
+ case SCRIPT:
+ config->script_name = parse_string(cfile);
+ return;
+ case INTERFACE:
+ if (ip)
+ parse_warn("nested interface declaration.");
+ parse_interface_declaration(cfile, config);
+ return;
+ case LEASE:
+ parse_client_lease_statement(cfile, 1);
+ return;
+ case ALIAS:
+ parse_client_lease_statement(cfile, 2);
+ return;
+ case REJECT:
+ parse_reject_statement(cfile, config);
+ return;
+ default:
+ parse_warn("expecting a statement.");
+ skip_to_semi(cfile);
+ break;
+ }
+ token = next_token(&val, cfile);
+ if (token != SEMI) {
+ parse_warn("semicolon expected.");
+ skip_to_semi(cfile);
+ }
+}
+
+int
+parse_X(FILE *cfile, u_int8_t *buf, int max)
+{
+ int token;
+ char *val;
+ int len;
+
+ token = peek_token(&val, cfile);
+ if (token == NUMBER_OR_NAME || token == NUMBER) {
+ len = 0;
+ do {
+ token = next_token(&val, cfile);
+ if (token != NUMBER && token != NUMBER_OR_NAME) {
+ parse_warn("expecting hexadecimal constant.");
+ skip_to_semi(cfile);
+ return (0);
+ }
+ convert_num(&buf[len], val, 16, 8);
+ if (len++ > max) {
+ parse_warn("hexadecimal constant too long.");
+ skip_to_semi(cfile);
+ return (0);
+ }
+ token = peek_token(&val, cfile);
+ if (token == COLON)
+ token = next_token(&val, cfile);
+ } while (token == COLON);
+ val = (char *)buf;
+ } else if (token == STRING) {
+ token = next_token(&val, cfile);
+ len = strlen(val);
+ if (len + 1 > max) {
+ parse_warn("string constant too long.");
+ skip_to_semi(cfile);
+ return (0);
+ }
+ memcpy(buf, val, len + 1);
+ } else {
+ parse_warn("expecting string or hexadecimal data");
+ skip_to_semi(cfile);
+ return (0);
+ }
+ return (len);
+}
+
+/*
+ * option-list :== option_name |
+ * option_list COMMA option_name
+ */
+int
+parse_option_list(FILE *cfile, u_int8_t *list)
+{
+ int ix, i;
+ int token;
+ char *val;
+
+ ix = 0;
+ do {
+ token = next_token(&val, cfile);
+ if (!is_identifier(token)) {
+ parse_warn("expected option name.");
+ skip_to_semi(cfile);
+ return (0);
+ }
+ for (i = 0; i < 256; i++)
+ if (!strcasecmp(dhcp_options[i].name, val))
+ break;
+
+ if (i == 256) {
+ parse_warn("%s: unexpected option name.", val);
+ skip_to_semi(cfile);
+ return (0);
+ }
+ list[ix++] = i;
+ if (ix == 256) {
+ parse_warn("%s: too many options.", val);
+ skip_to_semi(cfile);
+ return (0);
+ }
+ token = next_token(&val, cfile);
+ } while (token == COMMA);
+ if (token != SEMI) {
+ parse_warn("expecting semicolon.");
+ skip_to_semi(cfile);
+ return (0);
+ }
+ return (ix);
+}
+
+/*
+ * interface-declaration :==
+ * INTERFACE string LBRACE client-declarations RBRACE
+ */
+void
+parse_interface_declaration(FILE *cfile, struct client_config *outer_config)
+{
+ int token;
+ char *val;
+ struct interface_info *ip;
+
+ token = next_token(&val, cfile);
+ if (token != STRING) {
+ parse_warn("expecting interface name (in quotes).");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ ip = interface_or_dummy(val);
+
+ if (!ip->client)
+ make_client_state(ip);
+
+ if (!ip->client->config)
+ make_client_config(ip, outer_config);
+
+ token = next_token(&val, cfile);
+ if (token != LBRACE) {
+ parse_warn("expecting left brace.");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ do {
+ token = peek_token(&val, cfile);
+ if (token == EOF) {
+ parse_warn("unterminated interface declaration.");
+ return;
+ }
+ if (token == RBRACE)
+ break;
+ parse_client_statement(cfile, ip, ip->client->config);
+ } while (1);
+ token = next_token(&val, cfile);
+}
+
+struct interface_info *
+interface_or_dummy(char *name)
+{
+ struct interface_info *ip;
+
+ /* Find the interface (if any) that matches the name. */
+ if (!strcmp(ifi->name, name))
+ return (ifi);
+
+ /* If it's not a real interface, see if it's on the dummy list. */
+ for (ip = dummy_interfaces; ip; ip = ip->next)
+ if (!strcmp(ip->name, name))
+ return (ip);
+
+ /*
+ * If we didn't find an interface, make a dummy interface as a
+ * placeholder.
+ */
+ ip = malloc(sizeof(*ip));
+ if (!ip)
+ error("Insufficient memory to record interface %s", name);
+ memset(ip, 0, sizeof(*ip));
+ strlcpy(ip->name, name, IFNAMSIZ);
+ ip->next = dummy_interfaces;
+ dummy_interfaces = ip;
+ return (ip);
+}
+
+void
+make_client_state(struct interface_info *ip)
+{
+ ip->client = malloc(sizeof(*(ip->client)));
+ if (!ip->client)
+ error("no memory for state on %s", ip->name);
+ memset(ip->client, 0, sizeof(*(ip->client)));
+}
+
+void
+make_client_config(struct interface_info *ip, struct client_config *config)
+{
+ ip->client->config = malloc(sizeof(struct client_config));
+ if (!ip->client->config)
+ error("no memory for config for %s", ip->name);
+ memset(ip->client->config, 0, sizeof(*(ip->client->config)));
+ memcpy(ip->client->config, config, sizeof(*config));
+}
+
+/*
+ * client-lease-statement :==
+ * RBRACE client-lease-declarations LBRACE
+ *
+ * client-lease-declarations :==
+ * <nil> |
+ * client-lease-declaration |
+ * client-lease-declarations client-lease-declaration
+ */
+void
+parse_client_lease_statement(FILE *cfile, int is_static)
+{
+ struct client_lease *lease, *lp, *pl;
+ struct interface_info *ip;
+ int token;
+ char *val;
+
+ token = next_token(&val, cfile);
+ if (token != LBRACE) {
+ parse_warn("expecting left brace.");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ lease = malloc(sizeof(struct client_lease));
+ if (!lease)
+ error("no memory for lease.");
+ memset(lease, 0, sizeof(*lease));
+ lease->is_static = is_static;
+
+ ip = NULL;
+
+ do {
+ token = peek_token(&val, cfile);
+ if (token == EOF) {
+ parse_warn("unterminated lease declaration.");
+ return;
+ }
+ if (token == RBRACE)
+ break;
+ parse_client_lease_declaration(cfile, lease, &ip);
+ } while (1);
+ token = next_token(&val, cfile);
+
+ /* If the lease declaration didn't include an interface
+ * declaration that we recognized, it's of no use to us.
+ */
+ if (!ip) {
+ free_client_lease(lease);
+ return;
+ }
+
+ /* Make sure there's a client state structure... */
+ if (!ip->client)
+ make_client_state(ip);
+
+ /* If this is an alias lease, it doesn't need to be sorted in. */
+ if (is_static == 2) {
+ ip->client->alias = lease;
+ return;
+ }
+
+ /*
+ * The new lease may supersede a lease that's not the active
+ * lease but is still on the lease list, so scan the lease list
+ * looking for a lease with the same address, and if we find it,
+ * toss it.
+ */
+ pl = NULL;
+ for (lp = ip->client->leases; lp; lp = lp->next) {
+ if (lp->address.len == lease->address.len &&
+ !memcmp(lp->address.iabuf, lease->address.iabuf,
+ lease->address.len)) {
+ if (pl)
+ pl->next = lp->next;
+ else
+ ip->client->leases = lp->next;
+ free_client_lease(lp);
+ break;
+ }
+ }
+
+ /*
+ * If this is a preloaded lease, just put it on the list of
+ * recorded leases - don't make it the active lease.
+ */
+ if (is_static) {
+ lease->next = ip->client->leases;
+ ip->client->leases = lease;
+ return;
+ }
+
+ /*
+ * The last lease in the lease file on a particular interface is
+ * the active lease for that interface. Of course, we don't
+ * know what the last lease in the file is until we've parsed
+ * the whole file, so at this point, we assume that the lease we
+ * just parsed is the active lease for its interface. If
+ * there's already an active lease for the interface, and this
+ * lease is for the same ip address, then we just toss the old
+ * active lease and replace it with this one. If this lease is
+ * for a different address, then if the old active lease has
+ * expired, we dump it; if not, we put it on the list of leases
+ * for this interface which are still valid but no longer
+ * active.
+ */
+ if (ip->client->active) {
+ if (ip->client->active->expiry < cur_time)
+ free_client_lease(ip->client->active);
+ else if (ip->client->active->address.len ==
+ lease->address.len &&
+ !memcmp(ip->client->active->address.iabuf,
+ lease->address.iabuf, lease->address.len))
+ free_client_lease(ip->client->active);
+ else {
+ ip->client->active->next = ip->client->leases;
+ ip->client->leases = ip->client->active;
+ }
+ }
+ ip->client->active = lease;
+
+ /* Phew. */
+}
+
+/*
+ * client-lease-declaration :==
+ * BOOTP |
+ * INTERFACE string |
+ * FIXED_ADDR ip_address |
+ * FILENAME string |
+ * SERVER_NAME string |
+ * OPTION option-decl |
+ * RENEW time-decl |
+ * REBIND time-decl |
+ * EXPIRE time-decl
+ */
+void
+parse_client_lease_declaration(FILE *cfile, struct client_lease *lease,
+ struct interface_info **ipp)
+{
+ int token;
+ char *val;
+ struct interface_info *ip;
+
+ switch (next_token(&val, cfile)) {
+ case BOOTP:
+ lease->is_bootp = 1;
+ break;
+ case INTERFACE:
+ token = next_token(&val, cfile);
+ if (token != STRING) {
+ parse_warn("expecting interface name (in quotes).");
+ skip_to_semi(cfile);
+ break;
+ }
+ ip = interface_or_dummy(val);
+ *ipp = ip;
+ break;
+ case FIXED_ADDR:
+ if (!parse_ip_addr(cfile, &lease->address))
+ return;
+ break;
+ case MEDIUM:
+ parse_string_list(cfile, &lease->medium, 0);
+ return;
+ case FILENAME:
+ lease->filename = parse_string(cfile);
+ return;
+ case SERVER_NAME:
+ lease->server_name = parse_string(cfile);
+ return;
+ case RENEW:
+ lease->renewal = parse_date(cfile);
+ return;
+ case REBIND:
+ lease->rebind = parse_date(cfile);
+ return;
+ case EXPIRE:
+ lease->expiry = parse_date(cfile);
+ return;
+ case OPTION:
+ parse_option_decl(cfile, lease->options);
+ return;
+ default:
+ parse_warn("expecting lease declaration.");
+ skip_to_semi(cfile);
+ break;
+ }
+ token = next_token(&val, cfile);
+ if (token != SEMI) {
+ parse_warn("expecting semicolon.");
+ skip_to_semi(cfile);
+ }
+}
+
+struct option *
+parse_option_decl(FILE *cfile, struct option_data *options)
+{
+ char *val;
+ int token;
+ u_int8_t buf[4];
+ u_int8_t hunkbuf[1024];
+ int hunkix = 0;
+ char *vendor;
+ char *fmt;
+ struct universe *universe;
+ struct option *option;
+ struct iaddr ip_addr;
+ u_int8_t *dp;
+ int len;
+ int nul_term = 0;
+
+ token = next_token(&val, cfile);
+ if (!is_identifier(token)) {
+ parse_warn("expecting identifier after option keyword.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ if ((vendor = strdup(val)) == NULL)
+ error("no memory for vendor information.");
+
+ token = peek_token(&val, cfile);
+ if (token == DOT) {
+ /* Go ahead and take the DOT token... */
+ token = next_token(&val, cfile);
+
+ /* The next token should be an identifier... */
+ token = next_token(&val, cfile);
+ if (!is_identifier(token)) {
+ parse_warn("expecting identifier after '.'");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+
+ /* Look up the option name hash table for the specified
+ vendor. */
+ universe = ((struct universe *)hash_lookup(&universe_hash,
+ (unsigned char *)vendor, 0));
+ /* If it's not there, we can't parse the rest of the
+ declaration. */
+ if (!universe) {
+ parse_warn("no vendor named %s.", vendor);
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ } else {
+ /* Use the default hash table, which contains all the
+ standard dhcp option names. */
+ val = vendor;
+ universe = &dhcp_universe;
+ }
+
+ /* Look up the actual option info... */
+ option = (struct option *)hash_lookup(universe->hash,
+ (unsigned char *)val, 0);
+
+ /* If we didn't get an option structure, it's an undefined option. */
+ if (!option) {
+ if (val == vendor)
+ parse_warn("no option named %s", val);
+ else
+ parse_warn("no option named %s for vendor %s",
+ val, vendor);
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+
+ /* Free the initial identifier token. */
+ free(vendor);
+
+ /* Parse the option data... */
+ do {
+ for (fmt = option->format; *fmt; fmt++) {
+ if (*fmt == 'A')
+ break;
+ switch (*fmt) {
+ case 'X':
+ len = parse_X(cfile, &hunkbuf[hunkix],
+ sizeof(hunkbuf) - hunkix);
+ hunkix += len;
+ break;
+ case 't': /* Text string... */
+ token = next_token(&val, cfile);
+ if (token != STRING) {
+ parse_warn("expecting string.");
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ len = strlen(val);
+ if (hunkix + len + 1 > sizeof(hunkbuf)) {
+ parse_warn("option data buffer %s",
+ "overflow");
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ memcpy(&hunkbuf[hunkix], val, len + 1);
+ nul_term = 1;
+ hunkix += len;
+ break;
+ case 'I': /* IP address. */
+ if (!parse_ip_addr(cfile, &ip_addr))
+ return (NULL);
+ len = ip_addr.len;
+ dp = ip_addr.iabuf;
+alloc:
+ if (hunkix + len > sizeof(hunkbuf)) {
+ parse_warn("option data buffer "
+ "overflow");
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ memcpy(&hunkbuf[hunkix], dp, len);
+ hunkix += len;
+ break;
+ case 'L': /* Unsigned 32-bit integer... */
+ case 'l': /* Signed 32-bit integer... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+need_number:
+ parse_warn("expecting number.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ convert_num(buf, val, 0, 32);
+ len = 4;
+ dp = buf;
+ goto alloc;
+ case 's': /* Signed 16-bit integer. */
+ case 'S': /* Unsigned 16-bit integer. */
+ token = next_token(&val, cfile);
+ if (token != NUMBER)
+ goto need_number;
+ convert_num(buf, val, 0, 16);
+ len = 2;
+ dp = buf;
+ goto alloc;
+ case 'b': /* Signed 8-bit integer. */
+ case 'B': /* Unsigned 8-bit integer. */
+ token = next_token(&val, cfile);
+ if (token != NUMBER)
+ goto need_number;
+ convert_num(buf, val, 0, 8);
+ len = 1;
+ dp = buf;
+ goto alloc;
+ case 'f': /* Boolean flag. */
+ token = next_token(&val, cfile);
+ if (!is_identifier(token)) {
+ parse_warn("expecting identifier.");
+bad_flag:
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ if (!strcasecmp(val, "true") ||
+ !strcasecmp(val, "on"))
+ buf[0] = 1;
+ else if (!strcasecmp(val, "false") ||
+ !strcasecmp(val, "off"))
+ buf[0] = 0;
+ else {
+ parse_warn("expecting boolean.");
+ goto bad_flag;
+ }
+ len = 1;
+ dp = buf;
+ goto alloc;
+ default:
+ warning("Bad format %c in parse_option_param.",
+ *fmt);
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ }
+ token = next_token(&val, cfile);
+ } while (*fmt == 'A' && token == COMMA);
+
+ if (token != SEMI) {
+ parse_warn("semicolon expected.");
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+
+ options[option->code].data = malloc(hunkix + nul_term);
+ if (!options[option->code].data)
+ error("out of memory allocating option data.");
+ memcpy(options[option->code].data, hunkbuf, hunkix + nul_term);
+ options[option->code].len = hunkix;
+ return (option);
+}
+
+void
+parse_string_list(FILE *cfile, struct string_list **lp, int multiple)
+{
+ int token;
+ char *val;
+ struct string_list *cur, *tmp;
+
+ /* Find the last medium in the media list. */
+ if (*lp)
+ for (cur = *lp; cur->next; cur = cur->next)
+ ; /* nothing */
+ else
+ cur = NULL;
+
+ do {
+ token = next_token(&val, cfile);
+ if (token != STRING) {
+ parse_warn("Expecting media options.");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ tmp = new_string_list(strlen(val) + 1);
+ if (tmp == NULL)
+ error("no memory for string list entry.");
+ strlcpy(tmp->string, val, strlen(val) + 1);
+ tmp->next = NULL;
+
+ /* Store this medium at the end of the media list. */
+ if (cur)
+ cur->next = tmp;
+ else
+ *lp = tmp;
+ cur = tmp;
+
+ token = next_token(&val, cfile);
+ } while (multiple && token == COMMA);
+
+ if (token != SEMI) {
+ parse_warn("expecting semicolon.");
+ skip_to_semi(cfile);
+ }
+}
+
+void
+parse_reject_statement(FILE *cfile, struct client_config *config)
+{
+ int token;
+ char *val;
+ struct iaddr addr;
+ struct iaddrlist *list;
+
+ do {
+ if (!parse_ip_addr(cfile, &addr)) {
+ parse_warn("expecting IP address.");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ list = malloc(sizeof(struct iaddrlist));
+ if (!list)
+ error("no memory for reject list!");
+
+ list->addr = addr;
+ list->next = config->reject_list;
+ config->reject_list = list;
+
+ token = next_token(&val, cfile);
+ } while (token == COMMA);
+
+ if (token != SEMI) {
+ parse_warn("expecting semicolon.");
+ skip_to_semi(cfile);
+ }
+}
diff --git a/freebsd/sbin/dhclient/conflex.c b/freebsd/sbin/dhclient/conflex.c
new file mode 100644
index 00000000..3c8932db
--- /dev/null
+++ b/freebsd/sbin/dhclient/conflex.c
@@ -0,0 +1,529 @@
+/* $OpenBSD: conflex.c,v 1.7 2004/09/15 19:02:38 deraadt Exp $ */
+
+/* Lexical scanner for dhcpd config file... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+
+int lexline;
+int lexchar;
+char *token_line;
+char *prev_line;
+char *cur_line;
+char *tlname;
+int eol_token;
+
+static char line1[81];
+static char line2[81];
+static int lpos;
+static int line;
+static int tlpos;
+static int tline;
+static int token;
+static int ugflag;
+static char *tval;
+static char tokbuf[1500];
+
+static int get_char(FILE *);
+static int get_token(FILE *);
+static void skip_to_eol(FILE *);
+static int read_string(FILE *);
+static int read_number(int, FILE *);
+static int read_num_or_name(int, FILE *);
+static int intern(char *, int);
+
+void
+new_parse(char *name)
+{
+ tlname = name;
+ lpos = line = 1;
+ cur_line = line1;
+ prev_line = line2;
+ token_line = cur_line;
+ cur_line[0] = prev_line[0] = 0;
+ warnings_occurred = 0;
+}
+
+static int
+get_char(FILE *cfile)
+{
+ int c = getc(cfile);
+ if (!ugflag) {
+ if (c == '\n') {
+ if (cur_line == line1) {
+ cur_line = line2;
+ prev_line = line1;
+ } else {
+ cur_line = line2;
+ prev_line = line1;
+ }
+ line++;
+ lpos = 1;
+ cur_line[0] = 0;
+ } else if (c != EOF) {
+ if (lpos < sizeof(line1)) {
+ cur_line[lpos - 1] = c;
+ cur_line[lpos] = 0;
+ }
+ lpos++;
+ }
+ } else
+ ugflag = 0;
+ return (c);
+}
+
+static int
+get_token(FILE *cfile)
+{
+ int c, ttok;
+ static char tb[2];
+ int l, p;
+
+ do {
+ l = line;
+ p = lpos;
+
+ c = get_char(cfile);
+
+ if (!(c == '\n' && eol_token) && isascii(c) && isspace(c))
+ continue;
+ if (c == '#') {
+ skip_to_eol(cfile);
+ continue;
+ }
+ if (c == '"') {
+ lexline = l;
+ lexchar = p;
+ ttok = read_string(cfile);
+ break;
+ }
+ if ((isascii(c) && isdigit(c)) || c == '-') {
+ lexline = l;
+ lexchar = p;
+ ttok = read_number(c, cfile);
+ break;
+ } else if (isascii(c) && isalpha(c)) {
+ lexline = l;
+ lexchar = p;
+ ttok = read_num_or_name(c, cfile);
+ break;
+ } else {
+ lexline = l;
+ lexchar = p;
+ tb[0] = c;
+ tb[1] = 0;
+ tval = tb;
+ ttok = c;
+ break;
+ }
+ } while (1);
+ return (ttok);
+}
+
+int
+next_token(char **rval, FILE *cfile)
+{
+ int rv;
+
+ if (token) {
+ if (lexline != tline)
+ token_line = cur_line;
+ lexchar = tlpos;
+ lexline = tline;
+ rv = token;
+ token = 0;
+ } else {
+ rv = get_token(cfile);
+ token_line = cur_line;
+ }
+ if (rval)
+ *rval = tval;
+
+ return (rv);
+}
+
+int
+peek_token(char **rval, FILE *cfile)
+{
+ int x;
+
+ if (!token) {
+ tlpos = lexchar;
+ tline = lexline;
+ token = get_token(cfile);
+ if (lexline != tline)
+ token_line = prev_line;
+ x = lexchar;
+ lexchar = tlpos;
+ tlpos = x;
+ x = lexline;
+ lexline = tline;
+ tline = x;
+ }
+ if (rval)
+ *rval = tval;
+
+ return (token);
+}
+
+static void
+skip_to_eol(FILE *cfile)
+{
+ int c;
+
+ do {
+ c = get_char(cfile);
+ if (c == EOF)
+ return;
+ if (c == '\n')
+ return;
+ } while (1);
+}
+
+static int
+read_string(FILE *cfile)
+{
+ int i, c, bs = 0;
+
+ for (i = 0; i < sizeof(tokbuf); i++) {
+ c = get_char(cfile);
+ if (c == EOF) {
+ parse_warn("eof in string constant");
+ break;
+ }
+ if (bs) {
+ bs = 0;
+ i--;
+ tokbuf[i] = c;
+ } else if (c == '\\')
+ bs = 1;
+ else if (c == '"')
+ break;
+ else
+ tokbuf[i] = c;
+ }
+ /*
+ * Normally, I'd feel guilty about this, but we're talking about
+ * strings that'll fit in a DHCP packet here...
+ */
+ if (i == sizeof(tokbuf)) {
+ parse_warn("string constant larger than internal buffer");
+ i--;
+ }
+ tokbuf[i] = 0;
+ tval = tokbuf;
+ return (STRING);
+}
+
+static int
+read_number(int c, FILE *cfile)
+{
+ int seenx = 0, i = 0, token = NUMBER;
+
+ tokbuf[i++] = c;
+ for (; i < sizeof(tokbuf); i++) {
+ c = get_char(cfile);
+ if (!seenx && c == 'x')
+ seenx = 1;
+ else if (!isascii(c) || !isxdigit(c)) {
+ ungetc(c, cfile);
+ ugflag = 1;
+ break;
+ }
+ tokbuf[i] = c;
+ }
+ if (i == sizeof(tokbuf)) {
+ parse_warn("numeric token larger than internal buffer");
+ i--;
+ }
+ tokbuf[i] = 0;
+ tval = tokbuf;
+
+ return (token);
+}
+
+static int
+read_num_or_name(int c, FILE *cfile)
+{
+ int i = 0;
+ int rv = NUMBER_OR_NAME;
+
+ tokbuf[i++] = c;
+ for (; i < sizeof(tokbuf); i++) {
+ c = get_char(cfile);
+ if (!isascii(c) || (c != '-' && c != '_' && !isalnum(c))) {
+ ungetc(c, cfile);
+ ugflag = 1;
+ break;
+ }
+ if (!isxdigit(c))
+ rv = NAME;
+ tokbuf[i] = c;
+ }
+ if (i == sizeof(tokbuf)) {
+ parse_warn("token larger than internal buffer");
+ i--;
+ }
+ tokbuf[i] = 0;
+ tval = tokbuf;
+
+ return (intern(tval, rv));
+}
+
+static int
+intern(char *atom, int dfv)
+{
+ if (!isascii(atom[0]))
+ return (dfv);
+
+ switch (tolower(atom[0])) {
+ case 'a':
+ if (!strcasecmp(atom + 1, "lways-reply-rfc1048"))
+ return (ALWAYS_REPLY_RFC1048);
+ if (!strcasecmp(atom + 1, "ppend"))
+ return (APPEND);
+ if (!strcasecmp(atom + 1, "llow"))
+ return (ALLOW);
+ if (!strcasecmp(atom + 1, "lias"))
+ return (ALIAS);
+ if (!strcasecmp(atom + 1, "bandoned"))
+ return (ABANDONED);
+ if (!strcasecmp(atom + 1, "uthoritative"))
+ return (AUTHORITATIVE);
+ break;
+ case 'b':
+ if (!strcasecmp(atom + 1, "ackoff-cutoff"))
+ return (BACKOFF_CUTOFF);
+ if (!strcasecmp(atom + 1, "ootp"))
+ return (BOOTP);
+ if (!strcasecmp(atom + 1, "ooting"))
+ return (BOOTING);
+ if (!strcasecmp(atom + 1, "oot-unknown-clients"))
+ return (BOOT_UNKNOWN_CLIENTS);
+ case 'c':
+ if (!strcasecmp(atom + 1, "lass"))
+ return (CLASS);
+ if (!strcasecmp(atom + 1, "iaddr"))
+ return (CIADDR);
+ if (!strcasecmp(atom + 1, "lient-identifier"))
+ return (CLIENT_IDENTIFIER);
+ if (!strcasecmp(atom + 1, "lient-hostname"))
+ return (CLIENT_HOSTNAME);
+ break;
+ case 'd':
+ if (!strcasecmp(atom + 1, "omain"))
+ return (DOMAIN);
+ if (!strcasecmp(atom + 1, "eny"))
+ return (DENY);
+ if (!strncasecmp(atom + 1, "efault", 6)) {
+ if (!atom[7])
+ return (DEFAULT);
+ if (!strcasecmp(atom + 7, "-lease-time"))
+ return (DEFAULT_LEASE_TIME);
+ break;
+ }
+ if (!strncasecmp(atom + 1, "ynamic-bootp", 12)) {
+ if (!atom[13])
+ return (DYNAMIC_BOOTP);
+ if (!strcasecmp(atom + 13, "-lease-cutoff"))
+ return (DYNAMIC_BOOTP_LEASE_CUTOFF);
+ if (!strcasecmp(atom + 13, "-lease-length"))
+ return (DYNAMIC_BOOTP_LEASE_LENGTH);
+ break;
+ }
+ break;
+ case 'e':
+ if (!strcasecmp(atom + 1, "thernet"))
+ return (ETHERNET);
+ if (!strcasecmp(atom + 1, "nds"))
+ return (ENDS);
+ if (!strcasecmp(atom + 1, "xpire"))
+ return (EXPIRE);
+ break;
+ case 'f':
+ if (!strcasecmp(atom + 1, "ilename"))
+ return (FILENAME);
+ if (!strcasecmp(atom + 1, "ixed-address"))
+ return (FIXED_ADDR);
+ if (!strcasecmp(atom + 1, "ddi"))
+ return (FDDI);
+ break;
+ case 'g':
+ if (!strcasecmp(atom + 1, "iaddr"))
+ return (GIADDR);
+ if (!strcasecmp(atom + 1, "roup"))
+ return (GROUP);
+ if (!strcasecmp(atom + 1, "et-lease-hostnames"))
+ return (GET_LEASE_HOSTNAMES);
+ break;
+ case 'h':
+ if (!strcasecmp(atom + 1, "ost"))
+ return (HOST);
+ if (!strcasecmp(atom + 1, "ardware"))
+ return (HARDWARE);
+ if (!strcasecmp(atom + 1, "ostname"))
+ return (HOSTNAME);
+ break;
+ case 'i':
+ if (!strcasecmp(atom + 1, "nitial-interval"))
+ return (INITIAL_INTERVAL);
+ if (!strcasecmp(atom + 1, "nterface"))
+ return (INTERFACE);
+ break;
+ case 'l':
+ if (!strcasecmp(atom + 1, "ease"))
+ return (LEASE);
+ break;
+ case 'm':
+ if (!strcasecmp(atom + 1, "ax-lease-time"))
+ return (MAX_LEASE_TIME);
+ if (!strncasecmp(atom + 1, "edi", 3)) {
+ if (!strcasecmp(atom + 4, "a"))
+ return (MEDIA);
+ if (!strcasecmp(atom + 4, "um"))
+ return (MEDIUM);
+ break;
+ }
+ break;
+ case 'n':
+ if (!strcasecmp(atom + 1, "ameserver"))
+ return (NAMESERVER);
+ if (!strcasecmp(atom + 1, "etmask"))
+ return (NETMASK);
+ if (!strcasecmp(atom + 1, "ext-server"))
+ return (NEXT_SERVER);
+ if (!strcasecmp(atom + 1, "ot"))
+ return (TOKEN_NOT);
+ break;
+ case 'o':
+ if (!strcasecmp(atom + 1, "ption"))
+ return (OPTION);
+ if (!strcasecmp(atom + 1, "ne-lease-per-client"))
+ return (ONE_LEASE_PER_CLIENT);
+ break;
+ case 'p':
+ if (!strcasecmp(atom + 1, "repend"))
+ return (PREPEND);
+ if (!strcasecmp(atom + 1, "acket"))
+ return (PACKET);
+ break;
+ case 'r':
+ if (!strcasecmp(atom + 1, "ange"))
+ return (RANGE);
+ if (!strcasecmp(atom + 1, "equest"))
+ return (REQUEST);
+ if (!strcasecmp(atom + 1, "equire"))
+ return (REQUIRE);
+ if (!strcasecmp(atom + 1, "etry"))
+ return (RETRY);
+ if (!strcasecmp(atom + 1, "enew"))
+ return (RENEW);
+ if (!strcasecmp(atom + 1, "ebind"))
+ return (REBIND);
+ if (!strcasecmp(atom + 1, "eboot"))
+ return (REBOOT);
+ if (!strcasecmp(atom + 1, "eject"))
+ return (REJECT);
+ break;
+ case 's':
+ if (!strcasecmp(atom + 1, "earch"))
+ return (SEARCH);
+ if (!strcasecmp(atom + 1, "tarts"))
+ return (STARTS);
+ if (!strcasecmp(atom + 1, "iaddr"))
+ return (SIADDR);
+ if (!strcasecmp(atom + 1, "ubnet"))
+ return (SUBNET);
+ if (!strcasecmp(atom + 1, "hared-network"))
+ return (SHARED_NETWORK);
+ if (!strcasecmp(atom + 1, "erver-name"))
+ return (SERVER_NAME);
+ if (!strcasecmp(atom + 1, "erver-identifier"))
+ return (SERVER_IDENTIFIER);
+ if (!strcasecmp(atom + 1, "elect-timeout"))
+ return (SELECT_TIMEOUT);
+ if (!strcasecmp(atom + 1, "end"))
+ return (SEND);
+ if (!strcasecmp(atom + 1, "cript"))
+ return (SCRIPT);
+ if (!strcasecmp(atom + 1, "upersede"))
+ return (SUPERSEDE);
+ break;
+ case 't':
+ if (!strcasecmp(atom + 1, "imestamp"))
+ return (TIMESTAMP);
+ if (!strcasecmp(atom + 1, "imeout"))
+ return (TIMEOUT);
+ if (!strcasecmp(atom + 1, "oken-ring"))
+ return (TOKEN_RING);
+ break;
+ case 'u':
+ if (!strncasecmp(atom + 1, "se", 2)) {
+ if (!strcasecmp(atom + 3, "r-class"))
+ return (USER_CLASS);
+ if (!strcasecmp(atom + 3, "-host-decl-names"))
+ return (USE_HOST_DECL_NAMES);
+ if (!strcasecmp(atom + 3,
+ "-lease-addr-for-default-route"))
+ return (USE_LEASE_ADDR_FOR_DEFAULT_ROUTE);
+ break;
+ }
+ if (!strcasecmp(atom + 1, "id"))
+ return (UID);
+ if (!strcasecmp(atom + 1, "nknown-clients"))
+ return (UNKNOWN_CLIENTS);
+ break;
+ case 'v':
+ if (!strcasecmp(atom + 1, "endor-class"))
+ return (VENDOR_CLASS);
+ break;
+ case 'y':
+ if (!strcasecmp(atom + 1, "iaddr"))
+ return (YIADDR);
+ break;
+ }
+ return (dfv);
+}
diff --git a/freebsd/sbin/dhclient/convert.c b/freebsd/sbin/dhclient/convert.c
new file mode 100644
index 00000000..adca0929
--- /dev/null
+++ b/freebsd/sbin/dhclient/convert.c
@@ -0,0 +1,117 @@
+/* $OpenBSD: convert.c,v 1.5 2004/02/07 11:35:59 henning Exp $ */
+
+/*
+ * Safe copying of option values into and out of the option buffer,
+ * which can't be assumed to be aligned.
+ */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+u_int32_t
+getULong(unsigned char *buf)
+{
+ u_int32_t ibuf;
+
+ memcpy(&ibuf, buf, sizeof(ibuf));
+ return (ntohl(ibuf));
+}
+
+int32_t
+getLong(unsigned char *(buf))
+{
+ int32_t ibuf;
+
+ memcpy(&ibuf, buf, sizeof(ibuf));
+ return (ntohl(ibuf));
+}
+
+u_int16_t
+getUShort(unsigned char *buf)
+{
+ u_int16_t ibuf;
+
+ memcpy(&ibuf, buf, sizeof(ibuf));
+ return (ntohs(ibuf));
+}
+
+int16_t
+getShort(unsigned char *buf)
+{
+ int16_t ibuf;
+
+ memcpy(&ibuf, buf, sizeof(ibuf));
+ return (ntohs(ibuf));
+}
+
+void
+putULong(unsigned char *obuf, u_int32_t val)
+{
+ u_int32_t tmp = htonl(val);
+
+ memcpy(obuf, &tmp, sizeof(tmp));
+}
+
+void
+putLong(unsigned char *obuf, int32_t val)
+{
+ int32_t tmp = htonl(val);
+
+ memcpy(obuf, &tmp, sizeof(tmp));
+}
+
+void
+putUShort(unsigned char *obuf, unsigned int val)
+{
+ u_int16_t tmp = htons(val);
+
+ memcpy(obuf, &tmp, sizeof(tmp));
+}
+
+void
+putShort(unsigned char *obuf, int val)
+{
+ int16_t tmp = htons(val);
+
+ memcpy(obuf, &tmp, sizeof(tmp));
+}
diff --git a/freebsd/sbin/dhclient/dhclient.c b/freebsd/sbin/dhclient/dhclient.c
new file mode 100644
index 00000000..f3c1259d
--- /dev/null
+++ b/freebsd/sbin/dhclient/dhclient.c
@@ -0,0 +1,2669 @@
+/* $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $ */
+
+/*
+ * Copyright 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999
+ * The Internet Software Consortium. 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ *
+ * This client was substantially modified and enhanced by Elliot Poger
+ * for use on Linux while he was working on the MosquitoNet project at
+ * Stanford.
+ *
+ * The current version owes much to Elliot's Linux enhancements, but
+ * was substantially reorganized and partially rewritten by Ted Lemon
+ * so as to use the same networking framework that the Internet Software
+ * Consortium DHCP server uses. Much system-specific configuration code
+ * was moved into a shell script so that as support for more operating
+ * systems is added, it will not be necessary to port and maintain
+ * system-specific configuration code to these operating systems - instead,
+ * the shell script can invoke the native tools to accomplish the same
+ * purpose.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+#include "privsep.h"
+
+#ifdef __rtems__
+#include <freebsd/net80211/ieee80211_freebsd.h>
+#else
+#include <net80211/ieee80211_freebsd.h>
+#endif
+
+#ifndef _PATH_VAREMPTY
+#define _PATH_VAREMPTY "/var/empty"
+#endif
+
+#define PERIOD 0x2e
+#define hyphenchar(c) ((c) == 0x2d)
+#define bslashchar(c) ((c) == 0x5c)
+#define periodchar(c) ((c) == PERIOD)
+#define asterchar(c) ((c) == 0x2a)
+#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
+ ((c) >= 0x61 && (c) <= 0x7a))
+#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+#define whitechar(c) ((c) == ' ' || (c) == '\t')
+
+#define borderchar(c) (alphachar(c) || digitchar(c))
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+#define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
+
+time_t cur_time;
+time_t default_lease_time = 43200; /* 12 hours... */
+
+char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
+char *path_dhclient_db = NULL;
+
+int log_perror = 1;
+int privfd;
+int nullfd = -1;
+
+struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
+struct in_addr inaddr_any;
+struct sockaddr_in sockaddr_broadcast;
+
+/*
+ * ASSERT_STATE() does nothing now; it used to be
+ * assert (state_is == state_shouldbe).
+ */
+#define ASSERT_STATE(state_is, state_shouldbe) {}
+
+#define TIME_MAX 2147483647
+
+int log_priority;
+int no_daemon;
+int unknown_ok = 1;
+int routefd;
+
+struct interface_info *ifi;
+
+int findproto(char *, int);
+struct sockaddr *get_ifa(char *, int);
+void routehandler(struct protocol *);
+void usage(void);
+int check_option(struct client_lease *l, int option);
+int check_classless_option(unsigned char *data, int len);
+int ipv4addrs(char * buf);
+int res_hnok(const char *dn);
+int check_search(const char *srch);
+char *option_as_string(unsigned int code, unsigned char *data, int len);
+int fork_privchld(int, int);
+
+#define ROUNDUP(a) \
+ ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
+#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
+
+static time_t scripttime;
+
+int
+findproto(char *cp, int n)
+{
+ struct sockaddr *sa;
+ int i;
+
+ if (n == 0)
+ return -1;
+ for (i = 1; i; i <<= 1) {
+ if (i & n) {
+ sa = (struct sockaddr *)cp;
+ switch (i) {
+ case RTA_IFA:
+ case RTA_DST:
+ case RTA_GATEWAY:
+ case RTA_NETMASK:
+ if (sa->sa_family == AF_INET)
+ return AF_INET;
+ if (sa->sa_family == AF_INET6)
+ return AF_INET6;
+ break;
+ case RTA_IFP:
+ break;
+ }
+ ADVANCE(cp, sa);
+ }
+ }
+ return (-1);
+}
+
+struct sockaddr *
+get_ifa(char *cp, int n)
+{
+ struct sockaddr *sa;
+ int i;
+
+ if (n == 0)
+ return (NULL);
+ for (i = 1; i; i <<= 1)
+ if (i & n) {
+ sa = (struct sockaddr *)cp;
+ if (i == RTA_IFA)
+ return (sa);
+ ADVANCE(cp, sa);
+ }
+
+ return (NULL);
+}
+
+struct iaddr defaddr = { 4 };
+uint8_t curbssid[6];
+
+static void
+disassoc(void *arg)
+{
+ struct interface_info *ifi = arg;
+
+ /*
+ * Clear existing state.
+ */
+ if (ifi->client->active != NULL) {
+ script_init("EXPIRE", NULL);
+ script_write_params("old_",
+ ifi->client->active);
+ if (ifi->client->alias)
+ script_write_params("alias_",
+ ifi->client->alias);
+ script_go();
+ }
+ ifi->client->state = S_INIT;
+}
+
+/* ARGSUSED */
+void
+routehandler(struct protocol *p)
+{
+ char msg[2048], *addr;
+ struct rt_msghdr *rtm;
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+ struct if_announcemsghdr *ifan;
+ struct ieee80211_join_event *jev;
+ struct client_lease *l;
+ time_t t = time(NULL);
+ struct sockaddr *sa;
+ struct iaddr a;
+ ssize_t n;
+
+ n = read(routefd, &msg, sizeof(msg));
+ rtm = (struct rt_msghdr *)msg;
+ if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
+ rtm->rtm_version != RTM_VERSION)
+ return;
+
+ switch (rtm->rtm_type) {
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ ifam = (struct ifa_msghdr *)rtm;
+
+ if (ifam->ifam_index != ifi->index)
+ break;
+ if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
+ break;
+ if (scripttime == 0 || t < scripttime + 10)
+ break;
+
+ sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
+ if (sa == NULL)
+ break;
+
+ if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
+ error("king bula sez: len mismatch");
+ memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
+ if (addr_eq(a, defaddr))
+ break;
+
+ for (l = ifi->client->active; l != NULL; l = l->next)
+ if (addr_eq(a, l->address))
+ break;
+
+ if (l == NULL) /* added/deleted addr is not the one we set */
+ break;
+
+ addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
+ if (rtm->rtm_type == RTM_NEWADDR) {
+ /*
+ * XXX: If someone other than us adds our address,
+ * should we assume they are taking over from us,
+ * delete the lease record, and exit without modifying
+ * the interface?
+ */
+ warning("My address (%s) was re-added", addr);
+ } else {
+ warning("My address (%s) was deleted, dhclient exiting",
+ addr);
+ goto die;
+ }
+ break;
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)rtm;
+ if (ifm->ifm_index != ifi->index)
+ break;
+ if ((rtm->rtm_flags & RTF_UP) == 0) {
+ warning("Interface %s is down, dhclient exiting",
+ ifi->name);
+ goto die;
+ }
+ break;
+ case RTM_IFANNOUNCE:
+ ifan = (struct if_announcemsghdr *)rtm;
+ if (ifan->ifan_what == IFAN_DEPARTURE &&
+ ifan->ifan_index == ifi->index) {
+ warning("Interface %s is gone, dhclient exiting",
+ ifi->name);
+ goto die;
+ }
+ break;
+ case RTM_IEEE80211:
+ ifan = (struct if_announcemsghdr *)rtm;
+ if (ifan->ifan_index != ifi->index)
+ break;
+ switch (ifan->ifan_what) {
+ case RTM_IEEE80211_ASSOC:
+ case RTM_IEEE80211_REASSOC:
+ /*
+ * Use assoc/reassoc event to kick state machine
+ * in case we roam. Otherwise fall back to the
+ * normal state machine just like a wired network.
+ */
+ jev = (struct ieee80211_join_event *) &ifan[1];
+ if (memcmp(curbssid, jev->iev_addr, 6)) {
+ disassoc(ifi);
+ state_reboot(ifi);
+ }
+ memcpy(curbssid, jev->iev_addr, 6);
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ return;
+
+die:
+ script_init("FAIL", NULL);
+ if (ifi->client->alias)
+ script_write_params("alias_", ifi->client->alias);
+ script_go();
+ exit(1);
+}
+
+int
+main(int argc, char *argv[])
+{
+ extern char *__progname;
+ int ch, fd, quiet = 0, i = 0;
+ int pipe_fd[2];
+ int immediate_daemon = 0;
+ struct passwd *pw;
+
+ /* Initially, log errors to stderr as well as to syslogd. */
+ openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
+ setlogmask(LOG_UPTO(LOG_DEBUG));
+
+ while ((ch = getopt(argc, argv, "bc:dl:qu")) != -1)
+ switch (ch) {
+ case 'b':
+ immediate_daemon = 1;
+ break;
+ case 'c':
+ path_dhclient_conf = optarg;
+ break;
+ case 'd':
+ no_daemon = 1;
+ break;
+ case 'l':
+ path_dhclient_db = optarg;
+ break;
+ case 'q':
+ quiet = 1;
+ break;
+ case 'u':
+ unknown_ok = 0;
+ break;
+ default:
+ usage();
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 1)
+ usage();
+
+ if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
+ error("calloc");
+ if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
+ error("Interface name too long");
+ if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
+ _PATH_DHCLIENT_DB, ifi->name) == -1)
+ error("asprintf");
+
+ if (quiet)
+ log_perror = 0;
+
+ tzset();
+ time(&cur_time);
+
+ memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast));
+ sockaddr_broadcast.sin_family = AF_INET;
+ sockaddr_broadcast.sin_port = htons(REMOTE_PORT);
+ sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
+ sockaddr_broadcast.sin_len = sizeof(sockaddr_broadcast);
+ inaddr_any.s_addr = INADDR_ANY;
+
+ read_client_conf();
+
+ if (!interface_link_status(ifi->name)) {
+ fprintf(stderr, "%s: no link ...", ifi->name);
+ fflush(stderr);
+ sleep(1);
+ while (!interface_link_status(ifi->name)) {
+ fprintf(stderr, ".");
+ fflush(stderr);
+ if (++i > 10) {
+ fprintf(stderr, " giving up\n");
+ exit(1);
+ }
+ sleep(1);
+ }
+ fprintf(stderr, " got link\n");
+ }
+
+ if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
+ error("cannot open %s: %m", _PATH_DEVNULL);
+
+ if ((pw = getpwnam("_dhcp")) == NULL) {
+ warning("no such user: _dhcp, falling back to \"nobody\"");
+ if ((pw = getpwnam("nobody")) == NULL)
+ error("no such user: nobody");
+ }
+
+ if (pipe(pipe_fd) == -1)
+ error("pipe");
+
+ fork_privchld(pipe_fd[0], pipe_fd[1]);
+
+ close(pipe_fd[0]);
+ privfd = pipe_fd[1];
+
+ if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
+ error("can't open and lock %s: %m", path_dhclient_db);
+ read_client_leases();
+ rewrite_client_leases();
+ close(fd);
+
+ priv_script_init("PREINIT", NULL);
+ if (ifi->client->alias)
+ priv_script_write_params("alias_", ifi->client->alias);
+ priv_script_go();
+
+ if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
+ add_protocol("AF_ROUTE", routefd, routehandler, ifi);
+
+ /* set up the interface */
+ discover_interfaces(ifi);
+
+ if (chroot(_PATH_VAREMPTY) == -1)
+ error("chroot");
+ if (chdir("/") == -1)
+ error("chdir(\"/\")");
+
+ if (setgroups(1, &pw->pw_gid) ||
+ setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
+ seteuid(pw->pw_uid) || setuid(pw->pw_uid))
+ error("can't drop privileges: %m");
+
+ endpwent();
+
+ setproctitle("%s", ifi->name);
+
+ if (immediate_daemon)
+ go_daemon();
+
+ ifi->client->state = S_INIT;
+ state_reboot(ifi);
+
+ bootp_packet_handler = do_packet;
+
+ dispatch();
+
+ /* not reached */
+ return (0);
+}
+
+void
+usage(void)
+{
+ extern char *__progname;
+
+ fprintf(stderr, "usage: %s [-bdqu] ", __progname);
+ fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
+ exit(1);
+}
+
+/*
+ * Individual States:
+ *
+ * Each routine is called from the dhclient_state_machine() in one of
+ * these conditions:
+ * -> entering INIT state
+ * -> recvpacket_flag == 0: timeout in this state
+ * -> otherwise: received a packet in this state
+ *
+ * Return conditions as handled by dhclient_state_machine():
+ * Returns 1, sendpacket_flag = 1: send packet, reset timer.
+ * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
+ * Returns 0: finish the nap which was interrupted for no good reason.
+ *
+ * Several per-interface variables are used to keep track of the process:
+ * active_lease: the lease that is being used on the interface
+ * (null pointer if not configured yet).
+ * offered_leases: leases corresponding to DHCPOFFER messages that have
+ * been sent to us by DHCP servers.
+ * acked_leases: leases corresponding to DHCPACK messages that have been
+ * sent to us by DHCP servers.
+ * sendpacket: DHCP packet we're trying to send.
+ * destination: IP address to send sendpacket to
+ * In addition, there are several relevant per-lease variables.
+ * T1_expiry, T2_expiry, lease_expiry: lease milestones
+ * In the active lease, these control the process of renewing the lease;
+ * In leases on the acked_leases list, this simply determines when we
+ * can no longer legitimately use the lease.
+ */
+
+void
+state_reboot(void *ipp)
+{
+ struct interface_info *ip = ipp;
+
+ /* If we don't remember an active lease, go straight to INIT. */
+ if (!ip->client->active || ip->client->active->is_bootp) {
+ state_init(ip);
+ return;
+ }
+
+ /* We are in the rebooting state. */
+ ip->client->state = S_REBOOTING;
+
+ /* make_request doesn't initialize xid because it normally comes
+ from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
+ so pick an xid now. */
+ ip->client->xid = arc4random();
+
+ /* Make a DHCPREQUEST packet, and set appropriate per-interface
+ flags. */
+ make_request(ip, ip->client->active);
+ ip->client->destination = iaddr_broadcast;
+ ip->client->first_sending = cur_time;
+ ip->client->interval = ip->client->config->initial_interval;
+
+ /* Zap the medium list... */
+ ip->client->medium = NULL;
+
+ /* Send out the first DHCPREQUEST packet. */
+ send_request(ip);
+}
+
+/*
+ * Called when a lease has completely expired and we've
+ * been unable to renew it.
+ */
+void
+state_init(void *ipp)
+{
+ struct interface_info *ip = ipp;
+
+ ASSERT_STATE(state, S_INIT);
+
+ /* Make a DHCPDISCOVER packet, and set appropriate per-interface
+ flags. */
+ make_discover(ip, ip->client->active);
+ ip->client->xid = ip->client->packet.xid;
+ ip->client->destination = iaddr_broadcast;
+ ip->client->state = S_SELECTING;
+ ip->client->first_sending = cur_time;
+ ip->client->interval = ip->client->config->initial_interval;
+
+ /* Add an immediate timeout to cause the first DHCPDISCOVER packet
+ to go out. */
+ send_discover(ip);
+}
+
+/*
+ * state_selecting is called when one or more DHCPOFFER packets
+ * have been received and a configurable period of time has passed.
+ */
+void
+state_selecting(void *ipp)
+{
+ struct interface_info *ip = ipp;
+ struct client_lease *lp, *next, *picked;
+
+ ASSERT_STATE(state, S_SELECTING);
+
+ /* Cancel state_selecting and send_discover timeouts, since either
+ one could have got us here. */
+ cancel_timeout(state_selecting, ip);
+ cancel_timeout(send_discover, ip);
+
+ /* We have received one or more DHCPOFFER packets. Currently,
+ the only criterion by which we judge leases is whether or
+ not we get a response when we arp for them. */
+ picked = NULL;
+ for (lp = ip->client->offered_leases; lp; lp = next) {
+ next = lp->next;
+
+ /* Check to see if we got an ARPREPLY for the address
+ in this particular lease. */
+ if (!picked) {
+ script_init("ARPCHECK", lp->medium);
+ script_write_params("check_", lp);
+
+ /* If the ARPCHECK code detects another
+ machine using the offered address, it exits
+ nonzero. We need to send a DHCPDECLINE and
+ toss the lease. */
+ if (script_go()) {
+ make_decline(ip, lp);
+ send_decline(ip);
+ goto freeit;
+ }
+ picked = lp;
+ picked->next = NULL;
+ } else {
+freeit:
+ free_client_lease(lp);
+ }
+ }
+ ip->client->offered_leases = NULL;
+
+ /* If we just tossed all the leases we were offered, go back
+ to square one. */
+ if (!picked) {
+ ip->client->state = S_INIT;
+ state_init(ip);
+ return;
+ }
+
+ /* If it was a BOOTREPLY, we can just take the address right now. */
+ if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
+ ip->client->new = picked;
+
+ /* Make up some lease expiry times
+ XXX these should be configurable. */
+ ip->client->new->expiry = cur_time + 12000;
+ ip->client->new->renewal += cur_time + 8000;
+ ip->client->new->rebind += cur_time + 10000;
+
+ ip->client->state = S_REQUESTING;
+
+ /* Bind to the address we received. */
+ bind_lease(ip);
+ return;
+ }
+
+ /* Go to the REQUESTING state. */
+ ip->client->destination = iaddr_broadcast;
+ ip->client->state = S_REQUESTING;
+ ip->client->first_sending = cur_time;
+ ip->client->interval = ip->client->config->initial_interval;
+
+ /* Make a DHCPREQUEST packet from the lease we picked. */
+ make_request(ip, picked);
+ ip->client->xid = ip->client->packet.xid;
+
+ /* Toss the lease we picked - we'll get it back in a DHCPACK. */
+ free_client_lease(picked);
+
+ /* Add an immediate timeout to send the first DHCPREQUEST packet. */
+ send_request(ip);
+}
+
+/* state_requesting is called when we receive a DHCPACK message after
+ having sent out one or more DHCPREQUEST packets. */
+
+void
+dhcpack(struct packet *packet)
+{
+ struct interface_info *ip = packet->interface;
+ struct client_lease *lease;
+
+ /* If we're not receptive to an offer right now, or if the offer
+ has an unrecognizable transaction id, then just drop it. */
+ if (packet->interface->client->xid != packet->raw->xid ||
+ (packet->interface->hw_address.hlen != packet->raw->hlen) ||
+ (memcmp(packet->interface->hw_address.haddr,
+ packet->raw->chaddr, packet->raw->hlen)))
+ return;
+
+ if (ip->client->state != S_REBOOTING &&
+ ip->client->state != S_REQUESTING &&
+ ip->client->state != S_RENEWING &&
+ ip->client->state != S_REBINDING)
+ return;
+
+ note("DHCPACK from %s", piaddr(packet->client_addr));
+
+ lease = packet_to_lease(packet);
+ if (!lease) {
+ note("packet_to_lease failed.");
+ return;
+ }
+
+ ip->client->new = lease;
+
+ /* Stop resending DHCPREQUEST. */
+ cancel_timeout(send_request, ip);
+
+ /* Figure out the lease time. */
+ if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
+ ip->client->new->expiry = getULong(
+ ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
+ else
+ ip->client->new->expiry = default_lease_time;
+ /* A number that looks negative here is really just very large,
+ because the lease expiry offset is unsigned. */
+ if (ip->client->new->expiry < 0)
+ ip->client->new->expiry = TIME_MAX;
+ /* XXX should be fixed by resetting the client state */
+ if (ip->client->new->expiry < 60)
+ ip->client->new->expiry = 60;
+
+ /* Take the server-provided renewal time if there is one;
+ otherwise figure it out according to the spec. */
+ if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
+ ip->client->new->renewal = getULong(
+ ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
+ else
+ ip->client->new->renewal = ip->client->new->expiry / 2;
+
+ /* Same deal with the rebind time. */
+ if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
+ ip->client->new->rebind = getULong(
+ ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
+ else
+ ip->client->new->rebind = ip->client->new->renewal +
+ ip->client->new->renewal / 2 + ip->client->new->renewal / 4;
+
+ ip->client->new->expiry += cur_time;
+ /* Lease lengths can never be negative. */
+ if (ip->client->new->expiry < cur_time)
+ ip->client->new->expiry = TIME_MAX;
+ ip->client->new->renewal += cur_time;
+ if (ip->client->new->renewal < cur_time)
+ ip->client->new->renewal = TIME_MAX;
+ ip->client->new->rebind += cur_time;
+ if (ip->client->new->rebind < cur_time)
+ ip->client->new->rebind = TIME_MAX;
+
+ bind_lease(ip);
+}
+
+void
+bind_lease(struct interface_info *ip)
+{
+ /* Remember the medium. */
+ ip->client->new->medium = ip->client->medium;
+
+ /* Write out the new lease. */
+ write_client_lease(ip, ip->client->new, 0);
+
+ /* Run the client script with the new parameters. */
+ script_init((ip->client->state == S_REQUESTING ? "BOUND" :
+ (ip->client->state == S_RENEWING ? "RENEW" :
+ (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
+ ip->client->new->medium);
+ if (ip->client->active && ip->client->state != S_REBOOTING)
+ script_write_params("old_", ip->client->active);
+ script_write_params("new_", ip->client->new);
+ if (ip->client->alias)
+ script_write_params("alias_", ip->client->alias);
+ script_go();
+
+ /* Replace the old active lease with the new one. */
+ if (ip->client->active)
+ free_client_lease(ip->client->active);
+ ip->client->active = ip->client->new;
+ ip->client->new = NULL;
+
+ /* Set up a timeout to start the renewal process. */
+ add_timeout(ip->client->active->renewal, state_bound, ip);
+
+ note("bound to %s -- renewal in %d seconds.",
+ piaddr(ip->client->active->address),
+ (int)(ip->client->active->renewal - cur_time));
+ ip->client->state = S_BOUND;
+ reinitialize_interfaces();
+ go_daemon();
+}
+
+/*
+ * state_bound is called when we've successfully bound to a particular
+ * lease, but the renewal time on that lease has expired. We are
+ * expected to unicast a DHCPREQUEST to the server that gave us our
+ * original lease.
+ */
+void
+state_bound(void *ipp)
+{
+ struct interface_info *ip = ipp;
+
+ ASSERT_STATE(state, S_BOUND);
+
+ /* T1 has expired. */
+ make_request(ip, ip->client->active);
+ ip->client->xid = ip->client->packet.xid;
+
+ if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
+ memcpy(ip->client->destination.iabuf, ip->client->active->
+ options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
+ ip->client->destination.len = 4;
+ } else
+ ip->client->destination = iaddr_broadcast;
+
+ ip->client->first_sending = cur_time;
+ ip->client->interval = ip->client->config->initial_interval;
+ ip->client->state = S_RENEWING;
+
+ /* Send the first packet immediately. */
+ send_request(ip);
+}
+
+void
+bootp(struct packet *packet)
+{
+ struct iaddrlist *ap;
+
+ if (packet->raw->op != BOOTREPLY)
+ return;
+
+ /* If there's a reject list, make sure this packet's sender isn't
+ on it. */
+ for (ap = packet->interface->client->config->reject_list;
+ ap; ap = ap->next) {
+ if (addr_eq(packet->client_addr, ap->addr)) {
+ note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
+ return;
+ }
+ }
+ dhcpoffer(packet);
+}
+
+void
+dhcp(struct packet *packet)
+{
+ struct iaddrlist *ap;
+ void (*handler)(struct packet *);
+ char *type;
+
+ switch (packet->packet_type) {
+ case DHCPOFFER:
+ handler = dhcpoffer;
+ type = "DHCPOFFER";
+ break;
+ case DHCPNAK:
+ handler = dhcpnak;
+ type = "DHCPNACK";
+ break;
+ case DHCPACK:
+ handler = dhcpack;
+ type = "DHCPACK";
+ break;
+ default:
+ return;
+ }
+
+ /* If there's a reject list, make sure this packet's sender isn't
+ on it. */
+ for (ap = packet->interface->client->config->reject_list;
+ ap; ap = ap->next) {
+ if (addr_eq(packet->client_addr, ap->addr)) {
+ note("%s from %s rejected.", type, piaddr(ap->addr));
+ return;
+ }
+ }
+ (*handler)(packet);
+}
+
+void
+dhcpoffer(struct packet *packet)
+{
+ struct interface_info *ip = packet->interface;
+ struct client_lease *lease, *lp;
+ int i;
+ int arp_timeout_needed, stop_selecting;
+ char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
+ "DHCPOFFER" : "BOOTREPLY";
+
+ /* If we're not receptive to an offer right now, or if the offer
+ has an unrecognizable transaction id, then just drop it. */
+ if (ip->client->state != S_SELECTING ||
+ packet->interface->client->xid != packet->raw->xid ||
+ (packet->interface->hw_address.hlen != packet->raw->hlen) ||
+ (memcmp(packet->interface->hw_address.haddr,
+ packet->raw->chaddr, packet->raw->hlen)))
+ return;
+
+ note("%s from %s", name, piaddr(packet->client_addr));
+
+
+ /* If this lease doesn't supply the minimum required parameters,
+ blow it off. */
+ for (i = 0; ip->client->config->required_options[i]; i++) {
+ if (!packet->options[ip->client->config->
+ required_options[i]].len) {
+ note("%s isn't satisfactory.", name);
+ return;
+ }
+ }
+
+ /* If we've already seen this lease, don't record it again. */
+ for (lease = ip->client->offered_leases;
+ lease; lease = lease->next) {
+ if (lease->address.len == sizeof(packet->raw->yiaddr) &&
+ !memcmp(lease->address.iabuf,
+ &packet->raw->yiaddr, lease->address.len)) {
+ debug("%s already seen.", name);
+ return;
+ }
+ }
+
+ lease = packet_to_lease(packet);
+ if (!lease) {
+ note("packet_to_lease failed.");
+ return;
+ }
+
+ /* If this lease was acquired through a BOOTREPLY, record that
+ fact. */
+ if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
+ lease->is_bootp = 1;
+
+ /* Record the medium under which this lease was offered. */
+ lease->medium = ip->client->medium;
+
+ /* Send out an ARP Request for the offered IP address. */
+ script_init("ARPSEND", lease->medium);
+ script_write_params("check_", lease);
+ /* If the script can't send an ARP request without waiting,
+ we'll be waiting when we do the ARPCHECK, so don't wait now. */
+ if (script_go())
+ arp_timeout_needed = 0;
+ else
+ arp_timeout_needed = 2;
+
+ /* Figure out when we're supposed to stop selecting. */
+ stop_selecting =
+ ip->client->first_sending + ip->client->config->select_interval;
+
+ /* If this is the lease we asked for, put it at the head of the
+ list, and don't mess with the arp request timeout. */
+ if (lease->address.len == ip->client->requested_address.len &&
+ !memcmp(lease->address.iabuf,
+ ip->client->requested_address.iabuf,
+ ip->client->requested_address.len)) {
+ lease->next = ip->client->offered_leases;
+ ip->client->offered_leases = lease;
+ } else {
+ /* If we already have an offer, and arping for this
+ offer would take us past the selection timeout,
+ then don't extend the timeout - just hope for the
+ best. */
+ if (ip->client->offered_leases &&
+ (cur_time + arp_timeout_needed) > stop_selecting)
+ arp_timeout_needed = 0;
+
+ /* Put the lease at the end of the list. */
+ lease->next = NULL;
+ if (!ip->client->offered_leases)
+ ip->client->offered_leases = lease;
+ else {
+ for (lp = ip->client->offered_leases; lp->next;
+ lp = lp->next)
+ ; /* nothing */
+ lp->next = lease;
+ }
+ }
+
+ /* If we're supposed to stop selecting before we've had time
+ to wait for the ARPREPLY, add some delay to wait for
+ the ARPREPLY. */
+ if (stop_selecting - cur_time < arp_timeout_needed)
+ stop_selecting = cur_time + arp_timeout_needed;
+
+ /* If the selecting interval has expired, go immediately to
+ state_selecting(). Otherwise, time out into
+ state_selecting at the select interval. */
+ if (stop_selecting <= 0)
+ state_selecting(ip);
+ else {
+ add_timeout(stop_selecting, state_selecting, ip);
+ cancel_timeout(send_discover, ip);
+ }
+}
+
+/* Allocate a client_lease structure and initialize it from the parameters
+ in the specified packet. */
+
+struct client_lease *
+packet_to_lease(struct packet *packet)
+{
+ struct client_lease *lease;
+ int i;
+
+ lease = malloc(sizeof(struct client_lease));
+
+ if (!lease) {
+ warning("dhcpoffer: no memory to record lease.");
+ return (NULL);
+ }
+
+ memset(lease, 0, sizeof(*lease));
+
+ /* Copy the lease options. */
+ for (i = 0; i < 256; i++) {
+ if (packet->options[i].len) {
+ lease->options[i].data =
+ malloc(packet->options[i].len + 1);
+ if (!lease->options[i].data) {
+ warning("dhcpoffer: no memory for option %d", i);
+ free_client_lease(lease);
+ return (NULL);
+ } else {
+ memcpy(lease->options[i].data,
+ packet->options[i].data,
+ packet->options[i].len);
+ lease->options[i].len =
+ packet->options[i].len;
+ lease->options[i].data[lease->options[i].len] =
+ 0;
+ }
+ if (!check_option(lease,i)) {
+ /* ignore a bogus lease offer */
+ warning("Invalid lease option - ignoring offer");
+ free_client_lease(lease);
+ return (NULL);
+ }
+ }
+ }
+
+ lease->address.len = sizeof(packet->raw->yiaddr);
+ memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
+
+ /* If the server name was filled out, copy it.
+ Do not attempt to validate the server name as a host name.
+ RFC 2131 merely states that sname is NUL-terminated (which do
+ do not assume) and that it is the server's host name. Since
+ the ISC client and server allow arbitrary characters, we do
+ as well. */
+ if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
+ !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
+ packet->raw->sname[0]) {
+ lease->server_name = malloc(DHCP_SNAME_LEN + 1);
+ if (!lease->server_name) {
+ warning("dhcpoffer: no memory for server name.");
+ free_client_lease(lease);
+ return (NULL);
+ }
+ memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
+ lease->server_name[DHCP_SNAME_LEN]='\0';
+ }
+
+ /* Ditto for the filename. */
+ if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
+ !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
+ packet->raw->file[0]) {
+ /* Don't count on the NUL terminator. */
+ lease->filename = malloc(DHCP_FILE_LEN + 1);
+ if (!lease->filename) {
+ warning("dhcpoffer: no memory for filename.");
+ free_client_lease(lease);
+ return (NULL);
+ }
+ memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
+ lease->filename[DHCP_FILE_LEN]='\0';
+ }
+ return lease;
+}
+
+void
+dhcpnak(struct packet *packet)
+{
+ struct interface_info *ip = packet->interface;
+
+ /* If we're not receptive to an offer right now, or if the offer
+ has an unrecognizable transaction id, then just drop it. */
+ if (packet->interface->client->xid != packet->raw->xid ||
+ (packet->interface->hw_address.hlen != packet->raw->hlen) ||
+ (memcmp(packet->interface->hw_address.haddr,
+ packet->raw->chaddr, packet->raw->hlen)))
+ return;
+
+ if (ip->client->state != S_REBOOTING &&
+ ip->client->state != S_REQUESTING &&
+ ip->client->state != S_RENEWING &&
+ ip->client->state != S_REBINDING)
+ return;
+
+ note("DHCPNAK from %s", piaddr(packet->client_addr));
+
+ if (!ip->client->active) {
+ note("DHCPNAK with no active lease.\n");
+ return;
+ }
+
+ free_client_lease(ip->client->active);
+ ip->client->active = NULL;
+
+ /* Stop sending DHCPREQUEST packets... */
+ cancel_timeout(send_request, ip);
+
+ ip->client->state = S_INIT;
+ state_init(ip);
+}
+
+/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
+ one after the right interval has expired. If we don't get an offer by
+ the time we reach the panic interval, call the panic function. */
+
+void
+send_discover(void *ipp)
+{
+ struct interface_info *ip = ipp;
+ int interval, increase = 1;
+
+ /* Figure out how long it's been since we started transmitting. */
+ interval = cur_time - ip->client->first_sending;
+
+ /* If we're past the panic timeout, call the script and tell it
+ we haven't found anything for this interface yet. */
+ if (interval > ip->client->config->timeout) {
+ state_panic(ip);
+ return;
+ }
+
+ /* If we're selecting media, try the whole list before doing
+ the exponential backoff, but if we've already received an
+ offer, stop looping, because we obviously have it right. */
+ if (!ip->client->offered_leases &&
+ ip->client->config->media) {
+ int fail = 0;
+again:
+ if (ip->client->medium) {
+ ip->client->medium = ip->client->medium->next;
+ increase = 0;
+ }
+ if (!ip->client->medium) {
+ if (fail)
+ error("No valid media types for %s!", ip->name);
+ ip->client->medium = ip->client->config->media;
+ increase = 1;
+ }
+
+ note("Trying medium \"%s\" %d", ip->client->medium->string,
+ increase);
+ script_init("MEDIUM", ip->client->medium);
+ if (script_go())
+ goto again;
+ }
+
+ /*
+ * If we're supposed to increase the interval, do so. If it's
+ * currently zero (i.e., we haven't sent any packets yet), set
+ * it to one; otherwise, add to it a random number between zero
+ * and two times itself. On average, this means that it will
+ * double with every transmission.
+ */
+ if (increase) {
+ if (!ip->client->interval)
+ ip->client->interval =
+ ip->client->config->initial_interval;
+ else {
+ ip->client->interval += (arc4random() >> 2) %
+ (2 * ip->client->interval);
+ }
+
+ /* Don't backoff past cutoff. */
+ if (ip->client->interval >
+ ip->client->config->backoff_cutoff)
+ ip->client->interval =
+ ((ip->client->config->backoff_cutoff / 2)
+ + ((arc4random() >> 2) %
+ ip->client->config->backoff_cutoff));
+ } else if (!ip->client->interval)
+ ip->client->interval =
+ ip->client->config->initial_interval;
+
+ /* If the backoff would take us to the panic timeout, just use that
+ as the interval. */
+ if (cur_time + ip->client->interval >
+ ip->client->first_sending + ip->client->config->timeout)
+ ip->client->interval =
+ (ip->client->first_sending +
+ ip->client->config->timeout) - cur_time + 1;
+
+ /* Record the number of seconds since we started sending. */
+ if (interval < 65536)
+ ip->client->packet.secs = htons(interval);
+ else
+ ip->client->packet.secs = htons(65535);
+ ip->client->secs = ip->client->packet.secs;
+
+ note("DHCPDISCOVER on %s to %s port %d interval %d",
+ ip->name, inet_ntoa(sockaddr_broadcast.sin_addr),
+ ntohs(sockaddr_broadcast.sin_port),
+ (int)ip->client->interval);
+
+ /* Send out a packet. */
+ (void)send_packet(ip, &ip->client->packet, ip->client->packet_length,
+ inaddr_any, &sockaddr_broadcast, NULL);
+
+ add_timeout(cur_time + ip->client->interval, send_discover, ip);
+}
+
+/*
+ * state_panic gets called if we haven't received any offers in a preset
+ * amount of time. When this happens, we try to use existing leases
+ * that haven't yet expired, and failing that, we call the client script
+ * and hope it can do something.
+ */
+void
+state_panic(void *ipp)
+{
+ struct interface_info *ip = ipp;
+ struct client_lease *loop = ip->client->active;
+ struct client_lease *lp;
+
+ note("No DHCPOFFERS received.");
+
+ /* We may not have an active lease, but we may have some
+ predefined leases that we can try. */
+ if (!ip->client->active && ip->client->leases)
+ goto activate_next;
+
+ /* Run through the list of leases and see if one can be used. */
+ while (ip->client->active) {
+ if (ip->client->active->expiry > cur_time) {
+ note("Trying recorded lease %s",
+ piaddr(ip->client->active->address));
+ /* Run the client script with the existing
+ parameters. */
+ script_init("TIMEOUT",
+ ip->client->active->medium);
+ script_write_params("new_", ip->client->active);
+ if (ip->client->alias)
+ script_write_params("alias_",
+ ip->client->alias);
+
+ /* If the old lease is still good and doesn't
+ yet need renewal, go into BOUND state and
+ timeout at the renewal time. */
+ if (!script_go()) {
+ if (cur_time <
+ ip->client->active->renewal) {
+ ip->client->state = S_BOUND;
+ note("bound: renewal in %d seconds.",
+ (int)(ip->client->active->renewal -
+ cur_time));
+ add_timeout(
+ ip->client->active->renewal,
+ state_bound, ip);
+ } else {
+ ip->client->state = S_BOUND;
+ note("bound: immediate renewal.");
+ state_bound(ip);
+ }
+ reinitialize_interfaces();
+ go_daemon();
+ return;
+ }
+ }
+
+ /* If there are no other leases, give up. */
+ if (!ip->client->leases) {
+ ip->client->leases = ip->client->active;
+ ip->client->active = NULL;
+ break;
+ }
+
+activate_next:
+ /* Otherwise, put the active lease at the end of the
+ lease list, and try another lease.. */
+ for (lp = ip->client->leases; lp->next; lp = lp->next)
+ ;
+ lp->next = ip->client->active;
+ if (lp->next)
+ lp->next->next = NULL;
+ ip->client->active = ip->client->leases;
+ ip->client->leases = ip->client->leases->next;
+
+ /* If we already tried this lease, we've exhausted the
+ set of leases, so we might as well give up for
+ now. */
+ if (ip->client->active == loop)
+ break;
+ else if (!loop)
+ loop = ip->client->active;
+ }
+
+ /* No leases were available, or what was available didn't work, so
+ tell the shell script that we failed to allocate an address,
+ and try again later. */
+ note("No working leases in persistent database - sleeping.\n");
+ script_init("FAIL", NULL);
+ if (ip->client->alias)
+ script_write_params("alias_", ip->client->alias);
+ script_go();
+ ip->client->state = S_INIT;
+ add_timeout(cur_time + ip->client->config->retry_interval, state_init,
+ ip);
+ go_daemon();
+}
+
+void
+send_request(void *ipp)
+{
+ struct interface_info *ip = ipp;
+ struct sockaddr_in destination;
+ struct in_addr from;
+ int interval;
+
+ /* Figure out how long it's been since we started transmitting. */
+ interval = cur_time - ip->client->first_sending;
+
+ /* If we're in the INIT-REBOOT or REQUESTING state and we're
+ past the reboot timeout, go to INIT and see if we can
+ DISCOVER an address... */
+ /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
+ means either that we're on a network with no DHCP server,
+ or that our server is down. In the latter case, assuming
+ that there is a backup DHCP server, DHCPDISCOVER will get
+ us a new address, but we could also have successfully
+ reused our old address. In the former case, we're hosed
+ anyway. This is not a win-prone situation. */
+ if ((ip->client->state == S_REBOOTING ||
+ ip->client->state == S_REQUESTING) &&
+ interval > ip->client->config->reboot_timeout) {
+cancel:
+ ip->client->state = S_INIT;
+ cancel_timeout(send_request, ip);
+ state_init(ip);
+ return;
+ }
+
+ /* If we're in the reboot state, make sure the media is set up
+ correctly. */
+ if (ip->client->state == S_REBOOTING &&
+ !ip->client->medium &&
+ ip->client->active->medium ) {
+ script_init("MEDIUM", ip->client->active->medium);
+
+ /* If the medium we chose won't fly, go to INIT state. */
+ if (script_go())
+ goto cancel;
+
+ /* Record the medium. */
+ ip->client->medium = ip->client->active->medium;
+ }
+
+ /* If the lease has expired, relinquish the address and go back
+ to the INIT state. */
+ if (ip->client->state != S_REQUESTING &&
+ cur_time > ip->client->active->expiry) {
+ /* Run the client script with the new parameters. */
+ script_init("EXPIRE", NULL);
+ script_write_params("old_", ip->client->active);
+ if (ip->client->alias)
+ script_write_params("alias_", ip->client->alias);
+ script_go();
+
+ /* Now do a preinit on the interface so that we can
+ discover a new address. */
+ script_init("PREINIT", NULL);
+ if (ip->client->alias)
+ script_write_params("alias_", ip->client->alias);
+ script_go();
+
+ ip->client->state = S_INIT;
+ state_init(ip);
+ return;
+ }
+
+ /* Do the exponential backoff... */
+ if (!ip->client->interval)
+ ip->client->interval = ip->client->config->initial_interval;
+ else
+ ip->client->interval += ((arc4random() >> 2) %
+ (2 * ip->client->interval));
+
+ /* Don't backoff past cutoff. */
+ if (ip->client->interval >
+ ip->client->config->backoff_cutoff)
+ ip->client->interval =
+ ((ip->client->config->backoff_cutoff / 2) +
+ ((arc4random() >> 2) % ip->client->interval));
+
+ /* If the backoff would take us to the expiry time, just set the
+ timeout to the expiry time. */
+ if (ip->client->state != S_REQUESTING &&
+ cur_time + ip->client->interval >
+ ip->client->active->expiry)
+ ip->client->interval =
+ ip->client->active->expiry - cur_time + 1;
+
+ /* If the lease T2 time has elapsed, or if we're not yet bound,
+ broadcast the DHCPREQUEST rather than unicasting. */
+ memset(&destination, 0, sizeof(destination));
+ if (ip->client->state == S_REQUESTING ||
+ ip->client->state == S_REBOOTING ||
+ cur_time > ip->client->active->rebind)
+ destination.sin_addr.s_addr = INADDR_BROADCAST;
+ else
+ memcpy(&destination.sin_addr.s_addr,
+ ip->client->destination.iabuf,
+ sizeof(destination.sin_addr.s_addr));
+ destination.sin_port = htons(REMOTE_PORT);
+ destination.sin_family = AF_INET;
+ destination.sin_len = sizeof(destination);
+
+ if (ip->client->state != S_REQUESTING)
+ memcpy(&from, ip->client->active->address.iabuf,
+ sizeof(from));
+ else
+ from.s_addr = INADDR_ANY;
+
+ /* Record the number of seconds since we started sending. */
+ if (ip->client->state == S_REQUESTING)
+ ip->client->packet.secs = ip->client->secs;
+ else {
+ if (interval < 65536)
+ ip->client->packet.secs = htons(interval);
+ else
+ ip->client->packet.secs = htons(65535);
+ }
+
+ note("DHCPREQUEST on %s to %s port %d", ip->name,
+ inet_ntoa(destination.sin_addr), ntohs(destination.sin_port));
+
+ /* Send out a packet. */
+ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length,
+ from, &destination, NULL);
+
+ add_timeout(cur_time + ip->client->interval, send_request, ip);
+}
+
+void
+send_decline(void *ipp)
+{
+ struct interface_info *ip = ipp;
+
+ note("DHCPDECLINE on %s to %s port %d", ip->name,
+ inet_ntoa(sockaddr_broadcast.sin_addr),
+ ntohs(sockaddr_broadcast.sin_port));
+
+ /* Send out a packet. */
+ (void) send_packet(ip, &ip->client->packet, ip->client->packet_length,
+ inaddr_any, &sockaddr_broadcast, NULL);
+}
+
+void
+make_discover(struct interface_info *ip, struct client_lease *lease)
+{
+ unsigned char discover = DHCPDISCOVER;
+ struct tree_cache *options[256];
+ struct tree_cache option_elements[256];
+ int i;
+
+ memset(option_elements, 0, sizeof(option_elements));
+ memset(options, 0, sizeof(options));
+ memset(&ip->client->packet, 0, sizeof(ip->client->packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options[i] = &option_elements[i];
+ options[i]->value = &discover;
+ options[i]->len = sizeof(discover);
+ options[i]->buf_size = sizeof(discover);
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Request the options we want */
+ i = DHO_DHCP_PARAMETER_REQUEST_LIST;
+ options[i] = &option_elements[i];
+ options[i]->value = ip->client->config->requested_options;
+ options[i]->len = ip->client->config->requested_option_count;
+ options[i]->buf_size =
+ ip->client->config->requested_option_count;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* If we had an address, try to get it again. */
+ if (lease) {
+ ip->client->requested_address = lease->address;
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options[i] = &option_elements[i];
+ options[i]->value = lease->address.iabuf;
+ options[i]->len = lease->address.len;
+ options[i]->buf_size = lease->address.len;
+ options[i]->timeout = 0xFFFFFFFF;
+ } else
+ ip->client->requested_address.len = 0;
+
+ /* Send any options requested in the config file. */
+ for (i = 0; i < 256; i++)
+ if (!options[i] &&
+ ip->client->config->send_options[i].data) {
+ options[i] = &option_elements[i];
+ options[i]->value =
+ ip->client->config->send_options[i].data;
+ options[i]->len =
+ ip->client->config->send_options[i].len;
+ options[i]->buf_size =
+ ip->client->config->send_options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+
+ /* send host name if not set via config file. */
+ char hostname[_POSIX_HOST_NAME_MAX+1];
+ if (!options[DHO_HOST_NAME]) {
+ if (gethostname(hostname, sizeof(hostname)) == 0) {
+ size_t len;
+ char* posDot = strchr(hostname, '.');
+ if (posDot != NULL)
+ len = posDot - hostname;
+ else
+ len = strlen(hostname);
+ options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
+ options[DHO_HOST_NAME]->value = hostname;
+ options[DHO_HOST_NAME]->len = len;
+ options[DHO_HOST_NAME]->buf_size = len;
+ options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
+ }
+ }
+
+ /* set unique client identifier */
+ char client_ident[sizeof(struct hardware)];
+ if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
+ int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
+ ip->hw_address.hlen : sizeof(client_ident)-1;
+ client_ident[0] = ip->hw_address.htype;
+ memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
+ options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
+ }
+
+ /* Set up the option buffer... */
+ ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
+ options, 0, 0, 0, NULL, 0);
+ if (ip->client->packet_length < BOOTP_MIN_LEN)
+ ip->client->packet_length = BOOTP_MIN_LEN;
+
+ ip->client->packet.op = BOOTREQUEST;
+ ip->client->packet.htype = ip->hw_address.htype;
+ ip->client->packet.hlen = ip->hw_address.hlen;
+ ip->client->packet.hops = 0;
+ ip->client->packet.xid = arc4random();
+ ip->client->packet.secs = 0; /* filled in by send_discover. */
+ ip->client->packet.flags = 0;
+
+ memset(&(ip->client->packet.ciaddr),
+ 0, sizeof(ip->client->packet.ciaddr));
+ memset(&(ip->client->packet.yiaddr),
+ 0, sizeof(ip->client->packet.yiaddr));
+ memset(&(ip->client->packet.siaddr),
+ 0, sizeof(ip->client->packet.siaddr));
+ memset(&(ip->client->packet.giaddr),
+ 0, sizeof(ip->client->packet.giaddr));
+ memcpy(ip->client->packet.chaddr,
+ ip->hw_address.haddr, ip->hw_address.hlen);
+}
+
+
+void
+make_request(struct interface_info *ip, struct client_lease * lease)
+{
+ unsigned char request = DHCPREQUEST;
+ struct tree_cache *options[256];
+ struct tree_cache option_elements[256];
+ int i;
+
+ memset(options, 0, sizeof(options));
+ memset(&ip->client->packet, 0, sizeof(ip->client->packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options[i] = &option_elements[i];
+ options[i]->value = &request;
+ options[i]->len = sizeof(request);
+ options[i]->buf_size = sizeof(request);
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Request the options we want */
+ i = DHO_DHCP_PARAMETER_REQUEST_LIST;
+ options[i] = &option_elements[i];
+ options[i]->value = ip->client->config->requested_options;
+ options[i]->len = ip->client->config->requested_option_count;
+ options[i]->buf_size =
+ ip->client->config->requested_option_count;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* If we are requesting an address that hasn't yet been assigned
+ to us, use the DHCP Requested Address option. */
+ if (ip->client->state == S_REQUESTING) {
+ /* Send back the server identifier... */
+ i = DHO_DHCP_SERVER_IDENTIFIER;
+ options[i] = &option_elements[i];
+ options[i]->value = lease->options[i].data;
+ options[i]->len = lease->options[i].len;
+ options[i]->buf_size = lease->options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+ if (ip->client->state == S_REQUESTING ||
+ ip->client->state == S_REBOOTING) {
+ ip->client->requested_address = lease->address;
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options[i] = &option_elements[i];
+ options[i]->value = lease->address.iabuf;
+ options[i]->len = lease->address.len;
+ options[i]->buf_size = lease->address.len;
+ options[i]->timeout = 0xFFFFFFFF;
+ } else
+ ip->client->requested_address.len = 0;
+
+ /* Send any options requested in the config file. */
+ for (i = 0; i < 256; i++)
+ if (!options[i] &&
+ ip->client->config->send_options[i].data) {
+ options[i] = &option_elements[i];
+ options[i]->value =
+ ip->client->config->send_options[i].data;
+ options[i]->len =
+ ip->client->config->send_options[i].len;
+ options[i]->buf_size =
+ ip->client->config->send_options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+
+ /* send host name if not set via config file. */
+ char hostname[_POSIX_HOST_NAME_MAX+1];
+ if (!options[DHO_HOST_NAME]) {
+ if (gethostname(hostname, sizeof(hostname)) == 0) {
+ size_t len;
+ char* posDot = strchr(hostname, '.');
+ if (posDot != NULL)
+ len = posDot - hostname;
+ else
+ len = strlen(hostname);
+ options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
+ options[DHO_HOST_NAME]->value = hostname;
+ options[DHO_HOST_NAME]->len = len;
+ options[DHO_HOST_NAME]->buf_size = len;
+ options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
+ }
+ }
+
+ /* set unique client identifier */
+ char client_ident[sizeof(struct hardware)];
+ if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
+ int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
+ ip->hw_address.hlen : sizeof(client_ident)-1;
+ client_ident[0] = ip->hw_address.htype;
+ memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
+ options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
+ options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
+ }
+
+ /* Set up the option buffer... */
+ ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
+ options, 0, 0, 0, NULL, 0);
+ if (ip->client->packet_length < BOOTP_MIN_LEN)
+ ip->client->packet_length = BOOTP_MIN_LEN;
+
+ ip->client->packet.op = BOOTREQUEST;
+ ip->client->packet.htype = ip->hw_address.htype;
+ ip->client->packet.hlen = ip->hw_address.hlen;
+ ip->client->packet.hops = 0;
+ ip->client->packet.xid = ip->client->xid;
+ ip->client->packet.secs = 0; /* Filled in by send_request. */
+
+ /* If we own the address we're requesting, put it in ciaddr;
+ otherwise set ciaddr to zero. */
+ if (ip->client->state == S_BOUND ||
+ ip->client->state == S_RENEWING ||
+ ip->client->state == S_REBINDING) {
+ memcpy(&ip->client->packet.ciaddr,
+ lease->address.iabuf, lease->address.len);
+ ip->client->packet.flags = 0;
+ } else {
+ memset(&ip->client->packet.ciaddr, 0,
+ sizeof(ip->client->packet.ciaddr));
+ ip->client->packet.flags = 0;
+ }
+
+ memset(&ip->client->packet.yiaddr, 0,
+ sizeof(ip->client->packet.yiaddr));
+ memset(&ip->client->packet.siaddr, 0,
+ sizeof(ip->client->packet.siaddr));
+ memset(&ip->client->packet.giaddr, 0,
+ sizeof(ip->client->packet.giaddr));
+ memcpy(ip->client->packet.chaddr,
+ ip->hw_address.haddr, ip->hw_address.hlen);
+}
+
+void
+make_decline(struct interface_info *ip, struct client_lease *lease)
+{
+ struct tree_cache *options[256], message_type_tree;
+ struct tree_cache requested_address_tree;
+ struct tree_cache server_id_tree, client_id_tree;
+ unsigned char decline = DHCPDECLINE;
+ int i;
+
+ memset(options, 0, sizeof(options));
+ memset(&ip->client->packet, 0, sizeof(ip->client->packet));
+
+ /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
+ i = DHO_DHCP_MESSAGE_TYPE;
+ options[i] = &message_type_tree;
+ options[i]->value = &decline;
+ options[i]->len = sizeof(decline);
+ options[i]->buf_size = sizeof(decline);
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Send back the server identifier... */
+ i = DHO_DHCP_SERVER_IDENTIFIER;
+ options[i] = &server_id_tree;
+ options[i]->value = lease->options[i].data;
+ options[i]->len = lease->options[i].len;
+ options[i]->buf_size = lease->options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Send back the address we're declining. */
+ i = DHO_DHCP_REQUESTED_ADDRESS;
+ options[i] = &requested_address_tree;
+ options[i]->value = lease->address.iabuf;
+ options[i]->len = lease->address.len;
+ options[i]->buf_size = lease->address.len;
+ options[i]->timeout = 0xFFFFFFFF;
+
+ /* Send the uid if the user supplied one. */
+ i = DHO_DHCP_CLIENT_IDENTIFIER;
+ if (ip->client->config->send_options[i].len) {
+ options[i] = &client_id_tree;
+ options[i]->value = ip->client->config->send_options[i].data;
+ options[i]->len = ip->client->config->send_options[i].len;
+ options[i]->buf_size = ip->client->config->send_options[i].len;
+ options[i]->timeout = 0xFFFFFFFF;
+ }
+
+
+ /* Set up the option buffer... */
+ ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
+ options, 0, 0, 0, NULL, 0);
+ if (ip->client->packet_length < BOOTP_MIN_LEN)
+ ip->client->packet_length = BOOTP_MIN_LEN;
+
+ ip->client->packet.op = BOOTREQUEST;
+ ip->client->packet.htype = ip->hw_address.htype;
+ ip->client->packet.hlen = ip->hw_address.hlen;
+ ip->client->packet.hops = 0;
+ ip->client->packet.xid = ip->client->xid;
+ ip->client->packet.secs = 0; /* Filled in by send_request. */
+ ip->client->packet.flags = 0;
+
+ /* ciaddr must always be zero. */
+ memset(&ip->client->packet.ciaddr, 0,
+ sizeof(ip->client->packet.ciaddr));
+ memset(&ip->client->packet.yiaddr, 0,
+ sizeof(ip->client->packet.yiaddr));
+ memset(&ip->client->packet.siaddr, 0,
+ sizeof(ip->client->packet.siaddr));
+ memset(&ip->client->packet.giaddr, 0,
+ sizeof(ip->client->packet.giaddr));
+ memcpy(ip->client->packet.chaddr,
+ ip->hw_address.haddr, ip->hw_address.hlen);
+}
+
+void
+free_client_lease(struct client_lease *lease)
+{
+ int i;
+
+ if (lease->server_name)
+ free(lease->server_name);
+ if (lease->filename)
+ free(lease->filename);
+ for (i = 0; i < 256; i++) {
+ if (lease->options[i].len)
+ free(lease->options[i].data);
+ }
+ free(lease);
+}
+
+FILE *leaseFile;
+
+void
+rewrite_client_leases(void)
+{
+ struct client_lease *lp;
+
+ if (!leaseFile) {
+ leaseFile = fopen(path_dhclient_db, "w");
+ if (!leaseFile)
+ error("can't create %s: %m", path_dhclient_db);
+ } else {
+ fflush(leaseFile);
+ rewind(leaseFile);
+ }
+
+ for (lp = ifi->client->leases; lp; lp = lp->next)
+ write_client_lease(ifi, lp, 1);
+ if (ifi->client->active)
+ write_client_lease(ifi, ifi->client->active, 1);
+
+ fflush(leaseFile);
+ ftruncate(fileno(leaseFile), ftello(leaseFile));
+ fsync(fileno(leaseFile));
+}
+
+void
+write_client_lease(struct interface_info *ip, struct client_lease *lease,
+ int rewrite)
+{
+ static int leases_written;
+ struct tm *t;
+ int i;
+
+ if (!rewrite) {
+ if (leases_written++ > 20) {
+ rewrite_client_leases();
+ leases_written = 0;
+ }
+ }
+
+ /* If the lease came from the config file, we don't need to stash
+ a copy in the lease database. */
+ if (lease->is_static)
+ return;
+
+ if (!leaseFile) { /* XXX */
+ leaseFile = fopen(path_dhclient_db, "w");
+ if (!leaseFile)
+ error("can't create %s: %m", path_dhclient_db);
+ }
+
+ fprintf(leaseFile, "lease {\n");
+ if (lease->is_bootp)
+ fprintf(leaseFile, " bootp;\n");
+ fprintf(leaseFile, " interface \"%s\";\n", ip->name);
+ fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
+ if (lease->filename)
+ fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
+ if (lease->server_name)
+ fprintf(leaseFile, " server-name \"%s\";\n",
+ lease->server_name);
+ if (lease->medium)
+ fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
+ for (i = 0; i < 256; i++)
+ if (lease->options[i].len)
+ fprintf(leaseFile, " option %s %s;\n",
+ dhcp_options[i].name,
+ pretty_print_option(i, lease->options[i].data,
+ lease->options[i].len, 1, 1));
+
+ t = gmtime(&lease->renewal);
+ fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
+ t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ t = gmtime(&lease->rebind);
+ fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
+ t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ t = gmtime(&lease->expiry);
+ fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
+ t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec);
+ fprintf(leaseFile, "}\n");
+ fflush(leaseFile);
+}
+
+void
+script_init(char *reason, struct string_list *medium)
+{
+ size_t len, mediumlen = 0;
+ struct imsg_hdr hdr;
+ struct buf *buf;
+ int errs;
+
+ if (medium != NULL && medium->string != NULL)
+ mediumlen = strlen(medium->string);
+
+ hdr.code = IMSG_SCRIPT_INIT;
+ hdr.len = sizeof(struct imsg_hdr) +
+ sizeof(size_t) + mediumlen +
+ sizeof(size_t) + strlen(reason);
+
+ if ((buf = buf_open(hdr.len)) == NULL)
+ error("buf_open: %m");
+
+ errs = 0;
+ errs += buf_add(buf, &hdr, sizeof(hdr));
+ errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
+ if (mediumlen > 0)
+ errs += buf_add(buf, medium->string, mediumlen);
+ len = strlen(reason);
+ errs += buf_add(buf, &len, sizeof(len));
+ errs += buf_add(buf, reason, len);
+
+ if (errs)
+ error("buf_add: %m");
+
+ if (buf_close(privfd, buf) == -1)
+ error("buf_close: %m");
+}
+
+void
+priv_script_init(char *reason, char *medium)
+{
+ struct interface_info *ip = ifi;
+
+ if (ip) {
+ ip->client->scriptEnvsize = 100;
+ if (ip->client->scriptEnv == NULL)
+ ip->client->scriptEnv =
+ malloc(ip->client->scriptEnvsize * sizeof(char *));
+ if (ip->client->scriptEnv == NULL)
+ error("script_init: no memory for environment");
+
+ ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
+ if (ip->client->scriptEnv[0] == NULL)
+ error("script_init: no memory for environment");
+
+ ip->client->scriptEnv[1] = NULL;
+
+ script_set_env(ip->client, "", "interface", ip->name);
+
+ if (medium)
+ script_set_env(ip->client, "", "medium", medium);
+
+ script_set_env(ip->client, "", "reason", reason);
+ }
+}
+
+void
+priv_script_write_params(char *prefix, struct client_lease *lease)
+{
+ struct interface_info *ip = ifi;
+ u_int8_t dbuf[1500], *dp = NULL;
+ int i, len;
+ char tbuf[128];
+
+ script_set_env(ip->client, prefix, "ip_address",
+ piaddr(lease->address));
+
+ if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
+ ACTION_SUPERSEDE) {
+ dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
+ len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
+ } else {
+ dp = lease->options[DHO_SUBNET_MASK].data;
+ len = lease->options[DHO_SUBNET_MASK].len;
+ }
+ if (len && (len < sizeof(lease->address.iabuf))) {
+ struct iaddr netmask, subnet, broadcast;
+
+ memcpy(netmask.iabuf, dp, len);
+ netmask.len = len;
+ subnet = subnet_number(lease->address, netmask);
+ if (subnet.len) {
+ script_set_env(ip->client, prefix, "network_number",
+ piaddr(subnet));
+ if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
+ broadcast = broadcast_addr(subnet, netmask);
+ if (broadcast.len)
+ script_set_env(ip->client, prefix,
+ "broadcast_address",
+ piaddr(broadcast));
+ }
+ }
+ }
+
+ if (lease->filename)
+ script_set_env(ip->client, prefix, "filename", lease->filename);
+ if (lease->server_name)
+ script_set_env(ip->client, prefix, "server_name",
+ lease->server_name);
+ for (i = 0; i < 256; i++) {
+ len = 0;
+
+ if (ip->client->config->defaults[i].len) {
+ if (lease->options[i].len) {
+ switch (
+ ip->client->config->default_actions[i]) {
+ case ACTION_DEFAULT:
+ dp = lease->options[i].data;
+ len = lease->options[i].len;
+ break;
+ case ACTION_SUPERSEDE:
+supersede:
+ dp = ip->client->
+ config->defaults[i].data;
+ len = ip->client->
+ config->defaults[i].len;
+ break;
+ case ACTION_PREPEND:
+ len = ip->client->
+ config->defaults[i].len +
+ lease->options[i].len;
+ if (len >= sizeof(dbuf)) {
+ warning("no space to %s %s",
+ "prepend option",
+ dhcp_options[i].name);
+ goto supersede;
+ }
+ dp = dbuf;
+ memcpy(dp,
+ ip->client->
+ config->defaults[i].data,
+ ip->client->
+ config->defaults[i].len);
+ memcpy(dp + ip->client->
+ config->defaults[i].len,
+ lease->options[i].data,
+ lease->options[i].len);
+ dp[len] = '\0';
+ break;
+ case ACTION_APPEND:
+ /*
+ * When we append, we assume that we're
+ * appending to text. Some MS servers
+ * include a NUL byte at the end of
+ * the search string provided.
+ */
+ len = ip->client->
+ config->defaults[i].len +
+ lease->options[i].len;
+ if (len >= sizeof(dbuf)) {
+ warning("no space to %s %s",
+ "append option",
+ dhcp_options[i].name);
+ goto supersede;
+ }
+ memcpy(dbuf,
+ lease->options[i].data,
+ lease->options[i].len);
+ for (dp = dbuf + lease->options[i].len;
+ dp > dbuf; dp--, len--)
+ if (dp[-1] != '\0')
+ break;
+ memcpy(dp,
+ ip->client->
+ config->defaults[i].data,
+ ip->client->
+ config->defaults[i].len);
+ dp = dbuf;
+ dp[len] = '\0';
+ }
+ } else {
+ dp = ip->client->
+ config->defaults[i].data;
+ len = ip->client->
+ config->defaults[i].len;
+ }
+ } else if (lease->options[i].len) {
+ len = lease->options[i].len;
+ dp = lease->options[i].data;
+ } else {
+ len = 0;
+ }
+ if (len) {
+ char name[256];
+
+ if (dhcp_option_ev_name(name, sizeof(name),
+ &dhcp_options[i]))
+ script_set_env(ip->client, prefix, name,
+ pretty_print_option(i, dp, len, 0, 0));
+ }
+ }
+ snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
+ script_set_env(ip->client, prefix, "expiry", tbuf);
+}
+
+void
+script_write_params(char *prefix, struct client_lease *lease)
+{
+ size_t fn_len = 0, sn_len = 0, pr_len = 0;
+ struct imsg_hdr hdr;
+ struct buf *buf;
+ int errs, i;
+
+ if (lease->filename != NULL)
+ fn_len = strlen(lease->filename);
+ if (lease->server_name != NULL)
+ sn_len = strlen(lease->server_name);
+ if (prefix != NULL)
+ pr_len = strlen(prefix);
+
+ hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
+ hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
+ sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
+ sizeof(size_t) + pr_len;
+
+ for (i = 0; i < 256; i++)
+ hdr.len += sizeof(int) + lease->options[i].len;
+
+ scripttime = time(NULL);
+
+ if ((buf = buf_open(hdr.len)) == NULL)
+ error("buf_open: %m");
+
+ errs = 0;
+ errs += buf_add(buf, &hdr, sizeof(hdr));
+ errs += buf_add(buf, lease, sizeof(struct client_lease));
+ errs += buf_add(buf, &fn_len, sizeof(fn_len));
+ errs += buf_add(buf, lease->filename, fn_len);
+ errs += buf_add(buf, &sn_len, sizeof(sn_len));
+ errs += buf_add(buf, lease->server_name, sn_len);
+ errs += buf_add(buf, &pr_len, sizeof(pr_len));
+ errs += buf_add(buf, prefix, pr_len);
+
+ for (i = 0; i < 256; i++) {
+ errs += buf_add(buf, &lease->options[i].len,
+ sizeof(lease->options[i].len));
+ errs += buf_add(buf, lease->options[i].data,
+ lease->options[i].len);
+ }
+
+ if (errs)
+ error("buf_add: %m");
+
+ if (buf_close(privfd, buf) == -1)
+ error("buf_close: %m");
+}
+
+int
+script_go(void)
+{
+ struct imsg_hdr hdr;
+ struct buf *buf;
+ int ret;
+
+ hdr.code = IMSG_SCRIPT_GO;
+ hdr.len = sizeof(struct imsg_hdr);
+
+ if ((buf = buf_open(hdr.len)) == NULL)
+ error("buf_open: %m");
+
+ if (buf_add(buf, &hdr, sizeof(hdr)))
+ error("buf_add: %m");
+
+ if (buf_close(privfd, buf) == -1)
+ error("buf_close: %m");
+
+ bzero(&hdr, sizeof(hdr));
+ buf_read(privfd, &hdr, sizeof(hdr));
+ if (hdr.code != IMSG_SCRIPT_GO_RET)
+ error("unexpected msg type %u", hdr.code);
+ if (hdr.len != sizeof(hdr) + sizeof(int))
+ error("received corrupted message");
+ buf_read(privfd, &ret, sizeof(ret));
+
+ scripttime = time(NULL);
+
+ return (ret);
+}
+
+int
+priv_script_go(void)
+{
+ char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
+ static char client_path[] = CLIENT_PATH;
+ struct interface_info *ip = ifi;
+ int pid, wpid, wstatus;
+
+ scripttime = time(NULL);
+
+ if (ip) {
+ scriptName = ip->client->config->script_name;
+ envp = ip->client->scriptEnv;
+ } else {
+ scriptName = top_level_config.script_name;
+ epp[0] = reason;
+ epp[1] = client_path;
+ epp[2] = NULL;
+ envp = epp;
+ }
+
+ argv[0] = scriptName;
+ argv[1] = NULL;
+
+ pid = fork();
+ if (pid < 0) {
+ error("fork: %m");
+ wstatus = 0;
+ } else if (pid) {
+ do {
+ wpid = wait(&wstatus);
+ } while (wpid != pid && wpid > 0);
+ if (wpid < 0) {
+ error("wait: %m");
+ wstatus = 0;
+ }
+ } else {
+ execve(scriptName, argv, envp);
+ error("execve (%s, ...): %m", scriptName);
+ }
+
+ if (ip)
+ script_flush_env(ip->client);
+
+ return (wstatus & 0xff);
+}
+
+void
+script_set_env(struct client_state *client, const char *prefix,
+ const char *name, const char *value)
+{
+ int i, j, namelen;
+
+ namelen = strlen(name);
+
+ for (i = 0; client->scriptEnv[i]; i++)
+ if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
+ client->scriptEnv[i][namelen] == '=')
+ break;
+
+ if (client->scriptEnv[i])
+ /* Reuse the slot. */
+ free(client->scriptEnv[i]);
+ else {
+ /* New variable. Expand if necessary. */
+ if (i >= client->scriptEnvsize - 1) {
+ char **newscriptEnv;
+ int newscriptEnvsize = client->scriptEnvsize + 50;
+
+ newscriptEnv = realloc(client->scriptEnv,
+ newscriptEnvsize);
+ if (newscriptEnv == NULL) {
+ free(client->scriptEnv);
+ client->scriptEnv = NULL;
+ client->scriptEnvsize = 0;
+ error("script_set_env: no memory for variable");
+ }
+ client->scriptEnv = newscriptEnv;
+ client->scriptEnvsize = newscriptEnvsize;
+ }
+ /* need to set the NULL pointer at end of array beyond
+ the new slot. */
+ client->scriptEnv[i + 1] = NULL;
+ }
+ /* Allocate space and format the variable in the appropriate slot. */
+ client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
+ strlen(value) + 1);
+ if (client->scriptEnv[i] == NULL)
+ error("script_set_env: no memory for variable assignment");
+
+ /* No `` or $() command substitution allowed in environment values! */
+ for (j=0; j < strlen(value); j++)
+ switch (value[j]) {
+ case '`':
+ case '$':
+ error("illegal character (%c) in value '%s'", value[j],
+ value);
+ /* not reached */
+ }
+ snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
+ 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
+}
+
+void
+script_flush_env(struct client_state *client)
+{
+ int i;
+
+ for (i = 0; client->scriptEnv[i]; i++) {
+ free(client->scriptEnv[i]);
+ client->scriptEnv[i] = NULL;
+ }
+ client->scriptEnvsize = 0;
+}
+
+int
+dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
+{
+ int i;
+
+ for (i = 0; option->name[i]; i++) {
+ if (i + 1 == buflen)
+ return 0;
+ if (option->name[i] == '-')
+ buf[i] = '_';
+ else
+ buf[i] = option->name[i];
+ }
+
+ buf[i] = 0;
+ return 1;
+}
+
+void
+go_daemon(void)
+{
+ static int state = 0;
+
+ if (no_daemon || state)
+ return;
+
+ state = 1;
+
+ /* Stop logging to stderr... */
+ log_perror = 0;
+
+ if (daemon(1, 0) == -1)
+ error("daemon");
+
+ /* we are chrooted, daemon(3) fails to open /dev/null */
+ if (nullfd != -1) {
+ dup2(nullfd, STDIN_FILENO);
+ dup2(nullfd, STDOUT_FILENO);
+ dup2(nullfd, STDERR_FILENO);
+ close(nullfd);
+ nullfd = -1;
+ }
+}
+
+int
+check_option(struct client_lease *l, int option)
+{
+ char *opbuf;
+ char *sbuf;
+
+ /* we use this, since this is what gets passed to dhclient-script */
+
+ opbuf = pretty_print_option(option, l->options[option].data,
+ l->options[option].len, 0, 0);
+
+ sbuf = option_as_string(option, l->options[option].data,
+ l->options[option].len);
+
+ switch (option) {
+ case DHO_SUBNET_MASK:
+ case DHO_TIME_SERVERS:
+ case DHO_NAME_SERVERS:
+ case DHO_ROUTERS:
+ case DHO_DOMAIN_NAME_SERVERS:
+ case DHO_LOG_SERVERS:
+ case DHO_COOKIE_SERVERS:
+ case DHO_LPR_SERVERS:
+ case DHO_IMPRESS_SERVERS:
+ case DHO_RESOURCE_LOCATION_SERVERS:
+ case DHO_SWAP_SERVER:
+ case DHO_BROADCAST_ADDRESS:
+ case DHO_NIS_SERVERS:
+ case DHO_NTP_SERVERS:
+ case DHO_NETBIOS_NAME_SERVERS:
+ case DHO_NETBIOS_DD_SERVER:
+ case DHO_FONT_SERVERS:
+ case DHO_DHCP_SERVER_IDENTIFIER:
+ case DHO_NISPLUS_SERVERS:
+ case DHO_MOBILE_IP_HOME_AGENT:
+ case DHO_SMTP_SERVER:
+ case DHO_POP_SERVER:
+ case DHO_NNTP_SERVER:
+ case DHO_WWW_SERVER:
+ case DHO_FINGER_SERVER:
+ case DHO_IRC_SERVER:
+ case DHO_STREETTALK_SERVER:
+ case DHO_STREETTALK_DA_SERVER:
+ if (!ipv4addrs(opbuf)) {
+ warning("Invalid IP address in option: %s", opbuf);
+ return (0);
+ }
+ return (1) ;
+ case DHO_HOST_NAME:
+ case DHO_NIS_DOMAIN:
+ case DHO_NISPLUS_DOMAIN:
+ case DHO_TFTP_SERVER_NAME:
+ if (!res_hnok(sbuf)) {
+ warning("Bogus Host Name option %d: %s (%s)", option,
+ sbuf, opbuf);
+ l->options[option].len = 0;
+ free(l->options[option].data);
+ }
+ return (1);
+ case DHO_DOMAIN_NAME:
+ if (!res_hnok(sbuf)) {
+ if (!check_search(sbuf)) {
+ warning("Bogus domain search list %d: %s (%s)",
+ option, sbuf, opbuf);
+ l->options[option].len = 0;
+ free(l->options[option].data);
+ }
+ }
+ return (1);
+ case DHO_PAD:
+ case DHO_TIME_OFFSET:
+ case DHO_BOOT_SIZE:
+ case DHO_MERIT_DUMP:
+ case DHO_ROOT_PATH:
+ case DHO_EXTENSIONS_PATH:
+ case DHO_IP_FORWARDING:
+ case DHO_NON_LOCAL_SOURCE_ROUTING:
+ case DHO_POLICY_FILTER:
+ case DHO_MAX_DGRAM_REASSEMBLY:
+ case DHO_DEFAULT_IP_TTL:
+ case DHO_PATH_MTU_AGING_TIMEOUT:
+ case DHO_PATH_MTU_PLATEAU_TABLE:
+ case DHO_INTERFACE_MTU:
+ case DHO_ALL_SUBNETS_LOCAL:
+ case DHO_PERFORM_MASK_DISCOVERY:
+ case DHO_MASK_SUPPLIER:
+ case DHO_ROUTER_DISCOVERY:
+ case DHO_ROUTER_SOLICITATION_ADDRESS:
+ case DHO_STATIC_ROUTES:
+ case DHO_TRAILER_ENCAPSULATION:
+ case DHO_ARP_CACHE_TIMEOUT:
+ case DHO_IEEE802_3_ENCAPSULATION:
+ case DHO_DEFAULT_TCP_TTL:
+ case DHO_TCP_KEEPALIVE_INTERVAL:
+ case DHO_TCP_KEEPALIVE_GARBAGE:
+ case DHO_VENDOR_ENCAPSULATED_OPTIONS:
+ case DHO_NETBIOS_NODE_TYPE:
+ case DHO_NETBIOS_SCOPE:
+ case DHO_X_DISPLAY_MANAGER:
+ case DHO_DHCP_REQUESTED_ADDRESS:
+ case DHO_DHCP_LEASE_TIME:
+ case DHO_DHCP_OPTION_OVERLOAD:
+ case DHO_DHCP_MESSAGE_TYPE:
+ case DHO_DHCP_PARAMETER_REQUEST_LIST:
+ case DHO_DHCP_MESSAGE:
+ case DHO_DHCP_MAX_MESSAGE_SIZE:
+ case DHO_DHCP_RENEWAL_TIME:
+ case DHO_DHCP_REBINDING_TIME:
+ case DHO_DHCP_CLASS_IDENTIFIER:
+ case DHO_DHCP_CLIENT_IDENTIFIER:
+ case DHO_BOOTFILE_NAME:
+ case DHO_DHCP_USER_CLASS_ID:
+ case DHO_END:
+ return (1);
+ case DHO_CLASSLESS_ROUTES:
+ return (check_classless_option(l->options[option].data,
+ l->options[option].len));
+ default:
+ warning("unknown dhcp option value 0x%x", option);
+ return (unknown_ok);
+ }
+}
+
+/* RFC 3442 The Classless Static Routes option checks */
+int
+check_classless_option(unsigned char *data, int len)
+{
+ int i = 0;
+ unsigned char width;
+ in_addr_t addr, mask;
+
+ if (len < 5) {
+ warning("Too small length: %d", len);
+ return (0);
+ }
+ while(i < len) {
+ width = data[i++];
+ if (width == 0) {
+ i += 4;
+ continue;
+ } else if (width < 9) {
+ addr = (in_addr_t)(data[i] << 24);
+ i += 1;
+ } else if (width < 17) {
+ addr = (in_addr_t)(data[i] << 24) +
+ (in_addr_t)(data[i + 1] << 16);
+ i += 2;
+ } else if (width < 25) {
+ addr = (in_addr_t)(data[i] << 24) +
+ (in_addr_t)(data[i + 1] << 16) +
+ (in_addr_t)(data[i + 2] << 8);
+ i += 3;
+ } else if (width < 33) {
+ addr = (in_addr_t)(data[i] << 24) +
+ (in_addr_t)(data[i + 1] << 16) +
+ (in_addr_t)(data[i + 2] << 8) +
+ data[i + 3];
+ i += 4;
+ } else {
+ warning("Incorrect subnet width: %d", width);
+ return (0);
+ }
+ mask = (in_addr_t)(~0) << (32 - width);
+ addr = ntohl(addr);
+ mask = ntohl(mask);
+
+ /*
+ * From RFC 3442:
+ * ... After deriving a subnet number and subnet mask
+ * from each destination descriptor, the DHCP client
+ * MUST zero any bits in the subnet number where the
+ * corresponding bit in the mask is zero...
+ */
+ if ((addr & mask) != addr) {
+ addr &= mask;
+ data[i - 1] = (unsigned char)(
+ (addr >> (((32 - width)/8)*8)) & 0xFF);
+ }
+ i += 4;
+ }
+ if (i > len) {
+ warning("Incorrect data length: %d (must be %d)", len, i);
+ return (0);
+ }
+ return (1);
+}
+
+int
+res_hnok(const char *dn)
+{
+ int pch = PERIOD, ch = *dn++;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (periodchar(ch)) {
+ ;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ pch = ch, ch = nch;
+ }
+ return (1);
+}
+
+int
+check_search(const char *srch)
+{
+ int pch = PERIOD, ch = *srch++;
+ int domains = 1;
+
+ /* 256 char limit re resolv.conf(5) */
+ if (strlen(srch) > 256)
+ return (0);
+
+ while (whitechar(ch))
+ ch = *srch++;
+
+ while (ch != '\0') {
+ int nch = *srch++;
+
+ if (periodchar(ch) || whitechar(ch)) {
+ ;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ if (!whitechar(ch)) {
+ pch = ch;
+ } else {
+ while (whitechar(nch)) {
+ nch = *srch++;
+ }
+ if (nch != '\0')
+ domains++;
+ pch = PERIOD;
+ }
+ ch = nch;
+ }
+ /* 6 domain limit re resolv.conf(5) */
+ if (domains > 6)
+ return (0);
+ return (1);
+}
+
+/* Does buf consist only of dotted decimal ipv4 addrs?
+ * return how many if so,
+ * otherwise, return 0
+ */
+int
+ipv4addrs(char * buf)
+{
+ struct in_addr jnk;
+ int count = 0;
+
+ while (inet_aton(buf, &jnk) == 1){
+ count++;
+ while (periodchar(*buf) || digitchar(*buf))
+ buf++;
+ if (*buf == '\0')
+ return (count);
+ while (*buf == ' ')
+ buf++;
+ }
+ return (0);
+}
+
+
+char *
+option_as_string(unsigned int code, unsigned char *data, int len)
+{
+ static char optbuf[32768]; /* XXX */
+ char *op = optbuf;
+ int opleft = sizeof(optbuf);
+ unsigned char *dp = data;
+
+ if (code > 255)
+ error("option_as_string: bad code %d", code);
+
+ for (; dp < data + len; dp++) {
+ if (!isascii(*dp) || !isprint(*dp)) {
+ if (dp + 1 != data + len || *dp != 0) {
+ snprintf(op, opleft, "\\%03o", *dp);
+ op += 4;
+ opleft -= 4;
+ }
+ } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
+ *dp == '`' || *dp == '\\') {
+ *op++ = '\\';
+ *op++ = *dp;
+ opleft -= 2;
+ } else {
+ *op++ = *dp;
+ opleft--;
+ }
+ }
+ if (opleft < 1)
+ goto toobig;
+ *op = 0;
+ return optbuf;
+toobig:
+ warning("dhcp option too large");
+ return "<error>";
+}
+
+int
+fork_privchld(int fd, int fd2)
+{
+ struct pollfd pfd[1];
+ int nfds;
+
+ switch (fork()) {
+ case -1:
+ error("cannot fork");
+ case 0:
+ break;
+ default:
+ return (0);
+ }
+
+ setproctitle("%s [priv]", ifi->name);
+
+ setsid();
+ dup2(nullfd, STDIN_FILENO);
+ dup2(nullfd, STDOUT_FILENO);
+ dup2(nullfd, STDERR_FILENO);
+ close(nullfd);
+ close(fd2);
+
+ for (;;) {
+ pfd[0].fd = fd;
+ pfd[0].events = POLLIN;
+ if ((nfds = poll(pfd, 1, INFTIM)) == -1)
+ if (errno != EINTR)
+ error("poll error");
+
+ if (nfds == 0 || !(pfd[0].revents & POLLIN))
+ continue;
+
+ dispatch_imsg(fd);
+ }
+}
diff --git a/freebsd/sbin/dhclient/dhcp.h b/freebsd/sbin/dhclient/dhcp.h
new file mode 100644
index 00000000..e4fa9d17
--- /dev/null
+++ b/freebsd/sbin/dhclient/dhcp.h
@@ -0,0 +1,183 @@
+/* $OpenBSD: dhcp.h,v 1.5 2004/05/04 15:49:49 deraadt Exp $ */
+/* $FreeBSD$ */
+
+/* Protocol structures... */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#define DHCP_UDP_OVERHEAD (14 + /* Ethernet header */ \
+ 20 + /* IP header */ \
+ 8) /* UDP header */
+#define DHCP_SNAME_LEN 64
+#define DHCP_FILE_LEN 128
+#define DHCP_FIXED_NON_UDP 236
+#define DHCP_FIXED_LEN (DHCP_FIXED_NON_UDP + DHCP_UDP_OVERHEAD)
+ /* Everything but options. */
+#define DHCP_MTU_MAX 1500
+#define DHCP_OPTION_LEN (DHCP_MTU_MAX - DHCP_FIXED_LEN)
+
+#define BOOTP_MIN_LEN 300
+#define DHCP_MIN_LEN 548
+
+struct dhcp_packet {
+ u_int8_t op; /* Message opcode/type */
+ u_int8_t htype; /* Hardware addr type (see net/if_types.h) */
+ u_int8_t hlen; /* Hardware addr length */
+ u_int8_t hops; /* Number of relay agent hops from client */
+ u_int32_t xid; /* Transaction ID */
+ u_int16_t secs; /* Seconds since client started looking */
+ u_int16_t flags; /* Flag bits */
+ struct in_addr ciaddr; /* Client IP address (if already in use) */
+ struct in_addr yiaddr; /* Client IP address */
+ struct in_addr siaddr; /* IP address of next server to talk to */
+ struct in_addr giaddr; /* DHCP relay agent IP address */
+ unsigned char chaddr[16]; /* Client hardware address */
+ char sname[DHCP_SNAME_LEN]; /* Server name */
+ char file[DHCP_FILE_LEN]; /* Boot filename */
+ unsigned char options[DHCP_OPTION_LEN];
+ /* Optional parameters
+ (actual length dependent on MTU). */
+};
+
+/* BOOTP (rfc951) message types */
+#define BOOTREQUEST 1
+#define BOOTREPLY 2
+
+/* Possible values for flags field... */
+#define BOOTP_BROADCAST 32768L
+
+/* Possible values for hardware type (htype) field... */
+#define HTYPE_ETHER 1 /* Ethernet */
+#define HTYPE_IEEE802 6 /* IEEE 802.2 Token Ring... */
+#define HTYPE_FDDI 8 /* FDDI... */
+
+/* Magic cookie validating dhcp options field (and bootp vendor
+ extensions field). */
+#define DHCP_OPTIONS_COOKIE "\143\202\123\143"
+
+/* DHCP Option codes: */
+
+#define DHO_PAD 0
+#define DHO_SUBNET_MASK 1
+#define DHO_TIME_OFFSET 2
+#define DHO_ROUTERS 3
+#define DHO_TIME_SERVERS 4
+#define DHO_NAME_SERVERS 5
+#define DHO_DOMAIN_NAME_SERVERS 6
+#define DHO_LOG_SERVERS 7
+#define DHO_COOKIE_SERVERS 8
+#define DHO_LPR_SERVERS 9
+#define DHO_IMPRESS_SERVERS 10
+#define DHO_RESOURCE_LOCATION_SERVERS 11
+#define DHO_HOST_NAME 12
+#define DHO_BOOT_SIZE 13
+#define DHO_MERIT_DUMP 14
+#define DHO_DOMAIN_NAME 15
+#define DHO_SWAP_SERVER 16
+#define DHO_ROOT_PATH 17
+#define DHO_EXTENSIONS_PATH 18
+#define DHO_IP_FORWARDING 19
+#define DHO_NON_LOCAL_SOURCE_ROUTING 20
+#define DHO_POLICY_FILTER 21
+#define DHO_MAX_DGRAM_REASSEMBLY 22
+#define DHO_DEFAULT_IP_TTL 23
+#define DHO_PATH_MTU_AGING_TIMEOUT 24
+#define DHO_PATH_MTU_PLATEAU_TABLE 25
+#define DHO_INTERFACE_MTU 26
+#define DHO_ALL_SUBNETS_LOCAL 27
+#define DHO_BROADCAST_ADDRESS 28
+#define DHO_PERFORM_MASK_DISCOVERY 29
+#define DHO_MASK_SUPPLIER 30
+#define DHO_ROUTER_DISCOVERY 31
+#define DHO_ROUTER_SOLICITATION_ADDRESS 32
+#define DHO_STATIC_ROUTES 33
+#define DHO_TRAILER_ENCAPSULATION 34
+#define DHO_ARP_CACHE_TIMEOUT 35
+#define DHO_IEEE802_3_ENCAPSULATION 36
+#define DHO_DEFAULT_TCP_TTL 37
+#define DHO_TCP_KEEPALIVE_INTERVAL 38
+#define DHO_TCP_KEEPALIVE_GARBAGE 39
+#define DHO_NIS_DOMAIN 40
+#define DHO_NIS_SERVERS 41
+#define DHO_NTP_SERVERS 42
+#define DHO_VENDOR_ENCAPSULATED_OPTIONS 43
+#define DHO_NETBIOS_NAME_SERVERS 44
+#define DHO_NETBIOS_DD_SERVER 45
+#define DHO_NETBIOS_NODE_TYPE 46
+#define DHO_NETBIOS_SCOPE 47
+#define DHO_FONT_SERVERS 48
+#define DHO_X_DISPLAY_MANAGER 49
+#define DHO_DHCP_REQUESTED_ADDRESS 50
+#define DHO_DHCP_LEASE_TIME 51
+#define DHO_DHCP_OPTION_OVERLOAD 52
+#define DHO_DHCP_MESSAGE_TYPE 53
+#define DHO_DHCP_SERVER_IDENTIFIER 54
+#define DHO_DHCP_PARAMETER_REQUEST_LIST 55
+#define DHO_DHCP_MESSAGE 56
+#define DHO_DHCP_MAX_MESSAGE_SIZE 57
+#define DHO_DHCP_RENEWAL_TIME 58
+#define DHO_DHCP_REBINDING_TIME 59
+#define DHO_DHCP_CLASS_IDENTIFIER 60
+#define DHO_DHCP_CLIENT_IDENTIFIER 61
+#define DHO_NISPLUS_DOMAIN 64
+#define DHO_NISPLUS_SERVERS 65
+#define DHO_TFTP_SERVER_NAME 66
+#define DHO_BOOTFILE_NAME 67
+#define DHO_MOBILE_IP_HOME_AGENT 68
+#define DHO_SMTP_SERVER 69
+#define DHO_POP_SERVER 70
+#define DHO_NNTP_SERVER 71
+#define DHO_WWW_SERVER 72
+#define DHO_FINGER_SERVER 73
+#define DHO_IRC_SERVER 74
+#define DHO_STREETTALK_SERVER 75
+#define DHO_STREETTALK_DA_SERVER 76
+#define DHO_DHCP_USER_CLASS_ID 77
+#define DHO_CLASSLESS_ROUTES 121
+#define DHO_END 255
+
+/* DHCP message types. */
+#define DHCPDISCOVER 1
+#define DHCPOFFER 2
+#define DHCPREQUEST 3
+#define DHCPDECLINE 4
+#define DHCPACK 5
+#define DHCPNAK 6
+#define DHCPRELEASE 7
+#define DHCPINFORM 8
diff --git a/freebsd/sbin/dhclient/dhcpd.h b/freebsd/sbin/dhclient/dhcpd.h
new file mode 100644
index 00000000..bd4c9c0b
--- /dev/null
+++ b/freebsd/sbin/dhclient/dhcpd.h
@@ -0,0 +1,440 @@
+/* $OpenBSD: dhcpd.h,v 1.33 2004/05/06 22:29:15 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999
+ * The Internet Software Consortium. 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <sys/wait.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <paths.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "dhcp.h"
+#include "tree.h"
+
+#define LOCAL_PORT 68
+#define REMOTE_PORT 67
+
+struct option_data {
+ int len;
+ u_int8_t *data;
+};
+
+struct string_list {
+ struct string_list *next;
+ char *string;
+};
+
+struct iaddr {
+ int len;
+ unsigned char iabuf[16];
+};
+
+struct iaddrlist {
+ struct iaddrlist *next;
+ struct iaddr addr;
+};
+
+struct packet {
+ struct dhcp_packet *raw;
+ int packet_length;
+ int packet_type;
+ int options_valid;
+ int client_port;
+ struct iaddr client_addr;
+ struct interface_info *interface;
+ struct hardware *haddr;
+ struct option_data options[256];
+};
+
+struct hardware {
+ u_int8_t htype;
+ u_int8_t hlen;
+ u_int8_t haddr[16];
+};
+
+struct client_lease {
+ struct client_lease *next;
+ time_t expiry, renewal, rebind;
+ struct iaddr address;
+ char *server_name;
+ char *filename;
+ struct string_list *medium;
+ unsigned int is_static : 1;
+ unsigned int is_bootp : 1;
+ struct option_data options[256];
+};
+
+/* Possible states in which the client can be. */
+enum dhcp_state {
+ S_REBOOTING,
+ S_INIT,
+ S_SELECTING,
+ S_REQUESTING,
+ S_BOUND,
+ S_RENEWING,
+ S_REBINDING
+};
+
+struct client_config {
+ struct option_data defaults[256];
+ enum {
+ ACTION_DEFAULT,
+ ACTION_SUPERSEDE,
+ ACTION_PREPEND,
+ ACTION_APPEND
+ } default_actions[256];
+
+ struct option_data send_options[256];
+ u_int8_t required_options[256];
+ u_int8_t requested_options[256];
+ int requested_option_count;
+ time_t timeout;
+ time_t initial_interval;
+ time_t retry_interval;
+ time_t select_interval;
+ time_t reboot_timeout;
+ time_t backoff_cutoff;
+ struct string_list *media;
+ char *script_name;
+ enum { IGNORE, ACCEPT, PREFER }
+ bootp_policy;
+ struct string_list *medium;
+ struct iaddrlist *reject_list;
+};
+
+struct client_state {
+ struct client_lease *active;
+ struct client_lease *new;
+ struct client_lease *offered_leases;
+ struct client_lease *leases;
+ struct client_lease *alias;
+ enum dhcp_state state;
+ struct iaddr destination;
+ u_int32_t xid;
+ u_int16_t secs;
+ time_t first_sending;
+ time_t interval;
+ struct string_list *medium;
+ struct dhcp_packet packet;
+ int packet_length;
+ struct iaddr requested_address;
+ struct client_config *config;
+ char **scriptEnv;
+ int scriptEnvsize;
+ struct string_list *env;
+ int envc;
+};
+
+struct interface_info {
+ struct interface_info *next;
+ struct hardware hw_address;
+ struct in_addr primary_address;
+ char name[IFNAMSIZ];
+ int rfdesc;
+ int wfdesc;
+ int ufdesc;
+ unsigned char *rbuf;
+ size_t rbuf_max;
+ size_t rbuf_offset;
+ size_t rbuf_len;
+ struct ifreq *ifp;
+ struct client_state *client;
+ int noifmedia;
+ int errors;
+ int dead;
+ u_int16_t index;
+};
+
+struct timeout {
+ struct timeout *next;
+ time_t when;
+ void (*func)(void *);
+ void *what;
+};
+
+struct protocol {
+ struct protocol *next;
+ int fd;
+ void (*handler)(struct protocol *);
+ void *local;
+};
+
+#define DEFAULT_HASH_SIZE 97
+
+struct hash_bucket {
+ struct hash_bucket *next;
+ unsigned char *name;
+ int len;
+ unsigned char *value;
+};
+
+struct hash_table {
+ int hash_count;
+ struct hash_bucket *buckets[DEFAULT_HASH_SIZE];
+};
+
+/* Default path to dhcpd config file. */
+#define _PATH_DHCLIENT_CONF "/etc/dhclient.conf"
+#define _PATH_DHCLIENT_DB "/var/db/dhclient.leases"
+#define DHCPD_LOG_FACILITY LOG_DAEMON
+
+#define MAX_TIME 0x7fffffff
+#define MIN_TIME 0
+
+/* External definitions... */
+
+/* options.c */
+int cons_options(struct packet *, struct dhcp_packet *, int,
+ struct tree_cache **, int, int, int, u_int8_t *, int);
+char *pretty_print_option(unsigned int,
+ unsigned char *, int, int, int);
+void do_packet(struct interface_info *, struct dhcp_packet *,
+ int, unsigned int, struct iaddr, struct hardware *);
+
+/* errwarn.c */
+extern int warnings_occurred;
+void error(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int warning(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int note(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int debug(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+int parse_warn(char *, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+
+/* conflex.c */
+extern int lexline, lexchar;
+extern char *token_line, *tlname;
+extern char comments[4096];
+extern int comment_index;
+extern int eol_token;
+void new_parse(char *);
+int next_token(char **, FILE *);
+int peek_token(char **, FILE *);
+
+/* parse.c */
+void skip_to_semi(FILE *);
+int parse_semi(FILE *);
+char *parse_string(FILE *);
+int parse_ip_addr(FILE *, struct iaddr *);
+void parse_hardware_param(FILE *, struct hardware *);
+void parse_lease_time(FILE *, time_t *);
+unsigned char *parse_numeric_aggregate(FILE *, unsigned char *, int *,
+ int, int, int);
+void convert_num(unsigned char *, char *, int, int);
+time_t parse_date(FILE *);
+
+/* tree.c */
+pair cons(caddr_t, pair);
+
+/* alloc.c */
+struct string_list *new_string_list(size_t size);
+struct hash_table *new_hash_table(int);
+struct hash_bucket *new_hash_bucket(void);
+
+/* bpf.c */
+int if_register_bpf(struct interface_info *);
+void if_register_send(struct interface_info *);
+void if_register_receive(struct interface_info *);
+ssize_t send_packet(struct interface_info *, struct dhcp_packet *, size_t,
+ struct in_addr, struct sockaddr_in *, struct hardware *);
+ssize_t receive_packet(struct interface_info *, unsigned char *, size_t,
+ struct sockaddr_in *, struct hardware *);
+
+/* dispatch.c */
+extern void (*bootp_packet_handler)(struct interface_info *,
+ struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *);
+void discover_interfaces(struct interface_info *);
+void reinitialize_interfaces(void);
+void dispatch(void);
+void got_one(struct protocol *);
+void add_timeout(time_t, void (*)(void *), void *);
+void cancel_timeout(void (*)(void *), void *);
+void add_protocol(char *, int, void (*)(struct protocol *), void *);
+void remove_protocol(struct protocol *);
+int interface_link_status(char *);
+
+/* hash.c */
+struct hash_table *new_hash(void);
+void add_hash(struct hash_table *, unsigned char *, int, unsigned char *);
+unsigned char *hash_lookup(struct hash_table *, unsigned char *, int);
+
+/* tables.c */
+extern struct option dhcp_options[256];
+extern unsigned char dhcp_option_default_priority_list[];
+extern int sizeof_dhcp_option_default_priority_list;
+extern struct hash_table universe_hash;
+extern struct universe dhcp_universe;
+void initialize_universes(void);
+
+/* convert.c */
+u_int32_t getULong(unsigned char *);
+int32_t getLong(unsigned char *);
+u_int16_t getUShort(unsigned char *);
+int16_t getShort(unsigned char *);
+void putULong(unsigned char *, u_int32_t);
+void putLong(unsigned char *, int32_t);
+void putUShort(unsigned char *, unsigned int);
+void putShort(unsigned char *, int);
+
+/* inet.c */
+struct iaddr subnet_number(struct iaddr, struct iaddr);
+struct iaddr broadcast_addr(struct iaddr, struct iaddr);
+int addr_eq(struct iaddr, struct iaddr);
+char *piaddr(struct iaddr);
+
+/* dhclient.c */
+extern char *path_dhclient_conf;
+extern char *path_dhclient_db;
+extern time_t cur_time;
+extern int log_priority;
+extern int log_perror;
+
+extern struct client_config top_level_config;
+
+void dhcpoffer(struct packet *);
+void dhcpack(struct packet *);
+void dhcpnak(struct packet *);
+
+void send_discover(void *);
+void send_request(void *);
+void send_decline(void *);
+
+void state_reboot(void *);
+void state_init(void *);
+void state_selecting(void *);
+void state_requesting(void *);
+void state_bound(void *);
+void state_panic(void *);
+
+void bind_lease(struct interface_info *);
+
+void make_discover(struct interface_info *, struct client_lease *);
+void make_request(struct interface_info *, struct client_lease *);
+void make_decline(struct interface_info *, struct client_lease *);
+
+void free_client_lease(struct client_lease *);
+void rewrite_client_leases(void);
+void write_client_lease(struct interface_info *, struct client_lease *, int);
+
+void priv_script_init(char *, char *);
+void priv_script_write_params(char *, struct client_lease *);
+int priv_script_go(void);
+
+void script_init(char *, struct string_list *);
+void script_write_params(char *, struct client_lease *);
+int script_go(void);
+void client_envadd(struct client_state *,
+ const char *, const char *, const char *, ...);
+void script_set_env(struct client_state *, const char *, const char *,
+ const char *);
+void script_flush_env(struct client_state *);
+int dhcp_option_ev_name(char *, size_t, struct option *);
+
+struct client_lease *packet_to_lease(struct packet *);
+void go_daemon(void);
+void client_location_changed(void);
+
+void bootp(struct packet *);
+void dhcp(struct packet *);
+
+/* packet.c */
+void assemble_hw_header(struct interface_info *, unsigned char *,
+ int *, struct hardware *);
+void assemble_udp_ip_header(unsigned char *, int *, u_int32_t, u_int32_t,
+ unsigned int, unsigned char *, int);
+ssize_t decode_hw_header(unsigned char *, int, struct hardware *);
+ssize_t decode_udp_ip_header(unsigned char *, int, struct sockaddr_in *,
+ unsigned char *, int);
+
+/* ethernet.c */
+void assemble_ethernet_header(struct interface_info *, unsigned char *,
+ int *, struct hardware *);
+ssize_t decode_ethernet_header(struct interface_info *, unsigned char *,
+ int, struct hardware *);
+
+/* clparse.c */
+int read_client_conf(void);
+void read_client_leases(void);
+void parse_client_statement(FILE *, struct interface_info *,
+ struct client_config *);
+int parse_X(FILE *, u_int8_t *, int);
+int parse_option_list(FILE *, u_int8_t *);
+void parse_interface_declaration(FILE *, struct client_config *);
+struct interface_info *interface_or_dummy(char *);
+void make_client_state(struct interface_info *);
+void make_client_config(struct interface_info *, struct client_config *);
+void parse_client_lease_statement(FILE *, int);
+void parse_client_lease_declaration(FILE *, struct client_lease *,
+ struct interface_info **);
+struct option *parse_option_decl(FILE *, struct option_data *);
+void parse_string_list(FILE *, struct string_list **, int);
+void parse_reject_statement(FILE *, struct client_config *);
+
+/* privsep.c */
+struct buf *buf_open(size_t);
+int buf_add(struct buf *, void *, size_t);
+int buf_close(int, struct buf *);
+ssize_t buf_read(int, void *, size_t);
+void dispatch_imsg(int);
diff --git a/freebsd/sbin/dhclient/dhctoken.h b/freebsd/sbin/dhclient/dhctoken.h
new file mode 100644
index 00000000..7b23242f
--- /dev/null
+++ b/freebsd/sbin/dhclient/dhctoken.h
@@ -0,0 +1,136 @@
+/* $OpenBSD: dhctoken.h,v 1.2 2004/02/04 12:16:56 henning Exp $ */
+
+/* Tokens for config file lexer and parser. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999
+ * The Internet Software Consortium. 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#define SEMI ';'
+#define DOT '.'
+#define COLON ':'
+#define COMMA ','
+#define SLASH '/'
+#define LBRACE '{'
+#define RBRACE '}'
+
+#define FIRST_TOKEN HOST
+#define HOST 256
+#define HARDWARE 257
+#define FILENAME 258
+#define FIXED_ADDR 259
+#define OPTION 260
+#define ETHERNET 261
+#define STRING 262
+#define NUMBER 263
+#define NUMBER_OR_NAME 264
+#define NAME 265
+#define TIMESTAMP 266
+#define STARTS 267
+#define ENDS 268
+#define UID 269
+#define CLASS 270
+#define LEASE 271
+#define RANGE 272
+#define PACKET 273
+#define CIADDR 274
+#define YIADDR 275
+#define SIADDR 276
+#define GIADDR 277
+#define SUBNET 278
+#define NETMASK 279
+#define DEFAULT_LEASE_TIME 280
+#define MAX_LEASE_TIME 281
+#define VENDOR_CLASS 282
+#define USER_CLASS 283
+#define SHARED_NETWORK 284
+#define SERVER_NAME 285
+#define DYNAMIC_BOOTP 286
+#define SERVER_IDENTIFIER 287
+#define DYNAMIC_BOOTP_LEASE_CUTOFF 288
+#define DYNAMIC_BOOTP_LEASE_LENGTH 289
+#define BOOT_UNKNOWN_CLIENTS 290
+#define NEXT_SERVER 291
+#define TOKEN_RING 292
+#define GROUP 293
+#define ONE_LEASE_PER_CLIENT 294
+#define GET_LEASE_HOSTNAMES 295
+#define USE_HOST_DECL_NAMES 296
+#define SEND 297
+#define CLIENT_IDENTIFIER 298
+#define REQUEST 299
+#define REQUIRE 300
+#define TIMEOUT 301
+#define RETRY 302
+#define SELECT_TIMEOUT 303
+#define SCRIPT 304
+#define INTERFACE 305
+#define RENEW 306
+#define REBIND 307
+#define EXPIRE 308
+#define UNKNOWN_CLIENTS 309
+#define ALLOW 310
+#define BOOTP 311
+#define DENY 312
+#define BOOTING 313
+#define DEFAULT 314
+#define MEDIA 315
+#define MEDIUM 316
+#define ALIAS 317
+#define REBOOT 318
+#define ABANDONED 319
+#define BACKOFF_CUTOFF 320
+#define INITIAL_INTERVAL 321
+#define NAMESERVER 322
+#define DOMAIN 323
+#define SEARCH 324
+#define SUPERSEDE 325
+#define APPEND 326
+#define PREPEND 327
+#define HOSTNAME 328
+#define CLIENT_HOSTNAME 329
+#define REJECT 330
+#define FDDI 331
+#define USE_LEASE_ADDR_FOR_DEFAULT_ROUTE 332
+#define AUTHORITATIVE 333
+#define TOKEN_NOT 334
+#define ALWAYS_REPLY_RFC1048 335
+
+#define is_identifier(x) ((x) >= FIRST_TOKEN && \
+ (x) != STRING && \
+ (x) != NUMBER && \
+ (x) != EOF)
diff --git a/freebsd/sbin/dhclient/dispatch.c b/freebsd/sbin/dhclient/dispatch.c
new file mode 100644
index 00000000..b04d488f
--- /dev/null
+++ b/freebsd/sbin/dhclient/dispatch.c
@@ -0,0 +1,507 @@
+/* $OpenBSD: dispatch.c,v 1.31 2004/09/21 04:07:03 david Exp $ */
+
+/*
+ * Copyright 2004 Henning Brauer <henning@openbsd.org>
+ * Copyright (c) 1995, 1996, 1997, 1998, 1999
+ * The Internet Software Consortium. 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+#include <sys/ioctl.h>
+
+#ifdef __rtems__
+#include <freebsd/net/if_media.h>
+#else
+#include <net/if_media.h>
+#endif
+#include <ifaddrs.h>
+#include <poll.h>
+
+struct protocol *protocols;
+struct timeout *timeouts;
+static struct timeout *free_timeouts;
+static int interfaces_invalidated;
+void (*bootp_packet_handler)(struct interface_info *,
+ struct dhcp_packet *, int, unsigned int,
+ struct iaddr, struct hardware *);
+
+static int interface_status(struct interface_info *ifinfo);
+
+/*
+ * Use getifaddrs() to get a list of all the attached interfaces. For
+ * each interface that's of type INET and not the loopback interface,
+ * register that interface with the network I/O software, figure out
+ * what subnet it's on, and add it to the list of interfaces.
+ */
+void
+discover_interfaces(struct interface_info *iface)
+{
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_in foo;
+ struct ifreq *tif;
+
+ if (getifaddrs(&ifap) != 0)
+ error("getifaddrs failed");
+
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ if ((ifa->ifa_flags & IFF_LOOPBACK) ||
+ (ifa->ifa_flags & IFF_POINTOPOINT) ||
+ (!(ifa->ifa_flags & IFF_UP)))
+ continue;
+
+ if (strcmp(iface->name, ifa->ifa_name))
+ continue;
+
+ /*
+ * If we have the capability, extract link information
+ * and record it in a linked list.
+ */
+ if (ifa->ifa_addr->sa_family == AF_LINK) {
+ struct sockaddr_dl *foo =
+ (struct sockaddr_dl *)ifa->ifa_addr;
+
+ iface->index = foo->sdl_index;
+ iface->hw_address.hlen = foo->sdl_alen;
+ iface->hw_address.htype = HTYPE_ETHER; /* XXX */
+ memcpy(iface->hw_address.haddr,
+ LLADDR(foo), foo->sdl_alen);
+ } else if (ifa->ifa_addr->sa_family == AF_INET) {
+ struct iaddr addr;
+
+ memcpy(&foo, ifa->ifa_addr, sizeof(foo));
+ if (foo.sin_addr.s_addr == htonl(INADDR_LOOPBACK))
+ continue;
+ if (!iface->ifp) {
+ int len = IFNAMSIZ + ifa->ifa_addr->sa_len;
+ if ((tif = malloc(len)) == NULL)
+ error("no space to remember ifp");
+ strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ);
+ memcpy(&tif->ifr_addr, ifa->ifa_addr,
+ ifa->ifa_addr->sa_len);
+ iface->ifp = tif;
+ iface->primary_address = foo.sin_addr;
+ }
+ addr.len = 4;
+ memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len);
+ }
+ }
+
+ if (!iface->ifp)
+ error("%s: not found", iface->name);
+
+ /* Register the interface... */
+ if_register_receive(iface);
+ if_register_send(iface);
+ add_protocol(iface->name, iface->rfdesc, got_one, iface);
+ freeifaddrs(ifap);
+}
+
+void
+reinitialize_interfaces(void)
+{
+ interfaces_invalidated = 1;
+}
+
+/*
+ * Wait for packets to come in using poll(). When a packet comes in,
+ * call receive_packet to receive the packet and possibly strip hardware
+ * addressing information from it, and then call through the
+ * bootp_packet_handler hook to try to do something with it.
+ */
+void
+dispatch(void)
+{
+ int count, live_interfaces, i, to_msec, nfds = 0;
+ struct protocol *l;
+ struct pollfd *fds;
+ time_t howlong;
+
+ for (l = protocols; l; l = l->next)
+ nfds++;
+
+ fds = malloc(nfds * sizeof(struct pollfd));
+ if (fds == NULL)
+ error("Can't allocate poll structures.");
+
+ do {
+ /*
+ * Call any expired timeouts, and then if there's still
+ * a timeout registered, time out the select call then.
+ */
+another:
+ if (timeouts) {
+ struct timeout *t;
+
+ if (timeouts->when <= cur_time) {
+ t = timeouts;
+ timeouts = timeouts->next;
+ (*(t->func))(t->what);
+ t->next = free_timeouts;
+ free_timeouts = t;
+ goto another;
+ }
+
+ /*
+ * Figure timeout in milliseconds, and check for
+ * potential overflow, so we can cram into an
+ * int for poll, while not polling with a
+ * negative timeout and blocking indefinitely.
+ */
+ howlong = timeouts->when - cur_time;
+ if (howlong > INT_MAX / 1000)
+ howlong = INT_MAX / 1000;
+ to_msec = howlong * 1000;
+ } else
+ to_msec = -1;
+
+ /* Set up the descriptors to be polled. */
+ live_interfaces = 0;
+ for (i = 0, l = protocols; l; l = l->next) {
+ struct interface_info *ip = l->local;
+
+ if (ip == NULL || ip->dead)
+ continue;
+ fds[i].fd = l->fd;
+ fds[i].events = POLLIN;
+ fds[i].revents = 0;
+ i++;
+ if (l->handler == got_one)
+ live_interfaces++;
+ }
+ if (live_interfaces == 0)
+ error("No live interfaces to poll on - exiting.");
+
+ /* Wait for a packet or a timeout... XXX */
+ count = poll(fds, nfds, to_msec);
+
+ /* Not likely to be transitory... */
+ if (count == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ time(&cur_time);
+ continue;
+ } else
+ error("poll: %m");
+ }
+
+ /* Get the current time... */
+ time(&cur_time);
+
+ i = 0;
+ for (l = protocols; l; l = l->next) {
+ struct interface_info *ip;
+ ip = l->local;
+ if ((fds[i].revents & (POLLIN | POLLHUP))) {
+ fds[i].revents = 0;
+ if (ip && (l->handler != got_one ||
+ !ip->dead))
+ (*(l->handler))(l);
+ if (interfaces_invalidated)
+ break;
+ }
+ i++;
+ }
+ interfaces_invalidated = 0;
+ } while (1);
+}
+
+
+void
+got_one(struct protocol *l)
+{
+ struct sockaddr_in from;
+ struct hardware hfrom;
+ struct iaddr ifrom;
+ ssize_t result;
+ union {
+ /*
+ * Packet input buffer. Must be as large as largest
+ * possible MTU.
+ */
+ unsigned char packbuf[4095];
+ struct dhcp_packet packet;
+ } u;
+ struct interface_info *ip = l->local;
+
+ if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from,
+ &hfrom)) == -1) {
+ warning("receive_packet failed on %s: %s", ip->name,
+ strerror(errno));
+ ip->errors++;
+ if ((!interface_status(ip)) ||
+ (ip->noifmedia && ip->errors > 20)) {
+ /* our interface has gone away. */
+ warning("Interface %s no longer appears valid.",
+ ip->name);
+ ip->dead = 1;
+ interfaces_invalidated = 1;
+ close(l->fd);
+ remove_protocol(l);
+ free(ip);
+ }
+ return;
+ }
+ if (result == 0)
+ return;
+
+ if (bootp_packet_handler) {
+ ifrom.len = 4;
+ memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
+
+ (*bootp_packet_handler)(ip, &u.packet, result,
+ from.sin_port, ifrom, &hfrom);
+ }
+}
+
+int
+interface_status(struct interface_info *ifinfo)
+{
+ char *ifname = ifinfo->name;
+ int ifsock = ifinfo->rfdesc;
+ struct ifreq ifr;
+ struct ifmediareq ifmr;
+
+ /* get interface flags */
+ memset(&ifr, 0, sizeof(ifr));
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) {
+ syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", ifname);
+ goto inactive;
+ }
+
+ /*
+ * if one of UP and RUNNING flags is dropped,
+ * the interface is not active.
+ */
+ if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING))
+ goto inactive;
+
+ /* Next, check carrier on the interface, if possible */
+ if (ifinfo->noifmedia)
+ goto active;
+ memset(&ifmr, 0, sizeof(ifmr));
+ strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+ if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+ if (errno != EINVAL) {
+ syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m",
+ ifname);
+
+ ifinfo->noifmedia = 1;
+ goto active;
+ }
+ /*
+ * EINVAL (or ENOTTY) simply means that the interface
+ * does not support the SIOCGIFMEDIA ioctl. We regard it alive.
+ */
+ ifinfo->noifmedia = 1;
+ goto active;
+ }
+ if (ifmr.ifm_status & IFM_AVALID) {
+ switch (ifmr.ifm_active & IFM_NMASK) {
+ case IFM_ETHER:
+ case IFM_IEEE80211:
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ goto active;
+ else
+ goto inactive;
+ break;
+ default:
+ goto inactive;
+ }
+ }
+inactive:
+ return (0);
+active:
+ return (1);
+}
+
+void
+add_timeout(time_t when, void (*where)(void *), void *what)
+{
+ struct timeout *t, *q;
+
+ /* See if this timeout supersedes an existing timeout. */
+ t = NULL;
+ for (q = timeouts; q; q = q->next) {
+ if (q->func == where && q->what == what) {
+ if (t)
+ t->next = q->next;
+ else
+ timeouts = q->next;
+ break;
+ }
+ t = q;
+ }
+
+ /* If we didn't supersede a timeout, allocate a timeout
+ structure now. */
+ if (!q) {
+ if (free_timeouts) {
+ q = free_timeouts;
+ free_timeouts = q->next;
+ q->func = where;
+ q->what = what;
+ } else {
+ q = malloc(sizeof(struct timeout));
+ if (!q)
+ error("Can't allocate timeout structure!");
+ q->func = where;
+ q->what = what;
+ }
+ }
+
+ q->when = when;
+
+ /* Now sort this timeout into the timeout list. */
+
+ /* Beginning of list? */
+ if (!timeouts || timeouts->when > q->when) {
+ q->next = timeouts;
+ timeouts = q;
+ return;
+ }
+
+ /* Middle of list? */
+ for (t = timeouts; t->next; t = t->next) {
+ if (t->next->when > q->when) {
+ q->next = t->next;
+ t->next = q;
+ return;
+ }
+ }
+
+ /* End of list. */
+ t->next = q;
+ q->next = NULL;
+}
+
+void
+cancel_timeout(void (*where)(void *), void *what)
+{
+ struct timeout *t, *q;
+
+ /* Look for this timeout on the list, and unlink it if we find it. */
+ t = NULL;
+ for (q = timeouts; q; q = q->next) {
+ if (q->func == where && q->what == what) {
+ if (t)
+ t->next = q->next;
+ else
+ timeouts = q->next;
+ break;
+ }
+ t = q;
+ }
+
+ /* If we found the timeout, put it on the free list. */
+ if (q) {
+ q->next = free_timeouts;
+ free_timeouts = q;
+ }
+}
+
+/* Add a protocol to the list of protocols... */
+void
+add_protocol(char *name, int fd, void (*handler)(struct protocol *),
+ void *local)
+{
+ struct protocol *p;
+
+ p = malloc(sizeof(*p));
+ if (!p)
+ error("can't allocate protocol struct for %s", name);
+
+ p->fd = fd;
+ p->handler = handler;
+ p->local = local;
+ p->next = protocols;
+ protocols = p;
+}
+
+void
+remove_protocol(struct protocol *proto)
+{
+ struct protocol *p, *next, *prev;
+
+ prev = NULL;
+ for (p = protocols; p; p = next) {
+ next = p->next;
+ if (p == proto) {
+ if (prev)
+ prev->next = p->next;
+ else
+ protocols = p->next;
+ free(p);
+ }
+ }
+}
+
+int
+interface_link_status(char *ifname)
+{
+ struct ifmediareq ifmr;
+ int sock;
+
+ if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
+ error("Can't create socket");
+
+ memset(&ifmr, 0, sizeof(ifmr));
+ strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name));
+ if (ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmr) == -1) {
+ /* EINVAL -> link state unknown. treat as active */
+ if (errno != EINVAL)
+ syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m",
+ ifname);
+ close(sock);
+ return (1);
+ }
+ close(sock);
+
+ if (ifmr.ifm_status & IFM_AVALID) {
+ switch (ifmr.ifm_active & IFM_NMASK) {
+ case IFM_ETHER:
+ case IFM_IEEE80211:
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ return (1);
+ else
+ return (0);
+ }
+ }
+ return (1);
+}
diff --git a/freebsd/sbin/dhclient/errwarn.c b/freebsd/sbin/dhclient/errwarn.c
new file mode 100644
index 00000000..de345832
--- /dev/null
+++ b/freebsd/sbin/dhclient/errwarn.c
@@ -0,0 +1,237 @@
+/* $OpenBSD: errwarn.c,v 1.7 2004/05/04 22:23:01 mickey Exp $ */
+
+/* Errors and warnings... */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium.
+ * All Rights Reserved.
+ * Copyright (c) 1995 RadioMail 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 RadioMail Corporation, the Internet Software
+ * Consortium 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 RADIOMAIL CORPORATION, THE INTERNET
+ * SOFTWARE CONSORTIUM 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 RADIOMAIL CORPORATION 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 software was written for RadioMail Corporation by Ted Lemon
+ * under a contract with Vixie Enterprises. Further modifications have
+ * been made for the Internet Software Consortium under a contract
+ * with Vixie Laboratories.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+
+#include "dhcpd.h"
+
+static void do_percentm(char *obuf, size_t size, char *ibuf);
+
+static char mbuf[1024];
+static char fbuf[1024];
+
+int warnings_occurred;
+
+/*
+ * Log an error message, then exit.
+ */
+void
+error(char *fmt, ...)
+{
+ va_list list;
+
+ do_percentm(fbuf, sizeof(fbuf), fmt);
+
+ va_start(list, fmt);
+ vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
+ va_end(list);
+
+#ifndef DEBUG
+ syslog(log_priority | LOG_ERR, "%s", mbuf);
+#endif
+
+ /* Also log it to stderr? */
+ if (log_perror) {
+ write(2, mbuf, strlen(mbuf));
+ write(2, "\n", 1);
+ }
+
+ syslog(LOG_CRIT, "exiting.");
+ if (log_perror) {
+ fprintf(stderr, "exiting.\n");
+ fflush(stderr);
+ }
+ exit(1);
+}
+
+/*
+ * Log a warning message...
+ */
+int
+warning(char *fmt, ...)
+{
+ va_list list;
+
+ do_percentm(fbuf, sizeof(fbuf), fmt);
+
+ va_start(list, fmt);
+ vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
+ va_end(list);
+
+#ifndef DEBUG
+ syslog(log_priority | LOG_ERR, "%s", mbuf);
+#endif
+
+ if (log_perror) {
+ write(2, mbuf, strlen(mbuf));
+ write(2, "\n", 1);
+ }
+
+ return (0);
+}
+
+/*
+ * Log a note...
+ */
+int
+note(char *fmt, ...)
+{
+ va_list list;
+
+ do_percentm(fbuf, sizeof(fbuf), fmt);
+
+ va_start(list, fmt);
+ vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
+ va_end(list);
+
+#ifndef DEBUG
+ syslog(log_priority | LOG_INFO, "%s", mbuf);
+#endif
+
+ if (log_perror) {
+ write(2, mbuf, strlen(mbuf));
+ write(2, "\n", 1);
+ }
+
+ return (0);
+}
+
+/*
+ * Log a debug message...
+ */
+int
+debug(char *fmt, ...)
+{
+ va_list list;
+
+ do_percentm(fbuf, sizeof(fbuf), fmt);
+
+ va_start(list, fmt);
+ vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
+ va_end(list);
+
+#ifndef DEBUG
+ syslog(log_priority | LOG_DEBUG, "%s", mbuf);
+#endif
+
+ if (log_perror) {
+ write(2, mbuf, strlen(mbuf));
+ write(2, "\n", 1);
+ }
+
+ return (0);
+}
+
+/*
+ * Find %m in the input string and substitute an error message string.
+ */
+static void
+do_percentm(char *obuf, size_t size, char *ibuf)
+{
+ char ch;
+ char *s = ibuf;
+ char *t = obuf;
+ size_t prlen;
+ size_t fmt_left;
+ int saved_errno = errno;
+
+ /*
+ * We wouldn't need this mess if printf handled %m, or if
+ * strerror() had been invented before syslog().
+ */
+ for (fmt_left = size; (ch = *s); ++s) {
+ if (ch == '%' && s[1] == 'm') {
+ ++s;
+ prlen = snprintf(t, fmt_left, "%s",
+ strerror(saved_errno));
+ if (prlen >= fmt_left)
+ prlen = fmt_left - 1;
+ t += prlen;
+ fmt_left -= prlen;
+ } else {
+ if (fmt_left > 1) {
+ *t++ = ch;
+ fmt_left--;
+ }
+ }
+ }
+ *t = '\0';
+}
+
+int
+parse_warn(char *fmt, ...)
+{
+ va_list list;
+ static char spaces[] =
+ " "
+ " "; /* 80 spaces */
+
+ do_percentm(mbuf, sizeof(mbuf), fmt);
+ snprintf(fbuf, sizeof(fbuf), "%s line %d: %s", tlname, lexline, mbuf);
+ va_start(list, fmt);
+ vsnprintf(mbuf, sizeof(mbuf), fbuf, list);
+ va_end(list);
+
+#ifndef DEBUG
+ syslog(log_priority | LOG_ERR, "%s", mbuf);
+ syslog(log_priority | LOG_ERR, "%s", token_line);
+ if (lexline < 81)
+ syslog(log_priority | LOG_ERR,
+ "%s^", &spaces[sizeof(spaces) - lexchar]);
+#endif
+
+ if (log_perror) {
+ write(2, mbuf, strlen(mbuf));
+ write(2, "\n", 1);
+ write(2, token_line, strlen(token_line));
+ write(2, "\n", 1);
+ write(2, spaces, lexchar - 1);
+ write(2, "^\n", 2);
+ }
+
+ warnings_occurred = 1;
+
+ return (0);
+}
diff --git a/freebsd/sbin/dhclient/hash.c b/freebsd/sbin/dhclient/hash.c
new file mode 100644
index 00000000..040236ab
--- /dev/null
+++ b/freebsd/sbin/dhclient/hash.c
@@ -0,0 +1,122 @@
+/* $OpenBSD: hash.c,v 1.9 2004/05/10 15:30:47 deraadt Exp $ */
+
+/* Routines for manipulating hash tables... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+static int do_hash(unsigned char *, int, int);
+
+struct hash_table *
+new_hash(void)
+{
+ struct hash_table *rv = new_hash_table(DEFAULT_HASH_SIZE);
+
+ if (!rv)
+ return (rv);
+ memset(&rv->buckets[0], 0,
+ DEFAULT_HASH_SIZE * sizeof(struct hash_bucket *));
+ return (rv);
+}
+
+static int
+do_hash(unsigned char *name, int len, int size)
+{
+ unsigned char *s = name;
+ int accum = 0, i = len;
+
+ while (i--) {
+ /* Add the character in... */
+ accum += *s++;
+ /* Add carry back in... */
+ while (accum > 255)
+ accum = (accum & 255) + (accum >> 8);
+ }
+ return (accum % size);
+}
+
+void add_hash(struct hash_table *table, unsigned char *name, int len,
+ unsigned char *pointer)
+{
+ struct hash_bucket *bp;
+ int hashno;
+
+ if (!table)
+ return;
+ if (!len)
+ len = strlen((char *)name);
+
+ hashno = do_hash(name, len, table->hash_count);
+ bp = new_hash_bucket();
+
+ if (!bp) {
+ warning("Can't add %s to hash table.", name);
+ return;
+ }
+ bp->name = name;
+ bp->value = pointer;
+ bp->next = table->buckets[hashno];
+ bp->len = len;
+ table->buckets[hashno] = bp;
+}
+
+unsigned char *
+hash_lookup(struct hash_table *table, unsigned char *name, int len)
+{
+ struct hash_bucket *bp;
+ int hashno;
+
+ if (!table)
+ return (NULL);
+
+ if (!len)
+ len = strlen((char *)name);
+
+ hashno = do_hash(name, len, table->hash_count);
+
+ for (bp = table->buckets[hashno]; bp; bp = bp->next)
+ if (len == bp->len && !memcmp(bp->name, name, len))
+ return (bp->value);
+
+ return (NULL);
+}
diff --git a/freebsd/sbin/dhclient/inet.c b/freebsd/sbin/dhclient/inet.c
new file mode 100644
index 00000000..4b7b1cef
--- /dev/null
+++ b/freebsd/sbin/dhclient/inet.c
@@ -0,0 +1,121 @@
+/* $OpenBSD: inet.c,v 1.7 2004/05/04 21:48:16 deraadt Exp $ */
+
+/*
+ * Subroutines to manipulate internet addresses in a safely portable
+ * way...
+ */
+
+/*
+ * Copyright (c) 1996 The Internet Software Consortium. 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+/*
+ * Return just the network number of an internet address...
+ */
+struct iaddr
+subnet_number(struct iaddr addr, struct iaddr mask)
+{
+ struct iaddr rv;
+ int i;
+
+ rv.len = 0;
+
+ /* Both addresses must have the same length... */
+ if (addr.len != mask.len)
+ return (rv);
+
+ rv.len = addr.len;
+ for (i = 0; i < rv.len; i++)
+ rv.iabuf[i] = addr.iabuf[i] & mask.iabuf[i];
+ return (rv);
+}
+
+/*
+ * Given a subnet number and netmask, return the address on that subnet
+ * for which the host portion of the address is all ones (the standard
+ * broadcast address).
+ */
+struct iaddr
+broadcast_addr(struct iaddr subnet, struct iaddr mask)
+{
+ struct iaddr rv;
+ int i;
+
+ if (subnet.len != mask.len) {
+ rv.len = 0;
+ return (rv);
+ }
+
+ for (i = 0; i < subnet.len; i++)
+ rv.iabuf[i] = subnet.iabuf[i] | (~mask.iabuf[i] & 255);
+ rv.len = subnet.len;
+
+ return (rv);
+}
+
+int
+addr_eq(struct iaddr addr1, struct iaddr addr2)
+{
+ if (addr1.len != addr2.len)
+ return (0);
+ return (memcmp(addr1.iabuf, addr2.iabuf, addr1.len) == 0);
+}
+
+char *
+piaddr(struct iaddr addr)
+{
+ static char pbuf[32];
+ struct in_addr a;
+ char *s;
+
+ memcpy(&a, &(addr.iabuf), sizeof(struct in_addr));
+
+ if (addr.len == 0)
+ strlcpy(pbuf, "<null address>", sizeof(pbuf));
+ else {
+ s = inet_ntoa(a);
+ if (s != NULL)
+ strlcpy(pbuf, s, sizeof(pbuf));
+ else
+ strlcpy(pbuf, "<invalid address>", sizeof(pbuf));
+ }
+ return (pbuf);
+}
diff --git a/freebsd/sbin/dhclient/options.c b/freebsd/sbin/dhclient/options.c
new file mode 100644
index 00000000..09aa4d8f
--- /dev/null
+++ b/freebsd/sbin/dhclient/options.c
@@ -0,0 +1,720 @@
+/* $OpenBSD: options.c,v 1.15 2004/12/26 03:17:07 deraadt Exp $ */
+
+/* DHCP options parsing and reassembly. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+
+#define DHCP_OPTION_DATA
+#include "dhcpd.h"
+
+int bad_options = 0;
+int bad_options_max = 5;
+
+void parse_options(struct packet *);
+void parse_option_buffer(struct packet *, unsigned char *, int);
+int store_options(unsigned char *, int, struct tree_cache **,
+ unsigned char *, int, int, int, int);
+
+
+/*
+ * Parse all available options out of the specified packet.
+ */
+void
+parse_options(struct packet *packet)
+{
+ /* Initially, zero all option pointers. */
+ memset(packet->options, 0, sizeof(packet->options));
+
+ /* If we don't see the magic cookie, there's nothing to parse. */
+ if (memcmp(packet->raw->options, DHCP_OPTIONS_COOKIE, 4)) {
+ packet->options_valid = 0;
+ return;
+ }
+
+ /*
+ * Go through the options field, up to the end of the packet or
+ * the End field.
+ */
+ parse_option_buffer(packet, &packet->raw->options[4],
+ packet->packet_length - DHCP_FIXED_NON_UDP - 4);
+
+ /*
+ * If we parsed a DHCP Option Overload option, parse more
+ * options out of the buffer(s) containing them.
+ */
+ if (packet->options_valid &&
+ packet->options[DHO_DHCP_OPTION_OVERLOAD].data) {
+ if (packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)
+ parse_option_buffer(packet,
+ (unsigned char *)packet->raw->file,
+ sizeof(packet->raw->file));
+ if (packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)
+ parse_option_buffer(packet,
+ (unsigned char *)packet->raw->sname,
+ sizeof(packet->raw->sname));
+ }
+}
+
+/*
+ * Parse options out of the specified buffer, storing addresses of
+ * option values in packet->options and setting packet->options_valid if
+ * no errors are encountered.
+ */
+void
+parse_option_buffer(struct packet *packet,
+ unsigned char *buffer, int length)
+{
+ unsigned char *s, *t, *end = buffer + length;
+ int len, code;
+
+ for (s = buffer; *s != DHO_END && s < end; ) {
+ code = s[0];
+
+ /* Pad options don't have a length - just skip them. */
+ if (code == DHO_PAD) {
+ s++;
+ continue;
+ }
+ if (s + 2 > end) {
+ len = 65536;
+ goto bogus;
+ }
+
+ /*
+ * All other fields (except end, see above) have a
+ * one-byte length.
+ */
+ len = s[1];
+
+ /*
+ * If the length is outrageous, silently skip the rest,
+ * and mark the packet bad. Unfortunately some crappy
+ * dhcp servers always seem to give us garbage on the
+ * end of a packet. so rather than keep refusing, give
+ * up and try to take one after seeing a few without
+ * anything good.
+ */
+ if (s + len + 2 > end) {
+ bogus:
+ bad_options++;
+ warning("option %s (%d) %s.",
+ dhcp_options[code].name, len,
+ "larger than buffer");
+ if (bad_options == bad_options_max) {
+ packet->options_valid = 1;
+ bad_options = 0;
+ warning("Many bogus options seen in offers. "
+ "Taking this offer in spite of bogus "
+ "options - hope for the best!");
+ } else {
+ warning("rejecting bogus offer.");
+ packet->options_valid = 0;
+ }
+ return;
+ }
+ /*
+ * If we haven't seen this option before, just make
+ * space for it and copy it there.
+ */
+ if (!packet->options[code].data) {
+ if (!(t = calloc(1, len + 1)))
+ error("Can't allocate storage for option %s.",
+ dhcp_options[code].name);
+ /*
+ * Copy and NUL-terminate the option (in case
+ * it's an ASCII string.
+ */
+ memcpy(t, &s[2], len);
+ t[len] = 0;
+ packet->options[code].len = len;
+ packet->options[code].data = t;
+ } else {
+ /*
+ * If it's a repeat, concatenate it to whatever
+ * we last saw. This is really only required
+ * for clients, but what the heck...
+ */
+ t = calloc(1, len + packet->options[code].len + 1);
+ if (!t)
+ error("Can't expand storage for option %s.",
+ dhcp_options[code].name);
+ memcpy(t, packet->options[code].data,
+ packet->options[code].len);
+ memcpy(t + packet->options[code].len,
+ &s[2], len);
+ packet->options[code].len += len;
+ t[packet->options[code].len] = 0;
+ free(packet->options[code].data);
+ packet->options[code].data = t;
+ }
+ s += len + 2;
+ }
+ packet->options_valid = 1;
+}
+
+/*
+ * cons options into a big buffer, and then split them out into the
+ * three separate buffers if needed. This allows us to cons up a set of
+ * vendor options using the same routine.
+ */
+int
+cons_options(struct packet *inpacket, struct dhcp_packet *outpacket,
+ int mms, struct tree_cache **options,
+ int overload, /* Overload flags that may be set. */
+ int terminate, int bootpp, u_int8_t *prl, int prl_len)
+{
+ unsigned char priority_list[300], buffer[4096];
+ int priority_len, main_buffer_size, mainbufix, bufix;
+ int option_size, length;
+
+ /*
+ * If the client has provided a maximum DHCP message size, use
+ * that; otherwise, if it's BOOTP, only 64 bytes; otherwise use
+ * up to the minimum IP MTU size (576 bytes).
+ *
+ * XXX if a BOOTP client specifies a max message size, we will
+ * honor it.
+ */
+ if (!mms &&
+ inpacket &&
+ inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data &&
+ (inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].len >=
+ sizeof(u_int16_t)))
+ mms = getUShort(
+ inpacket->options[DHO_DHCP_MAX_MESSAGE_SIZE].data);
+
+ if (mms)
+ main_buffer_size = mms - DHCP_FIXED_LEN;
+ else if (bootpp)
+ main_buffer_size = 64;
+ else
+ main_buffer_size = 576 - DHCP_FIXED_LEN;
+
+ if (main_buffer_size > sizeof(buffer))
+ main_buffer_size = sizeof(buffer);
+
+ /* Preload the option priority list with mandatory options. */
+ priority_len = 0;
+ priority_list[priority_len++] = DHO_DHCP_MESSAGE_TYPE;
+ priority_list[priority_len++] = DHO_DHCP_SERVER_IDENTIFIER;
+ priority_list[priority_len++] = DHO_DHCP_LEASE_TIME;
+ priority_list[priority_len++] = DHO_DHCP_MESSAGE;
+
+ /*
+ * If the client has provided a list of options that it wishes
+ * returned, use it to prioritize. Otherwise, prioritize based
+ * on the default priority list.
+ */
+ if (inpacket &&
+ inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data) {
+ int prlen =
+ inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].len;
+ if (prlen + priority_len > sizeof(priority_list))
+ prlen = sizeof(priority_list) - priority_len;
+
+ memcpy(&priority_list[priority_len],
+ inpacket->options[DHO_DHCP_PARAMETER_REQUEST_LIST].data,
+ prlen);
+ priority_len += prlen;
+ prl = priority_list;
+ } else if (prl) {
+ if (prl_len + priority_len > sizeof(priority_list))
+ prl_len = sizeof(priority_list) - priority_len;
+
+ memcpy(&priority_list[priority_len], prl, prl_len);
+ priority_len += prl_len;
+ prl = priority_list;
+ } else {
+ memcpy(&priority_list[priority_len],
+ dhcp_option_default_priority_list,
+ sizeof_dhcp_option_default_priority_list);
+ priority_len += sizeof_dhcp_option_default_priority_list;
+ }
+
+ /* Copy the options into the big buffer... */
+ option_size = store_options(
+ buffer,
+ (main_buffer_size - 7 + ((overload & 1) ? DHCP_FILE_LEN : 0) +
+ ((overload & 2) ? DHCP_SNAME_LEN : 0)),
+ options, priority_list, priority_len, main_buffer_size,
+ (main_buffer_size + ((overload & 1) ? DHCP_FILE_LEN : 0)),
+ terminate);
+
+ /* Put the cookie up front... */
+ memcpy(outpacket->options, DHCP_OPTIONS_COOKIE, 4);
+ mainbufix = 4;
+
+ /*
+ * If we're going to have to overload, store the overload option
+ * at the beginning. If we can, though, just store the whole
+ * thing in the packet's option buffer and leave it at that.
+ */
+ if (option_size <= main_buffer_size - mainbufix) {
+ memcpy(&outpacket->options[mainbufix],
+ buffer, option_size);
+ mainbufix += option_size;
+ if (mainbufix < main_buffer_size)
+ outpacket->options[mainbufix++] = DHO_END;
+ length = DHCP_FIXED_NON_UDP + mainbufix;
+ } else {
+ outpacket->options[mainbufix++] = DHO_DHCP_OPTION_OVERLOAD;
+ outpacket->options[mainbufix++] = 1;
+ if (option_size >
+ main_buffer_size - mainbufix + DHCP_FILE_LEN)
+ outpacket->options[mainbufix++] = 3;
+ else
+ outpacket->options[mainbufix++] = 1;
+
+ memcpy(&outpacket->options[mainbufix],
+ buffer, main_buffer_size - mainbufix);
+ bufix = main_buffer_size - mainbufix;
+ length = DHCP_FIXED_NON_UDP + mainbufix;
+ if (overload & 1) {
+ if (option_size - bufix <= DHCP_FILE_LEN) {
+ memcpy(outpacket->file,
+ &buffer[bufix], option_size - bufix);
+ mainbufix = option_size - bufix;
+ if (mainbufix < DHCP_FILE_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_END;
+ while (mainbufix < DHCP_FILE_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_PAD;
+ } else {
+ memcpy(outpacket->file,
+ &buffer[bufix], DHCP_FILE_LEN);
+ bufix += DHCP_FILE_LEN;
+ }
+ }
+ if ((overload & 2) && option_size < bufix) {
+ memcpy(outpacket->sname,
+ &buffer[bufix], option_size - bufix);
+
+ mainbufix = option_size - bufix;
+ if (mainbufix < DHCP_SNAME_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_END;
+ while (mainbufix < DHCP_SNAME_LEN)
+ outpacket->file[mainbufix++] = (char)DHO_PAD;
+ }
+ }
+ return (length);
+}
+
+/*
+ * Store all the requested options into the requested buffer.
+ */
+int
+store_options(unsigned char *buffer, int buflen, struct tree_cache **options,
+ unsigned char *priority_list, int priority_len, int first_cutoff,
+ int second_cutoff, int terminate)
+{
+ int bufix = 0, option_stored[256], i, ix, tto;
+
+ /* Zero out the stored-lengths array. */
+ memset(option_stored, 0, sizeof(option_stored));
+
+ /*
+ * Copy out the options in the order that they appear in the
+ * priority list...
+ */
+ for (i = 0; i < priority_len; i++) {
+ /* Code for next option to try to store. */
+ int code = priority_list[i];
+ int optstart;
+
+ /*
+ * Number of bytes left to store (some may already have
+ * been stored by a previous pass).
+ */
+ int length;
+
+ /* If no data is available for this option, skip it. */
+ if (!options[code]) {
+ continue;
+ }
+
+ /*
+ * The client could ask for things that are mandatory,
+ * in which case we should avoid storing them twice...
+ */
+ if (option_stored[code])
+ continue;
+ option_stored[code] = 1;
+
+ /* We should now have a constant length for the option. */
+ length = options[code]->len;
+
+ /* Do we add a NUL? */
+ if (terminate && dhcp_options[code].format[0] == 't') {
+ length++;
+ tto = 1;
+ } else
+ tto = 0;
+
+ /* Try to store the option. */
+
+ /*
+ * If the option's length is more than 255, we must
+ * store it in multiple hunks. Store 255-byte hunks
+ * first. However, in any case, if the option data will
+ * cross a buffer boundary, split it across that
+ * boundary.
+ */
+ ix = 0;
+
+ optstart = bufix;
+ while (length) {
+ unsigned char incr = length > 255 ? 255 : length;
+
+ /*
+ * If this hunk of the buffer will cross a
+ * boundary, only go up to the boundary in this
+ * pass.
+ */
+ if (bufix < first_cutoff &&
+ bufix + incr > first_cutoff)
+ incr = first_cutoff - bufix;
+ else if (bufix < second_cutoff &&
+ bufix + incr > second_cutoff)
+ incr = second_cutoff - bufix;
+
+ /*
+ * If this option is going to overflow the
+ * buffer, skip it.
+ */
+ if (bufix + 2 + incr > buflen) {
+ bufix = optstart;
+ break;
+ }
+
+ /* Everything looks good - copy it in! */
+ buffer[bufix] = code;
+ buffer[bufix + 1] = incr;
+ if (tto && incr == length) {
+ memcpy(buffer + bufix + 2,
+ options[code]->value + ix, incr - 1);
+ buffer[bufix + 2 + incr - 1] = 0;
+ } else
+ memcpy(buffer + bufix + 2,
+ options[code]->value + ix, incr);
+ length -= incr;
+ ix += incr;
+ bufix += 2 + incr;
+ }
+ }
+ return (bufix);
+}
+
+/*
+ * Format the specified option so that a human can easily read it.
+ */
+char *
+pretty_print_option(unsigned int code, unsigned char *data, int len,
+ int emit_commas, int emit_quotes)
+{
+ static char optbuf[32768]; /* XXX */
+ int hunksize = 0, numhunk = -1, numelem = 0;
+ char fmtbuf[32], *op = optbuf;
+ int i, j, k, opleft = sizeof(optbuf);
+ unsigned char *dp = data;
+ struct in_addr foo;
+ char comma;
+
+ /* Code should be between 0 and 255. */
+ if (code > 255)
+ error("pretty_print_option: bad code %d", code);
+
+ if (emit_commas)
+ comma = ',';
+ else
+ comma = ' ';
+
+ /* Figure out the size of the data. */
+ for (i = 0; dhcp_options[code].format[i]; i++) {
+ if (!numhunk) {
+ warning("%s: Excess information in format string: %s",
+ dhcp_options[code].name,
+ &(dhcp_options[code].format[i]));
+ break;
+ }
+ numelem++;
+ fmtbuf[i] = dhcp_options[code].format[i];
+ switch (dhcp_options[code].format[i]) {
+ case 'A':
+ --numelem;
+ fmtbuf[i] = 0;
+ numhunk = 0;
+ break;
+ case 'X':
+ for (k = 0; k < len; k++)
+ if (!isascii(data[k]) ||
+ !isprint(data[k]))
+ break;
+ if (k == len) {
+ fmtbuf[i] = 't';
+ numhunk = -2;
+ } else {
+ fmtbuf[i] = 'x';
+ hunksize++;
+ comma = ':';
+ numhunk = 0;
+ }
+ fmtbuf[i + 1] = 0;
+ break;
+ case 't':
+ fmtbuf[i] = 't';
+ fmtbuf[i + 1] = 0;
+ numhunk = -2;
+ break;
+ case 'I':
+ case 'l':
+ case 'L':
+ hunksize += 4;
+ break;
+ case 's':
+ case 'S':
+ hunksize += 2;
+ break;
+ case 'b':
+ case 'B':
+ case 'f':
+ hunksize++;
+ break;
+ case 'e':
+ break;
+ default:
+ warning("%s: garbage in format string: %s",
+ dhcp_options[code].name,
+ &(dhcp_options[code].format[i]));
+ break;
+ }
+ }
+
+ /* Check for too few bytes... */
+ if (hunksize > len) {
+ warning("%s: expecting at least %d bytes; got %d",
+ dhcp_options[code].name, hunksize, len);
+ return ("<error>");
+ }
+ /* Check for too many bytes... */
+ if (numhunk == -1 && hunksize < len)
+ warning("%s: %d extra bytes",
+ dhcp_options[code].name, len - hunksize);
+
+ /* If this is an array, compute its size. */
+ if (!numhunk)
+ numhunk = len / hunksize;
+ /* See if we got an exact number of hunks. */
+ if (numhunk > 0 && numhunk * hunksize < len)
+ warning("%s: %d extra bytes at end of array",
+ dhcp_options[code].name, len - numhunk * hunksize);
+
+ /* A one-hunk array prints the same as a single hunk. */
+ if (numhunk < 0)
+ numhunk = 1;
+
+ /* Cycle through the array (or hunk) printing the data. */
+ for (i = 0; i < numhunk; i++) {
+ for (j = 0; j < numelem; j++) {
+ int opcount;
+ switch (fmtbuf[j]) {
+ case 't':
+ if (emit_quotes) {
+ *op++ = '"';
+ opleft--;
+ }
+ for (; dp < data + len; dp++) {
+ if (!isascii(*dp) ||
+ !isprint(*dp)) {
+ if (dp + 1 != data + len ||
+ *dp != 0) {
+ snprintf(op, opleft,
+ "\\%03o", *dp);
+ op += 4;
+ opleft -= 4;
+ }
+ } else if (*dp == '"' ||
+ *dp == '\'' ||
+ *dp == '$' ||
+ *dp == '`' ||
+ *dp == '\\') {
+ *op++ = '\\';
+ *op++ = *dp;
+ opleft -= 2;
+ } else {
+ *op++ = *dp;
+ opleft--;
+ }
+ }
+ if (emit_quotes) {
+ *op++ = '"';
+ opleft--;
+ }
+
+ *op = 0;
+ break;
+ case 'I':
+ foo.s_addr = htonl(getULong(dp));
+ opcount = strlcpy(op, inet_ntoa(foo), opleft);
+ if (opcount >= opleft)
+ goto toobig;
+ opleft -= opcount;
+ dp += 4;
+ break;
+ case 'l':
+ opcount = snprintf(op, opleft, "%ld",
+ (long)getLong(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 4;
+ break;
+ case 'L':
+ opcount = snprintf(op, opleft, "%ld",
+ (unsigned long)getULong(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 4;
+ break;
+ case 's':
+ opcount = snprintf(op, opleft, "%d",
+ getShort(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 2;
+ break;
+ case 'S':
+ opcount = snprintf(op, opleft, "%d",
+ getUShort(dp));
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ dp += 2;
+ break;
+ case 'b':
+ opcount = snprintf(op, opleft, "%d",
+ *(char *)dp++);
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ case 'B':
+ opcount = snprintf(op, opleft, "%d", *dp++);
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ case 'x':
+ opcount = snprintf(op, opleft, "%x", *dp++);
+ if (opcount >= opleft || opcount == -1)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ case 'f':
+ opcount = strlcpy(op,
+ *dp++ ? "true" : "false", opleft);
+ if (opcount >= opleft)
+ goto toobig;
+ opleft -= opcount;
+ break;
+ default:
+ warning("Unexpected format code %c", fmtbuf[j]);
+ }
+ op += strlen(op);
+ opleft -= strlen(op);
+ if (opleft < 1)
+ goto toobig;
+ if (j + 1 < numelem && comma != ':') {
+ *op++ = ' ';
+ opleft--;
+ }
+ }
+ if (i + 1 < numhunk) {
+ *op++ = comma;
+ opleft--;
+ }
+ if (opleft < 1)
+ goto toobig;
+
+ }
+ return (optbuf);
+ toobig:
+ warning("dhcp option too large");
+ return ("<error>");
+}
+
+void
+do_packet(struct interface_info *interface, struct dhcp_packet *packet,
+ int len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
+{
+ struct packet tp;
+ int i;
+
+ if (packet->hlen > sizeof(packet->chaddr)) {
+ note("Discarding packet with invalid hlen.");
+ return;
+ }
+
+ memset(&tp, 0, sizeof(tp));
+ tp.raw = packet;
+ tp.packet_length = len;
+ tp.client_port = from_port;
+ tp.client_addr = from;
+ tp.interface = interface;
+ tp.haddr = hfrom;
+
+ parse_options(&tp);
+ if (tp.options_valid &&
+ tp.options[DHO_DHCP_MESSAGE_TYPE].data)
+ tp.packet_type = tp.options[DHO_DHCP_MESSAGE_TYPE].data[0];
+ if (tp.packet_type)
+ dhcp(&tp);
+ else
+ bootp(&tp);
+
+ /* Free the data associated with the options. */
+ for (i = 0; i < 256; i++)
+ if (tp.options[i].len && tp.options[i].data)
+ free(tp.options[i].data);
+}
diff --git a/freebsd/sbin/dhclient/packet.c b/freebsd/sbin/dhclient/packet.c
new file mode 100644
index 00000000..2e90cc85
--- /dev/null
+++ b/freebsd/sbin/dhclient/packet.c
@@ -0,0 +1,267 @@
+/* $OpenBSD: packet.c,v 1.9 2004/05/04 18:58:50 deraadt Exp $ */
+
+/* Packet assembly code, originally contributed by Archie Cobbs. */
+
+/*
+ * Copyright (c) 1995, 1996, 1999 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/udp.h>
+#include <netinet/if_ether.h>
+
+#define ETHER_HEADER_SIZE (ETHER_ADDR_LEN * 2 + sizeof(u_int16_t))
+
+u_int32_t checksum(unsigned char *, unsigned, u_int32_t);
+u_int32_t wrapsum(u_int32_t);
+
+void assemble_ethernet_header(struct interface_info *, unsigned char *,
+ int *, struct hardware *);
+ssize_t decode_ethernet_header(struct interface_info *, unsigned char *,
+ int bufix, struct hardware *);
+
+u_int32_t
+checksum(unsigned char *buf, unsigned nbytes, u_int32_t sum)
+{
+ int i;
+
+ /* Checksum all the pairs of bytes first... */
+ for (i = 0; i < (nbytes & ~1U); i += 2) {
+ sum += (u_int16_t)ntohs(*((u_int16_t *)(buf + i)));
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ }
+
+ /*
+ * If there's a single byte left over, checksum it, too.
+ * Network byte order is big-endian, so the remaining byte is
+ * the high byte.
+ */
+ if (i < nbytes) {
+ sum += buf[i] << 8;
+ if (sum > 0xFFFF)
+ sum -= 0xFFFF;
+ }
+
+ return (sum);
+}
+
+u_int32_t
+wrapsum(u_int32_t sum)
+{
+ sum = ~sum & 0xFFFF;
+ return (htons(sum));
+}
+
+void
+assemble_hw_header(struct interface_info *interface, unsigned char *buf,
+ int *bufix, struct hardware *to)
+{
+ struct ether_header eh;
+
+ if (to != NULL && to->hlen == 6) /* XXX */
+ memcpy(eh.ether_dhost, to->haddr, sizeof(eh.ether_dhost));
+ else
+ memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost));
+ if (interface->hw_address.hlen == sizeof(eh.ether_shost))
+ memcpy(eh.ether_shost, interface->hw_address.haddr,
+ sizeof(eh.ether_shost));
+ else
+ memset(eh.ether_shost, 0x00, sizeof(eh.ether_shost));
+
+ eh.ether_type = htons(ETHERTYPE_IP);
+
+ memcpy(&buf[*bufix], &eh, ETHER_HEADER_SIZE);
+ *bufix += ETHER_HEADER_SIZE;
+}
+
+void
+assemble_udp_ip_header(unsigned char *buf, int *bufix, u_int32_t from,
+ u_int32_t to, unsigned int port, unsigned char *data, int len)
+{
+ struct ip ip;
+ struct udphdr udp;
+
+ ip.ip_v = 4;
+ ip.ip_hl = 5;
+ ip.ip_tos = IPTOS_LOWDELAY;
+ ip.ip_len = htons(sizeof(ip) + sizeof(udp) + len);
+ ip.ip_id = 0;
+ ip.ip_off = 0;
+ ip.ip_ttl = 16;
+ ip.ip_p = IPPROTO_UDP;
+ ip.ip_sum = 0;
+ ip.ip_src.s_addr = from;
+ ip.ip_dst.s_addr = to;
+
+ ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0));
+
+ /*
+ * While the BPF -- used for broadcasts -- expects a "true" IP header
+ * with all the bytes in network byte order, the raw socket interface
+ * which is used for unicasts expects the ip_len field to be in host
+ * byte order. In both cases, the checksum has to be correct, so this
+ * is as good a place as any to turn the bytes around again.
+ */
+ if (to != INADDR_BROADCAST)
+ ip.ip_len = ntohs(ip.ip_len);
+
+ memcpy(&buf[*bufix], &ip, sizeof(ip));
+ *bufix += sizeof(ip);
+
+ udp.uh_sport = htons(LOCAL_PORT); /* XXX */
+ udp.uh_dport = port; /* XXX */
+ udp.uh_ulen = htons(sizeof(udp) + len);
+ memset(&udp.uh_sum, 0, sizeof(udp.uh_sum));
+
+ udp.uh_sum = wrapsum(checksum((unsigned char *)&udp, sizeof(udp),
+ checksum(data, len, checksum((unsigned char *)&ip.ip_src,
+ 2 * sizeof(ip.ip_src),
+ IPPROTO_UDP + (u_int32_t)ntohs(udp.uh_ulen)))));
+
+ memcpy(&buf[*bufix], &udp, sizeof(udp));
+ *bufix += sizeof(udp);
+}
+
+ssize_t
+decode_hw_header(unsigned char *buf, int bufix, struct hardware *from)
+{
+ struct ether_header eh;
+
+ memcpy(&eh, buf + bufix, ETHER_HEADER_SIZE);
+
+ memcpy(from->haddr, eh.ether_shost, sizeof(eh.ether_shost));
+ from->htype = ARPHRD_ETHER;
+ from->hlen = sizeof(eh.ether_shost);
+
+ return (sizeof(eh));
+}
+
+ssize_t
+decode_udp_ip_header(unsigned char *buf, int bufix, struct sockaddr_in *from,
+ unsigned char *data, int buflen)
+{
+ struct ip *ip;
+ struct udphdr *udp;
+ u_int32_t ip_len = (buf[bufix] & 0xf) << 2;
+ u_int32_t sum, usum;
+ static int ip_packets_seen;
+ static int ip_packets_bad_checksum;
+ static int udp_packets_seen;
+ static int udp_packets_bad_checksum;
+ static int udp_packets_length_checked;
+ static int udp_packets_length_overflow;
+ int len = 0;
+
+ ip = (struct ip *)(buf + bufix);
+ udp = (struct udphdr *)(buf + bufix + ip_len);
+
+ /* Check the IP header checksum - it should be zero. */
+ ip_packets_seen++;
+ if (wrapsum(checksum(buf + bufix, ip_len, 0)) != 0) {
+ ip_packets_bad_checksum++;
+ if (ip_packets_seen > 4 &&
+ (ip_packets_seen / ip_packets_bad_checksum) < 2) {
+ note("%d bad IP checksums seen in %d packets",
+ ip_packets_bad_checksum, ip_packets_seen);
+ ip_packets_seen = ip_packets_bad_checksum = 0;
+ }
+ return (-1);
+ }
+
+ if (ntohs(ip->ip_len) != buflen)
+ debug("ip length %d disagrees with bytes received %d.",
+ ntohs(ip->ip_len), buflen);
+
+ memcpy(&from->sin_addr, &ip->ip_src, 4);
+
+ /*
+ * Compute UDP checksums, including the ``pseudo-header'', the
+ * UDP header and the data. If the UDP checksum field is zero,
+ * we're not supposed to do a checksum.
+ */
+ if (!data) {
+ data = buf + bufix + ip_len + sizeof(*udp);
+ len = ntohs(udp->uh_ulen) - sizeof(*udp);
+ udp_packets_length_checked++;
+ if (len + data > buf + bufix + buflen) {
+ udp_packets_length_overflow++;
+ if (udp_packets_length_checked > 4 &&
+ (udp_packets_length_checked /
+ udp_packets_length_overflow) < 2) {
+ note("%d udp packets in %d too long - dropped",
+ udp_packets_length_overflow,
+ udp_packets_length_checked);
+ udp_packets_length_overflow =
+ udp_packets_length_checked = 0;
+ }
+ return (-1);
+ }
+ if (len + data != buf + bufix + buflen)
+ debug("accepting packet with data after udp payload.");
+ }
+
+ usum = udp->uh_sum;
+ udp->uh_sum = 0;
+
+ sum = wrapsum(checksum((unsigned char *)udp, sizeof(*udp),
+ checksum(data, len, checksum((unsigned char *)&ip->ip_src,
+ 2 * sizeof(ip->ip_src),
+ IPPROTO_UDP + (u_int32_t)ntohs(udp->uh_ulen)))));
+
+ udp_packets_seen++;
+ if (usum && usum != sum) {
+ udp_packets_bad_checksum++;
+ if (udp_packets_seen > 4 &&
+ (udp_packets_seen / udp_packets_bad_checksum) < 2) {
+ note("%d bad udp checksums in %d packets",
+ udp_packets_bad_checksum, udp_packets_seen);
+ udp_packets_seen = udp_packets_bad_checksum = 0;
+ }
+ return (-1);
+ }
+
+ memcpy(&from->sin_port, &udp->uh_sport, sizeof(udp->uh_sport));
+
+ return (ip_len + sizeof(*udp));
+}
diff --git a/freebsd/sbin/dhclient/parse.c b/freebsd/sbin/dhclient/parse.c
new file mode 100644
index 00000000..6a54fd0a
--- /dev/null
+++ b/freebsd/sbin/dhclient/parse.c
@@ -0,0 +1,580 @@
+/* $OpenBSD: parse.c,v 1.11 2004/05/05 23:07:47 deraadt Exp $ */
+
+/* Common parser code for dhcpd and dhclient. */
+
+/*
+ * Copyright (c) 1995, 1996, 1997, 1998 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+#include "dhctoken.h"
+
+/* Skip to the semicolon ending the current statement. If we encounter
+ * braces, the matching closing brace terminates the statement. If we
+ * encounter a right brace but haven't encountered a left brace, return
+ * leaving the brace in the token buffer for the caller. If we see a
+ * semicolon and haven't seen a left brace, return. This lets us skip
+ * over:
+ *
+ * statement;
+ * statement foo bar { }
+ * statement foo bar { statement { } }
+ * statement}
+ *
+ * ...et cetera.
+ */
+void
+skip_to_semi(FILE *cfile)
+{
+ int brace_count = 0, token;
+ char *val;
+
+ do {
+ token = peek_token(&val, cfile);
+ if (token == RBRACE) {
+ if (brace_count) {
+ token = next_token(&val, cfile);
+ if (!--brace_count)
+ return;
+ } else
+ return;
+ } else if (token == LBRACE) {
+ brace_count++;
+ } else if (token == SEMI && !brace_count) {
+ token = next_token(&val, cfile);
+ return;
+ } else if (token == '\n') {
+ /*
+ * EOL only happens when parsing
+ * /etc/resolv.conf, and we treat it like a
+ * semicolon because the resolv.conf file is
+ * line-oriented.
+ */
+ token = next_token(&val, cfile);
+ return;
+ }
+ token = next_token(&val, cfile);
+ } while (token != EOF);
+}
+
+int
+parse_semi(FILE *cfile)
+{
+ int token;
+ char *val;
+
+ token = next_token(&val, cfile);
+ if (token != SEMI) {
+ parse_warn("semicolon expected.");
+ skip_to_semi(cfile);
+ return (0);
+ }
+ return (1);
+}
+
+/*
+ * string-parameter :== STRING SEMI
+ */
+char *
+parse_string(FILE *cfile)
+{
+ char *val, *s;
+ int token;
+
+ token = next_token(&val, cfile);
+ if (token != STRING) {
+ parse_warn("filename must be a string");
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ s = malloc(strlen(val) + 1);
+ if (!s)
+ error("no memory for string %s.", val);
+ strlcpy(s, val, strlen(val) + 1);
+
+ if (!parse_semi(cfile))
+ return (NULL);
+ return (s);
+}
+
+int
+parse_ip_addr(FILE *cfile, struct iaddr *addr)
+{
+ addr->len = 4;
+ if (parse_numeric_aggregate(cfile, addr->iabuf,
+ &addr->len, DOT, 10, 8))
+ return (1);
+ return (0);
+}
+
+/*
+ * hardware-parameter :== HARDWARE ETHERNET csns SEMI
+ * csns :== NUMBER | csns COLON NUMBER
+ */
+void
+parse_hardware_param(FILE *cfile, struct hardware *hardware)
+{
+ unsigned char *t;
+ int token, hlen;
+ char *val;
+
+ token = next_token(&val, cfile);
+ switch (token) {
+ case ETHERNET:
+ hardware->htype = HTYPE_ETHER;
+ break;
+ case TOKEN_RING:
+ hardware->htype = HTYPE_IEEE802;
+ break;
+ case FDDI:
+ hardware->htype = HTYPE_FDDI;
+ break;
+ default:
+ parse_warn("expecting a network hardware type");
+ skip_to_semi(cfile);
+ return;
+ }
+
+ /*
+ * Parse the hardware address information. Technically, it
+ * would make a lot of sense to restrict the length of the data
+ * we'll accept here to the length of a particular hardware
+ * address type. Unfortunately, there are some broken clients
+ * out there that put bogus data in the chaddr buffer, and we
+ * accept that data in the lease file rather than simply failing
+ * on such clients. Yuck.
+ */
+ hlen = 0;
+ t = parse_numeric_aggregate(cfile, NULL, &hlen, COLON, 16, 8);
+ if (!t)
+ return;
+ if (hlen > sizeof(hardware->haddr)) {
+ free(t);
+ parse_warn("hardware address too long");
+ } else {
+ hardware->hlen = hlen;
+ memcpy((unsigned char *)&hardware->haddr[0], t,
+ hardware->hlen);
+ if (hlen < sizeof(hardware->haddr))
+ memset(&hardware->haddr[hlen], 0,
+ sizeof(hardware->haddr) - hlen);
+ free(t);
+ }
+
+ token = next_token(&val, cfile);
+ if (token != SEMI) {
+ parse_warn("expecting semicolon.");
+ skip_to_semi(cfile);
+ }
+}
+
+/*
+ * lease-time :== NUMBER SEMI
+ */
+void
+parse_lease_time(FILE *cfile, time_t *timep)
+{
+ char *val;
+ int token;
+
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("Expecting numeric lease time");
+ skip_to_semi(cfile);
+ return;
+ }
+ convert_num((unsigned char *)timep, val, 10, 32);
+ /* Unswap the number - convert_num returns stuff in NBO. */
+ *timep = ntohl(*timep); /* XXX */
+
+ parse_semi(cfile);
+}
+
+/*
+ * No BNF for numeric aggregates - that's defined by the caller. What
+ * this function does is to parse a sequence of numbers separated by the
+ * token specified in separator. If max is zero, any number of numbers
+ * will be parsed; otherwise, exactly max numbers are expected. Base
+ * and size tell us how to internalize the numbers once they've been
+ * tokenized.
+ */
+unsigned char *
+parse_numeric_aggregate(FILE *cfile, unsigned char *buf, int *max,
+ int separator, int base, int size)
+{
+ unsigned char *bufp = buf, *s = NULL;
+ int token, count = 0;
+ char *val, *t;
+ pair c = NULL;
+
+ if (!bufp && *max) {
+ bufp = malloc(*max * size / 8);
+ if (!bufp)
+ error("can't allocate space for numeric aggregate");
+ } else
+ s = bufp;
+
+ do {
+ if (count) {
+ token = peek_token(&val, cfile);
+ if (token != separator) {
+ if (!*max)
+ break;
+ if (token != RBRACE && token != LBRACE)
+ token = next_token(&val, cfile);
+ parse_warn("too few numbers.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ token = next_token(&val, cfile);
+ }
+ token = next_token(&val, cfile);
+
+ if (token == EOF) {
+ parse_warn("unexpected end of file");
+ break;
+ }
+
+ /* Allow NUMBER_OR_NAME if base is 16. */
+ if (token != NUMBER &&
+ (base != 16 || token != NUMBER_OR_NAME)) {
+ parse_warn("expecting numeric value.");
+ skip_to_semi(cfile);
+ return (NULL);
+ }
+ /*
+ * If we can, convert the number now; otherwise, build a
+ * linked list of all the numbers.
+ */
+ if (s) {
+ convert_num(s, val, base, size);
+ s += size / 8;
+ } else {
+ t = malloc(strlen(val) + 1);
+ if (!t)
+ error("no temp space for number.");
+ strlcpy(t, val, strlen(val) + 1);
+ c = cons(t, c);
+ }
+ } while (++count != *max);
+
+ /* If we had to cons up a list, convert it now. */
+ if (c) {
+ bufp = malloc(count * size / 8);
+ if (!bufp)
+ error("can't allocate space for numeric aggregate.");
+ s = bufp + count - size / 8;
+ *max = count;
+ }
+ while (c) {
+ pair cdr = c->cdr;
+ convert_num(s, (char *)c->car, base, size);
+ s -= size / 8;
+ /* Free up temp space. */
+ free(c->car);
+ free(c);
+ c = cdr;
+ }
+ return (bufp);
+}
+
+void
+convert_num(unsigned char *buf, char *str, int base, int size)
+{
+ int negative = 0, tval, max;
+ u_int32_t val = 0;
+ char *ptr = str;
+
+ if (*ptr == '-') {
+ negative = 1;
+ ptr++;
+ }
+
+ /* If base wasn't specified, figure it out from the data. */
+ if (!base) {
+ if (ptr[0] == '0') {
+ if (ptr[1] == 'x') {
+ base = 16;
+ ptr += 2;
+ } else if (isascii(ptr[1]) && isdigit(ptr[1])) {
+ base = 8;
+ ptr += 1;
+ } else
+ base = 10;
+ } else
+ base = 10;
+ }
+
+ do {
+ tval = *ptr++;
+ /* XXX assumes ASCII... */
+ if (tval >= 'a')
+ tval = tval - 'a' + 10;
+ else if (tval >= 'A')
+ tval = tval - 'A' + 10;
+ else if (tval >= '0')
+ tval -= '0';
+ else {
+ warning("Bogus number: %s.", str);
+ break;
+ }
+ if (tval >= base) {
+ warning("Bogus number: %s: digit %d not in base %d",
+ str, tval, base);
+ break;
+ }
+ val = val * base + tval;
+ } while (*ptr);
+
+ if (negative)
+ max = (1 << (size - 1));
+ else
+ max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);
+ if (val > max) {
+ switch (base) {
+ case 8:
+ warning("value %s%o exceeds max (%d) for precision.",
+ negative ? "-" : "", val, max);
+ break;
+ case 16:
+ warning("value %s%x exceeds max (%d) for precision.",
+ negative ? "-" : "", val, max);
+ break;
+ default:
+ warning("value %s%u exceeds max (%d) for precision.",
+ negative ? "-" : "", val, max);
+ break;
+ }
+ }
+
+ if (negative)
+ switch (size) {
+ case 8:
+ *buf = -(unsigned long)val;
+ break;
+ case 16:
+ putShort(buf, -(unsigned long)val);
+ break;
+ case 32:
+ putLong(buf, -(unsigned long)val);
+ break;
+ default:
+ warning("Unexpected integer size: %d", size);
+ break;
+ }
+ else
+ switch (size) {
+ case 8:
+ *buf = (u_int8_t)val;
+ break;
+ case 16:
+ putUShort(buf, (u_int16_t)val);
+ break;
+ case 32:
+ putULong(buf, val);
+ break;
+ default:
+ warning("Unexpected integer size: %d", size);
+ break;
+ }
+}
+
+/*
+ * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER
+ * NUMBER COLON NUMBER COLON NUMBER SEMI
+ *
+ * Dates are always in GMT; first number is day of week; next is
+ * year/month/day; next is hours:minutes:seconds on a 24-hour
+ * clock.
+ */
+time_t
+parse_date(FILE *cfile)
+{
+ static int months[11] = { 31, 59, 90, 120, 151, 181,
+ 212, 243, 273, 304, 334 };
+ int guess, token;
+ struct tm tm;
+ char *val;
+
+ /* Day of week... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("numeric day of week expected.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+ tm.tm_wday = atoi(val);
+
+ /* Year... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("numeric year expected.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+ tm.tm_year = atoi(val);
+ if (tm.tm_year > 1900)
+ tm.tm_year -= 1900;
+
+ /* Slash separating year from month... */
+ token = next_token(&val, cfile);
+ if (token != SLASH) {
+ parse_warn("expected slash separating year from month.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+
+ /* Month... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("numeric month expected.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+ tm.tm_mon = atoi(val) - 1;
+
+ /* Slash separating month from day... */
+ token = next_token(&val, cfile);
+ if (token != SLASH) {
+ parse_warn("expected slash separating month from day.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+
+ /* Month... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("numeric day of month expected.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+ tm.tm_mday = atoi(val);
+
+ /* Hour... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("numeric hour expected.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+ tm.tm_hour = atoi(val);
+
+ /* Colon separating hour from minute... */
+ token = next_token(&val, cfile);
+ if (token != COLON) {
+ parse_warn("expected colon separating hour from minute.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+
+ /* Minute... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("numeric minute expected.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+ tm.tm_min = atoi(val);
+
+ /* Colon separating minute from second... */
+ token = next_token(&val, cfile);
+ if (token != COLON) {
+ parse_warn("expected colon separating hour from minute.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+
+ /* Minute... */
+ token = next_token(&val, cfile);
+ if (token != NUMBER) {
+ parse_warn("numeric minute expected.");
+ if (token != SEMI)
+ skip_to_semi(cfile);
+ return (0);
+ }
+ tm.tm_sec = atoi(val);
+ tm.tm_isdst = 0;
+
+ /* XXX: We assume that mktime does not use tm_yday. */
+ tm.tm_yday = 0;
+
+ /* Make sure the date ends in a semicolon... */
+ token = next_token(&val, cfile);
+ if (token != SEMI) {
+ parse_warn("semicolon expected.");
+ skip_to_semi(cfile);
+ return (0);
+ }
+
+ /* Guess the time value... */
+ guess = ((((((365 * (tm.tm_year - 70) + /* Days in years since '70 */
+ (tm.tm_year - 69) / 4 + /* Leap days since '70 */
+ (tm.tm_mon /* Days in months this year */
+ ? months[tm.tm_mon - 1]
+ : 0) +
+ (tm.tm_mon > 1 && /* Leap day this year */
+ !((tm.tm_year - 72) & 3)) +
+ tm.tm_mday - 1) * 24) + /* Day of month */
+ tm.tm_hour) * 60) +
+ tm.tm_min) * 60) + tm.tm_sec;
+
+ /*
+ * This guess could be wrong because of leap seconds or other
+ * weirdness we don't know about that the system does. For
+ * now, we're just going to accept the guess, but at some point
+ * it might be nice to do a successive approximation here to get
+ * an exact value. Even if the error is small, if the server
+ * is restarted frequently (and thus the lease database is
+ * reread), the error could accumulate into something
+ * significant.
+ */
+ return (guess);
+}
diff --git a/freebsd/sbin/dhclient/privsep.c b/freebsd/sbin/dhclient/privsep.c
new file mode 100644
index 00000000..b42572f2
--- /dev/null
+++ b/freebsd/sbin/dhclient/privsep.c
@@ -0,0 +1,238 @@
+/* $OpenBSD: privsep.c,v 1.7 2004/05/10 18:34:42 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2004 Henning Brauer <henning@openbsd.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 MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+#include "privsep.h"
+
+struct buf *
+buf_open(size_t len)
+{
+ struct buf *buf;
+
+ if ((buf = calloc(1, sizeof(struct buf))) == NULL)
+ return (NULL);
+ if ((buf->buf = malloc(len)) == NULL) {
+ free(buf);
+ return (NULL);
+ }
+ buf->size = len;
+
+ return (buf);
+}
+
+int
+buf_add(struct buf *buf, void *data, size_t len)
+{
+ if (buf->wpos + len > buf->size)
+ return (-1);
+
+ memcpy(buf->buf + buf->wpos, data, len);
+ buf->wpos += len;
+ return (0);
+}
+
+int
+buf_close(int sock, struct buf *buf)
+{
+ ssize_t n;
+
+ do {
+ n = write(sock, buf->buf + buf->rpos, buf->size - buf->rpos);
+ if (n != -1)
+ buf->rpos += n;
+ if (n == 0) { /* connection closed */
+ errno = 0;
+ return (-1);
+ }
+ } while (n == -1 && (errno == EAGAIN || errno == EINTR));
+
+ if (buf->rpos < buf->size)
+ error("short write: wanted %lu got %ld bytes",
+ (unsigned long)buf->size, (long)buf->rpos);
+
+ free(buf->buf);
+ free(buf);
+ return (n);
+}
+
+ssize_t
+buf_read(int sock, void *buf, size_t nbytes)
+{
+ ssize_t n, r = 0;
+ char *p = buf;
+
+ do {
+ n = read(sock, p, nbytes);
+ if (n == 0)
+ error("connection closed");
+ if (n != -1) {
+ r += n;
+ p += n;
+ nbytes -= n;
+ }
+ } while (n == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (n == -1)
+ error("buf_read: %m");
+
+ if (r < nbytes)
+ error("short read: wanted %lu got %ld bytes",
+ (unsigned long)nbytes, (long)r);
+
+ return (r);
+}
+
+void
+dispatch_imsg(int fd)
+{
+ struct imsg_hdr hdr;
+ char *medium, *reason, *filename,
+ *servername, *prefix;
+ size_t medium_len, reason_len, filename_len,
+ servername_len, prefix_len, totlen;
+ struct client_lease lease;
+ int ret, i, optlen;
+ struct buf *buf;
+
+ buf_read(fd, &hdr, sizeof(hdr));
+
+ switch (hdr.code) {
+ case IMSG_SCRIPT_INIT:
+ if (hdr.len < sizeof(hdr) + sizeof(size_t))
+ error("corrupted message received");
+ buf_read(fd, &medium_len, sizeof(medium_len));
+ if (hdr.len < medium_len + sizeof(size_t) + sizeof(hdr)
+ + sizeof(size_t) || medium_len == SIZE_T_MAX)
+ error("corrupted message received");
+ if (medium_len > 0) {
+ if ((medium = calloc(1, medium_len + 1)) == NULL)
+ error("%m");
+ buf_read(fd, medium, medium_len);
+ } else
+ medium = NULL;
+
+ buf_read(fd, &reason_len, sizeof(reason_len));
+ if (hdr.len < medium_len + reason_len + sizeof(hdr) ||
+ reason_len == SIZE_T_MAX)
+ error("corrupted message received");
+ if (reason_len > 0) {
+ if ((reason = calloc(1, reason_len + 1)) == NULL)
+ error("%m");
+ buf_read(fd, reason, reason_len);
+ } else
+ reason = NULL;
+
+ priv_script_init(reason, medium);
+ free(reason);
+ free(medium);
+ break;
+ case IMSG_SCRIPT_WRITE_PARAMS:
+ bzero(&lease, sizeof lease);
+ totlen = sizeof(hdr) + sizeof(lease) + sizeof(size_t);
+ if (hdr.len < totlen)
+ error("corrupted message received");
+ buf_read(fd, &lease, sizeof(lease));
+
+ buf_read(fd, &filename_len, sizeof(filename_len));
+ totlen += filename_len + sizeof(size_t);
+ if (hdr.len < totlen || filename_len == SIZE_T_MAX)
+ error("corrupted message received");
+ if (filename_len > 0) {
+ if ((filename = calloc(1, filename_len + 1)) == NULL)
+ error("%m");
+ buf_read(fd, filename, filename_len);
+ } else
+ filename = NULL;
+
+ buf_read(fd, &servername_len, sizeof(servername_len));
+ totlen += servername_len + sizeof(size_t);
+ if (hdr.len < totlen || servername_len == SIZE_T_MAX)
+ error("corrupted message received");
+ if (servername_len > 0) {
+ if ((servername =
+ calloc(1, servername_len + 1)) == NULL)
+ error("%m");
+ buf_read(fd, servername, servername_len);
+ } else
+ servername = NULL;
+
+ buf_read(fd, &prefix_len, sizeof(prefix_len));
+ totlen += prefix_len;
+ if (hdr.len < totlen || prefix_len == SIZE_T_MAX)
+ error("corrupted message received");
+ if (prefix_len > 0) {
+ if ((prefix = calloc(1, prefix_len + 1)) == NULL)
+ error("%m");
+ buf_read(fd, prefix, prefix_len);
+ } else
+ prefix = NULL;
+
+ for (i = 0; i < 256; i++) {
+ totlen += sizeof(optlen);
+ if (hdr.len < totlen)
+ error("corrupted message received");
+ buf_read(fd, &optlen, sizeof(optlen));
+ lease.options[i].data = NULL;
+ lease.options[i].len = optlen;
+ if (optlen > 0) {
+ totlen += optlen;
+ if (hdr.len < totlen || optlen == SIZE_T_MAX)
+ error("corrupted message received");
+ lease.options[i].data =
+ calloc(1, optlen + 1);
+ if (lease.options[i].data == NULL)
+ error("%m");
+ buf_read(fd, lease.options[i].data, optlen);
+ }
+ }
+ lease.server_name = servername;
+ lease.filename = filename;
+
+ priv_script_write_params(prefix, &lease);
+
+ free(servername);
+ free(filename);
+ free(prefix);
+ for (i = 0; i < 256; i++)
+ if (lease.options[i].len > 0)
+ free(lease.options[i].data);
+ break;
+ case IMSG_SCRIPT_GO:
+ if (hdr.len != sizeof(hdr))
+ error("corrupted message received");
+
+ ret = priv_script_go();
+
+ hdr.code = IMSG_SCRIPT_GO_RET;
+ hdr.len = sizeof(struct imsg_hdr) + sizeof(int);
+ if ((buf = buf_open(hdr.len)) == NULL)
+ error("buf_open: %m");
+ if (buf_add(buf, &hdr, sizeof(hdr)))
+ error("buf_add: %m");
+ if (buf_add(buf, &ret, sizeof(ret)))
+ error("buf_add: %m");
+ if (buf_close(fd, buf) == -1)
+ error("buf_close: %m");
+ break;
+ default:
+ error("received unknown message, code %d", hdr.code);
+ }
+}
diff --git a/freebsd/sbin/dhclient/privsep.h b/freebsd/sbin/dhclient/privsep.h
new file mode 100644
index 00000000..f30284ee
--- /dev/null
+++ b/freebsd/sbin/dhclient/privsep.h
@@ -0,0 +1,47 @@
+/* $OpenBSD: privsep.h,v 1.2 2004/05/04 18:51:18 henning Exp $ */
+
+/*
+ * Copyright (c) 2004 Henning Brauer <henning@openbsd.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 MIND, USE, DATA OR PROFITS, WHETHER IN
+ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE, ABUSE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <poll.h>
+#include <pwd.h>
+
+struct buf {
+ u_char *buf;
+ size_t size;
+ size_t wpos;
+ size_t rpos;
+};
+
+enum imsg_code {
+ IMSG_NONE,
+ IMSG_SCRIPT_INIT,
+ IMSG_SCRIPT_WRITE_PARAMS,
+ IMSG_SCRIPT_GO,
+ IMSG_SCRIPT_GO_RET
+};
+
+struct imsg_hdr {
+ enum imsg_code code;
+ size_t len;
+};
+
+struct buf *buf_open(size_t);
+int buf_add(struct buf *, void *, size_t);
+int buf_close(int, struct buf *);
+ssize_t buf_read(int sock, void *, size_t);
diff --git a/freebsd/sbin/dhclient/tables.c b/freebsd/sbin/dhclient/tables.c
new file mode 100644
index 00000000..81a9acc8
--- /dev/null
+++ b/freebsd/sbin/dhclient/tables.c
@@ -0,0 +1,446 @@
+/* $OpenBSD: tables.c,v 1.4 2004/05/04 20:28:40 deraadt Exp $ */
+
+/* Tables of information... */
+
+/*
+ * Copyright (c) 1995, 1996 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+/*
+ * DHCP Option names, formats and codes, from RFC1533.
+ *
+ * Format codes:
+ *
+ * e - end of data
+ * I - IP address
+ * l - 32-bit signed integer
+ * L - 32-bit unsigned integer
+ * s - 16-bit signed integer
+ * S - 16-bit unsigned integer
+ * b - 8-bit signed integer
+ * B - 8-bit unsigned integer
+ * t - ASCII text
+ * f - flag (true or false)
+ * A - array of whatever precedes (e.g., IA means array of IP addresses)
+ */
+
+struct universe dhcp_universe;
+struct option dhcp_options[256] = {
+ { "pad", "", &dhcp_universe, 0 },
+ { "subnet-mask", "I", &dhcp_universe, 1 },
+ { "time-offset", "l", &dhcp_universe, 2 },
+ { "routers", "IA", &dhcp_universe, 3 },
+ { "time-servers", "IA", &dhcp_universe, 4 },
+ { "ien116-name-servers", "IA", &dhcp_universe, 5 },
+ { "domain-name-servers", "IA", &dhcp_universe, 6 },
+ { "log-servers", "IA", &dhcp_universe, 7 },
+ { "cookie-servers", "IA", &dhcp_universe, 8 },
+ { "lpr-servers", "IA", &dhcp_universe, 9 },
+ { "impress-servers", "IA", &dhcp_universe, 10 },
+ { "resource-location-servers", "IA", &dhcp_universe, 11 },
+ { "host-name", "t", &dhcp_universe, 12 },
+ { "boot-size", "S", &dhcp_universe, 13 },
+ { "merit-dump", "t", &dhcp_universe, 14 },
+ { "domain-name", "t", &dhcp_universe, 15 },
+ { "swap-server", "I", &dhcp_universe, 16 },
+ { "root-path", "t", &dhcp_universe, 17 },
+ { "extensions-path", "t", &dhcp_universe, 18 },
+ { "ip-forwarding", "f", &dhcp_universe, 19 },
+ { "non-local-source-routing", "f", &dhcp_universe, 20 },
+ { "policy-filter", "IIA", &dhcp_universe, 21 },
+ { "max-dgram-reassembly", "S", &dhcp_universe, 22 },
+ { "default-ip-ttl", "B", &dhcp_universe, 23 },
+ { "path-mtu-aging-timeout", "L", &dhcp_universe, 24 },
+ { "path-mtu-plateau-table", "SA", &dhcp_universe, 25 },
+ { "interface-mtu", "S", &dhcp_universe, 26 },
+ { "all-subnets-local", "f", &dhcp_universe, 27 },
+ { "broadcast-address", "I", &dhcp_universe, 28 },
+ { "perform-mask-discovery", "f", &dhcp_universe, 29 },
+ { "mask-supplier", "f", &dhcp_universe, 30 },
+ { "router-discovery", "f", &dhcp_universe, 31 },
+ { "router-solicitation-address", "I", &dhcp_universe, 32 },
+ { "static-routes", "IIA", &dhcp_universe, 33 },
+ { "trailer-encapsulation", "f", &dhcp_universe, 34 },
+ { "arp-cache-timeout", "L", &dhcp_universe, 35 },
+ { "ieee802-3-encapsulation", "f", &dhcp_universe, 36 },
+ { "default-tcp-ttl", "B", &dhcp_universe, 37 },
+ { "tcp-keepalive-interval", "L", &dhcp_universe, 38 },
+ { "tcp-keepalive-garbage", "f", &dhcp_universe, 39 },
+ { "nis-domain", "t", &dhcp_universe, 40 },
+ { "nis-servers", "IA", &dhcp_universe, 41 },
+ { "ntp-servers", "IA", &dhcp_universe, 42 },
+ { "vendor-encapsulated-options", "X", &dhcp_universe, 43 },
+ { "netbios-name-servers", "IA", &dhcp_universe, 44 },
+ { "netbios-dd-server", "IA", &dhcp_universe, 45 },
+ { "netbios-node-type", "B", &dhcp_universe, 46 },
+ { "netbios-scope", "t", &dhcp_universe, 47 },
+ { "font-servers", "IA", &dhcp_universe, 48 },
+ { "x-display-manager", "IA", &dhcp_universe, 49 },
+ { "dhcp-requested-address", "I", &dhcp_universe, 50 },
+ { "dhcp-lease-time", "L", &dhcp_universe, 51 },
+ { "dhcp-option-overload", "B", &dhcp_universe, 52 },
+ { "dhcp-message-type", "B", &dhcp_universe, 53 },
+ { "dhcp-server-identifier", "I", &dhcp_universe, 54 },
+ { "dhcp-parameter-request-list", "BA", &dhcp_universe, 55 },
+ { "dhcp-message", "t", &dhcp_universe, 56 },
+ { "dhcp-max-message-size", "S", &dhcp_universe, 57 },
+ { "dhcp-renewal-time", "L", &dhcp_universe, 58 },
+ { "dhcp-rebinding-time", "L", &dhcp_universe, 59 },
+ { "dhcp-class-identifier", "t", &dhcp_universe, 60 },
+ { "dhcp-client-identifier", "X", &dhcp_universe, 61 },
+ { "option-62", "X", &dhcp_universe, 62 },
+ { "option-63", "X", &dhcp_universe, 63 },
+ { "nisplus-domain", "t", &dhcp_universe, 64 },
+ { "nisplus-servers", "IA", &dhcp_universe, 65 },
+ { "tftp-server-name", "t", &dhcp_universe, 66 },
+ { "bootfile-name", "t", &dhcp_universe, 67 },
+ { "mobile-ip-home-agent", "IA", &dhcp_universe, 68 },
+ { "smtp-server", "IA", &dhcp_universe, 69 },
+ { "pop-server", "IA", &dhcp_universe, 70 },
+ { "nntp-server", "IA", &dhcp_universe, 71 },
+ { "www-server", "IA", &dhcp_universe, 72 },
+ { "finger-server", "IA", &dhcp_universe, 73 },
+ { "irc-server", "IA", &dhcp_universe, 74 },
+ { "streettalk-server", "IA", &dhcp_universe, 75 },
+ { "streettalk-directory-assistance-server", "IA", &dhcp_universe, 76 },
+ { "user-class", "t", &dhcp_universe, 77 },
+ { "option-78", "X", &dhcp_universe, 78 },
+ { "option-79", "X", &dhcp_universe, 79 },
+ { "option-80", "X", &dhcp_universe, 80 },
+ { "option-81", "X", &dhcp_universe, 81 },
+ { "option-82", "X", &dhcp_universe, 82 },
+ { "option-83", "X", &dhcp_universe, 83 },
+ { "option-84", "X", &dhcp_universe, 84 },
+ { "nds-servers", "IA", &dhcp_universe, 85 },
+ { "nds-tree-name", "X", &dhcp_universe, 86 },
+ { "nds-context", "X", &dhcp_universe, 87 },
+ { "option-88", "X", &dhcp_universe, 88 },
+ { "option-89", "X", &dhcp_universe, 89 },
+ { "option-90", "X", &dhcp_universe, 90 },
+ { "option-91", "X", &dhcp_universe, 91 },
+ { "option-92", "X", &dhcp_universe, 92 },
+ { "option-93", "X", &dhcp_universe, 93 },
+ { "option-94", "X", &dhcp_universe, 94 },
+ { "option-95", "X", &dhcp_universe, 95 },
+ { "option-96", "X", &dhcp_universe, 96 },
+ { "option-97", "X", &dhcp_universe, 97 },
+ { "option-98", "X", &dhcp_universe, 98 },
+ { "option-99", "X", &dhcp_universe, 99 },
+ { "option-100", "X", &dhcp_universe, 100 },
+ { "option-101", "X", &dhcp_universe, 101 },
+ { "option-102", "X", &dhcp_universe, 102 },
+ { "option-103", "X", &dhcp_universe, 103 },
+ { "option-104", "X", &dhcp_universe, 104 },
+ { "option-105", "X", &dhcp_universe, 105 },
+ { "option-106", "X", &dhcp_universe, 106 },
+ { "option-107", "X", &dhcp_universe, 107 },
+ { "option-108", "X", &dhcp_universe, 108 },
+ { "option-109", "X", &dhcp_universe, 109 },
+ { "option-110", "X", &dhcp_universe, 110 },
+ { "option-111", "X", &dhcp_universe, 111 },
+ { "option-112", "X", &dhcp_universe, 112 },
+ { "option-113", "X", &dhcp_universe, 113 },
+ { "option-114", "X", &dhcp_universe, 114 },
+ { "option-115", "X", &dhcp_universe, 115 },
+ { "option-116", "X", &dhcp_universe, 116 },
+ { "option-117", "X", &dhcp_universe, 117 },
+ { "option-118", "X", &dhcp_universe, 118 },
+ { "option-119", "X", &dhcp_universe, 119 },
+ { "option-120", "X", &dhcp_universe, 120 },
+ { "classless-routes", "BA", &dhcp_universe, 121 },
+ { "option-122", "X", &dhcp_universe, 122 },
+ { "option-123", "X", &dhcp_universe, 123 },
+ { "option-124", "X", &dhcp_universe, 124 },
+ { "option-125", "X", &dhcp_universe, 125 },
+ { "option-126", "X", &dhcp_universe, 126 },
+ { "option-127", "X", &dhcp_universe, 127 },
+ { "option-128", "X", &dhcp_universe, 128 },
+ { "option-129", "X", &dhcp_universe, 129 },
+ { "option-130", "X", &dhcp_universe, 130 },
+ { "option-131", "X", &dhcp_universe, 131 },
+ { "option-132", "X", &dhcp_universe, 132 },
+ { "option-133", "X", &dhcp_universe, 133 },
+ { "option-134", "X", &dhcp_universe, 134 },
+ { "option-135", "X", &dhcp_universe, 135 },
+ { "option-136", "X", &dhcp_universe, 136 },
+ { "option-137", "X", &dhcp_universe, 137 },
+ { "option-138", "X", &dhcp_universe, 138 },
+ { "option-139", "X", &dhcp_universe, 139 },
+ { "option-140", "X", &dhcp_universe, 140 },
+ { "option-141", "X", &dhcp_universe, 141 },
+ { "option-142", "X", &dhcp_universe, 142 },
+ { "option-143", "X", &dhcp_universe, 143 },
+ { "option-144", "X", &dhcp_universe, 144 },
+ { "option-145", "X", &dhcp_universe, 145 },
+ { "option-146", "X", &dhcp_universe, 146 },
+ { "option-147", "X", &dhcp_universe, 147 },
+ { "option-148", "X", &dhcp_universe, 148 },
+ { "option-149", "X", &dhcp_universe, 149 },
+ { "option-150", "X", &dhcp_universe, 150 },
+ { "option-151", "X", &dhcp_universe, 151 },
+ { "option-152", "X", &dhcp_universe, 152 },
+ { "option-153", "X", &dhcp_universe, 153 },
+ { "option-154", "X", &dhcp_universe, 154 },
+ { "option-155", "X", &dhcp_universe, 155 },
+ { "option-156", "X", &dhcp_universe, 156 },
+ { "option-157", "X", &dhcp_universe, 157 },
+ { "option-158", "X", &dhcp_universe, 158 },
+ { "option-159", "X", &dhcp_universe, 159 },
+ { "option-160", "X", &dhcp_universe, 160 },
+ { "option-161", "X", &dhcp_universe, 161 },
+ { "option-162", "X", &dhcp_universe, 162 },
+ { "option-163", "X", &dhcp_universe, 163 },
+ { "option-164", "X", &dhcp_universe, 164 },
+ { "option-165", "X", &dhcp_universe, 165 },
+ { "option-166", "X", &dhcp_universe, 166 },
+ { "option-167", "X", &dhcp_universe, 167 },
+ { "option-168", "X", &dhcp_universe, 168 },
+ { "option-169", "X", &dhcp_universe, 169 },
+ { "option-170", "X", &dhcp_universe, 170 },
+ { "option-171", "X", &dhcp_universe, 171 },
+ { "option-172", "X", &dhcp_universe, 172 },
+ { "option-173", "X", &dhcp_universe, 173 },
+ { "option-174", "X", &dhcp_universe, 174 },
+ { "option-175", "X", &dhcp_universe, 175 },
+ { "option-176", "X", &dhcp_universe, 176 },
+ { "option-177", "X", &dhcp_universe, 177 },
+ { "option-178", "X", &dhcp_universe, 178 },
+ { "option-179", "X", &dhcp_universe, 179 },
+ { "option-180", "X", &dhcp_universe, 180 },
+ { "option-181", "X", &dhcp_universe, 181 },
+ { "option-182", "X", &dhcp_universe, 182 },
+ { "option-183", "X", &dhcp_universe, 183 },
+ { "option-184", "X", &dhcp_universe, 184 },
+ { "option-185", "X", &dhcp_universe, 185 },
+ { "option-186", "X", &dhcp_universe, 186 },
+ { "option-187", "X", &dhcp_universe, 187 },
+ { "option-188", "X", &dhcp_universe, 188 },
+ { "option-189", "X", &dhcp_universe, 189 },
+ { "option-190", "X", &dhcp_universe, 190 },
+ { "option-191", "X", &dhcp_universe, 191 },
+ { "option-192", "X", &dhcp_universe, 192 },
+ { "option-193", "X", &dhcp_universe, 193 },
+ { "option-194", "X", &dhcp_universe, 194 },
+ { "option-195", "X", &dhcp_universe, 195 },
+ { "option-196", "X", &dhcp_universe, 196 },
+ { "option-197", "X", &dhcp_universe, 197 },
+ { "option-198", "X", &dhcp_universe, 198 },
+ { "option-199", "X", &dhcp_universe, 199 },
+ { "option-200", "X", &dhcp_universe, 200 },
+ { "option-201", "X", &dhcp_universe, 201 },
+ { "option-202", "X", &dhcp_universe, 202 },
+ { "option-203", "X", &dhcp_universe, 203 },
+ { "option-204", "X", &dhcp_universe, 204 },
+ { "option-205", "X", &dhcp_universe, 205 },
+ { "option-206", "X", &dhcp_universe, 206 },
+ { "option-207", "X", &dhcp_universe, 207 },
+ { "option-208", "X", &dhcp_universe, 208 },
+ { "option-209", "X", &dhcp_universe, 209 },
+ { "option-210", "X", &dhcp_universe, 210 },
+ { "option-211", "X", &dhcp_universe, 211 },
+ { "option-212", "X", &dhcp_universe, 212 },
+ { "option-213", "X", &dhcp_universe, 213 },
+ { "option-214", "X", &dhcp_universe, 214 },
+ { "option-215", "X", &dhcp_universe, 215 },
+ { "option-216", "X", &dhcp_universe, 216 },
+ { "option-217", "X", &dhcp_universe, 217 },
+ { "option-218", "X", &dhcp_universe, 218 },
+ { "option-219", "X", &dhcp_universe, 219 },
+ { "option-220", "X", &dhcp_universe, 220 },
+ { "option-221", "X", &dhcp_universe, 221 },
+ { "option-222", "X", &dhcp_universe, 222 },
+ { "option-223", "X", &dhcp_universe, 223 },
+ { "option-224", "X", &dhcp_universe, 224 },
+ { "option-225", "X", &dhcp_universe, 225 },
+ { "option-226", "X", &dhcp_universe, 226 },
+ { "option-227", "X", &dhcp_universe, 227 },
+ { "option-228", "X", &dhcp_universe, 228 },
+ { "option-229", "X", &dhcp_universe, 229 },
+ { "option-230", "X", &dhcp_universe, 230 },
+ { "option-231", "X", &dhcp_universe, 231 },
+ { "option-232", "X", &dhcp_universe, 232 },
+ { "option-233", "X", &dhcp_universe, 233 },
+ { "option-234", "X", &dhcp_universe, 234 },
+ { "option-235", "X", &dhcp_universe, 235 },
+ { "option-236", "X", &dhcp_universe, 236 },
+ { "option-237", "X", &dhcp_universe, 237 },
+ { "option-238", "X", &dhcp_universe, 238 },
+ { "option-239", "X", &dhcp_universe, 239 },
+ { "option-240", "X", &dhcp_universe, 240 },
+ { "option-241", "X", &dhcp_universe, 241 },
+ { "option-242", "X", &dhcp_universe, 242 },
+ { "option-243", "X", &dhcp_universe, 243 },
+ { "option-244", "X", &dhcp_universe, 244 },
+ { "option-245", "X", &dhcp_universe, 245 },
+ { "option-246", "X", &dhcp_universe, 246 },
+ { "option-247", "X", &dhcp_universe, 247 },
+ { "option-248", "X", &dhcp_universe, 248 },
+ { "option-249", "X", &dhcp_universe, 249 },
+ { "option-250", "X", &dhcp_universe, 250 },
+ { "option-251", "X", &dhcp_universe, 251 },
+ { "option-252", "X", &dhcp_universe, 252 },
+ { "option-253", "X", &dhcp_universe, 253 },
+ { "option-254", "X", &dhcp_universe, 254 },
+ { "option-end", "e", &dhcp_universe, 255 },
+};
+
+/*
+ * Default dhcp option priority list (this is ad hoc and should not be
+ * mistaken for a carefully crafted and optimized list).
+ */
+unsigned char dhcp_option_default_priority_list[] = {
+ DHO_DHCP_REQUESTED_ADDRESS,
+ DHO_DHCP_OPTION_OVERLOAD,
+ DHO_DHCP_MAX_MESSAGE_SIZE,
+ DHO_DHCP_RENEWAL_TIME,
+ DHO_DHCP_REBINDING_TIME,
+ DHO_DHCP_CLASS_IDENTIFIER,
+ DHO_DHCP_CLIENT_IDENTIFIER,
+ DHO_SUBNET_MASK,
+ DHO_TIME_OFFSET,
+ DHO_CLASSLESS_ROUTES,
+ DHO_ROUTERS,
+ DHO_TIME_SERVERS,
+ DHO_NAME_SERVERS,
+ DHO_DOMAIN_NAME_SERVERS,
+ DHO_HOST_NAME,
+ DHO_LOG_SERVERS,
+ DHO_COOKIE_SERVERS,
+ DHO_LPR_SERVERS,
+ DHO_IMPRESS_SERVERS,
+ DHO_RESOURCE_LOCATION_SERVERS,
+ DHO_HOST_NAME,
+ DHO_BOOT_SIZE,
+ DHO_MERIT_DUMP,
+ DHO_DOMAIN_NAME,
+ DHO_SWAP_SERVER,
+ DHO_ROOT_PATH,
+ DHO_EXTENSIONS_PATH,
+ DHO_IP_FORWARDING,
+ DHO_NON_LOCAL_SOURCE_ROUTING,
+ DHO_POLICY_FILTER,
+ DHO_MAX_DGRAM_REASSEMBLY,
+ DHO_DEFAULT_IP_TTL,
+ DHO_PATH_MTU_AGING_TIMEOUT,
+ DHO_PATH_MTU_PLATEAU_TABLE,
+ DHO_INTERFACE_MTU,
+ DHO_ALL_SUBNETS_LOCAL,
+ DHO_BROADCAST_ADDRESS,
+ DHO_PERFORM_MASK_DISCOVERY,
+ DHO_MASK_SUPPLIER,
+ DHO_ROUTER_DISCOVERY,
+ DHO_ROUTER_SOLICITATION_ADDRESS,
+ DHO_STATIC_ROUTES,
+ DHO_TRAILER_ENCAPSULATION,
+ DHO_ARP_CACHE_TIMEOUT,
+ DHO_IEEE802_3_ENCAPSULATION,
+ DHO_DEFAULT_TCP_TTL,
+ DHO_TCP_KEEPALIVE_INTERVAL,
+ DHO_TCP_KEEPALIVE_GARBAGE,
+ DHO_NIS_DOMAIN,
+ DHO_NIS_SERVERS,
+ DHO_NTP_SERVERS,
+ DHO_VENDOR_ENCAPSULATED_OPTIONS,
+ DHO_NETBIOS_NAME_SERVERS,
+ DHO_NETBIOS_DD_SERVER,
+ DHO_NETBIOS_NODE_TYPE,
+ DHO_NETBIOS_SCOPE,
+ DHO_FONT_SERVERS,
+ DHO_X_DISPLAY_MANAGER,
+ DHO_DHCP_PARAMETER_REQUEST_LIST,
+ DHO_NISPLUS_DOMAIN,
+ DHO_NISPLUS_SERVERS,
+ DHO_TFTP_SERVER_NAME,
+ DHO_BOOTFILE_NAME,
+ DHO_MOBILE_IP_HOME_AGENT,
+ DHO_SMTP_SERVER,
+ DHO_POP_SERVER,
+ DHO_NNTP_SERVER,
+ DHO_WWW_SERVER,
+ DHO_FINGER_SERVER,
+ DHO_IRC_SERVER,
+ DHO_STREETTALK_SERVER,
+ DHO_STREETTALK_DA_SERVER,
+
+ /* Presently-undefined options... */
+ 62, 63, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+ 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
+ 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117,
+ 118, 119, 120, 122, 123, 124, 125, 126, 127, 128, 129, 130,
+ 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142,
+ 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
+ 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
+ 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
+ 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190,
+ 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202,
+ 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
+ 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226,
+ 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
+ 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
+ 251, 252, 253, 254,
+};
+
+int sizeof_dhcp_option_default_priority_list =
+ sizeof(dhcp_option_default_priority_list);
+
+struct hash_table universe_hash;
+
+void
+initialize_universes(void)
+{
+ int i;
+
+ dhcp_universe.name = "dhcp";
+ dhcp_universe.hash = new_hash();
+ if (!dhcp_universe.hash)
+ error("Can't allocate dhcp option hash table.");
+ for (i = 0; i < 256; i++) {
+ dhcp_universe.options[i] = &dhcp_options[i];
+ add_hash(dhcp_universe.hash,
+ (unsigned char *)dhcp_options[i].name, 0,
+ (unsigned char *)&dhcp_options[i]);
+ }
+ universe_hash.hash_count = DEFAULT_HASH_SIZE;
+ add_hash(&universe_hash,
+ (unsigned char *)dhcp_universe.name, 0,
+ (unsigned char *)&dhcp_universe);
+}
diff --git a/freebsd/sbin/dhclient/tree.c b/freebsd/sbin/dhclient/tree.c
new file mode 100644
index 00000000..0ed2919b
--- /dev/null
+++ b/freebsd/sbin/dhclient/tree.c
@@ -0,0 +1,59 @@
+/* $OpenBSD: tree.c,v 1.13 2004/05/06 22:29:15 deraadt Exp $ */
+
+/* Routines for manipulating parse trees... */
+
+/*
+ * Copyright (c) 1995, 1996, 1997 The Internet Software Consortium.
+ * 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "dhcpd.h"
+
+extern int h_errno;
+
+pair
+cons(caddr_t car, pair cdr)
+{
+ pair foo = calloc(1, sizeof(*foo));
+ if (!foo)
+ error("no memory for cons.");
+ foo->car = car;
+ foo->cdr = cdr;
+ return (foo);
+}
diff --git a/freebsd/sbin/dhclient/tree.h b/freebsd/sbin/dhclient/tree.h
new file mode 100644
index 00000000..04e08e7c
--- /dev/null
+++ b/freebsd/sbin/dhclient/tree.h
@@ -0,0 +1,66 @@
+/* $OpenBSD: tree.h,v 1.5 2004/05/06 22:29:15 deraadt Exp $ */
+
+/* Definitions for address trees... */
+
+/*
+ * Copyright (c) 1995 The Internet Software Consortium. 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 Internet Software Consortium 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 INTERNET SOFTWARE CONSORTIUM 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 INTERNET SOFTWARE CONSORTIUM 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 software has been written for the Internet Software Consortium
+ * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
+ * Enterprises. To learn more about the Internet Software Consortium,
+ * see ``http://www.vix.com/isc''. To learn more about Vixie
+ * Enterprises, see ``http://www.vix.com''.
+ */
+
+/* A pair of pointers, suitable for making a linked list. */
+typedef struct _pair {
+ caddr_t car;
+ struct _pair *cdr;
+} *pair;
+
+struct tree_cache {
+ unsigned char *value;
+ int len;
+ int buf_size;
+ time_t timeout;
+};
+
+struct universe {
+ char *name;
+ struct hash_table *hash;
+ struct option *options[256];
+};
+
+struct option {
+ char *name;
+ char *format;
+ struct universe *universe;
+ unsigned char code;
+};
diff --git a/freebsd/sbin/ifconfig/af_atalk.c b/freebsd/sbin/ifconfig/af_atalk.c
new file mode 100644
index 00000000..c50e0fd1
--- /dev/null
+++ b/freebsd/sbin/ifconfig/af_atalk.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 1983, 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 rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <netatalk/at.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ifaddrs.h>
+
+#include <arpa/inet.h>
+
+#include "ifconfig.h"
+
+static struct netrange at_nr; /* AppleTalk net range */
+static struct ifaliasreq at_addreq;
+
+/* XXX FIXME -- should use strtoul for better parsing. */
+static void
+setatrange(const char *range, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ u_int first = 123, last = 123;
+
+ if (sscanf(range, "%u-%u", &first, &last) != 2
+ || first == 0 || first > 0xffff
+ || last == 0 || last > 0xffff || first > last)
+ errx(1, "%s: illegal net range: %u-%u", range, first, last);
+ at_nr.nr_firstnet = htons(first);
+ at_nr.nr_lastnet = htons(last);
+}
+
+static void
+setatphase(const char *phase, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ if (!strcmp(phase, "1"))
+ at_nr.nr_phase = 1;
+ else if (!strcmp(phase, "2"))
+ at_nr.nr_phase = 2;
+ else
+ errx(1, "%s: illegal phase", phase);
+}
+
+static void
+at_status(int s __unused, const struct ifaddrs *ifa)
+{
+ struct sockaddr_at *sat, null_sat;
+ struct netrange *nr;
+
+ memset(&null_sat, 0, sizeof(null_sat));
+
+ sat = (struct sockaddr_at *)ifa->ifa_addr;
+ if (sat == NULL)
+ return;
+ nr = &sat->sat_range.r_netrange;
+ printf("\tatalk %d.%d range %d-%d phase %d",
+ ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
+ ntohs(nr->nr_firstnet), ntohs(nr->nr_lastnet), nr->nr_phase);
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ sat = (struct sockaddr_at *)ifa->ifa_dstaddr;
+ if (sat == NULL)
+ sat = &null_sat;
+ printf("--> %d.%d",
+ ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node);
+ }
+ if (ifa->ifa_flags & IFF_BROADCAST) {
+ sat = (struct sockaddr_at *)ifa->ifa_broadaddr;
+ if (sat != NULL)
+ printf(" broadcast %d.%d",
+ ntohs(sat->sat_addr.s_net),
+ sat->sat_addr.s_node);
+ }
+
+ putchar('\n');
+}
+
+static void
+at_getaddr(const char *addr, int which)
+{
+ struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
+ u_int net, node;
+
+ sat->sat_family = AF_APPLETALK;
+ sat->sat_len = sizeof(*sat);
+ if (which == MASK)
+ errx(1, "AppleTalk does not use netmasks");
+ if (sscanf(addr, "%u.%u", &net, &node) != 2
+ || net > 0xffff || node > 0xfe)
+ errx(1, "%s: illegal address", addr);
+ sat->sat_addr.s_net = htons(net);
+ sat->sat_addr.s_node = node;
+}
+
+static void
+at_postproc(int s, const struct afswtch *afp)
+{
+ struct sockaddr_at *sat = (struct sockaddr_at *) &at_addreq.ifra_addr;
+
+ if (at_nr.nr_phase == 0)
+ at_nr.nr_phase = 2; /* Default phase 2 */
+ if (at_nr.nr_firstnet == 0)
+ at_nr.nr_firstnet = /* Default range of one */
+ at_nr.nr_lastnet = sat->sat_addr.s_net;
+ printf("\tatalk %d.%d range %d-%d phase %d\n",
+ ntohs(sat->sat_addr.s_net), sat->sat_addr.s_node,
+ ntohs(at_nr.nr_firstnet), ntohs(at_nr.nr_lastnet),
+ at_nr.nr_phase);
+ if ((u_short) ntohs(at_nr.nr_firstnet) >
+ (u_short) ntohs(sat->sat_addr.s_net)
+ || (u_short) ntohs(at_nr.nr_lastnet) <
+ (u_short) ntohs(sat->sat_addr.s_net))
+ errx(1, "AppleTalk address is not in range");
+ sat->sat_range.r_netrange = at_nr;
+}
+
+static struct cmd atalk_cmds[] = {
+ DEF_CMD_ARG("range", setatrange),
+ DEF_CMD_ARG("phase", setatphase),
+};
+
+static struct afswtch af_atalk = {
+ .af_name = "atalk",
+ .af_af = AF_APPLETALK,
+ .af_status = at_status,
+ .af_getaddr = at_getaddr,
+ .af_postproc = at_postproc,
+ .af_difaddr = SIOCDIFADDR,
+ .af_aifaddr = SIOCAIFADDR,
+ .af_ridreq = &at_addreq,
+ .af_addreq = &at_addreq,
+};
+
+static __constructor void
+atalk_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(atalk_cmds); i++)
+ cmd_register(&atalk_cmds[i]);
+ af_register(&af_atalk);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/af_inet.c b/freebsd/sbin/ifconfig/af_inet.c
new file mode 100644
index 00000000..65488a35
--- /dev/null
+++ b/freebsd/sbin/ifconfig/af_inet.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 1983, 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 rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ifaddrs.h>
+
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h> /* for struct ifaddr */
+#include <freebsd/netinet/in_var.h>
+#else
+#include <net/if_var.h> /* for struct ifaddr */
+#include <netinet/in_var.h>
+#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "ifconfig.h"
+
+#ifdef __rtems__
+#include <freebsd/sys/sockio.h>
+#endif
+
+static struct in_aliasreq in_addreq;
+static struct ifreq in_ridreq;
+
+static void
+in_status(int s __unused, const struct ifaddrs *ifa)
+{
+ struct sockaddr_in *sin, null_sin;
+
+ memset(&null_sin, 0, sizeof(null_sin));
+
+ sin = (struct sockaddr_in *)ifa->ifa_addr;
+ if (sin == NULL)
+ return;
+
+ printf("\tinet %s ", inet_ntoa(sin->sin_addr));
+
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ sin = (struct sockaddr_in *)ifa->ifa_dstaddr;
+ if (sin == NULL)
+ sin = &null_sin;
+ printf("--> %s ", inet_ntoa(sin->sin_addr));
+ }
+
+ sin = (struct sockaddr_in *)ifa->ifa_netmask;
+ if (sin == NULL)
+ sin = &null_sin;
+ printf("netmask 0x%lx ", (unsigned long)ntohl(sin->sin_addr.s_addr));
+
+ if (ifa->ifa_flags & IFF_BROADCAST) {
+ sin = (struct sockaddr_in *)ifa->ifa_broadaddr;
+ if (sin != NULL && sin->sin_addr.s_addr != 0)
+ printf("broadcast %s", inet_ntoa(sin->sin_addr));
+ }
+ putchar('\n');
+}
+
+#define SIN(x) ((struct sockaddr_in *) &(x))
+static struct sockaddr_in *sintab[] = {
+ SIN(in_ridreq.ifr_addr), SIN(in_addreq.ifra_addr),
+ SIN(in_addreq.ifra_mask), SIN(in_addreq.ifra_broadaddr)
+};
+
+static void
+in_getaddr(const char *s, int which)
+{
+#define MIN(a,b) ((a)<(b)?(a):(b))
+ struct sockaddr_in *sin = sintab[which];
+ struct hostent *hp;
+ struct netent *np;
+
+ sin->sin_len = sizeof(*sin);
+ if (which != MASK)
+ sin->sin_family = AF_INET;
+
+ if (which == ADDR) {
+ char *p = NULL;
+
+ if((p = strrchr(s, '/')) != NULL) {
+ const char *errstr;
+ /* address is `name/masklen' */
+ int masklen;
+ struct sockaddr_in *min = sintab[MASK];
+ *p = '\0';
+ if (!isdigit(*(p + 1)))
+ errstr = "invalid";
+ else
+ masklen = (int)strtonum(p + 1, 0, 32, &errstr);
+ if (errstr != NULL) {
+ *p = '/';
+ errx(1, "%s: bad value (width %s)", s, errstr);
+ }
+ min->sin_len = sizeof(*min);
+ min->sin_addr.s_addr = htonl(~((1LL << (32 - masklen)) - 1) &
+ 0xffffffff);
+ }
+ }
+
+ if (inet_aton(s, &sin->sin_addr))
+ return;
+ if ((hp = gethostbyname(s)) != 0)
+ bcopy(hp->h_addr, (char *)&sin->sin_addr,
+ MIN((size_t)hp->h_length, sizeof(sin->sin_addr)));
+ else if ((np = getnetbyname(s)) != 0)
+ sin->sin_addr = inet_makeaddr(np->n_net, INADDR_ANY);
+ else
+ errx(1, "%s: bad value", s);
+#undef MIN
+}
+
+static void
+in_status_tunnel(int s)
+{
+ char src[NI_MAXHOST];
+ char dst[NI_MAXHOST];
+ struct ifreq ifr;
+ const struct sockaddr *sa = (const struct sockaddr *) &ifr.ifr_addr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, name, IFNAMSIZ);
+
+ if (ioctl(s, SIOCGIFPSRCADDR, (caddr_t)&ifr) < 0)
+ return;
+ if (sa->sa_family != AF_INET)
+ return;
+ if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0, NI_NUMERICHOST) != 0)
+ src[0] = '\0';
+
+ if (ioctl(s, SIOCGIFPDSTADDR, (caddr_t)&ifr) < 0)
+ return;
+ if (sa->sa_family != AF_INET)
+ return;
+ if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0, NI_NUMERICHOST) != 0)
+ dst[0] = '\0';
+
+ printf("\ttunnel inet %s --> %s\n", src, dst);
+}
+
+static void
+in_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
+{
+ struct in_aliasreq addreq;
+
+ memset(&addreq, 0, sizeof(addreq));
+ strncpy(addreq.ifra_name, name, IFNAMSIZ);
+ memcpy(&addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
+ memcpy(&addreq.ifra_dstaddr, dstres->ai_addr, dstres->ai_addr->sa_len);
+
+ if (ioctl(s, SIOCSIFPHYADDR, &addreq) < 0)
+ warn("SIOCSIFPHYADDR");
+}
+
+static struct afswtch af_inet = {
+ .af_name = "inet",
+ .af_af = AF_INET,
+ .af_status = in_status,
+ .af_getaddr = in_getaddr,
+ .af_status_tunnel = in_status_tunnel,
+ .af_settunnel = in_set_tunnel,
+ .af_difaddr = SIOCDIFADDR,
+ .af_aifaddr = SIOCAIFADDR,
+ .af_ridreq = &in_ridreq,
+ .af_addreq = &in_addreq,
+};
+
+static __constructor void
+inet_ctor(void)
+{
+ af_register(&af_inet);
+}
diff --git a/freebsd/sbin/ifconfig/af_inet6.c b/freebsd/sbin/ifconfig/af_inet6.c
new file mode 100644
index 00000000..ff0df5b0
--- /dev/null
+++ b/freebsd/sbin/ifconfig/af_inet6.c
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 1983, 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 rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ifaddrs.h>
+
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h> /* for struct ifaddr */
+#include <freebsd/netinet/in_var.h>
+#else
+#include <net/if_var.h> /* for struct ifaddr */
+#include <netinet/in_var.h>
+#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#ifdef __rtems__
+#include <freebsd/netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */
+#else
+#include <netinet6/nd6.h> /* Define ND6_INFINITE_LIFETIME */
+#endif
+
+#include "ifconfig.h"
+
+static struct in6_ifreq in6_ridreq;
+static struct in6_aliasreq in6_addreq =
+ { .ifra_flags = 0,
+ .ifra_lifetime = { 0, 0, ND6_INFINITE_LIFETIME, ND6_INFINITE_LIFETIME } };
+static int ip6lifetime;
+
+static void in6_fillscopeid(struct sockaddr_in6 *sin6);
+static int prefix(void *, int);
+static char *sec2str(time_t);
+static int explicit_prefix = 0;
+
+extern void setnd6flags(const char *, int, int, const struct afswtch *);
+extern void setnd6defif(const char *, int, int, const struct afswtch *);
+
+static char addr_buf[MAXHOSTNAMELEN *2 + 1]; /*for getnameinfo()*/
+
+static void
+setifprefixlen(const char *addr, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ if (afp->af_getprefix != NULL)
+ afp->af_getprefix(addr, MASK);
+ explicit_prefix = 1;
+}
+
+static void
+setip6flags(const char *dummyaddr __unused, int flag, int dummysoc __unused,
+ const struct afswtch *afp)
+{
+ if (afp->af_af != AF_INET6)
+ err(1, "address flags can be set only for inet6 addresses");
+
+ if (flag < 0)
+ in6_addreq.ifra_flags &= ~(-flag);
+ else
+ in6_addreq.ifra_flags |= flag;
+}
+
+static void
+setip6lifetime(const char *cmd, const char *val, int s,
+ const struct afswtch *afp)
+{
+ time_t newval, t;
+ char *ep;
+
+ t = time(NULL);
+ newval = (time_t)strtoul(val, &ep, 0);
+ if (val == ep)
+ errx(1, "invalid %s", cmd);
+ if (afp->af_af != AF_INET6)
+ errx(1, "%s not allowed for the AF", cmd);
+ if (strcmp(cmd, "vltime") == 0) {
+ in6_addreq.ifra_lifetime.ia6t_expire = t + newval;
+ in6_addreq.ifra_lifetime.ia6t_vltime = newval;
+ } else if (strcmp(cmd, "pltime") == 0) {
+ in6_addreq.ifra_lifetime.ia6t_preferred = t + newval;
+ in6_addreq.ifra_lifetime.ia6t_pltime = newval;
+ }
+}
+
+static void
+setip6pltime(const char *seconds, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ setip6lifetime("pltime", seconds, s, afp);
+}
+
+static void
+setip6vltime(const char *seconds, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ setip6lifetime("vltime", seconds, s, afp);
+}
+
+static void
+setip6eui64(const char *cmd, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ struct ifaddrs *ifap, *ifa;
+ const struct sockaddr_in6 *sin6 = NULL;
+ const struct in6_addr *lladdr = NULL;
+ struct in6_addr *in6;
+
+ if (afp->af_af != AF_INET6)
+ errx(EXIT_FAILURE, "%s not allowed for the AF", cmd);
+ in6 = (struct in6_addr *)&in6_addreq.ifra_addr.sin6_addr;
+ if (memcmp(&in6addr_any.s6_addr[8], &in6->s6_addr[8], 8) != 0)
+ errx(EXIT_FAILURE, "interface index is already filled");
+ if (getifaddrs(&ifap) != 0)
+ err(EXIT_FAILURE, "getifaddrs");
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family == AF_INET6 &&
+ strcmp(ifa->ifa_name, name) == 0) {
+ sin6 = (const struct sockaddr_in6 *)ifa->ifa_addr;
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ lladdr = &sin6->sin6_addr;
+ break;
+ }
+ }
+ }
+ if (!lladdr)
+ errx(EXIT_FAILURE, "could not determine link local address");
+
+ memcpy(&in6->s6_addr[8], &lladdr->s6_addr[8], 8);
+
+ freeifaddrs(ifap);
+}
+
+static void
+in6_fillscopeid(struct sockaddr_in6 *sin6)
+{
+#if defined(__KAME__) && defined(KAME_SCOPEID)
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+ sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+}
+
+static void
+in6_status(int s __unused, const struct ifaddrs *ifa)
+{
+ struct sockaddr_in6 *sin, null_sin;
+ struct in6_ifreq ifr6;
+ int s6;
+ u_int32_t flags6;
+ struct in6_addrlifetime lifetime;
+ time_t t = time(NULL);
+ int error;
+ u_int32_t scopeid;
+
+ memset(&null_sin, 0, sizeof(null_sin));
+
+ sin = (struct sockaddr_in6 *)ifa->ifa_addr;
+ if (sin == NULL)
+ return;
+
+ strncpy(ifr6.ifr_name, ifr.ifr_name, sizeof(ifr.ifr_name));
+ if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ warn("socket(AF_INET6,SOCK_DGRAM)");
+ return;
+ }
+ ifr6.ifr_addr = *sin;
+ if (ioctl(s6, SIOCGIFAFLAG_IN6, &ifr6) < 0) {
+ warn("ioctl(SIOCGIFAFLAG_IN6)");
+ close(s6);
+ return;
+ }
+ flags6 = ifr6.ifr_ifru.ifru_flags6;
+ memset(&lifetime, 0, sizeof(lifetime));
+ ifr6.ifr_addr = *sin;
+ if (ioctl(s6, SIOCGIFALIFETIME_IN6, &ifr6) < 0) {
+ warn("ioctl(SIOCGIFALIFETIME_IN6)");
+ close(s6);
+ return;
+ }
+ lifetime = ifr6.ifr_ifru.ifru_lifetime;
+ close(s6);
+
+ /* XXX: embedded link local addr check */
+ if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) &&
+ *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) {
+ u_short index;
+
+ index = *(u_short *)&sin->sin6_addr.s6_addr[2];
+ *(u_short *)&sin->sin6_addr.s6_addr[2] = 0;
+ if (sin->sin6_scope_id == 0)
+ sin->sin6_scope_id = ntohs(index);
+ }
+ scopeid = sin->sin6_scope_id;
+
+ error = getnameinfo((struct sockaddr *)sin, sin->sin6_len, addr_buf,
+ sizeof(addr_buf), NULL, 0, NI_NUMERICHOST);
+ if (error != 0)
+ inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
+ sizeof(addr_buf));
+ printf("\tinet6 %s ", addr_buf);
+
+ if (ifa->ifa_flags & IFF_POINTOPOINT) {
+ sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
+ /*
+ * some of the interfaces do not have valid destination
+ * address.
+ */
+ if (sin != NULL && sin->sin6_family == AF_INET6) {
+ int error;
+
+ /* XXX: embedded link local addr check */
+ if (IN6_IS_ADDR_LINKLOCAL(&sin->sin6_addr) &&
+ *(u_short *)&sin->sin6_addr.s6_addr[2] != 0) {
+ u_short index;
+
+ index = *(u_short *)&sin->sin6_addr.s6_addr[2];
+ *(u_short *)&sin->sin6_addr.s6_addr[2] = 0;
+ if (sin->sin6_scope_id == 0)
+ sin->sin6_scope_id = ntohs(index);
+ }
+
+ error = getnameinfo((struct sockaddr *)sin,
+ sin->sin6_len, addr_buf,
+ sizeof(addr_buf), NULL, 0,
+ NI_NUMERICHOST);
+ if (error != 0)
+ inet_ntop(AF_INET6, &sin->sin6_addr, addr_buf,
+ sizeof(addr_buf));
+ printf("--> %s ", addr_buf);
+ }
+ }
+
+ sin = (struct sockaddr_in6 *)ifa->ifa_netmask;
+ if (sin == NULL)
+ sin = &null_sin;
+ printf("prefixlen %d ", prefix(&sin->sin6_addr,
+ sizeof(struct in6_addr)));
+
+ if ((flags6 & IN6_IFF_ANYCAST) != 0)
+ printf("anycast ");
+ if ((flags6 & IN6_IFF_TENTATIVE) != 0)
+ printf("tentative ");
+ if ((flags6 & IN6_IFF_DUPLICATED) != 0)
+ printf("duplicated ");
+ if ((flags6 & IN6_IFF_DETACHED) != 0)
+ printf("detached ");
+ if ((flags6 & IN6_IFF_DEPRECATED) != 0)
+ printf("deprecated ");
+ if ((flags6 & IN6_IFF_AUTOCONF) != 0)
+ printf("autoconf ");
+ if ((flags6 & IN6_IFF_TEMPORARY) != 0)
+ printf("temporary ");
+
+ if (scopeid)
+ printf("scopeid 0x%x ", scopeid);
+
+ if (ip6lifetime && (lifetime.ia6t_preferred || lifetime.ia6t_expire)) {
+ printf("pltime ");
+ if (lifetime.ia6t_preferred) {
+ printf("%s ", lifetime.ia6t_preferred < t
+ ? "0" : sec2str(lifetime.ia6t_preferred - t));
+ } else
+ printf("infty ");
+
+ printf("vltime ");
+ if (lifetime.ia6t_expire) {
+ printf("%s ", lifetime.ia6t_expire < t
+ ? "0" : sec2str(lifetime.ia6t_expire - t));
+ } else
+ printf("infty ");
+ }
+
+ putchar('\n');
+}
+
+#define SIN6(x) ((struct sockaddr_in6 *) &(x))
+static struct sockaddr_in6 *sin6tab[] = {
+ SIN6(in6_ridreq.ifr_addr), SIN6(in6_addreq.ifra_addr),
+ SIN6(in6_addreq.ifra_prefixmask), SIN6(in6_addreq.ifra_dstaddr)
+};
+
+static void
+in6_getprefix(const char *plen, int which)
+{
+ struct sockaddr_in6 *sin = sin6tab[which];
+ u_char *cp;
+ int len = atoi(plen);
+
+ if ((len < 0) || (len > 128))
+ errx(1, "%s: bad value", plen);
+ sin->sin6_len = sizeof(*sin);
+ if (which != MASK)
+ sin->sin6_family = AF_INET6;
+ if ((len == 0) || (len == 128)) {
+ memset(&sin->sin6_addr, 0xff, sizeof(struct in6_addr));
+ return;
+ }
+ memset((void *)&sin->sin6_addr, 0x00, sizeof(sin->sin6_addr));
+ for (cp = (u_char *)&sin->sin6_addr; len > 7; len -= 8)
+ *cp++ = 0xff;
+ *cp = 0xff << (8 - len);
+}
+
+static void
+in6_getaddr(const char *s, int which)
+{
+ struct sockaddr_in6 *sin = sin6tab[which];
+ struct addrinfo hints, *res;
+ int error = -1;
+
+ newaddr &= 1;
+
+ sin->sin6_len = sizeof(*sin);
+ if (which != MASK)
+ sin->sin6_family = AF_INET6;
+
+ if (which == ADDR) {
+ char *p = NULL;
+ if((p = strrchr(s, '/')) != NULL) {
+ *p = '\0';
+ in6_getprefix(p + 1, MASK);
+ explicit_prefix = 1;
+ }
+ }
+
+ if (sin->sin6_family == AF_INET6) {
+ bzero(&hints, sizeof(struct addrinfo));
+ hints.ai_family = AF_INET6;
+ error = getaddrinfo(s, NULL, &hints, &res);
+ }
+ if (error != 0) {
+ if (inet_pton(AF_INET6, s, &sin->sin6_addr) != 1)
+ errx(1, "%s: bad value", s);
+ } else
+ bcopy(res->ai_addr, sin, res->ai_addrlen);
+}
+
+static int
+prefix(void *val, int size)
+{
+ u_char *name = (u_char *)val;
+ int byte, bit, plen = 0;
+
+ for (byte = 0; byte < size; byte++, plen += 8)
+ if (name[byte] != 0xff)
+ break;
+ if (byte == size)
+ return (plen);
+ for (bit = 7; bit != 0; bit--, plen++)
+ if (!(name[byte] & (1 << bit)))
+ break;
+ for (; bit != 0; bit--)
+ if (name[byte] & (1 << bit))
+ return(0);
+ byte++;
+ for (; byte < size; byte++)
+ if (name[byte])
+ return(0);
+ return (plen);
+}
+
+static char *
+sec2str(time_t total)
+{
+ static char result[256];
+ int days, hours, mins, secs;
+ int first = 1;
+ char *p = result;
+
+ if (0) {
+ days = total / 3600 / 24;
+ hours = (total / 3600) % 24;
+ mins = (total / 60) % 60;
+ secs = total % 60;
+
+ if (days) {
+ first = 0;
+ p += sprintf(p, "%dd", days);
+ }
+ if (!first || hours) {
+ first = 0;
+ p += sprintf(p, "%dh", hours);
+ }
+ if (!first || mins) {
+ first = 0;
+ p += sprintf(p, "%dm", mins);
+ }
+ sprintf(p, "%ds", secs);
+ } else
+ sprintf(result, "%lu", (unsigned long)total);
+
+ return(result);
+}
+
+static void
+in6_postproc(int s, const struct afswtch *afp)
+{
+ if (explicit_prefix == 0) {
+ /* Aggregatable address architecture defines all prefixes
+ are 64. So, it is convenient to set prefixlen to 64 if
+ it is not specified. */
+ setifprefixlen("64", 0, s, afp);
+ /* in6_getprefix("64", MASK) if MASK is available here... */
+ }
+}
+
+static void
+in6_status_tunnel(int s)
+{
+ char src[NI_MAXHOST];
+ char dst[NI_MAXHOST];
+ struct in6_ifreq in6_ifr;
+ const struct sockaddr *sa = (const struct sockaddr *) &in6_ifr.ifr_addr;
+
+ memset(&in6_ifr, 0, sizeof(in6_ifr));
+ strncpy(in6_ifr.ifr_name, name, IFNAMSIZ);
+
+ if (ioctl(s, SIOCGIFPSRCADDR_IN6, (caddr_t)&in6_ifr) < 0)
+ return;
+ if (sa->sa_family != AF_INET6)
+ return;
+ in6_fillscopeid(&in6_ifr.ifr_addr);
+ if (getnameinfo(sa, sa->sa_len, src, sizeof(src), 0, 0,
+ NI_NUMERICHOST) != 0)
+ src[0] = '\0';
+
+ if (ioctl(s, SIOCGIFPDSTADDR_IN6, (caddr_t)&in6_ifr) < 0)
+ return;
+ if (sa->sa_family != AF_INET6)
+ return;
+ in6_fillscopeid(&in6_ifr.ifr_addr);
+ if (getnameinfo(sa, sa->sa_len, dst, sizeof(dst), 0, 0,
+ NI_NUMERICHOST) != 0)
+ dst[0] = '\0';
+
+ printf("\ttunnel inet6 %s --> %s\n", src, dst);
+}
+
+static void
+in6_set_tunnel(int s, struct addrinfo *srcres, struct addrinfo *dstres)
+{
+ struct in6_aliasreq in6_addreq;
+
+ memset(&in6_addreq, 0, sizeof(in6_addreq));
+ strncpy(in6_addreq.ifra_name, name, IFNAMSIZ);
+ memcpy(&in6_addreq.ifra_addr, srcres->ai_addr, srcres->ai_addr->sa_len);
+ memcpy(&in6_addreq.ifra_dstaddr, dstres->ai_addr,
+ dstres->ai_addr->sa_len);
+
+ if (ioctl(s, SIOCSIFPHYADDR_IN6, &in6_addreq) < 0)
+ warn("SIOCSIFPHYADDR_IN6");
+}
+
+static struct cmd inet6_cmds[] = {
+ DEF_CMD_ARG("prefixlen", setifprefixlen),
+ DEF_CMD("anycast", IN6_IFF_ANYCAST, setip6flags),
+ DEF_CMD("tentative", IN6_IFF_TENTATIVE, setip6flags),
+ DEF_CMD("-tentative", -IN6_IFF_TENTATIVE, setip6flags),
+ DEF_CMD("deprecated", IN6_IFF_DEPRECATED, setip6flags),
+ DEF_CMD("-deprecated", -IN6_IFF_DEPRECATED, setip6flags),
+ DEF_CMD("autoconf", IN6_IFF_AUTOCONF, setip6flags),
+ DEF_CMD("-autoconf", -IN6_IFF_AUTOCONF, setip6flags),
+ DEF_CMD("accept_rtadv", ND6_IFF_ACCEPT_RTADV, setnd6flags),
+ DEF_CMD("-accept_rtadv",-ND6_IFF_ACCEPT_RTADV, setnd6flags),
+ DEF_CMD("defaultif", 1, setnd6defif),
+ DEF_CMD("-defaultif", -1, setnd6defif),
+ DEF_CMD("ifdisabled", ND6_IFF_IFDISABLED, setnd6flags),
+ DEF_CMD("-ifdisabled", -ND6_IFF_IFDISABLED, setnd6flags),
+ DEF_CMD("nud", ND6_IFF_PERFORMNUD, setnd6flags),
+ DEF_CMD("-nud", -ND6_IFF_PERFORMNUD, setnd6flags),
+ DEF_CMD("prefer_source",ND6_IFF_PREFER_SOURCE, setnd6flags),
+ DEF_CMD("-prefer_source",-ND6_IFF_PREFER_SOURCE,setnd6flags),
+ DEF_CMD_ARG("pltime", setip6pltime),
+ DEF_CMD_ARG("vltime", setip6vltime),
+ DEF_CMD("eui64", 0, setip6eui64),
+};
+
+static struct afswtch af_inet6 = {
+ .af_name = "inet6",
+ .af_af = AF_INET6,
+ .af_status = in6_status,
+ .af_getaddr = in6_getaddr,
+ .af_getprefix = in6_getprefix,
+ .af_postproc = in6_postproc,
+ .af_status_tunnel = in6_status_tunnel,
+ .af_settunnel = in6_set_tunnel,
+ .af_difaddr = SIOCDIFADDR_IN6,
+ .af_aifaddr = SIOCAIFADDR_IN6,
+ .af_ridreq = &in6_addreq,
+ .af_addreq = &in6_addreq,
+};
+
+static void
+in6_Lopt_cb(const char *optarg __unused)
+{
+ ip6lifetime++; /* print IPv6 address lifetime */
+}
+#ifdef __rtems__
+static struct ifconfig_option in6_Lopt = { .opt = "L", .opt_usage = "[-L]", .cb = in6_Lopt_cb };
+#else
+static struct option in6_Lopt = { .opt = "L", .opt_usage = "[-L]", .cb = in6_Lopt_cb };
+#endif
+
+static __constructor void
+inet6_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(inet6_cmds); i++)
+ cmd_register(&inet6_cmds[i]);
+ af_register(&af_inet6);
+ opt_register(&in6_Lopt);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/af_link.c b/freebsd/sbin/ifconfig/af_link.c
new file mode 100644
index 00000000..2de85045
--- /dev/null
+++ b/freebsd/sbin/ifconfig/af_link.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 1983, 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 rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ifaddrs.h>
+
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/ethernet.h>
+
+#include "ifconfig.h"
+
+#ifdef __rtems__
+#include <freebsd/sys/sockio.h>
+#endif
+
+static struct ifreq link_ridreq;
+
+static void
+link_status(int s __unused, const struct ifaddrs *ifa)
+{
+ /* XXX no const 'cuz LLADDR is defined wrong */
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *) ifa->ifa_addr;
+
+ if (sdl != NULL && sdl->sdl_alen > 0) {
+ if ((sdl->sdl_type == IFT_ETHER ||
+ sdl->sdl_type == IFT_L2VLAN ||
+ sdl->sdl_type == IFT_BRIDGE) &&
+ sdl->sdl_alen == ETHER_ADDR_LEN)
+ printf("\tether %s\n",
+ ether_ntoa((struct ether_addr *)LLADDR(sdl)));
+ else {
+ int n = sdl->sdl_nlen > 0 ? sdl->sdl_nlen + 1 : 0;
+
+ printf("\tlladdr %s\n", link_ntoa(sdl) + n);
+ }
+ }
+}
+
+static void
+link_getaddr(const char *addr, int which)
+{
+ char *temp;
+ struct sockaddr_dl sdl;
+ struct sockaddr *sa = &link_ridreq.ifr_addr;
+
+ if (which != ADDR)
+ errx(1, "can't set link-level netmask or broadcast");
+ if ((temp = malloc(strlen(addr) + 2)) == NULL)
+ errx(1, "malloc failed");
+ temp[0] = ':';
+ strcpy(temp + 1, addr);
+ sdl.sdl_len = sizeof(sdl);
+ link_addr(temp, &sdl);
+ free(temp);
+ if (sdl.sdl_alen > sizeof(sa->sa_data))
+ errx(1, "malformed link-level address");
+ sa->sa_family = AF_LINK;
+ sa->sa_len = sdl.sdl_alen;
+ bcopy(LLADDR(&sdl), sa->sa_data, sdl.sdl_alen);
+}
+
+static struct afswtch af_link = {
+ .af_name = "link",
+ .af_af = AF_LINK,
+ .af_status = link_status,
+ .af_getaddr = link_getaddr,
+ .af_aifaddr = SIOCSIFLLADDR,
+ .af_addreq = &link_ridreq,
+};
+static struct afswtch af_ether = {
+ .af_name = "ether",
+ .af_af = AF_LINK,
+ .af_status = link_status,
+ .af_getaddr = link_getaddr,
+ .af_aifaddr = SIOCSIFLLADDR,
+ .af_addreq = &link_ridreq,
+};
+static struct afswtch af_lladdr = {
+ .af_name = "lladdr",
+ .af_af = AF_LINK,
+ .af_status = link_status,
+ .af_getaddr = link_getaddr,
+ .af_aifaddr = SIOCSIFLLADDR,
+ .af_addreq = &link_ridreq,
+};
+
+static __constructor void
+link_ctor(void)
+{
+ af_register(&af_link);
+ af_register(&af_ether);
+ af_register(&af_lladdr);
+}
diff --git a/freebsd/sbin/ifconfig/af_nd6.c b/freebsd/sbin/ifconfig/af_nd6.c
new file mode 100644
index 00000000..74820732
--- /dev/null
+++ b/freebsd/sbin/ifconfig/af_nd6.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2009 Hiroki Sato. 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 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 rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <net/if.h>
+#include <net/route.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ifaddrs.h>
+
+#include <arpa/inet.h>
+
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#include <freebsd/netinet/in_var.h>
+#else
+#include <net/if_var.h>
+#include <netinet/in_var.h>
+#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#ifdef __rtems__
+#include <freebsd/netinet6/nd6.h>
+#else
+#include <netinet6/nd6.h>
+#endif
+
+#include "ifconfig.h"
+
+#define MAX_SYSCTL_TRY 5
+#define ND6BITS "\020\001PERFORMNUD\002ACCEPT_RTADV\003PREFER_SOURCE" \
+ "\004IFDISABLED\005DONT_SET_IFROUTE\006AUTO_LINKLOCAL" \
+ "\020DEFAULTIF"
+
+static int isnd6defif(int);
+void setnd6flags(const char *, int, int, const struct afswtch *);
+void setnd6defif(const char *, int, int, const struct afswtch *);
+
+void
+setnd6flags(const char *dummyaddr __unused,
+ int d, int s,
+ const struct afswtch *afp)
+{
+ struct in6_ndireq nd;
+ int error;
+
+ memset(&nd, 0, sizeof(nd));
+ strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+ error = ioctl(s, SIOCGIFINFO_IN6, &nd);
+ if (error) {
+ warn("ioctl(SIOCGIFINFO_IN6)");
+ return;
+ }
+ if (d < 0)
+ nd.ndi.flags &= ~(-d);
+ else
+ nd.ndi.flags |= d;
+ error = ioctl(s, SIOCSIFINFO_IN6, (caddr_t)&nd);
+ if (error)
+ warn("ioctl(SIOCSIFINFO_IN6)");
+}
+
+void
+setnd6defif(const char *dummyaddr __unused,
+ int d, int s,
+ const struct afswtch *afp)
+{
+ struct in6_ndifreq ndifreq;
+ int ifindex;
+ int error;
+
+ memset(&ndifreq, 0, sizeof(ndifreq));
+ strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+
+ if (d < 0) {
+ if (isnd6defif(s)) {
+ /* ifindex = 0 means to remove default if */
+ ifindex = 0;
+ } else
+ return;
+ } else if ((ifindex = if_nametoindex(ndifreq.ifname)) == 0) {
+ warn("if_nametoindex(%s)", ndifreq.ifname);
+ return;
+ }
+
+ ndifreq.ifindex = ifindex;
+ error = ioctl(s, SIOCSDEFIFACE_IN6, (caddr_t)&ndifreq);
+ if (error)
+ warn("ioctl(SIOCSDEFIFACE_IN6)");
+}
+
+static int
+isnd6defif(int s)
+{
+ struct in6_ndifreq ndifreq;
+ unsigned int ifindex;
+ int error;
+
+ memset(&ndifreq, 0, sizeof(ndifreq));
+ strncpy(ndifreq.ifname, ifr.ifr_name, sizeof(ndifreq.ifname));
+
+ ifindex = if_nametoindex(ndifreq.ifname);
+ error = ioctl(s, SIOCGDEFIFACE_IN6, (caddr_t)&ndifreq);
+ if (error) {
+ warn("ioctl(SIOCGDEFIFACE_IN6)");
+ return (error);
+ }
+ return (ndifreq.ifindex == ifindex);
+}
+
+static void
+nd6_status(int s)
+{
+ struct in6_ndireq nd;
+ struct rt_msghdr *rtm;
+ size_t needed;
+ char *buf, *next;
+ int mib[6], ntry;
+ int s6;
+ int error;
+ int isinet6, isdefif;
+
+ /* Check if the interface has at least one IPv6 address. */
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET6;
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = if_nametoindex(ifr.ifr_name);
+
+ /* Try to prevent a race between two sysctls. */
+ ntry = 0;
+ do {
+ error = sysctl(mib, 6, NULL, &needed, NULL, 0);
+ if (error) {
+ warn("sysctl(NET_RT_IFLIST)/estimate");
+ return;
+ }
+ buf = malloc(needed);
+ if (buf == NULL) {
+ warn("malloc for sysctl(NET_RT_IFLIST) failed");
+ return;
+ }
+ if ((error = sysctl(mib, 6, buf, &needed, NULL, 0)) < 0) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ warn("sysctl(NET_RT_IFLIST)/get");
+ free(buf);
+ return;
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ isinet6 = 0;
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ if (rtm->rtm_type == RTM_NEWADDR) {
+ isinet6 = 1;
+ break;
+ }
+ }
+ free(buf);
+ if (!isinet6)
+ return;
+
+ memset(&nd, 0, sizeof(nd));
+ strncpy(nd.ifname, ifr.ifr_name, sizeof(nd.ifname));
+ if ((s6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ warn("socket(AF_INET6, SOCK_DGRAM)");
+ return;
+ }
+ error = ioctl(s6, SIOCGIFINFO_IN6, &nd);
+ if (error) {
+ warn("ioctl(SIOCGIFINFO_IN6)");
+ close(s6);
+ return;
+ }
+ isdefif = isnd6defif(s6);
+ close(s6);
+ if (nd.ndi.flags == 0 && !isdefif)
+ return;
+ printb("\tnd6 options",
+ (unsigned int)(nd.ndi.flags | (isdefif << 15)), ND6BITS);
+ putchar('\n');
+}
+
+static struct afswtch af_nd6 = {
+ .af_name = "nd6",
+ .af_af = AF_LOCAL,
+ .af_other_status= nd6_status,
+};
+
+static __constructor void
+nd6_ctor(void)
+{
+ af_register(&af_nd6);
+}
diff --git a/freebsd/sbin/ifconfig/ifbridge.c b/freebsd/sbin/ifconfig/ifbridge.c
new file mode 100644
index 00000000..049a0e7c
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifbridge.c
@@ -0,0 +1,767 @@
+/*-
+ * Copyright 2001 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.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_bridgevar.h>
+#else
+#include <net/if_bridgevar.h>
+#endif
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+#ifdef __rtems__
+#include <freebsd/sys/sockio.h>
+#endif
+
+#define PV2ID(pv, epri, eaddr) do { \
+ epri = pv >> 48; \
+ eaddr[0] = pv >> 40; \
+ eaddr[1] = pv >> 32; \
+ eaddr[2] = pv >> 24; \
+ eaddr[3] = pv >> 16; \
+ eaddr[4] = pv >> 8; \
+ eaddr[5] = pv >> 0; \
+} while (0)
+
+static const char *stpstates[] = {
+ "disabled",
+ "listening",
+ "learning",
+ "forwarding",
+ "blocking",
+ "discarding"
+};
+static const char *stpproto[] = {
+ "stp",
+ "-",
+ "rstp"
+};
+static const char *stproles[] = {
+ "disabled",
+ "root",
+ "designated",
+ "alternate",
+ "backup"
+};
+
+static int
+get_val(const char *cp, u_long *valp)
+{
+ char *endptr;
+ u_long val;
+
+ errno = 0;
+ val = strtoul(cp, &endptr, 0);
+ if (cp[0] == '\0' || endptr[0] != '\0' || errno == ERANGE)
+ return (-1);
+
+ *valp = val;
+ return (0);
+}
+
+static int
+do_cmd(int sock, u_long op, void *arg, size_t argsize, int set)
+{
+ struct ifdrv ifd;
+
+ memset(&ifd, 0, sizeof(ifd));
+
+ strlcpy(ifd.ifd_name, ifr.ifr_name, sizeof(ifd.ifd_name));
+ ifd.ifd_cmd = op;
+ ifd.ifd_len = argsize;
+ ifd.ifd_data = arg;
+
+ return (ioctl(sock, set ? SIOCSDRVSPEC : SIOCGDRVSPEC, &ifd));
+}
+
+static void
+do_bridgeflag(int sock, const char *ifs, int flag, int set)
+{
+ struct ifbreq req;
+
+ strlcpy(req.ifbr_ifsname, ifs, sizeof(req.ifbr_ifsname));
+
+ if (do_cmd(sock, BRDGGIFFLGS, &req, sizeof(req), 0) < 0)
+ err(1, "unable to get bridge flags");
+
+ if (set)
+ req.ifbr_ifsflags |= flag;
+ else
+ req.ifbr_ifsflags &= ~flag;
+
+ if (do_cmd(sock, BRDGSIFFLGS, &req, sizeof(req), 1) < 0)
+ err(1, "unable to set bridge flags");
+}
+
+static void
+bridge_interfaces(int s, const char *prefix)
+{
+ struct ifbifconf bifc;
+ struct ifbreq *req;
+ char *inbuf = NULL, *ninbuf;
+ char *p, *pad;
+ int i, len = 8192;
+
+ pad = strdup(prefix);
+ if (pad == NULL)
+ err(1, "strdup");
+ /* replace the prefix with whitespace */
+ for (p = pad; *p != '\0'; p++) {
+ if(isprint(*p))
+ *p = ' ';
+ }
+
+ for (;;) {
+ ninbuf = realloc(inbuf, len);
+ if (ninbuf == NULL)
+ err(1, "unable to allocate interface buffer");
+ bifc.ifbic_len = len;
+ bifc.ifbic_buf = inbuf = ninbuf;
+ if (do_cmd(s, BRDGGIFS, &bifc, sizeof(bifc), 0) < 0)
+ err(1, "unable to get interface list");
+ if ((bifc.ifbic_len + sizeof(*req)) < len)
+ break;
+ len *= 2;
+ }
+
+ for (i = 0; i < bifc.ifbic_len / sizeof(*req); i++) {
+ req = bifc.ifbic_req + i;
+ printf("%s%s ", prefix, req->ifbr_ifsname);
+ printb("flags", req->ifbr_ifsflags, IFBIFBITS);
+ printf("\n");
+
+ printf("%s", pad);
+ printf("ifmaxaddr %u", req->ifbr_addrmax);
+ printf(" port %u priority %u", req->ifbr_portno,
+ req->ifbr_priority);
+ printf(" path cost %u", req->ifbr_path_cost);
+
+ if (req->ifbr_ifsflags & IFBIF_STP) {
+ if (req->ifbr_proto <
+ sizeof(stpproto) / sizeof(stpproto[0]))
+ printf(" proto %s", stpproto[req->ifbr_proto]);
+ else
+ printf(" <unknown proto %d>",
+ req->ifbr_proto);
+
+ printf("\n%s", pad);
+ if (req->ifbr_role <
+ sizeof(stproles) / sizeof(stproles[0]))
+ printf("role %s", stproles[req->ifbr_role]);
+ else
+ printf("<unknown role %d>",
+ req->ifbr_role);
+ if (req->ifbr_state <
+ sizeof(stpstates) / sizeof(stpstates[0]))
+ printf(" state %s", stpstates[req->ifbr_state]);
+ else
+ printf(" <unknown state %d>",
+ req->ifbr_state);
+ }
+ printf("\n");
+ }
+
+ free(inbuf);
+}
+
+static void
+bridge_addresses(int s, const char *prefix)
+{
+ struct ifbaconf ifbac;
+ struct ifbareq *ifba;
+ char *inbuf = NULL, *ninbuf;
+ int i, len = 8192;
+ struct ether_addr ea;
+
+ for (;;) {
+ ninbuf = realloc(inbuf, len);
+ if (ninbuf == NULL)
+ err(1, "unable to allocate address buffer");
+ ifbac.ifbac_len = len;
+ ifbac.ifbac_buf = inbuf = ninbuf;
+ if (do_cmd(s, BRDGRTS, &ifbac, sizeof(ifbac), 0) < 0)
+ err(1, "unable to get address cache");
+ if ((ifbac.ifbac_len + sizeof(*ifba)) < len)
+ break;
+ len *= 2;
+ }
+
+ for (i = 0; i < ifbac.ifbac_len / sizeof(*ifba); i++) {
+ ifba = ifbac.ifbac_req + i;
+ memcpy(ea.octet, ifba->ifba_dst,
+ sizeof(ea.octet));
+ printf("%s%s Vlan%d %s %lu ", prefix, ether_ntoa(&ea),
+ ifba->ifba_vlan, ifba->ifba_ifsname, ifba->ifba_expire);
+ printb("flags", ifba->ifba_flags, IFBAFBITS);
+ printf("\n");
+ }
+
+ free(inbuf);
+}
+
+static void
+bridge_status(int s)
+{
+ struct ifbropreq ifbp;
+ struct ifbrparam param;
+ u_int16_t pri;
+ u_int8_t ht, fd, ma, hc, pro;
+ u_int8_t lladdr[ETHER_ADDR_LEN];
+ u_int16_t bprio;
+ u_int32_t csize, ctime;
+
+ if (do_cmd(s, BRDGGCACHE, &param, sizeof(param), 0) < 0)
+ return;
+ csize = param.ifbrp_csize;
+ if (do_cmd(s, BRDGGTO, &param, sizeof(param), 0) < 0)
+ return;
+ ctime = param.ifbrp_ctime;
+ if (do_cmd(s, BRDGPARAM, &ifbp, sizeof(ifbp), 0) < 0)
+ return;
+ pri = ifbp.ifbop_priority;
+ pro = ifbp.ifbop_protocol;
+ ht = ifbp.ifbop_hellotime;
+ fd = ifbp.ifbop_fwddelay;
+ hc = ifbp.ifbop_holdcount;
+ ma = ifbp.ifbop_maxage;
+
+ PV2ID(ifbp.ifbop_bridgeid, bprio, lladdr);
+ printf("\tid %s priority %u hellotime %u fwddelay %u\n",
+ ether_ntoa((struct ether_addr *)lladdr), pri, ht, fd);
+ printf("\tmaxage %u holdcnt %u proto %s maxaddr %u timeout %u\n",
+ ma, hc, stpproto[pro], csize, ctime);
+
+ PV2ID(ifbp.ifbop_designated_root, bprio, lladdr);
+ printf("\troot id %s priority %d ifcost %u port %u\n",
+ ether_ntoa((struct ether_addr *)lladdr), bprio,
+ ifbp.ifbop_root_path_cost, ifbp.ifbop_root_port & 0xfff);
+
+ bridge_interfaces(s, "\tmember: ");
+
+ return;
+
+}
+
+static void
+setbridge_add(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
+ if (do_cmd(s, BRDGADD, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGADD %s", val);
+}
+
+static void
+setbridge_delete(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
+ if (do_cmd(s, BRDGDEL, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGDEL %s", val);
+}
+
+static void
+setbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_DISCOVER, 1);
+}
+
+static void
+unsetbridge_discover(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_DISCOVER, 0);
+}
+
+static void
+setbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_LEARNING, 1);
+}
+
+static void
+unsetbridge_learn(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_LEARNING, 0);
+}
+
+static void
+setbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_STICKY, 1);
+}
+
+static void
+unsetbridge_sticky(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_STICKY, 0);
+}
+
+static void
+setbridge_span(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
+ if (do_cmd(s, BRDGADDS, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGADDS %s", val);
+}
+
+static void
+unsetbridge_span(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.ifbr_ifsname, val, sizeof(req.ifbr_ifsname));
+ if (do_cmd(s, BRDGDELS, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGDELS %s", val);
+}
+
+static void
+setbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_STP, 1);
+}
+
+static void
+unsetbridge_stp(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_STP, 0);
+}
+
+static void
+setbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 1);
+}
+
+static void
+unsetbridge_edge(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_EDGE, 0);
+}
+
+static void
+setbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 1);
+}
+
+static void
+unsetbridge_autoedge(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_AUTOEDGE, 0);
+}
+
+static void
+setbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_PTP, 1);
+}
+
+static void
+unsetbridge_ptp(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_PTP, 0);
+}
+
+static void
+setbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 1);
+}
+
+static void
+unsetbridge_autoptp(const char *val, int d, int s, const struct afswtch *afp)
+{
+ do_bridgeflag(s, val, IFBIF_BSTP_AUTOPTP, 0);
+}
+
+static void
+setbridge_flush(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ req.ifbr_ifsflags = IFBF_FLUSHDYN;
+ if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGFLUSH");
+}
+
+static void
+setbridge_flushall(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifbreq req;
+
+ memset(&req, 0, sizeof(req));
+ req.ifbr_ifsflags = IFBF_FLUSHALL;
+ if (do_cmd(s, BRDGFLUSH, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGFLUSH");
+}
+
+static void
+setbridge_static(const char *val, const char *mac, int s,
+ const struct afswtch *afp)
+{
+ struct ifbareq req;
+ struct ether_addr *ea;
+
+ memset(&req, 0, sizeof(req));
+ strlcpy(req.ifba_ifsname, val, sizeof(req.ifba_ifsname));
+
+ ea = ether_aton(mac);
+ if (ea == NULL)
+ errx(1, "%s: invalid address: %s", val, mac);
+
+ memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
+ req.ifba_flags = IFBAF_STATIC;
+ req.ifba_vlan = 1; /* XXX allow user to specify */
+
+ if (do_cmd(s, BRDGSADDR, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSADDR %s", val);
+}
+
+static void
+setbridge_deladdr(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifbareq req;
+ struct ether_addr *ea;
+
+ memset(&req, 0, sizeof(req));
+
+ ea = ether_aton(val);
+ if (ea == NULL)
+ errx(1, "invalid address: %s", val);
+
+ memcpy(req.ifba_dst, ea->octet, sizeof(req.ifba_dst));
+
+ if (do_cmd(s, BRDGDADDR, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGDADDR %s", val);
+}
+
+static void
+setbridge_addr(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ bridge_addresses(s, "");
+}
+
+static void
+setbridge_maxaddr(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_csize = val & 0xffffffff;
+
+ if (do_cmd(s, BRDGSCACHE, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSCACHE %s", arg);
+}
+
+static void
+setbridge_hellotime(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_hellotime = val & 0xff;
+
+ if (do_cmd(s, BRDGSHT, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSHT %s", arg);
+}
+
+static void
+setbridge_fwddelay(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_fwddelay = val & 0xff;
+
+ if (do_cmd(s, BRDGSFD, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSFD %s", arg);
+}
+
+static void
+setbridge_maxage(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_maxage = val & 0xff;
+
+ if (do_cmd(s, BRDGSMA, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSMA %s", arg);
+}
+
+static void
+setbridge_priority(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xffff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_prio = val & 0xffff;
+
+ if (do_cmd(s, BRDGSPRI, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSPRI %s", arg);
+}
+
+static void
+setbridge_protocol(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+
+ if (strcasecmp(arg, "stp") == 0) {
+ param.ifbrp_proto = 0;
+ } else if (strcasecmp(arg, "rstp") == 0) {
+ param.ifbrp_proto = 2;
+ } else {
+ errx(1, "unknown stp protocol");
+ }
+
+ if (do_cmd(s, BRDGSPROTO, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSPROTO %s", arg);
+}
+
+static void
+setbridge_holdcount(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_txhc = val & 0xff;
+
+ if (do_cmd(s, BRDGSTXHC, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSTXHC %s", arg);
+}
+
+static void
+setbridge_ifpriority(const char *ifn, const char *pri, int s,
+ const struct afswtch *afp)
+{
+ struct ifbreq req;
+ u_long val;
+
+ memset(&req, 0, sizeof(req));
+
+ if (get_val(pri, &val) < 0 || (val & ~0xff) != 0)
+ errx(1, "invalid value: %s", pri);
+
+ strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+ req.ifbr_priority = val & 0xff;
+
+ if (do_cmd(s, BRDGSIFPRIO, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFPRIO %s", pri);
+}
+
+static void
+setbridge_ifpathcost(const char *ifn, const char *cost, int s,
+ const struct afswtch *afp)
+{
+ struct ifbreq req;
+ u_long val;
+
+ memset(&req, 0, sizeof(req));
+
+ if (get_val(cost, &val) < 0)
+ errx(1, "invalid value: %s", cost);
+
+ strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+ req.ifbr_path_cost = val;
+
+ if (do_cmd(s, BRDGSIFCOST, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFCOST %s", cost);
+}
+
+static void
+setbridge_ifmaxaddr(const char *ifn, const char *arg, int s,
+ const struct afswtch *afp)
+{
+ struct ifbreq req;
+ u_long val;
+
+ memset(&req, 0, sizeof(req));
+
+ if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ strlcpy(req.ifbr_ifsname, ifn, sizeof(req.ifbr_ifsname));
+ req.ifbr_addrmax = val & 0xffffffff;
+
+ if (do_cmd(s, BRDGSIFAMAX, &req, sizeof(req), 1) < 0)
+ err(1, "BRDGSIFAMAX %s", arg);
+}
+
+static void
+setbridge_timeout(const char *arg, int d, int s, const struct afswtch *afp)
+{
+ struct ifbrparam param;
+ u_long val;
+
+ if (get_val(arg, &val) < 0 || (val & ~0xffffffff) != 0)
+ errx(1, "invalid value: %s", arg);
+
+ param.ifbrp_ctime = val & 0xffffffff;
+
+ if (do_cmd(s, BRDGSTO, &param, sizeof(param), 1) < 0)
+ err(1, "BRDGSTO %s", arg);
+}
+
+static void
+setbridge_private(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_PRIVATE, 1);
+}
+
+static void
+unsetbridge_private(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ do_bridgeflag(s, val, IFBIF_PRIVATE, 0);
+}
+
+static struct cmd bridge_cmds[] = {
+ DEF_CMD_ARG("addm", setbridge_add),
+ DEF_CMD_ARG("deletem", setbridge_delete),
+ DEF_CMD_ARG("discover", setbridge_discover),
+ DEF_CMD_ARG("-discover", unsetbridge_discover),
+ DEF_CMD_ARG("learn", setbridge_learn),
+ DEF_CMD_ARG("-learn", unsetbridge_learn),
+ DEF_CMD_ARG("sticky", setbridge_sticky),
+ DEF_CMD_ARG("-sticky", unsetbridge_sticky),
+ DEF_CMD_ARG("span", setbridge_span),
+ DEF_CMD_ARG("-span", unsetbridge_span),
+ DEF_CMD_ARG("stp", setbridge_stp),
+ DEF_CMD_ARG("-stp", unsetbridge_stp),
+ DEF_CMD_ARG("edge", setbridge_edge),
+ DEF_CMD_ARG("-edge", unsetbridge_edge),
+ DEF_CMD_ARG("autoedge", setbridge_autoedge),
+ DEF_CMD_ARG("-autoedge", unsetbridge_autoedge),
+ DEF_CMD_ARG("ptp", setbridge_ptp),
+ DEF_CMD_ARG("-ptp", unsetbridge_ptp),
+ DEF_CMD_ARG("autoptp", setbridge_autoptp),
+ DEF_CMD_ARG("-autoptp", unsetbridge_autoptp),
+ DEF_CMD("flush", 0, setbridge_flush),
+ DEF_CMD("flushall", 0, setbridge_flushall),
+ DEF_CMD_ARG2("static", setbridge_static),
+ DEF_CMD_ARG("deladdr", setbridge_deladdr),
+ DEF_CMD("addr", 1, setbridge_addr),
+ DEF_CMD_ARG("maxaddr", setbridge_maxaddr),
+ DEF_CMD_ARG("hellotime", setbridge_hellotime),
+ DEF_CMD_ARG("fwddelay", setbridge_fwddelay),
+ DEF_CMD_ARG("maxage", setbridge_maxage),
+ DEF_CMD_ARG("priority", setbridge_priority),
+ DEF_CMD_ARG("proto", setbridge_protocol),
+ DEF_CMD_ARG("holdcnt", setbridge_holdcount),
+ DEF_CMD_ARG2("ifpriority", setbridge_ifpriority),
+ DEF_CMD_ARG2("ifpathcost", setbridge_ifpathcost),
+ DEF_CMD_ARG2("ifmaxaddr", setbridge_ifmaxaddr),
+ DEF_CMD_ARG("timeout", setbridge_timeout),
+ DEF_CMD_ARG("private", setbridge_private),
+ DEF_CMD_ARG("-private", unsetbridge_private),
+};
+static struct afswtch af_bridge = {
+ .af_name = "af_bridge",
+ .af_af = AF_UNSPEC,
+ .af_other_status = bridge_status,
+};
+
+static __constructor void
+bridge_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ int i;
+
+ for (i = 0; i < N(bridge_cmds); i++)
+ cmd_register(&bridge_cmds[i]);
+ af_register(&af_bridge);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifcarp.c b/freebsd/sbin/ifconfig/ifcarp.c
new file mode 100644
index 00000000..6c8c5a1b
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifcarp.c
@@ -0,0 +1,204 @@
+/* $FreeBSD$ */
+/* from $OpenBSD: ifconfig.c,v 1.82 2003/10/19 05:43:35 mcbride Exp $ */
+
+/*
+ * Copyright (c) 2002 Michael Shalayeff. All rights reserved.
+ * Copyright (c) 2003 Ryan McBride. 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/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/netinet/ip_carp.h>
+#else
+#include <netinet/ip_carp.h>
+#endif
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+static const char *carp_states[] = { CARP_STATES };
+
+void carp_status(int s);
+void setcarp_advbase(const char *,int, int, const struct afswtch *rafp);
+void setcarp_advskew(const char *, int, int, const struct afswtch *rafp);
+void setcarp_passwd(const char *, int, int, const struct afswtch *rafp);
+void setcarp_vhid(const char *, int, int, const struct afswtch *rafp);
+
+void
+carp_status(int s)
+{
+ const char *state;
+ struct carpreq carpr;
+
+ memset((char *)&carpr, 0, sizeof(struct carpreq));
+ ifr.ifr_data = (caddr_t)&carpr;
+
+ if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
+ return;
+
+ if (carpr.carpr_vhid > 0) {
+ if (carpr.carpr_state > CARP_MAXSTATE)
+ state = "<UNKNOWN>";
+ else
+ state = carp_states[carpr.carpr_state];
+
+ printf("\tcarp: %s vhid %d advbase %d advskew %d\n",
+ state, carpr.carpr_vhid, carpr.carpr_advbase,
+ carpr.carpr_advskew);
+ }
+
+ return;
+
+}
+
+void
+setcarp_passwd(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct carpreq carpr;
+
+ memset((char *)&carpr, 0, sizeof(struct carpreq));
+ ifr.ifr_data = (caddr_t)&carpr;
+
+ if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGVH");
+
+ memset(carpr.carpr_key, 0, sizeof(carpr.carpr_key));
+ /* XXX Should hash the password into the key here, perhaps? */
+ strlcpy(carpr.carpr_key, val, CARP_KEY_LEN);
+
+ if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSVH");
+
+ return;
+}
+
+void
+setcarp_vhid(const char *val, int d, int s, const struct afswtch *afp)
+{
+ int vhid;
+ struct carpreq carpr;
+
+ vhid = atoi(val);
+
+ if (vhid <= 0)
+ errx(1, "vhid must be greater than 0");
+
+ memset((char *)&carpr, 0, sizeof(struct carpreq));
+ ifr.ifr_data = (caddr_t)&carpr;
+
+ if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGVH");
+
+ carpr.carpr_vhid = vhid;
+
+ if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSVH");
+
+ return;
+}
+
+void
+setcarp_advskew(const char *val, int d, int s, const struct afswtch *afp)
+{
+ int advskew;
+ struct carpreq carpr;
+
+ advskew = atoi(val);
+
+ memset((char *)&carpr, 0, sizeof(struct carpreq));
+ ifr.ifr_data = (caddr_t)&carpr;
+
+ if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGVH");
+
+ carpr.carpr_advskew = advskew;
+
+ if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSVH");
+
+ return;
+}
+
+void
+setcarp_advbase(const char *val, int d, int s, const struct afswtch *afp)
+{
+ int advbase;
+ struct carpreq carpr;
+
+ advbase = atoi(val);
+
+ memset((char *)&carpr, 0, sizeof(struct carpreq));
+ ifr.ifr_data = (caddr_t)&carpr;
+
+ if (ioctl(s, SIOCGVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGVH");
+
+ carpr.carpr_advbase = advbase;
+
+ if (ioctl(s, SIOCSVH, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSVH");
+
+ return;
+}
+
+static struct cmd carp_cmds[] = {
+ DEF_CMD_ARG("advbase", setcarp_advbase),
+ DEF_CMD_ARG("advskew", setcarp_advskew),
+ DEF_CMD_ARG("pass", setcarp_passwd),
+ DEF_CMD_ARG("vhid", setcarp_vhid),
+};
+static struct afswtch af_carp = {
+ .af_name = "af_carp",
+ .af_af = AF_UNSPEC,
+ .af_other_status = carp_status,
+};
+
+static __constructor void
+carp_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ int i;
+
+ for (i = 0; i < N(carp_cmds); i++)
+ cmd_register(&carp_cmds[i]);
+ af_register(&af_carp);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifclone.c b/freebsd/sbin/ifconfig/ifclone.c
new file mode 100644
index 00000000..7929208b
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifclone.c
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1983, 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 rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+#ifdef __rtems__
+#include <freebsd/sys/sockio.h>
+#endif
+
+static void
+list_cloners(void)
+{
+ struct if_clonereq ifcr;
+ char *cp, *buf;
+ int idx;
+ int s;
+
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s == -1)
+ err(1, "socket(AF_LOCAL,SOCK_DGRAM)");
+
+ memset(&ifcr, 0, sizeof(ifcr));
+
+ if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
+ err(1, "SIOCIFGCLONERS for count");
+
+ buf = malloc(ifcr.ifcr_total * IFNAMSIZ);
+ if (buf == NULL)
+ err(1, "unable to allocate cloner name buffer");
+
+ ifcr.ifcr_count = ifcr.ifcr_total;
+ ifcr.ifcr_buffer = buf;
+
+ if (ioctl(s, SIOCIFGCLONERS, &ifcr) < 0)
+ err(1, "SIOCIFGCLONERS for names");
+
+ /*
+ * In case some disappeared in the mean time, clamp it down.
+ */
+ if (ifcr.ifcr_count > ifcr.ifcr_total)
+ ifcr.ifcr_count = ifcr.ifcr_total;
+
+ for (cp = buf, idx = 0; idx < ifcr.ifcr_count; idx++, cp += IFNAMSIZ) {
+ if (idx > 0)
+ putchar(' ');
+ printf("%s", cp);
+ }
+
+ putchar('\n');
+ free(buf);
+}
+
+struct clone_defcb {
+ char ifprefix[IFNAMSIZ];
+ clone_callback_func *clone_cb;
+ SLIST_ENTRY(clone_defcb) next;
+};
+
+static SLIST_HEAD(, clone_defcb) clone_defcbh =
+ SLIST_HEAD_INITIALIZER(clone_defcbh);
+
+void
+clone_setdefcallback(const char *ifprefix, clone_callback_func *p)
+{
+ struct clone_defcb *dcp;
+
+ dcp = malloc(sizeof(*dcp));
+ strlcpy(dcp->ifprefix, ifprefix, IFNAMSIZ-1);
+ dcp->clone_cb = p;
+ SLIST_INSERT_HEAD(&clone_defcbh, dcp, next);
+}
+
+/*
+ * Do the actual clone operation. Any parameters must have been
+ * setup by now. If a callback has been setup to do the work
+ * then defer to it; otherwise do a simple create operation with
+ * no parameters.
+ */
+static void
+ifclonecreate(int s, void *arg)
+{
+ struct ifreq ifr;
+ struct clone_defcb *dcp;
+ clone_callback_func *clone_cb = NULL;
+
+ memset(&ifr, 0, sizeof(ifr));
+ (void) strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ if (clone_cb == NULL) {
+ /* Try to find a default callback */
+ SLIST_FOREACH(dcp, &clone_defcbh, next) {
+ if (strncmp(dcp->ifprefix, ifr.ifr_name,
+ strlen(dcp->ifprefix)) == 0) {
+ clone_cb = dcp->clone_cb;
+ break;
+ }
+ }
+ }
+ if (clone_cb == NULL) {
+ /* NB: no parameters */
+ if (ioctl(s, SIOCIFCREATE2, &ifr) < 0)
+ err(1, "SIOCIFCREATE2");
+ } else {
+ clone_cb(s, &ifr);
+ }
+
+ /*
+ * If we get a different name back than we put in, print it.
+ */
+ if (strncmp(name, ifr.ifr_name, sizeof(name)) != 0) {
+ strlcpy(name, ifr.ifr_name, sizeof(name));
+ printf("%s\n", name);
+ }
+}
+
+static
+DECL_CMD_FUNC(clone_create, arg, d)
+{
+ callback_register(ifclonecreate, NULL);
+}
+
+static
+DECL_CMD_FUNC(clone_destroy, arg, d)
+{
+ (void) strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCIFDESTROY, &ifr) < 0)
+ err(1, "SIOCIFDESTROY");
+}
+
+static struct cmd clone_cmds[] = {
+ DEF_CLONE_CMD("create", 0, clone_create),
+ DEF_CMD("destroy", 0, clone_destroy),
+ DEF_CLONE_CMD("plumb", 0, clone_create),
+ DEF_CMD("unplumb", 0, clone_destroy),
+};
+
+static void
+clone_Copt_cb(const char *optarg __unused)
+{
+ list_cloners();
+ exit(0);
+}
+#ifdef __rtems__
+static struct ifconfig_option clone_Copt = { .opt = "C", .opt_usage = "[-C]", .cb = clone_Copt_cb };
+#else
+static struct option clone_Copt = { .opt = "C", .opt_usage = "[-C]", .cb = clone_Copt_cb };
+#endif
+
+static __constructor void
+clone_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(clone_cmds); i++)
+ cmd_register(&clone_cmds[i]);
+ opt_register(&clone_Copt);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifconfig.c b/freebsd/sbin/ifconfig/ifconfig.c
new file mode 100644
index 00000000..afc952af
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifconfig.c
@@ -0,0 +1,1259 @@
+#ifdef __rtems__
+#define __need_getopt_newlib
+#include <getopt.h>
+#endif
+/*
+ * Copyright (c) 1983, 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) 1983, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ifconfig.c 8.2 (Berkeley) 2/16/94";
+#endif
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#ifdef __rtems__
+#include <freebsd/sys/module.h>
+#include <freebsd/sys/linker.h>
+#else
+#include <sys/module.h>
+#include <sys/linker.h>
+#endif
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#else
+#include <net/if_var.h>
+#endif
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/route.h>
+
+/* IP */
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/netinet/in_var.h>
+#else
+#include <netinet/in_var.h>
+#endif
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <ifaddrs.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#ifndef __rtems__
+#include <jail.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+/*
+ * Since "struct ifreq" is composed of various union members, callers
+ * should pay special attention to interprete the value.
+ * (.e.g. little/big endian difference in the structure.)
+ */
+struct ifreq ifr;
+
+char name[IFNAMSIZ];
+char *descr = NULL;
+size_t descrlen = 64;
+int setaddr;
+int setmask;
+int doalias;
+int clearaddr;
+int newaddr = 1;
+int verbose;
+int noload;
+
+int supmedia = 0;
+int printkeys = 0; /* Print keying material for interfaces. */
+
+static int ifconfig(int argc, char *const *argv, int iscreate,
+ const struct afswtch *afp);
+static void status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
+ struct ifaddrs *ifa);
+static void tunnel_status(int s);
+static void usage(void);
+
+static struct afswtch *af_getbyname(const char *name);
+static struct afswtch *af_getbyfamily(int af);
+static void af_other_status(int);
+
+#ifdef __rtems__
+static int main_ifconfig(int argc, char *argv[]);
+static int rtems_shell_main_ifconfig(int argc, char *argv[])
+{
+ rtems_shell_globals_t ifconfig_globals;
+ rtems_shell_globals = &ifconfig_globals;
+ memset (rtems_shell_globals, 0, sizeof (ifconfig_globals));
+ descr = NULL;
+ descrlen = 64;
+ newaddr = 1;
+ supmedia = 0;
+ printkeys = 0;
+ ifconfig_globals.exit_code = 1;
+ if (setjmp (ifconfig_globals.exit_jmp) == 0)
+ return main_ifconfig ( argc, argv);
+ return ifconfig_globals.exit_code;
+}
+#endif
+
+#ifdef __rtems__
+static struct ifconfig_option *opts = NULL;
+
+void
+opt_register(struct ifconfig_option *p)
+{
+ p->next = opts;
+ opts = p;
+}
+#else
+static struct option *opts = NULL;
+
+void
+opt_register(struct option *p)
+{
+ p->next = opts;
+ opts = p;
+}
+#endif
+
+static void
+usage(void)
+{
+ char options[1024];
+ #ifdef __rtems__
+ struct ifconfig_option *p;
+ #else
+ struct option *p;
+ #endif
+
+ /* XXX not right but close enough for now */
+ options[0] = '\0';
+ for (p = opts; p != NULL; p = p->next) {
+ strlcat(options, p->opt_usage, sizeof(options));
+ strlcat(options, " ", sizeof(options));
+ }
+
+ fprintf(stderr,
+ "usage: ifconfig %sinterface address_family [address [dest_address]]\n"
+ " [parameters]\n"
+ " ifconfig interface create\n"
+ " ifconfig -a %s[-d] [-m] [-u] [-v] [address_family]\n"
+ " ifconfig -l [-d] [-u] [address_family]\n"
+ " ifconfig %s[-d] [-m] [-u] [-v]\n",
+ options, options, options);
+ exit(1);
+}
+
+#ifdef __rtems__
+int
+main_ifconfig(int argc, char *argv[])
+#else
+int
+main(int argc, char *argv[])
+#endif
+{
+ int c, all, namesonly, downonly, uponly;
+ const struct afswtch *afp = NULL;
+ int ifindex;
+ struct ifaddrs *ifap, *ifa;
+ struct ifreq paifr;
+ const struct sockaddr_dl *sdl;
+ char options[1024], *cp;
+ const char *ifname;
+#ifdef __rtems__
+ struct ifconfig_option *p;
+#else
+ struct option *p;
+#endif
+ size_t iflen;
+#ifdef __rtems__
+ struct getopt_data getopt_reent;
+#define optind getopt_reent.optind
+#define optarg getopt_reent.optarg
+#define opterr getopt_reent.opterr
+#define optopt getopt_reent.optopt
+#endif
+
+ all = downonly = uponly = namesonly = noload = verbose = 0;
+
+ /* Parse leading line options */
+ strlcpy(options, "adklmnuv", sizeof(options));
+ for (p = opts; p != NULL; p = p->next)
+ strlcat(options, p->opt, sizeof(options));
+#ifdef __rtems__
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+ while ((c = getopt_r(argc, argv, options, &getopt_reent)) != -1) {
+#else
+ while ((c = getopt(argc, argv, options)) != -1) {
+#endif
+ switch (c) {
+ case 'a': /* scan all interfaces */
+ all++;
+ break;
+ case 'd': /* restrict scan to "down" interfaces */
+ downonly++;
+ break;
+ case 'k':
+ printkeys++;
+ break;
+ case 'l': /* scan interface names only */
+ namesonly++;
+ break;
+ case 'm': /* show media choices in status */
+ supmedia = 1;
+ break;
+ case 'n': /* suppress module loading */
+ noload++;
+ break;
+ case 'u': /* restrict scan to "up" interfaces */
+ uponly++;
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ for (p = opts; p != NULL; p = p->next)
+ if (p->opt[0] == c) {
+ p->cb(optarg);
+ break;
+ }
+ if (p == NULL)
+ usage();
+ break;
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* -l cannot be used with -a or -m */
+ if (namesonly && (all || supmedia))
+ usage();
+
+ /* nonsense.. */
+ if (uponly && downonly)
+ usage();
+
+ /* no arguments is equivalent to '-a' */
+ if (!namesonly && argc < 1)
+ all = 1;
+
+ /* -a and -l allow an address family arg to limit the output */
+ if (all || namesonly) {
+ if (argc > 1)
+ usage();
+
+ ifname = NULL;
+ ifindex = 0;
+ if (argc == 1) {
+ afp = af_getbyname(*argv);
+ if (afp == NULL)
+ usage();
+ if (afp->af_name != NULL)
+ argc--, argv++;
+ /* leave with afp non-zero */
+ }
+ } else {
+ /* not listing, need an argument */
+ if (argc < 1)
+ usage();
+
+ ifname = *argv;
+ argc--, argv++;
+
+ /* check and maybe load support for this interface */
+ ifmaybeload(ifname);
+
+ ifindex = if_nametoindex(ifname);
+ if (ifindex == 0) {
+ /*
+ * NOTE: We must special-case the `create' command
+ * right here as we would otherwise fail when trying
+ * to find the interface.
+ */
+ if (argc > 0 && (strcmp(argv[0], "create") == 0 ||
+ strcmp(argv[0], "plumb") == 0)) {
+ iflen = strlcpy(name, ifname, sizeof(name));
+ if (iflen >= sizeof(name))
+ errx(1, "%s: cloning name too long",
+ ifname);
+ ifconfig(argc, argv, 1, NULL);
+ exit(0);
+ }
+ /*
+ * NOTE: We have to special-case the `-vnet' command
+ * right here as we would otherwise fail when trying
+ * to find the interface as it lives in another vnet.
+ */
+ if (argc > 0 && (strcmp(argv[0], "-vnet") == 0)) {
+ iflen = strlcpy(name, ifname, sizeof(name));
+ if (iflen >= sizeof(name))
+ errx(1, "%s: interface name too long",
+ ifname);
+ ifconfig(argc, argv, 0, NULL);
+ exit(0);
+ }
+ errx(1, "interface %s does not exist", ifname);
+ }
+ }
+
+ /* Check for address family */
+ if (argc > 0) {
+ afp = af_getbyname(*argv);
+ if (afp != NULL)
+ argc--, argv++;
+ }
+
+ if (getifaddrs(&ifap) != 0)
+ err(EXIT_FAILURE, "getifaddrs");
+ cp = NULL;
+ ifindex = 0;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ memset(&paifr, 0, sizeof(paifr));
+ strncpy(paifr.ifr_name, ifa->ifa_name, sizeof(paifr.ifr_name));
+ if (sizeof(paifr.ifr_addr) >= ifa->ifa_addr->sa_len) {
+ memcpy(&paifr.ifr_addr, ifa->ifa_addr,
+ ifa->ifa_addr->sa_len);
+ }
+
+ if (ifname != NULL && strcmp(ifname, ifa->ifa_name) != 0)
+ continue;
+ if (ifa->ifa_addr->sa_family == AF_LINK)
+ sdl = (const struct sockaddr_dl *) ifa->ifa_addr;
+ else
+ sdl = NULL;
+ if (cp != NULL && strcmp(cp, ifa->ifa_name) == 0)
+ continue;
+ iflen = strlcpy(name, ifa->ifa_name, sizeof(name));
+ if (iflen >= sizeof(name)) {
+ warnx("%s: interface name too long, skipping",
+ ifa->ifa_name);
+ continue;
+ }
+ cp = ifa->ifa_name;
+
+ if (downonly && (ifa->ifa_flags & IFF_UP) != 0)
+ continue;
+ if (uponly && (ifa->ifa_flags & IFF_UP) == 0)
+ continue;
+ ifindex++;
+ /*
+ * Are we just listing the interfaces?
+ */
+ if (namesonly) {
+ if (ifindex > 1)
+ printf(" ");
+ fputs(name, stdout);
+ continue;
+ }
+
+ if (argc > 0)
+ ifconfig(argc, argv, 0, afp);
+ else
+ status(afp, sdl, ifa);
+ }
+ if (namesonly)
+ printf("\n");
+ freeifaddrs(ifap);
+
+ exit(0);
+}
+
+static struct afswtch *afs = NULL;
+
+void
+af_register(struct afswtch *p)
+{
+ p->af_next = afs;
+ afs = p;
+}
+
+static struct afswtch *
+af_getbyname(const char *name)
+{
+ struct afswtch *afp;
+
+ for (afp = afs; afp != NULL; afp = afp->af_next)
+ if (strcmp(afp->af_name, name) == 0)
+ return afp;
+ return NULL;
+}
+
+static struct afswtch *
+af_getbyfamily(int af)
+{
+ struct afswtch *afp;
+
+ for (afp = afs; afp != NULL; afp = afp->af_next)
+ if (afp->af_af == af)
+ return afp;
+ return NULL;
+}
+
+static void
+af_other_status(int s)
+{
+ struct afswtch *afp;
+ uint8_t afmask[howmany(AF_MAX, NBBY)];
+
+ memset(afmask, 0, sizeof(afmask));
+ for (afp = afs; afp != NULL; afp = afp->af_next) {
+ if (afp->af_other_status == NULL)
+ continue;
+ if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
+ continue;
+ afp->af_other_status(s);
+ setbit(afmask, afp->af_af);
+ }
+}
+
+static void
+af_all_tunnel_status(int s)
+{
+ struct afswtch *afp;
+ uint8_t afmask[howmany(AF_MAX, NBBY)];
+
+ memset(afmask, 0, sizeof(afmask));
+ for (afp = afs; afp != NULL; afp = afp->af_next) {
+ if (afp->af_status_tunnel == NULL)
+ continue;
+ if (afp->af_af != AF_UNSPEC && isset(afmask, afp->af_af))
+ continue;
+ afp->af_status_tunnel(s);
+ setbit(afmask, afp->af_af);
+ }
+}
+
+static struct cmd *cmds = NULL;
+
+void
+cmd_register(struct cmd *p)
+{
+ p->c_next = cmds;
+ cmds = p;
+}
+
+static const struct cmd *
+cmd_lookup(const char *name, int iscreate)
+{
+#define N(a) (sizeof(a)/sizeof(a[0]))
+ const struct cmd *p;
+
+ for (p = cmds; p != NULL; p = p->c_next)
+ if (strcmp(name, p->c_name) == 0) {
+ if (iscreate) {
+ if (p->c_iscloneop)
+ return p;
+ } else {
+ if (!p->c_iscloneop)
+ return p;
+ }
+ }
+ return NULL;
+#undef N
+}
+
+struct callback {
+ callback_func *cb_func;
+ void *cb_arg;
+ struct callback *cb_next;
+};
+static struct callback *callbacks = NULL;
+
+void
+callback_register(callback_func *func, void *arg)
+{
+ struct callback *cb;
+
+ cb = malloc(sizeof(struct callback));
+ if (cb == NULL)
+ errx(1, "unable to allocate memory for callback");
+ cb->cb_func = func;
+ cb->cb_arg = arg;
+ cb->cb_next = callbacks;
+ callbacks = cb;
+}
+
+/* specially-handled commands */
+static void setifaddr(const char *, int, int, const struct afswtch *);
+static const struct cmd setifaddr_cmd = DEF_CMD("ifaddr", 0, setifaddr);
+
+static void setifdstaddr(const char *, int, int, const struct afswtch *);
+static const struct cmd setifdstaddr_cmd =
+ DEF_CMD("ifdstaddr", 0, setifdstaddr);
+
+static int
+ifconfig(int argc, char *const *argv, int iscreate, const struct afswtch *uafp)
+{
+ 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:
+ ifr.ifr_addr.sa_family =
+ afp->af_af == AF_LINK || afp->af_af == AF_UNSPEC ?
+ AF_LOCAL : afp->af_af;
+
+ 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) {
+ p = cmd_lookup(*argv, iscreate);
+ if (iscreate && p == NULL) {
+ /*
+ * Push the clone create callback so the new
+ * device is created and can be used for any
+ * remaining arguments.
+ */
+ cb = callbacks;
+ if (cb == NULL)
+ errx(1, "internal error, no callback");
+ callbacks = cb->cb_next;
+ cb->cb_func(s, cb->cb_arg);
+ iscreate = 0;
+ /*
+ * Handle any address family spec that
+ * immediately follows and potentially
+ * recreate the socket.
+ */
+ nafp = af_getbyname(*argv);
+ if (nafp != NULL) {
+ argc--, argv++;
+ if (nafp != afp) {
+ close(s);
+ afp = nafp;
+ goto top;
+ }
+ }
+ /*
+ * Look for a normal parameter.
+ */
+ continue;
+ }
+ if (p == NULL) {
+ /*
+ * Not a recognized command, choose between setting
+ * the interface address and the dst address.
+ */
+ p = (setaddr ? &setifdstaddr_cmd : &setifaddr_cmd);
+ }
+ if (p->c_u.c_func || p->c_u.c_func2) {
+ if (p->c_parameter == NEXTARG) {
+ if (argv[1] == NULL)
+ errx(1, "'%s' requires argument",
+ p->c_name);
+ p->c_u.c_func(argv[1], 0, s, afp);
+ argc--, argv++;
+ } else if (p->c_parameter == OPTARG) {
+ p->c_u.c_func(argv[1], 0, s, afp);
+ if (argv[1] != NULL)
+ argc--, argv++;
+ } else if (p->c_parameter == NEXTARG2) {
+ if (argc < 3)
+ errx(1, "'%s' requires 2 arguments",
+ p->c_name);
+ p->c_u.c_func2(argv[1], argv[2], s, afp);
+ argc -= 2, argv += 2;
+ } else
+ p->c_u.c_func(*argv, p->c_parameter, s, afp);
+ }
+ argc--, argv++;
+ }
+
+ /*
+ * Do any post argument processing required by the address family.
+ */
+ if (afp->af_postproc != NULL)
+ afp->af_postproc(s, afp);
+ /*
+ * Do deferred callbacks registered while processing
+ * command-line arguments.
+ */
+ for (cb = callbacks; cb != NULL; cb = cb->cb_next)
+ cb->cb_func(s, cb->cb_arg);
+ /*
+ * Do deferred operations.
+ */
+ if (clearaddr) {
+ if (afp->af_ridreq == NULL || afp->af_difaddr == 0) {
+ warnx("interface %s cannot change %s addresses!",
+ name, afp->af_name);
+ clearaddr = 0;
+ }
+ }
+ if (clearaddr) {
+ int ret;
+ strncpy(afp->af_ridreq, name, sizeof ifr.ifr_name);
+ ret = ioctl(s, afp->af_difaddr, afp->af_ridreq);
+ if (ret < 0) {
+ if (errno == EADDRNOTAVAIL && (doalias >= 0)) {
+ /* means no previous address for interface */
+ } else
+ Perror("ioctl (SIOCDIFADDR)");
+ }
+ }
+ if (newaddr) {
+ if (afp->af_addreq == NULL || afp->af_aifaddr == 0) {
+ warnx("interface %s cannot change %s addresses!",
+ name, afp->af_name);
+ newaddr = 0;
+ }
+ }
+ if (newaddr && (setaddr || setmask)) {
+ strncpy(afp->af_addreq, name, sizeof ifr.ifr_name);
+ if (ioctl(s, afp->af_aifaddr, afp->af_addreq) < 0)
+ Perror("ioctl (SIOCAIFADDR)");
+ }
+
+ close(s);
+ return(0);
+}
+
+/*ARGSUSED*/
+static void
+setifaddr(const char *addr, int param, int s, const struct afswtch *afp)
+{
+ if (afp->af_getaddr == NULL)
+ return;
+ /*
+ * Delay the ioctl to set the interface addr until flags are all set.
+ * The address interpretation may depend on the flags,
+ * and the flags may change when the address is set.
+ */
+ setaddr++;
+ if (doalias == 0 && afp->af_af != AF_LINK)
+ clearaddr = 1;
+ afp->af_getaddr(addr, (doalias >= 0 ? ADDR : RIDADDR));
+}
+
+static void
+settunnel(const char *src, const char *dst, int s, const struct afswtch *afp)
+{
+ struct addrinfo *srcres, *dstres;
+ int ecode;
+
+ if (afp->af_settunnel == NULL) {
+ warn("address family %s does not support tunnel setup",
+ afp->af_name);
+ return;
+ }
+
+ if ((ecode = getaddrinfo(src, NULL, NULL, &srcres)) != 0)
+ errx(1, "error in parsing address string: %s",
+ gai_strerror(ecode));
+
+ if ((ecode = getaddrinfo(dst, NULL, NULL, &dstres)) != 0)
+ errx(1, "error in parsing address string: %s",
+ gai_strerror(ecode));
+
+ if (srcres->ai_addr->sa_family != dstres->ai_addr->sa_family)
+ errx(1,
+ "source and destination address families do not match");
+
+ afp->af_settunnel(s, srcres, dstres);
+
+ freeaddrinfo(srcres);
+ freeaddrinfo(dstres);
+}
+
+/* ARGSUSED */
+static void
+deletetunnel(const char *vname, int param, int s, const struct afswtch *afp)
+{
+
+ if (ioctl(s, SIOCDIFPHYADDR, &ifr) < 0)
+ err(1, "SIOCDIFPHYADDR");
+}
+
+static void
+setifvnet(const char *jname, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ struct ifreq my_ifr;
+
+ memcpy(&my_ifr, &ifr, sizeof(my_ifr));
+#ifndef __rtems__
+ my_ifr.ifr_jid = jail_getid(jname);
+ if (my_ifr.ifr_jid < 0)
+ errx(1, "%s", jail_errmsg);
+#endif
+ if (ioctl(s, SIOCSIFVNET, &my_ifr) < 0)
+ err(1, "SIOCSIFVNET");
+}
+
+static void
+setifrvnet(const char *jname, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ struct ifreq my_ifr;
+
+ memcpy(&my_ifr, &ifr, sizeof(my_ifr));
+#ifndef __rtems__
+ my_ifr.ifr_jid = jail_getid(jname);
+ if (my_ifr.ifr_jid < 0)
+ errx(1, "%s", jail_errmsg);
+#endif
+ if (ioctl(s, SIOCSIFRVNET, &my_ifr) < 0)
+ err(1, "SIOCSIFRVNET(%d, %s)", my_ifr.ifr_jid, my_ifr.ifr_name);
+}
+
+static void
+setifnetmask(const char *addr, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ if (afp->af_getaddr != NULL) {
+ setmask++;
+ afp->af_getaddr(addr, MASK);
+ }
+}
+
+static void
+setifbroadaddr(const char *addr, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ if (afp->af_getaddr != NULL)
+ afp->af_getaddr(addr, DSTADDR);
+}
+
+static void
+setifipdst(const char *addr, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ const struct afswtch *inet;
+
+ inet = af_getbyname("inet");
+ if (inet == NULL)
+ return;
+ inet->af_getaddr(addr, DSTADDR);
+ clearaddr = 0;
+ newaddr = 0;
+}
+
+static void
+notealias(const char *addr, int param, int s, const struct afswtch *afp)
+{
+#define rqtosa(x) (&(((struct ifreq *)(afp->x))->ifr_addr))
+ if (setaddr && doalias == 0 && param < 0)
+ if (afp->af_addreq != NULL && afp->af_ridreq != NULL)
+ bcopy((caddr_t)rqtosa(af_addreq),
+ (caddr_t)rqtosa(af_ridreq),
+ rqtosa(af_addreq)->sa_len);
+ doalias = param;
+ if (param < 0) {
+ clearaddr = 1;
+ newaddr = 0;
+ } else
+ clearaddr = 0;
+#undef rqtosa
+}
+
+/*ARGSUSED*/
+static void
+setifdstaddr(const char *addr, int param __unused, int s,
+ const struct afswtch *afp)
+{
+ if (afp->af_getaddr != NULL)
+ afp->af_getaddr(addr, DSTADDR);
+}
+
+/*
+ * Note: doing an SIOCIGIFFLAGS scribbles on the union portion
+ * of the ifreq structure, which may confuse other parts of ifconfig.
+ * Make a private copy so we can avoid that.
+ */
+static void
+setifflags(const char *vname, int value, int s, const struct afswtch *afp)
+{
+ struct ifreq my_ifr;
+ int flags;
+
+ memset(&my_ifr, 0, sizeof(my_ifr));
+ (void) strlcpy(my_ifr.ifr_name, name, sizeof(my_ifr.ifr_name));
+
+ if (ioctl(s, SIOCGIFFLAGS, (caddr_t)&my_ifr) < 0) {
+ Perror("ioctl (SIOCGIFFLAGS)");
+ exit(1);
+ }
+ flags = (my_ifr.ifr_flags & 0xffff) | (my_ifr.ifr_flagshigh << 16);
+
+ if (value < 0) {
+ value = -value;
+ flags &= ~value;
+ } else
+ flags |= value;
+ my_ifr.ifr_flags = flags & 0xffff;
+ my_ifr.ifr_flagshigh = flags >> 16;
+ if (ioctl(s, SIOCSIFFLAGS, (caddr_t)&my_ifr) < 0)
+ Perror(vname);
+}
+
+void
+setifcap(const char *vname, int value, int s, const struct afswtch *afp)
+{
+ int flags;
+
+ if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) < 0) {
+ Perror("ioctl (SIOCGIFCAP)");
+ exit(1);
+ }
+ flags = ifr.ifr_curcap;
+ if (value < 0) {
+ value = -value;
+ flags &= ~value;
+ } else
+ flags |= value;
+ flags &= ifr.ifr_reqcap;
+ ifr.ifr_reqcap = flags;
+ if (ioctl(s, SIOCSIFCAP, (caddr_t)&ifr) < 0)
+ Perror(vname);
+}
+
+static void
+setifmetric(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+ ifr.ifr_metric = atoi(val);
+ if (ioctl(s, SIOCSIFMETRIC, (caddr_t)&ifr) < 0)
+ warn("ioctl (set metric)");
+}
+
+static void
+setifmtu(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+ ifr.ifr_mtu = atoi(val);
+ if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) < 0)
+ warn("ioctl (set mtu)");
+}
+
+static void
+setifname(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ char *newname;
+
+ newname = strdup(val);
+ if (newname == NULL) {
+ warn("no memory to set ifname");
+ return;
+ }
+ ifr.ifr_data = newname;
+ if (ioctl(s, SIOCSIFNAME, (caddr_t)&ifr) < 0) {
+ warn("ioctl (set name)");
+ free(newname);
+ return;
+ }
+ strlcpy(name, newname, sizeof(name));
+ free(newname);
+}
+
+/* ARGSUSED */
+static void
+setifdescr(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ char *newdescr;
+
+ ifr.ifr_buffer.length = strlen(val) + 1;
+ if (ifr.ifr_buffer.length == 1) {
+ ifr.ifr_buffer.buffer = newdescr = NULL;
+ ifr.ifr_buffer.length = 0;
+ } else {
+ newdescr = strdup(val);
+ ifr.ifr_buffer.buffer = newdescr;
+ if (newdescr == NULL) {
+ warn("no memory to set ifdescr");
+ return;
+ }
+ }
+
+ if (ioctl(s, SIOCSIFDESCR, (caddr_t)&ifr) < 0)
+ warn("ioctl (set descr)");
+
+ free(newdescr);
+}
+
+/* ARGSUSED */
+static void
+unsetifdescr(const char *val, int value, int s, const struct afswtch *afp)
+{
+
+ setifdescr("", 0, s, 0);
+}
+
+#define IFFBITS \
+"\020\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5POINTOPOINT\6SMART\7RUNNING" \
+"\10NOARP\11PROMISC\12ALLMULTI\13OACTIVE\14SIMPLEX\15LINK0\16LINK1\17LINK2" \
+"\20MULTICAST\22PPROMISC\23MONITOR\24STATICARP"
+
+#define IFCAPBITS \
+"\020\1RXCSUM\2TXCSUM\3NETCONS\4VLAN_MTU\5VLAN_HWTAGGING\6JUMBO_MTU\7POLLING" \
+"\10VLAN_HWCSUM\11TSO4\12TSO6\13LRO\14WOL_UCAST\15WOL_MCAST\16WOL_MAGIC" \
+"\21VLAN_HWFILTER\23VLAN_HWTSO\24LINKSTATE"
+
+/*
+ * Print the status of the interface. If an address family was
+ * specified, show only it; otherwise, show them all.
+ */
+static void
+status(const struct afswtch *afp, const struct sockaddr_dl *sdl,
+ struct ifaddrs *ifa)
+{
+ struct ifaddrs *ift;
+ int allfamilies, s;
+ struct ifstat ifs;
+
+ if (afp == NULL) {
+ allfamilies = 1;
+ ifr.ifr_addr.sa_family = AF_LOCAL;
+ } else {
+ allfamilies = 0;
+ ifr.ifr_addr.sa_family =
+ afp->af_af == AF_LINK ? AF_LOCAL : afp->af_af;
+ }
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ s = socket(ifr.ifr_addr.sa_family, SOCK_DGRAM, 0);
+ if (s < 0)
+ err(1, "socket(family %u,SOCK_DGRAM)", ifr.ifr_addr.sa_family);
+
+ printf("%s: ", name);
+ printb("flags", ifa->ifa_flags, IFFBITS);
+ if (ioctl(s, SIOCGIFMETRIC, &ifr) != -1)
+ printf(" metric %d", ifr.ifr_metric);
+ if (ioctl(s, SIOCGIFMTU, &ifr) != -1)
+ printf(" mtu %d", ifr.ifr_mtu);
+ putchar('\n');
+
+ for (;;) {
+ if ((descr = reallocf(descr, descrlen)) != NULL) {
+ ifr.ifr_buffer.buffer = descr;
+ ifr.ifr_buffer.length = descrlen;
+ if (ioctl(s, SIOCGIFDESCR, &ifr) == 0) {
+ if (ifr.ifr_buffer.buffer == descr) {
+ if (strlen(descr) > 0)
+ printf("\tdescription: %s\n",
+ descr);
+ } else if (ifr.ifr_buffer.length > descrlen) {
+ descrlen = ifr.ifr_buffer.length;
+ continue;
+ }
+ }
+ } else
+ warn("unable to allocate memory for interface"
+ "description");
+ break;
+ }
+
+ if (ioctl(s, SIOCGIFCAP, (caddr_t)&ifr) == 0) {
+ if (ifr.ifr_curcap != 0) {
+ printb("\toptions", ifr.ifr_curcap, IFCAPBITS);
+ putchar('\n');
+ }
+ if (supmedia && ifr.ifr_reqcap != 0) {
+ printb("\tcapabilities", ifr.ifr_reqcap, IFCAPBITS);
+ putchar('\n');
+ }
+ }
+
+ tunnel_status(s);
+
+ for (ift = ifa; ift != NULL; ift = ift->ifa_next) {
+ if (ift->ifa_addr == NULL)
+ continue;
+ if (strcmp(ifa->ifa_name, ift->ifa_name) != 0)
+ continue;
+ if (allfamilies) {
+ const struct afswtch *p;
+ p = af_getbyfamily(ift->ifa_addr->sa_family);
+ if (p != NULL && p->af_status != NULL)
+ p->af_status(s, ift);
+ } else if (afp->af_af == ift->ifa_addr->sa_family)
+ afp->af_status(s, ift);
+ }
+#if 0
+ if (allfamilies || afp->af_af == AF_LINK) {
+ const struct afswtch *lafp;
+
+ /*
+ * Hack; the link level address is received separately
+ * from the routing information so any address is not
+ * handled above. Cobble together an entry and invoke
+ * the status method specially.
+ */
+ lafp = af_getbyname("lladdr");
+ if (lafp != NULL) {
+ info.rti_info[RTAX_IFA] = (struct sockaddr *)sdl;
+ lafp->af_status(s, &info);
+ }
+ }
+#endif
+ if (allfamilies)
+ af_other_status(s);
+ else if (afp->af_other_status != NULL)
+ afp->af_other_status(s);
+
+ strncpy(ifs.ifs_name, name, sizeof ifs.ifs_name);
+ if (ioctl(s, SIOCGIFSTATUS, &ifs) == 0)
+ printf("%s", ifs.ascii);
+
+ close(s);
+ return;
+}
+
+static void
+tunnel_status(int s)
+{
+ af_all_tunnel_status(s);
+}
+
+void
+Perror(const char *cmd)
+{
+ switch (errno) {
+
+ case ENXIO:
+ errx(1, "%s: no such interface", cmd);
+ break;
+
+ case EPERM:
+ errx(1, "%s: permission denied", cmd);
+ break;
+
+ default:
+ err(1, "%s", cmd);
+ }
+}
+
+/*
+ * Print a value a la the %b format of the kernel's printf
+ */
+void
+printb(const char *s, unsigned v, const char *bits)
+{
+ int i, any = 0;
+ char c;
+
+ if (bits && *bits == 8)
+ printf("%s=%o", s, v);
+ else
+ printf("%s=%x", s, v);
+ bits++;
+ if (bits) {
+ putchar('<');
+ while ((i = *bits++) != '\0') {
+ if (v & (1 << (i-1))) {
+ if (any)
+ putchar(',');
+ any = 1;
+ for (; (c = *bits) > 32; bits++)
+ putchar(c);
+ } else
+ for (; *bits > 32; bits++)
+ ;
+ }
+ putchar('>');
+ }
+}
+
+void
+ifmaybeload(const char *name)
+{
+#ifndef __rtems__
+#define MOD_PREFIX_LEN 3 /* "if_" */
+ struct module_stat mstat;
+ int fileid, modid;
+ char ifkind[IFNAMSIZ + MOD_PREFIX_LEN], ifname[IFNAMSIZ], *dp;
+ const char *cp;
+
+ /* loading suppressed by the user */
+ if (noload)
+ return;
+
+ /* trim the interface number off the end */
+ strlcpy(ifname, name, sizeof(ifname));
+ for (dp = ifname; *dp != 0; dp++)
+ if (isdigit(*dp)) {
+ *dp = 0;
+ break;
+ }
+
+ /* turn interface and unit into module name */
+ strcpy(ifkind, "if_");
+ strlcpy(ifkind + MOD_PREFIX_LEN, ifname,
+ sizeof(ifkind) - MOD_PREFIX_LEN);
+
+ /* scan files in kernel */
+ mstat.version = sizeof(struct module_stat);
+ for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
+ /* scan modules in file */
+ for (modid = kldfirstmod(fileid); modid > 0;
+ modid = modfnext(modid)) {
+ if (modstat(modid, &mstat) < 0)
+ continue;
+ /* strip bus name if present */
+ if ((cp = strchr(mstat.name, '/')) != NULL) {
+ cp++;
+ } else {
+ cp = mstat.name;
+ }
+ /* already loaded? */
+ if (strncmp(ifname, cp, strlen(ifname) + 1) == 0 ||
+ strncmp(ifkind, cp, strlen(ifkind) + 1) == 0)
+ return;
+ }
+ }
+
+ /* not present, we should try to load it */
+ kldload(ifkind);
+#endif
+}
+
+static struct cmd basic_cmds[] = {
+ DEF_CMD("up", IFF_UP, setifflags),
+ DEF_CMD("down", -IFF_UP, setifflags),
+ DEF_CMD("arp", -IFF_NOARP, setifflags),
+ DEF_CMD("-arp", IFF_NOARP, setifflags),
+ DEF_CMD("debug", IFF_DEBUG, setifflags),
+ DEF_CMD("-debug", -IFF_DEBUG, setifflags),
+ DEF_CMD_ARG("description", setifdescr),
+ DEF_CMD_ARG("descr", setifdescr),
+ DEF_CMD("-description", 0, unsetifdescr),
+ DEF_CMD("-descr", 0, unsetifdescr),
+ DEF_CMD("promisc", IFF_PPROMISC, setifflags),
+ DEF_CMD("-promisc", -IFF_PPROMISC, setifflags),
+ DEF_CMD("add", IFF_UP, notealias),
+ DEF_CMD("alias", IFF_UP, notealias),
+ DEF_CMD("-alias", -IFF_UP, notealias),
+ DEF_CMD("delete", -IFF_UP, notealias),
+ DEF_CMD("remove", -IFF_UP, notealias),
+#ifdef notdef
+#define EN_SWABIPS 0x1000
+ DEF_CMD("swabips", EN_SWABIPS, setifflags),
+ DEF_CMD("-swabips", -EN_SWABIPS, setifflags),
+#endif
+ DEF_CMD_ARG("netmask", setifnetmask),
+ DEF_CMD_ARG("metric", setifmetric),
+ DEF_CMD_ARG("broadcast", setifbroadaddr),
+ DEF_CMD_ARG("ipdst", setifipdst),
+ DEF_CMD_ARG2("tunnel", settunnel),
+ DEF_CMD("-tunnel", 0, deletetunnel),
+ DEF_CMD("deletetunnel", 0, deletetunnel),
+ DEF_CMD_ARG("vnet", setifvnet),
+ DEF_CMD_ARG("-vnet", setifrvnet),
+ DEF_CMD("link0", IFF_LINK0, setifflags),
+ DEF_CMD("-link0", -IFF_LINK0, setifflags),
+ DEF_CMD("link1", IFF_LINK1, setifflags),
+ DEF_CMD("-link1", -IFF_LINK1, setifflags),
+ DEF_CMD("link2", IFF_LINK2, setifflags),
+ DEF_CMD("-link2", -IFF_LINK2, setifflags),
+ DEF_CMD("monitor", IFF_MONITOR, setifflags),
+ DEF_CMD("-monitor", -IFF_MONITOR, setifflags),
+ DEF_CMD("staticarp", IFF_STATICARP, setifflags),
+ DEF_CMD("-staticarp", -IFF_STATICARP, setifflags),
+ DEF_CMD("rxcsum", IFCAP_RXCSUM, setifcap),
+ DEF_CMD("-rxcsum", -IFCAP_RXCSUM, setifcap),
+ DEF_CMD("txcsum", IFCAP_TXCSUM, setifcap),
+ DEF_CMD("-txcsum", -IFCAP_TXCSUM, setifcap),
+ DEF_CMD("netcons", IFCAP_NETCONS, setifcap),
+ DEF_CMD("-netcons", -IFCAP_NETCONS, setifcap),
+ DEF_CMD("polling", IFCAP_POLLING, setifcap),
+ DEF_CMD("-polling", -IFCAP_POLLING, setifcap),
+ DEF_CMD("tso", IFCAP_TSO, setifcap),
+ DEF_CMD("-tso", -IFCAP_TSO, setifcap),
+ DEF_CMD("lro", IFCAP_LRO, setifcap),
+ DEF_CMD("-lro", -IFCAP_LRO, setifcap),
+ DEF_CMD("wol", IFCAP_WOL, setifcap),
+ DEF_CMD("-wol", -IFCAP_WOL, setifcap),
+ DEF_CMD("wol_ucast", IFCAP_WOL_UCAST, setifcap),
+ DEF_CMD("-wol_ucast", -IFCAP_WOL_UCAST, setifcap),
+ DEF_CMD("wol_mcast", IFCAP_WOL_MCAST, setifcap),
+ DEF_CMD("-wol_mcast", -IFCAP_WOL_MCAST, setifcap),
+ DEF_CMD("wol_magic", IFCAP_WOL_MAGIC, setifcap),
+ DEF_CMD("-wol_magic", -IFCAP_WOL_MAGIC, setifcap),
+ DEF_CMD("normal", -IFF_LINK0, setifflags),
+ DEF_CMD("compress", IFF_LINK0, setifflags),
+ DEF_CMD("noicmp", IFF_LINK1, setifflags),
+ DEF_CMD_ARG("mtu", setifmtu),
+ DEF_CMD_ARG("name", setifname),
+};
+
+static __constructor void
+ifconfig_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(basic_cmds); i++)
+ cmd_register(&basic_cmds[i]);
+#undef N
+}
+
+#ifdef __rtems__
+ #include <rtems/shell.h>
+
+ rtems_shell_cmd_t rtems_shell_IFCONFIG_Command = {
+ "ifconfig", /* name */
+ "ifconfig [args]", /* usage */
+ "net", /* topic */
+ rtems_shell_main_ifconfig, /* command */
+ NULL, /* alias */
+ NULL /* next */
+ };
+#endif
diff --git a/freebsd/sbin/ifconfig/ifconfig.h b/freebsd/sbin/ifconfig/ifconfig.h
new file mode 100644
index 00000000..479bc2ad
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifconfig.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 1997 Peter Wemm.
+ * 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 for the FreeBSD Project
+ * by Peter Wemm.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * so there!
+ *
+ * $FreeBSD$
+ */
+
+#ifdef __rtems__
+#include <freebsd/sys/sockio.h>
+#endif
+
+#define __constructor __attribute__((constructor))
+
+struct afswtch;
+struct cmd;
+
+typedef void c_func(const char *cmd, int arg, int s, const struct afswtch *afp);
+typedef void c_func2(const char *arg1, const char *arg2, int s, const struct afswtch *afp);
+
+struct cmd {
+ const char *c_name;
+ int c_parameter;
+#define NEXTARG 0xffffff /* has following arg */
+#define NEXTARG2 0xfffffe /* has 2 following args */
+#define OPTARG 0xfffffd /* has optional following arg */
+ union {
+ c_func *c_func;
+ c_func2 *c_func2;
+ } c_u;
+ int c_iscloneop;
+ struct cmd *c_next;
+};
+void cmd_register(struct cmd *);
+
+typedef void callback_func(int s, void *);
+void callback_register(callback_func *, void *);
+
+/*
+ * Macros for declaring command functions and initializing entries.
+ */
+#define DECL_CMD_FUNC(name, cmd, arg) \
+ void name(const char *cmd, int arg, int s, const struct afswtch *afp)
+#define DECL_CMD_FUNC2(name, arg1, arg2) \
+ void name(const char *arg1, const char *arg2, int s, const struct afswtch *afp)
+
+#define DEF_CMD(name, param, func) { name, param, { .c_func = func }, 0, NULL }
+#define DEF_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func }, 0, NULL }
+#define DEF_CMD_OPTARG(name, func) { name, OPTARG, { .c_func = func }, 0, NULL }
+#define DEF_CMD_ARG2(name, func) { name, NEXTARG2, { .c_func2 = func }, 0, NULL }
+#define DEF_CLONE_CMD(name, param, func) { name, param, { .c_func = func }, 1, NULL }
+#define DEF_CLONE_CMD_ARG(name, func) { name, NEXTARG, { .c_func = func }, 1, NULL }
+
+struct ifaddrs;
+struct addrinfo;
+
+enum {
+ RIDADDR,
+ ADDR,
+ MASK,
+ DSTADDR,
+};
+
+struct afswtch {
+ const char *af_name; /* as given on cmd line, e.g. "inet" */
+ short af_af; /* AF_* */
+ /*
+ * Status is handled one of two ways; if there is an
+ * address associated with the interface then the
+ * associated address family af_status method is invoked
+ * with the appropriate addressin info. Otherwise, if
+ * all possible info is to be displayed and af_other_status
+ * is defined then it is invoked after all address status
+ * is presented.
+ */
+ void (*af_status)(int, const struct ifaddrs *);
+ void (*af_other_status)(int);
+ /* parse address method */
+ void (*af_getaddr)(const char *, int);
+ /* parse prefix method (IPv6) */
+ void (*af_getprefix)(const char *, int);
+ void (*af_postproc)(int s, const struct afswtch *);
+ u_long af_difaddr; /* set dst if address ioctl */
+ u_long af_aifaddr; /* set if address ioctl */
+ void *af_ridreq; /* */
+ void *af_addreq; /* */
+ struct afswtch *af_next;
+
+ /* XXX doesn't fit model */
+ void (*af_status_tunnel)(int);
+ void (*af_settunnel)(int s, struct addrinfo *srcres,
+ struct addrinfo *dstres);
+};
+void af_register(struct afswtch *);
+
+#ifdef __rtems__
+struct ifconfig_option {
+#else
+struct option {
+#endif
+ const char *opt;
+ const char *opt_usage;
+ void (*cb)(const char *arg);
+ #ifdef __rtems__
+ struct ifconfig_option *next;
+ #else
+ struct option *next;
+ #endif
+};
+#ifdef __rtems__
+void opt_register(struct ifconfig_option *);
+#else
+void opt_register(struct option *);
+#endif
+
+extern struct ifreq ifr;
+extern char name[IFNAMSIZ]; /* name of interface */
+extern int allmedia;
+extern int supmedia;
+extern int printkeys;
+extern int newaddr;
+extern int verbose;
+
+void setifcap(const char *, int value, int s, const struct afswtch *);
+
+void Perror(const char *cmd);
+void printb(const char *s, unsigned value, const char *bits);
+
+void ifmaybeload(const char *name);
+
+typedef void clone_callback_func(int, struct ifreq *);
+void clone_setdefcallback(const char *, clone_callback_func *);
+
+/*
+ * XXX expose this so modules that neeed to know of any pending
+ * operations on ifmedia can avoid cmd line ordering confusion.
+ */
+struct ifmediareq *ifmedia_getstate(int s);
diff --git a/freebsd/sbin/ifconfig/ifgif.c b/freebsd/sbin/ifconfig/ifgif.c
new file mode 100644
index 00000000..d23b384b
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifgif.c
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 2009 Hiroki Sato. 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.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_gif.h>
+#else
+#include <net/if_gif.h>
+#endif
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+static void gif_status(int);
+
+static struct {
+ const char *label;
+ u_int mask;
+} gif_opts[] = {
+ { "ACCEPT_REV_ETHIP_VER", GIF_ACCEPT_REVETHIP },
+ { "SEND_REV_ETHIP_VER", GIF_SEND_REVETHIP },
+};
+
+static void
+gif_status(int s)
+{
+ int opts;
+ int nopts = 0;
+ size_t i;
+
+ ifr.ifr_data = (caddr_t)&opts;
+ if (ioctl(s, GIFGOPTS, &ifr) == -1)
+ return;
+ if (opts == 0)
+ return;
+
+ printf("\toptions=%d<", opts);
+ for (i=0; i < sizeof(gif_opts)/sizeof(gif_opts[0]); i++) {
+ if (opts & gif_opts[i].mask) {
+ if (nopts++)
+ printf(",");
+ printf("%s", gif_opts[i].label);
+ }
+ }
+ printf(">\n");
+}
+
+static void
+setgifopts(const char *val,
+ int d, int s, const struct afswtch *afp)
+{
+ int opts;
+
+ ifr.ifr_data = (caddr_t)&opts;
+ if (ioctl(s, GIFGOPTS, &ifr) == -1) {
+ warn("ioctl(GIFGOPTS)");
+ return;
+ }
+
+ if (d < 0)
+ opts &= ~(-d);
+ else
+ opts |= d;
+
+ if (ioctl(s, GIFSOPTS, &ifr) == -1) {
+ warn("ioctl(GIFSOPTS)");
+ return;
+ }
+}
+
+static struct cmd gif_cmds[] = {
+ DEF_CMD("accept_rev_ethip_ver", GIF_ACCEPT_REVETHIP, setgifopts),
+ DEF_CMD("-accept_rev_ethip_ver",-GIF_ACCEPT_REVETHIP, setgifopts),
+ DEF_CMD("send_rev_ethip_ver", GIF_SEND_REVETHIP, setgifopts),
+ DEF_CMD("-send_rev_ethip_ver", -GIF_SEND_REVETHIP, setgifopts),
+};
+
+static struct afswtch af_gif = {
+ .af_name = "af_gif",
+ .af_af = AF_UNSPEC,
+ .af_other_status = gif_status,
+};
+
+static __constructor void
+gif_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(gif_cmds); i++)
+ cmd_register(&gif_cmds[i]);
+ af_register(&af_gif);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifgre.c b/freebsd/sbin/ifconfig/ifgre.c
new file mode 100644
index 00000000..58d5bcf5
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifgre.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2008 Andrew Thompson. 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.
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_gre.h>
+#else
+#include <net/if_gre.h>
+#endif
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+static void gre_status(int s);
+
+static void
+gre_status(int s)
+{
+ int grekey = 0;
+
+ ifr.ifr_data = (caddr_t)&grekey;
+ if (ioctl(s, GREGKEY, &ifr) == 0)
+ if (grekey != 0)
+ printf("\tgrekey: %d\n", grekey);
+}
+
+static void
+setifgrekey(const char *val, int dummy __unused, int s,
+ const struct afswtch *afp)
+{
+ uint32_t grekey = atol(val);
+
+ strncpy(ifr.ifr_name, name, sizeof (ifr.ifr_name));
+ ifr.ifr_data = (caddr_t)&grekey;
+ if (ioctl(s, GRESKEY, (caddr_t)&ifr) < 0)
+ warn("ioctl (set grekey)");
+}
+
+static struct cmd gre_cmds[] = {
+ DEF_CMD_ARG("grekey", setifgrekey),
+};
+static struct afswtch af_gre = {
+ .af_name = "af_gre",
+ .af_af = AF_UNSPEC,
+ .af_other_status = gre_status,
+};
+
+static __constructor void
+gre_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(gre_cmds); i++)
+ cmd_register(&gre_cmds[i]);
+ af_register(&af_gre);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifgroup.c b/freebsd/sbin/ifconfig/ifgroup.c
new file mode 100644
index 00000000..2de03e73
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifgroup.c
@@ -0,0 +1,190 @@
+/*-
+ * Copyright (c) 2006 Max Laier. 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 lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+/* ARGSUSED */
+static void
+setifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
+{
+ struct ifgroupreq ifgr;
+
+ memset(&ifgr, 0, sizeof(ifgr));
+ strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+
+ if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
+ errx(1, "setifgroup: group names may not end in a digit");
+
+ if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
+ errx(1, "setifgroup: group name too long");
+ if (ioctl(s, SIOCAIFGROUP, (caddr_t)&ifgr) == -1)
+ err(1," SIOCAIFGROUP");
+}
+
+/* ARGSUSED */
+static void
+unsetifgroup(const char *group_name, int d, int s, const struct afswtch *rafp)
+{
+ struct ifgroupreq ifgr;
+
+ memset(&ifgr, 0, sizeof(ifgr));
+ strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+
+ if (group_name[0] && isdigit(group_name[strlen(group_name) - 1]))
+ errx(1, "unsetifgroup: group names may not end in a digit");
+
+ if (strlcpy(ifgr.ifgr_group, group_name, IFNAMSIZ) >= IFNAMSIZ)
+ errx(1, "unsetifgroup: group name too long");
+ if (ioctl(s, SIOCDIFGROUP, (caddr_t)&ifgr) == -1)
+ err(1, "SIOCDIFGROUP");
+}
+
+static void
+getifgroups(int s)
+{
+ int len, cnt;
+ struct ifgroupreq ifgr;
+ struct ifg_req *ifg;
+
+ if (!verbose)
+ return;
+
+ memset(&ifgr, 0, sizeof(ifgr));
+ strlcpy(ifgr.ifgr_name, name, IFNAMSIZ);
+
+ if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1) {
+ if (errno == EINVAL || errno == ENOTTY)
+ return;
+ else
+ err(1, "SIOCGIFGROUP");
+ }
+
+ len = ifgr.ifgr_len;
+ ifgr.ifgr_groups =
+ (struct ifg_req *)calloc(len / sizeof(struct ifg_req),
+ sizeof(struct ifg_req));
+ if (ifgr.ifgr_groups == NULL)
+ err(1, "getifgroups");
+ if (ioctl(s, SIOCGIFGROUP, (caddr_t)&ifgr) == -1)
+ err(1, "SIOCGIFGROUP");
+
+ cnt = 0;
+ ifg = ifgr.ifgr_groups;
+ for (; ifg && len >= sizeof(struct ifg_req); ifg++) {
+ len -= sizeof(struct ifg_req);
+ if (strcmp(ifg->ifgrq_group, "all")) {
+ if (cnt == 0)
+ printf("\tgroups: ");
+ cnt++;
+ printf("%s ", ifg->ifgrq_group);
+ }
+ }
+ if (cnt)
+ printf("\n");
+}
+
+static void
+printgroup(const char *groupname)
+{
+ struct ifgroupreq ifgr;
+ struct ifg_req *ifg;
+ int len, cnt = 0;
+ int s;
+
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s == -1)
+ 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) {
+ if (errno == EINVAL || errno == ENOTTY ||
+ errno == ENOENT)
+ exit(0);
+ else
+ err(1, "SIOCGIFGMEMB");
+ }
+
+ len = ifgr.ifgr_len;
+ if ((ifgr.ifgr_groups = calloc(1, len)) == NULL)
+ err(1, "printgroup");
+ if (ioctl(s, SIOCGIFGMEMB, (caddr_t)&ifgr) == -1)
+ err(1, "SIOCGIFGMEMB");
+
+ for (ifg = ifgr.ifgr_groups; ifg && len >= sizeof(struct ifg_req);
+ ifg++) {
+ len -= sizeof(struct ifg_req);
+ printf("%s\n", ifg->ifgrq_member);
+ cnt++;
+ }
+ free(ifgr.ifgr_groups);
+
+ exit(0);
+}
+
+static struct cmd group_cmds[] = {
+ DEF_CMD_ARG("group", setifgroup),
+ DEF_CMD_ARG("-group", unsetifgroup),
+};
+static struct afswtch af_group = {
+ .af_name = "af_group",
+ .af_af = AF_UNSPEC,
+ .af_other_status = getifgroups,
+};
+#ifdef __rtems__
+static struct ifconfig_option group_gopt = { "g:", "[-g groupname]", printgroup };
+#else
+static struct option group_gopt = { "g:", "[-g groupname]", printgroup };
+#endif
+
+static __constructor void
+group_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ int i;
+
+ for (i = 0; i < N(group_cmds); i++)
+ cmd_register(&group_cmds[i]);
+ af_register(&af_group);
+ opt_register(&group_gopt);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifieee80211.c b/freebsd/sbin/ifconfig/ifieee80211.c
new file mode 100644
index 00000000..57713ca4
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifieee80211.c
@@ -0,0 +1,5295 @@
+/*
+ * Copyright 2001 The Aerospace 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. The name of The Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION ``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 AEROSPACE CORPORATION 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$
+ */
+
+/*-
+ * Copyright (c) 1997, 1998, 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
+ * NASA Ames Research Center.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#ifdef __rtems__
+#include <freebsd/net/if_media.h>
+#else
+#include <net/if_media.h>
+#endif
+#include <net/route.h>
+
+#ifdef __rtems__
+#include <freebsd/net80211/ieee80211_ioctl.h>
+#include <freebsd/net80211/ieee80211_freebsd.h>
+#include <freebsd/net80211/ieee80211_superg.h>
+#include <freebsd/net80211/ieee80211_tdma.h>
+#include <freebsd/net80211/ieee80211_mesh.h>
+#else
+#include <net80211/ieee80211_ioctl.h>
+#include <net80211/ieee80211_freebsd.h>
+#include <net80211/ieee80211_superg.h>
+#include <net80211/ieee80211_tdma.h>
+#include <net80211/ieee80211_mesh.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stddef.h> /* NB: for offsetof */
+
+#include "ifconfig.h"
+#include "regdomain.h"
+
+#ifndef IEEE80211_FIXED_RATE_NONE
+#define IEEE80211_FIXED_RATE_NONE 0xff
+#endif
+
+/* XXX need these publicly defined or similar */
+#ifndef IEEE80211_NODE_AUTH
+#define IEEE80211_NODE_AUTH 0x000001 /* authorized for data */
+#define IEEE80211_NODE_QOS 0x000002 /* QoS enabled */
+#define IEEE80211_NODE_ERP 0x000004 /* ERP enabled */
+#define IEEE80211_NODE_PWR_MGT 0x000010 /* power save mode enabled */
+#define IEEE80211_NODE_AREF 0x000020 /* authentication ref held */
+#define IEEE80211_NODE_HT 0x000040 /* HT enabled */
+#define IEEE80211_NODE_HTCOMPAT 0x000080 /* HT setup w/ vendor OUI's */
+#define IEEE80211_NODE_WPS 0x000100 /* WPS association */
+#define IEEE80211_NODE_TSN 0x000200 /* TSN association */
+#define IEEE80211_NODE_AMPDU_RX 0x000400 /* AMPDU rx enabled */
+#define IEEE80211_NODE_AMPDU_TX 0x000800 /* AMPDU tx enabled */
+#define IEEE80211_NODE_MIMO_PS 0x001000 /* MIMO power save enabled */
+#define IEEE80211_NODE_MIMO_RTS 0x002000 /* send RTS in MIMO PS */
+#define IEEE80211_NODE_RIFS 0x004000 /* RIFS enabled */
+#define IEEE80211_NODE_SGI20 0x008000 /* Short GI in HT20 enabled */
+#define IEEE80211_NODE_SGI40 0x010000 /* Short GI in HT40 enabled */
+#define IEEE80211_NODE_ASSOCID 0x020000 /* xmit requires associd */
+#define IEEE80211_NODE_AMSDU_RX 0x040000 /* AMSDU rx enabled */
+#define IEEE80211_NODE_AMSDU_TX 0x080000 /* AMSDU tx enabled */
+#endif
+
+#define MAXCHAN 1536 /* max 1.5K channels */
+
+#define MAXCOL 78
+static int col;
+static char spacer;
+
+static void LINE_INIT(char c);
+static void LINE_BREAK(void);
+static void LINE_CHECK(const char *fmt, ...);
+
+static const char *modename[IEEE80211_MODE_MAX] = {
+ [IEEE80211_MODE_AUTO] = "auto",
+ [IEEE80211_MODE_11A] = "11a",
+ [IEEE80211_MODE_11B] = "11b",
+ [IEEE80211_MODE_11G] = "11g",
+ [IEEE80211_MODE_FH] = "fh",
+ [IEEE80211_MODE_TURBO_A] = "turboA",
+ [IEEE80211_MODE_TURBO_G] = "turboG",
+ [IEEE80211_MODE_STURBO_A] = "sturbo",
+ [IEEE80211_MODE_11NA] = "11na",
+ [IEEE80211_MODE_11NG] = "11ng",
+ [IEEE80211_MODE_HALF] = "half",
+ [IEEE80211_MODE_QUARTER] = "quarter"
+};
+
+static void set80211(int s, int type, int val, int len, void *data);
+static int get80211(int s, int type, void *data, int len);
+static int get80211len(int s, int type, void *data, int len, int *plen);
+static int get80211val(int s, int type, int *val);
+static const char *get_string(const char *val, const char *sep,
+ u_int8_t *buf, int *lenp);
+static void print_string(const u_int8_t *buf, int len);
+static void print_regdomain(const struct ieee80211_regdomain *, int);
+static void print_channels(int, const struct ieee80211req_chaninfo *,
+ int allchans, int verbose);
+static void regdomain_makechannels(struct ieee80211_regdomain_req *,
+ const struct ieee80211_devcaps_req *);
+static const char *mesh_linkstate_string(uint8_t state);
+
+static struct ieee80211req_chaninfo *chaninfo;
+static struct ieee80211_regdomain regdomain;
+static int gotregdomain = 0;
+static struct ieee80211_roamparams_req roamparams;
+static int gotroam = 0;
+static struct ieee80211_txparams_req txparams;
+static int gottxparams = 0;
+static struct ieee80211_channel curchan;
+static int gotcurchan = 0;
+static struct ifmediareq *ifmr;
+static int htconf = 0;
+static int gothtconf = 0;
+
+static void
+gethtconf(int s)
+{
+ if (gothtconf)
+ return;
+ if (get80211val(s, IEEE80211_IOC_HTCONF, &htconf) < 0)
+ warn("unable to get HT configuration information");
+ gothtconf = 1;
+}
+
+/*
+ * Collect channel info from the kernel. We use this (mostly)
+ * to handle mapping between frequency and IEEE channel number.
+ */
+static void
+getchaninfo(int s)
+{
+ if (chaninfo != NULL)
+ return;
+ chaninfo = malloc(IEEE80211_CHANINFO_SIZE(MAXCHAN));
+ if (chaninfo == NULL)
+ errx(1, "no space for channel list");
+ if (get80211(s, IEEE80211_IOC_CHANINFO, chaninfo,
+ IEEE80211_CHANINFO_SIZE(MAXCHAN)) < 0)
+ err(1, "unable to get channel information");
+ ifmr = ifmedia_getstate(s);
+ gethtconf(s);
+}
+
+static struct regdata *
+getregdata(void)
+{
+ static struct regdata *rdp = NULL;
+ if (rdp == NULL) {
+ rdp = lib80211_alloc_regdata();
+ if (rdp == NULL)
+ errx(-1, "missing or corrupted regdomain database");
+ }
+ return rdp;
+}
+
+/*
+ * Given the channel at index i with attributes from,
+ * check if there is a channel with attributes to in
+ * the channel table. With suitable attributes this
+ * allows the caller to look for promotion; e.g. from
+ * 11b > 11g.
+ */
+static int
+canpromote(int i, int from, int to)
+{
+ const struct ieee80211_channel *fc = &chaninfo->ic_chans[i];
+ int j;
+
+ if ((fc->ic_flags & from) != from)
+ return i;
+ /* NB: quick check exploiting ordering of chans w/ same frequency */
+ if (i+1 < chaninfo->ic_nchans &&
+ chaninfo->ic_chans[i+1].ic_freq == fc->ic_freq &&
+ (chaninfo->ic_chans[i+1].ic_flags & to) == to)
+ return i+1;
+ /* brute force search in case channel list is not ordered */
+ for (j = 0; j < chaninfo->ic_nchans; j++) {
+ const struct ieee80211_channel *tc = &chaninfo->ic_chans[j];
+ if (j != i &&
+ tc->ic_freq == fc->ic_freq && (tc->ic_flags & to) == to)
+ return j;
+ }
+ return i;
+}
+
+/*
+ * Handle channel promotion. When a channel is specified with
+ * only a frequency we want to promote it to the ``best'' channel
+ * available. The channel list has separate entries for 11b, 11g,
+ * 11a, and 11n[ga] channels so specifying a frequency w/o any
+ * attributes requires we upgrade, e.g. from 11b -> 11g. This
+ * gets complicated when the channel is specified on the same
+ * command line with a media request that constrains the available
+ * channe list (e.g. mode 11a); we want to honor that to avoid
+ * confusing behaviour.
+ */
+static int
+promote(int i)
+{
+ /*
+ * Query the current mode of the interface in case it's
+ * constrained (e.g. to 11a). We must do this carefully
+ * as there may be a pending ifmedia request in which case
+ * asking the kernel will give us the wrong answer. This
+ * is an unfortunate side-effect of the way ifconfig is
+ * structure for modularity (yech).
+ *
+ * NB: ifmr is actually setup in getchaninfo (above); we
+ * assume it's called coincident with to this call so
+ * we have a ``current setting''; otherwise we must pass
+ * the socket descriptor down to here so we can make
+ * the ifmedia_getstate call ourselves.
+ */
+ int chanmode = ifmr != NULL ? IFM_MODE(ifmr->ifm_current) : IFM_AUTO;
+
+ /* when ambiguous promote to ``best'' */
+ /* NB: we abitrarily pick HT40+ over HT40- */
+ if (chanmode != IFM_IEEE80211_11B)
+ i = canpromote(i, IEEE80211_CHAN_B, IEEE80211_CHAN_G);
+ if (chanmode != IFM_IEEE80211_11G && (htconf & 1)) {
+ i = canpromote(i, IEEE80211_CHAN_G,
+ IEEE80211_CHAN_G | IEEE80211_CHAN_HT20);
+ if (htconf & 2) {
+ i = canpromote(i, IEEE80211_CHAN_G,
+ IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D);
+ i = canpromote(i, IEEE80211_CHAN_G,
+ IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U);
+ }
+ }
+ if (chanmode != IFM_IEEE80211_11A && (htconf & 1)) {
+ i = canpromote(i, IEEE80211_CHAN_A,
+ IEEE80211_CHAN_A | IEEE80211_CHAN_HT20);
+ if (htconf & 2) {
+ i = canpromote(i, IEEE80211_CHAN_A,
+ IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D);
+ i = canpromote(i, IEEE80211_CHAN_A,
+ IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U);
+ }
+ }
+ return i;
+}
+
+static void
+mapfreq(struct ieee80211_channel *chan, int freq, int flags)
+{
+ int i;
+
+ for (i = 0; i < chaninfo->ic_nchans; i++) {
+ const struct ieee80211_channel *c = &chaninfo->ic_chans[i];
+
+ if (c->ic_freq == freq && (c->ic_flags & flags) == flags) {
+ if (flags == 0) {
+ /* when ambiguous promote to ``best'' */
+ c = &chaninfo->ic_chans[promote(i)];
+ }
+ *chan = *c;
+ return;
+ }
+ }
+ errx(1, "unknown/undefined frequency %u/0x%x", freq, flags);
+}
+
+static void
+mapchan(struct ieee80211_channel *chan, int ieee, int flags)
+{
+ int i;
+
+ for (i = 0; i < chaninfo->ic_nchans; i++) {
+ const struct ieee80211_channel *c = &chaninfo->ic_chans[i];
+
+ if (c->ic_ieee == ieee && (c->ic_flags & flags) == flags) {
+ if (flags == 0) {
+ /* when ambiguous promote to ``best'' */
+ c = &chaninfo->ic_chans[promote(i)];
+ }
+ *chan = *c;
+ return;
+ }
+ }
+ errx(1, "unknown/undefined channel number %d flags 0x%x", ieee, flags);
+}
+
+static const struct ieee80211_channel *
+getcurchan(int s)
+{
+ if (gotcurchan)
+ return &curchan;
+ if (get80211(s, IEEE80211_IOC_CURCHAN, &curchan, sizeof(curchan)) < 0) {
+ int val;
+ /* fall back to legacy ioctl */
+ if (get80211val(s, IEEE80211_IOC_CHANNEL, &val) < 0)
+ err(-1, "cannot figure out current channel");
+ getchaninfo(s);
+ mapchan(&curchan, val, 0);
+ }
+ gotcurchan = 1;
+ return &curchan;
+}
+
+static enum ieee80211_phymode
+chan2mode(const struct ieee80211_channel *c)
+{
+ if (IEEE80211_IS_CHAN_HTA(c))
+ return IEEE80211_MODE_11NA;
+ if (IEEE80211_IS_CHAN_HTG(c))
+ return IEEE80211_MODE_11NG;
+ if (IEEE80211_IS_CHAN_108A(c))
+ return IEEE80211_MODE_TURBO_A;
+ if (IEEE80211_IS_CHAN_108G(c))
+ return IEEE80211_MODE_TURBO_G;
+ if (IEEE80211_IS_CHAN_ST(c))
+ return IEEE80211_MODE_STURBO_A;
+ if (IEEE80211_IS_CHAN_FHSS(c))
+ return IEEE80211_MODE_FH;
+ if (IEEE80211_IS_CHAN_HALF(c))
+ return IEEE80211_MODE_HALF;
+ if (IEEE80211_IS_CHAN_QUARTER(c))
+ return IEEE80211_MODE_QUARTER;
+ if (IEEE80211_IS_CHAN_A(c))
+ return IEEE80211_MODE_11A;
+ if (IEEE80211_IS_CHAN_ANYG(c))
+ return IEEE80211_MODE_11G;
+ if (IEEE80211_IS_CHAN_B(c))
+ return IEEE80211_MODE_11B;
+ return IEEE80211_MODE_AUTO;
+}
+
+static void
+getroam(int s)
+{
+ if (gotroam)
+ return;
+ if (get80211(s, IEEE80211_IOC_ROAM,
+ &roamparams, sizeof(roamparams)) < 0)
+ err(1, "unable to get roaming parameters");
+ gotroam = 1;
+}
+
+static void
+setroam_cb(int s, void *arg)
+{
+ struct ieee80211_roamparams_req *roam = arg;
+ set80211(s, IEEE80211_IOC_ROAM, 0, sizeof(*roam), roam);
+}
+
+static void
+gettxparams(int s)
+{
+ if (gottxparams)
+ return;
+ if (get80211(s, IEEE80211_IOC_TXPARAMS,
+ &txparams, sizeof(txparams)) < 0)
+ err(1, "unable to get transmit parameters");
+ gottxparams = 1;
+}
+
+static void
+settxparams_cb(int s, void *arg)
+{
+ struct ieee80211_txparams_req *txp = arg;
+ set80211(s, IEEE80211_IOC_TXPARAMS, 0, sizeof(*txp), txp);
+}
+
+static void
+getregdomain(int s)
+{
+ if (gotregdomain)
+ return;
+ if (get80211(s, IEEE80211_IOC_REGDOMAIN,
+ &regdomain, sizeof(regdomain)) < 0)
+ err(1, "unable to get regulatory domain info");
+ gotregdomain = 1;
+}
+
+static void
+getdevcaps(int s, struct ieee80211_devcaps_req *dc)
+{
+ if (get80211(s, IEEE80211_IOC_DEVCAPS, dc,
+ IEEE80211_DEVCAPS_SPACE(dc)) < 0)
+ err(1, "unable to get device capabilities");
+}
+
+static void
+setregdomain_cb(int s, void *arg)
+{
+ struct ieee80211_regdomain_req *req;
+ struct ieee80211_regdomain *rd = arg;
+ struct ieee80211_devcaps_req *dc;
+ struct regdata *rdp = getregdata();
+
+ if (rd->country != NO_COUNTRY) {
+ const struct country *cc;
+ /*
+ * Check current country seting to make sure it's
+ * compatible with the new regdomain. If not, then
+ * override it with any default country for this
+ * SKU. If we cannot arrange a match, then abort.
+ */
+ cc = lib80211_country_findbycc(rdp, rd->country);
+ if (cc == NULL)
+ errx(1, "unknown ISO country code %d", rd->country);
+ if (cc->rd->sku != rd->regdomain) {
+ const struct regdomain *rp;
+ /*
+ * Check if country is incompatible with regdomain.
+ * To enable multiple regdomains for a country code
+ * we permit a mismatch between the regdomain and
+ * the country's associated regdomain when the
+ * regdomain is setup w/o a default country. For
+ * example, US is bound to the FCC regdomain but
+ * we allow US to be combined with FCC3 because FCC3
+ * has not default country. This allows bogus
+ * combinations like FCC3+DK which are resolved when
+ * constructing the channel list by deferring to the
+ * regdomain to construct the channel list.
+ */
+ rp = lib80211_regdomain_findbysku(rdp, rd->regdomain);
+ if (rp == NULL)
+ errx(1, "country %s (%s) is not usable with "
+ "regdomain %d", cc->isoname, cc->name,
+ rd->regdomain);
+ else if (rp->cc != NULL && rp->cc != cc)
+ errx(1, "country %s (%s) is not usable with "
+ "regdomain %s", cc->isoname, cc->name,
+ rp->name);
+ }
+ }
+ /*
+ * Fetch the device capabilities and calculate the
+ * full set of netbands for which we request a new
+ * channel list be constructed. Once that's done we
+ * push the regdomain info + channel list to the kernel.
+ */
+ dc = malloc(IEEE80211_DEVCAPS_SIZE(MAXCHAN));
+ if (dc == NULL)
+ errx(1, "no space for device capabilities");
+ dc->dc_chaninfo.ic_nchans = MAXCHAN;
+ getdevcaps(s, dc);
+#if 0
+ if (verbose) {
+ printf("drivercaps: 0x%x\n", dc->dc_drivercaps);
+ printf("cryptocaps: 0x%x\n", dc->dc_cryptocaps);
+ printf("htcaps : 0x%x\n", dc->dc_htcaps);
+ memcpy(chaninfo, &dc->dc_chaninfo,
+ IEEE80211_CHANINFO_SPACE(&dc->dc_chaninfo));
+ print_channels(s, &dc->dc_chaninfo, 1/*allchans*/, 1/*verbose*/);
+ }
+#endif
+ req = malloc(IEEE80211_REGDOMAIN_SIZE(dc->dc_chaninfo.ic_nchans));
+ if (req == NULL)
+ errx(1, "no space for regdomain request");
+ req->rd = *rd;
+ regdomain_makechannels(req, dc);
+ if (verbose) {
+ LINE_INIT(':');
+ print_regdomain(rd, 1/*verbose*/);
+ LINE_BREAK();
+ /* blech, reallocate channel list for new data */
+ if (chaninfo != NULL)
+ free(chaninfo);
+ chaninfo = malloc(IEEE80211_CHANINFO_SPACE(&req->chaninfo));
+ if (chaninfo == NULL)
+ errx(1, "no space for channel list");
+ memcpy(chaninfo, &req->chaninfo,
+ IEEE80211_CHANINFO_SPACE(&req->chaninfo));
+ print_channels(s, &req->chaninfo, 1/*allchans*/, 1/*verbose*/);
+ }
+ if (req->chaninfo.ic_nchans == 0)
+ errx(1, "no channels calculated");
+ set80211(s, IEEE80211_IOC_REGDOMAIN, 0,
+ IEEE80211_REGDOMAIN_SPACE(req), req);
+ free(req);
+ free(dc);
+}
+
+static int
+ieee80211_mhz2ieee(int freq, int flags)
+{
+ struct ieee80211_channel chan;
+ mapfreq(&chan, freq, flags);
+ return chan.ic_ieee;
+}
+
+static int
+isanyarg(const char *arg)
+{
+ return (strncmp(arg, "-", 1) == 0 ||
+ strncasecmp(arg, "any", 3) == 0 || strncasecmp(arg, "off", 3) == 0);
+}
+
+static void
+set80211ssid(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int ssid;
+ int len;
+ u_int8_t data[IEEE80211_NWID_LEN];
+
+ ssid = 0;
+ len = strlen(val);
+ if (len > 2 && isdigit((int)val[0]) && val[1] == ':') {
+ ssid = atoi(val)-1;
+ val += 2;
+ }
+
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ if (get_string(val, NULL, data, &len) == NULL)
+ exit(1);
+
+ set80211(s, IEEE80211_IOC_SSID, ssid, len, data);
+}
+
+static void
+set80211meshid(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int len;
+ u_int8_t data[IEEE80211_NWID_LEN];
+
+ memset(data, 0, sizeof(data));
+ len = sizeof(data);
+ if (get_string(val, NULL, data, &len) == NULL)
+ exit(1);
+
+ set80211(s, IEEE80211_IOC_MESH_ID, 0, len, data);
+}
+
+static void
+set80211stationname(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int len;
+ u_int8_t data[33];
+
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ get_string(val, NULL, data, &len);
+
+ set80211(s, IEEE80211_IOC_STATIONNAME, 0, len, data);
+}
+
+/*
+ * Parse a channel specification for attributes/flags.
+ * The syntax is:
+ * freq/xx channel width (5,10,20,40,40+,40-)
+ * freq:mode channel mode (a,b,g,h,n,t,s,d)
+ *
+ * These can be combined in either order; e.g. 2437:ng/40.
+ * Modes are case insensitive.
+ *
+ * The result is not validated here; it's assumed to be
+ * checked against the channel table fetched from the kernel.
+ */
+static int
+getchannelflags(const char *val, int freq)
+{
+#define _CHAN_HT 0x80000000
+ const char *cp;
+ int flags;
+
+ flags = 0;
+
+ cp = strchr(val, ':');
+ if (cp != NULL) {
+ for (cp++; isalpha((int) *cp); cp++) {
+ /* accept mixed case */
+ int c = *cp;
+ if (isupper(c))
+ c = tolower(c);
+ switch (c) {
+ case 'a': /* 802.11a */
+ flags |= IEEE80211_CHAN_A;
+ break;
+ case 'b': /* 802.11b */
+ flags |= IEEE80211_CHAN_B;
+ break;
+ case 'g': /* 802.11g */
+ flags |= IEEE80211_CHAN_G;
+ break;
+ case 'h': /* ht = 802.11n */
+ case 'n': /* 802.11n */
+ flags |= _CHAN_HT; /* NB: private */
+ break;
+ case 'd': /* dt = Atheros Dynamic Turbo */
+ flags |= IEEE80211_CHAN_TURBO;
+ break;
+ case 't': /* ht, dt, st, t */
+ /* dt and unadorned t specify Dynamic Turbo */
+ if ((flags & (IEEE80211_CHAN_STURBO|_CHAN_HT)) == 0)
+ flags |= IEEE80211_CHAN_TURBO;
+ break;
+ case 's': /* st = Atheros Static Turbo */
+ flags |= IEEE80211_CHAN_STURBO;
+ break;
+ default:
+ errx(-1, "%s: Invalid channel attribute %c\n",
+ val, *cp);
+ }
+ }
+ }
+ cp = strchr(val, '/');
+ if (cp != NULL) {
+ char *ep;
+ u_long cw = strtoul(cp+1, &ep, 10);
+
+ switch (cw) {
+ case 5:
+ flags |= IEEE80211_CHAN_QUARTER;
+ break;
+ case 10:
+ flags |= IEEE80211_CHAN_HALF;
+ break;
+ case 20:
+ /* NB: this may be removed below */
+ flags |= IEEE80211_CHAN_HT20;
+ break;
+ case 40:
+ if (ep != NULL && *ep == '+')
+ flags |= IEEE80211_CHAN_HT40U;
+ else if (ep != NULL && *ep == '-')
+ flags |= IEEE80211_CHAN_HT40D;
+ break;
+ default:
+ errx(-1, "%s: Invalid channel width\n", val);
+ }
+ }
+ /*
+ * Cleanup specifications.
+ */
+ if ((flags & _CHAN_HT) == 0) {
+ /*
+ * If user specified freq/20 or freq/40 quietly remove
+ * HT cw attributes depending on channel use. To give
+ * an explicit 20/40 width for an HT channel you must
+ * indicate it is an HT channel since all HT channels
+ * are also usable for legacy operation; e.g. freq:n/40.
+ */
+ flags &= ~IEEE80211_CHAN_HT;
+ } else {
+ /*
+ * Remove private indicator that this is an HT channel
+ * and if no explicit channel width has been given
+ * provide the default settings.
+ */
+ flags &= ~_CHAN_HT;
+ if ((flags & IEEE80211_CHAN_HT) == 0) {
+ struct ieee80211_channel chan;
+ /*
+ * Consult the channel list to see if we can use
+ * HT40+ or HT40- (if both the map routines choose).
+ */
+ if (freq > 255)
+ mapfreq(&chan, freq, 0);
+ else
+ mapchan(&chan, freq, 0);
+ flags |= (chan.ic_flags & IEEE80211_CHAN_HT);
+ }
+ }
+ return flags;
+#undef _CHAN_HT
+}
+
+static void
+getchannel(int s, struct ieee80211_channel *chan, const char *val)
+{
+ int v, flags;
+ char *eptr;
+
+ memset(chan, 0, sizeof(*chan));
+ if (isanyarg(val)) {
+ chan->ic_freq = IEEE80211_CHAN_ANY;
+ return;
+ }
+ getchaninfo(s);
+ errno = 0;
+ v = strtol(val, &eptr, 10);
+ if (val[0] == '\0' || val == eptr || errno == ERANGE ||
+ /* channel may be suffixed with nothing, :flag, or /width */
+ (eptr[0] != '\0' && eptr[0] != ':' && eptr[0] != '/'))
+ errx(1, "invalid channel specification%s",
+ errno == ERANGE ? " (out of range)" : "");
+ flags = getchannelflags(val, v);
+ if (v > 255) { /* treat as frequency */
+ mapfreq(chan, v, flags);
+ } else {
+ mapchan(chan, v, flags);
+ }
+}
+
+static void
+set80211channel(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct ieee80211_channel chan;
+
+ getchannel(s, &chan, val);
+ set80211(s, IEEE80211_IOC_CURCHAN, 0, sizeof(chan), &chan);
+}
+
+static void
+set80211chanswitch(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct ieee80211_chanswitch_req csr;
+
+ getchannel(s, &csr.csa_chan, val);
+ csr.csa_mode = 1;
+ csr.csa_count = 5;
+ set80211(s, IEEE80211_IOC_CHANSWITCH, 0, sizeof(csr), &csr);
+}
+
+static void
+set80211authmode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if (strcasecmp(val, "none") == 0) {
+ mode = IEEE80211_AUTH_NONE;
+ } else if (strcasecmp(val, "open") == 0) {
+ mode = IEEE80211_AUTH_OPEN;
+ } else if (strcasecmp(val, "shared") == 0) {
+ mode = IEEE80211_AUTH_SHARED;
+ } else if (strcasecmp(val, "8021x") == 0) {
+ mode = IEEE80211_AUTH_8021X;
+ } else if (strcasecmp(val, "wpa") == 0) {
+ mode = IEEE80211_AUTH_WPA;
+ } else {
+ errx(1, "unknown authmode");
+ }
+
+ set80211(s, IEEE80211_IOC_AUTHMODE, mode, 0, NULL);
+}
+
+static void
+set80211powersavemode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if (strcasecmp(val, "off") == 0) {
+ mode = IEEE80211_POWERSAVE_OFF;
+ } else if (strcasecmp(val, "on") == 0) {
+ mode = IEEE80211_POWERSAVE_ON;
+ } else if (strcasecmp(val, "cam") == 0) {
+ mode = IEEE80211_POWERSAVE_CAM;
+ } else if (strcasecmp(val, "psp") == 0) {
+ mode = IEEE80211_POWERSAVE_PSP;
+ } else if (strcasecmp(val, "psp-cam") == 0) {
+ mode = IEEE80211_POWERSAVE_PSP_CAM;
+ } else {
+ errx(1, "unknown powersavemode");
+ }
+
+ set80211(s, IEEE80211_IOC_POWERSAVE, mode, 0, NULL);
+}
+
+static void
+set80211powersave(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ if (d == 0)
+ set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_OFF,
+ 0, NULL);
+ else
+ set80211(s, IEEE80211_IOC_POWERSAVE, IEEE80211_POWERSAVE_ON,
+ 0, NULL);
+}
+
+static void
+set80211powersavesleep(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_POWERSAVESLEEP, atoi(val), 0, NULL);
+}
+
+static void
+set80211wepmode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if (strcasecmp(val, "off") == 0) {
+ mode = IEEE80211_WEP_OFF;
+ } else if (strcasecmp(val, "on") == 0) {
+ mode = IEEE80211_WEP_ON;
+ } else if (strcasecmp(val, "mixed") == 0) {
+ mode = IEEE80211_WEP_MIXED;
+ } else {
+ errx(1, "unknown wep mode");
+ }
+
+ set80211(s, IEEE80211_IOC_WEP, mode, 0, NULL);
+}
+
+static void
+set80211wep(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_WEP, d, 0, NULL);
+}
+
+static int
+isundefarg(const char *arg)
+{
+ return (strcmp(arg, "-") == 0 || strncasecmp(arg, "undef", 5) == 0);
+}
+
+static void
+set80211weptxkey(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ if (isundefarg(val))
+ set80211(s, IEEE80211_IOC_WEPTXKEY, IEEE80211_KEYIX_NONE, 0, NULL);
+ else
+ set80211(s, IEEE80211_IOC_WEPTXKEY, atoi(val)-1, 0, NULL);
+}
+
+static void
+set80211wepkey(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int key = 0;
+ int len;
+ u_int8_t data[IEEE80211_KEYBUF_SIZE];
+
+ if (isdigit((int)val[0]) && val[1] == ':') {
+ key = atoi(val)-1;
+ val += 2;
+ }
+
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ get_string(val, NULL, data, &len);
+
+ set80211(s, IEEE80211_IOC_WEPKEY, key, len, data);
+}
+
+/*
+ * This function is purely a NetBSD compatability interface. The NetBSD
+ * interface is too inflexible, but it's there so we'll support it since
+ * it's not all that hard.
+ */
+static void
+set80211nwkey(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int txkey;
+ int i, len;
+ u_int8_t data[IEEE80211_KEYBUF_SIZE];
+
+ set80211(s, IEEE80211_IOC_WEP, IEEE80211_WEP_ON, 0, NULL);
+
+ if (isdigit((int)val[0]) && val[1] == ':') {
+ txkey = val[0]-'0'-1;
+ val += 2;
+
+ for (i = 0; i < 4; i++) {
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ val = get_string(val, ",", data, &len);
+ if (val == NULL)
+ exit(1);
+
+ set80211(s, IEEE80211_IOC_WEPKEY, i, len, data);
+ }
+ } else {
+ bzero(data, sizeof(data));
+ len = sizeof(data);
+ get_string(val, NULL, data, &len);
+ txkey = 0;
+
+ set80211(s, IEEE80211_IOC_WEPKEY, 0, len, data);
+
+ bzero(data, sizeof(data));
+ for (i = 1; i < 4; i++)
+ set80211(s, IEEE80211_IOC_WEPKEY, i, 0, data);
+ }
+
+ set80211(s, IEEE80211_IOC_WEPTXKEY, txkey, 0, NULL);
+}
+
+static void
+set80211rtsthreshold(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_RTSTHRESHOLD,
+ isundefarg(val) ? IEEE80211_RTS_MAX : atoi(val), 0, NULL);
+}
+
+static void
+set80211protmode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if (strcasecmp(val, "off") == 0) {
+ mode = IEEE80211_PROTMODE_OFF;
+ } else if (strcasecmp(val, "cts") == 0) {
+ mode = IEEE80211_PROTMODE_CTS;
+ } else if (strncasecmp(val, "rtscts", 3) == 0) {
+ mode = IEEE80211_PROTMODE_RTSCTS;
+ } else {
+ errx(1, "unknown protection mode");
+ }
+
+ set80211(s, IEEE80211_IOC_PROTMODE, mode, 0, NULL);
+}
+
+static void
+set80211htprotmode(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if (strcasecmp(val, "off") == 0) {
+ mode = IEEE80211_PROTMODE_OFF;
+ } else if (strncasecmp(val, "rts", 3) == 0) {
+ mode = IEEE80211_PROTMODE_RTSCTS;
+ } else {
+ errx(1, "unknown protection mode");
+ }
+
+ set80211(s, IEEE80211_IOC_HTPROTMODE, mode, 0, NULL);
+}
+
+static void
+set80211txpower(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ double v = atof(val);
+ int txpow;
+
+ txpow = (int) (2*v);
+ if (txpow != 2*v)
+ errx(-1, "invalid tx power (must be .5 dBm units)");
+ set80211(s, IEEE80211_IOC_TXPOWER, txpow, 0, NULL);
+}
+
+#define IEEE80211_ROAMING_DEVICE 0
+#define IEEE80211_ROAMING_AUTO 1
+#define IEEE80211_ROAMING_MANUAL 2
+
+static void
+set80211roaming(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int mode;
+
+ if (strcasecmp(val, "device") == 0) {
+ mode = IEEE80211_ROAMING_DEVICE;
+ } else if (strcasecmp(val, "auto") == 0) {
+ mode = IEEE80211_ROAMING_AUTO;
+ } else if (strcasecmp(val, "manual") == 0) {
+ mode = IEEE80211_ROAMING_MANUAL;
+ } else {
+ errx(1, "unknown roaming mode");
+ }
+ set80211(s, IEEE80211_IOC_ROAMING, mode, 0, NULL);
+}
+
+static void
+set80211wme(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_WME, d, 0, NULL);
+}
+
+static void
+set80211hidessid(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_HIDESSID, d, 0, NULL);
+}
+
+static void
+set80211apbridge(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_APBRIDGE, d, 0, NULL);
+}
+
+static void
+set80211fastframes(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_FF, d, 0, NULL);
+}
+
+static void
+set80211dturbo(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_TURBOP, d, 0, NULL);
+}
+
+static void
+set80211chanlist(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct ieee80211req_chanlist chanlist;
+ char *temp, *cp, *tp;
+
+ temp = malloc(strlen(val) + 1);
+ if (temp == NULL)
+ errx(1, "malloc failed");
+ strcpy(temp, val);
+ memset(&chanlist, 0, sizeof(chanlist));
+ cp = temp;
+ for (;;) {
+ int first, last, f, c;
+
+ tp = strchr(cp, ',');
+ if (tp != NULL)
+ *tp++ = '\0';
+ switch (sscanf(cp, "%u-%u", &first, &last)) {
+ case 1:
+ if (first > IEEE80211_CHAN_MAX)
+ errx(-1, "channel %u out of range, max %u",
+ first, IEEE80211_CHAN_MAX);
+ setbit(chanlist.ic_channels, first);
+ break;
+ case 2:
+ if (first > IEEE80211_CHAN_MAX)
+ errx(-1, "channel %u out of range, max %u",
+ first, IEEE80211_CHAN_MAX);
+ if (last > IEEE80211_CHAN_MAX)
+ errx(-1, "channel %u out of range, max %u",
+ last, IEEE80211_CHAN_MAX);
+ if (first > last)
+ errx(-1, "void channel range, %u > %u",
+ first, last);
+ for (f = first; f <= last; f++)
+ setbit(chanlist.ic_channels, f);
+ break;
+ }
+ if (tp == NULL)
+ break;
+ c = *tp;
+ while (isspace(c))
+ tp++;
+ if (!isdigit(c))
+ break;
+ cp = tp;
+ }
+ set80211(s, IEEE80211_IOC_CHANLIST, 0, sizeof(chanlist), &chanlist);
+}
+
+static void
+set80211bssid(const char *val, int d, int s, const struct afswtch *rafp)
+{
+
+ if (!isanyarg(val)) {
+ char *temp;
+ struct sockaddr_dl sdl;
+
+ temp = malloc(strlen(val) + 2); /* ':' and '\0' */
+ if (temp == NULL)
+ errx(1, "malloc failed");
+ temp[0] = ':';
+ strcpy(temp + 1, val);
+ sdl.sdl_len = sizeof(sdl);
+ link_addr(temp, &sdl);
+ free(temp);
+ if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
+ errx(1, "malformed link-level address");
+ set80211(s, IEEE80211_IOC_BSSID, 0,
+ IEEE80211_ADDR_LEN, LLADDR(&sdl));
+ } else {
+ uint8_t zerobssid[IEEE80211_ADDR_LEN];
+ memset(zerobssid, 0, sizeof(zerobssid));
+ set80211(s, IEEE80211_IOC_BSSID, 0,
+ IEEE80211_ADDR_LEN, zerobssid);
+ }
+}
+
+static int
+getac(const char *ac)
+{
+ if (strcasecmp(ac, "ac_be") == 0 || strcasecmp(ac, "be") == 0)
+ return WME_AC_BE;
+ if (strcasecmp(ac, "ac_bk") == 0 || strcasecmp(ac, "bk") == 0)
+ return WME_AC_BK;
+ if (strcasecmp(ac, "ac_vi") == 0 || strcasecmp(ac, "vi") == 0)
+ return WME_AC_VI;
+ if (strcasecmp(ac, "ac_vo") == 0 || strcasecmp(ac, "vo") == 0)
+ return WME_AC_VO;
+ errx(1, "unknown wme access class %s", ac);
+}
+
+static
+DECL_CMD_FUNC2(set80211cwmin, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val), getac(ac), NULL);
+}
+
+static
+DECL_CMD_FUNC2(set80211cwmax, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val), getac(ac), NULL);
+}
+
+static
+DECL_CMD_FUNC2(set80211aifs, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val), getac(ac), NULL);
+}
+
+static
+DECL_CMD_FUNC2(set80211txoplimit, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val), getac(ac), NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211acm, ac, d)
+{
+ set80211(s, IEEE80211_IOC_WME_ACM, 1, getac(ac), NULL);
+}
+static
+DECL_CMD_FUNC(set80211noacm, ac, d)
+{
+ set80211(s, IEEE80211_IOC_WME_ACM, 0, getac(ac), NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211ackpolicy, ac, d)
+{
+ set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 1, getac(ac), NULL);
+}
+static
+DECL_CMD_FUNC(set80211noackpolicy, ac, d)
+{
+ set80211(s, IEEE80211_IOC_WME_ACKPOLICY, 0, getac(ac), NULL);
+}
+
+static
+DECL_CMD_FUNC2(set80211bsscwmin, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_CWMIN, atoi(val),
+ getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
+}
+
+static
+DECL_CMD_FUNC2(set80211bsscwmax, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_CWMAX, atoi(val),
+ getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
+}
+
+static
+DECL_CMD_FUNC2(set80211bssaifs, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_AIFS, atoi(val),
+ getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
+}
+
+static
+DECL_CMD_FUNC2(set80211bsstxoplimit, ac, val)
+{
+ set80211(s, IEEE80211_IOC_WME_TXOPLIMIT, atoi(val),
+ getac(ac)|IEEE80211_WMEPARAM_BSS, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211dtimperiod, val, d)
+{
+ set80211(s, IEEE80211_IOC_DTIM_PERIOD, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211bintval, val, d)
+{
+ set80211(s, IEEE80211_IOC_BEACON_INTERVAL, atoi(val), 0, NULL);
+}
+
+static void
+set80211macmac(int s, int op, const char *val)
+{
+ char *temp;
+ struct sockaddr_dl sdl;
+
+ temp = malloc(strlen(val) + 2); /* ':' and '\0' */
+ if (temp == NULL)
+ errx(1, "malloc failed");
+ temp[0] = ':';
+ strcpy(temp + 1, val);
+ sdl.sdl_len = sizeof(sdl);
+ link_addr(temp, &sdl);
+ free(temp);
+ if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
+ errx(1, "malformed link-level address");
+ set80211(s, op, 0, IEEE80211_ADDR_LEN, LLADDR(&sdl));
+}
+
+static
+DECL_CMD_FUNC(set80211addmac, val, d)
+{
+ set80211macmac(s, IEEE80211_IOC_ADDMAC, val);
+}
+
+static
+DECL_CMD_FUNC(set80211delmac, val, d)
+{
+ set80211macmac(s, IEEE80211_IOC_DELMAC, val);
+}
+
+static
+DECL_CMD_FUNC(set80211kickmac, val, d)
+{
+ char *temp;
+ struct sockaddr_dl sdl;
+ struct ieee80211req_mlme mlme;
+
+ temp = malloc(strlen(val) + 2); /* ':' and '\0' */
+ if (temp == NULL)
+ errx(1, "malloc failed");
+ temp[0] = ':';
+ strcpy(temp + 1, val);
+ sdl.sdl_len = sizeof(sdl);
+ link_addr(temp, &sdl);
+ free(temp);
+ if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
+ errx(1, "malformed link-level address");
+ memset(&mlme, 0, sizeof(mlme));
+ mlme.im_op = IEEE80211_MLME_DEAUTH;
+ mlme.im_reason = IEEE80211_REASON_AUTH_EXPIRE;
+ memcpy(mlme.im_macaddr, LLADDR(&sdl), IEEE80211_ADDR_LEN);
+ set80211(s, IEEE80211_IOC_MLME, 0, sizeof(mlme), &mlme);
+}
+
+static
+DECL_CMD_FUNC(set80211maccmd, val, d)
+{
+ set80211(s, IEEE80211_IOC_MACCMD, d, 0, NULL);
+}
+
+static void
+set80211meshrtmac(int s, int req, const char *val)
+{
+ char *temp;
+ struct sockaddr_dl sdl;
+
+ temp = malloc(strlen(val) + 2); /* ':' and '\0' */
+ if (temp == NULL)
+ errx(1, "malloc failed");
+ temp[0] = ':';
+ strcpy(temp + 1, val);
+ sdl.sdl_len = sizeof(sdl);
+ link_addr(temp, &sdl);
+ free(temp);
+ if (sdl.sdl_alen != IEEE80211_ADDR_LEN)
+ errx(1, "malformed link-level address");
+ set80211(s, IEEE80211_IOC_MESH_RTCMD, req,
+ IEEE80211_ADDR_LEN, LLADDR(&sdl));
+}
+
+static
+DECL_CMD_FUNC(set80211addmeshrt, val, d)
+{
+ set80211meshrtmac(s, IEEE80211_MESH_RTCMD_ADD, val);
+}
+
+static
+DECL_CMD_FUNC(set80211delmeshrt, val, d)
+{
+ set80211meshrtmac(s, IEEE80211_MESH_RTCMD_DELETE, val);
+}
+
+static
+DECL_CMD_FUNC(set80211meshrtcmd, val, d)
+{
+ set80211(s, IEEE80211_IOC_MESH_RTCMD, d, 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211hwmprootmode, val, d)
+{
+ int mode;
+
+ if (strcasecmp(val, "normal") == 0)
+ mode = IEEE80211_HWMP_ROOTMODE_NORMAL;
+ else if (strcasecmp(val, "proactive") == 0)
+ mode = IEEE80211_HWMP_ROOTMODE_PROACTIVE;
+ else if (strcasecmp(val, "rann") == 0)
+ mode = IEEE80211_HWMP_ROOTMODE_RANN;
+ else
+ mode = IEEE80211_HWMP_ROOTMODE_DISABLED;
+ set80211(s, IEEE80211_IOC_HWMP_ROOTMODE, mode, 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211hwmpmaxhops, val, d)
+{
+ set80211(s, IEEE80211_IOC_HWMP_MAXHOPS, atoi(val), 0, NULL);
+}
+
+static void
+set80211pureg(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_PUREG, d, 0, NULL);
+}
+
+static void
+set80211bgscan(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_BGSCAN, d, 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211bgscanidle, val, d)
+{
+ set80211(s, IEEE80211_IOC_BGSCAN_IDLE, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211bgscanintvl, val, d)
+{
+ set80211(s, IEEE80211_IOC_BGSCAN_INTERVAL, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211scanvalid, val, d)
+{
+ set80211(s, IEEE80211_IOC_SCANVALID, atoi(val), 0, NULL);
+}
+
+/*
+ * Parse an optional trailing specification of which netbands
+ * to apply a parameter to. This is basically the same syntax
+ * as used for channels but you can concatenate to specify
+ * multiple. For example:
+ * 14:abg apply to 11a, 11b, and 11g
+ * 6:ht apply to 11na and 11ng
+ * We don't make a big effort to catch silly things; this is
+ * really a convenience mechanism.
+ */
+static int
+getmodeflags(const char *val)
+{
+ const char *cp;
+ int flags;
+
+ flags = 0;
+
+ cp = strchr(val, ':');
+ if (cp != NULL) {
+ for (cp++; isalpha((int) *cp); cp++) {
+ /* accept mixed case */
+ int c = *cp;
+ if (isupper(c))
+ c = tolower(c);
+ switch (c) {
+ case 'a': /* 802.11a */
+ flags |= IEEE80211_CHAN_A;
+ break;
+ case 'b': /* 802.11b */
+ flags |= IEEE80211_CHAN_B;
+ break;
+ case 'g': /* 802.11g */
+ flags |= IEEE80211_CHAN_G;
+ break;
+ case 'n': /* 802.11n */
+ flags |= IEEE80211_CHAN_HT;
+ break;
+ case 'd': /* dt = Atheros Dynamic Turbo */
+ flags |= IEEE80211_CHAN_TURBO;
+ break;
+ case 't': /* ht, dt, st, t */
+ /* dt and unadorned t specify Dynamic Turbo */
+ if ((flags & (IEEE80211_CHAN_STURBO|IEEE80211_CHAN_HT)) == 0)
+ flags |= IEEE80211_CHAN_TURBO;
+ break;
+ case 's': /* st = Atheros Static Turbo */
+ flags |= IEEE80211_CHAN_STURBO;
+ break;
+ case 'h': /* 1/2-width channels */
+ flags |= IEEE80211_CHAN_HALF;
+ break;
+ case 'q': /* 1/4-width channels */
+ flags |= IEEE80211_CHAN_QUARTER;
+ break;
+ default:
+ errx(-1, "%s: Invalid mode attribute %c\n",
+ val, *cp);
+ }
+ }
+ }
+ return flags;
+}
+
+#define IEEE80211_CHAN_HTA (IEEE80211_CHAN_HT|IEEE80211_CHAN_5GHZ)
+#define IEEE80211_CHAN_HTG (IEEE80211_CHAN_HT|IEEE80211_CHAN_2GHZ)
+
+#define _APPLY(_flags, _base, _param, _v) do { \
+ if (_flags & IEEE80211_CHAN_HT) { \
+ if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\
+ _base.params[IEEE80211_MODE_11NA]._param = _v; \
+ _base.params[IEEE80211_MODE_11NG]._param = _v; \
+ } else if (_flags & IEEE80211_CHAN_5GHZ) \
+ _base.params[IEEE80211_MODE_11NA]._param = _v; \
+ else \
+ _base.params[IEEE80211_MODE_11NG]._param = _v; \
+ } \
+ if (_flags & IEEE80211_CHAN_TURBO) { \
+ if ((_flags & (IEEE80211_CHAN_5GHZ|IEEE80211_CHAN_2GHZ)) == 0) {\
+ _base.params[IEEE80211_MODE_TURBO_A]._param = _v; \
+ _base.params[IEEE80211_MODE_TURBO_G]._param = _v; \
+ } else if (_flags & IEEE80211_CHAN_5GHZ) \
+ _base.params[IEEE80211_MODE_TURBO_A]._param = _v; \
+ else \
+ _base.params[IEEE80211_MODE_TURBO_G]._param = _v; \
+ } \
+ if (_flags & IEEE80211_CHAN_STURBO) \
+ _base.params[IEEE80211_MODE_STURBO_A]._param = _v; \
+ if ((_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) \
+ _base.params[IEEE80211_MODE_11A]._param = _v; \
+ if ((_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) \
+ _base.params[IEEE80211_MODE_11G]._param = _v; \
+ if ((_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) \
+ _base.params[IEEE80211_MODE_11B]._param = _v; \
+ if (_flags & IEEE80211_CHAN_HALF) \
+ _base.params[IEEE80211_MODE_HALF]._param = _v; \
+ if (_flags & IEEE80211_CHAN_QUARTER) \
+ _base.params[IEEE80211_MODE_QUARTER]._param = _v; \
+} while (0)
+#define _APPLY1(_flags, _base, _param, _v) do { \
+ if (_flags & IEEE80211_CHAN_HT) { \
+ if (_flags & IEEE80211_CHAN_5GHZ) \
+ _base.params[IEEE80211_MODE_11NA]._param = _v; \
+ else \
+ _base.params[IEEE80211_MODE_11NG]._param = _v; \
+ } else if ((_flags & IEEE80211_CHAN_108A) == IEEE80211_CHAN_108A) \
+ _base.params[IEEE80211_MODE_TURBO_A]._param = _v; \
+ else if ((_flags & IEEE80211_CHAN_108G) == IEEE80211_CHAN_108G) \
+ _base.params[IEEE80211_MODE_TURBO_G]._param = _v; \
+ else if ((_flags & IEEE80211_CHAN_ST) == IEEE80211_CHAN_ST) \
+ _base.params[IEEE80211_MODE_STURBO_A]._param = _v; \
+ else if (_flags & IEEE80211_CHAN_HALF) \
+ _base.params[IEEE80211_MODE_HALF]._param = _v; \
+ else if (_flags & IEEE80211_CHAN_QUARTER) \
+ _base.params[IEEE80211_MODE_QUARTER]._param = _v; \
+ else if ((_flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) \
+ _base.params[IEEE80211_MODE_11A]._param = _v; \
+ else if ((_flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) \
+ _base.params[IEEE80211_MODE_11G]._param = _v; \
+ else if ((_flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) \
+ _base.params[IEEE80211_MODE_11B]._param = _v; \
+} while (0)
+#define _APPLY_RATE(_flags, _base, _param, _v) do { \
+ if (_flags & IEEE80211_CHAN_HT) { \
+ (_v) = (_v / 2) | IEEE80211_RATE_MCS; \
+ } \
+ _APPLY(_flags, _base, _param, _v); \
+} while (0)
+#define _APPLY_RATE1(_flags, _base, _param, _v) do { \
+ if (_flags & IEEE80211_CHAN_HT) { \
+ (_v) = (_v / 2) | IEEE80211_RATE_MCS; \
+ } \
+ _APPLY1(_flags, _base, _param, _v); \
+} while (0)
+
+static
+DECL_CMD_FUNC(set80211roamrssi, val, d)
+{
+ double v = atof(val);
+ int rssi, flags;
+
+ rssi = (int) (2*v);
+ if (rssi != 2*v)
+ errx(-1, "invalid rssi (must be .5 dBm units)");
+ flags = getmodeflags(val);
+ getroam(s);
+ if (flags == 0) { /* NB: no flags => current channel */
+ flags = getcurchan(s)->ic_flags;
+ _APPLY1(flags, roamparams, rssi, rssi);
+ } else
+ _APPLY(flags, roamparams, rssi, rssi);
+ callback_register(setroam_cb, &roamparams);
+}
+
+static int
+getrate(const char *val, const char *tag)
+{
+ double v = atof(val);
+ int rate;
+
+ rate = (int) (2*v);
+ if (rate != 2*v)
+ errx(-1, "invalid %s rate (must be .5 Mb/s units)", tag);
+ return rate; /* NB: returns 2x the specified value */
+}
+
+static
+DECL_CMD_FUNC(set80211roamrate, val, d)
+{
+ int rate, flags;
+
+ rate = getrate(val, "roam");
+ flags = getmodeflags(val);
+ getroam(s);
+ if (flags == 0) { /* NB: no flags => current channel */
+ flags = getcurchan(s)->ic_flags;
+ _APPLY_RATE1(flags, roamparams, rate, rate);
+ } else
+ _APPLY_RATE(flags, roamparams, rate, rate);
+ callback_register(setroam_cb, &roamparams);
+}
+
+static
+DECL_CMD_FUNC(set80211mcastrate, val, d)
+{
+ int rate, flags;
+
+ rate = getrate(val, "mcast");
+ flags = getmodeflags(val);
+ gettxparams(s);
+ if (flags == 0) { /* NB: no flags => current channel */
+ flags = getcurchan(s)->ic_flags;
+ _APPLY_RATE1(flags, txparams, mcastrate, rate);
+ } else
+ _APPLY_RATE(flags, txparams, mcastrate, rate);
+ callback_register(settxparams_cb, &txparams);
+}
+
+static
+DECL_CMD_FUNC(set80211mgtrate, val, d)
+{
+ int rate, flags;
+
+ rate = getrate(val, "mgmt");
+ flags = getmodeflags(val);
+ gettxparams(s);
+ if (flags == 0) { /* NB: no flags => current channel */
+ flags = getcurchan(s)->ic_flags;
+ _APPLY_RATE1(flags, txparams, mgmtrate, rate);
+ } else
+ _APPLY_RATE(flags, txparams, mgmtrate, rate);
+ callback_register(settxparams_cb, &txparams);
+}
+
+static
+DECL_CMD_FUNC(set80211ucastrate, val, d)
+{
+ int flags;
+
+ gettxparams(s);
+ flags = getmodeflags(val);
+ if (isanyarg(val)) {
+ if (flags == 0) { /* NB: no flags => current channel */
+ flags = getcurchan(s)->ic_flags;
+ _APPLY1(flags, txparams, ucastrate,
+ IEEE80211_FIXED_RATE_NONE);
+ } else
+ _APPLY(flags, txparams, ucastrate,
+ IEEE80211_FIXED_RATE_NONE);
+ } else {
+ int rate = getrate(val, "ucast");
+ if (flags == 0) { /* NB: no flags => current channel */
+ flags = getcurchan(s)->ic_flags;
+ _APPLY_RATE1(flags, txparams, ucastrate, rate);
+ } else
+ _APPLY_RATE(flags, txparams, ucastrate, rate);
+ }
+ callback_register(settxparams_cb, &txparams);
+}
+
+static
+DECL_CMD_FUNC(set80211maxretry, val, d)
+{
+ int v = atoi(val), flags;
+
+ flags = getmodeflags(val);
+ gettxparams(s);
+ if (flags == 0) { /* NB: no flags => current channel */
+ flags = getcurchan(s)->ic_flags;
+ _APPLY1(flags, txparams, maxretry, v);
+ } else
+ _APPLY(flags, txparams, maxretry, v);
+ callback_register(settxparams_cb, &txparams);
+}
+#undef _APPLY_RATE
+#undef _APPLY
+#undef IEEE80211_CHAN_HTA
+#undef IEEE80211_CHAN_HTG
+
+static
+DECL_CMD_FUNC(set80211fragthreshold, val, d)
+{
+ set80211(s, IEEE80211_IOC_FRAGTHRESHOLD,
+ isundefarg(val) ? IEEE80211_FRAG_MAX : atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211bmissthreshold, val, d)
+{
+ set80211(s, IEEE80211_IOC_BMISSTHRESHOLD,
+ isundefarg(val) ? IEEE80211_HWBMISS_MAX : atoi(val), 0, NULL);
+}
+
+static void
+set80211burst(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_BURST, d, 0, NULL);
+}
+
+static void
+set80211doth(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_DOTH, d, 0, NULL);
+}
+
+static void
+set80211dfs(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_DFS, d, 0, NULL);
+}
+
+static void
+set80211shortgi(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_SHORTGI,
+ d ? (IEEE80211_HTCAP_SHORTGI20 | IEEE80211_HTCAP_SHORTGI40) : 0,
+ 0, NULL);
+}
+
+static void
+set80211ampdu(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int ampdu;
+
+ if (get80211val(s, IEEE80211_IOC_AMPDU, &ampdu) < 0)
+ errx(-1, "cannot get AMPDU setting");
+ if (d < 0) {
+ d = -d;
+ ampdu &= ~d;
+ } else
+ ampdu |= d;
+ set80211(s, IEEE80211_IOC_AMPDU, ampdu, 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211ampdulimit, val, d)
+{
+ int v;
+
+ switch (atoi(val)) {
+ case 8:
+ case 8*1024:
+ v = IEEE80211_HTCAP_MAXRXAMPDU_8K;
+ break;
+ case 16:
+ case 16*1024:
+ v = IEEE80211_HTCAP_MAXRXAMPDU_16K;
+ break;
+ case 32:
+ case 32*1024:
+ v = IEEE80211_HTCAP_MAXRXAMPDU_32K;
+ break;
+ case 64:
+ case 64*1024:
+ v = IEEE80211_HTCAP_MAXRXAMPDU_64K;
+ break;
+ default:
+ errx(-1, "invalid A-MPDU limit %s", val);
+ }
+ set80211(s, IEEE80211_IOC_AMPDU_LIMIT, v, 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211ampdudensity, val, d)
+{
+ int v;
+
+ if (isanyarg(val) || strcasecmp(val, "na") == 0)
+ v = IEEE80211_HTCAP_MPDUDENSITY_NA;
+ else switch ((int)(atof(val)*4)) {
+ case 0:
+ v = IEEE80211_HTCAP_MPDUDENSITY_NA;
+ break;
+ case 1:
+ v = IEEE80211_HTCAP_MPDUDENSITY_025;
+ break;
+ case 2:
+ v = IEEE80211_HTCAP_MPDUDENSITY_05;
+ break;
+ case 4:
+ v = IEEE80211_HTCAP_MPDUDENSITY_1;
+ break;
+ case 8:
+ v = IEEE80211_HTCAP_MPDUDENSITY_2;
+ break;
+ case 16:
+ v = IEEE80211_HTCAP_MPDUDENSITY_4;
+ break;
+ case 32:
+ v = IEEE80211_HTCAP_MPDUDENSITY_8;
+ break;
+ case 64:
+ v = IEEE80211_HTCAP_MPDUDENSITY_16;
+ break;
+ default:
+ errx(-1, "invalid A-MPDU density %s", val);
+ }
+ set80211(s, IEEE80211_IOC_AMPDU_DENSITY, v, 0, NULL);
+}
+
+static void
+set80211amsdu(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ int amsdu;
+
+ if (get80211val(s, IEEE80211_IOC_AMSDU, &amsdu) < 0)
+ err(-1, "cannot get AMSDU setting");
+ if (d < 0) {
+ d = -d;
+ amsdu &= ~d;
+ } else
+ amsdu |= d;
+ set80211(s, IEEE80211_IOC_AMSDU, amsdu, 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211amsdulimit, val, d)
+{
+ set80211(s, IEEE80211_IOC_AMSDU_LIMIT, atoi(val), 0, NULL);
+}
+
+static void
+set80211puren(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_PUREN, d, 0, NULL);
+}
+
+static void
+set80211htcompat(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_HTCOMPAT, d, 0, NULL);
+}
+
+static void
+set80211htconf(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_HTCONF, d, 0, NULL);
+ htconf = d;
+}
+
+static void
+set80211dwds(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_DWDS, d, 0, NULL);
+}
+
+static void
+set80211inact(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_INACTIVITY, d, 0, NULL);
+}
+
+static void
+set80211tsn(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_TSN, d, 0, NULL);
+}
+
+static void
+set80211dotd(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_DOTD, d, 0, NULL);
+}
+
+static void
+set80211smps(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_SMPS, d, 0, NULL);
+}
+
+static void
+set80211rifs(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ set80211(s, IEEE80211_IOC_RIFS, d, 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211tdmaslot, val, d)
+{
+ set80211(s, IEEE80211_IOC_TDMA_SLOT, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211tdmaslotcnt, val, d)
+{
+ set80211(s, IEEE80211_IOC_TDMA_SLOTCNT, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211tdmaslotlen, val, d)
+{
+ set80211(s, IEEE80211_IOC_TDMA_SLOTLEN, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211tdmabintval, val, d)
+{
+ set80211(s, IEEE80211_IOC_TDMA_BINTERVAL, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211meshttl, val, d)
+{
+ set80211(s, IEEE80211_IOC_MESH_TTL, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211meshforward, val, d)
+{
+ set80211(s, IEEE80211_IOC_MESH_FWRD, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211meshpeering, val, d)
+{
+ set80211(s, IEEE80211_IOC_MESH_AP, atoi(val), 0, NULL);
+}
+
+static
+DECL_CMD_FUNC(set80211meshmetric, val, d)
+{
+ char v[12];
+
+ memcpy(v, val, sizeof(v));
+ set80211(s, IEEE80211_IOC_MESH_PR_METRIC, 0, 0, v);
+}
+
+static
+DECL_CMD_FUNC(set80211meshpath, val, d)
+{
+ char v[12];
+
+ memcpy(v, val, sizeof(v));
+ set80211(s, IEEE80211_IOC_MESH_PR_PATH, 0, 0, v);
+}
+
+static int
+regdomain_sort(const void *a, const void *b)
+{
+#define CHAN_ALL \
+ (IEEE80211_CHAN_ALLTURBO|IEEE80211_CHAN_HALF|IEEE80211_CHAN_QUARTER)
+ const struct ieee80211_channel *ca = a;
+ const struct ieee80211_channel *cb = b;
+
+ return ca->ic_freq == cb->ic_freq ?
+ (ca->ic_flags & CHAN_ALL) - (cb->ic_flags & CHAN_ALL) :
+ ca->ic_freq - cb->ic_freq;
+#undef CHAN_ALL
+}
+
+static const struct ieee80211_channel *
+chanlookup(const struct ieee80211_channel chans[], int nchans,
+ int freq, int flags)
+{
+ int i;
+
+ flags &= IEEE80211_CHAN_ALLTURBO;
+ for (i = 0; i < nchans; i++) {
+ const struct ieee80211_channel *c = &chans[i];
+ if (c->ic_freq == freq &&
+ (c->ic_flags & IEEE80211_CHAN_ALLTURBO) == flags)
+ return c;
+ }
+ return NULL;
+}
+
+static int
+chanfind(const struct ieee80211_channel chans[], int nchans, int flags)
+{
+ int i;
+
+ for (i = 0; i < nchans; i++) {
+ const struct ieee80211_channel *c = &chans[i];
+ if ((c->ic_flags & flags) == flags)
+ return 1;
+ }
+ return 0;
+}
+
+/*
+ * Check channel compatibility.
+ */
+static int
+checkchan(const struct ieee80211req_chaninfo *avail, int freq, int flags)
+{
+ flags &= ~REQ_FLAGS;
+ /*
+ * Check if exact channel is in the calibration table;
+ * everything below is to deal with channels that we
+ * want to include but that are not explicitly listed.
+ */
+ if (flags & IEEE80211_CHAN_HT40) {
+ /* NB: we use an HT40 channel center that matches HT20 */
+ flags = (flags &~ IEEE80211_CHAN_HT40) | IEEE80211_CHAN_HT20;
+ }
+ if (chanlookup(avail->ic_chans, avail->ic_nchans, freq, flags) != NULL)
+ return 1;
+ if (flags & IEEE80211_CHAN_GSM) {
+ /*
+ * XXX GSM frequency mapping is handled in the kernel
+ * so we cannot find them in the calibration table;
+ * just accept the channel and the kernel will reject
+ * the channel list if it's wrong.
+ */
+ return 1;
+ }
+ /*
+ * If this is a 1/2 or 1/4 width channel allow it if a full
+ * width channel is present for this frequency, and the device
+ * supports fractional channels on this band. This is a hack
+ * that avoids bloating the calibration table; it may be better
+ * by per-band attributes though (we are effectively calculating
+ * this attribute by scanning the channel list ourself).
+ */
+ if ((flags & (IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER)) == 0)
+ return 0;
+ if (chanlookup(avail->ic_chans, avail->ic_nchans, freq,
+ flags &~ (IEEE80211_CHAN_HALF | IEEE80211_CHAN_QUARTER)) == NULL)
+ return 0;
+ if (flags & IEEE80211_CHAN_HALF) {
+ return chanfind(avail->ic_chans, avail->ic_nchans,
+ IEEE80211_CHAN_HALF |
+ (flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ)));
+ } else {
+ return chanfind(avail->ic_chans, avail->ic_nchans,
+ IEEE80211_CHAN_QUARTER |
+ (flags & (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_5GHZ)));
+ }
+}
+
+static void
+regdomain_addchans(struct ieee80211req_chaninfo *ci,
+ const netband_head *bands,
+ const struct ieee80211_regdomain *reg,
+ uint32_t chanFlags,
+ const struct ieee80211req_chaninfo *avail)
+{
+ const struct netband *nb;
+ const struct freqband *b;
+ struct ieee80211_channel *c, *prev;
+ int freq, hi_adj, lo_adj, channelSep;
+ uint32_t flags;
+
+ hi_adj = (chanFlags & IEEE80211_CHAN_HT40U) ? -20 : 0;
+ lo_adj = (chanFlags & IEEE80211_CHAN_HT40D) ? 20 : 0;
+ channelSep = (chanFlags & IEEE80211_CHAN_2GHZ) ? 0 : 40;
+ LIST_FOREACH(nb, bands, next) {
+ b = nb->band;
+ if (verbose) {
+ printf("%s:", __func__);
+ printb(" chanFlags", chanFlags, IEEE80211_CHAN_BITS);
+ printb(" bandFlags", nb->flags | b->flags,
+ IEEE80211_CHAN_BITS);
+ putchar('\n');
+ }
+ prev = NULL;
+ for (freq = b->freqStart + lo_adj;
+ freq <= b->freqEnd + hi_adj; freq += b->chanSep) {
+ /*
+ * Construct flags for the new channel. We take
+ * the attributes from the band descriptions except
+ * for HT40 which is enabled generically (i.e. +/-
+ * extension channel) in the band description and
+ * then constrained according by channel separation.
+ */
+ flags = nb->flags | b->flags;
+ if (flags & IEEE80211_CHAN_HT) {
+ /*
+ * HT channels are generated specially; we're
+ * called to add HT20, HT40+, and HT40- chan's
+ * so we need to expand only band specs for
+ * the HT channel type being added.
+ */
+ if ((chanFlags & IEEE80211_CHAN_HT20) &&
+ (flags & IEEE80211_CHAN_HT20) == 0) {
+ if (verbose)
+ printf("%u: skip, not an "
+ "HT20 channel\n", freq);
+ continue;
+ }
+ if ((chanFlags & IEEE80211_CHAN_HT40) &&
+ (flags & IEEE80211_CHAN_HT40) == 0) {
+ if (verbose)
+ printf("%u: skip, not an "
+ "HT40 channel\n", freq);
+ continue;
+ }
+ /*
+ * DFS and HT40 don't mix. This should be
+ * expressed in the regdomain database but
+ * just in case enforce it here.
+ */
+ if ((chanFlags & IEEE80211_CHAN_HT40) &&
+ (flags & IEEE80211_CHAN_DFS)) {
+ if (verbose)
+ printf("%u: skip, HT40+DFS "
+ "not permitted\n", freq);
+ continue;
+ }
+ /* NB: HT attribute comes from caller */
+ flags &= ~IEEE80211_CHAN_HT;
+ flags |= chanFlags & IEEE80211_CHAN_HT;
+ }
+ /*
+ * Check if device can operate on this frequency.
+ */
+ if (!checkchan(avail, freq, flags)) {
+ if (verbose) {
+ printf("%u: skip, ", freq);
+ printb("flags", flags,
+ IEEE80211_CHAN_BITS);
+ printf(" not available\n");
+ }
+ continue;
+ }
+ if ((flags & REQ_ECM) && !reg->ecm) {
+ if (verbose)
+ printf("%u: skip, ECM channel\n", freq);
+ continue;
+ }
+ if ((flags & REQ_INDOOR) && reg->location == 'O') {
+ if (verbose)
+ printf("%u: skip, indoor channel\n",
+ freq);
+ continue;
+ }
+ if ((flags & REQ_OUTDOOR) && reg->location == 'I') {
+ if (verbose)
+ printf("%u: skip, outdoor channel\n",
+ freq);
+ continue;
+ }
+ if ((flags & IEEE80211_CHAN_HT40) &&
+ prev != NULL && (freq - prev->ic_freq) < channelSep) {
+ if (verbose)
+ printf("%u: skip, only %u channel "
+ "separation, need %d\n", freq,
+ freq - prev->ic_freq, channelSep);
+ continue;
+ }
+ if (ci->ic_nchans == IEEE80211_CHAN_MAX) {
+ if (verbose)
+ printf("%u: skip, channel table full\n",
+ freq);
+ break;
+ }
+ c = &ci->ic_chans[ci->ic_nchans++];
+ memset(c, 0, sizeof(*c));
+ c->ic_freq = freq;
+ c->ic_flags = flags;
+ if (c->ic_flags & IEEE80211_CHAN_DFS)
+ c->ic_maxregpower = nb->maxPowerDFS;
+ else
+ c->ic_maxregpower = nb->maxPower;
+ if (verbose) {
+ printf("[%3d] add freq %u ",
+ ci->ic_nchans-1, c->ic_freq);
+ printb("flags", c->ic_flags, IEEE80211_CHAN_BITS);
+ printf(" power %u\n", c->ic_maxregpower);
+ }
+ /* NB: kernel fills in other fields */
+ prev = c;
+ }
+ }
+}
+
+static void
+regdomain_makechannels(
+ struct ieee80211_regdomain_req *req,
+ const struct ieee80211_devcaps_req *dc)
+{
+ struct regdata *rdp = getregdata();
+ const struct country *cc;
+ const struct ieee80211_regdomain *reg = &req->rd;
+ struct ieee80211req_chaninfo *ci = &req->chaninfo;
+ const struct regdomain *rd;
+
+ /*
+ * Locate construction table for new channel list. We treat
+ * the regdomain/SKU as definitive so a country can be in
+ * multiple with different properties (e.g. US in FCC+FCC3).
+ * If no regdomain is specified then we fallback on the country
+ * code to find the associated regdomain since countries always
+ * belong to at least one regdomain.
+ */
+ if (reg->regdomain == 0) {
+ cc = lib80211_country_findbycc(rdp, reg->country);
+ if (cc == NULL)
+ errx(1, "internal error, country %d not found",
+ reg->country);
+ rd = cc->rd;
+ } else
+ rd = lib80211_regdomain_findbysku(rdp, reg->regdomain);
+ if (rd == NULL)
+ errx(1, "internal error, regdomain %d not found",
+ reg->regdomain);
+ if (rd->sku != SKU_DEBUG) {
+ /*
+ * regdomain_addchans incrememnts the channel count for
+ * each channel it adds so initialize ic_nchans to zero.
+ * Note that we know we have enough space to hold all possible
+ * channels because the devcaps list size was used to
+ * allocate our request.
+ */
+ ci->ic_nchans = 0;
+ if (!LIST_EMPTY(&rd->bands_11b))
+ regdomain_addchans(ci, &rd->bands_11b, reg,
+ IEEE80211_CHAN_B, &dc->dc_chaninfo);
+ if (!LIST_EMPTY(&rd->bands_11g))
+ regdomain_addchans(ci, &rd->bands_11g, reg,
+ IEEE80211_CHAN_G, &dc->dc_chaninfo);
+ if (!LIST_EMPTY(&rd->bands_11a))
+ regdomain_addchans(ci, &rd->bands_11a, reg,
+ IEEE80211_CHAN_A, &dc->dc_chaninfo);
+ if (!LIST_EMPTY(&rd->bands_11na) && dc->dc_htcaps != 0) {
+ regdomain_addchans(ci, &rd->bands_11na, reg,
+ IEEE80211_CHAN_A | IEEE80211_CHAN_HT20,
+ &dc->dc_chaninfo);
+ if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
+ regdomain_addchans(ci, &rd->bands_11na, reg,
+ IEEE80211_CHAN_A | IEEE80211_CHAN_HT40U,
+ &dc->dc_chaninfo);
+ regdomain_addchans(ci, &rd->bands_11na, reg,
+ IEEE80211_CHAN_A | IEEE80211_CHAN_HT40D,
+ &dc->dc_chaninfo);
+ }
+ }
+ if (!LIST_EMPTY(&rd->bands_11ng) && dc->dc_htcaps != 0) {
+ regdomain_addchans(ci, &rd->bands_11ng, reg,
+ IEEE80211_CHAN_G | IEEE80211_CHAN_HT20,
+ &dc->dc_chaninfo);
+ if (dc->dc_htcaps & IEEE80211_HTCAP_CHWIDTH40) {
+ regdomain_addchans(ci, &rd->bands_11ng, reg,
+ IEEE80211_CHAN_G | IEEE80211_CHAN_HT40U,
+ &dc->dc_chaninfo);
+ regdomain_addchans(ci, &rd->bands_11ng, reg,
+ IEEE80211_CHAN_G | IEEE80211_CHAN_HT40D,
+ &dc->dc_chaninfo);
+ }
+ }
+ qsort(ci->ic_chans, ci->ic_nchans, sizeof(ci->ic_chans[0]),
+ regdomain_sort);
+ } else
+ memcpy(ci, &dc->dc_chaninfo,
+ IEEE80211_CHANINFO_SPACE(&dc->dc_chaninfo));
+}
+
+static void
+list_countries(void)
+{
+ struct regdata *rdp = getregdata();
+ const struct country *cp;
+ const struct regdomain *dp;
+ int i;
+
+ i = 0;
+ printf("\nCountry codes:\n");
+ LIST_FOREACH(cp, &rdp->countries, next) {
+ printf("%2s %-15.15s%s", cp->isoname,
+ cp->name, ((i+1)%4) == 0 ? "\n" : " ");
+ i++;
+ }
+ i = 0;
+ printf("\nRegulatory domains:\n");
+ LIST_FOREACH(dp, &rdp->domains, next) {
+ printf("%-15.15s%s", dp->name, ((i+1)%4) == 0 ? "\n" : " ");
+ i++;
+ }
+ printf("\n");
+}
+
+static void
+defaultcountry(const struct regdomain *rd)
+{
+ struct regdata *rdp = getregdata();
+ const struct country *cc;
+
+ cc = lib80211_country_findbycc(rdp, rd->cc->code);
+ if (cc == NULL)
+ errx(1, "internal error, ISO country code %d not "
+ "defined for regdomain %s", rd->cc->code, rd->name);
+ regdomain.country = cc->code;
+ regdomain.isocc[0] = cc->isoname[0];
+ regdomain.isocc[1] = cc->isoname[1];
+}
+
+static
+DECL_CMD_FUNC(set80211regdomain, val, d)
+{
+ struct regdata *rdp = getregdata();
+ const struct regdomain *rd;
+
+ rd = lib80211_regdomain_findbyname(rdp, val);
+ if (rd == NULL) {
+ char *eptr;
+ long sku = strtol(val, &eptr, 0);
+
+ if (eptr != val)
+ rd = lib80211_regdomain_findbysku(rdp, sku);
+ if (eptr == val || rd == NULL)
+ errx(1, "unknown regdomain %s", val);
+ }
+ getregdomain(s);
+ regdomain.regdomain = rd->sku;
+ if (regdomain.country == 0 && rd->cc != NULL) {
+ /*
+ * No country code setup and there's a default
+ * one for this regdomain fill it in.
+ */
+ defaultcountry(rd);
+ }
+ callback_register(setregdomain_cb, &regdomain);
+}
+
+static
+DECL_CMD_FUNC(set80211country, val, d)
+{
+ struct regdata *rdp = getregdata();
+ const struct country *cc;
+
+ cc = lib80211_country_findbyname(rdp, val);
+ if (cc == NULL) {
+ char *eptr;
+ long code = strtol(val, &eptr, 0);
+
+ if (eptr != val)
+ cc = lib80211_country_findbycc(rdp, code);
+ if (eptr == val || cc == NULL)
+ errx(1, "unknown ISO country code %s", val);
+ }
+ getregdomain(s);
+ regdomain.regdomain = cc->rd->sku;
+ regdomain.country = cc->code;
+ regdomain.isocc[0] = cc->isoname[0];
+ regdomain.isocc[1] = cc->isoname[1];
+ callback_register(setregdomain_cb, &regdomain);
+}
+
+static void
+set80211location(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ getregdomain(s);
+ regdomain.location = d;
+ callback_register(setregdomain_cb, &regdomain);
+}
+
+static void
+set80211ecm(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ getregdomain(s);
+ regdomain.ecm = d;
+ callback_register(setregdomain_cb, &regdomain);
+}
+
+static void
+LINE_INIT(char c)
+{
+ spacer = c;
+ if (c == '\t')
+ col = 8;
+ else
+ col = 1;
+}
+
+static void
+LINE_BREAK(void)
+{
+ if (spacer != '\t') {
+ printf("\n");
+ spacer = '\t';
+ }
+ col = 8; /* 8-col tab */
+}
+
+static void
+LINE_CHECK(const char *fmt, ...)
+{
+ char buf[80];
+ va_list ap;
+ int n;
+
+ va_start(ap, fmt);
+ n = vsnprintf(buf+1, sizeof(buf)-1, fmt, ap);
+ va_end(ap);
+ col += 1+n;
+ if (col > MAXCOL) {
+ LINE_BREAK();
+ col += n;
+ }
+ buf[0] = spacer;
+ printf("%s", buf);
+ spacer = ' ';
+}
+
+static int
+getmaxrate(const uint8_t rates[15], uint8_t nrates)
+{
+ int i, maxrate = -1;
+
+ for (i = 0; i < nrates; i++) {
+ int rate = rates[i] & IEEE80211_RATE_VAL;
+ if (rate > maxrate)
+ maxrate = rate;
+ }
+ return maxrate / 2;
+}
+
+static const char *
+getcaps(int capinfo)
+{
+ static char capstring[32];
+ char *cp = capstring;
+
+ if (capinfo & IEEE80211_CAPINFO_ESS)
+ *cp++ = 'E';
+ if (capinfo & IEEE80211_CAPINFO_IBSS)
+ *cp++ = 'I';
+ if (capinfo & IEEE80211_CAPINFO_CF_POLLABLE)
+ *cp++ = 'c';
+ if (capinfo & IEEE80211_CAPINFO_CF_POLLREQ)
+ *cp++ = 'C';
+ if (capinfo & IEEE80211_CAPINFO_PRIVACY)
+ *cp++ = 'P';
+ if (capinfo & IEEE80211_CAPINFO_SHORT_PREAMBLE)
+ *cp++ = 'S';
+ if (capinfo & IEEE80211_CAPINFO_PBCC)
+ *cp++ = 'B';
+ if (capinfo & IEEE80211_CAPINFO_CHNL_AGILITY)
+ *cp++ = 'A';
+ if (capinfo & IEEE80211_CAPINFO_SHORT_SLOTTIME)
+ *cp++ = 's';
+ if (capinfo & IEEE80211_CAPINFO_RSN)
+ *cp++ = 'R';
+ if (capinfo & IEEE80211_CAPINFO_DSSSOFDM)
+ *cp++ = 'D';
+ *cp = '\0';
+ return capstring;
+}
+
+static const char *
+getflags(int flags)
+{
+ static char flagstring[32];
+ char *cp = flagstring;
+
+ if (flags & IEEE80211_NODE_AUTH)
+ *cp++ = 'A';
+ if (flags & IEEE80211_NODE_QOS)
+ *cp++ = 'Q';
+ if (flags & IEEE80211_NODE_ERP)
+ *cp++ = 'E';
+ if (flags & IEEE80211_NODE_PWR_MGT)
+ *cp++ = 'P';
+ if (flags & IEEE80211_NODE_HT) {
+ *cp++ = 'H';
+ if (flags & IEEE80211_NODE_HTCOMPAT)
+ *cp++ = '+';
+ }
+ if (flags & IEEE80211_NODE_WPS)
+ *cp++ = 'W';
+ if (flags & IEEE80211_NODE_TSN)
+ *cp++ = 'N';
+ if (flags & IEEE80211_NODE_AMPDU_TX)
+ *cp++ = 'T';
+ if (flags & IEEE80211_NODE_AMPDU_RX)
+ *cp++ = 'R';
+ if (flags & IEEE80211_NODE_MIMO_PS) {
+ *cp++ = 'M';
+ if (flags & IEEE80211_NODE_MIMO_RTS)
+ *cp++ = '+';
+ }
+ if (flags & IEEE80211_NODE_RIFS)
+ *cp++ = 'I';
+ if (flags & IEEE80211_NODE_SGI40) {
+ *cp++ = 'S';
+ if (flags & IEEE80211_NODE_SGI20)
+ *cp++ = '+';
+ } else if (flags & IEEE80211_NODE_SGI20)
+ *cp++ = 's';
+ if (flags & IEEE80211_NODE_AMSDU_TX)
+ *cp++ = 't';
+ if (flags & IEEE80211_NODE_AMSDU_RX)
+ *cp++ = 'r';
+ *cp = '\0';
+ return flagstring;
+}
+
+static void
+printie(const char* tag, const uint8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ maxlen -= strlen(tag)+2;
+ if (2*ielen > maxlen)
+ maxlen--;
+ printf("<");
+ for (; ielen > 0; ie++, ielen--) {
+ if (maxlen-- <= 0)
+ break;
+ printf("%02x", *ie);
+ }
+ if (ielen != 0)
+ printf("-");
+ printf(">");
+ }
+}
+
+#define LE_READ_2(p) \
+ ((u_int16_t) \
+ ((((const u_int8_t *)(p))[0] ) | \
+ (((const u_int8_t *)(p))[1] << 8)))
+#define LE_READ_4(p) \
+ ((u_int32_t) \
+ ((((const u_int8_t *)(p))[0] ) | \
+ (((const u_int8_t *)(p))[1] << 8) | \
+ (((const u_int8_t *)(p))[2] << 16) | \
+ (((const u_int8_t *)(p))[3] << 24)))
+
+/*
+ * NB: The decoding routines assume a properly formatted ie
+ * which should be safe as the kernel only retains them
+ * if they parse ok.
+ */
+
+static void
+printwmeparam(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+#define MS(_v, _f) (((_v) & _f) >> _f##_S)
+ static const char *acnames[] = { "BE", "BK", "VO", "VI" };
+ const struct ieee80211_wme_param *wme =
+ (const struct ieee80211_wme_param *) ie;
+ int i;
+
+ printf("%s", tag);
+ if (!verbose)
+ return;
+ printf("<qosinfo 0x%x", wme->param_qosInfo);
+ ie += offsetof(struct ieee80211_wme_param, params_acParams);
+ for (i = 0; i < WME_NUM_AC; i++) {
+ const struct ieee80211_wme_acparams *ac =
+ &wme->params_acParams[i];
+
+ printf(" %s[%saifsn %u cwmin %u cwmax %u txop %u]"
+ , acnames[i]
+ , MS(ac->acp_aci_aifsn, WME_PARAM_ACM) ? "acm " : ""
+ , MS(ac->acp_aci_aifsn, WME_PARAM_AIFSN)
+ , MS(ac->acp_logcwminmax, WME_PARAM_LOGCWMIN)
+ , MS(ac->acp_logcwminmax, WME_PARAM_LOGCWMAX)
+ , LE_READ_2(&ac->acp_txop)
+ );
+ }
+ printf(">");
+#undef MS
+}
+
+static void
+printwmeinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_wme_info *wme =
+ (const struct ieee80211_wme_info *) ie;
+ printf("<version 0x%x info 0x%x>",
+ wme->wme_version, wme->wme_info);
+ }
+}
+
+static void
+printhtcap(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_ie_htcap *htcap =
+ (const struct ieee80211_ie_htcap *) ie;
+ const char *sep;
+ int i, j;
+
+ printf("<cap 0x%x param 0x%x",
+ LE_READ_2(&htcap->hc_cap), htcap->hc_param);
+ printf(" mcsset[");
+ sep = "";
+ for (i = 0; i < IEEE80211_HTRATE_MAXSIZE; i++)
+ if (isset(htcap->hc_mcsset, i)) {
+ for (j = i+1; j < IEEE80211_HTRATE_MAXSIZE; j++)
+ if (isclr(htcap->hc_mcsset, j))
+ break;
+ j--;
+ if (i == j)
+ printf("%s%u", sep, i);
+ else
+ printf("%s%u-%u", sep, i, j);
+ i += j-i;
+ sep = ",";
+ }
+ printf("] extcap 0x%x txbf 0x%x antenna 0x%x>",
+ LE_READ_2(&htcap->hc_extcap),
+ LE_READ_4(&htcap->hc_txbf),
+ htcap->hc_antenna);
+ }
+}
+
+static void
+printhtinfo(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_ie_htinfo *htinfo =
+ (const struct ieee80211_ie_htinfo *) ie;
+ const char *sep;
+ int i, j;
+
+ printf("<ctl %u, %x,%x,%x,%x", htinfo->hi_ctrlchannel,
+ htinfo->hi_byte1, htinfo->hi_byte2, htinfo->hi_byte3,
+ LE_READ_2(&htinfo->hi_byte45));
+ printf(" basicmcs[");
+ sep = "";
+ for (i = 0; i < IEEE80211_HTRATE_MAXSIZE; i++)
+ if (isset(htinfo->hi_basicmcsset, i)) {
+ for (j = i+1; j < IEEE80211_HTRATE_MAXSIZE; j++)
+ if (isclr(htinfo->hi_basicmcsset, j))
+ break;
+ j--;
+ if (i == j)
+ printf("%s%u", sep, i);
+ else
+ printf("%s%u-%u", sep, i, j);
+ i += j-i;
+ sep = ",";
+ }
+ printf("]>");
+ }
+}
+
+static void
+printathie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_ath_ie *ath =
+ (const struct ieee80211_ath_ie *)ie;
+
+ printf("<");
+ if (ath->ath_capability & ATHEROS_CAP_TURBO_PRIME)
+ printf("DTURBO,");
+ if (ath->ath_capability & ATHEROS_CAP_COMPRESSION)
+ printf("COMP,");
+ if (ath->ath_capability & ATHEROS_CAP_FAST_FRAME)
+ printf("FF,");
+ if (ath->ath_capability & ATHEROS_CAP_XR)
+ printf("XR,");
+ if (ath->ath_capability & ATHEROS_CAP_AR)
+ printf("AR,");
+ if (ath->ath_capability & ATHEROS_CAP_BURST)
+ printf("BURST,");
+ if (ath->ath_capability & ATHEROS_CAP_WME)
+ printf("WME,");
+ if (ath->ath_capability & ATHEROS_CAP_BOOST)
+ printf("BOOST,");
+ printf("0x%x>", LE_READ_2(ath->ath_defkeyix));
+ }
+}
+
+
+static void
+printmeshconf(const char *tag, const uint8_t *ie, size_t ielen, int maxlen)
+{
+#define MATCHOUI(field, oui, string) \
+do { \
+ if (memcmp(field, oui, 4) == 0) \
+ printf("%s", string); \
+} while (0)
+
+ printf("%s", tag);
+ if (verbose) {
+ const struct ieee80211_meshconf_ie *mconf =
+ (const struct ieee80211_meshconf_ie *)ie;
+ printf("<PATH:");
+ if (mconf->conf_pselid == IEEE80211_MESHCONF_PATH_HWMP)
+ printf("HWMP");
+ else
+ printf("UNKNOWN");
+ printf(" LINK:");
+ if (mconf->conf_pmetid == IEEE80211_MESHCONF_METRIC_AIRTIME)
+ printf("AIRTIME");
+ else
+ printf("UNKNOWN");
+ printf(" CONGESTION:");
+ if (mconf->conf_ccid == IEEE80211_MESHCONF_CC_DISABLED)
+ printf("DISABLED");
+ else
+ printf("UNKNOWN");
+ printf(" SYNC:");
+ if (mconf->conf_syncid == IEEE80211_MESHCONF_SYNC_NEIGHOFF)
+ printf("NEIGHOFF");
+ else
+ printf("UNKNOWN");
+ printf(" AUTH:");
+ if (mconf->conf_authid == IEEE80211_MESHCONF_AUTH_DISABLED)
+ printf("DISABLED");
+ else
+ printf("UNKNOWN");
+ printf(" FORM:0x%x CAPS:0x%x>", mconf->conf_form,
+ mconf->conf_cap);
+ }
+#undef MATCHOUI
+}
+
+static const char *
+wpa_cipher(const u_int8_t *sel)
+{
+#define WPA_SEL(x) (((x)<<24)|WPA_OUI)
+ u_int32_t w = LE_READ_4(sel);
+
+ switch (w) {
+ case WPA_SEL(WPA_CSE_NULL):
+ return "NONE";
+ case WPA_SEL(WPA_CSE_WEP40):
+ return "WEP40";
+ case WPA_SEL(WPA_CSE_WEP104):
+ return "WEP104";
+ case WPA_SEL(WPA_CSE_TKIP):
+ return "TKIP";
+ case WPA_SEL(WPA_CSE_CCMP):
+ return "AES-CCMP";
+ }
+ return "?"; /* NB: so 1<< is discarded */
+#undef WPA_SEL
+}
+
+static const char *
+wpa_keymgmt(const u_int8_t *sel)
+{
+#define WPA_SEL(x) (((x)<<24)|WPA_OUI)
+ u_int32_t w = LE_READ_4(sel);
+
+ switch (w) {
+ case WPA_SEL(WPA_ASE_8021X_UNSPEC):
+ return "8021X-UNSPEC";
+ case WPA_SEL(WPA_ASE_8021X_PSK):
+ return "8021X-PSK";
+ case WPA_SEL(WPA_ASE_NONE):
+ return "NONE";
+ }
+ return "?";
+#undef WPA_SEL
+}
+
+static void
+printwpaie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ u_int8_t len = ie[1];
+
+ printf("%s", tag);
+ if (verbose) {
+ const char *sep;
+ int n;
+
+ ie += 6, len -= 4; /* NB: len is payload only */
+
+ printf("<v%u", LE_READ_2(ie));
+ ie += 2, len -= 2;
+
+ printf(" mc:%s", wpa_cipher(ie));
+ ie += 4, len -= 4;
+
+ /* unicast ciphers */
+ n = LE_READ_2(ie);
+ ie += 2, len -= 2;
+ sep = " uc:";
+ for (; n > 0; n--) {
+ printf("%s%s", sep, wpa_cipher(ie));
+ ie += 4, len -= 4;
+ sep = "+";
+ }
+
+ /* key management algorithms */
+ n = LE_READ_2(ie);
+ ie += 2, len -= 2;
+ sep = " km:";
+ for (; n > 0; n--) {
+ printf("%s%s", sep, wpa_keymgmt(ie));
+ ie += 4, len -= 4;
+ sep = "+";
+ }
+
+ if (len > 2) /* optional capabilities */
+ printf(", caps 0x%x", LE_READ_2(ie));
+ printf(">");
+ }
+}
+
+static const char *
+rsn_cipher(const u_int8_t *sel)
+{
+#define RSN_SEL(x) (((x)<<24)|RSN_OUI)
+ u_int32_t w = LE_READ_4(sel);
+
+ switch (w) {
+ case RSN_SEL(RSN_CSE_NULL):
+ return "NONE";
+ case RSN_SEL(RSN_CSE_WEP40):
+ return "WEP40";
+ case RSN_SEL(RSN_CSE_WEP104):
+ return "WEP104";
+ case RSN_SEL(RSN_CSE_TKIP):
+ return "TKIP";
+ case RSN_SEL(RSN_CSE_CCMP):
+ return "AES-CCMP";
+ case RSN_SEL(RSN_CSE_WRAP):
+ return "AES-OCB";
+ }
+ return "?";
+#undef WPA_SEL
+}
+
+static const char *
+rsn_keymgmt(const u_int8_t *sel)
+{
+#define RSN_SEL(x) (((x)<<24)|RSN_OUI)
+ u_int32_t w = LE_READ_4(sel);
+
+ switch (w) {
+ case RSN_SEL(RSN_ASE_8021X_UNSPEC):
+ return "8021X-UNSPEC";
+ case RSN_SEL(RSN_ASE_8021X_PSK):
+ return "8021X-PSK";
+ case RSN_SEL(RSN_ASE_NONE):
+ return "NONE";
+ }
+ return "?";
+#undef RSN_SEL
+}
+
+static void
+printrsnie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose) {
+ const char *sep;
+ int n;
+
+ ie += 2, ielen -= 2;
+
+ printf("<v%u", LE_READ_2(ie));
+ ie += 2, ielen -= 2;
+
+ printf(" mc:%s", rsn_cipher(ie));
+ ie += 4, ielen -= 4;
+
+ /* unicast ciphers */
+ n = LE_READ_2(ie);
+ ie += 2, ielen -= 2;
+ sep = " uc:";
+ for (; n > 0; n--) {
+ printf("%s%s", sep, rsn_cipher(ie));
+ ie += 4, ielen -= 4;
+ sep = "+";
+ }
+
+ /* key management algorithms */
+ n = LE_READ_2(ie);
+ ie += 2, ielen -= 2;
+ sep = " km:";
+ for (; n > 0; n--) {
+ printf("%s%s", sep, rsn_keymgmt(ie));
+ ie += 4, ielen -= 4;
+ sep = "+";
+ }
+
+ if (ielen > 2) /* optional capabilities */
+ printf(", caps 0x%x", LE_READ_2(ie));
+ /* XXXPMKID */
+ printf(">");
+ }
+}
+
+/* XXX move to a public include file */
+#define IEEE80211_WPS_DEV_PASS_ID 0x1012
+#define IEEE80211_WPS_SELECTED_REG 0x1041
+#define IEEE80211_WPS_SETUP_STATE 0x1044
+#define IEEE80211_WPS_UUID_E 0x1047
+#define IEEE80211_WPS_VERSION 0x104a
+
+#define BE_READ_2(p) \
+ ((u_int16_t) \
+ ((((const u_int8_t *)(p))[1] ) | \
+ (((const u_int8_t *)(p))[0] << 8)))
+
+static void
+printwpsie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ u_int8_t len = ie[1];
+
+ printf("%s", tag);
+ if (verbose) {
+ static const char *dev_pass_id[] = {
+ "D", /* Default (PIN) */
+ "U", /* User-specified */
+ "M", /* Machine-specified */
+ "K", /* Rekey */
+ "P", /* PushButton */
+ "R" /* Registrar-specified */
+ };
+ int n;
+
+ ie +=6, len -= 4; /* NB: len is payload only */
+
+ /* WPS IE in Beacon and Probe Resp frames have different fields */
+ printf("<");
+ while (len) {
+ uint16_t tlv_type = BE_READ_2(ie);
+ uint16_t tlv_len = BE_READ_2(ie + 2);
+
+ ie += 4, len -= 4;
+
+ switch (tlv_type) {
+ case IEEE80211_WPS_VERSION:
+ printf("v:%d.%d", *ie >> 4, *ie & 0xf);
+ break;
+ case IEEE80211_WPS_SETUP_STATE:
+ /* Only 1 and 2 are valid */
+ if (*ie == 0 || *ie >= 3)
+ printf(" state:B");
+ else
+ printf(" st:%s", *ie == 1 ? "N" : "C");
+ break;
+ case IEEE80211_WPS_SELECTED_REG:
+ printf(" sel:%s", *ie ? "T" : "F");
+ break;
+ case IEEE80211_WPS_DEV_PASS_ID:
+ n = LE_READ_2(ie);
+ if (n < N(dev_pass_id))
+ printf(" dpi:%s", dev_pass_id[n]);
+ break;
+ case IEEE80211_WPS_UUID_E:
+ printf(" uuid-e:");
+ for (n = 0; n < (tlv_len - 1); n++)
+ printf("%02x-", ie[n]);
+ printf("%02x", ie[n]);
+ break;
+ }
+ ie += tlv_len, len -= tlv_len;
+ }
+ printf(">");
+ }
+#undef N
+}
+
+static void
+printtdmaie(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ printf("%s", tag);
+ if (verbose && ielen >= sizeof(struct ieee80211_tdma_param)) {
+ const struct ieee80211_tdma_param *tdma =
+ (const struct ieee80211_tdma_param *) ie;
+
+ /* XXX tstamp */
+ printf("<v%u slot:%u slotcnt:%u slotlen:%u bintval:%u inuse:0x%x>",
+ tdma->tdma_version, tdma->tdma_slot, tdma->tdma_slotcnt,
+ LE_READ_2(&tdma->tdma_slotlen), tdma->tdma_bintval,
+ tdma->tdma_inuse[0]);
+ }
+}
+
+/*
+ * Copy the ssid string contents into buf, truncating to fit. If the
+ * ssid is entirely printable then just copy intact. Otherwise convert
+ * to hexadecimal. If the result is truncated then replace the last
+ * three characters with "...".
+ */
+static int
+copy_essid(char buf[], size_t bufsize, const u_int8_t *essid, size_t essid_len)
+{
+ const u_int8_t *p;
+ size_t maxlen;
+ int i;
+
+ if (essid_len > bufsize)
+ maxlen = bufsize;
+ else
+ maxlen = essid_len;
+ /* determine printable or not */
+ for (i = 0, p = essid; i < maxlen; i++, p++) {
+ if (*p < ' ' || *p > 0x7e)
+ break;
+ }
+ if (i != maxlen) { /* not printable, print as hex */
+ if (bufsize < 3)
+ return 0;
+ strlcpy(buf, "0x", bufsize);
+ bufsize -= 2;
+ p = essid;
+ for (i = 0; i < maxlen && bufsize >= 2; i++) {
+ sprintf(&buf[2+2*i], "%02x", p[i]);
+ bufsize -= 2;
+ }
+ if (i != essid_len)
+ memcpy(&buf[2+2*i-3], "...", 3);
+ } else { /* printable, truncate as needed */
+ memcpy(buf, essid, maxlen);
+ if (maxlen != essid_len)
+ memcpy(&buf[maxlen-3], "...", 3);
+ }
+ return maxlen;
+}
+
+static void
+printssid(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ char ssid[2*IEEE80211_NWID_LEN+1];
+
+ printf("%s<%.*s>", tag, copy_essid(ssid, maxlen, ie+2, ie[1]), ssid);
+}
+
+static void
+printrates(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ const char *sep;
+ int i;
+
+ printf("%s", tag);
+ sep = "<";
+ for (i = 2; i < ielen; i++) {
+ printf("%s%s%d", sep,
+ ie[i] & IEEE80211_RATE_BASIC ? "B" : "",
+ ie[i] & IEEE80211_RATE_VAL);
+ sep = ",";
+ }
+ printf(">");
+}
+
+static void
+printcountry(const char *tag, const u_int8_t *ie, size_t ielen, int maxlen)
+{
+ const struct ieee80211_country_ie *cie =
+ (const struct ieee80211_country_ie *) ie;
+ int i, nbands, schan, nchan;
+
+ printf("%s<%c%c%c", tag, cie->cc[0], cie->cc[1], cie->cc[2]);
+ nbands = (cie->len - 3) / sizeof(cie->band[0]);
+ for (i = 0; i < nbands; i++) {
+ schan = cie->band[i].schan;
+ nchan = cie->band[i].nchan;
+ if (nchan != 1)
+ printf(" %u-%u,%u", schan, schan + nchan-1,
+ cie->band[i].maxtxpwr);
+ else
+ printf(" %u,%u", schan, cie->band[i].maxtxpwr);
+ }
+ printf(">");
+}
+
+/* unaligned little endian access */
+#define LE_READ_4(p) \
+ ((u_int32_t) \
+ ((((const u_int8_t *)(p))[0] ) | \
+ (((const u_int8_t *)(p))[1] << 8) | \
+ (((const u_int8_t *)(p))[2] << 16) | \
+ (((const u_int8_t *)(p))[3] << 24)))
+
+static __inline int
+iswpaoui(const u_int8_t *frm)
+{
+ return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
+}
+
+static __inline int
+iswmeinfo(const u_int8_t *frm)
+{
+ return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
+ frm[6] == WME_INFO_OUI_SUBTYPE;
+}
+
+static __inline int
+iswmeparam(const u_int8_t *frm)
+{
+ return frm[1] > 5 && LE_READ_4(frm+2) == ((WME_OUI_TYPE<<24)|WME_OUI) &&
+ frm[6] == WME_PARAM_OUI_SUBTYPE;
+}
+
+static __inline int
+isatherosoui(const u_int8_t *frm)
+{
+ return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
+}
+
+static __inline int
+istdmaoui(const uint8_t *frm)
+{
+ return frm[1] > 3 && LE_READ_4(frm+2) == ((TDMA_OUI_TYPE<<24)|TDMA_OUI);
+}
+
+static __inline int
+iswpsoui(const uint8_t *frm)
+{
+ return frm[1] > 3 && LE_READ_4(frm+2) == ((WPS_OUI_TYPE<<24)|WPA_OUI);
+}
+
+static const char *
+iename(int elemid)
+{
+ switch (elemid) {
+ case IEEE80211_ELEMID_FHPARMS: return " FHPARMS";
+ case IEEE80211_ELEMID_CFPARMS: return " CFPARMS";
+ case IEEE80211_ELEMID_TIM: return " TIM";
+ case IEEE80211_ELEMID_IBSSPARMS:return " IBSSPARMS";
+ case IEEE80211_ELEMID_CHALLENGE:return " CHALLENGE";
+ case IEEE80211_ELEMID_PWRCNSTR: return " PWRCNSTR";
+ case IEEE80211_ELEMID_PWRCAP: return " PWRCAP";
+ case IEEE80211_ELEMID_TPCREQ: return " TPCREQ";
+ case IEEE80211_ELEMID_TPCREP: return " TPCREP";
+ case IEEE80211_ELEMID_SUPPCHAN: return " SUPPCHAN";
+ case IEEE80211_ELEMID_CSA: return " CSA";
+ case IEEE80211_ELEMID_MEASREQ: return " MEASREQ";
+ case IEEE80211_ELEMID_MEASREP: return " MEASREP";
+ case IEEE80211_ELEMID_QUIET: return " QUIET";
+ case IEEE80211_ELEMID_IBSSDFS: return " IBSSDFS";
+ case IEEE80211_ELEMID_TPC: return " TPC";
+ case IEEE80211_ELEMID_CCKM: return " CCKM";
+ }
+ return " ???";
+}
+
+static void
+printies(const u_int8_t *vp, int ielen, int maxcols)
+{
+ while (ielen > 0) {
+ switch (vp[0]) {
+ case IEEE80211_ELEMID_SSID:
+ if (verbose)
+ printssid(" SSID", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_RATES:
+ case IEEE80211_ELEMID_XRATES:
+ if (verbose)
+ printrates(vp[0] == IEEE80211_ELEMID_RATES ?
+ " RATES" : " XRATES", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_DSPARMS:
+ if (verbose)
+ printf(" DSPARMS<%u>", vp[2]);
+ break;
+ case IEEE80211_ELEMID_COUNTRY:
+ if (verbose)
+ printcountry(" COUNTRY", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_ERP:
+ if (verbose)
+ printf(" ERP<0x%x>", vp[2]);
+ break;
+ case IEEE80211_ELEMID_VENDOR:
+ if (iswpaoui(vp))
+ printwpaie(" WPA", vp, 2+vp[1], maxcols);
+ else if (iswmeinfo(vp))
+ printwmeinfo(" WME", vp, 2+vp[1], maxcols);
+ else if (iswmeparam(vp))
+ printwmeparam(" WME", vp, 2+vp[1], maxcols);
+ else if (isatherosoui(vp))
+ printathie(" ATH", vp, 2+vp[1], maxcols);
+ else if (iswpsoui(vp))
+ printwpsie(" WPS", vp, 2+vp[1], maxcols);
+ else if (istdmaoui(vp))
+ printtdmaie(" TDMA", vp, 2+vp[1], maxcols);
+ else if (verbose)
+ printie(" VEN", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_RSN:
+ printrsnie(" RSN", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_HTCAP:
+ printhtcap(" HTCAP", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_HTINFO:
+ if (verbose)
+ printhtinfo(" HTINFO", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_MESHID:
+ if (verbose)
+ printssid(" MESHID", vp, 2+vp[1], maxcols);
+ break;
+ case IEEE80211_ELEMID_MESHCONF:
+ printmeshconf(" MESHCONF", vp, 2+vp[1], maxcols);
+ break;
+ default:
+ if (verbose)
+ printie(iename(vp[0]), vp, 2+vp[1], maxcols);
+ break;
+ }
+ ielen -= 2+vp[1];
+ vp += 2+vp[1];
+ }
+}
+
+static void
+printmimo(const struct ieee80211_mimo_info *mi)
+{
+ /* NB: don't muddy display unless there's something to show */
+ if (mi->rssi[0] != 0 || mi->rssi[1] != 0 || mi->rssi[2] != 0) {
+ /* XXX ignore EVM for now */
+ printf(" (rssi %d:%d:%d nf %d:%d:%d)",
+ mi->rssi[0], mi->rssi[1], mi->rssi[2],
+ mi->noise[0], mi->noise[1], mi->noise[2]);
+ }
+}
+
+static void
+list_scan(int s)
+{
+ uint8_t buf[24*1024];
+ char ssid[IEEE80211_NWID_LEN+1];
+ const uint8_t *cp;
+ int len, ssidmax, idlen;
+
+ if (get80211len(s, IEEE80211_IOC_SCAN_RESULTS, buf, sizeof(buf), &len) < 0)
+ errx(1, "unable to get scan results");
+ if (len < sizeof(struct ieee80211req_scan_result))
+ return;
+
+ getchaninfo(s);
+
+ ssidmax = verbose ? IEEE80211_NWID_LEN - 1 : 14;
+ printf("%-*.*s %-17.17s %4s %4s %-7s %3s %4s\n"
+ , ssidmax, ssidmax, "SSID/MESH ID"
+ , "BSSID"
+ , "CHAN"
+ , "RATE"
+ , " S:N"
+ , "INT"
+ , "CAPS"
+ );
+ cp = buf;
+ do {
+ const struct ieee80211req_scan_result *sr;
+ const uint8_t *vp, *idp;
+
+ sr = (const struct ieee80211req_scan_result *) cp;
+ vp = cp + sr->isr_ie_off;
+ if (sr->isr_meshid_len) {
+ idp = vp + sr->isr_ssid_len;
+ idlen = sr->isr_meshid_len;
+ } else {
+ idp = vp;
+ idlen = sr->isr_ssid_len;
+ }
+ printf("%-*.*s %s %3d %3dM %3d:%-3d %3d %-4.4s"
+ , ssidmax
+ , copy_essid(ssid, ssidmax, idp, idlen)
+ , ssid
+ , ether_ntoa((const struct ether_addr *) sr->isr_bssid)
+ , ieee80211_mhz2ieee(sr->isr_freq, sr->isr_flags)
+ , getmaxrate(sr->isr_rates, sr->isr_nrates)
+ , (sr->isr_rssi/2)+sr->isr_noise, sr->isr_noise
+ , sr->isr_intval
+ , getcaps(sr->isr_capinfo)
+ );
+ printies(vp + sr->isr_ssid_len + sr->isr_meshid_len,
+ sr->isr_ie_len, 24);
+ printf("\n");
+ cp += sr->isr_len, len -= sr->isr_len;
+ } while (len >= sizeof(struct ieee80211req_scan_result));
+}
+
+static void
+scan_and_wait(int s)
+{
+ struct ieee80211_scan_req sr;
+ struct ieee80211req ireq;
+ int sroute;
+
+ sroute = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (sroute < 0) {
+ perror("socket(PF_ROUTE,SOCK_RAW)");
+ return;
+ }
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = IEEE80211_IOC_SCAN_REQ;
+
+ memset(&sr, 0, sizeof(sr));
+ sr.sr_flags = IEEE80211_IOC_SCAN_ACTIVE
+ | IEEE80211_IOC_SCAN_NOPICK
+ | IEEE80211_IOC_SCAN_ONCE;
+ sr.sr_duration = IEEE80211_IOC_SCAN_FOREVER;
+ sr.sr_nssid = 0;
+
+ ireq.i_data = &sr;
+ ireq.i_len = sizeof(sr);
+ /* NB: only root can trigger a scan so ignore errors */
+ if (ioctl(s, SIOCS80211, &ireq) >= 0) {
+ char buf[2048];
+ struct if_announcemsghdr *ifan;
+ struct rt_msghdr *rtm;
+
+ do {
+ if (read(sroute, buf, sizeof(buf)) < 0) {
+ perror("read(PF_ROUTE)");
+ break;
+ }
+ rtm = (struct rt_msghdr *) buf;
+ if (rtm->rtm_version != RTM_VERSION)
+ break;
+ ifan = (struct if_announcemsghdr *) rtm;
+ } while (rtm->rtm_type != RTM_IEEE80211 ||
+ ifan->ifan_what != RTM_IEEE80211_SCAN);
+ }
+ close(sroute);
+}
+
+static
+DECL_CMD_FUNC(set80211scan, val, d)
+{
+ scan_and_wait(s);
+ list_scan(s);
+}
+
+static enum ieee80211_opmode get80211opmode(int s);
+
+static int
+gettxseq(const struct ieee80211req_sta_info *si)
+{
+ int i, txseq;
+
+ if ((si->isi_state & IEEE80211_NODE_QOS) == 0)
+ return si->isi_txseqs[0];
+ /* XXX not right but usually what folks want */
+ txseq = 0;
+ for (i = 0; i < IEEE80211_TID_SIZE; i++)
+ if (si->isi_txseqs[i] > txseq)
+ txseq = si->isi_txseqs[i];
+ return txseq;
+}
+
+static int
+getrxseq(const struct ieee80211req_sta_info *si)
+{
+ int i, rxseq;
+
+ if ((si->isi_state & IEEE80211_NODE_QOS) == 0)
+ return si->isi_rxseqs[0];
+ /* XXX not right but usually what folks want */
+ rxseq = 0;
+ for (i = 0; i < IEEE80211_TID_SIZE; i++)
+ if (si->isi_rxseqs[i] > rxseq)
+ rxseq = si->isi_rxseqs[i];
+ return rxseq;
+}
+
+static void
+list_stations(int s)
+{
+ union {
+ struct ieee80211req_sta_req req;
+ uint8_t buf[24*1024];
+ } u;
+ enum ieee80211_opmode opmode = get80211opmode(s);
+ const uint8_t *cp;
+ int len;
+
+ /* broadcast address =>'s get all stations */
+ (void) memset(u.req.is_u.macaddr, 0xff, IEEE80211_ADDR_LEN);
+ if (opmode == IEEE80211_M_STA) {
+ /*
+ * Get information about the associated AP.
+ */
+ (void) get80211(s, IEEE80211_IOC_BSSID,
+ u.req.is_u.macaddr, IEEE80211_ADDR_LEN);
+ }
+ if (get80211len(s, IEEE80211_IOC_STA_INFO, &u, sizeof(u), &len) < 0)
+ errx(1, "unable to get station information");
+ if (len < sizeof(struct ieee80211req_sta_info))
+ return;
+
+ getchaninfo(s);
+
+ if (opmode == IEEE80211_M_MBSS)
+ printf("%-17.17s %4s %5s %5s %7s %4s %4s %4s %6s %6s\n"
+ , "ADDR"
+ , "CHAN"
+ , "LOCAL"
+ , "PEER"
+ , "STATE"
+ , "RATE"
+ , "RSSI"
+ , "IDLE"
+ , "TXSEQ"
+ , "RXSEQ"
+ );
+ else
+ printf("%-17.17s %4s %4s %4s %4s %4s %6s %6s %4s %-7s\n"
+ , "ADDR"
+ , "AID"
+ , "CHAN"
+ , "RATE"
+ , "RSSI"
+ , "IDLE"
+ , "TXSEQ"
+ , "RXSEQ"
+ , "CAPS"
+ , "FLAG"
+ );
+ cp = (const uint8_t *) u.req.info;
+ do {
+ const struct ieee80211req_sta_info *si;
+
+ si = (const struct ieee80211req_sta_info *) cp;
+ if (si->isi_len < sizeof(*si))
+ break;
+ if (opmode == IEEE80211_M_MBSS)
+ printf("%s %4d %5x %5x %7.7s %3dM %4.1f %4d %6d %6d"
+ , ether_ntoa((const struct ether_addr*)
+ si->isi_macaddr)
+ , ieee80211_mhz2ieee(si->isi_freq,
+ si->isi_flags)
+ , si->isi_localid
+ , si->isi_peerid
+ , mesh_linkstate_string(si->isi_peerstate)
+ , si->isi_txmbps/2
+ , si->isi_rssi/2.
+ , si->isi_inact
+ , gettxseq(si)
+ , getrxseq(si)
+ );
+ else
+ printf("%s %4u %4d %3dM %4.1f %4d %6d %6d %-4.4s %-7.7s"
+ , ether_ntoa((const struct ether_addr*)
+ si->isi_macaddr)
+ , IEEE80211_AID(si->isi_associd)
+ , ieee80211_mhz2ieee(si->isi_freq,
+ si->isi_flags)
+ , si->isi_txmbps/2
+ , si->isi_rssi/2.
+ , si->isi_inact
+ , gettxseq(si)
+ , getrxseq(si)
+ , getcaps(si->isi_capinfo)
+ , getflags(si->isi_state)
+ );
+ printies(cp + si->isi_ie_off, si->isi_ie_len, 24);
+ printmimo(&si->isi_mimo);
+ printf("\n");
+ cp += si->isi_len, len -= si->isi_len;
+ } while (len >= sizeof(struct ieee80211req_sta_info));
+}
+
+static const char *
+mesh_linkstate_string(uint8_t state)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ static const char *state_names[] = {
+ [0] = "IDLE",
+ [1] = "OPEN-TX",
+ [2] = "OPEN-RX",
+ [3] = "CONF-RX",
+ [4] = "ESTAB",
+ [5] = "HOLDING",
+ };
+
+ if (state >= N(state_names)) {
+ static char buf[10];
+ snprintf(buf, sizeof(buf), "#%u", state);
+ return buf;
+ } else
+ return state_names[state];
+#undef N
+}
+
+static const char *
+get_chaninfo(const struct ieee80211_channel *c, int precise,
+ char buf[], size_t bsize)
+{
+ buf[0] = '\0';
+ if (IEEE80211_IS_CHAN_FHSS(c))
+ strlcat(buf, " FHSS", bsize);
+ if (IEEE80211_IS_CHAN_A(c))
+ strlcat(buf, " 11a", bsize);
+ else if (IEEE80211_IS_CHAN_ANYG(c))
+ strlcat(buf, " 11g", bsize);
+ else if (IEEE80211_IS_CHAN_B(c))
+ strlcat(buf, " 11b", bsize);
+ if (IEEE80211_IS_CHAN_HALF(c))
+ strlcat(buf, "/10MHz", bsize);
+ if (IEEE80211_IS_CHAN_QUARTER(c))
+ strlcat(buf, "/5MHz", bsize);
+ if (IEEE80211_IS_CHAN_TURBO(c))
+ strlcat(buf, " Turbo", bsize);
+ if (precise) {
+ if (IEEE80211_IS_CHAN_HT20(c))
+ strlcat(buf, " ht/20", bsize);
+ else if (IEEE80211_IS_CHAN_HT40D(c))
+ strlcat(buf, " ht/40-", bsize);
+ else if (IEEE80211_IS_CHAN_HT40U(c))
+ strlcat(buf, " ht/40+", bsize);
+ } else {
+ if (IEEE80211_IS_CHAN_HT(c))
+ strlcat(buf, " ht", bsize);
+ }
+ return buf;
+}
+
+static void
+print_chaninfo(const struct ieee80211_channel *c, int verb)
+{
+ char buf[14];
+
+ printf("Channel %3u : %u%c MHz%-14.14s",
+ ieee80211_mhz2ieee(c->ic_freq, c->ic_flags), c->ic_freq,
+ IEEE80211_IS_CHAN_PASSIVE(c) ? '*' : ' ',
+ get_chaninfo(c, verb, buf, sizeof(buf)));
+}
+
+static int
+chanpref(const struct ieee80211_channel *c)
+{
+ if (IEEE80211_IS_CHAN_HT40(c))
+ return 40;
+ if (IEEE80211_IS_CHAN_HT20(c))
+ return 30;
+ if (IEEE80211_IS_CHAN_HALF(c))
+ return 10;
+ if (IEEE80211_IS_CHAN_QUARTER(c))
+ return 5;
+ if (IEEE80211_IS_CHAN_TURBO(c))
+ return 25;
+ if (IEEE80211_IS_CHAN_A(c))
+ return 20;
+ if (IEEE80211_IS_CHAN_G(c))
+ return 20;
+ if (IEEE80211_IS_CHAN_B(c))
+ return 15;
+ if (IEEE80211_IS_CHAN_PUREG(c))
+ return 15;
+ return 0;
+}
+
+static void
+print_channels(int s, const struct ieee80211req_chaninfo *chans,
+ int allchans, int verb)
+{
+ struct ieee80211req_chaninfo *achans;
+ uint8_t reported[IEEE80211_CHAN_BYTES];
+ const struct ieee80211_channel *c;
+ int i, half;
+
+ achans = malloc(IEEE80211_CHANINFO_SPACE(chans));
+ if (achans == NULL)
+ errx(1, "no space for active channel list");
+ achans->ic_nchans = 0;
+ memset(reported, 0, sizeof(reported));
+ if (!allchans) {
+ struct ieee80211req_chanlist active;
+
+ if (get80211(s, IEEE80211_IOC_CHANLIST, &active, sizeof(active)) < 0)
+ errx(1, "unable to get active channel list");
+ for (i = 0; i < chans->ic_nchans; i++) {
+ c = &chans->ic_chans[i];
+ if (!isset(active.ic_channels, c->ic_ieee))
+ continue;
+ /*
+ * Suppress compatible duplicates unless
+ * verbose. The kernel gives us it's
+ * complete channel list which has separate
+ * entries for 11g/11b and 11a/turbo.
+ */
+ if (isset(reported, c->ic_ieee) && !verb) {
+ /* XXX we assume duplicates are adjacent */
+ achans->ic_chans[achans->ic_nchans-1] = *c;
+ } else {
+ achans->ic_chans[achans->ic_nchans++] = *c;
+ setbit(reported, c->ic_ieee);
+ }
+ }
+ } else {
+ for (i = 0; i < chans->ic_nchans; i++) {
+ c = &chans->ic_chans[i];
+ /* suppress duplicates as above */
+ if (isset(reported, c->ic_ieee) && !verb) {
+ /* XXX we assume duplicates are adjacent */
+ struct ieee80211_channel *a =
+ &achans->ic_chans[achans->ic_nchans-1];
+ if (chanpref(c) > chanpref(a))
+ *a = *c;
+ } else {
+ achans->ic_chans[achans->ic_nchans++] = *c;
+ setbit(reported, c->ic_ieee);
+ }
+ }
+ }
+ half = achans->ic_nchans / 2;
+ if (achans->ic_nchans % 2)
+ half++;
+
+ for (i = 0; i < achans->ic_nchans / 2; i++) {
+ print_chaninfo(&achans->ic_chans[i], verb);
+ print_chaninfo(&achans->ic_chans[half+i], verb);
+ printf("\n");
+ }
+ if (achans->ic_nchans % 2) {
+ print_chaninfo(&achans->ic_chans[i], verb);
+ printf("\n");
+ }
+ free(achans);
+}
+
+static void
+list_channels(int s, int allchans)
+{
+ getchaninfo(s);
+ print_channels(s, chaninfo, allchans, verbose);
+}
+
+static void
+print_txpow(const struct ieee80211_channel *c)
+{
+ printf("Channel %3u : %u MHz %3.1f reg %2d ",
+ c->ic_ieee, c->ic_freq,
+ c->ic_maxpower/2., c->ic_maxregpower);
+}
+
+static void
+print_txpow_verbose(const struct ieee80211_channel *c)
+{
+ print_chaninfo(c, 1);
+ printf("min %4.1f dBm max %3.1f dBm reg %2d dBm",
+ c->ic_minpower/2., c->ic_maxpower/2., c->ic_maxregpower);
+ /* indicate where regulatory cap limits power use */
+ if (c->ic_maxpower > 2*c->ic_maxregpower)
+ printf(" <");
+}
+
+static void
+list_txpow(int s)
+{
+ struct ieee80211req_chaninfo *achans;
+ uint8_t reported[IEEE80211_CHAN_BYTES];
+ struct ieee80211_channel *c, *prev;
+ int i, half;
+
+ getchaninfo(s);
+ achans = malloc(IEEE80211_CHANINFO_SPACE(chaninfo));
+ if (achans == NULL)
+ errx(1, "no space for active channel list");
+ achans->ic_nchans = 0;
+ memset(reported, 0, sizeof(reported));
+ for (i = 0; i < chaninfo->ic_nchans; i++) {
+ c = &chaninfo->ic_chans[i];
+ /* suppress duplicates as above */
+ if (isset(reported, c->ic_ieee) && !verbose) {
+ /* XXX we assume duplicates are adjacent */
+ prev = &achans->ic_chans[achans->ic_nchans-1];
+ /* display highest power on channel */
+ if (c->ic_maxpower > prev->ic_maxpower)
+ *prev = *c;
+ } else {
+ achans->ic_chans[achans->ic_nchans++] = *c;
+ setbit(reported, c->ic_ieee);
+ }
+ }
+ if (!verbose) {
+ half = achans->ic_nchans / 2;
+ if (achans->ic_nchans % 2)
+ half++;
+
+ for (i = 0; i < achans->ic_nchans / 2; i++) {
+ print_txpow(&achans->ic_chans[i]);
+ print_txpow(&achans->ic_chans[half+i]);
+ printf("\n");
+ }
+ if (achans->ic_nchans % 2) {
+ print_txpow(&achans->ic_chans[i]);
+ printf("\n");
+ }
+ } else {
+ for (i = 0; i < achans->ic_nchans; i++) {
+ print_txpow_verbose(&achans->ic_chans[i]);
+ printf("\n");
+ }
+ }
+ free(achans);
+}
+
+static void
+list_keys(int s)
+{
+}
+
+#define IEEE80211_C_BITS \
+ "\20\1STA\002803ENCAP\7FF\10TURBOP\11IBSS\12PMGT" \
+ "\13HOSTAP\14AHDEMO\15SWRETRY\16TXPMGT\17SHSLOT\20SHPREAMBLE" \
+ "\21MONITOR\22DFS\23MBSS\30WPA1\31WPA2\32BURST\33WME\34WDS\36BGSCAN" \
+ "\37TXFRAG\40TDMA"
+
+static void
+list_capabilities(int s)
+{
+ struct ieee80211_devcaps_req *dc;
+
+ if (verbose)
+ dc = malloc(IEEE80211_DEVCAPS_SIZE(MAXCHAN));
+ else
+ dc = malloc(IEEE80211_DEVCAPS_SIZE(1));
+ if (dc == NULL)
+ errx(1, "no space for device capabilities");
+ dc->dc_chaninfo.ic_nchans = verbose ? MAXCHAN : 1;
+ getdevcaps(s, dc);
+ printb("drivercaps", dc->dc_drivercaps, IEEE80211_C_BITS);
+ if (dc->dc_cryptocaps != 0 || verbose) {
+ putchar('\n');
+ printb("cryptocaps", dc->dc_cryptocaps, IEEE80211_CRYPTO_BITS);
+ }
+ if (dc->dc_htcaps != 0 || verbose) {
+ putchar('\n');
+ printb("htcaps", dc->dc_htcaps, IEEE80211_HTCAP_BITS);
+ }
+ putchar('\n');
+ if (verbose) {
+ chaninfo = &dc->dc_chaninfo; /* XXX */
+ print_channels(s, &dc->dc_chaninfo, 1/*allchans*/, verbose);
+ }
+ free(dc);
+}
+
+static int
+get80211wme(int s, int param, int ac, int *val)
+{
+ struct ieee80211req ireq;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = param;
+ ireq.i_len = ac;
+ if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ warn("cannot get WME parameter %d, ac %d%s",
+ param, ac & IEEE80211_WMEPARAM_VAL,
+ ac & IEEE80211_WMEPARAM_BSS ? " (BSS)" : "");
+ return -1;
+ }
+ *val = ireq.i_val;
+ return 0;
+}
+
+static void
+list_wme_aci(int s, const char *tag, int ac)
+{
+ int val;
+
+ printf("\t%s", tag);
+
+ /* show WME BSS parameters */
+ if (get80211wme(s, IEEE80211_IOC_WME_CWMIN, ac, &val) != -1)
+ printf(" cwmin %2u", val);
+ if (get80211wme(s, IEEE80211_IOC_WME_CWMAX, ac, &val) != -1)
+ printf(" cwmax %2u", val);
+ if (get80211wme(s, IEEE80211_IOC_WME_AIFS, ac, &val) != -1)
+ printf(" aifs %2u", val);
+ if (get80211wme(s, IEEE80211_IOC_WME_TXOPLIMIT, ac, &val) != -1)
+ printf(" txopLimit %3u", val);
+ if (get80211wme(s, IEEE80211_IOC_WME_ACM, ac, &val) != -1) {
+ if (val)
+ printf(" acm");
+ else if (verbose)
+ printf(" -acm");
+ }
+ /* !BSS only */
+ if ((ac & IEEE80211_WMEPARAM_BSS) == 0) {
+ if (get80211wme(s, IEEE80211_IOC_WME_ACKPOLICY, ac, &val) != -1) {
+ if (!val)
+ printf(" -ack");
+ else if (verbose)
+ printf(" ack");
+ }
+ }
+ printf("\n");
+}
+
+static void
+list_wme(int s)
+{
+ static const char *acnames[] = { "AC_BE", "AC_BK", "AC_VI", "AC_VO" };
+ int ac;
+
+ if (verbose) {
+ /* display both BSS and local settings */
+ for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++) {
+ again:
+ if (ac & IEEE80211_WMEPARAM_BSS)
+ list_wme_aci(s, " ", ac);
+ else
+ list_wme_aci(s, acnames[ac], ac);
+ if ((ac & IEEE80211_WMEPARAM_BSS) == 0) {
+ ac |= IEEE80211_WMEPARAM_BSS;
+ goto again;
+ } else
+ ac &= ~IEEE80211_WMEPARAM_BSS;
+ }
+ } else {
+ /* display only channel settings */
+ for (ac = WME_AC_BE; ac <= WME_AC_VO; ac++)
+ list_wme_aci(s, acnames[ac], ac);
+ }
+}
+
+static void
+list_roam(int s)
+{
+ const struct ieee80211_roamparam *rp;
+ int mode;
+
+ getroam(s);
+ for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) {
+ rp = &roamparams.params[mode];
+ if (rp->rssi == 0 && rp->rate == 0)
+ continue;
+ if (mode == IEEE80211_MODE_11NA || mode == IEEE80211_MODE_11NG) {
+ if (rp->rssi & 1)
+ LINE_CHECK("roam:%-7.7s rssi %2u.5dBm MCS %2u ",
+ modename[mode], rp->rssi/2,
+ rp->rate &~ IEEE80211_RATE_MCS);
+ else
+ LINE_CHECK("roam:%-7.7s rssi %4udBm MCS %2u ",
+ modename[mode], rp->rssi/2,
+ rp->rate &~ IEEE80211_RATE_MCS);
+ } else {
+ if (rp->rssi & 1)
+ LINE_CHECK("roam:%-7.7s rssi %2u.5dBm rate %2u Mb/s",
+ modename[mode], rp->rssi/2, rp->rate/2);
+ else
+ LINE_CHECK("roam:%-7.7s rssi %4udBm rate %2u Mb/s",
+ modename[mode], rp->rssi/2, rp->rate/2);
+ }
+ }
+}
+
+static void
+list_txparams(int s)
+{
+ const struct ieee80211_txparam *tp;
+ int mode;
+
+ gettxparams(s);
+ for (mode = IEEE80211_MODE_11A; mode < IEEE80211_MODE_MAX; mode++) {
+ tp = &txparams.params[mode];
+ if (tp->mgmtrate == 0 && tp->mcastrate == 0)
+ continue;
+ if (mode == IEEE80211_MODE_11NA || mode == IEEE80211_MODE_11NG) {
+ if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
+ LINE_CHECK("%-7.7s ucast NONE mgmt %2u MCS "
+ "mcast %2u MCS maxretry %u",
+ modename[mode],
+ tp->mgmtrate &~ IEEE80211_RATE_MCS,
+ tp->mcastrate &~ IEEE80211_RATE_MCS,
+ tp->maxretry);
+ else
+ LINE_CHECK("%-7.7s ucast %2u MCS mgmt %2u MCS "
+ "mcast %2u MCS maxretry %u",
+ modename[mode],
+ tp->ucastrate &~ IEEE80211_RATE_MCS,
+ tp->mgmtrate &~ IEEE80211_RATE_MCS,
+ tp->mcastrate &~ IEEE80211_RATE_MCS,
+ tp->maxretry);
+ } else {
+ if (tp->ucastrate == IEEE80211_FIXED_RATE_NONE)
+ LINE_CHECK("%-7.7s ucast NONE mgmt %2u Mb/s "
+ "mcast %2u Mb/s maxretry %u",
+ modename[mode],
+ tp->mgmtrate/2,
+ tp->mcastrate/2, tp->maxretry);
+ else
+ LINE_CHECK("%-7.7s ucast %2u Mb/s mgmt %2u Mb/s "
+ "mcast %2u Mb/s maxretry %u",
+ modename[mode],
+ tp->ucastrate/2, tp->mgmtrate/2,
+ tp->mcastrate/2, tp->maxretry);
+ }
+ }
+}
+
+static void
+printpolicy(int policy)
+{
+ switch (policy) {
+ case IEEE80211_MACCMD_POLICY_OPEN:
+ printf("policy: open\n");
+ break;
+ case IEEE80211_MACCMD_POLICY_ALLOW:
+ printf("policy: allow\n");
+ break;
+ case IEEE80211_MACCMD_POLICY_DENY:
+ printf("policy: deny\n");
+ break;
+ case IEEE80211_MACCMD_POLICY_RADIUS:
+ printf("policy: radius\n");
+ break;
+ default:
+ printf("policy: unknown (%u)\n", policy);
+ break;
+ }
+}
+
+static void
+list_mac(int s)
+{
+ struct ieee80211req ireq;
+ struct ieee80211req_maclist *acllist;
+ int i, nacls, policy, len;
+ uint8_t *data;
+ char c;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name)); /* XXX ?? */
+ ireq.i_type = IEEE80211_IOC_MACCMD;
+ ireq.i_val = IEEE80211_MACCMD_POLICY;
+ if (ioctl(s, SIOCG80211, &ireq) < 0) {
+ if (errno == EINVAL) {
+ printf("No acl policy loaded\n");
+ return;
+ }
+ err(1, "unable to get mac policy");
+ }
+ policy = ireq.i_val;
+ if (policy == IEEE80211_MACCMD_POLICY_OPEN) {
+ c = '*';
+ } else if (policy == IEEE80211_MACCMD_POLICY_ALLOW) {
+ c = '+';
+ } else if (policy == IEEE80211_MACCMD_POLICY_DENY) {
+ c = '-';
+ } else if (policy == IEEE80211_MACCMD_POLICY_RADIUS) {
+ c = 'r'; /* NB: should never have entries */
+ } else {
+ printf("policy: unknown (%u)\n", policy);
+ c = '?';
+ }
+ if (verbose || c == '?')
+ printpolicy(policy);
+
+ ireq.i_val = IEEE80211_MACCMD_LIST;
+ ireq.i_len = 0;
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ err(1, "unable to get mac acl list size");
+ if (ireq.i_len == 0) { /* NB: no acls */
+ if (!(verbose || c == '?'))
+ printpolicy(policy);
+ return;
+ }
+ len = ireq.i_len;
+
+ data = malloc(len);
+ if (data == NULL)
+ err(1, "out of memory for acl list");
+
+ ireq.i_data = data;
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ err(1, "unable to get mac acl list");
+ nacls = len / sizeof(*acllist);
+ acllist = (struct ieee80211req_maclist *) data;
+ for (i = 0; i < nacls; i++)
+ printf("%c%s\n", c, ether_ntoa(
+ (const struct ether_addr *) acllist[i].ml_macaddr));
+ free(data);
+}
+
+static void
+print_regdomain(const struct ieee80211_regdomain *reg, int verb)
+{
+ if ((reg->regdomain != 0 &&
+ reg->regdomain != reg->country) || verb) {
+ const struct regdomain *rd =
+ lib80211_regdomain_findbysku(getregdata(), reg->regdomain);
+ if (rd == NULL)
+ LINE_CHECK("regdomain %d", reg->regdomain);
+ else
+ LINE_CHECK("regdomain %s", rd->name);
+ }
+ if (reg->country != 0 || verb) {
+ const struct country *cc =
+ lib80211_country_findbycc(getregdata(), reg->country);
+ if (cc == NULL)
+ LINE_CHECK("country %d", reg->country);
+ else
+ LINE_CHECK("country %s", cc->isoname);
+ }
+ if (reg->location == 'I')
+ LINE_CHECK("indoor");
+ else if (reg->location == 'O')
+ LINE_CHECK("outdoor");
+ else if (verb)
+ LINE_CHECK("anywhere");
+ if (reg->ecm)
+ LINE_CHECK("ecm");
+ else if (verb)
+ LINE_CHECK("-ecm");
+}
+
+static void
+list_regdomain(int s, int channelsalso)
+{
+ getregdomain(s);
+ if (channelsalso) {
+ getchaninfo(s);
+ spacer = ':';
+ print_regdomain(&regdomain, 1);
+ LINE_BREAK();
+ print_channels(s, chaninfo, 1/*allchans*/, 1/*verbose*/);
+ } else
+ print_regdomain(&regdomain, verbose);
+}
+
+static void
+list_mesh(int s)
+{
+ struct ieee80211req ireq;
+ struct ieee80211req_mesh_route routes[128];
+ struct ieee80211req_mesh_route *rt;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = IEEE80211_IOC_MESH_RTCMD;
+ ireq.i_val = IEEE80211_MESH_RTCMD_LIST;
+ ireq.i_data = &routes;
+ ireq.i_len = sizeof(routes);
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ err(1, "unable to get the Mesh routing table");
+
+ printf("%-17.17s %-17.17s %4s %4s %4s %6s %s\n"
+ , "DEST"
+ , "NEXT HOP"
+ , "HOPS"
+ , "METRIC"
+ , "LIFETIME"
+ , "MSEQ"
+ , "FLAGS");
+
+ for (rt = &routes[0]; rt - &routes[0] < ireq.i_len / sizeof(*rt); rt++){
+ printf("%s ",
+ ether_ntoa((const struct ether_addr *)rt->imr_dest));
+ printf("%s %4u %4u %6u %6u %c%c\n",
+ ether_ntoa((const struct ether_addr *)rt->imr_nexthop),
+ rt->imr_nhops, rt->imr_metric, rt->imr_lifetime,
+ rt->imr_lastmseq,
+ (rt->imr_flags & IEEE80211_MESHRT_FLAGS_VALID) ?
+ 'V' : '!',
+ (rt->imr_flags & IEEE80211_MESHRT_FLAGS_PROXY) ?
+ 'P' : ' ');
+ }
+}
+
+static
+DECL_CMD_FUNC(set80211list, arg, d)
+{
+#define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0)
+
+ LINE_INIT('\t');
+
+ if (iseq(arg, "sta"))
+ list_stations(s);
+ else if (iseq(arg, "scan") || iseq(arg, "ap"))
+ list_scan(s);
+ else if (iseq(arg, "chan") || iseq(arg, "freq"))
+ list_channels(s, 1);
+ else if (iseq(arg, "active"))
+ list_channels(s, 0);
+ else if (iseq(arg, "keys"))
+ list_keys(s);
+ else if (iseq(arg, "caps"))
+ list_capabilities(s);
+ else if (iseq(arg, "wme") || iseq(arg, "wmm"))
+ list_wme(s);
+ else if (iseq(arg, "mac"))
+ list_mac(s);
+ else if (iseq(arg, "txpow"))
+ list_txpow(s);
+ else if (iseq(arg, "roam"))
+ list_roam(s);
+ else if (iseq(arg, "txparam") || iseq(arg, "txparm"))
+ list_txparams(s);
+ else if (iseq(arg, "regdomain"))
+ list_regdomain(s, 1);
+ else if (iseq(arg, "countries"))
+ list_countries();
+ else if (iseq(arg, "mesh"))
+ list_mesh(s);
+ else
+ errx(1, "Don't know how to list %s for %s", arg, name);
+ LINE_BREAK();
+#undef iseq
+}
+
+static enum ieee80211_opmode
+get80211opmode(int s)
+{
+ struct ifmediareq ifmr;
+
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
+
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) >= 0) {
+ if (ifmr.ifm_current & IFM_IEEE80211_ADHOC) {
+ if (ifmr.ifm_current & IFM_FLAG0)
+ return IEEE80211_M_AHDEMO;
+ else
+ return IEEE80211_M_IBSS;
+ }
+ if (ifmr.ifm_current & IFM_IEEE80211_HOSTAP)
+ return IEEE80211_M_HOSTAP;
+ if (ifmr.ifm_current & IFM_IEEE80211_MONITOR)
+ return IEEE80211_M_MONITOR;
+ if (ifmr.ifm_current & IFM_IEEE80211_MBSS)
+ return IEEE80211_M_MBSS;
+ }
+ return IEEE80211_M_STA;
+}
+
+#if 0
+static void
+printcipher(int s, struct ieee80211req *ireq, int keylenop)
+{
+ switch (ireq->i_val) {
+ case IEEE80211_CIPHER_WEP:
+ ireq->i_type = keylenop;
+ if (ioctl(s, SIOCG80211, ireq) != -1)
+ printf("WEP-%s",
+ ireq->i_len <= 5 ? "40" :
+ ireq->i_len <= 13 ? "104" : "128");
+ else
+ printf("WEP");
+ break;
+ case IEEE80211_CIPHER_TKIP:
+ printf("TKIP");
+ break;
+ case IEEE80211_CIPHER_AES_OCB:
+ printf("AES-OCB");
+ break;
+ case IEEE80211_CIPHER_AES_CCM:
+ printf("AES-CCM");
+ break;
+ case IEEE80211_CIPHER_CKIP:
+ printf("CKIP");
+ break;
+ case IEEE80211_CIPHER_NONE:
+ printf("NONE");
+ break;
+ default:
+ printf("UNKNOWN (0x%x)", ireq->i_val);
+ break;
+ }
+}
+#endif
+
+static void
+printkey(const struct ieee80211req_key *ik)
+{
+ static const uint8_t zerodata[IEEE80211_KEYBUF_SIZE];
+ int keylen = ik->ik_keylen;
+ int printcontents;
+
+ printcontents = printkeys &&
+ (memcmp(ik->ik_keydata, zerodata, keylen) != 0 || verbose);
+ if (printcontents)
+ LINE_BREAK();
+ switch (ik->ik_type) {
+ case IEEE80211_CIPHER_WEP:
+ /* compatibility */
+ LINE_CHECK("wepkey %u:%s", ik->ik_keyix+1,
+ keylen <= 5 ? "40-bit" :
+ keylen <= 13 ? "104-bit" : "128-bit");
+ break;
+ case IEEE80211_CIPHER_TKIP:
+ if (keylen > 128/8)
+ keylen -= 128/8; /* ignore MIC for now */
+ LINE_CHECK("TKIP %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ break;
+ case IEEE80211_CIPHER_AES_OCB:
+ LINE_CHECK("AES-OCB %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ break;
+ case IEEE80211_CIPHER_AES_CCM:
+ LINE_CHECK("AES-CCM %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ break;
+ case IEEE80211_CIPHER_CKIP:
+ LINE_CHECK("CKIP %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ break;
+ case IEEE80211_CIPHER_NONE:
+ LINE_CHECK("NULL %u:%u-bit", ik->ik_keyix+1, 8*keylen);
+ break;
+ default:
+ LINE_CHECK("UNKNOWN (0x%x) %u:%u-bit",
+ ik->ik_type, ik->ik_keyix+1, 8*keylen);
+ break;
+ }
+ if (printcontents) {
+ int i;
+
+ printf(" <");
+ for (i = 0; i < keylen; i++)
+ printf("%02x", ik->ik_keydata[i]);
+ printf(">");
+ if (ik->ik_type != IEEE80211_CIPHER_WEP &&
+ (ik->ik_keyrsc != 0 || verbose))
+ printf(" rsc %ju", (uintmax_t)ik->ik_keyrsc);
+ if (ik->ik_type != IEEE80211_CIPHER_WEP &&
+ (ik->ik_keytsc != 0 || verbose))
+ printf(" tsc %ju", (uintmax_t)ik->ik_keytsc);
+ if (ik->ik_flags != 0 && verbose) {
+ const char *sep = " ";
+
+ if (ik->ik_flags & IEEE80211_KEY_XMIT)
+ printf("%stx", sep), sep = "+";
+ if (ik->ik_flags & IEEE80211_KEY_RECV)
+ printf("%srx", sep), sep = "+";
+ if (ik->ik_flags & IEEE80211_KEY_DEFAULT)
+ printf("%sdef", sep), sep = "+";
+ }
+ LINE_BREAK();
+ }
+}
+
+static void
+printrate(const char *tag, int v, int defrate, int defmcs)
+{
+ if ((v & IEEE80211_RATE_MCS) == 0) {
+ if (v != defrate) {
+ if (v & 1)
+ LINE_CHECK("%s %d.5", tag, v/2);
+ else
+ LINE_CHECK("%s %d", tag, v/2);
+ }
+ } else {
+ if (v != defmcs)
+ LINE_CHECK("%s %d", tag, v &~ 0x80);
+ }
+}
+
+static int
+getid(int s, int ix, void *data, size_t len, int *plen, int mesh)
+{
+ struct ieee80211req ireq;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = (!mesh) ? IEEE80211_IOC_SSID : IEEE80211_IOC_MESH_ID;
+ ireq.i_val = ix;
+ ireq.i_data = data;
+ ireq.i_len = len;
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ return -1;
+ *plen = ireq.i_len;
+ return 0;
+}
+
+static void
+ieee80211_status(int s)
+{
+ static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
+ enum ieee80211_opmode opmode = get80211opmode(s);
+ int i, num, wpa, wme, bgscan, bgscaninterval, val, len, wepmode;
+ uint8_t data[32];
+ const struct ieee80211_channel *c;
+ const struct ieee80211_roamparam *rp;
+ const struct ieee80211_txparam *tp;
+
+ if (getid(s, -1, data, sizeof(data), &len, 0) < 0) {
+ /* If we can't get the SSID, this isn't an 802.11 device. */
+ return;
+ }
+
+ /*
+ * Invalidate cached state so printing status for multiple
+ * if's doesn't reuse the first interfaces' cached state.
+ */
+ gotcurchan = 0;
+ gotroam = 0;
+ gottxparams = 0;
+ gothtconf = 0;
+ gotregdomain = 0;
+
+ printf("\t");
+ if (opmode == IEEE80211_M_MBSS) {
+ printf("meshid ");
+ getid(s, 0, data, sizeof(data), &len, 1);
+ print_string(data, len);
+ } else {
+ if (get80211val(s, IEEE80211_IOC_NUMSSIDS, &num) < 0)
+ num = 0;
+ printf("ssid ");
+ if (num > 1) {
+ for (i = 0; i < num; i++) {
+ if (getid(s, i, data, sizeof(data), &len, 0) >= 0 && len > 0) {
+ printf(" %d:", i + 1);
+ print_string(data, len);
+ }
+ }
+ } else
+ print_string(data, len);
+ }
+ c = getcurchan(s);
+ if (c->ic_freq != IEEE80211_CHAN_ANY) {
+ char buf[14];
+ printf(" channel %d (%u MHz%s)", c->ic_ieee, c->ic_freq,
+ get_chaninfo(c, 1, buf, sizeof(buf)));
+ } else if (verbose)
+ printf(" channel UNDEF");
+
+ if (get80211(s, IEEE80211_IOC_BSSID, data, IEEE80211_ADDR_LEN) >= 0 &&
+ (memcmp(data, zerobssid, sizeof(zerobssid)) != 0 || verbose))
+ printf(" bssid %s", ether_ntoa((struct ether_addr *)data));
+
+ if (get80211len(s, IEEE80211_IOC_STATIONNAME, data, sizeof(data), &len) != -1) {
+ printf("\n\tstationname ");
+ print_string(data, len);
+ }
+
+ spacer = ' '; /* force first break */
+ LINE_BREAK();
+
+ list_regdomain(s, 0);
+
+ wpa = 0;
+ if (get80211val(s, IEEE80211_IOC_AUTHMODE, &val) != -1) {
+ switch (val) {
+ case IEEE80211_AUTH_NONE:
+ LINE_CHECK("authmode NONE");
+ break;
+ case IEEE80211_AUTH_OPEN:
+ LINE_CHECK("authmode OPEN");
+ break;
+ case IEEE80211_AUTH_SHARED:
+ LINE_CHECK("authmode SHARED");
+ break;
+ case IEEE80211_AUTH_8021X:
+ LINE_CHECK("authmode 802.1x");
+ break;
+ case IEEE80211_AUTH_WPA:
+ if (get80211val(s, IEEE80211_IOC_WPA, &wpa) < 0)
+ wpa = 1; /* default to WPA1 */
+ switch (wpa) {
+ case 2:
+ LINE_CHECK("authmode WPA2/802.11i");
+ break;
+ case 3:
+ LINE_CHECK("authmode WPA1+WPA2/802.11i");
+ break;
+ default:
+ LINE_CHECK("authmode WPA");
+ break;
+ }
+ break;
+ case IEEE80211_AUTH_AUTO:
+ LINE_CHECK("authmode AUTO");
+ break;
+ default:
+ LINE_CHECK("authmode UNKNOWN (0x%x)", val);
+ break;
+ }
+ }
+
+ if (wpa || verbose) {
+ if (get80211val(s, IEEE80211_IOC_WPS, &val) != -1) {
+ if (val)
+ LINE_CHECK("wps");
+ else if (verbose)
+ LINE_CHECK("-wps");
+ }
+ if (get80211val(s, IEEE80211_IOC_TSN, &val) != -1) {
+ if (val)
+ LINE_CHECK("tsn");
+ else if (verbose)
+ LINE_CHECK("-tsn");
+ }
+ if (ioctl(s, IEEE80211_IOC_COUNTERMEASURES, &val) != -1) {
+ if (val)
+ LINE_CHECK("countermeasures");
+ else if (verbose)
+ LINE_CHECK("-countermeasures");
+ }
+#if 0
+ /* XXX not interesting with WPA done in user space */
+ ireq.i_type = IEEE80211_IOC_KEYMGTALGS;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ }
+
+ ireq.i_type = IEEE80211_IOC_MCASTCIPHER;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ LINE_CHECK("mcastcipher ");
+ printcipher(s, &ireq, IEEE80211_IOC_MCASTKEYLEN);
+ spacer = ' ';
+ }
+
+ ireq.i_type = IEEE80211_IOC_UCASTCIPHER;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ LINE_CHECK("ucastcipher ");
+ printcipher(s, &ireq, IEEE80211_IOC_UCASTKEYLEN);
+ }
+
+ if (wpa & 2) {
+ ireq.i_type = IEEE80211_IOC_RSNCAPS;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ LINE_CHECK("RSN caps 0x%x", ireq.i_val);
+ spacer = ' ';
+ }
+ }
+
+ ireq.i_type = IEEE80211_IOC_UCASTCIPHERS;
+ if (ioctl(s, SIOCG80211, &ireq) != -1) {
+ }
+#endif
+ }
+
+ if (get80211val(s, IEEE80211_IOC_WEP, &wepmode) != -1 &&
+ wepmode != IEEE80211_WEP_NOSUP) {
+ int firstkey;
+
+ switch (wepmode) {
+ case IEEE80211_WEP_OFF:
+ LINE_CHECK("privacy OFF");
+ break;
+ case IEEE80211_WEP_ON:
+ LINE_CHECK("privacy ON");
+ break;
+ case IEEE80211_WEP_MIXED:
+ LINE_CHECK("privacy MIXED");
+ break;
+ default:
+ LINE_CHECK("privacy UNKNOWN (0x%x)", wepmode);
+ break;
+ }
+
+ /*
+ * If we get here then we've got WEP support so we need
+ * to print WEP status.
+ */
+
+ if (get80211val(s, IEEE80211_IOC_WEPTXKEY, &val) < 0) {
+ warn("WEP support, but no tx key!");
+ goto end;
+ }
+ if (val != -1)
+ LINE_CHECK("deftxkey %d", val+1);
+ else if (wepmode != IEEE80211_WEP_OFF || verbose)
+ LINE_CHECK("deftxkey UNDEF");
+
+ if (get80211val(s, IEEE80211_IOC_NUMWEPKEYS, &num) < 0) {
+ warn("WEP support, but no NUMWEPKEYS support!");
+ goto end;
+ }
+
+ firstkey = 1;
+ for (i = 0; i < num; i++) {
+ struct ieee80211req_key ik;
+
+ memset(&ik, 0, sizeof(ik));
+ ik.ik_keyix = i;
+ if (get80211(s, IEEE80211_IOC_WPAKEY, &ik, sizeof(ik)) < 0) {
+ warn("WEP support, but can get keys!");
+ goto end;
+ }
+ if (ik.ik_keylen != 0) {
+ if (verbose)
+ LINE_BREAK();
+ printkey(&ik);
+ firstkey = 0;
+ }
+ }
+end:
+ ;
+ }
+
+ if (get80211val(s, IEEE80211_IOC_POWERSAVE, &val) != -1 &&
+ val != IEEE80211_POWERSAVE_NOSUP ) {
+ if (val != IEEE80211_POWERSAVE_OFF || verbose) {
+ switch (val) {
+ case IEEE80211_POWERSAVE_OFF:
+ LINE_CHECK("powersavemode OFF");
+ break;
+ case IEEE80211_POWERSAVE_CAM:
+ LINE_CHECK("powersavemode CAM");
+ break;
+ case IEEE80211_POWERSAVE_PSP:
+ LINE_CHECK("powersavemode PSP");
+ break;
+ case IEEE80211_POWERSAVE_PSP_CAM:
+ LINE_CHECK("powersavemode PSP-CAM");
+ break;
+ }
+ if (get80211val(s, IEEE80211_IOC_POWERSAVESLEEP, &val) != -1)
+ LINE_CHECK("powersavesleep %d", val);
+ }
+ }
+
+ if (get80211val(s, IEEE80211_IOC_TXPOWER, &val) != -1) {
+ if (val & 1)
+ LINE_CHECK("txpower %d.5", val/2);
+ else
+ LINE_CHECK("txpower %d", val/2);
+ }
+ if (verbose) {
+ if (get80211val(s, IEEE80211_IOC_TXPOWMAX, &val) != -1)
+ LINE_CHECK("txpowmax %.1f", val/2.);
+ }
+
+ if (get80211val(s, IEEE80211_IOC_DOTD, &val) != -1) {
+ if (val)
+ LINE_CHECK("dotd");
+ else if (verbose)
+ LINE_CHECK("-dotd");
+ }
+
+ if (get80211val(s, IEEE80211_IOC_RTSTHRESHOLD, &val) != -1) {
+ if (val != IEEE80211_RTS_MAX || verbose)
+ LINE_CHECK("rtsthreshold %d", val);
+ }
+
+ if (get80211val(s, IEEE80211_IOC_FRAGTHRESHOLD, &val) != -1) {
+ if (val != IEEE80211_FRAG_MAX || verbose)
+ LINE_CHECK("fragthreshold %d", val);
+ }
+ if (opmode == IEEE80211_M_STA || verbose) {
+ if (get80211val(s, IEEE80211_IOC_BMISSTHRESHOLD, &val) != -1) {
+ if (val != IEEE80211_HWBMISS_MAX || verbose)
+ LINE_CHECK("bmiss %d", val);
+ }
+ }
+
+ if (!verbose) {
+ gettxparams(s);
+ tp = &txparams.params[chan2mode(c)];
+ printrate("ucastrate", tp->ucastrate,
+ IEEE80211_FIXED_RATE_NONE, IEEE80211_FIXED_RATE_NONE);
+ printrate("mcastrate", tp->mcastrate, 2*1,
+ IEEE80211_RATE_MCS|0);
+ printrate("mgmtrate", tp->mgmtrate, 2*1,
+ IEEE80211_RATE_MCS|0);
+ if (tp->maxretry != 6) /* XXX */
+ LINE_CHECK("maxretry %d", tp->maxretry);
+ } else {
+ LINE_BREAK();
+ list_txparams(s);
+ }
+
+ bgscaninterval = -1;
+ (void) get80211val(s, IEEE80211_IOC_BGSCAN_INTERVAL, &bgscaninterval);
+
+ if (get80211val(s, IEEE80211_IOC_SCANVALID, &val) != -1) {
+ if (val != bgscaninterval || verbose)
+ LINE_CHECK("scanvalid %u", val);
+ }
+
+ bgscan = 0;
+ if (get80211val(s, IEEE80211_IOC_BGSCAN, &bgscan) != -1) {
+ if (bgscan)
+ LINE_CHECK("bgscan");
+ else if (verbose)
+ LINE_CHECK("-bgscan");
+ }
+ if (bgscan || verbose) {
+ if (bgscaninterval != -1)
+ LINE_CHECK("bgscanintvl %u", bgscaninterval);
+ if (get80211val(s, IEEE80211_IOC_BGSCAN_IDLE, &val) != -1)
+ LINE_CHECK("bgscanidle %u", val);
+ if (!verbose) {
+ getroam(s);
+ rp = &roamparams.params[chan2mode(c)];
+ if (rp->rssi & 1)
+ LINE_CHECK("roam:rssi %u.5", rp->rssi/2);
+ else
+ LINE_CHECK("roam:rssi %u", rp->rssi/2);
+ LINE_CHECK("roam:rate %u", rp->rate/2);
+ } else {
+ LINE_BREAK();
+ list_roam(s);
+ LINE_BREAK();
+ }
+ }
+
+ if (IEEE80211_IS_CHAN_ANYG(c) || verbose) {
+ if (get80211val(s, IEEE80211_IOC_PUREG, &val) != -1) {
+ if (val)
+ LINE_CHECK("pureg");
+ else if (verbose)
+ LINE_CHECK("-pureg");
+ }
+ if (get80211val(s, IEEE80211_IOC_PROTMODE, &val) != -1) {
+ switch (val) {
+ case IEEE80211_PROTMODE_OFF:
+ LINE_CHECK("protmode OFF");
+ break;
+ case IEEE80211_PROTMODE_CTS:
+ LINE_CHECK("protmode CTS");
+ break;
+ case IEEE80211_PROTMODE_RTSCTS:
+ LINE_CHECK("protmode RTSCTS");
+ break;
+ default:
+ LINE_CHECK("protmode UNKNOWN (0x%x)", val);
+ break;
+ }
+ }
+ }
+
+ if (IEEE80211_IS_CHAN_HT(c) || verbose) {
+ gethtconf(s);
+ switch (htconf & 3) {
+ case 0:
+ case 2:
+ LINE_CHECK("-ht");
+ break;
+ case 1:
+ LINE_CHECK("ht20");
+ break;
+ case 3:
+ if (verbose)
+ LINE_CHECK("ht");
+ break;
+ }
+ if (get80211val(s, IEEE80211_IOC_HTCOMPAT, &val) != -1) {
+ if (!val)
+ LINE_CHECK("-htcompat");
+ else if (verbose)
+ LINE_CHECK("htcompat");
+ }
+ if (get80211val(s, IEEE80211_IOC_AMPDU, &val) != -1) {
+ switch (val) {
+ case 0:
+ LINE_CHECK("-ampdu");
+ break;
+ case 1:
+ LINE_CHECK("ampdutx -ampdurx");
+ break;
+ case 2:
+ LINE_CHECK("-ampdutx ampdurx");
+ break;
+ case 3:
+ if (verbose)
+ LINE_CHECK("ampdu");
+ break;
+ }
+ }
+ if (get80211val(s, IEEE80211_IOC_AMPDU_LIMIT, &val) != -1) {
+ switch (val) {
+ case IEEE80211_HTCAP_MAXRXAMPDU_8K:
+ LINE_CHECK("ampdulimit 8k");
+ break;
+ case IEEE80211_HTCAP_MAXRXAMPDU_16K:
+ LINE_CHECK("ampdulimit 16k");
+ break;
+ case IEEE80211_HTCAP_MAXRXAMPDU_32K:
+ LINE_CHECK("ampdulimit 32k");
+ break;
+ case IEEE80211_HTCAP_MAXRXAMPDU_64K:
+ LINE_CHECK("ampdulimit 64k");
+ break;
+ }
+ }
+ if (get80211val(s, IEEE80211_IOC_AMPDU_DENSITY, &val) != -1) {
+ switch (val) {
+ case IEEE80211_HTCAP_MPDUDENSITY_NA:
+ if (verbose)
+ LINE_CHECK("ampdudensity NA");
+ break;
+ case IEEE80211_HTCAP_MPDUDENSITY_025:
+ LINE_CHECK("ampdudensity .25");
+ break;
+ case IEEE80211_HTCAP_MPDUDENSITY_05:
+ LINE_CHECK("ampdudensity .5");
+ break;
+ case IEEE80211_HTCAP_MPDUDENSITY_1:
+ LINE_CHECK("ampdudensity 1");
+ break;
+ case IEEE80211_HTCAP_MPDUDENSITY_2:
+ LINE_CHECK("ampdudensity 2");
+ break;
+ case IEEE80211_HTCAP_MPDUDENSITY_4:
+ LINE_CHECK("ampdudensity 4");
+ break;
+ case IEEE80211_HTCAP_MPDUDENSITY_8:
+ LINE_CHECK("ampdudensity 8");
+ break;
+ case IEEE80211_HTCAP_MPDUDENSITY_16:
+ LINE_CHECK("ampdudensity 16");
+ break;
+ }
+ }
+ if (get80211val(s, IEEE80211_IOC_AMSDU, &val) != -1) {
+ switch (val) {
+ case 0:
+ LINE_CHECK("-amsdu");
+ break;
+ case 1:
+ LINE_CHECK("amsdutx -amsdurx");
+ break;
+ case 2:
+ LINE_CHECK("-amsdutx amsdurx");
+ break;
+ case 3:
+ if (verbose)
+ LINE_CHECK("amsdu");
+ break;
+ }
+ }
+ /* XXX amsdu limit */
+ if (get80211val(s, IEEE80211_IOC_SHORTGI, &val) != -1) {
+ if (val)
+ LINE_CHECK("shortgi");
+ else if (verbose)
+ LINE_CHECK("-shortgi");
+ }
+ if (get80211val(s, IEEE80211_IOC_HTPROTMODE, &val) != -1) {
+ if (val == IEEE80211_PROTMODE_OFF)
+ LINE_CHECK("htprotmode OFF");
+ else if (val != IEEE80211_PROTMODE_RTSCTS)
+ LINE_CHECK("htprotmode UNKNOWN (0x%x)", val);
+ else if (verbose)
+ LINE_CHECK("htprotmode RTSCTS");
+ }
+ if (get80211val(s, IEEE80211_IOC_PUREN, &val) != -1) {
+ if (val)
+ LINE_CHECK("puren");
+ else if (verbose)
+ LINE_CHECK("-puren");
+ }
+ if (get80211val(s, IEEE80211_IOC_SMPS, &val) != -1) {
+ if (val == IEEE80211_HTCAP_SMPS_DYNAMIC)
+ LINE_CHECK("smpsdyn");
+ else if (val == IEEE80211_HTCAP_SMPS_ENA)
+ LINE_CHECK("smps");
+ else if (verbose)
+ LINE_CHECK("-smps");
+ }
+ if (get80211val(s, IEEE80211_IOC_RIFS, &val) != -1) {
+ if (val)
+ LINE_CHECK("rifs");
+ else if (verbose)
+ LINE_CHECK("-rifs");
+ }
+ }
+
+ if (get80211val(s, IEEE80211_IOC_WME, &wme) != -1) {
+ if (wme)
+ LINE_CHECK("wme");
+ else if (verbose)
+ LINE_CHECK("-wme");
+ } else
+ wme = 0;
+
+ if (get80211val(s, IEEE80211_IOC_BURST, &val) != -1) {
+ if (val)
+ LINE_CHECK("burst");
+ else if (verbose)
+ LINE_CHECK("-burst");
+ }
+
+ if (get80211val(s, IEEE80211_IOC_FF, &val) != -1) {
+ if (val)
+ LINE_CHECK("ff");
+ else if (verbose)
+ LINE_CHECK("-ff");
+ }
+ if (get80211val(s, IEEE80211_IOC_TURBOP, &val) != -1) {
+ if (val)
+ LINE_CHECK("dturbo");
+ else if (verbose)
+ LINE_CHECK("-dturbo");
+ }
+ if (get80211val(s, IEEE80211_IOC_DWDS, &val) != -1) {
+ if (val)
+ LINE_CHECK("dwds");
+ else if (verbose)
+ LINE_CHECK("-dwds");
+ }
+
+ if (opmode == IEEE80211_M_HOSTAP) {
+ if (get80211val(s, IEEE80211_IOC_HIDESSID, &val) != -1) {
+ if (val)
+ LINE_CHECK("hidessid");
+ else if (verbose)
+ LINE_CHECK("-hidessid");
+ }
+ if (get80211val(s, IEEE80211_IOC_APBRIDGE, &val) != -1) {
+ if (!val)
+ LINE_CHECK("-apbridge");
+ else if (verbose)
+ LINE_CHECK("apbridge");
+ }
+ if (get80211val(s, IEEE80211_IOC_DTIM_PERIOD, &val) != -1)
+ LINE_CHECK("dtimperiod %u", val);
+
+ if (get80211val(s, IEEE80211_IOC_DOTH, &val) != -1) {
+ if (!val)
+ LINE_CHECK("-doth");
+ else if (verbose)
+ LINE_CHECK("doth");
+ }
+ if (get80211val(s, IEEE80211_IOC_DFS, &val) != -1) {
+ if (!val)
+ LINE_CHECK("-dfs");
+ else if (verbose)
+ LINE_CHECK("dfs");
+ }
+ if (get80211val(s, IEEE80211_IOC_INACTIVITY, &val) != -1) {
+ if (!val)
+ LINE_CHECK("-inact");
+ else if (verbose)
+ LINE_CHECK("inact");
+ }
+ } else {
+ if (get80211val(s, IEEE80211_IOC_ROAMING, &val) != -1) {
+ if (val != IEEE80211_ROAMING_AUTO || verbose) {
+ switch (val) {
+ case IEEE80211_ROAMING_DEVICE:
+ LINE_CHECK("roaming DEVICE");
+ break;
+ case IEEE80211_ROAMING_AUTO:
+ LINE_CHECK("roaming AUTO");
+ break;
+ case IEEE80211_ROAMING_MANUAL:
+ LINE_CHECK("roaming MANUAL");
+ break;
+ default:
+ LINE_CHECK("roaming UNKNOWN (0x%x)",
+ val);
+ break;
+ }
+ }
+ }
+ }
+
+ if (opmode == IEEE80211_M_AHDEMO) {
+ if (get80211val(s, IEEE80211_IOC_TDMA_SLOT, &val) != -1)
+ LINE_CHECK("tdmaslot %u", val);
+ if (get80211val(s, IEEE80211_IOC_TDMA_SLOTCNT, &val) != -1)
+ LINE_CHECK("tdmaslotcnt %u", val);
+ if (get80211val(s, IEEE80211_IOC_TDMA_SLOTLEN, &val) != -1)
+ LINE_CHECK("tdmaslotlen %u", val);
+ if (get80211val(s, IEEE80211_IOC_TDMA_BINTERVAL, &val) != -1)
+ LINE_CHECK("tdmabintval %u", val);
+ } else if (get80211val(s, IEEE80211_IOC_BEACON_INTERVAL, &val) != -1) {
+ /* XXX default define not visible */
+ if (val != 100 || verbose)
+ LINE_CHECK("bintval %u", val);
+ }
+
+ if (wme && verbose) {
+ LINE_BREAK();
+ list_wme(s);
+ }
+
+ if (opmode == IEEE80211_M_MBSS) {
+ if (get80211val(s, IEEE80211_IOC_MESH_TTL, &val) != -1) {
+ LINE_CHECK("meshttl %u", val);
+ }
+ if (get80211val(s, IEEE80211_IOC_MESH_AP, &val) != -1) {
+ if (val)
+ LINE_CHECK("meshpeering");
+ else
+ LINE_CHECK("-meshpeering");
+ }
+ if (get80211val(s, IEEE80211_IOC_MESH_FWRD, &val) != -1) {
+ if (val)
+ LINE_CHECK("meshforward");
+ else
+ LINE_CHECK("-meshforward");
+ }
+ if (get80211len(s, IEEE80211_IOC_MESH_PR_METRIC, data, 12,
+ &len) != -1) {
+ data[len] = '\0';
+ LINE_CHECK("meshmetric %s", data);
+ }
+ if (get80211len(s, IEEE80211_IOC_MESH_PR_PATH, data, 12,
+ &len) != -1) {
+ data[len] = '\0';
+ LINE_CHECK("meshpath %s", data);
+ }
+ if (get80211val(s, IEEE80211_IOC_HWMP_ROOTMODE, &val) != -1) {
+ switch (val) {
+ case IEEE80211_HWMP_ROOTMODE_DISABLED:
+ LINE_CHECK("hwmprootmode DISABLED");
+ break;
+ case IEEE80211_HWMP_ROOTMODE_NORMAL:
+ LINE_CHECK("hwmprootmode NORMAL");
+ break;
+ case IEEE80211_HWMP_ROOTMODE_PROACTIVE:
+ LINE_CHECK("hwmprootmode PROACTIVE");
+ break;
+ case IEEE80211_HWMP_ROOTMODE_RANN:
+ LINE_CHECK("hwmprootmode RANN");
+ break;
+ default:
+ LINE_CHECK("hwmprootmode UNKNOWN(%d)", val);
+ break;
+ }
+ }
+ if (get80211val(s, IEEE80211_IOC_HWMP_MAXHOPS, &val) != -1) {
+ LINE_CHECK("hwmpmaxhops %u", val);
+ }
+ }
+
+ LINE_BREAK();
+}
+
+static int
+get80211(int s, int type, void *data, int len)
+{
+ struct ieee80211req ireq;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = type;
+ ireq.i_data = data;
+ ireq.i_len = len;
+ return ioctl(s, SIOCG80211, &ireq);
+}
+
+static int
+get80211len(int s, int type, void *data, int len, int *plen)
+{
+ struct ieee80211req ireq;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = type;
+ ireq.i_len = len;
+ assert(ireq.i_len == len); /* NB: check for 16-bit truncation */
+ ireq.i_data = data;
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ return -1;
+ *plen = ireq.i_len;
+ return 0;
+}
+
+static int
+get80211val(int s, int type, int *val)
+{
+ struct ieee80211req ireq;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = type;
+ if (ioctl(s, SIOCG80211, &ireq) < 0)
+ return -1;
+ *val = ireq.i_val;
+ return 0;
+}
+
+static void
+set80211(int s, int type, int val, int len, void *data)
+{
+ struct ieee80211req ireq;
+
+ (void) memset(&ireq, 0, sizeof(ireq));
+ (void) strncpy(ireq.i_name, name, sizeof(ireq.i_name));
+ ireq.i_type = type;
+ ireq.i_val = val;
+ ireq.i_len = len;
+ assert(ireq.i_len == len); /* NB: check for 16-bit truncation */
+ ireq.i_data = data;
+ if (ioctl(s, SIOCS80211, &ireq) < 0)
+ err(1, "SIOCS80211");
+}
+
+static const char *
+get_string(const char *val, const char *sep, u_int8_t *buf, int *lenp)
+{
+ int len;
+ int hexstr;
+ u_int8_t *p;
+
+ len = *lenp;
+ p = buf;
+ hexstr = (val[0] == '0' && tolower((u_char)val[1]) == 'x');
+ if (hexstr)
+ val += 2;
+ for (;;) {
+ if (*val == '\0')
+ break;
+ if (sep != NULL && strchr(sep, *val) != NULL) {
+ val++;
+ break;
+ }
+ if (hexstr) {
+ if (!isxdigit((u_char)val[0])) {
+ warnx("bad hexadecimal digits");
+ return NULL;
+ }
+ if (!isxdigit((u_char)val[1])) {
+ warnx("odd count hexadecimal digits");
+ return NULL;
+ }
+ }
+ if (p >= buf + len) {
+ if (hexstr)
+ warnx("hexadecimal digits too long");
+ else
+ warnx("string too long");
+ return NULL;
+ }
+ if (hexstr) {
+#define tohex(x) (isdigit(x) ? (x) - '0' : tolower(x) - 'a' + 10)
+ *p++ = (tohex((u_char)val[0]) << 4) |
+ tohex((u_char)val[1]);
+#undef tohex
+ val += 2;
+ } else
+ *p++ = *val++;
+ }
+ len = p - buf;
+ /* The string "-" is treated as the empty string. */
+ if (!hexstr && len == 1 && buf[0] == '-') {
+ len = 0;
+ memset(buf, 0, *lenp);
+ } else if (len < *lenp)
+ memset(p, 0, *lenp - len);
+ *lenp = len;
+ return val;
+}
+
+static void
+print_string(const u_int8_t *buf, int len)
+{
+ int i;
+ int hasspc;
+
+ i = 0;
+ hasspc = 0;
+ for (; i < len; i++) {
+ if (!isprint(buf[i]) && buf[i] != '\0')
+ break;
+ if (isspace(buf[i]))
+ hasspc++;
+ }
+ if (i == len) {
+ if (hasspc || len == 0 || buf[0] == '\0')
+ printf("\"%.*s\"", len, buf);
+ else
+ printf("%.*s", len, buf);
+ } else {
+ printf("0x");
+ for (i = 0; i < len; i++)
+ printf("%02x", buf[i]);
+ }
+}
+
+/*
+ * Virtual AP cloning support.
+ */
+static struct ieee80211_clone_params params = {
+ .icp_opmode = IEEE80211_M_STA, /* default to station mode */
+};
+
+static void
+wlan_create(int s, struct ifreq *ifr)
+{
+ static const uint8_t zerobssid[IEEE80211_ADDR_LEN];
+
+ if (params.icp_parent[0] == '\0')
+ errx(1, "must specify a parent device (wlandev) when creating "
+ "a wlan device");
+ if (params.icp_opmode == IEEE80211_M_WDS &&
+ memcmp(params.icp_bssid, zerobssid, sizeof(zerobssid)) == 0)
+ errx(1, "no bssid specified for WDS (use wlanbssid)");
+ ifr->ifr_data = (caddr_t) &params;
+ if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
+ err(1, "SIOCIFCREATE2");
+}
+
+static
+DECL_CMD_FUNC(set80211clone_wlandev, arg, d)
+{
+ strlcpy(params.icp_parent, arg, IFNAMSIZ);
+}
+
+static
+DECL_CMD_FUNC(set80211clone_wlanbssid, arg, d)
+{
+ const struct ether_addr *ea;
+
+ ea = ether_aton(arg);
+ if (ea == NULL)
+ errx(1, "%s: cannot parse bssid", arg);
+ memcpy(params.icp_bssid, ea->octet, IEEE80211_ADDR_LEN);
+}
+
+static
+DECL_CMD_FUNC(set80211clone_wlanaddr, arg, d)
+{
+ const struct ether_addr *ea;
+
+ ea = ether_aton(arg);
+ if (ea == NULL)
+ errx(1, "%s: cannot parse addres", arg);
+ memcpy(params.icp_macaddr, ea->octet, IEEE80211_ADDR_LEN);
+ params.icp_flags |= IEEE80211_CLONE_MACADDR;
+}
+
+static
+DECL_CMD_FUNC(set80211clone_wlanmode, arg, d)
+{
+#define iseq(a,b) (strncasecmp(a,b,sizeof(b)-1) == 0)
+ if (iseq(arg, "sta"))
+ params.icp_opmode = IEEE80211_M_STA;
+ else if (iseq(arg, "ahdemo") || iseq(arg, "adhoc-demo"))
+ params.icp_opmode = IEEE80211_M_AHDEMO;
+ else if (iseq(arg, "ibss") || iseq(arg, "adhoc"))
+ params.icp_opmode = IEEE80211_M_IBSS;
+ else if (iseq(arg, "ap") || iseq(arg, "host"))
+ params.icp_opmode = IEEE80211_M_HOSTAP;
+ else if (iseq(arg, "wds"))
+ params.icp_opmode = IEEE80211_M_WDS;
+ else if (iseq(arg, "monitor"))
+ params.icp_opmode = IEEE80211_M_MONITOR;
+ else if (iseq(arg, "tdma")) {
+ params.icp_opmode = IEEE80211_M_AHDEMO;
+ params.icp_flags |= IEEE80211_CLONE_TDMA;
+ } else if (iseq(arg, "mesh") || iseq(arg, "mp")) /* mesh point */
+ params.icp_opmode = IEEE80211_M_MBSS;
+ else
+ errx(1, "Don't know to create %s for %s", arg, name);
+#undef iseq
+}
+
+static void
+set80211clone_beacons(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ /* NB: inverted sense */
+ if (d)
+ params.icp_flags &= ~IEEE80211_CLONE_NOBEACONS;
+ else
+ params.icp_flags |= IEEE80211_CLONE_NOBEACONS;
+}
+
+static void
+set80211clone_bssid(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ if (d)
+ params.icp_flags |= IEEE80211_CLONE_BSSID;
+ else
+ params.icp_flags &= ~IEEE80211_CLONE_BSSID;
+}
+
+static void
+set80211clone_wdslegacy(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ if (d)
+ params.icp_flags |= IEEE80211_CLONE_WDSLEGACY;
+ else
+ params.icp_flags &= ~IEEE80211_CLONE_WDSLEGACY;
+}
+
+static struct cmd ieee80211_cmds[] = {
+ DEF_CMD_ARG("ssid", set80211ssid),
+ DEF_CMD_ARG("nwid", set80211ssid),
+ DEF_CMD_ARG("meshid", set80211meshid),
+ DEF_CMD_ARG("stationname", set80211stationname),
+ DEF_CMD_ARG("station", set80211stationname), /* BSD/OS */
+ DEF_CMD_ARG("channel", set80211channel),
+ DEF_CMD_ARG("authmode", set80211authmode),
+ DEF_CMD_ARG("powersavemode", set80211powersavemode),
+ DEF_CMD("powersave", 1, set80211powersave),
+ DEF_CMD("-powersave", 0, set80211powersave),
+ DEF_CMD_ARG("powersavesleep", set80211powersavesleep),
+ DEF_CMD_ARG("wepmode", set80211wepmode),
+ DEF_CMD("wep", 1, set80211wep),
+ DEF_CMD("-wep", 0, set80211wep),
+ DEF_CMD_ARG("deftxkey", set80211weptxkey),
+ DEF_CMD_ARG("weptxkey", set80211weptxkey),
+ DEF_CMD_ARG("wepkey", set80211wepkey),
+ DEF_CMD_ARG("nwkey", set80211nwkey), /* NetBSD */
+ DEF_CMD("-nwkey", 0, set80211wep), /* NetBSD */
+ DEF_CMD_ARG("rtsthreshold", set80211rtsthreshold),
+ DEF_CMD_ARG("protmode", set80211protmode),
+ DEF_CMD_ARG("txpower", set80211txpower),
+ DEF_CMD_ARG("roaming", set80211roaming),
+ DEF_CMD("wme", 1, set80211wme),
+ DEF_CMD("-wme", 0, set80211wme),
+ DEF_CMD("wmm", 1, set80211wme),
+ DEF_CMD("-wmm", 0, set80211wme),
+ DEF_CMD("hidessid", 1, set80211hidessid),
+ DEF_CMD("-hidessid", 0, set80211hidessid),
+ DEF_CMD("apbridge", 1, set80211apbridge),
+ DEF_CMD("-apbridge", 0, set80211apbridge),
+ DEF_CMD_ARG("chanlist", set80211chanlist),
+ DEF_CMD_ARG("bssid", set80211bssid),
+ DEF_CMD_ARG("ap", set80211bssid),
+ DEF_CMD("scan", 0, set80211scan),
+ DEF_CMD_ARG("list", set80211list),
+ DEF_CMD_ARG2("cwmin", set80211cwmin),
+ DEF_CMD_ARG2("cwmax", set80211cwmax),
+ DEF_CMD_ARG2("aifs", set80211aifs),
+ DEF_CMD_ARG2("txoplimit", set80211txoplimit),
+ DEF_CMD_ARG("acm", set80211acm),
+ DEF_CMD_ARG("-acm", set80211noacm),
+ DEF_CMD_ARG("ack", set80211ackpolicy),
+ DEF_CMD_ARG("-ack", set80211noackpolicy),
+ DEF_CMD_ARG2("bss:cwmin", set80211bsscwmin),
+ DEF_CMD_ARG2("bss:cwmax", set80211bsscwmax),
+ DEF_CMD_ARG2("bss:aifs", set80211bssaifs),
+ DEF_CMD_ARG2("bss:txoplimit", set80211bsstxoplimit),
+ DEF_CMD_ARG("dtimperiod", set80211dtimperiod),
+ DEF_CMD_ARG("bintval", set80211bintval),
+ DEF_CMD("mac:open", IEEE80211_MACCMD_POLICY_OPEN, set80211maccmd),
+ DEF_CMD("mac:allow", IEEE80211_MACCMD_POLICY_ALLOW, set80211maccmd),
+ DEF_CMD("mac:deny", IEEE80211_MACCMD_POLICY_DENY, set80211maccmd),
+ DEF_CMD("mac:radius", IEEE80211_MACCMD_POLICY_RADIUS, set80211maccmd),
+ DEF_CMD("mac:flush", IEEE80211_MACCMD_FLUSH, set80211maccmd),
+ DEF_CMD("mac:detach", IEEE80211_MACCMD_DETACH, set80211maccmd),
+ DEF_CMD_ARG("mac:add", set80211addmac),
+ DEF_CMD_ARG("mac:del", set80211delmac),
+ DEF_CMD_ARG("mac:kick", set80211kickmac),
+ DEF_CMD("pureg", 1, set80211pureg),
+ DEF_CMD("-pureg", 0, set80211pureg),
+ DEF_CMD("ff", 1, set80211fastframes),
+ DEF_CMD("-ff", 0, set80211fastframes),
+ DEF_CMD("dturbo", 1, set80211dturbo),
+ DEF_CMD("-dturbo", 0, set80211dturbo),
+ DEF_CMD("bgscan", 1, set80211bgscan),
+ DEF_CMD("-bgscan", 0, set80211bgscan),
+ DEF_CMD_ARG("bgscanidle", set80211bgscanidle),
+ DEF_CMD_ARG("bgscanintvl", set80211bgscanintvl),
+ DEF_CMD_ARG("scanvalid", set80211scanvalid),
+ DEF_CMD_ARG("roam:rssi", set80211roamrssi),
+ DEF_CMD_ARG("roam:rate", set80211roamrate),
+ DEF_CMD_ARG("mcastrate", set80211mcastrate),
+ DEF_CMD_ARG("ucastrate", set80211ucastrate),
+ DEF_CMD_ARG("mgtrate", set80211mgtrate),
+ DEF_CMD_ARG("mgmtrate", set80211mgtrate),
+ DEF_CMD_ARG("maxretry", set80211maxretry),
+ DEF_CMD_ARG("fragthreshold", set80211fragthreshold),
+ DEF_CMD("burst", 1, set80211burst),
+ DEF_CMD("-burst", 0, set80211burst),
+ DEF_CMD_ARG("bmiss", set80211bmissthreshold),
+ DEF_CMD_ARG("bmissthreshold", set80211bmissthreshold),
+ DEF_CMD("shortgi", 1, set80211shortgi),
+ DEF_CMD("-shortgi", 0, set80211shortgi),
+ DEF_CMD("ampdurx", 2, set80211ampdu),
+ DEF_CMD("-ampdurx", -2, set80211ampdu),
+ DEF_CMD("ampdutx", 1, set80211ampdu),
+ DEF_CMD("-ampdutx", -1, set80211ampdu),
+ DEF_CMD("ampdu", 3, set80211ampdu), /* NB: tx+rx */
+ DEF_CMD("-ampdu", -3, set80211ampdu),
+ DEF_CMD_ARG("ampdulimit", set80211ampdulimit),
+ DEF_CMD_ARG("ampdudensity", set80211ampdudensity),
+ DEF_CMD("amsdurx", 2, set80211amsdu),
+ DEF_CMD("-amsdurx", -2, set80211amsdu),
+ DEF_CMD("amsdutx", 1, set80211amsdu),
+ DEF_CMD("-amsdutx", -1, set80211amsdu),
+ DEF_CMD("amsdu", 3, set80211amsdu), /* NB: tx+rx */
+ DEF_CMD("-amsdu", -3, set80211amsdu),
+ DEF_CMD_ARG("amsdulimit", set80211amsdulimit),
+ DEF_CMD("puren", 1, set80211puren),
+ DEF_CMD("-puren", 0, set80211puren),
+ DEF_CMD("doth", 1, set80211doth),
+ DEF_CMD("-doth", 0, set80211doth),
+ DEF_CMD("dfs", 1, set80211dfs),
+ DEF_CMD("-dfs", 0, set80211dfs),
+ DEF_CMD("htcompat", 1, set80211htcompat),
+ DEF_CMD("-htcompat", 0, set80211htcompat),
+ DEF_CMD("dwds", 1, set80211dwds),
+ DEF_CMD("-dwds", 0, set80211dwds),
+ DEF_CMD("inact", 1, set80211inact),
+ DEF_CMD("-inact", 0, set80211inact),
+ DEF_CMD("tsn", 1, set80211tsn),
+ DEF_CMD("-tsn", 0, set80211tsn),
+ DEF_CMD_ARG("regdomain", set80211regdomain),
+ DEF_CMD_ARG("country", set80211country),
+ DEF_CMD("indoor", 'I', set80211location),
+ DEF_CMD("-indoor", 'O', set80211location),
+ DEF_CMD("outdoor", 'O', set80211location),
+ DEF_CMD("-outdoor", 'I', set80211location),
+ DEF_CMD("anywhere", ' ', set80211location),
+ DEF_CMD("ecm", 1, set80211ecm),
+ DEF_CMD("-ecm", 0, set80211ecm),
+ DEF_CMD("dotd", 1, set80211dotd),
+ DEF_CMD("-dotd", 0, set80211dotd),
+ DEF_CMD_ARG("htprotmode", set80211htprotmode),
+ DEF_CMD("ht20", 1, set80211htconf),
+ DEF_CMD("-ht20", 0, set80211htconf),
+ DEF_CMD("ht40", 3, set80211htconf), /* NB: 20+40 */
+ DEF_CMD("-ht40", 0, set80211htconf),
+ DEF_CMD("ht", 3, set80211htconf), /* NB: 20+40 */
+ DEF_CMD("-ht", 0, set80211htconf),
+ DEF_CMD("rifs", 1, set80211rifs),
+ DEF_CMD("-rifs", 0, set80211rifs),
+ DEF_CMD("smps", IEEE80211_HTCAP_SMPS_ENA, set80211smps),
+ DEF_CMD("smpsdyn", IEEE80211_HTCAP_SMPS_DYNAMIC, set80211smps),
+ DEF_CMD("-smps", IEEE80211_HTCAP_SMPS_OFF, set80211smps),
+ /* XXX for testing */
+ DEF_CMD_ARG("chanswitch", set80211chanswitch),
+
+ DEF_CMD_ARG("tdmaslot", set80211tdmaslot),
+ DEF_CMD_ARG("tdmaslotcnt", set80211tdmaslotcnt),
+ DEF_CMD_ARG("tdmaslotlen", set80211tdmaslotlen),
+ DEF_CMD_ARG("tdmabintval", set80211tdmabintval),
+
+ DEF_CMD_ARG("meshttl", set80211meshttl),
+ DEF_CMD("meshforward", 1, set80211meshforward),
+ DEF_CMD("-meshforward", 0, set80211meshforward),
+ DEF_CMD("meshpeering", 1, set80211meshpeering),
+ DEF_CMD("-meshpeering", 0, set80211meshpeering),
+ DEF_CMD_ARG("meshmetric", set80211meshmetric),
+ DEF_CMD_ARG("meshpath", set80211meshpath),
+ DEF_CMD("meshrt:flush", IEEE80211_MESH_RTCMD_FLUSH, set80211meshrtcmd),
+ DEF_CMD_ARG("meshrt:add", set80211addmeshrt),
+ DEF_CMD_ARG("meshrt:del", set80211delmeshrt),
+ DEF_CMD_ARG("hwmprootmode", set80211hwmprootmode),
+ DEF_CMD_ARG("hwmpmaxhops", set80211hwmpmaxhops),
+
+ /* vap cloning support */
+ DEF_CLONE_CMD_ARG("wlanaddr", set80211clone_wlanaddr),
+ DEF_CLONE_CMD_ARG("wlanbssid", set80211clone_wlanbssid),
+ DEF_CLONE_CMD_ARG("wlandev", set80211clone_wlandev),
+ DEF_CLONE_CMD_ARG("wlanmode", set80211clone_wlanmode),
+ DEF_CLONE_CMD("beacons", 1, set80211clone_beacons),
+ DEF_CLONE_CMD("-beacons", 0, set80211clone_beacons),
+ DEF_CLONE_CMD("bssid", 1, set80211clone_bssid),
+ DEF_CLONE_CMD("-bssid", 0, set80211clone_bssid),
+ DEF_CLONE_CMD("wdslegacy", 1, set80211clone_wdslegacy),
+ DEF_CLONE_CMD("-wdslegacy", 0, set80211clone_wdslegacy),
+};
+static struct afswtch af_ieee80211 = {
+ .af_name = "af_ieee80211",
+ .af_af = AF_UNSPEC,
+ .af_other_status = ieee80211_status,
+};
+
+static __constructor void
+ieee80211_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ int i;
+
+ for (i = 0; i < N(ieee80211_cmds); i++)
+ cmd_register(&ieee80211_cmds[i]);
+ af_register(&af_ieee80211);
+ clone_setdefcallback("wlan", wlan_create);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/iflagg.c b/freebsd/sbin/ifconfig/iflagg.c
new file mode 100644
index 00000000..4204d929
--- /dev/null
+++ b/freebsd/sbin/ifconfig/iflagg.c
@@ -0,0 +1,198 @@
+/*-
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_lagg.h>
+#else
+#include <net/if_lagg.h>
+#endif
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+char lacpbuf[120]; /* LACP peer '[(a,a,a),(p,p,p)]' */
+
+static void
+setlaggport(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct lagg_reqport rp;
+
+ bzero(&rp, sizeof(rp));
+ strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
+ strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
+
+ if (ioctl(s, SIOCSLAGGPORT, &rp))
+ err(1, "SIOCSLAGGPORT");
+}
+
+static void
+unsetlaggport(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct lagg_reqport rp;
+
+ bzero(&rp, sizeof(rp));
+ strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
+ strlcpy(rp.rp_portname, val, sizeof(rp.rp_portname));
+
+ if (ioctl(s, SIOCSLAGGDELPORT, &rp))
+ err(1, "SIOCSLAGGDELPORT");
+}
+
+static void
+setlaggproto(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct lagg_protos lpr[] = LAGG_PROTOS;
+ struct lagg_reqall ra;
+ int i;
+
+ bzero(&ra, sizeof(ra));
+ ra.ra_proto = LAGG_PROTO_MAX;
+
+ for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
+ if (strcmp(val, lpr[i].lpr_name) == 0) {
+ ra.ra_proto = lpr[i].lpr_proto;
+ break;
+ }
+ }
+ if (ra.ra_proto == LAGG_PROTO_MAX)
+ errx(1, "Invalid aggregation protocol: %s", val);
+
+ strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
+ if (ioctl(s, SIOCSLAGG, &ra) != 0)
+ err(1, "SIOCSLAGG");
+}
+
+static char *
+lacp_format_mac(const uint8_t *mac, char *buf, size_t buflen)
+{
+ snprintf(buf, buflen, "%02X-%02X-%02X-%02X-%02X-%02X",
+ (int)mac[0], (int)mac[1], (int)mac[2], (int)mac[3],
+ (int)mac[4], (int)mac[5]);
+
+ return (buf);
+}
+
+static char *
+lacp_format_peer(struct lacp_opreq *req, const char *sep)
+{
+ char macbuf1[20];
+ char macbuf2[20];
+
+ snprintf(lacpbuf, sizeof(lacpbuf),
+ "[(%04X,%s,%04X,%04X,%04X),%s(%04X,%s,%04X,%04X,%04X)]",
+ req->actor_prio,
+ lacp_format_mac(req->actor_mac, macbuf1, sizeof(macbuf1)),
+ req->actor_key, req->actor_portprio, req->actor_portno, sep,
+ req->partner_prio,
+ lacp_format_mac(req->partner_mac, macbuf2, sizeof(macbuf2)),
+ req->partner_key, req->partner_portprio, req->partner_portno);
+
+ return(lacpbuf);
+}
+
+static void
+lagg_status(int s)
+{
+ struct lagg_protos lpr[] = LAGG_PROTOS;
+ struct lagg_reqport rp, rpbuf[LAGG_MAX_PORTS];
+ struct lagg_reqall ra;
+ struct lacp_opreq *lp;
+ const char *proto = "<unknown>";
+ int i, isport = 0;
+
+ bzero(&rp, sizeof(rp));
+ bzero(&ra, sizeof(ra));
+
+ strlcpy(rp.rp_ifname, name, sizeof(rp.rp_ifname));
+ strlcpy(rp.rp_portname, name, sizeof(rp.rp_portname));
+
+ if (ioctl(s, SIOCGLAGGPORT, &rp) == 0)
+ isport = 1;
+
+ strlcpy(ra.ra_ifname, name, sizeof(ra.ra_ifname));
+ ra.ra_size = sizeof(rpbuf);
+ ra.ra_port = rpbuf;
+
+ if (ioctl(s, SIOCGLAGG, &ra) == 0) {
+ lp = (struct lacp_opreq *)&ra.ra_lacpreq;
+
+ for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++) {
+ if (ra.ra_proto == lpr[i].lpr_proto) {
+ proto = lpr[i].lpr_name;
+ break;
+ }
+ }
+
+ printf("\tlaggproto %s", proto);
+ if (isport)
+ printf(" laggdev %s", rp.rp_ifname);
+ putchar('\n');
+ if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
+ printf("\tlag id: %s\n",
+ lacp_format_peer(lp, "\n\t\t "));
+
+ for (i = 0; i < ra.ra_ports; i++) {
+ lp = (struct lacp_opreq *)&rpbuf[i].rp_lacpreq;
+ printf("\tlaggport: %s ", rpbuf[i].rp_portname);
+ printb("flags", rpbuf[i].rp_flags, LAGG_PORT_BITS);
+ if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
+ printf(" state=%X", lp->actor_state);
+ putchar('\n');
+ if (verbose && ra.ra_proto == LAGG_PROTO_LACP)
+ printf("\t\t%s\n",
+ lacp_format_peer(lp, "\n\t\t "));
+ }
+
+ if (0 /* XXX */) {
+ printf("\tsupported aggregation protocols:\n");
+ for (i = 0; i < (sizeof(lpr) / sizeof(lpr[0])); i++)
+ printf("\t\tlaggproto %s\n", lpr[i].lpr_name);
+ }
+ }
+}
+
+static struct cmd lagg_cmds[] = {
+ DEF_CMD_ARG("laggport", setlaggport),
+ DEF_CMD_ARG("-laggport", unsetlaggport),
+ DEF_CMD_ARG("laggproto", setlaggproto),
+};
+static struct afswtch af_lagg = {
+ .af_name = "af_lagg",
+ .af_af = AF_UNSPEC,
+ .af_other_status = lagg_status,
+};
+
+static __constructor void
+lagg_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ int i;
+
+ for (i = 0; i < N(lagg_cmds); i++)
+ cmd_register(&lagg_cmds[i]);
+ af_register(&af_lagg);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifmac.c b/freebsd/sbin/ifconfig/ifmac.c
new file mode 100644
index 00000000..31d40b13
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifmac.c
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2001 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by NAI Labs, the
+ * Security Research Division of Network Associates, Inc. under
+ * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
+ * CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/mac.h>
+#else
+#include <sys/mac.h>
+#endif
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "ifconfig.h"
+
+static void
+maclabel_status(int s)
+{
+ struct ifreq ifr;
+ mac_t label;
+ char *label_text;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+
+ if (mac_prepare_ifnet_label(&label) == -1)
+ return;
+ ifr.ifr_ifru.ifru_data = (void *)label;
+ if (ioctl(s, SIOCGIFMAC, &ifr) == -1)
+ goto mac_free;
+
+
+ if (mac_to_text(label, &label_text) == -1)
+ goto mac_free;
+
+ if (strlen(label_text) != 0)
+ printf("\tmaclabel %s\n", label_text);
+ free(label_text);
+
+mac_free:
+ mac_free(label);
+}
+
+static void
+setifmaclabel(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct ifreq ifr;
+ mac_t label;
+ int error;
+
+ if (mac_from_text(&label, val) == -1) {
+ perror(val);
+ return;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_ifru.ifru_data = (void *)label;
+
+ error = ioctl(s, SIOCSIFMAC, &ifr);
+ mac_free(label);
+ if (error == -1)
+ perror("setifmac");
+}
+
+static struct cmd mac_cmds[] = {
+ DEF_CMD_ARG("maclabel", setifmaclabel),
+};
+static struct afswtch af_mac = {
+ .af_name = "af_maclabel",
+ .af_af = AF_UNSPEC,
+ .af_other_status = maclabel_status,
+};
+
+static __constructor void
+mac_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(mac_cmds); i++)
+ cmd_register(&mac_cmds[i]);
+ af_register(&af_mac);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifmedia.c b/freebsd/sbin/ifconfig/ifmedia.c
new file mode 100644
index 00000000..ebca67de
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifmedia.c
@@ -0,0 +1,844 @@
+/* $NetBSD: ifconfig.c,v 1.34 1997/04/21 01:17:58 lukem Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Copyright (c) 1997 Jason R. Thorpe.
+ * 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 for the NetBSD Project
+ * by Jason R. Thorpe.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 1983, 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.
+ */
+
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#ifdef __rtems__
+#define _KERNEL
+#include <freebsd/net/if_media.h>
+#undef _KERNEL
+#else
+#include <net/if_media.h>
+#endif
+
+#include <net/route.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+static void domediaopt(const char *, int, int);
+static int get_media_subtype(int, const char *);
+static int get_media_mode(int, const char *);
+static int get_media_options(int, const char *);
+static int lookup_media_word(struct ifmedia_description *, const char *);
+static void print_media_word(int, int);
+static void print_media_word_ifconfig(int);
+
+static struct ifmedia_description *get_toptype_desc(int);
+static struct ifmedia_type_to_subtype *get_toptype_ttos(int);
+static struct ifmedia_description *get_subtype_desc(int,
+ struct ifmedia_type_to_subtype *ttos);
+
+#define IFM_OPMODE(x) \
+ ((x) & (IFM_IEEE80211_ADHOC | IFM_IEEE80211_HOSTAP | \
+ IFM_IEEE80211_IBSS | IFM_IEEE80211_WDS | IFM_IEEE80211_MONITOR | \
+ IFM_IEEE80211_MBSS))
+#define IFM_IEEE80211_STA 0
+
+static void
+media_status(int s)
+{
+ struct ifmediareq ifmr;
+ int *media_list, i;
+
+ (void) memset(&ifmr, 0, sizeof(ifmr));
+ (void) strncpy(ifmr.ifm_name, name, sizeof(ifmr.ifm_name));
+
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) {
+ /*
+ * Interface doesn't support SIOC{G,S}IFMEDIA.
+ */
+ return;
+ }
+
+ if (ifmr.ifm_count == 0) {
+ warnx("%s: no media types?", name);
+ return;
+ }
+
+ media_list = (int *)malloc(ifmr.ifm_count * sizeof(int));
+ if (media_list == NULL)
+ err(1, "malloc");
+ ifmr.ifm_ulist = media_list;
+
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0)
+ err(1, "SIOCGIFMEDIA");
+
+ printf("\tmedia: ");
+ print_media_word(ifmr.ifm_current, 1);
+ if (ifmr.ifm_active != ifmr.ifm_current) {
+ putchar(' ');
+ putchar('(');
+ print_media_word(ifmr.ifm_active, 0);
+ putchar(')');
+ }
+
+ putchar('\n');
+
+ if (ifmr.ifm_status & IFM_AVALID) {
+ printf("\tstatus: ");
+ switch (IFM_TYPE(ifmr.ifm_active)) {
+ case IFM_ETHER:
+ case IFM_ATM:
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ printf("active");
+ else
+ printf("no carrier");
+ break;
+
+ case IFM_FDDI:
+ case IFM_TOKEN:
+ if (ifmr.ifm_status & IFM_ACTIVE)
+ printf("inserted");
+ else
+ printf("no ring");
+ break;
+
+ case IFM_IEEE80211:
+ if (ifmr.ifm_status & IFM_ACTIVE) {
+ /* NB: only sta mode associates */
+ if (IFM_OPMODE(ifmr.ifm_active) == IFM_IEEE80211_STA)
+ printf("associated");
+ else
+ printf("running");
+ } else
+ printf("no carrier");
+ break;
+ }
+ putchar('\n');
+ }
+
+ if (ifmr.ifm_count > 0 && supmedia) {
+ printf("\tsupported media:\n");
+ for (i = 0; i < ifmr.ifm_count; i++) {
+ printf("\t\t");
+ print_media_word_ifconfig(media_list[i]);
+ putchar('\n');
+ }
+ }
+
+ free(media_list);
+}
+
+struct ifmediareq *
+ifmedia_getstate(int s)
+{
+ static struct ifmediareq *ifmr = NULL;
+ int *mwords;
+
+ if (ifmr == NULL) {
+ ifmr = (struct ifmediareq *)malloc(sizeof(struct ifmediareq));
+ if (ifmr == NULL)
+ err(1, "malloc");
+
+ (void) memset(ifmr, 0, sizeof(struct ifmediareq));
+ (void) strncpy(ifmr->ifm_name, name,
+ sizeof(ifmr->ifm_name));
+
+ ifmr->ifm_count = 0;
+ ifmr->ifm_ulist = NULL;
+
+ /*
+ * We must go through the motions of reading all
+ * supported media because we need to know both
+ * the current media type and the top-level type.
+ */
+
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0) {
+ err(1, "SIOCGIFMEDIA");
+ }
+
+ if (ifmr->ifm_count == 0)
+ errx(1, "%s: no media types?", name);
+
+ mwords = (int *)malloc(ifmr->ifm_count * sizeof(int));
+ if (mwords == NULL)
+ err(1, "malloc");
+
+ ifmr->ifm_ulist = mwords;
+ if (ioctl(s, SIOCGIFMEDIA, (caddr_t)ifmr) < 0)
+ err(1, "SIOCGIFMEDIA");
+ }
+
+ return ifmr;
+}
+
+static void
+setifmediacallback(int s, void *arg)
+{
+ struct ifmediareq *ifmr = (struct ifmediareq *)arg;
+ static int did_it = 0;
+
+ if (!did_it) {
+ ifr.ifr_media = ifmr->ifm_current;
+ if (ioctl(s, SIOCSIFMEDIA, (caddr_t)&ifr) < 0)
+ err(1, "SIOCSIFMEDIA (media)");
+ free(ifmr->ifm_ulist);
+ free(ifmr);
+ did_it = 1;
+ }
+}
+
+static void
+setmedia(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifmediareq *ifmr;
+ int subtype;
+
+ ifmr = ifmedia_getstate(s);
+
+ /*
+ * We are primarily concerned with the top-level type.
+ * However, "current" may be only IFM_NONE, so we just look
+ * for the top-level type in the first "supported type"
+ * entry.
+ *
+ * (I'm assuming that all supported media types for a given
+ * interface will be the same top-level type..)
+ */
+ subtype = get_media_subtype(IFM_TYPE(ifmr->ifm_ulist[0]), val);
+
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_media = (ifmr->ifm_current & ~(IFM_NMASK|IFM_TMASK)) |
+ IFM_TYPE(ifmr->ifm_ulist[0]) | subtype;
+
+ if ((ifr.ifr_media & IFM_TMASK) == 0) {
+ ifr.ifr_media &= ~(IFM_GMASK | IFM_OMASK);
+ }
+
+ ifmr->ifm_current = ifr.ifr_media;
+ callback_register(setifmediacallback, (void *)ifmr);
+}
+
+static void
+setmediaopt(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ domediaopt(val, 0, s);
+}
+
+static void
+unsetmediaopt(const char *val, int d, int s, const struct afswtch *afp)
+{
+
+ domediaopt(val, 1, s);
+}
+
+static void
+domediaopt(const char *val, int clear, int s)
+{
+ struct ifmediareq *ifmr;
+ int options;
+
+ ifmr = ifmedia_getstate(s);
+
+ options = get_media_options(IFM_TYPE(ifmr->ifm_ulist[0]), val);
+
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_media = ifmr->ifm_current;
+ if (clear)
+ ifr.ifr_media &= ~options;
+ else {
+ if (options & IFM_HDX) {
+ ifr.ifr_media &= ~IFM_FDX;
+ options &= ~IFM_HDX;
+ }
+ ifr.ifr_media |= options;
+ }
+ ifmr->ifm_current = ifr.ifr_media;
+ callback_register(setifmediacallback, (void *)ifmr);
+}
+
+static void
+setmediainst(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifmediareq *ifmr;
+ int inst;
+
+ ifmr = ifmedia_getstate(s);
+
+ inst = atoi(val);
+ if (inst < 0 || inst > (int)IFM_INST_MAX)
+ errx(1, "invalid media instance: %s", val);
+
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_media = (ifmr->ifm_current & ~IFM_IMASK) | inst << IFM_ISHIFT;
+
+ ifmr->ifm_current = ifr.ifr_media;
+ callback_register(setifmediacallback, (void *)ifmr);
+}
+
+static void
+setmediamode(const char *val, int d, int s, const struct afswtch *afp)
+{
+ struct ifmediareq *ifmr;
+ int mode;
+
+ ifmr = ifmedia_getstate(s);
+
+ mode = get_media_mode(IFM_TYPE(ifmr->ifm_ulist[0]), val);
+
+ strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ ifr.ifr_media = (ifmr->ifm_current & ~IFM_MMASK) | mode;
+
+ ifmr->ifm_current = ifr.ifr_media;
+ callback_register(setifmediacallback, (void *)ifmr);
+}
+
+/**********************************************************************
+ * A good chunk of this is duplicated from sys/net/ifmedia.c
+ **********************************************************************/
+
+static struct ifmedia_description ifm_type_descriptions[] =
+ IFM_TYPE_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ethernet_descriptions[] =
+ IFM_SUBTYPE_ETHERNET_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ethernet_aliases[] =
+ IFM_SUBTYPE_ETHERNET_ALIASES;
+
+static struct ifmedia_description ifm_subtype_ethernet_option_descriptions[] =
+ IFM_SUBTYPE_ETHERNET_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_tokenring_descriptions[] =
+ IFM_SUBTYPE_TOKENRING_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_tokenring_aliases[] =
+ IFM_SUBTYPE_TOKENRING_ALIASES;
+
+static struct ifmedia_description ifm_subtype_tokenring_option_descriptions[] =
+ IFM_SUBTYPE_TOKENRING_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_fddi_descriptions[] =
+ IFM_SUBTYPE_FDDI_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_fddi_aliases[] =
+ IFM_SUBTYPE_FDDI_ALIASES;
+
+static struct ifmedia_description ifm_subtype_fddi_option_descriptions[] =
+ IFM_SUBTYPE_FDDI_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_descriptions[] =
+ IFM_SUBTYPE_IEEE80211_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_ieee80211_aliases[] =
+ IFM_SUBTYPE_IEEE80211_ALIASES;
+
+static struct ifmedia_description ifm_subtype_ieee80211_option_descriptions[] =
+ IFM_SUBTYPE_IEEE80211_OPTION_DESCRIPTIONS;
+
+struct ifmedia_description ifm_subtype_ieee80211_mode_descriptions[] =
+ IFM_SUBTYPE_IEEE80211_MODE_DESCRIPTIONS;
+
+struct ifmedia_description ifm_subtype_ieee80211_mode_aliases[] =
+ IFM_SUBTYPE_IEEE80211_MODE_ALIASES;
+
+static struct ifmedia_description ifm_subtype_atm_descriptions[] =
+ IFM_SUBTYPE_ATM_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_atm_aliases[] =
+ IFM_SUBTYPE_ATM_ALIASES;
+
+static struct ifmedia_description ifm_subtype_atm_option_descriptions[] =
+ IFM_SUBTYPE_ATM_OPTION_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_shared_descriptions[] =
+ IFM_SUBTYPE_SHARED_DESCRIPTIONS;
+
+static struct ifmedia_description ifm_subtype_shared_aliases[] =
+ IFM_SUBTYPE_SHARED_ALIASES;
+
+static struct ifmedia_description ifm_shared_option_descriptions[] =
+ IFM_SHARED_OPTION_DESCRIPTIONS;
+
+struct ifmedia_type_to_subtype {
+ struct {
+ struct ifmedia_description *desc;
+ int alias;
+ } subtypes[5];
+ struct {
+ struct ifmedia_description *desc;
+ int alias;
+ } options[3];
+ struct {
+ struct ifmedia_description *desc;
+ int alias;
+ } modes[3];
+};
+
+/* must be in the same order as IFM_TYPE_DESCRIPTIONS */
+static struct ifmedia_type_to_subtype ifmedia_types_to_subtypes[] = {
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_ethernet_descriptions[0], 0 },
+ { &ifm_subtype_ethernet_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_subtype_ethernet_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_tokenring_descriptions[0], 0 },
+ { &ifm_subtype_tokenring_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_subtype_tokenring_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_fddi_descriptions[0], 0 },
+ { &ifm_subtype_fddi_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_subtype_fddi_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_ieee80211_descriptions[0], 0 },
+ { &ifm_subtype_ieee80211_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_subtype_ieee80211_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_subtype_ieee80211_mode_descriptions[0], 0 },
+ { &ifm_subtype_ieee80211_mode_aliases[0], 0 },
+ { NULL, 0 },
+ },
+ },
+ {
+ {
+ { &ifm_subtype_shared_descriptions[0], 0 },
+ { &ifm_subtype_shared_aliases[0], 1 },
+ { &ifm_subtype_atm_descriptions[0], 0 },
+ { &ifm_subtype_atm_aliases[0], 1 },
+ { NULL, 0 },
+ },
+ {
+ { &ifm_shared_option_descriptions[0], 0 },
+ { &ifm_subtype_atm_option_descriptions[0], 0 },
+ { NULL, 0 },
+ },
+ {
+ { NULL, 0 },
+ },
+ },
+};
+
+static int
+get_media_subtype(int type, const char *val)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+ int rval, i;
+
+ /* Find the top-level interface type. */
+ for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+ desc->ifmt_string != NULL; desc++, ttos++)
+ if (type == desc->ifmt_word)
+ break;
+ if (desc->ifmt_string == NULL)
+ errx(1, "unknown media type 0x%x", type);
+
+ for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
+ rval = lookup_media_word(ttos->subtypes[i].desc, val);
+ if (rval != -1)
+ return (rval);
+ }
+ errx(1, "unknown media subtype: %s", val);
+ /*NOTREACHED*/
+}
+
+static int
+get_media_mode(int type, const char *val)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+ int rval, i;
+
+ /* Find the top-level interface type. */
+ for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+ desc->ifmt_string != NULL; desc++, ttos++)
+ if (type == desc->ifmt_word)
+ break;
+ if (desc->ifmt_string == NULL)
+ errx(1, "unknown media mode 0x%x", type);
+
+ for (i = 0; ttos->modes[i].desc != NULL; i++) {
+ rval = lookup_media_word(ttos->modes[i].desc, val);
+ if (rval != -1)
+ return (rval);
+ }
+ return -1;
+}
+
+static int
+get_media_options(int type, const char *val)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+ char *optlist, *optptr;
+ int option = 0, i, rval = 0;
+
+ /* We muck with the string, so copy it. */
+ optlist = strdup(val);
+ if (optlist == NULL)
+ err(1, "strdup");
+
+ /* Find the top-level interface type. */
+ for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+ desc->ifmt_string != NULL; desc++, ttos++)
+ if (type == desc->ifmt_word)
+ break;
+ if (desc->ifmt_string == NULL)
+ errx(1, "unknown media type 0x%x", type);
+
+ /*
+ * Look up the options in the user-provided comma-separated
+ * list.
+ */
+ optptr = optlist;
+ for (; (optptr = strtok(optptr, ",")) != NULL; optptr = NULL) {
+ for (i = 0; ttos->options[i].desc != NULL; i++) {
+ option = lookup_media_word(ttos->options[i].desc, optptr);
+ if (option != -1)
+ break;
+ }
+ if (option == 0)
+ errx(1, "unknown option: %s", optptr);
+ rval |= option;
+ }
+
+ free(optlist);
+ return (rval);
+}
+
+static int
+lookup_media_word(struct ifmedia_description *desc, const char *val)
+{
+
+ for (; desc->ifmt_string != NULL; desc++)
+ if (strcasecmp(desc->ifmt_string, val) == 0)
+ return (desc->ifmt_word);
+
+ return (-1);
+}
+
+static struct ifmedia_description *get_toptype_desc(int ifmw)
+{
+ struct ifmedia_description *desc;
+
+ for (desc = ifm_type_descriptions; desc->ifmt_string != NULL; desc++)
+ if (IFM_TYPE(ifmw) == desc->ifmt_word)
+ break;
+
+ return desc;
+}
+
+static struct ifmedia_type_to_subtype *get_toptype_ttos(int ifmw)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+
+ for (desc = ifm_type_descriptions, ttos = ifmedia_types_to_subtypes;
+ desc->ifmt_string != NULL; desc++, ttos++)
+ if (IFM_TYPE(ifmw) == desc->ifmt_word)
+ break;
+
+ return ttos;
+}
+
+static struct ifmedia_description *get_subtype_desc(int ifmw,
+ struct ifmedia_type_to_subtype *ttos)
+{
+ int i;
+ struct ifmedia_description *desc;
+
+ for (i = 0; ttos->subtypes[i].desc != NULL; i++) {
+ if (ttos->subtypes[i].alias)
+ continue;
+ for (desc = ttos->subtypes[i].desc;
+ desc->ifmt_string != NULL; desc++) {
+ if (IFM_SUBTYPE(ifmw) == desc->ifmt_word)
+ return desc;
+ }
+ }
+
+ return NULL;
+}
+
+static struct ifmedia_description *get_mode_desc(int ifmw,
+ struct ifmedia_type_to_subtype *ttos)
+{
+ int i;
+ struct ifmedia_description *desc;
+
+ for (i = 0; ttos->modes[i].desc != NULL; i++) {
+ if (ttos->modes[i].alias)
+ continue;
+ for (desc = ttos->modes[i].desc;
+ desc->ifmt_string != NULL; desc++) {
+ if (IFM_MODE(ifmw) == desc->ifmt_word)
+ return desc;
+ }
+ }
+
+ return NULL;
+}
+
+static void
+print_media_word(int ifmw, int print_toptype)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+ int seen_option = 0, i;
+
+ /* Find the top-level interface type. */
+ desc = get_toptype_desc(ifmw);
+ ttos = get_toptype_ttos(ifmw);
+ if (desc->ifmt_string == NULL) {
+ printf("<unknown type>");
+ return;
+ } else if (print_toptype) {
+ printf("%s", desc->ifmt_string);
+ }
+
+ /*
+ * Don't print the top-level type; it's not like we can
+ * change it, or anything.
+ */
+
+ /* Find subtype. */
+ desc = get_subtype_desc(ifmw, ttos);
+ if (desc == NULL) {
+ printf("<unknown subtype>");
+ return;
+ }
+
+ if (print_toptype)
+ putchar(' ');
+
+ printf("%s", desc->ifmt_string);
+
+ if (print_toptype) {
+ desc = get_mode_desc(ifmw, ttos);
+ if (desc != NULL && strcasecmp("autoselect", desc->ifmt_string))
+ printf(" mode %s", desc->ifmt_string);
+ }
+
+ /* Find options. */
+ for (i = 0; ttos->options[i].desc != NULL; i++) {
+ if (ttos->options[i].alias)
+ continue;
+ for (desc = ttos->options[i].desc;
+ desc->ifmt_string != NULL; desc++) {
+ if (ifmw & desc->ifmt_word) {
+ if (seen_option == 0)
+ printf(" <");
+ printf("%s%s", seen_option++ ? "," : "",
+ desc->ifmt_string);
+ }
+ }
+ }
+ printf("%s", seen_option ? ">" : "");
+
+ if (print_toptype && IFM_INST(ifmw) != 0)
+ printf(" instance %d", IFM_INST(ifmw));
+}
+
+static void
+print_media_word_ifconfig(int ifmw)
+{
+ struct ifmedia_description *desc;
+ struct ifmedia_type_to_subtype *ttos;
+ int seen_option = 0, i;
+
+ /* Find the top-level interface type. */
+ desc = get_toptype_desc(ifmw);
+ ttos = get_toptype_ttos(ifmw);
+ if (desc->ifmt_string == NULL) {
+ printf("<unknown type>");
+ return;
+ }
+
+ /*
+ * Don't print the top-level type; it's not like we can
+ * change it, or anything.
+ */
+
+ /* Find subtype. */
+ desc = get_subtype_desc(ifmw, ttos);
+ if (desc == NULL) {
+ printf("<unknown subtype>");
+ return;
+ }
+
+ printf("media %s", desc->ifmt_string);
+
+ desc = get_mode_desc(ifmw, ttos);
+ if (desc != NULL)
+ printf(" mode %s", desc->ifmt_string);
+
+ /* Find options. */
+ for (i = 0; ttos->options[i].desc != NULL; i++) {
+ if (ttos->options[i].alias)
+ continue;
+ for (desc = ttos->options[i].desc;
+ desc->ifmt_string != NULL; desc++) {
+ if (ifmw & desc->ifmt_word) {
+ if (seen_option == 0)
+ printf(" mediaopt ");
+ printf("%s%s", seen_option++ ? "," : "",
+ desc->ifmt_string);
+ }
+ }
+ }
+
+ if (IFM_INST(ifmw) != 0)
+ printf(" instance %d", IFM_INST(ifmw));
+}
+
+/**********************************************************************
+ * ...until here.
+ **********************************************************************/
+
+static struct cmd media_cmds[] = {
+ DEF_CMD_ARG("media", setmedia),
+ DEF_CMD_ARG("mode", setmediamode),
+ DEF_CMD_ARG("mediaopt", setmediaopt),
+ DEF_CMD_ARG("-mediaopt",unsetmediaopt),
+ DEF_CMD_ARG("inst", setmediainst),
+ DEF_CMD_ARG("instance", setmediainst),
+};
+static struct afswtch af_media = {
+ .af_name = "af_media",
+ .af_af = AF_UNSPEC,
+ .af_other_status = media_status,
+};
+
+static __constructor void
+ifmedia_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(media_cmds); i++)
+ cmd_register(&media_cmds[i]);
+ af_register(&af_media);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifpfsync.c b/freebsd/sbin/ifconfig/ifpfsync.c
new file mode 100644
index 00000000..886a75e6
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifpfsync.c
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2003 Ryan McBride. All rights reserved.
+ * Copyright (c) 2004 Max Laier. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/net/pfvar.h>
+#include <freebsd/net/if_pfsync.h>
+#else
+#include <net/pfvar.h>
+#include <net/if_pfsync.h>
+#endif
+#include <net/route.h>
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "ifconfig.h"
+
+void setpfsync_syncdev(const char *, int, int, const struct afswtch *);
+void unsetpfsync_syncdev(const char *, int, int, const struct afswtch *);
+void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
+void unsetpfsync_syncpeer(const char *, int, int, const struct afswtch *);
+void setpfsync_syncpeer(const char *, int, int, const struct afswtch *);
+void setpfsync_maxupd(const char *, int, int, const struct afswtch *);
+void pfsync_status(int);
+
+void
+setpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct pfsyncreq preq;
+
+ bzero((char *)&preq, sizeof(struct pfsyncreq));
+ ifr.ifr_data = (caddr_t)&preq;
+
+ if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGETPFSYNC");
+
+ strlcpy(preq.pfsyncr_syncdev, val, sizeof(preq.pfsyncr_syncdev));
+
+ if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSETPFSYNC");
+}
+
+/* ARGSUSED */
+void
+unsetpfsync_syncdev(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct pfsyncreq preq;
+
+ bzero((char *)&preq, sizeof(struct pfsyncreq));
+ ifr.ifr_data = (caddr_t)&preq;
+
+ if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGETPFSYNC");
+
+ bzero((char *)&preq.pfsyncr_syncdev, sizeof(preq.pfsyncr_syncdev));
+
+ if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSETPFSYNC");
+}
+
+/* ARGSUSED */
+void
+setpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct pfsyncreq preq;
+ struct addrinfo hints, *peerres;
+ int ecode;
+
+ bzero((char *)&preq, sizeof(struct pfsyncreq));
+ ifr.ifr_data = (caddr_t)&preq;
+
+ if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGETPFSYNC");
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+
+ if ((ecode = getaddrinfo(val, NULL, &hints, &peerres)) != 0)
+ errx(1, "error in parsing address string: %s",
+ gai_strerror(ecode));
+
+ if (peerres->ai_addr->sa_family != AF_INET)
+ errx(1, "only IPv4 addresses supported for the syncpeer");
+
+ preq.pfsyncr_syncpeer.s_addr = ((struct sockaddr_in *)
+ peerres->ai_addr)->sin_addr.s_addr;
+
+ if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSETPFSYNC");
+}
+
+/* ARGSUSED */
+void
+unsetpfsync_syncpeer(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct pfsyncreq preq;
+
+ bzero((char *)&preq, sizeof(struct pfsyncreq));
+ ifr.ifr_data = (caddr_t)&preq;
+
+ if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGETPFSYNC");
+
+ preq.pfsyncr_syncpeer.s_addr = 0;
+
+ if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSETPFSYNC");
+}
+
+/* ARGSUSED */
+void
+setpfsync_maxupd(const char *val, int d, int s, const struct afswtch *rafp)
+{
+ struct pfsyncreq preq;
+ int maxupdates;
+
+ maxupdates = atoi(val);
+ if ((maxupdates < 0) || (maxupdates > 255))
+ errx(1, "maxupd %s: out of range", val);
+
+ memset((char *)&preq, 0, sizeof(struct pfsyncreq));
+ ifr.ifr_data = (caddr_t)&preq;
+
+ if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGETPFSYNC");
+
+ preq.pfsyncr_maxupdates = maxupdates;
+
+ if (ioctl(s, SIOCSETPFSYNC, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSETPFSYNC");
+}
+
+void
+pfsync_status(int s)
+{
+ struct pfsyncreq preq;
+
+ bzero((char *)&preq, sizeof(struct pfsyncreq));
+ ifr.ifr_data = (caddr_t)&preq;
+
+ if (ioctl(s, SIOCGETPFSYNC, (caddr_t)&ifr) == -1)
+ return;
+
+ if (preq.pfsyncr_syncdev[0] != '\0' ||
+ preq.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP)
+ printf("\t");
+
+ if (preq.pfsyncr_syncdev[0] != '\0')
+ printf("pfsync: syncdev: %s ", preq.pfsyncr_syncdev);
+ if (preq.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP)
+ printf("syncpeer: %s ", inet_ntoa(preq.pfsyncr_syncpeer));
+
+ if (preq.pfsyncr_syncdev[0] != '\0' ||
+ preq.pfsyncr_syncpeer.s_addr != INADDR_PFSYNC_GROUP)
+ printf("maxupd: %d\n", preq.pfsyncr_maxupdates);
+}
+
+static struct cmd pfsync_cmds[] = {
+ DEF_CMD_ARG("syncdev", setpfsync_syncdev),
+ DEF_CMD("-syncdev", 1, unsetpfsync_syncdev),
+ DEF_CMD_ARG("syncif", setpfsync_syncdev),
+ DEF_CMD("-syncif", 1, unsetpfsync_syncdev),
+ DEF_CMD_ARG("syncpeer", setpfsync_syncpeer),
+ DEF_CMD("-syncpeer", 1, unsetpfsync_syncpeer),
+ DEF_CMD_ARG("maxupd", setpfsync_maxupd)
+};
+static struct afswtch af_pfsync = {
+ .af_name = "af_pfsync",
+ .af_af = AF_UNSPEC,
+ .af_other_status = pfsync_status,
+};
+
+static __constructor void
+pfsync_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ int i;
+
+ for (i = 0; i < N(pfsync_cmds); i++)
+ cmd_register(&pfsync_cmds[i]);
+ af_register(&af_pfsync);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/ifvlan.c b/freebsd/sbin/ifconfig/ifvlan.c
new file mode 100644
index 00000000..8ec3766f
--- /dev/null
+++ b/freebsd/sbin/ifconfig/ifvlan.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1999
+ * Bill Paul <wpaul@ctr.columbia.edu>. 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 Bill Paul 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 Bill Paul 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.
+ */
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#include <freebsd/net/if_vlan_var.h>
+#else
+#include <net/if_var.h>
+#include <net/if_vlan_var.h>
+#endif
+#include <net/route.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <err.h>
+#include <errno.h>
+
+#include "ifconfig.h"
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif
+
+#define NOTAG ((u_short) -1)
+
+static struct vlanreq params = {
+ .vlr_tag = NOTAG,
+};
+
+static int
+getvlan(int s, struct ifreq *ifr, struct vlanreq *vreq)
+{
+ bzero((char *)vreq, sizeof(*vreq));
+ ifr->ifr_data = (caddr_t)vreq;
+
+ return ioctl(s, SIOCGETVLAN, (caddr_t)ifr);
+}
+
+static void
+vlan_status(int s)
+{
+ struct vlanreq vreq;
+
+ if (getvlan(s, &ifr, &vreq) != -1)
+ printf("\tvlan: %d parent interface: %s\n",
+ vreq.vlr_tag, vreq.vlr_parent[0] == '\0' ?
+ "<none>" : vreq.vlr_parent);
+}
+
+static void
+vlan_create(int s, struct ifreq *ifr)
+{
+ if (params.vlr_tag != NOTAG || params.vlr_parent[0] != '\0') {
+ /*
+ * One or both parameters were specified, make sure both.
+ */
+ if (params.vlr_tag == NOTAG)
+ errx(1, "must specify a tag for vlan create");
+ if (params.vlr_parent[0] == '\0')
+ errx(1, "must specify a parent device for vlan create");
+ ifr->ifr_data = (caddr_t) &params;
+ }
+ if (ioctl(s, SIOCIFCREATE2, ifr) < 0)
+ err(1, "SIOCIFCREATE2");
+}
+
+static void
+vlan_cb(int s, void *arg)
+{
+ if ((params.vlr_tag != NOTAG) ^ (params.vlr_parent[0] != '\0'))
+ errx(1, "both vlan and vlandev must be specified");
+}
+
+static void
+vlan_set(int s, struct ifreq *ifr)
+{
+ if (params.vlr_tag != NOTAG && params.vlr_parent[0] != '\0') {
+ ifr->ifr_data = (caddr_t) &params;
+ if (ioctl(s, SIOCSETVLAN, (caddr_t)ifr) == -1)
+ err(1, "SIOCSETVLAN");
+ }
+}
+
+static
+DECL_CMD_FUNC(setvlantag, val, d)
+{
+ struct vlanreq vreq;
+ u_long ul;
+ char *endp;
+
+ ul = strtoul(val, &endp, 0);
+ if (*endp != '\0')
+ errx(1, "invalid value for vlan");
+ params.vlr_tag = ul;
+ /* check if the value can be represented in vlr_tag */
+ if (params.vlr_tag != ul)
+ errx(1, "value for vlan out of range");
+
+ if (getvlan(s, &ifr, &vreq) != -1)
+ vlan_set(s, &ifr);
+}
+
+static
+DECL_CMD_FUNC(setvlandev, val, d)
+{
+ struct vlanreq vreq;
+
+ strlcpy(params.vlr_parent, val, sizeof(params.vlr_parent));
+
+ if (getvlan(s, &ifr, &vreq) != -1)
+ vlan_set(s, &ifr);
+}
+
+static
+DECL_CMD_FUNC(unsetvlandev, val, d)
+{
+ struct vlanreq vreq;
+
+ bzero((char *)&vreq, sizeof(struct vlanreq));
+ ifr.ifr_data = (caddr_t)&vreq;
+
+ if (ioctl(s, SIOCGETVLAN, (caddr_t)&ifr) == -1)
+ err(1, "SIOCGETVLAN");
+
+ bzero((char *)&vreq.vlr_parent, sizeof(vreq.vlr_parent));
+ vreq.vlr_tag = 0;
+
+ if (ioctl(s, SIOCSETVLAN, (caddr_t)&ifr) == -1)
+ err(1, "SIOCSETVLAN");
+}
+
+static struct cmd vlan_cmds[] = {
+ DEF_CLONE_CMD_ARG("vlan", setvlantag),
+ DEF_CLONE_CMD_ARG("vlandev", setvlandev),
+ /* NB: non-clone cmds */
+ DEF_CMD_ARG("vlan", setvlantag),
+ DEF_CMD_ARG("vlandev", setvlandev),
+ /* XXX For compatibility. Should become DEF_CMD() some day. */
+ DEF_CMD_OPTARG("-vlandev", unsetvlandev),
+ DEF_CMD("vlanmtu", IFCAP_VLAN_MTU, setifcap),
+ DEF_CMD("-vlanmtu", -IFCAP_VLAN_MTU, setifcap),
+ DEF_CMD("vlanhwtag", IFCAP_VLAN_HWTAGGING, setifcap),
+ DEF_CMD("-vlanhwtag", -IFCAP_VLAN_HWTAGGING, setifcap),
+ DEF_CMD("vlanhwfilter", IFCAP_VLAN_HWFILTER, setifcap),
+ DEF_CMD("-vlanhwfilter", -IFCAP_VLAN_HWFILTER, setifcap),
+ DEF_CMD("-vlanhwtso", -IFCAP_VLAN_HWTSO, setifcap),
+ DEF_CMD("vlanhwtso", IFCAP_VLAN_HWTSO, setifcap),
+};
+static struct afswtch af_vlan = {
+ .af_name = "af_vlan",
+ .af_af = AF_UNSPEC,
+ .af_other_status = vlan_status,
+};
+
+static __constructor void
+vlan_ctor(void)
+{
+#define N(a) (sizeof(a) / sizeof(a[0]))
+ size_t i;
+
+ for (i = 0; i < N(vlan_cmds); i++)
+ cmd_register(&vlan_cmds[i]);
+ af_register(&af_vlan);
+ callback_register(vlan_cb, NULL);
+ clone_setdefcallback("vlan", vlan_create);
+#undef N
+}
diff --git a/freebsd/sbin/ifconfig/regdomain.h b/freebsd/sbin/ifconfig/regdomain.h
new file mode 100644
index 00000000..81588752
--- /dev/null
+++ b/freebsd/sbin/ifconfig/regdomain.h
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 2007-2008 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 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 _LIB80211_H_
+#define _LIB80211_H_
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+
+#ifdef __rtems__
+#include <freebsd/net80211/ieee80211_regdomain.h>
+#else
+#include <net80211/ieee80211_regdomain.h>
+#endif
+
+
+__BEGIN_DECLS
+
+struct freqband {
+ uint16_t freqStart; /* starting frequency (MHz) */
+ uint16_t freqEnd; /* ending frequency (MHz) */
+ uint8_t chanWidth; /* channel width (MHz) */
+ uint8_t chanSep; /* channel sepaaration (MHz) */
+ uint32_t flags; /* common operational constraints */
+
+ const void *id;
+ LIST_ENTRY(freqband) next;
+};
+
+/* private flags, don't pass to os */
+#define REQ_ECM 0x1 /* enable if ECM set */
+#define REQ_INDOOR 0x2 /* enable only for indoor operation */
+#define REQ_OUTDOOR 0x4 /* enable only for outdoor operation */
+
+#define REQ_FLAGS (REQ_ECM|REQ_INDOOR|REQ_OUTDOOR)
+
+struct netband {
+ const struct freqband *band; /* channel list description */
+ uint8_t maxPower; /* regulatory cap on tx power (dBm) */
+ uint8_t maxPowerDFS; /* regulatory cap w/ DFS (dBm) */
+ uint8_t maxAntGain; /* max allowed antenna gain (.5 dBm) */
+ uint32_t flags; /* net80211 channel flags */
+
+ LIST_ENTRY(netband) next;
+};
+typedef LIST_HEAD(, netband) netband_head;
+
+struct country;
+
+struct regdomain {
+ enum RegdomainCode sku; /* regdomain code/SKU */
+ const char *name; /* printable name */
+ const struct country *cc; /* country code for 1-1/default map */
+
+ netband_head bands_11b; /* 11b operation */
+ netband_head bands_11g; /* 11g operation */
+ netband_head bands_11a; /* 11a operation */
+ netband_head bands_11ng;/* 11ng operation */
+ netband_head bands_11na;/* 11na operation */
+
+ LIST_ENTRY(regdomain) next;
+};
+
+struct country {
+ enum ISOCountryCode code;
+#define NO_COUNTRY 0xffff
+ const struct regdomain *rd;
+ const char* isoname;
+ const char* name;
+
+ LIST_ENTRY(country) next;
+};
+
+struct ident;
+
+struct regdata {
+ LIST_HEAD(, country) countries; /* country code table */
+ LIST_HEAD(, regdomain) domains; /* regulatory domains */
+ LIST_HEAD(, freqband) freqbands; /* frequency band table */
+ struct ident *ident; /* identifier table */
+};
+
+#define _PATH_REGDOMAIN "/etc/regdomain.xml"
+
+struct regdata *lib80211_alloc_regdata(void);
+void lib80211_free_regdata(struct regdata *);
+
+int lib80211_regdomain_readconfig(struct regdata *, const void *, size_t);
+void lib80211_regdomain_cleanup(struct regdata *);
+
+const struct regdomain *lib80211_regdomain_findbysku(const struct regdata *,
+ enum RegdomainCode);
+const struct regdomain *lib80211_regdomain_findbyname(const struct regdata *,
+ const char *);
+
+const struct country *lib80211_country_findbycc(const struct regdata *,
+ enum ISOCountryCode);
+const struct country *lib80211_country_findbyname(const struct regdata *,
+ const char *);
+
+__END_DECLS
+
+#endif /* _LIB80211_H_ */
diff --git a/freebsd/sbin/ping/ping.c b/freebsd/sbin/ping/ping.c
new file mode 100644
index 00000000..34d86325
--- /dev/null
+++ b/freebsd/sbin/ping/ping.c
@@ -0,0 +1,1810 @@
+#ifdef __rtems__
+#define __need_getopt_newlib
+#include <getopt.h>
+#endif
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * 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 0
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
+#endif /* not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * P I N G . C
+ *
+ * Using the Internet Control Message Protocol (ICMP) "ECHO" facility,
+ * measure round-trip-delays and packet loss across network paths.
+ *
+ * Author -
+ * Mike Muuss
+ * U. S. Army Ballistic Research Laboratory
+ * December, 1983
+ *
+ * Status -
+ * Public Domain. Distribution Unlimited.
+ * Bugs -
+ * More statistics could always be gathered.
+ * This program has to run SUID to ROOT to access the ICMP socket.
+ */
+
+#include <sys/param.h> /* NB: we rely on this for <sys/types.h> */
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_icmp.h>
+#include <freebsd/netinet/ip_var.h>
+#else
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#include <netinet/ip_var.h>
+#endif
+#include <arpa/inet.h>
+
+#ifdef IPSEC
+#ifdef __rtems__
+#include <freebsd/netipsec/ipsec.h>
+#else
+#include <netipsec/ipsec.h>
+#endif
+#endif /*IPSEC*/
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#ifdef __rtems__
+#define select __select
+#endif
+
+#define INADDR_LEN ((int)sizeof(in_addr_t))
+#define TIMEVAL_LEN ((int)sizeof(struct tv32))
+#define MASK_LEN (ICMP_MASKLEN - ICMP_MINLEN)
+#define TS_LEN (ICMP_TSLEN - ICMP_MINLEN)
+#define DEFDATALEN 56 /* default data length */
+#define FLOOD_BACKOFF 20000 /* usecs to back off if F_FLOOD mode */
+ /* runs out of buffer space */
+#define MAXIPLEN (sizeof(struct ip) + MAX_IPOPTLEN)
+#define MAXICMPLEN (ICMP_ADVLENMIN + MAX_IPOPTLEN)
+#define MAXWAIT 10000 /* max ms to wait for response */
+#define MAXALARM (60 * 60) /* max seconds for alarm timeout */
+#define MAXTOS 255
+
+#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
+#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
+#define SET(bit) (A(bit) |= B(bit))
+#define CLR(bit) (A(bit) &= (~B(bit)))
+#define TST(bit) (A(bit) & B(bit))
+
+struct tv32 {
+ int32_t tv32_sec;
+ int32_t tv32_usec;
+};
+
+/* various options */
+int options;
+#define F_FLOOD 0x0001
+#define F_INTERVAL 0x0002
+#define F_NUMERIC 0x0004
+#define F_PINGFILLED 0x0008
+#define F_QUIET 0x0010
+#define F_RROUTE 0x0020
+#define F_SO_DEBUG 0x0040
+#define F_SO_DONTROUTE 0x0080
+#define F_VERBOSE 0x0100
+#define F_QUIET2 0x0200
+#define F_NOLOOP 0x0400
+#define F_MTTL 0x0800
+#define F_MIF 0x1000
+#define F_AUDIBLE 0x2000
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+#define F_POLICY 0x4000
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+#define F_TTL 0x8000
+#define F_MISSED 0x10000
+#define F_ONCE 0x20000
+#define F_HDRINCL 0x40000
+#define F_MASK 0x80000
+#define F_TIME 0x100000
+#define F_SWEEP 0x200000
+#define F_WAITTIME 0x400000
+
+/*
+ * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
+ * number of received sequence numbers we can keep track of. Change 128
+ * to 8192 for complete accuracy...
+ */
+#define MAX_DUP_CHK (8 * 128)
+int mx_dup_ck = MAX_DUP_CHK;
+char rcvd_tbl[MAX_DUP_CHK / 8];
+
+struct sockaddr_in whereto; /* who to ping */
+int datalen = DEFDATALEN;
+int maxpayload;
+int s; /* socket file descriptor */
+u_char outpackhdr[IP_MAXPACKET], *outpack;
+char BBELL = '\a'; /* characters written for MISSED and AUDIBLE */
+char BSPACE = '\b'; /* characters written for flood */
+char DOT = '.';
+char *hostname;
+char *shostname;
+int ident; /* process id to identify our packets */
+int uid; /* cached uid for micro-optimization */
+u_char icmp_type = ICMP_ECHO;
+u_char icmp_type_rsp = ICMP_ECHOREPLY;
+int phdr_len = 0;
+int send_len;
+
+/* counters */
+long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
+long npackets; /* max packets to transmit */
+long nreceived; /* # of packets we got back */
+long nrepeats; /* number of duplicates */
+long ntransmitted; /* sequence # for outbound packets = #sent */
+long snpackets; /* max packets to transmit in one sweep */
+long snreceived; /* # of packets we got back in this sweep */
+long sntransmitted; /* # of packets we sent in this sweep */
+int sweepmax; /* max value of payload in sweep */
+int sweepmin = 0; /* start value of payload in sweep */
+int sweepincr = 1; /* payload increment in sweep */
+int interval = 1000; /* interval between packets, ms */
+int waittime = MAXWAIT; /* timeout for each packet */
+long nrcvtimeout = 0; /* # of packets we got back after waittime */
+
+/* timing */
+int timing; /* flag to do timing */
+double tmin = 999999999.0; /* minimum round trip time */
+double tmax = 0.0; /* maximum round trip time */
+double tsum = 0.0; /* sum of all times, for doing average */
+double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
+
+volatile sig_atomic_t finish_up; /* nonzero if we've been told to finish up */
+volatile sig_atomic_t siginfo_p;
+
+static void fill(char *, char *);
+static u_short in_cksum(u_short *, int);
+static void check_status(void);
+static void finish(void) __dead2;
+static void pinger(void);
+static char *pr_addr(struct in_addr);
+static char *pr_ntime(n_time);
+static void pr_icmph(struct icmp *);
+static void pr_iph(struct ip *);
+static void pr_pack(char *, int, struct sockaddr_in *, struct timeval *);
+static void pr_retip(struct ip *);
+static void status(int);
+static void stopit(int);
+static void tvsub(struct timeval *, struct timeval *);
+static void usage(void) __dead2;
+
+#ifdef __rtems__
+static int main_ping(int argc, char *const *argv);
+static int rtems_shell_main_ping(int argc, char *argv[])
+{
+ rtems_shell_globals_t ping_globals;
+ rtems_shell_globals = &ping_globals;
+ memset (rtems_shell_globals, 0, sizeof (ping_globals));
+ BBELL = '\a';
+ BSPACE = '\b';
+ DOT = '.';
+ icmp_type = ICMP_ECHO;
+ icmp_type_rsp = ICMP_ECHOREPLY;
+ phdr_len = 0;
+ sweepmin = 0;
+ sweepincr = 1;
+ interval = 1000;
+ waittime = MAXWAIT;
+ nrcvtimeout = 0;
+ tmin = 999999999.0;
+ tmax = 0.0;
+ tsum = 0.0;
+ tsumsq = 0.0;
+ ping_globals.exit_code = 1;
+ if (setjmp (ping_globals.exit_jmp) == 0)
+ return main_ping (argc, argv);
+ return ping_globals.exit_code;
+}
+#endif
+
+
+
+int
+#ifdef __rtems__
+main_ping(argc, argv)
+#else
+main(argc, argv)
+#endif
+ int argc;
+ char *const *argv;
+{
+ struct sockaddr_in from, sock_in;
+ struct in_addr ifaddr;
+ struct timeval last, intvl;
+ struct iovec iov;
+ struct ip *ip;
+ struct msghdr msg;
+ struct sigaction si_sa;
+ size_t sz;
+ u_char *datap, packet[IP_MAXPACKET] __aligned(4);
+ char *ep, *source, *target, *payload;
+ struct hostent *hp;
+#ifdef IPSEC_POLICY_IPSEC
+ char *policy_in, *policy_out;
+#endif
+ struct sockaddr_in *to;
+ double t;
+ u_long alarmtimeout, ultmp;
+ int almost_done, ch, df, hold, i, icmp_len, mib[4], preload, sockerrno,
+ tos, ttl;
+ char ctrl[CMSG_SPACE(sizeof(struct timeval))];
+ char hnamebuf[MAXHOSTNAMELEN], snamebuf[MAXHOSTNAMELEN];
+#ifdef IP_OPTIONS
+ char rspace[MAX_IPOPTLEN]; /* record route space */
+#endif
+ unsigned char loop, mttl;
+#ifdef __rtems__
+ struct getopt_data getopt_reent;
+#define optarg getopt_reent.optarg
+#define optind getopt_reent.optind
+#define opterr getopt.reent.opterr
+#define optopt getopt.reent.optopt
+#endif
+
+ payload = source = NULL;
+#ifdef IPSEC_POLICY_IPSEC
+ policy_in = policy_out = NULL;
+#endif
+
+ /*
+ * Do the stuff that we need root priv's for *first*, and
+ * then drop our setuid bit. Save error reporting for
+ * after arg parsing.
+ */
+ s = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP);
+ sockerrno = errno;
+
+ setuid(getuid());
+ uid = getuid();
+
+ alarmtimeout = df = preload = tos = 0;
+
+ outpack = outpackhdr + sizeof(struct ip);
+#ifdef __rtems__
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+ while ((ch = getopt_r(argc, argv,
+#else
+ while ((ch = getopt(argc, argv,
+#endif
+ "Aac:DdfG:g:h:I:i:Ll:M:m:nop:QqRrS:s:T:t:vW:z:"
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+ "P:"
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+#ifdef __rtems__
+ , &getopt_reent
+#endif
+ )) != -1)
+ {
+ switch(ch) {
+ case 'A':
+ options |= F_MISSED;
+ break;
+ case 'a':
+ options |= F_AUDIBLE;
+ break;
+ case 'c':
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg || ultmp > LONG_MAX || !ultmp)
+ errx(EX_USAGE,
+ "invalid count of packets to transmit: `%s'",
+ optarg);
+ npackets = ultmp;
+ break;
+ case 'D':
+ options |= F_HDRINCL;
+ df = 1;
+ break;
+ case 'd':
+ options |= F_SO_DEBUG;
+ break;
+ case 'f':
+ if (uid) {
+ errno = EPERM;
+ err(EX_NOPERM, "-f flag");
+ }
+ options |= F_FLOOD;
+ setbuf(stdout, (char *)NULL);
+ break;
+ case 'G': /* Maximum packet size for ping sweep */
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg)
+ errx(EX_USAGE, "invalid packet size: `%s'",
+ optarg);
+ if (uid != 0 && ultmp > DEFDATALEN) {
+ errno = EPERM;
+ err(EX_NOPERM,
+ "packet size too large: %lu > %u",
+ ultmp, DEFDATALEN);
+ }
+ options |= F_SWEEP;
+ sweepmax = ultmp;
+ break;
+ case 'g': /* Minimum packet size for ping sweep */
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg)
+ errx(EX_USAGE, "invalid packet size: `%s'",
+ optarg);
+ if (uid != 0 && ultmp > DEFDATALEN) {
+ errno = EPERM;
+ err(EX_NOPERM,
+ "packet size too large: %lu > %u",
+ ultmp, DEFDATALEN);
+ }
+ options |= F_SWEEP;
+ sweepmin = ultmp;
+ break;
+ case 'h': /* Packet size increment for ping sweep */
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg || ultmp < 1)
+ errx(EX_USAGE, "invalid increment size: `%s'",
+ optarg);
+ if (uid != 0 && ultmp > DEFDATALEN) {
+ errno = EPERM;
+ err(EX_NOPERM,
+ "packet size too large: %lu > %u",
+ ultmp, DEFDATALEN);
+ }
+ options |= F_SWEEP;
+ sweepincr = ultmp;
+ break;
+ case 'I': /* multicast interface */
+ if (inet_aton(optarg, &ifaddr) == 0)
+ errx(EX_USAGE,
+ "invalid multicast interface: `%s'",
+ optarg);
+ options |= F_MIF;
+ break;
+ case 'i': /* wait between sending packets */
+ t = strtod(optarg, &ep) * 1000.0;
+ if (*ep || ep == optarg || t > (double)INT_MAX)
+ errx(EX_USAGE, "invalid timing interval: `%s'",
+ optarg);
+ options |= F_INTERVAL;
+ interval = (int)t;
+ if (uid && interval < 1000) {
+ errno = EPERM;
+ err(EX_NOPERM, "-i interval too short");
+ }
+ break;
+ case 'L':
+ options |= F_NOLOOP;
+ loop = 0;
+ break;
+ case 'l':
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg || ultmp > INT_MAX)
+ errx(EX_USAGE,
+ "invalid preload value: `%s'", optarg);
+ if (uid) {
+ errno = EPERM;
+ err(EX_NOPERM, "-l flag");
+ }
+ preload = ultmp;
+ break;
+ case 'M':
+ switch(optarg[0]) {
+ case 'M':
+ case 'm':
+ options |= F_MASK;
+ break;
+ case 'T':
+ case 't':
+ options |= F_TIME;
+ break;
+ default:
+ errx(EX_USAGE, "invalid message: `%c'", optarg[0]);
+ break;
+ }
+ break;
+ case 'm': /* TTL */
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg || ultmp > MAXTTL)
+ errx(EX_USAGE, "invalid TTL: `%s'", optarg);
+ ttl = ultmp;
+ options |= F_TTL;
+ break;
+ case 'n':
+ options |= F_NUMERIC;
+ break;
+ case 'o':
+ options |= F_ONCE;
+ break;
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+ case 'P':
+ options |= F_POLICY;
+ if (!strncmp("in", optarg, 2))
+ policy_in = strdup(optarg);
+ else if (!strncmp("out", optarg, 3))
+ policy_out = strdup(optarg);
+ else
+ errx(1, "invalid security policy");
+ break;
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+ case 'p': /* fill buffer with user pattern */
+ options |= F_PINGFILLED;
+ payload = optarg;
+ break;
+ case 'Q':
+ options |= F_QUIET2;
+ break;
+ case 'q':
+ options |= F_QUIET;
+ break;
+ case 'R':
+ options |= F_RROUTE;
+ break;
+ case 'r':
+ options |= F_SO_DONTROUTE;
+ break;
+ case 'S':
+ source = optarg;
+ break;
+ case 's': /* size of packet to send */
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg)
+ errx(EX_USAGE, "invalid packet size: `%s'",
+ optarg);
+ if (uid != 0 && ultmp > DEFDATALEN) {
+ errno = EPERM;
+ err(EX_NOPERM,
+ "packet size too large: %lu > %u",
+ ultmp, DEFDATALEN);
+ }
+ datalen = ultmp;
+ break;
+ case 'T': /* multicast TTL */
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg || ultmp > MAXTTL)
+ errx(EX_USAGE, "invalid multicast TTL: `%s'",
+ optarg);
+ mttl = ultmp;
+ options |= F_MTTL;
+ break;
+ case 't':
+ alarmtimeout = strtoul(optarg, &ep, 0);
+ if ((alarmtimeout < 1) || (alarmtimeout == ULONG_MAX))
+ errx(EX_USAGE, "invalid timeout: `%s'",
+ optarg);
+ if (alarmtimeout > MAXALARM)
+ errx(EX_USAGE, "invalid timeout: `%s' > %d",
+ optarg, MAXALARM);
+ alarm((int)alarmtimeout);
+ break;
+ case 'v':
+ options |= F_VERBOSE;
+ break;
+ case 'W': /* wait ms for answer */
+ t = strtod(optarg, &ep);
+ if (*ep || ep == optarg || t > (double)INT_MAX)
+ errx(EX_USAGE, "invalid timing interval: `%s'",
+ optarg);
+ options |= F_WAITTIME;
+ waittime = (int)t;
+ break;
+ case 'z':
+ options |= F_HDRINCL;
+ ultmp = strtoul(optarg, &ep, 0);
+ if (*ep || ep == optarg || ultmp > MAXTOS)
+ errx(EX_USAGE, "invalid TOS: `%s'", optarg);
+ tos = ultmp;
+ break;
+ default:
+ usage();
+
+ }
+ }
+
+ if (argc - optind != 1)
+ usage();
+
+ target = argv[optind];
+
+ switch (options & (F_MASK|F_TIME)) {
+ case 0: break;
+ case F_MASK:
+ icmp_type = ICMP_MASKREQ;
+ icmp_type_rsp = ICMP_MASKREPLY;
+ phdr_len = MASK_LEN;
+ if (!(options & F_QUIET))
+ (void)printf("ICMP_MASKREQ\n");
+ break;
+ case F_TIME:
+ icmp_type = ICMP_TSTAMP;
+ icmp_type_rsp = ICMP_TSTAMPREPLY;
+ phdr_len = TS_LEN;
+ if (!(options & F_QUIET))
+ (void)printf("ICMP_TSTAMP\n");
+ break;
+ default:
+ errx(EX_USAGE, "ICMP_TSTAMP and ICMP_MASKREQ are exclusive.");
+ break;
+ }
+ icmp_len = sizeof(struct ip) + ICMP_MINLEN + phdr_len;
+ if (options & F_RROUTE)
+ icmp_len += MAX_IPOPTLEN;
+ maxpayload = IP_MAXPACKET - icmp_len;
+ if (datalen > maxpayload)
+ errx(EX_USAGE, "packet size too large: %d > %d", datalen,
+ maxpayload);
+ send_len = icmp_len + datalen;
+ datap = &outpack[ICMP_MINLEN + phdr_len + TIMEVAL_LEN];
+ if (options & F_PINGFILLED) {
+ fill((char *)datap, payload);
+ }
+ if (source) {
+ bzero((char *)&sock_in, sizeof(sock_in));
+ sock_in.sin_family = AF_INET;
+ if (inet_aton(source, &sock_in.sin_addr) != 0) {
+ shostname = source;
+ } else {
+ hp = gethostbyname2(source, AF_INET);
+ if (!hp)
+ errx(EX_NOHOST, "cannot resolve %s: %s",
+ source, hstrerror(h_errno));
+
+ sock_in.sin_len = sizeof sock_in;
+ if ((unsigned)hp->h_length > sizeof(sock_in.sin_addr) ||
+ hp->h_length < 0)
+ errx(1, "gethostbyname2: illegal address");
+ memcpy(&sock_in.sin_addr, hp->h_addr_list[0],
+ sizeof(sock_in.sin_addr));
+ (void)strncpy(snamebuf, hp->h_name,
+ sizeof(snamebuf) - 1);
+ snamebuf[sizeof(snamebuf) - 1] = '\0';
+ shostname = snamebuf;
+ }
+ if (bind(s, (struct sockaddr *)&sock_in, sizeof sock_in) == -1)
+ err(1, "bind");
+ }
+
+ bzero(&whereto, sizeof(whereto));
+ to = &whereto;
+ to->sin_family = AF_INET;
+ to->sin_len = sizeof *to;
+ if (inet_aton(target, &to->sin_addr) != 0) {
+ hostname = target;
+ } else {
+ hp = gethostbyname2(target, AF_INET);
+ if (!hp)
+ errx(EX_NOHOST, "cannot resolve %s: %s",
+ target, hstrerror(h_errno));
+
+ if ((unsigned)hp->h_length > sizeof(to->sin_addr))
+ errx(1, "gethostbyname2 returned an illegal address");
+ memcpy(&to->sin_addr, hp->h_addr_list[0], sizeof to->sin_addr);
+ (void)strncpy(hnamebuf, hp->h_name, sizeof(hnamebuf) - 1);
+ hnamebuf[sizeof(hnamebuf) - 1] = '\0';
+ hostname = hnamebuf;
+ }
+
+ if (options & F_FLOOD && options & F_INTERVAL)
+ errx(EX_USAGE, "-f and -i: incompatible options");
+
+ if (options & F_FLOOD && IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
+ errx(EX_USAGE,
+ "-f flag cannot be used with multicast destination");
+ if (options & (F_MIF | F_NOLOOP | F_MTTL)
+ && !IN_MULTICAST(ntohl(to->sin_addr.s_addr)))
+ errx(EX_USAGE,
+ "-I, -L, -T flags cannot be used with unicast destination");
+
+ if (datalen >= TIMEVAL_LEN) /* can we time transfer */
+ timing = 1;
+
+ if (!(options & F_PINGFILLED))
+ for (i = TIMEVAL_LEN; i < datalen; ++i)
+ *datap++ = i;
+
+ ident = getpid() & 0xFFFF;
+
+ if (s < 0) {
+ errno = sockerrno;
+ err(EX_OSERR, "socket");
+ }
+ hold = 1;
+ if (options & F_SO_DEBUG)
+ (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold,
+ sizeof(hold));
+ if (options & F_SO_DONTROUTE)
+ (void)setsockopt(s, SOL_SOCKET, SO_DONTROUTE, (char *)&hold,
+ sizeof(hold));
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+ if (options & F_POLICY) {
+ char *buf;
+ if (policy_in != NULL) {
+ buf = ipsec_set_policy(policy_in, strlen(policy_in));
+ if (buf == NULL)
+ errx(EX_CONFIG, "%s", ipsec_strerror());
+ if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
+ buf, ipsec_get_policylen(buf)) < 0)
+ err(EX_CONFIG,
+ "ipsec policy cannot be configured");
+ free(buf);
+ }
+
+ if (policy_out != NULL) {
+ buf = ipsec_set_policy(policy_out, strlen(policy_out));
+ if (buf == NULL)
+ errx(EX_CONFIG, "%s", ipsec_strerror());
+ if (setsockopt(s, IPPROTO_IP, IP_IPSEC_POLICY,
+ buf, ipsec_get_policylen(buf)) < 0)
+ err(EX_CONFIG,
+ "ipsec policy cannot be configured");
+ free(buf);
+ }
+ }
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+
+ if (options & F_HDRINCL) {
+ ip = (struct ip*)outpackhdr;
+ if (!(options & (F_TTL | F_MTTL))) {
+ mib[0] = CTL_NET;
+ mib[1] = PF_INET;
+ mib[2] = IPPROTO_IP;
+ mib[3] = IPCTL_DEFTTL;
+ sz = sizeof(ttl);
+ if (sysctl(mib, 4, &ttl, &sz, NULL, 0) == -1)
+ err(1, "sysctl(net.inet.ip.ttl)");
+ }
+ setsockopt(s, IPPROTO_IP, IP_HDRINCL, &hold, sizeof(hold));
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = sizeof(struct ip) >> 2;
+ ip->ip_tos = tos;
+ ip->ip_id = 0;
+ ip->ip_off = df ? IP_DF : 0;
+ ip->ip_ttl = ttl;
+ ip->ip_p = IPPROTO_ICMP;
+ ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY;
+ ip->ip_dst = to->sin_addr;
+ }
+ /* record route option */
+ if (options & F_RROUTE) {
+#ifdef IP_OPTIONS
+ bzero(rspace, sizeof(rspace));
+ rspace[IPOPT_OPTVAL] = IPOPT_RR;
+ rspace[IPOPT_OLEN] = sizeof(rspace) - 1;
+ rspace[IPOPT_OFFSET] = IPOPT_MINOFF;
+ rspace[sizeof(rspace) - 1] = IPOPT_EOL;
+ if (setsockopt(s, IPPROTO_IP, IP_OPTIONS, rspace,
+ sizeof(rspace)) < 0)
+ err(EX_OSERR, "setsockopt IP_OPTIONS");
+#else
+ errx(EX_UNAVAILABLE,
+ "record route not available in this implementation");
+#endif /* IP_OPTIONS */
+ }
+
+ if (options & F_TTL) {
+ if (setsockopt(s, IPPROTO_IP, IP_TTL, &ttl,
+ sizeof(ttl)) < 0) {
+ err(EX_OSERR, "setsockopt IP_TTL");
+ }
+ }
+ if (options & F_NOLOOP) {
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_LOOP, &loop,
+ sizeof(loop)) < 0) {
+ err(EX_OSERR, "setsockopt IP_MULTICAST_LOOP");
+ }
+ }
+ if (options & F_MTTL) {
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_TTL, &mttl,
+ sizeof(mttl)) < 0) {
+ err(EX_OSERR, "setsockopt IP_MULTICAST_TTL");
+ }
+ }
+ if (options & F_MIF) {
+ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr,
+ sizeof(ifaddr)) < 0) {
+ err(EX_OSERR, "setsockopt IP_MULTICAST_IF");
+ }
+ }
+#ifdef SO_TIMESTAMP
+ { int on = 1;
+ if (setsockopt(s, SOL_SOCKET, SO_TIMESTAMP, &on, sizeof(on)) < 0)
+ err(EX_OSERR, "setsockopt SO_TIMESTAMP");
+ }
+#endif
+ if (sweepmax) {
+ if (sweepmin >= sweepmax)
+ errx(EX_USAGE, "Maximum packet size must be greater than the minimum packet size");
+
+ if (datalen != DEFDATALEN)
+ errx(EX_USAGE, "Packet size and ping sweep are mutually exclusive");
+
+ if (npackets > 0) {
+ snpackets = npackets;
+ npackets = 0;
+ } else
+ snpackets = 1;
+ datalen = sweepmin;
+ send_len = icmp_len + sweepmin;
+ }
+ if (options & F_SWEEP && !sweepmax)
+ errx(EX_USAGE, "Maximum sweep size must be specified");
+
+ /*
+ * When pinging the broadcast address, you can get a lot of answers.
+ * Doing something so evil is useful if you are trying to stress the
+ * ethernet, or just want to fill the arp cache to get some stuff for
+ * /etc/ethers. But beware: RFC 1122 allows hosts to ignore broadcast
+ * or multicast pings if they wish.
+ */
+
+ /*
+ * XXX receive buffer needs undetermined space for mbuf overhead
+ * as well.
+ */
+ hold = IP_MAXPACKET + 128;
+ (void)setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
+ sizeof(hold));
+ if (uid == 0)
+ (void)setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&hold,
+ sizeof(hold));
+
+ if (to->sin_family == AF_INET) {
+ (void)printf("PING %s (%s)", hostname,
+ inet_ntoa(to->sin_addr));
+ if (source)
+ (void)printf(" from %s", shostname);
+ if (sweepmax)
+ (void)printf(": (%d ... %d) data bytes\n",
+ sweepmin, sweepmax);
+ else
+ (void)printf(": %d data bytes\n", datalen);
+
+ } else {
+ if (sweepmax)
+ (void)printf("PING %s: (%d ... %d) data bytes\n",
+ hostname, sweepmin, sweepmax);
+ else
+ (void)printf("PING %s: %d data bytes\n", hostname, datalen);
+ }
+
+ /*
+ * Use sigaction() instead of signal() to get unambiguous semantics,
+ * in particular with SA_RESTART not set.
+ */
+
+ sigemptyset(&si_sa.sa_mask);
+ si_sa.sa_flags = 0;
+
+ si_sa.sa_handler = stopit;
+ if (sigaction(SIGINT, &si_sa, 0) == -1) {
+ err(EX_OSERR, "sigaction SIGINT");
+ }
+
+#ifdef SIGINFO
+ si_sa.sa_handler = status;
+ if (sigaction(SIGINFO, &si_sa, 0) == -1) {
+ err(EX_OSERR, "sigaction");
+ }
+#endif
+
+ if (alarmtimeout > 0) {
+ si_sa.sa_handler = stopit;
+ if (sigaction(SIGALRM, &si_sa, 0) == -1)
+ err(EX_OSERR, "sigaction SIGALRM");
+ }
+
+ bzero(&msg, sizeof(msg));
+ msg.msg_name = (caddr_t)&from;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+#ifdef SO_TIMESTAMP
+ msg.msg_control = (caddr_t)ctrl;
+#endif
+ iov.iov_base = packet;
+ iov.iov_len = IP_MAXPACKET;
+
+ if (preload == 0)
+ pinger(); /* send the first ping */
+ else {
+ if (npackets != 0 && preload > npackets)
+ preload = npackets;
+ while (preload--) /* fire off them quickies */
+ pinger();
+ }
+ (void)gettimeofday(&last, NULL);
+
+ if (options & F_FLOOD) {
+ intvl.tv_sec = 0;
+ intvl.tv_usec = 10000;
+ } else {
+ intvl.tv_sec = interval / 1000;
+ intvl.tv_usec = interval % 1000 * 1000;
+ }
+
+ almost_done = 0;
+ while (!finish_up) {
+ struct timeval now, timeout;
+ fd_set rfds;
+ int cc, n;
+
+ check_status();
+ if ((unsigned)s >= FD_SETSIZE)
+ errx(EX_OSERR, "descriptor too large");
+ FD_ZERO(&rfds);
+ FD_SET(s, &rfds);
+ (void)gettimeofday(&now, NULL);
+ timeout.tv_sec = last.tv_sec + intvl.tv_sec - now.tv_sec;
+ timeout.tv_usec = last.tv_usec + intvl.tv_usec - now.tv_usec;
+ while (timeout.tv_usec < 0) {
+ timeout.tv_usec += 1000000;
+ timeout.tv_sec--;
+ }
+ while (timeout.tv_usec >= 1000000) {
+ timeout.tv_usec -= 1000000;
+ timeout.tv_sec++;
+ }
+ if (timeout.tv_sec < 0)
+ timeout.tv_sec = timeout.tv_usec = 0;
+ n = select(s + 1, &rfds, NULL, NULL, &timeout);
+ if (n < 0)
+ continue; /* Must be EINTR. */
+ if (n == 1) {
+ struct timeval *tv = NULL;
+#ifdef SO_TIMESTAMP
+ struct cmsghdr *cmsg = (struct cmsghdr *)&ctrl;
+
+ msg.msg_controllen = sizeof(ctrl);
+#endif
+ msg.msg_namelen = sizeof(from);
+ if ((cc = recvmsg(s, &msg, 0)) < 0) {
+ if (errno == EINTR)
+ continue;
+ warn("recvmsg");
+ continue;
+ }
+#ifdef SO_TIMESTAMP
+ if (cmsg->cmsg_level == SOL_SOCKET &&
+ cmsg->cmsg_type == SCM_TIMESTAMP &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof *tv)) {
+ /* Copy to avoid alignment problems: */
+ memcpy(&now, CMSG_DATA(cmsg), sizeof(now));
+ tv = &now;
+ }
+#endif
+ if (tv == NULL) {
+ (void)gettimeofday(&now, NULL);
+ tv = &now;
+ }
+ pr_pack((char *)packet, cc, &from, tv);
+ if ((options & F_ONCE && nreceived) ||
+ (npackets && nreceived >= npackets))
+ break;
+ }
+ if (n == 0 || options & F_FLOOD) {
+ if (sweepmax && sntransmitted == snpackets) {
+ for (i = 0; i < sweepincr ; ++i)
+ *datap++ = i;
+ datalen += sweepincr;
+ if (datalen > sweepmax)
+ break;
+ send_len = icmp_len + datalen;
+ sntransmitted = 0;
+ }
+ if (!npackets || ntransmitted < npackets)
+ pinger();
+ else {
+ if (almost_done)
+ break;
+ almost_done = 1;
+ intvl.tv_usec = 0;
+ if (nreceived) {
+ intvl.tv_sec = 2 * tmax / 1000;
+ if (!intvl.tv_sec)
+ intvl.tv_sec = 1;
+ } else {
+ intvl.tv_sec = waittime / 1000;
+ intvl.tv_usec = waittime % 1000 * 1000;
+ }
+ }
+ (void)gettimeofday(&last, NULL);
+ if (ntransmitted - nreceived - 1 > nmissedmax) {
+ nmissedmax = ntransmitted - nreceived - 1;
+ if (options & F_MISSED)
+ (void)write(STDOUT_FILENO, &BBELL, 1);
+ }
+ }
+ }
+ finish();
+#ifdef __rtems__
+ /* RTEMS shell programs return -- they do not exit */
+ if (nreceived)
+ return(0);
+ else
+ return(2);
+#endif
+ /* NOTREACHED */
+ exit(0); /* Make the compiler happy */
+}
+
+/*
+ * stopit --
+ * Set the global bit that causes the main loop to quit.
+ * Do NOT call finish() from here, since finish() does far too much
+ * to be called from a signal handler.
+ */
+void
+stopit(sig)
+ int sig __unused;
+{
+
+ /*
+ * When doing reverse DNS lookups, the finish_up flag might not
+ * be noticed for a while. Just exit if we get a second SIGINT.
+ */
+ if (!(options & F_NUMERIC) && finish_up)
+ _exit(nreceived ? 0 : 2);
+ finish_up = 1;
+}
+
+/*
+ * pinger --
+ * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
+ * will be added on by the kernel. The ID field is our UNIX process ID,
+ * and the sequence number is an ascending integer. The first TIMEVAL_LEN
+ * bytes of the data portion are used to hold a UNIX "timeval" struct in
+ * host byte-order, to compute the round-trip time.
+ */
+static void
+pinger(void)
+{
+ struct timeval now;
+ struct tv32 tv32;
+ struct ip *ip;
+ struct icmp *icp;
+ int cc, i;
+ u_char *packet;
+
+ packet = outpack;
+ icp = (struct icmp *)outpack;
+ icp->icmp_type = icmp_type;
+ icp->icmp_code = 0;
+ icp->icmp_cksum = 0;
+ icp->icmp_seq = htons(ntransmitted);
+ icp->icmp_id = ident; /* ID */
+
+ CLR(ntransmitted % mx_dup_ck);
+
+ if ((options & F_TIME) || timing) {
+ (void)gettimeofday(&now, NULL);
+
+ tv32.tv32_sec = htonl(now.tv_sec);
+ tv32.tv32_usec = htonl(now.tv_usec);
+ if (options & F_TIME)
+ icp->icmp_otime = htonl((now.tv_sec % (24*60*60))
+ * 1000 + now.tv_usec / 1000);
+ if (timing)
+ bcopy((void *)&tv32,
+ (void *)&outpack[ICMP_MINLEN + phdr_len],
+ sizeof(tv32));
+ }
+
+ cc = ICMP_MINLEN + phdr_len + datalen;
+
+ /* compute ICMP checksum here */
+ icp->icmp_cksum = in_cksum((u_short *)icp, cc);
+
+ if (options & F_HDRINCL) {
+ cc += sizeof(struct ip);
+ ip = (struct ip *)outpackhdr;
+ ip->ip_len = cc;
+ ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
+ packet = outpackhdr;
+ }
+ i = sendto(s, (char *)packet, cc, 0, (struct sockaddr *)&whereto,
+ sizeof(whereto));
+
+ if (i < 0 || i != cc) {
+ if (i < 0) {
+ if (options & F_FLOOD && errno == ENOBUFS) {
+ usleep(FLOOD_BACKOFF);
+ return;
+ }
+ warn("sendto");
+ } else {
+ warn("%s: partial write: %d of %d bytes",
+ hostname, i, cc);
+ }
+ }
+ ntransmitted++;
+ sntransmitted++;
+ if (!(options & F_QUIET) && options & F_FLOOD)
+ (void)write(STDOUT_FILENO, &DOT, 1);
+}
+
+/*
+ * pr_pack --
+ * Print out the packet, if it came from us. This logic is necessary
+ * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
+ * which arrive ('tis only fair). This permits multiple copies of this
+ * program to be run without having intermingled output (or statistics!).
+ */
+static void
+pr_pack(buf, cc, from, tv)
+ char *buf;
+ int cc;
+ struct sockaddr_in *from;
+ struct timeval *tv;
+{
+ struct in_addr ina;
+ u_char *cp, *dp;
+ struct icmp *icp;
+ struct ip *ip;
+ const void *tp;
+ double triptime;
+ int dupflag, hlen, i, j, recv_len, seq;
+ static int old_rrlen;
+ static char old_rr[MAX_IPOPTLEN];
+
+ /* Check the IP header */
+ ip = (struct ip *)buf;
+ hlen = ip->ip_hl << 2;
+ recv_len = cc;
+ if (cc < hlen + ICMP_MINLEN) {
+ if (options & F_VERBOSE)
+ warn("packet too short (%d bytes) from %s", cc,
+ inet_ntoa(from->sin_addr));
+ return;
+ }
+
+ /* Now the ICMP part */
+ cc -= hlen;
+ icp = (struct icmp *)(buf + hlen);
+ if (icp->icmp_type == icmp_type_rsp) {
+ if (icp->icmp_id != ident)
+ return; /* 'Twas not our ECHO */
+ ++nreceived;
+ triptime = 0.0;
+ if (timing) {
+ struct timeval tv1;
+ struct tv32 tv32;
+#ifndef icmp_data
+ tp = &icp->icmp_ip;
+#else
+ tp = icp->icmp_data;
+#endif
+ tp = (const char *)tp + phdr_len;
+
+ if (cc - ICMP_MINLEN - phdr_len >= sizeof(tv1)) {
+ /* Copy to avoid alignment problems: */
+ memcpy(&tv32, tp, sizeof(tv32));
+ tv1.tv_sec = ntohl(tv32.tv32_sec);
+ tv1.tv_usec = ntohl(tv32.tv32_usec);
+ tvsub(tv, &tv1);
+ triptime = ((double)tv->tv_sec) * 1000.0 +
+ ((double)tv->tv_usec) / 1000.0;
+ tsum += triptime;
+ tsumsq += triptime * triptime;
+ if (triptime < tmin)
+ tmin = triptime;
+ if (triptime > tmax)
+ tmax = triptime;
+ } else
+ timing = 0;
+ }
+
+ seq = ntohs(icp->icmp_seq);
+
+ if (TST(seq % mx_dup_ck)) {
+ ++nrepeats;
+ --nreceived;
+ dupflag = 1;
+ } else {
+ SET(seq % mx_dup_ck);
+ dupflag = 0;
+ }
+
+ if (options & F_QUIET)
+ return;
+
+ if (options & F_WAITTIME && triptime > waittime) {
+ ++nrcvtimeout;
+ return;
+ }
+
+ if (options & F_FLOOD)
+ (void)write(STDOUT_FILENO, &BSPACE, 1);
+ else {
+ (void)printf("%d bytes from %s: icmp_seq=%u", cc,
+ inet_ntoa(*(struct in_addr *)&from->sin_addr.s_addr),
+ seq);
+ (void)printf(" ttl=%d", ip->ip_ttl);
+ if (timing)
+ (void)printf(" time=%.3f ms", triptime);
+ if (dupflag)
+ (void)printf(" (DUP!)");
+ if (options & F_AUDIBLE)
+ (void)write(STDOUT_FILENO, &BBELL, 1);
+ if (options & F_MASK) {
+ /* Just prentend this cast isn't ugly */
+ (void)printf(" mask=%s",
+ pr_addr(*(struct in_addr *)&(icp->icmp_mask)));
+ }
+ if (options & F_TIME) {
+ (void)printf(" tso=%s", pr_ntime(icp->icmp_otime));
+ (void)printf(" tsr=%s", pr_ntime(icp->icmp_rtime));
+ (void)printf(" tst=%s", pr_ntime(icp->icmp_ttime));
+ }
+ if (recv_len != send_len) {
+ (void)printf(
+ "\nwrong total length %d instead of %d",
+ recv_len, send_len);
+ }
+ /* check the data */
+ cp = (u_char*)&icp->icmp_data[phdr_len];
+ dp = &outpack[ICMP_MINLEN + phdr_len];
+ cc -= ICMP_MINLEN + phdr_len;
+ i = 0;
+ if (timing) { /* don't check variable timestamp */
+ cp += TIMEVAL_LEN;
+ dp += TIMEVAL_LEN;
+ cc -= TIMEVAL_LEN;
+ i += TIMEVAL_LEN;
+ }
+ for (; i < datalen && cc > 0; ++i, ++cp, ++dp, --cc) {
+ if (*cp != *dp) {
+ (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x",
+ i, *dp, *cp);
+ (void)printf("\ncp:");
+ cp = (u_char*)&icp->icmp_data[0];
+ for (i = 0; i < datalen; ++i, ++cp) {
+ if ((i % 16) == 8)
+ (void)printf("\n\t");
+ (void)printf("%2x ", *cp);
+ }
+ (void)printf("\ndp:");
+ cp = &outpack[ICMP_MINLEN];
+ for (i = 0; i < datalen; ++i, ++cp) {
+ if ((i % 16) == 8)
+ (void)printf("\n\t");
+ (void)printf("%2x ", *cp);
+ }
+ break;
+ }
+ }
+ }
+ } else {
+ /*
+ * We've got something other than an ECHOREPLY.
+ * See if it's a reply to something that we sent.
+ * We can compare IP destination, protocol,
+ * and ICMP type and ID.
+ *
+ * Only print all the error messages if we are running
+ * as root to avoid leaking information not normally
+ * available to those not running as root.
+ */
+#ifndef icmp_data
+ struct ip *oip = &icp->icmp_ip;
+#else
+ struct ip *oip = (struct ip *)icp->icmp_data;
+#endif
+ struct icmp *oicmp = (struct icmp *)(oip + 1);
+
+ if (((options & F_VERBOSE) && uid == 0) ||
+ (!(options & F_QUIET2) &&
+ (oip->ip_dst.s_addr == whereto.sin_addr.s_addr) &&
+ (oip->ip_p == IPPROTO_ICMP) &&
+ (oicmp->icmp_type == ICMP_ECHO) &&
+ (oicmp->icmp_id == ident))) {
+ (void)printf("%d bytes from %s: ", cc,
+ pr_addr(from->sin_addr));
+ pr_icmph(icp);
+ } else
+ return;
+ }
+
+ /* Display any IP options */
+ cp = (u_char *)buf + sizeof(struct ip);
+
+ for (; hlen > (int)sizeof(struct ip); --hlen, ++cp)
+ switch (*cp) {
+ case IPOPT_EOL:
+ hlen = 0;
+ break;
+ case IPOPT_LSRR:
+ case IPOPT_SSRR:
+ (void)printf(*cp == IPOPT_LSRR ?
+ "\nLSRR: " : "\nSSRR: ");
+ j = cp[IPOPT_OLEN] - IPOPT_MINOFF + 1;
+ hlen -= 2;
+ cp += 2;
+ if (j >= INADDR_LEN &&
+ j <= hlen - (int)sizeof(struct ip)) {
+ for (;;) {
+ bcopy(++cp, &ina.s_addr, INADDR_LEN);
+ if (ina.s_addr == 0)
+ (void)printf("\t0.0.0.0");
+ else
+ (void)printf("\t%s",
+ pr_addr(ina));
+ hlen -= INADDR_LEN;
+ cp += INADDR_LEN - 1;
+ j -= INADDR_LEN;
+ if (j < INADDR_LEN)
+ break;
+ (void)putchar('\n');
+ }
+ } else
+ (void)printf("\t(truncated route)\n");
+ break;
+ case IPOPT_RR:
+ j = cp[IPOPT_OLEN]; /* get length */
+ i = cp[IPOPT_OFFSET]; /* and pointer */
+ hlen -= 2;
+ cp += 2;
+ if (i > j)
+ i = j;
+ i = i - IPOPT_MINOFF + 1;
+ if (i < 0 || i > (hlen - (int)sizeof(struct ip))) {
+ old_rrlen = 0;
+ continue;
+ }
+ if (i == old_rrlen
+ && !bcmp((char *)cp, old_rr, i)
+ && !(options & F_FLOOD)) {
+ (void)printf("\t(same route)");
+ hlen -= i;
+ cp += i;
+ break;
+ }
+ old_rrlen = i;
+ bcopy((char *)cp, old_rr, i);
+ (void)printf("\nRR: ");
+ if (i >= INADDR_LEN &&
+ i <= hlen - (int)sizeof(struct ip)) {
+ for (;;) {
+ bcopy(++cp, &ina.s_addr, INADDR_LEN);
+ if (ina.s_addr == 0)
+ (void)printf("\t0.0.0.0");
+ else
+ (void)printf("\t%s",
+ pr_addr(ina));
+ hlen -= INADDR_LEN;
+ cp += INADDR_LEN - 1;
+ i -= INADDR_LEN;
+ if (i < INADDR_LEN)
+ break;
+ (void)putchar('\n');
+ }
+ } else
+ (void)printf("\t(truncated route)");
+ break;
+ case IPOPT_NOP:
+ (void)printf("\nNOP");
+ break;
+ default:
+ (void)printf("\nunknown option %x", *cp);
+ break;
+ }
+ if (!(options & F_FLOOD)) {
+ (void)putchar('\n');
+ (void)fflush(stdout);
+ }
+}
+
+/*
+ * in_cksum --
+ * Checksum routine for Internet Protocol family headers (C Version)
+ */
+u_short
+in_cksum(addr, len)
+ u_short *addr;
+ int len;
+{
+ int nleft, sum;
+ u_short *w;
+ union {
+ u_short us;
+ u_char uc[2];
+ } last;
+ u_short answer;
+
+ nleft = len;
+ sum = 0;
+ w = addr;
+
+ /*
+ * Our algorithm is simple, using a 32 bit accumulator (sum), we add
+ * sequential 16 bit words to it, and at the end, fold back all the
+ * carry bits from the top 16 bits into the lower 16 bits.
+ */
+ while (nleft > 1) {
+ sum += *w++;
+ nleft -= 2;
+ }
+
+ /* mop up an odd byte, if necessary */
+ if (nleft == 1) {
+ last.uc[0] = *(u_char *)w;
+ last.uc[1] = 0;
+ sum += last.us;
+ }
+
+ /* add back carry outs from top 16 bits to low 16 bits */
+ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */
+ sum += (sum >> 16); /* add carry */
+ answer = ~sum; /* truncate to 16 bits */
+ return(answer);
+}
+
+/*
+ * tvsub --
+ * Subtract 2 timeval structs: out = out - in. Out is assumed to
+ * be >= in.
+ */
+static void
+tvsub(out, in)
+ struct timeval *out, *in;
+{
+
+ if ((out->tv_usec -= in->tv_usec) < 0) {
+ --out->tv_sec;
+ out->tv_usec += 1000000;
+ }
+ out->tv_sec -= in->tv_sec;
+}
+
+/*
+ * status --
+ * Print out statistics when SIGINFO is received.
+ */
+
+static void
+status(sig)
+ int sig __unused;
+{
+
+ siginfo_p = 1;
+}
+
+static void
+check_status()
+{
+
+ if (siginfo_p) {
+ siginfo_p = 0;
+ (void)fprintf(stderr, "\r%ld/%ld packets received (%.1f%%)",
+ nreceived, ntransmitted,
+ ntransmitted ? nreceived * 100.0 / ntransmitted : 0.0);
+ if (nreceived && timing)
+ (void)fprintf(stderr, " %.3f min / %.3f avg / %.3f max",
+ tmin, tsum / (nreceived + nrepeats), tmax);
+ (void)fprintf(stderr, "\n");
+ }
+}
+
+/*
+ * finish --
+ * Print out statistics, and give up.
+ */
+static void
+finish()
+{
+
+ (void)signal(SIGINT, SIG_IGN);
+ (void)signal(SIGALRM, SIG_IGN);
+ (void)putchar('\n');
+ (void)fflush(stdout);
+ (void)printf("--- %s ping statistics ---\n", hostname);
+ (void)printf("%ld packets transmitted, ", ntransmitted);
+ (void)printf("%ld packets received, ", nreceived);
+ if (nrepeats)
+ (void)printf("+%ld duplicates, ", nrepeats);
+ if (ntransmitted) {
+ if (nreceived > ntransmitted)
+ (void)printf("-- somebody's printing up packets!");
+ else
+ (void)printf("%.1f%% packet loss",
+ ((ntransmitted - nreceived) * 100.0) /
+ ntransmitted);
+ }
+ if (nrcvtimeout)
+ (void)printf(", %ld packets out of wait time", nrcvtimeout);
+ (void)putchar('\n');
+ if (nreceived && timing) {
+ double n = nreceived + nrepeats;
+ double avg = tsum / n;
+ double vari = tsumsq / n - avg * avg;
+ (void)printf(
+ "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms\n",
+ tmin, avg, tmax, sqrt(vari));
+ }
+ if (nreceived)
+ exit(0);
+ else
+ exit(2);
+}
+
+#ifdef notdef
+static char *ttab[] = {
+ "Echo Reply", /* ip + seq + udata */
+ "Dest Unreachable", /* net, host, proto, port, frag, sr + IP */
+ "Source Quench", /* IP */
+ "Redirect", /* redirect type, gateway, + IP */
+ "Echo",
+ "Time Exceeded", /* transit, frag reassem + IP */
+ "Parameter Problem", /* pointer + IP */
+ "Timestamp", /* id + seq + three timestamps */
+ "Timestamp Reply", /* " */
+ "Info Request", /* id + sq */
+ "Info Reply" /* " */
+};
+#endif
+
+/*
+ * pr_icmph --
+ * Print a descriptive string about an ICMP header.
+ */
+static void
+pr_icmph(icp)
+ struct icmp *icp;
+{
+
+ switch(icp->icmp_type) {
+ case ICMP_ECHOREPLY:
+ (void)printf("Echo Reply\n");
+ /* XXX ID + Seq + Data */
+ break;
+ case ICMP_UNREACH:
+ switch(icp->icmp_code) {
+ case ICMP_UNREACH_NET:
+ (void)printf("Destination Net Unreachable\n");
+ break;
+ case ICMP_UNREACH_HOST:
+ (void)printf("Destination Host Unreachable\n");
+ break;
+ case ICMP_UNREACH_PROTOCOL:
+ (void)printf("Destination Protocol Unreachable\n");
+ break;
+ case ICMP_UNREACH_PORT:
+ (void)printf("Destination Port Unreachable\n");
+ break;
+ case ICMP_UNREACH_NEEDFRAG:
+ (void)printf("frag needed and DF set (MTU %d)\n",
+ ntohs(icp->icmp_nextmtu));
+ break;
+ case ICMP_UNREACH_SRCFAIL:
+ (void)printf("Source Route Failed\n");
+ break;
+ case ICMP_UNREACH_FILTER_PROHIB:
+ (void)printf("Communication prohibited by filter\n");
+ break;
+ default:
+ (void)printf("Dest Unreachable, Bad Code: %d\n",
+ icp->icmp_code);
+ break;
+ }
+ /* Print returned IP header information */
+#ifndef icmp_data
+ pr_retip(&icp->icmp_ip);
+#else
+ pr_retip((struct ip *)icp->icmp_data);
+#endif
+ break;
+ case ICMP_SOURCEQUENCH:
+ (void)printf("Source Quench\n");
+#ifndef icmp_data
+ pr_retip(&icp->icmp_ip);
+#else
+ pr_retip((struct ip *)icp->icmp_data);
+#endif
+ break;
+ case ICMP_REDIRECT:
+ switch(icp->icmp_code) {
+ case ICMP_REDIRECT_NET:
+ (void)printf("Redirect Network");
+ break;
+ case ICMP_REDIRECT_HOST:
+ (void)printf("Redirect Host");
+ break;
+ case ICMP_REDIRECT_TOSNET:
+ (void)printf("Redirect Type of Service and Network");
+ break;
+ case ICMP_REDIRECT_TOSHOST:
+ (void)printf("Redirect Type of Service and Host");
+ break;
+ default:
+ (void)printf("Redirect, Bad Code: %d", icp->icmp_code);
+ break;
+ }
+ (void)printf("(New addr: %s)\n", inet_ntoa(icp->icmp_gwaddr));
+#ifndef icmp_data
+ pr_retip(&icp->icmp_ip);
+#else
+ pr_retip((struct ip *)icp->icmp_data);
+#endif
+ break;
+ case ICMP_ECHO:
+ (void)printf("Echo Request\n");
+ /* XXX ID + Seq + Data */
+ break;
+ case ICMP_TIMXCEED:
+ switch(icp->icmp_code) {
+ case ICMP_TIMXCEED_INTRANS:
+ (void)printf("Time to live exceeded\n");
+ break;
+ case ICMP_TIMXCEED_REASS:
+ (void)printf("Frag reassembly time exceeded\n");
+ break;
+ default:
+ (void)printf("Time exceeded, Bad Code: %d\n",
+ icp->icmp_code);
+ break;
+ }
+#ifndef icmp_data
+ pr_retip(&icp->icmp_ip);
+#else
+ pr_retip((struct ip *)icp->icmp_data);
+#endif
+ break;
+ case ICMP_PARAMPROB:
+ (void)printf("Parameter problem: pointer = 0x%02x\n",
+ icp->icmp_hun.ih_pptr);
+#ifndef icmp_data
+ pr_retip(&icp->icmp_ip);
+#else
+ pr_retip((struct ip *)icp->icmp_data);
+#endif
+ break;
+ case ICMP_TSTAMP:
+ (void)printf("Timestamp\n");
+ /* XXX ID + Seq + 3 timestamps */
+ break;
+ case ICMP_TSTAMPREPLY:
+ (void)printf("Timestamp Reply\n");
+ /* XXX ID + Seq + 3 timestamps */
+ break;
+ case ICMP_IREQ:
+ (void)printf("Information Request\n");
+ /* XXX ID + Seq */
+ break;
+ case ICMP_IREQREPLY:
+ (void)printf("Information Reply\n");
+ /* XXX ID + Seq */
+ break;
+ case ICMP_MASKREQ:
+ (void)printf("Address Mask Request\n");
+ break;
+ case ICMP_MASKREPLY:
+ (void)printf("Address Mask Reply\n");
+ break;
+ case ICMP_ROUTERADVERT:
+ (void)printf("Router Advertisement\n");
+ break;
+ case ICMP_ROUTERSOLICIT:
+ (void)printf("Router Solicitation\n");
+ break;
+ default:
+ (void)printf("Bad ICMP type: %d\n", icp->icmp_type);
+ }
+}
+
+/*
+ * pr_iph --
+ * Print an IP header with options.
+ */
+static void
+pr_iph(ip)
+ struct ip *ip;
+{
+ u_char *cp;
+ int hlen;
+
+ hlen = ip->ip_hl << 2;
+ cp = (u_char *)ip + 20; /* point to options */
+
+ (void)printf("Vr HL TOS Len ID Flg off TTL Pro cks Src Dst\n");
+ (void)printf(" %1x %1x %02x %04x %04x",
+ ip->ip_v, ip->ip_hl, ip->ip_tos, ntohs(ip->ip_len),
+ ntohs(ip->ip_id));
+ (void)printf(" %1lx %04lx",
+ (u_long) (ntohl(ip->ip_off) & 0xe000) >> 13,
+ (u_long) ntohl(ip->ip_off) & 0x1fff);
+ (void)printf(" %02x %02x %04x", ip->ip_ttl, ip->ip_p,
+ ntohs(ip->ip_sum));
+ (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_src.s_addr));
+ (void)printf(" %s ", inet_ntoa(*(struct in_addr *)&ip->ip_dst.s_addr));
+ /* dump any option bytes */
+ while (hlen-- > 20) {
+ (void)printf("%02x", *cp++);
+ }
+ (void)putchar('\n');
+}
+
+/*
+ * pr_addr --
+ * Return an ascii host address as a dotted quad and optionally with
+ * a hostname.
+ */
+static char *
+pr_addr(ina)
+ struct in_addr ina;
+{
+ struct hostent *hp;
+ static char buf[16 + 3 + MAXHOSTNAMELEN];
+
+ if ((options & F_NUMERIC) ||
+ !(hp = gethostbyaddr((char *)&ina, 4, AF_INET)))
+ return inet_ntoa(ina);
+ else
+ (void)snprintf(buf, sizeof(buf), "%s (%s)", hp->h_name,
+ inet_ntoa(ina));
+ return(buf);
+}
+
+/*
+ * pr_retip --
+ * Dump some info on a returned (via ICMP) IP packet.
+ */
+static void
+pr_retip(ip)
+ struct ip *ip;
+{
+ u_char *cp;
+ int hlen;
+
+ pr_iph(ip);
+ hlen = ip->ip_hl << 2;
+ cp = (u_char *)ip + hlen;
+
+ if (ip->ip_p == 6)
+ (void)printf("TCP: from port %u, to port %u (decimal)\n",
+ (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
+ else if (ip->ip_p == 17)
+ (void)printf("UDP: from port %u, to port %u (decimal)\n",
+ (*cp * 256 + *(cp + 1)), (*(cp + 2) * 256 + *(cp + 3)));
+}
+
+static char *
+pr_ntime (n_time timestamp)
+{
+ static char buf[10];
+ int hour, min, sec;
+
+ sec = ntohl(timestamp) / 1000;
+ hour = sec / 60 / 60;
+ min = (sec % (60 * 60)) / 60;
+ sec = (sec % (60 * 60)) % 60;
+
+ (void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d", hour, min, sec);
+
+ return (buf);
+}
+
+static void
+fill(bp, patp)
+ char *bp, *patp;
+{
+ char *cp;
+ int pat[16];
+ u_int ii, jj, kk;
+
+ for (cp = patp; *cp; cp++) {
+ if (!isxdigit(*cp))
+ errx(EX_USAGE,
+ "patterns must be specified as hex digits");
+
+ }
+ ii = sscanf(patp,
+ "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
+ &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
+ &pat[13], &pat[14], &pat[15]);
+
+ if (ii > 0)
+ for (kk = 0; kk <= maxpayload - (TIMEVAL_LEN + ii); kk += ii)
+ for (jj = 0; jj < ii; ++jj)
+ bp[jj + kk] = pat[jj];
+ if (!(options & F_QUIET)) {
+ (void)printf("PATTERN: 0x");
+ for (jj = 0; jj < ii; ++jj)
+ (void)printf("%02x", bp[jj] & 0xFF);
+ (void)printf("\n");
+ }
+}
+
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+#define SECOPT " [-P policy]"
+#else
+#define SECOPT ""
+#endif
+static void
+usage()
+{
+ (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+"usage: ping [-AaDdfnoQqRrv] [-c count] [-G sweepmaxsize] [-g sweepminsize]",
+" [-h sweepincrsize] [-i wait] [-l preload] [-M mask | time] [-m ttl]",
+" " SECOPT " [-p pattern] [-S src_addr] [-s packetsize] [-t timeout]",
+" [-W waittime] [-z tos] host",
+" ping [-AaDdfLnoQqRrv] [-c count] [-I iface] [-i wait] [-l preload]",
+" [-M mask | time] [-m ttl]" SECOPT " [-p pattern] [-S src_addr]",
+" [-s packetsize] [-T ttl] [-t timeout] [-W waittime]",
+" [-z tos] mcast-group");
+ exit(EX_USAGE);
+}
+
+#ifdef __rtems__
+ #include <rtems/shell.h>
+
+ rtems_shell_cmd_t rtems_shell_PING_Command = {
+ "ping", /* name */
+ "ping [args]", /* usage */
+ "net", /* topic */
+ rtems_shell_main_ping, /* command */
+ NULL, /* alias */
+ NULL /* next */
+ };
+#endif
diff --git a/freebsd/sbin/ping6/ping6.c b/freebsd/sbin/ping6/ping6.c
new file mode 100644
index 00000000..20b5f7ba
--- /dev/null
+++ b/freebsd/sbin/ping6/ping6.c
@@ -0,0 +1,2837 @@
+#ifdef __rtems__
+#define USE_RFC2292BIS
+
+#define __need_getopt_newlib
+#include <getopt.h>
+#endif
+/* $KAME: ping6.c,v 1.169 2003/07/25 06:01:47 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/* BSDI ping.c,v 2.3 1996/01/21 17:56:50 jch Exp */
+
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Muuss.
+ *
+ * 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.
+ */
+
+#ifndef lint
+static const char copyright[] =
+"@(#) Copyright (c) 1989, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)ping.c 8.1 (Berkeley) 6/5/93";
+#endif
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+/*
+ * Using the InterNet Control Message Protocol (ICMP) "ECHO" facility,
+ * measure round-trip-delays and packet loss across network paths.
+ *
+ * Author -
+ * Mike Muuss
+ * U. S. Army Ballistic Research Laboratory
+ * December, 1983
+ *
+ * Status -
+ * Public Domain. Distribution Unlimited.
+ * Bugs -
+ * More statistics could always be gathered.
+ * This program has to run SUID to ROOT to access the ICMP socket.
+ */
+/*
+ * NOTE:
+ * USE_SIN6_SCOPE_ID assumes that sin6_scope_id has the same semantics
+ * as IPV6_PKTINFO. Some people object it (sin6_scope_id specifies *link*
+ * while IPV6_PKTINFO specifies *interface*. Link is defined as collection of
+ * network attached to 1 or more interfaces)
+ */
+
+#include <sys/param.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#endif
+
+#ifdef IPSEC
+#ifdef __rtems__
+#include <freebsd/netipsec/ah.h>
+#include <freebsd/netipsec/ipsec.h>
+#else
+#include <netipsec/ah.h>
+#include <netipsec/ipsec.h>
+#endif
+#endif
+
+#include <md5.h>
+
+struct tv32 {
+ u_int32_t tv32_sec;
+ u_int32_t tv32_usec;
+};
+
+#define MAXPACKETLEN 131072
+#define IP6LEN 40
+#define ICMP6ECHOLEN 8 /* icmp echo header len excluding time */
+#define ICMP6ECHOTMLEN sizeof(struct tv32)
+#define ICMP6_NIQLEN (ICMP6ECHOLEN + 8)
+# define CONTROLLEN 10240 /* ancillary data buffer size RFC3542 20.1 */
+/* FQDN case, 64 bits of nonce + 32 bits ttl */
+#define ICMP6_NIRLEN (ICMP6ECHOLEN + 12)
+#define EXTRA 256 /* for AH and various other headers. weird. */
+#define DEFDATALEN ICMP6ECHOTMLEN
+#define MAXDATALEN MAXPACKETLEN - IP6LEN - ICMP6ECHOLEN
+#define NROUTES 9 /* number of record route slots */
+
+#define A(bit) rcvd_tbl[(bit)>>3] /* identify byte in array */
+#define B(bit) (1 << ((bit) & 0x07)) /* identify bit in byte */
+#define SET(bit) (A(bit) |= B(bit))
+#define CLR(bit) (A(bit) &= (~B(bit)))
+#define TST(bit) (A(bit) & B(bit))
+
+#define F_FLOOD 0x0001
+#define F_INTERVAL 0x0002
+#define F_PINGFILLED 0x0008
+#define F_QUIET 0x0010
+#define F_RROUTE 0x0020
+#define F_SO_DEBUG 0x0040
+#define F_VERBOSE 0x0100
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+#define F_POLICY 0x0400
+#else
+#define F_AUTHHDR 0x0200
+#define F_ENCRYPT 0x0400
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+#define F_NODEADDR 0x0800
+#define F_FQDN 0x1000
+#define F_INTERFACE 0x2000
+#define F_SRCADDR 0x4000
+#define F_HOSTNAME 0x10000
+#define F_FQDNOLD 0x20000
+#define F_NIGROUP 0x40000
+#define F_SUPTYPES 0x80000
+#define F_NOMINMTU 0x100000
+#define F_ONCE 0x200000
+#define F_AUDIBLE 0x400000
+#define F_MISSED 0x800000
+#define F_DONTFRAG 0x1000000
+#define F_NOUSERDATA (F_NODEADDR | F_FQDN | F_FQDNOLD | F_SUPTYPES)
+u_int options;
+
+#define IN6LEN sizeof(struct in6_addr)
+#define SA6LEN sizeof(struct sockaddr_in6)
+#define DUMMY_PORT 10101
+
+#define SIN6(s) ((struct sockaddr_in6 *)(s))
+
+/*
+ * MAX_DUP_CHK is the number of bits in received table, i.e. the maximum
+ * number of received sequence numbers we can keep track of. Change 128
+ * to 8192 for complete accuracy...
+ */
+#define MAX_DUP_CHK (8 * 8192)
+int mx_dup_ck = MAX_DUP_CHK;
+char rcvd_tbl[MAX_DUP_CHK / 8];
+
+struct addrinfo *res;
+struct sockaddr_in6 dst; /* who to ping6 */
+struct sockaddr_in6 src; /* src addr of this packet */
+socklen_t srclen;
+int datalen = DEFDATALEN;
+int s; /* socket file descriptor */
+u_char outpack[MAXPACKETLEN];
+char BSPACE = '\b'; /* characters written for flood */
+char BBELL = '\a'; /* characters written for AUDIBLE */
+char DOT = '.';
+char *hostname;
+int ident; /* process id to identify our packets */
+u_int8_t nonce[8]; /* nonce field for node information */
+int hoplimit = -1; /* hoplimit */
+int pathmtu = 0; /* path MTU for the destination. 0 = unspec. */
+
+/* counters */
+long nmissedmax; /* max value of ntransmitted - nreceived - 1 */
+long npackets; /* max packets to transmit */
+long nreceived; /* # of packets we got back */
+long nrepeats; /* number of duplicates */
+long ntransmitted; /* sequence # for outbound packets = #sent */
+struct timeval interval = {1, 0}; /* interval between packets */
+
+/* timing */
+int timing; /* flag to do timing */
+double tmin = 999999999.0; /* minimum round trip time */
+double tmax = 0.0; /* maximum round trip time */
+double tsum = 0.0; /* sum of all times, for doing average */
+double tsumsq = 0.0; /* sum of all times squared, for std. dev. */
+
+/* for node addresses */
+u_short naflags;
+
+/* for ancillary data(advanced API) */
+struct msghdr smsghdr;
+struct iovec smsgiov;
+char *scmsg = 0;
+
+volatile sig_atomic_t seenalrm;
+volatile sig_atomic_t seenint;
+#ifdef SIGINFO
+volatile sig_atomic_t seeninfo;
+#endif
+
+#ifdef __rtems__
+int main_ping6(int, char *[]);
+#else
+int main(int, char *[]);
+#endif
+void fill(char *, char *);
+int get_hoplim(struct msghdr *);
+int get_pathmtu(struct msghdr *);
+struct in6_pktinfo *get_rcvpktinfo(struct msghdr *);
+void onsignal(int);
+void retransmit(void);
+void onint(int);
+size_t pingerlen(void);
+int pinger(void);
+const char *pr_addr(struct sockaddr *, int);
+void pr_icmph(struct icmp6_hdr *, u_char *);
+void pr_iph(struct ip6_hdr *);
+void pr_suptypes(struct icmp6_nodeinfo *, size_t);
+void pr_nodeaddr(struct icmp6_nodeinfo *, int);
+int myechoreply(const struct icmp6_hdr *);
+int mynireply(const struct icmp6_nodeinfo *);
+char *dnsdecode(const u_char **, const u_char *, const u_char *,
+ char *, size_t);
+void pr_pack(u_char *, int, struct msghdr *);
+void pr_exthdrs(struct msghdr *);
+void pr_ip6opt(void *, size_t);
+void pr_rthdr(void *, size_t);
+int pr_bitrange(u_int32_t, int, int);
+void pr_retip(struct ip6_hdr *, u_char *);
+void summary(void);
+void tvsub(struct timeval *, struct timeval *);
+int setpolicy(int, char *);
+char *nigroup(char *);
+void usage(void);
+
+int
+#ifdef __rtems__
+main_ping6(argc, argv)
+#else
+main(argc, argv)
+#endif
+ int argc;
+ char *argv[];
+{
+ struct itimerval itimer;
+ struct sockaddr_in6 from;
+#ifndef HAVE_ARC4RANDOM
+ struct timeval seed;
+#endif
+#ifdef HAVE_POLL_H
+ int timeout;
+#else
+ struct timeval timeout, *tv;
+#endif
+ struct addrinfo hints;
+#ifdef HAVE_POLL_H
+ struct pollfd fdmaskp[1];
+#else
+ fd_set *fdmaskp;
+ int fdmasks;
+#endif
+ int cc, i;
+ int ch, hold, packlen, preload, optval, ret_ga;
+ u_char *datap, *packet;
+ char *e, *target, *ifname = NULL, *gateway = NULL;
+ int ip6optlen = 0;
+ struct cmsghdr *scmsgp = NULL;
+ struct cmsghdr *cm;
+#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
+ u_long lsockbufsize;
+ int sockbufsize = 0;
+#endif
+ int usepktinfo = 0;
+ struct in6_pktinfo *pktinfo = NULL;
+#ifdef USE_RFC2292BIS
+ struct ip6_rthdr *rthdr = NULL;
+#endif
+#ifdef IPSEC_POLICY_IPSEC
+ char *policy_in = NULL;
+ char *policy_out = NULL;
+#endif
+ double intval;
+ size_t rthlen;
+#ifdef IPV6_USE_MIN_MTU
+ int mflag = 0;
+#endif
+#ifdef __rtems__
+ struct getopt_data getopt_reent;
+#endif
+
+ /* just to be sure */
+ memset(&smsghdr, 0, sizeof(smsghdr));
+ memset(&smsgiov, 0, sizeof(smsgiov));
+
+ preload = 0;
+ datap = &outpack[ICMP6ECHOLEN + ICMP6ECHOTMLEN];
+#ifndef IPSEC
+#define ADDOPTS
+#else
+#ifdef IPSEC_POLICY_IPSEC
+#define ADDOPTS "P:"
+#else
+#define ADDOPTS "AE"
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif
+#ifdef __rtems__
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+ while ((ch = getopt_r(argc, argv,
+ "a:b:c:DdfHg:h:I:i:l:mnNop:qrRS:s:tvwW" ADDOPTS, &getopt_reent)) != -1) {
+#else
+ while ((ch = getopt(argc, argv,
+ "a:b:c:DdfHg:h:I:i:l:mnNop:qrRS:s:tvwW" ADDOPTS)) != -1) {
+#endif
+#undef ADDOPTS
+ switch (ch) {
+ case 'a':
+ {
+ char *cp;
+
+ options &= ~F_NOUSERDATA;
+ options |= F_NODEADDR;
+ for (cp = optarg; *cp != '\0'; cp++) {
+ switch (*cp) {
+ case 'a':
+ naflags |= NI_NODEADDR_FLAG_ALL;
+ break;
+ case 'c':
+ case 'C':
+ naflags |= NI_NODEADDR_FLAG_COMPAT;
+ break;
+ case 'l':
+ case 'L':
+ naflags |= NI_NODEADDR_FLAG_LINKLOCAL;
+ break;
+ case 's':
+ case 'S':
+ naflags |= NI_NODEADDR_FLAG_SITELOCAL;
+ break;
+ case 'g':
+ case 'G':
+ naflags |= NI_NODEADDR_FLAG_GLOBAL;
+ break;
+ case 'A': /* experimental. not in the spec */
+#ifdef NI_NODEADDR_FLAG_ANYCAST
+ naflags |= NI_NODEADDR_FLAG_ANYCAST;
+ break;
+#else
+ errx(1,
+"-a A is not supported on the platform");
+ /*NOTREACHED*/
+#endif
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+ break;
+ }
+ case 'b':
+#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
+ errno = 0;
+ e = NULL;
+ lsockbufsize = strtoul(optarg, &e, 10);
+ sockbufsize = lsockbufsize;
+ if (errno || !*optarg || *e ||
+ sockbufsize != lsockbufsize)
+ errx(1, "invalid socket buffer size");
+#else
+ errx(1,
+"-b option ignored: SO_SNDBUF/SO_RCVBUF socket options not supported");
+#endif
+ break;
+ case 'c':
+ npackets = strtol(optarg, &e, 10);
+ if (npackets <= 0 || *optarg == '\0' || *e != '\0')
+ errx(1,
+ "illegal number of packets -- %s", optarg);
+ break;
+ case 'D':
+ options |= F_DONTFRAG;
+ break;
+ case 'd':
+ options |= F_SO_DEBUG;
+ break;
+ case 'f':
+ if (getuid()) {
+ errno = EPERM;
+ errx(1, "Must be superuser to flood ping");
+ }
+ options |= F_FLOOD;
+ setbuf(stdout, (char *)NULL);
+ break;
+ case 'g':
+ gateway = optarg;
+ break;
+ case 'H':
+ options |= F_HOSTNAME;
+ break;
+ case 'h': /* hoplimit */
+ hoplimit = strtol(optarg, &e, 10);
+ if (*optarg == '\0' || *e != '\0')
+ errx(1, "illegal hoplimit %s", optarg);
+ if (255 < hoplimit || hoplimit < -1)
+ errx(1,
+ "illegal hoplimit -- %s", optarg);
+ break;
+ case 'I':
+ ifname = optarg;
+ options |= F_INTERFACE;
+#ifndef USE_SIN6_SCOPE_ID
+ usepktinfo++;
+#endif
+ break;
+ case 'i': /* wait between sending packets */
+ intval = strtod(optarg, &e);
+ if (*optarg == '\0' || *e != '\0')
+ errx(1, "illegal timing interval %s", optarg);
+ if (intval < 1 && getuid()) {
+ errx(1, "%s: only root may use interval < 1s",
+ strerror(EPERM));
+ }
+ interval.tv_sec = (long)intval;
+ interval.tv_usec =
+ (long)((intval - interval.tv_sec) * 1000000);
+ if (interval.tv_sec < 0)
+ errx(1, "illegal timing interval %s", optarg);
+ /* less than 1/hz does not make sense */
+ if (interval.tv_sec == 0 && interval.tv_usec < 1) {
+ warnx("too small interval, raised to .000001");
+ interval.tv_usec = 1;
+ }
+ options |= F_INTERVAL;
+ break;
+ case 'l':
+ if (getuid()) {
+ errno = EPERM;
+ errx(1, "Must be superuser to preload");
+ }
+ preload = strtol(optarg, &e, 10);
+ if (preload < 0 || *optarg == '\0' || *e != '\0')
+ errx(1, "illegal preload value -- %s", optarg);
+ break;
+ case 'm':
+#ifdef IPV6_USE_MIN_MTU
+ mflag++;
+ break;
+#else
+ errx(1, "-%c is not supported on this platform", ch);
+ /*NOTREACHED*/
+#endif
+ case 'n':
+ options &= ~F_HOSTNAME;
+ break;
+ case 'N':
+ options |= F_NIGROUP;
+ break;
+ case 'o':
+ options |= F_ONCE;
+ break;
+ case 'p': /* fill buffer with user pattern */
+ options |= F_PINGFILLED;
+ fill((char *)datap, optarg);
+ break;
+ case 'q':
+ options |= F_QUIET;
+ break;
+ case 'r':
+ options |= F_AUDIBLE;
+ break;
+ case 'R':
+ options |= F_MISSED;
+ break;
+ case 'S':
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_flags = AI_NUMERICHOST; /* allow hostname? */
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_RAW;
+ hints.ai_protocol = IPPROTO_ICMPV6;
+
+ ret_ga = getaddrinfo(optarg, NULL, &hints, &res);
+ if (ret_ga) {
+ errx(1, "invalid source address: %s",
+ gai_strerror(ret_ga));
+ }
+ /*
+ * res->ai_family must be AF_INET6 and res->ai_addrlen
+ * must be sizeof(src).
+ */
+ memcpy(&src, res->ai_addr, res->ai_addrlen);
+ srclen = res->ai_addrlen;
+ freeaddrinfo(res);
+ options |= F_SRCADDR;
+ break;
+ case 's': /* size of packet to send */
+ datalen = strtol(optarg, &e, 10);
+ if (datalen <= 0 || *optarg == '\0' || *e != '\0')
+ errx(1, "illegal datalen value -- %s", optarg);
+ if (datalen > MAXDATALEN) {
+ errx(1,
+ "datalen value too large, maximum is %d",
+ MAXDATALEN);
+ }
+ break;
+ case 't':
+ options &= ~F_NOUSERDATA;
+ options |= F_SUPTYPES;
+ break;
+ case 'v':
+ options |= F_VERBOSE;
+ break;
+ case 'w':
+ options &= ~F_NOUSERDATA;
+ options |= F_FQDN;
+ break;
+ case 'W':
+ options &= ~F_NOUSERDATA;
+ options |= F_FQDNOLD;
+ break;
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+ case 'P':
+ options |= F_POLICY;
+ if (!strncmp("in", optarg, 2)) {
+ if ((policy_in = strdup(optarg)) == NULL)
+ errx(1, "strdup");
+ } else if (!strncmp("out", optarg, 3)) {
+ if ((policy_out = strdup(optarg)) == NULL)
+ errx(1, "strdup");
+ } else
+ errx(1, "invalid security policy");
+ break;
+#else
+ case 'A':
+ options |= F_AUTHHDR;
+ break;
+ case 'E':
+ options |= F_ENCRYPT;
+ break;
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif /*IPSEC*/
+ default:
+ usage();
+ /*NOTREACHED*/
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage();
+ /*NOTREACHED*/
+ }
+
+ if (argc > 1) {
+#ifdef IPV6_RECVRTHDR /* 2292bis */
+ rthlen = CMSG_SPACE(inet6_rth_space(IPV6_RTHDR_TYPE_0,
+ argc - 1));
+#else /* RFC2292 */
+ rthlen = inet6_rthdr_space(IPV6_RTHDR_TYPE_0, argc - 1);
+#endif
+ if (rthlen == 0) {
+ errx(1, "too many intermediate hops");
+ /*NOTREACHED*/
+ }
+ ip6optlen += rthlen;
+ }
+
+ if (options & F_NIGROUP) {
+ target = nigroup(argv[argc - 1]);
+ if (target == NULL) {
+ usage();
+ /*NOTREACHED*/
+ }
+ } else
+ target = argv[argc - 1];
+
+ /* getaddrinfo */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_RAW;
+ hints.ai_protocol = IPPROTO_ICMPV6;
+
+ ret_ga = getaddrinfo(target, NULL, &hints, &res);
+ if (ret_ga)
+ errx(1, "%s", gai_strerror(ret_ga));
+ if (res->ai_canonname)
+ hostname = res->ai_canonname;
+ else
+ hostname = target;
+
+ if (!res->ai_addr)
+ errx(1, "getaddrinfo failed");
+
+ (void)memcpy(&dst, res->ai_addr, res->ai_addrlen);
+
+ if ((s = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol)) < 0)
+ err(1, "socket");
+
+ /* set the source address if specified. */
+ if ((options & F_SRCADDR) &&
+ bind(s, (struct sockaddr *)&src, srclen) != 0) {
+ err(1, "bind");
+ }
+
+ /* set the gateway (next hop) if specified */
+ if (gateway) {
+ struct addrinfo ghints, *gres;
+ int error;
+
+ memset(&ghints, 0, sizeof(ghints));
+ ghints.ai_family = AF_INET6;
+ ghints.ai_socktype = SOCK_RAW;
+ ghints.ai_protocol = IPPROTO_ICMPV6;
+
+ error = getaddrinfo(gateway, NULL, &hints, &gres);
+ if (error) {
+ errx(1, "getaddrinfo for the gateway %s: %s",
+ gateway, gai_strerror(error));
+ }
+ if (gres->ai_next && (options & F_VERBOSE))
+ warnx("gateway resolves to multiple addresses");
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_NEXTHOP,
+ gres->ai_addr, gres->ai_addrlen)) {
+ err(1, "setsockopt(IPV6_NEXTHOP)");
+ }
+
+ freeaddrinfo(gres);
+ }
+
+ /*
+ * let the kerel pass extension headers of incoming packets,
+ * for privileged socket options
+ */
+ if ((options & F_VERBOSE) != 0) {
+ int opton = 1;
+
+#ifdef IPV6_RECVHOPOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVHOPOPTS)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_HOPOPTS)");
+#endif
+#ifdef IPV6_RECVDSTOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVDSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVDSTOPTS)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_DSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_DSTOPTS)");
+#endif
+#ifdef IPV6_RECVRTHDRDSTOPTS
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDRDSTOPTS, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVRTHDRDSTOPTS)");
+#endif
+ }
+
+ /* revoke root privilege */
+ seteuid(getuid());
+ setuid(getuid());
+
+ if ((options & F_FLOOD) && (options & F_INTERVAL))
+ errx(1, "-f and -i incompatible options");
+
+ if ((options & F_NOUSERDATA) == 0) {
+ if (datalen >= sizeof(struct tv32)) {
+ /* we can time transfer */
+ timing = 1;
+ } else
+ timing = 0;
+ /* in F_VERBOSE case, we may get non-echoreply packets*/
+ if (options & F_VERBOSE)
+ packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
+ else
+ packlen = datalen + IP6LEN + ICMP6ECHOLEN + EXTRA;
+ } else {
+ /* suppress timing for node information query */
+ timing = 0;
+ datalen = 2048;
+ packlen = 2048 + IP6LEN + ICMP6ECHOLEN + EXTRA;
+ }
+
+ if (!(packet = (u_char *)malloc((u_int)packlen)))
+ err(1, "Unable to allocate packet");
+ if (!(options & F_PINGFILLED))
+ for (i = ICMP6ECHOLEN; i < packlen; ++i)
+ *datap++ = i;
+
+ ident = getpid() & 0xFFFF;
+#ifndef HAVE_ARC4RANDOM
+ gettimeofday(&seed, NULL);
+ srand((unsigned int)(seed.tv_sec ^ seed.tv_usec ^ (long)ident));
+ memset(nonce, 0, sizeof(nonce));
+ for (i = 0; i < sizeof(nonce); i += sizeof(int))
+ *((int *)&nonce[i]) = rand();
+#else
+ memset(nonce, 0, sizeof(nonce));
+ for (i = 0; i < sizeof(nonce); i += sizeof(u_int32_t))
+ *((u_int32_t *)&nonce[i]) = arc4random();
+#endif
+ optval = 1;
+ if (options & F_DONTFRAG)
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_DONTFRAG,
+ &optval, sizeof(optval)) == -1)
+ err(1, "IPV6_DONTFRAG");
+ hold = 1;
+
+ if (options & F_SO_DEBUG)
+ (void)setsockopt(s, SOL_SOCKET, SO_DEBUG, (char *)&hold,
+ sizeof(hold));
+ optval = IPV6_DEFHLIM;
+ if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &optval, sizeof(optval)) == -1)
+ err(1, "IPV6_MULTICAST_HOPS");
+#ifdef IPV6_USE_MIN_MTU
+ if (mflag != 1) {
+ optval = mflag > 1 ? 0 : 1;
+
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_USE_MIN_MTU,
+ &optval, sizeof(optval)) == -1)
+ err(1, "setsockopt(IPV6_USE_MIN_MTU)");
+ }
+#ifdef IPV6_RECVPATHMTU
+ else {
+ optval = 1;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPATHMTU,
+ &optval, sizeof(optval)) == -1)
+ err(1, "setsockopt(IPV6_RECVPATHMTU)");
+ }
+#endif /* IPV6_RECVPATHMTU */
+#endif /* IPV6_USE_MIN_MTU */
+
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+ if (options & F_POLICY) {
+ if (setpolicy(s, policy_in) < 0)
+ errx(1, "%s", ipsec_strerror());
+ if (setpolicy(s, policy_out) < 0)
+ errx(1, "%s", ipsec_strerror());
+ }
+#else
+ if (options & F_AUTHHDR) {
+ optval = IPSEC_LEVEL_REQUIRE;
+#ifdef IPV6_AUTH_TRANS_LEVEL
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_TRANS_LEVEL,
+ &optval, sizeof(optval)) == -1)
+ err(1, "setsockopt(IPV6_AUTH_TRANS_LEVEL)");
+#else /* old def */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_AUTH_LEVEL,
+ &optval, sizeof(optval)) == -1)
+ err(1, "setsockopt(IPV6_AUTH_LEVEL)");
+#endif
+ }
+ if (options & F_ENCRYPT) {
+ optval = IPSEC_LEVEL_REQUIRE;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_ESP_TRANS_LEVEL,
+ &optval, sizeof(optval)) == -1)
+ err(1, "setsockopt(IPV6_ESP_TRANS_LEVEL)");
+ }
+#endif /*IPSEC_POLICY_IPSEC*/
+#endif
+
+#ifdef ICMP6_FILTER
+ {
+ struct icmp6_filter filt;
+ if (!(options & F_VERBOSE)) {
+ ICMP6_FILTER_SETBLOCKALL(&filt);
+ if ((options & F_FQDN) || (options & F_FQDNOLD) ||
+ (options & F_NODEADDR) || (options & F_SUPTYPES))
+ ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);
+ else
+ ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
+ } else {
+ ICMP6_FILTER_SETPASSALL(&filt);
+ }
+ if (setsockopt(s, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
+ sizeof(filt)) < 0)
+ err(1, "setsockopt(ICMP6_FILTER)");
+ }
+#endif /*ICMP6_FILTER*/
+
+ /* let the kerel pass extension headers of incoming packets */
+ if ((options & F_VERBOSE) != 0) {
+ int opton = 1;
+
+#ifdef IPV6_RECVRTHDR
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVRTHDR, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RECVRTHDR)");
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RTHDR, &opton,
+ sizeof(opton)))
+ err(1, "setsockopt(IPV6_RTHDR)");
+#endif
+ }
+
+/*
+ optval = 1;
+ if (IN6_IS_ADDR_MULTICAST(&dst.sin6_addr))
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+ &optval, sizeof(optval)) == -1)
+ err(1, "IPV6_MULTICAST_LOOP");
+*/
+
+ /* Specify the outgoing interface and/or the source address */
+ if (usepktinfo)
+ ip6optlen += CMSG_SPACE(sizeof(struct in6_pktinfo));
+
+ if (hoplimit != -1)
+ ip6optlen += CMSG_SPACE(sizeof(int));
+
+ /* set IP6 packet options */
+ if (ip6optlen) {
+ if ((scmsg = (char *)malloc(ip6optlen)) == 0)
+ errx(1, "can't allocate enough memory");
+ smsghdr.msg_control = (caddr_t)scmsg;
+ smsghdr.msg_controllen = ip6optlen;
+ scmsgp = (struct cmsghdr *)scmsg;
+ }
+ if (usepktinfo) {
+ pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
+ memset(pktinfo, 0, sizeof(*pktinfo));
+ scmsgp->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
+ scmsgp->cmsg_level = IPPROTO_IPV6;
+ scmsgp->cmsg_type = IPV6_PKTINFO;
+ scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
+ }
+
+ /* set the outgoing interface */
+ if (ifname) {
+#ifndef USE_SIN6_SCOPE_ID
+ /* pktinfo must have already been allocated */
+ if ((pktinfo->ipi6_ifindex = if_nametoindex(ifname)) == 0)
+ errx(1, "%s: invalid interface name", ifname);
+#else
+ if ((dst.sin6_scope_id = if_nametoindex(ifname)) == 0)
+ errx(1, "%s: invalid interface name", ifname);
+#endif
+ }
+ if (hoplimit != -1) {
+ scmsgp->cmsg_len = CMSG_LEN(sizeof(int));
+ scmsgp->cmsg_level = IPPROTO_IPV6;
+ scmsgp->cmsg_type = IPV6_HOPLIMIT;
+ *(int *)(CMSG_DATA(scmsgp)) = hoplimit;
+
+ scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
+ }
+
+ if (argc > 1) { /* some intermediate addrs are specified */
+ int hops, error;
+#ifdef USE_RFC2292BIS
+ int rthdrlen;
+#endif
+
+#ifdef USE_RFC2292BIS
+ rthdrlen = inet6_rth_space(IPV6_RTHDR_TYPE_0, argc - 1);
+ scmsgp->cmsg_len = CMSG_LEN(rthdrlen);
+ scmsgp->cmsg_level = IPPROTO_IPV6;
+ scmsgp->cmsg_type = IPV6_RTHDR;
+ rthdr = (struct ip6_rthdr *)CMSG_DATA(scmsgp);
+ rthdr = inet6_rth_init((void *)rthdr, rthdrlen,
+ IPV6_RTHDR_TYPE_0, argc - 1);
+ if (rthdr == NULL)
+ errx(1, "can't initialize rthdr");
+#else /* old advanced API */
+ if ((scmsgp = (struct cmsghdr *)inet6_rthdr_init(scmsgp,
+ IPV6_RTHDR_TYPE_0)) == 0)
+ errx(1, "can't initialize rthdr");
+#endif /* USE_RFC2292BIS */
+
+ for (hops = 0; hops < argc - 1; hops++) {
+ struct addrinfo *iaip;
+
+ if ((error = getaddrinfo(argv[hops], NULL, &hints,
+ &iaip)))
+ errx(1, "%s", gai_strerror(error));
+ if (SIN6(iaip->ai_addr)->sin6_family != AF_INET6)
+ errx(1,
+ "bad addr family of an intermediate addr");
+
+#ifdef USE_RFC2292BIS
+ if (inet6_rth_add(rthdr,
+ &(SIN6(iaip->ai_addr))->sin6_addr))
+ errx(1, "can't add an intermediate node");
+#else /* old advanced API */
+ if (inet6_rthdr_add(scmsgp,
+ &(SIN6(iaip->ai_addr))->sin6_addr,
+ IPV6_RTHDR_LOOSE))
+ errx(1, "can't add an intermediate node");
+#endif /* USE_RFC2292BIS */
+ freeaddrinfo(iaip);
+ }
+
+#ifndef USE_RFC2292BIS
+ if (inet6_rthdr_lasthop(scmsgp, IPV6_RTHDR_LOOSE))
+ errx(1, "can't set the last flag");
+#endif
+
+ scmsgp = CMSG_NXTHDR(&smsghdr, scmsgp);
+ }
+
+ if (!(options & F_SRCADDR)) {
+ /*
+ * get the source address. XXX since we revoked the root
+ * privilege, we cannot use a raw socket for this.
+ */
+ int dummy;
+ socklen_t len = sizeof(src);
+
+ if ((dummy = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ err(1, "UDP socket");
+
+ src.sin6_family = AF_INET6;
+ src.sin6_addr = dst.sin6_addr;
+ src.sin6_port = ntohs(DUMMY_PORT);
+ src.sin6_scope_id = dst.sin6_scope_id;
+
+#ifdef USE_RFC2292BIS
+ if (pktinfo &&
+ setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTINFO,
+ (void *)pktinfo, sizeof(*pktinfo)))
+ err(1, "UDP setsockopt(IPV6_PKTINFO)");
+
+ if (hoplimit != -1 &&
+ setsockopt(dummy, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+ (void *)&hoplimit, sizeof(hoplimit)))
+ err(1, "UDP setsockopt(IPV6_UNICAST_HOPS)");
+
+ if (hoplimit != -1 &&
+ setsockopt(dummy, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ (void *)&hoplimit, sizeof(hoplimit)))
+ err(1, "UDP setsockopt(IPV6_MULTICAST_HOPS)");
+
+ if (rthdr &&
+ setsockopt(dummy, IPPROTO_IPV6, IPV6_RTHDR,
+ (void *)rthdr, (rthdr->ip6r_len + 1) << 3))
+ err(1, "UDP setsockopt(IPV6_RTHDR)");
+#else /* old advanced API */
+ if (smsghdr.msg_control &&
+ setsockopt(dummy, IPPROTO_IPV6, IPV6_PKTOPTIONS,
+ (void *)smsghdr.msg_control, smsghdr.msg_controllen))
+ err(1, "UDP setsockopt(IPV6_PKTOPTIONS)");
+#endif
+
+ if (connect(dummy, (struct sockaddr *)&src, len) < 0)
+ err(1, "UDP connect");
+
+ if (getsockname(dummy, (struct sockaddr *)&src, &len) < 0)
+ err(1, "getsockname");
+
+ close(dummy);
+ }
+
+#if defined(SO_SNDBUF) && defined(SO_RCVBUF)
+ if (sockbufsize) {
+ if (datalen > sockbufsize)
+ warnx("you need -b to increase socket buffer size");
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &sockbufsize,
+ sizeof(sockbufsize)) < 0)
+ err(1, "setsockopt(SO_SNDBUF)");
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &sockbufsize,
+ sizeof(sockbufsize)) < 0)
+ err(1, "setsockopt(SO_RCVBUF)");
+ }
+ else {
+ if (datalen > 8 * 1024) /*XXX*/
+ warnx("you need -b to increase socket buffer size");
+ /*
+ * When pinging the broadcast address, you can get a lot of
+ * answers. Doing something so evil is useful if you are trying
+ * to stress the ethernet, or just want to fill the arp cache
+ * to get some stuff for /etc/ethers.
+ */
+ hold = 48 * 1024;
+ setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char *)&hold,
+ sizeof(hold));
+ }
+#endif
+
+ optval = 1;
+#ifndef USE_SIN6_SCOPE_ID
+#ifdef IPV6_RECVPKTINFO
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVPKTINFO, &optval,
+ sizeof(optval)) < 0)
+ warn("setsockopt(IPV6_RECVPKTINFO)"); /* XXX err? */
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &optval,
+ sizeof(optval)) < 0)
+ warn("setsockopt(IPV6_PKTINFO)"); /* XXX err? */
+#endif
+#endif /* USE_SIN6_SCOPE_ID */
+#ifdef IPV6_RECVHOPLIMIT
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_RECVHOPLIMIT, &optval,
+ sizeof(optval)) < 0)
+ warn("setsockopt(IPV6_RECVHOPLIMIT)"); /* XXX err? */
+#else /* old adv. API */
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_HOPLIMIT, &optval,
+ sizeof(optval)) < 0)
+ warn("setsockopt(IPV6_HOPLIMIT)"); /* XXX err? */
+#endif
+
+ printf("PING6(%lu=40+8+%lu bytes) ", (unsigned long)(40 + pingerlen()),
+ (unsigned long)(pingerlen() - 8));
+ printf("%s --> ", pr_addr((struct sockaddr *)&src, sizeof(src)));
+ printf("%s\n", pr_addr((struct sockaddr *)&dst, sizeof(dst)));
+
+ while (preload--) /* Fire off them quickies. */
+ (void)pinger();
+
+ (void)signal(SIGINT, onsignal);
+#ifdef SIGINFO
+ (void)signal(SIGINFO, onsignal);
+#endif
+
+ if ((options & F_FLOOD) == 0) {
+ (void)signal(SIGALRM, onsignal);
+ itimer.it_interval = interval;
+ itimer.it_value = interval;
+ (void)setitimer(ITIMER_REAL, &itimer, NULL);
+ if (ntransmitted == 0)
+ retransmit();
+ }
+
+#ifndef HAVE_POLL_H
+ fdmasks = howmany(s + 1, NFDBITS) * sizeof(fd_mask);
+ if ((fdmaskp = malloc(fdmasks)) == NULL)
+ err(1, "malloc");
+#endif
+
+ seenalrm = seenint = 0;
+#ifdef SIGINFO
+ seeninfo = 0;
+#endif
+
+ /* For control (ancillary) data received from recvmsg() */
+ cm = (struct cmsghdr *)malloc(CONTROLLEN);
+ if (cm == NULL)
+ err(1, "malloc");
+
+ for (;;) {
+ struct msghdr m;
+ struct iovec iov[2];
+
+ /* signal handling */
+ if (seenalrm) {
+ /* last packet sent, timeout reached? */
+ if (npackets && ntransmitted >= npackets)
+ break;
+ retransmit();
+ seenalrm = 0;
+ continue;
+ }
+ if (seenint) {
+ onint(SIGINT);
+ seenint = 0;
+ continue;
+ }
+#ifdef SIGINFO
+ if (seeninfo) {
+ summary();
+ seeninfo = 0;
+ continue;
+ }
+#endif
+
+ if (options & F_FLOOD) {
+ (void)pinger();
+#ifdef HAVE_POLL_H
+ timeout = 10;
+#else
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 10000;
+ tv = &timeout;
+#endif
+ } else {
+#ifdef HAVE_POLL_H
+ timeout = INFTIM;
+#else
+ tv = NULL;
+#endif
+ }
+#ifdef HAVE_POLL_H
+ fdmaskp[0].fd = s;
+ fdmaskp[0].events = POLLIN;
+ cc = poll(fdmaskp, 1, timeout);
+#else
+ memset(fdmaskp, 0, fdmasks);
+ FD_SET(s, fdmaskp);
+ cc = select(s + 1, fdmaskp, NULL, NULL, tv);
+#endif
+ if (cc < 0) {
+ if (errno != EINTR) {
+#ifdef HAVE_POLL_H
+ warn("poll");
+#else
+ warn("select");
+#endif
+ sleep(1);
+ }
+ continue;
+ } else if (cc == 0)
+ continue;
+
+ m.msg_name = (caddr_t)&from;
+ m.msg_namelen = sizeof(from);
+ memset(&iov, 0, sizeof(iov));
+ iov[0].iov_base = (caddr_t)packet;
+ iov[0].iov_len = packlen;
+ m.msg_iov = iov;
+ m.msg_iovlen = 1;
+ memset(cm, 0, CONTROLLEN);
+ m.msg_control = (void *)cm;
+ m.msg_controllen = CONTROLLEN;
+
+ cc = recvmsg(s, &m, 0);
+ if (cc < 0) {
+ if (errno != EINTR) {
+ warn("recvmsg");
+ sleep(1);
+ }
+ continue;
+ } else if (cc == 0) {
+ int mtu;
+
+ /*
+ * receive control messages only. Process the
+ * exceptions (currently the only possiblity is
+ * a path MTU notification.)
+ */
+ if ((mtu = get_pathmtu(&m)) > 0) {
+ if ((options & F_VERBOSE) != 0) {
+ printf("new path MTU (%d) is "
+ "notified\n", mtu);
+ }
+ }
+ continue;
+ } else {
+ /*
+ * an ICMPv6 message (probably an echoreply) arrived.
+ */
+ pr_pack(packet, cc, &m);
+ }
+ if (((options & F_ONCE) != 0 && nreceived > 0) ||
+ (npackets > 0 && nreceived >= npackets))
+ break;
+ if (ntransmitted - nreceived - 1 > nmissedmax) {
+ nmissedmax = ntransmitted - nreceived - 1;
+ if (options & F_MISSED)
+ (void)write(STDOUT_FILENO, &BBELL, 1);
+ }
+ }
+ summary();
+ exit(nreceived == 0 ? 2 : 0);
+}
+
+void
+onsignal(sig)
+ int sig;
+{
+
+ switch (sig) {
+ case SIGALRM:
+ seenalrm++;
+ break;
+ case SIGINT:
+ seenint++;
+ break;
+#ifdef SIGINFO
+ case SIGINFO:
+ seeninfo++;
+ break;
+#endif
+ }
+}
+
+/*
+ * retransmit --
+ * This routine transmits another ping6.
+ */
+void
+retransmit()
+{
+ struct itimerval itimer;
+
+ if (pinger() == 0)
+ return;
+
+ /*
+ * If we're not transmitting any more packets, change the timer
+ * to wait two round-trip times if we've received any packets or
+ * ten seconds if we haven't.
+ */
+#define MAXWAIT 10
+ if (nreceived) {
+ itimer.it_value.tv_sec = 2 * tmax / 1000;
+ if (itimer.it_value.tv_sec == 0)
+ itimer.it_value.tv_sec = 1;
+ } else
+ itimer.it_value.tv_sec = MAXWAIT;
+ itimer.it_interval.tv_sec = 0;
+ itimer.it_interval.tv_usec = 0;
+ itimer.it_value.tv_usec = 0;
+
+ (void)signal(SIGALRM, onsignal);
+ (void)setitimer(ITIMER_REAL, &itimer, NULL);
+}
+
+/*
+ * pinger --
+ * Compose and transmit an ICMP ECHO REQUEST packet. The IP packet
+ * will be added on by the kernel. The ID field is our UNIX process ID,
+ * and the sequence number is an ascending integer. The first 8 bytes
+ * of the data portion are used to hold a UNIX "timeval" struct in VAX
+ * byte-order, to compute the round-trip time.
+ */
+size_t
+pingerlen()
+{
+ size_t l;
+
+ if (options & F_FQDN)
+ l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
+ else if (options & F_FQDNOLD)
+ l = ICMP6_NIQLEN;
+ else if (options & F_NODEADDR)
+ l = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
+ else if (options & F_SUPTYPES)
+ l = ICMP6_NIQLEN;
+ else
+ l = ICMP6ECHOLEN + datalen;
+
+ return l;
+}
+
+int
+pinger()
+{
+ struct icmp6_hdr *icp;
+ struct iovec iov[2];
+ int i, cc;
+ struct icmp6_nodeinfo *nip;
+ int seq;
+
+ if (npackets && ntransmitted >= npackets)
+ return(-1); /* no more transmission */
+
+ icp = (struct icmp6_hdr *)outpack;
+ nip = (struct icmp6_nodeinfo *)outpack;
+ memset(icp, 0, sizeof(*icp));
+ icp->icmp6_cksum = 0;
+ seq = ntransmitted++;
+ CLR(seq % mx_dup_ck);
+
+ if (options & F_FQDN) {
+ icp->icmp6_type = ICMP6_NI_QUERY;
+ icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
+ nip->ni_qtype = htons(NI_QTYPE_FQDN);
+ nip->ni_flags = htons(0);
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+
+ memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
+ sizeof(dst.sin6_addr));
+ cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
+ datalen = 0;
+ } else if (options & F_FQDNOLD) {
+ /* packet format in 03 draft - no Subject data on queries */
+ icp->icmp6_type = ICMP6_NI_QUERY;
+ icp->icmp6_code = 0; /* code field is always 0 */
+ nip->ni_qtype = htons(NI_QTYPE_FQDN);
+ nip->ni_flags = htons(0);
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+
+ cc = ICMP6_NIQLEN;
+ datalen = 0;
+ } else if (options & F_NODEADDR) {
+ icp->icmp6_type = ICMP6_NI_QUERY;
+ icp->icmp6_code = ICMP6_NI_SUBJ_IPV6;
+ nip->ni_qtype = htons(NI_QTYPE_NODEADDR);
+ nip->ni_flags = naflags;
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+
+ memcpy(&outpack[ICMP6_NIQLEN], &dst.sin6_addr,
+ sizeof(dst.sin6_addr));
+ cc = ICMP6_NIQLEN + sizeof(dst.sin6_addr);
+ datalen = 0;
+ } else if (options & F_SUPTYPES) {
+ icp->icmp6_type = ICMP6_NI_QUERY;
+ icp->icmp6_code = ICMP6_NI_SUBJ_FQDN; /*empty*/
+ nip->ni_qtype = htons(NI_QTYPE_SUPTYPES);
+ /* we support compressed bitmap */
+ nip->ni_flags = NI_SUPTYPE_FLAG_COMPRESS;
+
+ memcpy(nip->icmp6_ni_nonce, nonce,
+ sizeof(nip->icmp6_ni_nonce));
+ *(u_int16_t *)nip->icmp6_ni_nonce = ntohs(seq);
+ cc = ICMP6_NIQLEN;
+ datalen = 0;
+ } else {
+ icp->icmp6_type = ICMP6_ECHO_REQUEST;
+ icp->icmp6_code = 0;
+ icp->icmp6_id = htons(ident);
+ icp->icmp6_seq = ntohs(seq);
+ if (timing) {
+ struct timeval tv;
+ struct tv32 *tv32;
+ (void)gettimeofday(&tv, NULL);
+ tv32 = (struct tv32 *)&outpack[ICMP6ECHOLEN];
+ tv32->tv32_sec = htonl(tv.tv_sec);
+ tv32->tv32_usec = htonl(tv.tv_usec);
+ }
+ cc = ICMP6ECHOLEN + datalen;
+ }
+
+#ifdef DIAGNOSTIC
+ if (pingerlen() != cc)
+ errx(1, "internal error; length mismatch");
+#endif
+
+ smsghdr.msg_name = (caddr_t)&dst;
+ smsghdr.msg_namelen = sizeof(dst);
+ memset(&iov, 0, sizeof(iov));
+ iov[0].iov_base = (caddr_t)outpack;
+ iov[0].iov_len = cc;
+ smsghdr.msg_iov = iov;
+ smsghdr.msg_iovlen = 1;
+
+ i = sendmsg(s, &smsghdr, 0);
+
+ if (i < 0 || i != cc) {
+ if (i < 0)
+ warn("sendmsg");
+ (void)printf("ping6: wrote %s %d chars, ret=%d\n",
+ hostname, cc, i);
+ }
+ if (!(options & F_QUIET) && options & F_FLOOD)
+ (void)write(STDOUT_FILENO, &DOT, 1);
+
+ return(0);
+}
+
+int
+myechoreply(icp)
+ const struct icmp6_hdr *icp;
+{
+ if (ntohs(icp->icmp6_id) == ident)
+ return 1;
+ else
+ return 0;
+}
+
+int
+mynireply(nip)
+ const struct icmp6_nodeinfo *nip;
+{
+ if (memcmp(nip->icmp6_ni_nonce + sizeof(u_int16_t),
+ nonce + sizeof(u_int16_t),
+ sizeof(nonce) - sizeof(u_int16_t)) == 0)
+ return 1;
+ else
+ return 0;
+}
+
+char *
+dnsdecode(sp, ep, base, buf, bufsiz)
+ const u_char **sp;
+ const u_char *ep;
+ const u_char *base; /*base for compressed name*/
+ char *buf;
+ size_t bufsiz;
+{
+ int i;
+ const u_char *cp;
+ char cresult[MAXDNAME + 1];
+ const u_char *comp;
+ int l;
+
+ cp = *sp;
+ *buf = '\0';
+
+ if (cp >= ep)
+ return NULL;
+ while (cp < ep) {
+ i = *cp;
+ if (i == 0 || cp != *sp) {
+ if (strlcat((char *)buf, ".", bufsiz) >= bufsiz)
+ return NULL; /*result overrun*/
+ }
+ if (i == 0)
+ break;
+ cp++;
+
+ if ((i & 0xc0) == 0xc0 && cp - base > (i & 0x3f)) {
+ /* DNS compression */
+ if (!base)
+ return NULL;
+
+ comp = base + (i & 0x3f);
+ if (dnsdecode(&comp, cp, base, cresult,
+ sizeof(cresult)) == NULL)
+ return NULL;
+ if (strlcat(buf, cresult, bufsiz) >= bufsiz)
+ return NULL; /*result overrun*/
+ break;
+ } else if ((i & 0x3f) == i) {
+ if (i > ep - cp)
+ return NULL; /*source overrun*/
+ while (i-- > 0 && cp < ep) {
+ l = snprintf(cresult, sizeof(cresult),
+ isprint(*cp) ? "%c" : "\\%03o", *cp & 0xff);
+ if (l >= sizeof(cresult) || l < 0)
+ return NULL;
+ if (strlcat(buf, cresult, bufsiz) >= bufsiz)
+ return NULL; /*result overrun*/
+ cp++;
+ }
+ } else
+ return NULL; /*invalid label*/
+ }
+ if (i != 0)
+ return NULL; /*not terminated*/
+ cp++;
+ *sp = cp;
+ return buf;
+}
+
+/*
+ * pr_pack --
+ * Print out the packet, if it came from us. This logic is necessary
+ * because ALL readers of the ICMP socket get a copy of ALL ICMP packets
+ * which arrive ('tis only fair). This permits multiple copies of this
+ * program to be run without having intermingled output (or statistics!).
+ */
+void
+pr_pack(buf, cc, mhdr)
+ u_char *buf;
+ int cc;
+ struct msghdr *mhdr;
+{
+#define safeputc(c) printf((isprint((c)) ? "%c" : "\\%03o"), c)
+ struct icmp6_hdr *icp;
+ struct icmp6_nodeinfo *ni;
+ int i;
+ int hoplim;
+ struct sockaddr *from;
+ int fromlen;
+ u_char *cp = NULL, *dp, *end = buf + cc;
+ struct in6_pktinfo *pktinfo = NULL;
+ struct timeval tv, tp;
+ struct tv32 *tpp;
+ double triptime = 0;
+ int dupflag;
+ size_t off;
+ int oldfqdn;
+ u_int16_t seq;
+ char dnsname[MAXDNAME + 1];
+
+ (void)gettimeofday(&tv, NULL);
+
+ if (!mhdr || !mhdr->msg_name ||
+ mhdr->msg_namelen != sizeof(struct sockaddr_in6) ||
+ ((struct sockaddr *)mhdr->msg_name)->sa_family != AF_INET6) {
+ if (options & F_VERBOSE)
+ warnx("invalid peername");
+ return;
+ }
+ from = (struct sockaddr *)mhdr->msg_name;
+ fromlen = mhdr->msg_namelen;
+ if (cc < sizeof(struct icmp6_hdr)) {
+ if (options & F_VERBOSE)
+ warnx("packet too short (%d bytes) from %s", cc,
+ pr_addr(from, fromlen));
+ return;
+ }
+ if (((mhdr->msg_flags & MSG_CTRUNC) != 0) &&
+ (options & F_VERBOSE) != 0)
+ warnx("some control data discarded, insufficient buffer size");
+ icp = (struct icmp6_hdr *)buf;
+ ni = (struct icmp6_nodeinfo *)buf;
+ off = 0;
+
+ if ((hoplim = get_hoplim(mhdr)) == -1) {
+ warnx("failed to get receiving hop limit");
+ return;
+ }
+ if ((pktinfo = get_rcvpktinfo(mhdr)) == NULL) {
+ warnx("failed to get receiving packet information");
+ return;
+ }
+
+ if (icp->icmp6_type == ICMP6_ECHO_REPLY && myechoreply(icp)) {
+ seq = ntohs(icp->icmp6_seq);
+ ++nreceived;
+ if (timing) {
+ tpp = (struct tv32 *)(icp + 1);
+ tp.tv_sec = ntohl(tpp->tv32_sec);
+ tp.tv_usec = ntohl(tpp->tv32_usec);
+ tvsub(&tv, &tp);
+ triptime = ((double)tv.tv_sec) * 1000.0 +
+ ((double)tv.tv_usec) / 1000.0;
+ tsum += triptime;
+ tsumsq += triptime * triptime;
+ if (triptime < tmin)
+ tmin = triptime;
+ if (triptime > tmax)
+ tmax = triptime;
+ }
+
+ if (TST(seq % mx_dup_ck)) {
+ ++nrepeats;
+ --nreceived;
+ dupflag = 1;
+ } else {
+ SET(seq % mx_dup_ck);
+ dupflag = 0;
+ }
+
+ if (options & F_QUIET)
+ return;
+
+ if (options & F_FLOOD)
+ (void)write(STDOUT_FILENO, &BSPACE, 1);
+ else {
+ if (options & F_AUDIBLE)
+ (void)write(STDOUT_FILENO, &BBELL, 1);
+ (void)printf("%d bytes from %s, icmp_seq=%u", cc,
+ pr_addr(from, fromlen), seq);
+ (void)printf(" hlim=%d", hoplim);
+ if ((options & F_VERBOSE) != 0) {
+ struct sockaddr_in6 dstsa;
+
+ memset(&dstsa, 0, sizeof(dstsa));
+ dstsa.sin6_family = AF_INET6;
+ dstsa.sin6_len = sizeof(dstsa);
+ dstsa.sin6_scope_id = pktinfo->ipi6_ifindex;
+ dstsa.sin6_addr = pktinfo->ipi6_addr;
+ (void)printf(" dst=%s",
+ pr_addr((struct sockaddr *)&dstsa,
+ sizeof(dstsa)));
+ }
+ if (timing)
+ (void)printf(" time=%.3f ms", triptime);
+ if (dupflag)
+ (void)printf("(DUP!)");
+ /* check the data */
+ cp = buf + off + ICMP6ECHOLEN + ICMP6ECHOTMLEN;
+ dp = outpack + ICMP6ECHOLEN + ICMP6ECHOTMLEN;
+ for (i = 8; cp < end; ++i, ++cp, ++dp) {
+ if (*cp != *dp) {
+ (void)printf("\nwrong data byte #%d should be 0x%x but was 0x%x", i, *dp, *cp);
+ break;
+ }
+ }
+ }
+ } else if (icp->icmp6_type == ICMP6_NI_REPLY && mynireply(ni)) {
+ seq = ntohs(*(u_int16_t *)ni->icmp6_ni_nonce);
+ ++nreceived;
+ if (TST(seq % mx_dup_ck)) {
+ ++nrepeats;
+ --nreceived;
+ dupflag = 1;
+ } else {
+ SET(seq % mx_dup_ck);
+ dupflag = 0;
+ }
+
+ if (options & F_QUIET)
+ return;
+
+ (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
+
+ switch (ntohs(ni->ni_code)) {
+ case ICMP6_NI_SUCCESS:
+ break;
+ case ICMP6_NI_REFUSED:
+ printf("refused, type 0x%x", ntohs(ni->ni_type));
+ goto fqdnend;
+ case ICMP6_NI_UNKNOWN:
+ printf("unknown, type 0x%x", ntohs(ni->ni_type));
+ goto fqdnend;
+ default:
+ printf("unknown code 0x%x, type 0x%x",
+ ntohs(ni->ni_code), ntohs(ni->ni_type));
+ goto fqdnend;
+ }
+
+ switch (ntohs(ni->ni_qtype)) {
+ case NI_QTYPE_NOOP:
+ printf("NodeInfo NOOP");
+ break;
+ case NI_QTYPE_SUPTYPES:
+ pr_suptypes(ni, end - (u_char *)ni);
+ break;
+ case NI_QTYPE_NODEADDR:
+ pr_nodeaddr(ni, end - (u_char *)ni);
+ break;
+ case NI_QTYPE_FQDN:
+ default: /* XXX: for backward compatibility */
+ cp = (u_char *)ni + ICMP6_NIRLEN;
+ if (buf[off + ICMP6_NIRLEN] ==
+ cc - off - ICMP6_NIRLEN - 1)
+ oldfqdn = 1;
+ else
+ oldfqdn = 0;
+ if (oldfqdn) {
+ cp++; /* skip length */
+ while (cp < end) {
+ safeputc(*cp & 0xff);
+ cp++;
+ }
+ } else {
+ i = 0;
+ while (cp < end) {
+ if (dnsdecode((const u_char **)&cp, end,
+ (const u_char *)(ni + 1), dnsname,
+ sizeof(dnsname)) == NULL) {
+ printf("???");
+ break;
+ }
+ /*
+ * name-lookup special handling for
+ * truncated name
+ */
+ if (cp + 1 <= end && !*cp &&
+ strlen(dnsname) > 0) {
+ dnsname[strlen(dnsname) - 1] = '\0';
+ cp++;
+ }
+ printf("%s%s", i > 0 ? "," : "",
+ dnsname);
+ }
+ }
+ if (options & F_VERBOSE) {
+ int32_t ttl;
+ int comma = 0;
+
+ (void)printf(" ("); /*)*/
+
+ switch (ni->ni_code) {
+ case ICMP6_NI_REFUSED:
+ (void)printf("refused");
+ comma++;
+ break;
+ case ICMP6_NI_UNKNOWN:
+ (void)printf("unknown qtype");
+ comma++;
+ break;
+ }
+
+ if ((end - (u_char *)ni) < ICMP6_NIRLEN) {
+ /* case of refusion, unknown */
+ /*(*/
+ putchar(')');
+ goto fqdnend;
+ }
+ ttl = (int32_t)ntohl(*(u_long *)&buf[off+ICMP6ECHOLEN+8]);
+ if (comma)
+ printf(",");
+ if (!(ni->ni_flags & NI_FQDN_FLAG_VALIDTTL)) {
+ (void)printf("TTL=%d:meaningless",
+ (int)ttl);
+ } else {
+ if (ttl < 0) {
+ (void)printf("TTL=%d:invalid",
+ ttl);
+ } else
+ (void)printf("TTL=%d", ttl);
+ }
+ comma++;
+
+ if (oldfqdn) {
+ if (comma)
+ printf(",");
+ printf("03 draft");
+ comma++;
+ } else {
+ cp = (u_char *)ni + ICMP6_NIRLEN;
+ if (cp == end) {
+ if (comma)
+ printf(",");
+ printf("no name");
+ comma++;
+ }
+ }
+
+ if (buf[off + ICMP6_NIRLEN] !=
+ cc - off - ICMP6_NIRLEN - 1 && oldfqdn) {
+ if (comma)
+ printf(",");
+ (void)printf("invalid namelen:%d/%lu",
+ buf[off + ICMP6_NIRLEN],
+ (u_long)cc - off - ICMP6_NIRLEN - 1);
+ comma++;
+ }
+ /*(*/
+ putchar(')');
+ }
+ fqdnend:
+ ;
+ }
+ } else {
+ /* We've got something other than an ECHOREPLY */
+ if (!(options & F_VERBOSE))
+ return;
+ (void)printf("%d bytes from %s: ", cc, pr_addr(from, fromlen));
+ pr_icmph(icp, end);
+ }
+
+ if (!(options & F_FLOOD)) {
+ (void)putchar('\n');
+ if (options & F_VERBOSE)
+ pr_exthdrs(mhdr);
+ (void)fflush(stdout);
+ }
+#undef safeputc
+}
+
+void
+pr_exthdrs(mhdr)
+ struct msghdr *mhdr;
+{
+ ssize_t bufsize;
+ void *bufp;
+ struct cmsghdr *cm;
+
+ bufsize = 0;
+ bufp = mhdr->msg_control;
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_level != IPPROTO_IPV6)
+ continue;
+
+ bufsize = CONTROLLEN - ((caddr_t)CMSG_DATA(cm) - (caddr_t)bufp);
+ if (bufsize <= 0)
+ continue;
+ switch (cm->cmsg_type) {
+ case IPV6_HOPOPTS:
+ printf(" HbH Options: ");
+ pr_ip6opt(CMSG_DATA(cm), (size_t)bufsize);
+ break;
+ case IPV6_DSTOPTS:
+#ifdef IPV6_RTHDRDSTOPTS
+ case IPV6_RTHDRDSTOPTS:
+#endif
+ printf(" Dst Options: ");
+ pr_ip6opt(CMSG_DATA(cm), (size_t)bufsize);
+ break;
+ case IPV6_RTHDR:
+ printf(" Routing: ");
+ pr_rthdr(CMSG_DATA(cm), (size_t)bufsize);
+ break;
+ }
+ }
+}
+
+#ifdef USE_RFC2292BIS
+void
+pr_ip6opt(void *extbuf, size_t bufsize)
+{
+ struct ip6_hbh *ext;
+ int currentlen;
+ u_int8_t type;
+ socklen_t extlen, len, origextlen;
+ void *databuf;
+ size_t offset;
+ u_int16_t value2;
+ u_int32_t value4;
+
+ ext = (struct ip6_hbh *)extbuf;
+ extlen = (ext->ip6h_len + 1) * 8;
+ printf("nxt %u, len %u (%lu bytes)\n", ext->ip6h_nxt,
+ (unsigned int)ext->ip6h_len, (unsigned long)extlen);
+
+ /*
+ * Bounds checking on the ancillary data buffer:
+ * subtract the size of a cmsg structure from the buffer size.
+ */
+ if (bufsize < (extlen + CMSG_SPACE(0))) {
+ origextlen = extlen;
+ extlen = bufsize - CMSG_SPACE(0);
+ warnx("options truncated, showing only %u (total=%u)",
+ (unsigned int)(extlen / 8 - 1),
+ (unsigned int)(ext->ip6h_len));
+ }
+
+ currentlen = 0;
+ while (1) {
+ currentlen = inet6_opt_next(extbuf, extlen, currentlen,
+ &type, &len, &databuf);
+ if (currentlen == -1)
+ break;
+ switch (type) {
+ /*
+ * Note that inet6_opt_next automatically skips any padding
+ * optins.
+ */
+ case IP6OPT_JUMBO:
+ offset = 0;
+ offset = inet6_opt_get_val(databuf, offset,
+ &value4, sizeof(value4));
+ printf(" Jumbo Payload Opt: Length %u\n",
+ (u_int32_t)ntohl(value4));
+ break;
+ case IP6OPT_ROUTER_ALERT:
+ offset = 0;
+ offset = inet6_opt_get_val(databuf, offset,
+ &value2, sizeof(value2));
+ printf(" Router Alert Opt: Type %u\n",
+ ntohs(value2));
+ break;
+ default:
+ printf(" Received Opt %u len %lu\n",
+ type, (unsigned long)len);
+ break;
+ }
+ }
+ return;
+}
+#else /* !USE_RFC2292BIS */
+/* ARGSUSED */
+void
+pr_ip6opt(void *extbuf, size_t bufsize __unused)
+{
+ putchar('\n');
+ return;
+}
+#endif /* USE_RFC2292BIS */
+
+#ifdef USE_RFC2292BIS
+void
+pr_rthdr(void *extbuf, size_t bufsize)
+{
+ struct in6_addr *in6;
+ char ntopbuf[INET6_ADDRSTRLEN];
+ struct ip6_rthdr *rh = (struct ip6_rthdr *)extbuf;
+ int i, segments, origsegs, rthsize, size0, size1;
+
+ /* print fixed part of the header */
+ printf("nxt %u, len %u (%d bytes), type %u, ", rh->ip6r_nxt,
+ rh->ip6r_len, (rh->ip6r_len + 1) << 3, rh->ip6r_type);
+ if ((segments = inet6_rth_segments(extbuf)) >= 0) {
+ printf("%d segments, ", segments);
+ printf("%d left\n", rh->ip6r_segleft);
+ } else {
+ printf("segments unknown, ");
+ printf("%d left\n", rh->ip6r_segleft);
+ return;
+ }
+
+ /*
+ * Bounds checking on the ancillary data buffer. When calculating
+ * the number of items to show keep in mind:
+ * - The size of the cmsg structure
+ * - The size of one segment (the size of a Type 0 routing header)
+ * - When dividing add a fudge factor of one in case the
+ * dividend is not evenly divisible by the divisor
+ */
+ rthsize = (rh->ip6r_len + 1) * 8;
+ if (bufsize < (rthsize + CMSG_SPACE(0))) {
+ origsegs = segments;
+ size0 = inet6_rth_space(IPV6_RTHDR_TYPE_0, 0);
+ size1 = inet6_rth_space(IPV6_RTHDR_TYPE_0, 1);
+ segments -= (rthsize - (bufsize - CMSG_SPACE(0))) /
+ (size1 - size0) + 1;
+ warnx("segments truncated, showing only %d (total=%d)",
+ segments, origsegs);
+ }
+
+ for (i = 0; i < segments; i++) {
+ in6 = inet6_rth_getaddr(extbuf, i);
+ if (in6 == NULL)
+ printf(" [%d]<NULL>\n", i);
+ else {
+ if (!inet_ntop(AF_INET6, in6, ntopbuf,
+ sizeof(ntopbuf)))
+ strlcpy(ntopbuf, "?", sizeof(ntopbuf));
+ printf(" [%d]%s\n", i, ntopbuf);
+ }
+ }
+
+ return;
+
+}
+
+#else /* !USE_RFC2292BIS */
+/* ARGSUSED */
+void
+pr_rthdr(void *extbuf, size_t bufsize __unused)
+{
+ putchar('\n');
+ return;
+}
+#endif /* USE_RFC2292BIS */
+
+int
+pr_bitrange(v, soff, ii)
+ u_int32_t v;
+ int soff;
+ int ii;
+{
+ int off;
+ int i;
+
+ off = 0;
+ while (off < 32) {
+ /* shift till we have 0x01 */
+ if ((v & 0x01) == 0) {
+ if (ii > 1)
+ printf("-%u", soff + off - 1);
+ ii = 0;
+ switch (v & 0x0f) {
+ case 0x00:
+ v >>= 4;
+ off += 4;
+ continue;
+ case 0x08:
+ v >>= 3;
+ off += 3;
+ continue;
+ case 0x04: case 0x0c:
+ v >>= 2;
+ off += 2;
+ continue;
+ default:
+ v >>= 1;
+ off += 1;
+ continue;
+ }
+ }
+
+ /* we have 0x01 with us */
+ for (i = 0; i < 32 - off; i++) {
+ if ((v & (0x01 << i)) == 0)
+ break;
+ }
+ if (!ii)
+ printf(" %u", soff + off);
+ ii += i;
+ v >>= i; off += i;
+ }
+ return ii;
+}
+
+void
+pr_suptypes(ni, nilen)
+ struct icmp6_nodeinfo *ni; /* ni->qtype must be SUPTYPES */
+ size_t nilen;
+{
+ size_t clen;
+ u_int32_t v;
+ const u_char *cp, *end;
+ u_int16_t cur;
+ struct cbit {
+ u_int16_t words; /*32bit count*/
+ u_int16_t skip;
+ } cbit;
+#define MAXQTYPES (1 << 16)
+ size_t off;
+ int b;
+
+ cp = (u_char *)(ni + 1);
+ end = ((u_char *)ni) + nilen;
+ cur = 0;
+ b = 0;
+
+ printf("NodeInfo Supported Qtypes");
+ if (options & F_VERBOSE) {
+ if (ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS)
+ printf(", compressed bitmap");
+ else
+ printf(", raw bitmap");
+ }
+
+ while (cp < end) {
+ clen = (size_t)(end - cp);
+ if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) == 0) {
+ if (clen == 0 || clen > MAXQTYPES / 8 ||
+ clen % sizeof(v)) {
+ printf("???");
+ return;
+ }
+ } else {
+ if (clen < sizeof(cbit) || clen % sizeof(v))
+ return;
+ memcpy(&cbit, cp, sizeof(cbit));
+ if (sizeof(cbit) + ntohs(cbit.words) * sizeof(v) >
+ clen)
+ return;
+ cp += sizeof(cbit);
+ clen = ntohs(cbit.words) * sizeof(v);
+ if (cur + clen * 8 + (u_long)ntohs(cbit.skip) * 32 >
+ MAXQTYPES)
+ return;
+ }
+
+ for (off = 0; off < clen; off += sizeof(v)) {
+ memcpy(&v, cp + off, sizeof(v));
+ v = (u_int32_t)ntohl(v);
+ b = pr_bitrange(v, (int)(cur + off * 8), b);
+ }
+ /* flush the remaining bits */
+ b = pr_bitrange(0, (int)(cur + off * 8), b);
+
+ cp += clen;
+ cur += clen * 8;
+ if ((ni->ni_flags & NI_SUPTYPE_FLAG_COMPRESS) != 0)
+ cur += ntohs(cbit.skip) * 32;
+ }
+}
+
+void
+pr_nodeaddr(ni, nilen)
+ struct icmp6_nodeinfo *ni; /* ni->qtype must be NODEADDR */
+ int nilen;
+{
+ u_char *cp = (u_char *)(ni + 1);
+ char ntop_buf[INET6_ADDRSTRLEN];
+ int withttl = 0;
+
+ nilen -= sizeof(struct icmp6_nodeinfo);
+
+ if (options & F_VERBOSE) {
+ switch (ni->ni_code) {
+ case ICMP6_NI_REFUSED:
+ (void)printf("refused");
+ break;
+ case ICMP6_NI_UNKNOWN:
+ (void)printf("unknown qtype");
+ break;
+ }
+ if (ni->ni_flags & NI_NODEADDR_FLAG_TRUNCATE)
+ (void)printf(" truncated");
+ }
+ putchar('\n');
+ if (nilen <= 0)
+ printf(" no address\n");
+
+ /*
+ * In icmp-name-lookups 05 and later, TTL of each returned address
+ * is contained in the resposne. We try to detect the version
+ * by the length of the data, but note that the detection algorithm
+ * is incomplete. We assume the latest draft by default.
+ */
+ if (nilen % (sizeof(u_int32_t) + sizeof(struct in6_addr)) == 0)
+ withttl = 1;
+ while (nilen > 0) {
+ u_int32_t ttl;
+
+ if (withttl) {
+ /* XXX: alignment? */
+ ttl = (u_int32_t)ntohl(*(u_int32_t *)cp);
+ cp += sizeof(u_int32_t);
+ nilen -= sizeof(u_int32_t);
+ }
+
+ if (inet_ntop(AF_INET6, cp, ntop_buf, sizeof(ntop_buf)) ==
+ NULL)
+ strlcpy(ntop_buf, "?", sizeof(ntop_buf));
+ printf(" %s", ntop_buf);
+ if (withttl) {
+ if (ttl == 0xffffffff) {
+ /*
+ * XXX: can this convention be applied to all
+ * type of TTL (i.e. non-ND TTL)?
+ */
+ printf("(TTL=infty)");
+ }
+ else
+ printf("(TTL=%u)", ttl);
+ }
+ putchar('\n');
+
+ nilen -= sizeof(struct in6_addr);
+ cp += sizeof(struct in6_addr);
+ }
+}
+
+int
+get_hoplim(mhdr)
+ struct msghdr *mhdr;
+{
+ struct cmsghdr *cm;
+
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_len == 0)
+ return(-1);
+
+ if (cm->cmsg_level == IPPROTO_IPV6 &&
+ cm->cmsg_type == IPV6_HOPLIMIT &&
+ cm->cmsg_len == CMSG_LEN(sizeof(int)))
+ return(*(int *)CMSG_DATA(cm));
+ }
+
+ return(-1);
+}
+
+struct in6_pktinfo *
+get_rcvpktinfo(mhdr)
+ struct msghdr *mhdr;
+{
+ struct cmsghdr *cm;
+
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_len == 0)
+ return(NULL);
+
+ if (cm->cmsg_level == IPPROTO_IPV6 &&
+ cm->cmsg_type == IPV6_PKTINFO &&
+ cm->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo)))
+ return((struct in6_pktinfo *)CMSG_DATA(cm));
+ }
+
+ return(NULL);
+}
+
+int
+get_pathmtu(mhdr)
+ struct msghdr *mhdr;
+{
+#ifdef IPV6_RECVPATHMTU
+ struct cmsghdr *cm;
+ struct ip6_mtuinfo *mtuctl = NULL;
+
+ for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(mhdr); cm;
+ cm = (struct cmsghdr *)CMSG_NXTHDR(mhdr, cm)) {
+ if (cm->cmsg_len == 0)
+ return(0);
+
+ if (cm->cmsg_level == IPPROTO_IPV6 &&
+ cm->cmsg_type == IPV6_PATHMTU &&
+ cm->cmsg_len == CMSG_LEN(sizeof(struct ip6_mtuinfo))) {
+ mtuctl = (struct ip6_mtuinfo *)CMSG_DATA(cm);
+
+ /*
+ * If the notified destination is different from
+ * the one we are pinging, just ignore the info.
+ * We check the scope ID only when both notified value
+ * and our own value have non-0 values, because we may
+ * have used the default scope zone ID for sending,
+ * in which case the scope ID value is 0.
+ */
+ if (!IN6_ARE_ADDR_EQUAL(&mtuctl->ip6m_addr.sin6_addr,
+ &dst.sin6_addr) ||
+ (mtuctl->ip6m_addr.sin6_scope_id &&
+ dst.sin6_scope_id &&
+ mtuctl->ip6m_addr.sin6_scope_id !=
+ dst.sin6_scope_id)) {
+ if ((options & F_VERBOSE) != 0) {
+ printf("path MTU for %s is notified. "
+ "(ignored)\n",
+ pr_addr((struct sockaddr *)&mtuctl->ip6m_addr,
+ sizeof(mtuctl->ip6m_addr)));
+ }
+ return(0);
+ }
+
+ /*
+ * Ignore an invalid MTU. XXX: can we just believe
+ * the kernel check?
+ */
+ if (mtuctl->ip6m_mtu < IPV6_MMTU)
+ return(0);
+
+ /* notification for our destination. return the MTU. */
+ return((int)mtuctl->ip6m_mtu);
+ }
+ }
+#endif
+ return(0);
+}
+
+/*
+ * tvsub --
+ * Subtract 2 timeval structs: out = out - in. Out is assumed to
+ * be >= in.
+ */
+void
+tvsub(out, in)
+ struct timeval *out, *in;
+{
+ if ((out->tv_usec -= in->tv_usec) < 0) {
+ --out->tv_sec;
+ out->tv_usec += 1000000;
+ }
+ out->tv_sec -= in->tv_sec;
+}
+
+/*
+ * onint --
+ * SIGINT handler.
+ */
+/* ARGSUSED */
+void
+onint(notused)
+ int notused;
+{
+ summary();
+
+ (void)signal(SIGINT, SIG_DFL);
+ (void)kill(getpid(), SIGINT);
+
+ /* NOTREACHED */
+ exit(1);
+}
+
+/*
+ * summary --
+ * Print out statistics.
+ */
+void
+summary()
+{
+
+ (void)printf("\n--- %s ping6 statistics ---\n", hostname);
+ (void)printf("%ld packets transmitted, ", ntransmitted);
+ (void)printf("%ld packets received, ", nreceived);
+ if (nrepeats)
+ (void)printf("+%ld duplicates, ", nrepeats);
+ if (ntransmitted) {
+ if (nreceived > ntransmitted)
+ (void)printf("-- somebody's duplicating packets!");
+ else
+ (void)printf("%.1f%% packet loss",
+ ((((double)ntransmitted - nreceived) * 100.0) /
+ ntransmitted));
+ }
+ (void)putchar('\n');
+ if (nreceived && timing) {
+ /* Only display average to microseconds */
+ double num = nreceived + nrepeats;
+ double avg = tsum / num;
+ double dev = sqrt(tsumsq / num - avg * avg);
+ (void)printf(
+ "round-trip min/avg/max/std-dev = %.3f/%.3f/%.3f/%.3f ms\n",
+ tmin, avg, tmax, dev);
+ (void)fflush(stdout);
+ }
+ (void)fflush(stdout);
+}
+
+/*subject type*/
+static const char *niqcode[] = {
+ "IPv6 address",
+ "DNS label", /*or empty*/
+ "IPv4 address",
+};
+
+/*result code*/
+static const char *nircode[] = {
+ "Success", "Refused", "Unknown",
+};
+
+
+/*
+ * pr_icmph --
+ * Print a descriptive string about an ICMP header.
+ */
+void
+pr_icmph(icp, end)
+ struct icmp6_hdr *icp;
+ u_char *end;
+{
+ char ntop_buf[INET6_ADDRSTRLEN];
+ struct nd_redirect *red;
+ struct icmp6_nodeinfo *ni;
+ char dnsname[MAXDNAME + 1];
+ const u_char *cp;
+ size_t l;
+
+ switch (icp->icmp6_type) {
+ case ICMP6_DST_UNREACH:
+ switch (icp->icmp6_code) {
+ case ICMP6_DST_UNREACH_NOROUTE:
+ (void)printf("No Route to Destination\n");
+ break;
+ case ICMP6_DST_UNREACH_ADMIN:
+ (void)printf("Destination Administratively "
+ "Unreachable\n");
+ break;
+ case ICMP6_DST_UNREACH_BEYONDSCOPE:
+ (void)printf("Destination Unreachable Beyond Scope\n");
+ break;
+ case ICMP6_DST_UNREACH_ADDR:
+ (void)printf("Destination Host Unreachable\n");
+ break;
+ case ICMP6_DST_UNREACH_NOPORT:
+ (void)printf("Destination Port Unreachable\n");
+ break;
+ default:
+ (void)printf("Destination Unreachable, Bad Code: %d\n",
+ icp->icmp6_code);
+ break;
+ }
+ /* Print returned IP header information */
+ pr_retip((struct ip6_hdr *)(icp + 1), end);
+ break;
+ case ICMP6_PACKET_TOO_BIG:
+ (void)printf("Packet too big mtu = %d\n",
+ (int)ntohl(icp->icmp6_mtu));
+ pr_retip((struct ip6_hdr *)(icp + 1), end);
+ break;
+ case ICMP6_TIME_EXCEEDED:
+ switch (icp->icmp6_code) {
+ case ICMP6_TIME_EXCEED_TRANSIT:
+ (void)printf("Time to live exceeded\n");
+ break;
+ case ICMP6_TIME_EXCEED_REASSEMBLY:
+ (void)printf("Frag reassembly time exceeded\n");
+ break;
+ default:
+ (void)printf("Time exceeded, Bad Code: %d\n",
+ icp->icmp6_code);
+ break;
+ }
+ pr_retip((struct ip6_hdr *)(icp + 1), end);
+ break;
+ case ICMP6_PARAM_PROB:
+ (void)printf("Parameter problem: ");
+ switch (icp->icmp6_code) {
+ case ICMP6_PARAMPROB_HEADER:
+ (void)printf("Erroneous Header ");
+ break;
+ case ICMP6_PARAMPROB_NEXTHEADER:
+ (void)printf("Unknown Nextheader ");
+ break;
+ case ICMP6_PARAMPROB_OPTION:
+ (void)printf("Unrecognized Option ");
+ break;
+ default:
+ (void)printf("Bad code(%d) ", icp->icmp6_code);
+ break;
+ }
+ (void)printf("pointer = 0x%02x\n",
+ (u_int32_t)ntohl(icp->icmp6_pptr));
+ pr_retip((struct ip6_hdr *)(icp + 1), end);
+ break;
+ case ICMP6_ECHO_REQUEST:
+ (void)printf("Echo Request");
+ /* XXX ID + Seq + Data */
+ break;
+ case ICMP6_ECHO_REPLY:
+ (void)printf("Echo Reply");
+ /* XXX ID + Seq + Data */
+ break;
+ case ICMP6_MEMBERSHIP_QUERY:
+ (void)printf("Listener Query");
+ break;
+ case ICMP6_MEMBERSHIP_REPORT:
+ (void)printf("Listener Report");
+ break;
+ case ICMP6_MEMBERSHIP_REDUCTION:
+ (void)printf("Listener Done");
+ break;
+ case ND_ROUTER_SOLICIT:
+ (void)printf("Router Solicitation");
+ break;
+ case ND_ROUTER_ADVERT:
+ (void)printf("Router Advertisement");
+ break;
+ case ND_NEIGHBOR_SOLICIT:
+ (void)printf("Neighbor Solicitation");
+ break;
+ case ND_NEIGHBOR_ADVERT:
+ (void)printf("Neighbor Advertisement");
+ break;
+ case ND_REDIRECT:
+ red = (struct nd_redirect *)icp;
+ (void)printf("Redirect\n");
+ if (!inet_ntop(AF_INET6, &red->nd_rd_dst, ntop_buf,
+ sizeof(ntop_buf)))
+ strlcpy(ntop_buf, "?", sizeof(ntop_buf));
+ (void)printf("Destination: %s", ntop_buf);
+ if (!inet_ntop(AF_INET6, &red->nd_rd_target, ntop_buf,
+ sizeof(ntop_buf)))
+ strlcpy(ntop_buf, "?", sizeof(ntop_buf));
+ (void)printf(" New Target: %s", ntop_buf);
+ break;
+ case ICMP6_NI_QUERY:
+ (void)printf("Node Information Query");
+ /* XXX ID + Seq + Data */
+ ni = (struct icmp6_nodeinfo *)icp;
+ l = end - (u_char *)(ni + 1);
+ printf(", ");
+ switch (ntohs(ni->ni_qtype)) {
+ case NI_QTYPE_NOOP:
+ (void)printf("NOOP");
+ break;
+ case NI_QTYPE_SUPTYPES:
+ (void)printf("Supported qtypes");
+ break;
+ case NI_QTYPE_FQDN:
+ (void)printf("DNS name");
+ break;
+ case NI_QTYPE_NODEADDR:
+ (void)printf("nodeaddr");
+ break;
+ case NI_QTYPE_IPV4ADDR:
+ (void)printf("IPv4 nodeaddr");
+ break;
+ default:
+ (void)printf("unknown qtype");
+ break;
+ }
+ if (options & F_VERBOSE) {
+ switch (ni->ni_code) {
+ case ICMP6_NI_SUBJ_IPV6:
+ if (l == sizeof(struct in6_addr) &&
+ inet_ntop(AF_INET6, ni + 1, ntop_buf,
+ sizeof(ntop_buf)) != NULL) {
+ (void)printf(", subject=%s(%s)",
+ niqcode[ni->ni_code], ntop_buf);
+ } else {
+#if 1
+ /* backward compat to -W */
+ (void)printf(", oldfqdn");
+#else
+ (void)printf(", invalid");
+#endif
+ }
+ break;
+ case ICMP6_NI_SUBJ_FQDN:
+ if (end == (u_char *)(ni + 1)) {
+ (void)printf(", no subject");
+ break;
+ }
+ printf(", subject=%s", niqcode[ni->ni_code]);
+ cp = (const u_char *)(ni + 1);
+ if (dnsdecode(&cp, end, NULL, dnsname,
+ sizeof(dnsname)) != NULL)
+ printf("(%s)", dnsname);
+ else
+ printf("(invalid)");
+ break;
+ case ICMP6_NI_SUBJ_IPV4:
+ if (l == sizeof(struct in_addr) &&
+ inet_ntop(AF_INET, ni + 1, ntop_buf,
+ sizeof(ntop_buf)) != NULL) {
+ (void)printf(", subject=%s(%s)",
+ niqcode[ni->ni_code], ntop_buf);
+ } else
+ (void)printf(", invalid");
+ break;
+ default:
+ (void)printf(", invalid");
+ break;
+ }
+ }
+ break;
+ case ICMP6_NI_REPLY:
+ (void)printf("Node Information Reply");
+ /* XXX ID + Seq + Data */
+ ni = (struct icmp6_nodeinfo *)icp;
+ printf(", ");
+ switch (ntohs(ni->ni_qtype)) {
+ case NI_QTYPE_NOOP:
+ (void)printf("NOOP");
+ break;
+ case NI_QTYPE_SUPTYPES:
+ (void)printf("Supported qtypes");
+ break;
+ case NI_QTYPE_FQDN:
+ (void)printf("DNS name");
+ break;
+ case NI_QTYPE_NODEADDR:
+ (void)printf("nodeaddr");
+ break;
+ case NI_QTYPE_IPV4ADDR:
+ (void)printf("IPv4 nodeaddr");
+ break;
+ default:
+ (void)printf("unknown qtype");
+ break;
+ }
+ if (options & F_VERBOSE) {
+ if (ni->ni_code > sizeof(nircode) / sizeof(nircode[0]))
+ printf(", invalid");
+ else
+ printf(", %s", nircode[ni->ni_code]);
+ }
+ break;
+ default:
+ (void)printf("Bad ICMP type: %d", icp->icmp6_type);
+ }
+}
+
+/*
+ * pr_iph --
+ * Print an IP6 header.
+ */
+void
+pr_iph(ip6)
+ struct ip6_hdr *ip6;
+{
+ u_int32_t flow = ip6->ip6_flow & IPV6_FLOWLABEL_MASK;
+ u_int8_t tc;
+ char ntop_buf[INET6_ADDRSTRLEN];
+
+ tc = *(&ip6->ip6_vfc + 1); /* XXX */
+ tc = (tc >> 4) & 0x0f;
+ tc |= (ip6->ip6_vfc << 4);
+
+ printf("Vr TC Flow Plen Nxt Hlim\n");
+ printf(" %1x %02x %05x %04x %02x %02x\n",
+ (ip6->ip6_vfc & IPV6_VERSION_MASK) >> 4, tc, (u_int32_t)ntohl(flow),
+ ntohs(ip6->ip6_plen), ip6->ip6_nxt, ip6->ip6_hlim);
+ if (!inet_ntop(AF_INET6, &ip6->ip6_src, ntop_buf, sizeof(ntop_buf)))
+ strlcpy(ntop_buf, "?", sizeof(ntop_buf));
+ printf("%s->", ntop_buf);
+ if (!inet_ntop(AF_INET6, &ip6->ip6_dst, ntop_buf, sizeof(ntop_buf)))
+ strlcpy(ntop_buf, "?", sizeof(ntop_buf));
+ printf("%s\n", ntop_buf);
+}
+
+/*
+ * pr_addr --
+ * Return an ascii host address as a dotted quad and optionally with
+ * a hostname.
+ */
+const char *
+pr_addr(addr, addrlen)
+ struct sockaddr *addr;
+ int addrlen;
+{
+ static char buf[NI_MAXHOST];
+ int flag = 0;
+
+ if ((options & F_HOSTNAME) == 0)
+ flag |= NI_NUMERICHOST;
+
+ if (getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, flag) == 0)
+ return (buf);
+ else
+ return "?";
+}
+
+/*
+ * pr_retip --
+ * Dump some info on a returned (via ICMPv6) IPv6 packet.
+ */
+void
+pr_retip(ip6, end)
+ struct ip6_hdr *ip6;
+ u_char *end;
+{
+ u_char *cp = (u_char *)ip6, nh;
+ int hlen;
+
+ if (end - (u_char *)ip6 < sizeof(*ip6)) {
+ printf("IP6");
+ goto trunc;
+ }
+ pr_iph(ip6);
+ hlen = sizeof(*ip6);
+
+ nh = ip6->ip6_nxt;
+ cp += hlen;
+ while (end - cp >= 8) {
+ switch (nh) {
+ case IPPROTO_HOPOPTS:
+ printf("HBH ");
+ hlen = (((struct ip6_hbh *)cp)->ip6h_len+1) << 3;
+ nh = ((struct ip6_hbh *)cp)->ip6h_nxt;
+ break;
+ case IPPROTO_DSTOPTS:
+ printf("DSTOPT ");
+ hlen = (((struct ip6_dest *)cp)->ip6d_len+1) << 3;
+ nh = ((struct ip6_dest *)cp)->ip6d_nxt;
+ break;
+ case IPPROTO_FRAGMENT:
+ printf("FRAG ");
+ hlen = sizeof(struct ip6_frag);
+ nh = ((struct ip6_frag *)cp)->ip6f_nxt;
+ break;
+ case IPPROTO_ROUTING:
+ printf("RTHDR ");
+ hlen = (((struct ip6_rthdr *)cp)->ip6r_len+1) << 3;
+ nh = ((struct ip6_rthdr *)cp)->ip6r_nxt;
+ break;
+#ifdef IPSEC
+ case IPPROTO_AH:
+ printf("AH ");
+ hlen = (((struct ah *)cp)->ah_len+2) << 2;
+ nh = ((struct ah *)cp)->ah_nxt;
+ break;
+#endif
+ case IPPROTO_ICMPV6:
+ printf("ICMP6: type = %d, code = %d\n",
+ *cp, *(cp + 1));
+ return;
+ case IPPROTO_ESP:
+ printf("ESP\n");
+ return;
+ case IPPROTO_TCP:
+ printf("TCP: from port %u, to port %u (decimal)\n",
+ (*cp * 256 + *(cp + 1)),
+ (*(cp + 2) * 256 + *(cp + 3)));
+ return;
+ case IPPROTO_UDP:
+ printf("UDP: from port %u, to port %u (decimal)\n",
+ (*cp * 256 + *(cp + 1)),
+ (*(cp + 2) * 256 + *(cp + 3)));
+ return;
+ default:
+ printf("Unknown Header(%d)\n", nh);
+ return;
+ }
+
+ if ((cp += hlen) >= end)
+ goto trunc;
+ }
+ if (end - cp < 8)
+ goto trunc;
+
+ putchar('\n');
+ return;
+
+ trunc:
+ printf("...\n");
+ return;
+}
+
+void
+fill(bp, patp)
+ char *bp, *patp;
+{
+ int ii, jj, kk;
+ int pat[16];
+ char *cp;
+
+ for (cp = patp; *cp; cp++)
+ if (!isxdigit(*cp))
+ errx(1, "patterns must be specified as hex digits");
+ ii = sscanf(patp,
+ "%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &pat[0], &pat[1], &pat[2], &pat[3], &pat[4], &pat[5], &pat[6],
+ &pat[7], &pat[8], &pat[9], &pat[10], &pat[11], &pat[12],
+ &pat[13], &pat[14], &pat[15]);
+
+/* xxx */
+ if (ii > 0)
+ for (kk = 0;
+ kk <= MAXDATALEN - (8 + sizeof(struct tv32) + ii);
+ kk += ii)
+ for (jj = 0; jj < ii; ++jj)
+ bp[jj + kk] = pat[jj];
+ if (!(options & F_QUIET)) {
+ (void)printf("PATTERN: 0x");
+ for (jj = 0; jj < ii; ++jj)
+ (void)printf("%02x", bp[jj] & 0xFF);
+ (void)printf("\n");
+ }
+}
+
+#ifdef IPSEC
+#ifdef IPSEC_POLICY_IPSEC
+int
+setpolicy(so, policy)
+ int so;
+ char *policy;
+{
+ char *buf;
+
+ if (policy == NULL)
+ return 0; /* ignore */
+
+ buf = ipsec_set_policy(policy, strlen(policy));
+ if (buf == NULL)
+ errx(1, "%s", ipsec_strerror());
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_IPSEC_POLICY, buf,
+ ipsec_get_policylen(buf)) < 0)
+ warnx("Unable to set IPsec policy");
+ free(buf);
+
+ return 0;
+}
+#endif
+#endif
+
+char *
+nigroup(name)
+ char *name;
+{
+ char *p;
+ char *q;
+ MD5_CTX ctxt;
+ u_int8_t digest[16];
+ u_int8_t c;
+ size_t l;
+ char hbuf[NI_MAXHOST];
+ struct in6_addr in6;
+
+ p = strchr(name, '.');
+ if (!p)
+ p = name + strlen(name);
+ l = p - name;
+ if (l > 63 || l > sizeof(hbuf) - 1)
+ return NULL; /*label too long*/
+ strncpy(hbuf, name, l);
+ hbuf[(int)l] = '\0';
+
+ for (q = name; *q; q++) {
+ if (isupper(*(unsigned char *)q))
+ *q = tolower(*(unsigned char *)q);
+ }
+
+ /* generate 8 bytes of pseudo-random value. */
+ memset(&ctxt, 0, sizeof(ctxt));
+ MD5Init(&ctxt);
+ c = l & 0xff;
+ MD5Update(&ctxt, &c, sizeof(c));
+ MD5Update(&ctxt, (unsigned char *)name, l);
+ MD5Final(digest, &ctxt);
+
+ if (inet_pton(AF_INET6, "ff02::2:0000:0000", &in6) != 1)
+ return NULL; /*XXX*/
+ bcopy(digest, &in6.s6_addr[12], 4);
+
+ if (inet_ntop(AF_INET6, &in6, hbuf, sizeof(hbuf)) == NULL)
+ return NULL;
+
+ return strdup(hbuf);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+#if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC)
+ "A"
+#endif
+ "usage: ping6 [-"
+ "Dd"
+#if defined(IPSEC) && !defined(IPSEC_POLICY_IPSEC)
+ "E"
+#endif
+ "fH"
+#ifdef IPV6_USE_MIN_MTU
+ "m"
+#endif
+ "nNoqrRtvwW] "
+ "[-a addrtype] [-b bufsiz] [-c count] [-g gateway]\n"
+ " [-h hoplimit] [-I interface] [-i wait] [-l preload]"
+#if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC)
+ " [-P policy]"
+#endif
+ "\n"
+ " [-p pattern] [-S sourceaddr] [-s packetsize] "
+ "[hops ...] host\n");
+ exit(1);
+}
diff --git a/freebsd/sbin/route/keywords b/freebsd/sbin/route/keywords
new file mode 100644
index 00000000..8817f305
--- /dev/null
+++ b/freebsd/sbin/route/keywords
@@ -0,0 +1,55 @@
+# @(#)keywords 8.2 (Berkeley) 3/19/94
+# $FreeBSD$
+
+add
+atalk
+blackhole
+change
+cloning
+del
+delete
+dst
+expire
+flush
+gateway
+genmask
+get
+host
+hopcount
+iface
+interface
+ifa
+ifp
+inet
+inet6
+iso
+link
+llinfo
+lock
+lockrest
+mask
+monitor
+mtu
+net
+netmask
+nostatic
+nostick
+osi
+prefixlen
+proto1
+proto2
+proxy
+recvpipe
+reject
+rtt
+rttvar
+sa
+sendpipe
+show
+ssthresh
+static
+sticky
+weight
+x25
+xns
+xresolve
diff --git a/freebsd/sbin/route/route.c b/freebsd/sbin/route/route.c
new file mode 100644
index 00000000..c0f2d50a
--- /dev/null
+++ b/freebsd/sbin/route/route.c
@@ -0,0 +1,1733 @@
+#ifdef __rtems__
+#define __need_getopt_newlib
+#include <getopt.h>
+#endif
+/*
+ * Copyright (c) 1983, 1989, 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) 1983, 1989, 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#ifndef lint
+#if 0
+static char sccsid[] = "@(#)route.c 8.6 (Berkeley) 4/28/95";
+#endif
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/sysctl.h>
+#include <sys/types.h>
+
+#include <net/if.h>
+#include <net/route.h>
+#include <net/if_dl.h>
+#include <netinet/in.h>
+
+#include <netinet/if_ether.h>
+#include <netatalk/at.h>
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <ifaddrs.h>
+
+#ifdef __rtems__
+#ifndef _PATH_DEVNULL
+#define _PATH_DEVNULL "/dev/null"
+#endif
+#endif
+
+
+struct keytab {
+ char *kt_cp;
+ int kt_i;
+} keywords[] = {
+#include "keywords.h"
+ {0, 0}
+};
+
+struct ortentry route;
+union sockunion {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+ struct sockaddr_at sat;
+ struct sockaddr_dl sdl;
+ struct sockaddr_inarp sinarp;
+ struct sockaddr_storage ss; /* added to avoid memory overrun */
+} so_dst, so_gate, so_mask, so_genmask, so_ifa, so_ifp;
+
+typedef union sockunion *sup;
+int pid, rtm_addrs;
+int s;
+int forcehost, forcenet, doflush, nflag, af, qflag, tflag, keyword();
+int iflag, verbose, aflen = sizeof (struct sockaddr_in);
+int locking, lockrest, debugonly;
+struct rt_metrics rt_metrics;
+u_long rtm_inits;
+uid_t uid;
+int atalk_aton(const char *, struct at_addr *);
+char *atalk_ntoa(struct at_addr);
+const char *routename(), *netname();
+void flushroutes(), newroute(), monitor(), sockaddr(), sodump(), bprintf();
+void print_getmsg(), print_rtmsg(), pmsg_common(), pmsg_addrs(), mask_addr();
+#ifdef INET6
+static int inet6_makenetandmask(struct sockaddr_in6 *, char *);
+#endif
+int getaddr(), rtmsg(), x25_makemask();
+int prefixlen();
+extern char *iso_ntoa();
+
+void usage(const char *) __dead2;
+
+#ifdef __rtems__
+
+static int main_route(int argc, char **argv);
+
+static int rtems_shell_main_route(int argc, char *argv[])
+{
+ rtems_shell_globals_t route_globals;
+ rtems_shell_globals = &route_globals;
+ memset (rtems_shell_globals, 0, sizeof (route_globals));
+ route_globals.exit_code = 1;
+ if (setjmp (route_globals.exit_jmp) == 0)
+ return main_route ( argc, argv);
+ return route_globals.exit_code;
+}
+
+#endif
+
+
+void
+usage(cp)
+ const char *cp;
+{
+ if (cp)
+ warnx("bad keyword: %s", cp);
+ (void) fprintf(stderr,
+ "usage: route [-dnqtv] command [[modifiers] args]\n");
+ exit(EX_USAGE);
+ /* NOTREACHED */
+}
+
+#ifdef __rtems__
+int
+main_route(argc, argv)
+#else
+main(argc, argv)
+#endif
+ int argc;
+ char **argv;
+{
+ int ch;
+#ifdef __rtems__
+ struct getopt_data getopt_reent;
+#define optind getopt_reent.optind
+#define optarg getopt_reent.optarg
+#define opterr getopt_reent.opterr
+#define optopt getopt_reent.optopt
+#endif
+
+ if (argc < 2)
+ usage((char *)NULL);
+
+#ifdef __rtems__
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+ while ((ch = getopt_r(argc, argv, "nqdtv", &getopt_reent)) != -1)
+#else
+ while ((ch = getopt(argc, argv, "nqdtv")) != -1)
+#endif
+ switch(ch) {
+ case 'n':
+ nflag = 1;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'd':
+ debugonly = 1;
+ break;
+ case '?':
+ default:
+ usage((char *)NULL);
+ }
+ argc -= optind;
+ argv += optind;
+
+ pid = getpid();
+ uid = geteuid();
+ if (tflag)
+ s = open(_PATH_DEVNULL, O_WRONLY, 0);
+ else
+ s = socket(PF_ROUTE, SOCK_RAW, 0);
+ if (s < 0)
+ err(EX_OSERR, "socket");
+ if (*argv)
+ switch (keyword(*argv)) {
+ case K_GET:
+ case K_SHOW:
+ uid = 0;
+ /* FALLTHROUGH */
+
+ case K_CHANGE:
+ case K_ADD:
+ case K_DEL:
+ case K_DELETE:
+ newroute(argc, argv);
+ /* NOTREACHED */
+
+ case K_MONITOR:
+ monitor();
+ /* NOTREACHED */
+
+ case K_FLUSH:
+ flushroutes(argc, argv);
+ exit(0);
+ /* NOTREACHED */
+ }
+ usage(*argv);
+ /* NOTREACHED */
+}
+
+/*
+ * Purge all entries in the routing tables not
+ * associated with network interfaces.
+ */
+void
+flushroutes(argc, argv)
+ int argc;
+ char *argv[];
+{
+ size_t needed;
+ int mib[6], rlen, seqno, count = 0;
+ char *buf, *next, *lim;
+ struct rt_msghdr *rtm;
+
+ if (uid && !debugonly) {
+ errx(EX_NOPERM, "must be root to alter routing table");
+ }
+ shutdown(s, SHUT_RD); /* Don't want to read back our messages */
+ if (argc > 1) {
+ argv++;
+ if (argc == 2 && **argv == '-')
+ switch (keyword(*argv + 1)) {
+ case K_INET:
+ af = AF_INET;
+ break;
+#ifdef INET6
+ case K_INET6:
+ af = AF_INET6;
+ break;
+#endif
+ case K_ATALK:
+ af = AF_APPLETALK;
+ break;
+ case K_LINK:
+ af = AF_LINK;
+ break;
+ default:
+ goto bad;
+ } else
+bad: usage(*argv);
+ }
+retry:
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0; /* protocol */
+ mib[3] = 0; /* wildcard address family */
+ mib[4] = NET_RT_DUMP;
+ mib[5] = 0; /* no flags */
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ err(EX_OSERR, "route-sysctl-estimate");
+ if ((buf = malloc(needed)) == NULL)
+ errx(EX_OSERR, "malloc failed");
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ if (errno == ENOMEM && count++ < 10) {
+ warnx("Routing table grew, retrying");
+ sleep(1);
+ free(buf);
+ goto retry;
+ }
+ err(EX_OSERR, "route-sysctl-get");
+ }
+ lim = buf + needed;
+ if (verbose)
+ (void) printf("Examining routing table from sysctl\n");
+ seqno = 0; /* ??? */
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ if (verbose)
+ print_rtmsg(rtm, rtm->rtm_msglen);
+ if ((rtm->rtm_flags & RTF_GATEWAY) == 0)
+ continue;
+ if (af) {
+ struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+
+ if (sa->sa_family != af)
+ continue;
+ }
+ if (debugonly)
+ continue;
+ rtm->rtm_type = RTM_DELETE;
+ rtm->rtm_seq = seqno;
+ rlen = write(s, next, rtm->rtm_msglen);
+ if (rlen < 0 && errno == EPERM)
+ err(1, "write to routing socket");
+ if (rlen < (int)rtm->rtm_msglen) {
+ warn("write to routing socket");
+ (void) printf("got only %d for rlen\n", rlen);
+ free(buf);
+ goto retry;
+ break;
+ }
+ seqno++;
+ if (qflag)
+ continue;
+ if (verbose)
+ print_rtmsg(rtm, rlen);
+ else {
+ struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+ (void) printf("%-20.20s ", rtm->rtm_flags & RTF_HOST ?
+ routename(sa) : netname(sa));
+ sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
+ (void) printf("%-20.20s ", routename(sa));
+ (void) printf("done\n");
+ }
+ }
+}
+
+const char *
+routename(sa)
+ struct sockaddr *sa;
+{
+ char *cp;
+ static char line[MAXHOSTNAMELEN + 1];
+ struct hostent *hp;
+ static char domain[MAXHOSTNAMELEN + 1];
+ static int first = 1, n;
+
+ if (first) {
+ first = 0;
+ if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+ (cp = strchr(domain, '.'))) {
+ domain[MAXHOSTNAMELEN] = '\0';
+ (void) strcpy(domain, cp + 1);
+ } else
+ domain[0] = 0;
+ }
+
+ if (sa->sa_len == 0)
+ strcpy(line, "default");
+ else switch (sa->sa_family) {
+
+ case AF_INET:
+ { struct in_addr in;
+ in = ((struct sockaddr_in *)sa)->sin_addr;
+
+ cp = 0;
+ if (in.s_addr == INADDR_ANY || sa->sa_len < 4)
+ cp = "default";
+ if (cp == 0 && !nflag) {
+ hp = gethostbyaddr((char *)&in, sizeof (struct in_addr),
+ AF_INET);
+ if (hp) {
+ if ((cp = strchr(hp->h_name, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ cp = hp->h_name;
+ }
+ }
+ if (cp) {
+ strncpy(line, cp, sizeof(line) - 1);
+ line[sizeof(line) - 1] = '\0';
+ } else
+ (void) sprintf(line, "%s", inet_ntoa(in));
+ break;
+ }
+
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 sin6; /* use static var for safety */
+ int niflags = 0;
+
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6, sa, sa->sa_len);
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+#ifdef __KAME__
+ if (sa->sa_len == sizeof(struct sockaddr_in6) &&
+ (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
+ sin6.sin6_scope_id == 0) {
+ sin6.sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
+ sin6.sin6_addr.s6_addr[2] = 0;
+ sin6.sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+ if (nflag)
+ niflags |= NI_NUMERICHOST;
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ line, sizeof(line), NULL, 0, niflags) != 0)
+ strncpy(line, "invalid", sizeof(line));
+
+ return(line);
+ }
+#endif
+
+ case AF_APPLETALK:
+ (void) snprintf(line, sizeof(line), "atalk %s",
+ atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
+ break;
+
+ case AF_LINK:
+ return (link_ntoa((struct sockaddr_dl *)sa));
+
+ default:
+ { u_short *s = (u_short *)sa;
+ u_short *slim = s + ((sa->sa_len + 1) >> 1);
+ char *cp = line + sprintf(line, "(%d)", sa->sa_family);
+ char *cpe = line + sizeof(line);
+
+ while (++s < slim && cp < cpe) /* start with sa->sa_data */
+ if ((n = snprintf(cp, cpe - cp, " %x", *s)) > 0)
+ cp += n;
+ else
+ *cp = '\0';
+ break;
+ }
+ }
+ return (line);
+}
+
+/*
+ * Return the name of the network whose address is given.
+ * The address is assumed to be that of a net or subnet, not a host.
+ */
+const char *
+netname(sa)
+ struct sockaddr *sa;
+{
+ char *cp = 0;
+ static char line[MAXHOSTNAMELEN + 1];
+ struct netent *np = 0;
+ u_long net, mask;
+ u_long i;
+ int n, subnetshift;
+
+ switch (sa->sa_family) {
+
+ case AF_INET:
+ { struct in_addr in;
+ in = ((struct sockaddr_in *)sa)->sin_addr;
+
+ i = in.s_addr = ntohl(in.s_addr);
+ if (in.s_addr == 0)
+ cp = "default";
+ else if (!nflag) {
+ if (IN_CLASSA(i)) {
+ mask = IN_CLASSA_NET;
+ subnetshift = 8;
+ } else if (IN_CLASSB(i)) {
+ mask = IN_CLASSB_NET;
+ subnetshift = 8;
+ } else {
+ mask = IN_CLASSC_NET;
+ subnetshift = 4;
+ }
+ /*
+ * If there are more bits than the standard mask
+ * would suggest, subnets must be in use.
+ * Guess at the subnet mask, assuming reasonable
+ * width subnet fields.
+ */
+ while (in.s_addr &~ mask)
+ mask = (long)mask >> subnetshift;
+ net = in.s_addr & mask;
+ while ((mask & 1) == 0)
+ mask >>= 1, net >>= 1;
+ np = getnetbyaddr(net, AF_INET);
+ if (np)
+ cp = np->n_name;
+ }
+#define C(x) (unsigned)((x) & 0xff)
+ if (cp)
+ strncpy(line, cp, sizeof(line));
+ else if ((in.s_addr & 0xffffff) == 0)
+ (void) sprintf(line, "%u", C(in.s_addr >> 24));
+ else if ((in.s_addr & 0xffff) == 0)
+ (void) sprintf(line, "%u.%u", C(in.s_addr >> 24),
+ C(in.s_addr >> 16));
+ else if ((in.s_addr & 0xff) == 0)
+ (void) sprintf(line, "%u.%u.%u", C(in.s_addr >> 24),
+ C(in.s_addr >> 16), C(in.s_addr >> 8));
+ else
+ (void) sprintf(line, "%u.%u.%u.%u", C(in.s_addr >> 24),
+ C(in.s_addr >> 16), C(in.s_addr >> 8),
+ C(in.s_addr));
+#undef C
+ break;
+ }
+
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 sin6; /* use static var for safety */
+ int niflags = 0;
+
+ memset(&sin6, 0, sizeof(sin6));
+ memcpy(&sin6, sa, sa->sa_len);
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+#ifdef __KAME__
+ if (sa->sa_len == sizeof(struct sockaddr_in6) &&
+ (IN6_IS_ADDR_LINKLOCAL(&sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&sin6.sin6_addr)) &&
+ sin6.sin6_scope_id == 0) {
+ sin6.sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6.sin6_addr.s6_addr[2]);
+ sin6.sin6_addr.s6_addr[2] = 0;
+ sin6.sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+ if (nflag)
+ niflags |= NI_NUMERICHOST;
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ line, sizeof(line), NULL, 0, niflags) != 0)
+ strncpy(line, "invalid", sizeof(line));
+
+ return(line);
+ }
+#endif
+
+ case AF_APPLETALK:
+ (void) snprintf(line, sizeof(line), "atalk %s",
+ atalk_ntoa(((struct sockaddr_at *)sa)->sat_addr));
+ break;
+
+ case AF_LINK:
+ return (link_ntoa((struct sockaddr_dl *)sa));
+
+
+ default:
+ { u_short *s = (u_short *)sa->sa_data;
+ u_short *slim = s + ((sa->sa_len + 1)>>1);
+ char *cp = line + sprintf(line, "af %d:", sa->sa_family);
+ char *cpe = line + sizeof(line);
+
+ while (s < slim && cp < cpe)
+ if ((n = snprintf(cp, cpe - cp, " %x", *s++)) > 0)
+ cp += n;
+ else
+ *cp = '\0';
+ break;
+ }
+ }
+ return (line);
+}
+
+void
+set_metric(value, key)
+ char *value;
+ int key;
+{
+ int flag = 0;
+ u_long noval, *valp = &noval;
+
+ switch (key) {
+#define caseof(x, y, z) case x: valp = &rt_metrics.z; flag = y; break
+ caseof(K_MTU, RTV_MTU, rmx_mtu);
+ caseof(K_HOPCOUNT, RTV_HOPCOUNT, rmx_hopcount);
+ caseof(K_EXPIRE, RTV_EXPIRE, rmx_expire);
+ caseof(K_RECVPIPE, RTV_RPIPE, rmx_recvpipe);
+ caseof(K_SENDPIPE, RTV_SPIPE, rmx_sendpipe);
+ caseof(K_SSTHRESH, RTV_SSTHRESH, rmx_ssthresh);
+ caseof(K_RTT, RTV_RTT, rmx_rtt);
+ caseof(K_RTTVAR, RTV_RTTVAR, rmx_rttvar);
+ caseof(K_WEIGHT, RTV_WEIGHT, rmx_weight);
+ }
+ rtm_inits |= flag;
+ if (lockrest || locking)
+ rt_metrics.rmx_locks |= flag;
+ if (locking)
+ locking = 0;
+ *valp = atoi(value);
+}
+
+void
+newroute(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *cmd, *dest = "", *gateway = "", *err;
+ int ishost = 0, proxy = 0, ret, attempts, oerrno, flags = RTF_STATIC;
+ int key;
+ struct hostent *hp = 0;
+
+ if (uid) {
+ errx(EX_NOPERM, "must be root to alter routing table");
+ }
+ cmd = argv[0];
+ if (*cmd != 'g' && *cmd != 's')
+ shutdown(s, SHUT_RD); /* Don't want to read back our messages */
+
+ while (--argc > 0) {
+ if (**(++argv)== '-') {
+ switch (key = keyword(1 + *argv)) {
+ case K_LINK:
+ af = AF_LINK;
+ aflen = sizeof(struct sockaddr_dl);
+ break;
+ case K_INET:
+ af = AF_INET;
+ aflen = sizeof(struct sockaddr_in);
+ break;
+#ifdef INET6
+ case K_INET6:
+ af = AF_INET6;
+ aflen = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ case K_ATALK:
+ af = AF_APPLETALK;
+ aflen = sizeof(struct sockaddr_at);
+ break;
+ case K_SA:
+ af = PF_ROUTE;
+ aflen = sizeof(union sockunion);
+ break;
+ case K_IFACE:
+ case K_INTERFACE:
+ iflag++;
+ break;
+ case K_NOSTATIC:
+ flags &= ~RTF_STATIC;
+ break;
+ case K_LOCK:
+ locking = 1;
+ break;
+ case K_LOCKREST:
+ lockrest = 1;
+ break;
+ case K_HOST:
+ forcehost++;
+ break;
+ case K_REJECT:
+ flags |= RTF_REJECT;
+ break;
+ case K_BLACKHOLE:
+ flags |= RTF_BLACKHOLE;
+ break;
+ case K_PROTO1:
+ flags |= RTF_PROTO1;
+ break;
+ case K_PROTO2:
+ flags |= RTF_PROTO2;
+ break;
+ case K_PROXY:
+ proxy = 1;
+ break;
+ case K_XRESOLVE:
+ flags |= RTF_XRESOLVE;
+ break;
+ case K_STATIC:
+ flags |= RTF_STATIC;
+ break;
+ case K_STICKY:
+ flags |= RTF_STICKY;
+ break;
+ case K_NOSTICK:
+ flags &= ~RTF_STICKY;
+ break;
+ case K_IFA:
+ if (!--argc)
+ usage((char *)NULL);
+ (void) getaddr(RTA_IFA, *++argv, 0);
+ break;
+ case K_IFP:
+ if (!--argc)
+ usage((char *)NULL);
+ (void) getaddr(RTA_IFP, *++argv, 0);
+ break;
+ case K_GENMASK:
+ if (!--argc)
+ usage((char *)NULL);
+ (void) getaddr(RTA_GENMASK, *++argv, 0);
+ break;
+ case K_GATEWAY:
+ if (!--argc)
+ usage((char *)NULL);
+ (void) getaddr(RTA_GATEWAY, *++argv, 0);
+ break;
+ case K_DST:
+ if (!--argc)
+ usage((char *)NULL);
+ ishost = getaddr(RTA_DST, *++argv, &hp);
+ dest = *argv;
+ break;
+ case K_NETMASK:
+ if (!--argc)
+ usage((char *)NULL);
+ (void) getaddr(RTA_NETMASK, *++argv, 0);
+ /* FALLTHROUGH */
+ case K_NET:
+ forcenet++;
+ break;
+ case K_PREFIXLEN:
+ if (!--argc)
+ usage((char *)NULL);
+ if (prefixlen(*++argv) == -1) {
+ forcenet = 0;
+ ishost = 1;
+ } else {
+ forcenet = 1;
+ ishost = 0;
+ }
+ break;
+ case K_MTU:
+ case K_HOPCOUNT:
+ case K_EXPIRE:
+ case K_RECVPIPE:
+ case K_SENDPIPE:
+ case K_SSTHRESH:
+ case K_RTT:
+ case K_RTTVAR:
+ case K_WEIGHT:
+ if (!--argc)
+ usage((char *)NULL);
+ set_metric(*++argv, key);
+ break;
+ default:
+ usage(1+*argv);
+ }
+ } else {
+ if ((rtm_addrs & RTA_DST) == 0) {
+ dest = *argv;
+ ishost = getaddr(RTA_DST, *argv, &hp);
+ } else if ((rtm_addrs & RTA_GATEWAY) == 0) {
+ gateway = *argv;
+ (void) getaddr(RTA_GATEWAY, *argv, &hp);
+ } else {
+ (void) getaddr(RTA_NETMASK, *argv, 0);
+ forcenet = 1;
+ }
+ }
+ }
+ if (forcehost) {
+ ishost = 1;
+#ifdef INET6
+ if (af == AF_INET6) {
+ rtm_addrs &= ~RTA_NETMASK;
+ memset((void *)&so_mask, 0, sizeof(so_mask));
+ }
+#endif
+ }
+ if (forcenet)
+ ishost = 0;
+ flags |= RTF_UP;
+ if (ishost)
+ flags |= RTF_HOST;
+ if (iflag == 0)
+ flags |= RTF_GATEWAY;
+ if (proxy) {
+ so_dst.sinarp.sin_other = SIN_PROXY;
+ flags |= RTF_ANNOUNCE;
+ }
+ for (attempts = 1; ; attempts++) {
+ errno = 0;
+ if ((ret = rtmsg(*cmd, flags)) == 0)
+ break;
+ if (errno != ENETUNREACH && errno != ESRCH)
+ break;
+ if (af == AF_INET && *gateway && hp && hp->h_addr_list[1]) {
+ hp->h_addr_list++;
+ memmove(&so_gate.sin.sin_addr, hp->h_addr_list[0],
+ MIN(hp->h_length, sizeof(so_gate.sin.sin_addr)));
+ } else
+ break;
+ }
+ if (*cmd == 'g' || *cmd == 's')
+ exit(ret != 0);
+ if (!qflag) {
+ oerrno = errno;
+ (void) printf("%s %s %s", cmd, ishost? "host" : "net", dest);
+ if (*gateway) {
+ (void) printf(": gateway %s", gateway);
+ if (attempts > 1 && ret == 0 && af == AF_INET)
+ (void) printf(" (%s)",
+ inet_ntoa(((struct sockaddr_in *)&route.rt_gateway)->sin_addr));
+ }
+ if (ret == 0) {
+ (void) printf("\n");
+ } else {
+ switch (oerrno) {
+ case ESRCH:
+ err = "not in table";
+ break;
+ case EBUSY:
+ err = "entry in use";
+ break;
+ case ENOBUFS:
+ err = "not enough memory";
+ break;
+ case EADDRINUSE:
+ /* handle recursion avoidance in rt_setgate() */
+ err = "gateway uses the same route";
+ break;
+ case EEXIST:
+ err = "route already in table";
+ break;
+ default:
+ err = strerror(oerrno);
+ break;
+ }
+ (void) printf(": %s\n", err);
+ }
+ }
+ exit(ret != 0);
+}
+
+void
+inet_makenetandmask(net, sin, bits)
+ u_long net, bits;
+ struct sockaddr_in *sin;
+{
+ u_long addr, mask = 0;
+ char *cp;
+
+ rtm_addrs |= RTA_NETMASK;
+ /*
+ * XXX: This approach unable to handle 0.0.0.1/32 correctly
+ * as inet_network() converts 0.0.0.1 and 1 equally.
+ */
+ if (net <= 0xff)
+ addr = net << IN_CLASSA_NSHIFT;
+ else if (net <= 0xffff)
+ addr = net << IN_CLASSB_NSHIFT;
+ else if (net <= 0xffffff)
+ 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);
+
+ sin->sin_addr.s_addr = htonl(addr);
+ sin = &so_mask.sin;
+ sin->sin_addr.s_addr = htonl(mask);
+ sin->sin_len = 0;
+ sin->sin_family = 0;
+ cp = (char *)(&sin->sin_addr + 1);
+ while (*--cp == 0 && cp > (char *)sin)
+ ;
+ sin->sin_len = 1 + cp - (char *)sin;
+}
+
+#ifdef INET6
+/*
+ * XXX the function may need more improvement...
+ */
+static int
+inet6_makenetandmask(sin6, plen)
+ struct sockaddr_in6 *sin6;
+ char *plen;
+{
+ struct in6_addr in6;
+
+ if (!plen) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
+ sin6->sin6_scope_id == 0) {
+ plen = "0";
+ } else if ((sin6->sin6_addr.s6_addr[0] & 0xe0) == 0x20) {
+ /* aggregatable global unicast - RFC2374 */
+ memset(&in6, 0, sizeof(in6));
+ if (!memcmp(&sin6->sin6_addr.s6_addr[8],
+ &in6.s6_addr[8], 8))
+ plen = "64";
+ }
+ }
+
+ if (!plen || strcmp(plen, "128") == 0)
+ return 1;
+ rtm_addrs |= RTA_NETMASK;
+ (void)prefixlen(plen);
+ return 0;
+}
+#endif
+
+/*
+ * Interpret an argument as a network address of some kind,
+ * returning 1 if a host address, 0 if a network address.
+ */
+int
+getaddr(which, s, hpp)
+ int which;
+ char *s;
+ struct hostent **hpp;
+{
+ sup su;
+ struct hostent *hp;
+ struct netent *np;
+ u_long val;
+ char *q;
+ int afamily; /* local copy of af so we can change it */
+
+ if (af == 0) {
+ af = AF_INET;
+ aflen = sizeof(struct sockaddr_in);
+ }
+ afamily = af;
+ rtm_addrs |= which;
+ switch (which) {
+ case RTA_DST:
+ su = &so_dst;
+ break;
+ case RTA_GATEWAY:
+ su = &so_gate;
+ if (iflag) {
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr_dl *sdl = NULL;
+
+ if (getifaddrs(&ifap))
+ err(1, "getifaddrs");
+
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr->sa_family != AF_LINK)
+ continue;
+
+ if (strcmp(s, ifa->ifa_name))
+ continue;
+
+ sdl = (struct sockaddr_dl *)ifa->ifa_addr;
+ }
+ /* If we found it, then use it */
+ if (sdl) {
+ /*
+ * Copy is safe since we have a
+ * sockaddr_storage member in sockunion{}.
+ * Note that we need to copy before calling
+ * freeifaddrs().
+ */
+ memcpy(&su->sdl, sdl, sdl->sdl_len);
+ }
+ freeifaddrs(ifap);
+ if (sdl)
+ return(1);
+ }
+ break;
+ case RTA_NETMASK:
+ su = &so_mask;
+ break;
+ case RTA_GENMASK:
+ su = &so_genmask;
+ break;
+ case RTA_IFP:
+ su = &so_ifp;
+ afamily = AF_LINK;
+ break;
+ case RTA_IFA:
+ su = &so_ifa;
+ break;
+ default:
+ usage("internal error");
+ /*NOTREACHED*/
+ }
+ su->sa.sa_len = aflen;
+ su->sa.sa_family = afamily; /* cases that don't want it have left already */
+ if (strcmp(s, "default") == 0) {
+ /*
+ * Default is net 0.0.0.0/0
+ */
+ switch (which) {
+ case RTA_DST:
+ forcenet++;
+#if 0
+ bzero(su, sizeof(*su)); /* for readability */
+#endif
+ (void) getaddr(RTA_NETMASK, s, 0);
+ break;
+#if 0
+ case RTA_NETMASK:
+ case RTA_GENMASK:
+ bzero(su, sizeof(*su)); /* for readability */
+#endif
+ }
+ return (0);
+ }
+ switch (afamily) {
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct addrinfo hints, *res;
+ int ecode;
+
+ q = NULL;
+ if (which == RTA_DST && (q = strchr(s, '/')) != NULL)
+ *q = '\0';
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = afamily; /*AF_INET6*/
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ ecode = getaddrinfo(s, NULL, &hints, &res);
+ if (ecode != 0 || res->ai_family != AF_INET6 ||
+ res->ai_addrlen != sizeof(su->sin6)) {
+ (void) fprintf(stderr, "%s: %s\n", s,
+ gai_strerror(ecode));
+ exit(1);
+ }
+ memcpy(&su->sin6, res->ai_addr, sizeof(su->sin6));
+#ifdef __KAME__
+ if ((IN6_IS_ADDR_LINKLOCAL(&su->sin6.sin6_addr) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(&su->sin6.sin6_addr)) &&
+ su->sin6.sin6_scope_id) {
+ *(u_int16_t *)&su->sin6.sin6_addr.s6_addr[2] =
+ htons(su->sin6.sin6_scope_id);
+ su->sin6.sin6_scope_id = 0;
+ }
+#endif
+ freeaddrinfo(res);
+ if (q != NULL)
+ *q++ = '/';
+ if (which == RTA_DST)
+ return (inet6_makenetandmask(&su->sin6, q));
+ return (0);
+ }
+#endif /* INET6 */
+
+ case AF_APPLETALK:
+ if (!atalk_aton(s, &su->sat.sat_addr))
+ errx(EX_NOHOST, "bad address: %s", s);
+ rtm_addrs |= RTA_NETMASK;
+ return(forcehost || su->sat.sat_addr.s_node != 0);
+
+ case AF_LINK:
+ link_addr(s, &su->sdl);
+ return (1);
+
+
+ case PF_ROUTE:
+ su->sa.sa_len = sizeof(*su);
+ sockaddr(s, &su->sa);
+ return (1);
+
+ case AF_INET:
+ default:
+ break;
+ }
+
+ if (hpp == NULL)
+ hpp = &hp;
+ *hpp = NULL;
+
+ q = strchr(s,'/');
+ if (q && which == RTA_DST) {
+ *q = '\0';
+ if ((val = inet_network(s)) != INADDR_NONE) {
+ inet_makenetandmask(
+ val, &su->sin, strtoul(q+1, 0, 0));
+ return (0);
+ }
+ *q = '/';
+ }
+ if ((which != RTA_DST || forcenet == 0) &&
+ inet_aton(s, &su->sin.sin_addr)) {
+ val = su->sin.sin_addr.s_addr;
+ if (which != RTA_DST || forcehost ||
+ inet_lnaof(su->sin.sin_addr) != INADDR_ANY)
+ return (1);
+ else {
+ val = ntohl(val);
+ goto netdone;
+ }
+ }
+ if (which == RTA_DST && forcehost == 0 &&
+ ((val = inet_network(s)) != INADDR_NONE ||
+ ((np = getnetbyname(s)) != NULL && (val = np->n_net) != 0))) {
+netdone:
+ inet_makenetandmask(val, &su->sin, 0);
+ return (0);
+ }
+ hp = gethostbyname(s);
+ if (hp) {
+ *hpp = hp;
+ su->sin.sin_family = hp->h_addrtype;
+ memmove((char *)&su->sin.sin_addr, hp->h_addr,
+ MIN(hp->h_length, sizeof(su->sin.sin_addr)));
+ return (1);
+ }
+ errx(EX_NOHOST, "bad address: %s", s);
+}
+
+int
+prefixlen(s)
+ char *s;
+{
+ int len = atoi(s), q, r;
+ int max;
+ char *p;
+
+ rtm_addrs |= RTA_NETMASK;
+ switch (af) {
+#ifdef INET6
+ case AF_INET6:
+ max = 128;
+ p = (char *)&so_mask.sin6.sin6_addr;
+ break;
+#endif
+ case AF_INET:
+ max = 32;
+ p = (char *)&so_mask.sin.sin_addr;
+ break;
+ default:
+ (void) fprintf(stderr, "prefixlen not supported in this af\n");
+ exit(1);
+ /*NOTREACHED*/
+ }
+
+ if (len < 0 || max < len) {
+ (void) fprintf(stderr, "%s: bad value\n", s);
+ exit(1);
+ }
+
+ q = len >> 3;
+ r = len & 7;
+ so_mask.sa.sa_family = af;
+ so_mask.sa.sa_len = aflen;
+ memset((void *)p, 0, max / 8);
+ if (q > 0)
+ memset((void *)p, 0xff, q);
+ if (r > 0)
+ *((u_char *)p + q) = (0xff00 >> r) & 0xff;
+ if (len == max)
+ return -1;
+ else
+ return len;
+}
+
+void
+interfaces()
+{
+ size_t needed;
+ int mib[6];
+ char *buf, *lim, *next, count = 0;
+ struct rt_msghdr *rtm;
+
+retry2:
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0; /* protocol */
+ mib[3] = 0; /* wildcard address family */
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0; /* no flags */
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ err(EX_OSERR, "route-sysctl-estimate");
+ if ((buf = malloc(needed)) == NULL)
+ errx(EX_OSERR, "malloc failed");
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ if (errno == ENOMEM && count++ < 10) {
+ warnx("Routing table grew, retrying");
+ sleep(1);
+ free(buf);
+ goto retry2;
+ }
+ err(EX_OSERR, "actual retrieval of interface table");
+ }
+ lim = buf + needed;
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ print_rtmsg(rtm, rtm->rtm_msglen);
+ }
+}
+
+void
+monitor()
+{
+ int n;
+ char msg[2048];
+
+ verbose = 1;
+ if (debugonly) {
+ interfaces();
+ exit(0);
+ }
+ for(;;) {
+ time_t now;
+ n = read(s, msg, 2048);
+ now = time(NULL);
+ (void) printf("\ngot message of size %d on %s", n, ctime(&now));
+ print_rtmsg((struct rt_msghdr *)msg, n);
+ }
+}
+
+struct {
+ struct rt_msghdr m_rtm;
+ char m_space[512];
+} m_rtmsg;
+
+int
+rtmsg(cmd, flags)
+ int cmd, flags;
+{
+ static int seq;
+ int rlen;
+ char *cp = m_rtmsg.m_space;
+ int l;
+
+#define NEXTADDR(w, u) \
+ if (rtm_addrs & (w)) {\
+ l = SA_SIZE(&(u.sa)); memmove(cp, &(u), l); cp += l;\
+ if (verbose) sodump(&(u),#u);\
+ }
+
+ errno = 0;
+ memset(&m_rtmsg, 0, sizeof(m_rtmsg));
+ if (cmd == 'a')
+ cmd = RTM_ADD;
+ else if (cmd == 'c')
+ cmd = RTM_CHANGE;
+ else if (cmd == 'g' || cmd == 's') {
+ cmd = RTM_GET;
+ if (so_ifp.sa.sa_family == 0) {
+ so_ifp.sa.sa_family = AF_LINK;
+ so_ifp.sa.sa_len = sizeof(struct sockaddr_dl);
+ rtm_addrs |= RTA_IFP;
+ }
+ } else
+ cmd = RTM_DELETE;
+#define rtm m_rtmsg.m_rtm
+ rtm.rtm_type = cmd;
+ rtm.rtm_flags = flags;
+ rtm.rtm_version = RTM_VERSION;
+ rtm.rtm_seq = ++seq;
+ rtm.rtm_addrs = rtm_addrs;
+ rtm.rtm_rmx = rt_metrics;
+ rtm.rtm_inits = rtm_inits;
+
+ if (rtm_addrs & RTA_NETMASK)
+ mask_addr();
+ NEXTADDR(RTA_DST, so_dst);
+ NEXTADDR(RTA_GATEWAY, so_gate);
+ NEXTADDR(RTA_NETMASK, so_mask);
+ NEXTADDR(RTA_GENMASK, so_genmask);
+ NEXTADDR(RTA_IFP, so_ifp);
+ NEXTADDR(RTA_IFA, so_ifa);
+ rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
+ if (verbose)
+ print_rtmsg(&rtm, l);
+ if (debugonly)
+ return (0);
+ if ((rlen = write(s, (char *)&m_rtmsg, l)) < 0) {
+ if (errno == EPERM)
+ err(1, "writing to routing socket");
+ warn("writing to routing socket");
+ return (-1);
+ }
+ if (cmd == RTM_GET) {
+ do {
+ l = read(s, (char *)&m_rtmsg, sizeof(m_rtmsg));
+ } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
+ if (l < 0)
+ warn("read from routing socket");
+ else
+ print_getmsg(&rtm, l);
+ }
+#undef rtm
+ return (0);
+}
+
+void
+mask_addr()
+{
+ int olen = so_mask.sa.sa_len;
+ char *cp1 = olen + (char *)&so_mask, *cp2;
+
+ for (so_mask.sa.sa_len = 0; cp1 > (char *)&so_mask; )
+ if (*--cp1 != 0) {
+ so_mask.sa.sa_len = 1 + cp1 - (char *)&so_mask;
+ break;
+ }
+ if ((rtm_addrs & RTA_DST) == 0)
+ return;
+ switch (so_dst.sa.sa_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ case AF_APPLETALK:
+ case 0:
+ return;
+ }
+ cp1 = so_mask.sa.sa_len + 1 + (char *)&so_dst;
+ cp2 = so_dst.sa.sa_len + 1 + (char *)&so_dst;
+ while (cp2 > cp1)
+ *--cp2 = 0;
+ cp2 = so_mask.sa.sa_len + 1 + (char *)&so_mask;
+ while (cp1 > so_dst.sa.sa_data)
+ *--cp1 &= *--cp2;
+}
+
+char *msgtypes[] = {
+ "",
+ "RTM_ADD: Add Route",
+ "RTM_DELETE: Delete Route",
+ "RTM_CHANGE: Change Metrics or flags",
+ "RTM_GET: Report Metrics",
+ "RTM_LOSING: Kernel Suspects Partitioning",
+ "RTM_REDIRECT: Told to use different route",
+ "RTM_MISS: Lookup failed on this address",
+ "RTM_LOCK: fix specified metrics",
+ "RTM_OLDADD: caused by SIOCADDRT",
+ "RTM_OLDDEL: caused by SIOCDELRT",
+ "RTM_RESOLVE: Route created by cloning",
+ "RTM_NEWADDR: address being added to iface",
+ "RTM_DELADDR: address being removed from iface",
+ "RTM_IFINFO: iface status change",
+ "RTM_NEWMADDR: new multicast group membership on iface",
+ "RTM_DELMADDR: multicast group membership removed from iface",
+ "RTM_IFANNOUNCE: interface arrival/departure",
+ 0,
+};
+
+char metricnames[] =
+"\011weight\010rttvar\7rtt\6ssthresh\5sendpipe\4recvpipe\3expire"
+"\1mtu";
+char routeflags[] =
+"\1UP\2GATEWAY\3HOST\4REJECT\5DYNAMIC\6MODIFIED\7DONE"
+"\012XRESOLVE\013LLINFO\014STATIC\015BLACKHOLE"
+"\017PROTO2\020PROTO1\021PRCLONING\022WASCLONED\023PROTO3"
+"\025PINNED\026LOCAL\027BROADCAST\030MULTICAST\035STICKY";
+char ifnetflags[] =
+"\1UP\2BROADCAST\3DEBUG\4LOOPBACK\5PTP\6b6\7RUNNING\010NOARP"
+"\011PPROMISC\012ALLMULTI\013OACTIVE\014SIMPLEX\015LINK0\016LINK1"
+"\017LINK2\020MULTICAST";
+char addrnames[] =
+"\1DST\2GATEWAY\3NETMASK\4GENMASK\5IFP\6IFA\7AUTHOR\010BRD";
+
+void
+print_rtmsg(rtm, msglen)
+ struct rt_msghdr *rtm;
+ int msglen;
+{
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+#ifdef RTM_NEWMADDR
+ struct ifma_msghdr *ifmam;
+#endif
+ struct if_announcemsghdr *ifan;
+ char *state;
+
+ if (verbose == 0)
+ return;
+ if (rtm->rtm_version != RTM_VERSION) {
+ (void) printf("routing message version %d not understood\n",
+ rtm->rtm_version);
+ return;
+ }
+ if (msgtypes[rtm->rtm_type] != NULL)
+ (void)printf("%s: ", msgtypes[rtm->rtm_type]);
+ else
+ (void)printf("#%d: ", rtm->rtm_type);
+ (void)printf("len %d, ", rtm->rtm_msglen);
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ ifm = (struct if_msghdr *)rtm;
+ (void) printf("if# %d, ", ifm->ifm_index);
+ switch (ifm->ifm_data.ifi_link_state) {
+ case LINK_STATE_DOWN:
+ state = "down";
+ break;
+ case LINK_STATE_UP:
+ state = "up";
+ break;
+ default:
+ state = "unknown";
+ break;
+ }
+ (void) printf("link: %s, flags:", state);
+ bprintf(stdout, ifm->ifm_flags, ifnetflags);
+ pmsg_addrs((char *)(ifm + 1), ifm->ifm_addrs);
+ break;
+ case RTM_NEWADDR:
+ case RTM_DELADDR:
+ ifam = (struct ifa_msghdr *)rtm;
+ (void) printf("metric %d, flags:", ifam->ifam_metric);
+ bprintf(stdout, ifam->ifam_flags, routeflags);
+ pmsg_addrs((char *)(ifam + 1), ifam->ifam_addrs);
+ break;
+#ifdef RTM_NEWMADDR
+ case RTM_NEWMADDR:
+ case RTM_DELMADDR:
+ ifmam = (struct ifma_msghdr *)rtm;
+ pmsg_addrs((char *)(ifmam + 1), ifmam->ifmam_addrs);
+ break;
+#endif
+ case RTM_IFANNOUNCE:
+ ifan = (struct if_announcemsghdr *)rtm;
+ (void) printf("if# %d, what: ", ifan->ifan_index);
+ switch (ifan->ifan_what) {
+ case IFAN_ARRIVAL:
+ printf("arrival");
+ break;
+ case IFAN_DEPARTURE:
+ printf("departure");
+ break;
+ default:
+ printf("#%d", ifan->ifan_what);
+ break;
+ }
+ printf("\n");
+ break;
+
+ default:
+ (void) printf("pid: %ld, seq %d, errno %d, flags:",
+ (long)rtm->rtm_pid, rtm->rtm_seq, rtm->rtm_errno);
+ bprintf(stdout, rtm->rtm_flags, routeflags);
+ pmsg_common(rtm);
+ }
+}
+
+void
+print_getmsg(rtm, msglen)
+ struct rt_msghdr *rtm;
+ int msglen;
+{
+ struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
+ struct sockaddr_dl *ifp = NULL;
+ struct sockaddr *sa;
+ char *cp;
+ int i;
+
+ (void) printf(" route to: %s\n", routename(&so_dst));
+ if (rtm->rtm_version != RTM_VERSION) {
+ warnx("routing message version %d not understood",
+ rtm->rtm_version);
+ return;
+ }
+ if (rtm->rtm_msglen > msglen) {
+ warnx("message length mismatch, in packet %d, returned %d",
+ rtm->rtm_msglen, msglen);
+ }
+ if (rtm->rtm_errno) {
+ errno = rtm->rtm_errno;
+ warn("message indicates error %d", errno);
+ return;
+ }
+ cp = ((char *)(rtm + 1));
+ if (rtm->rtm_addrs)
+ for (i = 1; i; i <<= 1)
+ if (i & rtm->rtm_addrs) {
+ sa = (struct sockaddr *)cp;
+ switch (i) {
+ case RTA_DST:
+ dst = sa;
+ break;
+ case RTA_GATEWAY:
+ gate = sa;
+ break;
+ case RTA_NETMASK:
+ mask = sa;
+ break;
+ case RTA_IFP:
+ if (sa->sa_family == AF_LINK &&
+ ((struct sockaddr_dl *)sa)->sdl_nlen)
+ ifp = (struct sockaddr_dl *)sa;
+ break;
+ }
+ cp += SA_SIZE(sa);
+ }
+ if (dst && mask)
+ mask->sa_family = dst->sa_family; /* XXX */
+ if (dst)
+ (void)printf("destination: %s\n", routename(dst));
+ if (mask) {
+ int savenflag = nflag;
+
+ nflag = 1;
+ (void)printf(" mask: %s\n", routename(mask));
+ nflag = savenflag;
+ }
+ if (gate && rtm->rtm_flags & RTF_GATEWAY)
+ (void)printf(" gateway: %s\n", routename(gate));
+ if (ifp)
+ (void)printf(" interface: %.*s\n",
+ ifp->sdl_nlen, ifp->sdl_data);
+ (void)printf(" flags: ");
+ bprintf(stdout, rtm->rtm_flags, routeflags);
+
+#define lock(f) ((rtm->rtm_rmx.rmx_locks & __CONCAT(RTV_,f)) ? 'L' : ' ')
+#define msec(u) (((u) + 500) / 1000) /* usec to msec */
+
+ (void) printf("\n%s\n", "\
+ recvpipe sendpipe ssthresh rtt,msec mtu weight expire");
+ printf("%8ld%c ", rtm->rtm_rmx.rmx_recvpipe, lock(RPIPE));
+ printf("%8ld%c ", rtm->rtm_rmx.rmx_sendpipe, lock(SPIPE));
+ printf("%8ld%c ", rtm->rtm_rmx.rmx_ssthresh, lock(SSTHRESH));
+ printf("%8ld%c ", msec(rtm->rtm_rmx.rmx_rtt), lock(RTT));
+ printf("%8ld%c ", rtm->rtm_rmx.rmx_mtu, lock(MTU));
+ printf("%8ld%c ", rtm->rtm_rmx.rmx_weight, lock(WEIGHT));
+ if (rtm->rtm_rmx.rmx_expire)
+ rtm->rtm_rmx.rmx_expire -= time(0);
+ printf("%8ld%c\n", rtm->rtm_rmx.rmx_expire, lock(EXPIRE));
+#undef lock
+#undef msec
+#define RTA_IGN (RTA_DST|RTA_GATEWAY|RTA_NETMASK|RTA_IFP|RTA_IFA|RTA_BRD)
+ if (verbose)
+ pmsg_common(rtm);
+ else if (rtm->rtm_addrs &~ RTA_IGN) {
+ (void) printf("sockaddrs: ");
+ bprintf(stdout, rtm->rtm_addrs, addrnames);
+ putchar('\n');
+ }
+#undef RTA_IGN
+}
+
+void
+pmsg_common(rtm)
+ struct rt_msghdr *rtm;
+{
+ (void) printf("\nlocks: ");
+ bprintf(stdout, rtm->rtm_rmx.rmx_locks, metricnames);
+ (void) printf(" inits: ");
+ bprintf(stdout, rtm->rtm_inits, metricnames);
+ pmsg_addrs(((char *)(rtm + 1)), rtm->rtm_addrs);
+}
+
+void
+pmsg_addrs(cp, addrs)
+ char *cp;
+ int addrs;
+{
+ struct sockaddr *sa;
+ int i;
+
+ if (addrs == 0) {
+ (void) putchar('\n');
+ return;
+ }
+ (void) printf("\nsockaddrs: ");
+ bprintf(stdout, addrs, addrnames);
+ (void) putchar('\n');
+ for (i = 1; i; i <<= 1)
+ if (i & addrs) {
+ sa = (struct sockaddr *)cp;
+ (void) printf(" %s", routename(sa));
+ cp += SA_SIZE(sa);
+ }
+ (void) putchar('\n');
+ (void) fflush(stdout);
+}
+
+void
+bprintf(fp, b, s)
+ FILE *fp;
+ int b;
+ u_char *s;
+{
+ int i;
+ int gotsome = 0;
+
+ if (b == 0)
+ return;
+ while ((i = *s++) != 0) {
+ if (b & (1 << (i-1))) {
+ if (gotsome == 0)
+ i = '<';
+ else
+ i = ',';
+ (void) putc(i, fp);
+ gotsome = 1;
+ for (; (i = *s) > 32; s++)
+ (void) putc(i, fp);
+ } else
+ while (*s > 32)
+ s++;
+ }
+ if (gotsome)
+ (void) putc('>', fp);
+}
+
+int
+keyword(cp)
+ char *cp;
+{
+ struct keytab *kt = keywords;
+
+ while (kt->kt_cp && strcmp(kt->kt_cp, cp))
+ kt++;
+ return kt->kt_i;
+}
+
+void
+sodump(su, which)
+ sup su;
+ char *which;
+{
+ switch (su->sa.sa_family) {
+ case AF_LINK:
+ (void) printf("%s: link %s; ",
+ which, link_ntoa(&su->sdl));
+ break;
+ case AF_INET:
+ (void) printf("%s: inet %s; ",
+ which, inet_ntoa(su->sin.sin_addr));
+ break;
+ case AF_APPLETALK:
+ (void) printf("%s: atalk %s; ",
+ which, atalk_ntoa(su->sat.sat_addr));
+ break;
+ }
+ (void) fflush(stdout);
+}
+
+/* States*/
+#define VIRGIN 0
+#define GOTONE 1
+#define GOTTWO 2
+/* Inputs */
+#define DIGIT (4*0)
+#define END (4*1)
+#define DELIM (4*2)
+
+void
+sockaddr(addr, sa)
+ char *addr;
+ struct sockaddr *sa;
+{
+ char *cp = (char *)sa;
+ int size = sa->sa_len;
+ char *cplim = cp + size;
+ int byte = 0, state = VIRGIN, new = 0 /* foil gcc */;
+
+ memset(cp, 0, size);
+ cp++;
+ do {
+ if ((*addr >= '0') && (*addr <= '9')) {
+ new = *addr - '0';
+ } else if ((*addr >= 'a') && (*addr <= 'f')) {
+ new = *addr - 'a' + 10;
+ } else if ((*addr >= 'A') && (*addr <= 'F')) {
+ new = *addr - 'A' + 10;
+ } else if (*addr == 0)
+ state |= END;
+ else
+ state |= DELIM;
+ addr++;
+ switch (state /* | INPUT */) {
+ case GOTTWO | DIGIT:
+ *cp++ = byte; /*FALLTHROUGH*/
+ case VIRGIN | DIGIT:
+ state = GOTONE; byte = new; continue;
+ case GOTONE | DIGIT:
+ state = GOTTWO; byte = new + (byte << 4); continue;
+ default: /* | DELIM */
+ state = VIRGIN; *cp++ = byte; byte = 0; continue;
+ case GOTONE | END:
+ case GOTTWO | END:
+ *cp++ = byte; /* FALLTHROUGH */
+ case VIRGIN | END:
+ break;
+ }
+ break;
+ } while (cp < cplim);
+ sa->sa_len = cp - (char *)sa;
+}
+
+int
+atalk_aton(const char *text, struct at_addr *addr)
+{
+ u_int net, node;
+
+ if (sscanf(text, "%u.%u", &net, &node) != 2
+ || net > 0xffff || node > 0xff)
+ return(0);
+ addr->s_net = htons(net);
+ addr->s_node = node;
+ return(1);
+}
+
+char *
+atalk_ntoa(struct at_addr at)
+{
+ static char buf[20];
+
+ (void) snprintf(buf, sizeof(buf), "%u.%u", ntohs(at.s_net), at.s_node);
+ return(buf);
+}
+
+#ifdef __rtems__
+ #include <rtems/shell.h>
+
+ rtems_shell_cmd_t rtems_shell_ROUTE_Command = {
+ "route", /* name */
+ "route [args]", /* usage */
+ "net", /* topic */
+ rtems_shell_main_route, /* command */
+ NULL, /* alias */
+ NULL /* next */
+ };
+#endif
diff --git a/freebsd/security/audit/audit.h b/freebsd/security/audit/audit.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/security/audit/audit.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sys/_types.h b/freebsd/sys/_types.h
deleted file mode 100644
index b9f4d392..00000000
--- a/freebsd/sys/_types.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*-
- * Copyright (c) 2002 Mike Barcroft <mike@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$
- */
-
-#ifndef _SYS__TYPES_HH_
-#define _SYS__TYPES_HH_
-
-#include <freebsd/sys/cdefs.h>
-#include <freebsd/machine/_types.h>
-
-/*
- * Standard type definitions.
- */
-typedef __uint32_t __blksize_t; /* file block size */
-typedef __int64_t __blkcnt_t; /* file block count */
-typedef __int32_t __clockid_t; /* clock_gettime()... */
-typedef __uint32_t __fflags_t; /* file flags */
-typedef __uint64_t __fsblkcnt_t;
-typedef __uint64_t __fsfilcnt_t;
-typedef __uint32_t __gid_t;
-typedef __int64_t __id_t; /* can hold a gid_t, pid_t, or uid_t */
-typedef __uint32_t __ino_t; /* inode number */
-typedef long __key_t; /* IPC key (for Sys V IPC) */
-typedef __int32_t __lwpid_t; /* Thread ID (a.k.a. LWP) */
-typedef __uint16_t __mode_t; /* permissions */
-typedef int __accmode_t; /* access permissions */
-typedef int __nl_item;
-typedef __uint16_t __nlink_t; /* link count */
-typedef __int64_t __off_t; /* file offset */
-typedef __int32_t __pid_t; /* process [group] */
-typedef __int64_t __rlim_t; /* resource limit - intentionally */
- /* signed, because of legacy code */
- /* that uses -1 for RLIM_INFINITY */
-typedef __uint8_t __sa_family_t;
-typedef __uint32_t __socklen_t;
-typedef long __suseconds_t; /* microseconds (signed) */
-typedef struct __timer *__timer_t; /* timer_gettime()... */
-typedef struct __mq *__mqd_t; /* mq_open()... */
-typedef __uint32_t __uid_t;
-typedef unsigned int __useconds_t; /* microseconds (unsigned) */
-typedef int __cpuwhich_t; /* which parameter for cpuset. */
-typedef int __cpulevel_t; /* level parameter for cpuset. */
-typedef int __cpusetid_t; /* cpuset identifier. */
-
-/*
- * Unusual type definitions.
- */
-/*
- * rune_t is declared to be an ``int'' instead of the more natural
- * ``unsigned long'' or ``long''. Two things are happening here. It is not
- * unsigned so that EOF (-1) can be naturally assigned to it and used. Also,
- * it looks like 10646 will be a 31 bit standard. This means that if your
- * ints cannot hold 32 bits, you will be in trouble. The reason an int was
- * chosen over a long is that the is*() and to*() routines take ints (says
- * ANSI C), but they use __ct_rune_t instead of int.
- *
- * NOTE: rune_t is not covered by ANSI nor other standards, and should not
- * be instantiated outside of lib/libc/locale. Use wchar_t. wchar_t and
- * rune_t must be the same type. Also, wint_t must be no narrower than
- * wchar_t, and should be able to hold all members of the largest
- * character set plus one extra value (WEOF), and must be at least 16 bits.
- */
-typedef int __ct_rune_t; /* arg type for ctype funcs */
-typedef __ct_rune_t __rune_t; /* rune_t (see above) */
-typedef __ct_rune_t __wchar_t; /* wchar_t (see above) */
-typedef __ct_rune_t __wint_t; /* wint_t (see above) */
-
-typedef __uint32_t __dev_t; /* device number */
-
-typedef __uint32_t __fixpt_t; /* fixed point number */
-
-/*
- * mbstate_t is an opaque object to keep conversion state during multibyte
- * stream conversions.
- */
-typedef union {
- char __mbstate8[128];
- __int64_t _mbstateL; /* for alignment */
-} __mbstate_t;
-
-#endif /* !_SYS__TYPES_HH_ */
diff --git a/freebsd/arm/arm/in_cksum.c b/freebsd/sys/arm/arm/in_cksum.c
index db98915d..db98915d 100644
--- a/freebsd/arm/arm/in_cksum.c
+++ b/freebsd/sys/arm/arm/in_cksum.c
diff --git a/freebsd/arm/include/freebsd/machine/cpufunc.h b/freebsd/sys/arm/include/machine/cpufunc.h
index 822fadb1..822fadb1 100644
--- a/freebsd/arm/include/freebsd/machine/cpufunc.h
+++ b/freebsd/sys/arm/include/machine/cpufunc.h
diff --git a/freebsd/arm/include/freebsd/machine/in_cksum.h b/freebsd/sys/arm/include/machine/in_cksum.h
index 5e3e9333..5e3e9333 100644
--- a/freebsd/arm/include/freebsd/machine/in_cksum.h
+++ b/freebsd/sys/arm/include/machine/in_cksum.h
diff --git a/freebsd/i386/include/freebsd/machine/legacyvar.h b/freebsd/sys/arm/include/machine/legacyvar.h
index 4771faf5..4771faf5 100644
--- a/freebsd/i386/include/freebsd/machine/legacyvar.h
+++ b/freebsd/sys/arm/include/machine/legacyvar.h
diff --git a/freebsd/i386/include/freebsd/machine/pci_cfgreg.h b/freebsd/sys/arm/include/machine/pci_cfgreg.h
index bc72418d..bc72418d 100644
--- a/freebsd/i386/include/freebsd/machine/pci_cfgreg.h
+++ b/freebsd/sys/arm/include/machine/pci_cfgreg.h
diff --git a/freebsd/i386/pci/pci_bus.c b/freebsd/sys/arm/pci/pci_bus.c
index ec62ec14..ec62ec14 100644
--- a/freebsd/i386/pci/pci_bus.c
+++ b/freebsd/sys/arm/pci/pci_bus.c
diff --git a/freebsd/i386/include/freebsd/machine/in_cksum.h b/freebsd/sys/avr/include/machine/in_cksum.h
index 1f7dbac7..1f7dbac7 100644
--- a/freebsd/i386/include/freebsd/machine/in_cksum.h
+++ b/freebsd/sys/avr/include/machine/in_cksum.h
diff --git a/freebsd/sys/avr/pci/pci_bus.c b/freebsd/sys/avr/pci/pci_bus.c
new file mode 100644
index 00000000..62cd96c1
--- /dev/null
+++ b/freebsd/sys/avr/pci/pci_bus.c
@@ -0,0 +1,71 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/**
+ * @file
+ *
+ * @ingroup rtems_bsd_rtems
+ *
+ * @brief This file contains methods that are rtems specific implementation
+ * of methods in pci_bus.c.
+ */
+
+/*
+ * COPYRIGHT (c) 2012. On-Line Applications Research Corporation (OAR).
+ * 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 <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <freebsd/local/opt_cpu.h>
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/bus.h>
+#include <freebsd/sys/kernel.h>
+
+#include <freebsd/dev/pci/pcivar.h>
+#include <freebsd/dev/pci/pcireg.h>
+#include <freebsd/dev/pci/pcib_private.h>
+#include <freebsd/machine/resource.h>
+
+#include <freebsd/local/pcib_if.h>
+#include <rtems/pci.h>
+#include <freebsd/machine/bus.h>
+
+int
+pcibios_pcib_route_interrupt(device_t pcib, device_t dev, int pin)
+{
+ int bus;
+ int slot;
+ int func;
+ uint8_t irq;
+
+ bus = pci_get_bus(dev);
+ slot = pci_get_slot(dev);
+ func = pci_get_function(dev);
+
+ pci_read_config_byte(bus, slot, func, PCI_INTERRUPT_LINE, &irq);
+ return irq;
+}
diff --git a/freebsd/mips/include/freebsd/machine/in_cksum.h b/freebsd/sys/bfin/include/machine/in_cksum.h
index 4539d129..4539d129 100644
--- a/freebsd/mips/include/freebsd/machine/in_cksum.h
+++ b/freebsd/sys/bfin/include/machine/in_cksum.h
diff --git a/freebsd/sys/bio.h b/freebsd/sys/bio.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/bio.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/bsm/audit.h b/freebsd/sys/bsm/audit.h
index 98ee45c8..98ee45c8 100644
--- a/freebsd/bsm/audit.h
+++ b/freebsd/sys/bsm/audit.h
diff --git a/freebsd/bsm/audit_kevents.h b/freebsd/sys/bsm/audit_kevents.h
index 82580920..82580920 100644
--- a/freebsd/bsm/audit_kevents.h
+++ b/freebsd/sys/bsm/audit_kevents.h
diff --git a/freebsd/cam/ata/ata_all.h b/freebsd/sys/cam/ata/ata_all.h
index 6b23bd79..6b23bd79 100644
--- a/freebsd/cam/ata/ata_all.h
+++ b/freebsd/sys/cam/ata/ata_all.h
diff --git a/freebsd/cam/cam.c b/freebsd/sys/cam/cam.c
index 852d1d5b..852d1d5b 100644
--- a/freebsd/cam/cam.c
+++ b/freebsd/sys/cam/cam.c
diff --git a/freebsd/cam/cam.h b/freebsd/sys/cam/cam.h
index 6533fa42..6533fa42 100644
--- a/freebsd/cam/cam.h
+++ b/freebsd/sys/cam/cam.h
diff --git a/freebsd/cam/cam_ccb.h b/freebsd/sys/cam/cam_ccb.h
index d8b14458..d8b14458 100644
--- a/freebsd/cam/cam_ccb.h
+++ b/freebsd/sys/cam/cam_ccb.h
diff --git a/freebsd/cam/cam_debug.h b/freebsd/sys/cam/cam_debug.h
index 4b0fd245..4b0fd245 100644
--- a/freebsd/cam/cam_debug.h
+++ b/freebsd/sys/cam/cam_debug.h
diff --git a/freebsd/cam/cam_periph.h b/freebsd/sys/cam/cam_periph.h
index 8bf8fd21..8bf8fd21 100644
--- a/freebsd/cam/cam_periph.h
+++ b/freebsd/sys/cam/cam_periph.h
diff --git a/freebsd/cam/cam_sim.h b/freebsd/sys/cam/cam_sim.h
index 6b5a496f..6b5a496f 100644
--- a/freebsd/cam/cam_sim.h
+++ b/freebsd/sys/cam/cam_sim.h
diff --git a/freebsd/cam/cam_xpt.h b/freebsd/sys/cam/cam_xpt.h
index 61a7f3f0..61a7f3f0 100644
--- a/freebsd/cam/cam_xpt.h
+++ b/freebsd/sys/cam/cam_xpt.h
diff --git a/freebsd/cam/cam_xpt_sim.h b/freebsd/sys/cam/cam_xpt_sim.h
index 32c3082b..32c3082b 100644
--- a/freebsd/cam/cam_xpt_sim.h
+++ b/freebsd/sys/cam/cam_xpt_sim.h
diff --git a/freebsd/cam/scsi/scsi_all.c b/freebsd/sys/cam/scsi/scsi_all.c
index a25a20b8..a25a20b8 100644
--- a/freebsd/cam/scsi/scsi_all.c
+++ b/freebsd/sys/cam/scsi/scsi_all.c
diff --git a/freebsd/cam/scsi/scsi_all.h b/freebsd/sys/cam/scsi/scsi_all.h
index 47908b82..47908b82 100644
--- a/freebsd/cam/scsi/scsi_all.h
+++ b/freebsd/sys/cam/scsi/scsi_all.h
diff --git a/freebsd/cam/scsi/scsi_da.h b/freebsd/sys/cam/scsi/scsi_da.h
index 69dafefc..69dafefc 100644
--- a/freebsd/cam/scsi/scsi_da.h
+++ b/freebsd/sys/cam/scsi/scsi_da.h
diff --git a/freebsd/sys/contrib/altq/altq/altq.h b/freebsd/sys/contrib/altq/altq/altq.h
new file mode 100644
index 00000000..2c9e3536
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq.h
@@ -0,0 +1,204 @@
+/* $FreeBSD$ */
+/* $KAME: altq.h,v 1.10 2003/07/10 12:07:47 kjc Exp $ */
+
+/*
+ * Copyright (C) 1998-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 _ALTQ_ALTQ_HH_
+#define _ALTQ_ALTQ_HH_
+
+#if 0
+/*
+ * allow altq-3 (altqd(8) and /dev/altq) to coexist with the new pf-based altq.
+ * altq3 is mainly for research experiments. pf-based altq is for daily use.
+ */
+#define ALTQ3_COMPAT /* for compatibility with altq-3 */
+#define ALTQ3_CLFIER_COMPAT /* for compatibility with altq-3 classifier */
+#endif
+
+#ifdef ALTQ3_COMPAT
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/ioccom.h>
+#include <freebsd/sys/queue.h>
+#include <freebsd/netinet/in.h>
+
+#ifndef IFNAMSIZ
+#define IFNAMSIZ 16
+#endif
+#endif /* ALTQ3_COMPAT */
+
+/* altq discipline type */
+#define ALTQT_NONE 0 /* reserved */
+#define ALTQT_CBQ 1 /* cbq */
+#define ALTQT_WFQ 2 /* wfq */
+#define ALTQT_AFMAP 3 /* afmap */
+#define ALTQT_FIFOQ 4 /* fifoq */
+#define ALTQT_RED 5 /* red */
+#define ALTQT_RIO 6 /* rio */
+#define ALTQT_LOCALQ 7 /* local use */
+#define ALTQT_HFSC 8 /* hfsc */
+#define ALTQT_CDNR 9 /* traffic conditioner */
+#define ALTQT_BLUE 10 /* blue */
+#define ALTQT_PRIQ 11 /* priority queue */
+#define ALTQT_JOBS 12 /* JoBS */
+#define ALTQT_MAX 13 /* should be max discipline type + 1 */
+
+#ifdef ALTQ3_COMPAT
+struct altqreq {
+ char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */
+ u_long arg; /* request-specific argument */
+};
+#endif
+
+/* simple token backet meter profile */
+struct tb_profile {
+ u_int rate; /* rate in bit-per-sec */
+ u_int depth; /* depth in bytes */
+};
+
+#ifdef ALTQ3_COMPAT
+struct tbrreq {
+ char ifname[IFNAMSIZ]; /* if name, e.g. "en0" */
+ struct tb_profile tb_prof; /* token bucket profile */
+};
+
+#ifdef ALTQ3_CLFIER_COMPAT
+/*
+ * common network flow info structure
+ */
+struct flowinfo {
+ u_char fi_len; /* total length */
+ u_char fi_family; /* address family */
+ u_int8_t fi_data[46]; /* actually longer; address family
+ specific flow info. */
+};
+
+/*
+ * flow info structure for internet protocol family.
+ * (currently this is the only protocol family supported)
+ */
+struct flowinfo_in {
+ u_char fi_len; /* sizeof(struct flowinfo_in) */
+ u_char fi_family; /* AF_INET */
+ u_int8_t fi_proto; /* IPPROTO_XXX */
+ u_int8_t fi_tos; /* type-of-service */
+ struct in_addr fi_dst; /* dest address */
+ struct in_addr fi_src; /* src address */
+ u_int16_t fi_dport; /* dest port */
+ u_int16_t fi_sport; /* src port */
+ u_int32_t fi_gpi; /* generalized port id for ipsec */
+ u_int8_t _pad[28]; /* make the size equal to
+ flowinfo_in6 */
+};
+
+#ifdef SIN6_LEN
+struct flowinfo_in6 {
+ u_char fi6_len; /* sizeof(struct flowinfo_in6) */
+ u_char fi6_family; /* AF_INET6 */
+ u_int8_t fi6_proto; /* IPPROTO_XXX */
+ u_int8_t fi6_tclass; /* traffic class */
+ u_int32_t fi6_flowlabel; /* ipv6 flowlabel */
+ u_int16_t fi6_dport; /* dest port */
+ u_int16_t fi6_sport; /* src port */
+ u_int32_t fi6_gpi; /* generalized port id */
+ struct in6_addr fi6_dst; /* dest address */
+ struct in6_addr fi6_src; /* src address */
+};
+#endif /* INET6 */
+
+/*
+ * flow filters for AF_INET and AF_INET6
+ */
+struct flow_filter {
+ int ff_ruleno;
+ struct flowinfo_in ff_flow;
+ struct {
+ struct in_addr mask_dst;
+ struct in_addr mask_src;
+ u_int8_t mask_tos;
+ u_int8_t _pad[3];
+ } ff_mask;
+ u_int8_t _pad2[24]; /* make the size equal to flow_filter6 */
+};
+
+#ifdef SIN6_LEN
+struct flow_filter6 {
+ int ff_ruleno;
+ struct flowinfo_in6 ff_flow6;
+ struct {
+ struct in6_addr mask6_dst;
+ struct in6_addr mask6_src;
+ u_int8_t mask6_tclass;
+ u_int8_t _pad[3];
+ } ff_mask6;
+};
+#endif /* INET6 */
+#endif /* ALTQ3_CLFIER_COMPAT */
+#endif /* ALTQ3_COMPAT */
+
+/*
+ * generic packet counter
+ */
+struct pktcntr {
+ u_int64_t packets;
+ u_int64_t bytes;
+};
+
+#define PKTCNTR_ADD(cntr, len) \
+ do { (cntr)->packets++; (cntr)->bytes += len; } while (/*CONSTCOND*/ 0)
+
+#ifdef ALTQ3_COMPAT
+/*
+ * altq related ioctls
+ */
+#define ALTQGTYPE _IOWR('q', 0, struct altqreq) /* get queue type */
+#if 0
+/*
+ * these ioctls are currently discipline-specific but could be shared
+ * in the future.
+ */
+#define ALTQATTACH _IOW('q', 1, struct altqreq) /* attach discipline */
+#define ALTQDETACH _IOW('q', 2, struct altqreq) /* detach discipline */
+#define ALTQENABLE _IOW('q', 3, struct altqreq) /* enable discipline */
+#define ALTQDISABLE _IOW('q', 4, struct altqreq) /* disable discipline*/
+#define ALTQCLEAR _IOW('q', 5, struct altqreq) /* (re)initialize */
+#define ALTQCONFIG _IOWR('q', 6, struct altqreq) /* set config params */
+#define ALTQADDCLASS _IOWR('q', 7, struct altqreq) /* add a class */
+#define ALTQMODCLASS _IOWR('q', 8, struct altqreq) /* modify a class */
+#define ALTQDELCLASS _IOWR('q', 9, struct altqreq) /* delete a class */
+#define ALTQADDFILTER _IOWR('q', 10, struct altqreq) /* add a filter */
+#define ALTQDELFILTER _IOWR('q', 11, struct altqreq) /* delete a filter */
+#define ALTQGETSTATS _IOWR('q', 12, struct altqreq) /* get statistics */
+#define ALTQGETCNTR _IOWR('q', 13, struct altqreq) /* get a pkt counter */
+#endif /* 0 */
+#define ALTQTBRSET _IOW('q', 14, struct tbrreq) /* set tb regulator */
+#define ALTQTBRGET _IOWR('q', 15, struct tbrreq) /* get tb regulator */
+#endif /* ALTQ3_COMPAT */
+
+#ifdef _KERNEL
+#include <freebsd/altq/altq_var.h>
+#endif
+
+#endif /* _ALTQ_ALTQ_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_cbq.c b/freebsd/sys/contrib/altq/altq/altq_cbq.c
new file mode 100644
index 00000000..b5f21fb3
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_cbq.c
@@ -0,0 +1,1187 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_cbq.c,v 1.19 2003/09/17 14:23:25 kjc Exp $ */
+
+/*
+ * Copyright (c) Sun Microsystems, Inc. 1993-1998 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 SMCC Technology
+ * Development Group at Sun Microsystems, Inc.
+ *
+ * 4. The name of the Sun Microsystems, Inc nor may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * SUN MICROSYSTEMS DOES NOT CLAIM MERCHANTABILITY OF THIS SOFTWARE OR THE
+ * SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software is
+ * provided "as is" without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this software.
+ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#if (__FreeBSD__ != 2)
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+#ifdef ALTQ_CBQ /* cbq is enabled by ALTQ_CBQ option in opt_altq.h */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/errno.h>
+#include <freebsd/sys/time.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/sys/uio.h>
+#include <freebsd/sys/kernel.h>
+#endif
+
+#include <freebsd/net/if.h>
+#include <freebsd/netinet/in.h>
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_cbq.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/altq/altq_conf.h>
+#endif
+
+#ifdef ALTQ3_COMPAT
+/*
+ * Local Data structures.
+ */
+static cbq_state_t *cbq_list = NULL;
+#endif
+
+/*
+ * Forward Declarations.
+ */
+static int cbq_class_destroy(cbq_state_t *, struct rm_class *);
+static struct rm_class *clh_to_clp(cbq_state_t *, u_int32_t);
+static int cbq_clear_interface(cbq_state_t *);
+static int cbq_request(struct ifaltq *, int, void *);
+static int cbq_enqueue(struct ifaltq *, struct mbuf *,
+ struct altq_pktattr *);
+static struct mbuf *cbq_dequeue(struct ifaltq *, int);
+static void cbqrestart(struct ifaltq *);
+static void get_class_stats(class_stats_t *, struct rm_class *);
+static void cbq_purge(cbq_state_t *);
+#ifdef ALTQ3_COMPAT
+static int cbq_add_class(struct cbq_add_class *);
+static int cbq_delete_class(struct cbq_delete_class *);
+static int cbq_modify_class(struct cbq_modify_class *);
+static int cbq_class_create(cbq_state_t *, struct cbq_add_class *,
+ struct rm_class *, struct rm_class *);
+static int cbq_clear_hierarchy(struct cbq_interface *);
+static int cbq_set_enable(struct cbq_interface *, int);
+static int cbq_ifattach(struct cbq_interface *);
+static int cbq_ifdetach(struct cbq_interface *);
+static int cbq_getstats(struct cbq_getstats *);
+
+static int cbq_add_filter(struct cbq_add_filter *);
+static int cbq_delete_filter(struct cbq_delete_filter *);
+#endif /* ALTQ3_COMPAT */
+
+/*
+ * int
+ * cbq_class_destroy(cbq_mod_state_t *, struct rm_class *) - This
+ * function destroys a given traffic class. Before destroying
+ * the class, all traffic for that class is released.
+ */
+static int
+cbq_class_destroy(cbq_state_t *cbqp, struct rm_class *cl)
+{
+ int i;
+
+ /* delete the class */
+ rmc_delete_class(&cbqp->ifnp, cl);
+
+ /*
+ * free the class handle
+ */
+ for (i = 0; i < CBQ_MAX_CLASSES; i++)
+ if (cbqp->cbq_class_tbl[i] == cl)
+ cbqp->cbq_class_tbl[i] = NULL;
+
+ if (cl == cbqp->ifnp.root_)
+ cbqp->ifnp.root_ = NULL;
+ if (cl == cbqp->ifnp.default_)
+ cbqp->ifnp.default_ = NULL;
+#ifdef ALTQ3_COMPAT
+ if (cl == cbqp->ifnp.ctl_)
+ cbqp->ifnp.ctl_ = NULL;
+#endif
+ return (0);
+}
+
+/* convert class handle to class pointer */
+static struct rm_class *
+clh_to_clp(cbq_state_t *cbqp, u_int32_t chandle)
+{
+ int i;
+ struct rm_class *cl;
+
+ if (chandle == 0)
+ return (NULL);
+ /*
+ * first, try optimistically the slot matching the lower bits of
+ * the handle. if it fails, do the linear table search.
+ */
+ i = chandle % CBQ_MAX_CLASSES;
+ if ((cl = cbqp->cbq_class_tbl[i]) != NULL &&
+ cl->stats_.handle == chandle)
+ return (cl);
+ for (i = 0; i < CBQ_MAX_CLASSES; i++)
+ if ((cl = cbqp->cbq_class_tbl[i]) != NULL &&
+ cl->stats_.handle == chandle)
+ return (cl);
+ return (NULL);
+}
+
+static int
+cbq_clear_interface(cbq_state_t *cbqp)
+{
+ int again, i;
+ struct rm_class *cl;
+
+#ifdef ALTQ3_CLFIER_COMPAT
+ /* free the filters for this interface */
+ acc_discard_filters(&cbqp->cbq_classifier, NULL, 1);
+#endif
+
+ /* clear out the classes now */
+ do {
+ again = 0;
+ for (i = 0; i < CBQ_MAX_CLASSES; i++) {
+ if ((cl = cbqp->cbq_class_tbl[i]) != NULL) {
+ if (is_a_parent_class(cl))
+ again++;
+ else {
+ cbq_class_destroy(cbqp, cl);
+ cbqp->cbq_class_tbl[i] = NULL;
+ if (cl == cbqp->ifnp.root_)
+ cbqp->ifnp.root_ = NULL;
+ if (cl == cbqp->ifnp.default_)
+ cbqp->ifnp.default_ = NULL;
+#ifdef ALTQ3_COMPAT
+ if (cl == cbqp->ifnp.ctl_)
+ cbqp->ifnp.ctl_ = NULL;
+#endif
+ }
+ }
+ }
+ } while (again);
+
+ return (0);
+}
+
+static int
+cbq_request(struct ifaltq *ifq, int req, void *arg)
+{
+ cbq_state_t *cbqp = (cbq_state_t *)ifq->altq_disc;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ switch (req) {
+ case ALTRQ_PURGE:
+ cbq_purge(cbqp);
+ break;
+ }
+ return (0);
+}
+
+/* copy the stats info in rm_class to class_states_t */
+static void
+get_class_stats(class_stats_t *statsp, struct rm_class *cl)
+{
+ statsp->xmit_cnt = cl->stats_.xmit_cnt;
+ statsp->drop_cnt = cl->stats_.drop_cnt;
+ statsp->over = cl->stats_.over;
+ statsp->borrows = cl->stats_.borrows;
+ statsp->overactions = cl->stats_.overactions;
+ statsp->delays = cl->stats_.delays;
+
+ statsp->depth = cl->depth_;
+ statsp->priority = cl->pri_;
+ statsp->maxidle = cl->maxidle_;
+ statsp->minidle = cl->minidle_;
+ statsp->offtime = cl->offtime_;
+ statsp->qmax = qlimit(cl->q_);
+ statsp->ns_per_byte = cl->ns_per_byte_;
+ statsp->wrr_allot = cl->w_allotment_;
+ statsp->qcnt = qlen(cl->q_);
+ statsp->avgidle = cl->avgidle_;
+
+ statsp->qtype = qtype(cl->q_);
+#ifdef ALTQ_RED
+ if (q_is_red(cl->q_))
+ red_getstats(cl->red_, &statsp->red[0]);
+#endif
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->q_))
+ rio_getstats((rio_t *)cl->red_, &statsp->red[0]);
+#endif
+}
+
+int
+cbq_pfattach(struct pf_altq *a)
+{
+ struct ifnet *ifp;
+ int s, error;
+
+ if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL)
+ return (EINVAL);
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ error = altq_attach(&ifp->if_snd, ALTQT_CBQ, a->altq_disc,
+ cbq_enqueue, cbq_dequeue, cbq_request, NULL, NULL);
+ splx(s);
+ return (error);
+}
+
+int
+cbq_add_altq(struct pf_altq *a)
+{
+ cbq_state_t *cbqp;
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(a->ifname)) == NULL)
+ return (EINVAL);
+ if (!ALTQ_IS_READY(&ifp->if_snd))
+ return (ENODEV);
+
+ /* allocate and initialize cbq_state_t */
+ cbqp = malloc(sizeof(cbq_state_t), M_DEVBUF, M_WAITOK);
+ if (cbqp == NULL)
+ return (ENOMEM);
+ bzero(cbqp, sizeof(cbq_state_t));
+ CALLOUT_INIT(&cbqp->cbq_callout);
+ cbqp->cbq_qlen = 0;
+ cbqp->ifnp.ifq_ = &ifp->if_snd; /* keep the ifq */
+
+ /* keep the state in pf_altq */
+ a->altq_disc = cbqp;
+
+ return (0);
+}
+
+int
+cbq_remove_altq(struct pf_altq *a)
+{
+ cbq_state_t *cbqp;
+
+ if ((cbqp = a->altq_disc) == NULL)
+ return (EINVAL);
+ a->altq_disc = NULL;
+
+ cbq_clear_interface(cbqp);
+
+ if (cbqp->ifnp.default_)
+ cbq_class_destroy(cbqp, cbqp->ifnp.default_);
+ if (cbqp->ifnp.root_)
+ cbq_class_destroy(cbqp, cbqp->ifnp.root_);
+
+ /* deallocate cbq_state_t */
+ free(cbqp, M_DEVBUF);
+
+ return (0);
+}
+
+int
+cbq_add_queue(struct pf_altq *a)
+{
+ struct rm_class *borrow, *parent;
+ cbq_state_t *cbqp;
+ struct rm_class *cl;
+ struct cbq_opts *opts;
+ int i;
+
+ if ((cbqp = a->altq_disc) == NULL)
+ return (EINVAL);
+ if (a->qid == 0)
+ return (EINVAL);
+
+ /*
+ * find a free slot in the class table. if the slot matching
+ * the lower bits of qid is free, use this slot. otherwise,
+ * use the first free slot.
+ */
+ i = a->qid % CBQ_MAX_CLASSES;
+ if (cbqp->cbq_class_tbl[i] != NULL) {
+ for (i = 0; i < CBQ_MAX_CLASSES; i++)
+ if (cbqp->cbq_class_tbl[i] == NULL)
+ break;
+ if (i == CBQ_MAX_CLASSES)
+ return (EINVAL);
+ }
+
+ opts = &a->pq_u.cbq_opts;
+ /* check parameters */
+ if (a->priority >= CBQ_MAXPRI)
+ return (EINVAL);
+
+ /* Get pointers to parent and borrow classes. */
+ parent = clh_to_clp(cbqp, a->parent_qid);
+ if (opts->flags & CBQCLF_BORROW)
+ borrow = parent;
+ else
+ borrow = NULL;
+
+ /*
+ * A class must borrow from it's parent or it can not
+ * borrow at all. Hence, borrow can be null.
+ */
+ if (parent == NULL && (opts->flags & CBQCLF_ROOTCLASS) == 0) {
+ printf("cbq_add_queue: no parent class!\n");
+ return (EINVAL);
+ }
+
+ if ((borrow != parent) && (borrow != NULL)) {
+ printf("cbq_add_class: borrow class != parent\n");
+ return (EINVAL);
+ }
+
+ /*
+ * check parameters
+ */
+ switch (opts->flags & CBQCLF_CLASSMASK) {
+ case CBQCLF_ROOTCLASS:
+ if (parent != NULL)
+ return (EINVAL);
+ if (cbqp->ifnp.root_)
+ return (EINVAL);
+ break;
+ case CBQCLF_DEFCLASS:
+ if (cbqp->ifnp.default_)
+ return (EINVAL);
+ break;
+ case 0:
+ if (a->qid == 0)
+ return (EINVAL);
+ break;
+ default:
+ /* more than two flags bits set */
+ return (EINVAL);
+ }
+
+ /*
+ * create a class. if this is a root class, initialize the
+ * interface.
+ */
+ if ((opts->flags & CBQCLF_CLASSMASK) == CBQCLF_ROOTCLASS) {
+ rmc_init(cbqp->ifnp.ifq_, &cbqp->ifnp, opts->ns_per_byte,
+ cbqrestart, a->qlimit, RM_MAXQUEUED,
+ opts->maxidle, opts->minidle, opts->offtime,
+ opts->flags);
+ cl = cbqp->ifnp.root_;
+ } else {
+ cl = rmc_newclass(a->priority,
+ &cbqp->ifnp, opts->ns_per_byte,
+ rmc_delay_action, a->qlimit, parent, borrow,
+ opts->maxidle, opts->minidle, opts->offtime,
+ opts->pktsize, opts->flags);
+ }
+ if (cl == NULL)
+ return (ENOMEM);
+
+ /* return handle to user space. */
+ cl->stats_.handle = a->qid;
+ cl->stats_.depth = cl->depth_;
+
+ /* save the allocated class */
+ cbqp->cbq_class_tbl[i] = cl;
+
+ if ((opts->flags & CBQCLF_CLASSMASK) == CBQCLF_DEFCLASS)
+ cbqp->ifnp.default_ = cl;
+
+ return (0);
+}
+
+int
+cbq_remove_queue(struct pf_altq *a)
+{
+ struct rm_class *cl;
+ cbq_state_t *cbqp;
+ int i;
+
+ if ((cbqp = a->altq_disc) == NULL)
+ return (EINVAL);
+
+ if ((cl = clh_to_clp(cbqp, a->qid)) == NULL)
+ return (EINVAL);
+
+ /* if we are a parent class, then return an error. */
+ if (is_a_parent_class(cl))
+ return (EINVAL);
+
+ /* delete the class */
+ rmc_delete_class(&cbqp->ifnp, cl);
+
+ /*
+ * free the class handle
+ */
+ for (i = 0; i < CBQ_MAX_CLASSES; i++)
+ if (cbqp->cbq_class_tbl[i] == cl) {
+ cbqp->cbq_class_tbl[i] = NULL;
+ if (cl == cbqp->ifnp.root_)
+ cbqp->ifnp.root_ = NULL;
+ if (cl == cbqp->ifnp.default_)
+ cbqp->ifnp.default_ = NULL;
+ break;
+ }
+
+ return (0);
+}
+
+int
+cbq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+{
+ cbq_state_t *cbqp;
+ struct rm_class *cl;
+ class_stats_t stats;
+ int error = 0;
+
+ if ((cbqp = altq_lookup(a->ifname, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(cbqp, a->qid)) == NULL)
+ return (EINVAL);
+
+ if (*nbytes < sizeof(stats))
+ return (EINVAL);
+
+ get_class_stats(&stats, cl);
+
+ if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
+ return (error);
+ *nbytes = sizeof(stats);
+ return (0);
+}
+
+/*
+ * int
+ * cbq_enqueue(struct ifaltq *ifq, struct mbuf *m, struct altq_pktattr *pattr)
+ * - Queue data packets.
+ *
+ * cbq_enqueue is set to ifp->if_altqenqueue and called by an upper
+ * layer (e.g. ether_output). cbq_enqueue queues the given packet
+ * to the cbq, then invokes the driver's start routine.
+ *
+ * Assumptions: called in splimp
+ * Returns: 0 if the queueing is successful.
+ * ENOBUFS if a packet dropping occurred as a result of
+ * the queueing.
+ */
+
+static int
+cbq_enqueue(struct ifaltq *ifq, struct mbuf *m, struct altq_pktattr *pktattr)
+{
+ cbq_state_t *cbqp = (cbq_state_t *)ifq->altq_disc;
+ struct rm_class *cl;
+ struct pf_mtag *t;
+ int len;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ /* grab class set by classifier */
+ if ((m->m_flags & M_PKTHDR) == 0) {
+ /* should not happen */
+#if defined(__NetBSD__) || defined(__OpenBSD__)\
+ || (defined(__FreeBSD__) && __FreeBSD_version >= 501113)
+ printf("altq: packet for %s does not have pkthdr\n",
+ ifq->altq_ifp->if_xname);
+#else
+ printf("altq: packet for %s%d does not have pkthdr\n",
+ ifq->altq_ifp->if_name, ifq->altq_ifp->if_unit);
+#endif
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ cl = NULL;
+ if ((t = pf_find_mtag(m)) != NULL)
+ cl = clh_to_clp(cbqp, t->qid);
+#ifdef ALTQ3_COMPAT
+ else if ((ifq->altq_flags & ALTQF_CLASSIFY) && pktattr != NULL)
+ cl = pktattr->pattr_class;
+#endif
+ if (cl == NULL) {
+ cl = cbqp->ifnp.default_;
+ if (cl == NULL) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ }
+#ifdef ALTQ3_COMPAT
+ if (pktattr != NULL)
+ cl->pktattr_ = pktattr; /* save proto hdr used by ECN */
+ else
+#endif
+ cl->pktattr_ = NULL;
+ len = m_pktlen(m);
+ if (rmc_queue_packet(cl, m) != 0) {
+ /* drop occurred. some mbuf was freed in rmc_queue_packet. */
+ PKTCNTR_ADD(&cl->stats_.drop_cnt, len);
+ return (ENOBUFS);
+ }
+
+ /* successfully queued. */
+ ++cbqp->cbq_qlen;
+ IFQ_INC_LEN(ifq);
+ return (0);
+}
+
+static struct mbuf *
+cbq_dequeue(struct ifaltq *ifq, int op)
+{
+ cbq_state_t *cbqp = (cbq_state_t *)ifq->altq_disc;
+ struct mbuf *m;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ m = rmc_dequeue_next(&cbqp->ifnp, op);
+
+ if (m && op == ALTDQ_REMOVE) {
+ --cbqp->cbq_qlen; /* decrement # of packets in cbq */
+ IFQ_DEC_LEN(ifq);
+
+ /* Update the class. */
+ rmc_update_class_util(&cbqp->ifnp);
+ }
+ return (m);
+}
+
+/*
+ * void
+ * cbqrestart(queue_t *) - Restart sending of data.
+ * called from rmc_restart in splimp via timeout after waking up
+ * a suspended class.
+ * Returns: NONE
+ */
+
+static void
+cbqrestart(struct ifaltq *ifq)
+{
+ cbq_state_t *cbqp;
+ struct ifnet *ifp;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ if (!ALTQ_IS_ENABLED(ifq))
+ /* cbq must have been detached */
+ return;
+
+ if ((cbqp = (cbq_state_t *)ifq->altq_disc) == NULL)
+ /* should not happen */
+ return;
+
+ ifp = ifq->altq_ifp;
+ if (ifp->if_start &&
+ cbqp->cbq_qlen > 0 && (ifp->if_drv_flags & IFF_DRV_OACTIVE) == 0) {
+ IFQ_UNLOCK(ifq);
+ (*ifp->if_start)(ifp);
+ IFQ_LOCK(ifq);
+ }
+}
+
+static void cbq_purge(cbq_state_t *cbqp)
+{
+ struct rm_class *cl;
+ int i;
+
+ for (i = 0; i < CBQ_MAX_CLASSES; i++)
+ if ((cl = cbqp->cbq_class_tbl[i]) != NULL)
+ rmc_dropall(cl);
+ if (ALTQ_IS_ENABLED(cbqp->ifnp.ifq_))
+ cbqp->ifnp.ifq_->ifq_len = 0;
+}
+#ifdef ALTQ3_COMPAT
+
+static int
+cbq_add_class(acp)
+ struct cbq_add_class *acp;
+{
+ char *ifacename;
+ struct rm_class *borrow, *parent;
+ cbq_state_t *cbqp;
+
+ ifacename = acp->cbq_iface.cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ /* check parameters */
+ if (acp->cbq_class.priority >= CBQ_MAXPRI ||
+ acp->cbq_class.maxq > CBQ_MAXQSIZE)
+ return (EINVAL);
+
+ /* Get pointers to parent and borrow classes. */
+ parent = clh_to_clp(cbqp, acp->cbq_class.parent_class_handle);
+ borrow = clh_to_clp(cbqp, acp->cbq_class.borrow_class_handle);
+
+ /*
+ * A class must borrow from it's parent or it can not
+ * borrow at all. Hence, borrow can be null.
+ */
+ if (parent == NULL && (acp->cbq_class.flags & CBQCLF_ROOTCLASS) == 0) {
+ printf("cbq_add_class: no parent class!\n");
+ return (EINVAL);
+ }
+
+ if ((borrow != parent) && (borrow != NULL)) {
+ printf("cbq_add_class: borrow class != parent\n");
+ return (EINVAL);
+ }
+
+ return cbq_class_create(cbqp, acp, parent, borrow);
+}
+
+static int
+cbq_delete_class(dcp)
+ struct cbq_delete_class *dcp;
+{
+ char *ifacename;
+ struct rm_class *cl;
+ cbq_state_t *cbqp;
+
+ ifacename = dcp->cbq_iface.cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(cbqp, dcp->cbq_class_handle)) == NULL)
+ return (EINVAL);
+
+ /* if we are a parent class, then return an error. */
+ if (is_a_parent_class(cl))
+ return (EINVAL);
+
+ /* if a filter has a reference to this class delete the filter */
+ acc_discard_filters(&cbqp->cbq_classifier, cl, 0);
+
+ return cbq_class_destroy(cbqp, cl);
+}
+
+static int
+cbq_modify_class(acp)
+ struct cbq_modify_class *acp;
+{
+ char *ifacename;
+ struct rm_class *cl;
+ cbq_state_t *cbqp;
+
+ ifacename = acp->cbq_iface.cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ /* Get pointer to this class */
+ if ((cl = clh_to_clp(cbqp, acp->cbq_class_handle)) == NULL)
+ return (EINVAL);
+
+ if (rmc_modclass(cl, acp->cbq_class.nano_sec_per_byte,
+ acp->cbq_class.maxq, acp->cbq_class.maxidle,
+ acp->cbq_class.minidle, acp->cbq_class.offtime,
+ acp->cbq_class.pktsize) < 0)
+ return (EINVAL);
+ return (0);
+}
+
+/*
+ * struct rm_class *
+ * cbq_class_create(cbq_mod_state_t *cbqp, struct cbq_add_class *acp,
+ * struct rm_class *parent, struct rm_class *borrow)
+ *
+ * This function create a new traffic class in the CBQ class hierarchy of
+ * given paramters. The class that created is either the root, default,
+ * or a new dynamic class. If CBQ is not initilaized, the the root class
+ * will be created.
+ */
+static int
+cbq_class_create(cbqp, acp, parent, borrow)
+ cbq_state_t *cbqp;
+ struct cbq_add_class *acp;
+ struct rm_class *parent, *borrow;
+{
+ struct rm_class *cl;
+ cbq_class_spec_t *spec = &acp->cbq_class;
+ u_int32_t chandle;
+ int i;
+
+ /*
+ * allocate class handle
+ */
+ for (i = 1; i < CBQ_MAX_CLASSES; i++)
+ if (cbqp->cbq_class_tbl[i] == NULL)
+ break;
+ if (i == CBQ_MAX_CLASSES)
+ return (EINVAL);
+ chandle = i; /* use the slot number as class handle */
+
+ /*
+ * create a class. if this is a root class, initialize the
+ * interface.
+ */
+ if ((spec->flags & CBQCLF_CLASSMASK) == CBQCLF_ROOTCLASS) {
+ rmc_init(cbqp->ifnp.ifq_, &cbqp->ifnp, spec->nano_sec_per_byte,
+ cbqrestart, spec->maxq, RM_MAXQUEUED,
+ spec->maxidle, spec->minidle, spec->offtime,
+ spec->flags);
+ cl = cbqp->ifnp.root_;
+ } else {
+ cl = rmc_newclass(spec->priority,
+ &cbqp->ifnp, spec->nano_sec_per_byte,
+ rmc_delay_action, spec->maxq, parent, borrow,
+ spec->maxidle, spec->minidle, spec->offtime,
+ spec->pktsize, spec->flags);
+ }
+ if (cl == NULL)
+ return (ENOMEM);
+
+ /* return handle to user space. */
+ acp->cbq_class_handle = chandle;
+
+ cl->stats_.handle = chandle;
+ cl->stats_.depth = cl->depth_;
+
+ /* save the allocated class */
+ cbqp->cbq_class_tbl[i] = cl;
+
+ if ((spec->flags & CBQCLF_CLASSMASK) == CBQCLF_DEFCLASS)
+ cbqp->ifnp.default_ = cl;
+ if ((spec->flags & CBQCLF_CLASSMASK) == CBQCLF_CTLCLASS)
+ cbqp->ifnp.ctl_ = cl;
+
+ return (0);
+}
+
+static int
+cbq_add_filter(afp)
+ struct cbq_add_filter *afp;
+{
+ char *ifacename;
+ cbq_state_t *cbqp;
+ struct rm_class *cl;
+
+ ifacename = afp->cbq_iface.cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ /* Get the pointer to class. */
+ if ((cl = clh_to_clp(cbqp, afp->cbq_class_handle)) == NULL)
+ return (EINVAL);
+
+ return acc_add_filter(&cbqp->cbq_classifier, &afp->cbq_filter,
+ cl, &afp->cbq_filter_handle);
+}
+
+static int
+cbq_delete_filter(dfp)
+ struct cbq_delete_filter *dfp;
+{
+ char *ifacename;
+ cbq_state_t *cbqp;
+
+ ifacename = dfp->cbq_iface.cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ return acc_delete_filter(&cbqp->cbq_classifier,
+ dfp->cbq_filter_handle);
+}
+
+/*
+ * cbq_clear_hierarchy deletes all classes and their filters on the
+ * given interface.
+ */
+static int
+cbq_clear_hierarchy(ifacep)
+ struct cbq_interface *ifacep;
+{
+ char *ifacename;
+ cbq_state_t *cbqp;
+
+ ifacename = ifacep->cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ return cbq_clear_interface(cbqp);
+}
+
+/*
+ * static int
+ * cbq_set_enable(struct cbq_enable *ep) - this function processed the
+ * ioctl request to enable class based queueing. It searches the list
+ * of interfaces for the specified interface and then enables CBQ on
+ * that interface.
+ *
+ * Returns: 0, for no error.
+ * EBADF, for specified inteface not found.
+ */
+
+static int
+cbq_set_enable(ep, enable)
+ struct cbq_interface *ep;
+ int enable;
+{
+ int error = 0;
+ cbq_state_t *cbqp;
+ char *ifacename;
+
+ ifacename = ep->cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ switch (enable) {
+ case ENABLE:
+ if (cbqp->ifnp.root_ == NULL || cbqp->ifnp.default_ == NULL ||
+ cbqp->ifnp.ctl_ == NULL) {
+ if (cbqp->ifnp.root_ == NULL)
+ printf("No Root Class for %s\n", ifacename);
+ if (cbqp->ifnp.default_ == NULL)
+ printf("No Default Class for %s\n", ifacename);
+ if (cbqp->ifnp.ctl_ == NULL)
+ printf("No Control Class for %s\n", ifacename);
+ error = EINVAL;
+ } else if ((error = altq_enable(cbqp->ifnp.ifq_)) == 0) {
+ cbqp->cbq_qlen = 0;
+ }
+ break;
+
+ case DISABLE:
+ error = altq_disable(cbqp->ifnp.ifq_);
+ break;
+ }
+ return (error);
+}
+
+static int
+cbq_getstats(gsp)
+ struct cbq_getstats *gsp;
+{
+ char *ifacename;
+ int i, n, nclasses;
+ cbq_state_t *cbqp;
+ struct rm_class *cl;
+ class_stats_t stats, *usp;
+ int error = 0;
+
+ ifacename = gsp->iface.cbq_ifacename;
+ nclasses = gsp->nclasses;
+ usp = gsp->stats;
+
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+ if (nclasses <= 0)
+ return (EINVAL);
+
+ for (n = 0, i = 0; n < nclasses && i < CBQ_MAX_CLASSES; n++, i++) {
+ while ((cl = cbqp->cbq_class_tbl[i]) == NULL)
+ if (++i >= CBQ_MAX_CLASSES)
+ goto out;
+
+ get_class_stats(&stats, cl);
+ stats.handle = cl->stats_.handle;
+
+ if ((error = copyout((caddr_t)&stats, (caddr_t)usp++,
+ sizeof(stats))) != 0)
+ return (error);
+ }
+
+ out:
+ gsp->nclasses = n;
+ return (error);
+}
+
+static int
+cbq_ifattach(ifacep)
+ struct cbq_interface *ifacep;
+{
+ int error = 0;
+ char *ifacename;
+ cbq_state_t *new_cbqp;
+ struct ifnet *ifp;
+
+ ifacename = ifacep->cbq_ifacename;
+ if ((ifp = ifunit(ifacename)) == NULL)
+ return (ENXIO);
+ if (!ALTQ_IS_READY(&ifp->if_snd))
+ return (ENXIO);
+
+ /* allocate and initialize cbq_state_t */
+ new_cbqp = malloc(sizeof(cbq_state_t), M_DEVBUF, M_WAITOK);
+ if (new_cbqp == NULL)
+ return (ENOMEM);
+ bzero(new_cbqp, sizeof(cbq_state_t));
+ CALLOUT_INIT(&new_cbqp->cbq_callout);
+
+ new_cbqp->cbq_qlen = 0;
+ new_cbqp->ifnp.ifq_ = &ifp->if_snd; /* keep the ifq */
+
+ /*
+ * set CBQ to this ifnet structure.
+ */
+ error = altq_attach(&ifp->if_snd, ALTQT_CBQ, new_cbqp,
+ cbq_enqueue, cbq_dequeue, cbq_request,
+ &new_cbqp->cbq_classifier, acc_classify);
+ if (error) {
+ free(new_cbqp, M_DEVBUF);
+ return (error);
+ }
+
+ /* prepend to the list of cbq_state_t's. */
+ new_cbqp->cbq_next = cbq_list;
+ cbq_list = new_cbqp;
+
+ return (0);
+}
+
+static int
+cbq_ifdetach(ifacep)
+ struct cbq_interface *ifacep;
+{
+ char *ifacename;
+ cbq_state_t *cbqp;
+
+ ifacename = ifacep->cbq_ifacename;
+ if ((cbqp = altq_lookup(ifacename, ALTQT_CBQ)) == NULL)
+ return (EBADF);
+
+ (void)cbq_set_enable(ifacep, DISABLE);
+
+ cbq_clear_interface(cbqp);
+
+ /* remove CBQ from the ifnet structure. */
+ (void)altq_detach(cbqp->ifnp.ifq_);
+
+ /* remove from the list of cbq_state_t's. */
+ if (cbq_list == cbqp)
+ cbq_list = cbqp->cbq_next;
+ else {
+ cbq_state_t *cp;
+
+ for (cp = cbq_list; cp != NULL; cp = cp->cbq_next)
+ if (cp->cbq_next == cbqp) {
+ cp->cbq_next = cbqp->cbq_next;
+ break;
+ }
+ ASSERT(cp != NULL);
+ }
+
+ /* deallocate cbq_state_t */
+ free(cbqp, M_DEVBUF);
+
+ return (0);
+}
+
+/*
+ * cbq device interface
+ */
+
+altqdev_decl(cbq);
+
+int
+cbqopen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ return (0);
+}
+
+int
+cbqclose(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ struct ifnet *ifp;
+ struct cbq_interface iface;
+ int err, error = 0;
+
+ while (cbq_list) {
+ ifp = cbq_list->ifnp.ifq_->altq_ifp;
+#if defined(__NetBSD__) || defined(__OpenBSD__)\
+ || (defined(__FreeBSD__) && __FreeBSD_version >= 501113)
+ sprintf(iface.cbq_ifacename, "%s", ifp->if_xname);
+#else
+ sprintf(iface.cbq_ifacename,
+ "%s%d", ifp->if_name, ifp->if_unit);
+#endif
+ err = cbq_ifdetach(&iface);
+ if (err != 0 && error == 0)
+ error = err;
+ }
+
+ return (error);
+}
+
+int
+cbqioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ ioctlcmd_t cmd;
+ caddr_t addr;
+ int flag;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ int error = 0;
+
+ /* check cmd for superuser only */
+ switch (cmd) {
+ case CBQ_GETSTATS:
+ /* currently only command that an ordinary user can call */
+ break;
+ default:
+#if (__FreeBSD_version > 700000)
+ error = priv_check(p, PRIV_ALTQ_MANAGE);
+#elsif (__FreeBSD_version > 400000)
+ error = suser(p);
+#else
+ error = suser(p->p_ucred, &p->p_acflag);
+#endif
+ if (error)
+ return (error);
+ break;
+ }
+
+ switch (cmd) {
+
+ case CBQ_ENABLE:
+ error = cbq_set_enable((struct cbq_interface *)addr, ENABLE);
+ break;
+
+ case CBQ_DISABLE:
+ error = cbq_set_enable((struct cbq_interface *)addr, DISABLE);
+ break;
+
+ case CBQ_ADD_FILTER:
+ error = cbq_add_filter((struct cbq_add_filter *)addr);
+ break;
+
+ case CBQ_DEL_FILTER:
+ error = cbq_delete_filter((struct cbq_delete_filter *)addr);
+ break;
+
+ case CBQ_ADD_CLASS:
+ error = cbq_add_class((struct cbq_add_class *)addr);
+ break;
+
+ case CBQ_DEL_CLASS:
+ error = cbq_delete_class((struct cbq_delete_class *)addr);
+ break;
+
+ case CBQ_MODIFY_CLASS:
+ error = cbq_modify_class((struct cbq_modify_class *)addr);
+ break;
+
+ case CBQ_CLEAR_HIERARCHY:
+ error = cbq_clear_hierarchy((struct cbq_interface *)addr);
+ break;
+
+ case CBQ_IF_ATTACH:
+ error = cbq_ifattach((struct cbq_interface *)addr);
+ break;
+
+ case CBQ_IF_DETACH:
+ error = cbq_ifdetach((struct cbq_interface *)addr);
+ break;
+
+ case CBQ_GETSTATS:
+ error = cbq_getstats((struct cbq_getstats *)addr);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+#if 0
+/* for debug */
+static void cbq_class_dump(int);
+
+static void cbq_class_dump(i)
+ int i;
+{
+ struct rm_class *cl;
+ rm_class_stats_t *s;
+ struct _class_queue_ *q;
+
+ if (cbq_list == NULL) {
+ printf("cbq_class_dump: no cbq_state found\n");
+ return;
+ }
+ cl = cbq_list->cbq_class_tbl[i];
+
+ printf("class %d cl=%p\n", i, cl);
+ if (cl != NULL) {
+ s = &cl->stats_;
+ q = cl->q_;
+
+ printf("pri=%d, depth=%d, maxrate=%d, allotment=%d\n",
+ cl->pri_, cl->depth_, cl->maxrate_, cl->allotment_);
+ printf("w_allotment=%d, bytes_alloc=%d, avgidle=%d, maxidle=%d\n",
+ cl->w_allotment_, cl->bytes_alloc_, cl->avgidle_,
+ cl->maxidle_);
+ printf("minidle=%d, offtime=%d, sleeping=%d, leaf=%d\n",
+ cl->minidle_, cl->offtime_, cl->sleeping_, cl->leaf_);
+ printf("handle=%d, depth=%d, packets=%d, bytes=%d\n",
+ s->handle, s->depth,
+ (int)s->xmit_cnt.packets, (int)s->xmit_cnt.bytes);
+ printf("over=%d\n, borrows=%d, drops=%d, overactions=%d, delays=%d\n",
+ s->over, s->borrows, (int)s->drop_cnt.packets,
+ s->overactions, s->delays);
+ printf("tail=%p, head=%p, qlen=%d, qlim=%d, qthresh=%d,qtype=%d\n",
+ q->tail_, q->head_, q->qlen_, q->qlim_,
+ q->qthresh_, q->qtype_);
+ }
+}
+#endif /* 0 */
+
+#ifdef KLD_MODULE
+
+static struct altqsw cbq_sw =
+ {"cbq", cbqopen, cbqclose, cbqioctl};
+
+ALTQ_MODULE(altq_cbq, ALTQT_CBQ, &cbq_sw);
+MODULE_DEPEND(altq_cbq, altq_red, 1, 1, 1);
+MODULE_DEPEND(altq_cbq, altq_rio, 1, 1, 1);
+
+#endif /* KLD_MODULE */
+#endif /* ALTQ3_COMPAT */
+
+#endif /* ALTQ_CBQ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_cbq.h b/freebsd/sys/contrib/altq/altq/altq_cbq.h
new file mode 100644
index 00000000..4b90beb4
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_cbq.h
@@ -0,0 +1,221 @@
+/* $KAME: altq_cbq.h,v 1.12 2003/10/03 05:05:15 kjc Exp $ */
+
+/*
+ * Copyright (c) Sun Microsystems, Inc. 1993-1998 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 SMCC Technology
+ * Development Group at Sun Microsystems, Inc.
+ *
+ * 4. The name of the Sun Microsystems, Inc nor may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * SUN MICROSYSTEMS DOES NOT CLAIM MERCHANTABILITY OF THIS SOFTWARE OR THE
+ * SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software is
+ * provided "as is" without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this software.
+ */
+
+#ifndef _ALTQ_ALTQ_CBQ_HH_
+#define _ALTQ_ALTQ_CBQ_HH_
+
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_rmclass.h>
+#include <freebsd/altq/altq_red.h>
+#include <freebsd/altq/altq_rio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define NULL_CLASS_HANDLE 0
+
+/* class flags should be same as class flags in rm_class.h */
+#define CBQCLF_RED 0x0001 /* use RED */
+#define CBQCLF_ECN 0x0002 /* use RED/ECN */
+#define CBQCLF_RIO 0x0004 /* use RIO */
+#define CBQCLF_FLOWVALVE 0x0008 /* use flowvalve (aka penalty-box) */
+#define CBQCLF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
+#define CBQCLF_BORROW 0x0020 /* borrow from parent */
+
+/* class flags only for root class */
+#define CBQCLF_WRR 0x0100 /* weighted-round robin */
+#define CBQCLF_EFFICIENT 0x0200 /* work-conserving */
+
+/* class flags for special classes */
+#define CBQCLF_ROOTCLASS 0x1000 /* root class */
+#define CBQCLF_DEFCLASS 0x2000 /* default class */
+#ifdef ALTQ3_COMPAT
+#define CBQCLF_CTLCLASS 0x4000 /* control class */
+#endif
+#define CBQCLF_CLASSMASK 0xf000 /* class mask */
+
+#define CBQ_MAXQSIZE 200
+#define CBQ_MAXPRI RM_MAXPRIO
+
+typedef struct _cbq_class_stats_ {
+ u_int32_t handle;
+ u_int depth;
+
+ struct pktcntr xmit_cnt; /* packets sent in this class */
+ struct pktcntr drop_cnt; /* dropped packets */
+ u_int over; /* # times went over limit */
+ u_int borrows; /* # times tried to borrow */
+ u_int overactions; /* # times invoked overlimit action */
+ u_int delays; /* # times invoked delay actions */
+
+ /* other static class parameters useful for debugging */
+ int priority;
+ int maxidle;
+ int minidle;
+ int offtime;
+ int qmax;
+ int ns_per_byte;
+ int wrr_allot;
+
+ int qcnt; /* # packets in queue */
+ int avgidle;
+
+ /* red and rio related info */
+ int qtype;
+ struct redstats red[3];
+} class_stats_t;
+
+#ifdef ALTQ3_COMPAT
+/*
+ * Define structures associated with IOCTLS for cbq.
+ */
+
+/*
+ * Define the CBQ interface structure. This must be included in all
+ * IOCTL's such that the CBQ driver may find the appropriate CBQ module
+ * associated with the network interface to be affected.
+ */
+struct cbq_interface {
+ char cbq_ifacename[IFNAMSIZ];
+};
+
+typedef struct cbq_class_spec {
+ u_int priority;
+ u_int nano_sec_per_byte;
+ u_int maxq;
+ u_int maxidle;
+ int minidle;
+ u_int offtime;
+ u_int32_t parent_class_handle;
+ u_int32_t borrow_class_handle;
+
+ u_int pktsize;
+ int flags;
+} cbq_class_spec_t;
+
+struct cbq_add_class {
+ struct cbq_interface cbq_iface;
+
+ cbq_class_spec_t cbq_class;
+ u_int32_t cbq_class_handle;
+};
+
+struct cbq_delete_class {
+ struct cbq_interface cbq_iface;
+ u_int32_t cbq_class_handle;
+};
+
+struct cbq_modify_class {
+ struct cbq_interface cbq_iface;
+
+ cbq_class_spec_t cbq_class;
+ u_int32_t cbq_class_handle;
+};
+
+struct cbq_add_filter {
+ struct cbq_interface cbq_iface;
+ u_int32_t cbq_class_handle;
+ struct flow_filter cbq_filter;
+
+ u_long cbq_filter_handle;
+};
+
+struct cbq_delete_filter {
+ struct cbq_interface cbq_iface;
+ u_long cbq_filter_handle;
+};
+
+/* number of classes are returned in nclasses field */
+struct cbq_getstats {
+ struct cbq_interface iface;
+ int nclasses;
+ class_stats_t *stats;
+};
+
+/*
+ * Define IOCTLs for CBQ.
+ */
+#define CBQ_IF_ATTACH _IOW('Q', 1, struct cbq_interface)
+#define CBQ_IF_DETACH _IOW('Q', 2, struct cbq_interface)
+#define CBQ_ENABLE _IOW('Q', 3, struct cbq_interface)
+#define CBQ_DISABLE _IOW('Q', 4, struct cbq_interface)
+#define CBQ_CLEAR_HIERARCHY _IOW('Q', 5, struct cbq_interface)
+#define CBQ_ADD_CLASS _IOWR('Q', 7, struct cbq_add_class)
+#define CBQ_DEL_CLASS _IOW('Q', 8, struct cbq_delete_class)
+#define CBQ_MODIFY_CLASS _IOWR('Q', 9, struct cbq_modify_class)
+#define CBQ_ADD_FILTER _IOWR('Q', 10, struct cbq_add_filter)
+#define CBQ_DEL_FILTER _IOW('Q', 11, struct cbq_delete_filter)
+#define CBQ_GETSTATS _IOWR('Q', 12, struct cbq_getstats)
+#endif /* ALTQ3_COMPAT */
+
+#ifdef _KERNEL
+/*
+ * Define macros only good for kernel drivers and modules.
+ */
+#define CBQ_WATCHDOG (hz / 20)
+#define CBQ_TIMEOUT 10
+#define CBQ_LS_TIMEOUT (20 * hz / 1000)
+
+#define CBQ_MAX_CLASSES 256
+
+#ifdef ALTQ3_COMPAT
+#define CBQ_MAX_FILTERS 256
+
+#define DISABLE 0x00
+#define ENABLE 0x01
+#endif /* ALTQ3_COMPAT */
+
+/*
+ * Define State structures.
+ */
+typedef struct cbqstate {
+#ifdef ALTQ3_COMPAT
+ struct cbqstate *cbq_next;
+#endif
+ int cbq_qlen; /* # of packets in cbq */
+ struct rm_class *cbq_class_tbl[CBQ_MAX_CLASSES];
+
+ struct rm_ifdat ifnp;
+ struct callout cbq_callout; /* for timeouts */
+#ifdef ALTQ3_CLFIER_COMPAT
+ struct acc_classifier cbq_classifier;
+#endif
+} cbq_state_t;
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_ALTQ_ALTQ_CBQ_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_cdnr.c b/freebsd/sys/contrib/altq/altq/altq_cdnr.c
new file mode 100644
index 00000000..66095acc
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_cdnr.c
@@ -0,0 +1,1393 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_cdnr.c,v 1.14 2003/09/05 22:40:36 itojun Exp $ */
+
+/*
+ * Copyright (C) 1999-2002
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#if (__FreeBSD__ != 2)
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/sockio.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/errno.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/queue.h>
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/if_types.h>
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#endif
+
+#include <freebsd/altq/altq.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/altq/altq_conf.h>
+#endif
+#include <freebsd/altq/altq_cdnr.h>
+
+#ifdef ALTQ3_COMPAT
+/*
+ * diffserv traffic conditioning module
+ */
+
+int altq_cdnr_enabled = 0;
+
+/* traffic conditioner is enabled by ALTQ_CDNR option in opt_altq.h */
+#ifdef ALTQ_CDNR
+
+/* cdnr_list keeps all cdnr's allocated. */
+static LIST_HEAD(, top_cdnr) tcb_list;
+
+static int altq_cdnr_input(struct mbuf *, int);
+static struct top_cdnr *tcb_lookup(char *ifname);
+static struct cdnr_block *cdnr_handle2cb(u_long);
+static u_long cdnr_cb2handle(struct cdnr_block *);
+static void *cdnr_cballoc(struct top_cdnr *, int,
+ struct tc_action *(*)(struct cdnr_block *, struct cdnr_pktinfo *));
+static void cdnr_cbdestroy(void *);
+static int tca_verify_action(struct tc_action *);
+static void tca_import_action(struct tc_action *, struct tc_action *);
+static void tca_invalidate_action(struct tc_action *);
+
+static int generic_element_destroy(struct cdnr_block *);
+static struct top_cdnr *top_create(struct ifaltq *);
+static int top_destroy(struct top_cdnr *);
+static struct cdnr_block *element_create(struct top_cdnr *, struct tc_action *);
+static int element_destroy(struct cdnr_block *);
+static void tb_import_profile(struct tbe *, struct tb_profile *);
+static struct tbmeter *tbm_create(struct top_cdnr *, struct tb_profile *,
+ struct tc_action *, struct tc_action *);
+static int tbm_destroy(struct tbmeter *);
+static struct tc_action *tbm_input(struct cdnr_block *, struct cdnr_pktinfo *);
+static struct trtcm *trtcm_create(struct top_cdnr *,
+ struct tb_profile *, struct tb_profile *,
+ struct tc_action *, struct tc_action *, struct tc_action *,
+ int);
+static int trtcm_destroy(struct trtcm *);
+static struct tc_action *trtcm_input(struct cdnr_block *, struct cdnr_pktinfo *);
+static struct tswtcm *tswtcm_create(struct top_cdnr *,
+ u_int32_t, u_int32_t, u_int32_t,
+ struct tc_action *, struct tc_action *, struct tc_action *);
+static int tswtcm_destroy(struct tswtcm *);
+static struct tc_action *tswtcm_input(struct cdnr_block *, struct cdnr_pktinfo *);
+
+static int cdnrcmd_if_attach(char *);
+static int cdnrcmd_if_detach(char *);
+static int cdnrcmd_add_element(struct cdnr_add_element *);
+static int cdnrcmd_delete_element(struct cdnr_delete_element *);
+static int cdnrcmd_add_filter(struct cdnr_add_filter *);
+static int cdnrcmd_delete_filter(struct cdnr_delete_filter *);
+static int cdnrcmd_add_tbm(struct cdnr_add_tbmeter *);
+static int cdnrcmd_modify_tbm(struct cdnr_modify_tbmeter *);
+static int cdnrcmd_tbm_stats(struct cdnr_tbmeter_stats *);
+static int cdnrcmd_add_trtcm(struct cdnr_add_trtcm *);
+static int cdnrcmd_modify_trtcm(struct cdnr_modify_trtcm *);
+static int cdnrcmd_tcm_stats(struct cdnr_tcm_stats *);
+static int cdnrcmd_add_tswtcm(struct cdnr_add_tswtcm *);
+static int cdnrcmd_modify_tswtcm(struct cdnr_modify_tswtcm *);
+static int cdnrcmd_get_stats(struct cdnr_get_stats *);
+
+altqdev_decl(cdnr);
+
+/*
+ * top level input function called from ip_input.
+ * should be called before converting header fields to host-byte-order.
+ */
+int
+altq_cdnr_input(m, af)
+ struct mbuf *m;
+ int af; /* address family */
+{
+ struct ifnet *ifp;
+ struct ip *ip;
+ struct top_cdnr *top;
+ struct tc_action *tca;
+ struct cdnr_block *cb;
+ struct cdnr_pktinfo pktinfo;
+
+ ifp = m->m_pkthdr.rcvif;
+ if (!ALTQ_IS_CNDTNING(&ifp->if_snd))
+ /* traffic conditioner is not enabled on this interface */
+ return (1);
+
+ top = ifp->if_snd.altq_cdnr;
+
+ ip = mtod(m, struct ip *);
+#ifdef INET6
+ if (af == AF_INET6) {
+ u_int32_t flowlabel;
+
+ flowlabel = ((struct ip6_hdr *)ip)->ip6_flow;
+ pktinfo.pkt_dscp = (ntohl(flowlabel) >> 20) & DSCP_MASK;
+ } else
+#endif
+ pktinfo.pkt_dscp = ip->ip_tos & DSCP_MASK;
+ pktinfo.pkt_len = m_pktlen(m);
+
+ tca = NULL;
+
+ cb = acc_classify(&top->tc_classifier, m, af);
+ if (cb != NULL)
+ tca = &cb->cb_action;
+
+ if (tca == NULL)
+ tca = &top->tc_block.cb_action;
+
+ while (1) {
+ PKTCNTR_ADD(&top->tc_cnts[tca->tca_code], pktinfo.pkt_len);
+
+ switch (tca->tca_code) {
+ case TCACODE_PASS:
+ return (1);
+ case TCACODE_DROP:
+ m_freem(m);
+ return (0);
+ case TCACODE_RETURN:
+ return (0);
+ case TCACODE_MARK:
+#ifdef INET6
+ if (af == AF_INET6) {
+ struct ip6_hdr *ip6 = (struct ip6_hdr *)ip;
+ u_int32_t flowlabel;
+
+ flowlabel = ntohl(ip6->ip6_flow);
+ flowlabel = (tca->tca_dscp << 20) |
+ (flowlabel & ~(DSCP_MASK << 20));
+ ip6->ip6_flow = htonl(flowlabel);
+ } else
+#endif
+ ip->ip_tos = tca->tca_dscp |
+ (ip->ip_tos & DSCP_CUMASK);
+ return (1);
+ case TCACODE_NEXT:
+ cb = tca->tca_next;
+ tca = (*cb->cb_input)(cb, &pktinfo);
+ break;
+ case TCACODE_NONE:
+ default:
+ return (1);
+ }
+ }
+}
+
+static struct top_cdnr *
+tcb_lookup(ifname)
+ char *ifname;
+{
+ struct top_cdnr *top;
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(ifname)) != NULL)
+ LIST_FOREACH(top, &tcb_list, tc_next)
+ if (top->tc_ifq->altq_ifp == ifp)
+ return (top);
+ return (NULL);
+}
+
+static struct cdnr_block *
+cdnr_handle2cb(handle)
+ u_long handle;
+{
+ struct cdnr_block *cb;
+
+ cb = (struct cdnr_block *)handle;
+ if (handle != ALIGN(cb))
+ return (NULL);
+
+ if (cb == NULL || cb->cb_handle != handle)
+ return (NULL);
+ return (cb);
+}
+
+static u_long
+cdnr_cb2handle(cb)
+ struct cdnr_block *cb;
+{
+ return (cb->cb_handle);
+}
+
+static void *
+cdnr_cballoc(top, type, input_func)
+ struct top_cdnr *top;
+ int type;
+ struct tc_action *(*input_func)(struct cdnr_block *,
+ struct cdnr_pktinfo *);
+{
+ struct cdnr_block *cb;
+ int size;
+
+ switch (type) {
+ case TCETYPE_TOP:
+ size = sizeof(struct top_cdnr);
+ break;
+ case TCETYPE_ELEMENT:
+ size = sizeof(struct cdnr_block);
+ break;
+ case TCETYPE_TBMETER:
+ size = sizeof(struct tbmeter);
+ break;
+ case TCETYPE_TRTCM:
+ size = sizeof(struct trtcm);
+ break;
+ case TCETYPE_TSWTCM:
+ size = sizeof(struct tswtcm);
+ break;
+ default:
+ return (NULL);
+ }
+
+ cb = malloc(size, M_DEVBUF, M_WAITOK);
+ if (cb == NULL)
+ return (NULL);
+ bzero(cb, size);
+
+ cb->cb_len = size;
+ cb->cb_type = type;
+ cb->cb_ref = 0;
+ cb->cb_handle = (u_long)cb;
+ if (top == NULL)
+ cb->cb_top = (struct top_cdnr *)cb;
+ else
+ cb->cb_top = top;
+
+ if (input_func != NULL) {
+ /*
+ * if this cdnr has an action function,
+ * make tc_action to call itself.
+ */
+ cb->cb_action.tca_code = TCACODE_NEXT;
+ cb->cb_action.tca_next = cb;
+ cb->cb_input = input_func;
+ } else
+ cb->cb_action.tca_code = TCACODE_NONE;
+
+ /* if this isn't top, register the element to the top level cdnr */
+ if (top != NULL)
+ LIST_INSERT_HEAD(&top->tc_elements, cb, cb_next);
+
+ return ((void *)cb);
+}
+
+static void
+cdnr_cbdestroy(cblock)
+ void *cblock;
+{
+ struct cdnr_block *cb = cblock;
+
+ /* delete filters belonging to this cdnr */
+ acc_discard_filters(&cb->cb_top->tc_classifier, cb, 0);
+
+ /* remove from the top level cdnr */
+ if (cb->cb_top != cblock)
+ LIST_REMOVE(cb, cb_next);
+
+ free(cb, M_DEVBUF);
+}
+
+/*
+ * conditioner common destroy routine
+ */
+static int
+generic_element_destroy(cb)
+ struct cdnr_block *cb;
+{
+ int error = 0;
+
+ switch (cb->cb_type) {
+ case TCETYPE_TOP:
+ error = top_destroy((struct top_cdnr *)cb);
+ break;
+ case TCETYPE_ELEMENT:
+ error = element_destroy(cb);
+ break;
+ case TCETYPE_TBMETER:
+ error = tbm_destroy((struct tbmeter *)cb);
+ break;
+ case TCETYPE_TRTCM:
+ error = trtcm_destroy((struct trtcm *)cb);
+ break;
+ case TCETYPE_TSWTCM:
+ error = tswtcm_destroy((struct tswtcm *)cb);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+
+static int
+tca_verify_action(utca)
+ struct tc_action *utca;
+{
+ switch (utca->tca_code) {
+ case TCACODE_PASS:
+ case TCACODE_DROP:
+ case TCACODE_MARK:
+ /* these are ok */
+ break;
+
+ case TCACODE_HANDLE:
+ /* verify handle value */
+ if (cdnr_handle2cb(utca->tca_handle) == NULL)
+ return (-1);
+ break;
+
+ case TCACODE_NONE:
+ case TCACODE_RETURN:
+ case TCACODE_NEXT:
+ default:
+ /* should not be passed from a user */
+ return (-1);
+ }
+ return (0);
+}
+
+static void
+tca_import_action(ktca, utca)
+ struct tc_action *ktca, *utca;
+{
+ struct cdnr_block *cb;
+
+ *ktca = *utca;
+ if (ktca->tca_code == TCACODE_HANDLE) {
+ cb = cdnr_handle2cb(ktca->tca_handle);
+ if (cb == NULL) {
+ ktca->tca_code = TCACODE_NONE;
+ return;
+ }
+ ktca->tca_code = TCACODE_NEXT;
+ ktca->tca_next = cb;
+ cb->cb_ref++;
+ } else if (ktca->tca_code == TCACODE_MARK) {
+ ktca->tca_dscp &= DSCP_MASK;
+ }
+ return;
+}
+
+static void
+tca_invalidate_action(tca)
+ struct tc_action *tca;
+{
+ struct cdnr_block *cb;
+
+ if (tca->tca_code == TCACODE_NEXT) {
+ cb = tca->tca_next;
+ if (cb == NULL)
+ return;
+ cb->cb_ref--;
+ }
+ tca->tca_code = TCACODE_NONE;
+}
+
+/*
+ * top level traffic conditioner
+ */
+static struct top_cdnr *
+top_create(ifq)
+ struct ifaltq *ifq;
+{
+ struct top_cdnr *top;
+
+ if ((top = cdnr_cballoc(NULL, TCETYPE_TOP, NULL)) == NULL)
+ return (NULL);
+
+ top->tc_ifq = ifq;
+ /* set default action for the top level conditioner */
+ top->tc_block.cb_action.tca_code = TCACODE_PASS;
+
+ LIST_INSERT_HEAD(&tcb_list, top, tc_next);
+
+ ifq->altq_cdnr = top;
+
+ return (top);
+}
+
+static int
+top_destroy(top)
+ struct top_cdnr *top;
+{
+ struct cdnr_block *cb;
+
+ if (ALTQ_IS_CNDTNING(top->tc_ifq))
+ ALTQ_CLEAR_CNDTNING(top->tc_ifq);
+ top->tc_ifq->altq_cdnr = NULL;
+
+ /*
+ * destroy all the conditioner elements belonging to this interface
+ */
+ while ((cb = LIST_FIRST(&top->tc_elements)) != NULL) {
+ while (cb != NULL && cb->cb_ref > 0)
+ cb = LIST_NEXT(cb, cb_next);
+ if (cb != NULL)
+ generic_element_destroy(cb);
+ }
+
+ LIST_REMOVE(top, tc_next);
+
+ cdnr_cbdestroy(top);
+
+ /* if there is no active conditioner, remove the input hook */
+ if (altq_input != NULL) {
+ LIST_FOREACH(top, &tcb_list, tc_next)
+ if (ALTQ_IS_CNDTNING(top->tc_ifq))
+ break;
+ if (top == NULL)
+ altq_input = NULL;
+ }
+
+ return (0);
+}
+
+/*
+ * simple tc elements without input function (e.g., dropper and makers).
+ */
+static struct cdnr_block *
+element_create(top, action)
+ struct top_cdnr *top;
+ struct tc_action *action;
+{
+ struct cdnr_block *cb;
+
+ if (tca_verify_action(action) < 0)
+ return (NULL);
+
+ if ((cb = cdnr_cballoc(top, TCETYPE_ELEMENT, NULL)) == NULL)
+ return (NULL);
+
+ tca_import_action(&cb->cb_action, action);
+
+ return (cb);
+}
+
+static int
+element_destroy(cb)
+ struct cdnr_block *cb;
+{
+ if (cb->cb_ref > 0)
+ return (EBUSY);
+
+ tca_invalidate_action(&cb->cb_action);
+
+ cdnr_cbdestroy(cb);
+ return (0);
+}
+
+/*
+ * internal representation of token bucket parameters
+ * rate: byte_per_unittime << 32
+ * (((bits_per_sec) / 8) << 32) / machclk_freq
+ * depth: byte << 32
+ *
+ */
+#define TB_SHIFT 32
+#define TB_SCALE(x) ((u_int64_t)(x) << TB_SHIFT)
+#define TB_UNSCALE(x) ((x) >> TB_SHIFT)
+
+static void
+tb_import_profile(tb, profile)
+ struct tbe *tb;
+ struct tb_profile *profile;
+{
+ tb->rate = TB_SCALE(profile->rate / 8) / machclk_freq;
+ tb->depth = TB_SCALE(profile->depth);
+ if (tb->rate > 0)
+ tb->filluptime = tb->depth / tb->rate;
+ else
+ tb->filluptime = 0xffffffffffffffffLL;
+ tb->token = tb->depth;
+ tb->last = read_machclk();
+}
+
+/*
+ * simple token bucket meter
+ */
+static struct tbmeter *
+tbm_create(top, profile, in_action, out_action)
+ struct top_cdnr *top;
+ struct tb_profile *profile;
+ struct tc_action *in_action, *out_action;
+{
+ struct tbmeter *tbm = NULL;
+
+ if (tca_verify_action(in_action) < 0
+ || tca_verify_action(out_action) < 0)
+ return (NULL);
+
+ if ((tbm = cdnr_cballoc(top, TCETYPE_TBMETER,
+ tbm_input)) == NULL)
+ return (NULL);
+
+ tb_import_profile(&tbm->tb, profile);
+
+ tca_import_action(&tbm->in_action, in_action);
+ tca_import_action(&tbm->out_action, out_action);
+
+ return (tbm);
+}
+
+static int
+tbm_destroy(tbm)
+ struct tbmeter *tbm;
+{
+ if (tbm->cdnrblk.cb_ref > 0)
+ return (EBUSY);
+
+ tca_invalidate_action(&tbm->in_action);
+ tca_invalidate_action(&tbm->out_action);
+
+ cdnr_cbdestroy(tbm);
+ return (0);
+}
+
+static struct tc_action *
+tbm_input(cb, pktinfo)
+ struct cdnr_block *cb;
+ struct cdnr_pktinfo *pktinfo;
+{
+ struct tbmeter *tbm = (struct tbmeter *)cb;
+ u_int64_t len;
+ u_int64_t interval, now;
+
+ len = TB_SCALE(pktinfo->pkt_len);
+
+ if (tbm->tb.token < len) {
+ now = read_machclk();
+ interval = now - tbm->tb.last;
+ if (interval >= tbm->tb.filluptime)
+ tbm->tb.token = tbm->tb.depth;
+ else {
+ tbm->tb.token += interval * tbm->tb.rate;
+ if (tbm->tb.token > tbm->tb.depth)
+ tbm->tb.token = tbm->tb.depth;
+ }
+ tbm->tb.last = now;
+ }
+
+ if (tbm->tb.token < len) {
+ PKTCNTR_ADD(&tbm->out_cnt, pktinfo->pkt_len);
+ return (&tbm->out_action);
+ }
+
+ tbm->tb.token -= len;
+ PKTCNTR_ADD(&tbm->in_cnt, pktinfo->pkt_len);
+ return (&tbm->in_action);
+}
+
+/*
+ * two rate three color marker
+ * as described in draft-heinanen-diffserv-trtcm-01.txt
+ */
+static struct trtcm *
+trtcm_create(top, cmtd_profile, peak_profile,
+ green_action, yellow_action, red_action, coloraware)
+ struct top_cdnr *top;
+ struct tb_profile *cmtd_profile, *peak_profile;
+ struct tc_action *green_action, *yellow_action, *red_action;
+ int coloraware;
+{
+ struct trtcm *tcm = NULL;
+
+ if (tca_verify_action(green_action) < 0
+ || tca_verify_action(yellow_action) < 0
+ || tca_verify_action(red_action) < 0)
+ return (NULL);
+
+ if ((tcm = cdnr_cballoc(top, TCETYPE_TRTCM,
+ trtcm_input)) == NULL)
+ return (NULL);
+
+ tb_import_profile(&tcm->cmtd_tb, cmtd_profile);
+ tb_import_profile(&tcm->peak_tb, peak_profile);
+
+ tca_import_action(&tcm->green_action, green_action);
+ tca_import_action(&tcm->yellow_action, yellow_action);
+ tca_import_action(&tcm->red_action, red_action);
+
+ /* set dscps to use */
+ if (tcm->green_action.tca_code == TCACODE_MARK)
+ tcm->green_dscp = tcm->green_action.tca_dscp & DSCP_MASK;
+ else
+ tcm->green_dscp = DSCP_AF11;
+ if (tcm->yellow_action.tca_code == TCACODE_MARK)
+ tcm->yellow_dscp = tcm->yellow_action.tca_dscp & DSCP_MASK;
+ else
+ tcm->yellow_dscp = DSCP_AF12;
+ if (tcm->red_action.tca_code == TCACODE_MARK)
+ tcm->red_dscp = tcm->red_action.tca_dscp & DSCP_MASK;
+ else
+ tcm->red_dscp = DSCP_AF13;
+
+ tcm->coloraware = coloraware;
+
+ return (tcm);
+}
+
+static int
+trtcm_destroy(tcm)
+ struct trtcm *tcm;
+{
+ if (tcm->cdnrblk.cb_ref > 0)
+ return (EBUSY);
+
+ tca_invalidate_action(&tcm->green_action);
+ tca_invalidate_action(&tcm->yellow_action);
+ tca_invalidate_action(&tcm->red_action);
+
+ cdnr_cbdestroy(tcm);
+ return (0);
+}
+
+static struct tc_action *
+trtcm_input(cb, pktinfo)
+ struct cdnr_block *cb;
+ struct cdnr_pktinfo *pktinfo;
+{
+ struct trtcm *tcm = (struct trtcm *)cb;
+ u_int64_t len;
+ u_int64_t interval, now;
+ u_int8_t color;
+
+ len = TB_SCALE(pktinfo->pkt_len);
+ if (tcm->coloraware) {
+ color = pktinfo->pkt_dscp;
+ if (color != tcm->yellow_dscp && color != tcm->red_dscp)
+ color = tcm->green_dscp;
+ } else {
+ /* if color-blind, precolor it as green */
+ color = tcm->green_dscp;
+ }
+
+ now = read_machclk();
+ if (tcm->cmtd_tb.token < len) {
+ interval = now - tcm->cmtd_tb.last;
+ if (interval >= tcm->cmtd_tb.filluptime)
+ tcm->cmtd_tb.token = tcm->cmtd_tb.depth;
+ else {
+ tcm->cmtd_tb.token += interval * tcm->cmtd_tb.rate;
+ if (tcm->cmtd_tb.token > tcm->cmtd_tb.depth)
+ tcm->cmtd_tb.token = tcm->cmtd_tb.depth;
+ }
+ tcm->cmtd_tb.last = now;
+ }
+ if (tcm->peak_tb.token < len) {
+ interval = now - tcm->peak_tb.last;
+ if (interval >= tcm->peak_tb.filluptime)
+ tcm->peak_tb.token = tcm->peak_tb.depth;
+ else {
+ tcm->peak_tb.token += interval * tcm->peak_tb.rate;
+ if (tcm->peak_tb.token > tcm->peak_tb.depth)
+ tcm->peak_tb.token = tcm->peak_tb.depth;
+ }
+ tcm->peak_tb.last = now;
+ }
+
+ if (color == tcm->red_dscp || tcm->peak_tb.token < len) {
+ pktinfo->pkt_dscp = tcm->red_dscp;
+ PKTCNTR_ADD(&tcm->red_cnt, pktinfo->pkt_len);
+ return (&tcm->red_action);
+ }
+
+ if (color == tcm->yellow_dscp || tcm->cmtd_tb.token < len) {
+ pktinfo->pkt_dscp = tcm->yellow_dscp;
+ tcm->peak_tb.token -= len;
+ PKTCNTR_ADD(&tcm->yellow_cnt, pktinfo->pkt_len);
+ return (&tcm->yellow_action);
+ }
+
+ pktinfo->pkt_dscp = tcm->green_dscp;
+ tcm->cmtd_tb.token -= len;
+ tcm->peak_tb.token -= len;
+ PKTCNTR_ADD(&tcm->green_cnt, pktinfo->pkt_len);
+ return (&tcm->green_action);
+}
+
+/*
+ * time sliding window three color marker
+ * as described in draft-fang-diffserv-tc-tswtcm-00.txt
+ */
+static struct tswtcm *
+tswtcm_create(top, cmtd_rate, peak_rate, avg_interval,
+ green_action, yellow_action, red_action)
+ struct top_cdnr *top;
+ u_int32_t cmtd_rate, peak_rate, avg_interval;
+ struct tc_action *green_action, *yellow_action, *red_action;
+{
+ struct tswtcm *tsw;
+
+ if (tca_verify_action(green_action) < 0
+ || tca_verify_action(yellow_action) < 0
+ || tca_verify_action(red_action) < 0)
+ return (NULL);
+
+ if ((tsw = cdnr_cballoc(top, TCETYPE_TSWTCM,
+ tswtcm_input)) == NULL)
+ return (NULL);
+
+ tca_import_action(&tsw->green_action, green_action);
+ tca_import_action(&tsw->yellow_action, yellow_action);
+ tca_import_action(&tsw->red_action, red_action);
+
+ /* set dscps to use */
+ if (tsw->green_action.tca_code == TCACODE_MARK)
+ tsw->green_dscp = tsw->green_action.tca_dscp & DSCP_MASK;
+ else
+ tsw->green_dscp = DSCP_AF11;
+ if (tsw->yellow_action.tca_code == TCACODE_MARK)
+ tsw->yellow_dscp = tsw->yellow_action.tca_dscp & DSCP_MASK;
+ else
+ tsw->yellow_dscp = DSCP_AF12;
+ if (tsw->red_action.tca_code == TCACODE_MARK)
+ tsw->red_dscp = tsw->red_action.tca_dscp & DSCP_MASK;
+ else
+ tsw->red_dscp = DSCP_AF13;
+
+ /* convert rates from bits/sec to bytes/sec */
+ tsw->cmtd_rate = cmtd_rate / 8;
+ tsw->peak_rate = peak_rate / 8;
+ tsw->avg_rate = 0;
+
+ /* timewin is converted from msec to machine clock unit */
+ tsw->timewin = (u_int64_t)machclk_freq * avg_interval / 1000;
+
+ return (tsw);
+}
+
+static int
+tswtcm_destroy(tsw)
+ struct tswtcm *tsw;
+{
+ if (tsw->cdnrblk.cb_ref > 0)
+ return (EBUSY);
+
+ tca_invalidate_action(&tsw->green_action);
+ tca_invalidate_action(&tsw->yellow_action);
+ tca_invalidate_action(&tsw->red_action);
+
+ cdnr_cbdestroy(tsw);
+ return (0);
+}
+
+static struct tc_action *
+tswtcm_input(cb, pktinfo)
+ struct cdnr_block *cb;
+ struct cdnr_pktinfo *pktinfo;
+{
+ struct tswtcm *tsw = (struct tswtcm *)cb;
+ int len;
+ u_int32_t avg_rate;
+ u_int64_t interval, now, tmp;
+
+ /*
+ * rate estimator
+ */
+ len = pktinfo->pkt_len;
+ now = read_machclk();
+
+ interval = now - tsw->t_front;
+ /*
+ * calculate average rate:
+ * avg = (avg * timewin + pkt_len)/(timewin + interval)
+ * pkt_len needs to be multiplied by machclk_freq in order to
+ * get (bytes/sec).
+ * note: when avg_rate (bytes/sec) and timewin (machclk unit) are
+ * less than 32 bits, the following 64-bit operation has enough
+ * precision.
+ */
+ tmp = ((u_int64_t)tsw->avg_rate * tsw->timewin
+ + (u_int64_t)len * machclk_freq) / (tsw->timewin + interval);
+ tsw->avg_rate = avg_rate = (u_int32_t)tmp;
+ tsw->t_front = now;
+
+ /*
+ * marker
+ */
+ if (avg_rate > tsw->cmtd_rate) {
+ u_int32_t randval = arc4random() % avg_rate;
+
+ if (avg_rate > tsw->peak_rate) {
+ if (randval < avg_rate - tsw->peak_rate) {
+ /* mark red */
+ pktinfo->pkt_dscp = tsw->red_dscp;
+ PKTCNTR_ADD(&tsw->red_cnt, len);
+ return (&tsw->red_action);
+ } else if (randval < avg_rate - tsw->cmtd_rate)
+ goto mark_yellow;
+ } else {
+ /* peak_rate >= avg_rate > cmtd_rate */
+ if (randval < avg_rate - tsw->cmtd_rate) {
+ mark_yellow:
+ pktinfo->pkt_dscp = tsw->yellow_dscp;
+ PKTCNTR_ADD(&tsw->yellow_cnt, len);
+ return (&tsw->yellow_action);
+ }
+ }
+ }
+
+ /* mark green */
+ pktinfo->pkt_dscp = tsw->green_dscp;
+ PKTCNTR_ADD(&tsw->green_cnt, len);
+ return (&tsw->green_action);
+}
+
+/*
+ * ioctl requests
+ */
+static int
+cdnrcmd_if_attach(ifname)
+ char *ifname;
+{
+ struct ifnet *ifp;
+ struct top_cdnr *top;
+
+ if ((ifp = ifunit(ifname)) == NULL)
+ return (EBADF);
+
+ if (ifp->if_snd.altq_cdnr != NULL)
+ return (EBUSY);
+
+ if ((top = top_create(&ifp->if_snd)) == NULL)
+ return (ENOMEM);
+ return (0);
+}
+
+static int
+cdnrcmd_if_detach(ifname)
+ char *ifname;
+{
+ struct top_cdnr *top;
+
+ if ((top = tcb_lookup(ifname)) == NULL)
+ return (EBADF);
+
+ return top_destroy(top);
+}
+
+static int
+cdnrcmd_add_element(ap)
+ struct cdnr_add_element *ap;
+{
+ struct top_cdnr *top;
+ struct cdnr_block *cb;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ cb = element_create(top, &ap->action);
+ if (cb == NULL)
+ return (EINVAL);
+ /* return a class handle to the user */
+ ap->cdnr_handle = cdnr_cb2handle(cb);
+ return (0);
+}
+
+static int
+cdnrcmd_delete_element(ap)
+ struct cdnr_delete_element *ap;
+{
+ struct top_cdnr *top;
+ struct cdnr_block *cb;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ if ((cb = cdnr_handle2cb(ap->cdnr_handle)) == NULL)
+ return (EINVAL);
+
+ if (cb->cb_type != TCETYPE_ELEMENT)
+ return generic_element_destroy(cb);
+
+ return element_destroy(cb);
+}
+
+static int
+cdnrcmd_add_filter(ap)
+ struct cdnr_add_filter *ap;
+{
+ struct top_cdnr *top;
+ struct cdnr_block *cb;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ if ((cb = cdnr_handle2cb(ap->cdnr_handle)) == NULL)
+ return (EINVAL);
+
+ return acc_add_filter(&top->tc_classifier, &ap->filter,
+ cb, &ap->filter_handle);
+}
+
+static int
+cdnrcmd_delete_filter(ap)
+ struct cdnr_delete_filter *ap;
+{
+ struct top_cdnr *top;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ return acc_delete_filter(&top->tc_classifier, ap->filter_handle);
+}
+
+static int
+cdnrcmd_add_tbm(ap)
+ struct cdnr_add_tbmeter *ap;
+{
+ struct top_cdnr *top;
+ struct tbmeter *tbm;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ tbm = tbm_create(top, &ap->profile, &ap->in_action, &ap->out_action);
+ if (tbm == NULL)
+ return (EINVAL);
+ /* return a class handle to the user */
+ ap->cdnr_handle = cdnr_cb2handle(&tbm->cdnrblk);
+ return (0);
+}
+
+static int
+cdnrcmd_modify_tbm(ap)
+ struct cdnr_modify_tbmeter *ap;
+{
+ struct tbmeter *tbm;
+
+ if ((tbm = (struct tbmeter *)cdnr_handle2cb(ap->cdnr_handle)) == NULL)
+ return (EINVAL);
+
+ tb_import_profile(&tbm->tb, &ap->profile);
+
+ return (0);
+}
+
+static int
+cdnrcmd_tbm_stats(ap)
+ struct cdnr_tbmeter_stats *ap;
+{
+ struct tbmeter *tbm;
+
+ if ((tbm = (struct tbmeter *)cdnr_handle2cb(ap->cdnr_handle)) == NULL)
+ return (EINVAL);
+
+ ap->in_cnt = tbm->in_cnt;
+ ap->out_cnt = tbm->out_cnt;
+
+ return (0);
+}
+
+static int
+cdnrcmd_add_trtcm(ap)
+ struct cdnr_add_trtcm *ap;
+{
+ struct top_cdnr *top;
+ struct trtcm *tcm;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ tcm = trtcm_create(top, &ap->cmtd_profile, &ap->peak_profile,
+ &ap->green_action, &ap->yellow_action,
+ &ap->red_action, ap->coloraware);
+ if (tcm == NULL)
+ return (EINVAL);
+
+ /* return a class handle to the user */
+ ap->cdnr_handle = cdnr_cb2handle(&tcm->cdnrblk);
+ return (0);
+}
+
+static int
+cdnrcmd_modify_trtcm(ap)
+ struct cdnr_modify_trtcm *ap;
+{
+ struct trtcm *tcm;
+
+ if ((tcm = (struct trtcm *)cdnr_handle2cb(ap->cdnr_handle)) == NULL)
+ return (EINVAL);
+
+ tb_import_profile(&tcm->cmtd_tb, &ap->cmtd_profile);
+ tb_import_profile(&tcm->peak_tb, &ap->peak_profile);
+
+ return (0);
+}
+
+static int
+cdnrcmd_tcm_stats(ap)
+ struct cdnr_tcm_stats *ap;
+{
+ struct cdnr_block *cb;
+
+ if ((cb = cdnr_handle2cb(ap->cdnr_handle)) == NULL)
+ return (EINVAL);
+
+ if (cb->cb_type == TCETYPE_TRTCM) {
+ struct trtcm *tcm = (struct trtcm *)cb;
+
+ ap->green_cnt = tcm->green_cnt;
+ ap->yellow_cnt = tcm->yellow_cnt;
+ ap->red_cnt = tcm->red_cnt;
+ } else if (cb->cb_type == TCETYPE_TSWTCM) {
+ struct tswtcm *tsw = (struct tswtcm *)cb;
+
+ ap->green_cnt = tsw->green_cnt;
+ ap->yellow_cnt = tsw->yellow_cnt;
+ ap->red_cnt = tsw->red_cnt;
+ } else
+ return (EINVAL);
+
+ return (0);
+}
+
+static int
+cdnrcmd_add_tswtcm(ap)
+ struct cdnr_add_tswtcm *ap;
+{
+ struct top_cdnr *top;
+ struct tswtcm *tsw;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ if (ap->cmtd_rate > ap->peak_rate)
+ return (EINVAL);
+
+ tsw = tswtcm_create(top, ap->cmtd_rate, ap->peak_rate,
+ ap->avg_interval, &ap->green_action,
+ &ap->yellow_action, &ap->red_action);
+ if (tsw == NULL)
+ return (EINVAL);
+
+ /* return a class handle to the user */
+ ap->cdnr_handle = cdnr_cb2handle(&tsw->cdnrblk);
+ return (0);
+}
+
+static int
+cdnrcmd_modify_tswtcm(ap)
+ struct cdnr_modify_tswtcm *ap;
+{
+ struct tswtcm *tsw;
+
+ if ((tsw = (struct tswtcm *)cdnr_handle2cb(ap->cdnr_handle)) == NULL)
+ return (EINVAL);
+
+ if (ap->cmtd_rate > ap->peak_rate)
+ return (EINVAL);
+
+ /* convert rates from bits/sec to bytes/sec */
+ tsw->cmtd_rate = ap->cmtd_rate / 8;
+ tsw->peak_rate = ap->peak_rate / 8;
+ tsw->avg_rate = 0;
+
+ /* timewin is converted from msec to machine clock unit */
+ tsw->timewin = (u_int64_t)machclk_freq * ap->avg_interval / 1000;
+
+ return (0);
+}
+
+static int
+cdnrcmd_get_stats(ap)
+ struct cdnr_get_stats *ap;
+{
+ struct top_cdnr *top;
+ struct cdnr_block *cb;
+ struct tbmeter *tbm;
+ struct trtcm *tcm;
+ struct tswtcm *tsw;
+ struct tce_stats tce, *usp;
+ int error, n, nskip, nelements;
+
+ if ((top = tcb_lookup(ap->iface.cdnr_ifname)) == NULL)
+ return (EBADF);
+
+ /* copy action stats */
+ bcopy(top->tc_cnts, ap->cnts, sizeof(ap->cnts));
+
+ /* stats for each element */
+ nelements = ap->nelements;
+ usp = ap->tce_stats;
+ if (nelements <= 0 || usp == NULL)
+ return (0);
+
+ nskip = ap->nskip;
+ n = 0;
+ LIST_FOREACH(cb, &top->tc_elements, cb_next) {
+ if (nskip > 0) {
+ nskip--;
+ continue;
+ }
+
+ bzero(&tce, sizeof(tce));
+ tce.tce_handle = cb->cb_handle;
+ tce.tce_type = cb->cb_type;
+ switch (cb->cb_type) {
+ case TCETYPE_TBMETER:
+ tbm = (struct tbmeter *)cb;
+ tce.tce_cnts[0] = tbm->in_cnt;
+ tce.tce_cnts[1] = tbm->out_cnt;
+ break;
+ case TCETYPE_TRTCM:
+ tcm = (struct trtcm *)cb;
+ tce.tce_cnts[0] = tcm->green_cnt;
+ tce.tce_cnts[1] = tcm->yellow_cnt;
+ tce.tce_cnts[2] = tcm->red_cnt;
+ break;
+ case TCETYPE_TSWTCM:
+ tsw = (struct tswtcm *)cb;
+ tce.tce_cnts[0] = tsw->green_cnt;
+ tce.tce_cnts[1] = tsw->yellow_cnt;
+ tce.tce_cnts[2] = tsw->red_cnt;
+ break;
+ default:
+ continue;
+ }
+
+ if ((error = copyout((caddr_t)&tce, (caddr_t)usp++,
+ sizeof(tce))) != 0)
+ return (error);
+
+ if (++n == nelements)
+ break;
+ }
+ ap->nelements = n;
+
+ return (0);
+}
+
+/*
+ * conditioner device interface
+ */
+int
+cdnropen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ if (machclk_freq == 0)
+ init_machclk();
+
+ if (machclk_freq == 0) {
+ printf("cdnr: no cpu clock available!\n");
+ return (ENXIO);
+ }
+
+ /* everything will be done when the queueing scheme is attached. */
+ return 0;
+}
+
+int
+cdnrclose(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ struct top_cdnr *top;
+ int err, error = 0;
+
+ while ((top = LIST_FIRST(&tcb_list)) != NULL) {
+ /* destroy all */
+ err = top_destroy(top);
+ if (err != 0 && error == 0)
+ error = err;
+ }
+ altq_input = NULL;
+
+ return (error);
+}
+
+int
+cdnrioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ ioctlcmd_t cmd;
+ caddr_t addr;
+ int flag;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ struct top_cdnr *top;
+ struct cdnr_interface *ifacep;
+ int s, error = 0;
+
+ /* check super-user privilege */
+ switch (cmd) {
+ case CDNR_GETSTATS:
+ break;
+ default:
+#if (__FreeBSD_version > 700000)
+ if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+#elsif (__FreeBSD_version > 400000)
+ if ((error = suser(p)) != 0)
+#else
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+#endif
+ return (error);
+ break;
+ }
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ switch (cmd) {
+
+ case CDNR_IF_ATTACH:
+ ifacep = (struct cdnr_interface *)addr;
+ error = cdnrcmd_if_attach(ifacep->cdnr_ifname);
+ break;
+
+ case CDNR_IF_DETACH:
+ ifacep = (struct cdnr_interface *)addr;
+ error = cdnrcmd_if_detach(ifacep->cdnr_ifname);
+ break;
+
+ case CDNR_ENABLE:
+ case CDNR_DISABLE:
+ ifacep = (struct cdnr_interface *)addr;
+ if ((top = tcb_lookup(ifacep->cdnr_ifname)) == NULL) {
+ error = EBADF;
+ break;
+ }
+
+ switch (cmd) {
+
+ case CDNR_ENABLE:
+ ALTQ_SET_CNDTNING(top->tc_ifq);
+ if (altq_input == NULL)
+ altq_input = altq_cdnr_input;
+ break;
+
+ case CDNR_DISABLE:
+ ALTQ_CLEAR_CNDTNING(top->tc_ifq);
+ LIST_FOREACH(top, &tcb_list, tc_next)
+ if (ALTQ_IS_CNDTNING(top->tc_ifq))
+ break;
+ if (top == NULL)
+ altq_input = NULL;
+ break;
+ }
+ break;
+
+ case CDNR_ADD_ELEM:
+ error = cdnrcmd_add_element((struct cdnr_add_element *)addr);
+ break;
+
+ case CDNR_DEL_ELEM:
+ error = cdnrcmd_delete_element((struct cdnr_delete_element *)addr);
+ break;
+
+ case CDNR_ADD_TBM:
+ error = cdnrcmd_add_tbm((struct cdnr_add_tbmeter *)addr);
+ break;
+
+ case CDNR_MOD_TBM:
+ error = cdnrcmd_modify_tbm((struct cdnr_modify_tbmeter *)addr);
+ break;
+
+ case CDNR_TBM_STATS:
+ error = cdnrcmd_tbm_stats((struct cdnr_tbmeter_stats *)addr);
+ break;
+
+ case CDNR_ADD_TCM:
+ error = cdnrcmd_add_trtcm((struct cdnr_add_trtcm *)addr);
+ break;
+
+ case CDNR_MOD_TCM:
+ error = cdnrcmd_modify_trtcm((struct cdnr_modify_trtcm *)addr);
+ break;
+
+ case CDNR_TCM_STATS:
+ error = cdnrcmd_tcm_stats((struct cdnr_tcm_stats *)addr);
+ break;
+
+ case CDNR_ADD_FILTER:
+ error = cdnrcmd_add_filter((struct cdnr_add_filter *)addr);
+ break;
+
+ case CDNR_DEL_FILTER:
+ error = cdnrcmd_delete_filter((struct cdnr_delete_filter *)addr);
+ break;
+
+ case CDNR_GETSTATS:
+ error = cdnrcmd_get_stats((struct cdnr_get_stats *)addr);
+ break;
+
+ case CDNR_ADD_TSW:
+ error = cdnrcmd_add_tswtcm((struct cdnr_add_tswtcm *)addr);
+ break;
+
+ case CDNR_MOD_TSW:
+ error = cdnrcmd_modify_tswtcm((struct cdnr_modify_tswtcm *)addr);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ splx(s);
+
+ return error;
+}
+
+#ifdef KLD_MODULE
+
+static struct altqsw cdnr_sw =
+ {"cdnr", cdnropen, cdnrclose, cdnrioctl};
+
+ALTQ_MODULE(altq_cdnr, ALTQT_CDNR, &cdnr_sw);
+
+#endif /* KLD_MODULE */
+
+#endif /* ALTQ3_COMPAT */
+#endif /* ALTQ_CDNR */
diff --git a/freebsd/sys/contrib/altq/altq/altq_cdnr.h b/freebsd/sys/contrib/altq/altq/altq_cdnr.h
new file mode 100644
index 00000000..b765833f
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_cdnr.h
@@ -0,0 +1,335 @@
+/* $KAME: altq_cdnr.h,v 1.9 2003/07/10 12:07:48 kjc Exp $ */
+
+/*
+ * Copyright (C) 1999-2002
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 _ALTQ_ALTQ_CDNR_HH_
+#define _ALTQ_ALTQ_CDNR_HH_
+
+#include <freebsd/altq/altq.h>
+
+/*
+ * traffic conditioner element types
+ */
+#define TCETYPE_NONE 0
+#define TCETYPE_TOP 1 /* top level conditioner */
+#define TCETYPE_ELEMENT 2 /* a simple tc element */
+#define TCETYPE_TBMETER 3 /* token bucket meter */
+#define TCETYPE_TRTCM 4 /* (two-rate) three color marker */
+#define TCETYPE_TSWTCM 5 /* time sliding window 3-color maker */
+
+/*
+ * traffic conditioner action
+ */
+struct cdnr_block;
+
+struct tc_action {
+ int tca_code; /* e.g., TCACODE_PASS */
+ /* tca_code dependent variable */
+ union {
+ u_long un_value; /* template */
+ u_int8_t un_dscp; /* diffserv code point */
+ u_long un_handle; /* tc action handle */
+ struct cdnr_block *un_next; /* next tc element block */
+ } tca_un;
+};
+#define tca_value tca_un.un_value
+#define tca_dscp tca_un.un_dscp
+#define tca_handle tca_un.un_handle
+#define tca_next tca_un.un_next
+
+#define TCACODE_NONE 0 /* action is not set */
+#define TCACODE_PASS 1 /* pass this packet */
+#define TCACODE_DROP 2 /* discard this packet */
+#define TCACODE_RETURN 3 /* do not process this packet */
+#define TCACODE_MARK 4 /* mark dscp */
+#define TCACODE_HANDLE 5 /* take action specified by handle */
+#define TCACODE_NEXT 6 /* take action in the next tc element */
+#define TCACODE_MAX 6
+
+#define CDNR_NULL_HANDLE 0
+
+struct cdnr_interface {
+ char cdnr_ifname[IFNAMSIZ]; /* interface name (e.g., fxp0) */
+};
+
+/* simple element operations */
+struct cdnr_add_element {
+ struct cdnr_interface iface;
+ struct tc_action action;
+
+ u_long cdnr_handle; /* return value */
+};
+
+struct cdnr_delete_element {
+ struct cdnr_interface iface;
+ u_long cdnr_handle;
+};
+
+/* token-bucket meter operations */
+struct cdnr_add_tbmeter {
+ struct cdnr_interface iface;
+ struct tb_profile profile;
+ struct tc_action in_action;
+ struct tc_action out_action;
+
+ u_long cdnr_handle; /* return value */
+};
+
+struct cdnr_modify_tbmeter {
+ struct cdnr_interface iface;
+ u_long cdnr_handle;
+ struct tb_profile profile;
+};
+
+struct cdnr_tbmeter_stats {
+ struct cdnr_interface iface;
+ u_long cdnr_handle;
+ struct pktcntr in_cnt;
+ struct pktcntr out_cnt;
+};
+
+/* two-rate three-color marker operations */
+struct cdnr_add_trtcm {
+ struct cdnr_interface iface;
+ struct tb_profile cmtd_profile; /* profile for committed tb */
+ struct tb_profile peak_profile; /* profile for peak tb */
+ struct tc_action green_action; /* action for green packets */
+ struct tc_action yellow_action; /* action for yellow packets */
+ struct tc_action red_action; /* action for red packets */
+ int coloraware; /* color-aware/color-blind */
+
+ u_long cdnr_handle; /* return value */
+};
+
+struct cdnr_modify_trtcm {
+ struct cdnr_interface iface;
+ u_long cdnr_handle;
+ struct tb_profile cmtd_profile; /* profile for committed tb */
+ struct tb_profile peak_profile; /* profile for peak tb */
+ int coloraware; /* color-aware/color-blind */
+};
+
+struct cdnr_tcm_stats {
+ struct cdnr_interface iface;
+ u_long cdnr_handle;
+ struct pktcntr green_cnt;
+ struct pktcntr yellow_cnt;
+ struct pktcntr red_cnt;
+};
+
+/* time sliding window three-color marker operations */
+struct cdnr_add_tswtcm {
+ struct cdnr_interface iface;
+ u_int32_t cmtd_rate; /* committed rate (bits/sec) */
+ u_int32_t peak_rate; /* peak rate (bits/sec) */
+ u_int32_t avg_interval; /* averaging interval (msec) */
+ struct tc_action green_action; /* action for green packets */
+ struct tc_action yellow_action; /* action for yellow packets */
+ struct tc_action red_action; /* action for red packets */
+
+ u_long cdnr_handle; /* return value */
+};
+
+struct cdnr_modify_tswtcm {
+ struct cdnr_interface iface;
+ u_long cdnr_handle;
+ u_int32_t cmtd_rate; /* committed rate (bits/sec) */
+ u_int32_t peak_rate; /* peak rate (bits/sec) */
+ u_int32_t avg_interval; /* averaging interval (msec) */
+};
+
+struct cdnr_add_filter {
+ struct cdnr_interface iface;
+ u_long cdnr_handle;
+#ifdef ALTQ3_CLFIER_COMPAT
+ struct flow_filter filter;
+#endif
+ u_long filter_handle; /* return value */
+};
+
+struct cdnr_delete_filter {
+ struct cdnr_interface iface;
+ u_long filter_handle;
+};
+
+struct tce_stats {
+ u_long tce_handle; /* tc element handle */
+ int tce_type; /* e.g., TCETYPE_ELEMENT */
+ struct pktcntr tce_cnts[3]; /* tcm returns 3 counters */
+};
+
+struct cdnr_get_stats {
+ struct cdnr_interface iface;
+ struct pktcntr cnts[TCACODE_MAX+1];
+
+ /* element stats */
+ int nskip; /* skip # of elements */
+ int nelements; /* # of element stats (WR) */
+ struct tce_stats *tce_stats; /* pointer to stats array */
+};
+
+#define CDNR_IF_ATTACH _IOW('Q', 1, struct cdnr_interface)
+#define CDNR_IF_DETACH _IOW('Q', 2, struct cdnr_interface)
+#define CDNR_ENABLE _IOW('Q', 3, struct cdnr_interface)
+#define CDNR_DISABLE _IOW('Q', 4, struct cdnr_interface)
+#define CDNR_ADD_FILTER _IOWR('Q', 10, struct cdnr_add_filter)
+#define CDNR_DEL_FILTER _IOW('Q', 11, struct cdnr_delete_filter)
+#define CDNR_GETSTATS _IOWR('Q', 12, struct cdnr_get_stats)
+#define CDNR_ADD_ELEM _IOWR('Q', 30, struct cdnr_add_element)
+#define CDNR_DEL_ELEM _IOW('Q', 31, struct cdnr_delete_element)
+#define CDNR_ADD_TBM _IOWR('Q', 32, struct cdnr_add_tbmeter)
+#define CDNR_MOD_TBM _IOW('Q', 33, struct cdnr_modify_tbmeter)
+#define CDNR_TBM_STATS _IOWR('Q', 34, struct cdnr_tbmeter_stats)
+#define CDNR_ADD_TCM _IOWR('Q', 35, struct cdnr_add_trtcm)
+#define CDNR_MOD_TCM _IOWR('Q', 36, struct cdnr_modify_trtcm)
+#define CDNR_TCM_STATS _IOWR('Q', 37, struct cdnr_tcm_stats)
+#define CDNR_ADD_TSW _IOWR('Q', 38, struct cdnr_add_tswtcm)
+#define CDNR_MOD_TSW _IOWR('Q', 39, struct cdnr_modify_tswtcm)
+
+#ifndef DSCP_EF
+/* diffserve code points */
+#define DSCP_MASK 0xfc
+#define DSCP_CUMASK 0x03
+#define DSCP_EF 0xb8
+#define DSCP_AF11 0x28
+#define DSCP_AF12 0x30
+#define DSCP_AF13 0x38
+#define DSCP_AF21 0x48
+#define DSCP_AF22 0x50
+#define DSCP_AF23 0x58
+#define DSCP_AF31 0x68
+#define DSCP_AF32 0x70
+#define DSCP_AF33 0x78
+#define DSCP_AF41 0x88
+#define DSCP_AF42 0x90
+#define DSCP_AF43 0x98
+#define AF_CLASSMASK 0xe0
+#define AF_DROPPRECMASK 0x18
+#endif
+
+#ifdef _KERNEL
+
+/*
+ * packet information passed to the input function of tc elements
+ */
+struct cdnr_pktinfo {
+ int pkt_len; /* packet length */
+ u_int8_t pkt_dscp; /* diffserv code point */
+};
+
+/*
+ * traffic conditioner control block common to all types of tc elements
+ */
+struct cdnr_block {
+ LIST_ENTRY(cdnr_block) cb_next;
+ int cb_len; /* size of this tc element */
+ int cb_type; /* cdnr block type */
+ int cb_ref; /* reference count of this element */
+ u_long cb_handle; /* handle of this tc element */
+ struct top_cdnr *cb_top; /* back pointer to top */
+ struct tc_action cb_action; /* top level action for this tcb */
+ struct tc_action *(*cb_input)(struct cdnr_block *,
+ struct cdnr_pktinfo *);
+};
+
+/*
+ * top level traffic conditioner structure for an interface
+ */
+struct top_cdnr {
+ struct cdnr_block tc_block;
+
+ LIST_ENTRY(top_cdnr) tc_next;
+ struct ifaltq *tc_ifq;
+
+ LIST_HEAD(, cdnr_block) tc_elements;
+#ifdef ALTQ3_CLFIER_COMPAT
+ struct acc_classifier tc_classifier;
+#endif
+ struct pktcntr tc_cnts[TCACODE_MAX+1];
+};
+
+/* token bucket element */
+struct tbe {
+ u_int64_t rate;
+ u_int64_t depth;
+
+ u_int64_t token;
+ u_int64_t filluptime;
+ u_int64_t last;
+};
+
+/* token bucket meter structure */
+struct tbmeter {
+ struct cdnr_block cdnrblk; /* conditioner block */
+ struct tbe tb; /* token bucket */
+ struct tc_action in_action; /* actions for IN/OUT */
+ struct tc_action out_action; /* actions for IN/OUT */
+ struct pktcntr in_cnt; /* statistics for IN/OUT */
+ struct pktcntr out_cnt; /* statistics for IN/OUT */
+};
+
+/* two-rate three-color marker structure */
+struct trtcm {
+ struct cdnr_block cdnrblk; /* conditioner block */
+ struct tbe cmtd_tb; /* committed tb profile */
+ struct tbe peak_tb; /* peak tb profile */
+ struct tc_action green_action;
+ struct tc_action yellow_action;
+ struct tc_action red_action;
+ int coloraware;
+ u_int8_t green_dscp;
+ u_int8_t yellow_dscp;
+ u_int8_t red_dscp;
+ struct pktcntr green_cnt;
+ struct pktcntr yellow_cnt;
+ struct pktcntr red_cnt;
+};
+
+/* time sliding window three-color marker structure */
+struct tswtcm {
+ struct cdnr_block cdnrblk; /* conditioner block */
+
+ u_int32_t avg_rate; /* average rate (bytes/sec) */
+ u_int64_t t_front; /* timestamp of last update */
+
+ u_int64_t timewin; /* average interval */
+ u_int32_t cmtd_rate; /* committed target rate */
+ u_int32_t peak_rate; /* peak target rate */
+ struct tc_action green_action;
+ struct tc_action yellow_action;
+ struct tc_action red_action;
+ u_int8_t green_dscp;
+ u_int8_t yellow_dscp;
+ u_int8_t red_dscp;
+ struct pktcntr green_cnt;
+ struct pktcntr yellow_cnt;
+ struct pktcntr red_cnt;
+};
+
+#endif /* _KERNEL */
+
+#endif /* _ALTQ_ALTQ_CDNR_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_classq.h b/freebsd/sys/contrib/altq/altq/altq_classq.h
new file mode 100644
index 00000000..c3cfea37
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_classq.h
@@ -0,0 +1,206 @@
+/* $KAME: altq_classq.h,v 1.6 2003/01/07 07:33:38 kjc Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 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 Network Research
+ * 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.
+ */
+/*
+ * class queue definitions extracted from rm_class.h.
+ */
+#ifndef _ALTQ_ALTQ_CLASSQ_HH_
+#define _ALTQ_ALTQ_CLASSQ_HH_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Packet Queue types: RED or DROPHEAD.
+ */
+#define Q_DROPHEAD 0x00
+#define Q_RED 0x01
+#define Q_RIO 0x02
+#define Q_DROPTAIL 0x03
+
+#ifdef _KERNEL
+
+/*
+ * Packet Queue structures and macros to manipulate them.
+ */
+struct _class_queue_ {
+ struct mbuf *tail_; /* Tail of packet queue */
+ int qlen_; /* Queue length (in number of packets) */
+ int qlim_; /* Queue limit (in number of packets*) */
+ int qtype_; /* Queue type */
+};
+
+typedef struct _class_queue_ class_queue_t;
+
+#define qtype(q) (q)->qtype_ /* Get queue type */
+#define qlimit(q) (q)->qlim_ /* Max packets to be queued */
+#define qlen(q) (q)->qlen_ /* Current queue length. */
+#define qtail(q) (q)->tail_ /* Tail of the queue */
+#define qhead(q) ((q)->tail_ ? (q)->tail_->m_nextpkt : NULL)
+
+#define qempty(q) ((q)->qlen_ == 0) /* Is the queue empty?? */
+#define q_is_red(q) ((q)->qtype_ == Q_RED) /* Is the queue a red queue */
+#define q_is_rio(q) ((q)->qtype_ == Q_RIO) /* Is the queue a rio queue */
+#define q_is_red_or_rio(q) ((q)->qtype_ == Q_RED || (q)->qtype_ == Q_RIO)
+
+#if !defined(__GNUC__) || defined(ALTQ_DEBUG)
+
+extern void _addq(class_queue_t *, struct mbuf *);
+extern struct mbuf *_getq(class_queue_t *);
+extern struct mbuf *_getq_tail(class_queue_t *);
+extern struct mbuf *_getq_random(class_queue_t *);
+extern void _removeq(class_queue_t *, struct mbuf *);
+extern void _flushq(class_queue_t *);
+
+#else /* __GNUC__ && !ALTQ_DEBUG */
+/*
+ * inlined versions
+ */
+static __inline void
+_addq(class_queue_t *q, struct mbuf *m)
+{
+ struct mbuf *m0;
+
+ if ((m0 = qtail(q)) != NULL)
+ m->m_nextpkt = m0->m_nextpkt;
+ else
+ m0 = m;
+ m0->m_nextpkt = m;
+ qtail(q) = m;
+ qlen(q)++;
+}
+
+static __inline struct mbuf *
+_getq(class_queue_t *q)
+{
+ struct mbuf *m, *m0;
+
+ if ((m = qtail(q)) == NULL)
+ return (NULL);
+ if ((m0 = m->m_nextpkt) != m)
+ m->m_nextpkt = m0->m_nextpkt;
+ else
+ qtail(q) = NULL;
+ qlen(q)--;
+ m0->m_nextpkt = NULL;
+ return (m0);
+}
+
+/* drop a packet at the tail of the queue */
+static __inline struct mbuf *
+_getq_tail(class_queue_t *q)
+{
+ struct mbuf *m, *m0, *prev;
+
+ if ((m = m0 = qtail(q)) == NULL)
+ return NULL;
+ do {
+ prev = m0;
+ m0 = m0->m_nextpkt;
+ } while (m0 != m);
+ prev->m_nextpkt = m->m_nextpkt;
+ if (prev == m)
+ qtail(q) = NULL;
+ else
+ qtail(q) = prev;
+ qlen(q)--;
+ m->m_nextpkt = NULL;
+ return (m);
+}
+
+/* randomly select a packet in the queue */
+static __inline struct mbuf *
+_getq_random(class_queue_t *q)
+{
+ struct mbuf *m;
+ int i, n;
+
+ if ((m = qtail(q)) == NULL)
+ return NULL;
+ if (m->m_nextpkt == m)
+ qtail(q) = NULL;
+ else {
+ struct mbuf *prev = NULL;
+
+ n = random() % qlen(q) + 1;
+ for (i = 0; i < n; i++) {
+ prev = m;
+ m = m->m_nextpkt;
+ }
+ prev->m_nextpkt = m->m_nextpkt;
+ if (m == qtail(q))
+ qtail(q) = prev;
+ }
+ qlen(q)--;
+ m->m_nextpkt = NULL;
+ return (m);
+}
+
+static __inline void
+_removeq(class_queue_t *q, struct mbuf *m)
+{
+ struct mbuf *m0, *prev;
+
+ m0 = qtail(q);
+ do {
+ prev = m0;
+ m0 = m0->m_nextpkt;
+ } while (m0 != m);
+ prev->m_nextpkt = m->m_nextpkt;
+ if (prev == m)
+ qtail(q) = NULL;
+ else if (qtail(q) == m)
+ qtail(q) = prev;
+ qlen(q)--;
+}
+
+static __inline void
+_flushq(class_queue_t *q)
+{
+ struct mbuf *m;
+
+ while ((m = _getq(q)) != NULL)
+ m_freem(m);
+}
+
+#endif /* __GNUC__ && !ALTQ_DEBUG */
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ALTQ_ALTQ_CLASSQ_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_hfsc.c b/freebsd/sys/contrib/altq/altq/altq_hfsc.c
new file mode 100644
index 00000000..a559f006
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_hfsc.c
@@ -0,0 +1,2279 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_hfsc.c,v 1.24 2003/12/05 05:40:46 kjc Exp $ */
+
+/*
+ * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation is hereby granted (including for commercial or
+ * for-profit use), provided that both the copyright notice and this
+ * permission notice appear in all copies of the software, derivative
+ * works, or modified versions, and any portions thereof.
+ *
+ * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF
+ * WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS
+ * SOFTWARE IN ITS ``AS IS'' CONDITION, 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 CARNEGIE MELLON UNIVERSITY 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.
+ *
+ * Carnegie Mellon encourages (but does not require) users of this
+ * software to return any improvements or extensions that they make,
+ * and to grant Carnegie Mellon the rights to redistribute these
+ * changes without encumbrance.
+ */
+/*
+ * H-FSC is described in Proceedings of SIGCOMM'97,
+ * "A Hierarchical Fair Service Curve Algorithm for Link-Sharing,
+ * Real-Time and Priority Service"
+ * by Ion Stoica, Hui Zhang, and T. S. Eugene Ng.
+ *
+ * Oleg Cherevko <olwi@aq.ml.com.ua> added the upperlimit for link-sharing.
+ * when a class has an upperlimit, the fit-time is computed from the
+ * upperlimit service curve. the link-sharing scheduler does not schedule
+ * a class whose fit-time exceeds the current time.
+ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#if (__FreeBSD__ != 2)
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+
+#ifdef ALTQ_HFSC /* hfsc is enabled by ALTQ_HFSC option in opt_altq.h */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/errno.h>
+#include <freebsd/sys/queue.h>
+#if 1 /* ALTQ3_COMPAT */
+#include <freebsd/sys/sockio.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/kernel.h>
+#endif /* ALTQ3_COMPAT */
+
+#include <freebsd/net/if.h>
+#include <freebsd/netinet/in.h>
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_hfsc.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/altq/altq_conf.h>
+#endif
+
+/*
+ * function prototypes
+ */
+static int hfsc_clear_interface(struct hfsc_if *);
+static int hfsc_request(struct ifaltq *, int, void *);
+static void hfsc_purge(struct hfsc_if *);
+static struct hfsc_class *hfsc_class_create(struct hfsc_if *,
+ struct service_curve *, struct service_curve *, struct service_curve *,
+ struct hfsc_class *, int, int, int);
+static int hfsc_class_destroy(struct hfsc_class *);
+static struct hfsc_class *hfsc_nextclass(struct hfsc_class *);
+static int hfsc_enqueue(struct ifaltq *, struct mbuf *,
+ struct altq_pktattr *);
+static struct mbuf *hfsc_dequeue(struct ifaltq *, int);
+
+static int hfsc_addq(struct hfsc_class *, struct mbuf *);
+static struct mbuf *hfsc_getq(struct hfsc_class *);
+static struct mbuf *hfsc_pollq(struct hfsc_class *);
+static void hfsc_purgeq(struct hfsc_class *);
+
+static void update_cfmin(struct hfsc_class *);
+static void set_active(struct hfsc_class *, int);
+static void set_passive(struct hfsc_class *);
+
+static void init_ed(struct hfsc_class *, int);
+static void update_ed(struct hfsc_class *, int);
+static void update_d(struct hfsc_class *, int);
+static void init_vf(struct hfsc_class *, int);
+static void update_vf(struct hfsc_class *, int, u_int64_t);
+static ellist_t *ellist_alloc(void);
+static void ellist_destroy(ellist_t *);
+static void ellist_insert(struct hfsc_class *);
+static void ellist_remove(struct hfsc_class *);
+static void ellist_update(struct hfsc_class *);
+struct hfsc_class *ellist_get_mindl(ellist_t *, u_int64_t);
+static actlist_t *actlist_alloc(void);
+static void actlist_destroy(actlist_t *);
+static void actlist_insert(struct hfsc_class *);
+static void actlist_remove(struct hfsc_class *);
+static void actlist_update(struct hfsc_class *);
+
+static struct hfsc_class *actlist_firstfit(struct hfsc_class *,
+ u_int64_t);
+
+static __inline u_int64_t seg_x2y(u_int64_t, u_int64_t);
+static __inline u_int64_t seg_y2x(u_int64_t, u_int64_t);
+static __inline u_int64_t m2sm(u_int);
+static __inline u_int64_t m2ism(u_int);
+static __inline u_int64_t d2dx(u_int);
+static u_int sm2m(u_int64_t);
+static u_int dx2d(u_int64_t);
+
+static void sc2isc(struct service_curve *, struct internal_sc *);
+static void rtsc_init(struct runtime_sc *, struct internal_sc *,
+ u_int64_t, u_int64_t);
+static u_int64_t rtsc_y2x(struct runtime_sc *, u_int64_t);
+static u_int64_t rtsc_x2y(struct runtime_sc *, u_int64_t);
+static void rtsc_min(struct runtime_sc *, struct internal_sc *,
+ u_int64_t, u_int64_t);
+
+static void get_class_stats(struct hfsc_classstats *,
+ struct hfsc_class *);
+static struct hfsc_class *clh_to_clp(struct hfsc_if *, u_int32_t);
+
+
+#ifdef ALTQ3_COMPAT
+static struct hfsc_if *hfsc_attach(struct ifaltq *, u_int);
+static int hfsc_detach(struct hfsc_if *);
+static int hfsc_class_modify(struct hfsc_class *, struct service_curve *,
+ struct service_curve *, struct service_curve *);
+
+static int hfsccmd_if_attach(struct hfsc_attach *);
+static int hfsccmd_if_detach(struct hfsc_interface *);
+static int hfsccmd_add_class(struct hfsc_add_class *);
+static int hfsccmd_delete_class(struct hfsc_delete_class *);
+static int hfsccmd_modify_class(struct hfsc_modify_class *);
+static int hfsccmd_add_filter(struct hfsc_add_filter *);
+static int hfsccmd_delete_filter(struct hfsc_delete_filter *);
+static int hfsccmd_class_stats(struct hfsc_class_stats *);
+
+altqdev_decl(hfsc);
+#endif /* ALTQ3_COMPAT */
+
+/*
+ * macros
+ */
+#define is_a_parent_class(cl) ((cl)->cl_children != NULL)
+
+#define HT_INFINITY 0xffffffffffffffffLL /* infinite time value */
+
+#ifdef ALTQ3_COMPAT
+/* hif_list keeps all hfsc_if's allocated. */
+static struct hfsc_if *hif_list = NULL;
+#endif /* ALTQ3_COMPAT */
+
+int
+hfsc_pfattach(struct pf_altq *a)
+{
+ struct ifnet *ifp;
+ int s, error;
+
+ if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL)
+ return (EINVAL);
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ error = altq_attach(&ifp->if_snd, ALTQT_HFSC, a->altq_disc,
+ hfsc_enqueue, hfsc_dequeue, hfsc_request, NULL, NULL);
+ splx(s);
+ return (error);
+}
+
+int
+hfsc_add_altq(struct pf_altq *a)
+{
+ struct hfsc_if *hif;
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(a->ifname)) == NULL)
+ return (EINVAL);
+ if (!ALTQ_IS_READY(&ifp->if_snd))
+ return (ENODEV);
+
+ hif = malloc(sizeof(struct hfsc_if), M_DEVBUF, M_WAITOK);
+ if (hif == NULL)
+ return (ENOMEM);
+ bzero(hif, sizeof(struct hfsc_if));
+
+ hif->hif_eligible = ellist_alloc();
+ if (hif->hif_eligible == NULL) {
+ free(hif, M_DEVBUF);
+ return (ENOMEM);
+ }
+
+ hif->hif_ifq = &ifp->if_snd;
+
+ /* keep the state in pf_altq */
+ a->altq_disc = hif;
+
+ return (0);
+}
+
+int
+hfsc_remove_altq(struct pf_altq *a)
+{
+ struct hfsc_if *hif;
+
+ if ((hif = a->altq_disc) == NULL)
+ return (EINVAL);
+ a->altq_disc = NULL;
+
+ (void)hfsc_clear_interface(hif);
+ (void)hfsc_class_destroy(hif->hif_rootclass);
+
+ ellist_destroy(hif->hif_eligible);
+
+ free(hif, M_DEVBUF);
+
+ return (0);
+}
+
+int
+hfsc_add_queue(struct pf_altq *a)
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl, *parent;
+ struct hfsc_opts *opts;
+ struct service_curve rtsc, lssc, ulsc;
+
+ if ((hif = a->altq_disc) == NULL)
+ return (EINVAL);
+
+ opts = &a->pq_u.hfsc_opts;
+
+ if (a->parent_qid == HFSC_NULLCLASS_HANDLE &&
+ hif->hif_rootclass == NULL)
+ parent = NULL;
+ else if ((parent = clh_to_clp(hif, a->parent_qid)) == NULL)
+ return (EINVAL);
+
+ if (a->qid == 0)
+ return (EINVAL);
+
+ if (clh_to_clp(hif, a->qid) != NULL)
+ return (EBUSY);
+
+ rtsc.m1 = opts->rtsc_m1;
+ rtsc.d = opts->rtsc_d;
+ rtsc.m2 = opts->rtsc_m2;
+ lssc.m1 = opts->lssc_m1;
+ lssc.d = opts->lssc_d;
+ lssc.m2 = opts->lssc_m2;
+ ulsc.m1 = opts->ulsc_m1;
+ ulsc.d = opts->ulsc_d;
+ ulsc.m2 = opts->ulsc_m2;
+
+ cl = hfsc_class_create(hif, &rtsc, &lssc, &ulsc,
+ parent, a->qlimit, opts->flags, a->qid);
+ if (cl == NULL)
+ return (ENOMEM);
+
+ return (0);
+}
+
+int
+hfsc_remove_queue(struct pf_altq *a)
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+
+ if ((hif = a->altq_disc) == NULL)
+ return (EINVAL);
+
+ if ((cl = clh_to_clp(hif, a->qid)) == NULL)
+ return (EINVAL);
+
+ return (hfsc_class_destroy(cl));
+}
+
+int
+hfsc_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+ struct hfsc_classstats stats;
+ int error = 0;
+
+ if ((hif = altq_lookup(a->ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(hif, a->qid)) == NULL)
+ return (EINVAL);
+
+ if (*nbytes < sizeof(stats))
+ return (EINVAL);
+
+ get_class_stats(&stats, cl);
+
+ if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
+ return (error);
+ *nbytes = sizeof(stats);
+ return (0);
+}
+
+/*
+ * bring the interface back to the initial state by discarding
+ * all the filters and classes except the root class.
+ */
+static int
+hfsc_clear_interface(struct hfsc_if *hif)
+{
+ struct hfsc_class *cl;
+
+#ifdef ALTQ3_COMPAT
+ /* free the filters for this interface */
+ acc_discard_filters(&hif->hif_classifier, NULL, 1);
+#endif
+
+ /* clear out the classes */
+ while (hif->hif_rootclass != NULL &&
+ (cl = hif->hif_rootclass->cl_children) != NULL) {
+ /*
+ * remove the first leaf class found in the hierarchy
+ * then start over
+ */
+ for (; cl != NULL; cl = hfsc_nextclass(cl)) {
+ if (!is_a_parent_class(cl)) {
+ (void)hfsc_class_destroy(cl);
+ break;
+ }
+ }
+ }
+
+ return (0);
+}
+
+static int
+hfsc_request(struct ifaltq *ifq, int req, void *arg)
+{
+ struct hfsc_if *hif = (struct hfsc_if *)ifq->altq_disc;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ switch (req) {
+ case ALTRQ_PURGE:
+ hfsc_purge(hif);
+ break;
+ }
+ return (0);
+}
+
+/* discard all the queued packets on the interface */
+static void
+hfsc_purge(struct hfsc_if *hif)
+{
+ struct hfsc_class *cl;
+
+ for (cl = hif->hif_rootclass; cl != NULL; cl = hfsc_nextclass(cl))
+ if (!qempty(cl->cl_q))
+ hfsc_purgeq(cl);
+ if (ALTQ_IS_ENABLED(hif->hif_ifq))
+ hif->hif_ifq->ifq_len = 0;
+}
+
+struct hfsc_class *
+hfsc_class_create(struct hfsc_if *hif, struct service_curve *rsc,
+ struct service_curve *fsc, struct service_curve *usc,
+ struct hfsc_class *parent, int qlimit, int flags, int qid)
+{
+ struct hfsc_class *cl, *p;
+ int i, s;
+
+ if (hif->hif_classes >= HFSC_MAX_CLASSES)
+ return (NULL);
+
+#ifndef ALTQ_RED
+ if (flags & HFCF_RED) {
+#ifdef ALTQ_DEBUG
+ printf("hfsc_class_create: RED not configured for HFSC!\n");
+#endif
+ return (NULL);
+ }
+#endif
+
+ cl = malloc(sizeof(struct hfsc_class), M_DEVBUF, M_WAITOK);
+ if (cl == NULL)
+ return (NULL);
+ bzero(cl, sizeof(struct hfsc_class));
+
+ cl->cl_q = malloc(sizeof(class_queue_t), M_DEVBUF, M_WAITOK);
+ if (cl->cl_q == NULL)
+ goto err_ret;
+ bzero(cl->cl_q, sizeof(class_queue_t));
+
+ cl->cl_actc = actlist_alloc();
+ if (cl->cl_actc == NULL)
+ goto err_ret;
+
+ if (qlimit == 0)
+ qlimit = 50; /* use default */
+ qlimit(cl->cl_q) = qlimit;
+ qtype(cl->cl_q) = Q_DROPTAIL;
+ qlen(cl->cl_q) = 0;
+ cl->cl_flags = flags;
+#ifdef ALTQ_RED
+ if (flags & (HFCF_RED|HFCF_RIO)) {
+ int red_flags, red_pkttime;
+ u_int m2;
+
+ m2 = 0;
+ if (rsc != NULL && rsc->m2 > m2)
+ m2 = rsc->m2;
+ if (fsc != NULL && fsc->m2 > m2)
+ m2 = fsc->m2;
+ if (usc != NULL && usc->m2 > m2)
+ m2 = usc->m2;
+
+ red_flags = 0;
+ if (flags & HFCF_ECN)
+ red_flags |= REDF_ECN;
+#ifdef ALTQ_RIO
+ if (flags & HFCF_CLEARDSCP)
+ red_flags |= RIOF_CLEARDSCP;
+#endif
+ if (m2 < 8)
+ red_pkttime = 1000 * 1000 * 1000; /* 1 sec */
+ else
+ red_pkttime = (int64_t)hif->hif_ifq->altq_ifp->if_mtu
+ * 1000 * 1000 * 1000 / (m2 / 8);
+ if (flags & HFCF_RED) {
+ cl->cl_red = red_alloc(0, 0,
+ qlimit(cl->cl_q) * 10/100,
+ qlimit(cl->cl_q) * 30/100,
+ red_flags, red_pkttime);
+ if (cl->cl_red != NULL)
+ qtype(cl->cl_q) = Q_RED;
+ }
+#ifdef ALTQ_RIO
+ else {
+ cl->cl_red = (red_t *)rio_alloc(0, NULL,
+ red_flags, red_pkttime);
+ if (cl->cl_red != NULL)
+ qtype(cl->cl_q) = Q_RIO;
+ }
+#endif
+ }
+#endif /* ALTQ_RED */
+
+ if (rsc != NULL && (rsc->m1 != 0 || rsc->m2 != 0)) {
+ cl->cl_rsc = malloc(sizeof(struct internal_sc),
+ M_DEVBUF, M_WAITOK);
+ if (cl->cl_rsc == NULL)
+ goto err_ret;
+ sc2isc(rsc, cl->cl_rsc);
+ rtsc_init(&cl->cl_deadline, cl->cl_rsc, 0, 0);
+ rtsc_init(&cl->cl_eligible, cl->cl_rsc, 0, 0);
+ }
+ if (fsc != NULL && (fsc->m1 != 0 || fsc->m2 != 0)) {
+ cl->cl_fsc = malloc(sizeof(struct internal_sc),
+ M_DEVBUF, M_WAITOK);
+ if (cl->cl_fsc == NULL)
+ goto err_ret;
+ sc2isc(fsc, cl->cl_fsc);
+ rtsc_init(&cl->cl_virtual, cl->cl_fsc, 0, 0);
+ }
+ if (usc != NULL && (usc->m1 != 0 || usc->m2 != 0)) {
+ cl->cl_usc = malloc(sizeof(struct internal_sc),
+ M_DEVBUF, M_WAITOK);
+ if (cl->cl_usc == NULL)
+ goto err_ret;
+ sc2isc(usc, cl->cl_usc);
+ rtsc_init(&cl->cl_ulimit, cl->cl_usc, 0, 0);
+ }
+
+ cl->cl_id = hif->hif_classid++;
+ cl->cl_handle = qid;
+ cl->cl_hif = hif;
+ cl->cl_parent = parent;
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(hif->hif_ifq);
+ hif->hif_classes++;
+
+ /*
+ * find a free slot in the class table. if the slot matching
+ * the lower bits of qid is free, use this slot. otherwise,
+ * use the first free slot.
+ */
+ i = qid % HFSC_MAX_CLASSES;
+ if (hif->hif_class_tbl[i] == NULL)
+ hif->hif_class_tbl[i] = cl;
+ else {
+ for (i = 0; i < HFSC_MAX_CLASSES; i++)
+ if (hif->hif_class_tbl[i] == NULL) {
+ hif->hif_class_tbl[i] = cl;
+ break;
+ }
+ if (i == HFSC_MAX_CLASSES) {
+ IFQ_UNLOCK(hif->hif_ifq);
+ splx(s);
+ goto err_ret;
+ }
+ }
+
+ if (flags & HFCF_DEFAULTCLASS)
+ hif->hif_defaultclass = cl;
+
+ if (parent == NULL) {
+ /* this is root class */
+ hif->hif_rootclass = cl;
+ } else {
+ /* add this class to the children list of the parent */
+ if ((p = parent->cl_children) == NULL)
+ parent->cl_children = cl;
+ else {
+ while (p->cl_siblings != NULL)
+ p = p->cl_siblings;
+ p->cl_siblings = cl;
+ }
+ }
+ IFQ_UNLOCK(hif->hif_ifq);
+ splx(s);
+
+ return (cl);
+
+ err_ret:
+ if (cl->cl_actc != NULL)
+ actlist_destroy(cl->cl_actc);
+ if (cl->cl_red != NULL) {
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_destroy((rio_t *)cl->cl_red);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_destroy(cl->cl_red);
+#endif
+ }
+ if (cl->cl_fsc != NULL)
+ free(cl->cl_fsc, M_DEVBUF);
+ if (cl->cl_rsc != NULL)
+ free(cl->cl_rsc, M_DEVBUF);
+ if (cl->cl_usc != NULL)
+ free(cl->cl_usc, M_DEVBUF);
+ if (cl->cl_q != NULL)
+ free(cl->cl_q, M_DEVBUF);
+ free(cl, M_DEVBUF);
+ return (NULL);
+}
+
+static int
+hfsc_class_destroy(struct hfsc_class *cl)
+{
+ int i, s;
+
+ if (cl == NULL)
+ return (0);
+
+ if (is_a_parent_class(cl))
+ return (EBUSY);
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(cl->cl_hif->hif_ifq);
+
+#ifdef ALTQ3_COMPAT
+ /* delete filters referencing to this class */
+ acc_discard_filters(&cl->cl_hif->hif_classifier, cl, 0);
+#endif /* ALTQ3_COMPAT */
+
+ if (!qempty(cl->cl_q))
+ hfsc_purgeq(cl);
+
+ if (cl->cl_parent == NULL) {
+ /* this is root class */
+ } else {
+ struct hfsc_class *p = cl->cl_parent->cl_children;
+
+ if (p == cl)
+ cl->cl_parent->cl_children = cl->cl_siblings;
+ else do {
+ if (p->cl_siblings == cl) {
+ p->cl_siblings = cl->cl_siblings;
+ break;
+ }
+ } while ((p = p->cl_siblings) != NULL);
+ ASSERT(p != NULL);
+ }
+
+ for (i = 0; i < HFSC_MAX_CLASSES; i++)
+ if (cl->cl_hif->hif_class_tbl[i] == cl) {
+ cl->cl_hif->hif_class_tbl[i] = NULL;
+ break;
+ }
+
+ cl->cl_hif->hif_classes--;
+ IFQ_UNLOCK(cl->cl_hif->hif_ifq);
+ splx(s);
+
+ actlist_destroy(cl->cl_actc);
+
+ if (cl->cl_red != NULL) {
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_destroy((rio_t *)cl->cl_red);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_destroy(cl->cl_red);
+#endif
+ }
+
+ IFQ_LOCK(cl->cl_hif->hif_ifq);
+ if (cl == cl->cl_hif->hif_rootclass)
+ cl->cl_hif->hif_rootclass = NULL;
+ if (cl == cl->cl_hif->hif_defaultclass)
+ cl->cl_hif->hif_defaultclass = NULL;
+ IFQ_UNLOCK(cl->cl_hif->hif_ifq);
+
+ if (cl->cl_usc != NULL)
+ free(cl->cl_usc, M_DEVBUF);
+ if (cl->cl_fsc != NULL)
+ free(cl->cl_fsc, M_DEVBUF);
+ if (cl->cl_rsc != NULL)
+ free(cl->cl_rsc, M_DEVBUF);
+ free(cl->cl_q, M_DEVBUF);
+ free(cl, M_DEVBUF);
+
+ return (0);
+}
+
+/*
+ * hfsc_nextclass returns the next class in the tree.
+ * usage:
+ * for (cl = hif->hif_rootclass; cl != NULL; cl = hfsc_nextclass(cl))
+ * do_something;
+ */
+static struct hfsc_class *
+hfsc_nextclass(struct hfsc_class *cl)
+{
+ if (cl->cl_children != NULL)
+ cl = cl->cl_children;
+ else if (cl->cl_siblings != NULL)
+ cl = cl->cl_siblings;
+ else {
+ while ((cl = cl->cl_parent) != NULL)
+ if (cl->cl_siblings) {
+ cl = cl->cl_siblings;
+ break;
+ }
+ }
+
+ return (cl);
+}
+
+/*
+ * hfsc_enqueue is an enqueue function to be registered to
+ * (*altq_enqueue) in struct ifaltq.
+ */
+static int
+hfsc_enqueue(struct ifaltq *ifq, struct mbuf *m, struct altq_pktattr *pktattr)
+{
+ struct hfsc_if *hif = (struct hfsc_if *)ifq->altq_disc;
+ struct hfsc_class *cl;
+ struct pf_mtag *t;
+ int len;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ /* grab class set by classifier */
+ if ((m->m_flags & M_PKTHDR) == 0) {
+ /* should not happen */
+#if defined(__NetBSD__) || defined(__OpenBSD__)\
+ || (defined(__FreeBSD__) && __FreeBSD_version >= 501113)
+ printf("altq: packet for %s does not have pkthdr\n",
+ ifq->altq_ifp->if_xname);
+#else
+ printf("altq: packet for %s%d does not have pkthdr\n",
+ ifq->altq_ifp->if_name, ifq->altq_ifp->if_unit);
+#endif
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ cl = NULL;
+ if ((t = pf_find_mtag(m)) != NULL)
+ cl = clh_to_clp(hif, t->qid);
+#ifdef ALTQ3_COMPAT
+ else if ((ifq->altq_flags & ALTQF_CLASSIFY) && pktattr != NULL)
+ cl = pktattr->pattr_class;
+#endif
+ if (cl == NULL || is_a_parent_class(cl)) {
+ cl = hif->hif_defaultclass;
+ if (cl == NULL) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ }
+#ifdef ALTQ3_COMPAT
+ if (pktattr != NULL)
+ cl->cl_pktattr = pktattr; /* save proto hdr used by ECN */
+ else
+#endif
+ cl->cl_pktattr = NULL;
+ len = m_pktlen(m);
+ if (hfsc_addq(cl, m) != 0) {
+ /* drop occurred. mbuf was freed in hfsc_addq. */
+ PKTCNTR_ADD(&cl->cl_stats.drop_cnt, len);
+ return (ENOBUFS);
+ }
+ IFQ_INC_LEN(ifq);
+ cl->cl_hif->hif_packets++;
+
+ /* successfully queued. */
+ if (qlen(cl->cl_q) == 1)
+ set_active(cl, m_pktlen(m));
+
+ return (0);
+}
+
+/*
+ * hfsc_dequeue is a dequeue function to be registered to
+ * (*altq_dequeue) in struct ifaltq.
+ *
+ * note: ALTDQ_POLL returns the next packet without removing the packet
+ * from the queue. ALTDQ_REMOVE is a normal dequeue operation.
+ * ALTDQ_REMOVE must return the same packet if called immediately
+ * after ALTDQ_POLL.
+ */
+static struct mbuf *
+hfsc_dequeue(struct ifaltq *ifq, int op)
+{
+ struct hfsc_if *hif = (struct hfsc_if *)ifq->altq_disc;
+ struct hfsc_class *cl;
+ struct mbuf *m;
+ int len, next_len;
+ int realtime = 0;
+ u_int64_t cur_time;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ if (hif->hif_packets == 0)
+ /* no packet in the tree */
+ return (NULL);
+
+ cur_time = read_machclk();
+
+ if (op == ALTDQ_REMOVE && hif->hif_pollcache != NULL) {
+
+ cl = hif->hif_pollcache;
+ hif->hif_pollcache = NULL;
+ /* check if the class was scheduled by real-time criteria */
+ if (cl->cl_rsc != NULL)
+ realtime = (cl->cl_e <= cur_time);
+ } else {
+ /*
+ * if there are eligible classes, use real-time criteria.
+ * find the class with the minimum deadline among
+ * the eligible classes.
+ */
+ if ((cl = ellist_get_mindl(hif->hif_eligible, cur_time))
+ != NULL) {
+ realtime = 1;
+ } else {
+#ifdef ALTQ_DEBUG
+ int fits = 0;
+#endif
+ /*
+ * use link-sharing criteria
+ * get the class with the minimum vt in the hierarchy
+ */
+ cl = hif->hif_rootclass;
+ while (is_a_parent_class(cl)) {
+
+ cl = actlist_firstfit(cl, cur_time);
+ if (cl == NULL) {
+#ifdef ALTQ_DEBUG
+ if (fits > 0)
+ printf("%d fit but none found\n",fits);
+#endif
+ return (NULL);
+ }
+ /*
+ * update parent's cl_cvtmin.
+ * don't update if the new vt is smaller.
+ */
+ if (cl->cl_parent->cl_cvtmin < cl->cl_vt)
+ cl->cl_parent->cl_cvtmin = cl->cl_vt;
+#ifdef ALTQ_DEBUG
+ fits++;
+#endif
+ }
+ }
+
+ if (op == ALTDQ_POLL) {
+ hif->hif_pollcache = cl;
+ m = hfsc_pollq(cl);
+ return (m);
+ }
+ }
+
+ m = hfsc_getq(cl);
+ if (m == NULL)
+ panic("hfsc_dequeue:");
+ len = m_pktlen(m);
+ cl->cl_hif->hif_packets--;
+ IFQ_DEC_LEN(ifq);
+ PKTCNTR_ADD(&cl->cl_stats.xmit_cnt, len);
+
+ update_vf(cl, len, cur_time);
+ if (realtime)
+ cl->cl_cumul += len;
+
+ if (!qempty(cl->cl_q)) {
+ if (cl->cl_rsc != NULL) {
+ /* update ed */
+ next_len = m_pktlen(qhead(cl->cl_q));
+
+ if (realtime)
+ update_ed(cl, next_len);
+ else
+ update_d(cl, next_len);
+ }
+ } else {
+ /* the class becomes passive */
+ set_passive(cl);
+ }
+
+ return (m);
+}
+
+static int
+hfsc_addq(struct hfsc_class *cl, struct mbuf *m)
+{
+
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ return rio_addq((rio_t *)cl->cl_red, cl->cl_q,
+ m, cl->cl_pktattr);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ return red_addq(cl->cl_red, cl->cl_q, m, cl->cl_pktattr);
+#endif
+ if (qlen(cl->cl_q) >= qlimit(cl->cl_q)) {
+ m_freem(m);
+ return (-1);
+ }
+
+ if (cl->cl_flags & HFCF_CLEARDSCP)
+ write_dsfield(m, cl->cl_pktattr, 0);
+
+ _addq(cl->cl_q, m);
+
+ return (0);
+}
+
+static struct mbuf *
+hfsc_getq(struct hfsc_class *cl)
+{
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ return rio_getq((rio_t *)cl->cl_red, cl->cl_q);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ return red_getq(cl->cl_red, cl->cl_q);
+#endif
+ return _getq(cl->cl_q);
+}
+
+static struct mbuf *
+hfsc_pollq(struct hfsc_class *cl)
+{
+ return qhead(cl->cl_q);
+}
+
+static void
+hfsc_purgeq(struct hfsc_class *cl)
+{
+ struct mbuf *m;
+
+ if (qempty(cl->cl_q))
+ return;
+
+ while ((m = _getq(cl->cl_q)) != NULL) {
+ PKTCNTR_ADD(&cl->cl_stats.drop_cnt, m_pktlen(m));
+ m_freem(m);
+ cl->cl_hif->hif_packets--;
+ IFQ_DEC_LEN(cl->cl_hif->hif_ifq);
+ }
+ ASSERT(qlen(cl->cl_q) == 0);
+
+ update_vf(cl, 0, 0); /* remove cl from the actlist */
+ set_passive(cl);
+}
+
+static void
+set_active(struct hfsc_class *cl, int len)
+{
+ if (cl->cl_rsc != NULL)
+ init_ed(cl, len);
+ if (cl->cl_fsc != NULL)
+ init_vf(cl, len);
+
+ cl->cl_stats.period++;
+}
+
+static void
+set_passive(struct hfsc_class *cl)
+{
+ if (cl->cl_rsc != NULL)
+ ellist_remove(cl);
+
+ /*
+ * actlist is now handled in update_vf() so that update_vf(cl, 0, 0)
+ * needs to be called explicitly to remove a class from actlist
+ */
+}
+
+static void
+init_ed(struct hfsc_class *cl, int next_len)
+{
+ u_int64_t cur_time;
+
+ cur_time = read_machclk();
+
+ /* update the deadline curve */
+ rtsc_min(&cl->cl_deadline, cl->cl_rsc, cur_time, cl->cl_cumul);
+
+ /*
+ * update the eligible curve.
+ * for concave, it is equal to the deadline curve.
+ * for convex, it is a linear curve with slope m2.
+ */
+ cl->cl_eligible = cl->cl_deadline;
+ if (cl->cl_rsc->sm1 <= cl->cl_rsc->sm2) {
+ cl->cl_eligible.dx = 0;
+ cl->cl_eligible.dy = 0;
+ }
+
+ /* compute e and d */
+ cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
+ cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+
+ ellist_insert(cl);
+}
+
+static void
+update_ed(struct hfsc_class *cl, int next_len)
+{
+ cl->cl_e = rtsc_y2x(&cl->cl_eligible, cl->cl_cumul);
+ cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+
+ ellist_update(cl);
+}
+
+static void
+update_d(struct hfsc_class *cl, int next_len)
+{
+ cl->cl_d = rtsc_y2x(&cl->cl_deadline, cl->cl_cumul + next_len);
+}
+
+static void
+init_vf(struct hfsc_class *cl, int len)
+{
+ struct hfsc_class *max_cl, *p;
+ u_int64_t vt, f, cur_time;
+ int go_active;
+
+ cur_time = 0;
+ go_active = 1;
+ for ( ; cl->cl_parent != NULL; cl = cl->cl_parent) {
+
+ if (go_active && cl->cl_nactive++ == 0)
+ go_active = 1;
+ else
+ go_active = 0;
+
+ if (go_active) {
+ max_cl = actlist_last(cl->cl_parent->cl_actc);
+ if (max_cl != NULL) {
+ /*
+ * set vt to the average of the min and max
+ * classes. if the parent's period didn't
+ * change, don't decrease vt of the class.
+ */
+ vt = max_cl->cl_vt;
+ if (cl->cl_parent->cl_cvtmin != 0)
+ vt = (cl->cl_parent->cl_cvtmin + vt)/2;
+
+ if (cl->cl_parent->cl_vtperiod !=
+ cl->cl_parentperiod || vt > cl->cl_vt)
+ cl->cl_vt = vt;
+ } else {
+ /*
+ * first child for a new parent backlog period.
+ * add parent's cvtmax to vtoff of children
+ * to make a new vt (vtoff + vt) larger than
+ * the vt in the last period for all children.
+ */
+ vt = cl->cl_parent->cl_cvtmax;
+ for (p = cl->cl_parent->cl_children; p != NULL;
+ p = p->cl_siblings)
+ p->cl_vtoff += vt;
+ cl->cl_vt = 0;
+ cl->cl_parent->cl_cvtmax = 0;
+ cl->cl_parent->cl_cvtmin = 0;
+ }
+ cl->cl_initvt = cl->cl_vt;
+
+ /* update the virtual curve */
+ vt = cl->cl_vt + cl->cl_vtoff;
+ rtsc_min(&cl->cl_virtual, cl->cl_fsc, vt, cl->cl_total);
+ if (cl->cl_virtual.x == vt) {
+ cl->cl_virtual.x -= cl->cl_vtoff;
+ cl->cl_vtoff = 0;
+ }
+ cl->cl_vtadj = 0;
+
+ cl->cl_vtperiod++; /* increment vt period */
+ cl->cl_parentperiod = cl->cl_parent->cl_vtperiod;
+ if (cl->cl_parent->cl_nactive == 0)
+ cl->cl_parentperiod++;
+ cl->cl_f = 0;
+
+ actlist_insert(cl);
+
+ if (cl->cl_usc != NULL) {
+ /* class has upper limit curve */
+ if (cur_time == 0)
+ cur_time = read_machclk();
+
+ /* update the ulimit curve */
+ rtsc_min(&cl->cl_ulimit, cl->cl_usc, cur_time,
+ cl->cl_total);
+ /* compute myf */
+ cl->cl_myf = rtsc_y2x(&cl->cl_ulimit,
+ cl->cl_total);
+ cl->cl_myfadj = 0;
+ }
+ }
+
+ if (cl->cl_myf > cl->cl_cfmin)
+ f = cl->cl_myf;
+ else
+ f = cl->cl_cfmin;
+ if (f != cl->cl_f) {
+ cl->cl_f = f;
+ update_cfmin(cl->cl_parent);
+ }
+ }
+}
+
+static void
+update_vf(struct hfsc_class *cl, int len, u_int64_t cur_time)
+{
+ u_int64_t f, myf_bound, delta;
+ int go_passive;
+
+ go_passive = qempty(cl->cl_q);
+
+ for (; cl->cl_parent != NULL; cl = cl->cl_parent) {
+
+ cl->cl_total += len;
+
+ if (cl->cl_fsc == NULL || cl->cl_nactive == 0)
+ continue;
+
+ if (go_passive && --cl->cl_nactive == 0)
+ go_passive = 1;
+ else
+ go_passive = 0;
+
+ if (go_passive) {
+ /* no more active child, going passive */
+
+ /* update cvtmax of the parent class */
+ if (cl->cl_vt > cl->cl_parent->cl_cvtmax)
+ cl->cl_parent->cl_cvtmax = cl->cl_vt;
+
+ /* remove this class from the vt list */
+ actlist_remove(cl);
+
+ update_cfmin(cl->cl_parent);
+
+ continue;
+ }
+
+ /*
+ * update vt and f
+ */
+ cl->cl_vt = rtsc_y2x(&cl->cl_virtual, cl->cl_total)
+ - cl->cl_vtoff + cl->cl_vtadj;
+
+ /*
+ * if vt of the class is smaller than cvtmin,
+ * the class was skipped in the past due to non-fit.
+ * if so, we need to adjust vtadj.
+ */
+ if (cl->cl_vt < cl->cl_parent->cl_cvtmin) {
+ cl->cl_vtadj += cl->cl_parent->cl_cvtmin - cl->cl_vt;
+ cl->cl_vt = cl->cl_parent->cl_cvtmin;
+ }
+
+ /* update the vt list */
+ actlist_update(cl);
+
+ if (cl->cl_usc != NULL) {
+ cl->cl_myf = cl->cl_myfadj
+ + rtsc_y2x(&cl->cl_ulimit, cl->cl_total);
+
+ /*
+ * if myf lags behind by more than one clock tick
+ * from the current time, adjust myfadj to prevent
+ * a rate-limited class from going greedy.
+ * in a steady state under rate-limiting, myf
+ * fluctuates within one clock tick.
+ */
+ myf_bound = cur_time - machclk_per_tick;
+ if (cl->cl_myf < myf_bound) {
+ delta = cur_time - cl->cl_myf;
+ cl->cl_myfadj += delta;
+ cl->cl_myf += delta;
+ }
+ }
+
+ /* cl_f is max(cl_myf, cl_cfmin) */
+ if (cl->cl_myf > cl->cl_cfmin)
+ f = cl->cl_myf;
+ else
+ f = cl->cl_cfmin;
+ if (f != cl->cl_f) {
+ cl->cl_f = f;
+ update_cfmin(cl->cl_parent);
+ }
+ }
+}
+
+static void
+update_cfmin(struct hfsc_class *cl)
+{
+ struct hfsc_class *p;
+ u_int64_t cfmin;
+
+ if (TAILQ_EMPTY(cl->cl_actc)) {
+ cl->cl_cfmin = 0;
+ return;
+ }
+ cfmin = HT_INFINITY;
+ TAILQ_FOREACH(p, cl->cl_actc, cl_actlist) {
+ if (p->cl_f == 0) {
+ cl->cl_cfmin = 0;
+ return;
+ }
+ if (p->cl_f < cfmin)
+ cfmin = p->cl_f;
+ }
+ cl->cl_cfmin = cfmin;
+}
+
+/*
+ * TAILQ based ellist and actlist implementation
+ * (ion wanted to make a calendar queue based implementation)
+ */
+/*
+ * eligible list holds backlogged classes being sorted by their eligible times.
+ * there is one eligible list per interface.
+ */
+
+static ellist_t *
+ellist_alloc(void)
+{
+ ellist_t *head;
+
+ head = malloc(sizeof(ellist_t), M_DEVBUF, M_WAITOK);
+ TAILQ_INIT(head);
+ return (head);
+}
+
+static void
+ellist_destroy(ellist_t *head)
+{
+ free(head, M_DEVBUF);
+}
+
+static void
+ellist_insert(struct hfsc_class *cl)
+{
+ struct hfsc_if *hif = cl->cl_hif;
+ struct hfsc_class *p;
+
+ /* check the last entry first */
+ if ((p = TAILQ_LAST(hif->hif_eligible, _eligible)) == NULL ||
+ p->cl_e <= cl->cl_e) {
+ TAILQ_INSERT_TAIL(hif->hif_eligible, cl, cl_ellist);
+ return;
+ }
+
+ TAILQ_FOREACH(p, hif->hif_eligible, cl_ellist) {
+ if (cl->cl_e < p->cl_e) {
+ TAILQ_INSERT_BEFORE(p, cl, cl_ellist);
+ return;
+ }
+ }
+ ASSERT(0); /* should not reach here */
+}
+
+static void
+ellist_remove(struct hfsc_class *cl)
+{
+ struct hfsc_if *hif = cl->cl_hif;
+
+ TAILQ_REMOVE(hif->hif_eligible, cl, cl_ellist);
+}
+
+static void
+ellist_update(struct hfsc_class *cl)
+{
+ struct hfsc_if *hif = cl->cl_hif;
+ struct hfsc_class *p, *last;
+
+ /*
+ * the eligible time of a class increases monotonically.
+ * if the next entry has a larger eligible time, nothing to do.
+ */
+ p = TAILQ_NEXT(cl, cl_ellist);
+ if (p == NULL || cl->cl_e <= p->cl_e)
+ return;
+
+ /* check the last entry */
+ last = TAILQ_LAST(hif->hif_eligible, _eligible);
+ ASSERT(last != NULL);
+ if (last->cl_e <= cl->cl_e) {
+ TAILQ_REMOVE(hif->hif_eligible, cl, cl_ellist);
+ TAILQ_INSERT_TAIL(hif->hif_eligible, cl, cl_ellist);
+ return;
+ }
+
+ /*
+ * the new position must be between the next entry
+ * and the last entry
+ */
+ while ((p = TAILQ_NEXT(p, cl_ellist)) != NULL) {
+ if (cl->cl_e < p->cl_e) {
+ TAILQ_REMOVE(hif->hif_eligible, cl, cl_ellist);
+ TAILQ_INSERT_BEFORE(p, cl, cl_ellist);
+ return;
+ }
+ }
+ ASSERT(0); /* should not reach here */
+}
+
+/* find the class with the minimum deadline among the eligible classes */
+struct hfsc_class *
+ellist_get_mindl(ellist_t *head, u_int64_t cur_time)
+{
+ struct hfsc_class *p, *cl = NULL;
+
+ TAILQ_FOREACH(p, head, cl_ellist) {
+ if (p->cl_e > cur_time)
+ break;
+ if (cl == NULL || p->cl_d < cl->cl_d)
+ cl = p;
+ }
+ return (cl);
+}
+
+/*
+ * active children list holds backlogged child classes being sorted
+ * by their virtual time.
+ * each intermediate class has one active children list.
+ */
+static actlist_t *
+actlist_alloc(void)
+{
+ actlist_t *head;
+
+ head = malloc(sizeof(actlist_t), M_DEVBUF, M_WAITOK);
+ TAILQ_INIT(head);
+ return (head);
+}
+
+static void
+actlist_destroy(actlist_t *head)
+{
+ free(head, M_DEVBUF);
+}
+static void
+actlist_insert(struct hfsc_class *cl)
+{
+ struct hfsc_class *p;
+
+ /* check the last entry first */
+ if ((p = TAILQ_LAST(cl->cl_parent->cl_actc, _active)) == NULL
+ || p->cl_vt <= cl->cl_vt) {
+ TAILQ_INSERT_TAIL(cl->cl_parent->cl_actc, cl, cl_actlist);
+ return;
+ }
+
+ TAILQ_FOREACH(p, cl->cl_parent->cl_actc, cl_actlist) {
+ if (cl->cl_vt < p->cl_vt) {
+ TAILQ_INSERT_BEFORE(p, cl, cl_actlist);
+ return;
+ }
+ }
+ ASSERT(0); /* should not reach here */
+}
+
+static void
+actlist_remove(struct hfsc_class *cl)
+{
+ TAILQ_REMOVE(cl->cl_parent->cl_actc, cl, cl_actlist);
+}
+
+static void
+actlist_update(struct hfsc_class *cl)
+{
+ struct hfsc_class *p, *last;
+
+ /*
+ * the virtual time of a class increases monotonically during its
+ * backlogged period.
+ * if the next entry has a larger virtual time, nothing to do.
+ */
+ p = TAILQ_NEXT(cl, cl_actlist);
+ if (p == NULL || cl->cl_vt < p->cl_vt)
+ return;
+
+ /* check the last entry */
+ last = TAILQ_LAST(cl->cl_parent->cl_actc, _active);
+ ASSERT(last != NULL);
+ if (last->cl_vt <= cl->cl_vt) {
+ TAILQ_REMOVE(cl->cl_parent->cl_actc, cl, cl_actlist);
+ TAILQ_INSERT_TAIL(cl->cl_parent->cl_actc, cl, cl_actlist);
+ return;
+ }
+
+ /*
+ * the new position must be between the next entry
+ * and the last entry
+ */
+ while ((p = TAILQ_NEXT(p, cl_actlist)) != NULL) {
+ if (cl->cl_vt < p->cl_vt) {
+ TAILQ_REMOVE(cl->cl_parent->cl_actc, cl, cl_actlist);
+ TAILQ_INSERT_BEFORE(p, cl, cl_actlist);
+ return;
+ }
+ }
+ ASSERT(0); /* should not reach here */
+}
+
+static struct hfsc_class *
+actlist_firstfit(struct hfsc_class *cl, u_int64_t cur_time)
+{
+ struct hfsc_class *p;
+
+ TAILQ_FOREACH(p, cl->cl_actc, cl_actlist) {
+ if (p->cl_f <= cur_time)
+ return (p);
+ }
+ return (NULL);
+}
+
+/*
+ * service curve support functions
+ *
+ * external service curve parameters
+ * m: bits/sec
+ * d: msec
+ * internal service curve parameters
+ * sm: (bytes/tsc_interval) << SM_SHIFT
+ * ism: (tsc_count/byte) << ISM_SHIFT
+ * dx: tsc_count
+ *
+ * SM_SHIFT and ISM_SHIFT are scaled in order to keep effective digits.
+ * we should be able to handle 100K-1Gbps linkspeed with 200Hz-1GHz CPU
+ * speed. SM_SHIFT and ISM_SHIFT are selected to have at least 3 effective
+ * digits in decimal using the following table.
+ *
+ * bits/sec 100Kbps 1Mbps 10Mbps 100Mbps 1Gbps
+ * ----------+-------------------------------------------------------
+ * bytes/nsec 12.5e-6 125e-6 1250e-6 12500e-6 125000e-6
+ * sm(500MHz) 25.0e-6 250e-6 2500e-6 25000e-6 250000e-6
+ * sm(200MHz) 62.5e-6 625e-6 6250e-6 62500e-6 625000e-6
+ *
+ * nsec/byte 80000 8000 800 80 8
+ * ism(500MHz) 40000 4000 400 40 4
+ * ism(200MHz) 16000 1600 160 16 1.6
+ */
+#define SM_SHIFT 24
+#define ISM_SHIFT 10
+
+#define SM_MASK ((1LL << SM_SHIFT) - 1)
+#define ISM_MASK ((1LL << ISM_SHIFT) - 1)
+
+static __inline u_int64_t
+seg_x2y(u_int64_t x, u_int64_t sm)
+{
+ u_int64_t y;
+
+ /*
+ * compute
+ * y = x * sm >> SM_SHIFT
+ * but divide it for the upper and lower bits to avoid overflow
+ */
+ y = (x >> SM_SHIFT) * sm + (((x & SM_MASK) * sm) >> SM_SHIFT);
+ return (y);
+}
+
+static __inline u_int64_t
+seg_y2x(u_int64_t y, u_int64_t ism)
+{
+ u_int64_t x;
+
+ if (y == 0)
+ x = 0;
+ else if (ism == HT_INFINITY)
+ x = HT_INFINITY;
+ else {
+ x = (y >> ISM_SHIFT) * ism
+ + (((y & ISM_MASK) * ism) >> ISM_SHIFT);
+ }
+ return (x);
+}
+
+static __inline u_int64_t
+m2sm(u_int m)
+{
+ u_int64_t sm;
+
+ sm = ((u_int64_t)m << SM_SHIFT) / 8 / machclk_freq;
+ return (sm);
+}
+
+static __inline u_int64_t
+m2ism(u_int m)
+{
+ u_int64_t ism;
+
+ if (m == 0)
+ ism = HT_INFINITY;
+ else
+ ism = ((u_int64_t)machclk_freq << ISM_SHIFT) * 8 / m;
+ return (ism);
+}
+
+static __inline u_int64_t
+d2dx(u_int d)
+{
+ u_int64_t dx;
+
+ dx = ((u_int64_t)d * machclk_freq) / 1000;
+ return (dx);
+}
+
+static u_int
+sm2m(u_int64_t sm)
+{
+ u_int64_t m;
+
+ m = (sm * 8 * machclk_freq) >> SM_SHIFT;
+ return ((u_int)m);
+}
+
+static u_int
+dx2d(u_int64_t dx)
+{
+ u_int64_t d;
+
+ d = dx * 1000 / machclk_freq;
+ return ((u_int)d);
+}
+
+static void
+sc2isc(struct service_curve *sc, struct internal_sc *isc)
+{
+ isc->sm1 = m2sm(sc->m1);
+ isc->ism1 = m2ism(sc->m1);
+ isc->dx = d2dx(sc->d);
+ isc->dy = seg_x2y(isc->dx, isc->sm1);
+ isc->sm2 = m2sm(sc->m2);
+ isc->ism2 = m2ism(sc->m2);
+}
+
+/*
+ * initialize the runtime service curve with the given internal
+ * service curve starting at (x, y).
+ */
+static void
+rtsc_init(struct runtime_sc *rtsc, struct internal_sc * isc, u_int64_t x,
+ u_int64_t y)
+{
+ rtsc->x = x;
+ rtsc->y = y;
+ rtsc->sm1 = isc->sm1;
+ rtsc->ism1 = isc->ism1;
+ rtsc->dx = isc->dx;
+ rtsc->dy = isc->dy;
+ rtsc->sm2 = isc->sm2;
+ rtsc->ism2 = isc->ism2;
+}
+
+/*
+ * calculate the y-projection of the runtime service curve by the
+ * given x-projection value
+ */
+static u_int64_t
+rtsc_y2x(struct runtime_sc *rtsc, u_int64_t y)
+{
+ u_int64_t x;
+
+ if (y < rtsc->y)
+ x = rtsc->x;
+ else if (y <= rtsc->y + rtsc->dy) {
+ /* x belongs to the 1st segment */
+ if (rtsc->dy == 0)
+ x = rtsc->x + rtsc->dx;
+ else
+ x = rtsc->x + seg_y2x(y - rtsc->y, rtsc->ism1);
+ } else {
+ /* x belongs to the 2nd segment */
+ x = rtsc->x + rtsc->dx
+ + seg_y2x(y - rtsc->y - rtsc->dy, rtsc->ism2);
+ }
+ return (x);
+}
+
+static u_int64_t
+rtsc_x2y(struct runtime_sc *rtsc, u_int64_t x)
+{
+ u_int64_t y;
+
+ if (x <= rtsc->x)
+ y = rtsc->y;
+ else if (x <= rtsc->x + rtsc->dx)
+ /* y belongs to the 1st segment */
+ y = rtsc->y + seg_x2y(x - rtsc->x, rtsc->sm1);
+ else
+ /* y belongs to the 2nd segment */
+ y = rtsc->y + rtsc->dy
+ + seg_x2y(x - rtsc->x - rtsc->dx, rtsc->sm2);
+ return (y);
+}
+
+/*
+ * update the runtime service curve by taking the minimum of the current
+ * runtime service curve and the service curve starting at (x, y).
+ */
+static void
+rtsc_min(struct runtime_sc *rtsc, struct internal_sc *isc, u_int64_t x,
+ u_int64_t y)
+{
+ u_int64_t y1, y2, dx, dy;
+
+ if (isc->sm1 <= isc->sm2) {
+ /* service curve is convex */
+ y1 = rtsc_x2y(rtsc, x);
+ if (y1 < y)
+ /* the current rtsc is smaller */
+ return;
+ rtsc->x = x;
+ rtsc->y = y;
+ return;
+ }
+
+ /*
+ * service curve is concave
+ * compute the two y values of the current rtsc
+ * y1: at x
+ * y2: at (x + dx)
+ */
+ y1 = rtsc_x2y(rtsc, x);
+ if (y1 <= y) {
+ /* rtsc is below isc, no change to rtsc */
+ return;
+ }
+
+ y2 = rtsc_x2y(rtsc, x + isc->dx);
+ if (y2 >= y + isc->dy) {
+ /* rtsc is above isc, replace rtsc by isc */
+ rtsc->x = x;
+ rtsc->y = y;
+ rtsc->dx = isc->dx;
+ rtsc->dy = isc->dy;
+ return;
+ }
+
+ /*
+ * the two curves intersect
+ * compute the offsets (dx, dy) using the reverse
+ * function of seg_x2y()
+ * seg_x2y(dx, sm1) == seg_x2y(dx, sm2) + (y1 - y)
+ */
+ dx = ((y1 - y) << SM_SHIFT) / (isc->sm1 - isc->sm2);
+ /*
+ * check if (x, y1) belongs to the 1st segment of rtsc.
+ * if so, add the offset.
+ */
+ if (rtsc->x + rtsc->dx > x)
+ dx += rtsc->x + rtsc->dx - x;
+ dy = seg_x2y(dx, isc->sm1);
+
+ rtsc->x = x;
+ rtsc->y = y;
+ rtsc->dx = dx;
+ rtsc->dy = dy;
+ return;
+}
+
+static void
+get_class_stats(struct hfsc_classstats *sp, struct hfsc_class *cl)
+{
+ sp->class_id = cl->cl_id;
+ sp->class_handle = cl->cl_handle;
+
+ if (cl->cl_rsc != NULL) {
+ sp->rsc.m1 = sm2m(cl->cl_rsc->sm1);
+ sp->rsc.d = dx2d(cl->cl_rsc->dx);
+ sp->rsc.m2 = sm2m(cl->cl_rsc->sm2);
+ } else {
+ sp->rsc.m1 = 0;
+ sp->rsc.d = 0;
+ sp->rsc.m2 = 0;
+ }
+ if (cl->cl_fsc != NULL) {
+ sp->fsc.m1 = sm2m(cl->cl_fsc->sm1);
+ sp->fsc.d = dx2d(cl->cl_fsc->dx);
+ sp->fsc.m2 = sm2m(cl->cl_fsc->sm2);
+ } else {
+ sp->fsc.m1 = 0;
+ sp->fsc.d = 0;
+ sp->fsc.m2 = 0;
+ }
+ if (cl->cl_usc != NULL) {
+ sp->usc.m1 = sm2m(cl->cl_usc->sm1);
+ sp->usc.d = dx2d(cl->cl_usc->dx);
+ sp->usc.m2 = sm2m(cl->cl_usc->sm2);
+ } else {
+ sp->usc.m1 = 0;
+ sp->usc.d = 0;
+ sp->usc.m2 = 0;
+ }
+
+ sp->total = cl->cl_total;
+ sp->cumul = cl->cl_cumul;
+
+ sp->d = cl->cl_d;
+ sp->e = cl->cl_e;
+ sp->vt = cl->cl_vt;
+ sp->f = cl->cl_f;
+
+ sp->initvt = cl->cl_initvt;
+ sp->vtperiod = cl->cl_vtperiod;
+ sp->parentperiod = cl->cl_parentperiod;
+ sp->nactive = cl->cl_nactive;
+ sp->vtoff = cl->cl_vtoff;
+ sp->cvtmax = cl->cl_cvtmax;
+ sp->myf = cl->cl_myf;
+ sp->cfmin = cl->cl_cfmin;
+ sp->cvtmin = cl->cl_cvtmin;
+ sp->myfadj = cl->cl_myfadj;
+ sp->vtadj = cl->cl_vtadj;
+
+ sp->cur_time = read_machclk();
+ sp->machclk_freq = machclk_freq;
+
+ sp->qlength = qlen(cl->cl_q);
+ sp->qlimit = qlimit(cl->cl_q);
+ sp->xmit_cnt = cl->cl_stats.xmit_cnt;
+ sp->drop_cnt = cl->cl_stats.drop_cnt;
+ sp->period = cl->cl_stats.period;
+
+ sp->qtype = qtype(cl->cl_q);
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_getstats(cl->cl_red, &sp->red[0]);
+#endif
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_getstats((rio_t *)cl->cl_red, &sp->red[0]);
+#endif
+}
+
+/* convert a class handle to the corresponding class pointer */
+static struct hfsc_class *
+clh_to_clp(struct hfsc_if *hif, u_int32_t chandle)
+{
+ int i;
+ struct hfsc_class *cl;
+
+ if (chandle == 0)
+ return (NULL);
+ /*
+ * first, try optimistically the slot matching the lower bits of
+ * the handle. if it fails, do the linear table search.
+ */
+ i = chandle % HFSC_MAX_CLASSES;
+ if ((cl = hif->hif_class_tbl[i]) != NULL && cl->cl_handle == chandle)
+ return (cl);
+ for (i = 0; i < HFSC_MAX_CLASSES; i++)
+ if ((cl = hif->hif_class_tbl[i]) != NULL &&
+ cl->cl_handle == chandle)
+ return (cl);
+ return (NULL);
+}
+
+#ifdef ALTQ3_COMPAT
+static struct hfsc_if *
+hfsc_attach(ifq, bandwidth)
+ struct ifaltq *ifq;
+ u_int bandwidth;
+{
+ struct hfsc_if *hif;
+
+ hif = malloc(sizeof(struct hfsc_if), M_DEVBUF, M_WAITOK);
+ if (hif == NULL)
+ return (NULL);
+ bzero(hif, sizeof(struct hfsc_if));
+
+ hif->hif_eligible = ellist_alloc();
+ if (hif->hif_eligible == NULL) {
+ free(hif, M_DEVBUF);
+ return NULL;
+ }
+
+ hif->hif_ifq = ifq;
+
+ /* add this state to the hfsc list */
+ hif->hif_next = hif_list;
+ hif_list = hif;
+
+ return (hif);
+}
+
+static int
+hfsc_detach(hif)
+ struct hfsc_if *hif;
+{
+ (void)hfsc_clear_interface(hif);
+ (void)hfsc_class_destroy(hif->hif_rootclass);
+
+ /* remove this interface from the hif list */
+ if (hif_list == hif)
+ hif_list = hif->hif_next;
+ else {
+ struct hfsc_if *h;
+
+ for (h = hif_list; h != NULL; h = h->hif_next)
+ if (h->hif_next == hif) {
+ h->hif_next = hif->hif_next;
+ break;
+ }
+ ASSERT(h != NULL);
+ }
+
+ ellist_destroy(hif->hif_eligible);
+
+ free(hif, M_DEVBUF);
+
+ return (0);
+}
+
+static int
+hfsc_class_modify(cl, rsc, fsc, usc)
+ struct hfsc_class *cl;
+ struct service_curve *rsc, *fsc, *usc;
+{
+ struct internal_sc *rsc_tmp, *fsc_tmp, *usc_tmp;
+ u_int64_t cur_time;
+ int s;
+
+ rsc_tmp = fsc_tmp = usc_tmp = NULL;
+ if (rsc != NULL && (rsc->m1 != 0 || rsc->m2 != 0) &&
+ cl->cl_rsc == NULL) {
+ rsc_tmp = malloc(sizeof(struct internal_sc),
+ M_DEVBUF, M_WAITOK);
+ if (rsc_tmp == NULL)
+ return (ENOMEM);
+ }
+ if (fsc != NULL && (fsc->m1 != 0 || fsc->m2 != 0) &&
+ cl->cl_fsc == NULL) {
+ fsc_tmp = malloc(sizeof(struct internal_sc),
+ M_DEVBUF, M_WAITOK);
+ if (fsc_tmp == NULL) {
+ free(rsc_tmp);
+ return (ENOMEM);
+ }
+ }
+ if (usc != NULL && (usc->m1 != 0 || usc->m2 != 0) &&
+ cl->cl_usc == NULL) {
+ usc_tmp = malloc(sizeof(struct internal_sc),
+ M_DEVBUF, M_WAITOK);
+ if (usc_tmp == NULL) {
+ free(rsc_tmp);
+ free(fsc_tmp);
+ return (ENOMEM);
+ }
+ }
+
+ cur_time = read_machclk();
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(cl->cl_hif->hif_ifq);
+
+ if (rsc != NULL) {
+ if (rsc->m1 == 0 && rsc->m2 == 0) {
+ if (cl->cl_rsc != NULL) {
+ if (!qempty(cl->cl_q))
+ hfsc_purgeq(cl);
+ free(cl->cl_rsc, M_DEVBUF);
+ cl->cl_rsc = NULL;
+ }
+ } else {
+ if (cl->cl_rsc == NULL)
+ cl->cl_rsc = rsc_tmp;
+ sc2isc(rsc, cl->cl_rsc);
+ rtsc_init(&cl->cl_deadline, cl->cl_rsc, cur_time,
+ cl->cl_cumul);
+ cl->cl_eligible = cl->cl_deadline;
+ if (cl->cl_rsc->sm1 <= cl->cl_rsc->sm2) {
+ cl->cl_eligible.dx = 0;
+ cl->cl_eligible.dy = 0;
+ }
+ }
+ }
+
+ if (fsc != NULL) {
+ if (fsc->m1 == 0 && fsc->m2 == 0) {
+ if (cl->cl_fsc != NULL) {
+ if (!qempty(cl->cl_q))
+ hfsc_purgeq(cl);
+ free(cl->cl_fsc, M_DEVBUF);
+ cl->cl_fsc = NULL;
+ }
+ } else {
+ if (cl->cl_fsc == NULL)
+ cl->cl_fsc = fsc_tmp;
+ sc2isc(fsc, cl->cl_fsc);
+ rtsc_init(&cl->cl_virtual, cl->cl_fsc, cl->cl_vt,
+ cl->cl_total);
+ }
+ }
+
+ if (usc != NULL) {
+ if (usc->m1 == 0 && usc->m2 == 0) {
+ if (cl->cl_usc != NULL) {
+ free(cl->cl_usc, M_DEVBUF);
+ cl->cl_usc = NULL;
+ cl->cl_myf = 0;
+ }
+ } else {
+ if (cl->cl_usc == NULL)
+ cl->cl_usc = usc_tmp;
+ sc2isc(usc, cl->cl_usc);
+ rtsc_init(&cl->cl_ulimit, cl->cl_usc, cur_time,
+ cl->cl_total);
+ }
+ }
+
+ if (!qempty(cl->cl_q)) {
+ if (cl->cl_rsc != NULL)
+ update_ed(cl, m_pktlen(qhead(cl->cl_q)));
+ if (cl->cl_fsc != NULL)
+ update_vf(cl, 0, cur_time);
+ /* is this enough? */
+ }
+
+ IFQ_UNLOCK(cl->cl_hif->hif_ifq);
+ splx(s);
+
+ return (0);
+}
+
+/*
+ * hfsc device interface
+ */
+int
+hfscopen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ if (machclk_freq == 0)
+ init_machclk();
+
+ if (machclk_freq == 0) {
+ printf("hfsc: no cpu clock available!\n");
+ return (ENXIO);
+ }
+
+ /* everything will be done when the queueing scheme is attached. */
+ return 0;
+}
+
+int
+hfscclose(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ struct hfsc_if *hif;
+ int err, error = 0;
+
+ while ((hif = hif_list) != NULL) {
+ /* destroy all */
+ if (ALTQ_IS_ENABLED(hif->hif_ifq))
+ altq_disable(hif->hif_ifq);
+
+ err = altq_detach(hif->hif_ifq);
+ if (err == 0)
+ err = hfsc_detach(hif);
+ if (err != 0 && error == 0)
+ error = err;
+ }
+
+ return error;
+}
+
+int
+hfscioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ ioctlcmd_t cmd;
+ caddr_t addr;
+ int flag;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ struct hfsc_if *hif;
+ struct hfsc_interface *ifacep;
+ int error = 0;
+
+ /* check super-user privilege */
+ switch (cmd) {
+ case HFSC_GETSTATS:
+ break;
+ default:
+#if (__FreeBSD_version > 700000)
+ if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+ return (error);
+#elsif (__FreeBSD_version > 400000)
+ if ((error = suser(p)) != 0)
+ return (error);
+#else
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+ return (error);
+#endif
+ break;
+ }
+
+ switch (cmd) {
+
+ case HFSC_IF_ATTACH:
+ error = hfsccmd_if_attach((struct hfsc_attach *)addr);
+ break;
+
+ case HFSC_IF_DETACH:
+ error = hfsccmd_if_detach((struct hfsc_interface *)addr);
+ break;
+
+ case HFSC_ENABLE:
+ case HFSC_DISABLE:
+ case HFSC_CLEAR_HIERARCHY:
+ ifacep = (struct hfsc_interface *)addr;
+ if ((hif = altq_lookup(ifacep->hfsc_ifname,
+ ALTQT_HFSC)) == NULL) {
+ error = EBADF;
+ break;
+ }
+
+ switch (cmd) {
+
+ case HFSC_ENABLE:
+ if (hif->hif_defaultclass == NULL) {
+#ifdef ALTQ_DEBUG
+ printf("hfsc: no default class\n");
+#endif
+ error = EINVAL;
+ break;
+ }
+ error = altq_enable(hif->hif_ifq);
+ break;
+
+ case HFSC_DISABLE:
+ error = altq_disable(hif->hif_ifq);
+ break;
+
+ case HFSC_CLEAR_HIERARCHY:
+ hfsc_clear_interface(hif);
+ break;
+ }
+ break;
+
+ case HFSC_ADD_CLASS:
+ error = hfsccmd_add_class((struct hfsc_add_class *)addr);
+ break;
+
+ case HFSC_DEL_CLASS:
+ error = hfsccmd_delete_class((struct hfsc_delete_class *)addr);
+ break;
+
+ case HFSC_MOD_CLASS:
+ error = hfsccmd_modify_class((struct hfsc_modify_class *)addr);
+ break;
+
+ case HFSC_ADD_FILTER:
+ error = hfsccmd_add_filter((struct hfsc_add_filter *)addr);
+ break;
+
+ case HFSC_DEL_FILTER:
+ error = hfsccmd_delete_filter((struct hfsc_delete_filter *)addr);
+ break;
+
+ case HFSC_GETSTATS:
+ error = hfsccmd_class_stats((struct hfsc_class_stats *)addr);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static int
+hfsccmd_if_attach(ap)
+ struct hfsc_attach *ap;
+{
+ struct hfsc_if *hif;
+ struct ifnet *ifp;
+ int error;
+
+ if ((ifp = ifunit(ap->iface.hfsc_ifname)) == NULL)
+ return (ENXIO);
+
+ if ((hif = hfsc_attach(&ifp->if_snd, ap->bandwidth)) == NULL)
+ return (ENOMEM);
+
+ /*
+ * set HFSC to this ifnet structure.
+ */
+ if ((error = altq_attach(&ifp->if_snd, ALTQT_HFSC, hif,
+ hfsc_enqueue, hfsc_dequeue, hfsc_request,
+ &hif->hif_classifier, acc_classify)) != 0)
+ (void)hfsc_detach(hif);
+
+ return (error);
+}
+
+static int
+hfsccmd_if_detach(ap)
+ struct hfsc_interface *ap;
+{
+ struct hfsc_if *hif;
+ int error;
+
+ if ((hif = altq_lookup(ap->hfsc_ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ if (ALTQ_IS_ENABLED(hif->hif_ifq))
+ altq_disable(hif->hif_ifq);
+
+ if ((error = altq_detach(hif->hif_ifq)))
+ return (error);
+
+ return hfsc_detach(hif);
+}
+
+static int
+hfsccmd_add_class(ap)
+ struct hfsc_add_class *ap;
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl, *parent;
+ int i;
+
+ if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ if (ap->parent_handle == HFSC_NULLCLASS_HANDLE &&
+ hif->hif_rootclass == NULL)
+ parent = NULL;
+ else if ((parent = clh_to_clp(hif, ap->parent_handle)) == NULL)
+ return (EINVAL);
+
+ /* assign a class handle (use a free slot number for now) */
+ for (i = 1; i < HFSC_MAX_CLASSES; i++)
+ if (hif->hif_class_tbl[i] == NULL)
+ break;
+ if (i == HFSC_MAX_CLASSES)
+ return (EBUSY);
+
+ if ((cl = hfsc_class_create(hif, &ap->service_curve, NULL, NULL,
+ parent, ap->qlimit, ap->flags, i)) == NULL)
+ return (ENOMEM);
+
+ /* return a class handle to the user */
+ ap->class_handle = i;
+
+ return (0);
+}
+
+static int
+hfsccmd_delete_class(ap)
+ struct hfsc_delete_class *ap;
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+
+ if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(hif, ap->class_handle)) == NULL)
+ return (EINVAL);
+
+ return hfsc_class_destroy(cl);
+}
+
+static int
+hfsccmd_modify_class(ap)
+ struct hfsc_modify_class *ap;
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+ struct service_curve *rsc = NULL;
+ struct service_curve *fsc = NULL;
+ struct service_curve *usc = NULL;
+
+ if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(hif, ap->class_handle)) == NULL)
+ return (EINVAL);
+
+ if (ap->sctype & HFSC_REALTIMESC)
+ rsc = &ap->service_curve;
+ if (ap->sctype & HFSC_LINKSHARINGSC)
+ fsc = &ap->service_curve;
+ if (ap->sctype & HFSC_UPPERLIMITSC)
+ usc = &ap->service_curve;
+
+ return hfsc_class_modify(cl, rsc, fsc, usc);
+}
+
+static int
+hfsccmd_add_filter(ap)
+ struct hfsc_add_filter *ap;
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+
+ if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(hif, ap->class_handle)) == NULL)
+ return (EINVAL);
+
+ if (is_a_parent_class(cl)) {
+#ifdef ALTQ_DEBUG
+ printf("hfsccmd_add_filter: not a leaf class!\n");
+#endif
+ return (EINVAL);
+ }
+
+ return acc_add_filter(&hif->hif_classifier, &ap->filter,
+ cl, &ap->filter_handle);
+}
+
+static int
+hfsccmd_delete_filter(ap)
+ struct hfsc_delete_filter *ap;
+{
+ struct hfsc_if *hif;
+
+ if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ return acc_delete_filter(&hif->hif_classifier,
+ ap->filter_handle);
+}
+
+static int
+hfsccmd_class_stats(ap)
+ struct hfsc_class_stats *ap;
+{
+ struct hfsc_if *hif;
+ struct hfsc_class *cl;
+ struct hfsc_classstats stats, *usp;
+ int n, nclasses, error;
+
+ if ((hif = altq_lookup(ap->iface.hfsc_ifname, ALTQT_HFSC)) == NULL)
+ return (EBADF);
+
+ ap->cur_time = read_machclk();
+ ap->machclk_freq = machclk_freq;
+ ap->hif_classes = hif->hif_classes;
+ ap->hif_packets = hif->hif_packets;
+
+ /* skip the first N classes in the tree */
+ nclasses = ap->nskip;
+ for (cl = hif->hif_rootclass, n = 0; cl != NULL && n < nclasses;
+ cl = hfsc_nextclass(cl), n++)
+ ;
+ if (n != nclasses)
+ return (EINVAL);
+
+ /* then, read the next N classes in the tree */
+ nclasses = ap->nclasses;
+ usp = ap->stats;
+ for (n = 0; cl != NULL && n < nclasses; cl = hfsc_nextclass(cl), n++) {
+
+ get_class_stats(&stats, cl);
+
+ if ((error = copyout((caddr_t)&stats, (caddr_t)usp++,
+ sizeof(stats))) != 0)
+ return (error);
+ }
+
+ ap->nclasses = n;
+
+ return (0);
+}
+
+#ifdef KLD_MODULE
+
+static struct altqsw hfsc_sw =
+ {"hfsc", hfscopen, hfscclose, hfscioctl};
+
+ALTQ_MODULE(altq_hfsc, ALTQT_HFSC, &hfsc_sw);
+MODULE_DEPEND(altq_hfsc, altq_red, 1, 1, 1);
+MODULE_DEPEND(altq_hfsc, altq_rio, 1, 1, 1);
+
+#endif /* KLD_MODULE */
+#endif /* ALTQ3_COMPAT */
+
+#endif /* ALTQ_HFSC */
diff --git a/freebsd/sys/contrib/altq/altq/altq_hfsc.h b/freebsd/sys/contrib/altq/altq/altq_hfsc.h
new file mode 100644
index 00000000..fc983586
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_hfsc.h
@@ -0,0 +1,320 @@
+/* $KAME: altq_hfsc.h,v 1.12 2003/12/05 05:40:46 kjc Exp $ */
+
+/*
+ * Copyright (c) 1997-1999 Carnegie Mellon University. All Rights Reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation is hereby granted (including for commercial or
+ * for-profit use), provided that both the copyright notice and this
+ * permission notice appear in all copies of the software, derivative
+ * works, or modified versions, and any portions thereof.
+ *
+ * THIS SOFTWARE IS EXPERIMENTAL AND IS KNOWN TO HAVE BUGS, SOME OF
+ * WHICH MAY HAVE SERIOUS CONSEQUENCES. CARNEGIE MELLON PROVIDES THIS
+ * SOFTWARE IN ITS ``AS IS'' CONDITION, 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 CARNEGIE MELLON UNIVERSITY 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.
+ *
+ * Carnegie Mellon encourages (but does not require) users of this
+ * software to return any improvements or extensions that they make,
+ * and to grant Carnegie Mellon the rights to redistribute these
+ * changes without encumbrance.
+ */
+#ifndef _ALTQ_ALTQ_HFSC_HH_
+#define _ALTQ_ALTQ_HFSC_HH_
+
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_classq.h>
+#include <freebsd/altq/altq_red.h>
+#include <freebsd/altq/altq_rio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct service_curve {
+ u_int m1; /* slope of the first segment in bits/sec */
+ u_int d; /* the x-projection of the first segment in msec */
+ u_int m2; /* slope of the second segment in bits/sec */
+};
+
+/* special class handles */
+#define HFSC_NULLCLASS_HANDLE 0
+#define HFSC_MAX_CLASSES 64
+
+/* hfsc class flags */
+#define HFCF_RED 0x0001 /* use RED */
+#define HFCF_ECN 0x0002 /* use RED/ECN */
+#define HFCF_RIO 0x0004 /* use RIO */
+#define HFCF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
+#define HFCF_DEFAULTCLASS 0x1000 /* default class */
+
+/* service curve types */
+#define HFSC_REALTIMESC 1
+#define HFSC_LINKSHARINGSC 2
+#define HFSC_UPPERLIMITSC 4
+#define HFSC_DEFAULTSC (HFSC_REALTIMESC|HFSC_LINKSHARINGSC)
+
+struct hfsc_classstats {
+ u_int class_id;
+ u_int32_t class_handle;
+ struct service_curve rsc;
+ struct service_curve fsc;
+ struct service_curve usc; /* upper limit service curve */
+
+ u_int64_t total; /* total work in bytes */
+ u_int64_t cumul; /* cumulative work in bytes
+ done by real-time criteria */
+ u_int64_t d; /* deadline */
+ u_int64_t e; /* eligible time */
+ u_int64_t vt; /* virtual time */
+ u_int64_t f; /* fit time for upper-limit */
+
+ /* info helpful for debugging */
+ u_int64_t initvt; /* init virtual time */
+ u_int64_t vtoff; /* cl_vt_ipoff */
+ u_int64_t cvtmax; /* cl_maxvt */
+ u_int64_t myf; /* cl_myf */
+ u_int64_t cfmin; /* cl_mincf */
+ u_int64_t cvtmin; /* cl_mincvt */
+ u_int64_t myfadj; /* cl_myfadj */
+ u_int64_t vtadj; /* cl_vtadj */
+ u_int64_t cur_time;
+ u_int32_t machclk_freq;
+
+ u_int qlength;
+ u_int qlimit;
+ struct pktcntr xmit_cnt;
+ struct pktcntr drop_cnt;
+ u_int period;
+
+ u_int vtperiod; /* vt period sequence no */
+ u_int parentperiod; /* parent's vt period seqno */
+ int nactive; /* number of active children */
+
+ /* red and rio related info */
+ int qtype;
+ struct redstats red[3];
+};
+
+#ifdef ALTQ3_COMPAT
+struct hfsc_interface {
+ char hfsc_ifname[IFNAMSIZ]; /* interface name (e.g., fxp0) */
+};
+
+struct hfsc_attach {
+ struct hfsc_interface iface;
+ u_int bandwidth; /* link bandwidth in bits/sec */
+};
+
+struct hfsc_add_class {
+ struct hfsc_interface iface;
+ u_int32_t parent_handle;
+ struct service_curve service_curve;
+ int qlimit;
+ int flags;
+
+ u_int32_t class_handle; /* return value */
+};
+
+struct hfsc_delete_class {
+ struct hfsc_interface iface;
+ u_int32_t class_handle;
+};
+
+struct hfsc_modify_class {
+ struct hfsc_interface iface;
+ u_int32_t class_handle;
+ struct service_curve service_curve;
+ int sctype;
+};
+
+struct hfsc_add_filter {
+ struct hfsc_interface iface;
+ u_int32_t class_handle;
+ struct flow_filter filter;
+
+ u_long filter_handle; /* return value */
+};
+
+struct hfsc_delete_filter {
+ struct hfsc_interface iface;
+ u_long filter_handle;
+};
+
+struct hfsc_class_stats {
+ struct hfsc_interface iface;
+ int nskip; /* skip # of classes */
+ int nclasses; /* # of class stats (WR) */
+ u_int64_t cur_time; /* current time */
+ u_int32_t machclk_freq; /* machine clock frequency */
+ u_int hif_classes; /* # of classes in the tree */
+ u_int hif_packets; /* # of packets in the tree */
+ struct hfsc_classstats *stats; /* pointer to stats array */
+};
+
+#define HFSC_IF_ATTACH _IOW('Q', 1, struct hfsc_attach)
+#define HFSC_IF_DETACH _IOW('Q', 2, struct hfsc_interface)
+#define HFSC_ENABLE _IOW('Q', 3, struct hfsc_interface)
+#define HFSC_DISABLE _IOW('Q', 4, struct hfsc_interface)
+#define HFSC_CLEAR_HIERARCHY _IOW('Q', 5, struct hfsc_interface)
+#define HFSC_ADD_CLASS _IOWR('Q', 7, struct hfsc_add_class)
+#define HFSC_DEL_CLASS _IOW('Q', 8, struct hfsc_delete_class)
+#define HFSC_MOD_CLASS _IOW('Q', 9, struct hfsc_modify_class)
+#define HFSC_ADD_FILTER _IOWR('Q', 10, struct hfsc_add_filter)
+#define HFSC_DEL_FILTER _IOW('Q', 11, struct hfsc_delete_filter)
+#define HFSC_GETSTATS _IOWR('Q', 12, struct hfsc_class_stats)
+#endif /* ALTQ3_COMPAT */
+
+#ifdef _KERNEL
+/*
+ * kernel internal service curve representation
+ * coordinates are given by 64 bit unsigned integers.
+ * x-axis: unit is clock count. for the intel x86 architecture,
+ * the raw Pentium TSC (Timestamp Counter) value is used.
+ * virtual time is also calculated in this time scale.
+ * y-axis: unit is byte.
+ *
+ * the service curve parameters are converted to the internal
+ * representation.
+ * the slope values are scaled to avoid overflow.
+ * the inverse slope values as well as the y-projection of the 1st
+ * segment are kept in order to to avoid 64-bit divide operations
+ * that are expensive on 32-bit architectures.
+ *
+ * note: Intel Pentium TSC never wraps around in several thousands of years.
+ * x-axis doesn't wrap around for 1089 years with 1GHz clock.
+ * y-axis doesn't wrap around for 4358 years with 1Gbps bandwidth.
+ */
+
+/* kernel internal representation of a service curve */
+struct internal_sc {
+ u_int64_t sm1; /* scaled slope of the 1st segment */
+ u_int64_t ism1; /* scaled inverse-slope of the 1st segment */
+ u_int64_t dx; /* the x-projection of the 1st segment */
+ u_int64_t dy; /* the y-projection of the 1st segment */
+ u_int64_t sm2; /* scaled slope of the 2nd segment */
+ u_int64_t ism2; /* scaled inverse-slope of the 2nd segment */
+};
+
+/* runtime service curve */
+struct runtime_sc {
+ u_int64_t x; /* current starting position on x-axis */
+ u_int64_t y; /* current starting position on x-axis */
+ u_int64_t sm1; /* scaled slope of the 1st segment */
+ u_int64_t ism1; /* scaled inverse-slope of the 1st segment */
+ u_int64_t dx; /* the x-projection of the 1st segment */
+ u_int64_t dy; /* the y-projection of the 1st segment */
+ u_int64_t sm2; /* scaled slope of the 2nd segment */
+ u_int64_t ism2; /* scaled inverse-slope of the 2nd segment */
+};
+
+/* for TAILQ based ellist and actlist implementation */
+struct hfsc_class;
+typedef TAILQ_HEAD(_eligible, hfsc_class) ellist_t;
+typedef TAILQ_ENTRY(hfsc_class) elentry_t;
+typedef TAILQ_HEAD(_active, hfsc_class) actlist_t;
+typedef TAILQ_ENTRY(hfsc_class) actentry_t;
+#define ellist_first(s) TAILQ_FIRST(s)
+#define actlist_first(s) TAILQ_FIRST(s)
+#define actlist_last(s) TAILQ_LAST(s, _active)
+
+struct hfsc_class {
+ u_int cl_id; /* class id (just for debug) */
+ u_int32_t cl_handle; /* class handle */
+ struct hfsc_if *cl_hif; /* back pointer to struct hfsc_if */
+ int cl_flags; /* misc flags */
+
+ struct hfsc_class *cl_parent; /* parent class */
+ struct hfsc_class *cl_siblings; /* sibling classes */
+ struct hfsc_class *cl_children; /* child classes */
+
+ class_queue_t *cl_q; /* class queue structure */
+ struct red *cl_red; /* RED state */
+ struct altq_pktattr *cl_pktattr; /* saved header used by ECN */
+
+ u_int64_t cl_total; /* total work in bytes */
+ u_int64_t cl_cumul; /* cumulative work in bytes
+ done by real-time criteria */
+ u_int64_t cl_d; /* deadline */
+ u_int64_t cl_e; /* eligible time */
+ u_int64_t cl_vt; /* virtual time */
+ u_int64_t cl_f; /* time when this class will fit for
+ link-sharing, max(myf, cfmin) */
+ u_int64_t cl_myf; /* my fit-time (as calculated from this
+ class's own upperlimit curve) */
+ u_int64_t cl_myfadj; /* my fit-time adjustment
+ (to cancel history dependence) */
+ u_int64_t cl_cfmin; /* earliest children's fit-time (used
+ with cl_myf to obtain cl_f) */
+ u_int64_t cl_cvtmin; /* minimal virtual time among the
+ children fit for link-sharing
+ (monotonic within a period) */
+ u_int64_t cl_vtadj; /* intra-period cumulative vt
+ adjustment */
+ u_int64_t cl_vtoff; /* inter-period cumulative vt offset */
+ u_int64_t cl_cvtmax; /* max child's vt in the last period */
+
+ u_int64_t cl_initvt; /* init virtual time (for debugging) */
+
+ struct internal_sc *cl_rsc; /* internal real-time service curve */
+ struct internal_sc *cl_fsc; /* internal fair service curve */
+ struct internal_sc *cl_usc; /* internal upperlimit service curve */
+ struct runtime_sc cl_deadline; /* deadline curve */
+ struct runtime_sc cl_eligible; /* eligible curve */
+ struct runtime_sc cl_virtual; /* virtual curve */
+ struct runtime_sc cl_ulimit; /* upperlimit curve */
+
+ u_int cl_vtperiod; /* vt period sequence no */
+ u_int cl_parentperiod; /* parent's vt period seqno */
+ int cl_nactive; /* number of active children */
+ actlist_t *cl_actc; /* active children list */
+
+ actentry_t cl_actlist; /* active children list entry */
+ elentry_t cl_ellist; /* eligible list entry */
+
+ struct {
+ struct pktcntr xmit_cnt;
+ struct pktcntr drop_cnt;
+ u_int period;
+ } cl_stats;
+};
+
+/*
+ * hfsc interface state
+ */
+struct hfsc_if {
+ struct hfsc_if *hif_next; /* interface state list */
+ struct ifaltq *hif_ifq; /* backpointer to ifaltq */
+ struct hfsc_class *hif_rootclass; /* root class */
+ struct hfsc_class *hif_defaultclass; /* default class */
+ struct hfsc_class *hif_class_tbl[HFSC_MAX_CLASSES];
+ struct hfsc_class *hif_pollcache; /* cache for poll operation */
+
+ u_int hif_classes; /* # of classes in the tree */
+ u_int hif_packets; /* # of packets in the tree */
+ u_int hif_classid; /* class id sequence number */
+
+ ellist_t *hif_eligible; /* eligible list */
+
+#ifdef ALTQ3_CLFIER_COMPAT
+ struct acc_classifier hif_classifier;
+#endif
+};
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ALTQ_ALTQ_HFSC_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_priq.c b/freebsd/sys/contrib/altq/altq/altq_priq.c
new file mode 100644
index 00000000..d395a833
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_priq.c
@@ -0,0 +1,1055 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_priq.c,v 1.11 2003/09/17 14:23:25 kjc Exp $ */
+/*
+ * Copyright (C) 2000-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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.
+ */
+/*
+ * priority queue
+ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#if (__FreeBSD__ != 2)
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+
+#ifdef ALTQ_PRIQ /* priq is enabled by ALTQ_PRIQ option in opt_altq.h */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/sockio.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/errno.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/queue.h>
+
+#include <freebsd/net/if.h>
+#include <freebsd/netinet/in.h>
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/altq/altq.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/altq/altq_conf.h>
+#endif
+#include <freebsd/altq/altq_priq.h>
+
+/*
+ * function prototypes
+ */
+#ifdef ALTQ3_COMPAT
+static struct priq_if *priq_attach(struct ifaltq *, u_int);
+static int priq_detach(struct priq_if *);
+#endif
+static int priq_clear_interface(struct priq_if *);
+static int priq_request(struct ifaltq *, int, void *);
+static void priq_purge(struct priq_if *);
+static struct priq_class *priq_class_create(struct priq_if *, int, int, int,
+ int);
+static int priq_class_destroy(struct priq_class *);
+static int priq_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
+static struct mbuf *priq_dequeue(struct ifaltq *, int);
+
+static int priq_addq(struct priq_class *, struct mbuf *);
+static struct mbuf *priq_getq(struct priq_class *);
+static struct mbuf *priq_pollq(struct priq_class *);
+static void priq_purgeq(struct priq_class *);
+
+#ifdef ALTQ3_COMPAT
+static int priqcmd_if_attach(struct priq_interface *);
+static int priqcmd_if_detach(struct priq_interface *);
+static int priqcmd_add_class(struct priq_add_class *);
+static int priqcmd_delete_class(struct priq_delete_class *);
+static int priqcmd_modify_class(struct priq_modify_class *);
+static int priqcmd_add_filter(struct priq_add_filter *);
+static int priqcmd_delete_filter(struct priq_delete_filter *);
+static int priqcmd_class_stats(struct priq_class_stats *);
+#endif /* ALTQ3_COMPAT */
+
+static void get_class_stats(struct priq_classstats *, struct priq_class *);
+static struct priq_class *clh_to_clp(struct priq_if *, u_int32_t);
+
+#ifdef ALTQ3_COMPAT
+altqdev_decl(priq);
+
+/* pif_list keeps all priq_if's allocated. */
+static struct priq_if *pif_list = NULL;
+#endif /* ALTQ3_COMPAT */
+
+int
+priq_pfattach(struct pf_altq *a)
+{
+ struct ifnet *ifp;
+ int s, error;
+
+ if ((ifp = ifunit(a->ifname)) == NULL || a->altq_disc == NULL)
+ return (EINVAL);
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ error = altq_attach(&ifp->if_snd, ALTQT_PRIQ, a->altq_disc,
+ priq_enqueue, priq_dequeue, priq_request, NULL, NULL);
+ splx(s);
+ return (error);
+}
+
+int
+priq_add_altq(struct pf_altq *a)
+{
+ struct priq_if *pif;
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(a->ifname)) == NULL)
+ return (EINVAL);
+ if (!ALTQ_IS_READY(&ifp->if_snd))
+ return (ENODEV);
+
+ pif = malloc(sizeof(struct priq_if),
+ M_DEVBUF, M_WAITOK);
+ if (pif == NULL)
+ return (ENOMEM);
+ bzero(pif, sizeof(struct priq_if));
+ pif->pif_bandwidth = a->ifbandwidth;
+ pif->pif_maxpri = -1;
+ pif->pif_ifq = &ifp->if_snd;
+
+ /* keep the state in pf_altq */
+ a->altq_disc = pif;
+
+ return (0);
+}
+
+int
+priq_remove_altq(struct pf_altq *a)
+{
+ struct priq_if *pif;
+
+ if ((pif = a->altq_disc) == NULL)
+ return (EINVAL);
+ a->altq_disc = NULL;
+
+ (void)priq_clear_interface(pif);
+
+ free(pif, M_DEVBUF);
+ return (0);
+}
+
+int
+priq_add_queue(struct pf_altq *a)
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+
+ if ((pif = a->altq_disc) == NULL)
+ return (EINVAL);
+
+ /* check parameters */
+ if (a->priority >= PRIQ_MAXPRI)
+ return (EINVAL);
+ if (a->qid == 0)
+ return (EINVAL);
+ if (pif->pif_classes[a->priority] != NULL)
+ return (EBUSY);
+ if (clh_to_clp(pif, a->qid) != NULL)
+ return (EBUSY);
+
+ cl = priq_class_create(pif, a->priority, a->qlimit,
+ a->pq_u.priq_opts.flags, a->qid);
+ if (cl == NULL)
+ return (ENOMEM);
+
+ return (0);
+}
+
+int
+priq_remove_queue(struct pf_altq *a)
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+
+ if ((pif = a->altq_disc) == NULL)
+ return (EINVAL);
+
+ if ((cl = clh_to_clp(pif, a->qid)) == NULL)
+ return (EINVAL);
+
+ return (priq_class_destroy(cl));
+}
+
+int
+priq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+ struct priq_classstats stats;
+ int error = 0;
+
+ if ((pif = altq_lookup(a->ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(pif, a->qid)) == NULL)
+ return (EINVAL);
+
+ if (*nbytes < sizeof(stats))
+ return (EINVAL);
+
+ get_class_stats(&stats, cl);
+
+ if ((error = copyout((caddr_t)&stats, ubuf, sizeof(stats))) != 0)
+ return (error);
+ *nbytes = sizeof(stats);
+ return (0);
+}
+
+/*
+ * bring the interface back to the initial state by discarding
+ * all the filters and classes.
+ */
+static int
+priq_clear_interface(struct priq_if *pif)
+{
+ struct priq_class *cl;
+ int pri;
+
+#ifdef ALTQ3_CLFIER_COMPAT
+ /* free the filters for this interface */
+ acc_discard_filters(&pif->pif_classifier, NULL, 1);
+#endif
+
+ /* clear out the classes */
+ for (pri = 0; pri <= pif->pif_maxpri; pri++)
+ if ((cl = pif->pif_classes[pri]) != NULL)
+ priq_class_destroy(cl);
+
+ return (0);
+}
+
+static int
+priq_request(struct ifaltq *ifq, int req, void *arg)
+{
+ struct priq_if *pif = (struct priq_if *)ifq->altq_disc;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ switch (req) {
+ case ALTRQ_PURGE:
+ priq_purge(pif);
+ break;
+ }
+ return (0);
+}
+
+/* discard all the queued packets on the interface */
+static void
+priq_purge(struct priq_if *pif)
+{
+ struct priq_class *cl;
+ int pri;
+
+ for (pri = 0; pri <= pif->pif_maxpri; pri++) {
+ if ((cl = pif->pif_classes[pri]) != NULL && !qempty(cl->cl_q))
+ priq_purgeq(cl);
+ }
+ if (ALTQ_IS_ENABLED(pif->pif_ifq))
+ pif->pif_ifq->ifq_len = 0;
+}
+
+static struct priq_class *
+priq_class_create(struct priq_if *pif, int pri, int qlimit, int flags, int qid)
+{
+ struct priq_class *cl;
+ int s;
+
+#ifndef ALTQ_RED
+ if (flags & PRCF_RED) {
+#ifdef ALTQ_DEBUG
+ printf("priq_class_create: RED not configured for PRIQ!\n");
+#endif
+ return (NULL);
+ }
+#endif
+
+ if ((cl = pif->pif_classes[pri]) != NULL) {
+ /* modify the class instead of creating a new one */
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(cl->cl_pif->pif_ifq);
+ if (!qempty(cl->cl_q))
+ priq_purgeq(cl);
+ IFQ_UNLOCK(cl->cl_pif->pif_ifq);
+ splx(s);
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_destroy((rio_t *)cl->cl_red);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_destroy(cl->cl_red);
+#endif
+ } else {
+ cl = malloc(sizeof(struct priq_class),
+ M_DEVBUF, M_WAITOK);
+ if (cl == NULL)
+ return (NULL);
+ bzero(cl, sizeof(struct priq_class));
+
+ cl->cl_q = malloc(sizeof(class_queue_t),
+ M_DEVBUF, M_WAITOK);
+ if (cl->cl_q == NULL)
+ goto err_ret;
+ bzero(cl->cl_q, sizeof(class_queue_t));
+ }
+
+ pif->pif_classes[pri] = cl;
+ if (flags & PRCF_DEFAULTCLASS)
+ pif->pif_default = cl;
+ if (qlimit == 0)
+ qlimit = 50; /* use default */
+ qlimit(cl->cl_q) = qlimit;
+ qtype(cl->cl_q) = Q_DROPTAIL;
+ qlen(cl->cl_q) = 0;
+ cl->cl_flags = flags;
+ cl->cl_pri = pri;
+ if (pri > pif->pif_maxpri)
+ pif->pif_maxpri = pri;
+ cl->cl_pif = pif;
+ cl->cl_handle = qid;
+
+#ifdef ALTQ_RED
+ if (flags & (PRCF_RED|PRCF_RIO)) {
+ int red_flags, red_pkttime;
+
+ red_flags = 0;
+ if (flags & PRCF_ECN)
+ red_flags |= REDF_ECN;
+#ifdef ALTQ_RIO
+ if (flags & PRCF_CLEARDSCP)
+ red_flags |= RIOF_CLEARDSCP;
+#endif
+ if (pif->pif_bandwidth < 8)
+ red_pkttime = 1000 * 1000 * 1000; /* 1 sec */
+ else
+ red_pkttime = (int64_t)pif->pif_ifq->altq_ifp->if_mtu
+ * 1000 * 1000 * 1000 / (pif->pif_bandwidth / 8);
+#ifdef ALTQ_RIO
+ if (flags & PRCF_RIO) {
+ cl->cl_red = (red_t *)rio_alloc(0, NULL,
+ red_flags, red_pkttime);
+ if (cl->cl_red != NULL)
+ qtype(cl->cl_q) = Q_RIO;
+ } else
+#endif
+ if (flags & PRCF_RED) {
+ cl->cl_red = red_alloc(0, 0,
+ qlimit(cl->cl_q) * 10/100,
+ qlimit(cl->cl_q) * 30/100,
+ red_flags, red_pkttime);
+ if (cl->cl_red != NULL)
+ qtype(cl->cl_q) = Q_RED;
+ }
+ }
+#endif /* ALTQ_RED */
+
+ return (cl);
+
+ err_ret:
+ if (cl->cl_red != NULL) {
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_destroy((rio_t *)cl->cl_red);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_destroy(cl->cl_red);
+#endif
+ }
+ if (cl->cl_q != NULL)
+ free(cl->cl_q, M_DEVBUF);
+ free(cl, M_DEVBUF);
+ return (NULL);
+}
+
+static int
+priq_class_destroy(struct priq_class *cl)
+{
+ struct priq_if *pif;
+ int s, pri;
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(cl->cl_pif->pif_ifq);
+
+#ifdef ALTQ3_CLFIER_COMPAT
+ /* delete filters referencing to this class */
+ acc_discard_filters(&cl->cl_pif->pif_classifier, cl, 0);
+#endif
+
+ if (!qempty(cl->cl_q))
+ priq_purgeq(cl);
+
+ pif = cl->cl_pif;
+ pif->pif_classes[cl->cl_pri] = NULL;
+ if (pif->pif_maxpri == cl->cl_pri) {
+ for (pri = cl->cl_pri; pri >= 0; pri--)
+ if (pif->pif_classes[pri] != NULL) {
+ pif->pif_maxpri = pri;
+ break;
+ }
+ if (pri < 0)
+ pif->pif_maxpri = -1;
+ }
+ IFQ_UNLOCK(cl->cl_pif->pif_ifq);
+ splx(s);
+
+ if (cl->cl_red != NULL) {
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_destroy((rio_t *)cl->cl_red);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_destroy(cl->cl_red);
+#endif
+ }
+ free(cl->cl_q, M_DEVBUF);
+ free(cl, M_DEVBUF);
+ return (0);
+}
+
+/*
+ * priq_enqueue is an enqueue function to be registered to
+ * (*altq_enqueue) in struct ifaltq.
+ */
+static int
+priq_enqueue(struct ifaltq *ifq, struct mbuf *m, struct altq_pktattr *pktattr)
+{
+ struct priq_if *pif = (struct priq_if *)ifq->altq_disc;
+ struct priq_class *cl;
+ struct pf_mtag *t;
+ int len;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ /* grab class set by classifier */
+ if ((m->m_flags & M_PKTHDR) == 0) {
+ /* should not happen */
+#if defined(__NetBSD__) || defined(__OpenBSD__)\
+ || (defined(__FreeBSD__) && __FreeBSD_version >= 501113)
+ printf("altq: packet for %s does not have pkthdr\n",
+ ifq->altq_ifp->if_xname);
+#else
+ printf("altq: packet for %s%d does not have pkthdr\n",
+ ifq->altq_ifp->if_name, ifq->altq_ifp->if_unit);
+#endif
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ cl = NULL;
+ if ((t = pf_find_mtag(m)) != NULL)
+ cl = clh_to_clp(pif, t->qid);
+#ifdef ALTQ3_COMPAT
+ else if ((ifq->altq_flags & ALTQF_CLASSIFY) && pktattr != NULL)
+ cl = pktattr->pattr_class;
+#endif
+ if (cl == NULL) {
+ cl = pif->pif_default;
+ if (cl == NULL) {
+ m_freem(m);
+ return (ENOBUFS);
+ }
+ }
+#ifdef ALTQ3_COMPAT
+ if (pktattr != NULL)
+ cl->cl_pktattr = pktattr; /* save proto hdr used by ECN */
+ else
+#endif
+ cl->cl_pktattr = NULL;
+ len = m_pktlen(m);
+ if (priq_addq(cl, m) != 0) {
+ /* drop occurred. mbuf was freed in priq_addq. */
+ PKTCNTR_ADD(&cl->cl_dropcnt, len);
+ return (ENOBUFS);
+ }
+ IFQ_INC_LEN(ifq);
+
+ /* successfully queued. */
+ return (0);
+}
+
+/*
+ * priq_dequeue is a dequeue function to be registered to
+ * (*altq_dequeue) in struct ifaltq.
+ *
+ * note: ALTDQ_POLL returns the next packet without removing the packet
+ * from the queue. ALTDQ_REMOVE is a normal dequeue operation.
+ * ALTDQ_REMOVE must return the same packet if called immediately
+ * after ALTDQ_POLL.
+ */
+static struct mbuf *
+priq_dequeue(struct ifaltq *ifq, int op)
+{
+ struct priq_if *pif = (struct priq_if *)ifq->altq_disc;
+ struct priq_class *cl;
+ struct mbuf *m;
+ int pri;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ if (IFQ_IS_EMPTY(ifq))
+ /* no packet in the queue */
+ return (NULL);
+
+ for (pri = pif->pif_maxpri; pri >= 0; pri--) {
+ if ((cl = pif->pif_classes[pri]) != NULL &&
+ !qempty(cl->cl_q)) {
+ if (op == ALTDQ_POLL)
+ return (priq_pollq(cl));
+
+ m = priq_getq(cl);
+ if (m != NULL) {
+ IFQ_DEC_LEN(ifq);
+ if (qempty(cl->cl_q))
+ cl->cl_period++;
+ PKTCNTR_ADD(&cl->cl_xmitcnt, m_pktlen(m));
+ }
+ return (m);
+ }
+ }
+ return (NULL);
+}
+
+static int
+priq_addq(struct priq_class *cl, struct mbuf *m)
+{
+
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ return rio_addq((rio_t *)cl->cl_red, cl->cl_q, m,
+ cl->cl_pktattr);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ return red_addq(cl->cl_red, cl->cl_q, m, cl->cl_pktattr);
+#endif
+ if (qlen(cl->cl_q) >= qlimit(cl->cl_q)) {
+ m_freem(m);
+ return (-1);
+ }
+
+ if (cl->cl_flags & PRCF_CLEARDSCP)
+ write_dsfield(m, cl->cl_pktattr, 0);
+
+ _addq(cl->cl_q, m);
+
+ return (0);
+}
+
+static struct mbuf *
+priq_getq(struct priq_class *cl)
+{
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ return rio_getq((rio_t *)cl->cl_red, cl->cl_q);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ return red_getq(cl->cl_red, cl->cl_q);
+#endif
+ return _getq(cl->cl_q);
+}
+
+static struct mbuf *
+priq_pollq(cl)
+ struct priq_class *cl;
+{
+ return qhead(cl->cl_q);
+}
+
+static void
+priq_purgeq(struct priq_class *cl)
+{
+ struct mbuf *m;
+
+ if (qempty(cl->cl_q))
+ return;
+
+ while ((m = _getq(cl->cl_q)) != NULL) {
+ PKTCNTR_ADD(&cl->cl_dropcnt, m_pktlen(m));
+ m_freem(m);
+ }
+ ASSERT(qlen(cl->cl_q) == 0);
+}
+
+static void
+get_class_stats(struct priq_classstats *sp, struct priq_class *cl)
+{
+ sp->class_handle = cl->cl_handle;
+ sp->qlength = qlen(cl->cl_q);
+ sp->qlimit = qlimit(cl->cl_q);
+ sp->period = cl->cl_period;
+ sp->xmitcnt = cl->cl_xmitcnt;
+ sp->dropcnt = cl->cl_dropcnt;
+
+ sp->qtype = qtype(cl->cl_q);
+#ifdef ALTQ_RED
+ if (q_is_red(cl->cl_q))
+ red_getstats(cl->cl_red, &sp->red[0]);
+#endif
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->cl_q))
+ rio_getstats((rio_t *)cl->cl_red, &sp->red[0]);
+#endif
+
+}
+
+/* convert a class handle to the corresponding class pointer */
+static struct priq_class *
+clh_to_clp(struct priq_if *pif, u_int32_t chandle)
+{
+ struct priq_class *cl;
+ int idx;
+
+ if (chandle == 0)
+ return (NULL);
+
+ for (idx = pif->pif_maxpri; idx >= 0; idx--)
+ if ((cl = pif->pif_classes[idx]) != NULL &&
+ cl->cl_handle == chandle)
+ return (cl);
+
+ return (NULL);
+}
+
+
+#ifdef ALTQ3_COMPAT
+
+static struct priq_if *
+priq_attach(ifq, bandwidth)
+ struct ifaltq *ifq;
+ u_int bandwidth;
+{
+ struct priq_if *pif;
+
+ pif = malloc(sizeof(struct priq_if),
+ M_DEVBUF, M_WAITOK);
+ if (pif == NULL)
+ return (NULL);
+ bzero(pif, sizeof(struct priq_if));
+ pif->pif_bandwidth = bandwidth;
+ pif->pif_maxpri = -1;
+ pif->pif_ifq = ifq;
+
+ /* add this state to the priq list */
+ pif->pif_next = pif_list;
+ pif_list = pif;
+
+ return (pif);
+}
+
+static int
+priq_detach(pif)
+ struct priq_if *pif;
+{
+ (void)priq_clear_interface(pif);
+
+ /* remove this interface from the pif list */
+ if (pif_list == pif)
+ pif_list = pif->pif_next;
+ else {
+ struct priq_if *p;
+
+ for (p = pif_list; p != NULL; p = p->pif_next)
+ if (p->pif_next == pif) {
+ p->pif_next = pif->pif_next;
+ break;
+ }
+ ASSERT(p != NULL);
+ }
+
+ free(pif, M_DEVBUF);
+ return (0);
+}
+
+/*
+ * priq device interface
+ */
+int
+priqopen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ /* everything will be done when the queueing scheme is attached. */
+ return 0;
+}
+
+int
+priqclose(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ struct priq_if *pif;
+ int err, error = 0;
+
+ while ((pif = pif_list) != NULL) {
+ /* destroy all */
+ if (ALTQ_IS_ENABLED(pif->pif_ifq))
+ altq_disable(pif->pif_ifq);
+
+ err = altq_detach(pif->pif_ifq);
+ if (err == 0)
+ err = priq_detach(pif);
+ if (err != 0 && error == 0)
+ error = err;
+ }
+
+ return error;
+}
+
+int
+priqioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ ioctlcmd_t cmd;
+ caddr_t addr;
+ int flag;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ struct priq_if *pif;
+ struct priq_interface *ifacep;
+ int error = 0;
+
+ /* check super-user privilege */
+ switch (cmd) {
+ case PRIQ_GETSTATS:
+ break;
+ default:
+#if (__FreeBSD_version > 700000)
+ if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+ return (error);
+#elsif (__FreeBSD_version > 400000)
+ if ((error = suser(p)) != 0)
+ return (error);
+#else
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+ return (error);
+#endif
+ break;
+ }
+
+ switch (cmd) {
+
+ case PRIQ_IF_ATTACH:
+ error = priqcmd_if_attach((struct priq_interface *)addr);
+ break;
+
+ case PRIQ_IF_DETACH:
+ error = priqcmd_if_detach((struct priq_interface *)addr);
+ break;
+
+ case PRIQ_ENABLE:
+ case PRIQ_DISABLE:
+ case PRIQ_CLEAR:
+ ifacep = (struct priq_interface *)addr;
+ if ((pif = altq_lookup(ifacep->ifname,
+ ALTQT_PRIQ)) == NULL) {
+ error = EBADF;
+ break;
+ }
+
+ switch (cmd) {
+ case PRIQ_ENABLE:
+ if (pif->pif_default == NULL) {
+#ifdef ALTQ_DEBUG
+ printf("priq: no default class\n");
+#endif
+ error = EINVAL;
+ break;
+ }
+ error = altq_enable(pif->pif_ifq);
+ break;
+
+ case PRIQ_DISABLE:
+ error = altq_disable(pif->pif_ifq);
+ break;
+
+ case PRIQ_CLEAR:
+ priq_clear_interface(pif);
+ break;
+ }
+ break;
+
+ case PRIQ_ADD_CLASS:
+ error = priqcmd_add_class((struct priq_add_class *)addr);
+ break;
+
+ case PRIQ_DEL_CLASS:
+ error = priqcmd_delete_class((struct priq_delete_class *)addr);
+ break;
+
+ case PRIQ_MOD_CLASS:
+ error = priqcmd_modify_class((struct priq_modify_class *)addr);
+ break;
+
+ case PRIQ_ADD_FILTER:
+ error = priqcmd_add_filter((struct priq_add_filter *)addr);
+ break;
+
+ case PRIQ_DEL_FILTER:
+ error = priqcmd_delete_filter((struct priq_delete_filter *)addr);
+ break;
+
+ case PRIQ_GETSTATS:
+ error = priqcmd_class_stats((struct priq_class_stats *)addr);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static int
+priqcmd_if_attach(ap)
+ struct priq_interface *ap;
+{
+ struct priq_if *pif;
+ struct ifnet *ifp;
+ int error;
+
+ if ((ifp = ifunit(ap->ifname)) == NULL)
+ return (ENXIO);
+
+ if ((pif = priq_attach(&ifp->if_snd, ap->arg)) == NULL)
+ return (ENOMEM);
+
+ /*
+ * set PRIQ to this ifnet structure.
+ */
+ if ((error = altq_attach(&ifp->if_snd, ALTQT_PRIQ, pif,
+ priq_enqueue, priq_dequeue, priq_request,
+ &pif->pif_classifier, acc_classify)) != 0)
+ (void)priq_detach(pif);
+
+ return (error);
+}
+
+static int
+priqcmd_if_detach(ap)
+ struct priq_interface *ap;
+{
+ struct priq_if *pif;
+ int error;
+
+ if ((pif = altq_lookup(ap->ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ if (ALTQ_IS_ENABLED(pif->pif_ifq))
+ altq_disable(pif->pif_ifq);
+
+ if ((error = altq_detach(pif->pif_ifq)))
+ return (error);
+
+ return priq_detach(pif);
+}
+
+static int
+priqcmd_add_class(ap)
+ struct priq_add_class *ap;
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+ int qid;
+
+ if ((pif = altq_lookup(ap->iface.ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ if (ap->pri < 0 || ap->pri >= PRIQ_MAXPRI)
+ return (EINVAL);
+ if (pif->pif_classes[ap->pri] != NULL)
+ return (EBUSY);
+
+ qid = ap->pri + 1;
+ if ((cl = priq_class_create(pif, ap->pri,
+ ap->qlimit, ap->flags, qid)) == NULL)
+ return (ENOMEM);
+
+ /* return a class handle to the user */
+ ap->class_handle = cl->cl_handle;
+
+ return (0);
+}
+
+static int
+priqcmd_delete_class(ap)
+ struct priq_delete_class *ap;
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+
+ if ((pif = altq_lookup(ap->iface.ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(pif, ap->class_handle)) == NULL)
+ return (EINVAL);
+
+ return priq_class_destroy(cl);
+}
+
+static int
+priqcmd_modify_class(ap)
+ struct priq_modify_class *ap;
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+
+ if ((pif = altq_lookup(ap->iface.ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ if (ap->pri < 0 || ap->pri >= PRIQ_MAXPRI)
+ return (EINVAL);
+
+ if ((cl = clh_to_clp(pif, ap->class_handle)) == NULL)
+ return (EINVAL);
+
+ /*
+ * if priority is changed, move the class to the new priority
+ */
+ if (pif->pif_classes[ap->pri] != cl) {
+ if (pif->pif_classes[ap->pri] != NULL)
+ return (EEXIST);
+ pif->pif_classes[cl->cl_pri] = NULL;
+ pif->pif_classes[ap->pri] = cl;
+ cl->cl_pri = ap->pri;
+ }
+
+ /* call priq_class_create to change class parameters */
+ if ((cl = priq_class_create(pif, ap->pri,
+ ap->qlimit, ap->flags, ap->class_handle)) == NULL)
+ return (ENOMEM);
+ return 0;
+}
+
+static int
+priqcmd_add_filter(ap)
+ struct priq_add_filter *ap;
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+
+ if ((pif = altq_lookup(ap->iface.ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ if ((cl = clh_to_clp(pif, ap->class_handle)) == NULL)
+ return (EINVAL);
+
+ return acc_add_filter(&pif->pif_classifier, &ap->filter,
+ cl, &ap->filter_handle);
+}
+
+static int
+priqcmd_delete_filter(ap)
+ struct priq_delete_filter *ap;
+{
+ struct priq_if *pif;
+
+ if ((pif = altq_lookup(ap->iface.ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ return acc_delete_filter(&pif->pif_classifier,
+ ap->filter_handle);
+}
+
+static int
+priqcmd_class_stats(ap)
+ struct priq_class_stats *ap;
+{
+ struct priq_if *pif;
+ struct priq_class *cl;
+ struct priq_classstats stats, *usp;
+ int pri, error;
+
+ if ((pif = altq_lookup(ap->iface.ifname, ALTQT_PRIQ)) == NULL)
+ return (EBADF);
+
+ ap->maxpri = pif->pif_maxpri;
+
+ /* then, read the next N classes in the tree */
+ usp = ap->stats;
+ for (pri = 0; pri <= pif->pif_maxpri; pri++) {
+ cl = pif->pif_classes[pri];
+ if (cl != NULL)
+ get_class_stats(&stats, cl);
+ else
+ bzero(&stats, sizeof(stats));
+ if ((error = copyout((caddr_t)&stats, (caddr_t)usp++,
+ sizeof(stats))) != 0)
+ return (error);
+ }
+ return (0);
+}
+
+#ifdef KLD_MODULE
+
+static struct altqsw priq_sw =
+ {"priq", priqopen, priqclose, priqioctl};
+
+ALTQ_MODULE(altq_priq, ALTQT_PRIQ, &priq_sw);
+MODULE_DEPEND(altq_priq, altq_red, 1, 1, 1);
+MODULE_DEPEND(altq_priq, altq_rio, 1, 1, 1);
+
+#endif /* KLD_MODULE */
+
+#endif /* ALTQ3_COMPAT */
+#endif /* ALTQ_PRIQ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_priq.h b/freebsd/sys/contrib/altq/altq/altq_priq.h
new file mode 100644
index 00000000..7f553b8a
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_priq.h
@@ -0,0 +1,170 @@
+/* $KAME: altq_priq.h,v 1.7 2003/10/03 05:05:15 kjc Exp $ */
+/*
+ * Copyright (C) 2000-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 _ALTQ_ALTQ_PRIQ_HH_
+#define _ALTQ_ALTQ_PRIQ_HH_
+
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_classq.h>
+#include <freebsd/altq/altq_red.h>
+#include <freebsd/altq/altq_rio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PRIQ_MAXPRI 16 /* upper limit of the number of priorities */
+
+#ifdef ALTQ3_COMPAT
+struct priq_interface {
+ char ifname[IFNAMSIZ]; /* interface name (e.g., fxp0) */
+ u_long arg; /* request-specific argument */
+};
+
+struct priq_add_class {
+ struct priq_interface iface;
+ int pri; /* priority (0 is the lowest) */
+ int qlimit; /* queue size limit */
+ int flags; /* misc flags (see below) */
+
+ u_int32_t class_handle; /* return value */
+};
+#endif /* ALTQ3_COMPAT */
+
+/* priq class flags */
+#define PRCF_RED 0x0001 /* use RED */
+#define PRCF_ECN 0x0002 /* use RED/ECN */
+#define PRCF_RIO 0x0004 /* use RIO */
+#define PRCF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
+#define PRCF_DEFAULTCLASS 0x1000 /* default class */
+
+/* special class handles */
+#define PRIQ_NULLCLASS_HANDLE 0
+
+#ifdef ALTQ3_COMPAT
+struct priq_delete_class {
+ struct priq_interface iface;
+ u_int32_t class_handle;
+};
+
+struct priq_modify_class {
+ struct priq_interface iface;
+ u_int32_t class_handle;
+ int pri;
+ int qlimit;
+ int flags;
+};
+
+struct priq_add_filter {
+ struct priq_interface iface;
+ u_int32_t class_handle;
+ struct flow_filter filter;
+
+ u_long filter_handle; /* return value */
+};
+
+struct priq_delete_filter {
+ struct priq_interface iface;
+ u_long filter_handle;
+};
+#endif /* ALTQ3_COMPAT */
+
+struct priq_classstats {
+ u_int32_t class_handle;
+
+ u_int qlength;
+ u_int qlimit;
+ u_int period;
+ struct pktcntr xmitcnt; /* transmitted packet counter */
+ struct pktcntr dropcnt; /* dropped packet counter */
+
+ /* red and rio related info */
+ int qtype;
+ struct redstats red[3]; /* rio has 3 red stats */
+};
+
+#ifdef ALTQ3_COMPAT
+struct priq_class_stats {
+ struct priq_interface iface;
+ int maxpri; /* in/out */
+
+ struct priq_classstats *stats; /* pointer to stats array */
+};
+
+#define PRIQ_IF_ATTACH _IOW('Q', 1, struct priq_interface)
+#define PRIQ_IF_DETACH _IOW('Q', 2, struct priq_interface)
+#define PRIQ_ENABLE _IOW('Q', 3, struct priq_interface)
+#define PRIQ_DISABLE _IOW('Q', 4, struct priq_interface)
+#define PRIQ_CLEAR _IOW('Q', 5, struct priq_interface)
+#define PRIQ_ADD_CLASS _IOWR('Q', 7, struct priq_add_class)
+#define PRIQ_DEL_CLASS _IOW('Q', 8, struct priq_delete_class)
+#define PRIQ_MOD_CLASS _IOW('Q', 9, struct priq_modify_class)
+#define PRIQ_ADD_FILTER _IOWR('Q', 10, struct priq_add_filter)
+#define PRIQ_DEL_FILTER _IOW('Q', 11, struct priq_delete_filter)
+#define PRIQ_GETSTATS _IOWR('Q', 12, struct priq_class_stats)
+
+#endif /* ALTQ3_COMPAT */
+
+#ifdef _KERNEL
+
+struct priq_class {
+ u_int32_t cl_handle; /* class handle */
+ class_queue_t *cl_q; /* class queue structure */
+ struct red *cl_red; /* RED state */
+ int cl_pri; /* priority */
+ int cl_flags; /* class flags */
+ struct priq_if *cl_pif; /* back pointer to pif */
+ struct altq_pktattr *cl_pktattr; /* saved header used by ECN */
+
+ /* statistics */
+ u_int cl_period; /* backlog period */
+ struct pktcntr cl_xmitcnt; /* transmitted packet counter */
+ struct pktcntr cl_dropcnt; /* dropped packet counter */
+};
+
+/*
+ * priq interface state
+ */
+struct priq_if {
+ struct priq_if *pif_next; /* interface state list */
+ struct ifaltq *pif_ifq; /* backpointer to ifaltq */
+ u_int pif_bandwidth; /* link bandwidth in bps */
+ int pif_maxpri; /* max priority in use */
+ struct priq_class *pif_default; /* default class */
+ struct priq_class *pif_classes[PRIQ_MAXPRI]; /* classes */
+#ifdef ALTQ3_CLFIER_COMPAT
+ struct acc_classifier pif_classifier; /* classifier */
+#endif
+};
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ALTQ_ALTQ_PRIQ_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_red.c b/freebsd/sys/contrib/altq/altq/altq_red.c
new file mode 100644
index 00000000..18fa7209
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_red.c
@@ -0,0 +1,1503 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_red.c,v 1.18 2003/09/05 22:40:36 itojun Exp $ */
+
+/*
+ * Copyright (C) 1997-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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) 1990-1994 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.
+ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#if (__FreeBSD__ != 2)
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+#ifdef ALTQ_RED /* red is enabled by ALTQ_RED option in opt_altq.h */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/errno.h>
+#if 1 /* ALTQ3_COMPAT */
+#include <freebsd/sys/sockio.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/kernel.h>
+#ifdef ALTQ_FLOWVALVE
+#include <freebsd/sys/queue.h>
+#include <freebsd/sys/time.h>
+#endif
+#endif /* ALTQ3_COMPAT */
+
+#include <freebsd/net/if.h>
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#endif
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_red.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/altq/altq_conf.h>
+#ifdef ALTQ_FLOWVALVE
+#include <freebsd/altq/altq_flowvalve.h>
+#endif
+#endif
+
+/*
+ * ALTQ/RED (Random Early Detection) implementation using 32-bit
+ * fixed-point calculation.
+ *
+ * written by kjc using the ns code as a reference.
+ * you can learn more about red and ns from Sally's home page at
+ * http://www-nrg.ee.lbl.gov/floyd/
+ *
+ * most of the red parameter values are fixed in this implementation
+ * to prevent fixed-point overflow/underflow.
+ * if you change the parameters, watch out for overflow/underflow!
+ *
+ * the parameters used are recommended values by Sally.
+ * the corresponding ns config looks:
+ * q_weight=0.00195
+ * minthresh=5 maxthresh=15 queue-size=60
+ * linterm=30
+ * dropmech=drop-tail
+ * bytes=false (can't be handled by 32-bit fixed-point)
+ * doubleq=false dqthresh=false
+ * wait=true
+ */
+/*
+ * alternative red parameters for a slow link.
+ *
+ * assume the queue length becomes from zero to L and keeps L, it takes
+ * N packets for q_avg to reach 63% of L.
+ * when q_weight is 0.002, N is about 500 packets.
+ * for a slow link like dial-up, 500 packets takes more than 1 minute!
+ * when q_weight is 0.008, N is about 127 packets.
+ * when q_weight is 0.016, N is about 63 packets.
+ * bursts of 50 packets are allowed for 0.002, bursts of 25 packets
+ * are allowed for 0.016.
+ * see Sally's paper for more details.
+ */
+/* normal red parameters */
+#define W_WEIGHT 512 /* inverse of weight of EWMA (511/512) */
+ /* q_weight = 0.00195 */
+
+/* red parameters for a slow link */
+#define W_WEIGHT_1 128 /* inverse of weight of EWMA (127/128) */
+ /* q_weight = 0.0078125 */
+
+/* red parameters for a very slow link (e.g., dialup) */
+#define W_WEIGHT_2 64 /* inverse of weight of EWMA (63/64) */
+ /* q_weight = 0.015625 */
+
+/* fixed-point uses 12-bit decimal places */
+#define FP_SHIFT 12 /* fixed-point shift */
+
+/* red parameters for drop probability */
+#define INV_P_MAX 10 /* inverse of max drop probability */
+#define TH_MIN 5 /* min threshold */
+#define TH_MAX 15 /* max threshold */
+
+#define RED_LIMIT 60 /* default max queue lenght */
+#define RED_STATS /* collect statistics */
+
+/*
+ * our default policy for forced-drop is drop-tail.
+ * (in altq-1.1.2 or earlier, the default was random-drop.
+ * but it makes more sense to punish the cause of the surge.)
+ * to switch to the random-drop policy, define "RED_RANDOM_DROP".
+ */
+
+#ifdef ALTQ3_COMPAT
+#ifdef ALTQ_FLOWVALVE
+/*
+ * flow-valve is an extention to protect red from unresponsive flows
+ * and to promote end-to-end congestion control.
+ * flow-valve observes the average drop rates of the flows that have
+ * experienced packet drops in the recent past.
+ * when the average drop rate exceeds the threshold, the flow is
+ * blocked by the flow-valve. the trapped flow should back off
+ * exponentially to escape from the flow-valve.
+ */
+#ifdef RED_RANDOM_DROP
+#error "random-drop can't be used with flow-valve!"
+#endif
+#endif /* ALTQ_FLOWVALVE */
+
+/* red_list keeps all red_queue_t's allocated. */
+static red_queue_t *red_list = NULL;
+
+#endif /* ALTQ3_COMPAT */
+
+/* default red parameter values */
+static int default_th_min = TH_MIN;
+static int default_th_max = TH_MAX;
+static int default_inv_pmax = INV_P_MAX;
+
+#ifdef ALTQ3_COMPAT
+/* internal function prototypes */
+static int red_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
+static struct mbuf *red_dequeue(struct ifaltq *, int);
+static int red_request(struct ifaltq *, int, void *);
+static void red_purgeq(red_queue_t *);
+static int red_detach(red_queue_t *);
+#ifdef ALTQ_FLOWVALVE
+static __inline struct fve *flowlist_lookup(struct flowvalve *,
+ struct altq_pktattr *, struct timeval *);
+static __inline struct fve *flowlist_reclaim(struct flowvalve *,
+ struct altq_pktattr *);
+static __inline void flowlist_move_to_head(struct flowvalve *, struct fve *);
+static __inline int fv_p2f(struct flowvalve *, int);
+#if 0 /* XXX: make the compiler happy (fv_alloc unused) */
+static struct flowvalve *fv_alloc(struct red *);
+#endif
+static void fv_destroy(struct flowvalve *);
+static int fv_checkflow(struct flowvalve *, struct altq_pktattr *,
+ struct fve **);
+static void fv_dropbyred(struct flowvalve *fv, struct altq_pktattr *,
+ struct fve *);
+#endif
+#endif /* ALTQ3_COMPAT */
+
+/*
+ * red support routines
+ */
+red_t *
+red_alloc(int weight, int inv_pmax, int th_min, int th_max, int flags,
+ int pkttime)
+{
+ red_t *rp;
+ int w, i;
+ int npkts_per_sec;
+
+ rp = malloc(sizeof(red_t), M_DEVBUF, M_WAITOK);
+ if (rp == NULL)
+ return (NULL);
+ bzero(rp, sizeof(red_t));
+
+ rp->red_avg = 0;
+ rp->red_idle = 1;
+
+ if (weight == 0)
+ rp->red_weight = W_WEIGHT;
+ else
+ rp->red_weight = weight;
+ if (inv_pmax == 0)
+ rp->red_inv_pmax = default_inv_pmax;
+ else
+ rp->red_inv_pmax = inv_pmax;
+ if (th_min == 0)
+ rp->red_thmin = default_th_min;
+ else
+ rp->red_thmin = th_min;
+ if (th_max == 0)
+ rp->red_thmax = default_th_max;
+ else
+ rp->red_thmax = th_max;
+
+ rp->red_flags = flags;
+
+ if (pkttime == 0)
+ /* default packet time: 1000 bytes / 10Mbps * 8 * 1000000 */
+ rp->red_pkttime = 800;
+ else
+ rp->red_pkttime = pkttime;
+
+ if (weight == 0) {
+ /* when the link is very slow, adjust red parameters */
+ npkts_per_sec = 1000000 / rp->red_pkttime;
+ if (npkts_per_sec < 50) {
+ /* up to about 400Kbps */
+ rp->red_weight = W_WEIGHT_2;
+ } else if (npkts_per_sec < 300) {
+ /* up to about 2.4Mbps */
+ rp->red_weight = W_WEIGHT_1;
+ }
+ }
+
+ /* calculate wshift. weight must be power of 2 */
+ w = rp->red_weight;
+ for (i = 0; w > 1; i++)
+ w = w >> 1;
+ rp->red_wshift = i;
+ w = 1 << rp->red_wshift;
+ if (w != rp->red_weight) {
+ printf("invalid weight value %d for red! use %d\n",
+ rp->red_weight, w);
+ rp->red_weight = w;
+ }
+
+ /*
+ * thmin_s and thmax_s are scaled versions of th_min and th_max
+ * to be compared with avg.
+ */
+ rp->red_thmin_s = rp->red_thmin << (rp->red_wshift + FP_SHIFT);
+ rp->red_thmax_s = rp->red_thmax << (rp->red_wshift + FP_SHIFT);
+
+ /*
+ * precompute probability denominator
+ * probd = (2 * (TH_MAX-TH_MIN) / pmax) in fixed-point
+ */
+ rp->red_probd = (2 * (rp->red_thmax - rp->red_thmin)
+ * rp->red_inv_pmax) << FP_SHIFT;
+
+ /* allocate weight table */
+ rp->red_wtab = wtab_alloc(rp->red_weight);
+
+ microtime(&rp->red_last);
+ return (rp);
+}
+
+void
+red_destroy(red_t *rp)
+{
+#ifdef ALTQ3_COMPAT
+#ifdef ALTQ_FLOWVALVE
+ if (rp->red_flowvalve != NULL)
+ fv_destroy(rp->red_flowvalve);
+#endif
+#endif /* ALTQ3_COMPAT */
+ wtab_destroy(rp->red_wtab);
+ free(rp, M_DEVBUF);
+}
+
+void
+red_getstats(red_t *rp, struct redstats *sp)
+{
+ sp->q_avg = rp->red_avg >> rp->red_wshift;
+ sp->xmit_cnt = rp->red_stats.xmit_cnt;
+ sp->drop_cnt = rp->red_stats.drop_cnt;
+ sp->drop_forced = rp->red_stats.drop_forced;
+ sp->drop_unforced = rp->red_stats.drop_unforced;
+ sp->marked_packets = rp->red_stats.marked_packets;
+}
+
+int
+red_addq(red_t *rp, class_queue_t *q, struct mbuf *m,
+ struct altq_pktattr *pktattr)
+{
+ int avg, droptype;
+ int n;
+#ifdef ALTQ3_COMPAT
+#ifdef ALTQ_FLOWVALVE
+ struct fve *fve = NULL;
+
+ if (rp->red_flowvalve != NULL && rp->red_flowvalve->fv_flows > 0)
+ if (fv_checkflow(rp->red_flowvalve, pktattr, &fve)) {
+ m_freem(m);
+ return (-1);
+ }
+#endif
+#endif /* ALTQ3_COMPAT */
+
+ avg = rp->red_avg;
+
+ /*
+ * if we were idle, we pretend that n packets arrived during
+ * the idle period.
+ */
+ if (rp->red_idle) {
+ struct timeval now;
+ int t;
+
+ rp->red_idle = 0;
+ microtime(&now);
+ t = (now.tv_sec - rp->red_last.tv_sec);
+ if (t > 60) {
+ /*
+ * being idle for more than 1 minute, set avg to zero.
+ * this prevents t from overflow.
+ */
+ avg = 0;
+ } else {
+ t = t * 1000000 + (now.tv_usec - rp->red_last.tv_usec);
+ n = t / rp->red_pkttime - 1;
+
+ /* the following line does (avg = (1 - Wq)^n * avg) */
+ if (n > 0)
+ avg = (avg >> FP_SHIFT) *
+ pow_w(rp->red_wtab, n);
+ }
+ }
+
+ /* run estimator. (note: avg is scaled by WEIGHT in fixed-point) */
+ avg += (qlen(q) << FP_SHIFT) - (avg >> rp->red_wshift);
+ rp->red_avg = avg; /* save the new value */
+
+ /*
+ * red_count keeps a tally of arriving traffic that has not
+ * been dropped.
+ */
+ rp->red_count++;
+
+ /* see if we drop early */
+ droptype = DTYPE_NODROP;
+ if (avg >= rp->red_thmin_s && qlen(q) > 1) {
+ if (avg >= rp->red_thmax_s) {
+ /* avg >= th_max: forced drop */
+ droptype = DTYPE_FORCED;
+ } else if (rp->red_old == 0) {
+ /* first exceeds th_min */
+ rp->red_count = 1;
+ rp->red_old = 1;
+ } else if (drop_early((avg - rp->red_thmin_s) >> rp->red_wshift,
+ rp->red_probd, rp->red_count)) {
+ /* mark or drop by red */
+ if ((rp->red_flags & REDF_ECN) &&
+ mark_ecn(m, pktattr, rp->red_flags)) {
+ /* successfully marked. do not drop. */
+ rp->red_count = 0;
+#ifdef RED_STATS
+ rp->red_stats.marked_packets++;
+#endif
+ } else {
+ /* unforced drop by red */
+ droptype = DTYPE_EARLY;
+ }
+ }
+ } else {
+ /* avg < th_min */
+ rp->red_old = 0;
+ }
+
+ /*
+ * if the queue length hits the hard limit, it's a forced drop.
+ */
+ if (droptype == DTYPE_NODROP && qlen(q) >= qlimit(q))
+ droptype = DTYPE_FORCED;
+
+#ifdef RED_RANDOM_DROP
+ /* if successful or forced drop, enqueue this packet. */
+ if (droptype != DTYPE_EARLY)
+ _addq(q, m);
+#else
+ /* if successful, enqueue this packet. */
+ if (droptype == DTYPE_NODROP)
+ _addq(q, m);
+#endif
+ if (droptype != DTYPE_NODROP) {
+ if (droptype == DTYPE_EARLY) {
+ /* drop the incoming packet */
+#ifdef RED_STATS
+ rp->red_stats.drop_unforced++;
+#endif
+ } else {
+ /* forced drop, select a victim packet in the queue. */
+#ifdef RED_RANDOM_DROP
+ m = _getq_random(q);
+#endif
+#ifdef RED_STATS
+ rp->red_stats.drop_forced++;
+#endif
+ }
+#ifdef RED_STATS
+ PKTCNTR_ADD(&rp->red_stats.drop_cnt, m_pktlen(m));
+#endif
+ rp->red_count = 0;
+#ifdef ALTQ3_COMPAT
+#ifdef ALTQ_FLOWVALVE
+ if (rp->red_flowvalve != NULL)
+ fv_dropbyred(rp->red_flowvalve, pktattr, fve);
+#endif
+#endif /* ALTQ3_COMPAT */
+ m_freem(m);
+ return (-1);
+ }
+ /* successfully queued */
+#ifdef RED_STATS
+ PKTCNTR_ADD(&rp->red_stats.xmit_cnt, m_pktlen(m));
+#endif
+ return (0);
+}
+
+/*
+ * early-drop probability is calculated as follows:
+ * prob = p_max * (avg - th_min) / (th_max - th_min)
+ * prob_a = prob / (2 - count*prob)
+ * = (avg-th_min) / (2*(th_max-th_min)*inv_p_max - count*(avg-th_min))
+ * here prob_a increases as successive undrop count increases.
+ * (prob_a starts from prob/2, becomes prob when (count == (1 / prob)),
+ * becomes 1 when (count >= (2 / prob))).
+ */
+int
+drop_early(int fp_len, int fp_probd, int count)
+{
+ int d; /* denominator of drop-probability */
+
+ d = fp_probd - count * fp_len;
+ if (d <= 0)
+ /* count exceeds the hard limit: drop or mark */
+ return (1);
+
+ /*
+ * now the range of d is [1..600] in fixed-point. (when
+ * th_max-th_min=10 and p_max=1/30)
+ * drop probability = (avg - TH_MIN) / d
+ */
+
+ if ((arc4random() % d) < fp_len) {
+ /* drop or mark */
+ return (1);
+ }
+ /* no drop/mark */
+ return (0);
+}
+
+/*
+ * try to mark CE bit to the packet.
+ * returns 1 if successfully marked, 0 otherwise.
+ */
+int
+mark_ecn(struct mbuf *m, struct altq_pktattr *pktattr, int flags)
+{
+ struct mbuf *m0;
+ struct pf_mtag *at;
+ void *hdr;
+ int af;
+
+ at = pf_find_mtag(m);
+ if (at != NULL) {
+ af = at->af;
+ hdr = at->hdr;
+#ifdef ALTQ3_COMPAT
+ } else if (pktattr != NULL) {
+ af = pktattr->pattr_af;
+ hdr = pktattr->pattr_hdr;
+#endif /* ALTQ3_COMPAT */
+ } else
+ return (0);
+
+ if (af != AF_INET && af != AF_INET6)
+ return (0);
+
+ /* verify that pattr_hdr is within the mbuf data */
+ for (m0 = m; m0 != NULL; m0 = m0->m_next)
+ if (((caddr_t)hdr >= m0->m_data) &&
+ ((caddr_t)hdr < m0->m_data + m0->m_len))
+ break;
+ if (m0 == NULL) {
+ /* ick, tag info is stale */
+ return (0);
+ }
+
+ switch (af) {
+ case AF_INET:
+ if (flags & REDF_ECN4) {
+ struct ip *ip = hdr;
+ u_int8_t otos;
+ int sum;
+
+ if (ip->ip_v != 4)
+ return (0); /* version mismatch! */
+
+ if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_NOTECT)
+ return (0); /* not-ECT */
+ if ((ip->ip_tos & IPTOS_ECN_MASK) == IPTOS_ECN_CE)
+ return (1); /* already marked */
+
+ /*
+ * ecn-capable but not marked,
+ * mark CE and update checksum
+ */
+ otos = ip->ip_tos;
+ ip->ip_tos |= IPTOS_ECN_CE;
+ /*
+ * update checksum (from RFC1624)
+ * HC' = ~(~HC + ~m + m')
+ */
+ sum = ~ntohs(ip->ip_sum) & 0xffff;
+ sum += (~otos & 0xffff) + ip->ip_tos;
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16); /* add carry */
+ ip->ip_sum = htons(~sum & 0xffff);
+ return (1);
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (flags & REDF_ECN6) {
+ struct ip6_hdr *ip6 = hdr;
+ u_int32_t flowlabel;
+
+ flowlabel = ntohl(ip6->ip6_flow);
+ if ((flowlabel >> 28) != 6)
+ return (0); /* version mismatch! */
+ if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
+ (IPTOS_ECN_NOTECT << 20))
+ return (0); /* not-ECT */
+ if ((flowlabel & (IPTOS_ECN_MASK << 20)) ==
+ (IPTOS_ECN_CE << 20))
+ return (1); /* already marked */
+ /*
+ * ecn-capable but not marked, mark CE
+ */
+ flowlabel |= (IPTOS_ECN_CE << 20);
+ ip6->ip6_flow = htonl(flowlabel);
+ return (1);
+ }
+ break;
+#endif /* INET6 */
+ }
+
+ /* not marked */
+ return (0);
+}
+
+struct mbuf *
+red_getq(rp, q)
+ red_t *rp;
+ class_queue_t *q;
+{
+ struct mbuf *m;
+
+ if ((m = _getq(q)) == NULL) {
+ if (rp->red_idle == 0) {
+ rp->red_idle = 1;
+ microtime(&rp->red_last);
+ }
+ return NULL;
+ }
+
+ rp->red_idle = 0;
+ return (m);
+}
+
+/*
+ * helper routine to calibrate avg during idle.
+ * pow_w(wtab, n) returns (1 - Wq)^n in fixed-point
+ * here Wq = 1/weight and the code assumes Wq is close to zero.
+ *
+ * w_tab[n] holds ((1 - Wq)^(2^n)) in fixed-point.
+ */
+static struct wtab *wtab_list = NULL; /* pointer to wtab list */
+
+struct wtab *
+wtab_alloc(int weight)
+{
+ struct wtab *w;
+ int i;
+
+ for (w = wtab_list; w != NULL; w = w->w_next)
+ if (w->w_weight == weight) {
+ w->w_refcount++;
+ return (w);
+ }
+
+ w = malloc(sizeof(struct wtab), M_DEVBUF, M_WAITOK);
+ if (w == NULL)
+ panic("wtab_alloc: malloc failed!");
+ bzero(w, sizeof(struct wtab));
+ w->w_weight = weight;
+ w->w_refcount = 1;
+ w->w_next = wtab_list;
+ wtab_list = w;
+
+ /* initialize the weight table */
+ w->w_tab[0] = ((weight - 1) << FP_SHIFT) / weight;
+ for (i = 1; i < 32; i++) {
+ w->w_tab[i] = (w->w_tab[i-1] * w->w_tab[i-1]) >> FP_SHIFT;
+ if (w->w_tab[i] == 0 && w->w_param_max == 0)
+ w->w_param_max = 1 << i;
+ }
+
+ return (w);
+}
+
+int
+wtab_destroy(struct wtab *w)
+{
+ struct wtab *prev;
+
+ if (--w->w_refcount > 0)
+ return (0);
+
+ if (wtab_list == w)
+ wtab_list = w->w_next;
+ else for (prev = wtab_list; prev->w_next != NULL; prev = prev->w_next)
+ if (prev->w_next == w) {
+ prev->w_next = w->w_next;
+ break;
+ }
+
+ free(w, M_DEVBUF);
+ return (0);
+}
+
+int32_t
+pow_w(struct wtab *w, int n)
+{
+ int i, bit;
+ int32_t val;
+
+ if (n >= w->w_param_max)
+ return (0);
+
+ val = 1 << FP_SHIFT;
+ if (n <= 0)
+ return (val);
+
+ bit = 1;
+ i = 0;
+ while (n) {
+ if (n & bit) {
+ val = (val * w->w_tab[i]) >> FP_SHIFT;
+ n &= ~bit;
+ }
+ i++;
+ bit <<= 1;
+ }
+ return (val);
+}
+
+#ifdef ALTQ3_COMPAT
+/*
+ * red device interface
+ */
+altqdev_decl(red);
+
+int
+redopen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ /* everything will be done when the queueing scheme is attached. */
+ return 0;
+}
+
+int
+redclose(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ red_queue_t *rqp;
+ int err, error = 0;
+
+ while ((rqp = red_list) != NULL) {
+ /* destroy all */
+ err = red_detach(rqp);
+ if (err != 0 && error == 0)
+ error = err;
+ }
+
+ return error;
+}
+
+int
+redioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ ioctlcmd_t cmd;
+ caddr_t addr;
+ int flag;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ red_queue_t *rqp;
+ struct red_interface *ifacep;
+ struct ifnet *ifp;
+ int error = 0;
+
+ /* check super-user privilege */
+ switch (cmd) {
+ case RED_GETSTATS:
+ break;
+ default:
+#if (__FreeBSD_version > 700000)
+ if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+#elsif (__FreeBSD_version > 400000)
+ if ((error = suser(p)) != 0)
+#else
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+#endif
+ return (error);
+ break;
+ }
+
+ switch (cmd) {
+
+ case RED_ENABLE:
+ ifacep = (struct red_interface *)addr;
+ if ((rqp = altq_lookup(ifacep->red_ifname, ALTQT_RED)) == NULL) {
+ error = EBADF;
+ break;
+ }
+ error = altq_enable(rqp->rq_ifq);
+ break;
+
+ case RED_DISABLE:
+ ifacep = (struct red_interface *)addr;
+ if ((rqp = altq_lookup(ifacep->red_ifname, ALTQT_RED)) == NULL) {
+ error = EBADF;
+ break;
+ }
+ error = altq_disable(rqp->rq_ifq);
+ break;
+
+ case RED_IF_ATTACH:
+ ifp = ifunit(((struct red_interface *)addr)->red_ifname);
+ if (ifp == NULL) {
+ error = ENXIO;
+ break;
+ }
+
+ /* allocate and initialize red_queue_t */
+ rqp = malloc(sizeof(red_queue_t), M_DEVBUF, M_WAITOK);
+ if (rqp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bzero(rqp, sizeof(red_queue_t));
+
+ rqp->rq_q = malloc(sizeof(class_queue_t),
+ M_DEVBUF, M_WAITOK);
+ if (rqp->rq_q == NULL) {
+ free(rqp, M_DEVBUF);
+ error = ENOMEM;
+ break;
+ }
+ bzero(rqp->rq_q, sizeof(class_queue_t));
+
+ rqp->rq_red = red_alloc(0, 0, 0, 0, 0, 0);
+ if (rqp->rq_red == NULL) {
+ free(rqp->rq_q, M_DEVBUF);
+ free(rqp, M_DEVBUF);
+ error = ENOMEM;
+ break;
+ }
+
+ rqp->rq_ifq = &ifp->if_snd;
+ qtail(rqp->rq_q) = NULL;
+ qlen(rqp->rq_q) = 0;
+ qlimit(rqp->rq_q) = RED_LIMIT;
+ qtype(rqp->rq_q) = Q_RED;
+
+ /*
+ * set RED to this ifnet structure.
+ */
+ error = altq_attach(rqp->rq_ifq, ALTQT_RED, rqp,
+ red_enqueue, red_dequeue, red_request,
+ NULL, NULL);
+ if (error) {
+ red_destroy(rqp->rq_red);
+ free(rqp->rq_q, M_DEVBUF);
+ free(rqp, M_DEVBUF);
+ break;
+ }
+
+ /* add this state to the red list */
+ rqp->rq_next = red_list;
+ red_list = rqp;
+ break;
+
+ case RED_IF_DETACH:
+ ifacep = (struct red_interface *)addr;
+ if ((rqp = altq_lookup(ifacep->red_ifname, ALTQT_RED)) == NULL) {
+ error = EBADF;
+ break;
+ }
+ error = red_detach(rqp);
+ break;
+
+ case RED_GETSTATS:
+ do {
+ struct red_stats *q_stats;
+ red_t *rp;
+
+ q_stats = (struct red_stats *)addr;
+ if ((rqp = altq_lookup(q_stats->iface.red_ifname,
+ ALTQT_RED)) == NULL) {
+ error = EBADF;
+ break;
+ }
+
+ q_stats->q_len = qlen(rqp->rq_q);
+ q_stats->q_limit = qlimit(rqp->rq_q);
+
+ rp = rqp->rq_red;
+ q_stats->q_avg = rp->red_avg >> rp->red_wshift;
+ q_stats->xmit_cnt = rp->red_stats.xmit_cnt;
+ q_stats->drop_cnt = rp->red_stats.drop_cnt;
+ q_stats->drop_forced = rp->red_stats.drop_forced;
+ q_stats->drop_unforced = rp->red_stats.drop_unforced;
+ q_stats->marked_packets = rp->red_stats.marked_packets;
+
+ q_stats->weight = rp->red_weight;
+ q_stats->inv_pmax = rp->red_inv_pmax;
+ q_stats->th_min = rp->red_thmin;
+ q_stats->th_max = rp->red_thmax;
+
+#ifdef ALTQ_FLOWVALVE
+ if (rp->red_flowvalve != NULL) {
+ struct flowvalve *fv = rp->red_flowvalve;
+ q_stats->fv_flows = fv->fv_flows;
+ q_stats->fv_pass = fv->fv_stats.pass;
+ q_stats->fv_predrop = fv->fv_stats.predrop;
+ q_stats->fv_alloc = fv->fv_stats.alloc;
+ q_stats->fv_escape = fv->fv_stats.escape;
+ } else {
+#endif /* ALTQ_FLOWVALVE */
+ q_stats->fv_flows = 0;
+ q_stats->fv_pass = 0;
+ q_stats->fv_predrop = 0;
+ q_stats->fv_alloc = 0;
+ q_stats->fv_escape = 0;
+#ifdef ALTQ_FLOWVALVE
+ }
+#endif /* ALTQ_FLOWVALVE */
+ } while (/*CONSTCOND*/ 0);
+ break;
+
+ case RED_CONFIG:
+ do {
+ struct red_conf *fc;
+ red_t *new;
+ int s, limit;
+
+ fc = (struct red_conf *)addr;
+ if ((rqp = altq_lookup(fc->iface.red_ifname,
+ ALTQT_RED)) == NULL) {
+ error = EBADF;
+ break;
+ }
+ new = red_alloc(fc->red_weight,
+ fc->red_inv_pmax,
+ fc->red_thmin,
+ fc->red_thmax,
+ fc->red_flags,
+ fc->red_pkttime);
+ if (new == NULL) {
+ error = ENOMEM;
+ break;
+ }
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ red_purgeq(rqp);
+ limit = fc->red_limit;
+ if (limit < fc->red_thmax)
+ limit = fc->red_thmax;
+ qlimit(rqp->rq_q) = limit;
+ fc->red_limit = limit; /* write back the new value */
+
+ red_destroy(rqp->rq_red);
+ rqp->rq_red = new;
+
+ splx(s);
+
+ /* write back new values */
+ fc->red_limit = limit;
+ fc->red_inv_pmax = rqp->rq_red->red_inv_pmax;
+ fc->red_thmin = rqp->rq_red->red_thmin;
+ fc->red_thmax = rqp->rq_red->red_thmax;
+
+ } while (/*CONSTCOND*/ 0);
+ break;
+
+ case RED_SETDEFAULTS:
+ do {
+ struct redparams *rp;
+
+ rp = (struct redparams *)addr;
+
+ default_th_min = rp->th_min;
+ default_th_max = rp->th_max;
+ default_inv_pmax = rp->inv_pmax;
+ } while (/*CONSTCOND*/ 0);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static int
+red_detach(rqp)
+ red_queue_t *rqp;
+{
+ red_queue_t *tmp;
+ int error = 0;
+
+ if (ALTQ_IS_ENABLED(rqp->rq_ifq))
+ altq_disable(rqp->rq_ifq);
+
+ if ((error = altq_detach(rqp->rq_ifq)))
+ return (error);
+
+ if (red_list == rqp)
+ red_list = rqp->rq_next;
+ else {
+ for (tmp = red_list; tmp != NULL; tmp = tmp->rq_next)
+ if (tmp->rq_next == rqp) {
+ tmp->rq_next = rqp->rq_next;
+ break;
+ }
+ if (tmp == NULL)
+ printf("red_detach: no state found in red_list!\n");
+ }
+
+ red_destroy(rqp->rq_red);
+ free(rqp->rq_q, M_DEVBUF);
+ free(rqp, M_DEVBUF);
+ return (error);
+}
+
+/*
+ * enqueue routine:
+ *
+ * returns: 0 when successfully queued.
+ * ENOBUFS when drop occurs.
+ */
+static int
+red_enqueue(ifq, m, pktattr)
+ struct ifaltq *ifq;
+ struct mbuf *m;
+ struct altq_pktattr *pktattr;
+{
+ red_queue_t *rqp = (red_queue_t *)ifq->altq_disc;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ if (red_addq(rqp->rq_red, rqp->rq_q, m, pktattr) < 0)
+ return ENOBUFS;
+ ifq->ifq_len++;
+ return 0;
+}
+
+/*
+ * dequeue routine:
+ * must be called in splimp.
+ *
+ * returns: mbuf dequeued.
+ * NULL when no packet is available in the queue.
+ */
+
+static struct mbuf *
+red_dequeue(ifq, op)
+ struct ifaltq *ifq;
+ int op;
+{
+ red_queue_t *rqp = (red_queue_t *)ifq->altq_disc;
+ struct mbuf *m;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ if (op == ALTDQ_POLL)
+ return qhead(rqp->rq_q);
+
+ /* op == ALTDQ_REMOVE */
+ m = red_getq(rqp->rq_red, rqp->rq_q);
+ if (m != NULL)
+ ifq->ifq_len--;
+ return (m);
+}
+
+static int
+red_request(ifq, req, arg)
+ struct ifaltq *ifq;
+ int req;
+ void *arg;
+{
+ red_queue_t *rqp = (red_queue_t *)ifq->altq_disc;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ switch (req) {
+ case ALTRQ_PURGE:
+ red_purgeq(rqp);
+ break;
+ }
+ return (0);
+}
+
+static void
+red_purgeq(rqp)
+ red_queue_t *rqp;
+{
+ _flushq(rqp->rq_q);
+ if (ALTQ_IS_ENABLED(rqp->rq_ifq))
+ rqp->rq_ifq->ifq_len = 0;
+}
+
+#ifdef ALTQ_FLOWVALVE
+
+#define FV_PSHIFT 7 /* weight of average drop rate -- 1/128 */
+#define FV_PSCALE(x) ((x) << FV_PSHIFT)
+#define FV_PUNSCALE(x) ((x) >> FV_PSHIFT)
+#define FV_FSHIFT 5 /* weight of average fraction -- 1/32 */
+#define FV_FSCALE(x) ((x) << FV_FSHIFT)
+#define FV_FUNSCALE(x) ((x) >> FV_FSHIFT)
+
+#define FV_TIMER (3 * hz) /* timer value for garbage collector */
+#define FV_FLOWLISTSIZE 64 /* how many flows in flowlist */
+
+#define FV_N 10 /* update fve_f every FV_N packets */
+
+#define FV_BACKOFFTHRESH 1 /* backoff threshold interval in second */
+#define FV_TTHRESH 3 /* time threshold to delete fve */
+#define FV_ALPHA 5 /* extra packet count */
+
+#define FV_STATS
+
+#if (__FreeBSD_version > 300000)
+#define FV_TIMESTAMP(tp) getmicrotime(tp)
+#else
+#define FV_TIMESTAMP(tp) { (*(tp)) = time; }
+#endif
+
+/*
+ * Brtt table: 127 entry table to convert drop rate (p) to
+ * the corresponding bandwidth fraction (f)
+ * the following equation is implemented to use scaled values,
+ * fve_p and fve_f, in the fixed point format.
+ *
+ * Brtt(p) = 1 /(sqrt(4*p/3) + min(1,3*sqrt(p*6/8)) * p * (1+32 * p*p))
+ * f = Brtt(p) / (max_th + alpha)
+ */
+#define BRTT_SIZE 128
+#define BRTT_SHIFT 12
+#define BRTT_MASK 0x0007f000
+#define BRTT_PMAX (1 << (FV_PSHIFT + FP_SHIFT))
+
+const int brtt_tab[BRTT_SIZE] = {
+ 0, 1262010, 877019, 703694, 598706, 525854, 471107, 427728,
+ 392026, 361788, 335598, 312506, 291850, 273158, 256081, 240361,
+ 225800, 212247, 199585, 187788, 178388, 169544, 161207, 153333,
+ 145888, 138841, 132165, 125836, 119834, 114141, 108739, 103612,
+ 98747, 94129, 89746, 85585, 81637, 77889, 74333, 70957,
+ 67752, 64711, 61824, 59084, 56482, 54013, 51667, 49440,
+ 47325, 45315, 43406, 41591, 39866, 38227, 36667, 35184,
+ 33773, 32430, 31151, 29933, 28774, 27668, 26615, 25611,
+ 24653, 23740, 22868, 22035, 21240, 20481, 19755, 19062,
+ 18399, 17764, 17157, 16576, 16020, 15487, 14976, 14487,
+ 14017, 13567, 13136, 12721, 12323, 11941, 11574, 11222,
+ 10883, 10557, 10243, 9942, 9652, 9372, 9103, 8844,
+ 8594, 8354, 8122, 7898, 7682, 7474, 7273, 7079,
+ 6892, 6711, 6536, 6367, 6204, 6046, 5893, 5746,
+ 5603, 5464, 5330, 5201, 5075, 4954, 4836, 4722,
+ 4611, 4504, 4400, 4299, 4201, 4106, 4014, 3924
+};
+
+static __inline struct fve *
+flowlist_lookup(fv, pktattr, now)
+ struct flowvalve *fv;
+ struct altq_pktattr *pktattr;
+ struct timeval *now;
+{
+ struct fve *fve;
+ int flows;
+ struct ip *ip;
+#ifdef INET6
+ struct ip6_hdr *ip6;
+#endif
+ struct timeval tthresh;
+
+ if (pktattr == NULL)
+ return (NULL);
+
+ tthresh.tv_sec = now->tv_sec - FV_TTHRESH;
+ flows = 0;
+ /*
+ * search the flow list
+ */
+ switch (pktattr->pattr_af) {
+ case AF_INET:
+ ip = (struct ip *)pktattr->pattr_hdr;
+ TAILQ_FOREACH(fve, &fv->fv_flowlist, fve_lru){
+ if (fve->fve_lastdrop.tv_sec == 0)
+ break;
+ if (fve->fve_lastdrop.tv_sec < tthresh.tv_sec) {
+ fve->fve_lastdrop.tv_sec = 0;
+ break;
+ }
+ if (fve->fve_flow.flow_af == AF_INET &&
+ fve->fve_flow.flow_ip.ip_src.s_addr ==
+ ip->ip_src.s_addr &&
+ fve->fve_flow.flow_ip.ip_dst.s_addr ==
+ ip->ip_dst.s_addr)
+ return (fve);
+ flows++;
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
+ TAILQ_FOREACH(fve, &fv->fv_flowlist, fve_lru){
+ if (fve->fve_lastdrop.tv_sec == 0)
+ break;
+ if (fve->fve_lastdrop.tv_sec < tthresh.tv_sec) {
+ fve->fve_lastdrop.tv_sec = 0;
+ break;
+ }
+ if (fve->fve_flow.flow_af == AF_INET6 &&
+ IN6_ARE_ADDR_EQUAL(&fve->fve_flow.flow_ip6.ip6_src,
+ &ip6->ip6_src) &&
+ IN6_ARE_ADDR_EQUAL(&fve->fve_flow.flow_ip6.ip6_dst,
+ &ip6->ip6_dst))
+ return (fve);
+ flows++;
+ }
+ break;
+#endif /* INET6 */
+
+ default:
+ /* unknown protocol. no drop. */
+ return (NULL);
+ }
+ fv->fv_flows = flows; /* save the number of active fve's */
+ return (NULL);
+}
+
+static __inline struct fve *
+flowlist_reclaim(fv, pktattr)
+ struct flowvalve *fv;
+ struct altq_pktattr *pktattr;
+{
+ struct fve *fve;
+ struct ip *ip;
+#ifdef INET6
+ struct ip6_hdr *ip6;
+#endif
+
+ /*
+ * get an entry from the tail of the LRU list.
+ */
+ fve = TAILQ_LAST(&fv->fv_flowlist, fv_flowhead);
+
+ switch (pktattr->pattr_af) {
+ case AF_INET:
+ ip = (struct ip *)pktattr->pattr_hdr;
+ fve->fve_flow.flow_af = AF_INET;
+ fve->fve_flow.flow_ip.ip_src = ip->ip_src;
+ fve->fve_flow.flow_ip.ip_dst = ip->ip_dst;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
+ fve->fve_flow.flow_af = AF_INET6;
+ fve->fve_flow.flow_ip6.ip6_src = ip6->ip6_src;
+ fve->fve_flow.flow_ip6.ip6_dst = ip6->ip6_dst;
+ break;
+#endif
+ }
+
+ fve->fve_state = Green;
+ fve->fve_p = 0.0;
+ fve->fve_f = 0.0;
+ fve->fve_ifseq = fv->fv_ifseq - 1;
+ fve->fve_count = 0;
+
+ fv->fv_flows++;
+#ifdef FV_STATS
+ fv->fv_stats.alloc++;
+#endif
+ return (fve);
+}
+
+static __inline void
+flowlist_move_to_head(fv, fve)
+ struct flowvalve *fv;
+ struct fve *fve;
+{
+ if (TAILQ_FIRST(&fv->fv_flowlist) != fve) {
+ TAILQ_REMOVE(&fv->fv_flowlist, fve, fve_lru);
+ TAILQ_INSERT_HEAD(&fv->fv_flowlist, fve, fve_lru);
+ }
+}
+
+#if 0 /* XXX: make the compiler happy (fv_alloc unused) */
+/*
+ * allocate flowvalve structure
+ */
+static struct flowvalve *
+fv_alloc(rp)
+ struct red *rp;
+{
+ struct flowvalve *fv;
+ struct fve *fve;
+ int i, num;
+
+ num = FV_FLOWLISTSIZE;
+ fv = malloc(sizeof(struct flowvalve),
+ M_DEVBUF, M_WAITOK);
+ if (fv == NULL)
+ return (NULL);
+ bzero(fv, sizeof(struct flowvalve));
+
+ fv->fv_fves = malloc(sizeof(struct fve) * num,
+ M_DEVBUF, M_WAITOK);
+ if (fv->fv_fves == NULL) {
+ free(fv, M_DEVBUF);
+ return (NULL);
+ }
+ bzero(fv->fv_fves, sizeof(struct fve) * num);
+
+ fv->fv_flows = 0;
+ TAILQ_INIT(&fv->fv_flowlist);
+ for (i = 0; i < num; i++) {
+ fve = &fv->fv_fves[i];
+ fve->fve_lastdrop.tv_sec = 0;
+ TAILQ_INSERT_TAIL(&fv->fv_flowlist, fve, fve_lru);
+ }
+
+ /* initialize drop rate threshold in scaled fixed-point */
+ fv->fv_pthresh = (FV_PSCALE(1) << FP_SHIFT) / rp->red_inv_pmax;
+
+ /* initialize drop rate to fraction table */
+ fv->fv_p2ftab = malloc(sizeof(int) * BRTT_SIZE,
+ M_DEVBUF, M_WAITOK);
+ if (fv->fv_p2ftab == NULL) {
+ free(fv->fv_fves, M_DEVBUF);
+ free(fv, M_DEVBUF);
+ return (NULL);
+ }
+ /*
+ * create the p2f table.
+ * (shift is used to keep the precision)
+ */
+ for (i = 1; i < BRTT_SIZE; i++) {
+ int f;
+
+ f = brtt_tab[i] << 8;
+ fv->fv_p2ftab[i] = (f / (rp->red_thmax + FV_ALPHA)) >> 8;
+ }
+
+ return (fv);
+}
+#endif
+
+static void fv_destroy(fv)
+ struct flowvalve *fv;
+{
+ free(fv->fv_p2ftab, M_DEVBUF);
+ free(fv->fv_fves, M_DEVBUF);
+ free(fv, M_DEVBUF);
+}
+
+static __inline int
+fv_p2f(fv, p)
+ struct flowvalve *fv;
+ int p;
+{
+ int val, f;
+
+ if (p >= BRTT_PMAX)
+ f = fv->fv_p2ftab[BRTT_SIZE-1];
+ else if ((val = (p & BRTT_MASK)))
+ f = fv->fv_p2ftab[(val >> BRTT_SHIFT)];
+ else
+ f = fv->fv_p2ftab[1];
+ return (f);
+}
+
+/*
+ * check if an arriving packet should be pre-dropped.
+ * called from red_addq() when a packet arrives.
+ * returns 1 when the packet should be pre-dropped.
+ * should be called in splimp.
+ */
+static int
+fv_checkflow(fv, pktattr, fcache)
+ struct flowvalve *fv;
+ struct altq_pktattr *pktattr;
+ struct fve **fcache;
+{
+ struct fve *fve;
+ struct timeval now;
+
+ fv->fv_ifseq++;
+ FV_TIMESTAMP(&now);
+
+ if ((fve = flowlist_lookup(fv, pktattr, &now)) == NULL)
+ /* no matching entry in the flowlist */
+ return (0);
+
+ *fcache = fve;
+
+ /* update fraction f for every FV_N packets */
+ if (++fve->fve_count == FV_N) {
+ /*
+ * f = Wf * N / (fv_ifseq - fve_ifseq) + (1 - Wf) * f
+ */
+ fve->fve_f =
+ (FV_N << FP_SHIFT) / (fv->fv_ifseq - fve->fve_ifseq)
+ + fve->fve_f - FV_FUNSCALE(fve->fve_f);
+ fve->fve_ifseq = fv->fv_ifseq;
+ fve->fve_count = 0;
+ }
+
+ /*
+ * overpumping test
+ */
+ if (fve->fve_state == Green && fve->fve_p > fv->fv_pthresh) {
+ int fthresh;
+
+ /* calculate a threshold */
+ fthresh = fv_p2f(fv, fve->fve_p);
+ if (fve->fve_f > fthresh)
+ fve->fve_state = Red;
+ }
+
+ if (fve->fve_state == Red) {
+ /*
+ * backoff test
+ */
+ if (now.tv_sec - fve->fve_lastdrop.tv_sec > FV_BACKOFFTHRESH) {
+ /* no drop for at least FV_BACKOFFTHRESH sec */
+ fve->fve_p = 0;
+ fve->fve_state = Green;
+#ifdef FV_STATS
+ fv->fv_stats.escape++;
+#endif
+ } else {
+ /* block this flow */
+ flowlist_move_to_head(fv, fve);
+ fve->fve_lastdrop = now;
+#ifdef FV_STATS
+ fv->fv_stats.predrop++;
+#endif
+ return (1);
+ }
+ }
+
+ /*
+ * p = (1 - Wp) * p
+ */
+ fve->fve_p -= FV_PUNSCALE(fve->fve_p);
+ if (fve->fve_p < 0)
+ fve->fve_p = 0;
+#ifdef FV_STATS
+ fv->fv_stats.pass++;
+#endif
+ return (0);
+}
+
+/*
+ * called from red_addq when a packet is dropped by red.
+ * should be called in splimp.
+ */
+static void fv_dropbyred(fv, pktattr, fcache)
+ struct flowvalve *fv;
+ struct altq_pktattr *pktattr;
+ struct fve *fcache;
+{
+ struct fve *fve;
+ struct timeval now;
+
+ if (pktattr == NULL)
+ return;
+ FV_TIMESTAMP(&now);
+
+ if (fcache != NULL)
+ /* the fve of this packet is already cached */
+ fve = fcache;
+ else if ((fve = flowlist_lookup(fv, pktattr, &now)) == NULL)
+ fve = flowlist_reclaim(fv, pktattr);
+
+ flowlist_move_to_head(fv, fve);
+
+ /*
+ * update p: the following line cancels the update
+ * in fv_checkflow() and calculate
+ * p = Wp + (1 - Wp) * p
+ */
+ fve->fve_p = (1 << FP_SHIFT) + fve->fve_p;
+
+ fve->fve_lastdrop = now;
+}
+
+#endif /* ALTQ_FLOWVALVE */
+
+#ifdef KLD_MODULE
+
+static struct altqsw red_sw =
+ {"red", redopen, redclose, redioctl};
+
+ALTQ_MODULE(altq_red, ALTQT_RED, &red_sw);
+MODULE_VERSION(altq_red, 1);
+
+#endif /* KLD_MODULE */
+#endif /* ALTQ3_COMPAT */
+
+#endif /* ALTQ_RED */
diff --git a/freebsd/sys/contrib/altq/altq/altq_red.h b/freebsd/sys/contrib/altq/altq/altq_red.h
new file mode 100644
index 00000000..2d267101
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_red.h
@@ -0,0 +1,198 @@
+/* $KAME: altq_red.h,v 1.8 2003/07/10 12:07:49 kjc Exp $ */
+
+/*
+ * Copyright (C) 1997-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 _ALTQ_ALTQ_RED_HH_
+#define _ALTQ_ALTQ_RED_HH_
+
+#include <freebsd/altq/altq_classq.h>
+
+#ifdef ALTQ3_COMPAT
+struct red_interface {
+ char red_ifname[IFNAMSIZ];
+};
+
+struct red_stats {
+ struct red_interface iface;
+ int q_len;
+ int q_avg;
+
+ struct pktcntr xmit_cnt;
+ struct pktcntr drop_cnt;
+ u_int drop_forced;
+ u_int drop_unforced;
+ u_int marked_packets;
+
+ /* static red parameters */
+ int q_limit;
+ int weight;
+ int inv_pmax;
+ int th_min;
+ int th_max;
+
+ /* flowvalve related stuff */
+ u_int fv_flows;
+ u_int fv_pass;
+ u_int fv_predrop;
+ u_int fv_alloc;
+ u_int fv_escape;
+};
+
+struct red_conf {
+ struct red_interface iface;
+ int red_weight; /* weight for EWMA */
+ int red_inv_pmax; /* inverse of max drop probability */
+ int red_thmin; /* red min threshold */
+ int red_thmax; /* red max threshold */
+ int red_limit; /* max queue length */
+ int red_pkttime; /* average packet time in usec */
+ int red_flags; /* see below */
+};
+#endif /* ALTQ3_COMPAT */
+
+/* red flags */
+#define REDF_ECN4 0x01 /* use packet marking for IPv4 packets */
+#define REDF_ECN6 0x02 /* use packet marking for IPv6 packets */
+#define REDF_ECN (REDF_ECN4 | REDF_ECN6)
+#define REDF_FLOWVALVE 0x04 /* use flowvalve (aka penalty-box) */
+
+/*
+ * simpler versions of red parameters and statistics used by other
+ * disciplines (e.g., CBQ)
+ */
+struct redparams {
+ int th_min; /* red min threshold */
+ int th_max; /* red max threshold */
+ int inv_pmax; /* inverse of max drop probability */
+};
+
+struct redstats {
+ int q_avg;
+ struct pktcntr xmit_cnt;
+ struct pktcntr drop_cnt;
+ u_int drop_forced;
+ u_int drop_unforced;
+ u_int marked_packets;
+};
+
+#ifdef ALTQ3_COMPAT
+/*
+ * IOCTLs for RED
+ */
+#define RED_IF_ATTACH _IOW('Q', 1, struct red_interface)
+#define RED_IF_DETACH _IOW('Q', 2, struct red_interface)
+#define RED_ENABLE _IOW('Q', 3, struct red_interface)
+#define RED_DISABLE _IOW('Q', 4, struct red_interface)
+#define RED_CONFIG _IOWR('Q', 6, struct red_conf)
+#define RED_GETSTATS _IOWR('Q', 12, struct red_stats)
+#define RED_SETDEFAULTS _IOW('Q', 30, struct redparams)
+#endif /* ALTQ3_COMPAT */
+
+#ifdef _KERNEL
+
+#ifdef ALTQ3_COMPAT
+struct flowvalve;
+#endif
+
+/* weight table structure for idle time calibration */
+struct wtab {
+ struct wtab *w_next;
+ int w_weight;
+ int w_param_max;
+ int w_refcount;
+ int32_t w_tab[32];
+};
+
+typedef struct red {
+ int red_pkttime; /* average packet time in micro sec
+ used for idle calibration */
+ int red_flags; /* red flags */
+
+ /* red parameters */
+ int red_weight; /* weight for EWMA */
+ int red_inv_pmax; /* inverse of max drop probability */
+ int red_thmin; /* red min threshold */
+ int red_thmax; /* red max threshold */
+
+ /* variables for internal use */
+ int red_wshift; /* log(red_weight) */
+ int red_thmin_s; /* th_min scaled by avgshift */
+ int red_thmax_s; /* th_max scaled by avgshift */
+ int red_probd; /* drop probability denominator */
+
+ int red_avg; /* queue len avg scaled by avgshift */
+ int red_count; /* packet count since last dropped/
+ marked packet */
+ int red_idle; /* queue was empty */
+ int red_old; /* avg is above th_min */
+ struct wtab *red_wtab; /* weight table */
+ struct timeval red_last; /* time when the queue becomes idle */
+
+#ifdef ALTQ3_COMPAT
+ struct flowvalve *red_flowvalve; /* flowvalve state */
+#endif
+
+ struct {
+ struct pktcntr xmit_cnt;
+ struct pktcntr drop_cnt;
+ u_int drop_forced;
+ u_int drop_unforced;
+ u_int marked_packets;
+ } red_stats;
+} red_t;
+
+#ifdef ALTQ3_COMPAT
+typedef struct red_queue {
+ struct red_queue *rq_next; /* next red_state in the list */
+ struct ifaltq *rq_ifq; /* backpointer to ifaltq */
+
+ class_queue_t *rq_q;
+
+ red_t *rq_red;
+} red_queue_t;
+#endif /* ALTQ3_COMPAT */
+
+/* red drop types */
+#define DTYPE_NODROP 0 /* no drop */
+#define DTYPE_FORCED 1 /* a "forced" drop */
+#define DTYPE_EARLY 2 /* an "unforced" (early) drop */
+
+extern red_t *red_alloc(int, int, int, int, int, int);
+extern void red_destroy(red_t *);
+extern void red_getstats(red_t *, struct redstats *);
+extern int red_addq(red_t *, class_queue_t *, struct mbuf *,
+ struct altq_pktattr *);
+extern struct mbuf *red_getq(red_t *, class_queue_t *);
+extern int drop_early(int, int, int);
+extern int mark_ecn(struct mbuf *, struct altq_pktattr *, int);
+extern struct wtab *wtab_alloc(int);
+extern int wtab_destroy(struct wtab *);
+extern int32_t pow_w(struct wtab *, int);
+
+#endif /* _KERNEL */
+
+#endif /* _ALTQ_ALTQ_RED_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_rio.c b/freebsd/sys/contrib/altq/altq/altq_rio.c
new file mode 100644
index 00000000..33a5fce6
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_rio.c
@@ -0,0 +1,855 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_rio.c,v 1.17 2003/07/10 12:07:49 kjc Exp $ */
+
+/*
+ * Copyright (C) 1998-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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) 1990-1994 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.
+ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#if (__FreeBSD__ != 2)
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+#ifdef ALTQ_RIO /* rio is enabled by ALTQ_RIO option in opt_altq.h */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/errno.h>
+#if 1 /* ALTQ3_COMPAT */
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/sockio.h>
+#include <freebsd/sys/kernel.h>
+#endif
+
+#include <freebsd/net/if.h>
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#endif
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_cdnr.h>
+#include <freebsd/altq/altq_red.h>
+#include <freebsd/altq/altq_rio.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/altq/altq_conf.h>
+#endif
+
+/*
+ * RIO: RED with IN/OUT bit
+ * described in
+ * "Explicit Allocation of Best Effort Packet Delivery Service"
+ * David D. Clark and Wenjia Fang, MIT Lab for Computer Science
+ * http://diffserv.lcs.mit.edu/Papers/exp-alloc-ddc-wf.{ps,pdf}
+ *
+ * this implementation is extended to support more than 2 drop precedence
+ * values as described in RFC2597 (Assured Forwarding PHB Group).
+ *
+ */
+/*
+ * AF DS (differentiated service) codepoints.
+ * (classes can be mapped to CBQ or H-FSC classes.)
+ *
+ * 0 1 2 3 4 5 6 7
+ * +---+---+---+---+---+---+---+---+
+ * | CLASS |DropPre| 0 | CU |
+ * +---+---+---+---+---+---+---+---+
+ *
+ * class 1: 001
+ * class 2: 010
+ * class 3: 011
+ * class 4: 100
+ *
+ * low drop prec: 01
+ * medium drop prec: 10
+ * high drop prec: 01
+ */
+
+/* normal red parameters */
+#define W_WEIGHT 512 /* inverse of weight of EWMA (511/512) */
+ /* q_weight = 0.00195 */
+
+/* red parameters for a slow link */
+#define W_WEIGHT_1 128 /* inverse of weight of EWMA (127/128) */
+ /* q_weight = 0.0078125 */
+
+/* red parameters for a very slow link (e.g., dialup) */
+#define W_WEIGHT_2 64 /* inverse of weight of EWMA (63/64) */
+ /* q_weight = 0.015625 */
+
+/* fixed-point uses 12-bit decimal places */
+#define FP_SHIFT 12 /* fixed-point shift */
+
+/* red parameters for drop probability */
+#define INV_P_MAX 10 /* inverse of max drop probability */
+#define TH_MIN 5 /* min threshold */
+#define TH_MAX 15 /* max threshold */
+
+#define RIO_LIMIT 60 /* default max queue lenght */
+#define RIO_STATS /* collect statistics */
+
+#define TV_DELTA(a, b, delta) { \
+ register int xxs; \
+ \
+ delta = (a)->tv_usec - (b)->tv_usec; \
+ if ((xxs = (a)->tv_sec - (b)->tv_sec) != 0) { \
+ if (xxs < 0) { \
+ delta = 60000000; \
+ } else if (xxs > 4) { \
+ if (xxs > 60) \
+ delta = 60000000; \
+ else \
+ delta += xxs * 1000000; \
+ } else while (xxs > 0) { \
+ delta += 1000000; \
+ xxs--; \
+ } \
+ } \
+}
+
+#ifdef ALTQ3_COMPAT
+/* rio_list keeps all rio_queue_t's allocated. */
+static rio_queue_t *rio_list = NULL;
+#endif
+/* default rio parameter values */
+static struct redparams default_rio_params[RIO_NDROPPREC] = {
+ /* th_min, th_max, inv_pmax */
+ { TH_MAX * 2 + TH_MIN, TH_MAX * 3, INV_P_MAX }, /* low drop precedence */
+ { TH_MAX + TH_MIN, TH_MAX * 2, INV_P_MAX }, /* medium drop precedence */
+ { TH_MIN, TH_MAX, INV_P_MAX } /* high drop precedence */
+};
+
+/* internal function prototypes */
+static int dscp2index(u_int8_t);
+#ifdef ALTQ3_COMPAT
+static int rio_enqueue(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
+static struct mbuf *rio_dequeue(struct ifaltq *, int);
+static int rio_request(struct ifaltq *, int, void *);
+static int rio_detach(rio_queue_t *);
+
+/*
+ * rio device interface
+ */
+altqdev_decl(rio);
+
+#endif /* ALTQ3_COMPAT */
+
+rio_t *
+rio_alloc(int weight, struct redparams *params, int flags, int pkttime)
+{
+ rio_t *rp;
+ int w, i;
+ int npkts_per_sec;
+
+ rp = malloc(sizeof(rio_t), M_DEVBUF, M_WAITOK);
+ if (rp == NULL)
+ return (NULL);
+ bzero(rp, sizeof(rio_t));
+
+ rp->rio_flags = flags;
+ if (pkttime == 0)
+ /* default packet time: 1000 bytes / 10Mbps * 8 * 1000000 */
+ rp->rio_pkttime = 800;
+ else
+ rp->rio_pkttime = pkttime;
+
+ if (weight != 0)
+ rp->rio_weight = weight;
+ else {
+ /* use default */
+ rp->rio_weight = W_WEIGHT;
+
+ /* when the link is very slow, adjust red parameters */
+ npkts_per_sec = 1000000 / rp->rio_pkttime;
+ if (npkts_per_sec < 50) {
+ /* up to about 400Kbps */
+ rp->rio_weight = W_WEIGHT_2;
+ } else if (npkts_per_sec < 300) {
+ /* up to about 2.4Mbps */
+ rp->rio_weight = W_WEIGHT_1;
+ }
+ }
+
+ /* calculate wshift. weight must be power of 2 */
+ w = rp->rio_weight;
+ for (i = 0; w > 1; i++)
+ w = w >> 1;
+ rp->rio_wshift = i;
+ w = 1 << rp->rio_wshift;
+ if (w != rp->rio_weight) {
+ printf("invalid weight value %d for red! use %d\n",
+ rp->rio_weight, w);
+ rp->rio_weight = w;
+ }
+
+ /* allocate weight table */
+ rp->rio_wtab = wtab_alloc(rp->rio_weight);
+
+ for (i = 0; i < RIO_NDROPPREC; i++) {
+ struct dropprec_state *prec = &rp->rio_precstate[i];
+
+ prec->avg = 0;
+ prec->idle = 1;
+
+ if (params == NULL || params[i].inv_pmax == 0)
+ prec->inv_pmax = default_rio_params[i].inv_pmax;
+ else
+ prec->inv_pmax = params[i].inv_pmax;
+ if (params == NULL || params[i].th_min == 0)
+ prec->th_min = default_rio_params[i].th_min;
+ else
+ prec->th_min = params[i].th_min;
+ if (params == NULL || params[i].th_max == 0)
+ prec->th_max = default_rio_params[i].th_max;
+ else
+ prec->th_max = params[i].th_max;
+
+ /*
+ * th_min_s and th_max_s are scaled versions of th_min
+ * and th_max to be compared with avg.
+ */
+ prec->th_min_s = prec->th_min << (rp->rio_wshift + FP_SHIFT);
+ prec->th_max_s = prec->th_max << (rp->rio_wshift + FP_SHIFT);
+
+ /*
+ * precompute probability denominator
+ * probd = (2 * (TH_MAX-TH_MIN) / pmax) in fixed-point
+ */
+ prec->probd = (2 * (prec->th_max - prec->th_min)
+ * prec->inv_pmax) << FP_SHIFT;
+
+ microtime(&prec->last);
+ }
+
+ return (rp);
+}
+
+void
+rio_destroy(rio_t *rp)
+{
+ wtab_destroy(rp->rio_wtab);
+ free(rp, M_DEVBUF);
+}
+
+void
+rio_getstats(rio_t *rp, struct redstats *sp)
+{
+ int i;
+
+ for (i = 0; i < RIO_NDROPPREC; i++) {
+ bcopy(&rp->q_stats[i], sp, sizeof(struct redstats));
+ sp->q_avg = rp->rio_precstate[i].avg >> rp->rio_wshift;
+ sp++;
+ }
+}
+
+#if (RIO_NDROPPREC == 3)
+/*
+ * internally, a drop precedence value is converted to an index
+ * starting from 0.
+ */
+static int
+dscp2index(u_int8_t dscp)
+{
+ int dpindex = dscp & AF_DROPPRECMASK;
+
+ if (dpindex == 0)
+ return (0);
+ return ((dpindex >> 3) - 1);
+}
+#endif
+
+#if 1
+/*
+ * kludge: when a packet is dequeued, we need to know its drop precedence
+ * in order to keep the queue length of each drop precedence.
+ * use m_pkthdr.rcvif to pass this info.
+ */
+#define RIOM_SET_PRECINDEX(m, idx) \
+ do { (m)->m_pkthdr.rcvif = (void *)((long)(idx)); } while (0)
+#define RIOM_GET_PRECINDEX(m) \
+ ({ long idx; idx = (long)((m)->m_pkthdr.rcvif); \
+ (m)->m_pkthdr.rcvif = NULL; idx; })
+#endif
+
+int
+rio_addq(rio_t *rp, class_queue_t *q, struct mbuf *m,
+ struct altq_pktattr *pktattr)
+{
+ int avg, droptype;
+ u_int8_t dsfield, odsfield;
+ int dpindex, i, n, t;
+ struct timeval now;
+ struct dropprec_state *prec;
+
+ dsfield = odsfield = read_dsfield(m, pktattr);
+ dpindex = dscp2index(dsfield);
+
+ /*
+ * update avg of the precedence states whose drop precedence
+ * is larger than or equal to the drop precedence of the packet
+ */
+ now.tv_sec = 0;
+ for (i = dpindex; i < RIO_NDROPPREC; i++) {
+ prec = &rp->rio_precstate[i];
+ avg = prec->avg;
+ if (prec->idle) {
+ prec->idle = 0;
+ if (now.tv_sec == 0)
+ microtime(&now);
+ t = (now.tv_sec - prec->last.tv_sec);
+ if (t > 60)
+ avg = 0;
+ else {
+ t = t * 1000000 +
+ (now.tv_usec - prec->last.tv_usec);
+ n = t / rp->rio_pkttime;
+ /* calculate (avg = (1 - Wq)^n * avg) */
+ if (n > 0)
+ avg = (avg >> FP_SHIFT) *
+ pow_w(rp->rio_wtab, n);
+ }
+ }
+
+ /* run estimator. (avg is scaled by WEIGHT in fixed-point) */
+ avg += (prec->qlen << FP_SHIFT) - (avg >> rp->rio_wshift);
+ prec->avg = avg; /* save the new value */
+ /*
+ * count keeps a tally of arriving traffic that has not
+ * been dropped.
+ */
+ prec->count++;
+ }
+
+ prec = &rp->rio_precstate[dpindex];
+ avg = prec->avg;
+
+ /* see if we drop early */
+ droptype = DTYPE_NODROP;
+ if (avg >= prec->th_min_s && prec->qlen > 1) {
+ if (avg >= prec->th_max_s) {
+ /* avg >= th_max: forced drop */
+ droptype = DTYPE_FORCED;
+ } else if (prec->old == 0) {
+ /* first exceeds th_min */
+ prec->count = 1;
+ prec->old = 1;
+ } else if (drop_early((avg - prec->th_min_s) >> rp->rio_wshift,
+ prec->probd, prec->count)) {
+ /* unforced drop by red */
+ droptype = DTYPE_EARLY;
+ }
+ } else {
+ /* avg < th_min */
+ prec->old = 0;
+ }
+
+ /*
+ * if the queue length hits the hard limit, it's a forced drop.
+ */
+ if (droptype == DTYPE_NODROP && qlen(q) >= qlimit(q))
+ droptype = DTYPE_FORCED;
+
+ if (droptype != DTYPE_NODROP) {
+ /* always drop incoming packet (as opposed to randomdrop) */
+ for (i = dpindex; i < RIO_NDROPPREC; i++)
+ rp->rio_precstate[i].count = 0;
+#ifdef RIO_STATS
+ if (droptype == DTYPE_EARLY)
+ rp->q_stats[dpindex].drop_unforced++;
+ else
+ rp->q_stats[dpindex].drop_forced++;
+ PKTCNTR_ADD(&rp->q_stats[dpindex].drop_cnt, m_pktlen(m));
+#endif
+ m_freem(m);
+ return (-1);
+ }
+
+ for (i = dpindex; i < RIO_NDROPPREC; i++)
+ rp->rio_precstate[i].qlen++;
+
+ /* save drop precedence index in mbuf hdr */
+ RIOM_SET_PRECINDEX(m, dpindex);
+
+ if (rp->rio_flags & RIOF_CLEARDSCP)
+ dsfield &= ~DSCP_MASK;
+
+ if (dsfield != odsfield)
+ write_dsfield(m, pktattr, dsfield);
+
+ _addq(q, m);
+
+#ifdef RIO_STATS
+ PKTCNTR_ADD(&rp->q_stats[dpindex].xmit_cnt, m_pktlen(m));
+#endif
+ return (0);
+}
+
+struct mbuf *
+rio_getq(rio_t *rp, class_queue_t *q)
+{
+ struct mbuf *m;
+ int dpindex, i;
+
+ if ((m = _getq(q)) == NULL)
+ return NULL;
+
+ dpindex = RIOM_GET_PRECINDEX(m);
+ for (i = dpindex; i < RIO_NDROPPREC; i++) {
+ if (--rp->rio_precstate[i].qlen == 0) {
+ if (rp->rio_precstate[i].idle == 0) {
+ rp->rio_precstate[i].idle = 1;
+ microtime(&rp->rio_precstate[i].last);
+ }
+ }
+ }
+ return (m);
+}
+
+#ifdef ALTQ3_COMPAT
+int
+rioopen(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ /* everything will be done when the queueing scheme is attached. */
+ return 0;
+}
+
+int
+rioclose(dev, flag, fmt, p)
+ dev_t dev;
+ int flag, fmt;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ rio_queue_t *rqp;
+ int err, error = 0;
+
+ while ((rqp = rio_list) != NULL) {
+ /* destroy all */
+ err = rio_detach(rqp);
+ if (err != 0 && error == 0)
+ error = err;
+ }
+
+ return error;
+}
+
+int
+rioioctl(dev, cmd, addr, flag, p)
+ dev_t dev;
+ ioctlcmd_t cmd;
+ caddr_t addr;
+ int flag;
+#if (__FreeBSD_version > 500000)
+ struct thread *p;
+#else
+ struct proc *p;
+#endif
+{
+ rio_queue_t *rqp;
+ struct rio_interface *ifacep;
+ struct ifnet *ifp;
+ int error = 0;
+
+ /* check super-user privilege */
+ switch (cmd) {
+ case RIO_GETSTATS:
+ break;
+ default:
+#if (__FreeBSD_version > 700000)
+ if ((error = priv_check(p, PRIV_ALTQ_MANAGE)) != 0)
+ return (error);
+#elsif (__FreeBSD_version > 400000)
+ if ((error = suser(p)) != 0)
+ return (error);
+#else
+ if ((error = suser(p->p_ucred, &p->p_acflag)) != 0)
+ return (error);
+#endif
+ break;
+ }
+
+ switch (cmd) {
+
+ case RIO_ENABLE:
+ ifacep = (struct rio_interface *)addr;
+ if ((rqp = altq_lookup(ifacep->rio_ifname, ALTQT_RIO)) == NULL) {
+ error = EBADF;
+ break;
+ }
+ error = altq_enable(rqp->rq_ifq);
+ break;
+
+ case RIO_DISABLE:
+ ifacep = (struct rio_interface *)addr;
+ if ((rqp = altq_lookup(ifacep->rio_ifname, ALTQT_RIO)) == NULL) {
+ error = EBADF;
+ break;
+ }
+ error = altq_disable(rqp->rq_ifq);
+ break;
+
+ case RIO_IF_ATTACH:
+ ifp = ifunit(((struct rio_interface *)addr)->rio_ifname);
+ if (ifp == NULL) {
+ error = ENXIO;
+ break;
+ }
+
+ /* allocate and initialize rio_queue_t */
+ rqp = malloc(sizeof(rio_queue_t), M_DEVBUF, M_WAITOK);
+ if (rqp == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bzero(rqp, sizeof(rio_queue_t));
+
+ rqp->rq_q = malloc(sizeof(class_queue_t),
+ M_DEVBUF, M_WAITOK);
+ if (rqp->rq_q == NULL) {
+ free(rqp, M_DEVBUF);
+ error = ENOMEM;
+ break;
+ }
+ bzero(rqp->rq_q, sizeof(class_queue_t));
+
+ rqp->rq_rio = rio_alloc(0, NULL, 0, 0);
+ if (rqp->rq_rio == NULL) {
+ free(rqp->rq_q, M_DEVBUF);
+ free(rqp, M_DEVBUF);
+ error = ENOMEM;
+ break;
+ }
+
+ rqp->rq_ifq = &ifp->if_snd;
+ qtail(rqp->rq_q) = NULL;
+ qlen(rqp->rq_q) = 0;
+ qlimit(rqp->rq_q) = RIO_LIMIT;
+ qtype(rqp->rq_q) = Q_RIO;
+
+ /*
+ * set RIO to this ifnet structure.
+ */
+ error = altq_attach(rqp->rq_ifq, ALTQT_RIO, rqp,
+ rio_enqueue, rio_dequeue, rio_request,
+ NULL, NULL);
+ if (error) {
+ rio_destroy(rqp->rq_rio);
+ free(rqp->rq_q, M_DEVBUF);
+ free(rqp, M_DEVBUF);
+ break;
+ }
+
+ /* add this state to the rio list */
+ rqp->rq_next = rio_list;
+ rio_list = rqp;
+ break;
+
+ case RIO_IF_DETACH:
+ ifacep = (struct rio_interface *)addr;
+ if ((rqp = altq_lookup(ifacep->rio_ifname, ALTQT_RIO)) == NULL) {
+ error = EBADF;
+ break;
+ }
+ error = rio_detach(rqp);
+ break;
+
+ case RIO_GETSTATS:
+ do {
+ struct rio_stats *q_stats;
+ rio_t *rp;
+ int i;
+
+ q_stats = (struct rio_stats *)addr;
+ if ((rqp = altq_lookup(q_stats->iface.rio_ifname,
+ ALTQT_RIO)) == NULL) {
+ error = EBADF;
+ break;
+ }
+
+ rp = rqp->rq_rio;
+
+ q_stats->q_limit = qlimit(rqp->rq_q);
+ q_stats->weight = rp->rio_weight;
+ q_stats->flags = rp->rio_flags;
+
+ for (i = 0; i < RIO_NDROPPREC; i++) {
+ q_stats->q_len[i] = rp->rio_precstate[i].qlen;
+ bcopy(&rp->q_stats[i], &q_stats->q_stats[i],
+ sizeof(struct redstats));
+ q_stats->q_stats[i].q_avg =
+ rp->rio_precstate[i].avg >> rp->rio_wshift;
+
+ q_stats->q_params[i].inv_pmax
+ = rp->rio_precstate[i].inv_pmax;
+ q_stats->q_params[i].th_min
+ = rp->rio_precstate[i].th_min;
+ q_stats->q_params[i].th_max
+ = rp->rio_precstate[i].th_max;
+ }
+ } while (/*CONSTCOND*/ 0);
+ break;
+
+ case RIO_CONFIG:
+ do {
+ struct rio_conf *fc;
+ rio_t *new;
+ int s, limit, i;
+
+ fc = (struct rio_conf *)addr;
+ if ((rqp = altq_lookup(fc->iface.rio_ifname,
+ ALTQT_RIO)) == NULL) {
+ error = EBADF;
+ break;
+ }
+
+ new = rio_alloc(fc->rio_weight, &fc->q_params[0],
+ fc->rio_flags, fc->rio_pkttime);
+ if (new == NULL) {
+ error = ENOMEM;
+ break;
+ }
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ _flushq(rqp->rq_q);
+ limit = fc->rio_limit;
+ if (limit < fc->q_params[RIO_NDROPPREC-1].th_max)
+ limit = fc->q_params[RIO_NDROPPREC-1].th_max;
+ qlimit(rqp->rq_q) = limit;
+
+ rio_destroy(rqp->rq_rio);
+ rqp->rq_rio = new;
+
+ splx(s);
+
+ /* write back new values */
+ fc->rio_limit = limit;
+ for (i = 0; i < RIO_NDROPPREC; i++) {
+ fc->q_params[i].inv_pmax =
+ rqp->rq_rio->rio_precstate[i].inv_pmax;
+ fc->q_params[i].th_min =
+ rqp->rq_rio->rio_precstate[i].th_min;
+ fc->q_params[i].th_max =
+ rqp->rq_rio->rio_precstate[i].th_max;
+ }
+ } while (/*CONSTCOND*/ 0);
+ break;
+
+ case RIO_SETDEFAULTS:
+ do {
+ struct redparams *rp;
+ int i;
+
+ rp = (struct redparams *)addr;
+ for (i = 0; i < RIO_NDROPPREC; i++)
+ default_rio_params[i] = rp[i];
+ } while (/*CONSTCOND*/ 0);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+static int
+rio_detach(rqp)
+ rio_queue_t *rqp;
+{
+ rio_queue_t *tmp;
+ int error = 0;
+
+ if (ALTQ_IS_ENABLED(rqp->rq_ifq))
+ altq_disable(rqp->rq_ifq);
+
+ if ((error = altq_detach(rqp->rq_ifq)))
+ return (error);
+
+ if (rio_list == rqp)
+ rio_list = rqp->rq_next;
+ else {
+ for (tmp = rio_list; tmp != NULL; tmp = tmp->rq_next)
+ if (tmp->rq_next == rqp) {
+ tmp->rq_next = rqp->rq_next;
+ break;
+ }
+ if (tmp == NULL)
+ printf("rio_detach: no state found in rio_list!\n");
+ }
+
+ rio_destroy(rqp->rq_rio);
+ free(rqp->rq_q, M_DEVBUF);
+ free(rqp, M_DEVBUF);
+ return (error);
+}
+
+/*
+ * rio support routines
+ */
+static int
+rio_request(ifq, req, arg)
+ struct ifaltq *ifq;
+ int req;
+ void *arg;
+{
+ rio_queue_t *rqp = (rio_queue_t *)ifq->altq_disc;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ switch (req) {
+ case ALTRQ_PURGE:
+ _flushq(rqp->rq_q);
+ if (ALTQ_IS_ENABLED(ifq))
+ ifq->ifq_len = 0;
+ break;
+ }
+ return (0);
+}
+
+/*
+ * enqueue routine:
+ *
+ * returns: 0 when successfully queued.
+ * ENOBUFS when drop occurs.
+ */
+static int
+rio_enqueue(ifq, m, pktattr)
+ struct ifaltq *ifq;
+ struct mbuf *m;
+ struct altq_pktattr *pktattr;
+{
+ rio_queue_t *rqp = (rio_queue_t *)ifq->altq_disc;
+ int error = 0;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ if (rio_addq(rqp->rq_rio, rqp->rq_q, m, pktattr) == 0)
+ ifq->ifq_len++;
+ else
+ error = ENOBUFS;
+ return error;
+}
+
+/*
+ * dequeue routine:
+ * must be called in splimp.
+ *
+ * returns: mbuf dequeued.
+ * NULL when no packet is available in the queue.
+ */
+
+static struct mbuf *
+rio_dequeue(ifq, op)
+ struct ifaltq *ifq;
+ int op;
+{
+ rio_queue_t *rqp = (rio_queue_t *)ifq->altq_disc;
+ struct mbuf *m = NULL;
+
+ IFQ_LOCK_ASSERT(ifq);
+
+ if (op == ALTDQ_POLL)
+ return qhead(rqp->rq_q);
+
+ m = rio_getq(rqp->rq_rio, rqp->rq_q);
+ if (m != NULL)
+ ifq->ifq_len--;
+ return m;
+}
+
+#ifdef KLD_MODULE
+
+static struct altqsw rio_sw =
+ {"rio", rioopen, rioclose, rioioctl};
+
+ALTQ_MODULE(altq_rio, ALTQT_RIO, &rio_sw);
+MODULE_VERSION(altq_rio, 1);
+MODULE_DEPEND(altq_rio, altq_red, 1, 1, 1);
+
+#endif /* KLD_MODULE */
+#endif /* ALTQ3_COMPAT */
+
+#endif /* ALTQ_RIO */
diff --git a/freebsd/sys/contrib/altq/altq/altq_rio.h b/freebsd/sys/contrib/altq/altq/altq_rio.h
new file mode 100644
index 00000000..e32d2ee2
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_rio.h
@@ -0,0 +1,144 @@
+/* $KAME: altq_rio.h,v 1.9 2003/07/10 12:07:49 kjc Exp $ */
+
+/*
+ * Copyright (C) 1998-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 _ALTQ_ALTQ_RIO_HH_
+#define _ALTQ_ALTQ_RIO_HH_
+
+#include <freebsd/altq/altq_classq.h>
+
+/*
+ * RIO: RED with IN/OUT bit
+ * (extended to support more than 2 drop precedence values)
+ */
+#define RIO_NDROPPREC 3 /* number of drop precedence values */
+
+#ifdef ALTQ3_COMPAT
+struct rio_interface {
+ char rio_ifname[IFNAMSIZ];
+};
+
+struct rio_stats {
+ struct rio_interface iface;
+ int q_len[RIO_NDROPPREC];
+ struct redstats q_stats[RIO_NDROPPREC];
+
+ /* static red parameters */
+ int q_limit;
+ int weight;
+ int flags;
+ struct redparams q_params[RIO_NDROPPREC];
+};
+
+struct rio_conf {
+ struct rio_interface iface;
+ struct redparams q_params[RIO_NDROPPREC];
+ int rio_weight; /* weight for EWMA */
+ int rio_limit; /* max queue length */
+ int rio_pkttime; /* average packet time in usec */
+ int rio_flags; /* see below */
+};
+#endif /* ALTQ3_COMPAT */
+
+/* rio flags */
+#define RIOF_ECN4 0x01 /* use packet marking for IPv4 packets */
+#define RIOF_ECN6 0x02 /* use packet marking for IPv6 packets */
+#define RIOF_ECN (RIOF_ECN4 | RIOF_ECN6)
+#define RIOF_CLEARDSCP 0x200 /* clear diffserv codepoint */
+
+#ifdef ALTQ3_COMPAT
+/*
+ * IOCTLs for RIO
+ */
+#define RIO_IF_ATTACH _IOW('Q', 1, struct rio_interface)
+#define RIO_IF_DETACH _IOW('Q', 2, struct rio_interface)
+#define RIO_ENABLE _IOW('Q', 3, struct rio_interface)
+#define RIO_DISABLE _IOW('Q', 4, struct rio_interface)
+#define RIO_CONFIG _IOWR('Q', 6, struct rio_conf)
+#define RIO_GETSTATS _IOWR('Q', 12, struct rio_stats)
+#define RIO_SETDEFAULTS _IOW('Q', 30, struct redparams[RIO_NDROPPREC])
+#endif /* ALTQ3_COMPAT */
+
+#ifdef _KERNEL
+
+typedef struct rio {
+ /* per drop precedence structure */
+ struct dropprec_state {
+ /* red parameters */
+ int inv_pmax; /* inverse of max drop probability */
+ int th_min; /* red min threshold */
+ int th_max; /* red max threshold */
+
+ /* variables for internal use */
+ int th_min_s; /* th_min scaled by avgshift */
+ int th_max_s; /* th_max scaled by avgshift */
+ int probd; /* drop probability denominator */
+
+ int qlen; /* queue length */
+ int avg; /* (scaled) queue length average */
+ int count; /* packet count since the last dropped/
+ marked packet */
+ int idle; /* queue was empty */
+ int old; /* avg is above th_min */
+ struct timeval last; /* timestamp when queue becomes idle */
+ } rio_precstate[RIO_NDROPPREC];
+
+ int rio_wshift; /* log(red_weight) */
+ int rio_weight; /* weight for EWMA */
+ struct wtab *rio_wtab; /* weight table */
+
+ int rio_pkttime; /* average packet time in micro sec
+ used for idle calibration */
+ int rio_flags; /* rio flags */
+
+ u_int8_t rio_codepoint; /* codepoint value to tag packets */
+ u_int8_t rio_codepointmask; /* codepoint mask bits */
+
+ struct redstats q_stats[RIO_NDROPPREC]; /* statistics */
+} rio_t;
+
+#ifdef ALTQ3_COMPAT
+typedef struct rio_queue {
+ struct rio_queue *rq_next; /* next red_state in the list */
+ struct ifaltq *rq_ifq; /* backpointer to ifaltq */
+
+ class_queue_t *rq_q;
+
+ rio_t *rq_rio;
+} rio_queue_t;
+#endif /* ALTQ3_COMPAT */
+
+extern rio_t *rio_alloc(int, struct redparams *, int, int);
+extern void rio_destroy(rio_t *);
+extern void rio_getstats(rio_t *, struct redstats *);
+extern int rio_addq(rio_t *, class_queue_t *, struct mbuf *,
+ struct altq_pktattr *);
+extern struct mbuf *rio_getq(rio_t *, class_queue_t *);
+
+#endif /* _KERNEL */
+
+#endif /* _ALTQ_ALTQ_RIO_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_rmclass.c b/freebsd/sys/contrib/altq/altq/altq_rmclass.c
new file mode 100644
index 00000000..06f61bd3
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_rmclass.c
@@ -0,0 +1,1843 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_rmclass.c,v 1.18 2003/11/06 06:32:53 kjc Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 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 Network Research
+ * 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.
+ *
+ * LBL code modified by speer@eng.sun.com, May 1977.
+ * For questions and/or comments, please send mail to cbq@ee.lbl.gov
+ */
+
+#ident "@(#)rm_class.c 1.48 97/12/05 SMI"
+
+#if defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#if (__FreeBSD__ != 2)
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+#ifdef ALTQ_CBQ /* cbq is enabled by ALTQ_CBQ option in opt_altq.h */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/errno.h>
+#include <freebsd/sys/time.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/sys/kernel.h>
+#endif
+
+#include <freebsd/net/if.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#endif
+
+#include <freebsd/altq/altq.h>
+#include <freebsd/altq/altq_rmclass.h>
+#include <freebsd/altq/altq_rmclass_debug.h>
+#include <freebsd/altq/altq_red.h>
+#include <freebsd/altq/altq_rio.h>
+
+/*
+ * Local Macros
+ */
+
+#define reset_cutoff(ifd) { ifd->cutoff_ = RM_MAXDEPTH; }
+
+/*
+ * Local routines.
+ */
+
+static int rmc_satisfied(struct rm_class *, struct timeval *);
+static void rmc_wrr_set_weights(struct rm_ifdat *);
+static void rmc_depth_compute(struct rm_class *);
+static void rmc_depth_recompute(rm_class_t *);
+
+static mbuf_t *_rmc_wrr_dequeue_next(struct rm_ifdat *, int);
+static mbuf_t *_rmc_prr_dequeue_next(struct rm_ifdat *, int);
+
+static int _rmc_addq(rm_class_t *, mbuf_t *);
+static void _rmc_dropq(rm_class_t *);
+static mbuf_t *_rmc_getq(rm_class_t *);
+static mbuf_t *_rmc_pollq(rm_class_t *);
+
+static int rmc_under_limit(struct rm_class *, struct timeval *);
+static void rmc_tl_satisfied(struct rm_ifdat *, struct timeval *);
+static void rmc_drop_action(struct rm_class *);
+static void rmc_restart(struct rm_class *);
+static void rmc_root_overlimit(struct rm_class *, struct rm_class *);
+
+#define BORROW_OFFTIME
+/*
+ * BORROW_OFFTIME (experimental):
+ * borrow the offtime of the class borrowing from.
+ * the reason is that when its own offtime is set, the class is unable
+ * to borrow much, especially when cutoff is taking effect.
+ * but when the borrowed class is overloaded (advidle is close to minidle),
+ * use the borrowing class's offtime to avoid overload.
+ */
+#define ADJUST_CUTOFF
+/*
+ * ADJUST_CUTOFF (experimental):
+ * if no underlimit class is found due to cutoff, increase cutoff and
+ * retry the scheduling loop.
+ * also, don't invoke delay_actions while cutoff is taking effect,
+ * since a sleeping class won't have a chance to be scheduled in the
+ * next loop.
+ *
+ * now heuristics for setting the top-level variable (cutoff_) becomes:
+ * 1. if a packet arrives for a not-overlimit class, set cutoff
+ * to the depth of the class.
+ * 2. if cutoff is i, and a packet arrives for an overlimit class
+ * with an underlimit ancestor at a lower level than i (say j),
+ * then set cutoff to j.
+ * 3. at scheduling a packet, if there is no underlimit class
+ * due to the current cutoff level, increase cutoff by 1 and
+ * then try to schedule again.
+ */
+
+/*
+ * rm_class_t *
+ * rmc_newclass(...) - Create a new resource management class at priority
+ * 'pri' on the interface given by 'ifd'.
+ *
+ * nsecPerByte is the data rate of the interface in nanoseconds/byte.
+ * E.g., 800 for a 10Mb/s ethernet. If the class gets less
+ * than 100% of the bandwidth, this number should be the
+ * 'effective' rate for the class. Let f be the
+ * bandwidth fraction allocated to this class, and let
+ * nsPerByte be the data rate of the output link in
+ * nanoseconds/byte. Then nsecPerByte is set to
+ * nsPerByte / f. E.g., 1600 (= 800 / .5)
+ * for a class that gets 50% of an ethernet's bandwidth.
+ *
+ * action the routine to call when the class is over limit.
+ *
+ * maxq max allowable queue size for class (in packets).
+ *
+ * parent parent class pointer.
+ *
+ * borrow class to borrow from (should be either 'parent' or null).
+ *
+ * maxidle max value allowed for class 'idle' time estimate (this
+ * parameter determines how large an initial burst of packets
+ * can be before overlimit action is invoked.
+ *
+ * offtime how long 'delay' action will delay when class goes over
+ * limit (this parameter determines the steady-state burst
+ * size when a class is running over its limit).
+ *
+ * Maxidle and offtime have to be computed from the following: If the
+ * average packet size is s, the bandwidth fraction allocated to this
+ * class is f, we want to allow b packet bursts, and the gain of the
+ * averaging filter is g (= 1 - 2^(-RM_FILTER_GAIN)), then:
+ *
+ * ptime = s * nsPerByte * (1 - f) / f
+ * maxidle = ptime * (1 - g^b) / g^b
+ * minidle = -ptime * (1 / (f - 1))
+ * offtime = ptime * (1 + 1/(1 - g) * (1 - g^(b - 1)) / g^(b - 1)
+ *
+ * Operationally, it's convenient to specify maxidle & offtime in units
+ * independent of the link bandwidth so the maxidle & offtime passed to
+ * this routine are the above values multiplied by 8*f/(1000*nsPerByte).
+ * (The constant factor is a scale factor needed to make the parameters
+ * integers. This scaling also means that the 'unscaled' values of
+ * maxidle*nsecPerByte/8 and offtime*nsecPerByte/8 will be in microseconds,
+ * not nanoseconds.) Also note that the 'idle' filter computation keeps
+ * an estimate scaled upward by 2^RM_FILTER_GAIN so the passed value of
+ * maxidle also must be scaled upward by this value. Thus, the passed
+ * values for maxidle and offtime can be computed as follows:
+ *
+ * maxidle = maxidle * 2^RM_FILTER_GAIN * 8 / (1000 * nsecPerByte)
+ * offtime = offtime * 8 / (1000 * nsecPerByte)
+ *
+ * When USE_HRTIME is employed, then maxidle and offtime become:
+ * maxidle = maxilde * (8.0 / nsecPerByte);
+ * offtime = offtime * (8.0 / nsecPerByte);
+ */
+struct rm_class *
+rmc_newclass(int pri, struct rm_ifdat *ifd, u_int nsecPerByte,
+ void (*action)(rm_class_t *, rm_class_t *), int maxq,
+ struct rm_class *parent, struct rm_class *borrow, u_int maxidle,
+ int minidle, u_int offtime, int pktsize, int flags)
+{
+ struct rm_class *cl;
+ struct rm_class *peer;
+ int s;
+
+ if (pri >= RM_MAXPRIO)
+ return (NULL);
+#ifndef ALTQ_RED
+ if (flags & RMCF_RED) {
+#ifdef ALTQ_DEBUG
+ printf("rmc_newclass: RED not configured for CBQ!\n");
+#endif
+ return (NULL);
+ }
+#endif
+#ifndef ALTQ_RIO
+ if (flags & RMCF_RIO) {
+#ifdef ALTQ_DEBUG
+ printf("rmc_newclass: RIO not configured for CBQ!\n");
+#endif
+ return (NULL);
+ }
+#endif
+
+ cl = malloc(sizeof(struct rm_class),
+ M_DEVBUF, M_WAITOK);
+ if (cl == NULL)
+ return (NULL);
+ bzero(cl, sizeof(struct rm_class));
+ CALLOUT_INIT(&cl->callout_);
+ cl->q_ = malloc(sizeof(class_queue_t),
+ M_DEVBUF, M_WAITOK);
+ if (cl->q_ == NULL) {
+ free(cl, M_DEVBUF);
+ return (NULL);
+ }
+ bzero(cl->q_, sizeof(class_queue_t));
+
+ /*
+ * Class initialization.
+ */
+ cl->children_ = NULL;
+ cl->parent_ = parent;
+ cl->borrow_ = borrow;
+ cl->leaf_ = 1;
+ cl->ifdat_ = ifd;
+ cl->pri_ = pri;
+ cl->allotment_ = RM_NS_PER_SEC / nsecPerByte; /* Bytes per sec */
+ cl->depth_ = 0;
+ cl->qthresh_ = 0;
+ cl->ns_per_byte_ = nsecPerByte;
+
+ qlimit(cl->q_) = maxq;
+ qtype(cl->q_) = Q_DROPHEAD;
+ qlen(cl->q_) = 0;
+ cl->flags_ = flags;
+
+#if 1 /* minidle is also scaled in ALTQ */
+ cl->minidle_ = (minidle * (int)nsecPerByte) / 8;
+ if (cl->minidle_ > 0)
+ cl->minidle_ = 0;
+#else
+ cl->minidle_ = minidle;
+#endif
+ cl->maxidle_ = (maxidle * nsecPerByte) / 8;
+ if (cl->maxidle_ == 0)
+ cl->maxidle_ = 1;
+#if 1 /* offtime is also scaled in ALTQ */
+ cl->avgidle_ = cl->maxidle_;
+ cl->offtime_ = ((offtime * nsecPerByte) / 8) >> RM_FILTER_GAIN;
+ if (cl->offtime_ == 0)
+ cl->offtime_ = 1;
+#else
+ cl->avgidle_ = 0;
+ cl->offtime_ = (offtime * nsecPerByte) / 8;
+#endif
+ cl->overlimit = action;
+
+#ifdef ALTQ_RED
+ if (flags & (RMCF_RED|RMCF_RIO)) {
+ int red_flags, red_pkttime;
+
+ red_flags = 0;
+ if (flags & RMCF_ECN)
+ red_flags |= REDF_ECN;
+ if (flags & RMCF_FLOWVALVE)
+ red_flags |= REDF_FLOWVALVE;
+#ifdef ALTQ_RIO
+ if (flags & RMCF_CLEARDSCP)
+ red_flags |= RIOF_CLEARDSCP;
+#endif
+ red_pkttime = nsecPerByte * pktsize / 1000;
+
+ if (flags & RMCF_RED) {
+ cl->red_ = red_alloc(0, 0,
+ qlimit(cl->q_) * 10/100,
+ qlimit(cl->q_) * 30/100,
+ red_flags, red_pkttime);
+ if (cl->red_ != NULL)
+ qtype(cl->q_) = Q_RED;
+ }
+#ifdef ALTQ_RIO
+ else {
+ cl->red_ = (red_t *)rio_alloc(0, NULL,
+ red_flags, red_pkttime);
+ if (cl->red_ != NULL)
+ qtype(cl->q_) = Q_RIO;
+ }
+#endif
+ }
+#endif /* ALTQ_RED */
+
+ /*
+ * put the class into the class tree
+ */
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(ifd->ifq_);
+ if ((peer = ifd->active_[pri]) != NULL) {
+ /* find the last class at this pri */
+ cl->peer_ = peer;
+ while (peer->peer_ != ifd->active_[pri])
+ peer = peer->peer_;
+ peer->peer_ = cl;
+ } else {
+ ifd->active_[pri] = cl;
+ cl->peer_ = cl;
+ }
+
+ if (cl->parent_) {
+ cl->next_ = parent->children_;
+ parent->children_ = cl;
+ parent->leaf_ = 0;
+ }
+
+ /*
+ * Compute the depth of this class and its ancestors in the class
+ * hierarchy.
+ */
+ rmc_depth_compute(cl);
+
+ /*
+ * If CBQ's WRR is enabled, then initialize the class WRR state.
+ */
+ if (ifd->wrr_) {
+ ifd->num_[pri]++;
+ ifd->alloc_[pri] += cl->allotment_;
+ rmc_wrr_set_weights(ifd);
+ }
+ IFQ_UNLOCK(ifd->ifq_);
+ splx(s);
+ return (cl);
+}
+
+int
+rmc_modclass(struct rm_class *cl, u_int nsecPerByte, int maxq, u_int maxidle,
+ int minidle, u_int offtime, int pktsize)
+{
+ struct rm_ifdat *ifd;
+ u_int old_allotment;
+ int s;
+
+ ifd = cl->ifdat_;
+ old_allotment = cl->allotment_;
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(ifd->ifq_);
+ cl->allotment_ = RM_NS_PER_SEC / nsecPerByte; /* Bytes per sec */
+ cl->qthresh_ = 0;
+ cl->ns_per_byte_ = nsecPerByte;
+
+ qlimit(cl->q_) = maxq;
+
+#if 1 /* minidle is also scaled in ALTQ */
+ cl->minidle_ = (minidle * nsecPerByte) / 8;
+ if (cl->minidle_ > 0)
+ cl->minidle_ = 0;
+#else
+ cl->minidle_ = minidle;
+#endif
+ cl->maxidle_ = (maxidle * nsecPerByte) / 8;
+ if (cl->maxidle_ == 0)
+ cl->maxidle_ = 1;
+#if 1 /* offtime is also scaled in ALTQ */
+ cl->avgidle_ = cl->maxidle_;
+ cl->offtime_ = ((offtime * nsecPerByte) / 8) >> RM_FILTER_GAIN;
+ if (cl->offtime_ == 0)
+ cl->offtime_ = 1;
+#else
+ cl->avgidle_ = 0;
+ cl->offtime_ = (offtime * nsecPerByte) / 8;
+#endif
+
+ /*
+ * If CBQ's WRR is enabled, then initialize the class WRR state.
+ */
+ if (ifd->wrr_) {
+ ifd->alloc_[cl->pri_] += cl->allotment_ - old_allotment;
+ rmc_wrr_set_weights(ifd);
+ }
+ IFQ_UNLOCK(ifd->ifq_);
+ splx(s);
+ return (0);
+}
+
+/*
+ * static void
+ * rmc_wrr_set_weights(struct rm_ifdat *ifdat) - This function computes
+ * the appropriate run robin weights for the CBQ weighted round robin
+ * algorithm.
+ *
+ * Returns: NONE
+ */
+
+static void
+rmc_wrr_set_weights(struct rm_ifdat *ifd)
+{
+ int i;
+ struct rm_class *cl, *clh;
+
+ for (i = 0; i < RM_MAXPRIO; i++) {
+ /*
+ * This is inverted from that of the simulator to
+ * maintain precision.
+ */
+ if (ifd->num_[i] == 0)
+ ifd->M_[i] = 0;
+ else
+ ifd->M_[i] = ifd->alloc_[i] /
+ (ifd->num_[i] * ifd->maxpkt_);
+ /*
+ * Compute the weighted allotment for each class.
+ * This takes the expensive div instruction out
+ * of the main loop for the wrr scheduling path.
+ * These only get recomputed when a class comes or
+ * goes.
+ */
+ if (ifd->active_[i] != NULL) {
+ clh = cl = ifd->active_[i];
+ do {
+ /* safe-guard for slow link or alloc_ == 0 */
+ if (ifd->M_[i] == 0)
+ cl->w_allotment_ = 0;
+ else
+ cl->w_allotment_ = cl->allotment_ /
+ ifd->M_[i];
+ cl = cl->peer_;
+ } while ((cl != NULL) && (cl != clh));
+ }
+ }
+}
+
+int
+rmc_get_weight(struct rm_ifdat *ifd, int pri)
+{
+ if ((pri >= 0) && (pri < RM_MAXPRIO))
+ return (ifd->M_[pri]);
+ else
+ return (0);
+}
+
+/*
+ * static void
+ * rmc_depth_compute(struct rm_class *cl) - This function computes the
+ * appropriate depth of class 'cl' and its ancestors.
+ *
+ * Returns: NONE
+ */
+
+static void
+rmc_depth_compute(struct rm_class *cl)
+{
+ rm_class_t *t = cl, *p;
+
+ /*
+ * Recompute the depth for the branch of the tree.
+ */
+ while (t != NULL) {
+ p = t->parent_;
+ if (p && (t->depth_ >= p->depth_)) {
+ p->depth_ = t->depth_ + 1;
+ t = p;
+ } else
+ t = NULL;
+ }
+}
+
+/*
+ * static void
+ * rmc_depth_recompute(struct rm_class *cl) - This function re-computes
+ * the depth of the tree after a class has been deleted.
+ *
+ * Returns: NONE
+ */
+
+static void
+rmc_depth_recompute(rm_class_t *cl)
+{
+#if 1 /* ALTQ */
+ rm_class_t *p, *t;
+
+ p = cl;
+ while (p != NULL) {
+ if ((t = p->children_) == NULL) {
+ p->depth_ = 0;
+ } else {
+ int cdepth = 0;
+
+ while (t != NULL) {
+ if (t->depth_ > cdepth)
+ cdepth = t->depth_;
+ t = t->next_;
+ }
+
+ if (p->depth_ == cdepth + 1)
+ /* no change to this parent */
+ return;
+
+ p->depth_ = cdepth + 1;
+ }
+
+ p = p->parent_;
+ }
+#else
+ rm_class_t *t;
+
+ if (cl->depth_ >= 1) {
+ if (cl->children_ == NULL) {
+ cl->depth_ = 0;
+ } else if ((t = cl->children_) != NULL) {
+ while (t != NULL) {
+ if (t->children_ != NULL)
+ rmc_depth_recompute(t);
+ t = t->next_;
+ }
+ } else
+ rmc_depth_compute(cl);
+ }
+#endif
+}
+
+/*
+ * void
+ * rmc_delete_class(struct rm_ifdat *ifdat, struct rm_class *cl) - This
+ * function deletes a class from the link-sharing structure and frees
+ * all resources associated with the class.
+ *
+ * Returns: NONE
+ */
+
+void
+rmc_delete_class(struct rm_ifdat *ifd, struct rm_class *cl)
+{
+ struct rm_class *p, *head, *previous;
+ int s;
+
+ ASSERT(cl->children_ == NULL);
+
+ if (cl->sleeping_)
+ CALLOUT_STOP(&cl->callout_);
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(ifd->ifq_);
+ /*
+ * Free packets in the packet queue.
+ * XXX - this may not be a desired behavior. Packets should be
+ * re-queued.
+ */
+ rmc_dropall(cl);
+
+ /*
+ * If the class has a parent, then remove the class from the
+ * class from the parent's children chain.
+ */
+ if (cl->parent_ != NULL) {
+ head = cl->parent_->children_;
+ p = previous = head;
+ if (head->next_ == NULL) {
+ ASSERT(head == cl);
+ cl->parent_->children_ = NULL;
+ cl->parent_->leaf_ = 1;
+ } else while (p != NULL) {
+ if (p == cl) {
+ if (cl == head)
+ cl->parent_->children_ = cl->next_;
+ else
+ previous->next_ = cl->next_;
+ cl->next_ = NULL;
+ p = NULL;
+ } else {
+ previous = p;
+ p = p->next_;
+ }
+ }
+ }
+
+ /*
+ * Delete class from class priority peer list.
+ */
+ if ((p = ifd->active_[cl->pri_]) != NULL) {
+ /*
+ * If there is more than one member of this priority
+ * level, then look for class(cl) in the priority level.
+ */
+ if (p != p->peer_) {
+ while (p->peer_ != cl)
+ p = p->peer_;
+ p->peer_ = cl->peer_;
+
+ if (ifd->active_[cl->pri_] == cl)
+ ifd->active_[cl->pri_] = cl->peer_;
+ } else {
+ ASSERT(p == cl);
+ ifd->active_[cl->pri_] = NULL;
+ }
+ }
+
+ /*
+ * Recompute the WRR weights.
+ */
+ if (ifd->wrr_) {
+ ifd->alloc_[cl->pri_] -= cl->allotment_;
+ ifd->num_[cl->pri_]--;
+ rmc_wrr_set_weights(ifd);
+ }
+
+ /*
+ * Re-compute the depth of the tree.
+ */
+#if 1 /* ALTQ */
+ rmc_depth_recompute(cl->parent_);
+#else
+ rmc_depth_recompute(ifd->root_);
+#endif
+
+ IFQ_UNLOCK(ifd->ifq_);
+ splx(s);
+
+ /*
+ * Free the class structure.
+ */
+ if (cl->red_ != NULL) {
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->q_))
+ rio_destroy((rio_t *)cl->red_);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->q_))
+ red_destroy(cl->red_);
+#endif
+ }
+ free(cl->q_, M_DEVBUF);
+ free(cl, M_DEVBUF);
+}
+
+
+/*
+ * void
+ * rmc_init(...) - Initialize the resource management data structures
+ * associated with the output portion of interface 'ifp'. 'ifd' is
+ * where the structures will be built (for backwards compatibility, the
+ * structures aren't kept in the ifnet struct). 'nsecPerByte'
+ * gives the link speed (inverse of bandwidth) in nanoseconds/byte.
+ * 'restart' is the driver-specific routine that the generic 'delay
+ * until under limit' action will call to restart output. `maxq'
+ * is the queue size of the 'link' & 'default' classes. 'maxqueued'
+ * is the maximum number of packets that the resource management
+ * code will allow to be queued 'downstream' (this is typically 1).
+ *
+ * Returns: NONE
+ */
+
+void
+rmc_init(struct ifaltq *ifq, struct rm_ifdat *ifd, u_int nsecPerByte,
+ void (*restart)(struct ifaltq *), int maxq, int maxqueued, u_int maxidle,
+ int minidle, u_int offtime, int flags)
+{
+ int i, mtu;
+
+ /*
+ * Initialize the CBQ tracing/debug facility.
+ */
+ CBQTRACEINIT();
+
+ bzero((char *)ifd, sizeof (*ifd));
+ mtu = ifq->altq_ifp->if_mtu;
+ ifd->ifq_ = ifq;
+ ifd->restart = restart;
+ ifd->maxqueued_ = maxqueued;
+ ifd->ns_per_byte_ = nsecPerByte;
+ ifd->maxpkt_ = mtu;
+ ifd->wrr_ = (flags & RMCF_WRR) ? 1 : 0;
+ ifd->efficient_ = (flags & RMCF_EFFICIENT) ? 1 : 0;
+#if 1
+ ifd->maxiftime_ = mtu * nsecPerByte / 1000 * 16;
+ if (mtu * nsecPerByte > 10 * 1000000)
+ ifd->maxiftime_ /= 4;
+#endif
+
+ reset_cutoff(ifd);
+ CBQTRACE(rmc_init, 'INIT', ifd->cutoff_);
+
+ /*
+ * Initialize the CBQ's WRR state.
+ */
+ for (i = 0; i < RM_MAXPRIO; i++) {
+ ifd->alloc_[i] = 0;
+ ifd->M_[i] = 0;
+ ifd->num_[i] = 0;
+ ifd->na_[i] = 0;
+ ifd->active_[i] = NULL;
+ }
+
+ /*
+ * Initialize current packet state.
+ */
+ ifd->qi_ = 0;
+ ifd->qo_ = 0;
+ for (i = 0; i < RM_MAXQUEUED; i++) {
+ ifd->class_[i] = NULL;
+ ifd->curlen_[i] = 0;
+ ifd->borrowed_[i] = NULL;
+ }
+
+ /*
+ * Create the root class of the link-sharing structure.
+ */
+ if ((ifd->root_ = rmc_newclass(0, ifd,
+ nsecPerByte,
+ rmc_root_overlimit, maxq, 0, 0,
+ maxidle, minidle, offtime,
+ 0, 0)) == NULL) {
+ printf("rmc_init: root class not allocated\n");
+ return ;
+ }
+ ifd->root_->depth_ = 0;
+}
+
+/*
+ * void
+ * rmc_queue_packet(struct rm_class *cl, mbuf_t *m) - Add packet given by
+ * mbuf 'm' to queue for resource class 'cl'. This routine is called
+ * by a driver's if_output routine. This routine must be called with
+ * output packet completion interrupts locked out (to avoid racing with
+ * rmc_dequeue_next).
+ *
+ * Returns: 0 on successful queueing
+ * -1 when packet drop occurs
+ */
+int
+rmc_queue_packet(struct rm_class *cl, mbuf_t *m)
+{
+ struct timeval now;
+ struct rm_ifdat *ifd = cl->ifdat_;
+ int cpri = cl->pri_;
+ int is_empty = qempty(cl->q_);
+
+ RM_GETTIME(now);
+ if (ifd->cutoff_ > 0) {
+ if (TV_LT(&cl->undertime_, &now)) {
+ if (ifd->cutoff_ > cl->depth_)
+ ifd->cutoff_ = cl->depth_;
+ CBQTRACE(rmc_queue_packet, 'ffoc', cl->depth_);
+ }
+#if 1 /* ALTQ */
+ else {
+ /*
+ * the class is overlimit. if the class has
+ * underlimit ancestors, set cutoff to the lowest
+ * depth among them.
+ */
+ struct rm_class *borrow = cl->borrow_;
+
+ while (borrow != NULL &&
+ borrow->depth_ < ifd->cutoff_) {
+ if (TV_LT(&borrow->undertime_, &now)) {
+ ifd->cutoff_ = borrow->depth_;
+ CBQTRACE(rmc_queue_packet, 'ffob', ifd->cutoff_);
+ break;
+ }
+ borrow = borrow->borrow_;
+ }
+ }
+#else /* !ALTQ */
+ else if ((ifd->cutoff_ > 1) && cl->borrow_) {
+ if (TV_LT(&cl->borrow_->undertime_, &now)) {
+ ifd->cutoff_ = cl->borrow_->depth_;
+ CBQTRACE(rmc_queue_packet, 'ffob',
+ cl->borrow_->depth_);
+ }
+ }
+#endif /* !ALTQ */
+ }
+
+ if (_rmc_addq(cl, m) < 0)
+ /* failed */
+ return (-1);
+
+ if (is_empty) {
+ CBQTRACE(rmc_queue_packet, 'ytpe', cl->stats_.handle);
+ ifd->na_[cpri]++;
+ }
+
+ if (qlen(cl->q_) > qlimit(cl->q_)) {
+ /* note: qlimit can be set to 0 or 1 */
+ rmc_drop_action(cl);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * void
+ * rmc_tl_satisfied(struct rm_ifdat *ifd, struct timeval *now) - Check all
+ * classes to see if there are satified.
+ */
+
+static void
+rmc_tl_satisfied(struct rm_ifdat *ifd, struct timeval *now)
+{
+ int i;
+ rm_class_t *p, *bp;
+
+ for (i = RM_MAXPRIO - 1; i >= 0; i--) {
+ if ((bp = ifd->active_[i]) != NULL) {
+ p = bp;
+ do {
+ if (!rmc_satisfied(p, now)) {
+ ifd->cutoff_ = p->depth_;
+ return;
+ }
+ p = p->peer_;
+ } while (p != bp);
+ }
+ }
+
+ reset_cutoff(ifd);
+}
+
+/*
+ * rmc_satisfied - Return 1 of the class is satisfied. O, otherwise.
+ */
+
+static int
+rmc_satisfied(struct rm_class *cl, struct timeval *now)
+{
+ rm_class_t *p;
+
+ if (cl == NULL)
+ return (1);
+ if (TV_LT(now, &cl->undertime_))
+ return (1);
+ if (cl->depth_ == 0) {
+ if (!cl->sleeping_ && (qlen(cl->q_) > cl->qthresh_))
+ return (0);
+ else
+ return (1);
+ }
+ if (cl->children_ != NULL) {
+ p = cl->children_;
+ while (p != NULL) {
+ if (!rmc_satisfied(p, now))
+ return (0);
+ p = p->next_;
+ }
+ }
+
+ return (1);
+}
+
+/*
+ * Return 1 if class 'cl' is under limit or can borrow from a parent,
+ * 0 if overlimit. As a side-effect, this routine will invoke the
+ * class overlimit action if the class if overlimit.
+ */
+
+static int
+rmc_under_limit(struct rm_class *cl, struct timeval *now)
+{
+ rm_class_t *p = cl;
+ rm_class_t *top;
+ struct rm_ifdat *ifd = cl->ifdat_;
+
+ ifd->borrowed_[ifd->qi_] = NULL;
+ /*
+ * If cl is the root class, then always return that it is
+ * underlimit. Otherwise, check to see if the class is underlimit.
+ */
+ if (cl->parent_ == NULL)
+ return (1);
+
+ if (cl->sleeping_) {
+ if (TV_LT(now, &cl->undertime_))
+ return (0);
+
+ CALLOUT_STOP(&cl->callout_);
+ cl->sleeping_ = 0;
+ cl->undertime_.tv_sec = 0;
+ return (1);
+ }
+
+ top = NULL;
+ while (cl->undertime_.tv_sec && TV_LT(now, &cl->undertime_)) {
+ if (((cl = cl->borrow_) == NULL) ||
+ (cl->depth_ > ifd->cutoff_)) {
+#ifdef ADJUST_CUTOFF
+ if (cl != NULL)
+ /* cutoff is taking effect, just
+ return false without calling
+ the delay action. */
+ return (0);
+#endif
+#ifdef BORROW_OFFTIME
+ /*
+ * check if the class can borrow offtime too.
+ * borrow offtime from the top of the borrow
+ * chain if the top class is not overloaded.
+ */
+ if (cl != NULL) {
+ /* cutoff is taking effect, use this class as top. */
+ top = cl;
+ CBQTRACE(rmc_under_limit, 'ffou', ifd->cutoff_);
+ }
+ if (top != NULL && top->avgidle_ == top->minidle_)
+ top = NULL;
+ p->overtime_ = *now;
+ (p->overlimit)(p, top);
+#else
+ p->overtime_ = *now;
+ (p->overlimit)(p, NULL);
+#endif
+ return (0);
+ }
+ top = cl;
+ }
+
+ if (cl != p)
+ ifd->borrowed_[ifd->qi_] = cl;
+ return (1);
+}
+
+/*
+ * _rmc_wrr_dequeue_next() - This is scheduler for WRR as opposed to
+ * Packet-by-packet round robin.
+ *
+ * The heart of the weighted round-robin scheduler, which decides which
+ * class next gets to send a packet. Highest priority first, then
+ * weighted round-robin within priorites.
+ *
+ * Each able-to-send class gets to send until its byte allocation is
+ * exhausted. Thus, the active pointer is only changed after a class has
+ * exhausted its allocation.
+ *
+ * If the scheduler finds no class that is underlimit or able to borrow,
+ * then the first class found that had a nonzero queue and is allowed to
+ * borrow gets to send.
+ */
+
+static mbuf_t *
+_rmc_wrr_dequeue_next(struct rm_ifdat *ifd, int op)
+{
+ struct rm_class *cl = NULL, *first = NULL;
+ u_int deficit;
+ int cpri;
+ mbuf_t *m;
+ struct timeval now;
+
+ RM_GETTIME(now);
+
+ /*
+ * if the driver polls the top of the queue and then removes
+ * the polled packet, we must return the same packet.
+ */
+ if (op == ALTDQ_REMOVE && ifd->pollcache_) {
+ cl = ifd->pollcache_;
+ cpri = cl->pri_;
+ if (ifd->efficient_) {
+ /* check if this class is overlimit */
+ if (cl->undertime_.tv_sec != 0 &&
+ rmc_under_limit(cl, &now) == 0)
+ first = cl;
+ }
+ ifd->pollcache_ = NULL;
+ goto _wrr_out;
+ }
+ else {
+ /* mode == ALTDQ_POLL || pollcache == NULL */
+ ifd->pollcache_ = NULL;
+ ifd->borrowed_[ifd->qi_] = NULL;
+ }
+#ifdef ADJUST_CUTOFF
+ _again:
+#endif
+ for (cpri = RM_MAXPRIO - 1; cpri >= 0; cpri--) {
+ if (ifd->na_[cpri] == 0)
+ continue;
+ deficit = 0;
+ /*
+ * Loop through twice for a priority level, if some class
+ * was unable to send a packet the first round because
+ * of the weighted round-robin mechanism.
+ * During the second loop at this level, deficit==2.
+ * (This second loop is not needed if for every class,
+ * "M[cl->pri_])" times "cl->allotment" is greater than
+ * the byte size for the largest packet in the class.)
+ */
+ _wrr_loop:
+ cl = ifd->active_[cpri];
+ ASSERT(cl != NULL);
+ do {
+ if ((deficit < 2) && (cl->bytes_alloc_ <= 0))
+ cl->bytes_alloc_ += cl->w_allotment_;
+ if (!qempty(cl->q_)) {
+ if ((cl->undertime_.tv_sec == 0) ||
+ rmc_under_limit(cl, &now)) {
+ if (cl->bytes_alloc_ > 0 || deficit > 1)
+ goto _wrr_out;
+
+ /* underlimit but no alloc */
+ deficit = 1;
+#if 1
+ ifd->borrowed_[ifd->qi_] = NULL;
+#endif
+ }
+ else if (first == NULL && cl->borrow_ != NULL)
+ first = cl; /* borrowing candidate */
+ }
+
+ cl->bytes_alloc_ = 0;
+ cl = cl->peer_;
+ } while (cl != ifd->active_[cpri]);
+
+ if (deficit == 1) {
+ /* first loop found an underlimit class with deficit */
+ /* Loop on same priority level, with new deficit. */
+ deficit = 2;
+ goto _wrr_loop;
+ }
+ }
+
+#ifdef ADJUST_CUTOFF
+ /*
+ * no underlimit class found. if cutoff is taking effect,
+ * increase cutoff and try again.
+ */
+ if (first != NULL && ifd->cutoff_ < ifd->root_->depth_) {
+ ifd->cutoff_++;
+ CBQTRACE(_rmc_wrr_dequeue_next, 'ojda', ifd->cutoff_);
+ goto _again;
+ }
+#endif /* ADJUST_CUTOFF */
+ /*
+ * If LINK_EFFICIENCY is turned on, then the first overlimit
+ * class we encounter will send a packet if all the classes
+ * of the link-sharing structure are overlimit.
+ */
+ reset_cutoff(ifd);
+ CBQTRACE(_rmc_wrr_dequeue_next, 'otsr', ifd->cutoff_);
+
+ if (!ifd->efficient_ || first == NULL)
+ return (NULL);
+
+ cl = first;
+ cpri = cl->pri_;
+#if 0 /* too time-consuming for nothing */
+ if (cl->sleeping_)
+ CALLOUT_STOP(&cl->callout_);
+ cl->sleeping_ = 0;
+ cl->undertime_.tv_sec = 0;
+#endif
+ ifd->borrowed_[ifd->qi_] = cl->borrow_;
+ ifd->cutoff_ = cl->borrow_->depth_;
+
+ /*
+ * Deque the packet and do the book keeping...
+ */
+ _wrr_out:
+ if (op == ALTDQ_REMOVE) {
+ m = _rmc_getq(cl);
+ if (m == NULL)
+ panic("_rmc_wrr_dequeue_next");
+ if (qempty(cl->q_))
+ ifd->na_[cpri]--;
+
+ /*
+ * Update class statistics and link data.
+ */
+ if (cl->bytes_alloc_ > 0)
+ cl->bytes_alloc_ -= m_pktlen(m);
+
+ if ((cl->bytes_alloc_ <= 0) || first == cl)
+ ifd->active_[cl->pri_] = cl->peer_;
+ else
+ ifd->active_[cl->pri_] = cl;
+
+ ifd->class_[ifd->qi_] = cl;
+ ifd->curlen_[ifd->qi_] = m_pktlen(m);
+ ifd->now_[ifd->qi_] = now;
+ ifd->qi_ = (ifd->qi_ + 1) % ifd->maxqueued_;
+ ifd->queued_++;
+ } else {
+ /* mode == ALTDQ_PPOLL */
+ m = _rmc_pollq(cl);
+ ifd->pollcache_ = cl;
+ }
+ return (m);
+}
+
+/*
+ * Dequeue & return next packet from the highest priority class that
+ * has a packet to send & has enough allocation to send it. This
+ * routine is called by a driver whenever it needs a new packet to
+ * output.
+ */
+static mbuf_t *
+_rmc_prr_dequeue_next(struct rm_ifdat *ifd, int op)
+{
+ mbuf_t *m;
+ int cpri;
+ struct rm_class *cl, *first = NULL;
+ struct timeval now;
+
+ RM_GETTIME(now);
+
+ /*
+ * if the driver polls the top of the queue and then removes
+ * the polled packet, we must return the same packet.
+ */
+ if (op == ALTDQ_REMOVE && ifd->pollcache_) {
+ cl = ifd->pollcache_;
+ cpri = cl->pri_;
+ ifd->pollcache_ = NULL;
+ goto _prr_out;
+ } else {
+ /* mode == ALTDQ_POLL || pollcache == NULL */
+ ifd->pollcache_ = NULL;
+ ifd->borrowed_[ifd->qi_] = NULL;
+ }
+#ifdef ADJUST_CUTOFF
+ _again:
+#endif
+ for (cpri = RM_MAXPRIO - 1; cpri >= 0; cpri--) {
+ if (ifd->na_[cpri] == 0)
+ continue;
+ cl = ifd->active_[cpri];
+ ASSERT(cl != NULL);
+ do {
+ if (!qempty(cl->q_)) {
+ if ((cl->undertime_.tv_sec == 0) ||
+ rmc_under_limit(cl, &now))
+ goto _prr_out;
+ if (first == NULL && cl->borrow_ != NULL)
+ first = cl;
+ }
+ cl = cl->peer_;
+ } while (cl != ifd->active_[cpri]);
+ }
+
+#ifdef ADJUST_CUTOFF
+ /*
+ * no underlimit class found. if cutoff is taking effect, increase
+ * cutoff and try again.
+ */
+ if (first != NULL && ifd->cutoff_ < ifd->root_->depth_) {
+ ifd->cutoff_++;
+ goto _again;
+ }
+#endif /* ADJUST_CUTOFF */
+ /*
+ * If LINK_EFFICIENCY is turned on, then the first overlimit
+ * class we encounter will send a packet if all the classes
+ * of the link-sharing structure are overlimit.
+ */
+ reset_cutoff(ifd);
+ if (!ifd->efficient_ || first == NULL)
+ return (NULL);
+
+ cl = first;
+ cpri = cl->pri_;
+#if 0 /* too time-consuming for nothing */
+ if (cl->sleeping_)
+ CALLOUT_STOP(&cl->callout_);
+ cl->sleeping_ = 0;
+ cl->undertime_.tv_sec = 0;
+#endif
+ ifd->borrowed_[ifd->qi_] = cl->borrow_;
+ ifd->cutoff_ = cl->borrow_->depth_;
+
+ /*
+ * Deque the packet and do the book keeping...
+ */
+ _prr_out:
+ if (op == ALTDQ_REMOVE) {
+ m = _rmc_getq(cl);
+ if (m == NULL)
+ panic("_rmc_prr_dequeue_next");
+ if (qempty(cl->q_))
+ ifd->na_[cpri]--;
+
+ ifd->active_[cpri] = cl->peer_;
+
+ ifd->class_[ifd->qi_] = cl;
+ ifd->curlen_[ifd->qi_] = m_pktlen(m);
+ ifd->now_[ifd->qi_] = now;
+ ifd->qi_ = (ifd->qi_ + 1) % ifd->maxqueued_;
+ ifd->queued_++;
+ } else {
+ /* mode == ALTDQ_POLL */
+ m = _rmc_pollq(cl);
+ ifd->pollcache_ = cl;
+ }
+ return (m);
+}
+
+/*
+ * mbuf_t *
+ * rmc_dequeue_next(struct rm_ifdat *ifd, struct timeval *now) - this function
+ * is invoked by the packet driver to get the next packet to be
+ * dequeued and output on the link. If WRR is enabled, then the
+ * WRR dequeue next routine will determine the next packet to sent.
+ * Otherwise, packet-by-packet round robin is invoked.
+ *
+ * Returns: NULL, if a packet is not available or if all
+ * classes are overlimit.
+ *
+ * Otherwise, Pointer to the next packet.
+ */
+
+mbuf_t *
+rmc_dequeue_next(struct rm_ifdat *ifd, int mode)
+{
+ if (ifd->queued_ >= ifd->maxqueued_)
+ return (NULL);
+ else if (ifd->wrr_)
+ return (_rmc_wrr_dequeue_next(ifd, mode));
+ else
+ return (_rmc_prr_dequeue_next(ifd, mode));
+}
+
+/*
+ * Update the utilization estimate for the packet that just completed.
+ * The packet's class & the parent(s) of that class all get their
+ * estimators updated. This routine is called by the driver's output-
+ * packet-completion interrupt service routine.
+ */
+
+/*
+ * a macro to approximate "divide by 1000" that gives 0.000999,
+ * if a value has enough effective digits.
+ * (on pentium, mul takes 9 cycles but div takes 46!)
+ */
+#define NSEC_TO_USEC(t) (((t) >> 10) + ((t) >> 16) + ((t) >> 17))
+void
+rmc_update_class_util(struct rm_ifdat *ifd)
+{
+ int idle, avgidle, pktlen;
+ int pkt_time, tidle;
+ rm_class_t *cl, *borrowed;
+ rm_class_t *borrows;
+ struct timeval *nowp;
+
+ /*
+ * Get the most recent completed class.
+ */
+ if ((cl = ifd->class_[ifd->qo_]) == NULL)
+ return;
+
+ pktlen = ifd->curlen_[ifd->qo_];
+ borrowed = ifd->borrowed_[ifd->qo_];
+ borrows = borrowed;
+
+ PKTCNTR_ADD(&cl->stats_.xmit_cnt, pktlen);
+
+ /*
+ * Run estimator on class and its ancestors.
+ */
+ /*
+ * rm_update_class_util is designed to be called when the
+ * transfer is completed from a xmit complete interrupt,
+ * but most drivers don't implement an upcall for that.
+ * so, just use estimated completion time.
+ * as a result, ifd->qi_ and ifd->qo_ are always synced.
+ */
+ nowp = &ifd->now_[ifd->qo_];
+ /* get pkt_time (for link) in usec */
+#if 1 /* use approximation */
+ pkt_time = ifd->curlen_[ifd->qo_] * ifd->ns_per_byte_;
+ pkt_time = NSEC_TO_USEC(pkt_time);
+#else
+ pkt_time = ifd->curlen_[ifd->qo_] * ifd->ns_per_byte_ / 1000;
+#endif
+#if 1 /* ALTQ4PPP */
+ if (TV_LT(nowp, &ifd->ifnow_)) {
+ int iftime;
+
+ /*
+ * make sure the estimated completion time does not go
+ * too far. it can happen when the link layer supports
+ * data compression or the interface speed is set to
+ * a much lower value.
+ */
+ TV_DELTA(&ifd->ifnow_, nowp, iftime);
+ if (iftime+pkt_time < ifd->maxiftime_) {
+ TV_ADD_DELTA(&ifd->ifnow_, pkt_time, &ifd->ifnow_);
+ } else {
+ TV_ADD_DELTA(nowp, ifd->maxiftime_, &ifd->ifnow_);
+ }
+ } else {
+ TV_ADD_DELTA(nowp, pkt_time, &ifd->ifnow_);
+ }
+#else
+ if (TV_LT(nowp, &ifd->ifnow_)) {
+ TV_ADD_DELTA(&ifd->ifnow_, pkt_time, &ifd->ifnow_);
+ } else {
+ TV_ADD_DELTA(nowp, pkt_time, &ifd->ifnow_);
+ }
+#endif
+
+ while (cl != NULL) {
+ TV_DELTA(&ifd->ifnow_, &cl->last_, idle);
+ if (idle >= 2000000)
+ /*
+ * this class is idle enough, reset avgidle.
+ * (TV_DELTA returns 2000000 us when delta is large.)
+ */
+ cl->avgidle_ = cl->maxidle_;
+
+ /* get pkt_time (for class) in usec */
+#if 1 /* use approximation */
+ pkt_time = pktlen * cl->ns_per_byte_;
+ pkt_time = NSEC_TO_USEC(pkt_time);
+#else
+ pkt_time = pktlen * cl->ns_per_byte_ / 1000;
+#endif
+ idle -= pkt_time;
+
+ avgidle = cl->avgidle_;
+ avgidle += idle - (avgidle >> RM_FILTER_GAIN);
+ cl->avgidle_ = avgidle;
+
+ /* Are we overlimit ? */
+ if (avgidle <= 0) {
+ CBQTRACE(rmc_update_class_util, 'milo', cl->stats_.handle);
+#if 1 /* ALTQ */
+ /*
+ * need some lower bound for avgidle, otherwise
+ * a borrowing class gets unbounded penalty.
+ */
+ if (avgidle < cl->minidle_)
+ avgidle = cl->avgidle_ = cl->minidle_;
+#endif
+ /* set next idle to make avgidle 0 */
+ tidle = pkt_time +
+ (((1 - RM_POWER) * avgidle) >> RM_FILTER_GAIN);
+ TV_ADD_DELTA(nowp, tidle, &cl->undertime_);
+ ++cl->stats_.over;
+ } else {
+ cl->avgidle_ =
+ (avgidle > cl->maxidle_) ? cl->maxidle_ : avgidle;
+ cl->undertime_.tv_sec = 0;
+ if (cl->sleeping_) {
+ CALLOUT_STOP(&cl->callout_);
+ cl->sleeping_ = 0;
+ }
+ }
+
+ if (borrows != NULL) {
+ if (borrows != cl)
+ ++cl->stats_.borrows;
+ else
+ borrows = NULL;
+ }
+ cl->last_ = ifd->ifnow_;
+ cl->last_pkttime_ = pkt_time;
+
+#if 1
+ if (cl->parent_ == NULL) {
+ /* take stats of root class */
+ PKTCNTR_ADD(&cl->stats_.xmit_cnt, pktlen);
+ }
+#endif
+
+ cl = cl->parent_;
+ }
+
+ /*
+ * Check to see if cutoff needs to set to a new level.
+ */
+ cl = ifd->class_[ifd->qo_];
+ if (borrowed && (ifd->cutoff_ >= borrowed->depth_)) {
+#if 1 /* ALTQ */
+ if ((qlen(cl->q_) <= 0) || TV_LT(nowp, &borrowed->undertime_)) {
+ rmc_tl_satisfied(ifd, nowp);
+ CBQTRACE(rmc_update_class_util, 'broe', ifd->cutoff_);
+ } else {
+ ifd->cutoff_ = borrowed->depth_;
+ CBQTRACE(rmc_update_class_util, 'ffob', borrowed->depth_);
+ }
+#else /* !ALTQ */
+ if ((qlen(cl->q_) <= 1) || TV_LT(&now, &borrowed->undertime_)) {
+ reset_cutoff(ifd);
+#ifdef notdef
+ rmc_tl_satisfied(ifd, &now);
+#endif
+ CBQTRACE(rmc_update_class_util, 'broe', ifd->cutoff_);
+ } else {
+ ifd->cutoff_ = borrowed->depth_;
+ CBQTRACE(rmc_update_class_util, 'ffob', borrowed->depth_);
+ }
+#endif /* !ALTQ */
+ }
+
+ /*
+ * Release class slot
+ */
+ ifd->borrowed_[ifd->qo_] = NULL;
+ ifd->class_[ifd->qo_] = NULL;
+ ifd->qo_ = (ifd->qo_ + 1) % ifd->maxqueued_;
+ ifd->queued_--;
+}
+
+/*
+ * void
+ * rmc_drop_action(struct rm_class *cl) - Generic (not protocol-specific)
+ * over-limit action routines. These get invoked by rmc_under_limit()
+ * if a class with packets to send if over its bandwidth limit & can't
+ * borrow from a parent class.
+ *
+ * Returns: NONE
+ */
+
+static void
+rmc_drop_action(struct rm_class *cl)
+{
+ struct rm_ifdat *ifd = cl->ifdat_;
+
+ ASSERT(qlen(cl->q_) > 0);
+ _rmc_dropq(cl);
+ if (qempty(cl->q_))
+ ifd->na_[cl->pri_]--;
+}
+
+void rmc_dropall(struct rm_class *cl)
+{
+ struct rm_ifdat *ifd = cl->ifdat_;
+
+ if (!qempty(cl->q_)) {
+ _flushq(cl->q_);
+
+ ifd->na_[cl->pri_]--;
+ }
+}
+
+#if (__FreeBSD_version > 300000)
+/* hzto() is removed from FreeBSD-3.0 */
+static int hzto(struct timeval *);
+
+static int
+hzto(tv)
+ struct timeval *tv;
+{
+ struct timeval t2;
+
+ getmicrotime(&t2);
+ t2.tv_sec = tv->tv_sec - t2.tv_sec;
+ t2.tv_usec = tv->tv_usec - t2.tv_usec;
+ return (tvtohz(&t2));
+}
+#endif /* __FreeBSD_version > 300000 */
+
+/*
+ * void
+ * rmc_delay_action(struct rm_class *cl) - This function is the generic CBQ
+ * delay action routine. It is invoked via rmc_under_limit when the
+ * packet is discoverd to be overlimit.
+ *
+ * If the delay action is result of borrow class being overlimit, then
+ * delay for the offtime of the borrowing class that is overlimit.
+ *
+ * Returns: NONE
+ */
+
+void
+rmc_delay_action(struct rm_class *cl, struct rm_class *borrow)
+{
+ int delay, t, extradelay;
+
+ cl->stats_.overactions++;
+ TV_DELTA(&cl->undertime_, &cl->overtime_, delay);
+#ifndef BORROW_OFFTIME
+ delay += cl->offtime_;
+#endif
+
+ if (!cl->sleeping_) {
+ CBQTRACE(rmc_delay_action, 'yled', cl->stats_.handle);
+#ifdef BORROW_OFFTIME
+ if (borrow != NULL)
+ extradelay = borrow->offtime_;
+ else
+#endif
+ extradelay = cl->offtime_;
+
+#ifdef ALTQ
+ /*
+ * XXX recalculate suspend time:
+ * current undertime is (tidle + pkt_time) calculated
+ * from the last transmission.
+ * tidle: time required to bring avgidle back to 0
+ * pkt_time: target waiting time for this class
+ * we need to replace pkt_time by offtime
+ */
+ extradelay -= cl->last_pkttime_;
+#endif
+ if (extradelay > 0) {
+ TV_ADD_DELTA(&cl->undertime_, extradelay, &cl->undertime_);
+ delay += extradelay;
+ }
+
+ cl->sleeping_ = 1;
+ cl->stats_.delays++;
+
+ /*
+ * Since packets are phased randomly with respect to the
+ * clock, 1 tick (the next clock tick) can be an arbitrarily
+ * short time so we have to wait for at least two ticks.
+ * NOTE: If there's no other traffic, we need the timer as
+ * a 'backstop' to restart this class.
+ */
+ if (delay > tick * 2) {
+#ifdef __FreeBSD__
+ /* FreeBSD rounds up the tick */
+ t = hzto(&cl->undertime_);
+#else
+ /* other BSDs round down the tick */
+ t = hzto(&cl->undertime_) + 1;
+#endif
+ } else
+ t = 2;
+ CALLOUT_RESET(&cl->callout_, t,
+ (timeout_t *)rmc_restart, (caddr_t)cl);
+ }
+}
+
+/*
+ * void
+ * rmc_restart() - is just a helper routine for rmc_delay_action -- it is
+ * called by the system timer code & is responsible checking if the
+ * class is still sleeping (it might have been restarted as a side
+ * effect of the queue scan on a packet arrival) and, if so, restarting
+ * output for the class. Inspecting the class state & restarting output
+ * require locking the class structure. In general the driver is
+ * responsible for locking but this is the only routine that is not
+ * called directly or indirectly from the interface driver so it has
+ * know about system locking conventions. Under bsd, locking is done
+ * by raising IPL to splimp so that's what's implemented here. On a
+ * different system this would probably need to be changed.
+ *
+ * Returns: NONE
+ */
+
+static void
+rmc_restart(struct rm_class *cl)
+{
+ struct rm_ifdat *ifd = cl->ifdat_;
+ int s;
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_LOCK(ifd->ifq_);
+ if (cl->sleeping_) {
+ cl->sleeping_ = 0;
+ cl->undertime_.tv_sec = 0;
+
+ if (ifd->queued_ < ifd->maxqueued_ && ifd->restart != NULL) {
+ CBQTRACE(rmc_restart, 'trts', cl->stats_.handle);
+ (ifd->restart)(ifd->ifq_);
+ }
+ }
+ IFQ_UNLOCK(ifd->ifq_);
+ splx(s);
+}
+
+/*
+ * void
+ * rmc_root_overlimit(struct rm_class *cl) - This the generic overlimit
+ * handling routine for the root class of the link sharing structure.
+ *
+ * Returns: NONE
+ */
+
+static void
+rmc_root_overlimit(struct rm_class *cl, struct rm_class *borrow)
+{
+ panic("rmc_root_overlimit");
+}
+
+/*
+ * Packet Queue handling routines. Eventually, this is to localize the
+ * effects on the code whether queues are red queues or droptail
+ * queues.
+ */
+
+static int
+_rmc_addq(rm_class_t *cl, mbuf_t *m)
+{
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->q_))
+ return rio_addq((rio_t *)cl->red_, cl->q_, m, cl->pktattr_);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->q_))
+ return red_addq(cl->red_, cl->q_, m, cl->pktattr_);
+#endif /* ALTQ_RED */
+
+ if (cl->flags_ & RMCF_CLEARDSCP)
+ write_dsfield(m, cl->pktattr_, 0);
+
+ _addq(cl->q_, m);
+ return (0);
+}
+
+/* note: _rmc_dropq is not called for red */
+static void
+_rmc_dropq(rm_class_t *cl)
+{
+ mbuf_t *m;
+
+ if ((m = _getq(cl->q_)) != NULL)
+ m_freem(m);
+}
+
+static mbuf_t *
+_rmc_getq(rm_class_t *cl)
+{
+#ifdef ALTQ_RIO
+ if (q_is_rio(cl->q_))
+ return rio_getq((rio_t *)cl->red_, cl->q_);
+#endif
+#ifdef ALTQ_RED
+ if (q_is_red(cl->q_))
+ return red_getq(cl->red_, cl->q_);
+#endif
+ return _getq(cl->q_);
+}
+
+static mbuf_t *
+_rmc_pollq(rm_class_t *cl)
+{
+ return qhead(cl->q_);
+}
+
+#ifdef CBQ_TRACE
+
+struct cbqtrace cbqtrace_buffer[NCBQTRACE+1];
+struct cbqtrace *cbqtrace_ptr = NULL;
+int cbqtrace_count;
+
+/*
+ * DDB hook to trace cbq events:
+ * the last 1024 events are held in a circular buffer.
+ * use "call cbqtrace_dump(N)" to display 20 events from Nth event.
+ */
+void cbqtrace_dump(int);
+static char *rmc_funcname(void *);
+
+static struct rmc_funcs {
+ void *func;
+ char *name;
+} rmc_funcs[] =
+{
+ rmc_init, "rmc_init",
+ rmc_queue_packet, "rmc_queue_packet",
+ rmc_under_limit, "rmc_under_limit",
+ rmc_update_class_util, "rmc_update_class_util",
+ rmc_delay_action, "rmc_delay_action",
+ rmc_restart, "rmc_restart",
+ _rmc_wrr_dequeue_next, "_rmc_wrr_dequeue_next",
+ NULL, NULL
+};
+
+static char *rmc_funcname(void *func)
+{
+ struct rmc_funcs *fp;
+
+ for (fp = rmc_funcs; fp->func != NULL; fp++)
+ if (fp->func == func)
+ return (fp->name);
+ return ("unknown");
+}
+
+void cbqtrace_dump(int counter)
+{
+ int i, *p;
+ char *cp;
+
+ counter = counter % NCBQTRACE;
+ p = (int *)&cbqtrace_buffer[counter];
+
+ for (i=0; i<20; i++) {
+ printf("[0x%x] ", *p++);
+ printf("%s: ", rmc_funcname((void *)*p++));
+ cp = (char *)p++;
+ printf("%c%c%c%c: ", cp[0], cp[1], cp[2], cp[3]);
+ printf("%d\n",*p++);
+
+ if (p >= (int *)&cbqtrace_buffer[NCBQTRACE])
+ p = (int *)cbqtrace_buffer;
+ }
+}
+#endif /* CBQ_TRACE */
+#endif /* ALTQ_CBQ */
+
+#if defined(ALTQ_CBQ) || defined(ALTQ_RED) || defined(ALTQ_RIO) || defined(ALTQ_HFSC) || defined(ALTQ_PRIQ)
+#if !defined(__GNUC__) || defined(ALTQ_DEBUG)
+
+void
+_addq(class_queue_t *q, mbuf_t *m)
+{
+ mbuf_t *m0;
+
+ if ((m0 = qtail(q)) != NULL)
+ m->m_nextpkt = m0->m_nextpkt;
+ else
+ m0 = m;
+ m0->m_nextpkt = m;
+ qtail(q) = m;
+ qlen(q)++;
+}
+
+mbuf_t *
+_getq(class_queue_t *q)
+{
+ mbuf_t *m, *m0;
+
+ if ((m = qtail(q)) == NULL)
+ return (NULL);
+ if ((m0 = m->m_nextpkt) != m)
+ m->m_nextpkt = m0->m_nextpkt;
+ else {
+ ASSERT(qlen(q) == 1);
+ qtail(q) = NULL;
+ }
+ qlen(q)--;
+ m0->m_nextpkt = NULL;
+ return (m0);
+}
+
+/* drop a packet at the tail of the queue */
+mbuf_t *
+_getq_tail(class_queue_t *q)
+{
+ mbuf_t *m, *m0, *prev;
+
+ if ((m = m0 = qtail(q)) == NULL)
+ return NULL;
+ do {
+ prev = m0;
+ m0 = m0->m_nextpkt;
+ } while (m0 != m);
+ prev->m_nextpkt = m->m_nextpkt;
+ if (prev == m) {
+ ASSERT(qlen(q) == 1);
+ qtail(q) = NULL;
+ } else
+ qtail(q) = prev;
+ qlen(q)--;
+ m->m_nextpkt = NULL;
+ return (m);
+}
+
+/* randomly select a packet in the queue */
+mbuf_t *
+_getq_random(class_queue_t *q)
+{
+ struct mbuf *m;
+ int i, n;
+
+ if ((m = qtail(q)) == NULL)
+ return NULL;
+ if (m->m_nextpkt == m) {
+ ASSERT(qlen(q) == 1);
+ qtail(q) = NULL;
+ } else {
+ struct mbuf *prev = NULL;
+
+ n = arc4random() % qlen(q) + 1;
+ for (i = 0; i < n; i++) {
+ prev = m;
+ m = m->m_nextpkt;
+ }
+ prev->m_nextpkt = m->m_nextpkt;
+ if (m == qtail(q))
+ qtail(q) = prev;
+ }
+ qlen(q)--;
+ m->m_nextpkt = NULL;
+ return (m);
+}
+
+void
+_removeq(class_queue_t *q, mbuf_t *m)
+{
+ mbuf_t *m0, *prev;
+
+ m0 = qtail(q);
+ do {
+ prev = m0;
+ m0 = m0->m_nextpkt;
+ } while (m0 != m);
+ prev->m_nextpkt = m->m_nextpkt;
+ if (prev == m)
+ qtail(q) = NULL;
+ else if (qtail(q) == m)
+ qtail(q) = prev;
+ qlen(q)--;
+}
+
+void
+_flushq(class_queue_t *q)
+{
+ mbuf_t *m;
+
+ while ((m = _getq(q)) != NULL)
+ m_freem(m);
+ ASSERT(qlen(q) == 0);
+}
+
+#endif /* !__GNUC__ || ALTQ_DEBUG */
+#endif /* ALTQ_CBQ || ALTQ_RED || ALTQ_RIO || ALTQ_HFSC || ALTQ_PRIQ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_rmclass.h b/freebsd/sys/contrib/altq/altq/altq_rmclass.h
new file mode 100644
index 00000000..feb30c1c
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_rmclass.h
@@ -0,0 +1,266 @@
+/* $KAME: altq_rmclass.h,v 1.10 2003/08/20 23:30:23 itojun Exp $ */
+
+/*
+ * Copyright (c) 1991-1997 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 Network Research
+ * 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.
+ */
+
+#ifndef _ALTQ_ALTQ_RMCLASS_HH_
+#define _ALTQ_ALTQ_RMCLASS_HH_
+
+#include <freebsd/altq/altq_classq.h>
+
+/* #pragma ident "@(#)rm_class.h 1.20 97/10/23 SMI" */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define RM_MAXPRIO 8 /* Max priority */
+
+#ifdef _KERNEL
+
+typedef struct mbuf mbuf_t;
+typedef struct rm_ifdat rm_ifdat_t;
+typedef struct rm_class rm_class_t;
+
+struct red;
+
+/*
+ * Macros for dealing with time values. We assume all times are
+ * 'timevals'. `microtime' is used to get the best available clock
+ * resolution. If `microtime' *doesn't* return a value that's about
+ * ten times smaller than the average packet time on the fastest
+ * link that will use these routines, a slightly different clock
+ * scheme than this one should be used.
+ * (Bias due to truncation error in this scheme will overestimate utilization
+ * and discriminate against high bandwidth classes. To remove this bias an
+ * integrator needs to be added. The simplest integrator uses a history of
+ * 10 * avg.packet.time / min.tick.time packet completion entries. This is
+ * straight forward to add but we don't want to pay the extra memory
+ * traffic to maintain it if it's not necessary (occasionally a vendor
+ * accidentally builds a workstation with a decent clock - e.g., Sun & HP).)
+ */
+
+#define RM_GETTIME(now) microtime(&now)
+
+#define TV_LT(a, b) (((a)->tv_sec < (b)->tv_sec) || \
+ (((a)->tv_usec < (b)->tv_usec) && ((a)->tv_sec <= (b)->tv_sec)))
+
+#define TV_DELTA(a, b, delta) { \
+ register int xxs; \
+ \
+ delta = (a)->tv_usec - (b)->tv_usec; \
+ if ((xxs = (a)->tv_sec - (b)->tv_sec)) { \
+ switch (xxs) { \
+ default: \
+ /* if (xxs < 0) \
+ printf("rm_class: bogus time values\n"); */ \
+ delta = 0; \
+ /* fall through */ \
+ case 2: \
+ delta += 1000000; \
+ /* fall through */ \
+ case 1: \
+ delta += 1000000; \
+ break; \
+ } \
+ } \
+}
+
+#define TV_ADD_DELTA(a, delta, res) { \
+ register int xxus = (a)->tv_usec + (delta); \
+ \
+ (res)->tv_sec = (a)->tv_sec; \
+ while (xxus >= 1000000) { \
+ ++((res)->tv_sec); \
+ xxus -= 1000000; \
+ } \
+ (res)->tv_usec = xxus; \
+}
+
+#define RM_TIMEOUT 2 /* 1 Clock tick. */
+
+#if 1
+#define RM_MAXQUEUED 1 /* this isn't used in ALTQ/CBQ */
+#else
+#define RM_MAXQUEUED 16 /* Max number of packets downstream of CBQ */
+#endif
+#define RM_MAXQUEUE 64 /* Max queue length */
+#define RM_FILTER_GAIN 5 /* log2 of gain, e.g., 5 => 31/32 */
+#define RM_POWER (1 << RM_FILTER_GAIN)
+#define RM_MAXDEPTH 32
+#define RM_NS_PER_SEC (1000000000)
+
+typedef struct _rm_class_stats_ {
+ u_int handle;
+ u_int depth;
+
+ struct pktcntr xmit_cnt; /* packets sent in this class */
+ struct pktcntr drop_cnt; /* dropped packets */
+ u_int over; /* # times went over limit */
+ u_int borrows; /* # times tried to borrow */
+ u_int overactions; /* # times invoked overlimit action */
+ u_int delays; /* # times invoked delay actions */
+} rm_class_stats_t;
+
+/*
+ * CBQ Class state structure
+ */
+struct rm_class {
+ class_queue_t *q_; /* Queue of packets */
+ rm_ifdat_t *ifdat_;
+ int pri_; /* Class priority. */
+ int depth_; /* Class depth */
+ u_int ns_per_byte_; /* NanoSeconds per byte. */
+ u_int maxrate_; /* Bytes per second for this class. */
+ u_int allotment_; /* Fraction of link bandwidth. */
+ u_int w_allotment_; /* Weighted allotment for WRR */
+ int bytes_alloc_; /* Allocation for round of WRR */
+
+ int avgidle_;
+ int maxidle_;
+ int minidle_;
+ int offtime_;
+ int sleeping_; /* != 0 if delaying */
+ int qthresh_; /* Queue threshold for formal link sharing */
+ int leaf_; /* Note whether leaf class or not.*/
+
+ rm_class_t *children_; /* Children of this class */
+ rm_class_t *next_; /* Next pointer, used if child */
+
+ rm_class_t *peer_; /* Peer class */
+ rm_class_t *borrow_; /* Borrow class */
+ rm_class_t *parent_; /* Parent class */
+
+ void (*overlimit)(struct rm_class *, struct rm_class *);
+ void (*drop)(struct rm_class *); /* Class drop action. */
+
+ struct red *red_; /* RED state pointer */
+ struct altq_pktattr *pktattr_; /* saved hdr used by RED/ECN */
+ int flags_;
+
+ int last_pkttime_; /* saved pkt_time */
+ struct timeval undertime_; /* time can next send */
+ struct timeval last_; /* time last packet sent */
+ struct timeval overtime_;
+ struct callout callout_; /* for timeout() calls */
+
+ rm_class_stats_t stats_; /* Class Statistics */
+};
+
+/*
+ * CBQ Interface state
+ */
+struct rm_ifdat {
+ int queued_; /* # pkts queued downstream */
+ int efficient_; /* Link Efficency bit */
+ int wrr_; /* Enable Weighted Round-Robin */
+ u_long ns_per_byte_; /* Link byte speed. */
+ int maxqueued_; /* Max packets to queue */
+ int maxpkt_; /* Max packet size. */
+ int qi_; /* In/out pointers for downstream */
+ int qo_; /* packets */
+
+ /*
+ * Active class state and WRR state.
+ */
+ rm_class_t *active_[RM_MAXPRIO]; /* Active cl's in each pri */
+ int na_[RM_MAXPRIO]; /* # of active cl's in a pri */
+ int num_[RM_MAXPRIO]; /* # of cl's per pri */
+ int alloc_[RM_MAXPRIO]; /* Byte Allocation */
+ u_long M_[RM_MAXPRIO]; /* WRR weights. */
+
+ /*
+ * Network Interface/Solaris Queue state pointer.
+ */
+ struct ifaltq *ifq_;
+ rm_class_t *default_; /* Default Pkt class, BE */
+ rm_class_t *root_; /* Root Link class. */
+ rm_class_t *ctl_; /* Control Traffic class. */
+ void (*restart)(struct ifaltq *); /* Restart routine. */
+
+ /*
+ * Current packet downstream packet state and dynamic state.
+ */
+ rm_class_t *borrowed_[RM_MAXQUEUED]; /* Class borrowed last */
+ rm_class_t *class_[RM_MAXQUEUED]; /* class sending */
+ int curlen_[RM_MAXQUEUED]; /* Current pktlen */
+ struct timeval now_[RM_MAXQUEUED]; /* Current packet time. */
+ int is_overlimit_[RM_MAXQUEUED];/* Current packet time. */
+
+ int cutoff_; /* Cut-off depth for borrowing */
+
+ struct timeval ifnow_; /* expected xmit completion time */
+#if 1 /* ALTQ4PPP */
+ int maxiftime_; /* max delay inside interface */
+#endif
+ rm_class_t *pollcache_; /* cached rm_class by poll operation */
+};
+
+/* flags for rmc_init and rmc_newclass */
+/* class flags */
+#define RMCF_RED 0x0001
+#define RMCF_ECN 0x0002
+#define RMCF_RIO 0x0004
+#define RMCF_FLOWVALVE 0x0008 /* use flowvalve (aka penalty-box) */
+#define RMCF_CLEARDSCP 0x0010 /* clear diffserv codepoint */
+
+/* flags for rmc_init */
+#define RMCF_WRR 0x0100
+#define RMCF_EFFICIENT 0x0200
+
+#define is_a_parent_class(cl) ((cl)->children_ != NULL)
+
+extern rm_class_t *rmc_newclass(int, struct rm_ifdat *, u_int,
+ void (*)(struct rm_class *, struct rm_class *),
+ int, struct rm_class *, struct rm_class *,
+ u_int, int, u_int, int, int);
+extern void rmc_delete_class(struct rm_ifdat *, struct rm_class *);
+extern int rmc_modclass(struct rm_class *, u_int, int,
+ u_int, int, u_int, int);
+extern void rmc_init(struct ifaltq *, struct rm_ifdat *, u_int,
+ void (*)(struct ifaltq *),
+ int, int, u_int, int, u_int, int);
+extern int rmc_queue_packet(struct rm_class *, mbuf_t *);
+extern mbuf_t *rmc_dequeue_next(struct rm_ifdat *, int);
+extern void rmc_update_class_util(struct rm_ifdat *);
+extern void rmc_delay_action(struct rm_class *, struct rm_class *);
+extern void rmc_dropall(struct rm_class *);
+extern int rmc_get_weight(struct rm_ifdat *, int);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ALTQ_ALTQ_RMCLASS_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_rmclass_debug.h b/freebsd/sys/contrib/altq/altq/altq_rmclass_debug.h
new file mode 100644
index 00000000..6723a4b7
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_rmclass_debug.h
@@ -0,0 +1,112 @@
+/* $KAME: altq_rmclass_debug.h,v 1.3 2002/11/29 04:36:24 kjc Exp $ */
+
+/*
+ * Copyright (c) Sun Microsystems, Inc. 1998 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 SMCC Technology
+ * Development Group at Sun Microsystems, Inc.
+ *
+ * 4. The name of the Sun Microsystems, Inc nor may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * SUN MICROSYSTEMS DOES NOT CLAIM MERCHANTABILITY OF THIS SOFTWARE OR THE
+ * SUITABILITY OF THIS SOFTWARE FOR ANY PARTICULAR PURPOSE. The software is
+ * provided "as is" without express or implied warranty of any kind.
+ *
+ * These notices must be retained in any copies of any part of this software.
+ */
+
+#ifndef _ALTQ_ALTQ_RMCLASS_DEBUG_HH_
+#define _ALTQ_ALTQ_RMCLASS_DEBUG_HH_
+
+/* #pragma ident "@(#)rm_class_debug.h 1.7 98/05/04 SMI" */
+
+/*
+ * Cbq debugging macros
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef CBQ_TRACE
+#ifndef NCBQTRACE
+#define NCBQTRACE (16 * 1024)
+#endif
+
+/*
+ * To view the trace output, using adb, type:
+ * adb -k /dev/ksyms /dev/mem <cr>, then type
+ * cbqtrace_count/D to get the count, then type
+ * cbqtrace_buffer,0tcount/Dp4C" "Xn
+ * This will dump the trace buffer from 0 to count.
+ */
+/*
+ * in ALTQ, "call cbqtrace_dump(N)" from DDB to display 20 events
+ * from Nth event in the circular buffer.
+ */
+
+struct cbqtrace {
+ int count;
+ int function; /* address of function */
+ int trace_action; /* descriptive 4 characters */
+ int object; /* object operated on */
+};
+
+extern struct cbqtrace cbqtrace_buffer[];
+extern struct cbqtrace *cbqtrace_ptr;
+extern int cbqtrace_count;
+
+#define CBQTRACEINIT() { \
+ if (cbqtrace_ptr == NULL) \
+ cbqtrace_ptr = cbqtrace_buffer; \
+ else { \
+ cbqtrace_ptr = cbqtrace_buffer; \
+ bzero((void *)cbqtrace_ptr, sizeof(cbqtrace_buffer)); \
+ cbqtrace_count = 0; \
+ } \
+}
+
+#define LOCK_TRACE() splimp()
+#define UNLOCK_TRACE(x) splx(x)
+
+#define CBQTRACE(func, act, obj) { \
+ int __s = LOCK_TRACE(); \
+ int *_p = &cbqtrace_ptr->count; \
+ *_p++ = ++cbqtrace_count; \
+ *_p++ = (int)(func); \
+ *_p++ = (int)(act); \
+ *_p++ = (int)(obj); \
+ if ((struct cbqtrace *)(void *)_p >= &cbqtrace_buffer[NCBQTRACE])\
+ cbqtrace_ptr = cbqtrace_buffer; \
+ else \
+ cbqtrace_ptr = (struct cbqtrace *)(void *)_p; \
+ UNLOCK_TRACE(__s); \
+ }
+#else
+
+/* If no tracing, define no-ops */
+#define CBQTRACEINIT()
+#define CBQTRACE(a, b, c)
+
+#endif /* !CBQ_TRACE */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _ALTQ_ALTQ_RMCLASS_DEBUG_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altq_subr.c b/freebsd/sys/contrib/altq/altq/altq_subr.c
new file mode 100644
index 00000000..f4bb6b47
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_subr.c
@@ -0,0 +1,2042 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $KAME: altq_subr.c,v 1.21 2003/11/06 06:32:53 kjc Exp $ */
+
+/*
+ * Copyright (C) 1997-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 defined(__FreeBSD__) || defined(__NetBSD__)
+#include <freebsd/local/opt_altq.h>
+#include <freebsd/local/opt_inet.h>
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet6.h>
+#endif
+#endif /* __FreeBSD__ || __NetBSD__ */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/socketvar.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/errno.h>
+#include <freebsd/sys/syslog.h>
+#include <freebsd/sys/sysctl.h>
+#include <freebsd/sys/queue.h>
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/if_dl.h>
+#include <freebsd/net/if_types.h>
+#ifdef __FreeBSD__
+#include <freebsd/net/vnet.h>
+#endif
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#endif
+#include <freebsd/netinet/tcp.h>
+#include <freebsd/netinet/udp.h>
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/altq/altq.h>
+#ifdef ALTQ3_COMPAT
+#include <freebsd/altq/altq_conf.h>
+#endif
+
+/* machine dependent clock related includes */
+#ifdef __FreeBSD__
+#if __FreeBSD__ < 3
+#include <freebsd/local/opt_cpu.h> /* for FreeBSD-2.2.8 to get i586_ctr_freq */
+#endif
+#include <freebsd/sys/bus.h>
+#include <freebsd/sys/cpu.h>
+#include <freebsd/sys/eventhandler.h>
+#include <freebsd/machine/clock.h>
+#endif
+#if defined(__i386__)
+#include <freebsd/machine/cpufunc.h> /* for pentium tsc */
+#include <freebsd/machine/specialreg.h> /* for CPUID_TSC */
+#ifdef __FreeBSD__
+#include <freebsd/machine/md_var.h> /* for cpu_feature */
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+#include <freebsd/machine/cpu.h> /* for cpu_feature */
+#endif
+#endif /* __i386__ */
+
+/*
+ * internal function prototypes
+ */
+static void tbr_timeout(void *);
+int (*altq_input)(struct mbuf *, int) = NULL;
+static struct mbuf *tbr_dequeue(struct ifaltq *, int);
+static int tbr_timer = 0; /* token bucket regulator timer */
+#if !defined(__FreeBSD__) || (__FreeBSD_version < 600000)
+static struct callout tbr_callout = CALLOUT_INITIALIZER;
+#else
+static struct callout tbr_callout;
+#endif
+
+#ifdef ALTQ3_CLFIER_COMPAT
+static int extract_ports4(struct mbuf *, struct ip *, struct flowinfo_in *);
+#ifdef INET6
+static int extract_ports6(struct mbuf *, struct ip6_hdr *,
+ struct flowinfo_in6 *);
+#endif
+static int apply_filter4(u_int32_t, struct flow_filter *,
+ struct flowinfo_in *);
+static int apply_ppfilter4(u_int32_t, struct flow_filter *,
+ struct flowinfo_in *);
+#ifdef INET6
+static int apply_filter6(u_int32_t, struct flow_filter6 *,
+ struct flowinfo_in6 *);
+#endif
+static int apply_tosfilter4(u_int32_t, struct flow_filter *,
+ struct flowinfo_in *);
+static u_long get_filt_handle(struct acc_classifier *, int);
+static struct acc_filter *filth_to_filtp(struct acc_classifier *, u_long);
+static u_int32_t filt2fibmask(struct flow_filter *);
+
+static void ip4f_cache(struct ip *, struct flowinfo_in *);
+static int ip4f_lookup(struct ip *, struct flowinfo_in *);
+static int ip4f_init(void);
+static struct ip4_frag *ip4f_alloc(void);
+static void ip4f_free(struct ip4_frag *);
+#endif /* ALTQ3_CLFIER_COMPAT */
+
+/*
+ * alternate queueing support routines
+ */
+
+/* look up the queue state by the interface name and the queueing type. */
+void *
+altq_lookup(name, type)
+ char *name;
+ int type;
+{
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(name)) != NULL) {
+ /* read if_snd unlocked */
+ if (type != ALTQT_NONE && ifp->if_snd.altq_type == type)
+ return (ifp->if_snd.altq_disc);
+ }
+
+ return NULL;
+}
+
+int
+altq_attach(ifq, type, discipline, enqueue, dequeue, request, clfier, classify)
+ struct ifaltq *ifq;
+ int type;
+ void *discipline;
+ int (*enqueue)(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
+ struct mbuf *(*dequeue)(struct ifaltq *, int);
+ int (*request)(struct ifaltq *, int, void *);
+ void *clfier;
+ void *(*classify)(void *, struct mbuf *, int);
+{
+ IFQ_LOCK(ifq);
+ if (!ALTQ_IS_READY(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return ENXIO;
+ }
+
+#ifdef ALTQ3_COMPAT
+ /*
+ * pfaltq can override the existing discipline, but altq3 cannot.
+ * check these if clfier is not NULL (which implies altq3).
+ */
+ if (clfier != NULL) {
+ if (ALTQ_IS_ENABLED(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return EBUSY;
+ }
+ if (ALTQ_IS_ATTACHED(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return EEXIST;
+ }
+ }
+#endif
+ ifq->altq_type = type;
+ ifq->altq_disc = discipline;
+ ifq->altq_enqueue = enqueue;
+ ifq->altq_dequeue = dequeue;
+ ifq->altq_request = request;
+ ifq->altq_clfier = clfier;
+ ifq->altq_classify = classify;
+ ifq->altq_flags &= (ALTQF_CANTCHANGE|ALTQF_ENABLED);
+#ifdef ALTQ3_COMPAT
+#ifdef ALTQ_KLD
+ altq_module_incref(type);
+#endif
+#endif
+ IFQ_UNLOCK(ifq);
+ return 0;
+}
+
+int
+altq_detach(ifq)
+ struct ifaltq *ifq;
+{
+ IFQ_LOCK(ifq);
+
+ if (!ALTQ_IS_READY(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return ENXIO;
+ }
+ if (ALTQ_IS_ENABLED(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return EBUSY;
+ }
+ if (!ALTQ_IS_ATTACHED(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return (0);
+ }
+#ifdef ALTQ3_COMPAT
+#ifdef ALTQ_KLD
+ altq_module_declref(ifq->altq_type);
+#endif
+#endif
+
+ ifq->altq_type = ALTQT_NONE;
+ ifq->altq_disc = NULL;
+ ifq->altq_enqueue = NULL;
+ ifq->altq_dequeue = NULL;
+ ifq->altq_request = NULL;
+ ifq->altq_clfier = NULL;
+ ifq->altq_classify = NULL;
+ ifq->altq_flags &= ALTQF_CANTCHANGE;
+
+ IFQ_UNLOCK(ifq);
+ return 0;
+}
+
+int
+altq_enable(ifq)
+ struct ifaltq *ifq;
+{
+ int s;
+
+ IFQ_LOCK(ifq);
+
+ if (!ALTQ_IS_READY(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return ENXIO;
+ }
+ if (ALTQ_IS_ENABLED(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return 0;
+ }
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_PURGE_NOLOCK(ifq);
+ ASSERT(ifq->ifq_len == 0);
+ ifq->ifq_drv_maxlen = 0; /* disable bulk dequeue */
+ ifq->altq_flags |= ALTQF_ENABLED;
+ if (ifq->altq_clfier != NULL)
+ ifq->altq_flags |= ALTQF_CLASSIFY;
+ splx(s);
+
+ IFQ_UNLOCK(ifq);
+ return 0;
+}
+
+int
+altq_disable(ifq)
+ struct ifaltq *ifq;
+{
+ int s;
+
+ IFQ_LOCK(ifq);
+ if (!ALTQ_IS_ENABLED(ifq)) {
+ IFQ_UNLOCK(ifq);
+ return 0;
+ }
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ IFQ_PURGE_NOLOCK(ifq);
+ ASSERT(ifq->ifq_len == 0);
+ ifq->altq_flags &= ~(ALTQF_ENABLED|ALTQF_CLASSIFY);
+ splx(s);
+
+ IFQ_UNLOCK(ifq);
+ return 0;
+}
+
+#ifdef ALTQ_DEBUG
+void
+altq_assert(file, line, failedexpr)
+ const char *file, *failedexpr;
+ int line;
+{
+ (void)printf("altq assertion \"%s\" failed: file \"%s\", line %d\n",
+ failedexpr, file, line);
+ panic("altq assertion");
+ /* NOTREACHED */
+}
+#endif
+
+/*
+ * internal representation of token bucket parameters
+ * rate: byte_per_unittime << 32
+ * (((bits_per_sec) / 8) << 32) / machclk_freq
+ * depth: byte << 32
+ *
+ */
+#define TBR_SHIFT 32
+#define TBR_SCALE(x) ((int64_t)(x) << TBR_SHIFT)
+#define TBR_UNSCALE(x) ((x) >> TBR_SHIFT)
+
+static struct mbuf *
+tbr_dequeue(ifq, op)
+ struct ifaltq *ifq;
+ int op;
+{
+ struct tb_regulator *tbr;
+ struct mbuf *m;
+ int64_t interval;
+ u_int64_t now;
+
+ IFQ_LOCK_ASSERT(ifq);
+ tbr = ifq->altq_tbr;
+ if (op == ALTDQ_REMOVE && tbr->tbr_lastop == ALTDQ_POLL) {
+ /* if this is a remove after poll, bypass tbr check */
+ } else {
+ /* update token only when it is negative */
+ if (tbr->tbr_token <= 0) {
+ now = read_machclk();
+ interval = now - tbr->tbr_last;
+ if (interval >= tbr->tbr_filluptime)
+ tbr->tbr_token = tbr->tbr_depth;
+ else {
+ tbr->tbr_token += interval * tbr->tbr_rate;
+ if (tbr->tbr_token > tbr->tbr_depth)
+ tbr->tbr_token = tbr->tbr_depth;
+ }
+ tbr->tbr_last = now;
+ }
+ /* if token is still negative, don't allow dequeue */
+ if (tbr->tbr_token <= 0)
+ return (NULL);
+ }
+
+ if (ALTQ_IS_ENABLED(ifq))
+ m = (*ifq->altq_dequeue)(ifq, op);
+ else {
+ if (op == ALTDQ_POLL)
+ _IF_POLL(ifq, m);
+ else
+ _IF_DEQUEUE(ifq, m);
+ }
+
+ if (m != NULL && op == ALTDQ_REMOVE)
+ tbr->tbr_token -= TBR_SCALE(m_pktlen(m));
+ tbr->tbr_lastop = op;
+ return (m);
+}
+
+/*
+ * set a token bucket regulator.
+ * if the specified rate is zero, the token bucket regulator is deleted.
+ */
+int
+tbr_set(ifq, profile)
+ struct ifaltq *ifq;
+ struct tb_profile *profile;
+{
+ struct tb_regulator *tbr, *otbr;
+
+ if (tbr_dequeue_ptr == NULL)
+ tbr_dequeue_ptr = tbr_dequeue;
+
+ if (machclk_freq == 0)
+ init_machclk();
+ if (machclk_freq == 0) {
+ printf("tbr_set: no cpu clock available!\n");
+ return (ENXIO);
+ }
+
+ IFQ_LOCK(ifq);
+ if (profile->rate == 0) {
+ /* delete this tbr */
+ if ((tbr = ifq->altq_tbr) == NULL) {
+ IFQ_UNLOCK(ifq);
+ return (ENOENT);
+ }
+ ifq->altq_tbr = NULL;
+ free(tbr, M_DEVBUF);
+ IFQ_UNLOCK(ifq);
+ return (0);
+ }
+
+ IFQ_UNLOCK(ifq);
+ tbr = malloc(sizeof(struct tb_regulator),
+ M_DEVBUF, M_WAITOK);
+ if (tbr == NULL) { /* can not happen */
+ IFQ_UNLOCK(ifq);
+ return (ENOMEM);
+ }
+ bzero(tbr, sizeof(struct tb_regulator));
+
+ tbr->tbr_rate = TBR_SCALE(profile->rate / 8) / machclk_freq;
+ tbr->tbr_depth = TBR_SCALE(profile->depth);
+ if (tbr->tbr_rate > 0)
+ tbr->tbr_filluptime = tbr->tbr_depth / tbr->tbr_rate;
+ else
+ tbr->tbr_filluptime = 0xffffffffffffffffLL;
+ tbr->tbr_token = tbr->tbr_depth;
+ tbr->tbr_last = read_machclk();
+ tbr->tbr_lastop = ALTDQ_REMOVE;
+
+ IFQ_LOCK(ifq);
+ otbr = ifq->altq_tbr;
+ ifq->altq_tbr = tbr; /* set the new tbr */
+
+ if (otbr != NULL)
+ free(otbr, M_DEVBUF);
+ else {
+ if (tbr_timer == 0) {
+ CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0);
+ tbr_timer = 1;
+ }
+ }
+ IFQ_UNLOCK(ifq);
+ return (0);
+}
+
+/*
+ * tbr_timeout goes through the interface list, and kicks the drivers
+ * if necessary.
+ *
+ * MPSAFE
+ */
+static void
+tbr_timeout(arg)
+ void *arg;
+{
+#if defined(__FreeBSD__)
+ VNET_ITERATOR_DECL(vnet_iter);
+#endif
+ struct ifnet *ifp;
+ int active, s;
+
+ active = 0;
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500000)
+ IFNET_RLOCK_NOSLEEP();
+ VNET_LIST_RLOCK_NOSLEEP();
+ VNET_FOREACH(vnet_iter) {
+ CURVNET_SET(vnet_iter);
+#endif
+ for (ifp = TAILQ_FIRST(&V_ifnet); ifp;
+ ifp = TAILQ_NEXT(ifp, if_list)) {
+ /* read from if_snd unlocked */
+ if (!TBR_IS_ENABLED(&ifp->if_snd))
+ continue;
+ active++;
+ if (!IFQ_IS_EMPTY(&ifp->if_snd) &&
+ ifp->if_start != NULL)
+ (*ifp->if_start)(ifp);
+ }
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500000)
+ CURVNET_RESTORE();
+ }
+ VNET_LIST_RUNLOCK_NOSLEEP();
+ IFNET_RUNLOCK_NOSLEEP();
+#endif
+ splx(s);
+ if (active > 0)
+ CALLOUT_RESET(&tbr_callout, 1, tbr_timeout, (void *)0);
+ else
+ tbr_timer = 0; /* don't need tbr_timer anymore */
+#if defined(__alpha__) && !defined(ALTQ_NOPCC)
+ {
+ /*
+ * XXX read out the machine dependent clock once a second
+ * to detect counter wrap-around.
+ */
+ static u_int cnt;
+
+ if (++cnt >= hz) {
+ (void)read_machclk();
+ cnt = 0;
+ }
+ }
+#endif /* __alpha__ && !ALTQ_NOPCC */
+}
+
+/*
+ * get token bucket regulator profile
+ */
+int
+tbr_get(ifq, profile)
+ struct ifaltq *ifq;
+ struct tb_profile *profile;
+{
+ struct tb_regulator *tbr;
+
+ IFQ_LOCK(ifq);
+ if ((tbr = ifq->altq_tbr) == NULL) {
+ profile->rate = 0;
+ profile->depth = 0;
+ } else {
+ profile->rate =
+ (u_int)TBR_UNSCALE(tbr->tbr_rate * 8 * machclk_freq);
+ profile->depth = (u_int)TBR_UNSCALE(tbr->tbr_depth);
+ }
+ IFQ_UNLOCK(ifq);
+ return (0);
+}
+
+/*
+ * attach a discipline to the interface. if one already exists, it is
+ * overridden.
+ * Locking is done in the discipline specific attach functions. Basically
+ * they call back to altq_attach which takes care of the attach and locking.
+ */
+int
+altq_pfattach(struct pf_altq *a)
+{
+ int error = 0;
+
+ switch (a->scheduler) {
+ case ALTQT_NONE:
+ break;
+#ifdef ALTQ_CBQ
+ case ALTQT_CBQ:
+ error = cbq_pfattach(a);
+ break;
+#endif
+#ifdef ALTQ_PRIQ
+ case ALTQT_PRIQ:
+ error = priq_pfattach(a);
+ break;
+#endif
+#ifdef ALTQ_HFSC
+ case ALTQT_HFSC:
+ error = hfsc_pfattach(a);
+ break;
+#endif
+ default:
+ error = ENXIO;
+ }
+
+ return (error);
+}
+
+/*
+ * detach a discipline from the interface.
+ * it is possible that the discipline was already overridden by another
+ * discipline.
+ */
+int
+altq_pfdetach(struct pf_altq *a)
+{
+ struct ifnet *ifp;
+ int s, error = 0;
+
+ if ((ifp = ifunit(a->ifname)) == NULL)
+ return (EINVAL);
+
+ /* if this discipline is no longer referenced, just return */
+ /* read unlocked from if_snd */
+ if (a->altq_disc == NULL || a->altq_disc != ifp->if_snd.altq_disc)
+ return (0);
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ /* read unlocked from if_snd, _disable and _detach take care */
+ if (ALTQ_IS_ENABLED(&ifp->if_snd))
+ error = altq_disable(&ifp->if_snd);
+ if (error == 0)
+ error = altq_detach(&ifp->if_snd);
+ splx(s);
+
+ return (error);
+}
+
+/*
+ * add a discipline or a queue
+ * Locking is done in the discipline specific functions with regards to
+ * malloc with WAITOK, also it is not yet clear which lock to use.
+ */
+int
+altq_add(struct pf_altq *a)
+{
+ int error = 0;
+
+ if (a->qname[0] != 0)
+ return (altq_add_queue(a));
+
+ if (machclk_freq == 0)
+ init_machclk();
+ if (machclk_freq == 0)
+ panic("altq_add: no cpu clock");
+
+ switch (a->scheduler) {
+#ifdef ALTQ_CBQ
+ case ALTQT_CBQ:
+ error = cbq_add_altq(a);
+ break;
+#endif
+#ifdef ALTQ_PRIQ
+ case ALTQT_PRIQ:
+ error = priq_add_altq(a);
+ break;
+#endif
+#ifdef ALTQ_HFSC
+ case ALTQT_HFSC:
+ error = hfsc_add_altq(a);
+ break;
+#endif
+ default:
+ error = ENXIO;
+ }
+
+ return (error);
+}
+
+/*
+ * remove a discipline or a queue
+ * It is yet unclear what lock to use to protect this operation, the
+ * discipline specific functions will determine and grab it
+ */
+int
+altq_remove(struct pf_altq *a)
+{
+ int error = 0;
+
+ if (a->qname[0] != 0)
+ return (altq_remove_queue(a));
+
+ switch (a->scheduler) {
+#ifdef ALTQ_CBQ
+ case ALTQT_CBQ:
+ error = cbq_remove_altq(a);
+ break;
+#endif
+#ifdef ALTQ_PRIQ
+ case ALTQT_PRIQ:
+ error = priq_remove_altq(a);
+ break;
+#endif
+#ifdef ALTQ_HFSC
+ case ALTQT_HFSC:
+ error = hfsc_remove_altq(a);
+ break;
+#endif
+ default:
+ error = ENXIO;
+ }
+
+ return (error);
+}
+
+/*
+ * add a queue to the discipline
+ * It is yet unclear what lock to use to protect this operation, the
+ * discipline specific functions will determine and grab it
+ */
+int
+altq_add_queue(struct pf_altq *a)
+{
+ int error = 0;
+
+ switch (a->scheduler) {
+#ifdef ALTQ_CBQ
+ case ALTQT_CBQ:
+ error = cbq_add_queue(a);
+ break;
+#endif
+#ifdef ALTQ_PRIQ
+ case ALTQT_PRIQ:
+ error = priq_add_queue(a);
+ break;
+#endif
+#ifdef ALTQ_HFSC
+ case ALTQT_HFSC:
+ error = hfsc_add_queue(a);
+ break;
+#endif
+ default:
+ error = ENXIO;
+ }
+
+ return (error);
+}
+
+/*
+ * remove a queue from the discipline
+ * It is yet unclear what lock to use to protect this operation, the
+ * discipline specific functions will determine and grab it
+ */
+int
+altq_remove_queue(struct pf_altq *a)
+{
+ int error = 0;
+
+ switch (a->scheduler) {
+#ifdef ALTQ_CBQ
+ case ALTQT_CBQ:
+ error = cbq_remove_queue(a);
+ break;
+#endif
+#ifdef ALTQ_PRIQ
+ case ALTQT_PRIQ:
+ error = priq_remove_queue(a);
+ break;
+#endif
+#ifdef ALTQ_HFSC
+ case ALTQT_HFSC:
+ error = hfsc_remove_queue(a);
+ break;
+#endif
+ default:
+ error = ENXIO;
+ }
+
+ return (error);
+}
+
+/*
+ * get queue statistics
+ * Locking is done in the discipline specific functions with regards to
+ * copyout operations, also it is not yet clear which lock to use.
+ */
+int
+altq_getqstats(struct pf_altq *a, void *ubuf, int *nbytes)
+{
+ int error = 0;
+
+ switch (a->scheduler) {
+#ifdef ALTQ_CBQ
+ case ALTQT_CBQ:
+ error = cbq_getqstats(a, ubuf, nbytes);
+ break;
+#endif
+#ifdef ALTQ_PRIQ
+ case ALTQT_PRIQ:
+ error = priq_getqstats(a, ubuf, nbytes);
+ break;
+#endif
+#ifdef ALTQ_HFSC
+ case ALTQT_HFSC:
+ error = hfsc_getqstats(a, ubuf, nbytes);
+ break;
+#endif
+ default:
+ error = ENXIO;
+ }
+
+ return (error);
+}
+
+/*
+ * read and write diffserv field in IPv4 or IPv6 header
+ */
+u_int8_t
+read_dsfield(m, pktattr)
+ struct mbuf *m;
+ struct altq_pktattr *pktattr;
+{
+ struct mbuf *m0;
+ u_int8_t ds_field = 0;
+
+ if (pktattr == NULL ||
+ (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
+ return ((u_int8_t)0);
+
+ /* verify that pattr_hdr is within the mbuf data */
+ for (m0 = m; m0 != NULL; m0 = m0->m_next)
+ if ((pktattr->pattr_hdr >= m0->m_data) &&
+ (pktattr->pattr_hdr < m0->m_data + m0->m_len))
+ break;
+ if (m0 == NULL) {
+ /* ick, pattr_hdr is stale */
+ pktattr->pattr_af = AF_UNSPEC;
+#ifdef ALTQ_DEBUG
+ printf("read_dsfield: can't locate header!\n");
+#endif
+ return ((u_int8_t)0);
+ }
+
+ if (pktattr->pattr_af == AF_INET) {
+ struct ip *ip = (struct ip *)pktattr->pattr_hdr;
+
+ if (ip->ip_v != 4)
+ return ((u_int8_t)0); /* version mismatch! */
+ ds_field = ip->ip_tos;
+ }
+#ifdef INET6
+ else if (pktattr->pattr_af == AF_INET6) {
+ struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
+ u_int32_t flowlabel;
+
+ flowlabel = ntohl(ip6->ip6_flow);
+ if ((flowlabel >> 28) != 6)
+ return ((u_int8_t)0); /* version mismatch! */
+ ds_field = (flowlabel >> 20) & 0xff;
+ }
+#endif
+ return (ds_field);
+}
+
+void
+write_dsfield(struct mbuf *m, struct altq_pktattr *pktattr, u_int8_t dsfield)
+{
+ struct mbuf *m0;
+
+ if (pktattr == NULL ||
+ (pktattr->pattr_af != AF_INET && pktattr->pattr_af != AF_INET6))
+ return;
+
+ /* verify that pattr_hdr is within the mbuf data */
+ for (m0 = m; m0 != NULL; m0 = m0->m_next)
+ if ((pktattr->pattr_hdr >= m0->m_data) &&
+ (pktattr->pattr_hdr < m0->m_data + m0->m_len))
+ break;
+ if (m0 == NULL) {
+ /* ick, pattr_hdr is stale */
+ pktattr->pattr_af = AF_UNSPEC;
+#ifdef ALTQ_DEBUG
+ printf("write_dsfield: can't locate header!\n");
+#endif
+ return;
+ }
+
+ if (pktattr->pattr_af == AF_INET) {
+ struct ip *ip = (struct ip *)pktattr->pattr_hdr;
+ u_int8_t old;
+ int32_t sum;
+
+ if (ip->ip_v != 4)
+ return; /* version mismatch! */
+ old = ip->ip_tos;
+ dsfield |= old & 3; /* leave CU bits */
+ if (old == dsfield)
+ return;
+ ip->ip_tos = dsfield;
+ /*
+ * update checksum (from RFC1624)
+ * HC' = ~(~HC + ~m + m')
+ */
+ sum = ~ntohs(ip->ip_sum) & 0xffff;
+ sum += 0xff00 + (~old & 0xff) + dsfield;
+ sum = (sum >> 16) + (sum & 0xffff);
+ sum += (sum >> 16); /* add carry */
+
+ ip->ip_sum = htons(~sum & 0xffff);
+ }
+#ifdef INET6
+ else if (pktattr->pattr_af == AF_INET6) {
+ struct ip6_hdr *ip6 = (struct ip6_hdr *)pktattr->pattr_hdr;
+ u_int32_t flowlabel;
+
+ flowlabel = ntohl(ip6->ip6_flow);
+ if ((flowlabel >> 28) != 6)
+ return; /* version mismatch! */
+ flowlabel = (flowlabel & 0xf03fffff) | (dsfield << 20);
+ ip6->ip6_flow = htonl(flowlabel);
+ }
+#endif
+ return;
+}
+
+
+/*
+ * high resolution clock support taking advantage of a machine dependent
+ * high resolution time counter (e.g., timestamp counter of intel pentium).
+ * we assume
+ * - 64-bit-long monotonically-increasing counter
+ * - frequency range is 100M-4GHz (CPU speed)
+ */
+/* if pcc is not available or disabled, emulate 256MHz using microtime() */
+#define MACHCLK_SHIFT 8
+
+int machclk_usepcc;
+u_int32_t machclk_freq;
+u_int32_t machclk_per_tick;
+
+#ifdef __alpha__
+#ifdef __FreeBSD__
+extern u_int32_t cycles_per_sec; /* alpha cpu clock frequency */
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+extern u_int64_t cycles_per_usec; /* alpha cpu clock frequency */
+#endif
+#endif /* __alpha__ */
+#if defined(__i386__) && defined(__NetBSD__)
+extern u_int64_t cpu_tsc_freq;
+#endif /* __alpha__ */
+
+#ifndef __rtems__
+#if (__FreeBSD_version >= 700035)
+/* Update TSC freq with the value indicated by the caller. */
+static void
+tsc_freq_changed(void *arg, const struct cf_level *level, int status)
+{
+ /* If there was an error during the transition, don't do anything. */
+ if (status != 0)
+ return;
+
+#if (__FreeBSD_version >= 701102) && (defined(__amd64__) || defined(__i386__))
+ /* If TSC is P-state invariant, don't do anything. */
+ if (tsc_is_invariant)
+ return;
+#endif
+
+ /* Total setting for this level gives the new frequency in MHz. */
+ init_machclk();
+}
+EVENTHANDLER_DEFINE(cpufreq_post_change, tsc_freq_changed, NULL,
+ EVENTHANDLER_PRI_LAST);
+#endif /* __FreeBSD_version >= 700035 */
+#endif /* __rtems__ */
+
+static void
+init_machclk_setup(void)
+{
+#if (__FreeBSD_version >= 600000)
+ callout_init(&tbr_callout, 0);
+#endif
+
+ machclk_usepcc = 1;
+
+#if (!defined(__i386__) && !defined(__alpha__)) || defined(ALTQ_NOPCC)
+ machclk_usepcc = 0;
+#endif
+#if defined(__FreeBSD__) && defined(SMP)
+ machclk_usepcc = 0;
+#endif
+#if defined(__NetBSD__) && defined(MULTIPROCESSOR)
+ machclk_usepcc = 0;
+#endif
+#ifdef __i386__
+#ifndef __rtems__
+ /* check if TSC is available */
+ if (machclk_usepcc == 1 && ((cpu_feature & CPUID_TSC) == 0 ||
+ tsc_is_broken))
+#else /* __rtems__ */
+ /* check if TSC is available */
+ if (machclk_usepcc == 1 && ((cpu_feature & CPUID_TSC) == 0 ||
+ !(x86_has_tsc()) ))
+#endif /* __rtems__ */
+ machclk_usepcc = 0;
+#endif
+}
+
+void
+init_machclk(void)
+{
+ static int called;
+
+ /* Call one-time initialization function. */
+ if (!called) {
+ init_machclk_setup();
+ called = 1;
+ }
+
+ if (machclk_usepcc == 0) {
+ /* emulate 256MHz using microtime() */
+ machclk_freq = 1000000 << MACHCLK_SHIFT;
+ machclk_per_tick = machclk_freq / hz;
+#ifdef ALTQ_DEBUG
+ printf("altq: emulate %uHz cpu clock\n", machclk_freq);
+#endif
+ return;
+ }
+
+ /*
+ * if the clock frequency (of Pentium TSC or Alpha PCC) is
+ * accessible, just use it.
+ */
+#ifndef __rtems__
+#ifdef __i386__
+#ifdef __FreeBSD__
+#if (__FreeBSD_version > 300000)
+ machclk_freq = tsc_freq;
+#else
+ machclk_freq = i586_ctr_freq;
+#endif
+#elif defined(__NetBSD__)
+ machclk_freq = (u_int32_t)cpu_tsc_freq;
+#elif defined(__OpenBSD__) && (defined(I586_CPU) || defined(I686_CPU))
+ machclk_freq = pentium_mhz * 1000000;
+#endif
+#elif defined(__alpha__)
+#ifdef __FreeBSD__
+ machclk_freq = cycles_per_sec;
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+ machclk_freq = (u_int32_t)(cycles_per_usec * 1000000);
+#endif
+#endif /* __alpha__ */
+#endif /* __rtems__ */
+
+ /*
+ * if we don't know the clock frequency, measure it.
+ */
+ if (machclk_freq == 0) {
+ static int wait;
+ struct timeval tv_start, tv_end;
+ u_int64_t start, end, diff;
+ int timo;
+
+ microtime(&tv_start);
+ start = read_machclk();
+ timo = hz; /* 1 sec */
+ (void)tsleep(&wait, PWAIT | PCATCH, "init_machclk", timo);
+ microtime(&tv_end);
+ end = read_machclk();
+ diff = (u_int64_t)(tv_end.tv_sec - tv_start.tv_sec) * 1000000
+ + tv_end.tv_usec - tv_start.tv_usec;
+ if (diff != 0)
+ machclk_freq = (u_int)((end - start) * 1000000 / diff);
+ }
+
+ machclk_per_tick = machclk_freq / hz;
+
+#ifdef ALTQ_DEBUG
+ printf("altq: CPU clock: %uHz\n", machclk_freq);
+#endif
+}
+
+#if defined(__OpenBSD__) && defined(__i386__)
+static __inline u_int64_t
+rdtsc(void)
+{
+ u_int64_t rv;
+ __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
+ return (rv);
+}
+#endif /* __OpenBSD__ && __i386__ */
+
+u_int64_t
+read_machclk(void)
+{
+ u_int64_t val;
+
+ if (machclk_usepcc) {
+#if defined(__i386__)
+ val = rdtsc();
+#elif defined(__alpha__)
+ static u_int32_t last_pcc, upper;
+ u_int32_t pcc;
+
+ /*
+ * for alpha, make a 64bit counter value out of the 32bit
+ * alpha processor cycle counter.
+ * read_machclk must be called within a half of its
+ * wrap-around cycle (about 5 sec for 400MHz cpu) to properly
+ * detect a counter wrap-around.
+ * tbr_timeout calls read_machclk once a second.
+ */
+ pcc = (u_int32_t)alpha_rpcc();
+ if (pcc <= last_pcc)
+ upper++;
+ last_pcc = pcc;
+ val = ((u_int64_t)upper << 32) + pcc;
+#else
+ panic("read_machclk");
+#endif
+ } else {
+ struct timeval tv;
+
+ microtime(&tv);
+ val = (((u_int64_t)(tv.tv_sec - boottime.tv_sec) * 1000000
+ + tv.tv_usec) << MACHCLK_SHIFT);
+ }
+ return (val);
+}
+
+#ifdef ALTQ3_CLFIER_COMPAT
+
+#ifndef IPPROTO_ESP
+#define IPPROTO_ESP 50 /* encapsulating security payload */
+#endif
+#ifndef IPPROTO_AH
+#define IPPROTO_AH 51 /* authentication header */
+#endif
+
+/*
+ * extract flow information from a given packet.
+ * filt_mask shows flowinfo fields required.
+ * we assume the ip header is in one mbuf, and addresses and ports are
+ * in network byte order.
+ */
+int
+altq_extractflow(m, af, flow, filt_bmask)
+ struct mbuf *m;
+ int af;
+ struct flowinfo *flow;
+ u_int32_t filt_bmask;
+{
+
+ switch (af) {
+ case PF_INET: {
+ struct flowinfo_in *fin;
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+
+ if (ip->ip_v != 4)
+ break;
+
+ fin = (struct flowinfo_in *)flow;
+ fin->fi_len = sizeof(struct flowinfo_in);
+ fin->fi_family = AF_INET;
+
+ fin->fi_proto = ip->ip_p;
+ fin->fi_tos = ip->ip_tos;
+
+ fin->fi_src.s_addr = ip->ip_src.s_addr;
+ fin->fi_dst.s_addr = ip->ip_dst.s_addr;
+
+ if (filt_bmask & FIMB4_PORTS)
+ /* if port info is required, extract port numbers */
+ extract_ports4(m, ip, fin);
+ else {
+ fin->fi_sport = 0;
+ fin->fi_dport = 0;
+ fin->fi_gpi = 0;
+ }
+ return (1);
+ }
+
+#ifdef INET6
+ case PF_INET6: {
+ struct flowinfo_in6 *fin6;
+ struct ip6_hdr *ip6;
+
+ ip6 = mtod(m, struct ip6_hdr *);
+ /* should we check the ip version? */
+
+ fin6 = (struct flowinfo_in6 *)flow;
+ fin6->fi6_len = sizeof(struct flowinfo_in6);
+ fin6->fi6_family = AF_INET6;
+
+ fin6->fi6_proto = ip6->ip6_nxt;
+ fin6->fi6_tclass = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
+
+ fin6->fi6_flowlabel = ip6->ip6_flow & htonl(0x000fffff);
+ fin6->fi6_src = ip6->ip6_src;
+ fin6->fi6_dst = ip6->ip6_dst;
+
+ if ((filt_bmask & FIMB6_PORTS) ||
+ ((filt_bmask & FIMB6_PROTO)
+ && ip6->ip6_nxt > IPPROTO_IPV6))
+ /*
+ * if port info is required, or proto is required
+ * but there are option headers, extract port
+ * and protocol numbers.
+ */
+ extract_ports6(m, ip6, fin6);
+ else {
+ fin6->fi6_sport = 0;
+ fin6->fi6_dport = 0;
+ fin6->fi6_gpi = 0;
+ }
+ return (1);
+ }
+#endif /* INET6 */
+
+ default:
+ break;
+ }
+
+ /* failed */
+ flow->fi_len = sizeof(struct flowinfo);
+ flow->fi_family = AF_UNSPEC;
+ return (0);
+}
+
+/*
+ * helper routine to extract port numbers
+ */
+/* structure for ipsec and ipv6 option header template */
+struct _opt6 {
+ u_int8_t opt6_nxt; /* next header */
+ u_int8_t opt6_hlen; /* header extension length */
+ u_int16_t _pad;
+ u_int32_t ah_spi; /* security parameter index
+ for authentication header */
+};
+
+/*
+ * extract port numbers from a ipv4 packet.
+ */
+static int
+extract_ports4(m, ip, fin)
+ struct mbuf *m;
+ struct ip *ip;
+ struct flowinfo_in *fin;
+{
+ struct mbuf *m0;
+ u_short ip_off;
+ u_int8_t proto;
+ int off;
+
+ fin->fi_sport = 0;
+ fin->fi_dport = 0;
+ fin->fi_gpi = 0;
+
+ ip_off = ntohs(ip->ip_off);
+ /* if it is a fragment, try cached fragment info */
+ if (ip_off & IP_OFFMASK) {
+ ip4f_lookup(ip, fin);
+ return (1);
+ }
+
+ /* locate the mbuf containing the protocol header */
+ for (m0 = m; m0 != NULL; m0 = m0->m_next)
+ if (((caddr_t)ip >= m0->m_data) &&
+ ((caddr_t)ip < m0->m_data + m0->m_len))
+ break;
+ if (m0 == NULL) {
+#ifdef ALTQ_DEBUG
+ printf("extract_ports4: can't locate header! ip=%p\n", ip);
+#endif
+ return (0);
+ }
+ off = ((caddr_t)ip - m0->m_data) + (ip->ip_hl << 2);
+ proto = ip->ip_p;
+
+#ifdef ALTQ_IPSEC
+ again:
+#endif
+ while (off >= m0->m_len) {
+ off -= m0->m_len;
+ m0 = m0->m_next;
+ if (m0 == NULL)
+ return (0); /* bogus ip_hl! */
+ }
+ if (m0->m_len < off + 4)
+ return (0);
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP: {
+ struct udphdr *udp;
+
+ udp = (struct udphdr *)(mtod(m0, caddr_t) + off);
+ fin->fi_sport = udp->uh_sport;
+ fin->fi_dport = udp->uh_dport;
+ fin->fi_proto = proto;
+ }
+ break;
+
+#ifdef ALTQ_IPSEC
+ case IPPROTO_ESP:
+ if (fin->fi_gpi == 0){
+ u_int32_t *gpi;
+
+ gpi = (u_int32_t *)(mtod(m0, caddr_t) + off);
+ fin->fi_gpi = *gpi;
+ }
+ fin->fi_proto = proto;
+ break;
+
+ case IPPROTO_AH: {
+ /* get next header and header length */
+ struct _opt6 *opt6;
+
+ opt6 = (struct _opt6 *)(mtod(m0, caddr_t) + off);
+ proto = opt6->opt6_nxt;
+ off += 8 + (opt6->opt6_hlen * 4);
+ if (fin->fi_gpi == 0 && m0->m_len >= off + 8)
+ fin->fi_gpi = opt6->ah_spi;
+ }
+ /* goto the next header */
+ goto again;
+#endif /* ALTQ_IPSEC */
+
+ default:
+ fin->fi_proto = proto;
+ return (0);
+ }
+
+ /* if this is a first fragment, cache it. */
+ if (ip_off & IP_MF)
+ ip4f_cache(ip, fin);
+
+ return (1);
+}
+
+#ifdef INET6
+static int
+extract_ports6(m, ip6, fin6)
+ struct mbuf *m;
+ struct ip6_hdr *ip6;
+ struct flowinfo_in6 *fin6;
+{
+ struct mbuf *m0;
+ int off;
+ u_int8_t proto;
+
+ fin6->fi6_gpi = 0;
+ fin6->fi6_sport = 0;
+ fin6->fi6_dport = 0;
+
+ /* locate the mbuf containing the protocol header */
+ for (m0 = m; m0 != NULL; m0 = m0->m_next)
+ if (((caddr_t)ip6 >= m0->m_data) &&
+ ((caddr_t)ip6 < m0->m_data + m0->m_len))
+ break;
+ if (m0 == NULL) {
+#ifdef ALTQ_DEBUG
+ printf("extract_ports6: can't locate header! ip6=%p\n", ip6);
+#endif
+ return (0);
+ }
+ off = ((caddr_t)ip6 - m0->m_data) + sizeof(struct ip6_hdr);
+
+ proto = ip6->ip6_nxt;
+ do {
+ while (off >= m0->m_len) {
+ off -= m0->m_len;
+ m0 = m0->m_next;
+ if (m0 == NULL)
+ return (0);
+ }
+ if (m0->m_len < off + 4)
+ return (0);
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ case IPPROTO_UDP: {
+ struct udphdr *udp;
+
+ udp = (struct udphdr *)(mtod(m0, caddr_t) + off);
+ fin6->fi6_sport = udp->uh_sport;
+ fin6->fi6_dport = udp->uh_dport;
+ fin6->fi6_proto = proto;
+ }
+ return (1);
+
+ case IPPROTO_ESP:
+ if (fin6->fi6_gpi == 0) {
+ u_int32_t *gpi;
+
+ gpi = (u_int32_t *)(mtod(m0, caddr_t) + off);
+ fin6->fi6_gpi = *gpi;
+ }
+ fin6->fi6_proto = proto;
+ return (1);
+
+ case IPPROTO_AH: {
+ /* get next header and header length */
+ struct _opt6 *opt6;
+
+ opt6 = (struct _opt6 *)(mtod(m0, caddr_t) + off);
+ if (fin6->fi6_gpi == 0 && m0->m_len >= off + 8)
+ fin6->fi6_gpi = opt6->ah_spi;
+ proto = opt6->opt6_nxt;
+ off += 8 + (opt6->opt6_hlen * 4);
+ /* goto the next header */
+ break;
+ }
+
+ case IPPROTO_HOPOPTS:
+ case IPPROTO_ROUTING:
+ case IPPROTO_DSTOPTS: {
+ /* get next header and header length */
+ struct _opt6 *opt6;
+
+ opt6 = (struct _opt6 *)(mtod(m0, caddr_t) + off);
+ proto = opt6->opt6_nxt;
+ off += (opt6->opt6_hlen + 1) * 8;
+ /* goto the next header */
+ break;
+ }
+
+ case IPPROTO_FRAGMENT:
+ /* ipv6 fragmentations are not supported yet */
+ default:
+ fin6->fi6_proto = proto;
+ return (0);
+ }
+ } while (1);
+ /*NOTREACHED*/
+}
+#endif /* INET6 */
+
+/*
+ * altq common classifier
+ */
+int
+acc_add_filter(classifier, filter, class, phandle)
+ struct acc_classifier *classifier;
+ struct flow_filter *filter;
+ void *class;
+ u_long *phandle;
+{
+ struct acc_filter *afp, *prev, *tmp;
+ int i, s;
+
+#ifdef INET6
+ if (filter->ff_flow.fi_family != AF_INET &&
+ filter->ff_flow.fi_family != AF_INET6)
+ return (EINVAL);
+#else
+ if (filter->ff_flow.fi_family != AF_INET)
+ return (EINVAL);
+#endif
+
+ afp = malloc(sizeof(struct acc_filter),
+ M_DEVBUF, M_WAITOK);
+ if (afp == NULL)
+ return (ENOMEM);
+ bzero(afp, sizeof(struct acc_filter));
+
+ afp->f_filter = *filter;
+ afp->f_class = class;
+
+ i = ACC_WILDCARD_INDEX;
+ if (filter->ff_flow.fi_family == AF_INET) {
+ struct flow_filter *filter4 = &afp->f_filter;
+
+ /*
+ * if address is 0, it's a wildcard. if address mask
+ * isn't set, use full mask.
+ */
+ if (filter4->ff_flow.fi_dst.s_addr == 0)
+ filter4->ff_mask.mask_dst.s_addr = 0;
+ else if (filter4->ff_mask.mask_dst.s_addr == 0)
+ filter4->ff_mask.mask_dst.s_addr = 0xffffffff;
+ if (filter4->ff_flow.fi_src.s_addr == 0)
+ filter4->ff_mask.mask_src.s_addr = 0;
+ else if (filter4->ff_mask.mask_src.s_addr == 0)
+ filter4->ff_mask.mask_src.s_addr = 0xffffffff;
+
+ /* clear extra bits in addresses */
+ filter4->ff_flow.fi_dst.s_addr &=
+ filter4->ff_mask.mask_dst.s_addr;
+ filter4->ff_flow.fi_src.s_addr &=
+ filter4->ff_mask.mask_src.s_addr;
+
+ /*
+ * if dst address is a wildcard, use hash-entry
+ * ACC_WILDCARD_INDEX.
+ */
+ if (filter4->ff_mask.mask_dst.s_addr != 0xffffffff)
+ i = ACC_WILDCARD_INDEX;
+ else
+ i = ACC_GET_HASH_INDEX(filter4->ff_flow.fi_dst.s_addr);
+ }
+#ifdef INET6
+ else if (filter->ff_flow.fi_family == AF_INET6) {
+ struct flow_filter6 *filter6 =
+ (struct flow_filter6 *)&afp->f_filter;
+#ifndef IN6MASK0 /* taken from kame ipv6 */
+#define IN6MASK0 {{{ 0, 0, 0, 0 }}}
+#define IN6MASK128 {{{ 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff }}}
+ const struct in6_addr in6mask0 = IN6MASK0;
+ const struct in6_addr in6mask128 = IN6MASK128;
+#endif
+
+ if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_dst))
+ filter6->ff_mask6.mask6_dst = in6mask0;
+ else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_dst))
+ filter6->ff_mask6.mask6_dst = in6mask128;
+ if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_flow6.fi6_src))
+ filter6->ff_mask6.mask6_src = in6mask0;
+ else if (IN6_IS_ADDR_UNSPECIFIED(&filter6->ff_mask6.mask6_src))
+ filter6->ff_mask6.mask6_src = in6mask128;
+
+ /* clear extra bits in addresses */
+ for (i = 0; i < 16; i++)
+ filter6->ff_flow6.fi6_dst.s6_addr[i] &=
+ filter6->ff_mask6.mask6_dst.s6_addr[i];
+ for (i = 0; i < 16; i++)
+ filter6->ff_flow6.fi6_src.s6_addr[i] &=
+ filter6->ff_mask6.mask6_src.s6_addr[i];
+
+ if (filter6->ff_flow6.fi6_flowlabel == 0)
+ i = ACC_WILDCARD_INDEX;
+ else
+ i = ACC_GET_HASH_INDEX(filter6->ff_flow6.fi6_flowlabel);
+ }
+#endif /* INET6 */
+
+ afp->f_handle = get_filt_handle(classifier, i);
+
+ /* update filter bitmask */
+ afp->f_fbmask = filt2fibmask(filter);
+ classifier->acc_fbmask |= afp->f_fbmask;
+
+ /*
+ * add this filter to the filter list.
+ * filters are ordered from the highest rule number.
+ */
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ prev = NULL;
+ LIST_FOREACH(tmp, &classifier->acc_filters[i], f_chain) {
+ if (tmp->f_filter.ff_ruleno > afp->f_filter.ff_ruleno)
+ prev = tmp;
+ else
+ break;
+ }
+ if (prev == NULL)
+ LIST_INSERT_HEAD(&classifier->acc_filters[i], afp, f_chain);
+ else
+ LIST_INSERT_AFTER(prev, afp, f_chain);
+ splx(s);
+
+ *phandle = afp->f_handle;
+ return (0);
+}
+
+int
+acc_delete_filter(classifier, handle)
+ struct acc_classifier *classifier;
+ u_long handle;
+{
+ struct acc_filter *afp;
+ int s;
+
+ if ((afp = filth_to_filtp(classifier, handle)) == NULL)
+ return (EINVAL);
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ LIST_REMOVE(afp, f_chain);
+ splx(s);
+
+ free(afp, M_DEVBUF);
+
+ /* todo: update filt_bmask */
+
+ return (0);
+}
+
+/*
+ * delete filters referencing to the specified class.
+ * if the all flag is not 0, delete all the filters.
+ */
+int
+acc_discard_filters(classifier, class, all)
+ struct acc_classifier *classifier;
+ void *class;
+ int all;
+{
+ struct acc_filter *afp;
+ int i, s;
+
+#ifdef __NetBSD__
+ s = splnet();
+#else
+ s = splimp();
+#endif
+ for (i = 0; i < ACC_FILTER_TABLESIZE; i++) {
+ do {
+ LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
+ if (all || afp->f_class == class) {
+ LIST_REMOVE(afp, f_chain);
+ free(afp, M_DEVBUF);
+ /* start again from the head */
+ break;
+ }
+ } while (afp != NULL);
+ }
+ splx(s);
+
+ if (all)
+ classifier->acc_fbmask = 0;
+
+ return (0);
+}
+
+void *
+acc_classify(clfier, m, af)
+ void *clfier;
+ struct mbuf *m;
+ int af;
+{
+ struct acc_classifier *classifier;
+ struct flowinfo flow;
+ struct acc_filter *afp;
+ int i;
+
+ classifier = (struct acc_classifier *)clfier;
+ altq_extractflow(m, af, &flow, classifier->acc_fbmask);
+
+ if (flow.fi_family == AF_INET) {
+ struct flowinfo_in *fp = (struct flowinfo_in *)&flow;
+
+ if ((classifier->acc_fbmask & FIMB4_ALL) == FIMB4_TOS) {
+ /* only tos is used */
+ LIST_FOREACH(afp,
+ &classifier->acc_filters[ACC_WILDCARD_INDEX],
+ f_chain)
+ if (apply_tosfilter4(afp->f_fbmask,
+ &afp->f_filter, fp))
+ /* filter matched */
+ return (afp->f_class);
+ } else if ((classifier->acc_fbmask &
+ (~(FIMB4_PROTO|FIMB4_SPORT|FIMB4_DPORT) & FIMB4_ALL))
+ == 0) {
+ /* only proto and ports are used */
+ LIST_FOREACH(afp,
+ &classifier->acc_filters[ACC_WILDCARD_INDEX],
+ f_chain)
+ if (apply_ppfilter4(afp->f_fbmask,
+ &afp->f_filter, fp))
+ /* filter matched */
+ return (afp->f_class);
+ } else {
+ /* get the filter hash entry from its dest address */
+ i = ACC_GET_HASH_INDEX(fp->fi_dst.s_addr);
+ do {
+ /*
+ * go through this loop twice. first for dst
+ * hash, second for wildcards.
+ */
+ LIST_FOREACH(afp, &classifier->acc_filters[i],
+ f_chain)
+ if (apply_filter4(afp->f_fbmask,
+ &afp->f_filter, fp))
+ /* filter matched */
+ return (afp->f_class);
+
+ /*
+ * check again for filters with a dst addr
+ * wildcard.
+ * (daddr == 0 || dmask != 0xffffffff).
+ */
+ if (i != ACC_WILDCARD_INDEX)
+ i = ACC_WILDCARD_INDEX;
+ else
+ break;
+ } while (1);
+ }
+ }
+#ifdef INET6
+ else if (flow.fi_family == AF_INET6) {
+ struct flowinfo_in6 *fp6 = (struct flowinfo_in6 *)&flow;
+
+ /* get the filter hash entry from its flow ID */
+ if (fp6->fi6_flowlabel != 0)
+ i = ACC_GET_HASH_INDEX(fp6->fi6_flowlabel);
+ else
+ /* flowlable can be zero */
+ i = ACC_WILDCARD_INDEX;
+
+ /* go through this loop twice. first for flow hash, second
+ for wildcards. */
+ do {
+ LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
+ if (apply_filter6(afp->f_fbmask,
+ (struct flow_filter6 *)&afp->f_filter,
+ fp6))
+ /* filter matched */
+ return (afp->f_class);
+
+ /*
+ * check again for filters with a wildcard.
+ */
+ if (i != ACC_WILDCARD_INDEX)
+ i = ACC_WILDCARD_INDEX;
+ else
+ break;
+ } while (1);
+ }
+#endif /* INET6 */
+
+ /* no filter matched */
+ return (NULL);
+}
+
+static int
+apply_filter4(fbmask, filt, pkt)
+ u_int32_t fbmask;
+ struct flow_filter *filt;
+ struct flowinfo_in *pkt;
+{
+ if (filt->ff_flow.fi_family != AF_INET)
+ return (0);
+ if ((fbmask & FIMB4_SPORT) && filt->ff_flow.fi_sport != pkt->fi_sport)
+ return (0);
+ if ((fbmask & FIMB4_DPORT) && filt->ff_flow.fi_dport != pkt->fi_dport)
+ return (0);
+ if ((fbmask & FIMB4_DADDR) &&
+ filt->ff_flow.fi_dst.s_addr !=
+ (pkt->fi_dst.s_addr & filt->ff_mask.mask_dst.s_addr))
+ return (0);
+ if ((fbmask & FIMB4_SADDR) &&
+ filt->ff_flow.fi_src.s_addr !=
+ (pkt->fi_src.s_addr & filt->ff_mask.mask_src.s_addr))
+ return (0);
+ if ((fbmask & FIMB4_PROTO) && filt->ff_flow.fi_proto != pkt->fi_proto)
+ return (0);
+ if ((fbmask & FIMB4_TOS) && filt->ff_flow.fi_tos !=
+ (pkt->fi_tos & filt->ff_mask.mask_tos))
+ return (0);
+ if ((fbmask & FIMB4_GPI) && filt->ff_flow.fi_gpi != (pkt->fi_gpi))
+ return (0);
+ /* match */
+ return (1);
+}
+
+/*
+ * filter matching function optimized for a common case that checks
+ * only protocol and port numbers
+ */
+static int
+apply_ppfilter4(fbmask, filt, pkt)
+ u_int32_t fbmask;
+ struct flow_filter *filt;
+ struct flowinfo_in *pkt;
+{
+ if (filt->ff_flow.fi_family != AF_INET)
+ return (0);
+ if ((fbmask & FIMB4_SPORT) && filt->ff_flow.fi_sport != pkt->fi_sport)
+ return (0);
+ if ((fbmask & FIMB4_DPORT) && filt->ff_flow.fi_dport != pkt->fi_dport)
+ return (0);
+ if ((fbmask & FIMB4_PROTO) && filt->ff_flow.fi_proto != pkt->fi_proto)
+ return (0);
+ /* match */
+ return (1);
+}
+
+/*
+ * filter matching function only for tos field.
+ */
+static int
+apply_tosfilter4(fbmask, filt, pkt)
+ u_int32_t fbmask;
+ struct flow_filter *filt;
+ struct flowinfo_in *pkt;
+{
+ if (filt->ff_flow.fi_family != AF_INET)
+ return (0);
+ if ((fbmask & FIMB4_TOS) && filt->ff_flow.fi_tos !=
+ (pkt->fi_tos & filt->ff_mask.mask_tos))
+ return (0);
+ /* match */
+ return (1);
+}
+
+#ifdef INET6
+static int
+apply_filter6(fbmask, filt, pkt)
+ u_int32_t fbmask;
+ struct flow_filter6 *filt;
+ struct flowinfo_in6 *pkt;
+{
+ int i;
+
+ if (filt->ff_flow6.fi6_family != AF_INET6)
+ return (0);
+ if ((fbmask & FIMB6_FLABEL) &&
+ filt->ff_flow6.fi6_flowlabel != pkt->fi6_flowlabel)
+ return (0);
+ if ((fbmask & FIMB6_PROTO) &&
+ filt->ff_flow6.fi6_proto != pkt->fi6_proto)
+ return (0);
+ if ((fbmask & FIMB6_SPORT) &&
+ filt->ff_flow6.fi6_sport != pkt->fi6_sport)
+ return (0);
+ if ((fbmask & FIMB6_DPORT) &&
+ filt->ff_flow6.fi6_dport != pkt->fi6_dport)
+ return (0);
+ if (fbmask & FIMB6_SADDR) {
+ for (i = 0; i < 4; i++)
+ if (filt->ff_flow6.fi6_src.s6_addr32[i] !=
+ (pkt->fi6_src.s6_addr32[i] &
+ filt->ff_mask6.mask6_src.s6_addr32[i]))
+ return (0);
+ }
+ if (fbmask & FIMB6_DADDR) {
+ for (i = 0; i < 4; i++)
+ if (filt->ff_flow6.fi6_dst.s6_addr32[i] !=
+ (pkt->fi6_dst.s6_addr32[i] &
+ filt->ff_mask6.mask6_dst.s6_addr32[i]))
+ return (0);
+ }
+ if ((fbmask & FIMB6_TCLASS) &&
+ filt->ff_flow6.fi6_tclass !=
+ (pkt->fi6_tclass & filt->ff_mask6.mask6_tclass))
+ return (0);
+ if ((fbmask & FIMB6_GPI) &&
+ filt->ff_flow6.fi6_gpi != pkt->fi6_gpi)
+ return (0);
+ /* match */
+ return (1);
+}
+#endif /* INET6 */
+
+/*
+ * filter handle:
+ * bit 20-28: index to the filter hash table
+ * bit 0-19: unique id in the hash bucket.
+ */
+static u_long
+get_filt_handle(classifier, i)
+ struct acc_classifier *classifier;
+ int i;
+{
+ static u_long handle_number = 1;
+ u_long handle;
+ struct acc_filter *afp;
+
+ while (1) {
+ handle = handle_number++ & 0x000fffff;
+
+ if (LIST_EMPTY(&classifier->acc_filters[i]))
+ break;
+
+ LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
+ if ((afp->f_handle & 0x000fffff) == handle)
+ break;
+ if (afp == NULL)
+ break;
+ /* this handle is already used, try again */
+ }
+
+ return ((i << 20) | handle);
+}
+
+/* convert filter handle to filter pointer */
+static struct acc_filter *
+filth_to_filtp(classifier, handle)
+ struct acc_classifier *classifier;
+ u_long handle;
+{
+ struct acc_filter *afp;
+ int i;
+
+ i = ACC_GET_HINDEX(handle);
+
+ LIST_FOREACH(afp, &classifier->acc_filters[i], f_chain)
+ if (afp->f_handle == handle)
+ return (afp);
+
+ return (NULL);
+}
+
+/* create flowinfo bitmask */
+static u_int32_t
+filt2fibmask(filt)
+ struct flow_filter *filt;
+{
+ u_int32_t mask = 0;
+#ifdef INET6
+ struct flow_filter6 *filt6;
+#endif
+
+ switch (filt->ff_flow.fi_family) {
+ case AF_INET:
+ if (filt->ff_flow.fi_proto != 0)
+ mask |= FIMB4_PROTO;
+ if (filt->ff_flow.fi_tos != 0)
+ mask |= FIMB4_TOS;
+ if (filt->ff_flow.fi_dst.s_addr != 0)
+ mask |= FIMB4_DADDR;
+ if (filt->ff_flow.fi_src.s_addr != 0)
+ mask |= FIMB4_SADDR;
+ if (filt->ff_flow.fi_sport != 0)
+ mask |= FIMB4_SPORT;
+ if (filt->ff_flow.fi_dport != 0)
+ mask |= FIMB4_DPORT;
+ if (filt->ff_flow.fi_gpi != 0)
+ mask |= FIMB4_GPI;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ filt6 = (struct flow_filter6 *)filt;
+
+ if (filt6->ff_flow6.fi6_proto != 0)
+ mask |= FIMB6_PROTO;
+ if (filt6->ff_flow6.fi6_tclass != 0)
+ mask |= FIMB6_TCLASS;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&filt6->ff_flow6.fi6_dst))
+ mask |= FIMB6_DADDR;
+ if (!IN6_IS_ADDR_UNSPECIFIED(&filt6->ff_flow6.fi6_src))
+ mask |= FIMB6_SADDR;
+ if (filt6->ff_flow6.fi6_sport != 0)
+ mask |= FIMB6_SPORT;
+ if (filt6->ff_flow6.fi6_dport != 0)
+ mask |= FIMB6_DPORT;
+ if (filt6->ff_flow6.fi6_gpi != 0)
+ mask |= FIMB6_GPI;
+ if (filt6->ff_flow6.fi6_flowlabel != 0)
+ mask |= FIMB6_FLABEL;
+ break;
+#endif /* INET6 */
+ }
+ return (mask);
+}
+
+
+/*
+ * helper functions to handle IPv4 fragments.
+ * currently only in-sequence fragments are handled.
+ * - fragment info is cached in a LRU list.
+ * - when a first fragment is found, cache its flow info.
+ * - when a non-first fragment is found, lookup the cache.
+ */
+
+struct ip4_frag {
+ TAILQ_ENTRY(ip4_frag) ip4f_chain;
+ char ip4f_valid;
+ u_short ip4f_id;
+ struct flowinfo_in ip4f_info;
+};
+
+static TAILQ_HEAD(ip4f_list, ip4_frag) ip4f_list; /* IPv4 fragment cache */
+
+#define IP4F_TABSIZE 16 /* IPv4 fragment cache size */
+
+
+static void
+ip4f_cache(ip, fin)
+ struct ip *ip;
+ struct flowinfo_in *fin;
+{
+ struct ip4_frag *fp;
+
+ if (TAILQ_EMPTY(&ip4f_list)) {
+ /* first time call, allocate fragment cache entries. */
+ if (ip4f_init() < 0)
+ /* allocation failed! */
+ return;
+ }
+
+ fp = ip4f_alloc();
+ fp->ip4f_id = ip->ip_id;
+ fp->ip4f_info.fi_proto = ip->ip_p;
+ fp->ip4f_info.fi_src.s_addr = ip->ip_src.s_addr;
+ fp->ip4f_info.fi_dst.s_addr = ip->ip_dst.s_addr;
+
+ /* save port numbers */
+ fp->ip4f_info.fi_sport = fin->fi_sport;
+ fp->ip4f_info.fi_dport = fin->fi_dport;
+ fp->ip4f_info.fi_gpi = fin->fi_gpi;
+}
+
+static int
+ip4f_lookup(ip, fin)
+ struct ip *ip;
+ struct flowinfo_in *fin;
+{
+ struct ip4_frag *fp;
+
+ for (fp = TAILQ_FIRST(&ip4f_list); fp != NULL && fp->ip4f_valid;
+ fp = TAILQ_NEXT(fp, ip4f_chain))
+ if (ip->ip_id == fp->ip4f_id &&
+ ip->ip_src.s_addr == fp->ip4f_info.fi_src.s_addr &&
+ ip->ip_dst.s_addr == fp->ip4f_info.fi_dst.s_addr &&
+ ip->ip_p == fp->ip4f_info.fi_proto) {
+
+ /* found the matching entry */
+ fin->fi_sport = fp->ip4f_info.fi_sport;
+ fin->fi_dport = fp->ip4f_info.fi_dport;
+ fin->fi_gpi = fp->ip4f_info.fi_gpi;
+
+ if ((ntohs(ip->ip_off) & IP_MF) == 0)
+ /* this is the last fragment,
+ release the entry. */
+ ip4f_free(fp);
+
+ return (1);
+ }
+
+ /* no matching entry found */
+ return (0);
+}
+
+static int
+ip4f_init(void)
+{
+ struct ip4_frag *fp;
+ int i;
+
+ TAILQ_INIT(&ip4f_list);
+ for (i=0; i<IP4F_TABSIZE; i++) {
+ fp = malloc(sizeof(struct ip4_frag),
+ M_DEVBUF, M_NOWAIT);
+ if (fp == NULL) {
+ printf("ip4f_init: can't alloc %dth entry!\n", i);
+ if (i == 0)
+ return (-1);
+ return (0);
+ }
+ fp->ip4f_valid = 0;
+ TAILQ_INSERT_TAIL(&ip4f_list, fp, ip4f_chain);
+ }
+ return (0);
+}
+
+static struct ip4_frag *
+ip4f_alloc(void)
+{
+ struct ip4_frag *fp;
+
+ /* reclaim an entry at the tail, put it at the head */
+ fp = TAILQ_LAST(&ip4f_list, ip4f_list);
+ TAILQ_REMOVE(&ip4f_list, fp, ip4f_chain);
+ fp->ip4f_valid = 1;
+ TAILQ_INSERT_HEAD(&ip4f_list, fp, ip4f_chain);
+ return (fp);
+}
+
+static void
+ip4f_free(fp)
+ struct ip4_frag *fp;
+{
+ TAILQ_REMOVE(&ip4f_list, fp, ip4f_chain);
+ fp->ip4f_valid = 0;
+ TAILQ_INSERT_TAIL(&ip4f_list, fp, ip4f_chain);
+}
+
+#endif /* ALTQ3_CLFIER_COMPAT */
diff --git a/freebsd/sys/contrib/altq/altq/altq_var.h b/freebsd/sys/contrib/altq/altq/altq_var.h
new file mode 100644
index 00000000..9ebfe2ed
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altq_var.h
@@ -0,0 +1,265 @@
+/* $FreeBSD$ */
+/* $KAME: altq_var.h,v 1.16 2003/10/03 05:05:15 kjc Exp $ */
+
+/*
+ * Copyright (C) 1998-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 _ALTQ_ALTQ_VAR_HH_
+#define _ALTQ_ALTQ_VAR_HH_
+
+#ifdef _KERNEL
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/queue.h>
+
+#ifdef ALTQ3_CLFIER_COMPAT
+/*
+ * filter structure for altq common classifier
+ */
+struct acc_filter {
+ LIST_ENTRY(acc_filter) f_chain;
+ void *f_class; /* pointer to the class */
+ u_long f_handle; /* filter id */
+ u_int32_t f_fbmask; /* filter bitmask */
+ struct flow_filter f_filter; /* filter value */
+};
+
+/*
+ * XXX ACC_FILTER_TABLESIZE can't be larger than 2048 unless we fix
+ * the handle assignment.
+ */
+#define ACC_FILTER_TABLESIZE (256+1)
+#define ACC_FILTER_MASK (ACC_FILTER_TABLESIZE - 2)
+#define ACC_WILDCARD_INDEX (ACC_FILTER_TABLESIZE - 1)
+#ifdef __GNUC__
+#define ACC_GET_HASH_INDEX(addr) \
+ ({int x = (addr) + ((addr) >> 16); (x + (x >> 8)) & ACC_FILTER_MASK;})
+#else
+#define ACC_GET_HASH_INDEX(addr) \
+ (((addr) + ((addr) >> 8) + ((addr) >> 16) + ((addr) >> 24)) \
+ & ACC_FILTER_MASK)
+#endif
+#define ACC_GET_HINDEX(handle) ((handle) >> 20)
+
+#if (__FreeBSD_version > 500000)
+#define ACC_LOCK_INIT(ac) mtx_init(&(ac)->acc_mtx, "classifier", MTX_DEF)
+#define ACC_LOCK_DESTROY(ac) mtx_destroy(&(ac)->acc_mtx)
+#define ACC_LOCK(ac) mtx_lock(&(ac)->acc_mtx)
+#define ACC_UNLOCK(ac) mtx_unlock(&(ac)->acc_mtx)
+#else
+#define ACC_LOCK_INIT(ac)
+#define ACC_LOCK_DESTROY(ac)
+#define ACC_LOCK(ac)
+#define ACC_UNLOCK(ac)
+#endif
+
+struct acc_classifier {
+ u_int32_t acc_fbmask;
+ LIST_HEAD(filt, acc_filter) acc_filters[ACC_FILTER_TABLESIZE];
+
+#if (__FreeBSD_version > 500000)
+ struct mtx acc_mtx;
+#endif
+};
+
+/*
+ * flowinfo mask bits used by classifier
+ */
+/* for ipv4 */
+#define FIMB4_PROTO 0x0001
+#define FIMB4_TOS 0x0002
+#define FIMB4_DADDR 0x0004
+#define FIMB4_SADDR 0x0008
+#define FIMB4_DPORT 0x0010
+#define FIMB4_SPORT 0x0020
+#define FIMB4_GPI 0x0040
+#define FIMB4_ALL 0x007f
+/* for ipv6 */
+#define FIMB6_PROTO 0x0100
+#define FIMB6_TCLASS 0x0200
+#define FIMB6_DADDR 0x0400
+#define FIMB6_SADDR 0x0800
+#define FIMB6_DPORT 0x1000
+#define FIMB6_SPORT 0x2000
+#define FIMB6_GPI 0x4000
+#define FIMB6_FLABEL 0x8000
+#define FIMB6_ALL 0xff00
+
+#define FIMB_ALL (FIMB4_ALL|FIMB6_ALL)
+
+#define FIMB4_PORTS (FIMB4_DPORT|FIMB4_SPORT|FIMB4_GPI)
+#define FIMB6_PORTS (FIMB6_DPORT|FIMB6_SPORT|FIMB6_GPI)
+#endif /* ALTQ3_CLFIER_COMPAT */
+
+/*
+ * machine dependent clock
+ * a 64bit high resolution time counter.
+ */
+extern int machclk_usepcc;
+extern u_int32_t machclk_freq;
+extern u_int32_t machclk_per_tick;
+extern void init_machclk(void);
+extern u_int64_t read_machclk(void);
+
+/*
+ * debug support
+ */
+#ifdef ALTQ_DEBUG
+#ifdef __STDC__
+#define ASSERT(e) ((e) ? (void)0 : altq_assert(__FILE__, __LINE__, #e))
+#else /* PCC */
+#define ASSERT(e) ((e) ? (void)0 : altq_assert(__FILE__, __LINE__, "e"))
+#endif
+#else
+#define ASSERT(e) ((void)0)
+#endif
+
+/*
+ * misc stuff for compatibility
+ */
+/* ioctl cmd type */
+#if defined(__FreeBSD__) && (__FreeBSD__ < 3)
+typedef int ioctlcmd_t;
+#else
+typedef u_long ioctlcmd_t;
+#endif
+
+/*
+ * queue macros:
+ * the interface of TAILQ_LAST macro changed after the introduction
+ * of softupdate. redefine it here to make it work with pre-2.2.7.
+ */
+#undef TAILQ_LAST
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#ifndef TAILQ_EMPTY
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+#endif
+#ifndef TAILQ_FOREACH
+#define TAILQ_FOREACH(var, head, field) \
+ for (var = TAILQ_FIRST(head); var; var = TAILQ_NEXT(var, field))
+#endif
+
+/* macro for timeout/untimeout */
+#if (__FreeBSD_version > 300000) || defined(__NetBSD__)
+/* use callout */
+#include <freebsd/sys/callout.h>
+
+#if (__FreeBSD_version > 500000)
+#define CALLOUT_INIT(c) callout_init((c), 0)
+#else
+#define CALLOUT_INIT(c) callout_init((c))
+#endif
+#define CALLOUT_RESET(c,t,f,a) callout_reset((c),(t),(f),(a))
+#define CALLOUT_STOP(c) callout_stop((c))
+#if !defined(CALLOUT_INITIALIZER) && (__FreeBSD_version < 600000)
+#define CALLOUT_INITIALIZER { { { NULL } }, 0, NULL, NULL, 0 }
+#endif
+#elif defined(__OpenBSD__)
+#include <freebsd/sys/timeout.h>
+/* callout structure as a wrapper of struct timeout */
+struct callout {
+ struct timeout c_to;
+};
+#define CALLOUT_INIT(c) do { bzero((c), sizeof(*(c))); } while (/*CONSTCOND*/ 0)
+#define CALLOUT_RESET(c,t,f,a) do { if (!timeout_initialized(&(c)->c_to)) \
+ timeout_set(&(c)->c_to, (f), (a)); \
+ timeout_add(&(c)->c_to, (t)); } while (/*CONSTCOND*/ 0)
+#define CALLOUT_STOP(c) timeout_del(&(c)->c_to)
+#define CALLOUT_INITIALIZER { { { NULL }, NULL, NULL, 0, 0 } }
+#else
+/* use old-style timeout/untimeout */
+/* dummy callout structure */
+struct callout {
+ void *c_arg; /* function argument */
+ void (*c_func)(void *); /* functiuon to call */
+};
+#define CALLOUT_INIT(c) do { bzero((c), sizeof(*(c))); } while (/*CONSTCOND*/ 0)
+#define CALLOUT_RESET(c,t,f,a) do { (c)->c_arg = (a); \
+ (c)->c_func = (f); \
+ timeout((f),(a),(t)); } while (/*CONSTCOND*/ 0)
+#define CALLOUT_STOP(c) untimeout((c)->c_func,(c)->c_arg)
+#define CALLOUT_INITIALIZER { NULL, NULL }
+#endif
+#if !defined(__FreeBSD__)
+typedef void (timeout_t)(void *);
+#endif
+
+#define m_pktlen(m) ((m)->m_pkthdr.len)
+
+struct ifnet; struct mbuf;
+struct pf_altq;
+#ifdef ALTQ3_CLFIER_COMPAT
+struct flowinfo;
+#endif
+
+void *altq_lookup(char *, int);
+#ifdef ALTQ3_CLFIER_COMPAT
+int altq_extractflow(struct mbuf *, int, struct flowinfo *, u_int32_t);
+int acc_add_filter(struct acc_classifier *, struct flow_filter *,
+ void *, u_long *);
+int acc_delete_filter(struct acc_classifier *, u_long);
+int acc_discard_filters(struct acc_classifier *, void *, int);
+void *acc_classify(void *, struct mbuf *, int);
+#endif
+u_int8_t read_dsfield(struct mbuf *, struct altq_pktattr *);
+void write_dsfield(struct mbuf *, struct altq_pktattr *, u_int8_t);
+void altq_assert(const char *, int, const char *);
+int tbr_set(struct ifaltq *, struct tb_profile *);
+int tbr_get(struct ifaltq *, struct tb_profile *);
+
+int altq_pfattach(struct pf_altq *);
+int altq_pfdetach(struct pf_altq *);
+int altq_add(struct pf_altq *);
+int altq_remove(struct pf_altq *);
+int altq_add_queue(struct pf_altq *);
+int altq_remove_queue(struct pf_altq *);
+int altq_getqstats(struct pf_altq *, void *, int *);
+
+int cbq_pfattach(struct pf_altq *);
+int cbq_add_altq(struct pf_altq *);
+int cbq_remove_altq(struct pf_altq *);
+int cbq_add_queue(struct pf_altq *);
+int cbq_remove_queue(struct pf_altq *);
+int cbq_getqstats(struct pf_altq *, void *, int *);
+
+int priq_pfattach(struct pf_altq *);
+int priq_add_altq(struct pf_altq *);
+int priq_remove_altq(struct pf_altq *);
+int priq_add_queue(struct pf_altq *);
+int priq_remove_queue(struct pf_altq *);
+int priq_getqstats(struct pf_altq *, void *, int *);
+
+int hfsc_pfattach(struct pf_altq *);
+int hfsc_add_altq(struct pf_altq *);
+int hfsc_remove_altq(struct pf_altq *);
+int hfsc_add_queue(struct pf_altq *);
+int hfsc_remove_queue(struct pf_altq *);
+int hfsc_getqstats(struct pf_altq *, void *, int *);
+
+#endif /* _KERNEL */
+#endif /* _ALTQ_ALTQ_VAR_HH_ */
diff --git a/freebsd/sys/contrib/altq/altq/altqconf.h b/freebsd/sys/contrib/altq/altq/altqconf.h
new file mode 100644
index 00000000..b4d0f84e
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/altqconf.h
@@ -0,0 +1,29 @@
+/* $OpenBSD: altqconf.h,v 1.1 2001/06/27 05:28:36 kjc Exp $ */
+/* $NetBSD: altqconf.h,v 1.2 2001/05/30 11:57:16 mrg Exp $ */
+
+#if defined(_KERNEL_OPT) || defined(__OpenBSD__)
+
+#if defined(_KERNEL_OPT)
+#include <freebsd/local/opt_altq_enabled.h>
+#endif
+
+#include <freebsd/sys/conf.h>
+
+#ifdef ALTQ
+#define NALTQ 1
+#else
+#define NALTQ 0
+#endif
+
+cdev_decl(altq);
+
+#ifdef __OpenBSD__
+#define cdev_altq_init(c,n) { \
+ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \
+ (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \
+ (dev_type_stop((*))) enodev, 0, (dev_type_select((*))) enodev, \
+ (dev_type_mmap((*))) enodev }
+#else
+#define cdev_altq_init(x,y) cdev__oci_init(x,y)
+#endif
+#endif /* defined(_KERNEL_OPT) || defined(__OpenBSD__) */
diff --git a/freebsd/sys/contrib/altq/altq/if_altq.h b/freebsd/sys/contrib/altq/altq/if_altq.h
new file mode 100644
index 00000000..c2255b8c
--- /dev/null
+++ b/freebsd/sys/contrib/altq/altq/if_altq.h
@@ -0,0 +1,191 @@
+/* $FreeBSD$ */
+/* $KAME: if_altq.h,v 1.11 2003/07/10 12:07:50 kjc Exp $ */
+
+/*
+ * Copyright (C) 1997-2003
+ * Sony Computer Science Laboratories Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SONY CSL 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 SONY CSL 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 _ALTQ_IF_ALTQ_HH_
+#define _ALTQ_IF_ALTQ_HH_
+
+#if (defined(__FreeBSD__) && __FreeBSD_version >= 500000)
+#include <freebsd/sys/lock.h> /* XXX */
+#include <freebsd/sys/mutex.h> /* XXX */
+#include <freebsd/sys/event.h> /* XXX */
+#endif
+
+#ifdef _KERNEL_OPT
+#include <freebsd/altq/altqconf.h>
+#endif
+
+struct altq_pktattr; struct tb_regulator; struct top_cdnr;
+
+/*
+ * Structure defining a queue for a network interface.
+ */
+struct ifaltq {
+ /* fields compatible with struct ifqueue */
+ struct mbuf *ifq_head;
+ struct mbuf *ifq_tail;
+ int ifq_len;
+ int ifq_maxlen;
+ int ifq_drops;
+#if (defined(__FreeBSD__) && __FreeBSD_version >= 500000)
+ struct mtx ifq_mtx;
+#endif
+
+ /* driver owned queue (used for bulk dequeue and prepend) UNLOCKED */
+ struct mbuf *ifq_drv_head;
+ struct mbuf *ifq_drv_tail;
+ int ifq_drv_len;
+ int ifq_drv_maxlen;
+
+ /* alternate queueing related fields */
+ int altq_type; /* discipline type */
+ int altq_flags; /* flags (e.g. ready, in-use) */
+ void *altq_disc; /* for discipline-specific use */
+ struct ifnet *altq_ifp; /* back pointer to interface */
+
+ int (*altq_enqueue)(struct ifaltq *, struct mbuf *,
+ struct altq_pktattr *);
+ struct mbuf *(*altq_dequeue)(struct ifaltq *, int);
+ int (*altq_request)(struct ifaltq *, int, void *);
+
+ /* classifier fields */
+ void *altq_clfier; /* classifier-specific use */
+ void *(*altq_classify)(void *, struct mbuf *, int);
+
+ /* token bucket regulator */
+ struct tb_regulator *altq_tbr;
+
+ /* input traffic conditioner (doesn't belong to the output queue...) */
+ struct top_cdnr *altq_cdnr;
+};
+
+
+#ifdef _KERNEL
+
+/*
+ * packet attributes used by queueing disciplines.
+ * pattr_class is a discipline-dependent scheduling class that is
+ * set by a classifier.
+ * pattr_hdr and pattr_af may be used by a discipline to access
+ * the header within a mbuf. (e.g. ECN needs to update the CE bit)
+ * note that pattr_hdr could be stale after m_pullup, though link
+ * layer output routines usually don't use m_pullup. link-level
+ * compression also invalidates these fields. thus, pattr_hdr needs
+ * to be verified when a discipline touches the header.
+ */
+struct altq_pktattr {
+ void *pattr_class; /* sched class set by classifier */
+ int pattr_af; /* address family */
+ caddr_t pattr_hdr; /* saved header position in mbuf */
+};
+
+/*
+ * mbuf tag to carry a queue id (and hints for ECN).
+ */
+struct altq_tag {
+ u_int32_t qid; /* queue id */
+ /* hints for ecn */
+ int af; /* address family */
+ void *hdr; /* saved header position in mbuf */
+};
+
+/*
+ * a token-bucket regulator limits the rate that a network driver can
+ * dequeue packets from the output queue.
+ * modern cards are able to buffer a large amount of packets and dequeue
+ * too many packets at a time. this bursty dequeue behavior makes it
+ * impossible to schedule packets by queueing disciplines.
+ * a token-bucket is used to control the burst size in a device
+ * independent manner.
+ */
+struct tb_regulator {
+ int64_t tbr_rate; /* (scaled) token bucket rate */
+ int64_t tbr_depth; /* (scaled) token bucket depth */
+
+ int64_t tbr_token; /* (scaled) current token */
+ int64_t tbr_filluptime; /* (scaled) time to fill up bucket */
+ u_int64_t tbr_last; /* last time token was updated */
+
+ int tbr_lastop; /* last dequeue operation type
+ needed for poll-and-dequeue */
+};
+
+/* if_altqflags */
+#define ALTQF_READY 0x01 /* driver supports alternate queueing */
+#define ALTQF_ENABLED 0x02 /* altq is in use */
+#define ALTQF_CLASSIFY 0x04 /* classify packets */
+#define ALTQF_CNDTNING 0x08 /* altq traffic conditioning is enabled */
+#define ALTQF_DRIVER1 0x40 /* driver specific */
+
+/* if_altqflags set internally only: */
+#define ALTQF_CANTCHANGE (ALTQF_READY)
+
+/* altq_dequeue 2nd arg */
+#define ALTDQ_REMOVE 1 /* dequeue mbuf from the queue */
+#define ALTDQ_POLL 2 /* don't dequeue mbuf from the queue */
+
+/* altq request types (currently only purge is defined) */
+#define ALTRQ_PURGE 1 /* purge all packets */
+
+#define ALTQ_IS_READY(ifq) ((ifq)->altq_flags & ALTQF_READY)
+#define ALTQ_IS_ENABLED(ifq) ((ifq)->altq_flags & ALTQF_ENABLED)
+#define ALTQ_NEEDS_CLASSIFY(ifq) ((ifq)->altq_flags & ALTQF_CLASSIFY)
+#define ALTQ_IS_CNDTNING(ifq) ((ifq)->altq_flags & ALTQF_CNDTNING)
+
+#define ALTQ_SET_CNDTNING(ifq) ((ifq)->altq_flags |= ALTQF_CNDTNING)
+#define ALTQ_CLEAR_CNDTNING(ifq) ((ifq)->altq_flags &= ~ALTQF_CNDTNING)
+#define ALTQ_IS_ATTACHED(ifq) ((ifq)->altq_disc != NULL)
+
+#define ALTQ_ENQUEUE(ifq, m, pa, err) \
+ (err) = (*(ifq)->altq_enqueue)((ifq),(m),(pa))
+#define ALTQ_DEQUEUE(ifq, m) \
+ (m) = (*(ifq)->altq_dequeue)((ifq), ALTDQ_REMOVE)
+#define ALTQ_POLL(ifq, m) \
+ (m) = (*(ifq)->altq_dequeue)((ifq), ALTDQ_POLL)
+#define ALTQ_PURGE(ifq) \
+ (void)(*(ifq)->altq_request)((ifq), ALTRQ_PURGE, (void *)0)
+#define ALTQ_IS_EMPTY(ifq) ((ifq)->ifq_len == 0)
+#define TBR_IS_ENABLED(ifq) ((ifq)->altq_tbr != NULL)
+
+extern int altq_attach(struct ifaltq *, int, void *,
+ int (*)(struct ifaltq *, struct mbuf *,
+ struct altq_pktattr *),
+ struct mbuf *(*)(struct ifaltq *, int),
+ int (*)(struct ifaltq *, int, void *),
+ void *,
+ void *(*)(void *, struct mbuf *, int));
+extern int altq_detach(struct ifaltq *);
+extern int altq_enable(struct ifaltq *);
+extern int altq_disable(struct ifaltq *);
+extern struct mbuf *(*tbr_dequeue_ptr)(struct ifaltq *, int);
+extern int (*altq_input)(struct mbuf *, int);
+#if 0 /* ALTQ3_CLFIER_COMPAT */
+void altq_etherclassify(struct ifaltq *, struct mbuf *, struct altq_pktattr *);
+#endif
+#endif /* _KERNEL */
+
+#endif /* _ALTQ_IF_ALTQ_HH_ */
diff --git a/freebsd/sys/contrib/pf/net/if_pflog.c b/freebsd/sys/contrib/pf/net/if_pflog.c
new file mode 100644
index 00000000..8ecc7cee
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/if_pflog.c
@@ -0,0 +1,438 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: if_pflog.c,v 1.22 2006/12/15 09:31:20 otto Exp $ */
+/*
+ * The authors of this code are John Ioannidis (ji@tla.org),
+ * Angelos D. Keromytis (kermit@csd.uch.gr) and
+ * Niels Provos (provos@physnet.uni-hamburg.de).
+ *
+ * This code was written by John Ioannidis for BSD/OS in Athens, Greece,
+ * in November 1995.
+ *
+ * Ported to OpenBSD and NetBSD, with additional transforms, in December 1996,
+ * by Angelos D. Keromytis.
+ *
+ * Additional transforms and features in 1997 and 1998 by Angelos D. Keromytis
+ * and Niels Provos.
+ *
+ * Copyright (C) 1995, 1996, 1997, 1998 by John Ioannidis, Angelos D. Keromytis
+ * and Niels Provos.
+ * Copyright (c) 2001, Angelos D. Keromytis, Niels Provos.
+ *
+ * Permission to use, copy, and modify this software with or without fee
+ * is hereby granted, provided that this entire notice is included in
+ * all copies of any software which is or includes a copy or
+ * modification of this software.
+ * You may use this code under the GNU public license if you so wish. Please
+ * contribute changes back to the authors under this freer than GPL license
+ * so that we may further the use of strong encryption without limitations to
+ * all.
+ *
+ * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTY. IN PARTICULAR, NONE OF THE AUTHORS MAKES ANY
+ * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE
+ * MERCHANTABILITY OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR
+ * PURPOSE.
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+#include <freebsd/local/opt_bpf.h>
+#include <freebsd/local/opt_pf.h>
+
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef DEV_BPF
+#define NBPFILTER DEV_BPF
+#else
+#define NBPFILTER 0
+#endif
+
+#ifdef DEV_PFLOG
+#define NPFLOG DEV_PFLOG
+#else
+#define NPFLOG 0
+#endif
+
+#else /* ! __FreeBSD__ */
+#include <freebsd/local/bpfilter.h>
+#include <freebsd/local/pflog.h>
+#endif /* __FreeBSD__ */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/socket.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/limits.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/module.h>
+#include <freebsd/sys/sockio.h>
+#else
+#include <freebsd/sys/ioctl.h>
+#endif
+
+#include <freebsd/net/if.h>
+#ifdef __FreeBSD__
+#include <freebsd/net/if_clone.h>
+#endif
+#include <freebsd/net/if_types.h>
+#include <freebsd/net/route.h>
+#include <freebsd/net/bpf.h>
+
+#ifdef INET
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#endif
+
+#ifdef INET6
+#ifndef INET
+#include <freebsd/netinet/in.h>
+#endif
+#include <freebsd/netinet6/nd6.h>
+#endif /* INET6 */
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/net/if_pflog.h>
+
+#ifdef INET
+#ifdef __FreeBSD__
+#include <freebsd/machine/in_cksum.h>
+#endif
+#endif
+
+#define PFLOGMTU (32768 + MHLEN + MLEN)
+
+#ifdef PFLOGDEBUG
+#define DPRINTF(x) do { if (pflogdebug) printf x ; } while (0)
+#else
+#define DPRINTF(x)
+#endif
+
+void pflogattach(int);
+int pflogoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
+ struct route *);
+int pflogioctl(struct ifnet *, u_long, caddr_t);
+void pflogstart(struct ifnet *);
+#ifdef __FreeBSD__
+static int pflog_clone_create(struct if_clone *, int, caddr_t);
+static void pflog_clone_destroy(struct ifnet *);
+#else
+int pflog_clone_create(struct if_clone *, int);
+int pflog_clone_destroy(struct ifnet *);
+#endif
+
+LIST_HEAD(, pflog_softc) pflogif_list;
+#ifdef __FreeBSD__
+IFC_SIMPLE_DECLARE(pflog, 1);
+#else
+struct if_clone pflog_cloner =
+ IF_CLONE_INITIALIZER("pflog", pflog_clone_create, pflog_clone_destroy);
+#endif
+
+struct ifnet *pflogifs[PFLOGIFS_MAX]; /* for fast access */
+
+#ifndef __FreeBSD__
+extern int ifqmaxlen;
+#endif
+
+void
+pflogattach(int npflog)
+{
+ int i;
+ LIST_INIT(&pflogif_list);
+ for (i = 0; i < PFLOGIFS_MAX; i++)
+ pflogifs[i] = NULL;
+#ifndef __FreeBSD__
+ (void) pflog_clone_create(&pflog_cloner, 0);
+#endif
+ if_clone_attach(&pflog_cloner);
+}
+
+#ifdef __FreeBSD__
+static int
+pflog_clone_create(struct if_clone *ifc, int unit, caddr_t param)
+#else
+int
+pflog_clone_create(struct if_clone *ifc, int unit)
+#endif
+{
+ struct ifnet *ifp;
+ struct pflog_softc *pflogif;
+ int s;
+
+ if (unit >= PFLOGIFS_MAX)
+ return (EINVAL);
+
+ if ((pflogif = malloc(sizeof(*pflogif), M_DEVBUF, M_NOWAIT)) == NULL)
+ return (ENOMEM);
+ bzero(pflogif, sizeof(*pflogif));
+
+ pflogif->sc_unit = unit;
+#ifdef __FreeBSD__
+ ifp = pflogif->sc_ifp = if_alloc(IFT_PFLOG);
+ if (ifp == NULL) {
+ free(pflogif, M_DEVBUF);
+ return (ENOSPC);
+ }
+ if_initname(ifp, ifc->ifc_name, unit);
+#else
+ ifp = &pflogif->sc_if;
+ snprintf(ifp->if_xname, sizeof ifp->if_xname, "pflog%d", unit);
+#endif
+ ifp->if_softc = pflogif;
+ ifp->if_mtu = PFLOGMTU;
+ ifp->if_ioctl = pflogioctl;
+ ifp->if_output = pflogoutput;
+ ifp->if_start = pflogstart;
+#ifndef __FreeBSD__
+ ifp->if_type = IFT_PFLOG;
+#endif
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_hdrlen = PFLOG_HDRLEN;
+ if_attach(ifp);
+#ifndef __FreeBSD__
+ if_alloc_sadl(ifp);
+#endif
+
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+ bpfattach(ifp, DLT_PFLOG, PFLOG_HDRLEN);
+#else
+ bpfattach(&pflogif->sc_if.if_bpf, ifp, DLT_PFLOG, PFLOG_HDRLEN);
+#endif
+#endif
+
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ LIST_INSERT_HEAD(&pflogif_list, pflogif, sc_list);
+ pflogifs[unit] = ifp;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+
+ return (0);
+}
+
+#ifdef __FreeBSD__
+static void
+pflog_clone_destroy(struct ifnet *ifp)
+#else
+int
+pflog_clone_destroy(struct ifnet *ifp)
+#endif
+{
+ struct pflog_softc *pflogif = ifp->if_softc;
+ int s;
+
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ pflogifs[pflogif->sc_unit] = NULL;
+ LIST_REMOVE(pflogif, sc_list);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ if_detach(ifp);
+#ifdef __FreeBSD__
+ if_free(ifp);
+#endif
+ free(pflogif, M_DEVBUF);
+#ifndef __FreeBSD__
+ return (0);
+#endif
+}
+
+/*
+ * Start output on the pflog interface.
+ */
+void
+pflogstart(struct ifnet *ifp)
+{
+ struct mbuf *m;
+#ifndef __FreeBSD__
+ int s;
+#endif
+
+ for (;;) {
+#ifdef __FreeBSD__
+ IF_LOCK(&ifp->if_snd);
+ _IF_DROP(&ifp->if_snd);
+ _IF_DEQUEUE(&ifp->if_snd, m);
+ IF_UNLOCK(&ifp->if_snd);
+#else
+ s = splnet();
+ IF_DROP(&ifp->if_snd);
+ IF_DEQUEUE(&ifp->if_snd, m);
+ splx(s);
+#endif
+
+ if (m == NULL)
+ return;
+ else
+ m_freem(m);
+ }
+}
+
+int
+pflogoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+ struct route *ro)
+{
+ m_freem(m);
+ return (0);
+}
+
+/* ARGSUSED */
+int
+pflogioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCAIFADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFFLAGS:
+#ifdef __FreeBSD__
+ if (ifp->if_flags & IFF_UP)
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ else
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+#else
+ if (ifp->if_flags & IFF_UP)
+ ifp->if_flags |= IFF_RUNNING;
+ else
+ ifp->if_flags &= ~IFF_RUNNING;
+#endif
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+int
+pflog_packet(struct pfi_kif *kif, struct mbuf *m, sa_family_t af, u_int8_t dir,
+ u_int8_t reason, struct pf_rule *rm, struct pf_rule *am,
+ struct pf_ruleset *ruleset, struct pf_pdesc *pd)
+{
+#if NBPFILTER > 0
+ struct ifnet *ifn;
+ struct pfloghdr hdr;
+
+ if (kif == NULL || m == NULL || rm == NULL || pd == NULL)
+ return (-1);
+
+ if ((ifn = pflogifs[rm->logif]) == NULL || !ifn->if_bpf)
+ return (0);
+
+ bzero(&hdr, sizeof(hdr));
+ hdr.length = PFLOG_REAL_HDRLEN;
+ hdr.af = af;
+ hdr.action = rm->action;
+ hdr.reason = reason;
+ memcpy(hdr.ifname, kif->pfik_name, sizeof(hdr.ifname));
+
+ if (am == NULL) {
+ hdr.rulenr = htonl(rm->nr);
+ hdr.subrulenr = -1;
+ } else {
+ hdr.rulenr = htonl(am->nr);
+ hdr.subrulenr = htonl(rm->nr);
+ if (ruleset != NULL && ruleset->anchor != NULL)
+ strlcpy(hdr.ruleset, ruleset->anchor->name,
+ sizeof(hdr.ruleset));
+ }
+ if (rm->log & PF_LOG_SOCKET_LOOKUP && !pd->lookup.done)
+#ifdef __FreeBSD__
+ /*
+ * XXX: This should not happen as we force an early lookup
+ * via debug.pfugidhack
+ */
+ ; /* empty */
+#else
+ pd->lookup.done = pf_socket_lookup(dir, pd);
+#endif
+ if (pd->lookup.done > 0) {
+ hdr.uid = pd->lookup.uid;
+ hdr.pid = pd->lookup.pid;
+ } else {
+ hdr.uid = UID_MAX;
+ hdr.pid = NO_PID;
+ }
+ hdr.rule_uid = rm->cuid;
+ hdr.rule_pid = rm->cpid;
+ hdr.dir = dir;
+
+#ifdef INET
+ if (af == AF_INET && dir == PF_OUT) {
+ struct ip *ip;
+
+ ip = mtod(m, struct ip *);
+ ip->ip_sum = 0;
+ ip->ip_sum = in_cksum(m, ip->ip_hl << 2);
+ }
+#endif /* INET */
+
+ ifn->if_opackets++;
+ ifn->if_obytes += m->m_pkthdr.len;
+#ifdef __FreeBSD__
+ BPF_MTAP2(ifn, &hdr, PFLOG_HDRLEN, m);
+#else
+ bpf_mtap_hdr(ifn->if_bpf, (char *)&hdr, PFLOG_HDRLEN, m,
+ BPF_DIRECTION_OUT);
+#endif
+#endif
+
+ return (0);
+}
+
+#ifdef __FreeBSD__
+static int
+pflog_modevent(module_t mod, int type, void *data)
+{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ pflogattach(1);
+ PF_LOCK();
+ pflog_packet_ptr = pflog_packet;
+ PF_UNLOCK();
+ break;
+ case MOD_UNLOAD:
+ PF_LOCK();
+ pflog_packet_ptr = NULL;
+ PF_UNLOCK();
+ if_clone_detach(&pflog_cloner);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+static moduledata_t pflog_mod = { "pflog", pflog_modevent, 0 };
+
+#define PFLOG_MODVER 1
+
+DECLARE_MODULE(pflog, pflog_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+MODULE_VERSION(pflog, PFLOG_MODVER);
+MODULE_DEPEND(pflog, pf, PF_MODVER, PF_MODVER, PF_MODVER);
+#endif /* __FreeBSD__ */
diff --git a/freebsd/sys/contrib/pf/net/if_pflog.h b/freebsd/sys/contrib/pf/net/if_pflog.h
new file mode 100644
index 00000000..9e9efbef
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/if_pflog.h
@@ -0,0 +1,103 @@
+/* $FreeBSD$ */
+/* $OpenBSD: if_pflog.h,v 1.14 2006/10/25 11:27:01 henning Exp $ */
+/*
+ * Copyright 2001 Niels Provos <provos@citi.umich.edu>
+ * 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.
+ */
+
+#ifndef _NET_IF_PFLOG_HH_
+#define _NET_IF_PFLOG_HH_
+
+#define PFLOGIFS_MAX 16
+
+#ifdef _KERNEL
+struct pflog_softc {
+#ifdef __FreeBSD__
+ struct ifnet *sc_ifp; /* the interface pointer */
+#else
+ struct ifnet sc_if; /* the interface */
+#endif
+ int sc_unit;
+ LIST_ENTRY(pflog_softc) sc_list;
+};
+#endif /* _KERNEL */
+
+#define PFLOG_RULESET_NAME_SIZE 16
+
+struct pfloghdr {
+ u_int8_t length;
+ sa_family_t af;
+ u_int8_t action;
+ u_int8_t reason;
+ char ifname[IFNAMSIZ];
+ char ruleset[PFLOG_RULESET_NAME_SIZE];
+ u_int32_t rulenr;
+ u_int32_t subrulenr;
+ uid_t uid;
+ pid_t pid;
+ uid_t rule_uid;
+ pid_t rule_pid;
+ u_int8_t dir;
+ u_int8_t pad[3];
+};
+
+#define PFLOG_HDRLEN sizeof(struct pfloghdr)
+/* minus pad, also used as a signature */
+#define PFLOG_REAL_HDRLEN offsetof(struct pfloghdr, pad)
+
+/* XXX remove later when old format logs are no longer needed */
+struct old_pfloghdr {
+ u_int32_t af;
+ char ifname[IFNAMSIZ];
+ short rnr;
+ u_short reason;
+ u_short action;
+ u_short dir;
+};
+#define OLD_PFLOG_HDRLEN sizeof(struct old_pfloghdr)
+
+#ifdef _KERNEL
+
+#ifdef __FreeBSD__
+struct pf_rule;
+struct pf_ruleset;
+struct pfi_kif;
+struct pf_pdesc;
+
+typedef int pflog_packet_t(struct pfi_kif *, struct mbuf *, sa_family_t,
+ u_int8_t, u_int8_t, struct pf_rule *, struct pf_rule *,
+ struct pf_ruleset *, struct pf_pdesc *);
+extern pflog_packet_t *pflog_packet_ptr;
+#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) do { \
+ if (pflog_packet_ptr != NULL) \
+ pflog_packet_ptr(i,a,b,c,d,e,f,g,h); \
+} while (0)
+#else /* ! __FreeBSD__ */
+#if NPFLOG > 0
+#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) pflog_packet(i,a,b,c,d,e,f,g,h)
+#else
+#define PFLOG_PACKET(i,x,a,b,c,d,e,f,g,h) ((void)0)
+#endif /* NPFLOG > 0 */
+#endif /* __FreeBSD__ */
+#endif /* _KERNEL */
+#endif /* _NET_IF_PFLOG_HH_ */
diff --git a/freebsd/sys/contrib/pf/net/if_pfsync.c b/freebsd/sys/contrib/pf/net/if_pfsync.c
new file mode 100644
index 00000000..bc70adfe
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/if_pfsync.c
@@ -0,0 +1,2331 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: if_pfsync.c,v 1.73 2006/11/16 13:13:38 henning Exp $ */
+
+/*
+ * Copyright (c) 2002 Michael Shalayeff
+ * 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.
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+#include <freebsd/local/opt_carp.h>
+#include <freebsd/local/opt_bpf.h>
+#include <freebsd/local/opt_pf.h>
+
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef DEV_BPF
+#define NBPFILTER DEV_BPF
+#else
+#define NBPFILTER 0
+#endif
+
+#ifdef DEV_PFSYNC
+#define NPFSYNC DEV_PFSYNC
+#else
+#define NPFSYNC 0
+#endif
+
+#ifdef DEV_CARP
+#define NCARP DEV_CARP
+#else
+#define NCARP 0
+#endif
+#endif /* __FreeBSD__ */
+
+#include <freebsd/sys/param.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/priv.h>
+#endif
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/time.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/socket.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/endian.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/module.h>
+#include <freebsd/sys/sockio.h>
+#include <freebsd/sys/taskqueue.h>
+#include <freebsd/sys/lock.h>
+#include <freebsd/sys/mutex.h>
+#include <freebsd/sys/sysctl.h>
+#else
+#include <freebsd/sys/ioctl.h>
+#include <freebsd/sys/timeout.h>
+#endif
+#include <freebsd/sys/kernel.h>
+
+#include <freebsd/net/if.h>
+#ifdef __FreeBSD__
+#include <freebsd/net/if_clone.h>
+#endif
+#include <freebsd/net/if_types.h>
+#include <freebsd/net/route.h>
+#include <freebsd/net/bpf.h>
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/if_ether.h>
+#include <freebsd/netinet/tcp.h>
+#include <freebsd/netinet/tcp_seq.h>
+
+#ifdef INET
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/in_var.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_var.h>
+#endif
+
+#ifdef INET6
+#include <freebsd/netinet6/nd6.h>
+#endif /* INET6 */
+
+#ifndef __FreeBSD__
+#include <freebsd/local/carp.h>
+#endif
+#if NCARP > 0
+#include <freebsd/netinet/ip_carp.h>
+#endif
+
+#include <freebsd/net/pfvar.h>
+#include <freebsd/net/if_pfsync.h>
+
+#ifndef __FreeBSD__
+#include <freebsd/local/bpfilter.h>
+#include <freebsd/local/pfsync.h>
+#endif
+
+#define PFSYNC_MINMTU \
+ (sizeof(struct pfsync_header) + sizeof(struct pf_state))
+
+#ifdef PFSYNCDEBUG
+#define DPRINTF(x) do { if (pfsyncdebug) printf x ; } while (0)
+int pfsyncdebug;
+#else
+#define DPRINTF(x)
+#endif
+
+struct pfsync_softc *pfsyncif = NULL;
+struct pfsyncstats pfsyncstats;
+#ifdef __FreeBSD__
+SYSCTL_DECL(_net_inet_pfsync);
+SYSCTL_STRUCT(_net_inet_pfsync, 0, stats, CTLFLAG_RW,
+ &pfsyncstats, pfsyncstats,
+ "PFSYNC statistics (struct pfsyncstats, net/if_pfsync.h)");
+#endif
+
+void pfsyncattach(int);
+#ifdef __FreeBSD__
+int pfsync_clone_create(struct if_clone *, int, caddr_t);
+void pfsync_clone_destroy(struct ifnet *);
+#else
+int pfsync_clone_create(struct if_clone *, int);
+int pfsync_clone_destroy(struct ifnet *);
+#endif
+void pfsync_setmtu(struct pfsync_softc *, int);
+int pfsync_alloc_scrub_memory(struct pfsync_state_peer *,
+ struct pf_state_peer *);
+int pfsync_insert_net_state(struct pfsync_state *, u_int8_t);
+#ifdef PFSYNC_TDB
+void pfsync_update_net_tdb(struct pfsync_tdb *);
+#endif
+int pfsyncoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
+ struct route *);
+int pfsyncioctl(struct ifnet *, u_long, caddr_t);
+void pfsyncstart(struct ifnet *);
+
+struct mbuf *pfsync_get_mbuf(struct pfsync_softc *, u_int8_t, void **);
+int pfsync_request_update(struct pfsync_state_upd *, struct in_addr *);
+int pfsync_sendout(struct pfsync_softc *);
+#ifdef PFSYNC_TDB
+int pfsync_tdb_sendout(struct pfsync_softc *);
+#endif
+int pfsync_sendout_mbuf(struct pfsync_softc *, struct mbuf *);
+void pfsync_timeout(void *);
+#ifdef PFSYNC_TDB
+void pfsync_tdb_timeout(void *);
+#endif
+void pfsync_send_bus(struct pfsync_softc *, u_int8_t);
+void pfsync_bulk_update(void *);
+void pfsync_bulkfail(void *);
+
+#ifdef __FreeBSD__
+void pfsync_ifdetach(void *, struct ifnet *);
+void pfsync_senddef(void *, int);
+
+/* XXX: ugly */
+#define betoh64 (unsigned long long)be64toh
+#define timeout_del callout_stop
+#endif
+
+int pfsync_sync_ok;
+#ifndef __FreeBSD__
+extern int ifqmaxlen;
+#endif
+
+#ifdef __FreeBSD__
+IFC_SIMPLE_DECLARE(pfsync, 1);
+#else
+struct if_clone pfsync_cloner =
+ IF_CLONE_INITIALIZER("pfsync", pfsync_clone_create, pfsync_clone_destroy);
+#endif
+
+void
+pfsyncattach(int npfsync)
+{
+ if_clone_attach(&pfsync_cloner);
+}
+
+int
+#ifdef __FreeBSD__
+pfsync_clone_create(struct if_clone *ifc, int unit, caddr_t param)
+#else
+pfsync_clone_create(struct if_clone *ifc, int unit)
+#endif
+{
+ struct ifnet *ifp;
+
+ if (unit != 0)
+ return (EINVAL);
+
+ pfsync_sync_ok = 1;
+ if ((pfsyncif = malloc(sizeof(*pfsyncif), M_DEVBUF, M_NOWAIT)) == NULL)
+ return (ENOMEM);
+ bzero(pfsyncif, sizeof(*pfsyncif));
+#ifdef __FreeBSD__
+ if ((pfsyncif->sc_imo.imo_membership = (struct in_multi **)malloc(
+ (sizeof(struct in_multi *) * IP_MIN_MEMBERSHIPS), M_DEVBUF,
+ M_NOWAIT)) == NULL) {
+ free(pfsyncif, M_DEVBUF);
+ return (ENOSPC);
+ }
+ pfsyncif->sc_imo.imo_mfilters = NULL;
+ pfsyncif->sc_imo.imo_max_memberships = IP_MIN_MEMBERSHIPS;
+ pfsyncif->sc_imo.imo_multicast_vif = -1;
+
+ ifp = pfsyncif->sc_ifp = if_alloc(IFT_PFSYNC);
+ if (ifp == NULL) {
+ free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
+ free(pfsyncif, M_DEVBUF);
+ return (ENOSPC);
+ }
+ if_initname(ifp, ifc->ifc_name, unit);
+
+ pfsyncif->sc_detachtag = EVENTHANDLER_REGISTER(ifnet_departure_event,
+ pfsync_ifdetach, pfsyncif, EVENTHANDLER_PRI_ANY);
+ if (pfsyncif->sc_detachtag == NULL) {
+ if_free(ifp);
+ free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
+ free(pfsyncif, M_DEVBUF);
+ return (ENOSPC);
+ }
+
+ pfsyncif->sc_ifq.ifq_maxlen = ifqmaxlen;
+ mtx_init(&pfsyncif->sc_ifq.ifq_mtx, ifp->if_xname,
+ "pfsync send queue", MTX_DEF);
+ TASK_INIT(&pfsyncif->sc_send_task, 0, pfsync_senddef, pfsyncif);
+#endif
+ pfsyncif->sc_mbuf = NULL;
+ pfsyncif->sc_mbuf_net = NULL;
+#ifdef PFSYNC_TDB
+ pfsyncif->sc_mbuf_tdb = NULL;
+#endif
+ pfsyncif->sc_statep.s = NULL;
+ pfsyncif->sc_statep_net.s = NULL;
+#ifdef PFSYNC_TDB
+ pfsyncif->sc_statep_tdb.t = NULL;
+#endif
+ pfsyncif->sc_maxupdates = 128;
+#ifdef __FreeBSD__
+ pfsyncif->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP);
+ pfsyncif->sc_sendaddr.s_addr = htonl(INADDR_PFSYNC_GROUP);
+#else
+ pfsyncif->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
+ pfsyncif->sc_sendaddr.s_addr = INADDR_PFSYNC_GROUP;
+#endif
+ pfsyncif->sc_ureq_received = 0;
+ pfsyncif->sc_ureq_sent = 0;
+ pfsyncif->sc_bulk_send_next = NULL;
+ pfsyncif->sc_bulk_terminator = NULL;
+#ifndef __FreeBSD__
+ ifp = &pfsyncif->sc_if;
+ snprintf(ifp->if_xname, sizeof ifp->if_xname, "pfsync%d", unit);
+#endif
+ ifp->if_softc = pfsyncif;
+ ifp->if_ioctl = pfsyncioctl;
+ ifp->if_output = pfsyncoutput;
+ ifp->if_start = pfsyncstart;
+ ifp->if_type = IFT_PFSYNC;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_hdrlen = PFSYNC_HDRLEN;
+ pfsync_setmtu(pfsyncif, ETHERMTU);
+#ifdef __FreeBSD__
+ callout_init(&pfsyncif->sc_tmo, CALLOUT_MPSAFE);
+#ifdef PFSYNC_TDB
+ callout_init(&pfsyncif->sc_tdb_tmo, CALLOUT_MPSAFE);
+#endif
+ callout_init(&pfsyncif->sc_bulk_tmo, CALLOUT_MPSAFE);
+ callout_init(&pfsyncif->sc_bulkfail_tmo, CALLOUT_MPSAFE);
+#else
+ timeout_set(&pfsyncif->sc_tmo, pfsync_timeout, pfsyncif);
+ timeout_set(&pfsyncif->sc_tdb_tmo, pfsync_tdb_timeout, pfsyncif);
+ timeout_set(&pfsyncif->sc_bulk_tmo, pfsync_bulk_update, pfsyncif);
+ timeout_set(&pfsyncif->sc_bulkfail_tmo, pfsync_bulkfail, pfsyncif);
+#endif
+ if_attach(ifp);
+#ifndef __FreeBSD__
+ if_alloc_sadl(ifp);
+#endif
+
+#if NCARP > 0
+ if_addgroup(ifp, "carp");
+#endif
+
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+ bpfattach(ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
+#else
+ bpfattach(&pfsyncif->sc_if.if_bpf, ifp, DLT_PFSYNC, PFSYNC_HDRLEN);
+#endif
+#endif
+
+ return (0);
+}
+
+#ifdef __FreeBSD__
+void
+#else
+int
+#endif
+pfsync_clone_destroy(struct ifnet *ifp)
+{
+#ifdef __FreeBSD__
+ EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfsyncif->sc_detachtag);
+ callout_stop(&pfsyncif->sc_tmo);
+#ifdef PFSYNC_TDB
+ callout_stop(&pfsyncif->sc_tdb_tmo);
+#endif
+ callout_stop(&pfsyncif->sc_bulk_tmo);
+ callout_stop(&pfsyncif->sc_bulkfail_tmo);
+ /* XXX: more? */
+#endif
+
+#if NBPFILTER > 0
+ bpfdetach(ifp);
+#endif
+ if_detach(ifp);
+#ifdef __FreeBSD__
+ if_free(ifp);
+ free(pfsyncif->sc_imo.imo_membership, M_DEVBUF);
+#endif
+ free(pfsyncif, M_DEVBUF);
+ pfsyncif = NULL;
+#ifndef __FreeBSD__
+ return (0);
+#endif
+}
+
+/*
+ * Start output on the pfsync interface.
+ */
+void
+pfsyncstart(struct ifnet *ifp)
+{
+ struct mbuf *m;
+#ifndef __FreeBSD__
+ int s;
+#endif
+
+ for (;;) {
+#ifdef __FreeBSD__
+ IF_LOCK(&ifp->if_snd);
+ _IF_DROP(&ifp->if_snd);
+ _IF_DEQUEUE(&ifp->if_snd, m);
+ IF_UNLOCK(&ifp->if_snd);
+#else
+ s = splnet();
+ IF_DROP(&ifp->if_snd);
+ IF_DEQUEUE(&ifp->if_snd, m);
+ splx(s);
+#endif
+
+ if (m == NULL)
+ return;
+ else
+ m_freem(m);
+ }
+}
+
+int
+pfsync_alloc_scrub_memory(struct pfsync_state_peer *s,
+ struct pf_state_peer *d)
+{
+ if (s->scrub.scrub_flag && d->scrub == NULL) {
+ d->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
+ if (d->scrub == NULL)
+ return (ENOMEM);
+ bzero(d->scrub, sizeof(*d->scrub));
+ }
+
+ return (0);
+}
+
+int
+pfsync_insert_net_state(struct pfsync_state *sp, u_int8_t chksum_flag)
+{
+ struct pf_state *st = NULL;
+ struct pf_rule *r = NULL;
+ struct pfi_kif *kif;
+
+ if (sp->creatorid == 0 && pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pfsync_insert_net_state: invalid creator id:"
+ " %08x\n", ntohl(sp->creatorid));
+ return (EINVAL);
+ }
+
+ kif = pfi_kif_get(sp->ifname);
+ if (kif == NULL) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync_insert_net_state: "
+ "unknown interface: %s\n", sp->ifname);
+ /* skip this state */
+ return (0);
+ }
+
+ /*
+ * If the ruleset checksums match, it's safe to associate the state
+ * with the rule of that number.
+ */
+ if (sp->rule != htonl(-1) && sp->anchor == htonl(-1) && chksum_flag)
+ r = pf_main_ruleset.rules[
+ PF_RULESET_FILTER].active.ptr_array[ntohl(sp->rule)];
+ else
+ r = &pf_default_rule;
+
+ if (!r->max_states || r->states < r->max_states)
+ st = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (st == NULL) {
+ pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ return (ENOMEM);
+ }
+ bzero(st, sizeof(*st));
+
+ /* allocate memory for scrub info */
+ if (pfsync_alloc_scrub_memory(&sp->src, &st->src) ||
+ pfsync_alloc_scrub_memory(&sp->dst, &st->dst)) {
+ pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ if (st->src.scrub)
+ pool_put(&pf_state_scrub_pl, st->src.scrub);
+ pool_put(&pf_state_pl, st);
+ return (ENOMEM);
+ }
+
+ st->rule.ptr = r;
+ /* XXX get pointers to nat_rule and anchor */
+
+ /* XXX when we have nat_rule/anchors, use STATE_INC_COUNTERS */
+ r->states++;
+
+ /* fill in the rest of the state entry */
+ pf_state_host_ntoh(&sp->lan, &st->lan);
+ pf_state_host_ntoh(&sp->gwy, &st->gwy);
+ pf_state_host_ntoh(&sp->ext, &st->ext);
+
+ pf_state_peer_ntoh(&sp->src, &st->src);
+ pf_state_peer_ntoh(&sp->dst, &st->dst);
+
+ bcopy(&sp->rt_addr, &st->rt_addr, sizeof(st->rt_addr));
+ st->creation = time_second - ntohl(sp->creation);
+ st->expire = ntohl(sp->expire) + time_second;
+
+ st->af = sp->af;
+ st->proto = sp->proto;
+ st->direction = sp->direction;
+ st->log = sp->log;
+ st->timeout = sp->timeout;
+ st->state_flags = sp->state_flags;
+
+ bcopy(sp->id, &st->id, sizeof(st->id));
+ st->creatorid = sp->creatorid;
+ st->sync_flags = PFSTATE_FROMSYNC;
+
+ if (pf_insert_state(kif, st)) {
+ pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ /* XXX when we have nat_rule/anchors, use STATE_DEC_COUNTERS */
+ r->states--;
+ if (st->dst.scrub)
+ pool_put(&pf_state_scrub_pl, st->dst.scrub);
+ if (st->src.scrub)
+ pool_put(&pf_state_scrub_pl, st->src.scrub);
+ pool_put(&pf_state_pl, st);
+ return (EINVAL);
+ }
+
+ return (0);
+}
+
+void
+#ifdef __FreeBSD__
+pfsync_input(struct mbuf *m, __unused int off)
+#else
+pfsync_input(struct mbuf *m, ...)
+#endif
+{
+ struct ip *ip = mtod(m, struct ip *);
+ struct pfsync_header *ph;
+ struct pfsync_softc *sc = pfsyncif;
+ struct pf_state *st;
+ struct pf_state_cmp key;
+ struct pfsync_state *sp;
+ struct pfsync_state_upd *up;
+ struct pfsync_state_del *dp;
+ struct pfsync_state_clr *cp;
+ struct pfsync_state_upd_req *rup;
+ struct pfsync_state_bus *bus;
+#ifdef PFSYNC_TDB
+ struct pfsync_tdb *pt;
+#endif
+ struct in_addr src;
+ struct mbuf *mp;
+ int iplen, action, error, i, s, count, offp, sfail, stale = 0;
+ u_int8_t chksum_flag = 0;
+
+ pfsyncstats.pfsyncs_ipackets++;
+
+ /* verify that we have a sync interface configured */
+ if (!sc || !sc->sc_sync_ifp || !pf_status.running)
+ goto done;
+
+ /* verify that the packet came in on the right interface */
+ if (sc->sc_sync_ifp != m->m_pkthdr.rcvif) {
+ pfsyncstats.pfsyncs_badif++;
+ goto done;
+ }
+
+ /* verify that the IP TTL is 255. */
+ if (ip->ip_ttl != PFSYNC_DFLTTL) {
+ pfsyncstats.pfsyncs_badttl++;
+ goto done;
+ }
+
+ iplen = ip->ip_hl << 2;
+
+ if (m->m_pkthdr.len < iplen + sizeof(*ph)) {
+ pfsyncstats.pfsyncs_hdrops++;
+ goto done;
+ }
+
+ if (iplen + sizeof(*ph) > m->m_len) {
+ if ((m = m_pullup(m, iplen + sizeof(*ph))) == NULL) {
+ pfsyncstats.pfsyncs_hdrops++;
+ goto done;
+ }
+ ip = mtod(m, struct ip *);
+ }
+ ph = (struct pfsync_header *)((char *)ip + iplen);
+
+ /* verify the version */
+ if (ph->version != PFSYNC_VERSION) {
+ pfsyncstats.pfsyncs_badver++;
+ goto done;
+ }
+
+ action = ph->action;
+ count = ph->count;
+
+ /* make sure it's a valid action code */
+ if (action >= PFSYNC_ACT_MAX) {
+ pfsyncstats.pfsyncs_badact++;
+ goto done;
+ }
+
+ /* Cheaper to grab this now than having to mess with mbufs later */
+ src = ip->ip_src;
+
+ if (!bcmp(&ph->pf_chksum, &pf_status.pf_chksum, PF_MD5_DIGEST_LENGTH))
+ chksum_flag++;
+
+ switch (action) {
+ case PFSYNC_ACT_CLR: {
+ struct pf_state *nexts;
+ struct pfi_kif *kif;
+ u_int32_t creatorid;
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ sizeof(*cp), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+ cp = (struct pfsync_state_clr *)(mp->m_data + offp);
+ creatorid = cp->creatorid;
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (cp->ifname[0] == '\0') {
+ for (st = RB_MIN(pf_state_tree_id, &tree_id);
+ st; st = nexts) {
+ nexts = RB_NEXT(pf_state_tree_id, &tree_id, st);
+ if (st->creatorid == creatorid) {
+ st->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(st);
+ }
+ }
+ } else {
+ if ((kif = pfi_kif_get(cp->ifname)) == NULL) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ return;
+ }
+ for (st = RB_MIN(pf_state_tree_lan_ext,
+ &kif->pfik_lan_ext); st; st = nexts) {
+ nexts = RB_NEXT(pf_state_tree_lan_ext,
+ &kif->pfik_lan_ext, st);
+ if (st->creatorid == creatorid) {
+ st->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(st);
+ }
+ }
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+
+ break;
+ }
+ case PFSYNC_ACT_INS:
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ count * sizeof(*sp), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
+ i < count; i++, sp++) {
+ /* check for invalid values */
+ if (sp->timeout >= PFTM_MAX ||
+ sp->src.state > PF_TCPS_PROXY_DST ||
+ sp->dst.state > PF_TCPS_PROXY_DST ||
+ sp->direction > PF_OUT ||
+ (sp->af != AF_INET && sp->af != AF_INET6)) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync_insert: PFSYNC_ACT_INS: "
+ "invalid value\n");
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+
+ if ((error = pfsync_insert_net_state(sp,
+ chksum_flag))) {
+ if (error == ENOMEM) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ goto done;
+ }
+ continue;
+ }
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+ case PFSYNC_ACT_UPD:
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ count * sizeof(*sp), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
+ i < count; i++, sp++) {
+ int flags = PFSYNC_FLAG_STALE;
+
+ /* check for invalid values */
+ if (sp->timeout >= PFTM_MAX ||
+ sp->src.state > PF_TCPS_PROXY_DST ||
+ sp->dst.state > PF_TCPS_PROXY_DST) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync_insert: PFSYNC_ACT_UPD: "
+ "invalid value\n");
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+
+ bcopy(sp->id, &key.id, sizeof(key.id));
+ key.creatorid = sp->creatorid;
+
+ st = pf_find_state_byid(&key);
+ if (st == NULL) {
+ /* insert the update */
+ if (pfsync_insert_net_state(sp, chksum_flag))
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+ sfail = 0;
+ if (st->proto == IPPROTO_TCP) {
+ /*
+ * The state should never go backwards except
+ * for syn-proxy states. Neither should the
+ * sequence window slide backwards.
+ */
+ if (st->src.state > sp->src.state &&
+ (st->src.state < PF_TCPS_PROXY_SRC ||
+ sp->src.state >= PF_TCPS_PROXY_SRC))
+ sfail = 1;
+ else if (SEQ_GT(st->src.seqlo,
+ ntohl(sp->src.seqlo)))
+ sfail = 3;
+ else if (st->dst.state > sp->dst.state) {
+ /* There might still be useful
+ * information about the src state here,
+ * so import that part of the update,
+ * then "fail" so we send the updated
+ * state back to the peer who is missing
+ * our what we know. */
+ pf_state_peer_ntoh(&sp->src, &st->src);
+ /* XXX do anything with timeouts? */
+ sfail = 7;
+ flags = 0;
+ } else if (st->dst.state >= TCPS_SYN_SENT &&
+ SEQ_GT(st->dst.seqlo, ntohl(sp->dst.seqlo)))
+ sfail = 4;
+ } else {
+ /*
+ * Non-TCP protocol state machine always go
+ * forwards
+ */
+ if (st->src.state > sp->src.state)
+ sfail = 5;
+ else if (st->dst.state > sp->dst.state)
+ sfail = 6;
+ }
+ if (sfail) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: %s stale update "
+ "(%d) id: %016llx "
+ "creatorid: %08x\n",
+ (sfail < 7 ? "ignoring"
+ : "partial"), sfail,
+ betoh64(st->id),
+ ntohl(st->creatorid));
+ pfsyncstats.pfsyncs_badstate++;
+
+ if (!(sp->sync_flags & PFSTATE_STALE)) {
+ /* we have a better state, send it */
+ if (sc->sc_mbuf != NULL && !stale)
+ pfsync_sendout(sc);
+ stale++;
+ if (!st->sync_flags)
+ pfsync_pack_state(
+ PFSYNC_ACT_UPD, st, flags);
+ }
+ continue;
+ }
+ pfsync_alloc_scrub_memory(&sp->dst, &st->dst);
+ pf_state_peer_ntoh(&sp->src, &st->src);
+ pf_state_peer_ntoh(&sp->dst, &st->dst);
+ st->expire = ntohl(sp->expire) + time_second;
+ st->timeout = sp->timeout;
+ }
+ if (stale && sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+ /*
+ * It's not strictly necessary for us to support the "uncompressed"
+ * delete action, but it's relatively simple and maintains consistency.
+ */
+ case PFSYNC_ACT_DEL:
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ count * sizeof(*sp), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0, sp = (struct pfsync_state *)(mp->m_data + offp);
+ i < count; i++, sp++) {
+ bcopy(sp->id, &key.id, sizeof(key.id));
+ key.creatorid = sp->creatorid;
+
+ st = pf_find_state_byid(&key);
+ if (st == NULL) {
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+ st->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(st);
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+ case PFSYNC_ACT_UPD_C: {
+ int update_requested = 0;
+
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ count * sizeof(*up), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0, up = (struct pfsync_state_upd *)(mp->m_data + offp);
+ i < count; i++, up++) {
+ /* check for invalid values */
+ if (up->timeout >= PFTM_MAX ||
+ up->src.state > PF_TCPS_PROXY_DST ||
+ up->dst.state > PF_TCPS_PROXY_DST) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync_insert: "
+ "PFSYNC_ACT_UPD_C: "
+ "invalid value\n");
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+
+ bcopy(up->id, &key.id, sizeof(key.id));
+ key.creatorid = up->creatorid;
+
+ st = pf_find_state_byid(&key);
+ if (st == NULL) {
+ /* We don't have this state. Ask for it. */
+ error = pfsync_request_update(up, &src);
+ if (error == ENOMEM) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ goto done;
+ }
+ update_requested = 1;
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+ sfail = 0;
+ if (st->proto == IPPROTO_TCP) {
+ /*
+ * The state should never go backwards except
+ * for syn-proxy states. Neither should the
+ * sequence window slide backwards.
+ */
+ if (st->src.state > up->src.state &&
+ (st->src.state < PF_TCPS_PROXY_SRC ||
+ up->src.state >= PF_TCPS_PROXY_SRC))
+ sfail = 1;
+ else if (st->dst.state > up->dst.state)
+ sfail = 2;
+ else if (SEQ_GT(st->src.seqlo,
+ ntohl(up->src.seqlo)))
+ sfail = 3;
+ else if (st->dst.state >= TCPS_SYN_SENT &&
+ SEQ_GT(st->dst.seqlo, ntohl(up->dst.seqlo)))
+ sfail = 4;
+ } else {
+ /*
+ * Non-TCP protocol state machine always go
+ * forwards
+ */
+ if (st->src.state > up->src.state)
+ sfail = 5;
+ else if (st->dst.state > up->dst.state)
+ sfail = 6;
+ }
+ if (sfail) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: ignoring stale update "
+ "(%d) id: %016llx "
+ "creatorid: %08x\n", sfail,
+ betoh64(st->id),
+ ntohl(st->creatorid));
+ pfsyncstats.pfsyncs_badstate++;
+
+ /* we have a better state, send it out */
+ if ((!stale || update_requested) &&
+ sc->sc_mbuf != NULL) {
+ pfsync_sendout(sc);
+ update_requested = 0;
+ }
+ stale++;
+ if (!st->sync_flags)
+ pfsync_pack_state(PFSYNC_ACT_UPD, st,
+ PFSYNC_FLAG_STALE);
+ continue;
+ }
+ pfsync_alloc_scrub_memory(&up->dst, &st->dst);
+ pf_state_peer_ntoh(&up->src, &st->src);
+ pf_state_peer_ntoh(&up->dst, &st->dst);
+ st->expire = ntohl(up->expire) + time_second;
+ st->timeout = up->timeout;
+ }
+ if ((update_requested || stale) && sc->sc_mbuf)
+ pfsync_sendout(sc);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+ }
+ case PFSYNC_ACT_DEL_C:
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ count * sizeof(*dp), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0, dp = (struct pfsync_state_del *)(mp->m_data + offp);
+ i < count; i++, dp++) {
+ bcopy(dp->id, &key.id, sizeof(key.id));
+ key.creatorid = dp->creatorid;
+
+ st = pf_find_state_byid(&key);
+ if (st == NULL) {
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+ st->sync_flags |= PFSTATE_FROMSYNC;
+ pf_unlink_state(st);
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+ case PFSYNC_ACT_INS_F:
+ case PFSYNC_ACT_DEL_F:
+ /* not implemented */
+ break;
+ case PFSYNC_ACT_UREQ:
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ count * sizeof(*rup), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+ for (i = 0,
+ rup = (struct pfsync_state_upd_req *)(mp->m_data + offp);
+ i < count; i++, rup++) {
+ bcopy(rup->id, &key.id, sizeof(key.id));
+ key.creatorid = rup->creatorid;
+
+ if (key.id == 0 && key.creatorid == 0) {
+ sc->sc_ureq_received = time_uptime;
+ if (sc->sc_bulk_send_next == NULL)
+ sc->sc_bulk_send_next =
+ TAILQ_FIRST(&state_list);
+ sc->sc_bulk_terminator = sc->sc_bulk_send_next;
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received "
+ "bulk update request\n");
+ pfsync_send_bus(sc, PFSYNC_BUS_START);
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_bulk_tmo, 1 * hz,
+ pfsync_bulk_update, pfsyncif);
+#else
+ timeout_add(&sc->sc_bulk_tmo, 1 * hz);
+#endif
+ } else {
+ st = pf_find_state_byid(&key);
+ if (st == NULL) {
+ pfsyncstats.pfsyncs_badstate++;
+ continue;
+ }
+ if (!st->sync_flags)
+ pfsync_pack_state(PFSYNC_ACT_UPD,
+ st, 0);
+ }
+ }
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+ case PFSYNC_ACT_BUS:
+ /* If we're not waiting for a bulk update, who cares. */
+ if (sc->sc_ureq_sent == 0)
+ break;
+
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ sizeof(*bus), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+ bus = (struct pfsync_state_bus *)(mp->m_data + offp);
+ switch (bus->status) {
+ case PFSYNC_BUS_START:
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_bulkfail_tmo,
+ pf_pool_limits[PF_LIMIT_STATES].limit /
+ (PFSYNC_BULKPACKETS * sc->sc_maxcount),
+ pfsync_bulkfail, pfsyncif);
+#else
+ timeout_add(&sc->sc_bulkfail_tmo,
+ pf_pool_limits[PF_LIMIT_STATES].limit /
+ (PFSYNC_BULKPACKETS * sc->sc_maxcount));
+#endif
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received bulk "
+ "update start\n");
+ break;
+ case PFSYNC_BUS_END:
+ if (time_uptime - ntohl(bus->endtime) >=
+ sc->sc_ureq_sent) {
+ /* that's it, we're happy */
+ sc->sc_ureq_sent = 0;
+ sc->sc_bulk_tries = 0;
+ timeout_del(&sc->sc_bulkfail_tmo);
+#if NCARP > 0
+ if (!pfsync_sync_ok)
+#ifdef __FreeBSD__
+#ifdef CARP_ADVANCED
+ carp_group_demote_adj(sc->sc_ifp, -1);
+#endif
+#else
+ carp_group_demote_adj(&sc->sc_if, -1);
+#endif
+#endif
+ pfsync_sync_ok = 1;
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received valid "
+ "bulk update end\n");
+ } else {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: received invalid "
+ "bulk update end: bad timestamp\n");
+ }
+ break;
+ }
+ break;
+#ifdef PFSYNC_TDB
+ case PFSYNC_ACT_TDB_UPD:
+ if ((mp = m_pulldown(m, iplen + sizeof(*ph),
+ count * sizeof(*pt), &offp)) == NULL) {
+ pfsyncstats.pfsyncs_badlen++;
+ return;
+ }
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0, pt = (struct pfsync_tdb *)(mp->m_data + offp);
+ i < count; i++, pt++)
+ pfsync_update_net_tdb(pt);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+#endif
+ }
+
+done:
+ if (m)
+ m_freem(m);
+}
+
+int
+pfsyncoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+ struct route *ro)
+{
+ m_freem(m);
+ return (0);
+}
+
+/* ARGSUSED */
+int
+pfsyncioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+#ifndef __FreeBSD__
+ struct proc *p = curproc;
+#endif
+ struct pfsync_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct ip_moptions *imo = &sc->sc_imo;
+ struct pfsyncreq pfsyncr;
+ struct ifnet *sifp;
+ int s, error;
+
+ switch (cmd) {
+ case SIOCSIFADDR:
+ case SIOCAIFADDR:
+ case SIOCSIFDSTADDR:
+ case SIOCSIFFLAGS:
+#ifdef __FreeBSD__
+ if (ifp->if_flags & IFF_UP)
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ else
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+#else
+ if (ifp->if_flags & IFF_UP)
+ ifp->if_flags |= IFF_RUNNING;
+ else
+ ifp->if_flags &= ~IFF_RUNNING;
+#endif
+ break;
+ case SIOCSIFMTU:
+ if (ifr->ifr_mtu < PFSYNC_MINMTU)
+ return (EINVAL);
+ if (ifr->ifr_mtu > MCLBYTES)
+ ifr->ifr_mtu = MCLBYTES;
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (ifr->ifr_mtu < ifp->if_mtu)
+ pfsync_sendout(sc);
+ pfsync_setmtu(sc, ifr->ifr_mtu);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ break;
+ case SIOCGETPFSYNC:
+ bzero(&pfsyncr, sizeof(pfsyncr));
+ if (sc->sc_sync_ifp)
+ strlcpy(pfsyncr.pfsyncr_syncdev,
+ sc->sc_sync_ifp->if_xname, IFNAMSIZ);
+ pfsyncr.pfsyncr_syncpeer = sc->sc_sync_peer;
+ pfsyncr.pfsyncr_maxupdates = sc->sc_maxupdates;
+ if ((error = copyout(&pfsyncr, ifr->ifr_data, sizeof(pfsyncr))))
+ return (error);
+ break;
+ case SIOCSETPFSYNC:
+#ifdef __FreeBSD__
+ if ((error = priv_check(curthread, PRIV_NETINET_PF)) != 0)
+#else
+ if ((error = suser(p, p->p_acflag)) != 0)
+#endif
+ return (error);
+ if ((error = copyin(ifr->ifr_data, &pfsyncr, sizeof(pfsyncr))))
+ return (error);
+
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (pfsyncr.pfsyncr_syncpeer.s_addr == 0)
+#ifdef __FreeBSD__
+ sc->sc_sync_peer.s_addr = htonl(INADDR_PFSYNC_GROUP);
+#else
+ sc->sc_sync_peer.s_addr = INADDR_PFSYNC_GROUP;
+#endif
+ else
+ sc->sc_sync_peer.s_addr =
+ pfsyncr.pfsyncr_syncpeer.s_addr;
+
+ if (pfsyncr.pfsyncr_maxupdates > 255)
+#ifdef __FreeBSD__
+ {
+ PF_UNLOCK();
+#endif
+ return (EINVAL);
+#ifdef __FreeBSD__
+ }
+#endif
+ sc->sc_maxupdates = pfsyncr.pfsyncr_maxupdates;
+
+ if (pfsyncr.pfsyncr_syncdev[0] == 0) {
+ sc->sc_sync_ifp = NULL;
+ if (sc->sc_mbuf_net != NULL) {
+ /* Don't keep stale pfsync packets around. */
+ s = splnet();
+ m_freem(sc->sc_mbuf_net);
+ sc->sc_mbuf_net = NULL;
+ sc->sc_statep_net.s = NULL;
+ splx(s);
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ if (imo->imo_num_memberships > 0) {
+ in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
+ imo->imo_multicast_ifp = NULL;
+ }
+ break;
+ }
+
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ if ((sifp = ifunit(pfsyncr.pfsyncr_syncdev)) == NULL)
+ return (EINVAL);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+
+ s = splnet();
+#ifdef __FreeBSD__
+ if (sifp->if_mtu < sc->sc_ifp->if_mtu ||
+#else
+ if (sifp->if_mtu < sc->sc_if.if_mtu ||
+#endif
+ (sc->sc_sync_ifp != NULL &&
+ sifp->if_mtu < sc->sc_sync_ifp->if_mtu) ||
+ sifp->if_mtu < MCLBYTES - sizeof(struct ip))
+ pfsync_sendout(sc);
+ sc->sc_sync_ifp = sifp;
+
+#ifdef __FreeBSD__
+ pfsync_setmtu(sc, sc->sc_ifp->if_mtu);
+#else
+ pfsync_setmtu(sc, sc->sc_if.if_mtu);
+#endif
+
+ if (imo->imo_num_memberships > 0) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ in_delmulti(imo->imo_membership[--imo->imo_num_memberships]);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ imo->imo_multicast_ifp = NULL;
+ }
+
+ if (sc->sc_sync_ifp &&
+#ifdef __FreeBSD__
+ sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
+#else
+ sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
+#endif
+ struct in_addr addr;
+
+ if (!(sc->sc_sync_ifp->if_flags & IFF_MULTICAST)) {
+ sc->sc_sync_ifp = NULL;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ return (EADDRNOTAVAIL);
+ }
+
+#ifdef __FreeBSD__
+ addr.s_addr = htonl(INADDR_PFSYNC_GROUP);
+#else
+ addr.s_addr = INADDR_PFSYNC_GROUP;
+#endif
+
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ if ((imo->imo_membership[0] =
+ in_addmulti(&addr, sc->sc_sync_ifp)) == NULL) {
+ sc->sc_sync_ifp = NULL;
+ splx(s);
+ return (ENOBUFS);
+ }
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ imo->imo_num_memberships++;
+ imo->imo_multicast_ifp = sc->sc_sync_ifp;
+ imo->imo_multicast_ttl = PFSYNC_DFLTTL;
+ imo->imo_multicast_loop = 0;
+ }
+
+ if (sc->sc_sync_ifp ||
+#ifdef __FreeBSD__
+ sc->sc_sendaddr.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
+#else
+ sc->sc_sendaddr.s_addr != INADDR_PFSYNC_GROUP) {
+#endif
+ /* Request a full state table update. */
+ sc->sc_ureq_sent = time_uptime;
+#if NCARP > 0
+ if (pfsync_sync_ok)
+#ifdef __FreeBSD__
+#ifdef CARP_ADVANCED
+ carp_group_demote_adj(sc->sc_ifp, 1);
+#endif
+#else
+ carp_group_demote_adj(&sc->sc_if, 1);
+#endif
+#endif
+ pfsync_sync_ok = 0;
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: requesting bulk update\n");
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_bulkfail_tmo, 5 * hz,
+ pfsync_bulkfail, pfsyncif);
+#else
+ timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
+#endif
+ error = pfsync_request_update(NULL, NULL);
+ if (error == ENOMEM) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+ return (ENOMEM);
+ }
+ pfsync_sendout(sc);
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+
+ break;
+
+ default:
+ return (ENOTTY);
+ }
+
+ return (0);
+}
+
+void
+pfsync_setmtu(struct pfsync_softc *sc, int mtu_req)
+{
+ int mtu;
+
+ if (sc->sc_sync_ifp && sc->sc_sync_ifp->if_mtu < mtu_req)
+ mtu = sc->sc_sync_ifp->if_mtu;
+ else
+ mtu = mtu_req;
+
+ sc->sc_maxcount = (mtu - sizeof(struct pfsync_header)) /
+ sizeof(struct pfsync_state);
+ if (sc->sc_maxcount > 254)
+ sc->sc_maxcount = 254;
+#ifdef __FreeBSD__
+ sc->sc_ifp->if_mtu = sizeof(struct pfsync_header) +
+#else
+ sc->sc_if.if_mtu = sizeof(struct pfsync_header) +
+#endif
+ sc->sc_maxcount * sizeof(struct pfsync_state);
+}
+
+struct mbuf *
+pfsync_get_mbuf(struct pfsync_softc *sc, u_int8_t action, void **sp)
+{
+ struct pfsync_header *h;
+ struct mbuf *m;
+ int len;
+
+ MGETHDR(m, M_DONTWAIT, MT_DATA);
+ if (m == NULL) {
+#ifdef __FreeBSD__
+ sc->sc_ifp->if_oerrors++;
+#else
+ sc->sc_if.if_oerrors++;
+#endif
+ return (NULL);
+ }
+
+ switch (action) {
+ case PFSYNC_ACT_CLR:
+ len = sizeof(struct pfsync_header) +
+ sizeof(struct pfsync_state_clr);
+ break;
+ case PFSYNC_ACT_UPD_C:
+ len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd)) +
+ sizeof(struct pfsync_header);
+ break;
+ case PFSYNC_ACT_DEL_C:
+ len = (sc->sc_maxcount * sizeof(struct pfsync_state_del)) +
+ sizeof(struct pfsync_header);
+ break;
+ case PFSYNC_ACT_UREQ:
+ len = (sc->sc_maxcount * sizeof(struct pfsync_state_upd_req)) +
+ sizeof(struct pfsync_header);
+ break;
+ case PFSYNC_ACT_BUS:
+ len = sizeof(struct pfsync_header) +
+ sizeof(struct pfsync_state_bus);
+ break;
+#ifdef PFSYNC_TDB
+ case PFSYNC_ACT_TDB_UPD:
+ len = (sc->sc_maxcount * sizeof(struct pfsync_tdb)) +
+ sizeof(struct pfsync_header);
+ break;
+#endif
+ default:
+ len = (sc->sc_maxcount * sizeof(struct pfsync_state)) +
+ sizeof(struct pfsync_header);
+ break;
+ }
+
+ if (len > MHLEN) {
+ MCLGET(m, M_DONTWAIT);
+ if ((m->m_flags & M_EXT) == 0) {
+ m_free(m);
+#ifdef __FreeBSD__
+ sc->sc_ifp->if_oerrors++;
+#else
+ sc->sc_if.if_oerrors++;
+#endif
+ return (NULL);
+ }
+ m->m_data += (MCLBYTES - len) &~ (sizeof(long) - 1);
+ } else
+ MH_ALIGN(m, len);
+
+ m->m_pkthdr.rcvif = NULL;
+ m->m_pkthdr.len = m->m_len = sizeof(struct pfsync_header);
+ h = mtod(m, struct pfsync_header *);
+ h->version = PFSYNC_VERSION;
+ h->af = 0;
+ h->count = 0;
+ h->action = action;
+#ifndef PFSYNC_TDB
+ if (action != PFSYNC_ACT_TDB_UPD)
+#endif
+ bcopy(&pf_status.pf_chksum, &h->pf_chksum,
+ PF_MD5_DIGEST_LENGTH);
+
+ *sp = (void *)((char *)h + PFSYNC_HDRLEN);
+#ifdef PFSYNC_TDB
+ if (action == PFSYNC_ACT_TDB_UPD)
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_tdb_tmo, hz, pfsync_tdb_timeout,
+ pfsyncif);
+#else
+ timeout_add(&sc->sc_tdb_tmo, hz);
+#endif
+ else
+#endif
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_tmo, hz, pfsync_timeout, pfsyncif);
+#else
+ timeout_add(&sc->sc_tmo, hz);
+#endif
+ return (m);
+}
+
+int
+pfsync_pack_state(u_int8_t action, struct pf_state *st, int flags)
+{
+ struct ifnet *ifp = NULL;
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_header *h, *h_net;
+ struct pfsync_state *sp = NULL;
+ struct pfsync_state_upd *up = NULL;
+ struct pfsync_state_del *dp = NULL;
+ struct pf_rule *r;
+ u_long secs;
+ int s, ret = 0;
+ u_int8_t i = 255, newaction = 0;
+
+ if (sc == NULL)
+ return (0);
+#ifdef __FreeBSD__
+ ifp = sc->sc_ifp;
+#else
+ ifp = &sc->sc_if;
+#endif
+
+ /*
+ * If a packet falls in the forest and there's nobody around to
+ * hear, does it make a sound?
+ */
+ if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
+#ifdef __FreeBSD__
+ sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
+#else
+ sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
+#endif
+ /* Don't leave any stale pfsync packets hanging around. */
+ if (sc->sc_mbuf != NULL) {
+ m_freem(sc->sc_mbuf);
+ sc->sc_mbuf = NULL;
+ sc->sc_statep.s = NULL;
+ }
+ return (0);
+ }
+
+ if (action >= PFSYNC_ACT_MAX)
+ return (EINVAL);
+
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ if (sc->sc_mbuf == NULL) {
+ if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
+ (void *)&sc->sc_statep.s)) == NULL) {
+ splx(s);
+ return (ENOMEM);
+ }
+ h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ } else {
+ h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ if (h->action != action) {
+ pfsync_sendout(sc);
+ if ((sc->sc_mbuf = pfsync_get_mbuf(sc, action,
+ (void *)&sc->sc_statep.s)) == NULL) {
+ splx(s);
+ return (ENOMEM);
+ }
+ h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ } else {
+ /*
+ * If it's an update, look in the packet to see if
+ * we already have an update for the state.
+ */
+ if (action == PFSYNC_ACT_UPD && sc->sc_maxupdates) {
+ struct pfsync_state *usp =
+ (void *)((char *)h + PFSYNC_HDRLEN);
+
+ for (i = 0; i < h->count; i++) {
+ if (!memcmp(usp->id, &st->id,
+ PFSYNC_ID_LEN) &&
+ usp->creatorid == st->creatorid) {
+ sp = usp;
+ sp->updates++;
+ break;
+ }
+ usp++;
+ }
+ }
+ }
+ }
+
+ secs = time_second;
+
+ st->pfsync_time = time_uptime;
+
+ if (sp == NULL) {
+ /* not a "duplicate" update */
+ i = 255;
+ sp = sc->sc_statep.s++;
+ sc->sc_mbuf->m_pkthdr.len =
+ sc->sc_mbuf->m_len += sizeof(struct pfsync_state);
+ h->count++;
+ bzero(sp, sizeof(*sp));
+
+ bcopy(&st->id, sp->id, sizeof(sp->id));
+ sp->creatorid = st->creatorid;
+
+ strlcpy(sp->ifname, st->u.s.kif->pfik_name, sizeof(sp->ifname));
+ pf_state_host_hton(&st->lan, &sp->lan);
+ pf_state_host_hton(&st->gwy, &sp->gwy);
+ pf_state_host_hton(&st->ext, &sp->ext);
+
+ bcopy(&st->rt_addr, &sp->rt_addr, sizeof(sp->rt_addr));
+
+ sp->creation = htonl(secs - st->creation);
+ pf_state_counter_hton(st->packets[0], sp->packets[0]);
+ pf_state_counter_hton(st->packets[1], sp->packets[1]);
+ pf_state_counter_hton(st->bytes[0], sp->bytes[0]);
+ pf_state_counter_hton(st->bytes[1], sp->bytes[1]);
+ if ((r = st->rule.ptr) == NULL)
+ sp->rule = htonl(-1);
+ else
+ sp->rule = htonl(r->nr);
+ if ((r = st->anchor.ptr) == NULL)
+ sp->anchor = htonl(-1);
+ else
+ sp->anchor = htonl(r->nr);
+ sp->af = st->af;
+ sp->proto = st->proto;
+ sp->direction = st->direction;
+ sp->log = st->log;
+ sp->state_flags = st->state_flags;
+ sp->timeout = st->timeout;
+
+ if (flags & PFSYNC_FLAG_STALE)
+ sp->sync_flags |= PFSTATE_STALE;
+ }
+
+ pf_state_peer_hton(&st->src, &sp->src);
+ pf_state_peer_hton(&st->dst, &sp->dst);
+
+ if (st->expire <= secs)
+ sp->expire = htonl(0);
+ else
+ sp->expire = htonl(st->expire - secs);
+
+ /* do we need to build "compressed" actions for network transfer? */
+ if (sc->sc_sync_ifp && flags & PFSYNC_FLAG_COMPRESS) {
+ switch (action) {
+ case PFSYNC_ACT_UPD:
+ newaction = PFSYNC_ACT_UPD_C;
+ break;
+ case PFSYNC_ACT_DEL:
+ newaction = PFSYNC_ACT_DEL_C;
+ break;
+ default:
+ /* by default we just send the uncompressed states */
+ break;
+ }
+ }
+
+ if (newaction) {
+ if (sc->sc_mbuf_net == NULL) {
+ if ((sc->sc_mbuf_net = pfsync_get_mbuf(sc, newaction,
+ (void *)&sc->sc_statep_net.s)) == NULL) {
+ splx(s);
+ return (ENOMEM);
+ }
+ }
+ h_net = mtod(sc->sc_mbuf_net, struct pfsync_header *);
+
+ switch (newaction) {
+ case PFSYNC_ACT_UPD_C:
+ if (i != 255) {
+ up = (void *)((char *)h_net +
+ PFSYNC_HDRLEN + (i * sizeof(*up)));
+ up->updates++;
+ } else {
+ h_net->count++;
+ sc->sc_mbuf_net->m_pkthdr.len =
+ sc->sc_mbuf_net->m_len += sizeof(*up);
+ up = sc->sc_statep_net.u++;
+
+ bzero(up, sizeof(*up));
+ bcopy(&st->id, up->id, sizeof(up->id));
+ up->creatorid = st->creatorid;
+ }
+ up->timeout = st->timeout;
+ up->expire = sp->expire;
+ up->src = sp->src;
+ up->dst = sp->dst;
+ break;
+ case PFSYNC_ACT_DEL_C:
+ sc->sc_mbuf_net->m_pkthdr.len =
+ sc->sc_mbuf_net->m_len += sizeof(*dp);
+ dp = sc->sc_statep_net.d++;
+ h_net->count++;
+
+ bzero(dp, sizeof(*dp));
+ bcopy(&st->id, dp->id, sizeof(dp->id));
+ dp->creatorid = st->creatorid;
+ break;
+ }
+ }
+
+ if (h->count == sc->sc_maxcount ||
+ (sc->sc_maxupdates && (sp->updates >= sc->sc_maxupdates)))
+ ret = pfsync_sendout(sc);
+
+ splx(s);
+ return (ret);
+}
+
+/* This must be called in splnet() */
+int
+pfsync_request_update(struct pfsync_state_upd *up, struct in_addr *src)
+{
+ struct ifnet *ifp = NULL;
+ struct pfsync_header *h;
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_state_upd_req *rup;
+ int ret = 0;
+
+ if (sc == NULL)
+ return (0);
+
+#ifdef __FreeBSD__
+ ifp = sc->sc_ifp;
+#else
+ ifp = &sc->sc_if;
+#endif
+ if (sc->sc_mbuf == NULL) {
+ if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
+ (void *)&sc->sc_statep.s)) == NULL)
+ return (ENOMEM);
+ h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ } else {
+ h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ if (h->action != PFSYNC_ACT_UREQ) {
+ pfsync_sendout(sc);
+ if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_UREQ,
+ (void *)&sc->sc_statep.s)) == NULL)
+ return (ENOMEM);
+ h = mtod(sc->sc_mbuf, struct pfsync_header *);
+ }
+ }
+
+ if (src != NULL)
+ sc->sc_sendaddr = *src;
+ sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*rup);
+ h->count++;
+ rup = sc->sc_statep.r++;
+ bzero(rup, sizeof(*rup));
+ if (up != NULL) {
+ bcopy(up->id, rup->id, sizeof(rup->id));
+ rup->creatorid = up->creatorid;
+ }
+
+ if (h->count == sc->sc_maxcount)
+ ret = pfsync_sendout(sc);
+
+ return (ret);
+}
+
+int
+pfsync_clear_states(u_int32_t creatorid, char *ifname)
+{
+ struct ifnet *ifp = NULL;
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_state_clr *cp;
+ int s, ret;
+
+ if (sc == NULL)
+ return (0);
+
+#ifdef __FreeBSD__
+ ifp = sc->sc_ifp;
+#else
+ ifp = &sc->sc_if;
+#endif
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ s = splnet();
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+ if ((sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_CLR,
+ (void *)&sc->sc_statep.c)) == NULL) {
+ splx(s);
+ return (ENOMEM);
+ }
+ sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*cp);
+ cp = sc->sc_statep.c;
+ cp->creatorid = creatorid;
+ if (ifname != NULL)
+ strlcpy(cp->ifname, ifname, IFNAMSIZ);
+
+ ret = (pfsync_sendout(sc));
+ splx(s);
+ return (ret);
+}
+
+void
+pfsync_timeout(void *v)
+{
+ struct pfsync_softc *sc = v;
+ int s;
+
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ pfsync_sendout(sc);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+}
+
+#ifdef PFSYNC_TDB
+void
+pfsync_tdb_timeout(void *v)
+{
+ struct pfsync_softc *sc = v;
+ int s;
+
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ pfsync_tdb_sendout(sc);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ splx(s);
+}
+#endif
+
+/* This must be called in splnet() */
+void
+pfsync_send_bus(struct pfsync_softc *sc, u_int8_t status)
+{
+ struct pfsync_state_bus *bus;
+
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+
+ if (pfsync_sync_ok &&
+ (sc->sc_mbuf = pfsync_get_mbuf(sc, PFSYNC_ACT_BUS,
+ (void *)&sc->sc_statep.b)) != NULL) {
+ sc->sc_mbuf->m_pkthdr.len = sc->sc_mbuf->m_len += sizeof(*bus);
+ bus = sc->sc_statep.b;
+ bus->creatorid = pf_status.hostid;
+ bus->status = status;
+ bus->endtime = htonl(time_uptime - sc->sc_ureq_received);
+ pfsync_sendout(sc);
+ }
+}
+
+void
+pfsync_bulk_update(void *v)
+{
+ struct pfsync_softc *sc = v;
+ int s, i = 0;
+ struct pf_state *state;
+
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+
+ /*
+ * Grab at most PFSYNC_BULKPACKETS worth of states which have not
+ * been sent since the latest request was made.
+ */
+ state = sc->sc_bulk_send_next;
+ if (state)
+ do {
+ /* send state update if syncable and not already sent */
+ if (!state->sync_flags
+ && state->timeout < PFTM_MAX
+ && state->pfsync_time <= sc->sc_ureq_received) {
+ pfsync_pack_state(PFSYNC_ACT_UPD, state, 0);
+ i++;
+ }
+
+ /* figure next state to send */
+ state = TAILQ_NEXT(state, u.s.entry_list);
+
+ /* wrap to start of list if we hit the end */
+ if (!state)
+ state = TAILQ_FIRST(&state_list);
+ } while (i < sc->sc_maxcount * PFSYNC_BULKPACKETS &&
+ state != sc->sc_bulk_terminator);
+
+ if (!state || state == sc->sc_bulk_terminator) {
+ /* we're done */
+ pfsync_send_bus(sc, PFSYNC_BUS_END);
+ sc->sc_ureq_received = 0;
+ sc->sc_bulk_send_next = NULL;
+ sc->sc_bulk_terminator = NULL;
+ timeout_del(&sc->sc_bulk_tmo);
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: bulk update complete\n");
+ } else {
+ /* look again for more in a bit */
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_bulk_tmo, 1, pfsync_bulk_update,
+ pfsyncif);
+#else
+ timeout_add(&sc->sc_bulk_tmo, 1);
+#endif
+ sc->sc_bulk_send_next = state;
+ }
+ if (sc->sc_mbuf != NULL)
+ pfsync_sendout(sc);
+ splx(s);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+}
+
+void
+pfsync_bulkfail(void *v)
+{
+ struct pfsync_softc *sc = v;
+ int s, error;
+
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (sc->sc_bulk_tries++ < PFSYNC_MAX_BULKTRIES) {
+ /* Try again in a bit */
+#ifdef __FreeBSD__
+ callout_reset(&sc->sc_bulkfail_tmo, 5 * hz, pfsync_bulkfail,
+ pfsyncif);
+#else
+ timeout_add(&sc->sc_bulkfail_tmo, 5 * hz);
+#endif
+ s = splnet();
+ error = pfsync_request_update(NULL, NULL);
+ if (error == ENOMEM) {
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: cannot allocate mbufs for "
+ "bulk update\n");
+ } else
+ pfsync_sendout(sc);
+ splx(s);
+ } else {
+ /* Pretend like the transfer was ok */
+ sc->sc_ureq_sent = 0;
+ sc->sc_bulk_tries = 0;
+#if NCARP > 0
+ if (!pfsync_sync_ok)
+#ifdef __FreeBSD__
+#ifdef CARP_ADVANCED
+ carp_group_demote_adj(sc->sc_ifp, -1);
+#endif
+#else
+ carp_group_demote_adj(&sc->sc_if, -1);
+#endif
+#endif
+ pfsync_sync_ok = 1;
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync: failed to receive "
+ "bulk update status\n");
+ timeout_del(&sc->sc_bulkfail_tmo);
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+}
+
+/* This must be called in splnet() */
+int
+pfsync_sendout(struct pfsync_softc *sc)
+{
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+ struct ifnet *ifp = sc->sc_ifp;
+#else
+ struct ifnet *ifp = &sc->sc_if;
+#endif
+#endif
+ struct mbuf *m;
+
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ timeout_del(&sc->sc_tmo);
+
+ if (sc->sc_mbuf == NULL)
+ return (0);
+ m = sc->sc_mbuf;
+ sc->sc_mbuf = NULL;
+ sc->sc_statep.s = NULL;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+#ifdef __FreeBSD__
+ BPF_MTAP(ifp, m);
+#else
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+#endif
+
+ if (sc->sc_mbuf_net) {
+ m_freem(m);
+ m = sc->sc_mbuf_net;
+ sc->sc_mbuf_net = NULL;
+ sc->sc_statep_net.s = NULL;
+ }
+
+ return pfsync_sendout_mbuf(sc, m);
+}
+
+#ifdef PFSYNC_TDB
+int
+pfsync_tdb_sendout(struct pfsync_softc *sc)
+{
+#if NBPFILTER > 0
+#ifdef __FreeBSD__
+ struct ifnet *ifp = sc->sc_ifp;
+#else
+ struct ifnet *ifp = &sc->sc_if;
+#endif
+#endif
+ struct mbuf *m;
+
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ timeout_del(&sc->sc_tdb_tmo);
+
+ if (sc->sc_mbuf_tdb == NULL)
+ return (0);
+ m = sc->sc_mbuf_tdb;
+ sc->sc_mbuf_tdb = NULL;
+ sc->sc_statep_tdb.t = NULL;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+#ifdef __FreeBSD__
+ BPF_MTAP(ifp, m);
+#else
+ bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+#endif
+#endif
+
+ return pfsync_sendout_mbuf(sc, m);
+}
+#endif
+
+int
+pfsync_sendout_mbuf(struct pfsync_softc *sc, struct mbuf *m)
+{
+ struct sockaddr sa;
+ struct ip *ip;
+
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ if (sc->sc_sync_ifp ||
+#ifdef __FreeBSD__
+ sc->sc_sync_peer.s_addr != htonl(INADDR_PFSYNC_GROUP)) {
+#else
+ sc->sc_sync_peer.s_addr != INADDR_PFSYNC_GROUP) {
+#endif
+ M_PREPEND(m, sizeof(struct ip), M_DONTWAIT);
+ if (m == NULL) {
+ pfsyncstats.pfsyncs_onomem++;
+ return (0);
+ }
+ ip = mtod(m, struct ip *);
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = sizeof(*ip) >> 2;
+ ip->ip_tos = IPTOS_LOWDELAY;
+#ifdef __FreeBSD__
+ ip->ip_len = m->m_pkthdr.len;
+#else
+ ip->ip_len = htons(m->m_pkthdr.len);
+#endif
+ ip->ip_id = htons(ip_randomid());
+#ifdef __FreeBSD__
+ ip->ip_off = IP_DF;
+#else
+ ip->ip_off = htons(IP_DF);
+#endif
+ ip->ip_ttl = PFSYNC_DFLTTL;
+ ip->ip_p = IPPROTO_PFSYNC;
+ ip->ip_sum = 0;
+
+ bzero(&sa, sizeof(sa));
+ ip->ip_src.s_addr = INADDR_ANY;
+
+#ifdef __FreeBSD__
+ if (sc->sc_sendaddr.s_addr == htonl(INADDR_PFSYNC_GROUP))
+#else
+ if (sc->sc_sendaddr.s_addr == INADDR_PFSYNC_GROUP)
+#endif
+ m->m_flags |= M_MCAST;
+ ip->ip_dst = sc->sc_sendaddr;
+ sc->sc_sendaddr.s_addr = sc->sc_sync_peer.s_addr;
+
+ pfsyncstats.pfsyncs_opackets++;
+
+#ifdef __FreeBSD__
+ if (!IF_HANDOFF(&sc->sc_ifq, m, NULL))
+ pfsyncstats.pfsyncs_oerrors++;
+ taskqueue_enqueue(taskqueue_thread, &pfsyncif->sc_send_task);
+#else
+ if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
+ pfsyncstats.pfsyncs_oerrors++;
+#endif
+ } else
+ m_freem(m);
+
+ return (0);
+}
+
+#ifdef PFSYNC_TDB
+/* Update an in-kernel tdb. Silently fail if no tdb is found. */
+void
+pfsync_update_net_tdb(struct pfsync_tdb *pt)
+{
+ struct tdb *tdb;
+ int s;
+
+ /* check for invalid values */
+ if (ntohl(pt->spi) <= SPI_RESERVED_MAX ||
+ (pt->dst.sa.sa_family != AF_INET &&
+ pt->dst.sa.sa_family != AF_INET6))
+ goto bad;
+
+ s = spltdb();
+ tdb = gettdb(pt->spi, &pt->dst, pt->sproto);
+ if (tdb) {
+ pt->rpl = ntohl(pt->rpl);
+ pt->cur_bytes = betoh64(pt->cur_bytes);
+
+ /* Neither replay nor byte counter should ever decrease. */
+ if (pt->rpl < tdb->tdb_rpl ||
+ pt->cur_bytes < tdb->tdb_cur_bytes) {
+ splx(s);
+ goto bad;
+ }
+
+ tdb->tdb_rpl = pt->rpl;
+ tdb->tdb_cur_bytes = pt->cur_bytes;
+ }
+ splx(s);
+ return;
+
+ bad:
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("pfsync_insert: PFSYNC_ACT_TDB_UPD: "
+ "invalid value\n");
+ pfsyncstats.pfsyncs_badstate++;
+ return;
+}
+
+/* One of our local tdbs have been updated, need to sync rpl with others */
+int
+pfsync_update_tdb(struct tdb *tdb, int output)
+{
+ struct ifnet *ifp = NULL;
+ struct pfsync_softc *sc = pfsyncif;
+ struct pfsync_header *h;
+ struct pfsync_tdb *pt = NULL;
+ int s, i, ret;
+
+ if (sc == NULL)
+ return (0);
+
+#ifdef __FreeBSD__
+ ifp = sc->sc_ifp;
+#else
+ ifp = &sc->sc_if;
+#endif
+ if (ifp->if_bpf == NULL && sc->sc_sync_ifp == NULL &&
+#ifdef __FreeBSD__
+ sc->sc_sync_peer.s_addr == htonl(INADDR_PFSYNC_GROUP)) {
+#else
+ sc->sc_sync_peer.s_addr == INADDR_PFSYNC_GROUP) {
+#endif
+ /* Don't leave any stale pfsync packets hanging around. */
+ if (sc->sc_mbuf_tdb != NULL) {
+ m_freem(sc->sc_mbuf_tdb);
+ sc->sc_mbuf_tdb = NULL;
+ sc->sc_statep_tdb.t = NULL;
+ }
+ return (0);
+ }
+
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ s = splnet();
+ if (sc->sc_mbuf_tdb == NULL) {
+ if ((sc->sc_mbuf_tdb = pfsync_get_mbuf(sc, PFSYNC_ACT_TDB_UPD,
+ (void *)&sc->sc_statep_tdb.t)) == NULL) {
+ splx(s);
+ return (ENOMEM);
+ }
+ h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
+ } else {
+ h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
+ if (h->action != PFSYNC_ACT_TDB_UPD) {
+ /*
+ * XXX will never happen as long as there's
+ * only one "TDB action".
+ */
+ pfsync_tdb_sendout(sc);
+ sc->sc_mbuf_tdb = pfsync_get_mbuf(sc,
+ PFSYNC_ACT_TDB_UPD, (void *)&sc->sc_statep_tdb.t);
+ if (sc->sc_mbuf_tdb == NULL) {
+ splx(s);
+ return (ENOMEM);
+ }
+ h = mtod(sc->sc_mbuf_tdb, struct pfsync_header *);
+ } else if (sc->sc_maxupdates) {
+ /*
+ * If it's an update, look in the packet to see if
+ * we already have an update for the state.
+ */
+ struct pfsync_tdb *u =
+ (void *)((char *)h + PFSYNC_HDRLEN);
+
+ for (i = 0; !pt && i < h->count; i++) {
+ if (tdb->tdb_spi == u->spi &&
+ tdb->tdb_sproto == u->sproto &&
+ !bcmp(&tdb->tdb_dst, &u->dst,
+ SA_LEN(&u->dst.sa))) {
+ pt = u;
+ pt->updates++;
+ }
+ u++;
+ }
+ }
+ }
+
+ if (pt == NULL) {
+ /* not a "duplicate" update */
+ pt = sc->sc_statep_tdb.t++;
+ sc->sc_mbuf_tdb->m_pkthdr.len =
+ sc->sc_mbuf_tdb->m_len += sizeof(struct pfsync_tdb);
+ h->count++;
+ bzero(pt, sizeof(*pt));
+
+ pt->spi = tdb->tdb_spi;
+ memcpy(&pt->dst, &tdb->tdb_dst, sizeof pt->dst);
+ pt->sproto = tdb->tdb_sproto;
+ }
+
+ /*
+ * When a failover happens, the master's rpl is probably above
+ * what we see here (we may be up to a second late), so
+ * increase it a bit for outbound tdbs to manage most such
+ * situations.
+ *
+ * For now, just add an offset that is likely to be larger
+ * than the number of packets we can see in one second. The RFC
+ * just says the next packet must have a higher seq value.
+ *
+ * XXX What is a good algorithm for this? We could use
+ * a rate-determined increase, but to know it, we would have
+ * to extend struct tdb.
+ * XXX pt->rpl can wrap over MAXINT, but if so the real tdb
+ * will soon be replaced anyway. For now, just don't handle
+ * this edge case.
+ */
+#define RPL_INCR 16384
+ pt->rpl = htonl(tdb->tdb_rpl + (output ? RPL_INCR : 0));
+ pt->cur_bytes = htobe64(tdb->tdb_cur_bytes);
+
+ if (h->count == sc->sc_maxcount ||
+ (sc->sc_maxupdates && (pt->updates >= sc->sc_maxupdates)))
+ ret = pfsync_tdb_sendout(sc);
+
+ splx(s);
+ return (ret);
+}
+#endif /* PFSYNC_TDB */
+
+#ifdef __FreeBSD__
+void
+pfsync_ifdetach(void *arg, struct ifnet *ifp)
+{
+ struct pfsync_softc *sc = (struct pfsync_softc *)arg;
+ struct ip_moptions *imo;
+
+ if (sc == NULL || sc->sc_sync_ifp != ifp)
+ return; /* not for us; unlocked read */
+
+ PF_LOCK();
+
+ /* Deal with a member interface going away from under us. */
+ sc->sc_sync_ifp = NULL;
+ if (sc->sc_mbuf_net != NULL) {
+ m_freem(sc->sc_mbuf_net);
+ sc->sc_mbuf_net = NULL;
+ sc->sc_statep_net.s = NULL;
+ }
+ imo = &sc->sc_imo;
+ if (imo->imo_num_memberships > 0) {
+ KASSERT(imo->imo_num_memberships == 1,
+ ("%s: imo_num_memberships != 1", __func__));
+ /*
+ * Our event handler is always called after protocol
+ * domains have been detached from the underlying ifnet.
+ * Do not call in_delmulti(); we held a single reference
+ * which the protocol domain has purged in in_purgemaddrs().
+ */
+ PF_UNLOCK();
+ imo->imo_membership[--imo->imo_num_memberships] = NULL;
+ PF_LOCK();
+ imo->imo_multicast_ifp = NULL;
+ }
+
+ PF_UNLOCK();
+}
+
+void
+pfsync_senddef(void *arg, __unused int pending)
+{
+ struct pfsync_softc *sc = (struct pfsync_softc *)arg;
+ struct mbuf *m;
+
+ for(;;) {
+ IF_DEQUEUE(&sc->sc_ifq, m);
+ if (m == NULL)
+ break;
+ /* Deal with a member interface going away from under us. */
+ if (sc->sc_sync_ifp == NULL) {
+ pfsyncstats.pfsyncs_oerrors++;
+ m_freem(m);
+ continue;
+ }
+ if (ip_output(m, NULL, NULL, IP_RAWOUTPUT, &sc->sc_imo, NULL))
+ pfsyncstats.pfsyncs_oerrors++;
+ }
+}
+
+static int
+pfsync_modevent(module_t mod, int type, void *data)
+{
+ int error = 0;
+
+ switch (type) {
+ case MOD_LOAD:
+ pfsyncattach(0);
+ break;
+ case MOD_UNLOAD:
+ if_clone_detach(&pfsync_cloner);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return error;
+}
+
+static moduledata_t pfsync_mod = {
+ "pfsync",
+ pfsync_modevent,
+ 0
+};
+
+#define PFSYNC_MODVER 1
+
+DECLARE_MODULE(pfsync, pfsync_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+MODULE_VERSION(pfsync, PFSYNC_MODVER);
+MODULE_DEPEND(pflog, pf, PF_MODVER, PF_MODVER, PF_MODVER);
+#endif /* __FreeBSD__ */
diff --git a/freebsd/sys/contrib/pf/net/if_pfsync.h b/freebsd/sys/contrib/pf/net/if_pfsync.h
new file mode 100644
index 00000000..e3e6caf9
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/if_pfsync.h
@@ -0,0 +1,375 @@
+/* $FreeBSD$ */
+/* $OpenBSD: if_pfsync.h,v 1.30 2006/10/31 14:49:01 henning Exp $ */
+
+/*
+ * Copyright (c) 2001 Michael Shalayeff
+ * 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.
+ */
+
+#ifndef _NET_IF_PFSYNC_HH_
+#define _NET_IF_PFSYNC_HH_
+
+
+#define PFSYNC_ID_LEN sizeof(u_int64_t)
+
+struct pfsync_state_scrub {
+ u_int16_t pfss_flags;
+ u_int8_t pfss_ttl; /* stashed TTL */
+#define PFSYNC_SCRUB_FLAG_VALID 0x01
+ u_int8_t scrub_flag;
+ u_int32_t pfss_ts_mod; /* timestamp modulation */
+} __packed;
+
+struct pfsync_state_host {
+ struct pf_addr addr;
+ u_int16_t port;
+ u_int16_t pad[3];
+} __packed;
+
+struct pfsync_state_peer {
+ struct pfsync_state_scrub scrub; /* state is scrubbed */
+ u_int32_t seqlo; /* Max sequence number sent */
+ u_int32_t seqhi; /* Max the other end ACKd + win */
+ u_int32_t seqdiff; /* Sequence number modulator */
+ u_int16_t max_win; /* largest window (pre scaling) */
+ u_int16_t mss; /* Maximum segment size option */
+ u_int8_t state; /* active state level */
+ u_int8_t wscale; /* window scaling factor */
+ u_int8_t pad[6];
+} __packed;
+
+struct pfsync_state {
+ u_int32_t id[2];
+ char ifname[IFNAMSIZ];
+ struct pfsync_state_host lan;
+ struct pfsync_state_host gwy;
+ struct pfsync_state_host ext;
+ struct pfsync_state_peer src;
+ struct pfsync_state_peer dst;
+ struct pf_addr rt_addr;
+ u_int32_t rule;
+ u_int32_t anchor;
+ u_int32_t nat_rule;
+ u_int32_t creation;
+ u_int32_t expire;
+ u_int32_t packets[2][2];
+ u_int32_t bytes[2][2];
+ u_int32_t creatorid;
+ sa_family_t af;
+ u_int8_t proto;
+ u_int8_t direction;
+ u_int8_t log;
+ u_int8_t state_flags;
+ u_int8_t timeout;
+ u_int8_t sync_flags;
+ u_int8_t updates;
+} __packed;
+
+#define PFSYNC_FLAG_COMPRESS 0x01
+#define PFSYNC_FLAG_STALE 0x02
+
+#ifdef PFSYNC_TDB
+struct pfsync_tdb {
+ u_int32_t spi;
+ union sockaddr_union dst;
+ u_int32_t rpl;
+ u_int64_t cur_bytes;
+ u_int8_t sproto;
+ u_int8_t updates;
+ u_int8_t pad[2];
+} __packed;
+#endif
+
+struct pfsync_state_upd {
+ u_int32_t id[2];
+ struct pfsync_state_peer src;
+ struct pfsync_state_peer dst;
+ u_int32_t creatorid;
+ u_int32_t expire;
+ u_int8_t timeout;
+ u_int8_t updates;
+ u_int8_t pad[6];
+} __packed;
+
+struct pfsync_state_del {
+ u_int32_t id[2];
+ u_int32_t creatorid;
+ struct {
+ u_int8_t state;
+ } src;
+ struct {
+ u_int8_t state;
+ } dst;
+ u_int8_t pad[2];
+} __packed;
+
+struct pfsync_state_upd_req {
+ u_int32_t id[2];
+ u_int32_t creatorid;
+ u_int32_t pad;
+} __packed;
+
+struct pfsync_state_clr {
+ char ifname[IFNAMSIZ];
+ u_int32_t creatorid;
+ u_int32_t pad;
+} __packed;
+
+struct pfsync_state_bus {
+ u_int32_t creatorid;
+ u_int32_t endtime;
+ u_int8_t status;
+#define PFSYNC_BUS_START 1
+#define PFSYNC_BUS_END 2
+ u_int8_t pad[7];
+} __packed;
+
+#ifdef _KERNEL
+
+union sc_statep {
+ struct pfsync_state *s;
+ struct pfsync_state_upd *u;
+ struct pfsync_state_del *d;
+ struct pfsync_state_clr *c;
+ struct pfsync_state_bus *b;
+ struct pfsync_state_upd_req *r;
+};
+
+#ifdef PFSYNC_TDB
+union sc_tdb_statep {
+ struct pfsync_tdb *t;
+};
+#endif
+
+extern int pfsync_sync_ok;
+
+struct pfsync_softc {
+#ifdef __FreeBSD__
+ struct ifnet *sc_ifp;
+#else
+ struct ifnet sc_if;
+#endif
+ struct ifnet *sc_sync_ifp;
+
+ struct ip_moptions sc_imo;
+#ifdef __FreeBSD__
+ struct callout sc_tmo;
+#ifdef PFSYNC_TDB
+ struct callout sc_tdb_tmo;
+#endif
+ struct callout sc_bulk_tmo;
+ struct callout sc_bulkfail_tmo;
+#else
+ struct timeout sc_tmo;
+ struct timeout sc_tdb_tmo;
+ struct timeout sc_bulk_tmo;
+ struct timeout sc_bulkfail_tmo;
+#endif
+ struct in_addr sc_sync_peer;
+ struct in_addr sc_sendaddr;
+ struct mbuf *sc_mbuf; /* current cumulative mbuf */
+ struct mbuf *sc_mbuf_net; /* current cumulative mbuf */
+#ifdef PFSYNC_TDB
+ struct mbuf *sc_mbuf_tdb; /* dito for TDB updates */
+#endif
+#ifdef __FreeBSD__
+ struct ifqueue sc_ifq;
+ struct task sc_send_task;
+#endif
+ union sc_statep sc_statep;
+ union sc_statep sc_statep_net;
+#ifdef PFSYNC_TDB
+ union sc_tdb_statep sc_statep_tdb;
+#endif
+ u_int32_t sc_ureq_received;
+ u_int32_t sc_ureq_sent;
+ struct pf_state *sc_bulk_send_next;
+ struct pf_state *sc_bulk_terminator;
+ int sc_bulk_tries;
+ int sc_maxcount; /* number of states in mtu */
+ int sc_maxupdates; /* number of updates/state */
+#ifdef __FreeBSD__
+ eventhandler_tag sc_detachtag;
+#endif
+};
+
+extern struct pfsync_softc *pfsyncif;
+#endif
+
+
+struct pfsync_header {
+ u_int8_t version;
+#define PFSYNC_VERSION 3
+ u_int8_t af;
+ u_int8_t action;
+#define PFSYNC_ACT_CLR 0 /* clear all states */
+#define PFSYNC_ACT_INS 1 /* insert state */
+#define PFSYNC_ACT_UPD 2 /* update state */
+#define PFSYNC_ACT_DEL 3 /* delete state */
+#define PFSYNC_ACT_UPD_C 4 /* "compressed" state update */
+#define PFSYNC_ACT_DEL_C 5 /* "compressed" state delete */
+#define PFSYNC_ACT_INS_F 6 /* insert fragment */
+#define PFSYNC_ACT_DEL_F 7 /* delete fragments */
+#define PFSYNC_ACT_UREQ 8 /* request "uncompressed" state */
+#define PFSYNC_ACT_BUS 9 /* Bulk Update Status */
+#define PFSYNC_ACT_TDB_UPD 10 /* TDB replay counter update */
+#define PFSYNC_ACT_MAX 11
+ u_int8_t count;
+ u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
+} __packed;
+
+#define PFSYNC_BULKPACKETS 1 /* # of packets per timeout */
+#define PFSYNC_MAX_BULKTRIES 12
+#define PFSYNC_HDRLEN sizeof(struct pfsync_header)
+#define PFSYNC_ACTIONS \
+ "CLR ST", "INS ST", "UPD ST", "DEL ST", \
+ "UPD ST COMP", "DEL ST COMP", "INS FR", "DEL FR", \
+ "UPD REQ", "BLK UPD STAT", "TDB UPD"
+
+#define PFSYNC_DFLTTL 255
+
+struct pfsyncstats {
+ u_int64_t pfsyncs_ipackets; /* total input packets, IPv4 */
+ u_int64_t pfsyncs_ipackets6; /* total input packets, IPv6 */
+ u_int64_t pfsyncs_badif; /* not the right interface */
+ u_int64_t pfsyncs_badttl; /* TTL is not PFSYNC_DFLTTL */
+ u_int64_t pfsyncs_hdrops; /* packets shorter than hdr */
+ u_int64_t pfsyncs_badver; /* bad (incl unsupp) version */
+ u_int64_t pfsyncs_badact; /* bad action */
+ u_int64_t pfsyncs_badlen; /* data length does not match */
+ u_int64_t pfsyncs_badauth; /* bad authentication */
+ u_int64_t pfsyncs_stale; /* stale state */
+ u_int64_t pfsyncs_badval; /* bad values */
+ u_int64_t pfsyncs_badstate; /* insert/lookup failed */
+
+ u_int64_t pfsyncs_opackets; /* total output packets, IPv4 */
+ u_int64_t pfsyncs_opackets6; /* total output packets, IPv6 */
+ u_int64_t pfsyncs_onomem; /* no memory for an mbuf */
+ u_int64_t pfsyncs_oerrors; /* ip output error */
+};
+
+/*
+ * Configuration structure for SIOCSETPFSYNC SIOCGETPFSYNC
+ */
+struct pfsyncreq {
+ char pfsyncr_syncdev[IFNAMSIZ];
+ struct in_addr pfsyncr_syncpeer;
+ int pfsyncr_maxupdates;
+ int pfsyncr_authlevel;
+};
+
+#ifdef __FreeBSD__
+#define SIOCSETPFSYNC _IOW('i', 247, struct ifreq)
+#define SIOCGETPFSYNC _IOWR('i', 248, struct ifreq)
+#endif
+
+#define pf_state_peer_hton(s,d) do { \
+ (d)->seqlo = htonl((s)->seqlo); \
+ (d)->seqhi = htonl((s)->seqhi); \
+ (d)->seqdiff = htonl((s)->seqdiff); \
+ (d)->max_win = htons((s)->max_win); \
+ (d)->mss = htons((s)->mss); \
+ (d)->state = (s)->state; \
+ (d)->wscale = (s)->wscale; \
+ if ((s)->scrub) { \
+ (d)->scrub.pfss_flags = \
+ htons((s)->scrub->pfss_flags & PFSS_TIMESTAMP); \
+ (d)->scrub.pfss_ttl = (s)->scrub->pfss_ttl; \
+ (d)->scrub.pfss_ts_mod = htonl((s)->scrub->pfss_ts_mod);\
+ (d)->scrub.scrub_flag = PFSYNC_SCRUB_FLAG_VALID; \
+ } \
+} while (0)
+
+#define pf_state_peer_ntoh(s,d) do { \
+ (d)->seqlo = ntohl((s)->seqlo); \
+ (d)->seqhi = ntohl((s)->seqhi); \
+ (d)->seqdiff = ntohl((s)->seqdiff); \
+ (d)->max_win = ntohs((s)->max_win); \
+ (d)->mss = ntohs((s)->mss); \
+ (d)->state = (s)->state; \
+ (d)->wscale = (s)->wscale; \
+ if ((s)->scrub.scrub_flag == PFSYNC_SCRUB_FLAG_VALID && \
+ (d)->scrub != NULL) { \
+ (d)->scrub->pfss_flags = \
+ ntohs((s)->scrub.pfss_flags) & PFSS_TIMESTAMP; \
+ (d)->scrub->pfss_ttl = (s)->scrub.pfss_ttl; \
+ (d)->scrub->pfss_ts_mod = ntohl((s)->scrub.pfss_ts_mod);\
+ } \
+} while (0)
+
+#define pf_state_host_hton(s,d) do { \
+ bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
+ (d)->port = (s)->port; \
+} while (0)
+
+#define pf_state_host_ntoh(s,d) do { \
+ bcopy(&(s)->addr, &(d)->addr, sizeof((d)->addr)); \
+ (d)->port = (s)->port; \
+} while (0)
+
+#define pf_state_counter_hton(s,d) do { \
+ d[0] = htonl((s>>32)&0xffffffff); \
+ d[1] = htonl(s&0xffffffff); \
+} while (0)
+
+#define pf_state_counter_ntoh(s,d) do { \
+ d = ntohl(s[0]); \
+ d = d<<32; \
+ d += ntohl(s[1]); \
+} while (0)
+
+#ifdef _KERNEL
+#ifdef __FreeBSD__
+void pfsync_input(struct mbuf *, __unused int);
+#else
+void pfsync_input(struct mbuf *, ...);
+#endif
+int pfsync_clear_states(u_int32_t, char *);
+int pfsync_pack_state(u_int8_t, struct pf_state *, int);
+#define pfsync_insert_state(st) do { \
+ if ((st->rule.ptr->rule_flag & PFRULE_NOSYNC) || \
+ (st->proto == IPPROTO_PFSYNC)) \
+ st->sync_flags |= PFSTATE_NOSYNC; \
+ else if (!st->sync_flags) \
+ pfsync_pack_state(PFSYNC_ACT_INS, (st), \
+ PFSYNC_FLAG_COMPRESS); \
+ st->sync_flags &= ~PFSTATE_FROMSYNC; \
+} while (0)
+#define pfsync_update_state(st) do { \
+ if (!st->sync_flags) \
+ pfsync_pack_state(PFSYNC_ACT_UPD, (st), \
+ PFSYNC_FLAG_COMPRESS); \
+ st->sync_flags &= ~PFSTATE_FROMSYNC; \
+} while (0)
+#define pfsync_delete_state(st) do { \
+ if (!st->sync_flags) \
+ pfsync_pack_state(PFSYNC_ACT_DEL, (st), \
+ PFSYNC_FLAG_COMPRESS); \
+} while (0)
+#ifdef PFSYNC_TDB
+int pfsync_update_tdb(struct tdb *, int);
+#endif
+#endif
+
+#endif /* _NET_IF_PFSYNC_HH_ */
diff --git a/freebsd/sys/contrib/pf/net/pf.c b/freebsd/sys/contrib/pf/net/pf.c
new file mode 100644
index 00000000..4ac395f1
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf.c
@@ -0,0 +1,7771 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: pf.c,v 1.527 2007/02/22 15:23:23 pyr Exp $ */
+/* add: $OpenBSD: pf.c,v 1.559 2007/09/18 18:45:59 markus Exp $ */
+
+/*
+ * Copyright (c) 2001 Daniel Hartmeier
+ * Copyright (c) 2002,2003 Henning Brauer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_bpf.h>
+#include <freebsd/local/opt_pf.h>
+
+#ifdef DEV_BPF
+#define NBPFILTER DEV_BPF
+#else
+#define NBPFILTER 0
+#endif
+
+#ifdef DEV_PFLOG
+#define NPFLOG DEV_PFLOG
+#else
+#define NPFLOG 0
+#endif
+
+#ifdef DEV_PFSYNC
+#define NPFSYNC DEV_PFSYNC
+#else
+#define NPFSYNC 0
+#endif
+
+#else
+#include <freebsd/local/bpfilter.h>
+#include <freebsd/local/pflog.h>
+#include <freebsd/local/pfsync.h>
+#endif
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/filio.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/socketvar.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/time.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/sysctl.h>
+#include <freebsd/sys/endian.h>
+#else
+#include <freebsd/sys/pool.h>
+#endif
+#include <freebsd/sys/proc.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/kthread.h>
+#include <freebsd/sys/lock.h>
+#include <freebsd/sys/sx.h>
+#else
+#include <freebsd/sys/rwlock.h>
+#endif
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/if_types.h>
+#include <freebsd/net/bpf.h>
+#include <freebsd/net/route.h>
+#ifndef __FreeBSD__
+#include <freebsd/net/radix_mpath.h>
+#endif
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_var.h>
+#include <freebsd/netinet/tcp.h>
+#include <freebsd/netinet/tcp_seq.h>
+#include <freebsd/netinet/udp.h>
+#include <freebsd/netinet/ip_icmp.h>
+#include <freebsd/netinet/in_pcb.h>
+#include <freebsd/netinet/tcp_timer.h>
+#include <freebsd/netinet/tcp_var.h>
+#include <freebsd/netinet/udp_var.h>
+#include <freebsd/netinet/icmp_var.h>
+#include <freebsd/netinet/if_ether.h>
+
+#ifndef __FreeBSD__
+#include <freebsd/dev/rndvar.h>
+#endif
+#include <freebsd/net/pfvar.h>
+#include <freebsd/net/if_pflog.h>
+
+#if NPFSYNC > 0
+#include <freebsd/net/if_pfsync.h>
+#endif /* NPFSYNC > 0 */
+
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#include <freebsd/netinet/in_pcb.h>
+#include <freebsd/netinet/icmp6.h>
+#include <freebsd/netinet6/nd6.h>
+#ifdef __FreeBSD__
+#include <freebsd/netinet6/ip6_var.h>
+#include <freebsd/netinet6/in6_pcb.h>
+#endif
+#endif /* INET6 */
+
+#ifdef __FreeBSD__
+#include <freebsd/machine/in_cksum.h>
+#include <freebsd/sys/limits.h>
+#include <freebsd/sys/ucred.h>
+#include <freebsd/security/mac/mac_framework.h>
+
+extern int ip_optcopy(struct ip *, struct ip *);
+extern int debug_pfugidhack;
+#endif
+
+#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
+
+/*
+ * Global variables
+ */
+
+struct pf_altqqueue pf_altqs[2];
+struct pf_palist pf_pabuf;
+struct pf_altqqueue *pf_altqs_active;
+struct pf_altqqueue *pf_altqs_inactive;
+struct pf_status pf_status;
+
+u_int32_t ticket_altqs_active;
+u_int32_t ticket_altqs_inactive;
+int altqs_inactive_open;
+u_int32_t ticket_pabuf;
+
+struct pf_anchor_stackframe {
+ struct pf_ruleset *rs;
+ struct pf_rule *r;
+ struct pf_anchor_node *parent;
+ struct pf_anchor *child;
+} pf_anchor_stack[64];
+
+#ifdef __FreeBSD__
+uma_zone_t pf_src_tree_pl, pf_rule_pl;
+uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+#else
+struct pool pf_src_tree_pl, pf_rule_pl;
+struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+#endif
+
+void pf_print_host(struct pf_addr *, u_int16_t, u_int8_t);
+
+void pf_init_threshold(struct pf_threshold *, u_int32_t,
+ u_int32_t);
+void pf_add_threshold(struct pf_threshold *);
+int pf_check_threshold(struct pf_threshold *);
+
+void pf_change_ap(struct pf_addr *, u_int16_t *,
+ u_int16_t *, u_int16_t *, struct pf_addr *,
+ u_int16_t, u_int8_t, sa_family_t);
+int pf_modulate_sack(struct mbuf *, int, struct pf_pdesc *,
+ struct tcphdr *, struct pf_state_peer *);
+#ifdef INET6
+void pf_change_a6(struct pf_addr *, u_int16_t *,
+ struct pf_addr *, u_int8_t);
+#endif /* INET6 */
+void pf_change_icmp(struct pf_addr *, u_int16_t *,
+ struct pf_addr *, struct pf_addr *, u_int16_t,
+ u_int16_t *, u_int16_t *, u_int16_t *,
+ u_int16_t *, u_int8_t, sa_family_t);
+#ifdef __FreeBSD__
+void pf_send_tcp(struct mbuf *,
+ const struct pf_rule *, sa_family_t,
+#else
+void pf_send_tcp(const struct pf_rule *, sa_family_t,
+#endif
+ const struct pf_addr *, const struct pf_addr *,
+ u_int16_t, u_int16_t, u_int32_t, u_int32_t,
+ u_int8_t, u_int16_t, u_int16_t, u_int8_t, int,
+ u_int16_t, struct ether_header *, struct ifnet *);
+void pf_send_icmp(struct mbuf *, u_int8_t, u_int8_t,
+ sa_family_t, struct pf_rule *);
+struct pf_rule *pf_match_translation(struct pf_pdesc *, struct mbuf *,
+ int, int, struct pfi_kif *,
+ struct pf_addr *, u_int16_t, struct pf_addr *,
+ u_int16_t, int);
+struct pf_rule *pf_get_translation(struct pf_pdesc *, struct mbuf *,
+ int, int, struct pfi_kif *, struct pf_src_node **,
+ struct pf_addr *, u_int16_t,
+ struct pf_addr *, u_int16_t,
+ struct pf_addr *, u_int16_t *);
+int pf_test_tcp(struct pf_rule **, struct pf_state **,
+ int, struct pfi_kif *, struct mbuf *, int,
+ void *, struct pf_pdesc *, struct pf_rule **,
+#ifdef __FreeBSD__
+ struct pf_ruleset **, struct ifqueue *,
+ struct inpcb *);
+#else
+ struct pf_ruleset **, struct ifqueue *);
+#endif
+int pf_test_udp(struct pf_rule **, struct pf_state **,
+ int, struct pfi_kif *, struct mbuf *, int,
+ void *, struct pf_pdesc *, struct pf_rule **,
+#ifdef __FreeBSD__
+ struct pf_ruleset **, struct ifqueue *,
+ struct inpcb *);
+#else
+ struct pf_ruleset **, struct ifqueue *);
+#endif
+int pf_test_icmp(struct pf_rule **, struct pf_state **,
+ int, struct pfi_kif *, struct mbuf *, int,
+ void *, struct pf_pdesc *, struct pf_rule **,
+ struct pf_ruleset **, struct ifqueue *);
+int pf_test_other(struct pf_rule **, struct pf_state **,
+ int, struct pfi_kif *, struct mbuf *, int, void *,
+ struct pf_pdesc *, struct pf_rule **,
+ struct pf_ruleset **, struct ifqueue *);
+int pf_test_fragment(struct pf_rule **, int,
+ struct pfi_kif *, struct mbuf *, void *,
+ struct pf_pdesc *, struct pf_rule **,
+ struct pf_ruleset **);
+int pf_tcp_track_full(struct pf_state_peer *,
+ struct pf_state_peer *, struct pf_state **,
+ struct pfi_kif *, struct mbuf *, int,
+ struct pf_pdesc *, u_short *, int *);
+int pf_tcp_track_sloppy(struct pf_state_peer *,
+ struct pf_state_peer *, struct pf_state **,
+ struct pf_pdesc *, u_short *);
+int pf_test_state_tcp(struct pf_state **, int,
+ struct pfi_kif *, struct mbuf *, int,
+ void *, struct pf_pdesc *, u_short *);
+int pf_test_state_udp(struct pf_state **, int,
+ struct pfi_kif *, struct mbuf *, int,
+ void *, struct pf_pdesc *);
+int pf_test_state_icmp(struct pf_state **, int,
+ struct pfi_kif *, struct mbuf *, int,
+ void *, struct pf_pdesc *, u_short *);
+int pf_test_state_other(struct pf_state **, int,
+ struct pfi_kif *, struct pf_pdesc *);
+int pf_match_tag(struct mbuf *, struct pf_rule *,
+ struct pf_mtag *, int *);
+int pf_step_out_of_anchor(int *, struct pf_ruleset **,
+ int, struct pf_rule **, struct pf_rule **,
+ int *);
+void pf_hash(struct pf_addr *, struct pf_addr *,
+ struct pf_poolhashkey *, sa_family_t);
+int pf_map_addr(u_int8_t, struct pf_rule *,
+ struct pf_addr *, struct pf_addr *,
+ struct pf_addr *, struct pf_src_node **);
+int pf_get_sport(sa_family_t, u_int8_t, struct pf_rule *,
+ struct pf_addr *, struct pf_addr *, u_int16_t,
+ struct pf_addr *, u_int16_t*, u_int16_t, u_int16_t,
+ struct pf_src_node **);
+void pf_route(struct mbuf **, struct pf_rule *, int,
+ struct ifnet *, struct pf_state *,
+ struct pf_pdesc *);
+void pf_route6(struct mbuf **, struct pf_rule *, int,
+ struct ifnet *, struct pf_state *,
+ struct pf_pdesc *);
+#ifdef __FreeBSD__
+/* XXX: import */
+#else
+int pf_socket_lookup(int, struct pf_pdesc *);
+#endif
+u_int8_t pf_get_wscale(struct mbuf *, int, u_int16_t,
+ sa_family_t);
+u_int16_t pf_get_mss(struct mbuf *, int, u_int16_t,
+ sa_family_t);
+u_int16_t pf_calc_mss(struct pf_addr *, sa_family_t,
+ u_int16_t);
+void pf_set_rt_ifp(struct pf_state *,
+ struct pf_addr *);
+int pf_check_proto_cksum(struct mbuf *, int, int,
+ u_int8_t, sa_family_t);
+int pf_addr_wrap_neq(struct pf_addr_wrap *,
+ struct pf_addr_wrap *);
+struct pf_state *pf_find_state_recurse(struct pfi_kif *,
+ struct pf_state_cmp *, u_int8_t);
+int pf_src_connlimit(struct pf_state **);
+int pf_check_congestion(struct ifqueue *);
+
+#ifdef __FreeBSD__
+int in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len);
+
+extern int pf_end_threads;
+
+struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
+#else
+extern struct pool pfr_ktable_pl;
+extern struct pool pfr_kentry_pl;
+
+struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX] = {
+ { &pf_state_pl, PFSTATE_HIWAT },
+ { &pf_src_tree_pl, PFSNODE_HIWAT },
+ { &pf_frent_pl, PFFRAG_FRENT_HIWAT },
+ { &pfr_ktable_pl, PFR_KTABLE_HIWAT },
+ { &pfr_kentry_pl, PFR_KENTRY_HIWAT }
+};
+#endif
+
+#define STATE_LOOKUP() \
+ do { \
+ if (direction == PF_IN) \
+ *state = pf_find_state_recurse( \
+ kif, &key, PF_EXT_GWY); \
+ else \
+ *state = pf_find_state_recurse( \
+ kif, &key, PF_LAN_EXT); \
+ if (*state == NULL || (*state)->timeout == PFTM_PURGE) \
+ return (PF_DROP); \
+ if (direction == PF_OUT && \
+ (((*state)->rule.ptr->rt == PF_ROUTETO && \
+ (*state)->rule.ptr->direction == PF_OUT) || \
+ ((*state)->rule.ptr->rt == PF_REPLYTO && \
+ (*state)->rule.ptr->direction == PF_IN)) && \
+ (*state)->rt_kif != NULL && \
+ (*state)->rt_kif != kif) \
+ return (PF_PASS); \
+ } while (0)
+
+#define STATE_TRANSLATE(s) \
+ (s)->lan.addr.addr32[0] != (s)->gwy.addr.addr32[0] || \
+ ((s)->af == AF_INET6 && \
+ ((s)->lan.addr.addr32[1] != (s)->gwy.addr.addr32[1] || \
+ (s)->lan.addr.addr32[2] != (s)->gwy.addr.addr32[2] || \
+ (s)->lan.addr.addr32[3] != (s)->gwy.addr.addr32[3])) || \
+ (s)->lan.port != (s)->gwy.port
+
+#define BOUND_IFACE(r, k) \
+ ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : pfi_all
+
+#define STATE_INC_COUNTERS(s) \
+ do { \
+ s->rule.ptr->states++; \
+ if (s->anchor.ptr != NULL) \
+ s->anchor.ptr->states++; \
+ if (s->nat_rule.ptr != NULL) \
+ s->nat_rule.ptr->states++; \
+ } while (0)
+
+#define STATE_DEC_COUNTERS(s) \
+ do { \
+ if (s->nat_rule.ptr != NULL) \
+ s->nat_rule.ptr->states--; \
+ if (s->anchor.ptr != NULL) \
+ s->anchor.ptr->states--; \
+ s->rule.ptr->states--; \
+ } while (0)
+
+struct pf_src_tree tree_src_tracking;
+
+struct pf_state_tree_id tree_id;
+struct pf_state_queue state_list;
+
+#ifdef __FreeBSD__
+static int pf_src_compare(struct pf_src_node *, struct pf_src_node *);
+static int pf_state_compare_lan_ext(struct pf_state *, struct pf_state *);
+static int pf_state_compare_ext_gwy(struct pf_state *, struct pf_state *);
+static int pf_state_compare_id(struct pf_state *, struct pf_state *);
+#endif
+
+RB_GENERATE(pf_src_tree, pf_src_node, entry, pf_src_compare);
+RB_GENERATE(pf_state_tree_lan_ext, pf_state,
+ u.s.entry_lan_ext, pf_state_compare_lan_ext);
+RB_GENERATE(pf_state_tree_ext_gwy, pf_state,
+ u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
+RB_GENERATE(pf_state_tree_id, pf_state,
+ u.s.entry_id, pf_state_compare_id);
+
+#ifdef __FreeBSD__
+static int
+#else
+static __inline int
+#endif
+pf_src_compare(struct pf_src_node *a, struct pf_src_node *b)
+{
+ int diff;
+
+ if (a->rule.ptr > b->rule.ptr)
+ return (1);
+ if (a->rule.ptr < b->rule.ptr)
+ return (-1);
+ if ((diff = a->af - b->af) != 0)
+ return (diff);
+ switch (a->af) {
+#ifdef INET
+ case AF_INET:
+ if (a->addr.addr32[0] > b->addr.addr32[0])
+ return (1);
+ if (a->addr.addr32[0] < b->addr.addr32[0])
+ return (-1);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (a->addr.addr32[3] > b->addr.addr32[3])
+ return (1);
+ if (a->addr.addr32[3] < b->addr.addr32[3])
+ return (-1);
+ if (a->addr.addr32[2] > b->addr.addr32[2])
+ return (1);
+ if (a->addr.addr32[2] < b->addr.addr32[2])
+ return (-1);
+ if (a->addr.addr32[1] > b->addr.addr32[1])
+ return (1);
+ if (a->addr.addr32[1] < b->addr.addr32[1])
+ return (-1);
+ if (a->addr.addr32[0] > b->addr.addr32[0])
+ return (1);
+ if (a->addr.addr32[0] < b->addr.addr32[0])
+ return (-1);
+ break;
+#endif /* INET6 */
+ }
+ return (0);
+}
+
+#ifdef __FreeBSD__
+static int
+#else
+static __inline int
+#endif
+pf_state_compare_lan_ext(struct pf_state *a, struct pf_state *b)
+{
+ int diff;
+
+ if ((diff = a->proto - b->proto) != 0)
+ return (diff);
+ if ((diff = a->af - b->af) != 0)
+ return (diff);
+ switch (a->af) {
+#ifdef INET
+ case AF_INET:
+ if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
+ return (1);
+ if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
+ return (-1);
+ if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
+ return (1);
+ if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
+ return (-1);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (a->lan.addr.addr32[3] > b->lan.addr.addr32[3])
+ return (1);
+ if (a->lan.addr.addr32[3] < b->lan.addr.addr32[3])
+ return (-1);
+ if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
+ return (1);
+ if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
+ return (-1);
+ if (a->lan.addr.addr32[2] > b->lan.addr.addr32[2])
+ return (1);
+ if (a->lan.addr.addr32[2] < b->lan.addr.addr32[2])
+ return (-1);
+ if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
+ return (1);
+ if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
+ return (-1);
+ if (a->lan.addr.addr32[1] > b->lan.addr.addr32[1])
+ return (1);
+ if (a->lan.addr.addr32[1] < b->lan.addr.addr32[1])
+ return (-1);
+ if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
+ return (1);
+ if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
+ return (-1);
+ if (a->lan.addr.addr32[0] > b->lan.addr.addr32[0])
+ return (1);
+ if (a->lan.addr.addr32[0] < b->lan.addr.addr32[0])
+ return (-1);
+ if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
+ return (1);
+ if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
+ return (-1);
+ break;
+#endif /* INET6 */
+ }
+
+ if ((diff = a->lan.port - b->lan.port) != 0)
+ return (diff);
+ if ((diff = a->ext.port - b->ext.port) != 0)
+ return (diff);
+
+ return (0);
+}
+
+#ifdef __FreeBSD__
+static int
+#else
+static __inline int
+#endif
+pf_state_compare_ext_gwy(struct pf_state *a, struct pf_state *b)
+{
+ int diff;
+
+ if ((diff = a->proto - b->proto) != 0)
+ return (diff);
+ if ((diff = a->af - b->af) != 0)
+ return (diff);
+ switch (a->af) {
+#ifdef INET
+ case AF_INET:
+ if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
+ return (1);
+ if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
+ return (-1);
+ if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
+ return (1);
+ if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
+ return (-1);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (a->ext.addr.addr32[3] > b->ext.addr.addr32[3])
+ return (1);
+ if (a->ext.addr.addr32[3] < b->ext.addr.addr32[3])
+ return (-1);
+ if (a->gwy.addr.addr32[3] > b->gwy.addr.addr32[3])
+ return (1);
+ if (a->gwy.addr.addr32[3] < b->gwy.addr.addr32[3])
+ return (-1);
+ if (a->ext.addr.addr32[2] > b->ext.addr.addr32[2])
+ return (1);
+ if (a->ext.addr.addr32[2] < b->ext.addr.addr32[2])
+ return (-1);
+ if (a->gwy.addr.addr32[2] > b->gwy.addr.addr32[2])
+ return (1);
+ if (a->gwy.addr.addr32[2] < b->gwy.addr.addr32[2])
+ return (-1);
+ if (a->ext.addr.addr32[1] > b->ext.addr.addr32[1])
+ return (1);
+ if (a->ext.addr.addr32[1] < b->ext.addr.addr32[1])
+ return (-1);
+ if (a->gwy.addr.addr32[1] > b->gwy.addr.addr32[1])
+ return (1);
+ if (a->gwy.addr.addr32[1] < b->gwy.addr.addr32[1])
+ return (-1);
+ if (a->ext.addr.addr32[0] > b->ext.addr.addr32[0])
+ return (1);
+ if (a->ext.addr.addr32[0] < b->ext.addr.addr32[0])
+ return (-1);
+ if (a->gwy.addr.addr32[0] > b->gwy.addr.addr32[0])
+ return (1);
+ if (a->gwy.addr.addr32[0] < b->gwy.addr.addr32[0])
+ return (-1);
+ break;
+#endif /* INET6 */
+ }
+
+ if ((diff = a->ext.port - b->ext.port) != 0)
+ return (diff);
+ if ((diff = a->gwy.port - b->gwy.port) != 0)
+ return (diff);
+
+ return (0);
+}
+
+#ifdef __FreeBSD__
+static int
+#else
+static __inline int
+#endif
+pf_state_compare_id(struct pf_state *a, struct pf_state *b)
+{
+ if (a->id > b->id)
+ return (1);
+ if (a->id < b->id)
+ return (-1);
+ if (a->creatorid > b->creatorid)
+ return (1);
+ if (a->creatorid < b->creatorid)
+ return (-1);
+
+ return (0);
+}
+
+#ifdef INET6
+void
+pf_addrcpy(struct pf_addr *dst, struct pf_addr *src, sa_family_t af)
+{
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ dst->addr32[0] = src->addr32[0];
+ break;
+#endif /* INET */
+ case AF_INET6:
+ dst->addr32[0] = src->addr32[0];
+ dst->addr32[1] = src->addr32[1];
+ dst->addr32[2] = src->addr32[2];
+ dst->addr32[3] = src->addr32[3];
+ break;
+ }
+}
+#endif /* INET6 */
+
+struct pf_state *
+pf_find_state_byid(struct pf_state_cmp *key)
+{
+ pf_status.fcounters[FCNT_STATE_SEARCH]++;
+ return (RB_FIND(pf_state_tree_id, &tree_id, (struct pf_state *)key));
+}
+
+struct pf_state *
+pf_find_state_recurse(struct pfi_kif *kif, struct pf_state_cmp *key, u_int8_t tree)
+{
+ struct pf_state *s;
+
+ pf_status.fcounters[FCNT_STATE_SEARCH]++;
+
+ switch (tree) {
+ case PF_LAN_EXT:
+ if ((s = RB_FIND(pf_state_tree_lan_ext, &kif->pfik_lan_ext,
+ (struct pf_state *)key)) != NULL)
+ return (s);
+ if ((s = RB_FIND(pf_state_tree_lan_ext, &pfi_all->pfik_lan_ext,
+ (struct pf_state *)key)) != NULL)
+ return (s);
+ return (NULL);
+ case PF_EXT_GWY:
+ if ((s = RB_FIND(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy,
+ (struct pf_state *)key)) != NULL)
+ return (s);
+ if ((s = RB_FIND(pf_state_tree_ext_gwy, &pfi_all->pfik_ext_gwy,
+ (struct pf_state *)key)) != NULL)
+ return (s);
+ return (NULL);
+ default:
+ panic("pf_find_state_recurse");
+ }
+}
+
+struct pf_state *
+pf_find_state_all(struct pf_state_cmp *key, u_int8_t tree, int *more)
+{
+ struct pf_state *s, *ss = NULL;
+ struct pfi_kif *kif;
+
+ pf_status.fcounters[FCNT_STATE_SEARCH]++;
+
+ switch (tree) {
+ case PF_LAN_EXT:
+ TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
+ s = RB_FIND(pf_state_tree_lan_ext,
+ &kif->pfik_lan_ext, (struct pf_state *)key);
+ if (s == NULL)
+ continue;
+ if (more == NULL)
+ return (s);
+ ss = s;
+ (*more)++;
+ }
+ return (ss);
+ case PF_EXT_GWY:
+ TAILQ_FOREACH(kif, &pfi_statehead, pfik_w_states) {
+ s = RB_FIND(pf_state_tree_ext_gwy,
+ &kif->pfik_ext_gwy, (struct pf_state *)key);
+ if (s == NULL)
+ continue;
+ if (more == NULL)
+ return (s);
+ ss = s;
+ (*more)++;
+ }
+ return (ss);
+ default:
+ panic("pf_find_state_all");
+ }
+}
+
+void
+pf_init_threshold(struct pf_threshold *threshold,
+ u_int32_t limit, u_int32_t seconds)
+{
+ threshold->limit = limit * PF_THRESHOLD_MULT;
+ threshold->seconds = seconds;
+ threshold->count = 0;
+ threshold->last = time_second;
+}
+
+void
+pf_add_threshold(struct pf_threshold *threshold)
+{
+ u_int32_t t = time_second, diff = t - threshold->last;
+
+ if (diff >= threshold->seconds)
+ threshold->count = 0;
+ else
+ threshold->count -= threshold->count * diff /
+ threshold->seconds;
+ threshold->count += PF_THRESHOLD_MULT;
+ threshold->last = t;
+}
+
+int
+pf_check_threshold(struct pf_threshold *threshold)
+{
+ return (threshold->count > threshold->limit);
+}
+
+int
+pf_src_connlimit(struct pf_state **state)
+{
+ struct pf_state *s;
+ int bad = 0;
+
+ (*state)->src_node->conn++;
+ (*state)->src.tcp_est = 1;
+ pf_add_threshold(&(*state)->src_node->conn_rate);
+
+ if ((*state)->rule.ptr->max_src_conn &&
+ (*state)->rule.ptr->max_src_conn <
+ (*state)->src_node->conn) {
+ pf_status.lcounters[LCNT_SRCCONN]++;
+ bad++;
+ }
+
+ if ((*state)->rule.ptr->max_src_conn_rate.limit &&
+ pf_check_threshold(&(*state)->src_node->conn_rate)) {
+ pf_status.lcounters[LCNT_SRCCONNRATE]++;
+ bad++;
+ }
+
+ if (!bad)
+ return (0);
+
+ if ((*state)->rule.ptr->overload_tbl) {
+ struct pfr_addr p;
+ u_int32_t killed = 0;
+
+ pf_status.lcounters[LCNT_OVERLOAD_TABLE]++;
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf_src_connlimit: blocking address ");
+ pf_print_host(&(*state)->src_node->addr, 0,
+ (*state)->af);
+ }
+
+ bzero(&p, sizeof(p));
+ p.pfra_af = (*state)->af;
+ switch ((*state)->af) {
+#ifdef INET
+ case AF_INET:
+ p.pfra_net = 32;
+ p.pfra_ip4addr = (*state)->src_node->addr.v4;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ p.pfra_net = 128;
+ p.pfra_ip6addr = (*state)->src_node->addr.v6;
+ break;
+#endif /* INET6 */
+ }
+
+ pfr_insert_kentry((*state)->rule.ptr->overload_tbl,
+ &p, time_second);
+
+ /* kill existing states if that's required. */
+ if ((*state)->rule.ptr->flush) {
+ pf_status.lcounters[LCNT_OVERLOAD_FLUSH]++;
+
+ RB_FOREACH(s, pf_state_tree_id, &tree_id) {
+ /*
+ * Kill states from this source. (Only those
+ * from the same rule if PF_FLUSH_GLOBAL is not
+ * set)
+ */
+ if (s->af == (*state)->af &&
+ (((*state)->direction == PF_OUT &&
+ PF_AEQ(&(*state)->src_node->addr,
+ &s->lan.addr, s->af)) ||
+ ((*state)->direction == PF_IN &&
+ PF_AEQ(&(*state)->src_node->addr,
+ &s->ext.addr, s->af))) &&
+ ((*state)->rule.ptr->flush &
+ PF_FLUSH_GLOBAL ||
+ (*state)->rule.ptr == s->rule.ptr)) {
+ s->timeout = PFTM_PURGE;
+ s->src.state = s->dst.state =
+ TCPS_CLOSED;
+ killed++;
+ }
+ }
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf(", %u states killed", killed);
+ }
+ if (pf_status.debug >= PF_DEBUG_MISC)
+ printf("\n");
+ }
+
+ /* kill this state */
+ (*state)->timeout = PFTM_PURGE;
+ (*state)->src.state = (*state)->dst.state = TCPS_CLOSED;
+ return (1);
+}
+
+int
+pf_insert_src_node(struct pf_src_node **sn, struct pf_rule *rule,
+ struct pf_addr *src, sa_family_t af)
+{
+ struct pf_src_node k;
+
+ if (*sn == NULL) {
+ k.af = af;
+ PF_ACPY(&k.addr, src, af);
+ if (rule->rule_flag & PFRULE_RULESRCTRACK ||
+ rule->rpool.opts & PF_POOL_STICKYADDR)
+ k.rule.ptr = rule;
+ else
+ k.rule.ptr = NULL;
+ pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
+ *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
+ }
+ if (*sn == NULL) {
+ if (!rule->max_src_nodes ||
+ rule->src_nodes < rule->max_src_nodes)
+ (*sn) = pool_get(&pf_src_tree_pl, PR_NOWAIT);
+ else
+ pf_status.lcounters[LCNT_SRCNODES]++;
+ if ((*sn) == NULL)
+ return (-1);
+ bzero(*sn, sizeof(struct pf_src_node));
+
+ pf_init_threshold(&(*sn)->conn_rate,
+ rule->max_src_conn_rate.limit,
+ rule->max_src_conn_rate.seconds);
+
+ (*sn)->af = af;
+ if (rule->rule_flag & PFRULE_RULESRCTRACK ||
+ rule->rpool.opts & PF_POOL_STICKYADDR)
+ (*sn)->rule.ptr = rule;
+ else
+ (*sn)->rule.ptr = NULL;
+ PF_ACPY(&(*sn)->addr, src, af);
+ if (RB_INSERT(pf_src_tree,
+ &tree_src_tracking, *sn) != NULL) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: src_tree insert failed: ");
+ pf_print_host(&(*sn)->addr, 0, af);
+ printf("\n");
+ }
+ pool_put(&pf_src_tree_pl, *sn);
+ return (-1);
+ }
+ (*sn)->creation = time_second;
+ (*sn)->ruletype = rule->action;
+ if ((*sn)->rule.ptr != NULL)
+ (*sn)->rule.ptr->src_nodes++;
+ pf_status.scounters[SCNT_SRC_NODE_INSERT]++;
+ pf_status.src_nodes++;
+ } else {
+ if (rule->max_src_states &&
+ (*sn)->states >= rule->max_src_states) {
+ pf_status.lcounters[LCNT_SRCSTATES]++;
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+int
+pf_insert_state(struct pfi_kif *kif, struct pf_state *state)
+{
+ /* Thou MUST NOT insert multiple duplicate keys */
+ state->u.s.kif = kif;
+ if (RB_INSERT(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state)) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: state insert failed: tree_lan_ext");
+ printf(" lan: ");
+ pf_print_host(&state->lan.addr, state->lan.port,
+ state->af);
+ printf(" gwy: ");
+ pf_print_host(&state->gwy.addr, state->gwy.port,
+ state->af);
+ printf(" ext: ");
+ pf_print_host(&state->ext.addr, state->ext.port,
+ state->af);
+ if (state->sync_flags & PFSTATE_FROMSYNC)
+ printf(" (from sync)");
+ printf("\n");
+ }
+ return (-1);
+ }
+
+ if (RB_INSERT(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state)) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: state insert failed: tree_ext_gwy");
+ printf(" lan: ");
+ pf_print_host(&state->lan.addr, state->lan.port,
+ state->af);
+ printf(" gwy: ");
+ pf_print_host(&state->gwy.addr, state->gwy.port,
+ state->af);
+ printf(" ext: ");
+ pf_print_host(&state->ext.addr, state->ext.port,
+ state->af);
+ if (state->sync_flags & PFSTATE_FROMSYNC)
+ printf(" (from sync)");
+ printf("\n");
+ }
+ RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
+ return (-1);
+ }
+
+ if (state->id == 0 && state->creatorid == 0) {
+ state->id = htobe64(pf_status.stateid++);
+ state->creatorid = pf_status.hostid;
+ }
+ if (RB_INSERT(pf_state_tree_id, &tree_id, state) != NULL) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+#ifdef __FreeBSD__
+ printf("pf: state insert failed: "
+ "id: %016llx creatorid: %08x",
+ (long long)be64toh(state->id),
+ ntohl(state->creatorid));
+#else
+ printf("pf: state insert failed: "
+ "id: %016llx creatorid: %08x",
+ betoh64(state->id), ntohl(state->creatorid));
+#endif
+ if (state->sync_flags & PFSTATE_FROMSYNC)
+ printf(" (from sync)");
+ printf("\n");
+ }
+ RB_REMOVE(pf_state_tree_lan_ext, &kif->pfik_lan_ext, state);
+ RB_REMOVE(pf_state_tree_ext_gwy, &kif->pfik_ext_gwy, state);
+ return (-1);
+ }
+ TAILQ_INSERT_TAIL(&state_list, state, u.s.entry_list);
+ pf_status.fcounters[FCNT_STATE_INSERT]++;
+ pf_status.states++;
+ pfi_kif_ref(kif, PFI_KIF_REF_STATE);
+#if NPFSYNC
+ pfsync_insert_state(state);
+#endif
+ return (0);
+}
+
+void
+pf_purge_thread(void *v)
+{
+ int nloops = 0, s;
+#ifdef __FreeBSD__
+ int locked;
+#endif
+
+ for (;;) {
+ tsleep(pf_purge_thread, PWAIT, "pftm", 1 * hz);
+
+#ifdef __FreeBSD__
+ sx_slock(&pf_consistency_lock);
+ PF_LOCK();
+ locked = 0;
+
+ if (pf_end_threads) {
+ PF_UNLOCK();
+ sx_sunlock(&pf_consistency_lock);
+ sx_xlock(&pf_consistency_lock);
+ PF_LOCK();
+ pf_purge_expired_states(pf_status.states, 1);
+ pf_purge_expired_fragments();
+ pf_purge_expired_src_nodes(1);
+ pf_end_threads++;
+
+ sx_xunlock(&pf_consistency_lock);
+ PF_UNLOCK();
+ wakeup(pf_purge_thread);
+ kproc_exit(0);
+ }
+#endif
+ s = splsoftnet();
+
+ /* process a fraction of the state table every second */
+#ifdef __FreeBSD__
+ if(!pf_purge_expired_states(1 + (pf_status.states
+ / pf_default_rule.timeout[PFTM_INTERVAL]), 0)) {
+ PF_UNLOCK();
+ sx_sunlock(&pf_consistency_lock);
+ sx_xlock(&pf_consistency_lock);
+ PF_LOCK();
+ locked = 1;
+
+ pf_purge_expired_states(1 + (pf_status.states
+ / pf_default_rule.timeout[PFTM_INTERVAL]), 1);
+ }
+#else
+ pf_purge_expired_states(1 + (pf_status.states
+ / pf_default_rule.timeout[PFTM_INTERVAL]));
+#endif
+
+ /* purge other expired types every PFTM_INTERVAL seconds */
+ if (++nloops >= pf_default_rule.timeout[PFTM_INTERVAL]) {
+ pf_purge_expired_fragments();
+ if (!pf_purge_expired_src_nodes(locked)) {
+ PF_UNLOCK();
+ sx_sunlock(&pf_consistency_lock);
+ sx_xlock(&pf_consistency_lock);
+ PF_LOCK();
+ locked = 1;
+ pf_purge_expired_src_nodes(1);
+ }
+ nloops = 0;
+ }
+
+ splx(s);
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ if (locked)
+ sx_xunlock(&pf_consistency_lock);
+ else
+ sx_sunlock(&pf_consistency_lock);
+#endif
+ }
+}
+
+u_int32_t
+pf_state_expires(const struct pf_state *state)
+{
+ u_int32_t timeout;
+ u_int32_t start;
+ u_int32_t end;
+ u_int32_t states;
+
+ /* handle all PFTM_* > PFTM_MAX here */
+ if (state->timeout == PFTM_PURGE)
+ return (time_second);
+ if (state->timeout == PFTM_UNTIL_PACKET)
+ return (0);
+#ifdef __FreeBSD__
+ KASSERT(state->timeout != PFTM_UNLINKED,
+ ("pf_state_expires: timeout == PFTM_UNLINKED"));
+ KASSERT((state->timeout < PFTM_MAX),
+ ("pf_state_expires: timeout > PFTM_MAX"));
+#else
+ KASSERT(state->timeout != PFTM_UNLINKED);
+ KASSERT(state->timeout < PFTM_MAX);
+#endif
+ timeout = state->rule.ptr->timeout[state->timeout];
+ if (!timeout)
+ timeout = pf_default_rule.timeout[state->timeout];
+ start = state->rule.ptr->timeout[PFTM_ADAPTIVE_START];
+ if (start) {
+ end = state->rule.ptr->timeout[PFTM_ADAPTIVE_END];
+ states = state->rule.ptr->states;
+ } else {
+ start = pf_default_rule.timeout[PFTM_ADAPTIVE_START];
+ end = pf_default_rule.timeout[PFTM_ADAPTIVE_END];
+ states = pf_status.states;
+ }
+ if (end && states > start && start < end) {
+ if (states < end)
+ return (state->expire + timeout * (end - states) /
+ (end - start));
+ else
+ return (time_second);
+ }
+ return (state->expire + timeout);
+}
+
+#ifdef __FreeBSD__
+int
+pf_purge_expired_src_nodes(int waslocked)
+#else
+void
+pf_purge_expired_src_nodes(int waslocked)
+#endif
+{
+ struct pf_src_node *cur, *next;
+ int locked = waslocked;
+
+ for (cur = RB_MIN(pf_src_tree, &tree_src_tracking); cur; cur = next) {
+ next = RB_NEXT(pf_src_tree, &tree_src_tracking, cur);
+
+ if (cur->states <= 0 && cur->expire <= time_second) {
+ if (! locked) {
+#ifdef __FreeBSD__
+ if (!sx_try_upgrade(&pf_consistency_lock))
+ return (0);
+#else
+ rw_enter_write(&pf_consistency_lock);
+#endif
+ next = RB_NEXT(pf_src_tree,
+ &tree_src_tracking, cur);
+ locked = 1;
+ }
+ if (cur->rule.ptr != NULL) {
+ cur->rule.ptr->src_nodes--;
+ if (cur->rule.ptr->states <= 0 &&
+ cur->rule.ptr->max_src_nodes <= 0)
+ pf_rm_rule(NULL, cur->rule.ptr);
+ }
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, cur);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, cur);
+ }
+ }
+
+ if (locked && !waslocked)
+#ifdef __FreeBSD__
+ sx_downgrade(&pf_consistency_lock);
+#else
+ rw_exit_write(&pf_consistency_lock);
+#endif
+
+#ifdef __FreeBSD__
+ return (1);
+#endif
+}
+
+void
+pf_src_tree_remove_state(struct pf_state *s)
+{
+ u_int32_t timeout;
+
+ if (s->src_node != NULL) {
+ if (s->proto == IPPROTO_TCP) {
+ if (s->src.tcp_est)
+ --s->src_node->conn;
+ }
+ if (--s->src_node->states <= 0) {
+ timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
+ if (!timeout)
+ timeout =
+ pf_default_rule.timeout[PFTM_SRC_NODE];
+ s->src_node->expire = time_second + timeout;
+ }
+ }
+ if (s->nat_src_node != s->src_node && s->nat_src_node != NULL) {
+ if (--s->nat_src_node->states <= 0) {
+ timeout = s->rule.ptr->timeout[PFTM_SRC_NODE];
+ if (!timeout)
+ timeout =
+ pf_default_rule.timeout[PFTM_SRC_NODE];
+ s->nat_src_node->expire = time_second + timeout;
+ }
+ }
+ s->src_node = s->nat_src_node = NULL;
+}
+
+/* callers should be at splsoftnet */
+void
+pf_unlink_state(struct pf_state *cur)
+{
+#ifdef __FreeBSD__
+ if (cur->local_flags & PFSTATE_EXPIRING)
+ return;
+ cur->local_flags |= PFSTATE_EXPIRING;
+#endif
+ if (cur->src.state == PF_TCPS_PROXY_DST) {
+#ifdef __FreeBSD__
+ pf_send_tcp(NULL, cur->rule.ptr, cur->af,
+#else
+ pf_send_tcp(cur->rule.ptr, cur->af,
+#endif
+ &cur->ext.addr, &cur->lan.addr,
+ cur->ext.port, cur->lan.port,
+ cur->src.seqhi, cur->src.seqlo + 1,
+ TH_RST|TH_ACK, 0, 0, 0, 1, cur->tag, NULL, NULL);
+ }
+ RB_REMOVE(pf_state_tree_ext_gwy,
+ &cur->u.s.kif->pfik_ext_gwy, cur);
+ RB_REMOVE(pf_state_tree_lan_ext,
+ &cur->u.s.kif->pfik_lan_ext, cur);
+ RB_REMOVE(pf_state_tree_id, &tree_id, cur);
+#if NPFSYNC
+ if (cur->creatorid == pf_status.hostid)
+ pfsync_delete_state(cur);
+#endif
+ cur->timeout = PFTM_UNLINKED;
+ pf_src_tree_remove_state(cur);
+}
+
+/* callers should be at splsoftnet and hold the
+ * write_lock on pf_consistency_lock */
+void
+pf_free_state(struct pf_state *cur)
+{
+#if NPFSYNC
+ if (pfsyncif != NULL &&
+ (pfsyncif->sc_bulk_send_next == cur ||
+ pfsyncif->sc_bulk_terminator == cur))
+ return;
+#endif
+#ifdef __FreeBSD__
+ KASSERT(cur->timeout == PFTM_UNLINKED,
+ ("pf_free_state: cur->timeout != PFTM_UNLINKED"));
+#else
+ KASSERT(cur->timeout == PFTM_UNLINKED);
+#endif
+ if (--cur->rule.ptr->states <= 0 &&
+ cur->rule.ptr->src_nodes <= 0)
+ pf_rm_rule(NULL, cur->rule.ptr);
+ if (cur->nat_rule.ptr != NULL)
+ if (--cur->nat_rule.ptr->states <= 0 &&
+ cur->nat_rule.ptr->src_nodes <= 0)
+ pf_rm_rule(NULL, cur->nat_rule.ptr);
+ if (cur->anchor.ptr != NULL)
+ if (--cur->anchor.ptr->states <= 0)
+ pf_rm_rule(NULL, cur->anchor.ptr);
+ pf_normalize_tcp_cleanup(cur);
+ pfi_kif_unref(cur->u.s.kif, PFI_KIF_REF_STATE);
+ TAILQ_REMOVE(&state_list, cur, u.s.entry_list);
+ if (cur->tag)
+ pf_tag_unref(cur->tag);
+ pool_put(&pf_state_pl, cur);
+ pf_status.fcounters[FCNT_STATE_REMOVALS]++;
+ pf_status.states--;
+}
+
+#ifdef __FreeBSD__
+int
+pf_purge_expired_states(u_int32_t maxcheck, int waslocked)
+#else
+void
+pf_purge_expired_states(u_int32_t maxcheck)
+#endif
+{
+ static struct pf_state *cur = NULL;
+ struct pf_state *next;
+#ifdef __FreeBSD__
+ int locked = waslocked;
+#else
+ int locked = 0;
+#endif
+
+ while (maxcheck--) {
+ /* wrap to start of list when we hit the end */
+ if (cur == NULL) {
+ cur = TAILQ_FIRST(&state_list);
+ if (cur == NULL)
+ break; /* list empty */
+ }
+
+ /* get next state, as cur may get deleted */
+ next = TAILQ_NEXT(cur, u.s.entry_list);
+
+ if (cur->timeout == PFTM_UNLINKED) {
+ /* free unlinked state */
+ if (! locked) {
+#ifdef __FreeBSD__
+ if (!sx_try_upgrade(&pf_consistency_lock))
+ return (0);
+#else
+ rw_enter_write(&pf_consistency_lock);
+#endif
+ locked = 1;
+ }
+ pf_free_state(cur);
+ } else if (pf_state_expires(cur) <= time_second) {
+ /* unlink and free expired state */
+ pf_unlink_state(cur);
+ if (! locked) {
+#ifdef __FreeBSD__
+ if (!sx_try_upgrade(&pf_consistency_lock))
+ return (0);
+#else
+ rw_enter_write(&pf_consistency_lock);
+#endif
+ locked = 1;
+ }
+ pf_free_state(cur);
+ }
+ cur = next;
+ }
+
+#ifdef __FreeBSD__
+ if (!waslocked && locked)
+ sx_downgrade(&pf_consistency_lock);
+
+ return (1);
+#else
+ if (locked)
+ rw_exit_write(&pf_consistency_lock);
+#endif
+}
+
+int
+pf_tbladdr_setup(struct pf_ruleset *rs, struct pf_addr_wrap *aw)
+{
+ if (aw->type != PF_ADDR_TABLE)
+ return (0);
+ if ((aw->p.tbl = pfr_attach_table(rs, aw->v.tblname)) == NULL)
+ return (1);
+ return (0);
+}
+
+void
+pf_tbladdr_remove(struct pf_addr_wrap *aw)
+{
+ if (aw->type != PF_ADDR_TABLE || aw->p.tbl == NULL)
+ return;
+ pfr_detach_table(aw->p.tbl);
+ aw->p.tbl = NULL;
+}
+
+void
+pf_tbladdr_copyout(struct pf_addr_wrap *aw)
+{
+ struct pfr_ktable *kt = aw->p.tbl;
+
+ if (aw->type != PF_ADDR_TABLE || kt == NULL)
+ return;
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
+ kt = kt->pfrkt_root;
+ aw->p.tbl = NULL;
+ aw->p.tblcnt = (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) ?
+ kt->pfrkt_cnt : -1;
+}
+
+void
+pf_print_host(struct pf_addr *addr, u_int16_t p, sa_family_t af)
+{
+ switch (af) {
+#ifdef INET
+ case AF_INET: {
+ u_int32_t a = ntohl(addr->addr32[0]);
+ printf("%u.%u.%u.%u", (a>>24)&255, (a>>16)&255,
+ (a>>8)&255, a&255);
+ if (p) {
+ p = ntohs(p);
+ printf(":%u", p);
+ }
+ break;
+ }
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6: {
+ u_int16_t b;
+ u_int8_t i, curstart = 255, curend = 0,
+ maxstart = 0, maxend = 0;
+ for (i = 0; i < 8; i++) {
+ if (!addr->addr16[i]) {
+ if (curstart == 255)
+ curstart = i;
+ else
+ curend = i;
+ } else {
+ if (curstart) {
+ if ((curend - curstart) >
+ (maxend - maxstart)) {
+ maxstart = curstart;
+ maxend = curend;
+ curstart = 255;
+ }
+ }
+ }
+ }
+ for (i = 0; i < 8; i++) {
+ if (i >= maxstart && i <= maxend) {
+ if (maxend != 7) {
+ if (i == maxstart)
+ printf(":");
+ } else {
+ if (i == maxend)
+ printf(":");
+ }
+ } else {
+ b = ntohs(addr->addr16[i]);
+ printf("%x", b);
+ if (i < 7)
+ printf(":");
+ }
+ }
+ if (p) {
+ p = ntohs(p);
+ printf("[%u]", p);
+ }
+ break;
+ }
+#endif /* INET6 */
+ }
+}
+
+void
+pf_print_state(struct pf_state *s)
+{
+ switch (s->proto) {
+ case IPPROTO_TCP:
+ printf("TCP ");
+ break;
+ case IPPROTO_UDP:
+ printf("UDP ");
+ break;
+ case IPPROTO_ICMP:
+ printf("ICMP ");
+ break;
+ case IPPROTO_ICMPV6:
+ printf("ICMPV6 ");
+ break;
+ default:
+ printf("%u ", s->proto);
+ break;
+ }
+ pf_print_host(&s->lan.addr, s->lan.port, s->af);
+ printf(" ");
+ pf_print_host(&s->gwy.addr, s->gwy.port, s->af);
+ printf(" ");
+ pf_print_host(&s->ext.addr, s->ext.port, s->af);
+ printf(" [lo=%u high=%u win=%u modulator=%u", s->src.seqlo,
+ s->src.seqhi, s->src.max_win, s->src.seqdiff);
+ if (s->src.wscale && s->dst.wscale)
+ printf(" wscale=%u", s->src.wscale & PF_WSCALE_MASK);
+ printf("]");
+ printf(" [lo=%u high=%u win=%u modulator=%u", s->dst.seqlo,
+ s->dst.seqhi, s->dst.max_win, s->dst.seqdiff);
+ if (s->src.wscale && s->dst.wscale)
+ printf(" wscale=%u", s->dst.wscale & PF_WSCALE_MASK);
+ printf("]");
+ printf(" %u:%u", s->src.state, s->dst.state);
+}
+
+void
+pf_print_flags(u_int8_t f)
+{
+ if (f)
+ printf(" ");
+ if (f & TH_FIN)
+ printf("F");
+ if (f & TH_SYN)
+ printf("S");
+ if (f & TH_RST)
+ printf("R");
+ if (f & TH_PUSH)
+ printf("P");
+ if (f & TH_ACK)
+ printf("A");
+ if (f & TH_URG)
+ printf("U");
+ if (f & TH_ECE)
+ printf("E");
+ if (f & TH_CWR)
+ printf("W");
+}
+
+#define PF_SET_SKIP_STEPS(i) \
+ do { \
+ while (head[i] != cur) { \
+ head[i]->skip[i].ptr = cur; \
+ head[i] = TAILQ_NEXT(head[i], entries); \
+ } \
+ } while (0)
+
+void
+pf_calc_skip_steps(struct pf_rulequeue *rules)
+{
+ struct pf_rule *cur, *prev, *head[PF_SKIP_COUNT];
+ int i;
+
+ cur = TAILQ_FIRST(rules);
+ prev = cur;
+ for (i = 0; i < PF_SKIP_COUNT; ++i)
+ head[i] = cur;
+ while (cur != NULL) {
+
+ if (cur->kif != prev->kif || cur->ifnot != prev->ifnot)
+ PF_SET_SKIP_STEPS(PF_SKIP_IFP);
+ if (cur->direction != prev->direction)
+ PF_SET_SKIP_STEPS(PF_SKIP_DIR);
+ if (cur->af != prev->af)
+ PF_SET_SKIP_STEPS(PF_SKIP_AF);
+ if (cur->proto != prev->proto)
+ PF_SET_SKIP_STEPS(PF_SKIP_PROTO);
+ if (cur->src.neg != prev->src.neg ||
+ pf_addr_wrap_neq(&cur->src.addr, &prev->src.addr))
+ PF_SET_SKIP_STEPS(PF_SKIP_SRC_ADDR);
+ if (cur->src.port[0] != prev->src.port[0] ||
+ cur->src.port[1] != prev->src.port[1] ||
+ cur->src.port_op != prev->src.port_op)
+ PF_SET_SKIP_STEPS(PF_SKIP_SRC_PORT);
+ if (cur->dst.neg != prev->dst.neg ||
+ pf_addr_wrap_neq(&cur->dst.addr, &prev->dst.addr))
+ PF_SET_SKIP_STEPS(PF_SKIP_DST_ADDR);
+ if (cur->dst.port[0] != prev->dst.port[0] ||
+ cur->dst.port[1] != prev->dst.port[1] ||
+ cur->dst.port_op != prev->dst.port_op)
+ PF_SET_SKIP_STEPS(PF_SKIP_DST_PORT);
+
+ prev = cur;
+ cur = TAILQ_NEXT(cur, entries);
+ }
+ for (i = 0; i < PF_SKIP_COUNT; ++i)
+ PF_SET_SKIP_STEPS(i);
+}
+
+int
+pf_addr_wrap_neq(struct pf_addr_wrap *aw1, struct pf_addr_wrap *aw2)
+{
+ if (aw1->type != aw2->type)
+ return (1);
+ switch (aw1->type) {
+ case PF_ADDR_ADDRMASK:
+ if (PF_ANEQ(&aw1->v.a.addr, &aw2->v.a.addr, 0))
+ return (1);
+ if (PF_ANEQ(&aw1->v.a.mask, &aw2->v.a.mask, 0))
+ return (1);
+ return (0);
+ case PF_ADDR_DYNIFTL:
+ return (aw1->p.dyn->pfid_kt != aw2->p.dyn->pfid_kt);
+ case PF_ADDR_NOROUTE:
+ case PF_ADDR_URPFFAILED:
+ return (0);
+ case PF_ADDR_TABLE:
+ return (aw1->p.tbl != aw2->p.tbl);
+ case PF_ADDR_RTLABEL:
+ return (aw1->v.rtlabel != aw2->v.rtlabel);
+ default:
+ printf("invalid address type: %d\n", aw1->type);
+ return (1);
+ }
+}
+
+u_int16_t
+pf_cksum_fixup(u_int16_t cksum, u_int16_t old, u_int16_t new, u_int8_t udp)
+{
+ u_int32_t l;
+
+ if (udp && !cksum)
+ return (0x0000);
+ l = cksum + old - new;
+ l = (l >> 16) + (l & 65535);
+ l = l & 65535;
+ if (udp && !l)
+ return (0xFFFF);
+ return (l);
+}
+
+void
+pf_change_ap(struct pf_addr *a, u_int16_t *p, u_int16_t *ic, u_int16_t *pc,
+ struct pf_addr *an, u_int16_t pn, u_int8_t u, sa_family_t af)
+{
+ struct pf_addr ao;
+ u_int16_t po = *p;
+
+ PF_ACPY(&ao, a, af);
+ PF_ACPY(a, an, af);
+
+ *p = pn;
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
+ ao.addr16[0], an->addr16[0], 0),
+ ao.addr16[1], an->addr16[1], 0);
+ *p = pn;
+ *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
+ ao.addr16[0], an->addr16[0], u),
+ ao.addr16[1], an->addr16[1], u),
+ po, pn, u);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ *pc = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(*pc,
+ ao.addr16[0], an->addr16[0], u),
+ ao.addr16[1], an->addr16[1], u),
+ ao.addr16[2], an->addr16[2], u),
+ ao.addr16[3], an->addr16[3], u),
+ ao.addr16[4], an->addr16[4], u),
+ ao.addr16[5], an->addr16[5], u),
+ ao.addr16[6], an->addr16[6], u),
+ ao.addr16[7], an->addr16[7], u),
+ po, pn, u);
+ break;
+#endif /* INET6 */
+ }
+}
+
+
+/* Changes a u_int32_t. Uses a void * so there are no align restrictions */
+void
+pf_change_a(void *a, u_int16_t *c, u_int32_t an, u_int8_t u)
+{
+ u_int32_t ao;
+
+ memcpy(&ao, a, sizeof(ao));
+ memcpy(a, &an, sizeof(u_int32_t));
+ *c = pf_cksum_fixup(pf_cksum_fixup(*c, ao / 65536, an / 65536, u),
+ ao % 65536, an % 65536, u);
+}
+
+#ifdef INET6
+void
+pf_change_a6(struct pf_addr *a, u_int16_t *c, struct pf_addr *an, u_int8_t u)
+{
+ struct pf_addr ao;
+
+ PF_ACPY(&ao, a, AF_INET6);
+ PF_ACPY(a, an, AF_INET6);
+
+ *c = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(*c,
+ ao.addr16[0], an->addr16[0], u),
+ ao.addr16[1], an->addr16[1], u),
+ ao.addr16[2], an->addr16[2], u),
+ ao.addr16[3], an->addr16[3], u),
+ ao.addr16[4], an->addr16[4], u),
+ ao.addr16[5], an->addr16[5], u),
+ ao.addr16[6], an->addr16[6], u),
+ ao.addr16[7], an->addr16[7], u);
+}
+#endif /* INET6 */
+
+void
+pf_change_icmp(struct pf_addr *ia, u_int16_t *ip, struct pf_addr *oa,
+ struct pf_addr *na, u_int16_t np, u_int16_t *pc, u_int16_t *h2c,
+ u_int16_t *ic, u_int16_t *hc, u_int8_t u, sa_family_t af)
+{
+ struct pf_addr oia, ooa;
+
+ PF_ACPY(&oia, ia, af);
+ PF_ACPY(&ooa, oa, af);
+
+ /* Change inner protocol port, fix inner protocol checksum. */
+ if (ip != NULL) {
+ u_int16_t oip = *ip;
+ u_int32_t opc = 0; /* make the compiler happy */
+
+ if (pc != NULL)
+ opc = *pc;
+ *ip = np;
+ if (pc != NULL)
+ *pc = pf_cksum_fixup(*pc, oip, *ip, u);
+ *ic = pf_cksum_fixup(*ic, oip, *ip, 0);
+ if (pc != NULL)
+ *ic = pf_cksum_fixup(*ic, opc, *pc, 0);
+ }
+ /* Change inner ip address, fix inner ip and icmp checksums. */
+ PF_ACPY(ia, na, af);
+ switch (af) {
+#ifdef INET
+ case AF_INET: {
+ u_int32_t oh2c = *h2c;
+
+ *h2c = pf_cksum_fixup(pf_cksum_fixup(*h2c,
+ oia.addr16[0], ia->addr16[0], 0),
+ oia.addr16[1], ia->addr16[1], 0);
+ *ic = pf_cksum_fixup(pf_cksum_fixup(*ic,
+ oia.addr16[0], ia->addr16[0], 0),
+ oia.addr16[1], ia->addr16[1], 0);
+ *ic = pf_cksum_fixup(*ic, oh2c, *h2c, 0);
+ break;
+ }
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(*ic,
+ oia.addr16[0], ia->addr16[0], u),
+ oia.addr16[1], ia->addr16[1], u),
+ oia.addr16[2], ia->addr16[2], u),
+ oia.addr16[3], ia->addr16[3], u),
+ oia.addr16[4], ia->addr16[4], u),
+ oia.addr16[5], ia->addr16[5], u),
+ oia.addr16[6], ia->addr16[6], u),
+ oia.addr16[7], ia->addr16[7], u);
+ break;
+#endif /* INET6 */
+ }
+ /* Change outer ip address, fix outer ip or icmpv6 checksum. */
+ PF_ACPY(oa, na, af);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ *hc = pf_cksum_fixup(pf_cksum_fixup(*hc,
+ ooa.addr16[0], oa->addr16[0], 0),
+ ooa.addr16[1], oa->addr16[1], 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ *ic = pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(pf_cksum_fixup(
+ pf_cksum_fixup(pf_cksum_fixup(*ic,
+ ooa.addr16[0], oa->addr16[0], u),
+ ooa.addr16[1], oa->addr16[1], u),
+ ooa.addr16[2], oa->addr16[2], u),
+ ooa.addr16[3], oa->addr16[3], u),
+ ooa.addr16[4], oa->addr16[4], u),
+ ooa.addr16[5], oa->addr16[5], u),
+ ooa.addr16[6], oa->addr16[6], u),
+ ooa.addr16[7], oa->addr16[7], u);
+ break;
+#endif /* INET6 */
+ }
+}
+
+
+/*
+ * Need to modulate the sequence numbers in the TCP SACK option
+ * (credits to Krzysztof Pfaff for report and patch)
+ */
+int
+pf_modulate_sack(struct mbuf *m, int off, struct pf_pdesc *pd,
+ struct tcphdr *th, struct pf_state_peer *dst)
+{
+ int hlen = (th->th_off << 2) - sizeof(*th), thoptlen = hlen;
+#ifdef __FreeBSD__
+ u_int8_t opts[TCP_MAXOLEN], *opt = opts;
+#else
+ u_int8_t opts[MAX_TCPOPTLEN], *opt = opts;
+#endif
+ int copyback = 0, i, olen;
+ struct sackblk sack;
+
+#define TCPOLEN_SACKLEN (TCPOLEN_SACK + 2)
+ if (hlen < TCPOLEN_SACKLEN ||
+ !pf_pull_hdr(m, off + sizeof(*th), opts, hlen, NULL, NULL, pd->af))
+ return 0;
+
+ while (hlen >= TCPOLEN_SACKLEN) {
+ olen = opt[1];
+ switch (*opt) {
+ case TCPOPT_EOL: /* FALLTHROUGH */
+ case TCPOPT_NOP:
+ opt++;
+ hlen--;
+ break;
+ case TCPOPT_SACK:
+ if (olen > hlen)
+ olen = hlen;
+ if (olen >= TCPOLEN_SACKLEN) {
+ for (i = 2; i + TCPOLEN_SACK <= olen;
+ i += TCPOLEN_SACK) {
+ memcpy(&sack, &opt[i], sizeof(sack));
+ pf_change_a(&sack.start, &th->th_sum,
+ htonl(ntohl(sack.start) -
+ dst->seqdiff), 0);
+ pf_change_a(&sack.end, &th->th_sum,
+ htonl(ntohl(sack.end) -
+ dst->seqdiff), 0);
+ memcpy(&opt[i], &sack, sizeof(sack));
+ }
+ copyback = 1;
+ }
+ /* FALLTHROUGH */
+ default:
+ if (olen < 2)
+ olen = 2;
+ hlen -= olen;
+ opt += olen;
+ }
+ }
+
+ if (copyback)
+#ifdef __FreeBSD__
+ m_copyback(m, off + sizeof(*th), thoptlen, (caddr_t)opts);
+#else
+ m_copyback(m, off + sizeof(*th), thoptlen, opts);
+#endif
+ return (copyback);
+}
+
+void
+#ifdef __FreeBSD__
+pf_send_tcp(struct mbuf *replyto, const struct pf_rule *r, sa_family_t af,
+#else
+pf_send_tcp(const struct pf_rule *r, sa_family_t af,
+#endif
+ const struct pf_addr *saddr, const struct pf_addr *daddr,
+ u_int16_t sport, u_int16_t dport, u_int32_t seq, u_int32_t ack,
+ u_int8_t flags, u_int16_t win, u_int16_t mss, u_int8_t ttl, int tag,
+ u_int16_t rtag, struct ether_header *eh, struct ifnet *ifp)
+{
+ struct mbuf *m;
+ int len, tlen;
+#ifdef INET
+ struct ip *h;
+#endif /* INET */
+#ifdef INET6
+ struct ip6_hdr *h6;
+#endif /* INET6 */
+ struct tcphdr *th;
+ char *opt;
+ struct pf_mtag *pf_mtag;
+
+#ifdef __FreeBSD__
+ KASSERT(
+#ifdef INET
+ af == AF_INET
+#else
+ 0
+#endif
+ ||
+#ifdef INET6
+ af == AF_INET6
+#else
+ 0
+#endif
+ , ("Unsupported AF %d", af));
+ len = 0;
+ th = NULL;
+#ifdef INET
+ h = NULL;
+#endif
+#ifdef INET6
+ h6 = NULL;
+#endif
+#endif
+
+ /* maximum segment size tcp option */
+ tlen = sizeof(struct tcphdr);
+ if (mss)
+ tlen += 4;
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ len = sizeof(struct ip) + tlen;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ len = sizeof(struct ip6_hdr) + tlen;
+ break;
+#endif /* INET6 */
+ }
+
+ /* create outgoing mbuf */
+ m = m_gethdr(M_DONTWAIT, MT_HEADER);
+ if (m == NULL)
+ return;
+#ifdef __FreeBSD__
+#ifdef MAC
+ if (replyto)
+ mac_netinet_firewall_reply(replyto, m);
+ else
+ mac_netinet_firewall_send(m);
+#else
+ (void)replyto;
+#endif
+#endif
+ if ((pf_mtag = pf_get_mtag(m)) == NULL) {
+ m_freem(m);
+ return;
+ }
+ if (tag)
+#ifdef __FreeBSD__
+ m->m_flags |= M_SKIP_FIREWALL;
+#else
+ pf_mtag->flags |= PF_TAG_GENERATED;
+#endif
+
+ pf_mtag->tag = rtag;
+
+ if (r != NULL && r->rtableid >= 0)
+#ifdef __FreeBSD__
+ {
+ M_SETFIB(m, r->rtableid);
+#endif
+ pf_mtag->rtableid = r->rtableid;
+#ifdef __FreeBSD__
+ }
+#endif
+#ifdef ALTQ
+ if (r != NULL && r->qid) {
+ pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pf_mtag->af = af;
+ pf_mtag->hdr = mtod(m, struct ip *);
+ }
+#endif /* ALTQ */
+ m->m_data += max_linkhdr;
+ m->m_pkthdr.len = m->m_len = len;
+ m->m_pkthdr.rcvif = NULL;
+ bzero(m->m_data, len);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ h = mtod(m, struct ip *);
+
+ /* IP header fields included in the TCP checksum */
+ h->ip_p = IPPROTO_TCP;
+ h->ip_len = htons(tlen);
+ h->ip_src.s_addr = saddr->v4.s_addr;
+ h->ip_dst.s_addr = daddr->v4.s_addr;
+
+ th = (struct tcphdr *)((caddr_t)h + sizeof(struct ip));
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ h6 = mtod(m, struct ip6_hdr *);
+
+ /* IP header fields included in the TCP checksum */
+ h6->ip6_nxt = IPPROTO_TCP;
+ h6->ip6_plen = htons(tlen);
+ memcpy(&h6->ip6_src, &saddr->v6, sizeof(struct in6_addr));
+ memcpy(&h6->ip6_dst, &daddr->v6, sizeof(struct in6_addr));
+
+ th = (struct tcphdr *)((caddr_t)h6 + sizeof(struct ip6_hdr));
+ break;
+#endif /* INET6 */
+ }
+
+ /* TCP header */
+ th->th_sport = sport;
+ th->th_dport = dport;
+ th->th_seq = htonl(seq);
+ th->th_ack = htonl(ack);
+ th->th_off = tlen >> 2;
+ th->th_flags = flags;
+ th->th_win = htons(win);
+
+ if (mss) {
+ opt = (char *)(th + 1);
+ opt[0] = TCPOPT_MAXSEG;
+ opt[1] = 4;
+ HTONS(mss);
+ bcopy((caddr_t)&mss, (caddr_t)(opt + 2), 2);
+ }
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ /* TCP checksum */
+ th->th_sum = in_cksum(m, len);
+
+ /* Finish the IP header */
+ h->ip_v = 4;
+ h->ip_hl = sizeof(*h) >> 2;
+ h->ip_tos = IPTOS_LOWDELAY;
+#ifdef __FreeBSD__
+ h->ip_off = V_path_mtu_discovery ? IP_DF : 0;
+ h->ip_len = len;
+#else
+ h->ip_off = htons(ip_mtudisc ? IP_DF : 0);
+ h->ip_len = htons(len);
+#endif
+ h->ip_ttl = ttl ? ttl : V_ip_defttl;
+ h->ip_sum = 0;
+ if (eh == NULL) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ ip_output(m, (void *)NULL, (void *)NULL, 0,
+ (void *)NULL, (void *)NULL);
+ PF_LOCK();
+#else /* ! __FreeBSD__ */
+ ip_output(m, (void *)NULL, (void *)NULL, 0,
+ (void *)NULL, (void *)NULL);
+#endif
+ } else {
+ struct route ro;
+ struct rtentry rt;
+ struct ether_header *e = (void *)ro.ro_dst.sa_data;
+
+ if (ifp == NULL) {
+ m_freem(m);
+ return;
+ }
+ rt.rt_ifp = ifp;
+ ro.ro_rt = &rt;
+ ro.ro_dst.sa_len = sizeof(ro.ro_dst);
+ ro.ro_dst.sa_family = pseudo_AF_HDRCMPLT;
+ bcopy(eh->ether_dhost, e->ether_shost, ETHER_ADDR_LEN);
+ bcopy(eh->ether_shost, e->ether_dhost, ETHER_ADDR_LEN);
+ e->ether_type = eh->ether_type;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ /* XXX_IMPORT: later */
+ ip_output(m, (void *)NULL, &ro, 0,
+ (void *)NULL, (void *)NULL);
+ PF_LOCK();
+#else /* ! __FreeBSD__ */
+ ip_output(m, (void *)NULL, &ro, IP_ROUTETOETHER,
+ (void *)NULL, (void *)NULL);
+#endif
+ }
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ /* TCP checksum */
+ th->th_sum = in6_cksum(m, IPPROTO_TCP,
+ sizeof(struct ip6_hdr), tlen);
+
+ h6->ip6_vfc |= IPV6_VERSION;
+ h6->ip6_hlim = IPV6_DEFHLIM;
+
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
+ PF_LOCK();
+#else
+ ip6_output(m, NULL, NULL, 0, NULL, NULL);
+#endif
+ break;
+#endif /* INET6 */
+ }
+}
+
+void
+pf_send_icmp(struct mbuf *m, u_int8_t type, u_int8_t code, sa_family_t af,
+ struct pf_rule *r)
+{
+ struct pf_mtag *pf_mtag;
+ struct mbuf *m0;
+#ifdef __FreeBSD__
+ struct ip *ip;
+#endif
+
+#ifdef __FreeBSD__
+ m0 = m_copypacket(m, M_DONTWAIT);
+ if (m0 == NULL)
+ return;
+#else
+ m0 = m_copy(m, 0, M_COPYALL);
+#endif
+ if ((pf_mtag = pf_get_mtag(m0)) == NULL)
+ return;
+#ifdef __FreeBSD__
+ /* XXX: revisit */
+ m0->m_flags |= M_SKIP_FIREWALL;
+#else
+ pf_mtag->flags |= PF_TAG_GENERATED;
+#endif
+
+ if (r->rtableid >= 0)
+#ifdef __FreeBSD__
+ {
+ M_SETFIB(m0, r->rtableid);
+#endif
+ pf_mtag->rtableid = r->rtableid;
+#ifdef __FreeBSD__
+ }
+#endif
+
+#ifdef ALTQ
+ if (r->qid) {
+ pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pf_mtag->af = af;
+ pf_mtag->hdr = mtod(m0, struct ip *);
+ }
+#endif /* ALTQ */
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+#ifdef __FreeBSD__
+ /* icmp_error() expects host byte ordering */
+ ip = mtod(m0, struct ip *);
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+ PF_UNLOCK();
+ icmp_error(m0, type, code, 0, 0);
+ PF_LOCK();
+#else
+ icmp_error(m0, type, code, 0, 0);
+#endif
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ icmp6_error(m0, type, code, 0);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ break;
+#endif /* INET6 */
+ }
+}
+
+/*
+ * Return 1 if the addresses a and b match (with mask m), otherwise return 0.
+ * If n is 0, they match if they are equal. If n is != 0, they match if they
+ * are different.
+ */
+int
+pf_match_addr(u_int8_t n, struct pf_addr *a, struct pf_addr *m,
+ struct pf_addr *b, sa_family_t af)
+{
+ int match = 0;
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ if ((a->addr32[0] & m->addr32[0]) ==
+ (b->addr32[0] & m->addr32[0]))
+ match++;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (((a->addr32[0] & m->addr32[0]) ==
+ (b->addr32[0] & m->addr32[0])) &&
+ ((a->addr32[1] & m->addr32[1]) ==
+ (b->addr32[1] & m->addr32[1])) &&
+ ((a->addr32[2] & m->addr32[2]) ==
+ (b->addr32[2] & m->addr32[2])) &&
+ ((a->addr32[3] & m->addr32[3]) ==
+ (b->addr32[3] & m->addr32[3])))
+ match++;
+ break;
+#endif /* INET6 */
+ }
+ if (match) {
+ if (n)
+ return (0);
+ else
+ return (1);
+ } else {
+ if (n)
+ return (1);
+ else
+ return (0);
+ }
+}
+
+int
+pf_match(u_int8_t op, u_int32_t a1, u_int32_t a2, u_int32_t p)
+{
+ switch (op) {
+ case PF_OP_IRG:
+ return ((p > a1) && (p < a2));
+ case PF_OP_XRG:
+ return ((p < a1) || (p > a2));
+ case PF_OP_RRG:
+ return ((p >= a1) && (p <= a2));
+ case PF_OP_EQ:
+ return (p == a1);
+ case PF_OP_NE:
+ return (p != a1);
+ case PF_OP_LT:
+ return (p < a1);
+ case PF_OP_LE:
+ return (p <= a1);
+ case PF_OP_GT:
+ return (p > a1);
+ case PF_OP_GE:
+ return (p >= a1);
+ }
+ return (0); /* never reached */
+}
+
+int
+pf_match_port(u_int8_t op, u_int16_t a1, u_int16_t a2, u_int16_t p)
+{
+ NTOHS(a1);
+ NTOHS(a2);
+ NTOHS(p);
+ return (pf_match(op, a1, a2, p));
+}
+
+int
+pf_match_uid(u_int8_t op, uid_t a1, uid_t a2, uid_t u)
+{
+ if (u == UID_MAX && op != PF_OP_EQ && op != PF_OP_NE)
+ return (0);
+ return (pf_match(op, a1, a2, u));
+}
+
+int
+pf_match_gid(u_int8_t op, gid_t a1, gid_t a2, gid_t g)
+{
+ if (g == GID_MAX && op != PF_OP_EQ && op != PF_OP_NE)
+ return (0);
+ return (pf_match(op, a1, a2, g));
+}
+
+#ifndef __FreeBSD__
+struct pf_mtag *
+pf_find_mtag(struct mbuf *m)
+{
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL)
+ return (NULL);
+
+ return ((struct pf_mtag *)(mtag + 1));
+}
+
+struct pf_mtag *
+pf_get_mtag(struct mbuf *m)
+{
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL) {
+ mtag = m_tag_get(PACKET_TAG_PF, sizeof(struct pf_mtag),
+ M_NOWAIT);
+ if (mtag == NULL)
+ return (NULL);
+ bzero(mtag + 1, sizeof(struct pf_mtag));
+ m_tag_prepend(m, mtag);
+ }
+
+ return ((struct pf_mtag *)(mtag + 1));
+}
+#endif
+
+int
+pf_match_tag(struct mbuf *m, struct pf_rule *r, struct pf_mtag *pf_mtag,
+ int *tag)
+{
+ if (*tag == -1)
+ *tag = pf_mtag->tag;
+
+ return ((!r->match_tag_not && r->match_tag == *tag) ||
+ (r->match_tag_not && r->match_tag != *tag));
+}
+
+int
+pf_tag_packet(struct mbuf *m, struct pf_mtag *pf_mtag, int tag, int rtableid)
+{
+ if (tag <= 0 && rtableid < 0)
+ return (0);
+
+ if (pf_mtag == NULL)
+ if ((pf_mtag = pf_get_mtag(m)) == NULL)
+ return (1);
+ if (tag > 0)
+ pf_mtag->tag = tag;
+ if (rtableid >= 0)
+#ifdef __FreeBSD__
+ {
+ M_SETFIB(m, rtableid);
+#endif
+ pf_mtag->rtableid = rtableid;
+#ifdef __FreeBSD__
+ }
+#endif
+
+ return (0);
+}
+
+static void
+pf_step_into_anchor(int *depth, struct pf_ruleset **rs, int n,
+ struct pf_rule **r, struct pf_rule **a, int *match)
+{
+ struct pf_anchor_stackframe *f;
+
+ (*r)->anchor->match = 0;
+ if (match)
+ *match = 0;
+ if (*depth >= sizeof(pf_anchor_stack) /
+ sizeof(pf_anchor_stack[0])) {
+ printf("pf_step_into_anchor: stack overflow\n");
+ *r = TAILQ_NEXT(*r, entries);
+ return;
+ } else if (*depth == 0 && a != NULL)
+ *a = *r;
+ f = pf_anchor_stack + (*depth)++;
+ f->rs = *rs;
+ f->r = *r;
+ if ((*r)->anchor_wildcard) {
+ f->parent = &(*r)->anchor->children;
+ if ((f->child = RB_MIN(pf_anchor_node, f->parent)) ==
+ NULL) {
+ *r = NULL;
+ return;
+ }
+ *rs = &f->child->ruleset;
+ } else {
+ f->parent = NULL;
+ f->child = NULL;
+ *rs = &(*r)->anchor->ruleset;
+ }
+ *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
+}
+
+int
+pf_step_out_of_anchor(int *depth, struct pf_ruleset **rs, int n,
+ struct pf_rule **r, struct pf_rule **a, int *match)
+{
+ struct pf_anchor_stackframe *f;
+ int quick = 0;
+
+ do {
+ if (*depth <= 0)
+ break;
+ f = pf_anchor_stack + *depth - 1;
+ if (f->parent != NULL && f->child != NULL) {
+ if (f->child->match ||
+ (match != NULL && *match)) {
+ f->r->anchor->match = 1;
+ *match = 0;
+ }
+ f->child = RB_NEXT(pf_anchor_node, f->parent, f->child);
+ if (f->child != NULL) {
+ *rs = &f->child->ruleset;
+ *r = TAILQ_FIRST((*rs)->rules[n].active.ptr);
+ if (*r == NULL)
+ continue;
+ else
+ break;
+ }
+ }
+ (*depth)--;
+ if (*depth == 0 && a != NULL)
+ *a = NULL;
+ *rs = f->rs;
+ if (f->r->anchor->match || (match != NULL && *match))
+ quick = f->r->quick;
+ *r = TAILQ_NEXT(f->r, entries);
+ } while (*r == NULL);
+
+ return (quick);
+}
+
+#ifdef INET6
+void
+pf_poolmask(struct pf_addr *naddr, struct pf_addr *raddr,
+ struct pf_addr *rmask, struct pf_addr *saddr, sa_family_t af)
+{
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
+ ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
+ break;
+#endif /* INET */
+ case AF_INET6:
+ naddr->addr32[0] = (raddr->addr32[0] & rmask->addr32[0]) |
+ ((rmask->addr32[0] ^ 0xffffffff ) & saddr->addr32[0]);
+ naddr->addr32[1] = (raddr->addr32[1] & rmask->addr32[1]) |
+ ((rmask->addr32[1] ^ 0xffffffff ) & saddr->addr32[1]);
+ naddr->addr32[2] = (raddr->addr32[2] & rmask->addr32[2]) |
+ ((rmask->addr32[2] ^ 0xffffffff ) & saddr->addr32[2]);
+ naddr->addr32[3] = (raddr->addr32[3] & rmask->addr32[3]) |
+ ((rmask->addr32[3] ^ 0xffffffff ) & saddr->addr32[3]);
+ break;
+ }
+}
+
+void
+pf_addr_inc(struct pf_addr *addr, sa_family_t af)
+{
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ addr->addr32[0] = htonl(ntohl(addr->addr32[0]) + 1);
+ break;
+#endif /* INET */
+ case AF_INET6:
+ if (addr->addr32[3] == 0xffffffff) {
+ addr->addr32[3] = 0;
+ if (addr->addr32[2] == 0xffffffff) {
+ addr->addr32[2] = 0;
+ if (addr->addr32[1] == 0xffffffff) {
+ addr->addr32[1] = 0;
+ addr->addr32[0] =
+ htonl(ntohl(addr->addr32[0]) + 1);
+ } else
+ addr->addr32[1] =
+ htonl(ntohl(addr->addr32[1]) + 1);
+ } else
+ addr->addr32[2] =
+ htonl(ntohl(addr->addr32[2]) + 1);
+ } else
+ addr->addr32[3] =
+ htonl(ntohl(addr->addr32[3]) + 1);
+ break;
+ }
+}
+#endif /* INET6 */
+
+#define mix(a,b,c) \
+ do { \
+ a -= b; a -= c; a ^= (c >> 13); \
+ b -= c; b -= a; b ^= (a << 8); \
+ c -= a; c -= b; c ^= (b >> 13); \
+ a -= b; a -= c; a ^= (c >> 12); \
+ b -= c; b -= a; b ^= (a << 16); \
+ c -= a; c -= b; c ^= (b >> 5); \
+ a -= b; a -= c; a ^= (c >> 3); \
+ b -= c; b -= a; b ^= (a << 10); \
+ c -= a; c -= b; c ^= (b >> 15); \
+ } while (0)
+
+/*
+ * hash function based on bridge_hash in if_bridge.c
+ */
+void
+pf_hash(struct pf_addr *inaddr, struct pf_addr *hash,
+ struct pf_poolhashkey *key, sa_family_t af)
+{
+ u_int32_t a = 0x9e3779b9, b = 0x9e3779b9, c = key->key32[0];
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ a += inaddr->addr32[0];
+ b += key->key32[1];
+ mix(a, b, c);
+ hash->addr32[0] = c + key->key32[2];
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ a += inaddr->addr32[0];
+ b += inaddr->addr32[2];
+ mix(a, b, c);
+ hash->addr32[0] = c;
+ a += inaddr->addr32[1];
+ b += inaddr->addr32[3];
+ c += key->key32[1];
+ mix(a, b, c);
+ hash->addr32[1] = c;
+ a += inaddr->addr32[2];
+ b += inaddr->addr32[1];
+ c += key->key32[2];
+ mix(a, b, c);
+ hash->addr32[2] = c;
+ a += inaddr->addr32[3];
+ b += inaddr->addr32[0];
+ c += key->key32[3];
+ mix(a, b, c);
+ hash->addr32[3] = c;
+ break;
+#endif /* INET6 */
+ }
+}
+
+int
+pf_map_addr(sa_family_t af, struct pf_rule *r, struct pf_addr *saddr,
+ struct pf_addr *naddr, struct pf_addr *init_addr, struct pf_src_node **sn)
+{
+ unsigned char hash[16];
+ struct pf_pool *rpool = &r->rpool;
+ struct pf_addr *raddr = &rpool->cur->addr.v.a.addr;
+ struct pf_addr *rmask = &rpool->cur->addr.v.a.mask;
+ struct pf_pooladdr *acur = rpool->cur;
+ struct pf_src_node k;
+
+ if (*sn == NULL && r->rpool.opts & PF_POOL_STICKYADDR &&
+ (r->rpool.opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
+ k.af = af;
+ PF_ACPY(&k.addr, saddr, af);
+ if (r->rule_flag & PFRULE_RULESRCTRACK ||
+ r->rpool.opts & PF_POOL_STICKYADDR)
+ k.rule.ptr = r;
+ else
+ k.rule.ptr = NULL;
+ pf_status.scounters[SCNT_SRC_NODE_SEARCH]++;
+ *sn = RB_FIND(pf_src_tree, &tree_src_tracking, &k);
+ if (*sn != NULL && !PF_AZERO(&(*sn)->raddr, af)) {
+ PF_ACPY(naddr, &(*sn)->raddr, af);
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf_map_addr: src tracking maps ");
+ pf_print_host(&k.addr, 0, af);
+ printf(" to ");
+ pf_print_host(naddr, 0, af);
+ printf("\n");
+ }
+ return (0);
+ }
+ }
+
+ if (rpool->cur->addr.type == PF_ADDR_NOROUTE)
+ return (1);
+ if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ if (rpool->cur->addr.p.dyn->pfid_acnt4 < 1 &&
+ (rpool->opts & PF_POOL_TYPEMASK) !=
+ PF_POOL_ROUNDROBIN)
+ return (1);
+ raddr = &rpool->cur->addr.p.dyn->pfid_addr4;
+ rmask = &rpool->cur->addr.p.dyn->pfid_mask4;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (rpool->cur->addr.p.dyn->pfid_acnt6 < 1 &&
+ (rpool->opts & PF_POOL_TYPEMASK) !=
+ PF_POOL_ROUNDROBIN)
+ return (1);
+ raddr = &rpool->cur->addr.p.dyn->pfid_addr6;
+ rmask = &rpool->cur->addr.p.dyn->pfid_mask6;
+ break;
+#endif /* INET6 */
+ }
+ } else if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+ if ((rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_ROUNDROBIN)
+ return (1); /* unsupported */
+ } else {
+ raddr = &rpool->cur->addr.v.a.addr;
+ rmask = &rpool->cur->addr.v.a.mask;
+ }
+
+ switch (rpool->opts & PF_POOL_TYPEMASK) {
+ case PF_POOL_NONE:
+ PF_ACPY(naddr, raddr, af);
+ break;
+ case PF_POOL_BITMASK:
+ PF_POOLMASK(naddr, raddr, rmask, saddr, af);
+ break;
+ case PF_POOL_RANDOM:
+ if (init_addr != NULL && PF_AZERO(init_addr, af)) {
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ rpool->counter.addr32[0] = htonl(arc4random());
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (rmask->addr32[3] != 0xffffffff)
+ rpool->counter.addr32[3] =
+ htonl(arc4random());
+ else
+ break;
+ if (rmask->addr32[2] != 0xffffffff)
+ rpool->counter.addr32[2] =
+ htonl(arc4random());
+ else
+ break;
+ if (rmask->addr32[1] != 0xffffffff)
+ rpool->counter.addr32[1] =
+ htonl(arc4random());
+ else
+ break;
+ if (rmask->addr32[0] != 0xffffffff)
+ rpool->counter.addr32[0] =
+ htonl(arc4random());
+ break;
+#endif /* INET6 */
+ }
+ PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
+ PF_ACPY(init_addr, naddr, af);
+
+ } else {
+ PF_AINC(&rpool->counter, af);
+ PF_POOLMASK(naddr, raddr, rmask, &rpool->counter, af);
+ }
+ break;
+ case PF_POOL_SRCHASH:
+ pf_hash(saddr, (struct pf_addr *)&hash, &rpool->key, af);
+ PF_POOLMASK(naddr, raddr, rmask, (struct pf_addr *)&hash, af);
+ break;
+ case PF_POOL_ROUNDROBIN:
+ if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+ if (!pfr_pool_get(rpool->cur->addr.p.tbl,
+ &rpool->tblidx, &rpool->counter,
+ &raddr, &rmask, af))
+ goto get_addr;
+ } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+ if (!pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
+ &rpool->tblidx, &rpool->counter,
+ &raddr, &rmask, af))
+ goto get_addr;
+ } else if (pf_match_addr(0, raddr, rmask, &rpool->counter, af))
+ goto get_addr;
+
+ try_next:
+ if ((rpool->cur = TAILQ_NEXT(rpool->cur, entries)) == NULL)
+ rpool->cur = TAILQ_FIRST(&rpool->list);
+ if (rpool->cur->addr.type == PF_ADDR_TABLE) {
+ rpool->tblidx = -1;
+ if (pfr_pool_get(rpool->cur->addr.p.tbl,
+ &rpool->tblidx, &rpool->counter,
+ &raddr, &rmask, af)) {
+ /* table contains no address of type 'af' */
+ if (rpool->cur != acur)
+ goto try_next;
+ return (1);
+ }
+ } else if (rpool->cur->addr.type == PF_ADDR_DYNIFTL) {
+ rpool->tblidx = -1;
+ if (pfr_pool_get(rpool->cur->addr.p.dyn->pfid_kt,
+ &rpool->tblidx, &rpool->counter,
+ &raddr, &rmask, af)) {
+ /* table contains no address of type 'af' */
+ if (rpool->cur != acur)
+ goto try_next;
+ return (1);
+ }
+ } else {
+ raddr = &rpool->cur->addr.v.a.addr;
+ rmask = &rpool->cur->addr.v.a.mask;
+ PF_ACPY(&rpool->counter, raddr, af);
+ }
+
+ get_addr:
+ PF_ACPY(naddr, &rpool->counter, af);
+ if (init_addr != NULL && PF_AZERO(init_addr, af))
+ PF_ACPY(init_addr, naddr, af);
+ PF_AINC(&rpool->counter, af);
+ break;
+ }
+ if (*sn != NULL)
+ PF_ACPY(&(*sn)->raddr, naddr, af);
+
+ if (pf_status.debug >= PF_DEBUG_MISC &&
+ (rpool->opts & PF_POOL_TYPEMASK) != PF_POOL_NONE) {
+ printf("pf_map_addr: selected address ");
+ pf_print_host(naddr, 0, af);
+ printf("\n");
+ }
+
+ return (0);
+}
+
+int
+pf_get_sport(sa_family_t af, u_int8_t proto, struct pf_rule *r,
+ struct pf_addr *saddr, struct pf_addr *daddr, u_int16_t dport,
+ struct pf_addr *naddr, u_int16_t *nport, u_int16_t low, u_int16_t high,
+ struct pf_src_node **sn)
+{
+ struct pf_state_cmp key;
+ struct pf_addr init_addr;
+ u_int16_t cut;
+
+ bzero(&init_addr, sizeof(init_addr));
+ if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+ return (1);
+
+ if (proto == IPPROTO_ICMP) {
+ low = 1;
+ high = 65535;
+ }
+
+ do {
+ key.af = af;
+ key.proto = proto;
+ PF_ACPY(&key.ext.addr, daddr, key.af);
+ PF_ACPY(&key.gwy.addr, naddr, key.af);
+ key.ext.port = dport;
+
+ /*
+ * port search; start random, step;
+ * similar 2 portloop in in_pcbbind
+ */
+ if (!(proto == IPPROTO_TCP || proto == IPPROTO_UDP ||
+ proto == IPPROTO_ICMP)) {
+ key.gwy.port = dport;
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
+ return (0);
+ } else if (low == 0 && high == 0) {
+ key.gwy.port = *nport;
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL)
+ return (0);
+ } else if (low == high) {
+ key.gwy.port = htons(low);
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) == NULL) {
+ *nport = htons(low);
+ return (0);
+ }
+ } else {
+ u_int16_t tmp;
+
+ if (low > high) {
+ tmp = low;
+ low = high;
+ high = tmp;
+ }
+ /* low < high */
+ cut = htonl(arc4random()) % (1 + high - low) + low;
+ /* low <= cut <= high */
+ for (tmp = cut; tmp <= high; ++(tmp)) {
+ key.gwy.port = htons(tmp);
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
+ NULL) {
+ *nport = htons(tmp);
+ return (0);
+ }
+ }
+ for (tmp = cut - 1; tmp >= low; --(tmp)) {
+ key.gwy.port = htons(tmp);
+ if (pf_find_state_all(&key, PF_EXT_GWY, NULL) ==
+ NULL) {
+ *nport = htons(tmp);
+ return (0);
+ }
+ }
+ }
+
+ switch (r->rpool.opts & PF_POOL_TYPEMASK) {
+ case PF_POOL_RANDOM:
+ case PF_POOL_ROUNDROBIN:
+ if (pf_map_addr(af, r, saddr, naddr, &init_addr, sn))
+ return (1);
+ break;
+ case PF_POOL_NONE:
+ case PF_POOL_SRCHASH:
+ case PF_POOL_BITMASK:
+ default:
+ return (1);
+ }
+ } while (! PF_AEQ(&init_addr, naddr, af) );
+
+ return (1); /* none available */
+}
+
+struct pf_rule *
+pf_match_translation(struct pf_pdesc *pd, struct mbuf *m, int off,
+ int direction, struct pfi_kif *kif, struct pf_addr *saddr, u_int16_t sport,
+ struct pf_addr *daddr, u_int16_t dport, int rs_num)
+{
+ struct pf_rule *r, *rm = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ int tag = -1;
+ int rtableid = -1;
+ int asd = 0;
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[rs_num].active.ptr);
+ while (r && rm == NULL) {
+ struct pf_rule_addr *src = NULL, *dst = NULL;
+ struct pf_addr_wrap *xdst = NULL;
+
+ if (r->action == PF_BINAT && direction == PF_IN) {
+ src = &r->dst;
+ if (r->rpool.cur != NULL)
+ xdst = &r->rpool.cur->addr;
+ } else {
+ src = &r->src;
+ dst = &r->dst;
+ }
+
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != direction)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != pd->af)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != pd->proto)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&src->addr, saddr, pd->af,
+ src->neg, kif))
+ r = r->skip[src == &r->src ? PF_SKIP_SRC_ADDR :
+ PF_SKIP_DST_ADDR].ptr;
+ else if (src->port_op && !pf_match_port(src->port_op,
+ src->port[0], src->port[1], sport))
+ r = r->skip[src == &r->src ? PF_SKIP_SRC_PORT :
+ PF_SKIP_DST_PORT].ptr;
+ else if (dst != NULL &&
+ PF_MISMATCHAW(&dst->addr, daddr, pd->af, dst->neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else if (xdst != NULL && PF_MISMATCHAW(xdst, daddr, pd->af,
+ 0, NULL))
+ r = TAILQ_NEXT(r, entries);
+ else if (dst != NULL && dst->port_op &&
+ !pf_match_port(dst->port_op, dst->port[0],
+ dst->port[1], dport))
+ r = r->skip[PF_SKIP_DST_PORT].ptr;
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->os_fingerprint != PF_OSFP_ANY && (pd->proto !=
+ IPPROTO_TCP || !pf_osfp_match(pf_osfp_fingerprint(pd, m,
+ off, pd->hdr.tcp), r->os_fingerprint)))
+ r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->tag)
+ tag = r->tag;
+ if (r->rtableid >= 0)
+ rtableid = r->rtableid;
+ if (r->anchor == NULL) {
+ rm = r;
+ } else
+ pf_step_into_anchor(&asd, &ruleset, rs_num,
+ &r, NULL, NULL);
+ }
+ if (r == NULL)
+ pf_step_out_of_anchor(&asd, &ruleset, rs_num, &r,
+ NULL, NULL);
+ }
+ if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid))
+ return (NULL);
+ if (rm != NULL && (rm->action == PF_NONAT ||
+ rm->action == PF_NORDR || rm->action == PF_NOBINAT))
+ return (NULL);
+ return (rm);
+}
+
+struct pf_rule *
+pf_get_translation(struct pf_pdesc *pd, struct mbuf *m, int off, int direction,
+ struct pfi_kif *kif, struct pf_src_node **sn,
+ struct pf_addr *saddr, u_int16_t sport,
+ struct pf_addr *daddr, u_int16_t dport,
+ struct pf_addr *naddr, u_int16_t *nport)
+{
+ struct pf_rule *r = NULL;
+
+ if (direction == PF_OUT) {
+ r = pf_match_translation(pd, m, off, direction, kif, saddr,
+ sport, daddr, dport, PF_RULESET_BINAT);
+ if (r == NULL)
+ r = pf_match_translation(pd, m, off, direction, kif,
+ saddr, sport, daddr, dport, PF_RULESET_NAT);
+ } else {
+ r = pf_match_translation(pd, m, off, direction, kif, saddr,
+ sport, daddr, dport, PF_RULESET_RDR);
+ if (r == NULL)
+ r = pf_match_translation(pd, m, off, direction, kif,
+ saddr, sport, daddr, dport, PF_RULESET_BINAT);
+ }
+
+ if (r != NULL) {
+ switch (r->action) {
+ case PF_NONAT:
+ case PF_NOBINAT:
+ case PF_NORDR:
+ return (NULL);
+ case PF_NAT:
+ if (pf_get_sport(pd->af, pd->proto, r, saddr,
+ daddr, dport, naddr, nport, r->rpool.proxy_port[0],
+ r->rpool.proxy_port[1], sn)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: NAT proxy port allocation "
+ "(%u-%u) failed\n",
+ r->rpool.proxy_port[0],
+ r->rpool.proxy_port[1]));
+ return (NULL);
+ }
+ break;
+ case PF_BINAT:
+ switch (direction) {
+ case PF_OUT:
+ if (r->rpool.cur->addr.type == PF_ADDR_DYNIFTL){
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ if (r->rpool.cur->addr.p.dyn->
+ pfid_acnt4 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_addr4,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_mask4,
+ saddr, AF_INET);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (r->rpool.cur->addr.p.dyn->
+ pfid_acnt6 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_addr6,
+ &r->rpool.cur->addr.p.dyn->
+ pfid_mask6,
+ saddr, AF_INET6);
+ break;
+#endif /* INET6 */
+ }
+ } else
+ PF_POOLMASK(naddr,
+ &r->rpool.cur->addr.v.a.addr,
+ &r->rpool.cur->addr.v.a.mask,
+ saddr, pd->af);
+ break;
+ case PF_IN:
+ if (r->src.addr.type == PF_ADDR_DYNIFTL) {
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ if (r->src.addr.p.dyn->
+ pfid_acnt4 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->src.addr.p.dyn->
+ pfid_addr4,
+ &r->src.addr.p.dyn->
+ pfid_mask4,
+ daddr, AF_INET);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (r->src.addr.p.dyn->
+ pfid_acnt6 < 1)
+ return (NULL);
+ PF_POOLMASK(naddr,
+ &r->src.addr.p.dyn->
+ pfid_addr6,
+ &r->src.addr.p.dyn->
+ pfid_mask6,
+ daddr, AF_INET6);
+ break;
+#endif /* INET6 */
+ }
+ } else
+ PF_POOLMASK(naddr,
+ &r->src.addr.v.a.addr,
+ &r->src.addr.v.a.mask, daddr,
+ pd->af);
+ break;
+ }
+ break;
+ case PF_RDR: {
+ if (pf_map_addr(pd->af, r, saddr, naddr, NULL, sn))
+ return (NULL);
+ if ((r->rpool.opts & PF_POOL_TYPEMASK) ==
+ PF_POOL_BITMASK)
+ PF_POOLMASK(naddr, naddr,
+ &r->rpool.cur->addr.v.a.mask, daddr,
+ pd->af);
+
+ if (r->rpool.proxy_port[1]) {
+ u_int32_t tmp_nport;
+
+ tmp_nport = ((ntohs(dport) -
+ ntohs(r->dst.port[0])) %
+ (r->rpool.proxy_port[1] -
+ r->rpool.proxy_port[0] + 1)) +
+ r->rpool.proxy_port[0];
+
+ /* wrap around if necessary */
+ if (tmp_nport > 65535)
+ tmp_nport -= 65535;
+ *nport = htons((u_int16_t)tmp_nport);
+ } else if (r->rpool.proxy_port[0])
+ *nport = htons(r->rpool.proxy_port[0]);
+ break;
+ }
+ default:
+ return (NULL);
+ }
+ }
+
+ return (r);
+}
+
+int
+#ifdef __FreeBSD__
+pf_socket_lookup(int direction, struct pf_pdesc *pd, struct inpcb *inp_arg)
+#else
+pf_socket_lookup(int direction, struct pf_pdesc *pd)
+#endif
+{
+ struct pf_addr *saddr, *daddr;
+ u_int16_t sport, dport;
+#ifdef __FreeBSD__
+ struct inpcbinfo *pi;
+#else
+ struct inpcbtable *tb;
+#endif
+ struct inpcb *inp;
+
+ if (pd == NULL)
+ return (-1);
+ pd->lookup.uid = UID_MAX;
+ pd->lookup.gid = GID_MAX;
+ pd->lookup.pid = NO_PID; /* XXX: revisit */
+#ifdef __FreeBSD__
+ if (inp_arg != NULL) {
+ INP_LOCK_ASSERT(inp_arg);
+ pd->lookup.uid = inp_arg->inp_cred->cr_uid;
+ pd->lookup.gid = inp_arg->inp_cred->cr_groups[0];
+ return (1);
+ }
+#endif
+ switch (pd->proto) {
+ case IPPROTO_TCP:
+ if (pd->hdr.tcp == NULL)
+ return (-1);
+ sport = pd->hdr.tcp->th_sport;
+ dport = pd->hdr.tcp->th_dport;
+#ifdef __FreeBSD__
+ pi = &V_tcbinfo;
+#else
+ tb = &tcbtable;
+#endif
+ break;
+ case IPPROTO_UDP:
+ if (pd->hdr.udp == NULL)
+ return (-1);
+ sport = pd->hdr.udp->uh_sport;
+ dport = pd->hdr.udp->uh_dport;
+#ifdef __FreeBSD__
+ pi = &V_udbinfo;
+#else
+ tb = &udbtable;
+#endif
+ break;
+ default:
+ return (-1);
+ }
+ if (direction == PF_IN) {
+ saddr = pd->src;
+ daddr = pd->dst;
+ } else {
+ u_int16_t p;
+
+ p = sport;
+ sport = dport;
+ dport = p;
+ saddr = pd->dst;
+ daddr = pd->src;
+ }
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+#ifdef __FreeBSD__
+ INP_INFO_RLOCK(pi); /* XXX LOR */
+ inp = in_pcblookup_hash(pi, saddr->v4, sport, daddr->v4,
+ dport, 0, NULL);
+ if (inp == NULL) {
+ inp = in_pcblookup_hash(pi, saddr->v4, sport,
+ daddr->v4, dport, INPLOOKUP_WILDCARD, NULL);
+ if(inp == NULL) {
+ INP_INFO_RUNLOCK(pi);
+ return (-1);
+ }
+ }
+#else
+ inp = in_pcbhashlookup(tb, saddr->v4, sport, daddr->v4, dport);
+ if (inp == NULL) {
+ inp = in_pcblookup_listen(tb, daddr->v4, dport, 0);
+ if (inp == NULL)
+ return (-1);
+ }
+#endif
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+#ifdef __FreeBSD__
+ INP_INFO_RLOCK(pi);
+ inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
+ &daddr->v6, dport, 0, NULL);
+ if (inp == NULL) {
+ inp = in6_pcblookup_hash(pi, &saddr->v6, sport,
+ &daddr->v6, dport, INPLOOKUP_WILDCARD, NULL);
+ if (inp == NULL) {
+ INP_INFO_RUNLOCK(pi);
+ return (-1);
+ }
+ }
+#else
+ inp = in6_pcbhashlookup(tb, &saddr->v6, sport, &daddr->v6,
+ dport);
+ if (inp == NULL) {
+ inp = in6_pcblookup_listen(tb, &daddr->v6, dport, 0);
+ if (inp == NULL)
+ return (-1);
+ }
+#endif
+ break;
+#endif /* INET6 */
+
+ default:
+ return (-1);
+ }
+#ifdef __FreeBSD__
+ pd->lookup.uid = inp->inp_cred->cr_uid;
+ pd->lookup.gid = inp->inp_cred->cr_groups[0];
+ INP_INFO_RUNLOCK(pi);
+#else
+ pd->lookup.uid = inp->inp_socket->so_euid;
+ pd->lookup.gid = inp->inp_socket->so_egid;
+ pd->lookup.pid = inp->inp_socket->so_cpid;
+#endif
+ return (1);
+}
+
+u_int8_t
+pf_get_wscale(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
+{
+ int hlen;
+ u_int8_t hdr[60];
+ u_int8_t *opt, optlen;
+ u_int8_t wscale = 0;
+
+ hlen = th_off << 2; /* hlen <= sizeof(hdr) */
+ if (hlen <= sizeof(struct tcphdr))
+ return (0);
+ if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af))
+ return (0);
+ opt = hdr + sizeof(struct tcphdr);
+ hlen -= sizeof(struct tcphdr);
+ while (hlen >= 3) {
+ switch (*opt) {
+ case TCPOPT_EOL:
+ case TCPOPT_NOP:
+ ++opt;
+ --hlen;
+ break;
+ case TCPOPT_WINDOW:
+ wscale = opt[2];
+ if (wscale > TCP_MAX_WINSHIFT)
+ wscale = TCP_MAX_WINSHIFT;
+ wscale |= PF_WSCALE_FLAG;
+ /* FALLTHROUGH */
+ default:
+ optlen = opt[1];
+ if (optlen < 2)
+ optlen = 2;
+ hlen -= optlen;
+ opt += optlen;
+ break;
+ }
+ }
+ return (wscale);
+}
+
+u_int16_t
+pf_get_mss(struct mbuf *m, int off, u_int16_t th_off, sa_family_t af)
+{
+ int hlen;
+ u_int8_t hdr[60];
+ u_int8_t *opt, optlen;
+ u_int16_t mss = V_tcp_mssdflt;
+
+ hlen = th_off << 2; /* hlen <= sizeof(hdr) */
+ if (hlen <= sizeof(struct tcphdr))
+ return (0);
+ if (!pf_pull_hdr(m, off, hdr, hlen, NULL, NULL, af))
+ return (0);
+ opt = hdr + sizeof(struct tcphdr);
+ hlen -= sizeof(struct tcphdr);
+ while (hlen >= TCPOLEN_MAXSEG) {
+ switch (*opt) {
+ case TCPOPT_EOL:
+ case TCPOPT_NOP:
+ ++opt;
+ --hlen;
+ break;
+ case TCPOPT_MAXSEG:
+ bcopy((caddr_t)(opt + 2), (caddr_t)&mss, 2);
+ NTOHS(mss);
+ /* FALLTHROUGH */
+ default:
+ optlen = opt[1];
+ if (optlen < 2)
+ optlen = 2;
+ hlen -= optlen;
+ opt += optlen;
+ break;
+ }
+ }
+ return (mss);
+}
+
+u_int16_t
+pf_calc_mss(struct pf_addr *addr, sa_family_t af, u_int16_t offer)
+{
+#ifdef INET
+ struct sockaddr_in *dst;
+ struct route ro;
+#endif /* INET */
+#ifdef INET6
+ struct sockaddr_in6 *dst6;
+ struct route_in6 ro6;
+#endif /* INET6 */
+ struct rtentry *rt = NULL;
+ int hlen = 0; /* make the compiler happy */
+ u_int16_t mss = V_tcp_mssdflt;
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ hlen = sizeof(struct ip);
+ bzero(&ro, sizeof(ro));
+ dst = (struct sockaddr_in *)&ro.ro_dst;
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = addr->v4;
+#ifdef __FreeBSD__
+#ifdef RTF_PRCLONING
+ rtalloc_ign(&ro, (RTF_CLONING | RTF_PRCLONING));
+#else /* !RTF_PRCLONING */
+ in_rtalloc_ign(&ro, 0, 0);
+#endif
+#else /* ! __FreeBSD__ */
+ rtalloc_noclone(&ro, NO_CLONING);
+#endif
+ rt = ro.ro_rt;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ hlen = sizeof(struct ip6_hdr);
+ bzero(&ro6, sizeof(ro6));
+ dst6 = (struct sockaddr_in6 *)&ro6.ro_dst;
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(*dst6);
+ dst6->sin6_addr = addr->v6;
+#ifdef __FreeBSD__
+#ifdef RTF_PRCLONING
+ rtalloc_ign((struct route *)&ro6,
+ (RTF_CLONING | RTF_PRCLONING));
+#else /* !RTF_PRCLONING */
+ rtalloc_ign((struct route *)&ro6, 0);
+#endif
+#else /* ! __FreeBSD__ */
+ rtalloc_noclone((struct route *)&ro6, NO_CLONING);
+#endif
+ rt = ro6.ro_rt;
+ break;
+#endif /* INET6 */
+ }
+
+ if (rt && rt->rt_ifp) {
+ mss = rt->rt_ifp->if_mtu - hlen - sizeof(struct tcphdr);
+ mss = max(V_tcp_mssdflt, mss);
+ RTFREE(rt);
+ }
+ mss = min(mss, offer);
+ mss = max(mss, 64); /* sanity - at least max opt space */
+ return (mss);
+}
+
+void
+pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr)
+{
+ struct pf_rule *r = s->rule.ptr;
+
+ s->rt_kif = NULL;
+ if (!r->rt || r->rt == PF_FASTROUTE)
+ return;
+ switch (s->af) {
+#ifdef INET
+ case AF_INET:
+ pf_map_addr(AF_INET, r, saddr, &s->rt_addr, NULL,
+ &s->nat_src_node);
+ s->rt_kif = r->rpool.cur->kif;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ pf_map_addr(AF_INET6, r, saddr, &s->rt_addr, NULL,
+ &s->nat_src_node);
+ s->rt_kif = r->rpool.cur->kif;
+ break;
+#endif /* INET6 */
+ }
+}
+
+int
+pf_test_tcp(struct pf_rule **rm, struct pf_state **sm, int direction,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+#ifdef __FreeBSD__
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct ifqueue *ifq, struct inpcb *inp)
+#else
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct ifqueue *ifq)
+#endif
+{
+ struct pf_rule *nr = NULL;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct tcphdr *th = pd->hdr.tcp;
+ u_int16_t bport, nport = 0;
+ sa_family_t af = pd->af;
+ struct pf_rule *r, *a = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_src_node *nsn = NULL;
+ u_short reason;
+ int rewrite = 0;
+ int tag = -1, rtableid = -1;
+ u_int16_t mss = V_tcp_mssdflt;
+ int asd = 0;
+ int match = 0;
+
+ if (pf_check_congestion(ifq)) {
+ REASON_SET(&reason, PFRES_CONGEST);
+ return (PF_DROP);
+ }
+
+#ifdef __FreeBSD__
+ if (inp != NULL)
+ pd->lookup.done = pf_socket_lookup(direction, pd, inp);
+ else if (debug_pfugidhack) {
+ PF_UNLOCK();
+ DPFPRINTF(PF_DEBUG_MISC, ("pf: unlocked lookup\n"));
+ pd->lookup.done = pf_socket_lookup(direction, pd, inp);
+ PF_LOCK();
+ }
+#endif
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+
+ if (direction == PF_OUT) {
+ bport = nport = th->th_sport;
+ /* check outgoing packet for BINAT/NAT */
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
+ saddr, th->th_sport, daddr, th->th_dport,
+ &pd->naddr, &nport)) != NULL) {
+ PF_ACPY(&pd->baddr, saddr, af);
+ pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
+ &th->th_sum, &pd->naddr, nport, 0, af);
+ rewrite++;
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ } else {
+ bport = nport = th->th_dport;
+ /* check incoming packet for BINAT/RDR */
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
+ saddr, th->th_sport, daddr, th->th_dport,
+ &pd->naddr, &nport)) != NULL) {
+ PF_ACPY(&pd->baddr, daddr, af);
+ pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
+ &th->th_sum, &pd->naddr, nport, 0, af);
+ rewrite++;
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ }
+
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != direction)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != af)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != IPPROTO_TCP)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (r->src.port_op && !pf_match_port(r->src.port_op,
+ r->src.port[0], r->src.port[1], th->th_sport))
+ r = r->skip[PF_SKIP_SRC_PORT].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
+ r->dst.port[0], r->dst.port[1], th->th_dport))
+ r = r->skip[PF_SKIP_DST_PORT].ptr;
+ else if (r->tos && !(r->tos == pd->tos))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->rule_flag & PFRULE_FRAGMENT)
+ r = TAILQ_NEXT(r, entries);
+ else if ((r->flagset & th->th_flags) != r->flags)
+ r = TAILQ_NEXT(r, entries);
+ else if (r->uid.op && (pd->lookup.done || (pd->lookup.done =
+#ifdef __FreeBSD__
+ pf_socket_lookup(direction, pd, inp), 1)) &&
+#else
+ pf_socket_lookup(direction, pd), 1)) &&
+#endif
+ !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
+ pd->lookup.uid))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->gid.op && (pd->lookup.done || (pd->lookup.done =
+#ifdef __FreeBSD__
+ pf_socket_lookup(direction, pd, inp), 1)) &&
+#else
+ pf_socket_lookup(direction, pd), 1)) &&
+#endif
+ !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
+ pd->lookup.gid))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->prob && r->prob <= arc4random())
+ r = TAILQ_NEXT(r, entries);
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
+ pf_osfp_fingerprint(pd, m, off, th), r->os_fingerprint))
+ r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->tag)
+ tag = r->tag;
+ if (r->rtableid >= 0)
+ rtableid = r->rtableid;
+ if (r->anchor == NULL) {
+ match = 1;
+ *rm = r;
+ *am = a;
+ *rsm = ruleset;
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match);
+ }
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
+ }
+ r = *rm;
+ a = *am;
+ ruleset = *rsm;
+
+ REASON_SET(&reason, PFRES_MATCH);
+
+ if (r->log || (nr != NULL && nr->natpass && nr->log)) {
+ if (rewrite)
+#ifdef __FreeBSD__
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
+#else
+ m_copyback(m, off, sizeof(*th), th);
+#endif
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
+ a, ruleset, pd);
+ }
+
+ if ((r->action == PF_DROP) &&
+ ((r->rule_flag & PFRULE_RETURNRST) ||
+ (r->rule_flag & PFRULE_RETURNICMP) ||
+ (r->rule_flag & PFRULE_RETURN))) {
+ /* undo NAT changes, if they have taken place */
+ if (nr != NULL) {
+ if (direction == PF_OUT) {
+ pf_change_ap(saddr, &th->th_sport, pd->ip_sum,
+ &th->th_sum, &pd->baddr, bport, 0, af);
+ rewrite++;
+ } else {
+ pf_change_ap(daddr, &th->th_dport, pd->ip_sum,
+ &th->th_sum, &pd->baddr, bport, 0, af);
+ rewrite++;
+ }
+ }
+ if (((r->rule_flag & PFRULE_RETURNRST) ||
+ (r->rule_flag & PFRULE_RETURN)) &&
+ !(th->th_flags & TH_RST)) {
+ u_int32_t ack = ntohl(th->th_seq) + pd->p_len;
+
+ if (th->th_flags & TH_SYN)
+ ack++;
+ if (th->th_flags & TH_FIN)
+ ack++;
+#ifdef __FreeBSD__
+ pf_send_tcp(m, r, af, pd->dst,
+#else
+ pf_send_tcp(r, af, pd->dst,
+#endif
+ pd->src, th->th_dport, th->th_sport,
+ ntohl(th->th_ack), ack, TH_RST|TH_ACK, 0, 0,
+ r->return_ttl, 1, 0, pd->eh, kif->pfik_ifp);
+ } else if ((af == AF_INET) && r->return_icmp)
+ pf_send_icmp(m, r->return_icmp >> 8,
+ r->return_icmp & 255, af, r);
+ else if ((af == AF_INET6) && r->return_icmp6)
+ pf_send_icmp(m, r->return_icmp6 >> 8,
+ r->return_icmp6 & 255, af, r);
+ }
+
+ if (r->action == PF_DROP)
+ return (PF_DROP);
+
+ if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+
+ if (r->keep_state || nr != NULL ||
+ (pd->flags & PFDESC_TCP_NORM)) {
+ /* create new state */
+ u_int16_t len;
+ struct pf_state *s = NULL;
+ struct pf_src_node *sn = NULL;
+
+ len = pd->tot_len - off - (th->th_off << 2);
+
+ /* check maximums */
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
+ REASON_SET(&reason, PFRES_MAXSTATES);
+ goto cleanup;
+ }
+ /* src node for filter rule */
+ if ((r->rule_flag & PFRULE_SRCTRACK ||
+ r->rpool.opts & PF_POOL_STICKYADDR) &&
+ pf_insert_src_node(&sn, r, saddr, af) != 0) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ /* src node for translation rule */
+ if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
+ ((direction == PF_OUT &&
+ pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
+ (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (s == NULL) {
+ REASON_SET(&reason, PFRES_MEMORY);
+cleanup:
+ if (sn != NULL && sn->states == 0 && sn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, sn);
+ }
+ if (nsn != sn && nsn != NULL && nsn->states == 0 &&
+ nsn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, nsn);
+ }
+ return (PF_DROP);
+ }
+ bzero(s, sizeof(*s));
+ s->rule.ptr = r;
+ s->nat_rule.ptr = nr;
+ s->anchor.ptr = a;
+ STATE_INC_COUNTERS(s);
+ if (r->allow_opts)
+ s->state_flags |= PFSTATE_ALLOWOPTS;
+ if (r->rule_flag & PFRULE_STATESLOPPY)
+ s->state_flags |= PFSTATE_SLOPPY;
+ s->log = r->log & PF_LOG_ALL;
+ if (nr != NULL)
+ s->log |= nr->log & PF_LOG_ALL;
+ s->proto = IPPROTO_TCP;
+ s->direction = direction;
+ s->af = af;
+ if (direction == PF_OUT) {
+ PF_ACPY(&s->gwy.addr, saddr, af);
+ s->gwy.port = th->th_sport; /* sport */
+ PF_ACPY(&s->ext.addr, daddr, af);
+ s->ext.port = th->th_dport;
+ if (nr != NULL) {
+ PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ s->lan.port = bport;
+ } else {
+ PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
+ s->lan.port = s->gwy.port;
+ }
+ } else {
+ PF_ACPY(&s->lan.addr, daddr, af);
+ s->lan.port = th->th_dport;
+ PF_ACPY(&s->ext.addr, saddr, af);
+ s->ext.port = th->th_sport;
+ if (nr != NULL) {
+ PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ s->gwy.port = bport;
+ } else {
+ PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
+ s->gwy.port = s->lan.port;
+ }
+ }
+
+ s->src.seqlo = ntohl(th->th_seq);
+ s->src.seqhi = s->src.seqlo + len + 1;
+ if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
+ r->keep_state == PF_STATE_MODULATE) {
+ /* Generate sequence number modulator */
+#ifdef __FreeBSD__
+ while ((s->src.seqdiff =
+ pf_new_isn(s) - s->src.seqlo) == 0)
+ ;
+#else
+ while ((s->src.seqdiff =
+ tcp_rndiss_next() - s->src.seqlo) == 0)
+ ;
+#endif
+ pf_change_a(&th->th_seq, &th->th_sum,
+ htonl(s->src.seqlo + s->src.seqdiff), 0);
+ rewrite = 1;
+ } else
+ s->src.seqdiff = 0;
+ if (th->th_flags & TH_SYN) {
+ s->src.seqhi++;
+ s->src.wscale = pf_get_wscale(m, off, th->th_off, af);
+ }
+ s->src.max_win = MAX(ntohs(th->th_win), 1);
+ if (s->src.wscale & PF_WSCALE_MASK) {
+ /* Remove scale factor from initial window */
+ int win = s->src.max_win;
+ win += 1 << (s->src.wscale & PF_WSCALE_MASK);
+ s->src.max_win = (win - 1) >>
+ (s->src.wscale & PF_WSCALE_MASK);
+ }
+ if (th->th_flags & TH_FIN)
+ s->src.seqhi++;
+ s->dst.seqhi = 1;
+ s->dst.max_win = 1;
+ s->src.state = TCPS_SYN_SENT;
+ s->dst.state = TCPS_CLOSED;
+ s->creation = time_second;
+ s->expire = time_second;
+ s->timeout = PFTM_TCP_FIRST_PACKET;
+ pf_set_rt_ifp(s, saddr);
+ if (sn != NULL) {
+ s->src_node = sn;
+ s->src_node->states++;
+ }
+ if (nsn != NULL) {
+ PF_ACPY(&nsn->raddr, &pd->naddr, af);
+ s->nat_src_node = nsn;
+ s->nat_src_node->states++;
+ }
+ if ((pd->flags & PFDESC_TCP_NORM) && pf_normalize_tcp_init(m,
+ off, pd, th, &s->src, &s->dst)) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ pf_src_tree_remove_state(s);
+ STATE_DEC_COUNTERS(s);
+ pool_put(&pf_state_pl, s);
+ return (PF_DROP);
+ }
+ if ((pd->flags & PFDESC_TCP_NORM) && s->src.scrub &&
+ pf_normalize_tcp_stateful(m, off, pd, &reason, th, s,
+ &s->src, &s->dst, &rewrite)) {
+ /* This really shouldn't happen!!! */
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_normalize_tcp_stateful failed on first pkt"));
+ pf_normalize_tcp_cleanup(s);
+ pf_src_tree_remove_state(s);
+ STATE_DEC_COUNTERS(s);
+ pool_put(&pf_state_pl, s);
+ return (PF_DROP);
+ }
+ if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ pf_normalize_tcp_cleanup(s);
+ REASON_SET(&reason, PFRES_STATEINS);
+ pf_src_tree_remove_state(s);
+ STATE_DEC_COUNTERS(s);
+ pool_put(&pf_state_pl, s);
+ return (PF_DROP);
+ } else
+ *sm = s;
+ if (tag > 0) {
+ pf_tag_ref(tag);
+ s->tag = tag;
+ }
+ if ((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN &&
+ r->keep_state == PF_STATE_SYNPROXY) {
+ s->src.state = PF_TCPS_PROXY_SRC;
+ if (nr != NULL) {
+ if (direction == PF_OUT) {
+ pf_change_ap(saddr, &th->th_sport,
+ pd->ip_sum, &th->th_sum, &pd->baddr,
+ bport, 0, af);
+ } else {
+ pf_change_ap(daddr, &th->th_dport,
+ pd->ip_sum, &th->th_sum, &pd->baddr,
+ bport, 0, af);
+ }
+ }
+ s->src.seqhi = htonl(arc4random());
+ /* Find mss option */
+ mss = pf_get_mss(m, off, th->th_off, af);
+ mss = pf_calc_mss(saddr, af, mss);
+ mss = pf_calc_mss(daddr, af, mss);
+ s->src.mss = mss;
+#ifdef __FreeBSD__
+ pf_send_tcp(NULL, r, af, daddr, saddr, th->th_dport,
+#else
+ pf_send_tcp(r, af, daddr, saddr, th->th_dport,
+#endif
+ th->th_sport, s->src.seqhi, ntohl(th->th_seq) + 1,
+ TH_SYN|TH_ACK, 0, s->src.mss, 0, 1, 0, NULL, NULL);
+ REASON_SET(&reason, PFRES_SYNPROXY);
+ return (PF_SYNPROXY_DROP);
+ }
+ }
+
+ /* copy back packet headers if we performed NAT operations */
+ if (rewrite)
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
+
+ return (PF_PASS);
+}
+
+int
+pf_test_udp(struct pf_rule **rm, struct pf_state **sm, int direction,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+#ifdef __FreeBSD__
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct ifqueue *ifq, struct inpcb *inp)
+#else
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct ifqueue *ifq)
+#endif
+{
+ struct pf_rule *nr = NULL;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct udphdr *uh = pd->hdr.udp;
+ u_int16_t bport, nport = 0;
+ sa_family_t af = pd->af;
+ struct pf_rule *r, *a = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_src_node *nsn = NULL;
+ u_short reason;
+ int rewrite = 0;
+ int tag = -1, rtableid = -1;
+ int asd = 0;
+ int match = 0;
+
+ if (pf_check_congestion(ifq)) {
+ REASON_SET(&reason, PFRES_CONGEST);
+ return (PF_DROP);
+ }
+
+#ifdef __FreeBSD__
+ if (inp != NULL)
+ pd->lookup.done = pf_socket_lookup(direction, pd, inp);
+ else if (debug_pfugidhack) {
+ PF_UNLOCK();
+ DPFPRINTF(PF_DEBUG_MISC, ("pf: unlocked lookup\n"));
+ pd->lookup.done = pf_socket_lookup(direction, pd, inp);
+ PF_LOCK();
+ }
+#endif
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+
+ if (direction == PF_OUT) {
+ bport = nport = uh->uh_sport;
+ /* check outgoing packet for BINAT/NAT */
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
+ saddr, uh->uh_sport, daddr, uh->uh_dport,
+ &pd->naddr, &nport)) != NULL) {
+ PF_ACPY(&pd->baddr, saddr, af);
+ pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
+ &uh->uh_sum, &pd->naddr, nport, 1, af);
+ rewrite++;
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ } else {
+ bport = nport = uh->uh_dport;
+ /* check incoming packet for BINAT/RDR */
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
+ saddr, uh->uh_sport, daddr, uh->uh_dport, &pd->naddr,
+ &nport)) != NULL) {
+ PF_ACPY(&pd->baddr, daddr, af);
+ pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
+ &uh->uh_sum, &pd->naddr, nport, 1, af);
+ rewrite++;
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ }
+
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != direction)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != af)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != IPPROTO_UDP)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (r->src.port_op && !pf_match_port(r->src.port_op,
+ r->src.port[0], r->src.port[1], uh->uh_sport))
+ r = r->skip[PF_SKIP_SRC_PORT].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
+ r->dst.port[0], r->dst.port[1], uh->uh_dport))
+ r = r->skip[PF_SKIP_DST_PORT].ptr;
+ else if (r->tos && !(r->tos == pd->tos))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->rule_flag & PFRULE_FRAGMENT)
+ r = TAILQ_NEXT(r, entries);
+ else if (r->uid.op && (pd->lookup.done || (pd->lookup.done =
+#ifdef __FreeBSD__
+ pf_socket_lookup(direction, pd, inp), 1)) &&
+#else
+ pf_socket_lookup(direction, pd), 1)) &&
+#endif
+ !pf_match_uid(r->uid.op, r->uid.uid[0], r->uid.uid[1],
+ pd->lookup.uid))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->gid.op && (pd->lookup.done || (pd->lookup.done =
+#ifdef __FreeBSD__
+ pf_socket_lookup(direction, pd, inp), 1)) &&
+#else
+ pf_socket_lookup(direction, pd), 1)) &&
+#endif
+ !pf_match_gid(r->gid.op, r->gid.gid[0], r->gid.gid[1],
+ pd->lookup.gid))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->prob && r->prob <= arc4random())
+ r = TAILQ_NEXT(r, entries);
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->os_fingerprint != PF_OSFP_ANY)
+ r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->tag)
+ tag = r->tag;
+ if (r->rtableid >= 0)
+ rtableid = r->rtableid;
+ if (r->anchor == NULL) {
+ match = 1;
+ *rm = r;
+ *am = a;
+ *rsm = ruleset;
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match);
+ }
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
+ }
+ r = *rm;
+ a = *am;
+ ruleset = *rsm;
+
+ REASON_SET(&reason, PFRES_MATCH);
+
+ if (r->log || (nr != NULL && nr->natpass && nr->log)) {
+ if (rewrite)
+#ifdef __FreeBSD__
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
+#else
+ m_copyback(m, off, sizeof(*uh), uh);
+#endif
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
+ a, ruleset, pd);
+ }
+
+ if ((r->action == PF_DROP) &&
+ ((r->rule_flag & PFRULE_RETURNICMP) ||
+ (r->rule_flag & PFRULE_RETURN))) {
+ /* undo NAT changes, if they have taken place */
+ if (nr != NULL) {
+ if (direction == PF_OUT) {
+ pf_change_ap(saddr, &uh->uh_sport, pd->ip_sum,
+ &uh->uh_sum, &pd->baddr, bport, 1, af);
+ rewrite++;
+ } else {
+ pf_change_ap(daddr, &uh->uh_dport, pd->ip_sum,
+ &uh->uh_sum, &pd->baddr, bport, 1, af);
+ rewrite++;
+ }
+ }
+ if ((af == AF_INET) && r->return_icmp)
+ pf_send_icmp(m, r->return_icmp >> 8,
+ r->return_icmp & 255, af, r);
+ else if ((af == AF_INET6) && r->return_icmp6)
+ pf_send_icmp(m, r->return_icmp6 >> 8,
+ r->return_icmp6 & 255, af, r);
+ }
+
+ if (r->action == PF_DROP)
+ return (PF_DROP);
+
+ if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+
+ if (r->keep_state || nr != NULL) {
+ /* create new state */
+ struct pf_state *s = NULL;
+ struct pf_src_node *sn = NULL;
+
+ /* check maximums */
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
+ REASON_SET(&reason, PFRES_MAXSTATES);
+ goto cleanup;
+ }
+ /* src node for filter rule */
+ if ((r->rule_flag & PFRULE_SRCTRACK ||
+ r->rpool.opts & PF_POOL_STICKYADDR) &&
+ pf_insert_src_node(&sn, r, saddr, af) != 0) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ /* src node for translation rule */
+ if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
+ ((direction == PF_OUT &&
+ pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
+ (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (s == NULL) {
+ REASON_SET(&reason, PFRES_MEMORY);
+cleanup:
+ if (sn != NULL && sn->states == 0 && sn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, sn);
+ }
+ if (nsn != sn && nsn != NULL && nsn->states == 0 &&
+ nsn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, nsn);
+ }
+ return (PF_DROP);
+ }
+ bzero(s, sizeof(*s));
+ s->rule.ptr = r;
+ s->nat_rule.ptr = nr;
+ s->anchor.ptr = a;
+ STATE_INC_COUNTERS(s);
+ if (r->allow_opts)
+ s->state_flags |= PFSTATE_ALLOWOPTS;
+ if (r->rule_flag & PFRULE_STATESLOPPY)
+ s->state_flags |= PFSTATE_SLOPPY;
+ s->log = r->log & PF_LOG_ALL;
+ if (nr != NULL)
+ s->log |= nr->log & PF_LOG_ALL;
+ s->proto = IPPROTO_UDP;
+ s->direction = direction;
+ s->af = af;
+ if (direction == PF_OUT) {
+ PF_ACPY(&s->gwy.addr, saddr, af);
+ s->gwy.port = uh->uh_sport;
+ PF_ACPY(&s->ext.addr, daddr, af);
+ s->ext.port = uh->uh_dport;
+ if (nr != NULL) {
+ PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ s->lan.port = bport;
+ } else {
+ PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
+ s->lan.port = s->gwy.port;
+ }
+ } else {
+ PF_ACPY(&s->lan.addr, daddr, af);
+ s->lan.port = uh->uh_dport;
+ PF_ACPY(&s->ext.addr, saddr, af);
+ s->ext.port = uh->uh_sport;
+ if (nr != NULL) {
+ PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ s->gwy.port = bport;
+ } else {
+ PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
+ s->gwy.port = s->lan.port;
+ }
+ }
+ s->src.state = PFUDPS_SINGLE;
+ s->dst.state = PFUDPS_NO_TRAFFIC;
+ s->creation = time_second;
+ s->expire = time_second;
+ s->timeout = PFTM_UDP_FIRST_PACKET;
+ pf_set_rt_ifp(s, saddr);
+ if (sn != NULL) {
+ s->src_node = sn;
+ s->src_node->states++;
+ }
+ if (nsn != NULL) {
+ PF_ACPY(&nsn->raddr, &pd->naddr, af);
+ s->nat_src_node = nsn;
+ s->nat_src_node->states++;
+ }
+ if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ REASON_SET(&reason, PFRES_STATEINS);
+ pf_src_tree_remove_state(s);
+ STATE_DEC_COUNTERS(s);
+ pool_put(&pf_state_pl, s);
+ return (PF_DROP);
+ } else
+ *sm = s;
+ if (tag > 0) {
+ pf_tag_ref(tag);
+ s->tag = tag;
+ }
+ }
+
+ /* copy back packet headers if we performed NAT operations */
+ if (rewrite)
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
+
+ return (PF_PASS);
+}
+
+int
+pf_test_icmp(struct pf_rule **rm, struct pf_state **sm, int direction,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h,
+ struct pf_pdesc *pd, struct pf_rule **am, struct pf_ruleset **rsm,
+ struct ifqueue *ifq)
+{
+ struct pf_rule *nr = NULL;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ struct pf_rule *r, *a = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_src_node *nsn = NULL;
+ u_short reason;
+ u_int16_t icmpid = 0, bport, nport = 0;
+ sa_family_t af = pd->af;
+ u_int8_t icmptype = 0; /* make the compiler happy */
+ u_int8_t icmpcode = 0; /* make the compiler happy */
+ int state_icmp = 0;
+ int tag = -1, rtableid = -1;
+#ifdef INET6
+ int rewrite = 0;
+#endif /* INET6 */
+ int asd = 0;
+ int match = 0;
+
+ if (pf_check_congestion(ifq)) {
+ REASON_SET(&reason, PFRES_CONGEST);
+ return (PF_DROP);
+ }
+
+ switch (pd->proto) {
+#ifdef INET
+ case IPPROTO_ICMP:
+ icmptype = pd->hdr.icmp->icmp_type;
+ icmpcode = pd->hdr.icmp->icmp_code;
+ icmpid = pd->hdr.icmp->icmp_id;
+
+ if (icmptype == ICMP_UNREACH ||
+ icmptype == ICMP_SOURCEQUENCH ||
+ icmptype == ICMP_REDIRECT ||
+ icmptype == ICMP_TIMXCEED ||
+ icmptype == ICMP_PARAMPROB)
+ state_icmp++;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+ icmptype = pd->hdr.icmp6->icmp6_type;
+ icmpcode = pd->hdr.icmp6->icmp6_code;
+ icmpid = pd->hdr.icmp6->icmp6_id;
+
+ if (icmptype == ICMP6_DST_UNREACH ||
+ icmptype == ICMP6_PACKET_TOO_BIG ||
+ icmptype == ICMP6_TIME_EXCEEDED ||
+ icmptype == ICMP6_PARAM_PROB)
+ state_icmp++;
+ break;
+#endif /* INET6 */
+ }
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+
+ if (direction == PF_OUT) {
+ bport = nport = icmpid;
+ /* check outgoing packet for BINAT/NAT */
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
+ saddr, icmpid, daddr, icmpid, &pd->naddr, &nport)) !=
+ NULL) {
+ PF_ACPY(&pd->baddr, saddr, af);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
+ pd->naddr.v4.s_addr, 0);
+ pd->hdr.icmp->icmp_cksum = pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum, icmpid, nport, 0);
+ pd->hdr.icmp->icmp_id = nport;
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ pf_change_a6(saddr, &pd->hdr.icmp6->icmp6_cksum,
+ &pd->naddr, 0);
+ rewrite++;
+ break;
+#endif /* INET6 */
+ }
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ } else {
+ bport = nport = icmpid;
+ /* check incoming packet for BINAT/RDR */
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
+ saddr, icmpid, daddr, icmpid, &pd->naddr, &nport)) !=
+ NULL) {
+ PF_ACPY(&pd->baddr, daddr, af);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&daddr->v4.s_addr,
+ pd->ip_sum, pd->naddr.v4.s_addr, 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ pf_change_a6(daddr, &pd->hdr.icmp6->icmp6_cksum,
+ &pd->naddr, 0);
+ rewrite++;
+ break;
+#endif /* INET6 */
+ }
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ }
+
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != direction)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != af)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != pd->proto)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&r->src.addr, saddr, af,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr, daddr, af,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else if (r->type && r->type != icmptype + 1)
+ r = TAILQ_NEXT(r, entries);
+ else if (r->code && r->code != icmpcode + 1)
+ r = TAILQ_NEXT(r, entries);
+ else if (r->tos && !(r->tos == pd->tos))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->rule_flag & PFRULE_FRAGMENT)
+ r = TAILQ_NEXT(r, entries);
+ else if (r->prob && r->prob <= arc4random())
+ r = TAILQ_NEXT(r, entries);
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->os_fingerprint != PF_OSFP_ANY)
+ r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->tag)
+ tag = r->tag;
+ if (r->rtableid >= 0)
+ rtableid = r->rtableid;
+ if (r->anchor == NULL) {
+ match = 1;
+ *rm = r;
+ *am = a;
+ *rsm = ruleset;
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match);
+ }
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
+ }
+ r = *rm;
+ a = *am;
+ ruleset = *rsm;
+
+ REASON_SET(&reason, PFRES_MATCH);
+
+ if (r->log || (nr != NULL && nr->natpass && nr->log)) {
+#ifdef INET6
+ if (rewrite)
+ m_copyback(m, off, sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+#endif /* INET6 */
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
+ a, ruleset, pd);
+ }
+
+ if (r->action != PF_PASS)
+ return (PF_DROP);
+
+ if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+
+ if (!state_icmp && (r->keep_state || nr != NULL)) {
+ /* create new state */
+ struct pf_state *s = NULL;
+ struct pf_src_node *sn = NULL;
+
+ /* check maximums */
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
+ REASON_SET(&reason, PFRES_MAXSTATES);
+ goto cleanup;
+ }
+ /* src node for filter rule */
+ if ((r->rule_flag & PFRULE_SRCTRACK ||
+ r->rpool.opts & PF_POOL_STICKYADDR) &&
+ pf_insert_src_node(&sn, r, saddr, af) != 0) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ /* src node for translation rule */
+ if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
+ ((direction == PF_OUT &&
+ pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
+ (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (s == NULL) {
+ REASON_SET(&reason, PFRES_MEMORY);
+cleanup:
+ if (sn != NULL && sn->states == 0 && sn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, sn);
+ }
+ if (nsn != sn && nsn != NULL && nsn->states == 0 &&
+ nsn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, nsn);
+ }
+ return (PF_DROP);
+ }
+ bzero(s, sizeof(*s));
+ s->rule.ptr = r;
+ s->nat_rule.ptr = nr;
+ s->anchor.ptr = a;
+ STATE_INC_COUNTERS(s);
+ if (r->allow_opts)
+ s->state_flags |= PFSTATE_ALLOWOPTS;
+ if (r->rule_flag & PFRULE_STATESLOPPY)
+ s->state_flags |= PFSTATE_SLOPPY;
+ s->log = r->log & PF_LOG_ALL;
+ if (nr != NULL)
+ s->log |= nr->log & PF_LOG_ALL;
+ s->proto = pd->proto;
+ s->direction = direction;
+ s->af = af;
+ if (direction == PF_OUT) {
+ PF_ACPY(&s->gwy.addr, saddr, af);
+ s->gwy.port = nport;
+ PF_ACPY(&s->ext.addr, daddr, af);
+ s->ext.port = 0;
+ if (nr != NULL) {
+ PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ s->lan.port = bport;
+ } else {
+ PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
+ s->lan.port = s->gwy.port;
+ }
+ } else {
+ PF_ACPY(&s->lan.addr, daddr, af);
+ s->lan.port = nport;
+ PF_ACPY(&s->ext.addr, saddr, af);
+ s->ext.port = 0;
+ if (nr != NULL) {
+ PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ s->gwy.port = bport;
+ } else {
+ PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
+ s->gwy.port = s->lan.port;
+ }
+ }
+ s->creation = time_second;
+ s->expire = time_second;
+ s->timeout = PFTM_ICMP_FIRST_PACKET;
+ pf_set_rt_ifp(s, saddr);
+ if (sn != NULL) {
+ s->src_node = sn;
+ s->src_node->states++;
+ }
+ if (nsn != NULL) {
+ PF_ACPY(&nsn->raddr, &pd->naddr, af);
+ s->nat_src_node = nsn;
+ s->nat_src_node->states++;
+ }
+ if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ REASON_SET(&reason, PFRES_STATEINS);
+ pf_src_tree_remove_state(s);
+ STATE_DEC_COUNTERS(s);
+ pool_put(&pf_state_pl, s);
+ return (PF_DROP);
+ } else
+ *sm = s;
+ if (tag > 0) {
+ pf_tag_ref(tag);
+ s->tag = tag;
+ }
+ }
+
+#ifdef INET6
+ /* copy back packet headers if we performed IPv6 NAT operations */
+ if (rewrite)
+ m_copyback(m, off, sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+#endif /* INET6 */
+
+ return (PF_PASS);
+}
+
+int
+pf_test_other(struct pf_rule **rm, struct pf_state **sm, int direction,
+ struct pfi_kif *kif, struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
+ struct pf_rule **am, struct pf_ruleset **rsm, struct ifqueue *ifq)
+{
+ struct pf_rule *nr = NULL;
+ struct pf_rule *r, *a = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_src_node *nsn = NULL;
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ sa_family_t af = pd->af;
+ u_short reason;
+ int tag = -1, rtableid = -1;
+ int asd = 0;
+ int match = 0;
+
+ if (pf_check_congestion(ifq)) {
+ REASON_SET(&reason, PFRES_CONGEST);
+ return (PF_DROP);
+ }
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+
+ if (direction == PF_OUT) {
+ /* check outgoing packet for BINAT/NAT */
+ if ((nr = pf_get_translation(pd, m, off, PF_OUT, kif, &nsn,
+ saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
+ PF_ACPY(&pd->baddr, saddr, af);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&saddr->v4.s_addr, pd->ip_sum,
+ pd->naddr.v4.s_addr, 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ PF_ACPY(saddr, &pd->naddr, af);
+ break;
+#endif /* INET6 */
+ }
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ } else {
+ /* check incoming packet for BINAT/RDR */
+ if ((nr = pf_get_translation(pd, m, off, PF_IN, kif, &nsn,
+ saddr, 0, daddr, 0, &pd->naddr, NULL)) != NULL) {
+ PF_ACPY(&pd->baddr, daddr, af);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&daddr->v4.s_addr,
+ pd->ip_sum, pd->naddr.v4.s_addr, 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ PF_ACPY(daddr, &pd->naddr, af);
+ break;
+#endif /* INET6 */
+ }
+ if (nr->natpass)
+ r = NULL;
+ pd->nat_rule = nr;
+ }
+ }
+
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != direction)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != af)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != pd->proto)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else if (r->tos && !(r->tos == pd->tos))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->rule_flag & PFRULE_FRAGMENT)
+ r = TAILQ_NEXT(r, entries);
+ else if (r->prob && r->prob <= arc4random())
+ r = TAILQ_NEXT(r, entries);
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->os_fingerprint != PF_OSFP_ANY)
+ r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->tag)
+ tag = r->tag;
+ if (r->rtableid >= 0)
+ rtableid = r->rtableid;
+ if (r->anchor == NULL) {
+ match = 1;
+ *rm = r;
+ *am = a;
+ *rsm = ruleset;
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match);
+ }
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
+ }
+ r = *rm;
+ a = *am;
+ ruleset = *rsm;
+
+ REASON_SET(&reason, PFRES_MATCH);
+
+ if (r->log || (nr != NULL && nr->natpass && nr->log))
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r->log ? r : nr,
+ a, ruleset, pd);
+
+ if ((r->action == PF_DROP) &&
+ ((r->rule_flag & PFRULE_RETURNICMP) ||
+ (r->rule_flag & PFRULE_RETURN))) {
+ struct pf_addr *a = NULL;
+
+ if (nr != NULL) {
+ if (direction == PF_OUT)
+ a = saddr;
+ else
+ a = daddr;
+ }
+ if (a != NULL) {
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&a->v4.s_addr, pd->ip_sum,
+ pd->baddr.v4.s_addr, 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ PF_ACPY(a, &pd->baddr, af);
+ break;
+#endif /* INET6 */
+ }
+ }
+ if ((af == AF_INET) && r->return_icmp)
+ pf_send_icmp(m, r->return_icmp >> 8,
+ r->return_icmp & 255, af, r);
+ else if ((af == AF_INET6) && r->return_icmp6)
+ pf_send_icmp(m, r->return_icmp6 >> 8,
+ r->return_icmp6 & 255, af, r);
+ }
+
+ if (r->action != PF_PASS)
+ return (PF_DROP);
+
+ if (pf_tag_packet(m, pd->pf_mtag, tag, rtableid)) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+
+ if (r->keep_state || nr != NULL) {
+ /* create new state */
+ struct pf_state *s = NULL;
+ struct pf_src_node *sn = NULL;
+
+ /* check maximums */
+ if (r->max_states && (r->states >= r->max_states)) {
+ pf_status.lcounters[LCNT_STATES]++;
+ REASON_SET(&reason, PFRES_MAXSTATES);
+ goto cleanup;
+ }
+ /* src node for filter rule */
+ if ((r->rule_flag & PFRULE_SRCTRACK ||
+ r->rpool.opts & PF_POOL_STICKYADDR) &&
+ pf_insert_src_node(&sn, r, saddr, af) != 0) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ /* src node for translation rule */
+ if (nr != NULL && (nr->rpool.opts & PF_POOL_STICKYADDR) &&
+ ((direction == PF_OUT &&
+ pf_insert_src_node(&nsn, nr, &pd->baddr, af) != 0) ||
+ (pf_insert_src_node(&nsn, nr, saddr, af) != 0))) {
+ REASON_SET(&reason, PFRES_SRCLIMIT);
+ goto cleanup;
+ }
+ s = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (s == NULL) {
+ REASON_SET(&reason, PFRES_MEMORY);
+cleanup:
+ if (sn != NULL && sn->states == 0 && sn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, sn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, sn);
+ }
+ if (nsn != sn && nsn != NULL && nsn->states == 0 &&
+ nsn->expire == 0) {
+ RB_REMOVE(pf_src_tree, &tree_src_tracking, nsn);
+ pf_status.scounters[SCNT_SRC_NODE_REMOVALS]++;
+ pf_status.src_nodes--;
+ pool_put(&pf_src_tree_pl, nsn);
+ }
+ return (PF_DROP);
+ }
+ bzero(s, sizeof(*s));
+ s->rule.ptr = r;
+ s->nat_rule.ptr = nr;
+ s->anchor.ptr = a;
+ STATE_INC_COUNTERS(s);
+ if (r->allow_opts)
+ s->state_flags |= PFSTATE_ALLOWOPTS;
+ if (r->rule_flag & PFRULE_STATESLOPPY)
+ s->state_flags |= PFSTATE_SLOPPY;
+ s->log = r->log & PF_LOG_ALL;
+ if (nr != NULL)
+ s->log |= nr->log & PF_LOG_ALL;
+ s->proto = pd->proto;
+ s->direction = direction;
+ s->af = af;
+ if (direction == PF_OUT) {
+ PF_ACPY(&s->gwy.addr, saddr, af);
+ PF_ACPY(&s->ext.addr, daddr, af);
+ if (nr != NULL)
+ PF_ACPY(&s->lan.addr, &pd->baddr, af);
+ else
+ PF_ACPY(&s->lan.addr, &s->gwy.addr, af);
+ } else {
+ PF_ACPY(&s->lan.addr, daddr, af);
+ PF_ACPY(&s->ext.addr, saddr, af);
+ if (nr != NULL)
+ PF_ACPY(&s->gwy.addr, &pd->baddr, af);
+ else
+ PF_ACPY(&s->gwy.addr, &s->lan.addr, af);
+ }
+ s->src.state = PFOTHERS_SINGLE;
+ s->dst.state = PFOTHERS_NO_TRAFFIC;
+ s->creation = time_second;
+ s->expire = time_second;
+ s->timeout = PFTM_OTHER_FIRST_PACKET;
+ pf_set_rt_ifp(s, saddr);
+ if (sn != NULL) {
+ s->src_node = sn;
+ s->src_node->states++;
+ }
+ if (nsn != NULL) {
+ PF_ACPY(&nsn->raddr, &pd->naddr, af);
+ s->nat_src_node = nsn;
+ s->nat_src_node->states++;
+ }
+ if (pf_insert_state(BOUND_IFACE(r, kif), s)) {
+ REASON_SET(&reason, PFRES_STATEINS);
+ pf_src_tree_remove_state(s);
+ STATE_DEC_COUNTERS(s);
+ pool_put(&pf_state_pl, s);
+ return (PF_DROP);
+ } else
+ *sm = s;
+ if (tag > 0) {
+ pf_tag_ref(tag);
+ s->tag = tag;
+ }
+ }
+
+ return (PF_PASS);
+}
+
+int
+pf_test_fragment(struct pf_rule **rm, int direction, struct pfi_kif *kif,
+ struct mbuf *m, void *h, struct pf_pdesc *pd, struct pf_rule **am,
+ struct pf_ruleset **rsm)
+{
+ struct pf_rule *r, *a = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ sa_family_t af = pd->af;
+ u_short reason;
+ int tag = -1;
+ int asd = 0;
+ int match = 0;
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_FILTER].active.ptr);
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != direction)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != af)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != pd->proto)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else if (r->tos && !(r->tos == pd->tos))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->os_fingerprint != PF_OSFP_ANY)
+ r = TAILQ_NEXT(r, entries);
+ else if (pd->proto == IPPROTO_UDP &&
+ (r->src.port_op || r->dst.port_op))
+ r = TAILQ_NEXT(r, entries);
+ else if (pd->proto == IPPROTO_TCP &&
+ (r->src.port_op || r->dst.port_op || r->flagset))
+ r = TAILQ_NEXT(r, entries);
+ else if ((pd->proto == IPPROTO_ICMP ||
+ pd->proto == IPPROTO_ICMPV6) &&
+ (r->type || r->code))
+ r = TAILQ_NEXT(r, entries);
+ else if (r->prob && r->prob <= arc4random())
+ r = TAILQ_NEXT(r, entries);
+ else if (r->match_tag && !pf_match_tag(m, r, pd->pf_mtag, &tag))
+ r = TAILQ_NEXT(r, entries);
+ else {
+ if (r->anchor == NULL) {
+ match = 1;
+ *rm = r;
+ *am = a;
+ *rsm = ruleset;
+ if ((*rm)->quick)
+ break;
+ r = TAILQ_NEXT(r, entries);
+ } else
+ pf_step_into_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match);
+ }
+ if (r == NULL && pf_step_out_of_anchor(&asd, &ruleset,
+ PF_RULESET_FILTER, &r, &a, &match))
+ break;
+ }
+ r = *rm;
+ a = *am;
+ ruleset = *rsm;
+
+ REASON_SET(&reason, PFRES_MATCH);
+
+ if (r->log)
+ PFLOG_PACKET(kif, h, m, af, direction, reason, r, a, ruleset,
+ pd);
+
+ if (r->action != PF_PASS)
+ return (PF_DROP);
+
+ if (pf_tag_packet(m, pd->pf_mtag, tag, -1)) {
+ REASON_SET(&reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+
+ return (PF_PASS);
+}
+
+int
+pf_tcp_track_full(struct pf_state_peer *src, struct pf_state_peer *dst,
+ struct pf_state **state, struct pfi_kif *kif, struct mbuf *m, int off,
+ struct pf_pdesc *pd, u_short *reason, int *copyback)
+{
+ struct tcphdr *th = pd->hdr.tcp;
+ u_int16_t win = ntohs(th->th_win);
+ u_int32_t ack, end, seq, orig_seq;
+ u_int8_t sws, dws;
+ int ackskew;
+
+ if (src->wscale && dst->wscale && !(th->th_flags & TH_SYN)) {
+ sws = src->wscale & PF_WSCALE_MASK;
+ dws = dst->wscale & PF_WSCALE_MASK;
+ } else
+ sws = dws = 0;
+
+ /*
+ * Sequence tracking algorithm from Guido van Rooij's paper:
+ * http://www.madison-gurkha.com/publications/tcp_filtering/
+ * tcp_filtering.ps
+ */
+
+ orig_seq = seq = ntohl(th->th_seq);
+ if (src->seqlo == 0) {
+ /* First packet from this end. Set its state */
+
+ if ((pd->flags & PFDESC_TCP_NORM || dst->scrub) &&
+ src->scrub == NULL) {
+ if (pf_normalize_tcp_init(m, off, pd, th, src, dst)) {
+ REASON_SET(reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+ }
+
+ /* Deferred generation of sequence number modulator */
+ if (dst->seqdiff && !src->seqdiff) {
+#ifdef __FreeBSD__
+ while ((src->seqdiff = pf_new_isn(*state) - seq) == 0)
+ ;
+#else
+ while ((src->seqdiff = tcp_rndiss_next() - seq) == 0)
+ ;
+#endif
+ ack = ntohl(th->th_ack) - dst->seqdiff;
+ pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
+ src->seqdiff), 0);
+ pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
+ *copyback = 1;
+ } else {
+ ack = ntohl(th->th_ack);
+ }
+
+ end = seq + pd->p_len;
+ if (th->th_flags & TH_SYN) {
+ end++;
+ if (dst->wscale & PF_WSCALE_FLAG) {
+ src->wscale = pf_get_wscale(m, off, th->th_off,
+ pd->af);
+ if (src->wscale & PF_WSCALE_FLAG) {
+ /* Remove scale factor from initial
+ * window */
+ sws = src->wscale & PF_WSCALE_MASK;
+ win = ((u_int32_t)win + (1 << sws) - 1)
+ >> sws;
+ dws = dst->wscale & PF_WSCALE_MASK;
+ } else {
+ /* fixup other window */
+ dst->max_win <<= dst->wscale &
+ PF_WSCALE_MASK;
+ /* in case of a retrans SYN|ACK */
+ dst->wscale = 0;
+ }
+ }
+ }
+ if (th->th_flags & TH_FIN)
+ end++;
+
+ src->seqlo = seq;
+ if (src->state < TCPS_SYN_SENT)
+ src->state = TCPS_SYN_SENT;
+
+ /*
+ * May need to slide the window (seqhi may have been set by
+ * the crappy stack check or if we picked up the connection
+ * after establishment)
+ */
+ if (src->seqhi == 1 ||
+ SEQ_GEQ(end + MAX(1, dst->max_win << dws), src->seqhi))
+ src->seqhi = end + MAX(1, dst->max_win << dws);
+ if (win > src->max_win)
+ src->max_win = win;
+
+ } else {
+ ack = ntohl(th->th_ack) - dst->seqdiff;
+ if (src->seqdiff) {
+ /* Modulate sequence numbers */
+ pf_change_a(&th->th_seq, &th->th_sum, htonl(seq +
+ src->seqdiff), 0);
+ pf_change_a(&th->th_ack, &th->th_sum, htonl(ack), 0);
+ *copyback = 1;
+ }
+ end = seq + pd->p_len;
+ if (th->th_flags & TH_SYN)
+ end++;
+ if (th->th_flags & TH_FIN)
+ end++;
+ }
+
+ if ((th->th_flags & TH_ACK) == 0) {
+ /* Let it pass through the ack skew check */
+ ack = dst->seqlo;
+ } else if ((ack == 0 &&
+ (th->th_flags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) ||
+ /* broken tcp stacks do not set ack */
+ (dst->state < TCPS_SYN_SENT)) {
+ /*
+ * Many stacks (ours included) will set the ACK number in an
+ * FIN|ACK if the SYN times out -- no sequence to ACK.
+ */
+ ack = dst->seqlo;
+ }
+
+ if (seq == end) {
+ /* Ease sequencing restrictions on no data packets */
+ seq = src->seqlo;
+ end = seq;
+ }
+
+ ackskew = dst->seqlo - ack;
+
+
+ /*
+ * Need to demodulate the sequence numbers in any TCP SACK options
+ * (Selective ACK). We could optionally validate the SACK values
+ * against the current ACK window, either forwards or backwards, but
+ * I'm not confident that SACK has been implemented properly
+ * everywhere. It wouldn't surprise me if several stacks accidently
+ * SACK too far backwards of previously ACKed data. There really aren't
+ * any security implications of bad SACKing unless the target stack
+ * doesn't validate the option length correctly. Someone trying to
+ * spoof into a TCP connection won't bother blindly sending SACK
+ * options anyway.
+ */
+ if (dst->seqdiff && (th->th_off << 2) > sizeof(struct tcphdr)) {
+ if (pf_modulate_sack(m, off, pd, th, dst))
+ *copyback = 1;
+ }
+
+
+#define MAXACKWINDOW (0xffff + 1500) /* 1500 is an arbitrary fudge factor */
+ if (SEQ_GEQ(src->seqhi, end) &&
+ /* Last octet inside other's window space */
+ SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) &&
+ /* Retrans: not more than one window back */
+ (ackskew >= -MAXACKWINDOW) &&
+ /* Acking not more than one reassembled fragment backwards */
+ (ackskew <= (MAXACKWINDOW << sws)) &&
+ /* Acking not more than one window forward */
+ ((th->th_flags & TH_RST) == 0 || orig_seq == src->seqlo ||
+ (orig_seq == src->seqlo + 1) || (pd->flags & PFDESC_IP_REAS) == 0)) {
+ /* Require an exact/+1 sequence match on resets when possible */
+
+ if (dst->scrub || src->scrub) {
+ if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
+ *state, src, dst, copyback))
+ return (PF_DROP);
+ }
+
+ /* update max window */
+ if (src->max_win < win)
+ src->max_win = win;
+ /* synchronize sequencing */
+ if (SEQ_GT(end, src->seqlo))
+ src->seqlo = end;
+ /* slide the window of what the other end can send */
+ if (SEQ_GEQ(ack + (win << sws), dst->seqhi))
+ dst->seqhi = ack + MAX((win << sws), 1);
+
+
+ /* update states */
+ if (th->th_flags & TH_SYN)
+ if (src->state < TCPS_SYN_SENT)
+ src->state = TCPS_SYN_SENT;
+ if (th->th_flags & TH_FIN)
+ if (src->state < TCPS_CLOSING)
+ src->state = TCPS_CLOSING;
+ if (th->th_flags & TH_ACK) {
+ if (dst->state == TCPS_SYN_SENT) {
+ dst->state = TCPS_ESTABLISHED;
+ if (src->state == TCPS_ESTABLISHED &&
+ (*state)->src_node != NULL &&
+ pf_src_connlimit(state)) {
+ REASON_SET(reason, PFRES_SRCLIMIT);
+ return (PF_DROP);
+ }
+ } else if (dst->state == TCPS_CLOSING)
+ dst->state = TCPS_FIN_WAIT_2;
+ }
+ if (th->th_flags & TH_RST)
+ src->state = dst->state = TCPS_TIME_WAIT;
+
+ /* update expire time */
+ (*state)->expire = time_second;
+ if (src->state >= TCPS_FIN_WAIT_2 &&
+ dst->state >= TCPS_FIN_WAIT_2)
+ (*state)->timeout = PFTM_TCP_CLOSED;
+ else if (src->state >= TCPS_CLOSING &&
+ dst->state >= TCPS_CLOSING)
+ (*state)->timeout = PFTM_TCP_FIN_WAIT;
+ else if (src->state < TCPS_ESTABLISHED ||
+ dst->state < TCPS_ESTABLISHED)
+ (*state)->timeout = PFTM_TCP_OPENING;
+ else if (src->state >= TCPS_CLOSING ||
+ dst->state >= TCPS_CLOSING)
+ (*state)->timeout = PFTM_TCP_CLOSING;
+ else
+ (*state)->timeout = PFTM_TCP_ESTABLISHED;
+
+ /* Fall through to PASS packet */
+
+ } else if ((dst->state < TCPS_SYN_SENT ||
+ dst->state >= TCPS_FIN_WAIT_2 ||
+ src->state >= TCPS_FIN_WAIT_2) &&
+ SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) &&
+ /* Within a window forward of the originating packet */
+ SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW)) {
+ /* Within a window backward of the originating packet */
+
+ /*
+ * This currently handles three situations:
+ * 1) Stupid stacks will shotgun SYNs before their peer
+ * replies.
+ * 2) When PF catches an already established stream (the
+ * firewall rebooted, the state table was flushed, routes
+ * changed...)
+ * 3) Packets get funky immediately after the connection
+ * closes (this should catch Solaris spurious ACK|FINs
+ * that web servers like to spew after a close)
+ *
+ * This must be a little more careful than the above code
+ * since packet floods will also be caught here. We don't
+ * update the TTL here to mitigate the damage of a packet
+ * flood and so the same code can handle awkward establishment
+ * and a loosened connection close.
+ * In the establishment case, a correct peer response will
+ * validate the connection, go through the normal state code
+ * and keep updating the state TTL.
+ */
+
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: loose state match: ");
+ pf_print_state(*state);
+ pf_print_flags(th->th_flags);
+ printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
+ "pkts=%llu:%llu\n", seq, orig_seq, ack, pd->p_len,
+#ifdef __FreeBSD__
+ ackskew, (unsigned long long)(*state)->packets[0],
+ (unsigned long long)(*state)->packets[1]);
+#else
+ ackskew, (*state)->packets[0],
+ (*state)->packets[1]);
+#endif
+ }
+
+ if (dst->scrub || src->scrub) {
+ if (pf_normalize_tcp_stateful(m, off, pd, reason, th,
+ *state, src, dst, copyback))
+ return (PF_DROP);
+ }
+
+ /* update max window */
+ if (src->max_win < win)
+ src->max_win = win;
+ /* synchronize sequencing */
+ if (SEQ_GT(end, src->seqlo))
+ src->seqlo = end;
+ /* slide the window of what the other end can send */
+ if (SEQ_GEQ(ack + (win << sws), dst->seqhi))
+ dst->seqhi = ack + MAX((win << sws), 1);
+
+ /*
+ * Cannot set dst->seqhi here since this could be a shotgunned
+ * SYN and not an already established connection.
+ */
+
+ if (th->th_flags & TH_FIN)
+ if (src->state < TCPS_CLOSING)
+ src->state = TCPS_CLOSING;
+ if (th->th_flags & TH_RST)
+ src->state = dst->state = TCPS_TIME_WAIT;
+
+ /* Fall through to PASS packet */
+
+ } else {
+ if ((*state)->dst.state == TCPS_SYN_SENT &&
+ (*state)->src.state == TCPS_SYN_SENT) {
+ /* Send RST for state mismatches during handshake */
+ if (!(th->th_flags & TH_RST))
+#ifdef __FreeBSD__
+ pf_send_tcp(m, (*state)->rule.ptr, pd->af,
+#else
+ pf_send_tcp((*state)->rule.ptr, pd->af,
+#endif
+ pd->dst, pd->src, th->th_dport,
+ th->th_sport, ntohl(th->th_ack), 0,
+ TH_RST, 0, 0,
+ (*state)->rule.ptr->return_ttl, 1, 0,
+ pd->eh, kif->pfik_ifp);
+ src->seqlo = 0;
+ src->seqhi = 1;
+ src->max_win = 1;
+ } else if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: BAD state: ");
+ pf_print_state(*state);
+ pf_print_flags(th->th_flags);
+ printf(" seq=%u (%u) ack=%u len=%u ackskew=%d "
+#ifdef notyet
+ "pkts=%llu:%llu dir=%s,%s\n",
+#else
+ "pkts=%llu:%llu%s\n",
+#endif
+ seq, orig_seq, ack, pd->p_len, ackskew,
+#ifdef __FreeBSD__
+ (unsigned long long)(*state)->packets[0],
+ (unsigned long long)(*state)->packets[1],
+#else
+ (*state)->packets[0], (*state)->packets[1],
+#endif
+#ifdef notyet
+ direction == PF_IN ? "in" : "out",
+ direction == (*state)->direction ? "fwd" : "rev");
+#else
+ "");
+#endif
+ printf("pf: State failure on: %c %c %c %c | %c %c\n",
+ SEQ_GEQ(src->seqhi, end) ? ' ' : '1',
+ SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)) ?
+ ' ': '2',
+ (ackskew >= -MAXACKWINDOW) ? ' ' : '3',
+ (ackskew <= (MAXACKWINDOW << sws)) ? ' ' : '4',
+ SEQ_GEQ(src->seqhi + MAXACKWINDOW, end) ?' ' :'5',
+ SEQ_GEQ(seq, src->seqlo - MAXACKWINDOW) ?' ' :'6');
+ }
+ REASON_SET(reason, PFRES_BADSTATE);
+ return (PF_DROP);
+ }
+
+ /* Any packets which have gotten here are to be passed */
+ return (PF_PASS);
+}
+
+int
+pf_tcp_track_sloppy(struct pf_state_peer *src, struct pf_state_peer *dst,
+ struct pf_state **state, struct pf_pdesc *pd, u_short *reason)
+{
+ struct tcphdr *th = pd->hdr.tcp;
+
+ if (th->th_flags & TH_SYN)
+ if (src->state < TCPS_SYN_SENT)
+ src->state = TCPS_SYN_SENT;
+ if (th->th_flags & TH_FIN)
+ if (src->state < TCPS_CLOSING)
+ src->state = TCPS_CLOSING;
+ if (th->th_flags & TH_ACK) {
+ if (dst->state == TCPS_SYN_SENT) {
+ dst->state = TCPS_ESTABLISHED;
+ if (src->state == TCPS_ESTABLISHED &&
+ (*state)->src_node != NULL &&
+ pf_src_connlimit(state)) {
+ REASON_SET(reason, PFRES_SRCLIMIT);
+ return (PF_DROP);
+ }
+ } else if (dst->state == TCPS_CLOSING) {
+ dst->state = TCPS_FIN_WAIT_2;
+ } else if (src->state == TCPS_SYN_SENT &&
+ dst->state < TCPS_SYN_SENT) {
+ /*
+ * Handle a special sloppy case where we only see one
+ * half of the connection. If there is a ACK after
+ * the initial SYN without ever seeing a packet from
+ * the destination, set the connection to established.
+ */
+ dst->state = src->state = TCPS_ESTABLISHED;
+ if ((*state)->src_node != NULL &&
+ pf_src_connlimit(state)) {
+ REASON_SET(reason, PFRES_SRCLIMIT);
+ return (PF_DROP);
+ }
+ } else if (src->state == TCPS_CLOSING &&
+ dst->state == TCPS_ESTABLISHED &&
+ dst->seqlo == 0) {
+ /*
+ * Handle the closing of half connections where we
+ * don't see the full bidirectional FIN/ACK+ACK
+ * handshake.
+ */
+ dst->state = TCPS_CLOSING;
+ }
+ }
+ if (th->th_flags & TH_RST)
+ src->state = dst->state = TCPS_TIME_WAIT;
+
+ /* update expire time */
+ (*state)->expire = time_second;
+ if (src->state >= TCPS_FIN_WAIT_2 &&
+ dst->state >= TCPS_FIN_WAIT_2)
+ (*state)->timeout = PFTM_TCP_CLOSED;
+ else if (src->state >= TCPS_CLOSING &&
+ dst->state >= TCPS_CLOSING)
+ (*state)->timeout = PFTM_TCP_FIN_WAIT;
+ else if (src->state < TCPS_ESTABLISHED ||
+ dst->state < TCPS_ESTABLISHED)
+ (*state)->timeout = PFTM_TCP_OPENING;
+ else if (src->state >= TCPS_CLOSING ||
+ dst->state >= TCPS_CLOSING)
+ (*state)->timeout = PFTM_TCP_CLOSING;
+ else
+ (*state)->timeout = PFTM_TCP_ESTABLISHED;
+
+ return (PF_PASS);
+}
+
+
+int
+pf_test_state_tcp(struct pf_state **state, int direction, struct pfi_kif *kif,
+ struct mbuf *m, int off, void *h, struct pf_pdesc *pd,
+ u_short *reason)
+{
+ struct pf_state_cmp key;
+ struct tcphdr *th = pd->hdr.tcp;
+ int copyback = 0;
+ struct pf_state_peer *src, *dst;
+
+ key.af = pd->af;
+ key.proto = IPPROTO_TCP;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd->src, key.af);
+ PF_ACPY(&key.gwy.addr, pd->dst, key.af);
+ key.ext.port = th->th_sport;
+ key.gwy.port = th->th_dport;
+ } else {
+ PF_ACPY(&key.lan.addr, pd->src, key.af);
+ PF_ACPY(&key.ext.addr, pd->dst, key.af);
+ key.lan.port = th->th_sport;
+ key.ext.port = th->th_dport;
+ }
+
+ STATE_LOOKUP();
+
+ if (direction == (*state)->direction) {
+ src = &(*state)->src;
+ dst = &(*state)->dst;
+ } else {
+ src = &(*state)->dst;
+ dst = &(*state)->src;
+ }
+
+ if ((*state)->src.state == PF_TCPS_PROXY_SRC) {
+ if (direction != (*state)->direction) {
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_SYNPROXY_DROP);
+ }
+ if (th->th_flags & TH_SYN) {
+ if (ntohl(th->th_seq) != (*state)->src.seqlo) {
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_DROP);
+ }
+#ifdef __FreeBSD__
+ pf_send_tcp(NULL, (*state)->rule.ptr, pd->af, pd->dst,
+#else
+ pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
+#endif
+ pd->src, th->th_dport, th->th_sport,
+ (*state)->src.seqhi, ntohl(th->th_seq) + 1,
+ TH_SYN|TH_ACK, 0, (*state)->src.mss, 0, 1,
+ 0, NULL, NULL);
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_SYNPROXY_DROP);
+ } else if (!(th->th_flags & TH_ACK) ||
+ (ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
+ (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) {
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_DROP);
+ } else if ((*state)->src_node != NULL &&
+ pf_src_connlimit(state)) {
+ REASON_SET(reason, PFRES_SRCLIMIT);
+ return (PF_DROP);
+ } else
+ (*state)->src.state = PF_TCPS_PROXY_DST;
+ }
+ if ((*state)->src.state == PF_TCPS_PROXY_DST) {
+ struct pf_state_host *src, *dst;
+
+ if (direction == PF_OUT) {
+ src = &(*state)->gwy;
+ dst = &(*state)->ext;
+ } else {
+ src = &(*state)->ext;
+ dst = &(*state)->lan;
+ }
+ if (direction == (*state)->direction) {
+ if (((th->th_flags & (TH_SYN|TH_ACK)) != TH_ACK) ||
+ (ntohl(th->th_ack) != (*state)->src.seqhi + 1) ||
+ (ntohl(th->th_seq) != (*state)->src.seqlo + 1)) {
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_DROP);
+ }
+ (*state)->src.max_win = MAX(ntohs(th->th_win), 1);
+ if ((*state)->dst.seqhi == 1)
+ (*state)->dst.seqhi = htonl(arc4random());
+#ifdef __FreeBSD__
+ pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
+ &src->addr,
+#else
+ pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
+#endif
+ &dst->addr, src->port, dst->port,
+ (*state)->dst.seqhi, 0, TH_SYN, 0,
+ (*state)->src.mss, 0, 0, (*state)->tag, NULL, NULL);
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_SYNPROXY_DROP);
+ } else if (((th->th_flags & (TH_SYN|TH_ACK)) !=
+ (TH_SYN|TH_ACK)) ||
+ (ntohl(th->th_ack) != (*state)->dst.seqhi + 1)) {
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_DROP);
+ } else {
+ (*state)->dst.max_win = MAX(ntohs(th->th_win), 1);
+ (*state)->dst.seqlo = ntohl(th->th_seq);
+#ifdef __FreeBSD__
+ pf_send_tcp(NULL, (*state)->rule.ptr, pd->af, pd->dst,
+#else
+ pf_send_tcp((*state)->rule.ptr, pd->af, pd->dst,
+#endif
+ pd->src, th->th_dport, th->th_sport,
+ ntohl(th->th_ack), ntohl(th->th_seq) + 1,
+ TH_ACK, (*state)->src.max_win, 0, 0, 0,
+ (*state)->tag, NULL, NULL);
+#ifdef __FreeBSD__
+ pf_send_tcp(NULL, (*state)->rule.ptr, pd->af,
+ &src->addr,
+#else
+ pf_send_tcp((*state)->rule.ptr, pd->af, &src->addr,
+#endif
+ &dst->addr, src->port, dst->port,
+ (*state)->src.seqhi + 1, (*state)->src.seqlo + 1,
+ TH_ACK, (*state)->dst.max_win, 0, 0, 1,
+ 0, NULL, NULL);
+ (*state)->src.seqdiff = (*state)->dst.seqhi -
+ (*state)->src.seqlo;
+ (*state)->dst.seqdiff = (*state)->src.seqhi -
+ (*state)->dst.seqlo;
+ (*state)->src.seqhi = (*state)->src.seqlo +
+ (*state)->dst.max_win;
+ (*state)->dst.seqhi = (*state)->dst.seqlo +
+ (*state)->src.max_win;
+ (*state)->src.wscale = (*state)->dst.wscale = 0;
+ (*state)->src.state = (*state)->dst.state =
+ TCPS_ESTABLISHED;
+ REASON_SET(reason, PFRES_SYNPROXY);
+ return (PF_SYNPROXY_DROP);
+ }
+ }
+
+ if (((th->th_flags & (TH_SYN|TH_ACK)) == TH_SYN) &&
+ dst->state >= TCPS_FIN_WAIT_2 &&
+ src->state >= TCPS_FIN_WAIT_2) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: state reuse ");
+ pf_print_state(*state);
+ pf_print_flags(th->th_flags);
+ printf("\n");
+ }
+ /* XXX make sure it's the same direction ?? */
+ (*state)->src.state = (*state)->dst.state = TCPS_CLOSED;
+ pf_unlink_state(*state);
+ *state = NULL;
+ return (PF_DROP);
+ }
+
+ if ((*state)->state_flags & PFSTATE_SLOPPY) {
+ if (pf_tcp_track_sloppy(src, dst, state, pd, reason) == PF_DROP)
+ return (PF_DROP);
+ } else {
+ if (pf_tcp_track_full(src, dst, state, kif, m, off, pd, reason,
+ &copyback) == PF_DROP)
+ return (PF_DROP);
+ }
+
+ /* translate source/destination address, if necessary */
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_OUT)
+ pf_change_ap(pd->src, &th->th_sport, pd->ip_sum,
+ &th->th_sum, &(*state)->gwy.addr,
+ (*state)->gwy.port, 0, pd->af);
+ else
+ pf_change_ap(pd->dst, &th->th_dport, pd->ip_sum,
+ &th->th_sum, &(*state)->lan.addr,
+ (*state)->lan.port, 0, pd->af);
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
+ } else if (copyback) {
+ /* Copyback sequence modulation or stateful scrub changes */
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
+ }
+
+ return (PF_PASS);
+}
+
+int
+pf_test_state_udp(struct pf_state **state, int direction, struct pfi_kif *kif,
+ struct mbuf *m, int off, void *h, struct pf_pdesc *pd)
+{
+ struct pf_state_peer *src, *dst;
+ struct pf_state_cmp key;
+ struct udphdr *uh = pd->hdr.udp;
+
+ key.af = pd->af;
+ key.proto = IPPROTO_UDP;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd->src, key.af);
+ PF_ACPY(&key.gwy.addr, pd->dst, key.af);
+ key.ext.port = uh->uh_sport;
+ key.gwy.port = uh->uh_dport;
+ } else {
+ PF_ACPY(&key.lan.addr, pd->src, key.af);
+ PF_ACPY(&key.ext.addr, pd->dst, key.af);
+ key.lan.port = uh->uh_sport;
+ key.ext.port = uh->uh_dport;
+ }
+
+ STATE_LOOKUP();
+
+ if (direction == (*state)->direction) {
+ src = &(*state)->src;
+ dst = &(*state)->dst;
+ } else {
+ src = &(*state)->dst;
+ dst = &(*state)->src;
+ }
+
+ /* update states */
+ if (src->state < PFUDPS_SINGLE)
+ src->state = PFUDPS_SINGLE;
+ if (dst->state == PFUDPS_SINGLE)
+ dst->state = PFUDPS_MULTIPLE;
+
+ /* update expire time */
+ (*state)->expire = time_second;
+ if (src->state == PFUDPS_MULTIPLE && dst->state == PFUDPS_MULTIPLE)
+ (*state)->timeout = PFTM_UDP_MULTIPLE;
+ else
+ (*state)->timeout = PFTM_UDP_SINGLE;
+
+ /* translate source/destination address, if necessary */
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_OUT)
+ pf_change_ap(pd->src, &uh->uh_sport, pd->ip_sum,
+ &uh->uh_sum, &(*state)->gwy.addr,
+ (*state)->gwy.port, 1, pd->af);
+ else
+ pf_change_ap(pd->dst, &uh->uh_dport, pd->ip_sum,
+ &uh->uh_sum, &(*state)->lan.addr,
+ (*state)->lan.port, 1, pd->af);
+ m_copyback(m, off, sizeof(*uh), (caddr_t)uh);
+ }
+
+ return (PF_PASS);
+}
+
+int
+pf_test_state_icmp(struct pf_state **state, int direction, struct pfi_kif *kif,
+ struct mbuf *m, int off, void *h, struct pf_pdesc *pd, u_short *reason)
+{
+ struct pf_addr *saddr = pd->src, *daddr = pd->dst;
+ u_int16_t icmpid = 0; /* make the compiler happy */
+ u_int16_t *icmpsum = NULL; /* make the compiler happy */
+ u_int8_t icmptype = 0; /* make the compiler happy */
+ int state_icmp = 0;
+ struct pf_state_cmp key;
+
+ switch (pd->proto) {
+#ifdef INET
+ case IPPROTO_ICMP:
+ icmptype = pd->hdr.icmp->icmp_type;
+ icmpid = pd->hdr.icmp->icmp_id;
+ icmpsum = &pd->hdr.icmp->icmp_cksum;
+
+ if (icmptype == ICMP_UNREACH ||
+ icmptype == ICMP_SOURCEQUENCH ||
+ icmptype == ICMP_REDIRECT ||
+ icmptype == ICMP_TIMXCEED ||
+ icmptype == ICMP_PARAMPROB)
+ state_icmp++;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+ icmptype = pd->hdr.icmp6->icmp6_type;
+ icmpid = pd->hdr.icmp6->icmp6_id;
+ icmpsum = &pd->hdr.icmp6->icmp6_cksum;
+
+ if (icmptype == ICMP6_DST_UNREACH ||
+ icmptype == ICMP6_PACKET_TOO_BIG ||
+ icmptype == ICMP6_TIME_EXCEEDED ||
+ icmptype == ICMP6_PARAM_PROB)
+ state_icmp++;
+ break;
+#endif /* INET6 */
+ }
+
+ if (!state_icmp) {
+
+ /*
+ * ICMP query/reply message not related to a TCP/UDP packet.
+ * Search for an ICMP state.
+ */
+ key.af = pd->af;
+ key.proto = pd->proto;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd->src, key.af);
+ PF_ACPY(&key.gwy.addr, pd->dst, key.af);
+ key.ext.port = 0;
+ key.gwy.port = icmpid;
+ } else {
+ PF_ACPY(&key.lan.addr, pd->src, key.af);
+ PF_ACPY(&key.ext.addr, pd->dst, key.af);
+ key.lan.port = icmpid;
+ key.ext.port = 0;
+ }
+
+ STATE_LOOKUP();
+
+ (*state)->expire = time_second;
+ (*state)->timeout = PFTM_ICMP_ERROR_REPLY;
+
+ /* translate source/destination address, if necessary */
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_OUT) {
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&saddr->v4.s_addr,
+ pd->ip_sum,
+ (*state)->gwy.addr.v4.s_addr, 0);
+ pd->hdr.icmp->icmp_cksum =
+ pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum, icmpid,
+ (*state)->gwy.port, 0);
+ pd->hdr.icmp->icmp_id =
+ (*state)->gwy.port;
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ pf_change_a6(saddr,
+ &pd->hdr.icmp6->icmp6_cksum,
+ &(*state)->gwy.addr, 0);
+ m_copyback(m, off,
+ sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+ break;
+#endif /* INET6 */
+ }
+ } else {
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&daddr->v4.s_addr,
+ pd->ip_sum,
+ (*state)->lan.addr.v4.s_addr, 0);
+ pd->hdr.icmp->icmp_cksum =
+ pf_cksum_fixup(
+ pd->hdr.icmp->icmp_cksum, icmpid,
+ (*state)->lan.port, 0);
+ pd->hdr.icmp->icmp_id =
+ (*state)->lan.port;
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ pf_change_a6(daddr,
+ &pd->hdr.icmp6->icmp6_cksum,
+ &(*state)->lan.addr, 0);
+ m_copyback(m, off,
+ sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+ break;
+#endif /* INET6 */
+ }
+ }
+ }
+
+ return (PF_PASS);
+
+ } else {
+ /*
+ * ICMP error message in response to a TCP/UDP packet.
+ * Extract the inner TCP/UDP header and search for that state.
+ */
+
+ struct pf_pdesc pd2;
+#ifdef INET
+ struct ip h2;
+#endif /* INET */
+#ifdef INET6
+ struct ip6_hdr h2_6;
+ int terminal = 0;
+#endif /* INET6 */
+ int ipoff2 = 0; /* make the compiler happy */
+ int off2 = 0; /* make the compiler happy */
+
+ pd2.af = pd->af;
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ /* offset of h2 in mbuf chain */
+ ipoff2 = off + ICMP_MINLEN;
+
+ if (!pf_pull_hdr(m, ipoff2, &h2, sizeof(h2),
+ NULL, reason, pd2.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short "
+ "(ip)\n"));
+ return (PF_DROP);
+ }
+ /*
+ * ICMP error messages don't refer to non-first
+ * fragments
+ */
+ if (h2.ip_off & htons(IP_OFFMASK)) {
+ REASON_SET(reason, PFRES_FRAG);
+ return (PF_DROP);
+ }
+
+ /* offset of protocol header that follows h2 */
+ off2 = ipoff2 + (h2.ip_hl << 2);
+
+ pd2.proto = h2.ip_p;
+ pd2.src = (struct pf_addr *)&h2.ip_src;
+ pd2.dst = (struct pf_addr *)&h2.ip_dst;
+ pd2.ip_sum = &h2.ip_sum;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ ipoff2 = off + sizeof(struct icmp6_hdr);
+
+ if (!pf_pull_hdr(m, ipoff2, &h2_6, sizeof(h2_6),
+ NULL, reason, pd2.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short "
+ "(ip6)\n"));
+ return (PF_DROP);
+ }
+ pd2.proto = h2_6.ip6_nxt;
+ pd2.src = (struct pf_addr *)&h2_6.ip6_src;
+ pd2.dst = (struct pf_addr *)&h2_6.ip6_dst;
+ pd2.ip_sum = NULL;
+ off2 = ipoff2 + sizeof(h2_6);
+ do {
+ switch (pd2.proto) {
+ case IPPROTO_FRAGMENT:
+ /*
+ * ICMPv6 error messages for
+ * non-first fragments
+ */
+ REASON_SET(reason, PFRES_FRAG);
+ return (PF_DROP);
+ case IPPROTO_AH:
+ case IPPROTO_HOPOPTS:
+ case IPPROTO_ROUTING:
+ case IPPROTO_DSTOPTS: {
+ /* get next header and header length */
+ struct ip6_ext opt6;
+
+ if (!pf_pull_hdr(m, off2, &opt6,
+ sizeof(opt6), NULL, reason,
+ pd2.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMPv6 short opt\n"));
+ return (PF_DROP);
+ }
+ if (pd2.proto == IPPROTO_AH)
+ off2 += (opt6.ip6e_len + 2) * 4;
+ else
+ off2 += (opt6.ip6e_len + 1) * 8;
+ pd2.proto = opt6.ip6e_nxt;
+ /* goto the next header */
+ break;
+ }
+ default:
+ terminal++;
+ break;
+ }
+ } while (!terminal);
+ break;
+#endif /* INET6 */
+#ifdef __FreeBSD__
+ default:
+ panic("AF not supported: %d", pd->af);
+#endif
+ }
+
+ switch (pd2.proto) {
+ case IPPROTO_TCP: {
+ struct tcphdr th;
+ u_int32_t seq;
+ struct pf_state_peer *src, *dst;
+ u_int8_t dws;
+ int copyback = 0;
+
+ /*
+ * Only the first 8 bytes of the TCP header can be
+ * expected. Don't access any TCP header fields after
+ * th_seq, an ackskew test is not possible.
+ */
+ if (!pf_pull_hdr(m, off2, &th, 8, NULL, reason,
+ pd2.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short "
+ "(tcp)\n"));
+ return (PF_DROP);
+ }
+
+ key.af = pd2.af;
+ key.proto = IPPROTO_TCP;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd2.dst, key.af);
+ PF_ACPY(&key.gwy.addr, pd2.src, key.af);
+ key.ext.port = th.th_dport;
+ key.gwy.port = th.th_sport;
+ } else {
+ PF_ACPY(&key.lan.addr, pd2.dst, key.af);
+ PF_ACPY(&key.ext.addr, pd2.src, key.af);
+ key.lan.port = th.th_dport;
+ key.ext.port = th.th_sport;
+ }
+
+ STATE_LOOKUP();
+
+ if (direction == (*state)->direction) {
+ src = &(*state)->dst;
+ dst = &(*state)->src;
+ } else {
+ src = &(*state)->src;
+ dst = &(*state)->dst;
+ }
+
+ if (src->wscale && dst->wscale)
+ dws = dst->wscale & PF_WSCALE_MASK;
+ else
+ dws = 0;
+
+ /* Demodulate sequence number */
+ seq = ntohl(th.th_seq) - src->seqdiff;
+ if (src->seqdiff) {
+ pf_change_a(&th.th_seq, icmpsum,
+ htonl(seq), 0);
+ copyback = 1;
+ }
+
+ if (!((*state)->state_flags & PFSTATE_SLOPPY) &&
+ (!SEQ_GEQ(src->seqhi, seq) ||
+ !SEQ_GEQ(seq, src->seqlo - (dst->max_win << dws)))) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ printf("pf: BAD ICMP %d:%d ",
+ icmptype, pd->hdr.icmp->icmp_code);
+ pf_print_host(pd->src, 0, pd->af);
+ printf(" -> ");
+ pf_print_host(pd->dst, 0, pd->af);
+ printf(" state: ");
+ pf_print_state(*state);
+ printf(" seq=%u\n", seq);
+ }
+ REASON_SET(reason, PFRES_BADSTATE);
+ return (PF_DROP);
+ }
+
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_IN) {
+ pf_change_icmp(pd2.src, &th.th_sport,
+ daddr, &(*state)->lan.addr,
+ (*state)->lan.port, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, pd2.af);
+ } else {
+ pf_change_icmp(pd2.dst, &th.th_dport,
+ saddr, &(*state)->gwy.addr,
+ (*state)->gwy.port, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, pd2.af);
+ }
+ copyback = 1;
+ }
+
+ if (copyback) {
+ switch (pd2.af) {
+#ifdef INET
+ case AF_INET:
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ m_copyback(m, off,
+ sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+ m_copyback(m, ipoff2, sizeof(h2_6),
+ (caddr_t)&h2_6);
+ break;
+#endif /* INET6 */
+ }
+ m_copyback(m, off2, 8, (caddr_t)&th);
+ }
+
+ return (PF_PASS);
+ break;
+ }
+ case IPPROTO_UDP: {
+ struct udphdr uh;
+
+ if (!pf_pull_hdr(m, off2, &uh, sizeof(uh),
+ NULL, reason, pd2.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short "
+ "(udp)\n"));
+ return (PF_DROP);
+ }
+
+ key.af = pd2.af;
+ key.proto = IPPROTO_UDP;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd2.dst, key.af);
+ PF_ACPY(&key.gwy.addr, pd2.src, key.af);
+ key.ext.port = uh.uh_dport;
+ key.gwy.port = uh.uh_sport;
+ } else {
+ PF_ACPY(&key.lan.addr, pd2.dst, key.af);
+ PF_ACPY(&key.ext.addr, pd2.src, key.af);
+ key.lan.port = uh.uh_dport;
+ key.ext.port = uh.uh_sport;
+ }
+
+ STATE_LOOKUP();
+
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_IN) {
+ pf_change_icmp(pd2.src, &uh.uh_sport,
+ daddr, &(*state)->lan.addr,
+ (*state)->lan.port, &uh.uh_sum,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 1, pd2.af);
+ } else {
+ pf_change_icmp(pd2.dst, &uh.uh_dport,
+ saddr, &(*state)->gwy.addr,
+ (*state)->gwy.port, &uh.uh_sum,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 1, pd2.af);
+ }
+ switch (pd2.af) {
+#ifdef INET
+ case AF_INET:
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ m_copyback(m, off,
+ sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+ m_copyback(m, ipoff2, sizeof(h2_6),
+ (caddr_t)&h2_6);
+ break;
+#endif /* INET6 */
+ }
+ m_copyback(m, off2, sizeof(uh),
+ (caddr_t)&uh);
+ }
+
+ return (PF_PASS);
+ break;
+ }
+#ifdef INET
+ case IPPROTO_ICMP: {
+ struct icmp iih;
+
+ if (!pf_pull_hdr(m, off2, &iih, ICMP_MINLEN,
+ NULL, reason, pd2.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short i"
+ "(icmp)\n"));
+ return (PF_DROP);
+ }
+
+ key.af = pd2.af;
+ key.proto = IPPROTO_ICMP;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd2.dst, key.af);
+ PF_ACPY(&key.gwy.addr, pd2.src, key.af);
+ key.ext.port = 0;
+ key.gwy.port = iih.icmp_id;
+ } else {
+ PF_ACPY(&key.lan.addr, pd2.dst, key.af);
+ PF_ACPY(&key.ext.addr, pd2.src, key.af);
+ key.lan.port = iih.icmp_id;
+ key.ext.port = 0;
+ }
+
+ STATE_LOOKUP();
+
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_IN) {
+ pf_change_icmp(pd2.src, &iih.icmp_id,
+ daddr, &(*state)->lan.addr,
+ (*state)->lan.port, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, AF_INET);
+ } else {
+ pf_change_icmp(pd2.dst, &iih.icmp_id,
+ saddr, &(*state)->gwy.addr,
+ (*state)->gwy.port, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, AF_INET);
+ }
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
+ m_copyback(m, off2, ICMP_MINLEN,
+ (caddr_t)&iih);
+ }
+
+ return (PF_PASS);
+ break;
+ }
+#endif /* INET */
+#ifdef INET6
+ case IPPROTO_ICMPV6: {
+ struct icmp6_hdr iih;
+
+ if (!pf_pull_hdr(m, off2, &iih,
+ sizeof(struct icmp6_hdr), NULL, reason, pd2.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: ICMP error message too short "
+ "(icmp6)\n"));
+ return (PF_DROP);
+ }
+
+ key.af = pd2.af;
+ key.proto = IPPROTO_ICMPV6;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd2.dst, key.af);
+ PF_ACPY(&key.gwy.addr, pd2.src, key.af);
+ key.ext.port = 0;
+ key.gwy.port = iih.icmp6_id;
+ } else {
+ PF_ACPY(&key.lan.addr, pd2.dst, key.af);
+ PF_ACPY(&key.ext.addr, pd2.src, key.af);
+ key.lan.port = iih.icmp6_id;
+ key.ext.port = 0;
+ }
+
+ STATE_LOOKUP();
+
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_IN) {
+ pf_change_icmp(pd2.src, &iih.icmp6_id,
+ daddr, &(*state)->lan.addr,
+ (*state)->lan.port, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, AF_INET6);
+ } else {
+ pf_change_icmp(pd2.dst, &iih.icmp6_id,
+ saddr, &(*state)->gwy.addr,
+ (*state)->gwy.port, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, AF_INET6);
+ }
+ m_copyback(m, off, sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+ m_copyback(m, ipoff2, sizeof(h2_6),
+ (caddr_t)&h2_6);
+ m_copyback(m, off2, sizeof(struct icmp6_hdr),
+ (caddr_t)&iih);
+ }
+
+ return (PF_PASS);
+ break;
+ }
+#endif /* INET6 */
+ default: {
+ key.af = pd2.af;
+ key.proto = pd2.proto;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd2.dst, key.af);
+ PF_ACPY(&key.gwy.addr, pd2.src, key.af);
+ key.ext.port = 0;
+ key.gwy.port = 0;
+ } else {
+ PF_ACPY(&key.lan.addr, pd2.dst, key.af);
+ PF_ACPY(&key.ext.addr, pd2.src, key.af);
+ key.lan.port = 0;
+ key.ext.port = 0;
+ }
+
+ STATE_LOOKUP();
+
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_IN) {
+ pf_change_icmp(pd2.src, NULL,
+ daddr, &(*state)->lan.addr,
+ 0, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, pd2.af);
+ } else {
+ pf_change_icmp(pd2.dst, NULL,
+ saddr, &(*state)->gwy.addr,
+ 0, NULL,
+ pd2.ip_sum, icmpsum,
+ pd->ip_sum, 0, pd2.af);
+ }
+ switch (pd2.af) {
+#ifdef INET
+ case AF_INET:
+ m_copyback(m, off, ICMP_MINLEN,
+ (caddr_t)pd->hdr.icmp);
+ m_copyback(m, ipoff2, sizeof(h2),
+ (caddr_t)&h2);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ m_copyback(m, off,
+ sizeof(struct icmp6_hdr),
+ (caddr_t)pd->hdr.icmp6);
+ m_copyback(m, ipoff2, sizeof(h2_6),
+ (caddr_t)&h2_6);
+ break;
+#endif /* INET6 */
+ }
+ }
+
+ return (PF_PASS);
+ break;
+ }
+ }
+ }
+}
+
+int
+pf_test_state_other(struct pf_state **state, int direction, struct pfi_kif *kif,
+ struct pf_pdesc *pd)
+{
+ struct pf_state_peer *src, *dst;
+ struct pf_state_cmp key;
+
+ key.af = pd->af;
+ key.proto = pd->proto;
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, pd->src, key.af);
+ PF_ACPY(&key.gwy.addr, pd->dst, key.af);
+ key.ext.port = 0;
+ key.gwy.port = 0;
+ } else {
+ PF_ACPY(&key.lan.addr, pd->src, key.af);
+ PF_ACPY(&key.ext.addr, pd->dst, key.af);
+ key.lan.port = 0;
+ key.ext.port = 0;
+ }
+
+ STATE_LOOKUP();
+
+ if (direction == (*state)->direction) {
+ src = &(*state)->src;
+ dst = &(*state)->dst;
+ } else {
+ src = &(*state)->dst;
+ dst = &(*state)->src;
+ }
+
+ /* update states */
+ if (src->state < PFOTHERS_SINGLE)
+ src->state = PFOTHERS_SINGLE;
+ if (dst->state == PFOTHERS_SINGLE)
+ dst->state = PFOTHERS_MULTIPLE;
+
+ /* update expire time */
+ (*state)->expire = time_second;
+ if (src->state == PFOTHERS_MULTIPLE && dst->state == PFOTHERS_MULTIPLE)
+ (*state)->timeout = PFTM_OTHER_MULTIPLE;
+ else
+ (*state)->timeout = PFTM_OTHER_SINGLE;
+
+ /* translate source/destination address, if necessary */
+ if (STATE_TRANSLATE(*state)) {
+ if (direction == PF_OUT)
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&pd->src->v4.s_addr,
+ pd->ip_sum, (*state)->gwy.addr.v4.s_addr,
+ 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ PF_ACPY(pd->src, &(*state)->gwy.addr, pd->af);
+ break;
+#endif /* INET6 */
+ }
+ else
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET:
+ pf_change_a(&pd->dst->v4.s_addr,
+ pd->ip_sum, (*state)->lan.addr.v4.s_addr,
+ 0);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ PF_ACPY(pd->dst, &(*state)->lan.addr, pd->af);
+ break;
+#endif /* INET6 */
+ }
+ }
+
+ return (PF_PASS);
+}
+
+/*
+ * ipoff and off are measured from the start of the mbuf chain.
+ * h must be at "ipoff" on the mbuf chain.
+ */
+void *
+pf_pull_hdr(struct mbuf *m, int off, void *p, int len,
+ u_short *actionp, u_short *reasonp, sa_family_t af)
+{
+ switch (af) {
+#ifdef INET
+ case AF_INET: {
+ struct ip *h = mtod(m, struct ip *);
+ u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
+
+ if (fragoff) {
+ if (fragoff >= len)
+ ACTION_SET(actionp, PF_PASS);
+ else {
+ ACTION_SET(actionp, PF_DROP);
+ REASON_SET(reasonp, PFRES_FRAG);
+ }
+ return (NULL);
+ }
+ if (m->m_pkthdr.len < off + len ||
+ ntohs(h->ip_len) < off + len) {
+ ACTION_SET(actionp, PF_DROP);
+ REASON_SET(reasonp, PFRES_SHORT);
+ return (NULL);
+ }
+ break;
+ }
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6: {
+ struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
+
+ if (m->m_pkthdr.len < off + len ||
+ (ntohs(h->ip6_plen) + sizeof(struct ip6_hdr)) <
+ (unsigned)(off + len)) {
+ ACTION_SET(actionp, PF_DROP);
+ REASON_SET(reasonp, PFRES_SHORT);
+ return (NULL);
+ }
+ break;
+ }
+#endif /* INET6 */
+ }
+ m_copydata(m, off, len, p);
+ return (p);
+}
+
+int
+pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *kif)
+{
+ struct sockaddr_in *dst;
+ int ret = 1;
+ int check_mpath;
+#ifndef __FreeBSD__
+ extern int ipmultipath;
+#endif
+#ifdef INET6
+#ifndef __FreeBSD__
+ extern int ip6_multipath;
+#endif
+ struct sockaddr_in6 *dst6;
+ struct route_in6 ro;
+#else
+ struct route ro;
+#endif
+ struct radix_node *rn;
+ struct rtentry *rt;
+ struct ifnet *ifp;
+
+ check_mpath = 0;
+ bzero(&ro, sizeof(ro));
+ switch (af) {
+ case AF_INET:
+ dst = satosin(&ro.ro_dst);
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = addr->v4;
+#ifndef __FreeBSD__ /* MULTIPATH_ROUTING */
+ if (ipmultipath)
+ check_mpath = 1;
+#endif
+ break;
+#ifdef INET6
+ case AF_INET6:
+ dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(*dst6);
+ dst6->sin6_addr = addr->v6;
+#ifndef __FreeBSD__ /* MULTIPATH_ROUTING */
+ if (ip6_multipath)
+ check_mpath = 1;
+#endif
+ break;
+#endif /* INET6 */
+ default:
+ return (0);
+ }
+
+ /* Skip checks for ipsec interfaces */
+ if (kif != NULL && kif->pfik_ifp->if_type == IFT_ENC)
+ goto out;
+
+#ifdef __FreeBSD__
+/* XXX MRT not always INET */ /* stick with table 0 though */
+ if (af == AF_INET)
+ in_rtalloc_ign((struct route *)&ro, 0, 0);
+ else
+ rtalloc_ign((struct route *)&ro, 0);
+#else /* ! __FreeBSD__ */
+ rtalloc_noclone((struct route *)&ro, NO_CLONING);
+#endif
+
+ if (ro.ro_rt != NULL) {
+ /* No interface given, this is a no-route check */
+ if (kif == NULL)
+ goto out;
+
+ if (kif->pfik_ifp == NULL) {
+ ret = 0;
+ goto out;
+ }
+
+ /* Perform uRPF check if passed input interface */
+ ret = 0;
+ rn = (struct radix_node *)ro.ro_rt;
+ do {
+ rt = (struct rtentry *)rn;
+#ifndef __FreeBSD__ /* CARPDEV */
+ if (rt->rt_ifp->if_type == IFT_CARP)
+ ifp = rt->rt_ifp->if_carpdev;
+ else
+#endif
+ ifp = rt->rt_ifp;
+
+ if (kif->pfik_ifp == ifp)
+ ret = 1;
+#ifdef __FreeBSD__ /* MULTIPATH_ROUTING */
+ rn = NULL;
+#else
+ rn = rn_mpath_next(rn);
+#endif
+ } while (check_mpath == 1 && rn != NULL && ret == 0);
+ } else
+ ret = 0;
+out:
+ if (ro.ro_rt != NULL)
+ RTFREE(ro.ro_rt);
+ return (ret);
+}
+
+int
+pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw)
+{
+ struct sockaddr_in *dst;
+#ifdef INET6
+ struct sockaddr_in6 *dst6;
+ struct route_in6 ro;
+#else
+ struct route ro;
+#endif
+ int ret = 0;
+
+ bzero(&ro, sizeof(ro));
+ switch (af) {
+ case AF_INET:
+ dst = satosin(&ro.ro_dst);
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = addr->v4;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ dst6 = (struct sockaddr_in6 *)&ro.ro_dst;
+ dst6->sin6_family = AF_INET6;
+ dst6->sin6_len = sizeof(*dst6);
+ dst6->sin6_addr = addr->v6;
+ break;
+#endif /* INET6 */
+ default:
+ return (0);
+ }
+
+#ifdef __FreeBSD__
+# ifdef RTF_PRCLONING
+ rtalloc_ign((struct route *)&ro, (RTF_CLONING|RTF_PRCLONING));
+# else /* !RTF_PRCLONING */
+ if (af == AF_INET)
+ in_rtalloc_ign((struct route *)&ro, 0, 0);
+ else
+ rtalloc_ign((struct route *)&ro, 0);
+# endif
+#else /* ! __FreeBSD__ */
+ rtalloc_noclone((struct route *)&ro, NO_CLONING);
+#endif
+
+ if (ro.ro_rt != NULL) {
+#ifdef __FreeBSD__
+ /* XXX_IMPORT: later */
+#else
+ if (ro.ro_rt->rt_labelid == aw->v.rtlabel)
+ ret = 1;
+#endif
+ RTFREE(ro.ro_rt);
+ }
+
+ return (ret);
+}
+
+#ifdef INET
+
+void
+pf_route(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
+ struct pf_state *s, struct pf_pdesc *pd)
+{
+ struct mbuf *m0, *m1;
+ struct route iproute;
+ struct route *ro = NULL;
+ struct sockaddr_in *dst;
+ struct ip *ip;
+ struct ifnet *ifp = NULL;
+ struct pf_addr naddr;
+ struct pf_src_node *sn = NULL;
+ int error = 0;
+#ifdef __FreeBSD__
+ int sw_csum;
+#endif
+#ifdef IPSEC
+ struct m_tag *mtag;
+#endif /* IPSEC */
+
+ if (m == NULL || *m == NULL || r == NULL ||
+ (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
+ panic("pf_route: invalid parameters");
+
+ if (pd->pf_mtag->routed++ > 3) {
+ m0 = *m;
+ *m = NULL;
+ goto bad;
+ }
+
+ if (r->rt == PF_DUPTO) {
+#ifdef __FreeBSD__
+ if ((m0 = m_dup(*m, M_DONTWAIT)) == NULL)
+#else
+ if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
+#endif
+ return;
+ } else {
+ if ((r->rt == PF_REPLYTO) == (r->direction == dir))
+ return;
+ m0 = *m;
+ }
+
+ if (m0->m_len < sizeof(struct ip)) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_route: m0->m_len < sizeof(struct ip)\n"));
+ goto bad;
+ }
+
+ ip = mtod(m0, struct ip *);
+
+ ro = &iproute;
+ bzero((caddr_t)ro, sizeof(*ro));
+ dst = satosin(&ro->ro_dst);
+ dst->sin_family = AF_INET;
+ dst->sin_len = sizeof(*dst);
+ dst->sin_addr = ip->ip_dst;
+
+ if (r->rt == PF_FASTROUTE) {
+ in_rtalloc(ro, 0);
+ if (ro->ro_rt == 0) {
+ KMOD_IPSTAT_INC(ips_noroute);
+ goto bad;
+ }
+
+ ifp = ro->ro_rt->rt_ifp;
+ ro->ro_rt->rt_use++;
+
+ if (ro->ro_rt->rt_flags & RTF_GATEWAY)
+ dst = satosin(ro->ro_rt->rt_gateway);
+ } else {
+ if (TAILQ_EMPTY(&r->rpool.list)) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_route: TAILQ_EMPTY(&r->rpool.list)\n"));
+ goto bad;
+ }
+ if (s == NULL) {
+ pf_map_addr(AF_INET, r, (struct pf_addr *)&ip->ip_src,
+ &naddr, NULL, &sn);
+ if (!PF_AZERO(&naddr, AF_INET))
+ dst->sin_addr.s_addr = naddr.v4.s_addr;
+ ifp = r->rpool.cur->kif ?
+ r->rpool.cur->kif->pfik_ifp : NULL;
+ } else {
+ if (!PF_AZERO(&s->rt_addr, AF_INET))
+ dst->sin_addr.s_addr =
+ s->rt_addr.v4.s_addr;
+ ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
+ }
+ }
+ if (ifp == NULL)
+ goto bad;
+
+ if (oifp != ifp) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ if (pf_test(PF_OUT, ifp, &m0, NULL, NULL) != PF_PASS) {
+ PF_LOCK();
+ goto bad;
+ } else if (m0 == NULL) {
+ PF_LOCK();
+ goto done;
+ }
+ PF_LOCK();
+#else
+ if (pf_test(PF_OUT, ifp, &m0, NULL) != PF_PASS)
+ goto bad;
+ else if (m0 == NULL)
+ goto done;
+#endif
+ if (m0->m_len < sizeof(struct ip)) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_route: m0->m_len < sizeof(struct ip)\n"));
+ goto bad;
+ }
+ ip = mtod(m0, struct ip *);
+ }
+
+#ifdef __FreeBSD__
+ /* Copied from FreeBSD 5.1-CURRENT ip_output. */
+ m0->m_pkthdr.csum_flags |= CSUM_IP;
+ sw_csum = m0->m_pkthdr.csum_flags & ~ifp->if_hwassist;
+ if (sw_csum & CSUM_DELAY_DATA) {
+ /*
+ * XXX: in_delayed_cksum assumes HBO for ip->ip_len (at least)
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off); /* XXX: needed? */
+ in_delayed_cksum(m0);
+ HTONS(ip->ip_len);
+ HTONS(ip->ip_off);
+ sw_csum &= ~CSUM_DELAY_DATA;
+ }
+ m0->m_pkthdr.csum_flags &= ifp->if_hwassist;
+
+ if (ntohs(ip->ip_len) <= ifp->if_mtu ||
+ (m0->m_pkthdr.csum_flags & ifp->if_hwassist & CSUM_TSO) != 0 ||
+ (ifp->if_hwassist & CSUM_FRAGMENT &&
+ ((ip->ip_off & htons(IP_DF)) == 0))) {
+ /*
+ * ip->ip_len = htons(ip->ip_len);
+ * ip->ip_off = htons(ip->ip_off);
+ */
+ ip->ip_sum = 0;
+ if (sw_csum & CSUM_DELAY_IP) {
+ /* From KAME */
+ if (ip->ip_v == IPVERSION &&
+ (ip->ip_hl << 2) == sizeof(*ip)) {
+ ip->ip_sum = in_cksum_hdr(ip);
+ } else {
+ ip->ip_sum = in_cksum(m0, ip->ip_hl << 2);
+ }
+ }
+ PF_UNLOCK();
+ error = (*ifp->if_output)(ifp, m0, sintosa(dst), ro);
+ PF_LOCK();
+ goto done;
+ }
+
+#else
+ /* Copied from ip_output. */
+#ifdef IPSEC
+ /*
+ * If deferred crypto processing is needed, check that the
+ * interface supports it.
+ */
+ if ((mtag = m_tag_find(m0, PACKET_TAG_IPSEC_OUT_CRYPTO_NEEDED, NULL))
+ != NULL && (ifp->if_capabilities & IFCAP_IPSEC) == 0) {
+ /* Notify IPsec to do its own crypto. */
+ ipsp_skipcrypto_unmark((struct tdb_ident *)(mtag + 1));
+ goto bad;
+ }
+#endif /* IPSEC */
+
+ /* Catch routing changes wrt. hardware checksumming for TCP or UDP. */
+ if (m0->m_pkthdr.csum_flags & M_TCPV4_CSUM_OUT) {
+ if (!(ifp->if_capabilities & IFCAP_CSUM_TCPv4) ||
+ ifp->if_bridge != NULL) {
+ in_delayed_cksum(m0);
+ m0->m_pkthdr.csum_flags &= ~M_TCPV4_CSUM_OUT; /* Clear */
+ }
+ } else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT) {
+ if (!(ifp->if_capabilities & IFCAP_CSUM_UDPv4) ||
+ ifp->if_bridge != NULL) {
+ in_delayed_cksum(m0);
+ m0->m_pkthdr.csum_flags &= ~M_UDPV4_CSUM_OUT; /* Clear */
+ }
+ }
+
+ if (ntohs(ip->ip_len) <= ifp->if_mtu) {
+ if ((ifp->if_capabilities & IFCAP_CSUM_IPv4) &&
+ ifp->if_bridge == NULL) {
+ m0->m_pkthdr.csum_flags |= M_IPV4_CSUM_OUT;
+ KMOD_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)
+ KMOD_TCPSTAT_INC(tcps_outhwcsum);
+ else if (m0->m_pkthdr.csum_flags & M_UDPV4_CSUM_OUT)
+ KMOD_UDPSTAT_INC(udps_outhwcsum);
+ error = (*ifp->if_output)(ifp, m0, sintosa(dst), NULL);
+ goto done;
+ }
+#endif
+ /*
+ * Too large for interface; fragment if possible.
+ * Must be able to put at least 8 bytes per fragment.
+ */
+ if (ip->ip_off & htons(IP_DF) || (m0->m_pkthdr.csum_flags & CSUM_TSO)) {
+ KMOD_IPSTAT_INC(ips_cantfrag);
+ if (r->rt != PF_DUPTO) {
+#ifdef __FreeBSD__
+ /* icmp_error() expects host byte ordering */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+ PF_UNLOCK();
+ icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
+ ifp->if_mtu);
+ PF_LOCK();
+#else
+ icmp_error(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, 0,
+ ifp->if_mtu);
+#endif
+ goto done;
+ } else
+ goto bad;
+ }
+
+ m1 = m0;
+#ifdef __FreeBSD__
+ /*
+ * XXX: is cheaper + less error prone than own function
+ */
+ NTOHS(ip->ip_len);
+ NTOHS(ip->ip_off);
+ error = ip_fragment(ip, &m0, ifp->if_mtu, ifp->if_hwassist, sw_csum);
+#else
+ error = ip_fragment(m0, ifp, ifp->if_mtu);
+#endif
+ if (error) {
+#ifndef __FreeBSD__ /* ip_fragment does not do m_freem() on FreeBSD */
+ m0 = NULL;
+#endif
+ goto bad;
+ }
+
+ for (m0 = m1; m0; m0 = m1) {
+ m1 = m0->m_nextpkt;
+ m0->m_nextpkt = 0;
+#ifdef __FreeBSD__
+ if (error == 0) {
+ PF_UNLOCK();
+ error = (*ifp->if_output)(ifp, m0, sintosa(dst),
+ NULL);
+ PF_LOCK();
+ } else
+#else
+ if (error == 0)
+ error = (*ifp->if_output)(ifp, m0, sintosa(dst),
+ NULL);
+ else
+#endif
+ m_freem(m0);
+ }
+
+ if (error == 0)
+ KMOD_IPSTAT_INC(ips_fragmented);
+
+done:
+ if (r->rt != PF_DUPTO)
+ *m = NULL;
+ if (ro == &iproute && ro->ro_rt)
+ RTFREE(ro->ro_rt);
+ return;
+
+bad:
+ m_freem(m0);
+ goto done;
+}
+#endif /* INET */
+
+#ifdef INET6
+void
+pf_route6(struct mbuf **m, struct pf_rule *r, int dir, struct ifnet *oifp,
+ struct pf_state *s, struct pf_pdesc *pd)
+{
+ struct mbuf *m0;
+ struct route_in6 ip6route;
+ struct route_in6 *ro;
+ struct sockaddr_in6 *dst;
+ struct ip6_hdr *ip6;
+ struct ifnet *ifp = NULL;
+ struct pf_addr naddr;
+ struct pf_src_node *sn = NULL;
+ int error = 0;
+
+ if (m == NULL || *m == NULL || r == NULL ||
+ (dir != PF_IN && dir != PF_OUT) || oifp == NULL)
+ panic("pf_route6: invalid parameters");
+
+ if (pd->pf_mtag->routed++ > 3) {
+ m0 = *m;
+ *m = NULL;
+ goto bad;
+ }
+
+ if (r->rt == PF_DUPTO) {
+#ifdef __FreeBSD__
+ if ((m0 = m_dup(*m, M_DONTWAIT)) == NULL)
+#else
+ if ((m0 = m_copym2(*m, 0, M_COPYALL, M_NOWAIT)) == NULL)
+#endif
+ return;
+ } else {
+ if ((r->rt == PF_REPLYTO) == (r->direction == dir))
+ return;
+ m0 = *m;
+ }
+
+ if (m0->m_len < sizeof(struct ip6_hdr)) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_route6: m0->m_len < sizeof(struct ip6_hdr)\n"));
+ goto bad;
+ }
+ ip6 = mtod(m0, struct ip6_hdr *);
+
+ ro = &ip6route;
+ bzero((caddr_t)ro, sizeof(*ro));
+ dst = (struct sockaddr_in6 *)&ro->ro_dst;
+ dst->sin6_family = AF_INET6;
+ dst->sin6_len = sizeof(*dst);
+ dst->sin6_addr = ip6->ip6_dst;
+
+ /* Cheat. XXX why only in the v6 case??? */
+ if (r->rt == PF_FASTROUTE) {
+#ifdef __FreeBSD__
+ m0->m_flags |= M_SKIP_FIREWALL;
+ PF_UNLOCK();
+ ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
+ PF_LOCK();
+#else
+ mtag = m_tag_get(PACKET_TAG_PF_GENERATED, 0, M_NOWAIT);
+ if (mtag == NULL)
+ goto bad;
+ m_tag_prepend(m0, mtag);
+ pd->pf_mtag->flags |= PF_TAG_GENERATED;
+ ip6_output(m0, NULL, NULL, 0, NULL, NULL);
+#endif
+ return;
+ }
+
+ if (TAILQ_EMPTY(&r->rpool.list)) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_route6: TAILQ_EMPTY(&r->rpool.list)\n"));
+ goto bad;
+ }
+ if (s == NULL) {
+ pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src,
+ &naddr, NULL, &sn);
+ if (!PF_AZERO(&naddr, AF_INET6))
+ PF_ACPY((struct pf_addr *)&dst->sin6_addr,
+ &naddr, AF_INET6);
+ ifp = r->rpool.cur->kif ? r->rpool.cur->kif->pfik_ifp : NULL;
+ } else {
+ if (!PF_AZERO(&s->rt_addr, AF_INET6))
+ PF_ACPY((struct pf_addr *)&dst->sin6_addr,
+ &s->rt_addr, AF_INET6);
+ ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL;
+ }
+ if (ifp == NULL)
+ goto bad;
+
+ if (oifp != ifp) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ if (pf_test6(PF_OUT, ifp, &m0, NULL, NULL) != PF_PASS) {
+ PF_LOCK();
+ goto bad;
+ } else if (m0 == NULL) {
+ PF_LOCK();
+ goto done;
+ }
+ PF_LOCK();
+#else
+ if (pf_test6(PF_OUT, ifp, &m0, NULL) != PF_PASS)
+ goto bad;
+ else if (m0 == NULL)
+ goto done;
+#endif
+ if (m0->m_len < sizeof(struct ip6_hdr)) {
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_route6: m0->m_len < sizeof(struct ip6_hdr)\n"));
+ goto bad;
+ }
+ ip6 = mtod(m0, struct ip6_hdr *);
+ }
+
+ /*
+ * If the packet is too large for the outgoing interface,
+ * send back an icmp6 error.
+ */
+ if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr))
+ dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
+ if ((u_long)m0->m_pkthdr.len <= ifp->if_mtu) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ error = nd6_output(ifp, ifp, m0, dst, NULL);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ } else {
+ in6_ifstat_inc(ifp, ifs6_in_toobig);
+#ifdef __FreeBSD__
+ if (r->rt != PF_DUPTO) {
+ PF_UNLOCK();
+ icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
+ PF_LOCK();
+ } else
+#else
+ if (r->rt != PF_DUPTO)
+ icmp6_error(m0, ICMP6_PACKET_TOO_BIG, 0, ifp->if_mtu);
+ else
+#endif
+ goto bad;
+ }
+
+done:
+ if (r->rt != PF_DUPTO)
+ *m = NULL;
+ return;
+
+bad:
+ m_freem(m0);
+ goto done;
+}
+#endif /* INET6 */
+
+
+#ifdef __FreeBSD__
+/*
+ * FreeBSD supports cksum offloads for the following drivers.
+ * em(4), fxp(4), ixgb(4), lge(4), ndis(4), nge(4), re(4),
+ * ti(4), txp(4), xl(4)
+ *
+ * CSUM_DATA_VALID | CSUM_PSEUDO_HDR :
+ * network driver performed cksum including pseudo header, need to verify
+ * csum_data
+ * CSUM_DATA_VALID :
+ * network driver performed cksum, needs to additional pseudo header
+ * cksum computation with partial csum_data(i.e. lack of H/W support for
+ * pseudo header, for instance hme(4), sk(4) and possibly gem(4))
+ *
+ * After validating the cksum of packet, set both flag CSUM_DATA_VALID and
+ * CSUM_PSEUDO_HDR in order to avoid recomputation of the cksum in upper
+ * TCP/UDP layer.
+ * Also, set csum_data to 0xffff to force cksum validation.
+ */
+int
+pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p, sa_family_t af)
+{
+ u_int16_t sum = 0;
+ int hw_assist = 0;
+ struct ip *ip;
+
+ if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
+ return (1);
+ if (m->m_pkthdr.len < off + len)
+ return (1);
+
+ switch (p) {
+ case IPPROTO_TCP:
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+ if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
+ sum = m->m_pkthdr.csum_data;
+ } else {
+ ip = mtod(m, struct ip *);
+ sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr, htonl((u_short)len +
+ m->m_pkthdr.csum_data + IPPROTO_TCP));
+ }
+ sum ^= 0xffff;
+ ++hw_assist;
+ }
+ break;
+ case IPPROTO_UDP:
+ if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
+ if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR) {
+ sum = m->m_pkthdr.csum_data;
+ } else {
+ ip = mtod(m, struct ip *);
+ sum = in_pseudo(ip->ip_src.s_addr,
+ ip->ip_dst.s_addr, htonl((u_short)len +
+ m->m_pkthdr.csum_data + IPPROTO_UDP));
+ }
+ sum ^= 0xffff;
+ ++hw_assist;
+ }
+ break;
+ case IPPROTO_ICMP:
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+#endif /* INET6 */
+ break;
+ default:
+ return (1);
+ }
+
+ if (!hw_assist) {
+ switch (af) {
+ case AF_INET:
+ if (p == IPPROTO_ICMP) {
+ if (m->m_len < off)
+ return (1);
+ m->m_data += off;
+ m->m_len -= off;
+ sum = in_cksum(m, len);
+ m->m_data -= off;
+ m->m_len += off;
+ } else {
+ if (m->m_len < sizeof(struct ip))
+ return (1);
+ sum = in4_cksum(m, p, off, len);
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (m->m_len < sizeof(struct ip6_hdr))
+ return (1);
+ sum = in6_cksum(m, p, off, len);
+ break;
+#endif /* INET6 */
+ default:
+ return (1);
+ }
+ }
+ if (sum) {
+ switch (p) {
+ case IPPROTO_TCP:
+ {
+ KMOD_TCPSTAT_INC(tcps_rcvbadsum);
+ break;
+ }
+ case IPPROTO_UDP:
+ {
+ KMOD_UDPSTAT_INC(udps_badsum);
+ break;
+ }
+ case IPPROTO_ICMP:
+ {
+ KMOD_ICMPSTAT_INC(icps_checksum);
+ break;
+ }
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+ {
+ KMOD_ICMP6STAT_INC(icp6s_checksum);
+ break;
+ }
+#endif /* INET6 */
+ }
+ return (1);
+ } else {
+ if (p == IPPROTO_TCP || p == IPPROTO_UDP) {
+ m->m_pkthdr.csum_flags |=
+ (CSUM_DATA_VALID | CSUM_PSEUDO_HDR);
+ m->m_pkthdr.csum_data = 0xffff;
+ }
+ }
+ return (0);
+}
+#else /* !__FreeBSD__ */
+/*
+ * check protocol (tcp/udp/icmp/icmp6) checksum and set mbuf flag
+ * off is the offset where the protocol header starts
+ * len is the total length of protocol header plus payload
+ * returns 0 when the checksum is valid, otherwise returns 1.
+ */
+int
+pf_check_proto_cksum(struct mbuf *m, int off, int len, u_int8_t p,
+ sa_family_t af)
+{
+ u_int16_t flag_ok, flag_bad;
+ u_int16_t sum;
+
+ switch (p) {
+ case IPPROTO_TCP:
+ flag_ok = M_TCP_CSUM_IN_OK;
+ flag_bad = M_TCP_CSUM_IN_BAD;
+ break;
+ case IPPROTO_UDP:
+ flag_ok = M_UDP_CSUM_IN_OK;
+ flag_bad = M_UDP_CSUM_IN_BAD;
+ break;
+ case IPPROTO_ICMP:
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+#endif /* INET6 */
+ flag_ok = flag_bad = 0;
+ break;
+ default:
+ return (1);
+ }
+ if (m->m_pkthdr.csum_flags & flag_ok)
+ return (0);
+ if (m->m_pkthdr.csum_flags & flag_bad)
+ return (1);
+ if (off < sizeof(struct ip) || len < sizeof(struct udphdr))
+ return (1);
+ if (m->m_pkthdr.len < off + len)
+ return (1);
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ if (p == IPPROTO_ICMP) {
+ if (m->m_len < off)
+ return (1);
+ m->m_data += off;
+ m->m_len -= off;
+ sum = in_cksum(m, len);
+ m->m_data -= off;
+ m->m_len += off;
+ } else {
+ if (m->m_len < sizeof(struct ip))
+ return (1);
+ sum = in4_cksum(m, p, off, len);
+ }
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (m->m_len < sizeof(struct ip6_hdr))
+ return (1);
+ sum = in6_cksum(m, p, off, len);
+ break;
+#endif /* INET6 */
+ default:
+ return (1);
+ }
+ if (sum) {
+ m->m_pkthdr.csum_flags |= flag_bad;
+ switch (p) {
+ case IPPROTO_TCP:
+ KMOD_TCPSTAT_INC(tcps_rcvbadsum);
+ break;
+ case IPPROTO_UDP:
+ KMOD_UDPSTAT_INC(udps_badsum);
+ break;
+ case IPPROTO_ICMP:
+ KMOD_ICMPSTAT_INC(icps_checksum);
+ break;
+#ifdef INET6
+ case IPPROTO_ICMPV6:
+ KMOD_ICMP6STAT_INC(icp6s_checksum);
+ break;
+#endif /* INET6 */
+ }
+ return (1);
+ }
+ m->m_pkthdr.csum_flags |= flag_ok;
+ return (0);
+}
+#endif /* __FreeBSD__ */
+
+#ifdef INET
+int
+#ifdef __FreeBSD__
+pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
+ struct ether_header *eh, struct inpcb *inp)
+#else
+pf_test(int dir, struct ifnet *ifp, struct mbuf **m0,
+ struct ether_header *eh)
+#endif
+{
+ struct pfi_kif *kif;
+ u_short action, reason = 0, log = 0;
+ struct mbuf *m = *m0;
+ struct ip *h = NULL; /* make the compiler happy */
+ struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
+ struct pf_state *s = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_pdesc pd;
+ int off, dirndx, pqid = 0;
+
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (!pf_status.running)
+#ifdef __FreeBSD__
+ {
+ PF_UNLOCK();
+#endif
+ return (PF_PASS);
+#ifdef __FreeBSD__
+ }
+#endif
+
+ memset(&pd, 0, sizeof(pd));
+ if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_test: pf_get_mtag returned NULL\n"));
+ return (PF_DROP);
+ }
+#ifdef __FreeBSD__
+ if (m->m_flags & M_SKIP_FIREWALL) {
+ PF_UNLOCK();
+ return (PF_PASS);
+ }
+#else
+ if (pd.pf_mtag->flags & PF_TAG_GENERATED)
+ return (PF_PASS);
+#endif
+
+#ifdef __FreeBSD__
+ /* XXX_IMPORT: later */
+#else
+ if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
+ ifp = ifp->if_carpdev;
+#endif
+
+ kif = (struct pfi_kif *)ifp->if_pf_kif;
+ if (kif == NULL) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_test: kif == NULL, if_xname %s\n", ifp->if_xname));
+ return (PF_DROP);
+ }
+ if (kif->pfik_flags & PFI_IFLAG_SKIP) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ return (PF_PASS);
+ }
+
+#ifdef __FreeBSD__
+ M_ASSERTPKTHDR(m);
+#else
+#ifdef DIAGNOSTIC
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("non-M_PKTHDR is passed to pf_test");
+#endif /* DIAGNOSTIC */
+#endif /* __FreeBSD__ */
+
+ if (m->m_pkthdr.len < (int)sizeof(*h)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
+ log = 1;
+ goto done;
+ }
+
+ /* We do IP header normalization and packet reassembly here */
+ if (pf_normalize_ip(m0, dir, kif, &reason, &pd) != PF_PASS) {
+ action = PF_DROP;
+ goto done;
+ }
+ m = *m0;
+ h = mtod(m, struct ip *);
+
+ off = h->ip_hl << 2;
+ if (off < (int)sizeof(*h)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
+ log = 1;
+ goto done;
+ }
+
+ pd.src = (struct pf_addr *)&h->ip_src;
+ pd.dst = (struct pf_addr *)&h->ip_dst;
+ PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET);
+ pd.ip_sum = &h->ip_sum;
+ pd.proto = h->ip_p;
+ pd.af = AF_INET;
+ pd.tos = h->ip_tos;
+ pd.tot_len = ntohs(h->ip_len);
+ pd.eh = eh;
+
+ /* handle fragments that didn't get reassembled by normalization */
+ if (h->ip_off & htons(IP_MF | IP_OFFMASK)) {
+ action = pf_test_fragment(&r, dir, kif, m, h,
+ &pd, &a, &ruleset);
+ goto done;
+ }
+
+ switch (h->ip_p) {
+
+ case IPPROTO_TCP: {
+ struct tcphdr th;
+
+ pd.hdr.tcp = &th;
+ if (!pf_pull_hdr(m, off, &th, sizeof(th),
+ &action, &reason, AF_INET)) {
+ log = action != PF_PASS;
+ goto done;
+ }
+ if (dir == PF_IN && pf_check_proto_cksum(m, off,
+ ntohs(h->ip_len) - off, IPPROTO_TCP, AF_INET)) {
+ REASON_SET(&reason, PFRES_PROTCKSUM);
+ action = PF_DROP;
+ goto done;
+ }
+ pd.p_len = pd.tot_len - off - (th.th_off << 2);
+ if ((th.th_flags & TH_ACK) && pd.p_len == 0)
+ pqid = 1;
+ action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
+ if (action == PF_DROP)
+ goto done;
+ action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
+ &reason);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, NULL, inp);
+#else
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, &ipintrq);
+#endif
+ break;
+ }
+
+ case IPPROTO_UDP: {
+ struct udphdr uh;
+
+ pd.hdr.udp = &uh;
+ if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
+ &action, &reason, AF_INET)) {
+ log = action != PF_PASS;
+ goto done;
+ }
+ if (dir == PF_IN && uh.uh_sum && pf_check_proto_cksum(m,
+ off, ntohs(h->ip_len) - off, IPPROTO_UDP, AF_INET)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_PROTCKSUM);
+ goto done;
+ }
+ if (uh.uh_dport == 0 ||
+ ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
+ ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
+ goto done;
+ }
+ action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, NULL, inp);
+#else
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, &ipintrq);
+#endif
+ break;
+ }
+
+ case IPPROTO_ICMP: {
+ struct icmp ih;
+
+ pd.hdr.icmp = &ih;
+ if (!pf_pull_hdr(m, off, &ih, ICMP_MINLEN,
+ &action, &reason, AF_INET)) {
+ log = action != PF_PASS;
+ goto done;
+ }
+ if (dir == PF_IN && pf_check_proto_cksum(m, off,
+ ntohs(h->ip_len) - off, IPPROTO_ICMP, AF_INET)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_PROTCKSUM);
+ goto done;
+ }
+ action = pf_test_state_icmp(&s, dir, kif, m, off, h, &pd,
+ &reason);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_icmp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, NULL);
+#else
+ action = pf_test_icmp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, &ipintrq);
+#endif
+ break;
+ }
+
+ default:
+ action = pf_test_state_other(&s, dir, kif, &pd);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_other(&r, &s, dir, kif, m, off, h,
+ &pd, &a, &ruleset, NULL);
+#else
+ action = pf_test_other(&r, &s, dir, kif, m, off, h,
+ &pd, &a, &ruleset, &ipintrq);
+#endif
+ break;
+ }
+
+done:
+ if (action == PF_PASS && h->ip_hl > 5 &&
+ !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: dropping packet with ip options\n"));
+ }
+
+ if ((s && s->tag) || r->rtableid)
+ pf_tag_packet(m, pd.pf_mtag, s ? s->tag : 0, r->rtableid);
+
+#ifdef ALTQ
+ if (action == PF_PASS && r->qid) {
+ if (pqid || (pd.tos & IPTOS_LOWDELAY))
+ pd.pf_mtag->qid = r->pqid;
+ else
+ pd.pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pd.pf_mtag->af = AF_INET;
+ pd.pf_mtag->hdr = h;
+ }
+#endif /* ALTQ */
+
+ /*
+ * connections redirected to loopback should not match sockets
+ * bound specifically to loopback due to security implications,
+ * see tcp_input() and in_pcblookup_listen().
+ */
+ if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
+ pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
+ (s->nat_rule.ptr->action == PF_RDR ||
+ s->nat_rule.ptr->action == PF_BINAT) &&
+ (ntohl(pd.dst->v4.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
+ pd.pf_mtag->flags |= PF_TAG_TRANSLATE_LOCALHOST;
+
+ if (log) {
+ struct pf_rule *lr;
+
+ if (s != NULL && s->nat_rule.ptr != NULL &&
+ s->nat_rule.ptr->log & PF_LOG_ALL)
+ lr = s->nat_rule.ptr;
+ else
+ lr = r;
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, lr, a, ruleset,
+ &pd);
+ }
+
+ kif->pfik_bytes[0][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
+ kif->pfik_packets[0][dir == PF_OUT][action != PF_PASS]++;
+
+ if (action == PF_PASS || r->action == PF_DROP) {
+ dirndx = (dir == PF_OUT);
+ r->packets[dirndx]++;
+ r->bytes[dirndx] += pd.tot_len;
+ if (a != NULL) {
+ a->packets[dirndx]++;
+ a->bytes[dirndx] += pd.tot_len;
+ }
+ if (s != NULL) {
+ if (s->nat_rule.ptr != NULL) {
+ s->nat_rule.ptr->packets[dirndx]++;
+ s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
+ }
+ if (s->src_node != NULL) {
+ s->src_node->packets[dirndx]++;
+ s->src_node->bytes[dirndx] += pd.tot_len;
+ }
+ if (s->nat_src_node != NULL) {
+ s->nat_src_node->packets[dirndx]++;
+ s->nat_src_node->bytes[dirndx] += pd.tot_len;
+ }
+ dirndx = (dir == s->direction) ? 0 : 1;
+ s->packets[dirndx]++;
+ s->bytes[dirndx] += pd.tot_len;
+ }
+ tr = r;
+ nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
+ if (nr != NULL) {
+ struct pf_addr *x;
+ /*
+ * XXX: we need to make sure that the addresses
+ * passed to pfr_update_stats() are the same than
+ * the addresses used during matching (pfr_match)
+ */
+ if (r == &pf_default_rule) {
+ tr = nr;
+ x = (s == NULL || s->direction == dir) ?
+ &pd.baddr : &pd.naddr;
+ } else
+ x = (s == NULL || s->direction == dir) ?
+ &pd.naddr : &pd.baddr;
+ if (x == &pd.baddr || s == NULL) {
+ /* we need to change the address */
+ if (dir == PF_OUT)
+ pd.src = x;
+ else
+ pd.dst = x;
+ }
+ }
+ if (tr->src.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
+ s->direction == dir) ? pd.src : pd.dst, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->src.neg);
+ if (tr->dst.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
+ s->direction == dir) ? pd.dst : pd.src, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->dst.neg);
+ }
+
+
+ if (action == PF_SYNPROXY_DROP) {
+ m_freem(*m0);
+ *m0 = NULL;
+ action = PF_PASS;
+ } else if (r->rt)
+ /* pf_route can free the mbuf causing *m0 to become NULL */
+ pf_route(m0, r, dir, ifp, s, &pd);
+
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+
+ return (action);
+}
+#endif /* INET */
+
+#ifdef INET6
+int
+#ifdef __FreeBSD__
+pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
+ struct ether_header *eh, struct inpcb *inp)
+#else
+pf_test6(int dir, struct ifnet *ifp, struct mbuf **m0,
+ struct ether_header *eh)
+#endif
+{
+ struct pfi_kif *kif;
+ u_short action, reason = 0, log = 0;
+ struct mbuf *m = *m0, *n = NULL;
+ struct ip6_hdr *h;
+ struct pf_rule *a = NULL, *r = &pf_default_rule, *tr, *nr;
+ struct pf_state *s = NULL;
+ struct pf_ruleset *ruleset = NULL;
+ struct pf_pdesc pd;
+ int off, terminal = 0, dirndx, rh_cnt = 0;
+
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+
+ if (!pf_status.running)
+#ifdef __FreeBSD__
+ {
+ PF_UNLOCK();
+#endif
+ return (PF_PASS);
+#ifdef __FreeBSD__
+ }
+#endif
+
+ memset(&pd, 0, sizeof(pd));
+ if ((pd.pf_mtag = pf_get_mtag(m)) == NULL) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_test6: pf_get_mtag returned NULL\n"));
+ return (PF_DROP);
+ }
+ if (pd.pf_mtag->flags & PF_TAG_GENERATED)
+ return (PF_PASS);
+
+#ifdef __FreeBSD__
+ /* XXX_IMPORT: later */
+#else
+ if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
+ ifp = ifp->if_carpdev;
+#endif
+
+ kif = (struct pfi_kif *)ifp->if_pf_kif;
+ if (kif == NULL) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ DPFPRINTF(PF_DEBUG_URGENT,
+ ("pf_test6: kif == NULL, if_xname %s\n", ifp->if_xname));
+ return (PF_DROP);
+ }
+ if (kif->pfik_flags & PFI_IFLAG_SKIP) {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ return (PF_PASS);
+ }
+
+#ifdef __FreeBSD__
+ M_ASSERTPKTHDR(m);
+#else
+#ifdef DIAGNOSTIC
+ if ((m->m_flags & M_PKTHDR) == 0)
+ panic("non-M_PKTHDR is passed to pf_test6");
+#endif /* DIAGNOSTIC */
+#endif
+
+#ifdef __FreeBSD__
+ h = NULL; /* make the compiler happy */
+#endif
+
+ if (m->m_pkthdr.len < (int)sizeof(*h)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
+ log = 1;
+ goto done;
+ }
+
+ /* We do IP header normalization and packet reassembly here */
+ if (pf_normalize_ip6(m0, dir, kif, &reason, &pd) != PF_PASS) {
+ action = PF_DROP;
+ goto done;
+ }
+ m = *m0;
+ h = mtod(m, struct ip6_hdr *);
+
+#if 1
+ /*
+ * we do not support jumbogram yet. if we keep going, zero ip6_plen
+ * will do something bad, so drop the packet for now.
+ */
+ if (htons(h->ip6_plen) == 0) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_NORM); /*XXX*/
+ goto done;
+ }
+#endif
+
+ pd.src = (struct pf_addr *)&h->ip6_src;
+ pd.dst = (struct pf_addr *)&h->ip6_dst;
+ PF_ACPY(&pd.baddr, dir == PF_OUT ? pd.src : pd.dst, AF_INET6);
+ pd.ip_sum = NULL;
+ pd.af = AF_INET6;
+ pd.tos = 0;
+ pd.tot_len = ntohs(h->ip6_plen) + sizeof(struct ip6_hdr);
+ pd.eh = eh;
+
+ off = ((caddr_t)h - m->m_data) + sizeof(struct ip6_hdr);
+ pd.proto = h->ip6_nxt;
+ do {
+ switch (pd.proto) {
+ case IPPROTO_FRAGMENT:
+ action = pf_test_fragment(&r, dir, kif, m, h,
+ &pd, &a, &ruleset);
+ if (action == PF_DROP)
+ REASON_SET(&reason, PFRES_FRAG);
+ goto done;
+ case IPPROTO_ROUTING: {
+ struct ip6_rthdr rthdr;
+
+ if (rh_cnt++) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 more than one rthdr\n"));
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ goto done;
+ }
+ if (!pf_pull_hdr(m, off, &rthdr, sizeof(rthdr), NULL,
+ &reason, pd.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 short rthdr\n"));
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
+ log = 1;
+ goto done;
+ }
+ if (rthdr.ip6r_type == IPV6_RTHDR_TYPE_0) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 rthdr0\n"));
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ goto done;
+ }
+ /* fallthrough */
+ }
+ case IPPROTO_AH:
+ case IPPROTO_HOPOPTS:
+ case IPPROTO_DSTOPTS: {
+ /* get next header and header length */
+ struct ip6_ext opt6;
+
+ if (!pf_pull_hdr(m, off, &opt6, sizeof(opt6),
+ NULL, &reason, pd.af)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: IPv6 short opt\n"));
+ action = PF_DROP;
+ log = 1;
+ goto done;
+ }
+ if (pd.proto == IPPROTO_AH)
+ off += (opt6.ip6e_len + 2) * 4;
+ else
+ off += (opt6.ip6e_len + 1) * 8;
+ pd.proto = opt6.ip6e_nxt;
+ /* goto the next header */
+ break;
+ }
+ default:
+ terminal++;
+ break;
+ }
+ } while (!terminal);
+
+ /* if there's no routing header, use unmodified mbuf for checksumming */
+ if (!n)
+ n = m;
+
+ switch (pd.proto) {
+
+ case IPPROTO_TCP: {
+ struct tcphdr th;
+
+ pd.hdr.tcp = &th;
+ if (!pf_pull_hdr(m, off, &th, sizeof(th),
+ &action, &reason, AF_INET6)) {
+ log = action != PF_PASS;
+ goto done;
+ }
+ if (dir == PF_IN && pf_check_proto_cksum(n, off,
+ ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
+ IPPROTO_TCP, AF_INET6)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_PROTCKSUM);
+ goto done;
+ }
+ pd.p_len = pd.tot_len - off - (th.th_off << 2);
+ action = pf_normalize_tcp(dir, kif, m, 0, off, h, &pd);
+ if (action == PF_DROP)
+ goto done;
+ action = pf_test_state_tcp(&s, dir, kif, m, off, h, &pd,
+ &reason);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, NULL, inp);
+#else
+ action = pf_test_tcp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, &ip6intrq);
+#endif
+ break;
+ }
+
+ case IPPROTO_UDP: {
+ struct udphdr uh;
+
+ pd.hdr.udp = &uh;
+ if (!pf_pull_hdr(m, off, &uh, sizeof(uh),
+ &action, &reason, AF_INET6)) {
+ log = action != PF_PASS;
+ goto done;
+ }
+ if (dir == PF_IN && uh.uh_sum && pf_check_proto_cksum(n,
+ off, ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
+ IPPROTO_UDP, AF_INET6)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_PROTCKSUM);
+ goto done;
+ }
+ if (uh.uh_dport == 0 ||
+ ntohs(uh.uh_ulen) > m->m_pkthdr.len - off ||
+ ntohs(uh.uh_ulen) < sizeof(struct udphdr)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_SHORT);
+ goto done;
+ }
+ action = pf_test_state_udp(&s, dir, kif, m, off, h, &pd);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, NULL, inp);
+#else
+ action = pf_test_udp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, &ip6intrq);
+#endif
+ break;
+ }
+
+ case IPPROTO_ICMPV6: {
+ struct icmp6_hdr ih;
+
+ pd.hdr.icmp6 = &ih;
+ if (!pf_pull_hdr(m, off, &ih, sizeof(ih),
+ &action, &reason, AF_INET6)) {
+ log = action != PF_PASS;
+ goto done;
+ }
+ if (dir == PF_IN && pf_check_proto_cksum(n, off,
+ ntohs(h->ip6_plen) - (off - sizeof(struct ip6_hdr)),
+ IPPROTO_ICMPV6, AF_INET6)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_PROTCKSUM);
+ goto done;
+ }
+ action = pf_test_state_icmp(&s, dir, kif,
+ m, off, h, &pd, &reason);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_icmp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, NULL);
+#else
+ action = pf_test_icmp(&r, &s, dir, kif,
+ m, off, h, &pd, &a, &ruleset, &ip6intrq);
+#endif
+ break;
+ }
+
+ default:
+ action = pf_test_state_other(&s, dir, kif, &pd);
+ if (action == PF_PASS) {
+#if NPFSYNC
+ pfsync_update_state(s);
+#endif /* NPFSYNC */
+ r = s->rule.ptr;
+ a = s->anchor.ptr;
+ log = s->log;
+ } else if (s == NULL)
+#ifdef __FreeBSD__
+ action = pf_test_other(&r, &s, dir, kif, m, off, h,
+ &pd, &a, &ruleset, NULL);
+#else
+ action = pf_test_other(&r, &s, dir, kif, m, off, h,
+ &pd, &a, &ruleset, &ip6intrq);
+#endif
+ break;
+ }
+
+done:
+ /* handle dangerous IPv6 extension headers. */
+ if (action == PF_PASS && rh_cnt &&
+ !((s && s->state_flags & PFSTATE_ALLOWOPTS) || r->allow_opts)) {
+ action = PF_DROP;
+ REASON_SET(&reason, PFRES_IPOPTIONS);
+ log = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: dropping packet with dangerous v6 headers\n"));
+ }
+
+ if ((s && s->tag) || r->rtableid)
+ pf_tag_packet(m, pd.pf_mtag, s ? s->tag : 0, r->rtableid);
+
+#ifdef ALTQ
+ if (action == PF_PASS && r->qid) {
+ if (pd.tos & IPTOS_LOWDELAY)
+ pd.pf_mtag->qid = r->pqid;
+ else
+ pd.pf_mtag->qid = r->qid;
+ /* add hints for ecn */
+ pd.pf_mtag->af = AF_INET6;
+ pd.pf_mtag->hdr = h;
+ }
+#endif /* ALTQ */
+
+ if (dir == PF_IN && action == PF_PASS && (pd.proto == IPPROTO_TCP ||
+ pd.proto == IPPROTO_UDP) && s != NULL && s->nat_rule.ptr != NULL &&
+ (s->nat_rule.ptr->action == PF_RDR ||
+ s->nat_rule.ptr->action == PF_BINAT) &&
+ IN6_IS_ADDR_LOOPBACK(&pd.dst->v6))
+ pd.pf_mtag->flags |= PF_TAG_TRANSLATE_LOCALHOST;
+
+ if (log) {
+ struct pf_rule *lr;
+
+ if (s != NULL && s->nat_rule.ptr != NULL &&
+ s->nat_rule.ptr->log & PF_LOG_ALL)
+ lr = s->nat_rule.ptr;
+ else
+ lr = r;
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, reason, lr, a, ruleset,
+ &pd);
+ }
+
+ kif->pfik_bytes[1][dir == PF_OUT][action != PF_PASS] += pd.tot_len;
+ kif->pfik_packets[1][dir == PF_OUT][action != PF_PASS]++;
+
+ if (action == PF_PASS || r->action == PF_DROP) {
+ dirndx = (dir == PF_OUT);
+ r->packets[dirndx]++;
+ r->bytes[dirndx] += pd.tot_len;
+ if (a != NULL) {
+ a->packets[dirndx]++;
+ a->bytes[dirndx] += pd.tot_len;
+ }
+ if (s != NULL) {
+ if (s->nat_rule.ptr != NULL) {
+ s->nat_rule.ptr->packets[dirndx]++;
+ s->nat_rule.ptr->bytes[dirndx] += pd.tot_len;
+ }
+ if (s->src_node != NULL) {
+ s->src_node->packets[dirndx]++;
+ s->src_node->bytes[dirndx] += pd.tot_len;
+ }
+ if (s->nat_src_node != NULL) {
+ s->nat_src_node->packets[dirndx]++;
+ s->nat_src_node->bytes[dirndx] += pd.tot_len;
+ }
+ dirndx = (dir == s->direction) ? 0 : 1;
+ s->packets[dirndx]++;
+ s->bytes[dirndx] += pd.tot_len;
+ }
+ tr = r;
+ nr = (s != NULL) ? s->nat_rule.ptr : pd.nat_rule;
+ if (nr != NULL) {
+ struct pf_addr *x;
+ /*
+ * XXX: we need to make sure that the addresses
+ * passed to pfr_update_stats() are the same than
+ * the addresses used during matching (pfr_match)
+ */
+ if (r == &pf_default_rule) {
+ tr = nr;
+ x = (s == NULL || s->direction == dir) ?
+ &pd.baddr : &pd.naddr;
+ } else {
+ x = (s == NULL || s->direction == dir) ?
+ &pd.naddr : &pd.baddr;
+ }
+ if (x == &pd.baddr || s == NULL) {
+ if (dir == PF_OUT)
+ pd.src = x;
+ else
+ pd.dst = x;
+ }
+ }
+ if (tr->src.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->src.addr.p.tbl, (s == NULL ||
+ s->direction == dir) ? pd.src : pd.dst, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->src.neg);
+ if (tr->dst.addr.type == PF_ADDR_TABLE)
+ pfr_update_stats(tr->dst.addr.p.tbl, (s == NULL ||
+ s->direction == dir) ? pd.dst : pd.src, pd.af,
+ pd.tot_len, dir == PF_OUT, r->action == PF_PASS,
+ tr->dst.neg);
+ }
+
+
+ if (action == PF_SYNPROXY_DROP) {
+ m_freem(*m0);
+ *m0 = NULL;
+ action = PF_PASS;
+ } else if (r->rt)
+ /* pf_route6 can free the mbuf causing *m0 to become NULL */
+ pf_route6(m0, r, dir, ifp, s, &pd);
+
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ return (action);
+}
+#endif /* INET6 */
+
+int
+pf_check_congestion(struct ifqueue *ifq)
+{
+#ifdef __FreeBSD__
+ /* XXX_IMPORT: later */
+ return (0);
+#else
+ if (ifq->ifq_congestion)
+ return (1);
+ else
+ return (0);
+#endif
+}
diff --git a/freebsd/sys/contrib/pf/net/pf_if.c b/freebsd/sys/contrib/pf/net/pf_if.c
new file mode 100644
index 00000000..e873a2ef
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_if.c
@@ -0,0 +1,950 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: pf_if.c,v 1.46 2006/12/13 09:01:59 itojun Exp $ */
+
+/*
+ * Copyright 2005 Henning Brauer <henning@openbsd.org>
+ * Copyright 2005 Ryan McBride <mcbride@openbsd.org>
+ * Copyright (c) 2001 Daniel Hartmeier
+ * Copyright (c) 2003 Cedric Berger
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(__FreeBSD__)
+#include <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/malloc.h>
+#endif
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/filio.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/socketvar.h>
+#include <freebsd/sys/kernel.h>
+#ifndef __FreeBSD__
+#include <freebsd/sys/device.h>
+#endif
+#include <freebsd/sys/time.h>
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/if_types.h>
+#ifdef __FreeBSD__
+#include <freebsd/net/vnet.h>
+#endif
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_var.h>
+
+#include <freebsd/net/pfvar.h>
+
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#endif /* INET6 */
+
+struct pfi_kif *pfi_all = NULL;
+struct pfi_statehead pfi_statehead;
+#ifdef __FreeBSD__
+uma_zone_t pfi_addr_pl;
+#else
+struct pool pfi_addr_pl;
+#endif
+struct pfi_ifhead pfi_ifs;
+long pfi_update = 1;
+struct pfr_addr *pfi_buffer;
+int pfi_buffer_cnt;
+int pfi_buffer_max;
+#ifdef __FreeBSD__
+eventhandler_tag pfi_attach_cookie = NULL;
+eventhandler_tag pfi_detach_cookie = NULL;
+eventhandler_tag pfi_attach_group_cookie = NULL;
+eventhandler_tag pfi_change_group_cookie = NULL;
+eventhandler_tag pfi_detach_group_cookie = NULL;
+eventhandler_tag pfi_ifaddr_event_cookie = NULL;
+#endif
+
+void pfi_kif_update(struct pfi_kif *);
+void pfi_dynaddr_update(struct pfi_dynaddr *dyn);
+void pfi_table_update(struct pfr_ktable *, struct pfi_kif *,
+ int, int);
+void pfi_kifaddr_update(void *);
+void pfi_instance_add(struct ifnet *, int, int);
+void pfi_address_add(struct sockaddr *, int, int);
+int pfi_if_compare(struct pfi_kif *, struct pfi_kif *);
+int pfi_skip_if(const char *, struct pfi_kif *);
+int pfi_unmask(void *);
+#ifdef __FreeBSD__
+void pfi_attach_ifnet_event(void * __unused, struct ifnet *);
+void pfi_detach_ifnet_event(void * __unused, struct ifnet *);
+void pfi_attach_group_event(void * __unused, struct ifg_group *);
+void pfi_change_group_event(void * __unused, char *);
+void pfi_detach_group_event(void * __unused, struct ifg_group *);
+void pfi_ifaddr_event(void * __unused, struct ifnet *);
+
+#endif
+
+RB_PROTOTYPE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
+RB_GENERATE(pfi_ifhead, pfi_kif, pfik_tree, pfi_if_compare);
+
+#define PFI_BUFFER_MAX 0x10000
+#define PFI_MTYPE M_IFADDR
+
+void
+pfi_initialize(void)
+{
+
+ if (pfi_all != NULL) /* already initialized */
+ return;
+
+ TAILQ_INIT(&pfi_statehead);
+#ifndef __FreeBSD__
+ pool_init(&pfi_addr_pl, sizeof(struct pfi_dynaddr), 0, 0, 0,
+ "pfiaddrpl", &pool_allocator_nointr);
+#endif
+ pfi_buffer_max = 64;
+ pfi_buffer = malloc(pfi_buffer_max * sizeof(*pfi_buffer),
+ PFI_MTYPE, M_WAITOK);
+
+ if ((pfi_all = pfi_kif_get(IFG_ALL)) == NULL)
+ panic("pfi_kif_get for pfi_all failed");
+
+#ifdef __FreeBSD__
+ struct ifg_group *ifg;
+ struct ifnet *ifp;
+
+ IFNET_RLOCK();
+ TAILQ_FOREACH(ifg, &V_ifg_head, ifg_next)
+ pfi_attach_ifgroup(ifg);
+ TAILQ_FOREACH(ifp, &V_ifnet, if_link)
+ pfi_attach_ifnet(ifp);
+ IFNET_RUNLOCK();
+
+ pfi_attach_cookie = EVENTHANDLER_REGISTER(ifnet_arrival_event,
+ pfi_attach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
+ pfi_detach_cookie = EVENTHANDLER_REGISTER(ifnet_departure_event,
+ pfi_detach_ifnet_event, NULL, EVENTHANDLER_PRI_ANY);
+ pfi_attach_group_cookie = EVENTHANDLER_REGISTER(group_attach_event,
+ pfi_attach_group_event, NULL, EVENTHANDLER_PRI_ANY);
+ pfi_change_group_cookie = EVENTHANDLER_REGISTER(group_change_event,
+ pfi_change_group_event, NULL, EVENTHANDLER_PRI_ANY);
+ pfi_detach_group_cookie = EVENTHANDLER_REGISTER(group_detach_event,
+ pfi_detach_group_event, NULL, EVENTHANDLER_PRI_ANY);
+ pfi_ifaddr_event_cookie = EVENTHANDLER_REGISTER(ifaddr_event,
+ pfi_ifaddr_event, NULL, EVENTHANDLER_PRI_ANY);
+#endif
+}
+
+#ifdef __FreeBSD__
+void
+pfi_cleanup(void)
+{
+ struct pfi_kif *p;
+
+ PF_UNLOCK();
+ EVENTHANDLER_DEREGISTER(ifnet_arrival_event, pfi_attach_cookie);
+ EVENTHANDLER_DEREGISTER(ifnet_departure_event, pfi_detach_cookie);
+ EVENTHANDLER_DEREGISTER(group_attach_event, pfi_attach_group_cookie);
+ EVENTHANDLER_DEREGISTER(group_change_event, pfi_change_group_cookie);
+ EVENTHANDLER_DEREGISTER(group_detach_event, pfi_detach_group_cookie);
+ EVENTHANDLER_DEREGISTER(ifaddr_event, pfi_ifaddr_event_cookie);
+ PF_LOCK();
+
+ pfi_all = NULL;
+ while ((p = RB_MIN(pfi_ifhead, &pfi_ifs))) {
+ if (p->pfik_rules || p->pfik_states) {
+ printf("pfi_cleanup: dangling refs for %s\n",
+ p->pfik_name);
+ }
+
+ RB_REMOVE(pfi_ifhead, &pfi_ifs, p);
+ free(p, PFI_MTYPE);
+ }
+
+ free(pfi_buffer, PFI_MTYPE);
+}
+#endif
+
+struct pfi_kif *
+pfi_kif_get(const char *kif_name)
+{
+ struct pfi_kif *kif;
+ struct pfi_kif_cmp s;
+
+ bzero(&s, sizeof(s));
+ strlcpy(s.pfik_name, kif_name, sizeof(s.pfik_name));
+ if ((kif = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&s)) != NULL)
+ return (kif);
+
+ /* create new one */
+#ifdef __FreeBSD__
+ if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_NOWAIT)) == NULL)
+#else
+ if ((kif = malloc(sizeof(*kif), PFI_MTYPE, M_DONTWAIT)) == NULL)
+#endif
+ return (NULL);
+
+ bzero(kif, sizeof(*kif));
+ strlcpy(kif->pfik_name, kif_name, sizeof(kif->pfik_name));
+#ifdef __FreeBSD__
+ /*
+ * It seems that the value of time_second is in unintialzied state
+ * when pf sets interface statistics clear time in boot phase if pf
+ * was statically linked to kernel. Instead of setting the bogus
+ * time value have pfi_get_ifaces handle this case. In
+ * pfi_get_ifaces it uses boottime.tv_sec if it sees the time is 0.
+ */
+ kif->pfik_tzero = time_second > 1 ? time_second : 0;
+#else
+ kif->pfik_tzero = time_second;
+#endif
+ TAILQ_INIT(&kif->pfik_dynaddrs);
+
+ RB_INSERT(pfi_ifhead, &pfi_ifs, kif);
+ return (kif);
+}
+
+void
+pfi_kif_ref(struct pfi_kif *kif, enum pfi_kif_refs what)
+{
+ switch (what) {
+ case PFI_KIF_REF_RULE:
+ kif->pfik_rules++;
+ break;
+ case PFI_KIF_REF_STATE:
+ if (!kif->pfik_states++)
+ TAILQ_INSERT_TAIL(&pfi_statehead, kif, pfik_w_states);
+ break;
+ default:
+ panic("pfi_kif_ref with unknown type");
+ }
+}
+
+void
+pfi_kif_unref(struct pfi_kif *kif, enum pfi_kif_refs what)
+{
+ if (kif == NULL)
+ return;
+
+ switch (what) {
+ case PFI_KIF_REF_NONE:
+ break;
+ case PFI_KIF_REF_RULE:
+ if (kif->pfik_rules <= 0) {
+ printf("pfi_kif_unref: rules refcount <= 0\n");
+ return;
+ }
+ kif->pfik_rules--;
+ break;
+ case PFI_KIF_REF_STATE:
+ if (kif->pfik_states <= 0) {
+ printf("pfi_kif_unref: state refcount <= 0\n");
+ return;
+ }
+ if (!--kif->pfik_states)
+ TAILQ_REMOVE(&pfi_statehead, kif, pfik_w_states);
+ break;
+ default:
+ panic("pfi_kif_unref with unknown type");
+ }
+
+ if (kif->pfik_ifp != NULL || kif->pfik_group != NULL || kif == pfi_all)
+ return;
+
+ if (kif->pfik_rules || kif->pfik_states)
+ return;
+
+ RB_REMOVE(pfi_ifhead, &pfi_ifs, kif);
+ free(kif, PFI_MTYPE);
+}
+
+int
+pfi_kif_match(struct pfi_kif *rule_kif, struct pfi_kif *packet_kif)
+{
+ struct ifg_list *p;
+
+ if (rule_kif == NULL || rule_kif == packet_kif)
+ return (1);
+
+ if (rule_kif->pfik_group != NULL)
+ TAILQ_FOREACH(p, &packet_kif->pfik_ifp->if_groups, ifgl_next)
+ if (p->ifgl_group == rule_kif->pfik_group)
+ return (1);
+
+ return (0);
+}
+
+void
+pfi_attach_ifnet(struct ifnet *ifp)
+{
+ struct pfi_kif *kif;
+ int s;
+
+ pfi_initialize();
+ s = splsoftnet();
+ pfi_update++;
+ if ((kif = pfi_kif_get(ifp->if_xname)) == NULL)
+ panic("pfi_kif_get failed");
+
+ kif->pfik_ifp = ifp;
+ ifp->if_pf_kif = (caddr_t)kif;
+
+#ifndef __FreeBSD__
+ if ((kif->pfik_ah_cookie = hook_establish(ifp->if_addrhooks, 1,
+ pfi_kifaddr_update, kif)) == NULL)
+ panic("pfi_attach_ifnet: cannot allocate '%s' address hook",
+ ifp->if_xname);
+#endif
+
+ pfi_kif_update(kif);
+
+ splx(s);
+}
+
+void
+pfi_detach_ifnet(struct ifnet *ifp)
+{
+ int s;
+ struct pfi_kif *kif;
+
+ if ((kif = (struct pfi_kif *)ifp->if_pf_kif) == NULL)
+ return;
+
+ s = splsoftnet();
+ pfi_update++;
+#ifndef __FreeBSD__
+ hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie);
+#endif
+ pfi_kif_update(kif);
+
+ kif->pfik_ifp = NULL;
+ ifp->if_pf_kif = NULL;
+ pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ splx(s);
+}
+
+void
+pfi_attach_ifgroup(struct ifg_group *ifg)
+{
+ struct pfi_kif *kif;
+ int s;
+
+ pfi_initialize();
+ s = splsoftnet();
+ pfi_update++;
+ if ((kif = pfi_kif_get(ifg->ifg_group)) == NULL)
+ panic("pfi_kif_get failed");
+
+ kif->pfik_group = ifg;
+ ifg->ifg_pf_kif = (caddr_t)kif;
+
+ splx(s);
+}
+
+void
+pfi_detach_ifgroup(struct ifg_group *ifg)
+{
+ int s;
+ struct pfi_kif *kif;
+
+ if ((kif = (struct pfi_kif *)ifg->ifg_pf_kif) == NULL)
+ return;
+
+ s = splsoftnet();
+ pfi_update++;
+
+ kif->pfik_group = NULL;
+ ifg->ifg_pf_kif = NULL;
+ pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ splx(s);
+}
+
+void
+pfi_group_change(const char *group)
+{
+ struct pfi_kif *kif;
+ int s;
+
+ s = splsoftnet();
+ pfi_update++;
+ if ((kif = pfi_kif_get(group)) == NULL)
+ panic("pfi_kif_get failed");
+
+ pfi_kif_update(kif);
+
+ splx(s);
+}
+
+int
+pfi_match_addr(struct pfi_dynaddr *dyn, struct pf_addr *a, sa_family_t af)
+{
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ switch (dyn->pfid_acnt4) {
+ case 0:
+ return (0);
+ case 1:
+ return (PF_MATCHA(0, &dyn->pfid_addr4,
+ &dyn->pfid_mask4, a, AF_INET));
+ default:
+ return (pfr_match_addr(dyn->pfid_kt, a, AF_INET));
+ }
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ switch (dyn->pfid_acnt6) {
+ case 0:
+ return (0);
+ case 1:
+ return (PF_MATCHA(0, &dyn->pfid_addr6,
+ &dyn->pfid_mask6, a, AF_INET6));
+ default:
+ return (pfr_match_addr(dyn->pfid_kt, a, AF_INET6));
+ }
+ break;
+#endif /* INET6 */
+ default:
+ return (0);
+ }
+}
+
+int
+pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af)
+{
+ struct pfi_dynaddr *dyn;
+ char tblname[PF_TABLE_NAME_SIZE];
+ struct pf_ruleset *ruleset = NULL;
+ int s, rv = 0;
+
+ if (aw->type != PF_ADDR_DYNIFTL)
+ return (0);
+ if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL)
+ return (1);
+ bzero(dyn, sizeof(*dyn));
+
+ s = splsoftnet();
+ if (!strcmp(aw->v.ifname, "self"))
+ dyn->pfid_kif = pfi_kif_get(IFG_ALL);
+ else
+ dyn->pfid_kif = pfi_kif_get(aw->v.ifname);
+ if (dyn->pfid_kif == NULL) {
+ rv = 1;
+ goto _bad;
+ }
+ pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE);
+
+ dyn->pfid_net = pfi_unmask(&aw->v.a.mask);
+ if (af == AF_INET && dyn->pfid_net == 32)
+ dyn->pfid_net = 128;
+ strlcpy(tblname, aw->v.ifname, sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_NETWORK)
+ strlcat(tblname, ":network", sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_BROADCAST)
+ strlcat(tblname, ":broadcast", sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_PEER)
+ strlcat(tblname, ":peer", sizeof(tblname));
+ if (aw->iflags & PFI_AFLAG_NOALIAS)
+ strlcat(tblname, ":0", sizeof(tblname));
+ if (dyn->pfid_net != 128)
+ snprintf(tblname + strlen(tblname),
+ sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net);
+ if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) {
+ rv = 1;
+ goto _bad;
+ }
+
+ if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) {
+ rv = 1;
+ goto _bad;
+ }
+
+ dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE;
+ dyn->pfid_iflags = aw->iflags;
+ dyn->pfid_af = af;
+
+ TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry);
+ aw->p.dyn = dyn;
+ pfi_kif_update(dyn->pfid_kif);
+ splx(s);
+ return (0);
+
+_bad:
+ if (dyn->pfid_kt != NULL)
+ pfr_detach_table(dyn->pfid_kt);
+ if (ruleset != NULL)
+ pf_remove_if_empty_ruleset(ruleset);
+ if (dyn->pfid_kif != NULL)
+ pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE);
+ pool_put(&pfi_addr_pl, dyn);
+ splx(s);
+ return (rv);
+}
+
+void
+pfi_kif_update(struct pfi_kif *kif)
+{
+ struct ifg_list *ifgl;
+ struct pfi_dynaddr *p;
+
+ /* update all dynaddr */
+ TAILQ_FOREACH(p, &kif->pfik_dynaddrs, entry)
+ pfi_dynaddr_update(p);
+
+ /* again for all groups kif is member of */
+ if (kif->pfik_ifp != NULL)
+ TAILQ_FOREACH(ifgl, &kif->pfik_ifp->if_groups, ifgl_next)
+ pfi_kif_update((struct pfi_kif *)
+ ifgl->ifgl_group->ifg_pf_kif);
+}
+
+void
+pfi_dynaddr_update(struct pfi_dynaddr *dyn)
+{
+ struct pfi_kif *kif;
+ struct pfr_ktable *kt;
+
+ if (dyn == NULL || dyn->pfid_kif == NULL || dyn->pfid_kt == NULL)
+ panic("pfi_dynaddr_update");
+
+ kif = dyn->pfid_kif;
+ kt = dyn->pfid_kt;
+
+ if (kt->pfrkt_larg != pfi_update) {
+ /* this table needs to be brought up-to-date */
+ pfi_table_update(kt, kif, dyn->pfid_net, dyn->pfid_iflags);
+ kt->pfrkt_larg = pfi_update;
+ }
+ pfr_dynaddr_update(kt, dyn);
+}
+
+void
+pfi_table_update(struct pfr_ktable *kt, struct pfi_kif *kif, int net, int flags)
+{
+ int e, size2 = 0;
+ struct ifg_member *ifgm;
+
+ pfi_buffer_cnt = 0;
+
+ if (kif->pfik_ifp != NULL)
+ pfi_instance_add(kif->pfik_ifp, net, flags);
+ else if (kif->pfik_group != NULL)
+ TAILQ_FOREACH(ifgm, &kif->pfik_group->ifg_members, ifgm_next)
+ pfi_instance_add(ifgm->ifgm_ifp, net, flags);
+
+ if ((e = pfr_set_addrs(&kt->pfrkt_t, pfi_buffer, pfi_buffer_cnt, &size2,
+ NULL, NULL, NULL, 0, PFR_TFLAG_ALLMASK)))
+ printf("pfi_table_update: cannot set %d new addresses "
+ "into table %s: %d\n", pfi_buffer_cnt, kt->pfrkt_name, e);
+}
+
+void
+pfi_instance_add(struct ifnet *ifp, int net, int flags)
+{
+ struct ifaddr *ia;
+ int got4 = 0, got6 = 0;
+ int net2, af;
+
+ if (ifp == NULL)
+ return;
+ TAILQ_FOREACH(ia, &ifp->if_addrlist, ifa_list) {
+ if (ia->ifa_addr == NULL)
+ continue;
+ af = ia->ifa_addr->sa_family;
+ if (af != AF_INET && af != AF_INET6)
+ continue;
+#ifdef __FreeBSD__
+ /*
+ * XXX: For point-to-point interfaces, (ifname:0) and IPv4,
+ * jump over addresses without a proper route to work
+ * around a problem with ppp not fully removing the
+ * address used during IPCP.
+ */
+ if ((ifp->if_flags & IFF_POINTOPOINT) &&
+ !(ia->ifa_flags & IFA_ROUTE) &&
+ (flags & PFI_AFLAG_NOALIAS) && (af == AF_INET))
+ continue;
+#endif
+ if ((flags & PFI_AFLAG_BROADCAST) && af == AF_INET6)
+ continue;
+ if ((flags & PFI_AFLAG_BROADCAST) &&
+ !(ifp->if_flags & IFF_BROADCAST))
+ continue;
+ if ((flags & PFI_AFLAG_PEER) &&
+ !(ifp->if_flags & IFF_POINTOPOINT))
+ continue;
+ if ((flags & PFI_AFLAG_NETWORK) && af == AF_INET6 &&
+ IN6_IS_ADDR_LINKLOCAL(
+ &((struct sockaddr_in6 *)ia->ifa_addr)->sin6_addr))
+ continue;
+ if (flags & PFI_AFLAG_NOALIAS) {
+ if (af == AF_INET && got4)
+ continue;
+ if (af == AF_INET6 && got6)
+ continue;
+ }
+ if (af == AF_INET)
+ got4 = 1;
+ else if (af == AF_INET6)
+ got6 = 1;
+ net2 = net;
+ if (net2 == 128 && (flags & PFI_AFLAG_NETWORK)) {
+ if (af == AF_INET)
+ net2 = pfi_unmask(&((struct sockaddr_in *)
+ ia->ifa_netmask)->sin_addr);
+ else if (af == AF_INET6)
+ net2 = pfi_unmask(&((struct sockaddr_in6 *)
+ ia->ifa_netmask)->sin6_addr);
+ }
+ if (af == AF_INET && net2 > 32)
+ net2 = 32;
+ if (flags & PFI_AFLAG_BROADCAST)
+ pfi_address_add(ia->ifa_broadaddr, af, net2);
+ else if (flags & PFI_AFLAG_PEER)
+ pfi_address_add(ia->ifa_dstaddr, af, net2);
+ else
+ pfi_address_add(ia->ifa_addr, af, net2);
+ }
+}
+
+void
+pfi_address_add(struct sockaddr *sa, int af, int net)
+{
+ struct pfr_addr *p;
+ int i;
+
+ if (pfi_buffer_cnt >= pfi_buffer_max) {
+ int new_max = pfi_buffer_max * 2;
+
+ if (new_max > PFI_BUFFER_MAX) {
+ printf("pfi_address_add: address buffer full (%d/%d)\n",
+ pfi_buffer_cnt, PFI_BUFFER_MAX);
+ return;
+ }
+ p = malloc(new_max * sizeof(*pfi_buffer), PFI_MTYPE,
+#ifdef __FreeBSD__
+ M_NOWAIT);
+#else
+ M_DONTWAIT);
+#endif
+ if (p == NULL) {
+ printf("pfi_address_add: no memory to grow buffer "
+ "(%d/%d)\n", pfi_buffer_cnt, PFI_BUFFER_MAX);
+ return;
+ }
+ memcpy(p, pfi_buffer, pfi_buffer_max * sizeof(*pfi_buffer));
+ /* no need to zero buffer */
+ free(pfi_buffer, PFI_MTYPE);
+ pfi_buffer = p;
+ pfi_buffer_max = new_max;
+ }
+ if (af == AF_INET && net > 32)
+ net = 128;
+ p = pfi_buffer + pfi_buffer_cnt++;
+ bzero(p, sizeof(*p));
+ p->pfra_af = af;
+ p->pfra_net = net;
+ if (af == AF_INET)
+ p->pfra_ip4addr = ((struct sockaddr_in *)sa)->sin_addr;
+ else if (af == AF_INET6) {
+ p->pfra_ip6addr = ((struct sockaddr_in6 *)sa)->sin6_addr;
+ if (IN6_IS_SCOPE_EMBED(&p->pfra_ip6addr))
+ p->pfra_ip6addr.s6_addr16[1] = 0;
+ }
+ /* mask network address bits */
+ if (net < 128)
+ ((caddr_t)p)[p->pfra_net/8] &= ~(0xFF >> (p->pfra_net%8));
+ for (i = (p->pfra_net+7)/8; i < sizeof(p->pfra_u); i++)
+ ((caddr_t)p)[i] = 0;
+}
+
+void
+pfi_dynaddr_remove(struct pf_addr_wrap *aw)
+{
+ int s;
+
+ if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
+ aw->p.dyn->pfid_kif == NULL || aw->p.dyn->pfid_kt == NULL)
+ return;
+
+ s = splsoftnet();
+ TAILQ_REMOVE(&aw->p.dyn->pfid_kif->pfik_dynaddrs, aw->p.dyn, entry);
+ pfi_kif_unref(aw->p.dyn->pfid_kif, PFI_KIF_REF_RULE);
+ aw->p.dyn->pfid_kif = NULL;
+ pfr_detach_table(aw->p.dyn->pfid_kt);
+ aw->p.dyn->pfid_kt = NULL;
+ pool_put(&pfi_addr_pl, aw->p.dyn);
+ aw->p.dyn = NULL;
+ splx(s);
+}
+
+void
+pfi_dynaddr_copyout(struct pf_addr_wrap *aw)
+{
+ if (aw->type != PF_ADDR_DYNIFTL || aw->p.dyn == NULL ||
+ aw->p.dyn->pfid_kif == NULL)
+ return;
+ aw->p.dyncnt = aw->p.dyn->pfid_acnt4 + aw->p.dyn->pfid_acnt6;
+}
+
+void
+pfi_kifaddr_update(void *v)
+{
+ int s;
+ struct pfi_kif *kif = (struct pfi_kif *)v;
+
+ s = splsoftnet();
+ pfi_update++;
+ pfi_kif_update(kif);
+ splx(s);
+}
+
+int
+pfi_if_compare(struct pfi_kif *p, struct pfi_kif *q)
+{
+ return (strncmp(p->pfik_name, q->pfik_name, IFNAMSIZ));
+}
+
+void
+pfi_fill_oldstatus(struct pf_status *pfs)
+{
+ struct pfi_kif *p;
+ struct pfi_kif_cmp key;
+ int i, j, k, s;
+
+ strlcpy(key.pfik_name, pfs->ifname, sizeof(key.pfik_name));
+ s = splsoftnet();
+ p = RB_FIND(pfi_ifhead, &pfi_ifs, (struct pfi_kif *)&key);
+ if (p == NULL) {
+ splx(s);
+ return;
+ }
+ bzero(pfs->pcounters, sizeof(pfs->pcounters));
+ bzero(pfs->bcounters, sizeof(pfs->bcounters));
+ for (i = 0; i < 2; i++)
+ for (j = 0; j < 2; j++)
+ for (k = 0; k < 2; k++) {
+ pfs->pcounters[i][j][k] =
+ p->pfik_packets[i][j][k];
+ pfs->bcounters[i][j] +=
+ p->pfik_bytes[i][j][k];
+ }
+ splx(s);
+}
+
+int
+pfi_clr_istats(const char *name)
+{
+ struct pfi_kif *p;
+ int s;
+
+ s = splsoftnet();
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p))
+ continue;
+ bzero(p->pfik_packets, sizeof(p->pfik_packets));
+ bzero(p->pfik_bytes, sizeof(p->pfik_bytes));
+ p->pfik_tzero = time_second;
+ }
+ splx(s);
+
+ return (0);
+}
+
+int
+pfi_get_ifaces(const char *name, struct pfi_kif *buf, int *size)
+{
+ struct pfi_kif *p, *nextp;
+ int s, n = 0;
+#ifdef __FreeBSD__
+ int error;
+#endif
+
+ s = splsoftnet();
+ for (p = RB_MIN(pfi_ifhead, &pfi_ifs); p; p = nextp) {
+ nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
+ if (pfi_skip_if(name, p))
+ continue;
+ if (*size > n++) {
+ if (!p->pfik_tzero)
+ p->pfik_tzero = time_second;
+ pfi_kif_ref(p, PFI_KIF_REF_RULE);
+#ifdef __FreeBSD__
+ PF_COPYOUT(p, buf++, sizeof(*buf), error);
+ if (error) {
+#else
+ if (copyout(p, buf++, sizeof(*buf))) {
+#endif
+ pfi_kif_unref(p, PFI_KIF_REF_RULE);
+ splx(s);
+ return (EFAULT);
+ }
+ nextp = RB_NEXT(pfi_ifhead, &pfi_ifs, p);
+ pfi_kif_unref(p, PFI_KIF_REF_RULE);
+ }
+ }
+ splx(s);
+ *size = n;
+ return (0);
+}
+
+int
+pfi_skip_if(const char *filter, struct pfi_kif *p)
+{
+ int n;
+
+ if (filter == NULL || !*filter)
+ return (0);
+ if (!strcmp(p->pfik_name, filter))
+ return (0); /* exact match */
+ n = strlen(filter);
+ if (n < 1 || n >= IFNAMSIZ)
+ return (1); /* sanity check */
+ if (filter[n-1] >= '0' && filter[n-1] <= '9')
+ return (1); /* only do exact match in that case */
+ if (strncmp(p->pfik_name, filter, n))
+ return (1); /* prefix doesn't match */
+ return (p->pfik_name[n] < '0' || p->pfik_name[n] > '9');
+}
+
+int
+pfi_set_flags(const char *name, int flags)
+{
+ struct pfi_kif *p;
+ int s;
+
+ s = splsoftnet();
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p))
+ continue;
+ p->pfik_flags |= flags;
+ }
+ splx(s);
+ return (0);
+}
+
+int
+pfi_clear_flags(const char *name, int flags)
+{
+ struct pfi_kif *p;
+ int s;
+
+ s = splsoftnet();
+ RB_FOREACH(p, pfi_ifhead, &pfi_ifs) {
+ if (pfi_skip_if(name, p))
+ continue;
+ p->pfik_flags &= ~flags;
+ }
+ splx(s);
+ return (0);
+}
+
+/* from pf_print_state.c */
+int
+pfi_unmask(void *addr)
+{
+ struct pf_addr *m = addr;
+ int i = 31, j = 0, b = 0;
+ u_int32_t tmp;
+
+ while (j < 4 && m->addr32[j] == 0xffffffff) {
+ b += 32;
+ j++;
+ }
+ if (j < 4) {
+ tmp = ntohl(m->addr32[j]);
+ for (i = 31; tmp & (1 << i); --i)
+ b++;
+ }
+ return (b);
+}
+
+#ifdef __FreeBSD__
+void
+pfi_attach_ifnet_event(void *arg __unused, struct ifnet *ifp)
+{
+ PF_LOCK();
+ pfi_attach_ifnet(ifp);
+#ifdef ALTQ
+ pf_altq_ifnet_event(ifp, 0);
+#endif
+ PF_UNLOCK();
+}
+
+void
+pfi_detach_ifnet_event(void *arg __unused, struct ifnet *ifp)
+{
+ PF_LOCK();
+ pfi_detach_ifnet(ifp);
+#ifdef ALTQ
+ pf_altq_ifnet_event(ifp, 1);
+#endif
+ PF_UNLOCK();
+}
+
+void
+pfi_attach_group_event(void *arg __unused, struct ifg_group *ifg)
+{
+ PF_LOCK();
+ pfi_attach_ifgroup(ifg);
+ PF_UNLOCK();
+}
+
+void
+pfi_change_group_event(void *arg __unused, char *gname)
+{
+ PF_LOCK();
+ pfi_group_change(gname);
+ PF_UNLOCK();
+}
+
+void
+pfi_detach_group_event(void *arg __unused, struct ifg_group *ifg)
+{
+ PF_LOCK();
+ pfi_detach_ifgroup(ifg);
+ PF_UNLOCK();
+}
+
+void
+pfi_ifaddr_event(void *arg __unused, struct ifnet *ifp)
+{
+ PF_LOCK();
+ if (ifp && ifp->if_pf_kif)
+ pfi_kifaddr_update(ifp->if_pf_kif);
+ PF_UNLOCK();
+}
+#endif /* __FreeBSD__ */
diff --git a/freebsd/sys/contrib/pf/net/pf_ioctl.c b/freebsd/sys/contrib/pf/net/pf_ioctl.c
new file mode 100644
index 00000000..de612b4f
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_ioctl.c
@@ -0,0 +1,3896 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: pf_ioctl.c,v 1.175 2007/02/26 22:47:43 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2001 Daniel Hartmeier
+ * Copyright (c) 2002,2003 Henning Brauer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+#include <freebsd/local/opt_bpf.h>
+#include <freebsd/local/opt_pf.h>
+
+#ifdef DEV_BPF
+#define NBPFILTER DEV_BPF
+#else
+#define NBPFILTER 0
+#endif
+
+#ifdef DEV_PFLOG
+#define NPFLOG DEV_PFLOG
+#else
+#define NPFLOG 0
+#endif
+
+#ifdef DEV_PFSYNC
+#define NPFSYNC DEV_PFSYNC
+#else
+#define NPFSYNC 0
+#endif
+
+#else
+#include <freebsd/local/bpfilter.h>
+#include <freebsd/local/pflog.h>
+#include <freebsd/local/pfsync.h>
+#endif
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/filio.h>
+#include <freebsd/sys/fcntl.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/socketvar.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/time.h>
+#include <freebsd/sys/malloc.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/module.h>
+#include <freebsd/sys/conf.h>
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/sysctl.h>
+#else
+#include <freebsd/sys/timeout.h>
+#include <freebsd/sys/pool.h>
+#endif
+#include <freebsd/sys/proc.h>
+#include <freebsd/sys/malloc.h>
+#include <freebsd/sys/kthread.h>
+#ifndef __FreeBSD__
+#include <freebsd/sys/rwlock.h>
+#include <freebsd/uvm/uvm_extern.h>
+#endif
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/if_types.h>
+#ifdef __FreeBSD__
+#include <freebsd/net/vnet.h>
+#endif
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_var.h>
+#include <freebsd/netinet/ip_icmp.h>
+
+#ifdef __FreeBSD__
+#include <freebsd/sys/md5.h>
+#else
+#include <freebsd/dev/rndvar.h>
+#include <freebsd/crypto/md5.h>
+#endif
+#include <freebsd/net/pfvar.h>
+
+#if NPFSYNC > 0
+#include <freebsd/net/if_pfsync.h>
+#endif /* NPFSYNC > 0 */
+
+#include <freebsd/net/if_pflog.h>
+
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#include <freebsd/netinet/in_pcb.h>
+#endif /* INET6 */
+
+#ifdef ALTQ
+#include <freebsd/altq/altq.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <freebsd/sys/limits.h>
+#include <freebsd/sys/lock.h>
+#include <freebsd/sys/mutex.h>
+#include <freebsd/net/pfil.h>
+#endif /* __FreeBSD__ */
+
+#ifdef __FreeBSD__
+void init_zone_var(void);
+void cleanup_pf_zone(void);
+int pfattach(void);
+#else
+void pfattach(int);
+void pf_thread_create(void *);
+int pfopen(dev_t, int, int, struct proc *);
+int pfclose(dev_t, int, int, struct proc *);
+#endif
+struct pf_pool *pf_get_pool(char *, u_int32_t, u_int8_t, u_int32_t,
+ u_int8_t, u_int8_t, u_int8_t);
+
+void pf_mv_pool(struct pf_palist *, struct pf_palist *);
+void pf_empty_pool(struct pf_palist *);
+#ifdef __FreeBSD__
+int pfioctl(struct cdev *, u_long, caddr_t, int, struct thread *);
+#else
+int pfioctl(struct cdev *, u_long, caddr_t, int, struct proc *);
+#endif
+#ifdef ALTQ
+int pf_begin_altq(u_int32_t *);
+int pf_rollback_altq(u_int32_t);
+int pf_commit_altq(u_int32_t);
+int pf_enable_altq(struct pf_altq *);
+int pf_disable_altq(struct pf_altq *);
+#endif /* ALTQ */
+int pf_begin_rules(u_int32_t *, int, const char *);
+int pf_rollback_rules(u_int32_t, int, char *);
+int pf_setup_pfsync_matching(struct pf_ruleset *);
+void pf_hash_rule(MD5_CTX *, struct pf_rule *);
+void pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
+int pf_commit_rules(u_int32_t, int, char *);
+
+struct pf_rule pf_default_rule;
+#ifdef __FreeBSD__
+struct sx pf_consistency_lock;
+SX_SYSINIT(pf_consistency_lock, &pf_consistency_lock, "pf_statetbl_lock");
+#else
+struct rwlock pf_consistency_lock = RWLOCK_INITIALIZER;
+#endif
+#ifdef ALTQ
+static int pf_altq_running;
+#endif
+
+#define TAGID_MAX 50000
+TAILQ_HEAD(pf_tags, pf_tagname) pf_tags = TAILQ_HEAD_INITIALIZER(pf_tags),
+ pf_qids = TAILQ_HEAD_INITIALIZER(pf_qids);
+
+#if (PF_QNAME_SIZE != PF_TAG_NAME_SIZE)
+#error PF_QNAME_SIZE must be equal to PF_TAG_NAME_SIZE
+#endif
+u_int16_t tagname2tag(struct pf_tags *, char *);
+void tag2tagname(struct pf_tags *, u_int16_t, char *);
+void tag_unref(struct pf_tags *, u_int16_t);
+int pf_rtlabel_add(struct pf_addr_wrap *);
+void pf_rtlabel_remove(struct pf_addr_wrap *);
+void pf_rtlabel_copyout(struct pf_addr_wrap *);
+
+#define DPFPRINTF(n, x) if (pf_status.debug >= (n)) printf x
+
+
+#ifdef __FreeBSD__
+static struct cdev *pf_dev;
+
+/*
+ * XXX - These are new and need to be checked when moveing to a new version
+ */
+static void pf_clear_states(void);
+static int pf_clear_tables(void);
+static void pf_clear_srcnodes(void);
+/*
+ * XXX - These are new and need to be checked when moveing to a new version
+ */
+
+/*
+ * Wrapper functions for pfil(9) hooks
+ */
+static int pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir, struct inpcb *inp);
+static int pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir, struct inpcb *inp);
+#ifdef INET6
+static int pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir, struct inpcb *inp);
+static int pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp,
+ int dir, struct inpcb *inp);
+#endif
+
+static int hook_pf(void);
+static int dehook_pf(void);
+static int shutdown_pf(void);
+static int pf_load(void);
+static int pf_unload(void);
+
+static struct cdevsw pf_cdevsw = {
+ .d_ioctl = pfioctl,
+ .d_name = PF_NAME,
+ .d_version = D_VERSION,
+};
+
+static volatile int pf_pfil_hooked = 0;
+int pf_end_threads = 0;
+struct mtx pf_task_mtx;
+pflog_packet_t *pflog_packet_ptr = NULL;
+
+int debug_pfugidhack = 0;
+SYSCTL_INT(_debug, OID_AUTO, pfugidhack, CTLFLAG_RW, &debug_pfugidhack, 0,
+ "Enable/disable pf user/group rules mpsafe hack");
+
+void
+init_pf_mutex(void)
+{
+ mtx_init(&pf_task_mtx, "pf task mtx", NULL, MTX_DEF);
+}
+
+void
+destroy_pf_mutex(void)
+{
+ mtx_destroy(&pf_task_mtx);
+}
+
+void
+init_zone_var(void)
+{
+ pf_src_tree_pl = pf_rule_pl = NULL;
+ pf_state_pl = pf_altq_pl = pf_pooladdr_pl = NULL;
+ pf_frent_pl = pf_frag_pl = pf_cache_pl = pf_cent_pl = NULL;
+ pf_state_scrub_pl = NULL;
+ pfr_ktable_pl = pfr_kentry_pl = NULL;
+}
+
+void
+cleanup_pf_zone(void)
+{
+ UMA_DESTROY(pf_src_tree_pl);
+ UMA_DESTROY(pf_rule_pl);
+ UMA_DESTROY(pf_state_pl);
+ UMA_DESTROY(pf_altq_pl);
+ UMA_DESTROY(pf_pooladdr_pl);
+ UMA_DESTROY(pf_frent_pl);
+ UMA_DESTROY(pf_frag_pl);
+ UMA_DESTROY(pf_cache_pl);
+ UMA_DESTROY(pf_cent_pl);
+ UMA_DESTROY(pfr_ktable_pl);
+ UMA_DESTROY(pfr_kentry_pl2);
+ UMA_DESTROY(pfr_kentry_pl);
+ UMA_DESTROY(pf_state_scrub_pl);
+ UMA_DESTROY(pfi_addr_pl);
+}
+
+int
+pfattach(void)
+{
+ u_int32_t *my_timeout = pf_default_rule.timeout;
+ int error = 1;
+
+ do {
+ UMA_CREATE(pf_src_tree_pl,struct pf_src_node, "pfsrctrpl");
+ UMA_CREATE(pf_rule_pl, struct pf_rule, "pfrulepl");
+ UMA_CREATE(pf_state_pl, struct pf_state, "pfstatepl");
+ UMA_CREATE(pf_altq_pl, struct pf_altq, "pfaltqpl");
+ UMA_CREATE(pf_pooladdr_pl, struct pf_pooladdr, "pfpooladdrpl");
+ UMA_CREATE(pfr_ktable_pl, struct pfr_ktable, "pfrktable");
+ UMA_CREATE(pfr_kentry_pl, struct pfr_kentry, "pfrkentry");
+ UMA_CREATE(pfr_kentry_pl2, struct pfr_kentry, "pfrkentry2");
+ UMA_CREATE(pf_frent_pl, struct pf_frent, "pffrent");
+ UMA_CREATE(pf_frag_pl, struct pf_fragment, "pffrag");
+ UMA_CREATE(pf_cache_pl, struct pf_fragment, "pffrcache");
+ UMA_CREATE(pf_cent_pl, struct pf_frcache, "pffrcent");
+ UMA_CREATE(pf_state_scrub_pl, struct pf_state_scrub,
+ "pfstatescrub");
+ UMA_CREATE(pfi_addr_pl, struct pfi_dynaddr, "pfiaddrpl");
+ error = 0;
+ } while(0);
+ if (error) {
+ cleanup_pf_zone();
+ return (error);
+ }
+ pfr_initialize();
+ pfi_initialize();
+ if ( (error = pf_osfp_initialize()) ) {
+ cleanup_pf_zone();
+ pf_osfp_cleanup();
+ return (error);
+ }
+
+ pf_pool_limits[PF_LIMIT_STATES].pp = pf_state_pl;
+ pf_pool_limits[PF_LIMIT_STATES].limit = PFSTATE_HIWAT;
+ pf_pool_limits[PF_LIMIT_SRC_NODES].pp = pf_src_tree_pl;
+ pf_pool_limits[PF_LIMIT_SRC_NODES].limit = PFSNODE_HIWAT;
+ pf_pool_limits[PF_LIMIT_FRAGS].pp = pf_frent_pl;
+ pf_pool_limits[PF_LIMIT_FRAGS].limit = PFFRAG_FRENT_HIWAT;
+ pf_pool_limits[PF_LIMIT_TABLES].pp = pfr_ktable_pl;
+ pf_pool_limits[PF_LIMIT_TABLES].limit = PFR_KTABLE_HIWAT;
+ pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].pp = pfr_kentry_pl;
+ pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit = PFR_KENTRY_HIWAT;
+ uma_zone_set_max(pf_pool_limits[PF_LIMIT_STATES].pp,
+ pf_pool_limits[PF_LIMIT_STATES].limit);
+
+ RB_INIT(&tree_src_tracking);
+ RB_INIT(&pf_anchors);
+ pf_init_ruleset(&pf_main_ruleset);
+ TAILQ_INIT(&pf_altqs[0]);
+ TAILQ_INIT(&pf_altqs[1]);
+ TAILQ_INIT(&pf_pabuf);
+ pf_altqs_active = &pf_altqs[0];
+ pf_altqs_inactive = &pf_altqs[1];
+ TAILQ_INIT(&state_list);
+
+ /* default rule should never be garbage collected */
+ pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
+ pf_default_rule.action = PF_PASS;
+ pf_default_rule.nr = -1;
+ pf_default_rule.rtableid = -1;
+
+ /* initialize default timeouts */
+ my_timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
+ my_timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
+ my_timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
+ my_timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
+ my_timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
+ my_timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
+ my_timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
+ my_timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
+ my_timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
+ my_timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
+ my_timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
+ my_timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
+ my_timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
+ my_timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
+ my_timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
+ my_timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
+ my_timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
+ my_timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
+ my_timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
+ my_timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
+
+ pf_normalize_init();
+ bzero(&pf_status, sizeof(pf_status));
+ pf_status.debug = PF_DEBUG_URGENT;
+
+ pf_pfil_hooked = 0;
+
+ /* XXX do our best to avoid a conflict */
+ pf_status.hostid = arc4random();
+
+ if (kproc_create(pf_purge_thread, NULL, NULL, 0, 0, "pfpurge"))
+ return (ENXIO);
+
+ return (error);
+}
+#else /* !__FreeBSD__ */
+void
+pfattach(int num)
+{
+ u_int32_t *timeout = pf_default_rule.timeout;
+
+ pool_init(&pf_rule_pl, sizeof(struct pf_rule), 0, 0, 0, "pfrulepl",
+ &pool_allocator_nointr);
+ pool_init(&pf_src_tree_pl, sizeof(struct pf_src_node), 0, 0, 0,
+ "pfsrctrpl", NULL);
+ pool_init(&pf_state_pl, sizeof(struct pf_state), 0, 0, 0, "pfstatepl",
+ NULL);
+ pool_init(&pf_altq_pl, sizeof(struct pf_altq), 0, 0, 0, "pfaltqpl",
+ &pool_allocator_nointr);
+ pool_init(&pf_pooladdr_pl, sizeof(struct pf_pooladdr), 0, 0, 0,
+ "pfpooladdrpl", &pool_allocator_nointr);
+ pfr_initialize();
+ pfi_initialize();
+ pf_osfp_initialize();
+
+ pool_sethardlimit(pf_pool_limits[PF_LIMIT_STATES].pp,
+ pf_pool_limits[PF_LIMIT_STATES].limit, NULL, 0);
+
+ if (ctob(physmem) <= 100*1024*1024)
+ pf_pool_limits[PF_LIMIT_TABLE_ENTRIES].limit =
+ PFR_KENTRY_HIWAT_SMALL;
+
+ RB_INIT(&tree_src_tracking);
+ RB_INIT(&pf_anchors);
+ pf_init_ruleset(&pf_main_ruleset);
+ TAILQ_INIT(&pf_altqs[0]);
+ TAILQ_INIT(&pf_altqs[1]);
+ TAILQ_INIT(&pf_pabuf);
+ pf_altqs_active = &pf_altqs[0];
+ pf_altqs_inactive = &pf_altqs[1];
+ TAILQ_INIT(&state_list);
+
+ /* default rule should never be garbage collected */
+ pf_default_rule.entries.tqe_prev = &pf_default_rule.entries.tqe_next;
+ pf_default_rule.action = PF_PASS;
+ pf_default_rule.nr = -1;
+ pf_default_rule.rtableid = -1;
+
+ /* initialize default timeouts */
+ timeout[PFTM_TCP_FIRST_PACKET] = PFTM_TCP_FIRST_PACKET_VAL;
+ timeout[PFTM_TCP_OPENING] = PFTM_TCP_OPENING_VAL;
+ timeout[PFTM_TCP_ESTABLISHED] = PFTM_TCP_ESTABLISHED_VAL;
+ timeout[PFTM_TCP_CLOSING] = PFTM_TCP_CLOSING_VAL;
+ timeout[PFTM_TCP_FIN_WAIT] = PFTM_TCP_FIN_WAIT_VAL;
+ timeout[PFTM_TCP_CLOSED] = PFTM_TCP_CLOSED_VAL;
+ timeout[PFTM_UDP_FIRST_PACKET] = PFTM_UDP_FIRST_PACKET_VAL;
+ timeout[PFTM_UDP_SINGLE] = PFTM_UDP_SINGLE_VAL;
+ timeout[PFTM_UDP_MULTIPLE] = PFTM_UDP_MULTIPLE_VAL;
+ timeout[PFTM_ICMP_FIRST_PACKET] = PFTM_ICMP_FIRST_PACKET_VAL;
+ timeout[PFTM_ICMP_ERROR_REPLY] = PFTM_ICMP_ERROR_REPLY_VAL;
+ timeout[PFTM_OTHER_FIRST_PACKET] = PFTM_OTHER_FIRST_PACKET_VAL;
+ timeout[PFTM_OTHER_SINGLE] = PFTM_OTHER_SINGLE_VAL;
+ timeout[PFTM_OTHER_MULTIPLE] = PFTM_OTHER_MULTIPLE_VAL;
+ timeout[PFTM_FRAG] = PFTM_FRAG_VAL;
+ timeout[PFTM_INTERVAL] = PFTM_INTERVAL_VAL;
+ timeout[PFTM_SRC_NODE] = PFTM_SRC_NODE_VAL;
+ timeout[PFTM_TS_DIFF] = PFTM_TS_DIFF_VAL;
+ timeout[PFTM_ADAPTIVE_START] = PFSTATE_ADAPT_START;
+ timeout[PFTM_ADAPTIVE_END] = PFSTATE_ADAPT_END;
+
+ pf_normalize_init();
+ bzero(&pf_status, sizeof(pf_status));
+ pf_status.debug = PF_DEBUG_URGENT;
+
+ /* XXX do our best to avoid a conflict */
+ pf_status.hostid = arc4random();
+
+ /* require process context to purge states, so perform in a thread */
+ kproc_create_deferred(pf_thread_create, NULL);
+}
+
+void
+pf_thread_create(void *v)
+{
+ if (kproc_create(pf_purge_thread, NULL, NULL, "pfpurge"))
+ panic("pfpurge thread");
+}
+
+int
+pfopen(struct cdev *dev, int flags, int fmt, struct proc *p)
+{
+ if (dev2unit(dev) >= 1)
+ return (ENXIO);
+ return (0);
+}
+
+int
+pfclose(struct cdev *dev, int flags, int fmt, struct proc *p)
+{
+ if (dev2unit(dev) >= 1)
+ return (ENXIO);
+ return (0);
+}
+#endif /* __FreeBSD__ */
+
+struct pf_pool *
+pf_get_pool(char *anchor, u_int32_t ticket, u_int8_t rule_action,
+ u_int32_t rule_number, u_int8_t r_last, u_int8_t active,
+ u_int8_t check_ticket)
+{
+ struct pf_ruleset *ruleset;
+ struct pf_rule *rule;
+ int rs_num;
+
+ ruleset = pf_find_ruleset(anchor);
+ if (ruleset == NULL)
+ return (NULL);
+ rs_num = pf_get_ruleset_number(rule_action);
+ if (rs_num >= PF_RULESET_MAX)
+ return (NULL);
+ if (active) {
+ if (check_ticket && ticket !=
+ ruleset->rules[rs_num].active.ticket)
+ return (NULL);
+ if (r_last)
+ rule = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
+ pf_rulequeue);
+ else
+ rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
+ } else {
+ if (check_ticket && ticket !=
+ ruleset->rules[rs_num].inactive.ticket)
+ return (NULL);
+ if (r_last)
+ rule = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
+ pf_rulequeue);
+ else
+ rule = TAILQ_FIRST(ruleset->rules[rs_num].inactive.ptr);
+ }
+ if (!r_last) {
+ while ((rule != NULL) && (rule->nr != rule_number))
+ rule = TAILQ_NEXT(rule, entries);
+ }
+ if (rule == NULL)
+ return (NULL);
+
+ return (&rule->rpool);
+}
+
+void
+pf_mv_pool(struct pf_palist *poola, struct pf_palist *poolb)
+{
+ struct pf_pooladdr *mv_pool_pa;
+
+ while ((mv_pool_pa = TAILQ_FIRST(poola)) != NULL) {
+ TAILQ_REMOVE(poola, mv_pool_pa, entries);
+ TAILQ_INSERT_TAIL(poolb, mv_pool_pa, entries);
+ }
+}
+
+void
+pf_empty_pool(struct pf_palist *poola)
+{
+ struct pf_pooladdr *empty_pool_pa;
+
+ while ((empty_pool_pa = TAILQ_FIRST(poola)) != NULL) {
+ pfi_dynaddr_remove(&empty_pool_pa->addr);
+ pf_tbladdr_remove(&empty_pool_pa->addr);
+ pfi_kif_unref(empty_pool_pa->kif, PFI_KIF_REF_RULE);
+ TAILQ_REMOVE(poola, empty_pool_pa, entries);
+ pool_put(&pf_pooladdr_pl, empty_pool_pa);
+ }
+}
+
+void
+pf_rm_rule(struct pf_rulequeue *rulequeue, struct pf_rule *rule)
+{
+ if (rulequeue != NULL) {
+ if (rule->states <= 0) {
+ /*
+ * XXX - we need to remove the table *before* detaching
+ * the rule to make sure the table code does not delete
+ * the anchor under our feet.
+ */
+ pf_tbladdr_remove(&rule->src.addr);
+ pf_tbladdr_remove(&rule->dst.addr);
+ if (rule->overload_tbl)
+ pfr_detach_table(rule->overload_tbl);
+ }
+ TAILQ_REMOVE(rulequeue, rule, entries);
+ rule->entries.tqe_prev = NULL;
+ rule->nr = -1;
+ }
+
+ if (rule->states > 0 || rule->src_nodes > 0 ||
+ rule->entries.tqe_prev != NULL)
+ return;
+ pf_tag_unref(rule->tag);
+ pf_tag_unref(rule->match_tag);
+#ifdef ALTQ
+ if (rule->pqid != rule->qid)
+ pf_qid_unref(rule->pqid);
+ pf_qid_unref(rule->qid);
+#endif
+ pf_rtlabel_remove(&rule->src.addr);
+ pf_rtlabel_remove(&rule->dst.addr);
+ pfi_dynaddr_remove(&rule->src.addr);
+ pfi_dynaddr_remove(&rule->dst.addr);
+ if (rulequeue == NULL) {
+ pf_tbladdr_remove(&rule->src.addr);
+ pf_tbladdr_remove(&rule->dst.addr);
+ if (rule->overload_tbl)
+ pfr_detach_table(rule->overload_tbl);
+ }
+ pfi_kif_unref(rule->kif, PFI_KIF_REF_RULE);
+ pf_anchor_remove(rule);
+ pf_empty_pool(&rule->rpool.list);
+ pool_put(&pf_rule_pl, rule);
+}
+
+u_int16_t
+tagname2tag(struct pf_tags *head, char *tagname)
+{
+ struct pf_tagname *tag, *p = NULL;
+ u_int16_t new_tagid = 1;
+
+ TAILQ_FOREACH(tag, head, entries)
+ if (strcmp(tagname, tag->name) == 0) {
+ tag->ref++;
+ return (tag->tag);
+ }
+
+ /*
+ * to avoid fragmentation, we do a linear search from the beginning
+ * and take the first free slot we find. if there is none or the list
+ * is empty, append a new entry at the end.
+ */
+
+ /* new entry */
+ if (!TAILQ_EMPTY(head))
+ for (p = TAILQ_FIRST(head); p != NULL &&
+ p->tag == new_tagid; p = TAILQ_NEXT(p, entries))
+ new_tagid = p->tag + 1;
+
+ if (new_tagid > TAGID_MAX)
+ return (0);
+
+ /* allocate and fill new struct pf_tagname */
+ tag = (struct pf_tagname *)malloc(sizeof(struct pf_tagname),
+ M_TEMP, M_NOWAIT);
+ if (tag == NULL)
+ return (0);
+ bzero(tag, sizeof(struct pf_tagname));
+ strlcpy(tag->name, tagname, sizeof(tag->name));
+ tag->tag = new_tagid;
+ tag->ref++;
+
+ if (p != NULL) /* insert new entry before p */
+ TAILQ_INSERT_BEFORE(p, tag, entries);
+ else /* either list empty or no free slot in between */
+ TAILQ_INSERT_TAIL(head, tag, entries);
+
+ return (tag->tag);
+}
+
+void
+tag2tagname(struct pf_tags *head, u_int16_t tagid, char *p)
+{
+ struct pf_tagname *tag;
+
+ TAILQ_FOREACH(tag, head, entries)
+ if (tag->tag == tagid) {
+ strlcpy(p, tag->name, PF_TAG_NAME_SIZE);
+ return;
+ }
+}
+
+void
+tag_unref(struct pf_tags *head, u_int16_t tag)
+{
+ struct pf_tagname *p, *next;
+
+ if (tag == 0)
+ return;
+
+ for (p = TAILQ_FIRST(head); p != NULL; p = next) {
+ next = TAILQ_NEXT(p, entries);
+ if (tag == p->tag) {
+ if (--p->ref == 0) {
+ TAILQ_REMOVE(head, p, entries);
+ free(p, M_TEMP);
+ }
+ break;
+ }
+ }
+}
+
+u_int16_t
+pf_tagname2tag(char *tagname)
+{
+ return (tagname2tag(&pf_tags, tagname));
+}
+
+void
+pf_tag2tagname(u_int16_t tagid, char *p)
+{
+ tag2tagname(&pf_tags, tagid, p);
+}
+
+void
+pf_tag_ref(u_int16_t tag)
+{
+ struct pf_tagname *t;
+
+ TAILQ_FOREACH(t, &pf_tags, entries)
+ if (t->tag == tag)
+ break;
+ if (t != NULL)
+ t->ref++;
+}
+
+void
+pf_tag_unref(u_int16_t tag)
+{
+ tag_unref(&pf_tags, tag);
+}
+
+int
+pf_rtlabel_add(struct pf_addr_wrap *a)
+{
+#ifdef __FreeBSD__
+ /* XXX_IMPORT: later */
+ return (0);
+#else
+ if (a->type == PF_ADDR_RTLABEL &&
+ (a->v.rtlabel = rtlabel_name2id(a->v.rtlabelname)) == 0)
+ return (-1);
+ return (0);
+#endif
+}
+
+void
+pf_rtlabel_remove(struct pf_addr_wrap *a)
+{
+#ifdef __FreeBSD__
+ /* XXX_IMPORT: later */
+#else
+ if (a->type == PF_ADDR_RTLABEL)
+ rtlabel_unref(a->v.rtlabel);
+#endif
+}
+
+void
+pf_rtlabel_copyout(struct pf_addr_wrap *a)
+{
+#ifdef __FreeBSD__
+ /* XXX_IMPORT: later */
+ if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel)
+ strlcpy(a->v.rtlabelname, "?", sizeof(a->v.rtlabelname));
+#else
+ const char *name;
+
+ if (a->type == PF_ADDR_RTLABEL && a->v.rtlabel) {
+ if ((name = rtlabel_id2name(a->v.rtlabel)) == NULL)
+ strlcpy(a->v.rtlabelname, "?",
+ sizeof(a->v.rtlabelname));
+ else
+ strlcpy(a->v.rtlabelname, name,
+ sizeof(a->v.rtlabelname));
+ }
+#endif
+}
+
+#ifdef ALTQ
+u_int32_t
+pf_qname2qid(char *qname)
+{
+ return ((u_int32_t)tagname2tag(&pf_qids, qname));
+}
+
+void
+pf_qid2qname(u_int32_t qid, char *p)
+{
+ tag2tagname(&pf_qids, (u_int16_t)qid, p);
+}
+
+void
+pf_qid_unref(u_int32_t qid)
+{
+ tag_unref(&pf_qids, (u_int16_t)qid);
+}
+
+int
+pf_begin_altq(u_int32_t *ticket)
+{
+ struct pf_altq *altq;
+ int error = 0;
+
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
+ if (altq->qname[0] == 0) {
+#endif
+ /* detach and destroy the discipline */
+ error = altq_remove(altq);
+ } else
+ pf_qid_unref(altq->qid);
+ pool_put(&pf_altq_pl, altq);
+ }
+ if (error)
+ return (error);
+ *ticket = ++ticket_altqs_inactive;
+ altqs_inactive_open = 1;
+ return (0);
+}
+
+int
+pf_rollback_altq(u_int32_t ticket)
+{
+ struct pf_altq *altq;
+ int error = 0;
+
+ if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
+ return (0);
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
+ if (altq->qname[0] == 0) {
+#endif
+ /* detach and destroy the discipline */
+ error = altq_remove(altq);
+ } else
+ pf_qid_unref(altq->qid);
+ pool_put(&pf_altq_pl, altq);
+ }
+ altqs_inactive_open = 0;
+ return (error);
+}
+
+int
+pf_commit_altq(u_int32_t ticket)
+{
+ struct pf_altqqueue *old_altqs;
+ struct pf_altq *altq;
+ int s, err, error = 0;
+
+ if (!altqs_inactive_open || ticket != ticket_altqs_inactive)
+ return (EBUSY);
+
+ /* swap altqs, keep the old. */
+ s = splsoftnet();
+ old_altqs = pf_altqs_active;
+ pf_altqs_active = pf_altqs_inactive;
+ pf_altqs_inactive = old_altqs;
+ ticket_altqs_active = ticket_altqs_inactive;
+
+ /* Attach new disciplines */
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
+ if (altq->qname[0] == 0) {
+#endif
+ /* attach the discipline */
+ error = altq_pfattach(altq);
+ if (error == 0 && pf_altq_running)
+ error = pf_enable_altq(altq);
+ if (error != 0) {
+ splx(s);
+ return (error);
+ }
+ }
+ }
+
+ /* Purge the old altq list */
+ while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
+ TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
+ if (altq->qname[0] == 0) {
+#endif
+ /* detach and destroy the discipline */
+ if (pf_altq_running)
+ error = pf_disable_altq(altq);
+ err = altq_pfdetach(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ err = altq_remove(altq);
+ if (err != 0 && error == 0)
+ error = err;
+ } else
+ pf_qid_unref(altq->qid);
+ pool_put(&pf_altq_pl, altq);
+ }
+ splx(s);
+
+ altqs_inactive_open = 0;
+ return (error);
+}
+
+int
+pf_enable_altq(struct pf_altq *altq)
+{
+ struct ifnet *ifp;
+ struct tb_profile tb;
+ int s, error = 0;
+
+ if ((ifp = ifunit(altq->ifname)) == NULL)
+ return (EINVAL);
+
+ if (ifp->if_snd.altq_type != ALTQT_NONE)
+ error = altq_enable(&ifp->if_snd);
+
+ /* set tokenbucket regulator */
+ if (error == 0 && ifp != NULL && ALTQ_IS_ENABLED(&ifp->if_snd)) {
+ tb.rate = altq->ifbandwidth;
+ tb.depth = altq->tbrsize;
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ error = tbr_set(&ifp->if_snd, &tb);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ splx(s);
+ }
+
+ return (error);
+}
+
+int
+pf_disable_altq(struct pf_altq *altq)
+{
+ struct ifnet *ifp;
+ struct tb_profile tb;
+ int s, error;
+
+ if ((ifp = ifunit(altq->ifname)) == NULL)
+ return (EINVAL);
+
+ /*
+ * when the discipline is no longer referenced, it was overridden
+ * by a new one. if so, just return.
+ */
+ if (altq->altq_disc != ifp->if_snd.altq_disc)
+ return (0);
+
+ error = altq_disable(&ifp->if_snd);
+
+ if (error == 0) {
+ /* clear tokenbucket regulator */
+ tb.rate = 0;
+ s = splnet();
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ error = tbr_set(&ifp->if_snd, &tb);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ splx(s);
+ }
+
+ return (error);
+}
+
+#ifdef __FreeBSD__
+void
+pf_altq_ifnet_event(struct ifnet *ifp, int remove)
+{
+ struct ifnet *ifp1;
+ struct pf_altq *a1, *a2, *a3;
+ u_int32_t ticket;
+ int error = 0;
+
+ /* Interrupt userland queue modifications */
+ if (altqs_inactive_open)
+ pf_rollback_altq(ticket_altqs_inactive);
+
+ /* Start new altq ruleset */
+ if (pf_begin_altq(&ticket))
+ return;
+
+ /* Copy the current active set */
+ TAILQ_FOREACH(a1, pf_altqs_active, entries) {
+ a2 = pool_get(&pf_altq_pl, PR_NOWAIT);
+ if (a2 == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(a1, a2, sizeof(struct pf_altq));
+
+ if (a2->qname[0] != 0) {
+ if ((a2->qid = pf_qname2qid(a2->qname)) == 0) {
+ error = EBUSY;
+ pool_put(&pf_altq_pl, a2);
+ break;
+ }
+ a2->altq_disc = NULL;
+ TAILQ_FOREACH(a3, pf_altqs_inactive, entries) {
+ if (strncmp(a3->ifname, a2->ifname,
+ IFNAMSIZ) == 0 && a3->qname[0] == 0) {
+ a2->altq_disc = a3->altq_disc;
+ break;
+ }
+ }
+ }
+ /* Deactivate the interface in question */
+ a2->local_flags &= ~PFALTQ_FLAG_IF_REMOVED;
+ if ((ifp1 = ifunit(a2->ifname)) == NULL ||
+ (remove && ifp1 == ifp)) {
+ a2->local_flags |= PFALTQ_FLAG_IF_REMOVED;
+ } else {
+ PF_UNLOCK();
+ error = altq_add(a2);
+ PF_LOCK();
+
+ if (ticket != ticket_altqs_inactive)
+ error = EBUSY;
+
+ if (error) {
+ pool_put(&pf_altq_pl, a2);
+ break;
+ }
+ }
+
+ TAILQ_INSERT_TAIL(pf_altqs_inactive, a2, entries);
+ }
+
+ if (error != 0)
+ pf_rollback_altq(ticket);
+ else
+ pf_commit_altq(ticket);
+}
+#endif
+#endif /* ALTQ */
+
+int
+pf_begin_rules(u_int32_t *ticket, int rs_num, const char *anchor)
+{
+ struct pf_ruleset *rs;
+ struct pf_rule *rule;
+
+ if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
+ return (EINVAL);
+ rs = pf_find_or_create_ruleset(anchor);
+ if (rs == NULL)
+ return (EINVAL);
+ while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
+ pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
+ rs->rules[rs_num].inactive.rcount--;
+ }
+ *ticket = ++rs->rules[rs_num].inactive.ticket;
+ rs->rules[rs_num].inactive.open = 1;
+ return (0);
+}
+
+int
+pf_rollback_rules(u_int32_t ticket, int rs_num, char *anchor)
+{
+ struct pf_ruleset *rs;
+ struct pf_rule *rule;
+
+ if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
+ return (EINVAL);
+ rs = pf_find_ruleset(anchor);
+ if (rs == NULL || !rs->rules[rs_num].inactive.open ||
+ rs->rules[rs_num].inactive.ticket != ticket)
+ return (0);
+ while ((rule = TAILQ_FIRST(rs->rules[rs_num].inactive.ptr)) != NULL) {
+ pf_rm_rule(rs->rules[rs_num].inactive.ptr, rule);
+ rs->rules[rs_num].inactive.rcount--;
+ }
+ rs->rules[rs_num].inactive.open = 0;
+ return (0);
+}
+
+#define PF_MD5_UPD(st, elm) \
+ MD5Update(ctx, (u_int8_t *) &(st)->elm, sizeof((st)->elm))
+
+#define PF_MD5_UPD_STR(st, elm) \
+ MD5Update(ctx, (u_int8_t *) (st)->elm, strlen((st)->elm))
+
+#define PF_MD5_UPD_HTONL(st, elm, stor) do { \
+ (stor) = htonl((st)->elm); \
+ MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int32_t));\
+} while (0)
+
+#define PF_MD5_UPD_HTONS(st, elm, stor) do { \
+ (stor) = htons((st)->elm); \
+ MD5Update(ctx, (u_int8_t *) &(stor), sizeof(u_int16_t));\
+} while (0)
+
+void
+pf_hash_rule_addr(MD5_CTX *ctx, struct pf_rule_addr *pfr)
+{
+ PF_MD5_UPD(pfr, addr.type);
+ switch (pfr->addr.type) {
+ case PF_ADDR_DYNIFTL:
+ PF_MD5_UPD(pfr, addr.v.ifname);
+ PF_MD5_UPD(pfr, addr.iflags);
+ break;
+ case PF_ADDR_TABLE:
+ PF_MD5_UPD(pfr, addr.v.tblname);
+ break;
+ case PF_ADDR_ADDRMASK:
+ /* XXX ignore af? */
+ PF_MD5_UPD(pfr, addr.v.a.addr.addr32);
+ PF_MD5_UPD(pfr, addr.v.a.mask.addr32);
+ break;
+ case PF_ADDR_RTLABEL:
+ PF_MD5_UPD(pfr, addr.v.rtlabelname);
+ break;
+ }
+
+ PF_MD5_UPD(pfr, port[0]);
+ PF_MD5_UPD(pfr, port[1]);
+ PF_MD5_UPD(pfr, neg);
+ PF_MD5_UPD(pfr, port_op);
+}
+
+void
+pf_hash_rule(MD5_CTX *ctx, struct pf_rule *rule)
+{
+ u_int16_t x;
+ u_int32_t y;
+
+ pf_hash_rule_addr(ctx, &rule->src);
+ pf_hash_rule_addr(ctx, &rule->dst);
+ PF_MD5_UPD_STR(rule, label);
+ PF_MD5_UPD_STR(rule, ifname);
+ PF_MD5_UPD_STR(rule, match_tagname);
+ PF_MD5_UPD_HTONS(rule, match_tag, x); /* dup? */
+ PF_MD5_UPD_HTONL(rule, os_fingerprint, y);
+ PF_MD5_UPD_HTONL(rule, prob, y);
+ PF_MD5_UPD_HTONL(rule, uid.uid[0], y);
+ PF_MD5_UPD_HTONL(rule, uid.uid[1], y);
+ PF_MD5_UPD(rule, uid.op);
+ PF_MD5_UPD_HTONL(rule, gid.gid[0], y);
+ PF_MD5_UPD_HTONL(rule, gid.gid[1], y);
+ PF_MD5_UPD(rule, gid.op);
+ PF_MD5_UPD_HTONL(rule, rule_flag, y);
+ PF_MD5_UPD(rule, action);
+ PF_MD5_UPD(rule, direction);
+ PF_MD5_UPD(rule, af);
+ PF_MD5_UPD(rule, quick);
+ PF_MD5_UPD(rule, ifnot);
+ PF_MD5_UPD(rule, match_tag_not);
+ PF_MD5_UPD(rule, natpass);
+ PF_MD5_UPD(rule, keep_state);
+ PF_MD5_UPD(rule, proto);
+ PF_MD5_UPD(rule, type);
+ PF_MD5_UPD(rule, code);
+ PF_MD5_UPD(rule, flags);
+ PF_MD5_UPD(rule, flagset);
+ PF_MD5_UPD(rule, allow_opts);
+ PF_MD5_UPD(rule, rt);
+ PF_MD5_UPD(rule, tos);
+}
+
+int
+pf_commit_rules(u_int32_t ticket, int rs_num, char *anchor)
+{
+ struct pf_ruleset *rs;
+ struct pf_rule *rule, **old_array;
+ struct pf_rulequeue *old_rules;
+ int s, error;
+ u_int32_t old_rcount;
+
+ if (rs_num < 0 || rs_num >= PF_RULESET_MAX)
+ return (EINVAL);
+ rs = pf_find_ruleset(anchor);
+ if (rs == NULL || !rs->rules[rs_num].inactive.open ||
+ ticket != rs->rules[rs_num].inactive.ticket)
+ return (EBUSY);
+
+ /* Calculate checksum for the main ruleset */
+ if (rs == &pf_main_ruleset) {
+ error = pf_setup_pfsync_matching(rs);
+ if (error != 0)
+ return (error);
+ }
+
+ /* Swap rules, keep the old. */
+ s = splsoftnet();
+ old_rules = rs->rules[rs_num].active.ptr;
+ old_rcount = rs->rules[rs_num].active.rcount;
+ old_array = rs->rules[rs_num].active.ptr_array;
+
+ rs->rules[rs_num].active.ptr =
+ rs->rules[rs_num].inactive.ptr;
+ rs->rules[rs_num].active.ptr_array =
+ rs->rules[rs_num].inactive.ptr_array;
+ rs->rules[rs_num].active.rcount =
+ rs->rules[rs_num].inactive.rcount;
+ rs->rules[rs_num].inactive.ptr = old_rules;
+ rs->rules[rs_num].inactive.ptr_array = old_array;
+ rs->rules[rs_num].inactive.rcount = old_rcount;
+
+ rs->rules[rs_num].active.ticket =
+ rs->rules[rs_num].inactive.ticket;
+ pf_calc_skip_steps(rs->rules[rs_num].active.ptr);
+
+
+ /* Purge the old rule list. */
+ while ((rule = TAILQ_FIRST(old_rules)) != NULL)
+ pf_rm_rule(old_rules, rule);
+ if (rs->rules[rs_num].inactive.ptr_array)
+ free(rs->rules[rs_num].inactive.ptr_array, M_TEMP);
+ rs->rules[rs_num].inactive.ptr_array = NULL;
+ rs->rules[rs_num].inactive.rcount = 0;
+ rs->rules[rs_num].inactive.open = 0;
+ pf_remove_if_empty_ruleset(rs);
+ splx(s);
+ return (0);
+}
+
+int
+pf_setup_pfsync_matching(struct pf_ruleset *rs)
+{
+ MD5_CTX ctx;
+ struct pf_rule *rule;
+ int rs_cnt;
+ u_int8_t digest[PF_MD5_DIGEST_LENGTH];
+
+ MD5Init(&ctx);
+ for (rs_cnt = 0; rs_cnt < PF_RULESET_MAX; rs_cnt++) {
+ /* XXX PF_RULESET_SCRUB as well? */
+ if (rs_cnt == PF_RULESET_SCRUB)
+ continue;
+
+ if (rs->rules[rs_cnt].inactive.ptr_array)
+ free(rs->rules[rs_cnt].inactive.ptr_array, M_TEMP);
+ rs->rules[rs_cnt].inactive.ptr_array = NULL;
+
+ if (rs->rules[rs_cnt].inactive.rcount) {
+ rs->rules[rs_cnt].inactive.ptr_array =
+ malloc(sizeof(caddr_t) *
+ rs->rules[rs_cnt].inactive.rcount,
+ M_TEMP, M_NOWAIT);
+
+ if (!rs->rules[rs_cnt].inactive.ptr_array)
+ return (ENOMEM);
+ }
+
+ TAILQ_FOREACH(rule, rs->rules[rs_cnt].inactive.ptr,
+ entries) {
+ pf_hash_rule(&ctx, rule);
+ (rs->rules[rs_cnt].inactive.ptr_array)[rule->nr] = rule;
+ }
+ }
+
+ MD5Final(digest, &ctx);
+ memcpy(pf_status.pf_chksum, digest, sizeof(pf_status.pf_chksum));
+ return (0);
+}
+
+int
+#ifdef __FreeBSD__
+pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td)
+#else
+pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
+#endif
+{
+ struct pf_pooladdr *pa = NULL;
+ struct pf_pool *pool = NULL;
+#ifndef __FreeBSD__
+ int s;
+#endif
+ int error = 0;
+
+ /* XXX keep in sync with switch() below */
+#ifdef __FreeBSD__
+ if (securelevel_gt(td->td_ucred, 2))
+#else
+ if (securelevel > 1)
+#endif
+ switch (cmd) {
+ case DIOCGETRULES:
+ case DIOCGETRULE:
+ case DIOCGETADDRS:
+ case DIOCGETADDR:
+ case DIOCGETSTATE:
+ case DIOCSETSTATUSIF:
+ case DIOCGETSTATUS:
+ case DIOCCLRSTATUS:
+ case DIOCNATLOOK:
+ case DIOCSETDEBUG:
+ case DIOCGETSTATES:
+ case DIOCGETTIMEOUT:
+ case DIOCCLRRULECTRS:
+ case DIOCGETLIMIT:
+ case DIOCGETALTQS:
+ case DIOCGETALTQ:
+ case DIOCGETQSTATS:
+ case DIOCGETRULESETS:
+ case DIOCGETRULESET:
+ case DIOCRGETTABLES:
+ case DIOCRGETTSTATS:
+ case DIOCRCLRTSTATS:
+ case DIOCRCLRADDRS:
+ case DIOCRADDADDRS:
+ case DIOCRDELADDRS:
+ case DIOCRSETADDRS:
+ case DIOCRGETADDRS:
+ case DIOCRGETASTATS:
+ case DIOCRCLRASTATS:
+ case DIOCRTSTADDRS:
+ case DIOCOSFPGET:
+ case DIOCGETSRCNODES:
+ case DIOCCLRSRCNODES:
+ case DIOCIGETIFACES:
+#ifdef __FreeBSD__
+ case DIOCGIFSPEED:
+#endif
+ case DIOCSETIFFLAG:
+ case DIOCCLRIFFLAG:
+ break;
+ case DIOCRCLRTABLES:
+ case DIOCRADDTABLES:
+ case DIOCRDELTABLES:
+ case DIOCRSETTFLAGS:
+ if (((struct pfioc_table *)addr)->pfrio_flags &
+ PFR_FLAG_DUMMY)
+ break; /* dummy operation ok */
+ return (EPERM);
+ default:
+ return (EPERM);
+ }
+
+ if (!(flags & FWRITE))
+ switch (cmd) {
+ case DIOCGETRULES:
+ case DIOCGETADDRS:
+ case DIOCGETADDR:
+ case DIOCGETSTATE:
+ case DIOCGETSTATUS:
+ case DIOCGETSTATES:
+ case DIOCGETTIMEOUT:
+ case DIOCGETLIMIT:
+ case DIOCGETALTQS:
+ case DIOCGETALTQ:
+ case DIOCGETQSTATS:
+ case DIOCGETRULESETS:
+ case DIOCGETRULESET:
+ case DIOCNATLOOK:
+ case DIOCRGETTABLES:
+ case DIOCRGETTSTATS:
+ case DIOCRGETADDRS:
+ case DIOCRGETASTATS:
+ case DIOCRTSTADDRS:
+ case DIOCOSFPGET:
+ case DIOCGETSRCNODES:
+ case DIOCIGETIFACES:
+#ifdef __FreeBSD__
+ case DIOCGIFSPEED:
+#endif
+ break;
+ case DIOCRCLRTABLES:
+ case DIOCRADDTABLES:
+ case DIOCRDELTABLES:
+ case DIOCRCLRTSTATS:
+ case DIOCRCLRADDRS:
+ case DIOCRADDADDRS:
+ case DIOCRDELADDRS:
+ case DIOCRSETADDRS:
+ case DIOCRSETTFLAGS:
+ if (((struct pfioc_table *)addr)->pfrio_flags &
+ PFR_FLAG_DUMMY) {
+ flags |= FWRITE; /* need write lock for dummy */
+ break; /* dummy operation ok */
+ }
+ return (EACCES);
+ case DIOCGETRULE:
+ if (((struct pfioc_rule *)addr)->action == PF_GET_CLR_CNTR)
+ return (EACCES);
+ break;
+ default:
+ return (EACCES);
+ }
+
+ if (flags & FWRITE)
+#ifdef __FreeBSD__
+ sx_xlock(&pf_consistency_lock);
+ else
+ sx_slock(&pf_consistency_lock);
+#else
+ rw_enter_write(&pf_consistency_lock);
+ else
+ rw_enter_read(&pf_consistency_lock);
+#endif
+
+#ifdef __FreeBSD__
+ PF_LOCK();
+#else
+ s = splsoftnet();
+#endif
+ switch (cmd) {
+
+ case DIOCSTART:
+ if (pf_status.running)
+ error = EEXIST;
+ else {
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ error = hook_pf();
+ PF_LOCK();
+ if (error) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: pfil registeration fail\n"));
+ break;
+ }
+#endif
+ pf_status.running = 1;
+ pf_status.since = time_second;
+ if (pf_status.stateid == 0) {
+ pf_status.stateid = time_second;
+ pf_status.stateid = pf_status.stateid << 32;
+ }
+ DPFPRINTF(PF_DEBUG_MISC, ("pf: started\n"));
+ }
+ break;
+
+ case DIOCSTOP:
+ if (!pf_status.running)
+ error = ENOENT;
+ else {
+ pf_status.running = 0;
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+ error = dehook_pf();
+ PF_LOCK();
+ if (error) {
+ pf_status.running = 1;
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: pfil unregisteration failed\n"));
+ }
+#endif
+ pf_status.since = time_second;
+ DPFPRINTF(PF_DEBUG_MISC, ("pf: stopped\n"));
+ }
+ break;
+
+ case DIOCADDRULE: {
+ struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rule *rule, *tail;
+ struct pf_pooladdr *pa;
+ int rs_num;
+
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
+ ruleset = pf_find_ruleset(pr->anchor);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ rs_num = pf_get_ruleset_number(pr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rules[rs_num].inactive.ticket) {
+#ifdef __FreeBSD__
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("ticket: %d != [%d]%d\n", pr->ticket, rs_num,
+ ruleset->rules[rs_num].inactive.ticket));
+#endif
+ error = EBUSY;
+ break;
+ }
+ if (pr->pool_ticket != ticket_pabuf) {
+#ifdef __FreeBSD__
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pool_ticket: %d != %d\n", pr->pool_ticket,
+ ticket_pabuf));
+#endif
+ error = EBUSY;
+ break;
+ }
+ rule = pool_get(&pf_rule_pl, PR_NOWAIT);
+ if (rule == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(&pr->rule, rule, sizeof(struct pf_rule));
+#ifdef __FreeBSD__
+ rule->cuid = td->td_ucred->cr_ruid;
+ rule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
+#else
+ rule->cuid = p->p_cred->p_ruid;
+ rule->cpid = p->p_pid;
+#endif
+ rule->anchor = NULL;
+ rule->kif = NULL;
+ TAILQ_INIT(&rule->rpool.list);
+ /* initialize refcounting */
+ rule->states = 0;
+ rule->src_nodes = 0;
+ rule->entries.tqe_prev = NULL;
+#ifndef INET
+ if (rule->af == AF_INET) {
+ pool_put(&pf_rule_pl, rule);
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET */
+#ifndef INET6
+ if (rule->af == AF_INET6) {
+ pool_put(&pf_rule_pl, rule);
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET6 */
+ tail = TAILQ_LAST(ruleset->rules[rs_num].inactive.ptr,
+ pf_rulequeue);
+ if (tail)
+ rule->nr = tail->nr + 1;
+ else
+ rule->nr = 0;
+ if (rule->ifname[0]) {
+ rule->kif = pfi_kif_get(rule->ifname);
+ if (rule->kif == NULL) {
+ pool_put(&pf_rule_pl, rule);
+ error = EINVAL;
+ break;
+ }
+ pfi_kif_ref(rule->kif, PFI_KIF_REF_RULE);
+ }
+
+#ifdef __FreeBSD__ /* ROUTING */
+ if (rule->rtableid > 0 && rule->rtableid > rt_numfibs)
+#else
+ if (rule->rtableid > 0 && !rtable_exists(rule->rtableid))
+#endif
+ error = EBUSY;
+
+#ifdef ALTQ
+ /* set queue IDs */
+ if (rule->qname[0] != 0) {
+ if ((rule->qid = pf_qname2qid(rule->qname)) == 0)
+ error = EBUSY;
+ else if (rule->pqname[0] != 0) {
+ if ((rule->pqid =
+ pf_qname2qid(rule->pqname)) == 0)
+ error = EBUSY;
+ } else
+ rule->pqid = rule->qid;
+ }
+#endif
+ if (rule->tagname[0])
+ if ((rule->tag = pf_tagname2tag(rule->tagname)) == 0)
+ error = EBUSY;
+ if (rule->match_tagname[0])
+ if ((rule->match_tag =
+ pf_tagname2tag(rule->match_tagname)) == 0)
+ error = EBUSY;
+ if (rule->rt && !rule->direction)
+ error = EINVAL;
+#if NPFLOG > 0
+#ifdef __FreeBSD__
+ if (!rule->log)
+ rule->logif = 0;
+#endif
+ if (rule->logif >= PFLOGIFS_MAX)
+ error = EINVAL;
+#endif
+ if (pf_rtlabel_add(&rule->src.addr) ||
+ pf_rtlabel_add(&rule->dst.addr))
+ error = EBUSY;
+ if (pfi_dynaddr_setup(&rule->src.addr, rule->af))
+ error = EINVAL;
+ if (pfi_dynaddr_setup(&rule->dst.addr, rule->af))
+ error = EINVAL;
+ if (pf_tbladdr_setup(ruleset, &rule->src.addr))
+ error = EINVAL;
+ if (pf_tbladdr_setup(ruleset, &rule->dst.addr))
+ error = EINVAL;
+ if (pf_anchor_setup(rule, ruleset, pr->anchor_call))
+ error = EINVAL;
+ TAILQ_FOREACH(pa, &pf_pabuf, entries)
+ if (pf_tbladdr_setup(ruleset, &pa->addr))
+ error = EINVAL;
+
+ if (rule->overload_tblname[0]) {
+ if ((rule->overload_tbl = pfr_attach_table(ruleset,
+ rule->overload_tblname)) == NULL)
+ error = EINVAL;
+ else
+ rule->overload_tbl->pfrkt_flags |=
+ PFR_TFLAG_ACTIVE;
+ }
+
+ pf_mv_pool(&pf_pabuf, &rule->rpool.list);
+ if (((((rule->action == PF_NAT) || (rule->action == PF_RDR) ||
+ (rule->action == PF_BINAT)) && rule->anchor == NULL) ||
+ (rule->rt > PF_FASTROUTE)) &&
+ (TAILQ_FIRST(&rule->rpool.list) == NULL))
+ error = EINVAL;
+
+ if (error) {
+ pf_rm_rule(NULL, rule);
+ break;
+ }
+
+#ifdef __FreeBSD__
+ if (!debug_pfugidhack && (rule->uid.op || rule->gid.op ||
+ rule->log & PF_LOG_SOCKET_LOOKUP)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: debug.pfugidhack enabled\n"));
+ debug_pfugidhack = 1;
+ }
+#endif
+
+ rule->rpool.cur = TAILQ_FIRST(&rule->rpool.list);
+ rule->evaluations = rule->packets[0] = rule->packets[1] =
+ rule->bytes[0] = rule->bytes[1] = 0;
+ TAILQ_INSERT_TAIL(ruleset->rules[rs_num].inactive.ptr,
+ rule, entries);
+ ruleset->rules[rs_num].inactive.rcount++;
+ break;
+ }
+
+ case DIOCGETRULES: {
+ struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rule *tail;
+ int rs_num;
+
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
+ ruleset = pf_find_ruleset(pr->anchor);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ rs_num = pf_get_ruleset_number(pr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+ tail = TAILQ_LAST(ruleset->rules[rs_num].active.ptr,
+ pf_rulequeue);
+ if (tail)
+ pr->nr = tail->nr + 1;
+ else
+ pr->nr = 0;
+ pr->ticket = ruleset->rules[rs_num].active.ticket;
+ break;
+ }
+
+ case DIOCGETRULE: {
+ struct pfioc_rule *pr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rule *rule;
+ int rs_num, i;
+
+ pr->anchor[sizeof(pr->anchor) - 1] = 0;
+ ruleset = pf_find_ruleset(pr->anchor);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ rs_num = pf_get_ruleset_number(pr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+ if (pr->ticket != ruleset->rules[rs_num].active.ticket) {
+ error = EBUSY;
+ break;
+ }
+ rule = TAILQ_FIRST(ruleset->rules[rs_num].active.ptr);
+ while ((rule != NULL) && (rule->nr != pr->nr))
+ rule = TAILQ_NEXT(rule, entries);
+ if (rule == NULL) {
+ error = EBUSY;
+ break;
+ }
+ bcopy(rule, &pr->rule, sizeof(struct pf_rule));
+ if (pf_anchor_copyout(ruleset, rule, pr)) {
+ error = EBUSY;
+ break;
+ }
+ pfi_dynaddr_copyout(&pr->rule.src.addr);
+ pfi_dynaddr_copyout(&pr->rule.dst.addr);
+ pf_tbladdr_copyout(&pr->rule.src.addr);
+ pf_tbladdr_copyout(&pr->rule.dst.addr);
+ pf_rtlabel_copyout(&pr->rule.src.addr);
+ pf_rtlabel_copyout(&pr->rule.dst.addr);
+ for (i = 0; i < PF_SKIP_COUNT; ++i)
+ if (rule->skip[i].ptr == NULL)
+ pr->rule.skip[i].nr = -1;
+ else
+ pr->rule.skip[i].nr =
+ rule->skip[i].ptr->nr;
+
+ if (pr->action == PF_GET_CLR_CNTR) {
+ rule->evaluations = 0;
+ rule->packets[0] = rule->packets[1] = 0;
+ rule->bytes[0] = rule->bytes[1] = 0;
+ }
+ break;
+ }
+
+ case DIOCCHANGERULE: {
+ struct pfioc_rule *pcr = (struct pfioc_rule *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_rule *oldrule = NULL, *newrule = NULL;
+ u_int32_t nr = 0;
+ int rs_num;
+
+ if (!(pcr->action == PF_CHANGE_REMOVE ||
+ pcr->action == PF_CHANGE_GET_TICKET) &&
+ pcr->pool_ticket != ticket_pabuf) {
+ error = EBUSY;
+ break;
+ }
+
+ if (pcr->action < PF_CHANGE_ADD_HEAD ||
+ pcr->action > PF_CHANGE_GET_TICKET) {
+ error = EINVAL;
+ break;
+ }
+ ruleset = pf_find_ruleset(pcr->anchor);
+ if (ruleset == NULL) {
+ error = EINVAL;
+ break;
+ }
+ rs_num = pf_get_ruleset_number(pcr->rule.action);
+ if (rs_num >= PF_RULESET_MAX) {
+ error = EINVAL;
+ break;
+ }
+
+ if (pcr->action == PF_CHANGE_GET_TICKET) {
+ pcr->ticket = ++ruleset->rules[rs_num].active.ticket;
+ break;
+ } else {
+ if (pcr->ticket !=
+ ruleset->rules[rs_num].active.ticket) {
+ error = EINVAL;
+ break;
+ }
+ if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) {
+ error = EINVAL;
+ break;
+ }
+ }
+
+ if (pcr->action != PF_CHANGE_REMOVE) {
+ newrule = pool_get(&pf_rule_pl, PR_NOWAIT);
+ if (newrule == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(&pcr->rule, newrule, sizeof(struct pf_rule));
+#ifdef __FreeBSD__
+ newrule->cuid = td->td_ucred->cr_ruid;
+ newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0;
+#else
+ newrule->cuid = p->p_cred->p_ruid;
+ newrule->cpid = p->p_pid;
+#endif
+ TAILQ_INIT(&newrule->rpool.list);
+ /* initialize refcounting */
+ newrule->states = 0;
+ newrule->entries.tqe_prev = NULL;
+#ifndef INET
+ if (newrule->af == AF_INET) {
+ pool_put(&pf_rule_pl, newrule);
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET */
+#ifndef INET6
+ if (newrule->af == AF_INET6) {
+ pool_put(&pf_rule_pl, newrule);
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET6 */
+ if (newrule->ifname[0]) {
+ newrule->kif = pfi_kif_get(newrule->ifname);
+ if (newrule->kif == NULL) {
+ pool_put(&pf_rule_pl, newrule);
+ error = EINVAL;
+ break;
+ }
+ pfi_kif_ref(newrule->kif, PFI_KIF_REF_RULE);
+ } else
+ newrule->kif = NULL;
+
+ if (newrule->rtableid > 0 &&
+#ifdef __FreeBSD__ /* ROUTING */
+ newrule->rtableid > rt_numfibs)
+#else
+ !rtable_exists(newrule->rtableid))
+#endif
+ error = EBUSY;
+
+#ifdef ALTQ
+ /* set queue IDs */
+ if (newrule->qname[0] != 0) {
+ if ((newrule->qid =
+ pf_qname2qid(newrule->qname)) == 0)
+ error = EBUSY;
+ else if (newrule->pqname[0] != 0) {
+ if ((newrule->pqid =
+ pf_qname2qid(newrule->pqname)) == 0)
+ error = EBUSY;
+ } else
+ newrule->pqid = newrule->qid;
+ }
+#endif /* ALTQ */
+ if (newrule->tagname[0])
+ if ((newrule->tag =
+ pf_tagname2tag(newrule->tagname)) == 0)
+ error = EBUSY;
+ if (newrule->match_tagname[0])
+ if ((newrule->match_tag = pf_tagname2tag(
+ newrule->match_tagname)) == 0)
+ error = EBUSY;
+ if (newrule->rt && !newrule->direction)
+ error = EINVAL;
+#ifdef __FreeBSD__
+#if NPFLOG > 0
+ if (!newrule->log)
+ newrule->logif = 0;
+ if (newrule->logif >= PFLOGIFS_MAX)
+ error = EINVAL;
+#endif
+#endif
+ if (pf_rtlabel_add(&newrule->src.addr) ||
+ pf_rtlabel_add(&newrule->dst.addr))
+ error = EBUSY;
+ if (pfi_dynaddr_setup(&newrule->src.addr, newrule->af))
+ error = EINVAL;
+ if (pfi_dynaddr_setup(&newrule->dst.addr, newrule->af))
+ error = EINVAL;
+ if (pf_tbladdr_setup(ruleset, &newrule->src.addr))
+ error = EINVAL;
+ if (pf_tbladdr_setup(ruleset, &newrule->dst.addr))
+ error = EINVAL;
+ if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call))
+ error = EINVAL;
+ TAILQ_FOREACH(pa, &pf_pabuf, entries)
+ if (pf_tbladdr_setup(ruleset, &pa->addr))
+ error = EINVAL;
+
+ if (newrule->overload_tblname[0]) {
+ if ((newrule->overload_tbl = pfr_attach_table(
+ ruleset, newrule->overload_tblname)) ==
+ NULL)
+ error = EINVAL;
+ else
+ newrule->overload_tbl->pfrkt_flags |=
+ PFR_TFLAG_ACTIVE;
+ }
+
+ pf_mv_pool(&pf_pabuf, &newrule->rpool.list);
+ if (((((newrule->action == PF_NAT) ||
+ (newrule->action == PF_RDR) ||
+ (newrule->action == PF_BINAT) ||
+ (newrule->rt > PF_FASTROUTE)) &&
+ !newrule->anchor)) &&
+ (TAILQ_FIRST(&newrule->rpool.list) == NULL))
+ error = EINVAL;
+
+ if (error) {
+ pf_rm_rule(NULL, newrule);
+ break;
+ }
+
+#ifdef __FreeBSD__
+ if (!debug_pfugidhack && (newrule->uid.op ||
+ newrule->gid.op ||
+ newrule->log & PF_LOG_SOCKET_LOOKUP)) {
+ DPFPRINTF(PF_DEBUG_MISC,
+ ("pf: debug.pfugidhack enabled\n"));
+ debug_pfugidhack = 1;
+ }
+#endif
+
+ newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list);
+ newrule->evaluations = 0;
+ newrule->packets[0] = newrule->packets[1] = 0;
+ newrule->bytes[0] = newrule->bytes[1] = 0;
+ }
+ pf_empty_pool(&pf_pabuf);
+
+ if (pcr->action == PF_CHANGE_ADD_HEAD)
+ oldrule = TAILQ_FIRST(
+ ruleset->rules[rs_num].active.ptr);
+ else if (pcr->action == PF_CHANGE_ADD_TAIL)
+ oldrule = TAILQ_LAST(
+ ruleset->rules[rs_num].active.ptr, pf_rulequeue);
+ else {
+ oldrule = TAILQ_FIRST(
+ ruleset->rules[rs_num].active.ptr);
+ while ((oldrule != NULL) && (oldrule->nr != pcr->nr))
+ oldrule = TAILQ_NEXT(oldrule, entries);
+ if (oldrule == NULL) {
+ if (newrule != NULL)
+ pf_rm_rule(NULL, newrule);
+ error = EINVAL;
+ break;
+ }
+ }
+
+ if (pcr->action == PF_CHANGE_REMOVE) {
+ pf_rm_rule(ruleset->rules[rs_num].active.ptr, oldrule);
+ ruleset->rules[rs_num].active.rcount--;
+ } else {
+ if (oldrule == NULL)
+ TAILQ_INSERT_TAIL(
+ ruleset->rules[rs_num].active.ptr,
+ newrule, entries);
+ else if (pcr->action == PF_CHANGE_ADD_HEAD ||
+ pcr->action == PF_CHANGE_ADD_BEFORE)
+ TAILQ_INSERT_BEFORE(oldrule, newrule, entries);
+ else
+ TAILQ_INSERT_AFTER(
+ ruleset->rules[rs_num].active.ptr,
+ oldrule, newrule, entries);
+ ruleset->rules[rs_num].active.rcount++;
+ }
+
+ nr = 0;
+ TAILQ_FOREACH(oldrule,
+ ruleset->rules[rs_num].active.ptr, entries)
+ oldrule->nr = nr++;
+
+ ruleset->rules[rs_num].active.ticket++;
+
+ pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr);
+ pf_remove_if_empty_ruleset(ruleset);
+
+ break;
+ }
+
+ case DIOCCLRSTATES: {
+ struct pf_state *state, *nexts;
+ struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
+ int killed = 0;
+
+ for (state = RB_MIN(pf_state_tree_id, &tree_id); state;
+ state = nexts) {
+ nexts = RB_NEXT(pf_state_tree_id, &tree_id, state);
+
+ if (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
+ state->u.s.kif->pfik_name)) {
+#if NPFSYNC
+ /* don't send out individual delete messages */
+ state->sync_flags = PFSTATE_NOSYNC;
+#endif
+ pf_unlink_state(state);
+ killed++;
+ }
+ }
+ psk->psk_af = killed;
+#if NPFSYNC
+ pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
+#endif
+ break;
+ }
+
+ case DIOCKILLSTATES: {
+ struct pf_state *state, *nexts;
+ struct pf_state_host *src, *dst;
+ struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
+ int killed = 0;
+
+ for (state = RB_MIN(pf_state_tree_id, &tree_id); state;
+ state = nexts) {
+ nexts = RB_NEXT(pf_state_tree_id, &tree_id, state);
+
+ if (state->direction == PF_OUT) {
+ src = &state->lan;
+ dst = &state->ext;
+ } else {
+ src = &state->ext;
+ dst = &state->lan;
+ }
+ if ((!psk->psk_af || state->af == psk->psk_af)
+ && (!psk->psk_proto || psk->psk_proto ==
+ state->proto) &&
+ PF_MATCHA(psk->psk_src.neg,
+ &psk->psk_src.addr.v.a.addr,
+ &psk->psk_src.addr.v.a.mask,
+ &src->addr, state->af) &&
+ PF_MATCHA(psk->psk_dst.neg,
+ &psk->psk_dst.addr.v.a.addr,
+ &psk->psk_dst.addr.v.a.mask,
+ &dst->addr, state->af) &&
+ (psk->psk_src.port_op == 0 ||
+ pf_match_port(psk->psk_src.port_op,
+ psk->psk_src.port[0], psk->psk_src.port[1],
+ src->port)) &&
+ (psk->psk_dst.port_op == 0 ||
+ pf_match_port(psk->psk_dst.port_op,
+ psk->psk_dst.port[0], psk->psk_dst.port[1],
+ dst->port)) &&
+ (!psk->psk_ifname[0] || !strcmp(psk->psk_ifname,
+ state->u.s.kif->pfik_name))) {
+#if NPFSYNC > 0
+ /* send immediate delete of state */
+ pfsync_delete_state(state);
+ state->sync_flags |= PFSTATE_NOSYNC;
+#endif
+ pf_unlink_state(state);
+ killed++;
+ }
+ }
+ psk->psk_af = killed;
+ break;
+ }
+
+ case DIOCADDSTATE: {
+ struct pfioc_state *ps = (struct pfioc_state *)addr;
+ struct pf_state *state;
+ struct pfi_kif *kif;
+
+ if (ps->state.timeout >= PFTM_MAX &&
+ ps->state.timeout != PFTM_UNTIL_PACKET) {
+ error = EINVAL;
+ break;
+ }
+ state = pool_get(&pf_state_pl, PR_NOWAIT);
+ if (state == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ kif = pfi_kif_get(ps->state.u.ifname);
+ if (kif == NULL) {
+ pool_put(&pf_state_pl, state);
+ error = ENOENT;
+ break;
+ }
+ bcopy(&ps->state, state, sizeof(struct pf_state));
+ bzero(&state->u, sizeof(state->u));
+ state->rule.ptr = &pf_default_rule;
+ state->nat_rule.ptr = NULL;
+ state->anchor.ptr = NULL;
+ state->rt_kif = NULL;
+ state->creation = time_second;
+ state->pfsync_time = 0;
+ state->packets[0] = state->packets[1] = 0;
+ state->bytes[0] = state->bytes[1] = 0;
+
+ if (pf_insert_state(kif, state)) {
+ pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+ pool_put(&pf_state_pl, state);
+ error = ENOMEM;
+ }
+ break;
+ }
+
+ case DIOCGETSTATE: {
+ struct pfioc_state *ps = (struct pfioc_state *)addr;
+ struct pf_state *state;
+ u_int32_t nr;
+ int secs;
+
+ nr = 0;
+ RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+ if (nr >= ps->nr)
+ break;
+ nr++;
+ }
+ if (state == NULL) {
+ error = EBUSY;
+ break;
+ }
+ secs = time_second;
+ bcopy(state, &ps->state, sizeof(ps->state));
+ strlcpy(ps->state.u.ifname, state->u.s.kif->pfik_name,
+ sizeof(ps->state.u.ifname));
+ ps->state.rule.nr = state->rule.ptr->nr;
+ ps->state.nat_rule.nr = (state->nat_rule.ptr == NULL) ?
+ -1 : state->nat_rule.ptr->nr;
+ ps->state.anchor.nr = (state->anchor.ptr == NULL) ?
+ -1 : state->anchor.ptr->nr;
+ ps->state.creation = secs - ps->state.creation;
+ ps->state.expire = pf_state_expires(state);
+ if (ps->state.expire > secs)
+ ps->state.expire -= secs;
+ else
+ ps->state.expire = 0;
+ break;
+ }
+
+ case DIOCGETSTATES: {
+ struct pfioc_states *ps = (struct pfioc_states *)addr;
+ struct pf_state *state;
+ struct pf_state *p, *pstore;
+ u_int32_t nr = 0;
+ int space = ps->ps_len;
+
+ if (space == 0) {
+ nr = pf_status.states;
+ ps->ps_len = sizeof(struct pf_state) * nr;
+ break;
+ }
+
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+
+ p = ps->ps_states;
+
+ state = TAILQ_FIRST(&state_list);
+ while (state) {
+ if (state->timeout != PFTM_UNLINKED) {
+ int secs = time_second;
+
+ if ((nr+1) * sizeof(*p) > (unsigned)ps->ps_len)
+ break;
+
+ bcopy(state, pstore, sizeof(*pstore));
+ strlcpy(pstore->u.ifname,
+ state->u.s.kif->pfik_name,
+ sizeof(pstore->u.ifname));
+ pstore->rule.nr = state->rule.ptr->nr;
+ pstore->nat_rule.nr = (state->nat_rule.ptr ==
+ NULL) ? -1 : state->nat_rule.ptr->nr;
+ pstore->anchor.nr = (state->anchor.ptr ==
+ NULL) ? -1 : state->anchor.ptr->nr;
+ pstore->creation = secs - pstore->creation;
+ pstore->expire = pf_state_expires(state);
+ if (pstore->expire > secs)
+ pstore->expire -= secs;
+ else
+ pstore->expire = 0;
+#ifdef __FreeBSD__
+ PF_COPYOUT(pstore, p, sizeof(*p), error);
+#else
+ error = copyout(pstore, p, sizeof(*p));
+#endif
+ if (error) {
+ free(pstore, M_TEMP);
+ goto fail;
+ }
+ p++;
+ nr++;
+ }
+ state = TAILQ_NEXT(state, u.s.entry_list);
+ }
+
+ ps->ps_len = sizeof(struct pf_state) * nr;
+
+ free(pstore, M_TEMP);
+ break;
+ }
+
+ case DIOCGETSTATUS: {
+ struct pf_status *s = (struct pf_status *)addr;
+ bcopy(&pf_status, s, sizeof(struct pf_status));
+ pfi_fill_oldstatus(s);
+ break;
+ }
+
+ case DIOCSETSTATUSIF: {
+ struct pfioc_if *pi = (struct pfioc_if *)addr;
+
+ if (pi->ifname[0] == 0) {
+ bzero(pf_status.ifname, IFNAMSIZ);
+ break;
+ }
+ if (ifunit(pi->ifname) == NULL) {
+ error = EINVAL;
+ break;
+ }
+ strlcpy(pf_status.ifname, pi->ifname, IFNAMSIZ);
+ break;
+ }
+
+ case DIOCCLRSTATUS: {
+ bzero(pf_status.counters, sizeof(pf_status.counters));
+ bzero(pf_status.fcounters, sizeof(pf_status.fcounters));
+ bzero(pf_status.scounters, sizeof(pf_status.scounters));
+ pf_status.since = time_second;
+ if (*pf_status.ifname)
+ pfi_clr_istats(pf_status.ifname);
+ break;
+ }
+
+ case DIOCNATLOOK: {
+ struct pfioc_natlook *pnl = (struct pfioc_natlook *)addr;
+ struct pf_state *state;
+ struct pf_state_cmp key;
+ int m = 0, direction = pnl->direction;
+
+ key.af = pnl->af;
+ key.proto = pnl->proto;
+
+ if (!pnl->proto ||
+ PF_AZERO(&pnl->saddr, pnl->af) ||
+ PF_AZERO(&pnl->daddr, pnl->af) ||
+ ((pnl->proto == IPPROTO_TCP ||
+ pnl->proto == IPPROTO_UDP) &&
+ (!pnl->dport || !pnl->sport)))
+ error = EINVAL;
+ else {
+ /*
+ * userland gives us source and dest of connection,
+ * reverse the lookup so we ask for what happens with
+ * the return traffic, enabling us to find it in the
+ * state tree.
+ */
+ if (direction == PF_IN) {
+ PF_ACPY(&key.ext.addr, &pnl->daddr, pnl->af);
+ key.ext.port = pnl->dport;
+ PF_ACPY(&key.gwy.addr, &pnl->saddr, pnl->af);
+ key.gwy.port = pnl->sport;
+ state = pf_find_state_all(&key, PF_EXT_GWY, &m);
+ } else {
+ PF_ACPY(&key.lan.addr, &pnl->daddr, pnl->af);
+ key.lan.port = pnl->dport;
+ PF_ACPY(&key.ext.addr, &pnl->saddr, pnl->af);
+ key.ext.port = pnl->sport;
+ state = pf_find_state_all(&key, PF_LAN_EXT, &m);
+ }
+ if (m > 1)
+ error = E2BIG; /* more than one state */
+ else if (state != NULL) {
+ if (direction == PF_IN) {
+ PF_ACPY(&pnl->rsaddr, &state->lan.addr,
+ state->af);
+ pnl->rsport = state->lan.port;
+ PF_ACPY(&pnl->rdaddr, &pnl->daddr,
+ pnl->af);
+ pnl->rdport = pnl->dport;
+ } else {
+ PF_ACPY(&pnl->rdaddr, &state->gwy.addr,
+ state->af);
+ pnl->rdport = state->gwy.port;
+ PF_ACPY(&pnl->rsaddr, &pnl->saddr,
+ pnl->af);
+ pnl->rsport = pnl->sport;
+ }
+ } else
+ error = ENOENT;
+ }
+ break;
+ }
+
+ case DIOCSETTIMEOUT: {
+ struct pfioc_tm *pt = (struct pfioc_tm *)addr;
+ int old;
+
+ if (pt->timeout < 0 || pt->timeout >= PFTM_MAX ||
+ pt->seconds < 0) {
+ error = EINVAL;
+ goto fail;
+ }
+ old = pf_default_rule.timeout[pt->timeout];
+ if (pt->timeout == PFTM_INTERVAL && pt->seconds == 0)
+ pt->seconds = 1;
+ pf_default_rule.timeout[pt->timeout] = pt->seconds;
+ if (pt->timeout == PFTM_INTERVAL && pt->seconds < old)
+ wakeup(pf_purge_thread);
+ pt->seconds = old;
+ break;
+ }
+
+ case DIOCGETTIMEOUT: {
+ struct pfioc_tm *pt = (struct pfioc_tm *)addr;
+
+ if (pt->timeout < 0 || pt->timeout >= PFTM_MAX) {
+ error = EINVAL;
+ goto fail;
+ }
+ pt->seconds = pf_default_rule.timeout[pt->timeout];
+ break;
+ }
+
+ case DIOCGETLIMIT: {
+ struct pfioc_limit *pl = (struct pfioc_limit *)addr;
+
+ if (pl->index < 0 || pl->index >= PF_LIMIT_MAX) {
+ error = EINVAL;
+ goto fail;
+ }
+ pl->limit = pf_pool_limits[pl->index].limit;
+ break;
+ }
+
+ case DIOCSETLIMIT: {
+ struct pfioc_limit *pl = (struct pfioc_limit *)addr;
+ int old_limit;
+
+ if (pl->index < 0 || pl->index >= PF_LIMIT_MAX ||
+ pf_pool_limits[pl->index].pp == NULL) {
+ error = EINVAL;
+ goto fail;
+ }
+#ifdef __FreeBSD__
+ uma_zone_set_max(pf_pool_limits[pl->index].pp, pl->limit);
+#else
+ if (pool_sethardlimit(pf_pool_limits[pl->index].pp,
+ pl->limit, NULL, 0) != 0) {
+ error = EBUSY;
+ goto fail;
+ }
+#endif
+ old_limit = pf_pool_limits[pl->index].limit;
+ pf_pool_limits[pl->index].limit = pl->limit;
+ pl->limit = old_limit;
+ break;
+ }
+
+ case DIOCSETDEBUG: {
+ u_int32_t *level = (u_int32_t *)addr;
+
+ pf_status.debug = *level;
+ break;
+ }
+
+ case DIOCCLRRULECTRS: {
+ /* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */
+ struct pf_ruleset *ruleset = &pf_main_ruleset;
+ struct pf_rule *rule;
+
+ TAILQ_FOREACH(rule,
+ ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) {
+ rule->evaluations = 0;
+ rule->packets[0] = rule->packets[1] = 0;
+ rule->bytes[0] = rule->bytes[1] = 0;
+ }
+ break;
+ }
+
+#ifdef __FreeBSD__
+ case DIOCGIFSPEED: {
+ struct pf_ifspeed *psp = (struct pf_ifspeed *)addr;
+ struct pf_ifspeed ps;
+ struct ifnet *ifp;
+
+ if (psp->ifname[0] != 0) {
+ /* Can we completely trust user-land? */
+ strlcpy(ps.ifname, psp->ifname, IFNAMSIZ);
+ ifp = ifunit(ps.ifname);
+ if (ifp != NULL)
+ psp->baudrate = ifp->if_baudrate;
+ else
+ error = EINVAL;
+ } else
+ error = EINVAL;
+ break;
+ }
+#endif /* __FreeBSD__ */
+
+#ifdef ALTQ
+ case DIOCSTARTALTQ: {
+ struct pf_altq *altq;
+
+ /* enable all altq interfaces on active list */
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 && (altq->local_flags &
+ PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
+ if (altq->qname[0] == 0) {
+#endif
+ error = pf_enable_altq(altq);
+ if (error != 0)
+ break;
+ }
+ }
+ if (error == 0)
+ pf_altq_running = 1;
+ DPFPRINTF(PF_DEBUG_MISC, ("altq: started\n"));
+ break;
+ }
+
+ case DIOCSTOPALTQ: {
+ struct pf_altq *altq;
+
+ /* disable all altq interfaces on active list */
+ TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 && (altq->local_flags &
+ PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
+ if (altq->qname[0] == 0) {
+#endif
+ error = pf_disable_altq(altq);
+ if (error != 0)
+ break;
+ }
+ }
+ if (error == 0)
+ pf_altq_running = 0;
+ DPFPRINTF(PF_DEBUG_MISC, ("altq: stopped\n"));
+ break;
+ }
+
+ case DIOCADDALTQ: {
+ struct pfioc_altq *pa = (struct pfioc_altq *)addr;
+ struct pf_altq *altq, *a;
+
+ if (pa->ticket != ticket_altqs_inactive) {
+ error = EBUSY;
+ break;
+ }
+ altq = pool_get(&pf_altq_pl, PR_NOWAIT);
+ if (altq == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(&pa->altq, altq, sizeof(struct pf_altq));
+#ifdef __FreeBSD__
+ altq->local_flags = 0;
+#endif
+
+ /*
+ * if this is for a queue, find the discipline and
+ * copy the necessary fields
+ */
+ if (altq->qname[0] != 0) {
+ if ((altq->qid = pf_qname2qid(altq->qname)) == 0) {
+ error = EBUSY;
+ pool_put(&pf_altq_pl, altq);
+ break;
+ }
+ altq->altq_disc = NULL;
+ TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
+ if (strncmp(a->ifname, altq->ifname,
+ IFNAMSIZ) == 0 && a->qname[0] == 0) {
+ altq->altq_disc = a->altq_disc;
+ break;
+ }
+ }
+ }
+
+#ifdef __FreeBSD__
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(altq->ifname)) == NULL) {
+ altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
+ } else {
+ PF_UNLOCK();
+#endif
+ error = altq_add(altq);
+#ifdef __FreeBSD__
+ PF_LOCK();
+ }
+#endif
+ if (error) {
+ pool_put(&pf_altq_pl, altq);
+ break;
+ }
+
+ TAILQ_INSERT_TAIL(pf_altqs_inactive, altq, entries);
+ bcopy(altq, &pa->altq, sizeof(struct pf_altq));
+ break;
+ }
+
+ case DIOCGETALTQS: {
+ struct pfioc_altq *pa = (struct pfioc_altq *)addr;
+ struct pf_altq *altq;
+
+ pa->nr = 0;
+ TAILQ_FOREACH(altq, pf_altqs_active, entries)
+ pa->nr++;
+ pa->ticket = ticket_altqs_active;
+ break;
+ }
+
+ case DIOCGETALTQ: {
+ struct pfioc_altq *pa = (struct pfioc_altq *)addr;
+ struct pf_altq *altq;
+ u_int32_t nr;
+
+ if (pa->ticket != ticket_altqs_active) {
+ error = EBUSY;
+ break;
+ }
+ nr = 0;
+ altq = TAILQ_FIRST(pf_altqs_active);
+ while ((altq != NULL) && (nr < pa->nr)) {
+ altq = TAILQ_NEXT(altq, entries);
+ nr++;
+ }
+ if (altq == NULL) {
+ error = EBUSY;
+ break;
+ }
+ bcopy(altq, &pa->altq, sizeof(struct pf_altq));
+ break;
+ }
+
+ case DIOCCHANGEALTQ:
+ /* CHANGEALTQ not supported yet! */
+ error = ENODEV;
+ break;
+
+ case DIOCGETQSTATS: {
+ struct pfioc_qstats *pq = (struct pfioc_qstats *)addr;
+ struct pf_altq *altq;
+ u_int32_t nr;
+ int nbytes;
+
+ if (pq->ticket != ticket_altqs_active) {
+ error = EBUSY;
+ break;
+ }
+ nbytes = pq->nbytes;
+ nr = 0;
+ altq = TAILQ_FIRST(pf_altqs_active);
+ while ((altq != NULL) && (nr < pq->nr)) {
+ altq = TAILQ_NEXT(altq, entries);
+ nr++;
+ }
+ if (altq == NULL) {
+ error = EBUSY;
+ break;
+ }
+#ifdef __FreeBSD__
+ if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
+ error = ENXIO;
+ break;
+ }
+ PF_UNLOCK();
+#endif
+ error = altq_getqstats(altq, pq->buf, &nbytes);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ if (error == 0) {
+ pq->scheduler = altq->scheduler;
+ pq->nbytes = nbytes;
+ }
+ break;
+ }
+#endif /* ALTQ */
+
+ case DIOCBEGINADDRS: {
+ struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+
+ pf_empty_pool(&pf_pabuf);
+ pp->ticket = ++ticket_pabuf;
+ break;
+ }
+
+ case DIOCADDADDR: {
+ struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+
+ if (pp->ticket != ticket_pabuf) {
+ error = EBUSY;
+ break;
+ }
+#ifndef INET
+ if (pp->af == AF_INET) {
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET */
+#ifndef INET6
+ if (pp->af == AF_INET6) {
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET6 */
+ if (pp->addr.addr.type != PF_ADDR_ADDRMASK &&
+ pp->addr.addr.type != PF_ADDR_DYNIFTL &&
+ pp->addr.addr.type != PF_ADDR_TABLE) {
+ error = EINVAL;
+ break;
+ }
+ pa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
+ if (pa == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(&pp->addr, pa, sizeof(struct pf_pooladdr));
+ if (pa->ifname[0]) {
+ pa->kif = pfi_kif_get(pa->ifname);
+ if (pa->kif == NULL) {
+ pool_put(&pf_pooladdr_pl, pa);
+ error = EINVAL;
+ break;
+ }
+ pfi_kif_ref(pa->kif, PFI_KIF_REF_RULE);
+ }
+ if (pfi_dynaddr_setup(&pa->addr, pp->af)) {
+ pfi_dynaddr_remove(&pa->addr);
+ pfi_kif_unref(pa->kif, PFI_KIF_REF_RULE);
+ pool_put(&pf_pooladdr_pl, pa);
+ error = EINVAL;
+ break;
+ }
+ TAILQ_INSERT_TAIL(&pf_pabuf, pa, entries);
+ break;
+ }
+
+ case DIOCGETADDRS: {
+ struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+
+ pp->nr = 0;
+ pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
+ pp->r_num, 0, 1, 0);
+ if (pool == NULL) {
+ error = EBUSY;
+ break;
+ }
+ TAILQ_FOREACH(pa, &pool->list, entries)
+ pp->nr++;
+ break;
+ }
+
+ case DIOCGETADDR: {
+ struct pfioc_pooladdr *pp = (struct pfioc_pooladdr *)addr;
+ u_int32_t nr = 0;
+
+ pool = pf_get_pool(pp->anchor, pp->ticket, pp->r_action,
+ pp->r_num, 0, 1, 1);
+ if (pool == NULL) {
+ error = EBUSY;
+ break;
+ }
+ pa = TAILQ_FIRST(&pool->list);
+ while ((pa != NULL) && (nr < pp->nr)) {
+ pa = TAILQ_NEXT(pa, entries);
+ nr++;
+ }
+ if (pa == NULL) {
+ error = EBUSY;
+ break;
+ }
+ bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
+ pfi_dynaddr_copyout(&pp->addr.addr);
+ pf_tbladdr_copyout(&pp->addr.addr);
+ pf_rtlabel_copyout(&pp->addr.addr);
+ break;
+ }
+
+ case DIOCCHANGEADDR: {
+ struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr;
+ struct pf_pooladdr *oldpa = NULL, *newpa = NULL;
+ struct pf_ruleset *ruleset;
+
+ if (pca->action < PF_CHANGE_ADD_HEAD ||
+ pca->action > PF_CHANGE_REMOVE) {
+ error = EINVAL;
+ break;
+ }
+ if (pca->addr.addr.type != PF_ADDR_ADDRMASK &&
+ pca->addr.addr.type != PF_ADDR_DYNIFTL &&
+ pca->addr.addr.type != PF_ADDR_TABLE) {
+ error = EINVAL;
+ break;
+ }
+
+ ruleset = pf_find_ruleset(pca->anchor);
+ if (ruleset == NULL) {
+ error = EBUSY;
+ break;
+ }
+ pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action,
+ pca->r_num, pca->r_last, 1, 1);
+ if (pool == NULL) {
+ error = EBUSY;
+ break;
+ }
+ if (pca->action != PF_CHANGE_REMOVE) {
+ newpa = pool_get(&pf_pooladdr_pl, PR_NOWAIT);
+ if (newpa == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr));
+#ifndef INET
+ if (pca->af == AF_INET) {
+ pool_put(&pf_pooladdr_pl, newpa);
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET */
+#ifndef INET6
+ if (pca->af == AF_INET6) {
+ pool_put(&pf_pooladdr_pl, newpa);
+ error = EAFNOSUPPORT;
+ break;
+ }
+#endif /* INET6 */
+ if (newpa->ifname[0]) {
+ newpa->kif = pfi_kif_get(newpa->ifname);
+ if (newpa->kif == NULL) {
+ pool_put(&pf_pooladdr_pl, newpa);
+ error = EINVAL;
+ break;
+ }
+ pfi_kif_ref(newpa->kif, PFI_KIF_REF_RULE);
+ } else
+ newpa->kif = NULL;
+ if (pfi_dynaddr_setup(&newpa->addr, pca->af) ||
+ pf_tbladdr_setup(ruleset, &newpa->addr)) {
+ pfi_dynaddr_remove(&newpa->addr);
+ pfi_kif_unref(newpa->kif, PFI_KIF_REF_RULE);
+ pool_put(&pf_pooladdr_pl, newpa);
+ error = EINVAL;
+ break;
+ }
+ }
+
+ if (pca->action == PF_CHANGE_ADD_HEAD)
+ oldpa = TAILQ_FIRST(&pool->list);
+ else if (pca->action == PF_CHANGE_ADD_TAIL)
+ oldpa = TAILQ_LAST(&pool->list, pf_palist);
+ else {
+ int i = 0;
+
+ oldpa = TAILQ_FIRST(&pool->list);
+ while ((oldpa != NULL) && (i < pca->nr)) {
+ oldpa = TAILQ_NEXT(oldpa, entries);
+ i++;
+ }
+ if (oldpa == NULL) {
+ error = EINVAL;
+ break;
+ }
+ }
+
+ if (pca->action == PF_CHANGE_REMOVE) {
+ TAILQ_REMOVE(&pool->list, oldpa, entries);
+ pfi_dynaddr_remove(&oldpa->addr);
+ pf_tbladdr_remove(&oldpa->addr);
+ pfi_kif_unref(oldpa->kif, PFI_KIF_REF_RULE);
+ pool_put(&pf_pooladdr_pl, oldpa);
+ } else {
+ if (oldpa == NULL)
+ TAILQ_INSERT_TAIL(&pool->list, newpa, entries);
+ else if (pca->action == PF_CHANGE_ADD_HEAD ||
+ pca->action == PF_CHANGE_ADD_BEFORE)
+ TAILQ_INSERT_BEFORE(oldpa, newpa, entries);
+ else
+ TAILQ_INSERT_AFTER(&pool->list, oldpa,
+ newpa, entries);
+ }
+
+ pool->cur = TAILQ_FIRST(&pool->list);
+ PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr,
+ pca->af);
+ break;
+ }
+
+ case DIOCGETRULESETS: {
+ struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_anchor *anchor;
+
+ pr->path[sizeof(pr->path) - 1] = 0;
+ if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
+ error = EINVAL;
+ break;
+ }
+ pr->nr = 0;
+ if (ruleset->anchor == NULL) {
+ /* XXX kludge for pf_main_ruleset */
+ RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
+ if (anchor->parent == NULL)
+ pr->nr++;
+ } else {
+ RB_FOREACH(anchor, pf_anchor_node,
+ &ruleset->anchor->children)
+ pr->nr++;
+ }
+ break;
+ }
+
+ case DIOCGETRULESET: {
+ struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr;
+ struct pf_ruleset *ruleset;
+ struct pf_anchor *anchor;
+ u_int32_t nr = 0;
+
+ pr->path[sizeof(pr->path) - 1] = 0;
+ if ((ruleset = pf_find_ruleset(pr->path)) == NULL) {
+ error = EINVAL;
+ break;
+ }
+ pr->name[0] = 0;
+ if (ruleset->anchor == NULL) {
+ /* XXX kludge for pf_main_ruleset */
+ RB_FOREACH(anchor, pf_anchor_global, &pf_anchors)
+ if (anchor->parent == NULL && nr++ == pr->nr) {
+ strlcpy(pr->name, anchor->name,
+ sizeof(pr->name));
+ break;
+ }
+ } else {
+ RB_FOREACH(anchor, pf_anchor_node,
+ &ruleset->anchor->children)
+ if (nr++ == pr->nr) {
+ strlcpy(pr->name, anchor->name,
+ sizeof(pr->name));
+ break;
+ }
+ }
+ if (!pr->name[0])
+ error = EBUSY;
+ break;
+ }
+
+ case DIOCRCLRTABLES: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != 0) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_clr_tables(&io->pfrio_table, &io->pfrio_ndel,
+ io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRADDTABLES: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_table)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_add_tables(io->pfrio_buffer, io->pfrio_size,
+ &io->pfrio_nadd, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRDELTABLES: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_table)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_del_tables(io->pfrio_buffer, io->pfrio_size,
+ &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRGETTABLES: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_table)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_get_tables(&io->pfrio_table, io->pfrio_buffer,
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRGETTSTATS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_tstats)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_get_tstats(&io->pfrio_table, io->pfrio_buffer,
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRCLRTSTATS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_table)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_clr_tstats(io->pfrio_buffer, io->pfrio_size,
+ &io->pfrio_nzero, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRSETTFLAGS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_table)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_set_tflags(io->pfrio_buffer, io->pfrio_size,
+ io->pfrio_setflag, io->pfrio_clrflag, &io->pfrio_nchange,
+ &io->pfrio_ndel, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRCLRADDRS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != 0) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_clr_addrs(&io->pfrio_table, &io->pfrio_ndel,
+ io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRADDADDRS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_addr)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_add_addrs(&io->pfrio_table, io->pfrio_buffer,
+ io->pfrio_size, &io->pfrio_nadd, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRDELADDRS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_addr)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_del_addrs(&io->pfrio_table, io->pfrio_buffer,
+ io->pfrio_size, &io->pfrio_ndel, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRSETADDRS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_addr)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_set_addrs(&io->pfrio_table, io->pfrio_buffer,
+ io->pfrio_size, &io->pfrio_size2, &io->pfrio_nadd,
+ &io->pfrio_ndel, &io->pfrio_nchange, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL, 0);
+ break;
+ }
+
+ case DIOCRGETADDRS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_addr)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_get_addrs(&io->pfrio_table, io->pfrio_buffer,
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRGETASTATS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_astats)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_get_astats(&io->pfrio_table, io->pfrio_buffer,
+ &io->pfrio_size, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRCLRASTATS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_addr)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_clr_astats(&io->pfrio_table, io->pfrio_buffer,
+ io->pfrio_size, &io->pfrio_nzero, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRTSTADDRS: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_addr)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_tst_addrs(&io->pfrio_table, io->pfrio_buffer,
+ io->pfrio_size, &io->pfrio_nmatch, io->pfrio_flags |
+ PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCRINADEFINE: {
+ struct pfioc_table *io = (struct pfioc_table *)addr;
+
+ if (io->pfrio_esize != sizeof(struct pfr_addr)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfr_ina_define(&io->pfrio_table, io->pfrio_buffer,
+ io->pfrio_size, &io->pfrio_nadd, &io->pfrio_naddr,
+ io->pfrio_ticket, io->pfrio_flags | PFR_FLAG_USERIOCTL);
+ break;
+ }
+
+ case DIOCOSFPADD: {
+ struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
+ error = pf_osfp_add(io);
+ break;
+ }
+
+ case DIOCOSFPGET: {
+ struct pf_osfp_ioctl *io = (struct pf_osfp_ioctl *)addr;
+ error = pf_osfp_get(io);
+ break;
+ }
+
+ case DIOCXBEGIN: {
+ struct pfioc_trans *io = (struct pfioc_trans *)addr;
+ struct pfioc_trans_e *ioe;
+ struct pfr_table *table;
+ int i;
+
+ if (io->esize != sizeof(*ioe)) {
+ error = ENODEV;
+ goto fail;
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
+ M_TEMP, M_WAITOK);
+ table = (struct pfr_table *)malloc(sizeof(*table),
+ M_TEMP, M_WAITOK);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0; i < io->size; i++) {
+#ifdef __FreeBSD__
+ PF_COPYIN(io->array+i, ioe, sizeof(*ioe), error);
+ if (error) {
+#else
+ if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+#endif
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EFAULT;
+ goto fail;
+ }
+ switch (ioe->rs_num) {
+#ifdef ALTQ
+ case PF_RULESET_ALTQ:
+ if (ioe->anchor[0]) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EINVAL;
+ goto fail;
+ }
+ if ((error = pf_begin_altq(&ioe->ticket))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail;
+ }
+ break;
+#endif /* ALTQ */
+ case PF_RULESET_TABLE:
+ bzero(table, sizeof(*table));
+ strlcpy(table->pfrt_anchor, ioe->anchor,
+ sizeof(table->pfrt_anchor));
+ if ((error = pfr_ina_begin(table,
+ &ioe->ticket, NULL, 0))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail;
+ }
+ break;
+ default:
+ if ((error = pf_begin_rules(&ioe->ticket,
+ ioe->rs_num, ioe->anchor))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail;
+ }
+ break;
+ }
+#ifdef __FreeBSD__
+ PF_COPYOUT(ioe, io->array+i, sizeof(io->array[i]),
+ error);
+ if (error) {
+#else
+ if (copyout(ioe, io->array+i, sizeof(io->array[i]))) {
+#endif
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EFAULT;
+ goto fail;
+ }
+ }
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ break;
+ }
+
+ case DIOCXROLLBACK: {
+ struct pfioc_trans *io = (struct pfioc_trans *)addr;
+ struct pfioc_trans_e *ioe;
+ struct pfr_table *table;
+ int i;
+
+ if (io->esize != sizeof(*ioe)) {
+ error = ENODEV;
+ goto fail;
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
+ M_TEMP, M_WAITOK);
+ table = (struct pfr_table *)malloc(sizeof(*table),
+ M_TEMP, M_WAITOK);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ for (i = 0; i < io->size; i++) {
+#ifdef __FreeBSD__
+ PF_COPYIN(io->array+i, ioe, sizeof(*ioe), error);
+ if (error) {
+#else
+ if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+#endif
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EFAULT;
+ goto fail;
+ }
+ switch (ioe->rs_num) {
+#ifdef ALTQ
+ case PF_RULESET_ALTQ:
+ if (ioe->anchor[0]) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EINVAL;
+ goto fail;
+ }
+ if ((error = pf_rollback_altq(ioe->ticket))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail; /* really bad */
+ }
+ break;
+#endif /* ALTQ */
+ case PF_RULESET_TABLE:
+ bzero(table, sizeof(*table));
+ strlcpy(table->pfrt_anchor, ioe->anchor,
+ sizeof(table->pfrt_anchor));
+ if ((error = pfr_ina_rollback(table,
+ ioe->ticket, NULL, 0))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail; /* really bad */
+ }
+ break;
+ default:
+ if ((error = pf_rollback_rules(ioe->ticket,
+ ioe->rs_num, ioe->anchor))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail; /* really bad */
+ }
+ break;
+ }
+ }
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ break;
+ }
+
+ case DIOCXCOMMIT: {
+ struct pfioc_trans *io = (struct pfioc_trans *)addr;
+ struct pfioc_trans_e *ioe;
+ struct pfr_table *table;
+ struct pf_ruleset *rs;
+ int i;
+
+ if (io->esize != sizeof(*ioe)) {
+ error = ENODEV;
+ goto fail;
+ }
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ ioe = (struct pfioc_trans_e *)malloc(sizeof(*ioe),
+ M_TEMP, M_WAITOK);
+ table = (struct pfr_table *)malloc(sizeof(*table),
+ M_TEMP, M_WAITOK);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+ /* first makes sure everything will succeed */
+ for (i = 0; i < io->size; i++) {
+#ifdef __FreeBSD__
+ PF_COPYIN(io->array+i, ioe, sizeof(*ioe), error);
+ if (error) {
+#else
+ if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+#endif
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EFAULT;
+ goto fail;
+ }
+ switch (ioe->rs_num) {
+#ifdef ALTQ
+ case PF_RULESET_ALTQ:
+ if (ioe->anchor[0]) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EINVAL;
+ goto fail;
+ }
+ if (!altqs_inactive_open || ioe->ticket !=
+ ticket_altqs_inactive) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EBUSY;
+ goto fail;
+ }
+ break;
+#endif /* ALTQ */
+ case PF_RULESET_TABLE:
+ rs = pf_find_ruleset(ioe->anchor);
+ if (rs == NULL || !rs->topen || ioe->ticket !=
+ rs->tticket) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EBUSY;
+ goto fail;
+ }
+ break;
+ default:
+ if (ioe->rs_num < 0 || ioe->rs_num >=
+ PF_RULESET_MAX) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EINVAL;
+ goto fail;
+ }
+ rs = pf_find_ruleset(ioe->anchor);
+ if (rs == NULL ||
+ !rs->rules[ioe->rs_num].inactive.open ||
+ rs->rules[ioe->rs_num].inactive.ticket !=
+ ioe->ticket) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EBUSY;
+ goto fail;
+ }
+ break;
+ }
+ }
+ /* now do the commit - no errors should happen here */
+ for (i = 0; i < io->size; i++) {
+#ifdef __FreeBSD__
+ PF_COPYIN(io->array+i, ioe, sizeof(*ioe), error);
+ if (error) {
+#else
+ if (copyin(io->array+i, ioe, sizeof(*ioe))) {
+#endif
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ error = EFAULT;
+ goto fail;
+ }
+ switch (ioe->rs_num) {
+#ifdef ALTQ
+ case PF_RULESET_ALTQ:
+ if ((error = pf_commit_altq(ioe->ticket))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail; /* really bad */
+ }
+ break;
+#endif /* ALTQ */
+ case PF_RULESET_TABLE:
+ bzero(table, sizeof(*table));
+ strlcpy(table->pfrt_anchor, ioe->anchor,
+ sizeof(table->pfrt_anchor));
+ if ((error = pfr_ina_commit(table, ioe->ticket,
+ NULL, NULL, 0))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail; /* really bad */
+ }
+ break;
+ default:
+ if ((error = pf_commit_rules(ioe->ticket,
+ ioe->rs_num, ioe->anchor))) {
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ goto fail; /* really bad */
+ }
+ break;
+ }
+ }
+ free(table, M_TEMP);
+ free(ioe, M_TEMP);
+ break;
+ }
+
+ case DIOCGETSRCNODES: {
+ struct pfioc_src_nodes *psn = (struct pfioc_src_nodes *)addr;
+ struct pf_src_node *n, *p, *pstore;
+ u_int32_t nr = 0;
+ int space = psn->psn_len;
+
+ if (space == 0) {
+ RB_FOREACH(n, pf_src_tree, &tree_src_tracking)
+ nr++;
+ psn->psn_len = sizeof(struct pf_src_node) * nr;
+ break;
+ }
+
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+#endif
+ pstore = malloc(sizeof(*pstore), M_TEMP, M_WAITOK);
+#ifdef __FreeBSD__
+ PF_LOCK();
+#endif
+
+ p = psn->psn_src_nodes;
+ RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
+ int secs = time_second, diff;
+
+ if ((nr + 1) * sizeof(*p) > (unsigned)psn->psn_len)
+ break;
+
+ bcopy(n, pstore, sizeof(*pstore));
+ if (n->rule.ptr != NULL)
+ pstore->rule.nr = n->rule.ptr->nr;
+ pstore->creation = secs - pstore->creation;
+ if (pstore->expire > secs)
+ pstore->expire -= secs;
+ else
+ pstore->expire = 0;
+
+ /* adjust the connection rate estimate */
+ diff = secs - n->conn_rate.last;
+ if (diff >= n->conn_rate.seconds)
+ pstore->conn_rate.count = 0;
+ else
+ pstore->conn_rate.count -=
+ n->conn_rate.count * diff /
+ n->conn_rate.seconds;
+
+#ifdef __FreeBSD__
+ PF_COPYOUT(pstore, p, sizeof(*p), error);
+#else
+ error = copyout(pstore, p, sizeof(*p));
+#endif
+ if (error) {
+ free(pstore, M_TEMP);
+ goto fail;
+ }
+ p++;
+ nr++;
+ }
+ psn->psn_len = sizeof(struct pf_src_node) * nr;
+
+ free(pstore, M_TEMP);
+ break;
+ }
+
+ case DIOCCLRSRCNODES: {
+ struct pf_src_node *n;
+ struct pf_state *state;
+
+ RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+ state->src_node = NULL;
+ state->nat_src_node = NULL;
+ }
+ RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
+ n->expire = 1;
+ n->states = 0;
+ }
+ pf_purge_expired_src_nodes(1);
+ pf_status.src_nodes = 0;
+ break;
+ }
+
+ case DIOCKILLSRCNODES: {
+ struct pf_src_node *sn;
+ struct pf_state *s;
+ struct pfioc_src_node_kill *psnk = \
+ (struct pfioc_src_node_kill *) addr;
+ int killed = 0;
+
+ RB_FOREACH(sn, pf_src_tree, &tree_src_tracking) {
+ if (PF_MATCHA(psnk->psnk_src.neg, \
+ &psnk->psnk_src.addr.v.a.addr, \
+ &psnk->psnk_src.addr.v.a.mask, \
+ &sn->addr, sn->af) &&
+ PF_MATCHA(psnk->psnk_dst.neg, \
+ &psnk->psnk_dst.addr.v.a.addr, \
+ &psnk->psnk_dst.addr.v.a.mask, \
+ &sn->raddr, sn->af)) {
+ /* Handle state to src_node linkage */
+ if (sn->states != 0) {
+ RB_FOREACH(s, pf_state_tree_id,
+ &tree_id) {
+ if (s->src_node == sn)
+ s->src_node = NULL;
+ if (s->nat_src_node == sn)
+ s->nat_src_node = NULL;
+ }
+ sn->states = 0;
+ }
+ sn->expire = 1;
+ killed++;
+ }
+ }
+
+ if (killed > 0)
+ pf_purge_expired_src_nodes(1);
+
+ psnk->psnk_af = killed;
+ break;
+ }
+
+ case DIOCSETHOSTID: {
+ u_int32_t *hostid = (u_int32_t *)addr;
+
+ if (*hostid == 0)
+ pf_status.hostid = arc4random();
+ else
+ pf_status.hostid = *hostid;
+ break;
+ }
+
+ case DIOCOSFPFLUSH:
+ pf_osfp_flush();
+ break;
+
+ case DIOCIGETIFACES: {
+ struct pfioc_iface *io = (struct pfioc_iface *)addr;
+
+ if (io->pfiio_esize != sizeof(struct pfi_kif)) {
+ error = ENODEV;
+ break;
+ }
+ error = pfi_get_ifaces(io->pfiio_name, io->pfiio_buffer,
+ &io->pfiio_size);
+ break;
+ }
+
+ case DIOCSETIFFLAG: {
+ struct pfioc_iface *io = (struct pfioc_iface *)addr;
+
+ error = pfi_set_flags(io->pfiio_name, io->pfiio_flags);
+ break;
+ }
+
+ case DIOCCLRIFFLAG: {
+ struct pfioc_iface *io = (struct pfioc_iface *)addr;
+
+ error = pfi_clear_flags(io->pfiio_name, io->pfiio_flags);
+ break;
+ }
+
+ default:
+ error = ENODEV;
+ break;
+ }
+fail:
+#ifdef __FreeBSD__
+ PF_UNLOCK();
+
+ if (flags & FWRITE)
+ sx_xunlock(&pf_consistency_lock);
+ else
+ sx_sunlock(&pf_consistency_lock);
+#else
+ splx(s);
+ /* XXX: Lock order? */
+ if (flags & FWRITE)
+ rw_exit_write(&pf_consistency_lock);
+ else
+ rw_exit_read(&pf_consistency_lock);
+#endif
+ return (error);
+}
+
+#ifdef __FreeBSD__
+/*
+ * XXX - Check for version missmatch!!!
+ */
+static void
+pf_clear_states(void)
+{
+ struct pf_state *state;
+
+ RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+ state->timeout = PFTM_PURGE;
+#if NPFSYNC
+ /* don't send out individual delete messages */
+ state->sync_flags = PFSTATE_NOSYNC;
+#endif
+ pf_unlink_state(state);
+ }
+
+#if 0 /* NPFSYNC */
+/*
+ * XXX This is called on module unload, we do not want to sync that over? */
+ */
+ pfsync_clear_states(pf_status.hostid, psk->psk_ifname);
+#endif
+}
+
+static int
+pf_clear_tables(void)
+{
+ struct pfioc_table io;
+ int error;
+
+ bzero(&io, sizeof(io));
+
+ error = pfr_clr_tables(&io.pfrio_table, &io.pfrio_ndel,
+ io.pfrio_flags);
+
+ return (error);
+}
+
+static void
+pf_clear_srcnodes(void)
+{
+ struct pf_src_node *n;
+ struct pf_state *state;
+
+ RB_FOREACH(state, pf_state_tree_id, &tree_id) {
+ state->src_node = NULL;
+ state->nat_src_node = NULL;
+ }
+ RB_FOREACH(n, pf_src_tree, &tree_src_tracking) {
+ n->expire = 1;
+ n->states = 0;
+ }
+}
+/*
+ * XXX - Check for version missmatch!!!
+ */
+
+/*
+ * Duplicate pfctl -Fa operation to get rid of as much as we can.
+ */
+static int
+shutdown_pf(void)
+{
+ int error = 0;
+ u_int32_t t[5];
+ char nn = '\0';
+
+ pf_status.running = 0;
+ do {
+ if ((error = pf_begin_rules(&t[0], PF_RULESET_SCRUB, &nn))
+ != 0) {
+ DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: SCRUB\n"));
+ break;
+ }
+ if ((error = pf_begin_rules(&t[1], PF_RULESET_FILTER, &nn))
+ != 0) {
+ DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: FILTER\n"));
+ break; /* XXX: rollback? */
+ }
+ if ((error = pf_begin_rules(&t[2], PF_RULESET_NAT, &nn))
+ != 0) {
+ DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: NAT\n"));
+ break; /* XXX: rollback? */
+ }
+ if ((error = pf_begin_rules(&t[3], PF_RULESET_BINAT, &nn))
+ != 0) {
+ DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: BINAT\n"));
+ break; /* XXX: rollback? */
+ }
+ if ((error = pf_begin_rules(&t[4], PF_RULESET_RDR, &nn))
+ != 0) {
+ DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: RDR\n"));
+ break; /* XXX: rollback? */
+ }
+
+ /* XXX: these should always succeed here */
+ pf_commit_rules(t[0], PF_RULESET_SCRUB, &nn);
+ pf_commit_rules(t[1], PF_RULESET_FILTER, &nn);
+ pf_commit_rules(t[2], PF_RULESET_NAT, &nn);
+ pf_commit_rules(t[3], PF_RULESET_BINAT, &nn);
+ pf_commit_rules(t[4], PF_RULESET_RDR, &nn);
+
+ if ((error = pf_clear_tables()) != 0)
+ break;
+
+#ifdef ALTQ
+ if ((error = pf_begin_altq(&t[0])) != 0) {
+ DPFPRINTF(PF_DEBUG_MISC, ("shutdown_pf: ALTQ\n"));
+ break;
+ }
+ pf_commit_altq(t[0]);
+#endif
+
+ pf_clear_states();
+
+ pf_clear_srcnodes();
+
+ /* status does not use malloced mem so no need to cleanup */
+ /* fingerprints and interfaces have thier own cleanup code */
+ } while(0);
+
+ return (error);
+}
+
+static int
+pf_check_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ /*
+ * XXX Wed Jul 9 22:03:16 2003 UTC
+ * OpenBSD has changed its byte ordering convention on ip_len/ip_off
+ * in network stack. OpenBSD's network stack have converted
+ * ip_len/ip_off to host byte order frist as FreeBSD.
+ * Now this is not true anymore , so we should convert back to network
+ * byte order.
+ */
+ struct ip *h = NULL;
+ int chk;
+
+ if ((*m)->m_pkthdr.len >= (int)sizeof(struct ip)) {
+ /* if m_pkthdr.len is less than ip header, pf will handle. */
+ h = mtod(*m, struct ip *);
+ HTONS(h->ip_len);
+ HTONS(h->ip_off);
+ }
+ chk = pf_test(PF_IN, ifp, m, NULL, inp);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ if (*m != NULL) {
+ /* pf_test can change ip header location */
+ h = mtod(*m, struct ip *);
+ NTOHS(h->ip_len);
+ NTOHS(h->ip_off);
+ }
+ return chk;
+}
+
+static int
+pf_check_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ /*
+ * XXX Wed Jul 9 22:03:16 2003 UTC
+ * OpenBSD has changed its byte ordering convention on ip_len/ip_off
+ * in network stack. OpenBSD's network stack have converted
+ * ip_len/ip_off to host byte order frist as FreeBSD.
+ * Now this is not true anymore , so we should convert back to network
+ * byte order.
+ */
+ struct ip *h = NULL;
+ int chk;
+
+ /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
+ if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ in_delayed_cksum(*m);
+ (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ }
+ if ((*m)->m_pkthdr.len >= (int)sizeof(*h)) {
+ /* if m_pkthdr.len is less than ip header, pf will handle. */
+ h = mtod(*m, struct ip *);
+ HTONS(h->ip_len);
+ HTONS(h->ip_off);
+ }
+ chk = pf_test(PF_OUT, ifp, m, NULL, inp);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ if (*m != NULL) {
+ /* pf_test can change ip header location */
+ h = mtod(*m, struct ip *);
+ NTOHS(h->ip_len);
+ NTOHS(h->ip_off);
+ }
+ return chk;
+}
+
+#ifdef INET6
+static int
+pf_check6_in(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+
+ /*
+ * IPv6 is not affected by ip_len/ip_off byte order changes.
+ */
+ int chk;
+
+ /*
+ * In case of loopback traffic IPv6 uses the real interface in
+ * order to support scoped addresses. In order to support stateful
+ * filtering we have change this to lo0 as it is the case in IPv4.
+ */
+ chk = pf_test6(PF_IN, (*m)->m_flags & M_LOOP ? V_loif : ifp, m,
+ NULL, inp);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ return chk;
+}
+
+static int
+pf_check6_out(void *arg, struct mbuf **m, struct ifnet *ifp, int dir,
+ struct inpcb *inp)
+{
+ /*
+ * IPv6 does not affected ip_len/ip_off byte order changes.
+ */
+ int chk;
+
+ /* We need a proper CSUM befor we start (s. OpenBSD ip_output) */
+ if ((*m)->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ in_delayed_cksum(*m);
+ (*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ }
+ chk = pf_test6(PF_OUT, ifp, m, NULL, inp);
+ if (chk && *m) {
+ m_freem(*m);
+ *m = NULL;
+ }
+ return chk;
+}
+#endif /* INET6 */
+
+static int
+hook_pf(void)
+{
+ struct pfil_head *pfh_inet;
+#ifdef INET6
+ struct pfil_head *pfh_inet6;
+#endif
+
+ PF_ASSERT(MA_NOTOWNED);
+
+ if (pf_pfil_hooked)
+ return (0);
+
+ pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (pfh_inet == NULL)
+ return (ESRCH); /* XXX */
+ pfil_add_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet);
+ pfil_add_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet);
+#ifdef INET6
+ pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+ if (pfh_inet6 == NULL) {
+ pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
+ return (ESRCH); /* XXX */
+ }
+ pfil_add_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK, pfh_inet6);
+ pfil_add_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK, pfh_inet6);
+#endif
+
+ pf_pfil_hooked = 1;
+ return (0);
+}
+
+static int
+dehook_pf(void)
+{
+ struct pfil_head *pfh_inet;
+#ifdef INET6
+ struct pfil_head *pfh_inet6;
+#endif
+
+ PF_ASSERT(MA_NOTOWNED);
+
+ if (pf_pfil_hooked == 0)
+ return (0);
+
+ pfh_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
+ if (pfh_inet == NULL)
+ return (ESRCH); /* XXX */
+ pfil_remove_hook(pf_check_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet);
+ pfil_remove_hook(pf_check_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet);
+#ifdef INET6
+ pfh_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
+ if (pfh_inet6 == NULL)
+ return (ESRCH); /* XXX */
+ pfil_remove_hook(pf_check6_in, NULL, PFIL_IN | PFIL_WAITOK,
+ pfh_inet6);
+ pfil_remove_hook(pf_check6_out, NULL, PFIL_OUT | PFIL_WAITOK,
+ pfh_inet6);
+#endif
+
+ pf_pfil_hooked = 0;
+ return (0);
+}
+
+static int
+pf_load(void)
+{
+ init_zone_var();
+ init_pf_mutex();
+ pf_dev = make_dev(&pf_cdevsw, 0, 0, 0, 0600, PF_NAME);
+ if (pfattach() < 0) {
+ destroy_dev(pf_dev);
+ destroy_pf_mutex();
+ return (ENOMEM);
+ }
+ return (0);
+}
+
+static int
+pf_unload(void)
+{
+ int error = 0;
+
+ PF_LOCK();
+ pf_status.running = 0;
+ PF_UNLOCK();
+ error = dehook_pf();
+ if (error) {
+ /*
+ * Should not happen!
+ * XXX Due to error code ESRCH, kldunload will show
+ * a message like 'No such process'.
+ */
+ printf("%s : pfil unregisteration fail\n", __FUNCTION__);
+ return error;
+ }
+ PF_LOCK();
+ shutdown_pf();
+ pf_end_threads = 1;
+ while (pf_end_threads < 2) {
+ wakeup_one(pf_purge_thread);
+ msleep(pf_purge_thread, &pf_task_mtx, 0, "pftmo", hz);
+ }
+ pfi_cleanup();
+ pf_osfp_flush();
+ pf_osfp_cleanup();
+ cleanup_pf_zone();
+ PF_UNLOCK();
+ destroy_dev(pf_dev);
+ destroy_pf_mutex();
+ return error;
+}
+
+static int
+pf_modevent(module_t mod, int type, void *data)
+{
+ int error = 0;
+
+ switch(type) {
+ case MOD_LOAD:
+ error = pf_load();
+ break;
+
+ case MOD_UNLOAD:
+ error = pf_unload();
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+ return error;
+}
+
+static moduledata_t pf_mod = {
+ "pf",
+ pf_modevent,
+ 0
+};
+
+DECLARE_MODULE(pf, pf_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_FIRST);
+MODULE_VERSION(pf, PF_MODVER);
+#endif /* __FreeBSD__ */
diff --git a/freebsd/sys/contrib/pf/net/pf_mtag.h b/freebsd/sys/contrib/pf/net/pf_mtag.h
new file mode 100644
index 00000000..09aeb25c
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_mtag.h
@@ -0,0 +1,82 @@
+/* $FreeBSD$ */
+/*
+ * Copyright (c) 2001 Daniel Hartmeier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _NET_PF_MTAG_HH_
+#define _NET_PF_MTAG_HH_
+
+#ifdef _KERNEL
+
+#define PF_TAG_GENERATED 0x01
+#define PF_TAG_FRAGCACHE 0x02
+#define PF_TAG_TRANSLATE_LOCALHOST 0x04
+
+struct pf_mtag {
+ void *hdr; /* saved hdr pos in mbuf, for ECN */
+ u_int rtableid; /* alternate routing table id */
+ u_int32_t qid; /* queue id */
+ u_int16_t tag; /* tag id */
+ u_int8_t flags;
+ u_int8_t routed;
+ sa_family_t af; /* for ECN */
+};
+
+static __inline struct pf_mtag *pf_find_mtag(struct mbuf *);
+static __inline struct pf_mtag *pf_get_mtag(struct mbuf *);
+
+static __inline struct pf_mtag *
+pf_find_mtag(struct mbuf *m)
+{
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL)
+ return (NULL);
+
+ return ((struct pf_mtag *)(mtag + 1));
+}
+
+static __inline struct pf_mtag *
+pf_get_mtag(struct mbuf *m)
+{
+ struct m_tag *mtag;
+
+ if ((mtag = m_tag_find(m, PACKET_TAG_PF, NULL)) == NULL) {
+ mtag = m_tag_get(PACKET_TAG_PF, sizeof(struct pf_mtag),
+ M_NOWAIT);
+ if (mtag == NULL)
+ return (NULL);
+ bzero(mtag + 1, sizeof(struct pf_mtag));
+ m_tag_prepend(m, mtag);
+ }
+
+ return ((struct pf_mtag *)(mtag + 1));
+}
+#endif /* _KERNEL */
+#endif /* _NET_PF_MTAG_HH_ */
diff --git a/freebsd/sys/contrib/pf/net/pf_norm.c b/freebsd/sys/contrib/pf/net/pf_norm.c
new file mode 100644
index 00000000..ea68ab50
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_norm.c
@@ -0,0 +1,2062 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: pf_norm.c,v 1.107 2006/04/16 00:59:52 pascoe Exp $ */
+
+/*
+ * Copyright 2001 Niels Provos <provos@citi.umich.edu>
+ * 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.
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+#include <freebsd/local/opt_pf.h>
+
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef DEV_PFLOG
+#define NPFLOG DEV_PFLOG
+#else
+#define NPFLOG 0
+#endif
+#else
+#include <freebsd/local/pflog.h>
+#endif
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/filio.h>
+#include <freebsd/sys/fcntl.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/time.h>
+#ifndef __FreeBSD__
+#include <freebsd/sys/pool.h>
+
+#include <freebsd/dev/rndvar.h>
+#endif
+#include <freebsd/net/if.h>
+#include <freebsd/net/if_types.h>
+#include <freebsd/net/bpf.h>
+#include <freebsd/net/route.h>
+#include <freebsd/net/if_pflog.h>
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_var.h>
+#include <freebsd/netinet/tcp.h>
+#include <freebsd/netinet/tcp_seq.h>
+#include <freebsd/netinet/udp.h>
+#include <freebsd/netinet/ip_icmp.h>
+
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#endif /* INET6 */
+
+#include <freebsd/net/pfvar.h>
+
+#ifndef __FreeBSD__
+#include <freebsd/inttypes.h>
+
+struct pf_frent {
+ LIST_ENTRY(pf_frent) fr_next;
+ struct ip *fr_ip;
+ struct mbuf *fr_m;
+};
+
+struct pf_frcache {
+ LIST_ENTRY(pf_frcache) fr_next;
+ uint16_t fr_off;
+ uint16_t fr_end;
+};
+#endif
+
+#define PFFRAG_SEENLAST 0x0001 /* Seen the last fragment for this */
+#define PFFRAG_NOBUFFER 0x0002 /* Non-buffering fragment cache */
+#define PFFRAG_DROP 0x0004 /* Drop all fragments */
+#define BUFFER_FRAGMENTS(fr) (!((fr)->fr_flags & PFFRAG_NOBUFFER))
+
+#ifndef __FreeBSD__
+struct pf_fragment {
+ RB_ENTRY(pf_fragment) fr_entry;
+ TAILQ_ENTRY(pf_fragment) frag_next;
+ struct in_addr fr_src;
+ struct in_addr fr_dst;
+ u_int8_t fr_p; /* protocol of this fragment */
+ u_int8_t fr_flags; /* status flags */
+ u_int16_t fr_id; /* fragment id for reassemble */
+ u_int16_t fr_max; /* fragment data max */
+ u_int32_t fr_timeout;
+#define fr_queue fr_u.fru_queue
+#define fr_cache fr_u.fru_cache
+ union {
+ LIST_HEAD(pf_fragq, pf_frent) fru_queue; /* buffering */
+ LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */
+ } fr_u;
+};
+#endif
+
+TAILQ_HEAD(pf_fragqueue, pf_fragment) pf_fragqueue;
+TAILQ_HEAD(pf_cachequeue, pf_fragment) pf_cachequeue;
+
+#ifndef __FreeBSD__
+static __inline int pf_frag_compare(struct pf_fragment *,
+ struct pf_fragment *);
+#else
+static int pf_frag_compare(struct pf_fragment *,
+ struct pf_fragment *);
+#endif
+RB_HEAD(pf_frag_tree, pf_fragment) pf_frag_tree, pf_cache_tree;
+RB_PROTOTYPE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
+RB_GENERATE(pf_frag_tree, pf_fragment, fr_entry, pf_frag_compare);
+
+/* Private prototypes */
+void pf_ip2key(struct pf_fragment *, struct ip *);
+void pf_remove_fragment(struct pf_fragment *);
+void pf_flush_fragments(void);
+void pf_free_fragment(struct pf_fragment *);
+struct pf_fragment *pf_find_fragment(struct ip *, struct pf_frag_tree *);
+struct mbuf *pf_reassemble(struct mbuf **, struct pf_fragment **,
+ struct pf_frent *, int);
+struct mbuf *pf_fragcache(struct mbuf **, struct ip*,
+ struct pf_fragment **, int, int, int *);
+int pf_normalize_tcpopt(struct pf_rule *, struct mbuf *,
+ struct tcphdr *, int);
+
+#define DPFPRINTF(x) do { \
+ if (pf_status.debug >= PF_DEBUG_MISC) { \
+ printf("%s: ", __func__); \
+ printf x ; \
+ } \
+} while(0)
+
+/* Globals */
+#ifdef __FreeBSD__
+uma_zone_t pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
+uma_zone_t pf_state_scrub_pl;
+#else
+struct pool pf_frent_pl, pf_frag_pl, pf_cache_pl, pf_cent_pl;
+struct pool pf_state_scrub_pl;
+#endif
+int pf_nfrents, pf_ncache;
+
+void
+pf_normalize_init(void)
+{
+#ifdef __FreeBSD__
+ /*
+ * XXX
+ * No high water mark support(It's hint not hard limit).
+ * uma_zone_set_max(pf_frag_pl, PFFRAG_FRAG_HIWAT);
+ */
+ uma_zone_set_max(pf_frent_pl, PFFRAG_FRENT_HIWAT);
+ uma_zone_set_max(pf_cache_pl, PFFRAG_FRCACHE_HIWAT);
+ uma_zone_set_max(pf_cent_pl, PFFRAG_FRCENT_HIWAT);
+#else
+ pool_init(&pf_frent_pl, sizeof(struct pf_frent), 0, 0, 0, "pffrent",
+ NULL);
+ pool_init(&pf_frag_pl, sizeof(struct pf_fragment), 0, 0, 0, "pffrag",
+ NULL);
+ pool_init(&pf_cache_pl, sizeof(struct pf_fragment), 0, 0, 0,
+ "pffrcache", NULL);
+ pool_init(&pf_cent_pl, sizeof(struct pf_frcache), 0, 0, 0, "pffrcent",
+ NULL);
+ pool_init(&pf_state_scrub_pl, sizeof(struct pf_state_scrub), 0, 0, 0,
+ "pfstscr", NULL);
+
+ pool_sethiwat(&pf_frag_pl, PFFRAG_FRAG_HIWAT);
+ pool_sethardlimit(&pf_frent_pl, PFFRAG_FRENT_HIWAT, NULL, 0);
+ pool_sethardlimit(&pf_cache_pl, PFFRAG_FRCACHE_HIWAT, NULL, 0);
+ pool_sethardlimit(&pf_cent_pl, PFFRAG_FRCENT_HIWAT, NULL, 0);
+#endif
+
+ TAILQ_INIT(&pf_fragqueue);
+ TAILQ_INIT(&pf_cachequeue);
+}
+
+#ifdef __FreeBSD__
+static int
+#else
+static __inline int
+#endif
+pf_frag_compare(struct pf_fragment *a, struct pf_fragment *b)
+{
+ int diff;
+
+ if ((diff = a->fr_id - b->fr_id))
+ return (diff);
+ else if ((diff = a->fr_p - b->fr_p))
+ return (diff);
+ else if (a->fr_src.s_addr < b->fr_src.s_addr)
+ return (-1);
+ else if (a->fr_src.s_addr > b->fr_src.s_addr)
+ return (1);
+ else if (a->fr_dst.s_addr < b->fr_dst.s_addr)
+ return (-1);
+ else if (a->fr_dst.s_addr > b->fr_dst.s_addr)
+ return (1);
+ return (0);
+}
+
+void
+pf_purge_expired_fragments(void)
+{
+ struct pf_fragment *frag;
+ u_int32_t expire = time_second -
+ pf_default_rule.timeout[PFTM_FRAG];
+
+ while ((frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue)) != NULL) {
+#ifdef __FreeBSD__
+ KASSERT((BUFFER_FRAGMENTS(frag)),
+ ("BUFFER_FRAGMENTS(frag) == 0: %s", __FUNCTION__));
+#else
+ KASSERT(BUFFER_FRAGMENTS(frag));
+#endif
+ if (frag->fr_timeout > expire)
+ break;
+
+ DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
+ pf_free_fragment(frag);
+ }
+
+ while ((frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue)) != NULL) {
+#ifdef __FreeBSD__
+ KASSERT((!BUFFER_FRAGMENTS(frag)),
+ ("BUFFER_FRAGMENTS(frag) != 0: %s", __FUNCTION__));
+#else
+ KASSERT(!BUFFER_FRAGMENTS(frag));
+#endif
+ if (frag->fr_timeout > expire)
+ break;
+
+ DPFPRINTF(("expiring %d(%p)\n", frag->fr_id, frag));
+ pf_free_fragment(frag);
+#ifdef __FreeBSD__
+ KASSERT((TAILQ_EMPTY(&pf_cachequeue) ||
+ TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag),
+ ("!(TAILQ_EMPTY() || TAILQ_LAST() == farg): %s",
+ __FUNCTION__));
+#else
+ KASSERT(TAILQ_EMPTY(&pf_cachequeue) ||
+ TAILQ_LAST(&pf_cachequeue, pf_cachequeue) != frag);
+#endif
+ }
+}
+
+/*
+ * Try to flush old fragments to make space for new ones
+ */
+
+void
+pf_flush_fragments(void)
+{
+ struct pf_fragment *frag;
+ int goal;
+
+ goal = pf_nfrents * 9 / 10;
+ DPFPRINTF(("trying to free > %d frents\n",
+ pf_nfrents - goal));
+ while (goal < pf_nfrents) {
+ frag = TAILQ_LAST(&pf_fragqueue, pf_fragqueue);
+ if (frag == NULL)
+ break;
+ pf_free_fragment(frag);
+ }
+
+
+ goal = pf_ncache * 9 / 10;
+ DPFPRINTF(("trying to free > %d cache entries\n",
+ pf_ncache - goal));
+ while (goal < pf_ncache) {
+ frag = TAILQ_LAST(&pf_cachequeue, pf_cachequeue);
+ if (frag == NULL)
+ break;
+ pf_free_fragment(frag);
+ }
+}
+
+/* Frees the fragments and all associated entries */
+
+void
+pf_free_fragment(struct pf_fragment *frag)
+{
+ struct pf_frent *frent;
+ struct pf_frcache *frcache;
+
+ /* Free all fragments */
+ if (BUFFER_FRAGMENTS(frag)) {
+ for (frent = LIST_FIRST(&frag->fr_queue); frent;
+ frent = LIST_FIRST(&frag->fr_queue)) {
+ LIST_REMOVE(frent, fr_next);
+
+ m_freem(frent->fr_m);
+ pool_put(&pf_frent_pl, frent);
+ pf_nfrents--;
+ }
+ } else {
+ for (frcache = LIST_FIRST(&frag->fr_cache); frcache;
+ frcache = LIST_FIRST(&frag->fr_cache)) {
+ LIST_REMOVE(frcache, fr_next);
+
+#ifdef __FreeBSD__
+ KASSERT((LIST_EMPTY(&frag->fr_cache) ||
+ LIST_FIRST(&frag->fr_cache)->fr_off >
+ frcache->fr_end),
+ ("! (LIST_EMPTY() || LIST_FIRST()->fr_off >"
+ " frcache->fr_end): %s", __FUNCTION__));
+#else
+ KASSERT(LIST_EMPTY(&frag->fr_cache) ||
+ LIST_FIRST(&frag->fr_cache)->fr_off >
+ frcache->fr_end);
+#endif
+
+ pool_put(&pf_cent_pl, frcache);
+ pf_ncache--;
+ }
+ }
+
+ pf_remove_fragment(frag);
+}
+
+void
+pf_ip2key(struct pf_fragment *key, struct ip *ip)
+{
+ key->fr_p = ip->ip_p;
+ key->fr_id = ip->ip_id;
+ key->fr_src.s_addr = ip->ip_src.s_addr;
+ key->fr_dst.s_addr = ip->ip_dst.s_addr;
+}
+
+struct pf_fragment *
+pf_find_fragment(struct ip *ip, struct pf_frag_tree *tree)
+{
+ struct pf_fragment key;
+ struct pf_fragment *frag;
+
+ pf_ip2key(&key, ip);
+
+ frag = RB_FIND(pf_frag_tree, tree, &key);
+ if (frag != NULL) {
+ /* XXX Are we sure we want to update the timeout? */
+ frag->fr_timeout = time_second;
+ if (BUFFER_FRAGMENTS(frag)) {
+ TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
+ TAILQ_INSERT_HEAD(&pf_fragqueue, frag, frag_next);
+ } else {
+ TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
+ TAILQ_INSERT_HEAD(&pf_cachequeue, frag, frag_next);
+ }
+ }
+
+ return (frag);
+}
+
+/* Removes a fragment from the fragment queue and frees the fragment */
+
+void
+pf_remove_fragment(struct pf_fragment *frag)
+{
+ if (BUFFER_FRAGMENTS(frag)) {
+ RB_REMOVE(pf_frag_tree, &pf_frag_tree, frag);
+ TAILQ_REMOVE(&pf_fragqueue, frag, frag_next);
+ pool_put(&pf_frag_pl, frag);
+ } else {
+ RB_REMOVE(pf_frag_tree, &pf_cache_tree, frag);
+ TAILQ_REMOVE(&pf_cachequeue, frag, frag_next);
+ pool_put(&pf_cache_pl, frag);
+ }
+}
+
+#define FR_IP_OFF(fr) ((ntohs((fr)->fr_ip->ip_off) & IP_OFFMASK) << 3)
+struct mbuf *
+pf_reassemble(struct mbuf **m0, struct pf_fragment **frag,
+ struct pf_frent *frent, int mff)
+{
+ struct mbuf *m = *m0, *m2;
+ struct pf_frent *frea, *next;
+ struct pf_frent *frep = NULL;
+ struct ip *ip = frent->fr_ip;
+ int hlen = ip->ip_hl << 2;
+ u_int16_t off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
+ u_int16_t ip_len = ntohs(ip->ip_len) - ip->ip_hl * 4;
+ u_int16_t max = ip_len + off;
+
+#ifdef __FreeBSD__
+ KASSERT((*frag == NULL || BUFFER_FRAGMENTS(*frag)),
+ ("! (*frag == NULL || BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
+#else
+ KASSERT(*frag == NULL || BUFFER_FRAGMENTS(*frag));
+#endif
+
+ /* Strip off ip header */
+ m->m_data += hlen;
+ m->m_len -= hlen;
+
+ /* Create a new reassembly queue for this packet */
+ if (*frag == NULL) {
+ *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+ if (*frag == NULL) {
+ pf_flush_fragments();
+ *frag = pool_get(&pf_frag_pl, PR_NOWAIT);
+ if (*frag == NULL)
+ goto drop_fragment;
+ }
+
+ (*frag)->fr_flags = 0;
+ (*frag)->fr_max = 0;
+ (*frag)->fr_src = frent->fr_ip->ip_src;
+ (*frag)->fr_dst = frent->fr_ip->ip_dst;
+ (*frag)->fr_p = frent->fr_ip->ip_p;
+ (*frag)->fr_id = frent->fr_ip->ip_id;
+ (*frag)->fr_timeout = time_second;
+ LIST_INIT(&(*frag)->fr_queue);
+
+ RB_INSERT(pf_frag_tree, &pf_frag_tree, *frag);
+ TAILQ_INSERT_HEAD(&pf_fragqueue, *frag, frag_next);
+
+ /* We do not have a previous fragment */
+ frep = NULL;
+ goto insert;
+ }
+
+ /*
+ * Find a fragment after the current one:
+ * - off contains the real shifted offset.
+ */
+ LIST_FOREACH(frea, &(*frag)->fr_queue, fr_next) {
+ if (FR_IP_OFF(frea) > off)
+ break;
+ frep = frea;
+ }
+
+#ifdef __FreeBSD__
+ KASSERT((frep != NULL || frea != NULL),
+ ("!(frep != NULL || frea != NULL): %s", __FUNCTION__));;
+#else
+ KASSERT(frep != NULL || frea != NULL);
+#endif
+
+ if (frep != NULL &&
+ FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl *
+ 4 > off)
+ {
+ u_int16_t precut;
+
+ precut = FR_IP_OFF(frep) + ntohs(frep->fr_ip->ip_len) -
+ frep->fr_ip->ip_hl * 4 - off;
+ if (precut >= ip_len)
+ goto drop_fragment;
+ m_adj(frent->fr_m, precut);
+ DPFPRINTF(("overlap -%d\n", precut));
+ /* Enforce 8 byte boundaries */
+ ip->ip_off = htons(ntohs(ip->ip_off) + (precut >> 3));
+ off = (ntohs(ip->ip_off) & IP_OFFMASK) << 3;
+ ip_len -= precut;
+ ip->ip_len = htons(ip_len);
+ }
+
+ for (; frea != NULL && ip_len + off > FR_IP_OFF(frea);
+ frea = next)
+ {
+ u_int16_t aftercut;
+
+ aftercut = ip_len + off - FR_IP_OFF(frea);
+ DPFPRINTF(("adjust overlap %d\n", aftercut));
+ if (aftercut < ntohs(frea->fr_ip->ip_len) - frea->fr_ip->ip_hl
+ * 4)
+ {
+ frea->fr_ip->ip_len =
+ htons(ntohs(frea->fr_ip->ip_len) - aftercut);
+ frea->fr_ip->ip_off = htons(ntohs(frea->fr_ip->ip_off) +
+ (aftercut >> 3));
+ m_adj(frea->fr_m, aftercut);
+ break;
+ }
+
+ /* This fragment is completely overlapped, lose it */
+ next = LIST_NEXT(frea, fr_next);
+ m_freem(frea->fr_m);
+ LIST_REMOVE(frea, fr_next);
+ pool_put(&pf_frent_pl, frea);
+ pf_nfrents--;
+ }
+
+ insert:
+ /* Update maximum data size */
+ if ((*frag)->fr_max < max)
+ (*frag)->fr_max = max;
+ /* This is the last segment */
+ if (!mff)
+ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ if (frep == NULL)
+ LIST_INSERT_HEAD(&(*frag)->fr_queue, frent, fr_next);
+ else
+ LIST_INSERT_AFTER(frep, frent, fr_next);
+
+ /* Check if we are completely reassembled */
+ if (!((*frag)->fr_flags & PFFRAG_SEENLAST))
+ return (NULL);
+
+ /* Check if we have all the data */
+ off = 0;
+ for (frep = LIST_FIRST(&(*frag)->fr_queue); frep; frep = next) {
+ next = LIST_NEXT(frep, fr_next);
+
+ off += ntohs(frep->fr_ip->ip_len) - frep->fr_ip->ip_hl * 4;
+ if (off < (*frag)->fr_max &&
+ (next == NULL || FR_IP_OFF(next) != off))
+ {
+ DPFPRINTF(("missing fragment at %d, next %d, max %d\n",
+ off, next == NULL ? -1 : FR_IP_OFF(next),
+ (*frag)->fr_max));
+ return (NULL);
+ }
+ }
+ DPFPRINTF(("%d < %d?\n", off, (*frag)->fr_max));
+ if (off < (*frag)->fr_max)
+ return (NULL);
+
+ /* We have all the data */
+ frent = LIST_FIRST(&(*frag)->fr_queue);
+#ifdef __FreeBSD__
+ KASSERT((frent != NULL), ("frent == NULL: %s", __FUNCTION__));
+#else
+ KASSERT(frent != NULL);
+#endif
+ if ((frent->fr_ip->ip_hl << 2) + off > IP_MAXPACKET) {
+ DPFPRINTF(("drop: too big: %d\n", off));
+ pf_free_fragment(*frag);
+ *frag = NULL;
+ return (NULL);
+ }
+ next = LIST_NEXT(frent, fr_next);
+
+ /* Magic from ip_input */
+ ip = frent->fr_ip;
+ m = frent->fr_m;
+ m2 = m->m_next;
+ m->m_next = NULL;
+ m_cat(m, m2);
+ pool_put(&pf_frent_pl, frent);
+ pf_nfrents--;
+ for (frent = next; frent != NULL; frent = next) {
+ next = LIST_NEXT(frent, fr_next);
+
+ m2 = frent->fr_m;
+ pool_put(&pf_frent_pl, frent);
+ pf_nfrents--;
+#ifdef __FreeBSD__
+ m->m_pkthdr.csum_flags &= m2->m_pkthdr.csum_flags;
+ m->m_pkthdr.csum_data += m2->m_pkthdr.csum_data;
+#endif
+ m_cat(m, m2);
+ }
+#ifdef __FreeBSD__
+ while (m->m_pkthdr.csum_data & 0xffff0000)
+ m->m_pkthdr.csum_data = (m->m_pkthdr.csum_data & 0xffff) +
+ (m->m_pkthdr.csum_data >> 16);
+#endif
+
+ ip->ip_src = (*frag)->fr_src;
+ ip->ip_dst = (*frag)->fr_dst;
+
+ /* Remove from fragment queue */
+ pf_remove_fragment(*frag);
+ *frag = NULL;
+
+ hlen = ip->ip_hl << 2;
+ ip->ip_len = htons(off + hlen);
+ m->m_len += hlen;
+ m->m_data -= hlen;
+
+ /* some debugging cruft by sklower, below, will go away soon */
+ /* XXX this should be done elsewhere */
+ if (m->m_flags & M_PKTHDR) {
+ int plen = 0;
+ for (m2 = m; m2; m2 = m2->m_next)
+ plen += m2->m_len;
+ m->m_pkthdr.len = plen;
+ }
+
+ DPFPRINTF(("complete: %p(%d)\n", m, ntohs(ip->ip_len)));
+ return (m);
+
+ drop_fragment:
+ /* Oops - fail safe - drop packet */
+ pool_put(&pf_frent_pl, frent);
+ pf_nfrents--;
+ m_freem(m);
+ return (NULL);
+}
+
+struct mbuf *
+pf_fragcache(struct mbuf **m0, struct ip *h, struct pf_fragment **frag, int mff,
+ int drop, int *nomem)
+{
+ struct mbuf *m = *m0;
+ struct pf_frcache *frp, *fra, *cur = NULL;
+ int ip_len = ntohs(h->ip_len) - (h->ip_hl << 2);
+ u_int16_t off = ntohs(h->ip_off) << 3;
+ u_int16_t max = ip_len + off;
+ int hosed = 0;
+
+#ifdef __FreeBSD__
+ KASSERT((*frag == NULL || !BUFFER_FRAGMENTS(*frag)),
+ ("!(*frag == NULL || !BUFFER_FRAGMENTS(*frag)): %s", __FUNCTION__));
+#else
+ KASSERT(*frag == NULL || !BUFFER_FRAGMENTS(*frag));
+#endif
+
+ /* Create a new range queue for this packet */
+ if (*frag == NULL) {
+ *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+ if (*frag == NULL) {
+ pf_flush_fragments();
+ *frag = pool_get(&pf_cache_pl, PR_NOWAIT);
+ if (*frag == NULL)
+ goto no_mem;
+ }
+
+ /* Get an entry for the queue */
+ cur = pool_get(&pf_cent_pl, PR_NOWAIT);
+ if (cur == NULL) {
+ pool_put(&pf_cache_pl, *frag);
+ *frag = NULL;
+ goto no_mem;
+ }
+ pf_ncache++;
+
+ (*frag)->fr_flags = PFFRAG_NOBUFFER;
+ (*frag)->fr_max = 0;
+ (*frag)->fr_src = h->ip_src;
+ (*frag)->fr_dst = h->ip_dst;
+ (*frag)->fr_p = h->ip_p;
+ (*frag)->fr_id = h->ip_id;
+ (*frag)->fr_timeout = time_second;
+
+ cur->fr_off = off;
+ cur->fr_end = max;
+ LIST_INIT(&(*frag)->fr_cache);
+ LIST_INSERT_HEAD(&(*frag)->fr_cache, cur, fr_next);
+
+ RB_INSERT(pf_frag_tree, &pf_cache_tree, *frag);
+ TAILQ_INSERT_HEAD(&pf_cachequeue, *frag, frag_next);
+
+ DPFPRINTF(("fragcache[%d]: new %d-%d\n", h->ip_id, off, max));
+
+ goto pass;
+ }
+
+ /*
+ * Find a fragment after the current one:
+ * - off contains the real shifted offset.
+ */
+ frp = NULL;
+ LIST_FOREACH(fra, &(*frag)->fr_cache, fr_next) {
+ if (fra->fr_off > off)
+ break;
+ frp = fra;
+ }
+
+#ifdef __FreeBSD__
+ KASSERT((frp != NULL || fra != NULL),
+ ("!(frp != NULL || fra != NULL): %s", __FUNCTION__));
+#else
+ KASSERT(frp != NULL || fra != NULL);
+#endif
+
+ if (frp != NULL) {
+ int precut;
+
+ precut = frp->fr_end - off;
+ if (precut >= ip_len) {
+ /* Fragment is entirely a duplicate */
+ DPFPRINTF(("fragcache[%d]: dead (%d-%d) %d-%d\n",
+ h->ip_id, frp->fr_off, frp->fr_end, off, max));
+ goto drop_fragment;
+ }
+ if (precut == 0) {
+ /* They are adjacent. Fixup cache entry */
+ DPFPRINTF(("fragcache[%d]: adjacent (%d-%d) %d-%d\n",
+ h->ip_id, frp->fr_off, frp->fr_end, off, max));
+ frp->fr_end = max;
+ } else if (precut > 0) {
+ /* The first part of this payload overlaps with a
+ * fragment that has already been passed.
+ * Need to trim off the first part of the payload.
+ * But to do so easily, we need to create another
+ * mbuf to throw the original header into.
+ */
+
+ DPFPRINTF(("fragcache[%d]: chop %d (%d-%d) %d-%d\n",
+ h->ip_id, precut, frp->fr_off, frp->fr_end, off,
+ max));
+
+ off += precut;
+ max -= precut;
+ /* Update the previous frag to encompass this one */
+ frp->fr_end = max;
+
+ if (!drop) {
+ /* XXX Optimization opportunity
+ * This is a very heavy way to trim the payload.
+ * we could do it much faster by diddling mbuf
+ * internals but that would be even less legible
+ * than this mbuf magic. For my next trick,
+ * I'll pull a rabbit out of my laptop.
+ */
+#ifdef __FreeBSD__
+ *m0 = m_dup(m, M_DONTWAIT);
+#else
+ *m0 = m_copym2(m, 0, h->ip_hl << 2, M_NOWAIT);
+#endif
+ if (*m0 == NULL)
+ goto no_mem;
+#ifdef __FreeBSD__
+ /* From KAME Project : We have missed this! */
+ m_adj(*m0, (h->ip_hl << 2) -
+ (*m0)->m_pkthdr.len);
+
+ KASSERT(((*m0)->m_next == NULL),
+ ("(*m0)->m_next != NULL: %s",
+ __FUNCTION__));
+#else
+ KASSERT((*m0)->m_next == NULL);
+#endif
+ m_adj(m, precut + (h->ip_hl << 2));
+ m_cat(*m0, m);
+ m = *m0;
+ if (m->m_flags & M_PKTHDR) {
+ int plen = 0;
+ struct mbuf *t;
+ for (t = m; t; t = t->m_next)
+ plen += t->m_len;
+ m->m_pkthdr.len = plen;
+ }
+
+
+ h = mtod(m, struct ip *);
+
+#ifdef __FreeBSD__
+ KASSERT(((int)m->m_len ==
+ ntohs(h->ip_len) - precut),
+ ("m->m_len != ntohs(h->ip_len) - precut: %s",
+ __FUNCTION__));
+#else
+ KASSERT((int)m->m_len ==
+ ntohs(h->ip_len) - precut);
+#endif
+ h->ip_off = htons(ntohs(h->ip_off) +
+ (precut >> 3));
+ h->ip_len = htons(ntohs(h->ip_len) - precut);
+ } else {
+ hosed++;
+ }
+ } else {
+ /* There is a gap between fragments */
+
+ DPFPRINTF(("fragcache[%d]: gap %d (%d-%d) %d-%d\n",
+ h->ip_id, -precut, frp->fr_off, frp->fr_end, off,
+ max));
+
+ cur = pool_get(&pf_cent_pl, PR_NOWAIT);
+ if (cur == NULL)
+ goto no_mem;
+ pf_ncache++;
+
+ cur->fr_off = off;
+ cur->fr_end = max;
+ LIST_INSERT_AFTER(frp, cur, fr_next);
+ }
+ }
+
+ if (fra != NULL) {
+ int aftercut;
+ int merge = 0;
+
+ aftercut = max - fra->fr_off;
+ if (aftercut == 0) {
+ /* Adjacent fragments */
+ DPFPRINTF(("fragcache[%d]: adjacent %d-%d (%d-%d)\n",
+ h->ip_id, off, max, fra->fr_off, fra->fr_end));
+ fra->fr_off = off;
+ merge = 1;
+ } else if (aftercut > 0) {
+ /* Need to chop off the tail of this fragment */
+ DPFPRINTF(("fragcache[%d]: chop %d %d-%d (%d-%d)\n",
+ h->ip_id, aftercut, off, max, fra->fr_off,
+ fra->fr_end));
+ fra->fr_off = off;
+ max -= aftercut;
+
+ merge = 1;
+
+ if (!drop) {
+ m_adj(m, -aftercut);
+ if (m->m_flags & M_PKTHDR) {
+ int plen = 0;
+ struct mbuf *t;
+ for (t = m; t; t = t->m_next)
+ plen += t->m_len;
+ m->m_pkthdr.len = plen;
+ }
+ h = mtod(m, struct ip *);
+#ifdef __FreeBSD__
+ KASSERT(((int)m->m_len == ntohs(h->ip_len) - aftercut),
+ ("m->m_len != ntohs(h->ip_len) - aftercut: %s",
+ __FUNCTION__));
+#else
+ KASSERT((int)m->m_len ==
+ ntohs(h->ip_len) - aftercut);
+#endif
+ h->ip_len = htons(ntohs(h->ip_len) - aftercut);
+ } else {
+ hosed++;
+ }
+ } else if (frp == NULL) {
+ /* There is a gap between fragments */
+ DPFPRINTF(("fragcache[%d]: gap %d %d-%d (%d-%d)\n",
+ h->ip_id, -aftercut, off, max, fra->fr_off,
+ fra->fr_end));
+
+ cur = pool_get(&pf_cent_pl, PR_NOWAIT);
+ if (cur == NULL)
+ goto no_mem;
+ pf_ncache++;
+
+ cur->fr_off = off;
+ cur->fr_end = max;
+ LIST_INSERT_BEFORE(fra, cur, fr_next);
+ }
+
+
+ /* Need to glue together two separate fragment descriptors */
+ if (merge) {
+ if (cur && fra->fr_off <= cur->fr_end) {
+ /* Need to merge in a previous 'cur' */
+ DPFPRINTF(("fragcache[%d]: adjacent(merge "
+ "%d-%d) %d-%d (%d-%d)\n",
+ h->ip_id, cur->fr_off, cur->fr_end, off,
+ max, fra->fr_off, fra->fr_end));
+ fra->fr_off = cur->fr_off;
+ LIST_REMOVE(cur, fr_next);
+ pool_put(&pf_cent_pl, cur);
+ pf_ncache--;
+ cur = NULL;
+
+ } else if (frp && fra->fr_off <= frp->fr_end) {
+ /* Need to merge in a modified 'frp' */
+#ifdef __FreeBSD__
+ KASSERT((cur == NULL), ("cur != NULL: %s",
+ __FUNCTION__));
+#else
+ KASSERT(cur == NULL);
+#endif
+ DPFPRINTF(("fragcache[%d]: adjacent(merge "
+ "%d-%d) %d-%d (%d-%d)\n",
+ h->ip_id, frp->fr_off, frp->fr_end, off,
+ max, fra->fr_off, fra->fr_end));
+ fra->fr_off = frp->fr_off;
+ LIST_REMOVE(frp, fr_next);
+ pool_put(&pf_cent_pl, frp);
+ pf_ncache--;
+ frp = NULL;
+
+ }
+ }
+ }
+
+ if (hosed) {
+ /*
+ * We must keep tracking the overall fragment even when
+ * we're going to drop it anyway so that we know when to
+ * free the overall descriptor. Thus we drop the frag late.
+ */
+ goto drop_fragment;
+ }
+
+
+ pass:
+ /* Update maximum data size */
+ if ((*frag)->fr_max < max)
+ (*frag)->fr_max = max;
+
+ /* This is the last segment */
+ if (!mff)
+ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ /* Check if we are completely reassembled */
+ if (((*frag)->fr_flags & PFFRAG_SEENLAST) &&
+ LIST_FIRST(&(*frag)->fr_cache)->fr_off == 0 &&
+ LIST_FIRST(&(*frag)->fr_cache)->fr_end == (*frag)->fr_max) {
+ /* Remove from fragment queue */
+ DPFPRINTF(("fragcache[%d]: done 0-%d\n", h->ip_id,
+ (*frag)->fr_max));
+ pf_free_fragment(*frag);
+ *frag = NULL;
+ }
+
+ return (m);
+
+ no_mem:
+ *nomem = 1;
+
+ /* Still need to pay attention to !IP_MF */
+ if (!mff && *frag != NULL)
+ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ m_freem(m);
+ return (NULL);
+
+ drop_fragment:
+
+ /* Still need to pay attention to !IP_MF */
+ if (!mff && *frag != NULL)
+ (*frag)->fr_flags |= PFFRAG_SEENLAST;
+
+ if (drop) {
+ /* This fragment has been deemed bad. Don't reass */
+ if (((*frag)->fr_flags & PFFRAG_DROP) == 0)
+ DPFPRINTF(("fragcache[%d]: dropping overall fragment\n",
+ h->ip_id));
+ (*frag)->fr_flags |= PFFRAG_DROP;
+ }
+
+ m_freem(m);
+ return (NULL);
+}
+
+int
+pf_normalize_ip(struct mbuf **m0, int dir, struct pfi_kif *kif, u_short *reason,
+ struct pf_pdesc *pd)
+{
+ struct mbuf *m = *m0;
+ struct pf_rule *r;
+ struct pf_frent *frent;
+ struct pf_fragment *frag = NULL;
+ struct ip *h = mtod(m, struct ip *);
+ int mff = (ntohs(h->ip_off) & IP_MF);
+ int hlen = h->ip_hl << 2;
+ u_int16_t fragoff = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
+ u_int16_t max;
+ int ip_len;
+ int ip_off;
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != dir)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != AF_INET)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != h->ip_p)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&r->src.addr,
+ (struct pf_addr *)&h->ip_src.s_addr, AF_INET,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr,
+ (struct pf_addr *)&h->ip_dst.s_addr, AF_INET,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else
+ break;
+ }
+
+ if (r == NULL || r->action == PF_NOSCRUB)
+ return (PF_PASS);
+ else {
+ r->packets[dir == PF_OUT]++;
+ r->bytes[dir == PF_OUT] += pd->tot_len;
+ }
+
+ /* Check for illegal packets */
+ if (hlen < (int)sizeof(struct ip))
+ goto drop;
+
+ if (hlen > ntohs(h->ip_len))
+ goto drop;
+
+ /* Clear IP_DF if the rule uses the no-df option */
+ if (r->rule_flag & PFRULE_NODF && h->ip_off & htons(IP_DF)) {
+ u_int16_t ip_off = h->ip_off;
+
+ h->ip_off &= htons(~IP_DF);
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
+ }
+
+ /* We will need other tests here */
+ if (!fragoff && !mff)
+ goto no_fragment;
+
+ /* We're dealing with a fragment now. Don't allow fragments
+ * with IP_DF to enter the cache. If the flag was cleared by
+ * no-df above, fine. Otherwise drop it.
+ */
+ if (h->ip_off & htons(IP_DF)) {
+ DPFPRINTF(("IP_DF\n"));
+ goto bad;
+ }
+
+ ip_len = ntohs(h->ip_len) - hlen;
+ ip_off = (ntohs(h->ip_off) & IP_OFFMASK) << 3;
+
+ /* All fragments are 8 byte aligned */
+ if (mff && (ip_len & 0x7)) {
+ DPFPRINTF(("mff and %d\n", ip_len));
+ goto bad;
+ }
+
+ /* Respect maximum length */
+ if (fragoff + ip_len > IP_MAXPACKET) {
+ DPFPRINTF(("max packet %d\n", fragoff + ip_len));
+ goto bad;
+ }
+ max = fragoff + ip_len;
+
+ if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0) {
+ /* Fully buffer all of the fragments */
+
+ frag = pf_find_fragment(h, &pf_frag_tree);
+
+ /* Check if we saw the last fragment already */
+ if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
+ max > frag->fr_max)
+ goto bad;
+
+ /* Get an entry for the fragment queue */
+ frent = pool_get(&pf_frent_pl, PR_NOWAIT);
+ if (frent == NULL) {
+ REASON_SET(reason, PFRES_MEMORY);
+ return (PF_DROP);
+ }
+ pf_nfrents++;
+ frent->fr_ip = h;
+ frent->fr_m = m;
+
+ /* Might return a completely reassembled mbuf, or NULL */
+ DPFPRINTF(("reass frag %d @ %d-%d\n", h->ip_id, fragoff, max));
+ *m0 = m = pf_reassemble(m0, &frag, frent, mff);
+
+ if (m == NULL)
+ return (PF_DROP);
+
+ /* use mtag from concatenated mbuf chain */
+ pd->pf_mtag = pf_find_mtag(m);
+#ifdef DIAGNOSTIC
+ if (pd->pf_mtag == NULL) {
+ printf("%s: pf_find_mtag returned NULL(1)\n", __func__);
+ if ((pd->pf_mtag = pf_get_mtag(m)) == NULL) {
+ m_freem(m);
+ *m0 = NULL;
+ goto no_mem;
+ }
+ }
+#endif
+ if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
+ goto drop;
+
+ h = mtod(m, struct ip *);
+ } else {
+ /* non-buffering fragment cache (drops or masks overlaps) */
+ int nomem = 0;
+
+ if (dir == PF_OUT && pd->pf_mtag->flags & PF_TAG_FRAGCACHE) {
+ /*
+ * Already passed the fragment cache in the
+ * input direction. If we continued, it would
+ * appear to be a dup and would be dropped.
+ */
+ goto fragment_pass;
+ }
+
+ frag = pf_find_fragment(h, &pf_cache_tree);
+
+ /* Check if we saw the last fragment already */
+ if (frag != NULL && (frag->fr_flags & PFFRAG_SEENLAST) &&
+ max > frag->fr_max) {
+ if (r->rule_flag & PFRULE_FRAGDROP)
+ frag->fr_flags |= PFFRAG_DROP;
+ goto bad;
+ }
+
+ *m0 = m = pf_fragcache(m0, h, &frag, mff,
+ (r->rule_flag & PFRULE_FRAGDROP) ? 1 : 0, &nomem);
+ if (m == NULL) {
+ if (nomem)
+ goto no_mem;
+ goto drop;
+ }
+
+ /* use mtag from copied and trimmed mbuf chain */
+ pd->pf_mtag = pf_find_mtag(m);
+#ifdef DIAGNOSTIC
+ if (pd->pf_mtag == NULL) {
+ printf("%s: pf_find_mtag returned NULL(2)\n", __func__);
+ if ((pd->pf_mtag = pf_get_mtag(m)) == NULL) {
+ m_freem(m);
+ *m0 = NULL;
+ goto no_mem;
+ }
+ }
+#endif
+ if (dir == PF_IN)
+ pd->pf_mtag->flags |= PF_TAG_FRAGCACHE;
+
+ if (frag != NULL && (frag->fr_flags & PFFRAG_DROP))
+ goto drop;
+ goto fragment_pass;
+ }
+
+ no_fragment:
+ /* At this point, only IP_DF is allowed in ip_off */
+ if (h->ip_off & ~htons(IP_DF)) {
+ u_int16_t ip_off = h->ip_off;
+
+ h->ip_off &= htons(IP_DF);
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_off, h->ip_off, 0);
+ }
+
+ /* Enforce a minimum ttl, may cause endless packet loops */
+ if (r->min_ttl && h->ip_ttl < r->min_ttl) {
+ u_int16_t ip_ttl = h->ip_ttl;
+
+ h->ip_ttl = r->min_ttl;
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
+ }
+
+ if (r->rule_flag & PFRULE_RANDOMID) {
+ u_int16_t ip_id = h->ip_id;
+
+ h->ip_id = ip_randomid();
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_id, h->ip_id, 0);
+ }
+ if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
+ pd->flags |= PFDESC_IP_REAS;
+
+ return (PF_PASS);
+
+ fragment_pass:
+ /* Enforce a minimum ttl, may cause endless packet loops */
+ if (r->min_ttl && h->ip_ttl < r->min_ttl) {
+ u_int16_t ip_ttl = h->ip_ttl;
+
+ h->ip_ttl = r->min_ttl;
+ h->ip_sum = pf_cksum_fixup(h->ip_sum, ip_ttl, h->ip_ttl, 0);
+ }
+ if ((r->rule_flag & (PFRULE_FRAGCROP|PFRULE_FRAGDROP)) == 0)
+ pd->flags |= PFDESC_IP_REAS;
+ return (PF_PASS);
+
+ no_mem:
+ REASON_SET(reason, PFRES_MEMORY);
+ if (r != NULL && r->log)
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
+ return (PF_DROP);
+
+ drop:
+ REASON_SET(reason, PFRES_NORM);
+ if (r != NULL && r->log)
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
+ return (PF_DROP);
+
+ bad:
+ DPFPRINTF(("dropping bad fragment\n"));
+
+ /* Free associated fragments */
+ if (frag != NULL)
+ pf_free_fragment(frag);
+
+ REASON_SET(reason, PFRES_FRAG);
+ if (r != NULL && r->log)
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, *reason, r, NULL, NULL, pd);
+
+ return (PF_DROP);
+}
+
+#ifdef INET6
+int
+pf_normalize_ip6(struct mbuf **m0, int dir, struct pfi_kif *kif,
+ u_short *reason, struct pf_pdesc *pd)
+{
+ struct mbuf *m = *m0;
+ struct pf_rule *r;
+ struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
+ int off;
+ struct ip6_ext ext;
+ struct ip6_opt opt;
+ struct ip6_opt_jumbo jumbo;
+ struct ip6_frag frag;
+ u_int32_t jumbolen = 0, plen;
+ u_int16_t fragoff = 0;
+ int optend;
+ int ooff;
+ u_int8_t proto;
+ int terminal;
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != dir)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != AF_INET6)
+ r = r->skip[PF_SKIP_AF].ptr;
+#if 0 /* header chain! */
+ else if (r->proto && r->proto != h->ip6_nxt)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+#endif
+ else if (PF_MISMATCHAW(&r->src.addr,
+ (struct pf_addr *)&h->ip6_src, AF_INET6,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr,
+ (struct pf_addr *)&h->ip6_dst, AF_INET6,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else
+ break;
+ }
+
+ if (r == NULL || r->action == PF_NOSCRUB)
+ return (PF_PASS);
+ else {
+ r->packets[dir == PF_OUT]++;
+ r->bytes[dir == PF_OUT] += pd->tot_len;
+ }
+
+ /* Check for illegal packets */
+ if (sizeof(struct ip6_hdr) + IPV6_MAXPACKET < m->m_pkthdr.len)
+ goto drop;
+
+ off = sizeof(struct ip6_hdr);
+ proto = h->ip6_nxt;
+ terminal = 0;
+ do {
+ switch (proto) {
+ case IPPROTO_FRAGMENT:
+ goto fragment;
+ break;
+ case IPPROTO_AH:
+ case IPPROTO_ROUTING:
+ case IPPROTO_DSTOPTS:
+ if (!pf_pull_hdr(m, off, &ext, sizeof(ext), NULL,
+ NULL, AF_INET6))
+ goto shortpkt;
+ if (proto == IPPROTO_AH)
+ off += (ext.ip6e_len + 2) * 4;
+ else
+ off += (ext.ip6e_len + 1) * 8;
+ proto = ext.ip6e_nxt;
+ break;
+ case IPPROTO_HOPOPTS:
+ if (!pf_pull_hdr(m, off, &ext, sizeof(ext), NULL,
+ NULL, AF_INET6))
+ goto shortpkt;
+ optend = off + (ext.ip6e_len + 1) * 8;
+ ooff = off + sizeof(ext);
+ do {
+ if (!pf_pull_hdr(m, ooff, &opt.ip6o_type,
+ sizeof(opt.ip6o_type), NULL, NULL,
+ AF_INET6))
+ goto shortpkt;
+ if (opt.ip6o_type == IP6OPT_PAD1) {
+ ooff++;
+ continue;
+ }
+ if (!pf_pull_hdr(m, ooff, &opt, sizeof(opt),
+ NULL, NULL, AF_INET6))
+ goto shortpkt;
+ if (ooff + sizeof(opt) + opt.ip6o_len > optend)
+ goto drop;
+ switch (opt.ip6o_type) {
+ case IP6OPT_JUMBO:
+ if (h->ip6_plen != 0)
+ goto drop;
+ if (!pf_pull_hdr(m, ooff, &jumbo,
+ sizeof(jumbo), NULL, NULL,
+ AF_INET6))
+ goto shortpkt;
+ memcpy(&jumbolen, jumbo.ip6oj_jumbo_len,
+ sizeof(jumbolen));
+ jumbolen = ntohl(jumbolen);
+ if (jumbolen <= IPV6_MAXPACKET)
+ goto drop;
+ if (sizeof(struct ip6_hdr) + jumbolen !=
+ m->m_pkthdr.len)
+ goto drop;
+ break;
+ default:
+ break;
+ }
+ ooff += sizeof(opt) + opt.ip6o_len;
+ } while (ooff < optend);
+
+ off = optend;
+ proto = ext.ip6e_nxt;
+ break;
+ default:
+ terminal = 1;
+ break;
+ }
+ } while (!terminal);
+
+ /* jumbo payload option must be present, or plen > 0 */
+ if (ntohs(h->ip6_plen) == 0)
+ plen = jumbolen;
+ else
+ plen = ntohs(h->ip6_plen);
+ if (plen == 0)
+ goto drop;
+ if (sizeof(struct ip6_hdr) + plen > m->m_pkthdr.len)
+ goto shortpkt;
+
+ /* Enforce a minimum ttl, may cause endless packet loops */
+ if (r->min_ttl && h->ip6_hlim < r->min_ttl)
+ h->ip6_hlim = r->min_ttl;
+
+ return (PF_PASS);
+
+ fragment:
+ if (ntohs(h->ip6_plen) == 0 || jumbolen)
+ goto drop;
+ plen = ntohs(h->ip6_plen);
+
+ if (!pf_pull_hdr(m, off, &frag, sizeof(frag), NULL, NULL, AF_INET6))
+ goto shortpkt;
+ fragoff = ntohs(frag.ip6f_offlg & IP6F_OFF_MASK);
+ if (fragoff + (plen - off - sizeof(frag)) > IPV6_MAXPACKET)
+ goto badfrag;
+
+ /* do something about it */
+ /* remember to set pd->flags |= PFDESC_IP_REAS */
+ return (PF_PASS);
+
+ shortpkt:
+ REASON_SET(reason, PFRES_SHORT);
+ if (r != NULL && r->log)
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
+ return (PF_DROP);
+
+ drop:
+ REASON_SET(reason, PFRES_NORM);
+ if (r != NULL && r->log)
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
+ return (PF_DROP);
+
+ badfrag:
+ REASON_SET(reason, PFRES_FRAG);
+ if (r != NULL && r->log)
+ PFLOG_PACKET(kif, h, m, AF_INET6, dir, *reason, r, NULL, NULL, pd);
+ return (PF_DROP);
+}
+#endif /* INET6 */
+
+int
+pf_normalize_tcp(int dir, struct pfi_kif *kif, struct mbuf *m, int ipoff,
+ int off, void *h, struct pf_pdesc *pd)
+{
+ struct pf_rule *r, *rm = NULL;
+ struct tcphdr *th = pd->hdr.tcp;
+ int rewrite = 0;
+ u_short reason;
+ u_int8_t flags;
+ sa_family_t af = pd->af;
+
+ r = TAILQ_FIRST(pf_main_ruleset.rules[PF_RULESET_SCRUB].active.ptr);
+ while (r != NULL) {
+ r->evaluations++;
+ if (pfi_kif_match(r->kif, kif) == r->ifnot)
+ r = r->skip[PF_SKIP_IFP].ptr;
+ else if (r->direction && r->direction != dir)
+ r = r->skip[PF_SKIP_DIR].ptr;
+ else if (r->af && r->af != af)
+ r = r->skip[PF_SKIP_AF].ptr;
+ else if (r->proto && r->proto != pd->proto)
+ r = r->skip[PF_SKIP_PROTO].ptr;
+ else if (PF_MISMATCHAW(&r->src.addr, pd->src, af,
+ r->src.neg, kif))
+ r = r->skip[PF_SKIP_SRC_ADDR].ptr;
+ else if (r->src.port_op && !pf_match_port(r->src.port_op,
+ r->src.port[0], r->src.port[1], th->th_sport))
+ r = r->skip[PF_SKIP_SRC_PORT].ptr;
+ else if (PF_MISMATCHAW(&r->dst.addr, pd->dst, af,
+ r->dst.neg, NULL))
+ r = r->skip[PF_SKIP_DST_ADDR].ptr;
+ else if (r->dst.port_op && !pf_match_port(r->dst.port_op,
+ r->dst.port[0], r->dst.port[1], th->th_dport))
+ r = r->skip[PF_SKIP_DST_PORT].ptr;
+ else if (r->os_fingerprint != PF_OSFP_ANY && !pf_osfp_match(
+ pf_osfp_fingerprint(pd, m, off, th),
+ r->os_fingerprint))
+ r = TAILQ_NEXT(r, entries);
+ else {
+ rm = r;
+ break;
+ }
+ }
+
+ if (rm == NULL || rm->action == PF_NOSCRUB)
+ return (PF_PASS);
+ else {
+ r->packets[dir == PF_OUT]++;
+ r->bytes[dir == PF_OUT] += pd->tot_len;
+ }
+
+ if (rm->rule_flag & PFRULE_REASSEMBLE_TCP)
+ pd->flags |= PFDESC_TCP_NORM;
+
+ flags = th->th_flags;
+ if (flags & TH_SYN) {
+ /* Illegal packet */
+ if (flags & TH_RST)
+ goto tcp_drop;
+
+ if (flags & TH_FIN)
+ flags &= ~TH_FIN;
+ } else {
+ /* Illegal packet */
+ if (!(flags & (TH_ACK|TH_RST)))
+ goto tcp_drop;
+ }
+
+ if (!(flags & TH_ACK)) {
+ /* These flags are only valid if ACK is set */
+ if ((flags & TH_FIN) || (flags & TH_PUSH) || (flags & TH_URG))
+ goto tcp_drop;
+ }
+
+ /* Check for illegal header length */
+ if (th->th_off < (sizeof(struct tcphdr) >> 2))
+ goto tcp_drop;
+
+ /* If flags changed, or reserved data set, then adjust */
+ if (flags != th->th_flags || th->th_x2 != 0) {
+ u_int16_t ov, nv;
+
+ ov = *(u_int16_t *)(&th->th_ack + 1);
+ th->th_flags = flags;
+ th->th_x2 = 0;
+ nv = *(u_int16_t *)(&th->th_ack + 1);
+
+ th->th_sum = pf_cksum_fixup(th->th_sum, ov, nv, 0);
+ rewrite = 1;
+ }
+
+ /* Remove urgent pointer, if TH_URG is not set */
+ if (!(flags & TH_URG) && th->th_urp) {
+ th->th_sum = pf_cksum_fixup(th->th_sum, th->th_urp, 0, 0);
+ th->th_urp = 0;
+ rewrite = 1;
+ }
+
+ /* Process options */
+ if (r->max_mss && pf_normalize_tcpopt(r, m, th, off))
+ rewrite = 1;
+
+ /* copy back packet headers if we sanitized */
+ if (rewrite)
+ m_copyback(m, off, sizeof(*th), (caddr_t)th);
+
+ return (PF_PASS);
+
+ tcp_drop:
+ REASON_SET(&reason, PFRES_NORM);
+ if (rm != NULL && r->log)
+ PFLOG_PACKET(kif, h, m, AF_INET, dir, reason, r, NULL, NULL, pd);
+ return (PF_DROP);
+}
+
+int
+pf_normalize_tcp_init(struct mbuf *m, int off, struct pf_pdesc *pd,
+ struct tcphdr *th, struct pf_state_peer *src, struct pf_state_peer *dst)
+{
+ u_int32_t tsval, tsecr;
+ u_int8_t hdr[60];
+ u_int8_t *opt;
+
+#ifdef __FreeBSD__
+ KASSERT((src->scrub == NULL),
+ ("pf_normalize_tcp_init: src->scrub != NULL"));
+#else
+ KASSERT(src->scrub == NULL);
+#endif
+
+ src->scrub = pool_get(&pf_state_scrub_pl, PR_NOWAIT);
+ if (src->scrub == NULL)
+ return (1);
+ bzero(src->scrub, sizeof(*src->scrub));
+
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET: {
+ struct ip *h = mtod(m, struct ip *);
+ src->scrub->pfss_ttl = h->ip_ttl;
+ break;
+ }
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6: {
+ struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
+ src->scrub->pfss_ttl = h->ip6_hlim;
+ break;
+ }
+#endif /* INET6 */
+ }
+
+
+ /*
+ * All normalizations below are only begun if we see the start of
+ * the connections. They must all set an enabled bit in pfss_flags
+ */
+ if ((th->th_flags & TH_SYN) == 0)
+ return (0);
+
+
+ if (th->th_off > (sizeof(struct tcphdr) >> 2) && src->scrub &&
+ pf_pull_hdr(m, off, hdr, th->th_off << 2, NULL, NULL, pd->af)) {
+ /* Diddle with TCP options */
+ int hlen;
+ opt = hdr + sizeof(struct tcphdr);
+ hlen = (th->th_off << 2) - sizeof(struct tcphdr);
+ while (hlen >= TCPOLEN_TIMESTAMP) {
+ switch (*opt) {
+ case TCPOPT_EOL: /* FALLTHROUGH */
+ case TCPOPT_NOP:
+ opt++;
+ hlen--;
+ break;
+ case TCPOPT_TIMESTAMP:
+ if (opt[1] >= TCPOLEN_TIMESTAMP) {
+ src->scrub->pfss_flags |=
+ PFSS_TIMESTAMP;
+ src->scrub->pfss_ts_mod =
+ htonl(arc4random());
+
+ /* note PFSS_PAWS not set yet */
+ memcpy(&tsval, &opt[2],
+ sizeof(u_int32_t));
+ memcpy(&tsecr, &opt[6],
+ sizeof(u_int32_t));
+ src->scrub->pfss_tsval0 = ntohl(tsval);
+ src->scrub->pfss_tsval = ntohl(tsval);
+ src->scrub->pfss_tsecr = ntohl(tsecr);
+ getmicrouptime(&src->scrub->pfss_last);
+ }
+ /* FALLTHROUGH */
+ default:
+ hlen -= MAX(opt[1], 2);
+ opt += MAX(opt[1], 2);
+ break;
+ }
+ }
+ }
+
+ return (0);
+}
+
+void
+pf_normalize_tcp_cleanup(struct pf_state *state)
+{
+ if (state->src.scrub)
+ pool_put(&pf_state_scrub_pl, state->src.scrub);
+ if (state->dst.scrub)
+ pool_put(&pf_state_scrub_pl, state->dst.scrub);
+
+ /* Someday... flush the TCP segment reassembly descriptors. */
+}
+
+int
+pf_normalize_tcp_stateful(struct mbuf *m, int off, struct pf_pdesc *pd,
+ u_short *reason, struct tcphdr *th, struct pf_state *state,
+ struct pf_state_peer *src, struct pf_state_peer *dst, int *writeback)
+{
+ struct timeval uptime;
+ u_int32_t tsval, tsecr;
+ u_int tsval_from_last;
+ u_int8_t hdr[60];
+ u_int8_t *opt;
+ int copyback = 0;
+ int got_ts = 0;
+
+#ifdef __FreeBSD__
+ KASSERT((src->scrub || dst->scrub),
+ ("pf_normalize_tcp_statefull: src->scrub && dst->scrub!"));
+#else
+ KASSERT(src->scrub || dst->scrub);
+#endif
+
+ /*
+ * Enforce the minimum TTL seen for this connection. Negate a common
+ * technique to evade an intrusion detection system and confuse
+ * firewall state code.
+ */
+ switch (pd->af) {
+#ifdef INET
+ case AF_INET: {
+ if (src->scrub) {
+ struct ip *h = mtod(m, struct ip *);
+ if (h->ip_ttl > src->scrub->pfss_ttl)
+ src->scrub->pfss_ttl = h->ip_ttl;
+ h->ip_ttl = src->scrub->pfss_ttl;
+ }
+ break;
+ }
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6: {
+ if (src->scrub) {
+ struct ip6_hdr *h = mtod(m, struct ip6_hdr *);
+ if (h->ip6_hlim > src->scrub->pfss_ttl)
+ src->scrub->pfss_ttl = h->ip6_hlim;
+ h->ip6_hlim = src->scrub->pfss_ttl;
+ }
+ break;
+ }
+#endif /* INET6 */
+ }
+
+ if (th->th_off > (sizeof(struct tcphdr) >> 2) &&
+ ((src->scrub && (src->scrub->pfss_flags & PFSS_TIMESTAMP)) ||
+ (dst->scrub && (dst->scrub->pfss_flags & PFSS_TIMESTAMP))) &&
+ pf_pull_hdr(m, off, hdr, th->th_off << 2, NULL, NULL, pd->af)) {
+ /* Diddle with TCP options */
+ int hlen;
+ opt = hdr + sizeof(struct tcphdr);
+ hlen = (th->th_off << 2) - sizeof(struct tcphdr);
+ while (hlen >= TCPOLEN_TIMESTAMP) {
+ switch (*opt) {
+ case TCPOPT_EOL: /* FALLTHROUGH */
+ case TCPOPT_NOP:
+ opt++;
+ hlen--;
+ break;
+ case TCPOPT_TIMESTAMP:
+ /* Modulate the timestamps. Can be used for
+ * NAT detection, OS uptime determination or
+ * reboot detection.
+ */
+
+ if (got_ts) {
+ /* Huh? Multiple timestamps!? */
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("multiple TS??"));
+ pf_print_state(state);
+ printf("\n");
+ }
+ REASON_SET(reason, PFRES_TS);
+ return (PF_DROP);
+ }
+ if (opt[1] >= TCPOLEN_TIMESTAMP) {
+ memcpy(&tsval, &opt[2],
+ sizeof(u_int32_t));
+ if (tsval && src->scrub &&
+ (src->scrub->pfss_flags &
+ PFSS_TIMESTAMP)) {
+ tsval = ntohl(tsval);
+ pf_change_a(&opt[2],
+ &th->th_sum,
+ htonl(tsval +
+ src->scrub->pfss_ts_mod),
+ 0);
+ copyback = 1;
+ }
+
+ /* Modulate TS reply iff valid (!0) */
+ memcpy(&tsecr, &opt[6],
+ sizeof(u_int32_t));
+ if (tsecr && dst->scrub &&
+ (dst->scrub->pfss_flags &
+ PFSS_TIMESTAMP)) {
+ tsecr = ntohl(tsecr)
+ - dst->scrub->pfss_ts_mod;
+ pf_change_a(&opt[6],
+ &th->th_sum, htonl(tsecr),
+ 0);
+ copyback = 1;
+ }
+ got_ts = 1;
+ }
+ /* FALLTHROUGH */
+ default:
+ hlen -= MAX(opt[1], 2);
+ opt += MAX(opt[1], 2);
+ break;
+ }
+ }
+ if (copyback) {
+ /* Copyback the options, caller copys back header */
+ *writeback = 1;
+ m_copyback(m, off + sizeof(struct tcphdr),
+ (th->th_off << 2) - sizeof(struct tcphdr), hdr +
+ sizeof(struct tcphdr));
+ }
+ }
+
+
+ /*
+ * Must invalidate PAWS checks on connections idle for too long.
+ * The fastest allowed timestamp clock is 1ms. That turns out to
+ * be about 24 days before it wraps. XXX Right now our lowerbound
+ * TS echo check only works for the first 12 days of a connection
+ * when the TS has exhausted half its 32bit space
+ */
+#define TS_MAX_IDLE (24*24*60*60)
+#define TS_MAX_CONN (12*24*60*60) /* XXX remove when better tsecr check */
+
+ getmicrouptime(&uptime);
+ if (src->scrub && (src->scrub->pfss_flags & PFSS_PAWS) &&
+ (uptime.tv_sec - src->scrub->pfss_last.tv_sec > TS_MAX_IDLE ||
+ time_second - state->creation > TS_MAX_CONN)) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("src idled out of PAWS\n"));
+ pf_print_state(state);
+ printf("\n");
+ }
+ src->scrub->pfss_flags = (src->scrub->pfss_flags & ~PFSS_PAWS)
+ | PFSS_PAWS_IDLED;
+ }
+ if (dst->scrub && (dst->scrub->pfss_flags & PFSS_PAWS) &&
+ uptime.tv_sec - dst->scrub->pfss_last.tv_sec > TS_MAX_IDLE) {
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("dst idled out of PAWS\n"));
+ pf_print_state(state);
+ printf("\n");
+ }
+ dst->scrub->pfss_flags = (dst->scrub->pfss_flags & ~PFSS_PAWS)
+ | PFSS_PAWS_IDLED;
+ }
+
+ if (got_ts && src->scrub && dst->scrub &&
+ (src->scrub->pfss_flags & PFSS_PAWS) &&
+ (dst->scrub->pfss_flags & PFSS_PAWS)) {
+ /* Validate that the timestamps are "in-window".
+ * RFC1323 describes TCP Timestamp options that allow
+ * measurement of RTT (round trip time) and PAWS
+ * (protection against wrapped sequence numbers). PAWS
+ * gives us a set of rules for rejecting packets on
+ * long fat pipes (packets that were somehow delayed
+ * in transit longer than the time it took to send the
+ * full TCP sequence space of 4Gb). We can use these
+ * rules and infer a few others that will let us treat
+ * the 32bit timestamp and the 32bit echoed timestamp
+ * as sequence numbers to prevent a blind attacker from
+ * inserting packets into a connection.
+ *
+ * RFC1323 tells us:
+ * - The timestamp on this packet must be greater than
+ * or equal to the last value echoed by the other
+ * endpoint. The RFC says those will be discarded
+ * since it is a dup that has already been acked.
+ * This gives us a lowerbound on the timestamp.
+ * timestamp >= other last echoed timestamp
+ * - The timestamp will be less than or equal to
+ * the last timestamp plus the time between the
+ * last packet and now. The RFC defines the max
+ * clock rate as 1ms. We will allow clocks to be
+ * up to 10% fast and will allow a total difference
+ * or 30 seconds due to a route change. And this
+ * gives us an upperbound on the timestamp.
+ * timestamp <= last timestamp + max ticks
+ * We have to be careful here. Windows will send an
+ * initial timestamp of zero and then initialize it
+ * to a random value after the 3whs; presumably to
+ * avoid a DoS by having to call an expensive RNG
+ * during a SYN flood. Proof MS has at least one
+ * good security geek.
+ *
+ * - The TCP timestamp option must also echo the other
+ * endpoints timestamp. The timestamp echoed is the
+ * one carried on the earliest unacknowledged segment
+ * on the left edge of the sequence window. The RFC
+ * states that the host will reject any echoed
+ * timestamps that were larger than any ever sent.
+ * This gives us an upperbound on the TS echo.
+ * tescr <= largest_tsval
+ * - The lowerbound on the TS echo is a little more
+ * tricky to determine. The other endpoint's echoed
+ * values will not decrease. But there may be
+ * network conditions that re-order packets and
+ * cause our view of them to decrease. For now the
+ * only lowerbound we can safely determine is that
+ * the TS echo will never be less than the orginal
+ * TS. XXX There is probably a better lowerbound.
+ * Remove TS_MAX_CONN with better lowerbound check.
+ * tescr >= other original TS
+ *
+ * It is also important to note that the fastest
+ * timestamp clock of 1ms will wrap its 32bit space in
+ * 24 days. So we just disable TS checking after 24
+ * days of idle time. We actually must use a 12d
+ * connection limit until we can come up with a better
+ * lowerbound to the TS echo check.
+ */
+ struct timeval delta_ts;
+ int ts_fudge;
+
+
+ /*
+ * PFTM_TS_DIFF is how many seconds of leeway to allow
+ * a host's timestamp. This can happen if the previous
+ * packet got delayed in transit for much longer than
+ * this packet.
+ */
+ if ((ts_fudge = state->rule.ptr->timeout[PFTM_TS_DIFF]) == 0)
+ ts_fudge = pf_default_rule.timeout[PFTM_TS_DIFF];
+
+
+ /* Calculate max ticks since the last timestamp */
+#define TS_MAXFREQ 1100 /* RFC max TS freq of 1Khz + 10% skew */
+#define TS_MICROSECS 1000000 /* microseconds per second */
+#ifdef __FreeBSD__
+#ifndef timersub
+#define timersub(tvp, uvp, vvp) \
+ do { \
+ (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
+ (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
+ if ((vvp)->tv_usec < 0) { \
+ (vvp)->tv_sec--; \
+ (vvp)->tv_usec += 1000000; \
+ } \
+ } while (0)
+#endif
+#endif
+ timersub(&uptime, &src->scrub->pfss_last, &delta_ts);
+ tsval_from_last = (delta_ts.tv_sec + ts_fudge) * TS_MAXFREQ;
+ tsval_from_last += delta_ts.tv_usec / (TS_MICROSECS/TS_MAXFREQ);
+
+
+ if ((src->state >= TCPS_ESTABLISHED &&
+ dst->state >= TCPS_ESTABLISHED) &&
+ (SEQ_LT(tsval, dst->scrub->pfss_tsecr) ||
+ SEQ_GT(tsval, src->scrub->pfss_tsval + tsval_from_last) ||
+ (tsecr && (SEQ_GT(tsecr, dst->scrub->pfss_tsval) ||
+ SEQ_LT(tsecr, dst->scrub->pfss_tsval0))))) {
+ /* Bad RFC1323 implementation or an insertion attack.
+ *
+ * - Solaris 2.6 and 2.7 are known to send another ACK
+ * after the FIN,FIN|ACK,ACK closing that carries
+ * an old timestamp.
+ */
+
+ DPFPRINTF(("Timestamp failed %c%c%c%c\n",
+ SEQ_LT(tsval, dst->scrub->pfss_tsecr) ? '0' : ' ',
+ SEQ_GT(tsval, src->scrub->pfss_tsval +
+ tsval_from_last) ? '1' : ' ',
+ SEQ_GT(tsecr, dst->scrub->pfss_tsval) ? '2' : ' ',
+ SEQ_LT(tsecr, dst->scrub->pfss_tsval0)? '3' : ' '));
+#ifdef __FreeBSD__
+ DPFPRINTF((" tsval: %u tsecr: %u +ticks: %u "
+ "idle: %jus %lums\n",
+ tsval, tsecr, tsval_from_last,
+ (uintmax_t)delta_ts.tv_sec,
+ delta_ts.tv_usec / 1000));
+ DPFPRINTF((" src->tsval: %u tsecr: %u\n",
+ src->scrub->pfss_tsval, src->scrub->pfss_tsecr));
+ DPFPRINTF((" dst->tsval: %u tsecr: %u tsval0: %u"
+ "\n", dst->scrub->pfss_tsval,
+ dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0));
+#else
+ DPFPRINTF((" tsval: %lu tsecr: %lu +ticks: %lu "
+ "idle: %lus %lums\n",
+ tsval, tsecr, tsval_from_last, delta_ts.tv_sec,
+ delta_ts.tv_usec / 1000));
+ DPFPRINTF((" src->tsval: %lu tsecr: %lu\n",
+ src->scrub->pfss_tsval, src->scrub->pfss_tsecr));
+ DPFPRINTF((" dst->tsval: %lu tsecr: %lu tsval0: %lu"
+ "\n", dst->scrub->pfss_tsval,
+ dst->scrub->pfss_tsecr, dst->scrub->pfss_tsval0));
+#endif
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ pf_print_state(state);
+ pf_print_flags(th->th_flags);
+ printf("\n");
+ }
+ REASON_SET(reason, PFRES_TS);
+ return (PF_DROP);
+ }
+
+ /* XXX I'd really like to require tsecr but it's optional */
+
+ } else if (!got_ts && (th->th_flags & TH_RST) == 0 &&
+ ((src->state == TCPS_ESTABLISHED && dst->state == TCPS_ESTABLISHED)
+ || pd->p_len > 0 || (th->th_flags & TH_SYN)) &&
+ src->scrub && dst->scrub &&
+ (src->scrub->pfss_flags & PFSS_PAWS) &&
+ (dst->scrub->pfss_flags & PFSS_PAWS)) {
+ /* Didn't send a timestamp. Timestamps aren't really useful
+ * when:
+ * - connection opening or closing (often not even sent).
+ * but we must not let an attacker to put a FIN on a
+ * data packet to sneak it through our ESTABLISHED check.
+ * - on a TCP reset. RFC suggests not even looking at TS.
+ * - on an empty ACK. The TS will not be echoed so it will
+ * probably not help keep the RTT calculation in sync and
+ * there isn't as much danger when the sequence numbers
+ * got wrapped. So some stacks don't include TS on empty
+ * ACKs :-(
+ *
+ * To minimize the disruption to mostly RFC1323 conformant
+ * stacks, we will only require timestamps on data packets.
+ *
+ * And what do ya know, we cannot require timestamps on data
+ * packets. There appear to be devices that do legitimate
+ * TCP connection hijacking. There are HTTP devices that allow
+ * a 3whs (with timestamps) and then buffer the HTTP request.
+ * If the intermediate device has the HTTP response cache, it
+ * will spoof the response but not bother timestamping its
+ * packets. So we can look for the presence of a timestamp in
+ * the first data packet and if there, require it in all future
+ * packets.
+ */
+
+ if (pd->p_len > 0 && (src->scrub->pfss_flags & PFSS_DATA_TS)) {
+ /*
+ * Hey! Someone tried to sneak a packet in. Or the
+ * stack changed its RFC1323 behavior?!?!
+ */
+ if (pf_status.debug >= PF_DEBUG_MISC) {
+ DPFPRINTF(("Did not receive expected RFC1323 "
+ "timestamp\n"));
+ pf_print_state(state);
+ pf_print_flags(th->th_flags);
+ printf("\n");
+ }
+ REASON_SET(reason, PFRES_TS);
+ return (PF_DROP);
+ }
+ }
+
+
+ /*
+ * We will note if a host sends his data packets with or without
+ * timestamps. And require all data packets to contain a timestamp
+ * if the first does. PAWS implicitly requires that all data packets be
+ * timestamped. But I think there are middle-man devices that hijack
+ * TCP streams immediately after the 3whs and don't timestamp their
+ * packets (seen in a WWW accelerator or cache).
+ */
+ if (pd->p_len > 0 && src->scrub && (src->scrub->pfss_flags &
+ (PFSS_TIMESTAMP|PFSS_DATA_TS|PFSS_DATA_NOTS)) == PFSS_TIMESTAMP) {
+ if (got_ts)
+ src->scrub->pfss_flags |= PFSS_DATA_TS;
+ else {
+ src->scrub->pfss_flags |= PFSS_DATA_NOTS;
+ if (pf_status.debug >= PF_DEBUG_MISC && dst->scrub &&
+ (dst->scrub->pfss_flags & PFSS_TIMESTAMP)) {
+ /* Don't warn if other host rejected RFC1323 */
+ DPFPRINTF(("Broken RFC1323 stack did not "
+ "timestamp data packet. Disabled PAWS "
+ "security.\n"));
+ pf_print_state(state);
+ pf_print_flags(th->th_flags);
+ printf("\n");
+ }
+ }
+ }
+
+
+ /*
+ * Update PAWS values
+ */
+ if (got_ts && src->scrub && PFSS_TIMESTAMP == (src->scrub->pfss_flags &
+ (PFSS_PAWS_IDLED|PFSS_TIMESTAMP))) {
+ getmicrouptime(&src->scrub->pfss_last);
+ if (SEQ_GEQ(tsval, src->scrub->pfss_tsval) ||
+ (src->scrub->pfss_flags & PFSS_PAWS) == 0)
+ src->scrub->pfss_tsval = tsval;
+
+ if (tsecr) {
+ if (SEQ_GEQ(tsecr, src->scrub->pfss_tsecr) ||
+ (src->scrub->pfss_flags & PFSS_PAWS) == 0)
+ src->scrub->pfss_tsecr = tsecr;
+
+ if ((src->scrub->pfss_flags & PFSS_PAWS) == 0 &&
+ (SEQ_LT(tsval, src->scrub->pfss_tsval0) ||
+ src->scrub->pfss_tsval0 == 0)) {
+ /* tsval0 MUST be the lowest timestamp */
+ src->scrub->pfss_tsval0 = tsval;
+ }
+
+ /* Only fully initialized after a TS gets echoed */
+ if ((src->scrub->pfss_flags & PFSS_PAWS) == 0)
+ src->scrub->pfss_flags |= PFSS_PAWS;
+ }
+ }
+
+ /* I have a dream.... TCP segment reassembly.... */
+ return (0);
+}
+
+int
+pf_normalize_tcpopt(struct pf_rule *r, struct mbuf *m, struct tcphdr *th,
+ int off)
+{
+ u_int16_t *mss;
+ int thoff;
+ int opt, cnt, optlen = 0;
+ int rewrite = 0;
+ u_char *optp;
+
+ thoff = th->th_off << 2;
+ cnt = thoff - sizeof(struct tcphdr);
+ optp = mtod(m, caddr_t) + off + sizeof(struct tcphdr);
+
+ for (; cnt > 0; cnt -= optlen, optp += optlen) {
+ opt = optp[0];
+ if (opt == TCPOPT_EOL)
+ break;
+ if (opt == TCPOPT_NOP)
+ optlen = 1;
+ else {
+ if (cnt < 2)
+ break;
+ optlen = optp[1];
+ if (optlen < 2 || optlen > cnt)
+ break;
+ }
+ switch (opt) {
+ case TCPOPT_MAXSEG:
+ mss = (u_int16_t *)(optp + 2);
+ if ((ntohs(*mss)) > r->max_mss) {
+ th->th_sum = pf_cksum_fixup(th->th_sum,
+ *mss, htons(r->max_mss), 0);
+ *mss = htons(r->max_mss);
+ rewrite = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ return (rewrite);
+}
diff --git a/freebsd/sys/contrib/pf/net/pf_osfp.c b/freebsd/sys/contrib/pf/net/pf_osfp.c
new file mode 100644
index 00000000..dafeabf1
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_osfp.c
@@ -0,0 +1,640 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: pf_osfp.c,v 1.12 2006/12/13 18:14:10 itojun Exp $ */
+
+/*
+ * Copyright (c) 2003 Mike Frantzen <frantzen@w4g.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.
+ *
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/socket.h>
+#ifdef _KERNEL
+# include <freebsd/sys/systm.h>
+#endif /* _KERNEL */
+#include <freebsd/sys/mbuf.h>
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/tcp.h>
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/pfvar.h>
+
+#include <freebsd/netinet/ip6.h>
+#ifdef _KERNEL
+#include <freebsd/netinet6/in6_var.h>
+#endif
+
+#ifdef _KERNEL
+# define DPFPRINTF(format, x...) \
+ if (pf_status.debug >= PF_DEBUG_NOISY) \
+ printf(format , ##x)
+#ifdef __FreeBSD__
+typedef uma_zone_t pool_t;
+#else
+typedef struct pool pool_t;
+#endif
+
+#else
+/* Userland equivalents so we can lend code to tcpdump et al. */
+
+# include <freebsd/arpa/inet.h>
+# include <freebsd/errno.h>
+# include <freebsd/stdio.h>
+# include <freebsd/stdlib.h>
+# include <freebsd/string.h>
+# include <freebsd/netdb.h>
+# define pool_t int
+# define pool_get(pool, flags) malloc(*(pool))
+# define pool_put(pool, item) free(item)
+# define pool_init(pool, size, a, ao, f, m, p) (*(pool)) = (size)
+
+# ifdef __FreeBSD__
+# define NTOHS(x) (x) = ntohs((u_int16_t)(x))
+# endif
+
+# ifdef PFDEBUG
+# include <freebsd/sys/stdarg.h>
+# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
+# else
+# define DPFPRINTF(format, x...) ((void)0)
+# endif /* PFDEBUG */
+#endif /* _KERNEL */
+
+
+SLIST_HEAD(pf_osfp_list, pf_os_fingerprint) pf_osfp_list;
+pool_t pf_osfp_entry_pl;
+pool_t pf_osfp_pl;
+
+struct pf_os_fingerprint *pf_osfp_find(struct pf_osfp_list *,
+ struct pf_os_fingerprint *, u_int8_t);
+struct pf_os_fingerprint *pf_osfp_find_exact(struct pf_osfp_list *,
+ struct pf_os_fingerprint *);
+void pf_osfp_insert(struct pf_osfp_list *,
+ struct pf_os_fingerprint *);
+
+
+#ifdef _KERNEL
+/*
+ * Passively fingerprint the OS of the host (IPv4 TCP SYN packets only)
+ * Returns the list of possible OSes.
+ */
+struct pf_osfp_enlist *
+pf_osfp_fingerprint(struct pf_pdesc *pd, struct mbuf *m, int off,
+ const struct tcphdr *tcp)
+{
+ struct ip *ip;
+ struct ip6_hdr *ip6;
+ char hdr[60];
+
+ if ((pd->af != PF_INET && pd->af != PF_INET6) ||
+ pd->proto != IPPROTO_TCP || (tcp->th_off << 2) < sizeof(*tcp))
+ return (NULL);
+
+ if (pd->af == PF_INET) {
+ ip = mtod(m, struct ip *);
+ ip6 = (struct ip6_hdr *)NULL;
+ } else {
+ ip = (struct ip *)NULL;
+ ip6 = mtod(m, struct ip6_hdr *);
+ }
+ if (!pf_pull_hdr(m, off, hdr, tcp->th_off << 2, NULL, NULL,
+ pd->af)) return (NULL);
+
+ return (pf_osfp_fingerprint_hdr(ip, ip6, (struct tcphdr *)hdr));
+}
+#endif /* _KERNEL */
+
+struct pf_osfp_enlist *
+pf_osfp_fingerprint_hdr(const struct ip *ip, const struct ip6_hdr *ip6, const struct tcphdr *tcp)
+{
+ struct pf_os_fingerprint fp, *fpresult;
+ int cnt, optlen = 0;
+ const u_int8_t *optp;
+#ifdef _KERNEL
+ char srcname[128];
+#else
+ char srcname[NI_MAXHOST];
+#endif
+#ifdef __rtems__
+#ifdef INET6
+char ip6buf[INET6_ADDRSTRLEN];
+#endif //INET6
+#endif //__rtems__
+
+ if ((tcp->th_flags & (TH_SYN|TH_ACK)) != TH_SYN)
+ return (NULL);
+ if (ip) {
+ if ((ip->ip_off & htons(IP_OFFMASK)) != 0)
+ return (NULL);
+ }
+
+ memset(&fp, 0, sizeof(fp));
+
+ if (ip) {
+#ifndef _KERNEL
+ struct sockaddr_in sin;
+#endif
+
+ fp.fp_psize = ntohs(ip->ip_len);
+ fp.fp_ttl = ip->ip_ttl;
+ if (ip->ip_off & htons(IP_DF))
+ fp.fp_flags |= PF_OSFP_DF;
+#ifdef _KERNEL
+ strlcpy(srcname, inet_ntoa(ip->ip_src), sizeof(srcname));
+#else
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_addr = ip->ip_src;
+ (void)getnameinfo((struct sockaddr *)&sin,
+ sizeof(struct sockaddr_in), srcname, sizeof(srcname),
+ NULL, 0, NI_NUMERICHOST);
+#endif
+ }
+#ifdef INET6
+ else if (ip6) {
+#ifndef _KERNEL
+ struct sockaddr_in6 sin6;
+#endif
+
+ /* jumbo payload? */
+ fp.fp_psize = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
+ fp.fp_ttl = ip6->ip6_hlim;
+ fp.fp_flags |= PF_OSFP_DF;
+ fp.fp_flags |= PF_OSFP_INET6;
+#ifdef _KERNEL
+#ifndef __rtems__
+ strlcpy(srcname, ip6_sprintf((struct in6_addr *)&ip6->ip6_src),
+ sizeof(srcname));
+#else
+ strlcpy(srcname, ip6_sprintf(&ip6buf, (struct in6_addr *)&ip6->ip6_src),
+ sizeof(srcname));
+#endif
+#else
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_addr = ip6->ip6_src;
+ (void)getnameinfo((struct sockaddr *)&sin6,
+ sizeof(struct sockaddr_in6), srcname, sizeof(srcname),
+ NULL, 0, NI_NUMERICHOST);
+#endif
+ }
+#endif
+ else
+ return (NULL);
+ fp.fp_wsize = ntohs(tcp->th_win);
+
+
+ cnt = (tcp->th_off << 2) - sizeof(*tcp);
+ optp = (const u_int8_t *)((const char *)tcp + sizeof(*tcp));
+ for (; cnt > 0; cnt -= optlen, optp += optlen) {
+ if (*optp == TCPOPT_EOL)
+ break;
+
+ fp.fp_optcnt++;
+ if (*optp == TCPOPT_NOP) {
+ fp.fp_tcpopts = (fp.fp_tcpopts << PF_OSFP_TCPOPT_BITS) |
+ PF_OSFP_TCPOPT_NOP;
+ optlen = 1;
+ } else {
+ if (cnt < 2)
+ return (NULL);
+ optlen = optp[1];
+ if (optlen > cnt || optlen < 2)
+ return (NULL);
+ switch (*optp) {
+ case TCPOPT_MAXSEG:
+ if (optlen >= TCPOLEN_MAXSEG)
+ memcpy(&fp.fp_mss, &optp[2],
+ sizeof(fp.fp_mss));
+ fp.fp_tcpopts = (fp.fp_tcpopts <<
+ PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_MSS;
+ NTOHS(fp.fp_mss);
+ break;
+ case TCPOPT_WINDOW:
+ if (optlen >= TCPOLEN_WINDOW)
+ memcpy(&fp.fp_wscale, &optp[2],
+ sizeof(fp.fp_wscale));
+ NTOHS(fp.fp_wscale);
+ fp.fp_tcpopts = (fp.fp_tcpopts <<
+ PF_OSFP_TCPOPT_BITS) |
+ PF_OSFP_TCPOPT_WSCALE;
+ break;
+ case TCPOPT_SACK_PERMITTED:
+ fp.fp_tcpopts = (fp.fp_tcpopts <<
+ PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_SACK;
+ break;
+ case TCPOPT_TIMESTAMP:
+ if (optlen >= TCPOLEN_TIMESTAMP) {
+ u_int32_t ts;
+ memcpy(&ts, &optp[2], sizeof(ts));
+ if (ts == 0)
+ fp.fp_flags |= PF_OSFP_TS0;
+
+ }
+ fp.fp_tcpopts = (fp.fp_tcpopts <<
+ PF_OSFP_TCPOPT_BITS) | PF_OSFP_TCPOPT_TS;
+ break;
+ default:
+ return (NULL);
+ }
+ }
+ optlen = MAX(optlen, 1); /* paranoia */
+ }
+
+ DPFPRINTF("fingerprinted %s:%d %d:%d:%d:%d:%llx (%d) "
+ "(TS=%s,M=%s%d,W=%s%d)\n",
+ srcname, ntohs(tcp->th_sport),
+ fp.fp_wsize, fp.fp_ttl, (fp.fp_flags & PF_OSFP_DF) != 0,
+ fp.fp_psize, (long long int)fp.fp_tcpopts, fp.fp_optcnt,
+ (fp.fp_flags & PF_OSFP_TS0) ? "0" : "",
+ (fp.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
+ (fp.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
+ fp.fp_mss,
+ (fp.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
+ (fp.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
+ fp.fp_wscale);
+
+ if ((fpresult = pf_osfp_find(&pf_osfp_list, &fp,
+ PF_OSFP_MAXTTL_OFFSET)))
+ return (&fpresult->fp_oses);
+ return (NULL);
+}
+
+/* Match a fingerprint ID against a list of OSes */
+int
+pf_osfp_match(struct pf_osfp_enlist *list, pf_osfp_t os)
+{
+ struct pf_osfp_entry *entry;
+ int os_class, os_version, os_subtype;
+ int en_class, en_version, en_subtype;
+
+ if (os == PF_OSFP_ANY)
+ return (1);
+ if (list == NULL) {
+ DPFPRINTF("osfp no match against %x\n", os);
+ return (os == PF_OSFP_UNKNOWN);
+ }
+ PF_OSFP_UNPACK(os, os_class, os_version, os_subtype);
+ SLIST_FOREACH(entry, list, fp_entry) {
+ PF_OSFP_UNPACK(entry->fp_os, en_class, en_version, en_subtype);
+ if ((os_class == PF_OSFP_ANY || en_class == os_class) &&
+ (os_version == PF_OSFP_ANY || en_version == os_version) &&
+ (os_subtype == PF_OSFP_ANY || en_subtype == os_subtype)) {
+ DPFPRINTF("osfp matched %s %s %s %x==%x\n",
+ entry->fp_class_nm, entry->fp_version_nm,
+ entry->fp_subtype_nm, os, entry->fp_os);
+ return (1);
+ }
+ }
+ DPFPRINTF("fingerprint 0x%x didn't match\n", os);
+ return (0);
+}
+
+/* Initialize the OS fingerprint system */
+#ifdef __FreeBSD__
+int
+#else
+void
+#endif
+pf_osfp_initialize(void)
+{
+#if defined(__FreeBSD__) && defined(_KERNEL)
+ int error = ENOMEM;
+
+ do {
+ pf_osfp_entry_pl = pf_osfp_pl = NULL;
+ UMA_CREATE(pf_osfp_entry_pl, struct pf_osfp_entry, "pfospfen");
+ UMA_CREATE(pf_osfp_pl, struct pf_os_fingerprint, "pfosfp");
+ error = 0;
+ } while(0);
+#else
+ pool_init(&pf_osfp_entry_pl, sizeof(struct pf_osfp_entry), 0, 0, 0,
+ "pfosfpen", &pool_allocator_nointr);
+ pool_init(&pf_osfp_pl, sizeof(struct pf_os_fingerprint), 0, 0, 0,
+ "pfosfp", &pool_allocator_nointr);
+#endif
+ SLIST_INIT(&pf_osfp_list);
+#ifdef __FreeBSD__
+#ifdef _KERNEL
+ return (error);
+#else
+ return (0);
+#endif
+#endif
+}
+
+#if defined(__FreeBSD__) && (_KERNEL)
+void
+pf_osfp_cleanup(void)
+{
+ UMA_DESTROY(pf_osfp_entry_pl);
+ UMA_DESTROY(pf_osfp_pl);
+}
+#endif
+
+/* Flush the fingerprint list */
+void
+pf_osfp_flush(void)
+{
+ struct pf_os_fingerprint *fp;
+ struct pf_osfp_entry *entry;
+
+ while ((fp = SLIST_FIRST(&pf_osfp_list))) {
+ SLIST_REMOVE_HEAD(&pf_osfp_list, fp_next);
+ while ((entry = SLIST_FIRST(&fp->fp_oses))) {
+ SLIST_REMOVE_HEAD(&fp->fp_oses, fp_entry);
+ pool_put(&pf_osfp_entry_pl, entry);
+ }
+ pool_put(&pf_osfp_pl, fp);
+ }
+}
+
+
+/* Add a fingerprint */
+int
+pf_osfp_add(struct pf_osfp_ioctl *fpioc)
+{
+ struct pf_os_fingerprint *fp, fpadd;
+ struct pf_osfp_entry *entry;
+
+ memset(&fpadd, 0, sizeof(fpadd));
+ fpadd.fp_tcpopts = fpioc->fp_tcpopts;
+ fpadd.fp_wsize = fpioc->fp_wsize;
+ fpadd.fp_psize = fpioc->fp_psize;
+ fpadd.fp_mss = fpioc->fp_mss;
+ fpadd.fp_flags = fpioc->fp_flags;
+ fpadd.fp_optcnt = fpioc->fp_optcnt;
+ fpadd.fp_wscale = fpioc->fp_wscale;
+ fpadd.fp_ttl = fpioc->fp_ttl;
+
+ DPFPRINTF("adding osfp %s %s %s = %s%d:%d:%d:%s%d:0x%llx %d "
+ "(TS=%s,M=%s%d,W=%s%d) %x\n",
+ fpioc->fp_os.fp_class_nm, fpioc->fp_os.fp_version_nm,
+ fpioc->fp_os.fp_subtype_nm,
+ (fpadd.fp_flags & PF_OSFP_WSIZE_MOD) ? "%" :
+ (fpadd.fp_flags & PF_OSFP_WSIZE_MSS) ? "S" :
+ (fpadd.fp_flags & PF_OSFP_WSIZE_MTU) ? "T" :
+ (fpadd.fp_flags & PF_OSFP_WSIZE_DC) ? "*" : "",
+ fpadd.fp_wsize,
+ fpadd.fp_ttl,
+ (fpadd.fp_flags & PF_OSFP_DF) ? 1 : 0,
+ (fpadd.fp_flags & PF_OSFP_PSIZE_MOD) ? "%" :
+ (fpadd.fp_flags & PF_OSFP_PSIZE_DC) ? "*" : "",
+ fpadd.fp_psize,
+ (long long int)fpadd.fp_tcpopts, fpadd.fp_optcnt,
+ (fpadd.fp_flags & PF_OSFP_TS0) ? "0" : "",
+ (fpadd.fp_flags & PF_OSFP_MSS_MOD) ? "%" :
+ (fpadd.fp_flags & PF_OSFP_MSS_DC) ? "*" : "",
+ fpadd.fp_mss,
+ (fpadd.fp_flags & PF_OSFP_WSCALE_MOD) ? "%" :
+ (fpadd.fp_flags & PF_OSFP_WSCALE_DC) ? "*" : "",
+ fpadd.fp_wscale,
+ fpioc->fp_os.fp_os);
+
+
+ if ((fp = pf_osfp_find_exact(&pf_osfp_list, &fpadd))) {
+ SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
+ if (PF_OSFP_ENTRY_EQ(entry, &fpioc->fp_os))
+ return (EEXIST);
+ }
+ if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL)
+ return (ENOMEM);
+ } else {
+ if ((fp = pool_get(&pf_osfp_pl, PR_NOWAIT)) == NULL)
+ return (ENOMEM);
+ memset(fp, 0, sizeof(*fp));
+ fp->fp_tcpopts = fpioc->fp_tcpopts;
+ fp->fp_wsize = fpioc->fp_wsize;
+ fp->fp_psize = fpioc->fp_psize;
+ fp->fp_mss = fpioc->fp_mss;
+ fp->fp_flags = fpioc->fp_flags;
+ fp->fp_optcnt = fpioc->fp_optcnt;
+ fp->fp_wscale = fpioc->fp_wscale;
+ fp->fp_ttl = fpioc->fp_ttl;
+ SLIST_INIT(&fp->fp_oses);
+ if ((entry = pool_get(&pf_osfp_entry_pl, PR_NOWAIT)) == NULL) {
+ pool_put(&pf_osfp_pl, fp);
+ return (ENOMEM);
+ }
+ pf_osfp_insert(&pf_osfp_list, fp);
+ }
+ memcpy(entry, &fpioc->fp_os, sizeof(*entry));
+
+ /* Make sure the strings are NUL terminated */
+ entry->fp_class_nm[sizeof(entry->fp_class_nm)-1] = '\0';
+ entry->fp_version_nm[sizeof(entry->fp_version_nm)-1] = '\0';
+ entry->fp_subtype_nm[sizeof(entry->fp_subtype_nm)-1] = '\0';
+
+ SLIST_INSERT_HEAD(&fp->fp_oses, entry, fp_entry);
+
+#ifdef PFDEBUG
+ if ((fp = pf_osfp_validate()))
+ printf("Invalid fingerprint list\n");
+#endif /* PFDEBUG */
+ return (0);
+}
+
+
+/* Find a fingerprint in the list */
+struct pf_os_fingerprint *
+pf_osfp_find(struct pf_osfp_list *list, struct pf_os_fingerprint *find,
+ u_int8_t ttldiff)
+{
+ struct pf_os_fingerprint *f;
+
+#define MATCH_INT(_MOD, _DC, _field) \
+ if ((f->fp_flags & _DC) == 0) { \
+ if ((f->fp_flags & _MOD) == 0) { \
+ if (f->_field != find->_field) \
+ continue; \
+ } else { \
+ if (f->_field == 0 || find->_field % f->_field) \
+ continue; \
+ } \
+ }
+
+ SLIST_FOREACH(f, list, fp_next) {
+ if (f->fp_tcpopts != find->fp_tcpopts ||
+ f->fp_optcnt != find->fp_optcnt ||
+ f->fp_ttl < find->fp_ttl ||
+ f->fp_ttl - find->fp_ttl > ttldiff ||
+ (f->fp_flags & (PF_OSFP_DF|PF_OSFP_TS0)) !=
+ (find->fp_flags & (PF_OSFP_DF|PF_OSFP_TS0)))
+ continue;
+
+ MATCH_INT(PF_OSFP_PSIZE_MOD, PF_OSFP_PSIZE_DC, fp_psize)
+ MATCH_INT(PF_OSFP_MSS_MOD, PF_OSFP_MSS_DC, fp_mss)
+ MATCH_INT(PF_OSFP_WSCALE_MOD, PF_OSFP_WSCALE_DC, fp_wscale)
+ if ((f->fp_flags & PF_OSFP_WSIZE_DC) == 0) {
+ if (f->fp_flags & PF_OSFP_WSIZE_MSS) {
+ if (find->fp_mss == 0)
+ continue;
+
+/* Some "smart" NAT devices and DSL routers will tweak the MSS size and
+ * will set it to whatever is suitable for the link type.
+ */
+#define SMART_MSS 1460
+ if ((find->fp_wsize % find->fp_mss ||
+ find->fp_wsize / find->fp_mss !=
+ f->fp_wsize) &&
+ (find->fp_wsize % SMART_MSS ||
+ find->fp_wsize / SMART_MSS !=
+ f->fp_wsize))
+ continue;
+ } else if (f->fp_flags & PF_OSFP_WSIZE_MTU) {
+ if (find->fp_mss == 0)
+ continue;
+
+#define MTUOFF (sizeof(struct ip) + sizeof(struct tcphdr))
+#define SMART_MTU (SMART_MSS + MTUOFF)
+ if ((find->fp_wsize % (find->fp_mss + MTUOFF) ||
+ find->fp_wsize / (find->fp_mss + MTUOFF) !=
+ f->fp_wsize) &&
+ (find->fp_wsize % SMART_MTU ||
+ find->fp_wsize / SMART_MTU !=
+ f->fp_wsize))
+ continue;
+ } else if (f->fp_flags & PF_OSFP_WSIZE_MOD) {
+ if (f->fp_wsize == 0 || find->fp_wsize %
+ f->fp_wsize)
+ continue;
+ } else {
+ if (f->fp_wsize != find->fp_wsize)
+ continue;
+ }
+ }
+ return (f);
+ }
+
+ return (NULL);
+}
+
+/* Find an exact fingerprint in the list */
+struct pf_os_fingerprint *
+pf_osfp_find_exact(struct pf_osfp_list *list, struct pf_os_fingerprint *find)
+{
+ struct pf_os_fingerprint *f;
+
+ SLIST_FOREACH(f, list, fp_next) {
+ if (f->fp_tcpopts == find->fp_tcpopts &&
+ f->fp_wsize == find->fp_wsize &&
+ f->fp_psize == find->fp_psize &&
+ f->fp_mss == find->fp_mss &&
+ f->fp_flags == find->fp_flags &&
+ f->fp_optcnt == find->fp_optcnt &&
+ f->fp_wscale == find->fp_wscale &&
+ f->fp_ttl == find->fp_ttl)
+ return (f);
+ }
+
+ return (NULL);
+}
+
+/* Insert a fingerprint into the list */
+void
+pf_osfp_insert(struct pf_osfp_list *list, struct pf_os_fingerprint *ins)
+{
+ struct pf_os_fingerprint *f, *prev = NULL;
+
+ /* XXX need to go semi tree based. can key on tcp options */
+
+ SLIST_FOREACH(f, list, fp_next)
+ prev = f;
+ if (prev)
+ SLIST_INSERT_AFTER(prev, ins, fp_next);
+ else
+ SLIST_INSERT_HEAD(list, ins, fp_next);
+}
+
+/* Fill a fingerprint by its number (from an ioctl) */
+int
+pf_osfp_get(struct pf_osfp_ioctl *fpioc)
+{
+ struct pf_os_fingerprint *fp;
+ struct pf_osfp_entry *entry;
+ int num = fpioc->fp_getnum;
+ int i = 0;
+
+
+ memset(fpioc, 0, sizeof(*fpioc));
+ SLIST_FOREACH(fp, &pf_osfp_list, fp_next) {
+ SLIST_FOREACH(entry, &fp->fp_oses, fp_entry) {
+ if (i++ == num) {
+ fpioc->fp_mss = fp->fp_mss;
+ fpioc->fp_wsize = fp->fp_wsize;
+ fpioc->fp_flags = fp->fp_flags;
+ fpioc->fp_psize = fp->fp_psize;
+ fpioc->fp_ttl = fp->fp_ttl;
+ fpioc->fp_wscale = fp->fp_wscale;
+ fpioc->fp_getnum = num;
+ memcpy(&fpioc->fp_os, entry,
+ sizeof(fpioc->fp_os));
+ return (0);
+ }
+ }
+ }
+
+ return (EBUSY);
+}
+
+
+/* Validate that each signature is reachable */
+struct pf_os_fingerprint *
+pf_osfp_validate(void)
+{
+ struct pf_os_fingerprint *f, *f2, find;
+
+ SLIST_FOREACH(f, &pf_osfp_list, fp_next) {
+ memcpy(&find, f, sizeof(find));
+
+ /* We do a few MSS/th_win percolations to make things unique */
+ if (find.fp_mss == 0)
+ find.fp_mss = 128;
+ if (f->fp_flags & PF_OSFP_WSIZE_MSS)
+ find.fp_wsize *= find.fp_mss, 1;
+ else if (f->fp_flags & PF_OSFP_WSIZE_MTU)
+ find.fp_wsize *= (find.fp_mss + 40);
+ else if (f->fp_flags & PF_OSFP_WSIZE_MOD)
+ find.fp_wsize *= 2;
+ if (f != (f2 = pf_osfp_find(&pf_osfp_list, &find, 0))) {
+ if (f2)
+ printf("Found \"%s %s %s\" instead of "
+ "\"%s %s %s\"\n",
+ SLIST_FIRST(&f2->fp_oses)->fp_class_nm,
+ SLIST_FIRST(&f2->fp_oses)->fp_version_nm,
+ SLIST_FIRST(&f2->fp_oses)->fp_subtype_nm,
+ SLIST_FIRST(&f->fp_oses)->fp_class_nm,
+ SLIST_FIRST(&f->fp_oses)->fp_version_nm,
+ SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
+ else
+ printf("Couldn't find \"%s %s %s\"\n",
+ SLIST_FIRST(&f->fp_oses)->fp_class_nm,
+ SLIST_FIRST(&f->fp_oses)->fp_version_nm,
+ SLIST_FIRST(&f->fp_oses)->fp_subtype_nm);
+ return (f);
+ }
+ }
+ return (NULL);
+}
diff --git a/freebsd/sys/contrib/pf/net/pf_ruleset.c b/freebsd/sys/contrib/pf/net/pf_ruleset.c
new file mode 100644
index 00000000..8705d4ca
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_ruleset.c
@@ -0,0 +1,433 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: pf_ruleset.c,v 1.1 2006/10/27 13:56:51 mcbride Exp $ */
+
+/*
+ * Copyright (c) 2001 Daniel Hartmeier
+ * Copyright (c) 2002,2003 Henning Brauer
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Effort sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F30602-01-2-0537.
+ *
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/socket.h>
+#ifdef _KERNEL
+# include <freebsd/sys/systm.h>
+#endif /* _KERNEL */
+#include <freebsd/sys/mbuf.h>
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/tcp.h>
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/pfvar.h>
+
+#ifdef INET6
+#include <freebsd/netinet/ip6.h>
+#endif /* INET6 */
+
+
+#ifdef _KERNEL
+# define DPFPRINTF(format, x...) \
+ if (pf_status.debug >= PF_DEBUG_NOISY) \
+ printf(format , ##x)
+#ifdef __FreeBSD__
+#define rs_malloc(x) malloc(x, M_TEMP, M_NOWAIT)
+#else
+#define rs_malloc(x) malloc(x, M_TEMP, M_WAITOK)
+#endif
+#define rs_free(x) free(x, M_TEMP)
+
+#else
+/* Userland equivalents so we can lend code to pfctl et al. */
+
+# include <freebsd/arpa/inet.h>
+# include <freebsd/errno.h>
+# include <freebsd/stdio.h>
+# include <freebsd/stdlib.h>
+# include <freebsd/string.h>
+# define rs_malloc(x) malloc(x)
+# define rs_free(x) free(x)
+
+# ifdef PFDEBUG
+# include <freebsd/sys/stdarg.h>
+# define DPFPRINTF(format, x...) fprintf(stderr, format , ##x)
+# else
+# define DPFPRINTF(format, x...) ((void)0)
+# endif /* PFDEBUG */
+#endif /* _KERNEL */
+
+
+struct pf_anchor_global pf_anchors;
+struct pf_anchor pf_main_anchor;
+
+#ifndef __FreeBSD__
+/* XXX: hum? */
+int pf_get_ruleset_number(u_int8_t);
+void pf_init_ruleset(struct pf_ruleset *);
+int pf_anchor_setup(struct pf_rule *,
+ const struct pf_ruleset *, const char *);
+int pf_anchor_copyout(const struct pf_ruleset *,
+ const struct pf_rule *, struct pfioc_rule *);
+void pf_anchor_remove(struct pf_rule *);
+#endif
+
+static __inline int pf_anchor_compare(struct pf_anchor *, struct pf_anchor *);
+
+RB_GENERATE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
+RB_GENERATE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
+
+static __inline int
+pf_anchor_compare(struct pf_anchor *a, struct pf_anchor *b)
+{
+ int c = strcmp(a->path, b->path);
+
+ return (c ? (c < 0 ? -1 : 1) : 0);
+}
+
+int
+pf_get_ruleset_number(u_int8_t action)
+{
+ switch (action) {
+ case PF_SCRUB:
+ case PF_NOSCRUB:
+ return (PF_RULESET_SCRUB);
+ break;
+ case PF_PASS:
+ case PF_DROP:
+ return (PF_RULESET_FILTER);
+ break;
+ case PF_NAT:
+ case PF_NONAT:
+ return (PF_RULESET_NAT);
+ break;
+ case PF_BINAT:
+ case PF_NOBINAT:
+ return (PF_RULESET_BINAT);
+ break;
+ case PF_RDR:
+ case PF_NORDR:
+ return (PF_RULESET_RDR);
+ break;
+ default:
+ return (PF_RULESET_MAX);
+ break;
+ }
+}
+
+void
+pf_init_ruleset(struct pf_ruleset *ruleset)
+{
+ int i;
+
+ memset(ruleset, 0, sizeof(struct pf_ruleset));
+ for (i = 0; i < PF_RULESET_MAX; i++) {
+ TAILQ_INIT(&ruleset->rules[i].queues[0]);
+ TAILQ_INIT(&ruleset->rules[i].queues[1]);
+ ruleset->rules[i].active.ptr = &ruleset->rules[i].queues[0];
+ ruleset->rules[i].inactive.ptr = &ruleset->rules[i].queues[1];
+ }
+}
+
+struct pf_anchor *
+pf_find_anchor(const char *path)
+{
+ struct pf_anchor *key, *found;
+
+ key = (struct pf_anchor *)rs_malloc(sizeof(*key));
+ memset(key, 0, sizeof(*key));
+ strlcpy(key->path, path, sizeof(key->path));
+ found = RB_FIND(pf_anchor_global, &pf_anchors, key);
+ rs_free(key);
+ return (found);
+}
+
+struct pf_ruleset *
+pf_find_ruleset(const char *path)
+{
+ struct pf_anchor *anchor;
+
+ while (*path == '/')
+ path++;
+ if (!*path)
+ return (&pf_main_ruleset);
+ anchor = pf_find_anchor(path);
+ if (anchor == NULL)
+ return (NULL);
+ else
+ return (&anchor->ruleset);
+}
+
+struct pf_ruleset *
+pf_find_or_create_ruleset(const char *path)
+{
+ char *p, *q, *r;
+ struct pf_ruleset *ruleset;
+#ifdef __FreeBSD__
+ struct pf_anchor *anchor = NULL, *dup, *parent = NULL;
+#else
+ struct pf_anchor *anchor, *dup, *parent = NULL;
+#endif
+
+ if (path[0] == 0)
+ return (&pf_main_ruleset);
+ while (*path == '/')
+ path++;
+ ruleset = pf_find_ruleset(path);
+ if (ruleset != NULL)
+ return (ruleset);
+ p = (char *)rs_malloc(MAXPATHLEN);
+ bzero(p, MAXPATHLEN);
+ strlcpy(p, path, MAXPATHLEN);
+ while (parent == NULL && (q = strrchr(p, '/')) != NULL) {
+ *q = 0;
+ if ((ruleset = pf_find_ruleset(p)) != NULL) {
+ parent = ruleset->anchor;
+ break;
+ }
+ }
+ if (q == NULL)
+ q = p;
+ else
+ q++;
+ strlcpy(p, path, MAXPATHLEN);
+ if (!*q) {
+ rs_free(p);
+ return (NULL);
+ }
+ while ((r = strchr(q, '/')) != NULL || *q) {
+ if (r != NULL)
+ *r = 0;
+ if (!*q || strlen(q) >= PF_ANCHOR_NAME_SIZE ||
+ (parent != NULL && strlen(parent->path) >=
+ MAXPATHLEN - PF_ANCHOR_NAME_SIZE - 1)) {
+ rs_free(p);
+ return (NULL);
+ }
+ anchor = (struct pf_anchor *)rs_malloc(sizeof(*anchor));
+ if (anchor == NULL) {
+ rs_free(p);
+ return (NULL);
+ }
+ memset(anchor, 0, sizeof(*anchor));
+ RB_INIT(&anchor->children);
+ strlcpy(anchor->name, q, sizeof(anchor->name));
+ if (parent != NULL) {
+ strlcpy(anchor->path, parent->path,
+ sizeof(anchor->path));
+ strlcat(anchor->path, "/", sizeof(anchor->path));
+ }
+ strlcat(anchor->path, anchor->name, sizeof(anchor->path));
+ if ((dup = RB_INSERT(pf_anchor_global, &pf_anchors, anchor)) !=
+ NULL) {
+ printf("pf_find_or_create_ruleset: RB_INSERT1 "
+ "'%s' '%s' collides with '%s' '%s'\n",
+ anchor->path, anchor->name, dup->path, dup->name);
+ rs_free(anchor);
+ rs_free(p);
+ return (NULL);
+ }
+ if (parent != NULL) {
+ anchor->parent = parent;
+ if ((dup = RB_INSERT(pf_anchor_node, &parent->children,
+ anchor)) != NULL) {
+ printf("pf_find_or_create_ruleset: "
+ "RB_INSERT2 '%s' '%s' collides with "
+ "'%s' '%s'\n", anchor->path, anchor->name,
+ dup->path, dup->name);
+ RB_REMOVE(pf_anchor_global, &pf_anchors,
+ anchor);
+ rs_free(anchor);
+ rs_free(p);
+ return (NULL);
+ }
+ }
+ pf_init_ruleset(&anchor->ruleset);
+ anchor->ruleset.anchor = anchor;
+ parent = anchor;
+ if (r != NULL)
+ q = r + 1;
+ else
+ *q = 0;
+ }
+ rs_free(p);
+ return (&anchor->ruleset);
+}
+
+void
+pf_remove_if_empty_ruleset(struct pf_ruleset *ruleset)
+{
+ struct pf_anchor *parent;
+ int i;
+
+ while (ruleset != NULL) {
+ if (ruleset == &pf_main_ruleset || ruleset->anchor == NULL ||
+ !RB_EMPTY(&ruleset->anchor->children) ||
+ ruleset->anchor->refcnt > 0 || ruleset->tables > 0 ||
+ ruleset->topen)
+ return;
+ for (i = 0; i < PF_RULESET_MAX; ++i)
+ if (!TAILQ_EMPTY(ruleset->rules[i].active.ptr) ||
+ !TAILQ_EMPTY(ruleset->rules[i].inactive.ptr) ||
+ ruleset->rules[i].inactive.open)
+ return;
+ RB_REMOVE(pf_anchor_global, &pf_anchors, ruleset->anchor);
+ if ((parent = ruleset->anchor->parent) != NULL)
+ RB_REMOVE(pf_anchor_node, &parent->children,
+ ruleset->anchor);
+ rs_free(ruleset->anchor);
+ if (parent == NULL)
+ return;
+ ruleset = &parent->ruleset;
+ }
+}
+
+int
+pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s,
+ const char *name)
+{
+ char *p, *path;
+ struct pf_ruleset *ruleset;
+
+ r->anchor = NULL;
+ r->anchor_relative = 0;
+ r->anchor_wildcard = 0;
+ if (!name[0])
+ return (0);
+ path = (char *)rs_malloc(MAXPATHLEN);
+ bzero(path, MAXPATHLEN);
+ if (name[0] == '/')
+ strlcpy(path, name + 1, MAXPATHLEN);
+ else {
+ /* relative path */
+ r->anchor_relative = 1;
+ if (s->anchor == NULL || !s->anchor->path[0])
+ path[0] = 0;
+ else
+ strlcpy(path, s->anchor->path, MAXPATHLEN);
+ while (name[0] == '.' && name[1] == '.' && name[2] == '/') {
+ if (!path[0]) {
+ printf("pf_anchor_setup: .. beyond root\n");
+ rs_free(path);
+ return (1);
+ }
+ if ((p = strrchr(path, '/')) != NULL)
+ *p = 0;
+ else
+ path[0] = 0;
+ r->anchor_relative++;
+ name += 3;
+ }
+ if (path[0])
+ strlcat(path, "/", MAXPATHLEN);
+ strlcat(path, name, MAXPATHLEN);
+ }
+ if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) {
+ r->anchor_wildcard = 1;
+ *p = 0;
+ }
+ ruleset = pf_find_or_create_ruleset(path);
+ rs_free(path);
+ if (ruleset == NULL || ruleset->anchor == NULL) {
+ printf("pf_anchor_setup: ruleset\n");
+ return (1);
+ }
+ r->anchor = ruleset->anchor;
+ r->anchor->refcnt++;
+ return (0);
+}
+
+int
+pf_anchor_copyout(const struct pf_ruleset *rs, const struct pf_rule *r,
+ struct pfioc_rule *pr)
+{
+ pr->anchor_call[0] = 0;
+ if (r->anchor == NULL)
+ return (0);
+ if (!r->anchor_relative) {
+ strlcpy(pr->anchor_call, "/", sizeof(pr->anchor_call));
+ strlcat(pr->anchor_call, r->anchor->path,
+ sizeof(pr->anchor_call));
+ } else {
+ char *a, *p;
+ int i;
+
+ a = (char *)rs_malloc(MAXPATHLEN);
+ bzero(a, MAXPATHLEN);
+ if (rs->anchor == NULL)
+ a[0] = 0;
+ else
+ strlcpy(a, rs->anchor->path, MAXPATHLEN);
+ for (i = 1; i < r->anchor_relative; ++i) {
+ if ((p = strrchr(a, '/')) == NULL)
+ p = a;
+ *p = 0;
+ strlcat(pr->anchor_call, "../",
+ sizeof(pr->anchor_call));
+ }
+ if (strncmp(a, r->anchor->path, strlen(a))) {
+ printf("pf_anchor_copyout: '%s' '%s'\n", a,
+ r->anchor->path);
+ rs_free(a);
+ return (1);
+ }
+ if (strlen(r->anchor->path) > strlen(a))
+ strlcat(pr->anchor_call, r->anchor->path + (a[0] ?
+ strlen(a) + 1 : 0), sizeof(pr->anchor_call));
+ rs_free(a);
+ }
+ if (r->anchor_wildcard)
+ strlcat(pr->anchor_call, pr->anchor_call[0] ? "/*" : "*",
+ sizeof(pr->anchor_call));
+ return (0);
+}
+
+void
+pf_anchor_remove(struct pf_rule *r)
+{
+ if (r->anchor == NULL)
+ return;
+ if (r->anchor->refcnt <= 0) {
+ printf("pf_anchor_remove: broken refcount\n");
+ r->anchor = NULL;
+ return;
+ }
+ if (!--r->anchor->refcnt)
+ pf_remove_if_empty_ruleset(&r->anchor->ruleset);
+ r->anchor = NULL;
+}
diff --git a/freebsd/sys/contrib/pf/net/pf_subr.c b/freebsd/sys/contrib/pf/net/pf_subr.c
new file mode 100644
index 00000000..14cf232e
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_subr.c
@@ -0,0 +1,170 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1990, 1993, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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 <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/libkern.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/md5.h>
+#include <freebsd/sys/time.h>
+#include <freebsd/sys/random.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/socketvar.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/time.h>
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/if_types.h>
+#include <freebsd/net/bpf.h>
+#include <freebsd/net/route.h>
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_var.h>
+#include <freebsd/netinet/tcp.h>
+#include <freebsd/netinet/tcp_seq.h>
+#include <freebsd/netinet/udp.h>
+#include <freebsd/netinet/ip_icmp.h>
+#include <freebsd/netinet/in_pcb.h>
+#include <freebsd/netinet/tcp_timer.h>
+#include <freebsd/netinet/tcp_var.h>
+#include <freebsd/netinet/if_ether.h>
+#include <freebsd/net/pfvar.h>
+
+/*
+ * Following is where TCP initial sequence number generation occurs.
+ *
+ * There are two places where we must use initial sequence numbers:
+ * 1. In SYN-ACK packets.
+ * 2. In SYN packets.
+ *
+ * All ISNs for SYN-ACK packets are generated by the syncache. See
+ * tcp_syncache.c for details.
+ *
+ * The ISNs in SYN packets must be monotonic; TIME_WAIT recycling
+ * depends on this property. In addition, these ISNs should be
+ * unguessable so as to prevent connection hijacking. To satisfy
+ * the requirements of this situation, the algorithm outlined in
+ * RFC 1948 is used, with only small modifications.
+ *
+ * Implementation details:
+ *
+ * Time is based off the system timer, and is corrected so that it
+ * increases by one megabyte per second. This allows for proper
+ * recycling on high speed LANs while still leaving over an hour
+ * before rollover.
+ *
+ * As reading the *exact* system time is too expensive to be done
+ * whenever setting up a TCP connection, we increment the time
+ * offset in two ways. First, a small random positive increment
+ * is added to isn_offset for each connection that is set up.
+ * Second, the function tcp_isn_tick fires once per clock tick
+ * and increments isn_offset as necessary so that sequence numbers
+ * are incremented at approximately ISN_BYTES_PER_SECOND. The
+ * random positive increments serve only to ensure that the same
+ * exact sequence number is never sent out twice (as could otherwise
+ * happen when a port is recycled in less than the system tick
+ * interval.)
+ *
+ * net.inet.tcp.isn_reseed_interval controls the number of seconds
+ * between seeding of isn_secret. This is normally set to zero,
+ * as reseeding should not be necessary.
+ *
+ * Locking of the global variables isn_secret, isn_last_reseed, isn_offset,
+ * isn_offset_old, and isn_ctx is performed using the TCP pcbinfo lock. In
+ * general, this means holding an exclusive (write) lock.
+ */
+
+#define ISN_BYTES_PER_SECOND 1048576
+#define ISN_STATIC_INCREMENT 4096
+#define ISN_RANDOM_INCREMENT (4096 - 1)
+
+static u_char pf_isn_secret[32];
+static int pf_isn_last_reseed;
+static u_int32_t pf_isn_offset;
+
+u_int32_t
+pf_new_isn(struct pf_state *s)
+{
+ MD5_CTX isn_ctx;
+ u_int32_t md5_buffer[4];
+ u_int32_t new_isn;
+ struct pf_state_host *src, *dst;
+
+ /* Seed if this is the first use, reseed if requested. */
+ if (pf_isn_last_reseed == 0) {
+ read_random(&pf_isn_secret, sizeof(pf_isn_secret));
+ pf_isn_last_reseed = ticks;
+ }
+
+ if (s->direction == PF_IN) {
+ src = &s->ext;
+ dst = &s->gwy;
+ } else {
+ src = &s->lan;
+ dst = &s->ext;
+ }
+
+ /* Compute the md5 hash and return the ISN. */
+ MD5Init(&isn_ctx);
+ MD5Update(&isn_ctx, (u_char *) &dst->port, sizeof(u_short));
+ MD5Update(&isn_ctx, (u_char *) &src->port, sizeof(u_short));
+#ifdef INET6
+ if (s->af == AF_INET6) {
+ MD5Update(&isn_ctx, (u_char *) &dst->addr,
+ sizeof(struct in6_addr));
+ MD5Update(&isn_ctx, (u_char *) &src->addr,
+ sizeof(struct in6_addr));
+ } else
+#endif
+ {
+ MD5Update(&isn_ctx, (u_char *) &dst->addr,
+ sizeof(struct in_addr));
+ MD5Update(&isn_ctx, (u_char *) &src->addr,
+ sizeof(struct in_addr));
+ }
+ MD5Update(&isn_ctx, (u_char *) &pf_isn_secret, sizeof(pf_isn_secret));
+ MD5Final((u_char *) &md5_buffer, &isn_ctx);
+ new_isn = (tcp_seq) md5_buffer[0];
+ pf_isn_offset += ISN_STATIC_INCREMENT +
+ (arc4random() & ISN_RANDOM_INCREMENT);
+ new_isn += pf_isn_offset;
+ return (new_isn);
+}
diff --git a/freebsd/sys/contrib/pf/net/pf_table.c b/freebsd/sys/contrib/pf/net/pf_table.c
new file mode 100644
index 00000000..b07fb7c0
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pf_table.c
@@ -0,0 +1,2363 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $OpenBSD: pf_table.c,v 1.68 2006/05/02 10:08:45 dhartmei Exp $ */
+
+/*
+ * Copyright (c) 2002 Cedric Berger
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef __FreeBSD__
+#include <freebsd/local/opt_inet.h>
+#include <freebsd/local/opt_inet6.h>
+
+#include <freebsd/sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#endif
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/socket.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/kernel.h>
+#include <freebsd/sys/lock.h>
+#include <freebsd/sys/rwlock.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/malloc.h>
+#endif
+
+#include <freebsd/net/if.h>
+#include <freebsd/net/route.h>
+#include <freebsd/netinet/in.h>
+#ifndef __FreeBSD__
+#include <freebsd/netinet/ip_ipsp.h>
+#endif
+
+#include <freebsd/net/pfvar.h>
+
+#define ACCEPT_FLAGS(oklist) \
+ do { \
+ if ((flags & ~(oklist)) & \
+ PFR_FLAG_ALLMASK) \
+ return (EINVAL); \
+ } while (0)
+
+#ifdef __FreeBSD__
+static inline int
+_copyin(const void *uaddr, void *kaddr, size_t len)
+{
+ int r;
+
+ PF_UNLOCK();
+ r = copyin(uaddr, kaddr, len);
+ PF_LOCK();
+
+ return (r);
+}
+
+static inline int
+_copyout(const void *uaddr, void *kaddr, size_t len)
+{
+ int r;
+
+ PF_UNLOCK();
+ r = copyout(uaddr, kaddr, len);
+ PF_LOCK();
+
+ return (r);
+}
+
+#define COPYIN(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ _copyin((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
+#define COPYOUT(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ _copyout((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
+#else
+
+#define COPYIN(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ copyin((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
+#define COPYOUT(from, to, size) \
+ ((flags & PFR_FLAG_USERIOCTL) ? \
+ copyout((from), (to), (size)) : \
+ (bcopy((from), (to), (size)), 0))
+
+#endif
+
+#define FILLIN_SIN(sin, addr) \
+ do { \
+ (sin).sin_len = sizeof(sin); \
+ (sin).sin_family = AF_INET; \
+ (sin).sin_addr = (addr); \
+ } while (0)
+
+#define FILLIN_SIN6(sin6, addr) \
+ do { \
+ (sin6).sin6_len = sizeof(sin6); \
+ (sin6).sin6_family = AF_INET6; \
+ (sin6).sin6_addr = (addr); \
+ } while (0)
+
+#define SWAP(type, a1, a2) \
+ do { \
+ type tmp = a1; \
+ a1 = a2; \
+ a2 = tmp; \
+ } while (0)
+
+#define SUNION2PF(su, af) (((af)==AF_INET) ? \
+ (struct pf_addr *)&(su)->sin.sin_addr : \
+ (struct pf_addr *)&(su)->sin6.sin6_addr)
+
+#define AF_BITS(af) (((af)==AF_INET)?32:128)
+#define ADDR_NETWORK(ad) ((ad)->pfra_net < AF_BITS((ad)->pfra_af))
+#define KENTRY_NETWORK(ke) ((ke)->pfrke_net < AF_BITS((ke)->pfrke_af))
+#define KENTRY_RNF_ROOT(ke) \
+ ((((struct radix_node *)(ke))->rn_flags & RNF_ROOT) != 0)
+
+#define NO_ADDRESSES (-1)
+#define ENQUEUE_UNMARKED_ONLY (1)
+#define INVERT_NEG_FLAG (1)
+
+struct pfr_walktree {
+ enum pfrw_op {
+ PFRW_MARK,
+ PFRW_SWEEP,
+ PFRW_ENQUEUE,
+ PFRW_GET_ADDRS,
+ PFRW_GET_ASTATS,
+ PFRW_POOL_GET,
+ PFRW_DYNADDR_UPDATE
+ } pfrw_op;
+ union {
+ struct pfr_addr *pfrw1_addr;
+ struct pfr_astats *pfrw1_astats;
+ struct pfr_kentryworkq *pfrw1_workq;
+ struct pfr_kentry *pfrw1_kentry;
+ struct pfi_dynaddr *pfrw1_dyn;
+ } pfrw_1;
+ int pfrw_free;
+ int pfrw_flags;
+};
+#define pfrw_addr pfrw_1.pfrw1_addr
+#define pfrw_astats pfrw_1.pfrw1_astats
+#define pfrw_workq pfrw_1.pfrw1_workq
+#define pfrw_kentry pfrw_1.pfrw1_kentry
+#define pfrw_dyn pfrw_1.pfrw1_dyn
+#define pfrw_cnt pfrw_free
+
+#define senderr(e) do { rv = (e); goto _bad; } while (0)
+
+#ifdef __FreeBSD__
+uma_zone_t pfr_ktable_pl;
+uma_zone_t pfr_kentry_pl;
+uma_zone_t pfr_kentry_pl2;
+#else
+struct pool pfr_ktable_pl;
+struct pool pfr_kentry_pl;
+struct pool pfr_kentry_pl2;
+#endif
+struct sockaddr_in pfr_sin;
+struct sockaddr_in6 pfr_sin6;
+union sockaddr_union pfr_mask;
+struct pf_addr pfr_ffaddr;
+
+void pfr_copyout_addr(struct pfr_addr *,
+ struct pfr_kentry *ke);
+int pfr_validate_addr(struct pfr_addr *);
+void pfr_enqueue_addrs(struct pfr_ktable *,
+ struct pfr_kentryworkq *, int *, int);
+void pfr_mark_addrs(struct pfr_ktable *);
+struct pfr_kentry *pfr_lookup_addr(struct pfr_ktable *,
+ struct pfr_addr *, int);
+struct pfr_kentry *pfr_create_kentry(struct pfr_addr *, int);
+void pfr_destroy_kentries(struct pfr_kentryworkq *);
+void pfr_destroy_kentry(struct pfr_kentry *);
+void pfr_insert_kentries(struct pfr_ktable *,
+ struct pfr_kentryworkq *, long);
+void pfr_remove_kentries(struct pfr_ktable *,
+ struct pfr_kentryworkq *);
+void pfr_clstats_kentries(struct pfr_kentryworkq *, long,
+ int);
+void pfr_reset_feedback(struct pfr_addr *, int, int);
+void pfr_prepare_network(union sockaddr_union *, int, int);
+int pfr_route_kentry(struct pfr_ktable *,
+ struct pfr_kentry *);
+int pfr_unroute_kentry(struct pfr_ktable *,
+ struct pfr_kentry *);
+int pfr_walktree(struct radix_node *, void *);
+int pfr_validate_table(struct pfr_table *, int, int);
+int pfr_fix_anchor(char *);
+void pfr_commit_ktable(struct pfr_ktable *, long);
+void pfr_insert_ktables(struct pfr_ktableworkq *);
+void pfr_insert_ktable(struct pfr_ktable *);
+void pfr_setflags_ktables(struct pfr_ktableworkq *);
+void pfr_setflags_ktable(struct pfr_ktable *, int);
+void pfr_clstats_ktables(struct pfr_ktableworkq *, long,
+ int);
+void pfr_clstats_ktable(struct pfr_ktable *, long, int);
+struct pfr_ktable *pfr_create_ktable(struct pfr_table *, long, int);
+void pfr_destroy_ktables(struct pfr_ktableworkq *, int);
+void pfr_destroy_ktable(struct pfr_ktable *, int);
+int pfr_ktable_compare(struct pfr_ktable *,
+ struct pfr_ktable *);
+struct pfr_ktable *pfr_lookup_table(struct pfr_table *);
+void pfr_clean_node_mask(struct pfr_ktable *,
+ struct pfr_kentryworkq *);
+int pfr_table_count(struct pfr_table *, int);
+int pfr_skip_table(struct pfr_table *,
+ struct pfr_ktable *, int);
+struct pfr_kentry *pfr_kentry_byidx(struct pfr_ktable *, int, int);
+
+RB_PROTOTYPE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
+RB_GENERATE(pfr_ktablehead, pfr_ktable, pfrkt_tree, pfr_ktable_compare);
+
+struct pfr_ktablehead pfr_ktables;
+struct pfr_table pfr_nulltable;
+int pfr_ktable_cnt;
+
+void
+pfr_initialize(void)
+{
+#ifndef __FreeBSD__
+ pool_init(&pfr_ktable_pl, sizeof(struct pfr_ktable), 0, 0, 0,
+ "pfrktable", &pool_allocator_oldnointr);
+ pool_init(&pfr_kentry_pl, sizeof(struct pfr_kentry), 0, 0, 0,
+ "pfrkentry", &pool_allocator_oldnointr);
+ pool_init(&pfr_kentry_pl2, sizeof(struct pfr_kentry), 0, 0, 0,
+ "pfrkentry2", NULL);
+#endif
+
+ pfr_sin.sin_len = sizeof(pfr_sin);
+ pfr_sin.sin_family = AF_INET;
+ pfr_sin6.sin6_len = sizeof(pfr_sin6);
+ pfr_sin6.sin6_family = AF_INET6;
+
+ memset(&pfr_ffaddr, 0xff, sizeof(pfr_ffaddr));
+}
+
+int
+pfr_clr_addrs(struct pfr_table *tbl, int *ndel, int flags)
+{
+ struct pfr_ktable *kt;
+ struct pfr_kentryworkq workq;
+ int s;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+ if (kt->pfrkt_flags & PFR_TFLAG_CONST)
+ return (EPERM);
+ pfr_enqueue_addrs(kt, &workq, ndel, 0);
+
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ s = 0;
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_remove_kentries(kt, &workq);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ if (kt->pfrkt_cnt) {
+ printf("pfr_clr_addrs: corruption detected (%d).\n",
+ kt->pfrkt_cnt);
+ kt->pfrkt_cnt = 0;
+ }
+ }
+ return (0);
+}
+
+int
+pfr_add_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *nadd, int flags)
+{
+ struct pfr_ktable *kt, *tmpkt;
+ struct pfr_kentryworkq workq;
+ struct pfr_kentry *p, *q;
+ struct pfr_addr ad;
+ int i, rv, s = 0, xadd = 0;
+ long tzero = time_second;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+ if (kt->pfrkt_flags & PFR_TFLAG_CONST)
+ return (EPERM);
+ tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
+ if (tmpkt == NULL)
+ return (ENOMEM);
+ SLIST_INIT(&workq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ senderr(EFAULT);
+ if (pfr_validate_addr(&ad))
+ senderr(EINVAL);
+ p = pfr_lookup_addr(kt, &ad, 1);
+ q = pfr_lookup_addr(tmpkt, &ad, 1);
+ if (flags & PFR_FLAG_FEEDBACK) {
+ if (q != NULL)
+ ad.pfra_fback = PFR_FB_DUPLICATE;
+ else if (p == NULL)
+ ad.pfra_fback = PFR_FB_ADDED;
+ else if (p->pfrke_not != ad.pfra_not)
+ ad.pfra_fback = PFR_FB_CONFLICT;
+ else
+ ad.pfra_fback = PFR_FB_NONE;
+ }
+ if (p == NULL && q == NULL) {
+ p = pfr_create_kentry(&ad, 0);
+ if (p == NULL)
+ senderr(ENOMEM);
+ if (pfr_route_kentry(tmpkt, p)) {
+ pfr_destroy_kentry(p);
+ ad.pfra_fback = PFR_FB_NONE;
+ } else {
+ SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
+ xadd++;
+ }
+ }
+ if (flags & PFR_FLAG_FEEDBACK) {
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ senderr(EFAULT);
+ }
+ }
+ pfr_clean_node_mask(tmpkt, &workq);
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_insert_kentries(kt, &workq, tzero);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ } else
+ pfr_destroy_kentries(&workq);
+ if (nadd != NULL)
+ *nadd = xadd;
+ pfr_destroy_ktable(tmpkt, 0);
+ return (0);
+_bad:
+ pfr_clean_node_mask(tmpkt, &workq);
+ pfr_destroy_kentries(&workq);
+ if (flags & PFR_FLAG_FEEDBACK)
+ pfr_reset_feedback(addr, size, flags);
+ pfr_destroy_ktable(tmpkt, 0);
+ return (rv);
+}
+
+int
+pfr_del_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *ndel, int flags)
+{
+ struct pfr_ktable *kt;
+ struct pfr_kentryworkq workq;
+ struct pfr_kentry *p;
+ struct pfr_addr ad;
+ int i, rv, s = 0, xdel = 0, log = 1;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+ if (pfr_validate_table(tbl, 0, flags & PFR_FLAG_USERIOCTL))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+ if (kt->pfrkt_flags & PFR_TFLAG_CONST)
+ return (EPERM);
+ /*
+ * there are two algorithms to choose from here.
+ * with:
+ * n: number of addresses to delete
+ * N: number of addresses in the table
+ *
+ * one is O(N) and is better for large 'n'
+ * one is O(n*LOG(N)) and is better for small 'n'
+ *
+ * following code try to decide which one is best.
+ */
+ for (i = kt->pfrkt_cnt; i > 0; i >>= 1)
+ log++;
+ if (size > kt->pfrkt_cnt/log) {
+ /* full table scan */
+ pfr_mark_addrs(kt);
+ } else {
+ /* iterate over addresses to delete */
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ return (EFAULT);
+ if (pfr_validate_addr(&ad))
+ return (EINVAL);
+ p = pfr_lookup_addr(kt, &ad, 1);
+ if (p != NULL)
+ p->pfrke_mark = 0;
+ }
+ }
+ SLIST_INIT(&workq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ senderr(EFAULT);
+ if (pfr_validate_addr(&ad))
+ senderr(EINVAL);
+ p = pfr_lookup_addr(kt, &ad, 1);
+ if (flags & PFR_FLAG_FEEDBACK) {
+ if (p == NULL)
+ ad.pfra_fback = PFR_FB_NONE;
+ else if (p->pfrke_not != ad.pfra_not)
+ ad.pfra_fback = PFR_FB_CONFLICT;
+ else if (p->pfrke_mark)
+ ad.pfra_fback = PFR_FB_DUPLICATE;
+ else
+ ad.pfra_fback = PFR_FB_DELETED;
+ }
+ if (p != NULL && p->pfrke_not == ad.pfra_not &&
+ !p->pfrke_mark) {
+ p->pfrke_mark = 1;
+ SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
+ xdel++;
+ }
+ if (flags & PFR_FLAG_FEEDBACK)
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ senderr(EFAULT);
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_remove_kentries(kt, &workq);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ }
+ if (ndel != NULL)
+ *ndel = xdel;
+ return (0);
+_bad:
+ if (flags & PFR_FLAG_FEEDBACK)
+ pfr_reset_feedback(addr, size, flags);
+ return (rv);
+}
+
+int
+pfr_set_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *size2, int *nadd, int *ndel, int *nchange, int flags,
+ u_int32_t ignore_pfrt_flags)
+{
+ struct pfr_ktable *kt, *tmpkt;
+ struct pfr_kentryworkq addq, delq, changeq;
+ struct pfr_kentry *p, *q;
+ struct pfr_addr ad;
+ int i, rv, s = 0, xadd = 0, xdel = 0, xchange = 0;
+ long tzero = time_second;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+ if (pfr_validate_table(tbl, ignore_pfrt_flags, flags &
+ PFR_FLAG_USERIOCTL))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+ if (kt->pfrkt_flags & PFR_TFLAG_CONST)
+ return (EPERM);
+ tmpkt = pfr_create_ktable(&pfr_nulltable, 0, 0);
+ if (tmpkt == NULL)
+ return (ENOMEM);
+ pfr_mark_addrs(kt);
+ SLIST_INIT(&addq);
+ SLIST_INIT(&delq);
+ SLIST_INIT(&changeq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ senderr(EFAULT);
+ if (pfr_validate_addr(&ad))
+ senderr(EINVAL);
+ ad.pfra_fback = PFR_FB_NONE;
+ p = pfr_lookup_addr(kt, &ad, 1);
+ if (p != NULL) {
+ if (p->pfrke_mark) {
+ ad.pfra_fback = PFR_FB_DUPLICATE;
+ goto _skip;
+ }
+ p->pfrke_mark = 1;
+ if (p->pfrke_not != ad.pfra_not) {
+ SLIST_INSERT_HEAD(&changeq, p, pfrke_workq);
+ ad.pfra_fback = PFR_FB_CHANGED;
+ xchange++;
+ }
+ } else {
+ q = pfr_lookup_addr(tmpkt, &ad, 1);
+ if (q != NULL) {
+ ad.pfra_fback = PFR_FB_DUPLICATE;
+ goto _skip;
+ }
+ p = pfr_create_kentry(&ad, 0);
+ if (p == NULL)
+ senderr(ENOMEM);
+ if (pfr_route_kentry(tmpkt, p)) {
+ pfr_destroy_kentry(p);
+ ad.pfra_fback = PFR_FB_NONE;
+ } else {
+ SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
+ ad.pfra_fback = PFR_FB_ADDED;
+ xadd++;
+ }
+ }
+_skip:
+ if (flags & PFR_FLAG_FEEDBACK)
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ senderr(EFAULT);
+ }
+ pfr_enqueue_addrs(kt, &delq, &xdel, ENQUEUE_UNMARKED_ONLY);
+ if ((flags & PFR_FLAG_FEEDBACK) && *size2) {
+ if (*size2 < size+xdel) {
+ *size2 = size+xdel;
+ senderr(0);
+ }
+ i = 0;
+ SLIST_FOREACH(p, &delq, pfrke_workq) {
+ pfr_copyout_addr(&ad, p);
+ ad.pfra_fback = PFR_FB_DELETED;
+ if (COPYOUT(&ad, addr+size+i, sizeof(ad)))
+ senderr(EFAULT);
+ i++;
+ }
+ }
+ pfr_clean_node_mask(tmpkt, &addq);
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_insert_kentries(kt, &addq, tzero);
+ pfr_remove_kentries(kt, &delq);
+ pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ } else
+ pfr_destroy_kentries(&addq);
+ if (nadd != NULL)
+ *nadd = xadd;
+ if (ndel != NULL)
+ *ndel = xdel;
+ if (nchange != NULL)
+ *nchange = xchange;
+ if ((flags & PFR_FLAG_FEEDBACK) && size2)
+ *size2 = size+xdel;
+ pfr_destroy_ktable(tmpkt, 0);
+ return (0);
+_bad:
+ pfr_clean_node_mask(tmpkt, &addq);
+ pfr_destroy_kentries(&addq);
+ if (flags & PFR_FLAG_FEEDBACK)
+ pfr_reset_feedback(addr, size, flags);
+ pfr_destroy_ktable(tmpkt, 0);
+ return (rv);
+}
+
+int
+pfr_tst_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *nmatch, int flags)
+{
+ struct pfr_ktable *kt;
+ struct pfr_kentry *p;
+ struct pfr_addr ad;
+ int i, xmatch = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_REPLACE);
+ if (pfr_validate_table(tbl, 0, 0))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ return (EFAULT);
+ if (pfr_validate_addr(&ad))
+ return (EINVAL);
+ if (ADDR_NETWORK(&ad))
+ return (EINVAL);
+ p = pfr_lookup_addr(kt, &ad, 0);
+ if (flags & PFR_FLAG_REPLACE)
+ pfr_copyout_addr(&ad, p);
+ ad.pfra_fback = (p == NULL) ? PFR_FB_NONE :
+ (p->pfrke_not ? PFR_FB_NOTMATCH : PFR_FB_MATCH);
+ if (p != NULL && !p->pfrke_not)
+ xmatch++;
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ return (EFAULT);
+ }
+ if (nmatch != NULL)
+ *nmatch = xmatch;
+ return (0);
+}
+
+int
+pfr_get_addrs(struct pfr_table *tbl, struct pfr_addr *addr, int *size,
+ int flags)
+{
+ struct pfr_ktable *kt;
+ struct pfr_walktree w;
+ int rv;
+
+ ACCEPT_FLAGS(0);
+ if (pfr_validate_table(tbl, 0, 0))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+ if (kt->pfrkt_cnt > *size) {
+ *size = kt->pfrkt_cnt;
+ return (0);
+ }
+
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_GET_ADDRS;
+ w.pfrw_addr = addr;
+ w.pfrw_free = kt->pfrkt_cnt;
+ w.pfrw_flags = flags;
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
+ rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
+ if (!rv)
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
+ &w);
+#else
+ rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
+ if (rv)
+ return (rv);
+
+ if (w.pfrw_free) {
+ printf("pfr_get_addrs: corruption detected (%d).\n",
+ w.pfrw_free);
+ return (ENOTTY);
+ }
+ *size = kt->pfrkt_cnt;
+ return (0);
+}
+
+int
+pfr_get_astats(struct pfr_table *tbl, struct pfr_astats *addr, int *size,
+ int flags)
+{
+ struct pfr_ktable *kt;
+ struct pfr_walktree w;
+ struct pfr_kentryworkq workq;
+ int rv, s = 0;
+ long tzero = time_second;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC); /* XXX PFR_FLAG_CLSTATS disabled */
+ if (pfr_validate_table(tbl, 0, 0))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+ if (kt->pfrkt_cnt > *size) {
+ *size = kt->pfrkt_cnt;
+ return (0);
+ }
+
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_GET_ASTATS;
+ w.pfrw_astats = addr;
+ w.pfrw_free = kt->pfrkt_cnt;
+ w.pfrw_flags = flags;
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
+ rv = rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
+ if (!rv)
+#ifdef __FreeBSD__
+ rv = kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
+ &w);
+#else
+ rv = rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
+ if (!rv && (flags & PFR_FLAG_CLSTATS)) {
+ pfr_enqueue_addrs(kt, &workq, NULL, 0);
+ pfr_clstats_kentries(&workq, tzero, 0);
+ }
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ if (rv)
+ return (rv);
+
+ if (w.pfrw_free) {
+ printf("pfr_get_astats: corruption detected (%d).\n",
+ w.pfrw_free);
+ return (ENOTTY);
+ }
+ *size = kt->pfrkt_cnt;
+ return (0);
+}
+
+int
+pfr_clr_astats(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *nzero, int flags)
+{
+ struct pfr_ktable *kt;
+ struct pfr_kentryworkq workq;
+ struct pfr_kentry *p;
+ struct pfr_addr ad;
+ int i, rv, s = 0, xzero = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_FEEDBACK);
+ if (pfr_validate_table(tbl, 0, 0))
+ return (EINVAL);
+ kt = pfr_lookup_table(tbl);
+ if (kt == NULL || !(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (ESRCH);
+ SLIST_INIT(&workq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ senderr(EFAULT);
+ if (pfr_validate_addr(&ad))
+ senderr(EINVAL);
+ p = pfr_lookup_addr(kt, &ad, 1);
+ if (flags & PFR_FLAG_FEEDBACK) {
+ ad.pfra_fback = (p != NULL) ?
+ PFR_FB_CLEARED : PFR_FB_NONE;
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ senderr(EFAULT);
+ }
+ if (p != NULL) {
+ SLIST_INSERT_HEAD(&workq, p, pfrke_workq);
+ xzero++;
+ }
+ }
+
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_clstats_kentries(&workq, 0, 0);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ }
+ if (nzero != NULL)
+ *nzero = xzero;
+ return (0);
+_bad:
+ if (flags & PFR_FLAG_FEEDBACK)
+ pfr_reset_feedback(addr, size, flags);
+ return (rv);
+}
+
+int
+pfr_validate_addr(struct pfr_addr *ad)
+{
+ int i;
+
+ switch (ad->pfra_af) {
+#ifdef INET
+ case AF_INET:
+ if (ad->pfra_net > 32)
+ return (-1);
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ if (ad->pfra_net > 128)
+ return (-1);
+ break;
+#endif /* INET6 */
+ default:
+ return (-1);
+ }
+ if (ad->pfra_net < 128 &&
+ (((caddr_t)ad)[ad->pfra_net/8] & (0xFF >> (ad->pfra_net%8))))
+ return (-1);
+ for (i = (ad->pfra_net+7)/8; i < sizeof(ad->pfra_u); i++)
+ if (((caddr_t)ad)[i])
+ return (-1);
+ if (ad->pfra_not && ad->pfra_not != 1)
+ return (-1);
+ if (ad->pfra_fback)
+ return (-1);
+ return (0);
+}
+
+void
+pfr_enqueue_addrs(struct pfr_ktable *kt, struct pfr_kentryworkq *workq,
+ int *naddr, int sweep)
+{
+ struct pfr_walktree w;
+
+ SLIST_INIT(workq);
+ bzero(&w, sizeof(w));
+ w.pfrw_op = sweep ? PFRW_SWEEP : PFRW_ENQUEUE;
+ w.pfrw_workq = workq;
+ if (kt->pfrkt_ip4 != NULL)
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree,
+ &w))
+#else
+ if (rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w))
+#endif
+ printf("pfr_enqueue_addrs: IPv4 walktree failed.\n");
+ if (kt->pfrkt_ip6 != NULL)
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree,
+ &w))
+#else
+ if (rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w))
+#endif
+ printf("pfr_enqueue_addrs: IPv6 walktree failed.\n");
+ if (naddr != NULL)
+ *naddr = w.pfrw_cnt;
+}
+
+void
+pfr_mark_addrs(struct pfr_ktable *kt)
+{
+ struct pfr_walktree w;
+
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_MARK;
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w))
+#else
+ if (rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w))
+#endif
+ printf("pfr_mark_addrs: IPv4 walktree failed.\n");
+#ifdef __FreeBSD__
+ if (kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w))
+#else
+ if (rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w))
+#endif
+ printf("pfr_mark_addrs: IPv6 walktree failed.\n");
+}
+
+
+struct pfr_kentry *
+pfr_lookup_addr(struct pfr_ktable *kt, struct pfr_addr *ad, int exact)
+{
+ union sockaddr_union sa, mask;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
+ struct pfr_kentry *ke;
+ int s;
+
+ bzero(&sa, sizeof(sa));
+ if (ad->pfra_af == AF_INET) {
+ FILLIN_SIN(sa.sin, ad->pfra_ip4addr);
+ head = kt->pfrkt_ip4;
+ } else if ( ad->pfra_af == AF_INET6 ) {
+ FILLIN_SIN6(sa.sin6, ad->pfra_ip6addr);
+ head = kt->pfrkt_ip6;
+ }
+ if (ADDR_NETWORK(ad)) {
+ pfr_prepare_network(&mask, ad->pfra_af, ad->pfra_net);
+ s = splsoftnet(); /* rn_lookup makes use of globals */
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ ke = (struct pfr_kentry *)rn_lookup(&sa, &mask, head);
+ splx(s);
+ if (ke && KENTRY_RNF_ROOT(ke))
+ ke = NULL;
+ } else {
+ ke = (struct pfr_kentry *)rn_match(&sa, head);
+ if (ke && KENTRY_RNF_ROOT(ke))
+ ke = NULL;
+ if (exact && ke && KENTRY_NETWORK(ke))
+ ke = NULL;
+ }
+ return (ke);
+}
+
+struct pfr_kentry *
+pfr_create_kentry(struct pfr_addr *ad, int intr)
+{
+ struct pfr_kentry *ke;
+
+ if (intr)
+ ke = pool_get(&pfr_kentry_pl2, PR_NOWAIT);
+ else
+ ke = pool_get(&pfr_kentry_pl, PR_NOWAIT);
+ if (ke == NULL)
+ return (NULL);
+ bzero(ke, sizeof(*ke));
+
+ if (ad->pfra_af == AF_INET)
+ FILLIN_SIN(ke->pfrke_sa.sin, ad->pfra_ip4addr);
+ else if (ad->pfra_af == AF_INET6)
+ FILLIN_SIN6(ke->pfrke_sa.sin6, ad->pfra_ip6addr);
+ ke->pfrke_af = ad->pfra_af;
+ ke->pfrke_net = ad->pfra_net;
+ ke->pfrke_not = ad->pfra_not;
+ ke->pfrke_intrpool = intr;
+ return (ke);
+}
+
+void
+pfr_destroy_kentries(struct pfr_kentryworkq *workq)
+{
+ struct pfr_kentry *p, *q;
+
+ for (p = SLIST_FIRST(workq); p != NULL; p = q) {
+ q = SLIST_NEXT(p, pfrke_workq);
+ pfr_destroy_kentry(p);
+ }
+}
+
+void
+pfr_destroy_kentry(struct pfr_kentry *ke)
+{
+ if (ke->pfrke_intrpool)
+ pool_put(&pfr_kentry_pl2, ke);
+ else
+ pool_put(&pfr_kentry_pl, ke);
+}
+
+void
+pfr_insert_kentries(struct pfr_ktable *kt,
+ struct pfr_kentryworkq *workq, long tzero)
+{
+ struct pfr_kentry *p;
+ int rv, n = 0;
+
+ SLIST_FOREACH(p, workq, pfrke_workq) {
+ rv = pfr_route_kentry(kt, p);
+ if (rv) {
+ printf("pfr_insert_kentries: cannot route entry "
+ "(code=%d).\n", rv);
+ break;
+ }
+ p->pfrke_tzero = tzero;
+ n++;
+ }
+ kt->pfrkt_cnt += n;
+}
+
+int
+pfr_insert_kentry(struct pfr_ktable *kt, struct pfr_addr *ad, long tzero)
+{
+ struct pfr_kentry *p;
+ int rv;
+
+ p = pfr_lookup_addr(kt, ad, 1);
+ if (p != NULL)
+ return (0);
+ p = pfr_create_kentry(ad, 1);
+ if (p == NULL)
+ return (EINVAL);
+
+ rv = pfr_route_kentry(kt, p);
+ if (rv)
+ return (rv);
+
+ p->pfrke_tzero = tzero;
+ kt->pfrkt_cnt++;
+
+ return (0);
+}
+
+void
+pfr_remove_kentries(struct pfr_ktable *kt,
+ struct pfr_kentryworkq *workq)
+{
+ struct pfr_kentry *p;
+ int n = 0;
+
+ SLIST_FOREACH(p, workq, pfrke_workq) {
+ pfr_unroute_kentry(kt, p);
+ n++;
+ }
+ kt->pfrkt_cnt -= n;
+ pfr_destroy_kentries(workq);
+}
+
+void
+pfr_clean_node_mask(struct pfr_ktable *kt,
+ struct pfr_kentryworkq *workq)
+{
+ struct pfr_kentry *p;
+
+ SLIST_FOREACH(p, workq, pfrke_workq)
+ pfr_unroute_kentry(kt, p);
+}
+
+void
+pfr_clstats_kentries(struct pfr_kentryworkq *workq, long tzero, int negchange)
+{
+ struct pfr_kentry *p;
+ int s;
+
+ SLIST_FOREACH(p, workq, pfrke_workq) {
+ s = splsoftnet();
+ if (negchange)
+ p->pfrke_not = !p->pfrke_not;
+ bzero(p->pfrke_packets, sizeof(p->pfrke_packets));
+ bzero(p->pfrke_bytes, sizeof(p->pfrke_bytes));
+ splx(s);
+ p->pfrke_tzero = tzero;
+ }
+}
+
+void
+pfr_reset_feedback(struct pfr_addr *addr, int size, int flags)
+{
+ struct pfr_addr ad;
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ break;
+ ad.pfra_fback = PFR_FB_NONE;
+ if (COPYOUT(&ad, addr+i, sizeof(ad)))
+ break;
+ }
+}
+
+void
+pfr_prepare_network(union sockaddr_union *sa, int af, int net)
+{
+ int i;
+
+ bzero(sa, sizeof(*sa));
+ if (af == AF_INET) {
+ sa->sin.sin_len = sizeof(sa->sin);
+ sa->sin.sin_family = AF_INET;
+ sa->sin.sin_addr.s_addr = net ? htonl(-1 << (32-net)) : 0;
+ } else if (af == AF_INET6) {
+ sa->sin6.sin6_len = sizeof(sa->sin6);
+ sa->sin6.sin6_family = AF_INET6;
+ for (i = 0; i < 4; i++) {
+ if (net <= 32) {
+ sa->sin6.sin6_addr.s6_addr32[i] =
+ net ? htonl(-1 << (32-net)) : 0;
+ break;
+ }
+ sa->sin6.sin6_addr.s6_addr32[i] = 0xFFFFFFFF;
+ net -= 32;
+ }
+ }
+}
+
+int
+pfr_route_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
+{
+ union sockaddr_union mask;
+ struct radix_node *rn;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
+ int s;
+
+ bzero(ke->pfrke_node, sizeof(ke->pfrke_node));
+ if (ke->pfrke_af == AF_INET)
+ head = kt->pfrkt_ip4;
+ else if (ke->pfrke_af == AF_INET6)
+ head = kt->pfrkt_ip6;
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ if (KENTRY_NETWORK(ke)) {
+ pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
+ rn = rn_addroute(&ke->pfrke_sa, &mask, head, ke->pfrke_node);
+ } else
+ rn = rn_addroute(&ke->pfrke_sa, NULL, head, ke->pfrke_node);
+ splx(s);
+
+ return (rn == NULL ? -1 : 0);
+}
+
+int
+pfr_unroute_kentry(struct pfr_ktable *kt, struct pfr_kentry *ke)
+{
+ union sockaddr_union mask;
+ struct radix_node *rn;
+ struct radix_node_head *head = NULL; /* make the compiler happy */
+ int s;
+
+ if (ke->pfrke_af == AF_INET)
+ head = kt->pfrkt_ip4;
+ else if (ke->pfrke_af == AF_INET6)
+ head = kt->pfrkt_ip6;
+
+ s = splsoftnet();
+#ifdef __FreeBSD__
+ PF_ASSERT(MA_OWNED);
+#endif
+ if (KENTRY_NETWORK(ke)) {
+ pfr_prepare_network(&mask, ke->pfrke_af, ke->pfrke_net);
+#ifdef __FreeBSD__
+ rn = rn_delete(&ke->pfrke_sa, &mask, head);
+#else
+ rn = rn_delete(&ke->pfrke_sa, &mask, head, NULL);
+#endif
+ } else
+#ifdef __FreeBSD__
+ rn = rn_delete(&ke->pfrke_sa, NULL, head);
+#else
+ rn = rn_delete(&ke->pfrke_sa, NULL, head, NULL);
+#endif
+ splx(s);
+
+ if (rn == NULL) {
+ printf("pfr_unroute_kentry: delete failed.\n");
+ return (-1);
+ }
+ return (0);
+}
+
+void
+pfr_copyout_addr(struct pfr_addr *ad, struct pfr_kentry *ke)
+{
+ bzero(ad, sizeof(*ad));
+ if (ke == NULL)
+ return;
+ ad->pfra_af = ke->pfrke_af;
+ ad->pfra_net = ke->pfrke_net;
+ ad->pfra_not = ke->pfrke_not;
+ if (ad->pfra_af == AF_INET)
+ ad->pfra_ip4addr = ke->pfrke_sa.sin.sin_addr;
+ else if (ad->pfra_af == AF_INET6)
+ ad->pfra_ip6addr = ke->pfrke_sa.sin6.sin6_addr;
+}
+
+int
+pfr_walktree(struct radix_node *rn, void *arg)
+{
+ struct pfr_kentry *ke = (struct pfr_kentry *)rn;
+ struct pfr_walktree *w = arg;
+ int s, flags = w->pfrw_flags;
+
+ switch (w->pfrw_op) {
+ case PFRW_MARK:
+ ke->pfrke_mark = 0;
+ break;
+ case PFRW_SWEEP:
+ if (ke->pfrke_mark)
+ break;
+ /* FALLTHROUGH */
+ case PFRW_ENQUEUE:
+ SLIST_INSERT_HEAD(w->pfrw_workq, ke, pfrke_workq);
+ w->pfrw_cnt++;
+ break;
+ case PFRW_GET_ADDRS:
+ if (w->pfrw_free-- > 0) {
+ struct pfr_addr ad;
+
+ pfr_copyout_addr(&ad, ke);
+ if (COPYOUT(&ad, w->pfrw_addr, sizeof(ad)))
+ return (EFAULT);
+ w->pfrw_addr++;
+ }
+ break;
+ case PFRW_GET_ASTATS:
+ if (w->pfrw_free-- > 0) {
+ struct pfr_astats as;
+
+ pfr_copyout_addr(&as.pfras_a, ke);
+
+ s = splsoftnet();
+ bcopy(ke->pfrke_packets, as.pfras_packets,
+ sizeof(as.pfras_packets));
+ bcopy(ke->pfrke_bytes, as.pfras_bytes,
+ sizeof(as.pfras_bytes));
+ splx(s);
+ as.pfras_tzero = ke->pfrke_tzero;
+
+ if (COPYOUT(&as, w->pfrw_astats, sizeof(as)))
+ return (EFAULT);
+ w->pfrw_astats++;
+ }
+ break;
+ case PFRW_POOL_GET:
+ if (ke->pfrke_not)
+ break; /* negative entries are ignored */
+ if (!w->pfrw_cnt--) {
+ w->pfrw_kentry = ke;
+ return (1); /* finish search */
+ }
+ break;
+ case PFRW_DYNADDR_UPDATE:
+ if (ke->pfrke_af == AF_INET) {
+ if (w->pfrw_dyn->pfid_acnt4++ > 0)
+ break;
+ pfr_prepare_network(&pfr_mask, AF_INET, ke->pfrke_net);
+ w->pfrw_dyn->pfid_addr4 = *SUNION2PF(
+ &ke->pfrke_sa, AF_INET);
+ w->pfrw_dyn->pfid_mask4 = *SUNION2PF(
+ &pfr_mask, AF_INET);
+ } else if (ke->pfrke_af == AF_INET6){
+ if (w->pfrw_dyn->pfid_acnt6++ > 0)
+ break;
+ pfr_prepare_network(&pfr_mask, AF_INET6, ke->pfrke_net);
+ w->pfrw_dyn->pfid_addr6 = *SUNION2PF(
+ &ke->pfrke_sa, AF_INET6);
+ w->pfrw_dyn->pfid_mask6 = *SUNION2PF(
+ &pfr_mask, AF_INET6);
+ }
+ break;
+ }
+ return (0);
+}
+
+int
+pfr_clr_tables(struct pfr_table *filter, int *ndel, int flags)
+{
+ struct pfr_ktableworkq workq;
+ struct pfr_ktable *p;
+ int s = 0, xdel = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ALLRSETS);
+ if (pfr_fix_anchor(filter->pfrt_anchor))
+ return (EINVAL);
+ if (pfr_table_count(filter, flags) < 0)
+ return (ENOENT);
+
+ SLIST_INIT(&workq);
+ RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (pfr_skip_table(filter, p, flags))
+ continue;
+ if (!strcmp(p->pfrkt_anchor, PF_RESERVED_ANCHOR))
+ continue;
+ if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ continue;
+ p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ xdel++;
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_setflags_ktables(&workq);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ }
+ if (ndel != NULL)
+ *ndel = xdel;
+ return (0);
+}
+
+int
+pfr_add_tables(struct pfr_table *tbl, int size, int *nadd, int flags)
+{
+ struct pfr_ktableworkq addq, changeq;
+ struct pfr_ktable *p, *q, *r, key;
+ int i, rv, s = 0, xadd = 0;
+ long tzero = time_second;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+ SLIST_INIT(&addq);
+ SLIST_INIT(&changeq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ senderr(EFAULT);
+ if (pfr_validate_table(&key.pfrkt_t, PFR_TFLAG_USRMASK,
+ flags & PFR_FLAG_USERIOCTL))
+ senderr(EINVAL);
+ key.pfrkt_flags |= PFR_TFLAG_ACTIVE;
+ p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
+ if (p == NULL) {
+ p = pfr_create_ktable(&key.pfrkt_t, tzero, 1);
+ if (p == NULL)
+ senderr(ENOMEM);
+ SLIST_FOREACH(q, &addq, pfrkt_workq) {
+ if (!pfr_ktable_compare(p, q))
+ goto _skip;
+ }
+ SLIST_INSERT_HEAD(&addq, p, pfrkt_workq);
+ xadd++;
+ if (!key.pfrkt_anchor[0])
+ goto _skip;
+
+ /* find or create root table */
+ bzero(key.pfrkt_anchor, sizeof(key.pfrkt_anchor));
+ r = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
+ if (r != NULL) {
+ p->pfrkt_root = r;
+ goto _skip;
+ }
+ SLIST_FOREACH(q, &addq, pfrkt_workq) {
+ if (!pfr_ktable_compare(&key, q)) {
+ p->pfrkt_root = q;
+ goto _skip;
+ }
+ }
+ key.pfrkt_flags = 0;
+ r = pfr_create_ktable(&key.pfrkt_t, 0, 1);
+ if (r == NULL)
+ senderr(ENOMEM);
+ SLIST_INSERT_HEAD(&addq, r, pfrkt_workq);
+ p->pfrkt_root = r;
+ } else if (!(p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
+ SLIST_FOREACH(q, &changeq, pfrkt_workq)
+ if (!pfr_ktable_compare(&key, q))
+ goto _skip;
+ p->pfrkt_nflags = (p->pfrkt_flags &
+ ~PFR_TFLAG_USRMASK) | key.pfrkt_flags;
+ SLIST_INSERT_HEAD(&changeq, p, pfrkt_workq);
+ xadd++;
+ }
+_skip:
+ ;
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_insert_ktables(&addq);
+ pfr_setflags_ktables(&changeq);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ } else
+ pfr_destroy_ktables(&addq, 0);
+ if (nadd != NULL)
+ *nadd = xadd;
+ return (0);
+_bad:
+ pfr_destroy_ktables(&addq, 0);
+ return (rv);
+}
+
+int
+pfr_del_tables(struct pfr_table *tbl, int size, int *ndel, int flags)
+{
+ struct pfr_ktableworkq workq;
+ struct pfr_ktable *p, *q, key;
+ int i, s = 0, xdel = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+ SLIST_INIT(&workq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ return (EFAULT);
+ if (pfr_validate_table(&key.pfrkt_t, 0,
+ flags & PFR_FLAG_USERIOCTL))
+ return (EINVAL);
+ p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
+ if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
+ SLIST_FOREACH(q, &workq, pfrkt_workq)
+ if (!pfr_ktable_compare(p, q))
+ goto _skip;
+ p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_ACTIVE;
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ xdel++;
+ }
+_skip:
+ ;
+ }
+
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_setflags_ktables(&workq);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ }
+ if (ndel != NULL)
+ *ndel = xdel;
+ return (0);
+}
+
+int
+pfr_get_tables(struct pfr_table *filter, struct pfr_table *tbl, int *size,
+ int flags)
+{
+ struct pfr_ktable *p;
+ int n, nn;
+
+ ACCEPT_FLAGS(PFR_FLAG_ALLRSETS);
+ if (pfr_fix_anchor(filter->pfrt_anchor))
+ return (EINVAL);
+ n = nn = pfr_table_count(filter, flags);
+ if (n < 0)
+ return (ENOENT);
+ if (n > *size) {
+ *size = n;
+ return (0);
+ }
+ RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (pfr_skip_table(filter, p, flags))
+ continue;
+ if (n-- <= 0)
+ continue;
+ if (COPYOUT(&p->pfrkt_t, tbl++, sizeof(*tbl)))
+ return (EFAULT);
+ }
+ if (n) {
+ printf("pfr_get_tables: corruption detected (%d).\n", n);
+ return (ENOTTY);
+ }
+ *size = nn;
+ return (0);
+}
+
+int
+pfr_get_tstats(struct pfr_table *filter, struct pfr_tstats *tbl, int *size,
+ int flags)
+{
+ struct pfr_ktable *p;
+ struct pfr_ktableworkq workq;
+ int s = 0, n, nn;
+ long tzero = time_second;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC|PFR_FLAG_ALLRSETS);
+ /* XXX PFR_FLAG_CLSTATS disabled */
+ if (pfr_fix_anchor(filter->pfrt_anchor))
+ return (EINVAL);
+ n = nn = pfr_table_count(filter, flags);
+ if (n < 0)
+ return (ENOENT);
+ if (n > *size) {
+ *size = n;
+ return (0);
+ }
+ SLIST_INIT(&workq);
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (pfr_skip_table(filter, p, flags))
+ continue;
+ if (n-- <= 0)
+ continue;
+ if (!(flags & PFR_FLAG_ATOMIC))
+ s = splsoftnet();
+ if (COPYOUT(&p->pfrkt_ts, tbl++, sizeof(*tbl))) {
+ if (!(flags & PFR_FLAG_ATOMIC))
+ splx(s);
+ return (EFAULT);
+ }
+ if (!(flags & PFR_FLAG_ATOMIC))
+ splx(s);
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ }
+ if (flags & PFR_FLAG_CLSTATS)
+ pfr_clstats_ktables(&workq, tzero,
+ flags & PFR_FLAG_ADDRSTOO);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ if (n) {
+ printf("pfr_get_tstats: corruption detected (%d).\n", n);
+ return (ENOTTY);
+ }
+ *size = nn;
+ return (0);
+}
+
+int
+pfr_clr_tstats(struct pfr_table *tbl, int size, int *nzero, int flags)
+{
+ struct pfr_ktableworkq workq;
+ struct pfr_ktable *p, key;
+ int i, s = 0, xzero = 0;
+ long tzero = time_second;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY+PFR_FLAG_ADDRSTOO);
+ SLIST_INIT(&workq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ return (EFAULT);
+ if (pfr_validate_table(&key.pfrkt_t, 0, 0))
+ return (EINVAL);
+ p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
+ if (p != NULL) {
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ xzero++;
+ }
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_clstats_ktables(&workq, tzero, flags & PFR_FLAG_ADDRSTOO);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ }
+ if (nzero != NULL)
+ *nzero = xzero;
+ return (0);
+}
+
+int
+pfr_set_tflags(struct pfr_table *tbl, int size, int setflag, int clrflag,
+ int *nchange, int *ndel, int flags)
+{
+ struct pfr_ktableworkq workq;
+ struct pfr_ktable *p, *q, key;
+ int i, s = 0, xchange = 0, xdel = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+ if ((setflag & ~PFR_TFLAG_USRMASK) ||
+ (clrflag & ~PFR_TFLAG_USRMASK) ||
+ (setflag & clrflag))
+ return (EINVAL);
+ SLIST_INIT(&workq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(tbl+i, &key.pfrkt_t, sizeof(key.pfrkt_t)))
+ return (EFAULT);
+ if (pfr_validate_table(&key.pfrkt_t, 0,
+ flags & PFR_FLAG_USERIOCTL))
+ return (EINVAL);
+ p = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
+ if (p != NULL && (p->pfrkt_flags & PFR_TFLAG_ACTIVE)) {
+ p->pfrkt_nflags = (p->pfrkt_flags | setflag) &
+ ~clrflag;
+ if (p->pfrkt_nflags == p->pfrkt_flags)
+ goto _skip;
+ SLIST_FOREACH(q, &workq, pfrkt_workq)
+ if (!pfr_ktable_compare(p, q))
+ goto _skip;
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ if ((p->pfrkt_flags & PFR_TFLAG_PERSIST) &&
+ (clrflag & PFR_TFLAG_PERSIST) &&
+ !(p->pfrkt_flags & PFR_TFLAG_REFERENCED))
+ xdel++;
+ else
+ xchange++;
+ }
+_skip:
+ ;
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ pfr_setflags_ktables(&workq);
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ }
+ if (nchange != NULL)
+ *nchange = xchange;
+ if (ndel != NULL)
+ *ndel = xdel;
+ return (0);
+}
+
+int
+pfr_ina_begin(struct pfr_table *trs, u_int32_t *ticket, int *ndel, int flags)
+{
+ struct pfr_ktableworkq workq;
+ struct pfr_ktable *p;
+ struct pf_ruleset *rs;
+ int xdel = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_DUMMY);
+ rs = pf_find_or_create_ruleset(trs->pfrt_anchor);
+ if (rs == NULL)
+ return (ENOMEM);
+ SLIST_INIT(&workq);
+ RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
+ pfr_skip_table(trs, p, 0))
+ continue;
+ p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ xdel++;
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ pfr_setflags_ktables(&workq);
+ if (ticket != NULL)
+ *ticket = ++rs->tticket;
+ rs->topen = 1;
+ } else
+ pf_remove_if_empty_ruleset(rs);
+ if (ndel != NULL)
+ *ndel = xdel;
+ return (0);
+}
+
+int
+pfr_ina_define(struct pfr_table *tbl, struct pfr_addr *addr, int size,
+ int *nadd, int *naddr, u_int32_t ticket, int flags)
+{
+ struct pfr_ktableworkq tableq;
+ struct pfr_kentryworkq addrq;
+ struct pfr_ktable *kt, *rt, *shadow, key;
+ struct pfr_kentry *p;
+ struct pfr_addr ad;
+ struct pf_ruleset *rs;
+ int i, rv, xadd = 0, xaddr = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_DUMMY|PFR_FLAG_ADDRSTOO);
+ if (size && !(flags & PFR_FLAG_ADDRSTOO))
+ return (EINVAL);
+ if (pfr_validate_table(tbl, PFR_TFLAG_USRMASK,
+ flags & PFR_FLAG_USERIOCTL))
+ return (EINVAL);
+ rs = pf_find_ruleset(tbl->pfrt_anchor);
+ if (rs == NULL || !rs->topen || ticket != rs->tticket)
+ return (EBUSY);
+ tbl->pfrt_flags |= PFR_TFLAG_INACTIVE;
+ SLIST_INIT(&tableq);
+ kt = RB_FIND(pfr_ktablehead, &pfr_ktables, (struct pfr_ktable *)tbl);
+ if (kt == NULL) {
+ kt = pfr_create_ktable(tbl, 0, 1);
+ if (kt == NULL)
+ return (ENOMEM);
+ SLIST_INSERT_HEAD(&tableq, kt, pfrkt_workq);
+ xadd++;
+ if (!tbl->pfrt_anchor[0])
+ goto _skip;
+
+ /* find or create root table */
+ bzero(&key, sizeof(key));
+ strlcpy(key.pfrkt_name, tbl->pfrt_name, sizeof(key.pfrkt_name));
+ rt = RB_FIND(pfr_ktablehead, &pfr_ktables, &key);
+ if (rt != NULL) {
+ kt->pfrkt_root = rt;
+ goto _skip;
+ }
+ rt = pfr_create_ktable(&key.pfrkt_t, 0, 1);
+ if (rt == NULL) {
+ pfr_destroy_ktables(&tableq, 0);
+ return (ENOMEM);
+ }
+ SLIST_INSERT_HEAD(&tableq, rt, pfrkt_workq);
+ kt->pfrkt_root = rt;
+ } else if (!(kt->pfrkt_flags & PFR_TFLAG_INACTIVE))
+ xadd++;
+_skip:
+ shadow = pfr_create_ktable(tbl, 0, 0);
+ if (shadow == NULL) {
+ pfr_destroy_ktables(&tableq, 0);
+ return (ENOMEM);
+ }
+ SLIST_INIT(&addrq);
+ for (i = 0; i < size; i++) {
+ if (COPYIN(addr+i, &ad, sizeof(ad)))
+ senderr(EFAULT);
+ if (pfr_validate_addr(&ad))
+ senderr(EINVAL);
+ if (pfr_lookup_addr(shadow, &ad, 1) != NULL)
+ continue;
+ p = pfr_create_kentry(&ad, 0);
+ if (p == NULL)
+ senderr(ENOMEM);
+ if (pfr_route_kentry(shadow, p)) {
+ pfr_destroy_kentry(p);
+ continue;
+ }
+ SLIST_INSERT_HEAD(&addrq, p, pfrke_workq);
+ xaddr++;
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (kt->pfrkt_shadow != NULL)
+ pfr_destroy_ktable(kt->pfrkt_shadow, 1);
+ kt->pfrkt_flags |= PFR_TFLAG_INACTIVE;
+ pfr_insert_ktables(&tableq);
+ shadow->pfrkt_cnt = (flags & PFR_FLAG_ADDRSTOO) ?
+ xaddr : NO_ADDRESSES;
+ kt->pfrkt_shadow = shadow;
+ } else {
+ pfr_clean_node_mask(shadow, &addrq);
+ pfr_destroy_ktable(shadow, 0);
+ pfr_destroy_ktables(&tableq, 0);
+ pfr_destroy_kentries(&addrq);
+ }
+ if (nadd != NULL)
+ *nadd = xadd;
+ if (naddr != NULL)
+ *naddr = xaddr;
+ return (0);
+_bad:
+ pfr_destroy_ktable(shadow, 0);
+ pfr_destroy_ktables(&tableq, 0);
+ pfr_destroy_kentries(&addrq);
+ return (rv);
+}
+
+int
+pfr_ina_rollback(struct pfr_table *trs, u_int32_t ticket, int *ndel, int flags)
+{
+ struct pfr_ktableworkq workq;
+ struct pfr_ktable *p;
+ struct pf_ruleset *rs;
+ int xdel = 0;
+
+ ACCEPT_FLAGS(PFR_FLAG_DUMMY);
+ rs = pf_find_ruleset(trs->pfrt_anchor);
+ if (rs == NULL || !rs->topen || ticket != rs->tticket)
+ return (0);
+ SLIST_INIT(&workq);
+ RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
+ pfr_skip_table(trs, p, 0))
+ continue;
+ p->pfrkt_nflags = p->pfrkt_flags & ~PFR_TFLAG_INACTIVE;
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ xdel++;
+ }
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ pfr_setflags_ktables(&workq);
+ rs->topen = 0;
+ pf_remove_if_empty_ruleset(rs);
+ }
+ if (ndel != NULL)
+ *ndel = xdel;
+ return (0);
+}
+
+int
+pfr_ina_commit(struct pfr_table *trs, u_int32_t ticket, int *nadd,
+ int *nchange, int flags)
+{
+ struct pfr_ktable *p, *q;
+ struct pfr_ktableworkq workq;
+ struct pf_ruleset *rs;
+ int s = 0, xadd = 0, xchange = 0;
+ long tzero = time_second;
+
+ ACCEPT_FLAGS(PFR_FLAG_ATOMIC+PFR_FLAG_DUMMY);
+ rs = pf_find_ruleset(trs->pfrt_anchor);
+ if (rs == NULL || !rs->topen || ticket != rs->tticket)
+ return (EBUSY);
+
+ SLIST_INIT(&workq);
+ RB_FOREACH(p, pfr_ktablehead, &pfr_ktables) {
+ if (!(p->pfrkt_flags & PFR_TFLAG_INACTIVE) ||
+ pfr_skip_table(trs, p, 0))
+ continue;
+ SLIST_INSERT_HEAD(&workq, p, pfrkt_workq);
+ if (p->pfrkt_flags & PFR_TFLAG_ACTIVE)
+ xchange++;
+ else
+ xadd++;
+ }
+
+ if (!(flags & PFR_FLAG_DUMMY)) {
+ if (flags & PFR_FLAG_ATOMIC)
+ s = splsoftnet();
+ for (p = SLIST_FIRST(&workq); p != NULL; p = q) {
+ q = SLIST_NEXT(p, pfrkt_workq);
+ pfr_commit_ktable(p, tzero);
+ }
+ if (flags & PFR_FLAG_ATOMIC)
+ splx(s);
+ rs->topen = 0;
+ pf_remove_if_empty_ruleset(rs);
+ }
+ if (nadd != NULL)
+ *nadd = xadd;
+ if (nchange != NULL)
+ *nchange = xchange;
+
+ return (0);
+}
+
+void
+pfr_commit_ktable(struct pfr_ktable *kt, long tzero)
+{
+ struct pfr_ktable *shadow = kt->pfrkt_shadow;
+ int nflags;
+
+ if (shadow->pfrkt_cnt == NO_ADDRESSES) {
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ pfr_clstats_ktable(kt, tzero, 1);
+ } else if (kt->pfrkt_flags & PFR_TFLAG_ACTIVE) {
+ /* kt might contain addresses */
+ struct pfr_kentryworkq addrq, addq, changeq, delq, garbageq;
+ struct pfr_kentry *p, *q, *next;
+ struct pfr_addr ad;
+
+ pfr_enqueue_addrs(shadow, &addrq, NULL, 0);
+ pfr_mark_addrs(kt);
+ SLIST_INIT(&addq);
+ SLIST_INIT(&changeq);
+ SLIST_INIT(&delq);
+ SLIST_INIT(&garbageq);
+ pfr_clean_node_mask(shadow, &addrq);
+ for (p = SLIST_FIRST(&addrq); p != NULL; p = next) {
+ next = SLIST_NEXT(p, pfrke_workq); /* XXX */
+ pfr_copyout_addr(&ad, p);
+ q = pfr_lookup_addr(kt, &ad, 1);
+ if (q != NULL) {
+ if (q->pfrke_not != p->pfrke_not)
+ SLIST_INSERT_HEAD(&changeq, q,
+ pfrke_workq);
+ q->pfrke_mark = 1;
+ SLIST_INSERT_HEAD(&garbageq, p, pfrke_workq);
+ } else {
+ p->pfrke_tzero = tzero;
+ SLIST_INSERT_HEAD(&addq, p, pfrke_workq);
+ }
+ }
+ pfr_enqueue_addrs(kt, &delq, NULL, ENQUEUE_UNMARKED_ONLY);
+ pfr_insert_kentries(kt, &addq, tzero);
+ pfr_remove_kentries(kt, &delq);
+ pfr_clstats_kentries(&changeq, tzero, INVERT_NEG_FLAG);
+ pfr_destroy_kentries(&garbageq);
+ } else {
+ /* kt cannot contain addresses */
+ SWAP(struct radix_node_head *, kt->pfrkt_ip4,
+ shadow->pfrkt_ip4);
+ SWAP(struct radix_node_head *, kt->pfrkt_ip6,
+ shadow->pfrkt_ip6);
+ SWAP(int, kt->pfrkt_cnt, shadow->pfrkt_cnt);
+ pfr_clstats_ktable(kt, tzero, 1);
+ }
+ nflags = ((shadow->pfrkt_flags & PFR_TFLAG_USRMASK) |
+ (kt->pfrkt_flags & PFR_TFLAG_SETMASK) | PFR_TFLAG_ACTIVE)
+ & ~PFR_TFLAG_INACTIVE;
+ pfr_destroy_ktable(shadow, 0);
+ kt->pfrkt_shadow = NULL;
+ pfr_setflags_ktable(kt, nflags);
+}
+
+int
+pfr_validate_table(struct pfr_table *tbl, int allowedflags, int no_reserved)
+{
+ int i;
+
+ if (!tbl->pfrt_name[0])
+ return (-1);
+ if (no_reserved && !strcmp(tbl->pfrt_anchor, PF_RESERVED_ANCHOR))
+ return (-1);
+ if (tbl->pfrt_name[PF_TABLE_NAME_SIZE-1])
+ return (-1);
+ for (i = strlen(tbl->pfrt_name); i < PF_TABLE_NAME_SIZE; i++)
+ if (tbl->pfrt_name[i])
+ return (-1);
+ if (pfr_fix_anchor(tbl->pfrt_anchor))
+ return (-1);
+ if (tbl->pfrt_flags & ~allowedflags)
+ return (-1);
+ return (0);
+}
+
+/*
+ * Rewrite anchors referenced by tables to remove slashes
+ * and check for validity.
+ */
+int
+pfr_fix_anchor(char *anchor)
+{
+ size_t siz = MAXPATHLEN;
+ int i;
+
+ if (anchor[0] == '/') {
+ char *path;
+ int off;
+
+ path = anchor;
+ off = 1;
+ while (*++path == '/')
+ off++;
+ bcopy(path, anchor, siz - off);
+ memset(anchor + siz - off, 0, off);
+ }
+ if (anchor[siz - 1])
+ return (-1);
+ for (i = strlen(anchor); i < siz; i++)
+ if (anchor[i])
+ return (-1);
+ return (0);
+}
+
+int
+pfr_table_count(struct pfr_table *filter, int flags)
+{
+ struct pf_ruleset *rs;
+
+ if (flags & PFR_FLAG_ALLRSETS)
+ return (pfr_ktable_cnt);
+ if (filter->pfrt_anchor[0]) {
+ rs = pf_find_ruleset(filter->pfrt_anchor);
+ return ((rs != NULL) ? rs->tables : -1);
+ }
+ return (pf_main_ruleset.tables);
+}
+
+int
+pfr_skip_table(struct pfr_table *filter, struct pfr_ktable *kt, int flags)
+{
+ if (flags & PFR_FLAG_ALLRSETS)
+ return (0);
+ if (strcmp(filter->pfrt_anchor, kt->pfrkt_anchor))
+ return (1);
+ return (0);
+}
+
+void
+pfr_insert_ktables(struct pfr_ktableworkq *workq)
+{
+ struct pfr_ktable *p;
+
+ SLIST_FOREACH(p, workq, pfrkt_workq)
+ pfr_insert_ktable(p);
+}
+
+void
+pfr_insert_ktable(struct pfr_ktable *kt)
+{
+ RB_INSERT(pfr_ktablehead, &pfr_ktables, kt);
+ pfr_ktable_cnt++;
+ if (kt->pfrkt_root != NULL)
+ if (!kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR]++)
+ pfr_setflags_ktable(kt->pfrkt_root,
+ kt->pfrkt_root->pfrkt_flags|PFR_TFLAG_REFDANCHOR);
+}
+
+void
+pfr_setflags_ktables(struct pfr_ktableworkq *workq)
+{
+ struct pfr_ktable *p, *q;
+
+ for (p = SLIST_FIRST(workq); p; p = q) {
+ q = SLIST_NEXT(p, pfrkt_workq);
+ pfr_setflags_ktable(p, p->pfrkt_nflags);
+ }
+}
+
+void
+pfr_setflags_ktable(struct pfr_ktable *kt, int newf)
+{
+ struct pfr_kentryworkq addrq;
+
+ if (!(newf & PFR_TFLAG_REFERENCED) &&
+ !(newf & PFR_TFLAG_PERSIST))
+ newf &= ~PFR_TFLAG_ACTIVE;
+ if (!(newf & PFR_TFLAG_ACTIVE))
+ newf &= ~PFR_TFLAG_USRMASK;
+ if (!(newf & PFR_TFLAG_SETMASK)) {
+ RB_REMOVE(pfr_ktablehead, &pfr_ktables, kt);
+ if (kt->pfrkt_root != NULL)
+ if (!--kt->pfrkt_root->pfrkt_refcnt[PFR_REFCNT_ANCHOR])
+ pfr_setflags_ktable(kt->pfrkt_root,
+ kt->pfrkt_root->pfrkt_flags &
+ ~PFR_TFLAG_REFDANCHOR);
+ pfr_destroy_ktable(kt, 1);
+ pfr_ktable_cnt--;
+ return;
+ }
+ if (!(newf & PFR_TFLAG_ACTIVE) && kt->pfrkt_cnt) {
+ pfr_enqueue_addrs(kt, &addrq, NULL, 0);
+ pfr_remove_kentries(kt, &addrq);
+ }
+ if (!(newf & PFR_TFLAG_INACTIVE) && kt->pfrkt_shadow != NULL) {
+ pfr_destroy_ktable(kt->pfrkt_shadow, 1);
+ kt->pfrkt_shadow = NULL;
+ }
+ kt->pfrkt_flags = newf;
+}
+
+void
+pfr_clstats_ktables(struct pfr_ktableworkq *workq, long tzero, int recurse)
+{
+ struct pfr_ktable *p;
+
+ SLIST_FOREACH(p, workq, pfrkt_workq)
+ pfr_clstats_ktable(p, tzero, recurse);
+}
+
+void
+pfr_clstats_ktable(struct pfr_ktable *kt, long tzero, int recurse)
+{
+ struct pfr_kentryworkq addrq;
+ int s;
+
+ if (recurse) {
+ pfr_enqueue_addrs(kt, &addrq, NULL, 0);
+ pfr_clstats_kentries(&addrq, tzero, 0);
+ }
+ s = splsoftnet();
+ bzero(kt->pfrkt_packets, sizeof(kt->pfrkt_packets));
+ bzero(kt->pfrkt_bytes, sizeof(kt->pfrkt_bytes));
+ kt->pfrkt_match = kt->pfrkt_nomatch = 0;
+ splx(s);
+ kt->pfrkt_tzero = tzero;
+}
+
+struct pfr_ktable *
+pfr_create_ktable(struct pfr_table *tbl, long tzero, int attachruleset)
+{
+ struct pfr_ktable *kt;
+ struct pf_ruleset *rs;
+
+ kt = pool_get(&pfr_ktable_pl, PR_NOWAIT);
+ if (kt == NULL)
+ return (NULL);
+ bzero(kt, sizeof(*kt));
+ kt->pfrkt_t = *tbl;
+
+ if (attachruleset) {
+ rs = pf_find_or_create_ruleset(tbl->pfrt_anchor);
+ if (!rs) {
+ pfr_destroy_ktable(kt, 0);
+ return (NULL);
+ }
+ kt->pfrkt_rs = rs;
+ rs->tables++;
+ }
+
+ if (!rn_inithead((void **)&kt->pfrkt_ip4,
+ offsetof(struct sockaddr_in, sin_addr) * 8) ||
+ !rn_inithead((void **)&kt->pfrkt_ip6,
+ offsetof(struct sockaddr_in6, sin6_addr) * 8)) {
+ pfr_destroy_ktable(kt, 0);
+ return (NULL);
+ }
+ kt->pfrkt_tzero = tzero;
+
+ return (kt);
+}
+
+void
+pfr_destroy_ktables(struct pfr_ktableworkq *workq, int flushaddr)
+{
+ struct pfr_ktable *p, *q;
+
+ for (p = SLIST_FIRST(workq); p; p = q) {
+ q = SLIST_NEXT(p, pfrkt_workq);
+ pfr_destroy_ktable(p, flushaddr);
+ }
+}
+
+void
+pfr_destroy_ktable(struct pfr_ktable *kt, int flushaddr)
+{
+ struct pfr_kentryworkq addrq;
+
+ if (flushaddr) {
+ pfr_enqueue_addrs(kt, &addrq, NULL, 0);
+ pfr_clean_node_mask(kt, &addrq);
+ pfr_destroy_kentries(&addrq);
+ }
+#if defined(__FreeBSD__) && (__FreeBSD_version >= 500100)
+ if (kt->pfrkt_ip4 != NULL) {
+ RADIX_NODE_HEAD_DESTROY(kt->pfrkt_ip4);
+ free((caddr_t)kt->pfrkt_ip4, M_RTABLE);
+ }
+ if (kt->pfrkt_ip6 != NULL) {
+ RADIX_NODE_HEAD_DESTROY(kt->pfrkt_ip6);
+ free((caddr_t)kt->pfrkt_ip6, M_RTABLE);
+ }
+#else
+ if (kt->pfrkt_ip4 != NULL)
+ free((caddr_t)kt->pfrkt_ip4, M_RTABLE);
+ if (kt->pfrkt_ip6 != NULL)
+ free((caddr_t)kt->pfrkt_ip6, M_RTABLE);
+#endif
+ if (kt->pfrkt_shadow != NULL)
+ pfr_destroy_ktable(kt->pfrkt_shadow, flushaddr);
+ if (kt->pfrkt_rs != NULL) {
+ kt->pfrkt_rs->tables--;
+ pf_remove_if_empty_ruleset(kt->pfrkt_rs);
+ }
+ pool_put(&pfr_ktable_pl, kt);
+}
+
+int
+pfr_ktable_compare(struct pfr_ktable *p, struct pfr_ktable *q)
+{
+ int d;
+
+ if ((d = strncmp(p->pfrkt_name, q->pfrkt_name, PF_TABLE_NAME_SIZE)))
+ return (d);
+ return (strcmp(p->pfrkt_anchor, q->pfrkt_anchor));
+}
+
+struct pfr_ktable *
+pfr_lookup_table(struct pfr_table *tbl)
+{
+ /* struct pfr_ktable start like a struct pfr_table */
+ return (RB_FIND(pfr_ktablehead, &pfr_ktables,
+ (struct pfr_ktable *)tbl));
+}
+
+int
+pfr_match_addr(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af)
+{
+ struct pfr_kentry *ke = NULL;
+ int match;
+
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
+ kt = kt->pfrkt_root;
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (0);
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ pfr_sin.sin_addr.s_addr = a->addr32[0];
+ ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
+ if (ke && KENTRY_RNF_ROOT(ke))
+ ke = NULL;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
+ ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
+ if (ke && KENTRY_RNF_ROOT(ke))
+ ke = NULL;
+ break;
+#endif /* INET6 */
+ }
+ match = (ke && !ke->pfrke_not);
+ if (match)
+ kt->pfrkt_match++;
+ else
+ kt->pfrkt_nomatch++;
+ return (match);
+}
+
+void
+pfr_update_stats(struct pfr_ktable *kt, struct pf_addr *a, sa_family_t af,
+ u_int64_t len, int dir_out, int op_pass, int notrule)
+{
+ struct pfr_kentry *ke = NULL;
+
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
+ kt = kt->pfrkt_root;
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return;
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+ pfr_sin.sin_addr.s_addr = a->addr32[0];
+ ke = (struct pfr_kentry *)rn_match(&pfr_sin, kt->pfrkt_ip4);
+ if (ke && KENTRY_RNF_ROOT(ke))
+ ke = NULL;
+ break;
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+ bcopy(a, &pfr_sin6.sin6_addr, sizeof(pfr_sin6.sin6_addr));
+ ke = (struct pfr_kentry *)rn_match(&pfr_sin6, kt->pfrkt_ip6);
+ if (ke && KENTRY_RNF_ROOT(ke))
+ ke = NULL;
+ break;
+#endif /* INET6 */
+ default:
+ ;
+ }
+ if ((ke == NULL || ke->pfrke_not) != notrule) {
+ if (op_pass != PFR_OP_PASS)
+ printf("pfr_update_stats: assertion failed.\n");
+ op_pass = PFR_OP_XPASS;
+ }
+ kt->pfrkt_packets[dir_out][op_pass]++;
+ kt->pfrkt_bytes[dir_out][op_pass] += len;
+ if (ke != NULL && op_pass != PFR_OP_XPASS) {
+ ke->pfrke_packets[dir_out][op_pass]++;
+ ke->pfrke_bytes[dir_out][op_pass] += len;
+ }
+}
+
+struct pfr_ktable *
+pfr_attach_table(struct pf_ruleset *rs, char *name)
+{
+ struct pfr_ktable *kt, *rt;
+ struct pfr_table tbl;
+ struct pf_anchor *ac = rs->anchor;
+
+ bzero(&tbl, sizeof(tbl));
+ strlcpy(tbl.pfrt_name, name, sizeof(tbl.pfrt_name));
+ if (ac != NULL)
+ strlcpy(tbl.pfrt_anchor, ac->path, sizeof(tbl.pfrt_anchor));
+ kt = pfr_lookup_table(&tbl);
+ if (kt == NULL) {
+ kt = pfr_create_ktable(&tbl, time_second, 1);
+ if (kt == NULL)
+ return (NULL);
+ if (ac != NULL) {
+ bzero(tbl.pfrt_anchor, sizeof(tbl.pfrt_anchor));
+ rt = pfr_lookup_table(&tbl);
+ if (rt == NULL) {
+ rt = pfr_create_ktable(&tbl, 0, 1);
+ if (rt == NULL) {
+ pfr_destroy_ktable(kt, 0);
+ return (NULL);
+ }
+ pfr_insert_ktable(rt);
+ }
+ kt->pfrkt_root = rt;
+ }
+ pfr_insert_ktable(kt);
+ }
+ if (!kt->pfrkt_refcnt[PFR_REFCNT_RULE]++)
+ pfr_setflags_ktable(kt, kt->pfrkt_flags|PFR_TFLAG_REFERENCED);
+ return (kt);
+}
+
+void
+pfr_detach_table(struct pfr_ktable *kt)
+{
+ if (kt->pfrkt_refcnt[PFR_REFCNT_RULE] <= 0)
+ printf("pfr_detach_table: refcount = %d.\n",
+ kt->pfrkt_refcnt[PFR_REFCNT_RULE]);
+ else if (!--kt->pfrkt_refcnt[PFR_REFCNT_RULE])
+ pfr_setflags_ktable(kt, kt->pfrkt_flags&~PFR_TFLAG_REFERENCED);
+}
+
+
+int
+pfr_pool_get(struct pfr_ktable *kt, int *pidx, struct pf_addr *counter,
+ struct pf_addr **raddr, struct pf_addr **rmask, sa_family_t af)
+{
+ struct pfr_kentry *ke, *ke2 = NULL;
+ struct pf_addr *addr = NULL;
+ union sockaddr_union mask;
+ int idx = -1, use_counter = 0;
+
+ if (af == AF_INET)
+ addr = (struct pf_addr *)&pfr_sin.sin_addr;
+ else if (af == AF_INET6)
+ addr = (struct pf_addr *)&pfr_sin6.sin6_addr;
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE) && kt->pfrkt_root != NULL)
+ kt = kt->pfrkt_root;
+ if (!(kt->pfrkt_flags & PFR_TFLAG_ACTIVE))
+ return (-1);
+
+ if (pidx != NULL)
+ idx = *pidx;
+ if (counter != NULL && idx >= 0)
+ use_counter = 1;
+ if (idx < 0)
+ idx = 0;
+
+_next_block:
+ ke = pfr_kentry_byidx(kt, idx, af);
+ if (ke == NULL)
+ return (1);
+ pfr_prepare_network(&pfr_mask, af, ke->pfrke_net);
+ *raddr = SUNION2PF(&ke->pfrke_sa, af);
+ *rmask = SUNION2PF(&pfr_mask, af);
+
+ if (use_counter) {
+ /* is supplied address within block? */
+ if (!PF_MATCHA(0, *raddr, *rmask, counter, af)) {
+ /* no, go to next block in table */
+ idx++;
+ use_counter = 0;
+ goto _next_block;
+ }
+ PF_ACPY(addr, counter, af);
+ } else {
+ /* use first address of block */
+ PF_ACPY(addr, *raddr, af);
+ }
+
+ if (!KENTRY_NETWORK(ke)) {
+ /* this is a single IP address - no possible nested block */
+ PF_ACPY(counter, addr, af);
+ *pidx = idx;
+ return (0);
+ }
+ for (;;) {
+ /* we don't want to use a nested block */
+ if (af == AF_INET)
+ ke2 = (struct pfr_kentry *)rn_match(&pfr_sin,
+ kt->pfrkt_ip4);
+ else if (af == AF_INET6)
+ ke2 = (struct pfr_kentry *)rn_match(&pfr_sin6,
+ kt->pfrkt_ip6);
+ /* no need to check KENTRY_RNF_ROOT() here */
+ if (ke2 == ke) {
+ /* lookup return the same block - perfect */
+ PF_ACPY(counter, addr, af);
+ *pidx = idx;
+ return (0);
+ }
+
+ /* we need to increase the counter past the nested block */
+ pfr_prepare_network(&mask, AF_INET, ke2->pfrke_net);
+ PF_POOLMASK(addr, addr, SUNION2PF(&mask, af), &pfr_ffaddr, af);
+ PF_AINC(addr, af);
+ if (!PF_MATCHA(0, *raddr, *rmask, addr, af)) {
+ /* ok, we reached the end of our main block */
+ /* go to next block in table */
+ idx++;
+ use_counter = 0;
+ goto _next_block;
+ }
+ }
+}
+
+struct pfr_kentry *
+pfr_kentry_byidx(struct pfr_ktable *kt, int idx, int af)
+{
+ struct pfr_walktree w;
+
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_POOL_GET;
+ w.pfrw_cnt = idx;
+
+ switch (af) {
+#ifdef INET
+ case AF_INET:
+#ifdef __FreeBSD__
+ kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
+ rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
+ return (w.pfrw_kentry);
+#endif /* INET */
+#ifdef INET6
+ case AF_INET6:
+#ifdef __FreeBSD__
+ kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#else
+ rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
+ return (w.pfrw_kentry);
+#endif /* INET6 */
+ default:
+ return (NULL);
+ }
+}
+
+void
+pfr_dynaddr_update(struct pfr_ktable *kt, struct pfi_dynaddr *dyn)
+{
+ struct pfr_walktree w;
+ int s;
+
+ bzero(&w, sizeof(w));
+ w.pfrw_op = PFRW_DYNADDR_UPDATE;
+ w.pfrw_dyn = dyn;
+
+ s = splsoftnet();
+ dyn->pfid_acnt4 = 0;
+ dyn->pfid_acnt6 = 0;
+ if (!dyn->pfid_af || dyn->pfid_af == AF_INET)
+#ifdef __FreeBSD__
+ kt->pfrkt_ip4->rnh_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#else
+ rn_walktree(kt->pfrkt_ip4, pfr_walktree, &w);
+#endif
+ if (!dyn->pfid_af || dyn->pfid_af == AF_INET6)
+#ifdef __FreeBSD__
+ kt->pfrkt_ip6->rnh_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#else
+ rn_walktree(kt->pfrkt_ip6, pfr_walktree, &w);
+#endif
+ splx(s);
+}
diff --git a/freebsd/sys/contrib/pf/net/pfvar.h b/freebsd/sys/contrib/pf/net/pfvar.h
new file mode 100644
index 00000000..c6429781
--- /dev/null
+++ b/freebsd/sys/contrib/pf/net/pfvar.h
@@ -0,0 +1,1866 @@
+/* $FreeBSD$ */
+/* $OpenBSD: pfvar.h,v 1.244 2007/02/23 21:31:51 deraadt Exp $ */
+
+/*
+ * Copyright (c) 2001 Daniel Hartmeier
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _NET_PFVAR_HH_
+#define _NET_PFVAR_HH_
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/types.h>
+#include <freebsd/sys/queue.h>
+#include <freebsd/sys/tree.h>
+#ifdef __FreeBSD__
+#include <freebsd/sys/lock.h>
+#include <freebsd/sys/sx.h>
+#else
+#include <freebsd/sys/rwlock.h>
+#endif
+
+#include <freebsd/net/radix.h>
+#include <freebsd/net/route.h>
+#ifdef __FreeBSD__
+#include <freebsd/net/if_clone.h>
+#include <freebsd/net/pf_mtag.h>
+#include <freebsd/vm/uma.h>
+#else
+#include <freebsd/netinet/ip_ipsp.h>
+#endif
+
+#ifdef __FreeBSD__
+#include <freebsd/netinet/in.h>
+#endif
+
+#include <freebsd/netinet/tcp_fsm.h>
+
+struct ip;
+struct ip6_hdr;
+#ifdef __FreeBSD__
+struct inpcb;
+#endif
+
+#define PF_TCPS_PROXY_SRC ((TCP_NSTATES)+0)
+#define PF_TCPS_PROXY_DST ((TCP_NSTATES)+1)
+
+#define PF_MD5_DIGEST_LENGTH 16
+#ifdef MD5_DIGEST_LENGTH
+#if PF_MD5_DIGEST_LENGTH != MD5_DIGEST_LENGTH
+#error
+#endif
+#endif
+
+enum { PF_INOUT, PF_IN, PF_OUT };
+enum { PF_LAN_EXT, PF_EXT_GWY, PF_ID };
+enum { PF_PASS, PF_DROP, PF_SCRUB, PF_NOSCRUB, PF_NAT, PF_NONAT,
+ PF_BINAT, PF_NOBINAT, PF_RDR, PF_NORDR, PF_SYNPROXY_DROP };
+enum { PF_RULESET_SCRUB, PF_RULESET_FILTER, PF_RULESET_NAT,
+ PF_RULESET_BINAT, PF_RULESET_RDR, PF_RULESET_MAX };
+enum { PF_OP_NONE, PF_OP_IRG, PF_OP_EQ, PF_OP_NE, PF_OP_LT,
+ PF_OP_LE, PF_OP_GT, PF_OP_GE, PF_OP_XRG, PF_OP_RRG };
+enum { PF_DEBUG_NONE, PF_DEBUG_URGENT, PF_DEBUG_MISC, PF_DEBUG_NOISY };
+enum { PF_CHANGE_NONE, PF_CHANGE_ADD_HEAD, PF_CHANGE_ADD_TAIL,
+ PF_CHANGE_ADD_BEFORE, PF_CHANGE_ADD_AFTER,
+ PF_CHANGE_REMOVE, PF_CHANGE_GET_TICKET };
+enum { PF_GET_NONE, PF_GET_CLR_CNTR };
+
+/*
+ * Note about PFTM_*: real indices into pf_rule.timeout[] come before
+ * PFTM_MAX, special cases afterwards. See pf_state_expires().
+ */
+enum { PFTM_TCP_FIRST_PACKET, PFTM_TCP_OPENING, PFTM_TCP_ESTABLISHED,
+ PFTM_TCP_CLOSING, PFTM_TCP_FIN_WAIT, PFTM_TCP_CLOSED,
+ PFTM_UDP_FIRST_PACKET, PFTM_UDP_SINGLE, PFTM_UDP_MULTIPLE,
+ PFTM_ICMP_FIRST_PACKET, PFTM_ICMP_ERROR_REPLY,
+ PFTM_OTHER_FIRST_PACKET, PFTM_OTHER_SINGLE,
+ PFTM_OTHER_MULTIPLE, PFTM_FRAG, PFTM_INTERVAL,
+ PFTM_ADAPTIVE_START, PFTM_ADAPTIVE_END, PFTM_SRC_NODE,
+ PFTM_TS_DIFF, PFTM_MAX, PFTM_PURGE, PFTM_UNLINKED,
+ PFTM_UNTIL_PACKET };
+
+/* PFTM default values */
+#define PFTM_TCP_FIRST_PACKET_VAL 120 /* First TCP packet */
+#define PFTM_TCP_OPENING_VAL 30 /* No response yet */
+#define PFTM_TCP_ESTABLISHED_VAL 24*60*60/* Established */
+#define PFTM_TCP_CLOSING_VAL 15 * 60 /* Half closed */
+#define PFTM_TCP_FIN_WAIT_VAL 45 /* Got both FINs */
+#define PFTM_TCP_CLOSED_VAL 90 /* Got a RST */
+#define PFTM_UDP_FIRST_PACKET_VAL 60 /* First UDP packet */
+#define PFTM_UDP_SINGLE_VAL 30 /* Unidirectional */
+#define PFTM_UDP_MULTIPLE_VAL 60 /* Bidirectional */
+#define PFTM_ICMP_FIRST_PACKET_VAL 20 /* First ICMP packet */
+#define PFTM_ICMP_ERROR_REPLY_VAL 10 /* Got error response */
+#define PFTM_OTHER_FIRST_PACKET_VAL 60 /* First packet */
+#define PFTM_OTHER_SINGLE_VAL 30 /* Unidirectional */
+#define PFTM_OTHER_MULTIPLE_VAL 60 /* Bidirectional */
+#define PFTM_FRAG_VAL 30 /* Fragment expire */
+#define PFTM_INTERVAL_VAL 10 /* Expire interval */
+#define PFTM_SRC_NODE_VAL 0 /* Source tracking */
+#define PFTM_TS_DIFF_VAL 30 /* Allowed TS diff */
+
+enum { PF_NOPFROUTE, PF_FASTROUTE, PF_ROUTETO, PF_DUPTO, PF_REPLYTO };
+enum { PF_LIMIT_STATES, PF_LIMIT_SRC_NODES, PF_LIMIT_FRAGS,
+ PF_LIMIT_TABLES, PF_LIMIT_TABLE_ENTRIES, PF_LIMIT_MAX };
+#define PF_POOL_IDMASK 0x0f
+enum { PF_POOL_NONE, PF_POOL_BITMASK, PF_POOL_RANDOM,
+ PF_POOL_SRCHASH, PF_POOL_ROUNDROBIN };
+enum { PF_ADDR_ADDRMASK, PF_ADDR_NOROUTE, PF_ADDR_DYNIFTL,
+ PF_ADDR_TABLE, PF_ADDR_RTLABEL, PF_ADDR_URPFFAILED };
+#define PF_POOL_TYPEMASK 0x0f
+#define PF_POOL_STICKYADDR 0x20
+#define PF_WSCALE_FLAG 0x80
+#define PF_WSCALE_MASK 0x0f
+
+#define PF_LOG 0x01
+#define PF_LOG_ALL 0x02
+#define PF_LOG_SOCKET_LOOKUP 0x04
+
+struct pf_addr {
+ union {
+ struct in_addr v4;
+ struct in6_addr v6;
+ u_int8_t addr8[16];
+ u_int16_t addr16[8];
+ u_int32_t addr32[4];
+ } pfa; /* 128-bit address */
+#define v4 pfa.v4
+#define v6 pfa.v6
+#define addr8 pfa.addr8
+#define addr16 pfa.addr16
+#define addr32 pfa.addr32
+};
+
+#define PF_TABLE_NAME_SIZE 32
+
+#define PFI_AFLAG_NETWORK 0x01
+#define PFI_AFLAG_BROADCAST 0x02
+#define PFI_AFLAG_PEER 0x04
+#define PFI_AFLAG_MODEMASK 0x07
+#define PFI_AFLAG_NOALIAS 0x08
+
+struct pf_addr_wrap {
+ union {
+ struct {
+ struct pf_addr addr;
+ struct pf_addr mask;
+ } a;
+ char ifname[IFNAMSIZ];
+ char tblname[PF_TABLE_NAME_SIZE];
+#ifdef __FreeBSD__
+#define RTLABEL_LEN 32
+#endif
+ char rtlabelname[RTLABEL_LEN];
+ u_int32_t rtlabel;
+ } v;
+ union {
+ struct pfi_dynaddr *dyn;
+ struct pfr_ktable *tbl;
+ int dyncnt;
+ int tblcnt;
+ } p;
+ u_int8_t type; /* PF_ADDR_* */
+ u_int8_t iflags; /* PFI_AFLAG_* */
+};
+
+#ifdef _KERNEL
+
+struct pfi_dynaddr {
+ TAILQ_ENTRY(pfi_dynaddr) entry;
+ struct pf_addr pfid_addr4;
+ struct pf_addr pfid_mask4;
+ struct pf_addr pfid_addr6;
+ struct pf_addr pfid_mask6;
+ struct pfr_ktable *pfid_kt;
+ struct pfi_kif *pfid_kif;
+ void *pfid_hook_cookie;
+ int pfid_net; /* mask or 128 */
+ int pfid_acnt4; /* address count IPv4 */
+ int pfid_acnt6; /* address count IPv6 */
+ sa_family_t pfid_af; /* rule af */
+ u_int8_t pfid_iflags; /* PFI_AFLAG_* */
+};
+
+/*
+ * Address manipulation macros
+ */
+
+#ifdef __FreeBSD__
+#define splsoftnet() splnet()
+
+#define HTONL(x) (x) = htonl((__uint32_t)(x))
+#define HTONS(x) (x) = htons((__uint16_t)(x))
+#define NTOHL(x) (x) = ntohl((__uint32_t)(x))
+#define NTOHS(x) (x) = ntohs((__uint16_t)(x))
+
+#define PF_NAME "pf"
+
+#define PR_NOWAIT M_NOWAIT
+#define pool_get(p, f) uma_zalloc(*(p), (f))
+#define pool_put(p, o) uma_zfree(*(p), (o))
+
+#define UMA_CREATE(var, type, desc) \
+ var = uma_zcreate(desc, sizeof(type), \
+ NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0); \
+ if (var == NULL) break
+#define UMA_DESTROY(var) \
+ if(var) uma_zdestroy(var)
+
+extern struct mtx pf_task_mtx;
+
+#define PF_ASSERT(h) mtx_assert(&pf_task_mtx, (h))
+
+#define PF_LOCK() do { \
+ PF_ASSERT(MA_NOTOWNED); \
+ mtx_lock(&pf_task_mtx); \
+} while(0)
+#define PF_UNLOCK() do { \
+ PF_ASSERT(MA_OWNED); \
+ mtx_unlock(&pf_task_mtx); \
+} while(0)
+
+#define PF_COPYIN(uaddr, kaddr, len, r) do { \
+ PF_UNLOCK(); \
+ r = copyin((uaddr), (kaddr), (len)); \
+ PF_LOCK(); \
+} while(0)
+
+#define PF_COPYOUT(kaddr, uaddr, len, r) do { \
+ PF_UNLOCK(); \
+ r = copyout((kaddr), (uaddr), (len)); \
+ PF_LOCK(); \
+} while(0)
+
+extern void init_pf_mutex(void);
+extern void destroy_pf_mutex(void);
+
+#define PF_MODVER 1
+#define PFLOG_MODVER 1
+#define PFSYNC_MODVER 1
+
+#define PFLOG_MINVER 1
+#define PFLOG_PREFVER PFLOG_MODVER
+#define PFLOG_MAXVER 1
+#define PFSYNC_MINVER 1
+#define PFSYNC_PREFVER PFSYNC_MODVER
+#define PFSYNC_MAXVER 1
+#endif /* __FreeBSD__ */
+
+#ifdef INET
+#ifndef INET6
+#define PF_INET_ONLY
+#endif /* ! INET6 */
+#endif /* INET */
+
+#ifdef INET6
+#ifndef INET
+#define PF_INET6_ONLY
+#endif /* ! INET */
+#endif /* INET6 */
+
+#ifdef INET
+#ifdef INET6
+#define PF_INET_INET6
+#endif /* INET6 */
+#endif /* INET */
+
+#else
+
+#define PF_INET_INET6
+
+#endif /* _KERNEL */
+
+/* Both IPv4 and IPv6 */
+#ifdef PF_INET_INET6
+
+#define PF_AEQ(a, b, c) \
+ ((c == AF_INET && (a)->addr32[0] == (b)->addr32[0]) || \
+ ((a)->addr32[3] == (b)->addr32[3] && \
+ (a)->addr32[2] == (b)->addr32[2] && \
+ (a)->addr32[1] == (b)->addr32[1] && \
+ (a)->addr32[0] == (b)->addr32[0])) \
+
+#define PF_ANEQ(a, b, c) \
+ ((c == AF_INET && (a)->addr32[0] != (b)->addr32[0]) || \
+ ((a)->addr32[3] != (b)->addr32[3] || \
+ (a)->addr32[2] != (b)->addr32[2] || \
+ (a)->addr32[1] != (b)->addr32[1] || \
+ (a)->addr32[0] != (b)->addr32[0])) \
+
+#define PF_AZERO(a, c) \
+ ((c == AF_INET && !(a)->addr32[0]) || \
+ (!(a)->addr32[0] && !(a)->addr32[1] && \
+ !(a)->addr32[2] && !(a)->addr32[3] )) \
+
+#define PF_MATCHA(n, a, m, b, f) \
+ pf_match_addr(n, a, m, b, f)
+
+#define PF_ACPY(a, b, f) \
+ pf_addrcpy(a, b, f)
+
+#define PF_AINC(a, f) \
+ pf_addr_inc(a, f)
+
+#define PF_POOLMASK(a, b, c, d, f) \
+ pf_poolmask(a, b, c, d, f)
+
+#else
+
+/* Just IPv6 */
+
+#ifdef PF_INET6_ONLY
+
+#define PF_AEQ(a, b, c) \
+ ((a)->addr32[3] == (b)->addr32[3] && \
+ (a)->addr32[2] == (b)->addr32[2] && \
+ (a)->addr32[1] == (b)->addr32[1] && \
+ (a)->addr32[0] == (b)->addr32[0]) \
+
+#define PF_ANEQ(a, b, c) \
+ ((a)->addr32[3] != (b)->addr32[3] || \
+ (a)->addr32[2] != (b)->addr32[2] || \
+ (a)->addr32[1] != (b)->addr32[1] || \
+ (a)->addr32[0] != (b)->addr32[0]) \
+
+#define PF_AZERO(a, c) \
+ (!(a)->addr32[0] && \
+ !(a)->addr32[1] && \
+ !(a)->addr32[2] && \
+ !(a)->addr32[3] ) \
+
+#define PF_MATCHA(n, a, m, b, f) \
+ pf_match_addr(n, a, m, b, f)
+
+#define PF_ACPY(a, b, f) \
+ pf_addrcpy(a, b, f)
+
+#define PF_AINC(a, f) \
+ pf_addr_inc(a, f)
+
+#define PF_POOLMASK(a, b, c, d, f) \
+ pf_poolmask(a, b, c, d, f)
+
+#else
+
+/* Just IPv4 */
+#ifdef PF_INET_ONLY
+
+#define PF_AEQ(a, b, c) \
+ ((a)->addr32[0] == (b)->addr32[0])
+
+#define PF_ANEQ(a, b, c) \
+ ((a)->addr32[0] != (b)->addr32[0])
+
+#define PF_AZERO(a, c) \
+ (!(a)->addr32[0])
+
+#define PF_MATCHA(n, a, m, b, f) \
+ pf_match_addr(n, a, m, b, f)
+
+#define PF_ACPY(a, b, f) \
+ (a)->v4.s_addr = (b)->v4.s_addr
+
+#define PF_AINC(a, f) \
+ do { \
+ (a)->addr32[0] = htonl(ntohl((a)->addr32[0]) + 1); \
+ } while (0)
+
+#define PF_POOLMASK(a, b, c, d, f) \
+ do { \
+ (a)->addr32[0] = ((b)->addr32[0] & (c)->addr32[0]) | \
+ (((c)->addr32[0] ^ 0xffffffff ) & (d)->addr32[0]); \
+ } while (0)
+
+#endif /* PF_INET_ONLY */
+#endif /* PF_INET6_ONLY */
+#endif /* PF_INET_INET6 */
+
+#define PF_MISMATCHAW(aw, x, af, neg, ifp) \
+ ( \
+ (((aw)->type == PF_ADDR_NOROUTE && \
+ pf_routable((x), (af), NULL)) || \
+ (((aw)->type == PF_ADDR_URPFFAILED && (ifp) != NULL && \
+ pf_routable((x), (af), (ifp))) || \
+ ((aw)->type == PF_ADDR_RTLABEL && \
+ !pf_rtlabel_match((x), (af), (aw))) || \
+ ((aw)->type == PF_ADDR_TABLE && \
+ !pfr_match_addr((aw)->p.tbl, (x), (af))) || \
+ ((aw)->type == PF_ADDR_DYNIFTL && \
+ !pfi_match_addr((aw)->p.dyn, (x), (af))) || \
+ ((aw)->type == PF_ADDR_ADDRMASK && \
+ !PF_AZERO(&(aw)->v.a.mask, (af)) && \
+ !PF_MATCHA(0, &(aw)->v.a.addr, \
+ &(aw)->v.a.mask, (x), (af))))) != \
+ (neg) \
+ )
+
+
+struct pf_rule_uid {
+ uid_t uid[2];
+ u_int8_t op;
+};
+
+struct pf_rule_gid {
+ uid_t gid[2];
+ u_int8_t op;
+};
+
+struct pf_rule_addr {
+ struct pf_addr_wrap addr;
+ u_int16_t port[2];
+ u_int8_t neg;
+ u_int8_t port_op;
+};
+
+struct pf_pooladdr {
+ struct pf_addr_wrap addr;
+ TAILQ_ENTRY(pf_pooladdr) entries;
+ char ifname[IFNAMSIZ];
+ struct pfi_kif *kif;
+};
+
+TAILQ_HEAD(pf_palist, pf_pooladdr);
+
+struct pf_poolhashkey {
+ union {
+ u_int8_t key8[16];
+ u_int16_t key16[8];
+ u_int32_t key32[4];
+ } pfk; /* 128-bit hash key */
+#define key8 pfk.key8
+#define key16 pfk.key16
+#define key32 pfk.key32
+};
+
+struct pf_pool {
+ struct pf_palist list;
+ struct pf_pooladdr *cur;
+ struct pf_poolhashkey key;
+ struct pf_addr counter;
+ int tblidx;
+ u_int16_t proxy_port[2];
+ u_int8_t port_op;
+ u_int8_t opts;
+};
+
+
+/* A packed Operating System description for fingerprinting */
+typedef u_int32_t pf_osfp_t;
+#define PF_OSFP_ANY ((pf_osfp_t)0)
+#define PF_OSFP_UNKNOWN ((pf_osfp_t)-1)
+#define PF_OSFP_NOMATCH ((pf_osfp_t)-2)
+
+struct pf_osfp_entry {
+ SLIST_ENTRY(pf_osfp_entry) fp_entry;
+ pf_osfp_t fp_os;
+ int fp_enflags;
+#define PF_OSFP_EXPANDED 0x001 /* expanded entry */
+#define PF_OSFP_GENERIC 0x002 /* generic signature */
+#define PF_OSFP_NODETAIL 0x004 /* no p0f details */
+#define PF_OSFP_LEN 32
+ char fp_class_nm[PF_OSFP_LEN];
+ char fp_version_nm[PF_OSFP_LEN];
+ char fp_subtype_nm[PF_OSFP_LEN];
+};
+#define PF_OSFP_ENTRY_EQ(a, b) \
+ ((a)->fp_os == (b)->fp_os && \
+ memcmp((a)->fp_class_nm, (b)->fp_class_nm, PF_OSFP_LEN) == 0 && \
+ memcmp((a)->fp_version_nm, (b)->fp_version_nm, PF_OSFP_LEN) == 0 && \
+ memcmp((a)->fp_subtype_nm, (b)->fp_subtype_nm, PF_OSFP_LEN) == 0)
+
+/* handle pf_osfp_t packing */
+#define _FP_RESERVED_BIT 1 /* For the special negative #defines */
+#define _FP_UNUSED_BITS 1
+#define _FP_CLASS_BITS 10 /* OS Class (Windows, Linux) */
+#define _FP_VERSION_BITS 10 /* OS version (95, 98, NT, 2.4.54, 3.2) */
+#define _FP_SUBTYPE_BITS 10 /* patch level (NT SP4, SP3, ECN patch) */
+#define PF_OSFP_UNPACK(osfp, class, version, subtype) do { \
+ (class) = ((osfp) >> (_FP_VERSION_BITS+_FP_SUBTYPE_BITS)) & \
+ ((1 << _FP_CLASS_BITS) - 1); \
+ (version) = ((osfp) >> _FP_SUBTYPE_BITS) & \
+ ((1 << _FP_VERSION_BITS) - 1);\
+ (subtype) = (osfp) & ((1 << _FP_SUBTYPE_BITS) - 1); \
+} while(0)
+#define PF_OSFP_PACK(osfp, class, version, subtype) do { \
+ (osfp) = ((class) & ((1 << _FP_CLASS_BITS) - 1)) << (_FP_VERSION_BITS \
+ + _FP_SUBTYPE_BITS); \
+ (osfp) |= ((version) & ((1 << _FP_VERSION_BITS) - 1)) << \
+ _FP_SUBTYPE_BITS; \
+ (osfp) |= (subtype) & ((1 << _FP_SUBTYPE_BITS) - 1); \
+} while(0)
+
+/* the fingerprint of an OSes TCP SYN packet */
+typedef u_int64_t pf_tcpopts_t;
+struct pf_os_fingerprint {
+ SLIST_HEAD(pf_osfp_enlist, pf_osfp_entry) fp_oses; /* list of matches */
+ pf_tcpopts_t fp_tcpopts; /* packed TCP options */
+ u_int16_t fp_wsize; /* TCP window size */
+ u_int16_t fp_psize; /* ip->ip_len */
+ u_int16_t fp_mss; /* TCP MSS */
+ u_int16_t fp_flags;
+#define PF_OSFP_WSIZE_MOD 0x0001 /* Window modulus */
+#define PF_OSFP_WSIZE_DC 0x0002 /* Window don't care */
+#define PF_OSFP_WSIZE_MSS 0x0004 /* Window multiple of MSS */
+#define PF_OSFP_WSIZE_MTU 0x0008 /* Window multiple of MTU */
+#define PF_OSFP_PSIZE_MOD 0x0010 /* packet size modulus */
+#define PF_OSFP_PSIZE_DC 0x0020 /* packet size don't care */
+#define PF_OSFP_WSCALE 0x0040 /* TCP window scaling */
+#define PF_OSFP_WSCALE_MOD 0x0080 /* TCP window scale modulus */
+#define PF_OSFP_WSCALE_DC 0x0100 /* TCP window scale dont-care */
+#define PF_OSFP_MSS 0x0200 /* TCP MSS */
+#define PF_OSFP_MSS_MOD 0x0400 /* TCP MSS modulus */
+#define PF_OSFP_MSS_DC 0x0800 /* TCP MSS dont-care */
+#define PF_OSFP_DF 0x1000 /* IPv4 don't fragment bit */
+#define PF_OSFP_TS0 0x2000 /* Zero timestamp */
+#define PF_OSFP_INET6 0x4000 /* IPv6 */
+ u_int8_t fp_optcnt; /* TCP option count */
+ u_int8_t fp_wscale; /* TCP window scaling */
+ u_int8_t fp_ttl; /* IPv4 TTL */
+#define PF_OSFP_MAXTTL_OFFSET 40
+/* TCP options packing */
+#define PF_OSFP_TCPOPT_NOP 0x0 /* TCP NOP option */
+#define PF_OSFP_TCPOPT_WSCALE 0x1 /* TCP window scaling option */
+#define PF_OSFP_TCPOPT_MSS 0x2 /* TCP max segment size opt */
+#define PF_OSFP_TCPOPT_SACK 0x3 /* TCP SACK OK option */
+#define PF_OSFP_TCPOPT_TS 0x4 /* TCP timestamp option */
+#define PF_OSFP_TCPOPT_BITS 3 /* bits used by each option */
+#define PF_OSFP_MAX_OPTS \
+ (sizeof(((struct pf_os_fingerprint *)0)->fp_tcpopts) * 8) \
+ / PF_OSFP_TCPOPT_BITS
+
+ SLIST_ENTRY(pf_os_fingerprint) fp_next;
+};
+
+struct pf_osfp_ioctl {
+ struct pf_osfp_entry fp_os;
+ pf_tcpopts_t fp_tcpopts; /* packed TCP options */
+ u_int16_t fp_wsize; /* TCP window size */
+ u_int16_t fp_psize; /* ip->ip_len */
+ u_int16_t fp_mss; /* TCP MSS */
+ u_int16_t fp_flags;
+ u_int8_t fp_optcnt; /* TCP option count */
+ u_int8_t fp_wscale; /* TCP window scaling */
+ u_int8_t fp_ttl; /* IPv4 TTL */
+
+ int fp_getnum; /* DIOCOSFPGET number */
+};
+
+
+union pf_rule_ptr {
+ struct pf_rule *ptr;
+ u_int32_t nr;
+};
+
+#define PF_ANCHOR_NAME_SIZE 64
+
+struct pf_rule {
+ struct pf_rule_addr src;
+ struct pf_rule_addr dst;
+#define PF_SKIP_IFP 0
+#define PF_SKIP_DIR 1
+#define PF_SKIP_AF 2
+#define PF_SKIP_PROTO 3
+#define PF_SKIP_SRC_ADDR 4
+#define PF_SKIP_SRC_PORT 5
+#define PF_SKIP_DST_ADDR 6
+#define PF_SKIP_DST_PORT 7
+#define PF_SKIP_COUNT 8
+ union pf_rule_ptr skip[PF_SKIP_COUNT];
+#define PF_RULE_LABEL_SIZE 64
+ char label[PF_RULE_LABEL_SIZE];
+#define PF_QNAME_SIZE 64
+ char ifname[IFNAMSIZ];
+ char qname[PF_QNAME_SIZE];
+ char pqname[PF_QNAME_SIZE];
+#define PF_TAG_NAME_SIZE 64
+ char tagname[PF_TAG_NAME_SIZE];
+ char match_tagname[PF_TAG_NAME_SIZE];
+
+ char overload_tblname[PF_TABLE_NAME_SIZE];
+
+ TAILQ_ENTRY(pf_rule) entries;
+ struct pf_pool rpool;
+
+ u_int64_t evaluations;
+ u_int64_t packets[2];
+ u_int64_t bytes[2];
+
+ struct pfi_kif *kif;
+ struct pf_anchor *anchor;
+ struct pfr_ktable *overload_tbl;
+
+ pf_osfp_t os_fingerprint;
+
+ int rtableid;
+ u_int32_t timeout[PFTM_MAX];
+ u_int32_t states;
+ u_int32_t max_states;
+ u_int32_t src_nodes;
+ u_int32_t max_src_nodes;
+ u_int32_t max_src_states;
+ u_int32_t spare1; /* netgraph */
+ u_int32_t max_src_conn;
+ struct {
+ u_int32_t limit;
+ u_int32_t seconds;
+ } max_src_conn_rate;
+ u_int32_t qid;
+ u_int32_t pqid;
+ u_int32_t rt_listid;
+ u_int32_t nr;
+ u_int32_t prob;
+ uid_t cuid;
+ pid_t cpid;
+
+ u_int16_t return_icmp;
+ u_int16_t return_icmp6;
+ u_int16_t max_mss;
+ u_int16_t tag;
+ u_int16_t match_tag;
+ u_int16_t spare2; /* netgraph */
+
+ struct pf_rule_uid uid;
+ struct pf_rule_gid gid;
+
+ u_int32_t rule_flag;
+ u_int8_t action;
+ u_int8_t direction;
+ u_int8_t log;
+ u_int8_t logif;
+ u_int8_t quick;
+ u_int8_t ifnot;
+ u_int8_t match_tag_not;
+ u_int8_t natpass;
+
+#define PF_STATE_NORMAL 0x1
+#define PF_STATE_MODULATE 0x2
+#define PF_STATE_SYNPROXY 0x3
+ u_int8_t keep_state;
+ sa_family_t af;
+ u_int8_t proto;
+ u_int8_t type;
+ u_int8_t code;
+ u_int8_t flags;
+ u_int8_t flagset;
+ u_int8_t min_ttl;
+ u_int8_t allow_opts;
+ u_int8_t rt;
+ u_int8_t return_ttl;
+ u_int8_t tos;
+ u_int8_t anchor_relative;
+ u_int8_t anchor_wildcard;
+
+#define PF_FLUSH 0x01
+#define PF_FLUSH_GLOBAL 0x02
+ u_int8_t flush;
+};
+
+/* rule flags */
+#define PFRULE_DROP 0x0000
+#define PFRULE_RETURNRST 0x0001
+#define PFRULE_FRAGMENT 0x0002
+#define PFRULE_RETURNICMP 0x0004
+#define PFRULE_RETURN 0x0008
+#define PFRULE_NOSYNC 0x0010
+#define PFRULE_SRCTRACK 0x0020 /* track source states */
+#define PFRULE_RULESRCTRACK 0x0040 /* per rule */
+
+/* scrub flags */
+#define PFRULE_NODF 0x0100
+#define PFRULE_FRAGCROP 0x0200 /* non-buffering frag cache */
+#define PFRULE_FRAGDROP 0x0400 /* drop funny fragments */
+#define PFRULE_RANDOMID 0x0800
+#define PFRULE_REASSEMBLE_TCP 0x1000
+
+/* rule flags again */
+#define PFRULE_IFBOUND 0x00010000 /* if-bound */
+#define PFRULE_STATESLOPPY 0x00020000 /* sloppy state tracking */
+
+#define PFSTATE_HIWAT 10000 /* default state table size */
+#define PFSTATE_ADAPT_START 6000 /* default adaptive timeout start */
+#define PFSTATE_ADAPT_END 12000 /* default adaptive timeout end */
+
+
+struct pf_threshold {
+ u_int32_t limit;
+#define PF_THRESHOLD_MULT 1000
+#define PF_THRESHOLD_MAX 0xffffffff / PF_THRESHOLD_MULT
+ u_int32_t seconds;
+ u_int32_t count;
+ u_int32_t last;
+};
+
+struct pf_src_node {
+ RB_ENTRY(pf_src_node) entry;
+ struct pf_addr addr;
+ struct pf_addr raddr;
+ union pf_rule_ptr rule;
+ struct pfi_kif *kif;
+ u_int64_t bytes[2];
+ u_int64_t packets[2];
+ u_int32_t states;
+ u_int32_t conn;
+ struct pf_threshold conn_rate;
+ u_int32_t creation;
+ u_int32_t expire;
+ sa_family_t af;
+ u_int8_t ruletype;
+};
+
+#define PFSNODE_HIWAT 10000 /* default source node table size */
+
+struct pf_state_scrub {
+ struct timeval pfss_last; /* time received last packet */
+ u_int32_t pfss_tsecr; /* last echoed timestamp */
+ u_int32_t pfss_tsval; /* largest timestamp */
+ u_int32_t pfss_tsval0; /* original timestamp */
+ u_int16_t pfss_flags;
+#define PFSS_TIMESTAMP 0x0001 /* modulate timestamp */
+#define PFSS_PAWS 0x0010 /* stricter PAWS checks */
+#define PFSS_PAWS_IDLED 0x0020 /* was idle too long. no PAWS */
+#define PFSS_DATA_TS 0x0040 /* timestamp on data packets */
+#define PFSS_DATA_NOTS 0x0080 /* no timestamp on data packets */
+ u_int8_t pfss_ttl; /* stashed TTL */
+ u_int8_t pad;
+ u_int32_t pfss_ts_mod; /* timestamp modulation */
+};
+
+struct pf_state_host {
+ struct pf_addr addr;
+ u_int16_t port;
+ u_int16_t pad;
+};
+
+struct pf_state_peer {
+ u_int32_t seqlo; /* Max sequence number sent */
+ u_int32_t seqhi; /* Max the other end ACKd + win */
+ u_int32_t seqdiff; /* Sequence number modulator */
+ u_int16_t max_win; /* largest window (pre scaling) */
+ u_int8_t state; /* active state level */
+ u_int8_t wscale; /* window scaling factor */
+ u_int16_t mss; /* Maximum segment size option */
+ u_int8_t tcp_est; /* Did we reach TCPS_ESTABLISHED */
+ struct pf_state_scrub *scrub; /* state is scrubbed */
+ u_int8_t pad[3];
+};
+
+TAILQ_HEAD(pf_state_queue, pf_state);
+
+/* keep synced with struct pf_state, used in RB_FIND */
+struct pf_state_cmp {
+ u_int64_t id;
+ u_int32_t creatorid;
+ struct pf_state_host lan;
+ struct pf_state_host gwy;
+ struct pf_state_host ext;
+ sa_family_t af;
+ u_int8_t proto;
+ u_int8_t direction;
+ u_int8_t pad;
+};
+
+struct pf_state {
+ u_int64_t id;
+ u_int32_t creatorid;
+ struct pf_state_host lan;
+ struct pf_state_host gwy;
+ struct pf_state_host ext;
+ sa_family_t af;
+ u_int8_t proto;
+ u_int8_t direction;
+#ifdef __FreeBSD__
+ u_int8_t local_flags;
+#define PFSTATE_EXPIRING 0x01
+#else
+ u_int8_t pad;
+#endif
+ u_int8_t log;
+ u_int8_t state_flags;
+#define PFSTATE_ALLOWOPTS 0x01
+#define PFSTATE_SLOPPY 0x02
+ u_int8_t timeout;
+ u_int8_t sync_flags;
+#define PFSTATE_NOSYNC 0x01
+#define PFSTATE_FROMSYNC 0x02
+#define PFSTATE_STALE 0x04
+ union {
+ struct {
+ RB_ENTRY(pf_state) entry_lan_ext;
+ RB_ENTRY(pf_state) entry_ext_gwy;
+ RB_ENTRY(pf_state) entry_id;
+ TAILQ_ENTRY(pf_state) entry_list;
+ struct pfi_kif *kif;
+ } s;
+ char ifname[IFNAMSIZ];
+ } u;
+ struct pf_state_peer src;
+ struct pf_state_peer dst;
+ union pf_rule_ptr rule;
+ union pf_rule_ptr anchor;
+ union pf_rule_ptr nat_rule;
+ struct pf_addr rt_addr;
+ struct pfi_kif *rt_kif;
+ struct pf_src_node *src_node;
+ struct pf_src_node *nat_src_node;
+ u_int64_t packets[2];
+ u_int64_t bytes[2];
+ u_int32_t creation;
+ u_int32_t expire;
+ u_int32_t pfsync_time;
+ u_int16_t tag;
+};
+
+TAILQ_HEAD(pf_rulequeue, pf_rule);
+
+struct pf_anchor;
+
+struct pf_ruleset {
+ struct {
+ struct pf_rulequeue queues[2];
+ struct {
+ struct pf_rulequeue *ptr;
+ struct pf_rule **ptr_array;
+ u_int32_t rcount;
+ u_int32_t ticket;
+ int open;
+ } active, inactive;
+ } rules[PF_RULESET_MAX];
+ struct pf_anchor *anchor;
+ u_int32_t tticket;
+ int tables;
+ int topen;
+};
+
+RB_HEAD(pf_anchor_global, pf_anchor);
+RB_HEAD(pf_anchor_node, pf_anchor);
+struct pf_anchor {
+ RB_ENTRY(pf_anchor) entry_global;
+ RB_ENTRY(pf_anchor) entry_node;
+ struct pf_anchor *parent;
+ struct pf_anchor_node children;
+ char name[PF_ANCHOR_NAME_SIZE];
+ char path[MAXPATHLEN];
+ struct pf_ruleset ruleset;
+ int refcnt; /* anchor rules */
+ int match;
+};
+RB_PROTOTYPE(pf_anchor_global, pf_anchor, entry_global, pf_anchor_compare);
+RB_PROTOTYPE(pf_anchor_node, pf_anchor, entry_node, pf_anchor_compare);
+
+#define PF_RESERVED_ANCHOR "_pf"
+
+#define PFR_TFLAG_PERSIST 0x00000001
+#define PFR_TFLAG_CONST 0x00000002
+#define PFR_TFLAG_ACTIVE 0x00000004
+#define PFR_TFLAG_INACTIVE 0x00000008
+#define PFR_TFLAG_REFERENCED 0x00000010
+#define PFR_TFLAG_REFDANCHOR 0x00000020
+#define PFR_TFLAG_USRMASK 0x00000003
+#define PFR_TFLAG_SETMASK 0x0000003C
+#define PFR_TFLAG_ALLMASK 0x0000003F
+
+struct pfr_table {
+ char pfrt_anchor[MAXPATHLEN];
+ char pfrt_name[PF_TABLE_NAME_SIZE];
+ u_int32_t pfrt_flags;
+ u_int8_t pfrt_fback;
+};
+
+enum { PFR_FB_NONE, PFR_FB_MATCH, PFR_FB_ADDED, PFR_FB_DELETED,
+ PFR_FB_CHANGED, PFR_FB_CLEARED, PFR_FB_DUPLICATE,
+ PFR_FB_NOTMATCH, PFR_FB_CONFLICT, PFR_FB_MAX };
+
+struct pfr_addr {
+ union {
+ struct in_addr _pfra_ip4addr;
+ struct in6_addr _pfra_ip6addr;
+ } pfra_u;
+ u_int8_t pfra_af;
+ u_int8_t pfra_net;
+ u_int8_t pfra_not;
+ u_int8_t pfra_fback;
+};
+#define pfra_ip4addr pfra_u._pfra_ip4addr
+#define pfra_ip6addr pfra_u._pfra_ip6addr
+
+enum { PFR_DIR_IN, PFR_DIR_OUT, PFR_DIR_MAX };
+enum { PFR_OP_BLOCK, PFR_OP_PASS, PFR_OP_ADDR_MAX, PFR_OP_TABLE_MAX };
+#define PFR_OP_XPASS PFR_OP_ADDR_MAX
+
+struct pfr_astats {
+ struct pfr_addr pfras_a;
+ u_int64_t pfras_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+ u_int64_t pfras_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+ long pfras_tzero;
+};
+
+enum { PFR_REFCNT_RULE, PFR_REFCNT_ANCHOR, PFR_REFCNT_MAX };
+
+struct pfr_tstats {
+ struct pfr_table pfrts_t;
+ u_int64_t pfrts_packets[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
+ u_int64_t pfrts_bytes[PFR_DIR_MAX][PFR_OP_TABLE_MAX];
+ u_int64_t pfrts_match;
+ u_int64_t pfrts_nomatch;
+ long pfrts_tzero;
+ int pfrts_cnt;
+ int pfrts_refcnt[PFR_REFCNT_MAX];
+};
+#define pfrts_name pfrts_t.pfrt_name
+#define pfrts_flags pfrts_t.pfrt_flags
+
+#ifndef _SOCKADDR_UNION_DEFINED
+#define _SOCKADDR_UNION_DEFINED
+union sockaddr_union {
+ struct sockaddr sa;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+};
+#endif /* _SOCKADDR_UNION_DEFINED */
+
+SLIST_HEAD(pfr_kentryworkq, pfr_kentry);
+struct pfr_kentry {
+ struct radix_node pfrke_node[2];
+ union sockaddr_union pfrke_sa;
+ u_int64_t pfrke_packets[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+ u_int64_t pfrke_bytes[PFR_DIR_MAX][PFR_OP_ADDR_MAX];
+ SLIST_ENTRY(pfr_kentry) pfrke_workq;
+ long pfrke_tzero;
+ u_int8_t pfrke_af;
+ u_int8_t pfrke_net;
+ u_int8_t pfrke_not;
+ u_int8_t pfrke_mark;
+ u_int8_t pfrke_intrpool;
+};
+
+SLIST_HEAD(pfr_ktableworkq, pfr_ktable);
+RB_HEAD(pfr_ktablehead, pfr_ktable);
+struct pfr_ktable {
+ struct pfr_tstats pfrkt_ts;
+ RB_ENTRY(pfr_ktable) pfrkt_tree;
+ SLIST_ENTRY(pfr_ktable) pfrkt_workq;
+ struct radix_node_head *pfrkt_ip4;
+ struct radix_node_head *pfrkt_ip6;
+ struct pfr_ktable *pfrkt_shadow;
+ struct pfr_ktable *pfrkt_root;
+ struct pf_ruleset *pfrkt_rs;
+ long pfrkt_larg;
+ int pfrkt_nflags;
+};
+#define pfrkt_t pfrkt_ts.pfrts_t
+#define pfrkt_name pfrkt_t.pfrt_name
+#define pfrkt_anchor pfrkt_t.pfrt_anchor
+#define pfrkt_ruleset pfrkt_t.pfrt_ruleset
+#define pfrkt_flags pfrkt_t.pfrt_flags
+#define pfrkt_cnt pfrkt_ts.pfrts_cnt
+#define pfrkt_refcnt pfrkt_ts.pfrts_refcnt
+#define pfrkt_packets pfrkt_ts.pfrts_packets
+#define pfrkt_bytes pfrkt_ts.pfrts_bytes
+#define pfrkt_match pfrkt_ts.pfrts_match
+#define pfrkt_nomatch pfrkt_ts.pfrts_nomatch
+#define pfrkt_tzero pfrkt_ts.pfrts_tzero
+
+RB_HEAD(pf_state_tree_lan_ext, pf_state);
+RB_PROTOTYPE(pf_state_tree_lan_ext, pf_state,
+ u.s.entry_lan_ext, pf_state_compare_lan_ext);
+
+RB_HEAD(pf_state_tree_ext_gwy, pf_state);
+RB_PROTOTYPE(pf_state_tree_ext_gwy, pf_state,
+ u.s.entry_ext_gwy, pf_state_compare_ext_gwy);
+
+TAILQ_HEAD(pfi_statehead, pfi_kif);
+RB_HEAD(pfi_ifhead, pfi_kif);
+
+/* keep synced with pfi_kif, used in RB_FIND */
+struct pfi_kif_cmp {
+ char pfik_name[IFNAMSIZ];
+};
+
+struct pfi_kif {
+ char pfik_name[IFNAMSIZ];
+ RB_ENTRY(pfi_kif) pfik_tree;
+ u_int64_t pfik_packets[2][2][2];
+ u_int64_t pfik_bytes[2][2][2];
+ u_int32_t pfik_tzero;
+ int pfik_flags;
+ struct pf_state_tree_lan_ext pfik_lan_ext;
+ struct pf_state_tree_ext_gwy pfik_ext_gwy;
+ TAILQ_ENTRY(pfi_kif) pfik_w_states;
+#ifndef __FreeBSD__
+ void *pfik_ah_cookie;
+#endif
+ struct ifnet *pfik_ifp;
+ struct ifg_group *pfik_group;
+ int pfik_states;
+ int pfik_rules;
+ TAILQ_HEAD(, pfi_dynaddr) pfik_dynaddrs;
+};
+
+enum pfi_kif_refs {
+ PFI_KIF_REF_NONE,
+ PFI_KIF_REF_STATE,
+ PFI_KIF_REF_RULE
+};
+
+#define PFI_IFLAG_SKIP 0x0100 /* skip filtering on interface */
+/* XXX: revisist */
+#define PFI_IFLAG_SETABLE_MASK 0x0100 /* setable via DIOC{SET,CLR}IFFLAG */
+#define PFI_IFLAG_PLACEHOLDER 0x8000 /* placeholder group/interface */
+
+struct pf_pdesc {
+ struct {
+ int done;
+ uid_t uid;
+ gid_t gid;
+ pid_t pid;
+ } lookup;
+ u_int64_t tot_len; /* Make Mickey money */
+ union {
+ struct tcphdr *tcp;
+ struct udphdr *udp;
+ struct icmp *icmp;
+#ifdef INET6
+ struct icmp6_hdr *icmp6;
+#endif /* INET6 */
+ void *any;
+ } hdr;
+ struct pf_addr baddr; /* address before translation */
+ struct pf_addr naddr; /* address after translation */
+ struct pf_rule *nat_rule; /* nat/rdr rule applied to packet */
+ struct pf_addr *src;
+ struct pf_addr *dst;
+ struct ether_header
+ *eh;
+ struct pf_mtag *pf_mtag;
+ u_int16_t *ip_sum;
+ u_int32_t p_len; /* total length of payload */
+ u_int16_t flags; /* Let SCRUB trigger behavior in
+ * state code. Easier than tags */
+#define PFDESC_TCP_NORM 0x0001 /* TCP shall be statefully scrubbed */
+#define PFDESC_IP_REAS 0x0002 /* IP frags would've been reassembled */
+ sa_family_t af;
+ u_int8_t proto;
+ u_int8_t tos;
+};
+
+/* flags for RDR options */
+#define PF_DPORT_RANGE 0x01 /* Dest port uses range */
+#define PF_RPORT_RANGE 0x02 /* RDR'ed port uses range */
+
+/* Reasons code for passing/dropping a packet */
+#define PFRES_MATCH 0 /* Explicit match of a rule */
+#define PFRES_BADOFF 1 /* Bad offset for pull_hdr */
+#define PFRES_FRAG 2 /* Dropping following fragment */
+#define PFRES_SHORT 3 /* Dropping short packet */
+#define PFRES_NORM 4 /* Dropping by normalizer */
+#define PFRES_MEMORY 5 /* Dropped due to lacking mem */
+#define PFRES_TS 6 /* Bad TCP Timestamp (RFC1323) */
+#define PFRES_CONGEST 7 /* Congestion (of ipintrq) */
+#define PFRES_IPOPTIONS 8 /* IP option */
+#define PFRES_PROTCKSUM 9 /* Protocol checksum invalid */
+#define PFRES_BADSTATE 10 /* State mismatch */
+#define PFRES_STATEINS 11 /* State insertion failure */
+#define PFRES_MAXSTATES 12 /* State limit */
+#define PFRES_SRCLIMIT 13 /* Source node/conn limit */
+#define PFRES_SYNPROXY 14 /* SYN proxy */
+#define PFRES_MAX 15 /* total+1 */
+
+#define PFRES_NAMES { \
+ "match", \
+ "bad-offset", \
+ "fragment", \
+ "short", \
+ "normalize", \
+ "memory", \
+ "bad-timestamp", \
+ "congestion", \
+ "ip-option", \
+ "proto-cksum", \
+ "state-mismatch", \
+ "state-insert", \
+ "state-limit", \
+ "src-limit", \
+ "synproxy", \
+ NULL \
+}
+
+/* Counters for other things we want to keep track of */
+#define LCNT_STATES 0 /* states */
+#define LCNT_SRCSTATES 1 /* max-src-states */
+#define LCNT_SRCNODES 2 /* max-src-nodes */
+#define LCNT_SRCCONN 3 /* max-src-conn */
+#define LCNT_SRCCONNRATE 4 /* max-src-conn-rate */
+#define LCNT_OVERLOAD_TABLE 5 /* entry added to overload table */
+#define LCNT_OVERLOAD_FLUSH 6 /* state entries flushed */
+#define LCNT_MAX 7 /* total+1 */
+
+#define LCNT_NAMES { \
+ "max states per rule", \
+ "max-src-states", \
+ "max-src-nodes", \
+ "max-src-conn", \
+ "max-src-conn-rate", \
+ "overload table insertion", \
+ "overload flush states", \
+ NULL \
+}
+
+/* UDP state enumeration */
+#define PFUDPS_NO_TRAFFIC 0
+#define PFUDPS_SINGLE 1
+#define PFUDPS_MULTIPLE 2
+
+#define PFUDPS_NSTATES 3 /* number of state levels */
+
+#define PFUDPS_NAMES { \
+ "NO_TRAFFIC", \
+ "SINGLE", \
+ "MULTIPLE", \
+ NULL \
+}
+
+/* Other protocol state enumeration */
+#define PFOTHERS_NO_TRAFFIC 0
+#define PFOTHERS_SINGLE 1
+#define PFOTHERS_MULTIPLE 2
+
+#define PFOTHERS_NSTATES 3 /* number of state levels */
+
+#define PFOTHERS_NAMES { \
+ "NO_TRAFFIC", \
+ "SINGLE", \
+ "MULTIPLE", \
+ NULL \
+}
+
+#define FCNT_STATE_SEARCH 0
+#define FCNT_STATE_INSERT 1
+#define FCNT_STATE_REMOVALS 2
+#define FCNT_MAX 3
+
+#define SCNT_SRC_NODE_SEARCH 0
+#define SCNT_SRC_NODE_INSERT 1
+#define SCNT_SRC_NODE_REMOVALS 2
+#define SCNT_MAX 3
+
+#define ACTION_SET(a, x) \
+ do { \
+ if ((a) != NULL) \
+ *(a) = (x); \
+ } while (0)
+
+#define REASON_SET(a, x) \
+ do { \
+ if ((a) != NULL) \
+ *(a) = (x); \
+ if (x < PFRES_MAX) \
+ pf_status.counters[x]++; \
+ } while (0)
+
+struct pf_status {
+ u_int64_t counters[PFRES_MAX];
+ u_int64_t lcounters[LCNT_MAX]; /* limit counters */
+ u_int64_t fcounters[FCNT_MAX];
+ u_int64_t scounters[SCNT_MAX];
+ u_int64_t pcounters[2][2][3];
+ u_int64_t bcounters[2][2];
+ u_int64_t stateid;
+ u_int32_t running;
+ u_int32_t states;
+ u_int32_t src_nodes;
+ u_int32_t since;
+ u_int32_t debug;
+ u_int32_t hostid;
+ char ifname[IFNAMSIZ];
+ u_int8_t pf_chksum[PF_MD5_DIGEST_LENGTH];
+};
+
+struct cbq_opts {
+ u_int minburst;
+ u_int maxburst;
+ u_int pktsize;
+ u_int maxpktsize;
+ u_int ns_per_byte;
+ u_int maxidle;
+ int minidle;
+ u_int offtime;
+ int flags;
+};
+
+struct priq_opts {
+ int flags;
+};
+
+struct hfsc_opts {
+ /* real-time service curve */
+ u_int rtsc_m1; /* slope of the 1st segment in bps */
+ u_int rtsc_d; /* the x-projection of m1 in msec */
+ u_int rtsc_m2; /* slope of the 2nd segment in bps */
+ /* link-sharing service curve */
+ u_int lssc_m1;
+ u_int lssc_d;
+ u_int lssc_m2;
+ /* upper-limit service curve */
+ u_int ulsc_m1;
+ u_int ulsc_d;
+ u_int ulsc_m2;
+ int flags;
+};
+
+struct pf_altq {
+ char ifname[IFNAMSIZ];
+
+ void *altq_disc; /* discipline-specific state */
+ TAILQ_ENTRY(pf_altq) entries;
+
+ /* scheduler spec */
+ u_int8_t scheduler; /* scheduler type */
+ u_int16_t tbrsize; /* tokenbucket regulator size */
+ u_int32_t ifbandwidth; /* interface bandwidth */
+
+ /* queue spec */
+ char qname[PF_QNAME_SIZE]; /* queue name */
+ char parent[PF_QNAME_SIZE]; /* parent name */
+ u_int32_t parent_qid; /* parent queue id */
+ u_int32_t bandwidth; /* queue bandwidth */
+ u_int8_t priority; /* priority */
+#ifdef __FreeBSD__
+ u_int8_t local_flags; /* dynamic interface */
+#define PFALTQ_FLAG_IF_REMOVED 0x01
+#endif
+ u_int16_t qlimit; /* queue size limit */
+ u_int16_t flags; /* misc flags */
+ union {
+ struct cbq_opts cbq_opts;
+ struct priq_opts priq_opts;
+ struct hfsc_opts hfsc_opts;
+ } pq_u;
+
+ u_int32_t qid; /* return value */
+};
+
+#ifndef __FreeBSD__
+
+#define PF_TAG_GENERATED 0x01
+#define PF_TAG_FRAGCACHE 0x02
+#define PF_TAG_TRANSLATE_LOCALHOST 0x04
+
+struct pf_mtag {
+ void *hdr; /* saved hdr pos in mbuf, for ECN */
+ u_int rtableid; /* alternate routing table id */
+ u_int32_t qid; /* queue id */
+ u_int16_t tag; /* tag id */
+ u_int8_t flags;
+ u_int8_t routed;
+ sa_family_t af; /* for ECN */
+};
+#endif
+
+struct pf_tag {
+ u_int16_t tag; /* tag id */
+};
+
+struct pf_tagname {
+ TAILQ_ENTRY(pf_tagname) entries;
+ char name[PF_TAG_NAME_SIZE];
+ u_int16_t tag;
+ int ref;
+};
+
+#define PFFRAG_FRENT_HIWAT 5000 /* Number of fragment entries */
+#define PFFRAG_FRAG_HIWAT 1000 /* Number of fragmented packets */
+#define PFFRAG_FRCENT_HIWAT 50000 /* Number of fragment cache entries */
+#define PFFRAG_FRCACHE_HIWAT 10000 /* Number of fragment descriptors */
+
+#define PFR_KTABLE_HIWAT 1000 /* Number of tables */
+#define PFR_KENTRY_HIWAT 200000 /* Number of table entries */
+#define PFR_KENTRY_HIWAT_SMALL 100000 /* Number of table entries (tiny hosts) */
+
+/*
+ * ioctl parameter structures
+ */
+
+struct pfioc_pooladdr {
+ u_int32_t action;
+ u_int32_t ticket;
+ u_int32_t nr;
+ u_int32_t r_num;
+ u_int8_t r_action;
+ u_int8_t r_last;
+ u_int8_t af;
+ char anchor[MAXPATHLEN];
+ struct pf_pooladdr addr;
+};
+
+struct pfioc_rule {
+ u_int32_t action;
+ u_int32_t ticket;
+ u_int32_t pool_ticket;
+ u_int32_t nr;
+ char anchor[MAXPATHLEN];
+ char anchor_call[MAXPATHLEN];
+ struct pf_rule rule;
+};
+
+struct pfioc_natlook {
+ struct pf_addr saddr;
+ struct pf_addr daddr;
+ struct pf_addr rsaddr;
+ struct pf_addr rdaddr;
+ u_int16_t sport;
+ u_int16_t dport;
+ u_int16_t rsport;
+ u_int16_t rdport;
+ sa_family_t af;
+ u_int8_t proto;
+ u_int8_t direction;
+};
+
+struct pfioc_state {
+ u_int32_t nr;
+ struct pf_state state;
+};
+
+struct pfioc_src_node_kill {
+ /* XXX returns the number of src nodes killed in psnk_af */
+ sa_family_t psnk_af;
+ struct pf_rule_addr psnk_src;
+ struct pf_rule_addr psnk_dst;
+};
+
+struct pfioc_state_kill {
+ /* XXX returns the number of states killed in psk_af */
+ sa_family_t psk_af;
+ int psk_proto;
+ struct pf_rule_addr psk_src;
+ struct pf_rule_addr psk_dst;
+ char psk_ifname[IFNAMSIZ];
+};
+
+struct pfioc_states {
+ int ps_len;
+ union {
+ caddr_t psu_buf;
+ struct pf_state *psu_states;
+ } ps_u;
+#define ps_buf ps_u.psu_buf
+#define ps_states ps_u.psu_states
+};
+
+struct pfioc_src_nodes {
+ int psn_len;
+ union {
+ caddr_t psu_buf;
+ struct pf_src_node *psu_src_nodes;
+ } psn_u;
+#define psn_buf psn_u.psu_buf
+#define psn_src_nodes psn_u.psu_src_nodes
+};
+
+struct pfioc_if {
+ char ifname[IFNAMSIZ];
+};
+
+struct pfioc_tm {
+ int timeout;
+ int seconds;
+};
+
+struct pfioc_limit {
+ int index;
+ unsigned limit;
+};
+
+struct pfioc_altq {
+ u_int32_t action;
+ u_int32_t ticket;
+ u_int32_t nr;
+ struct pf_altq altq;
+};
+
+struct pfioc_qstats {
+ u_int32_t ticket;
+ u_int32_t nr;
+ void *buf;
+ int nbytes;
+ u_int8_t scheduler;
+};
+
+struct pfioc_ruleset {
+ u_int32_t nr;
+ char path[MAXPATHLEN];
+ char name[PF_ANCHOR_NAME_SIZE];
+};
+
+#define PF_RULESET_ALTQ (PF_RULESET_MAX)
+#define PF_RULESET_TABLE (PF_RULESET_MAX+1)
+struct pfioc_trans {
+ int size; /* number of elements */
+ int esize; /* size of each element in bytes */
+ struct pfioc_trans_e {
+ int rs_num;
+ char anchor[MAXPATHLEN];
+ u_int32_t ticket;
+ } *array;
+};
+
+#define PFR_FLAG_ATOMIC 0x00000001
+#define PFR_FLAG_DUMMY 0x00000002
+#define PFR_FLAG_FEEDBACK 0x00000004
+#define PFR_FLAG_CLSTATS 0x00000008
+#define PFR_FLAG_ADDRSTOO 0x00000010
+#define PFR_FLAG_REPLACE 0x00000020
+#define PFR_FLAG_ALLRSETS 0x00000040
+#define PFR_FLAG_ALLMASK 0x0000007F
+#ifdef _KERNEL
+#define PFR_FLAG_USERIOCTL 0x10000000
+#endif
+
+struct pfioc_table {
+ struct pfr_table pfrio_table;
+ void *pfrio_buffer;
+ int pfrio_esize;
+ int pfrio_size;
+ int pfrio_size2;
+ int pfrio_nadd;
+ int pfrio_ndel;
+ int pfrio_nchange;
+ int pfrio_flags;
+ u_int32_t pfrio_ticket;
+};
+#define pfrio_exists pfrio_nadd
+#define pfrio_nzero pfrio_nadd
+#define pfrio_nmatch pfrio_nadd
+#define pfrio_naddr pfrio_size2
+#define pfrio_setflag pfrio_size2
+#define pfrio_clrflag pfrio_nadd
+
+struct pfioc_iface {
+ char pfiio_name[IFNAMSIZ];
+ void *pfiio_buffer;
+ int pfiio_esize;
+ int pfiio_size;
+ int pfiio_nzero;
+ int pfiio_flags;
+};
+
+
+/*
+ * ioctl operations
+ */
+
+#define DIOCSTART _IO ('D', 1)
+#define DIOCSTOP _IO ('D', 2)
+#define DIOCADDRULE _IOWR('D', 4, struct pfioc_rule)
+#define DIOCGETRULES _IOWR('D', 6, struct pfioc_rule)
+#define DIOCGETRULE _IOWR('D', 7, struct pfioc_rule)
+/* XXX cut 8 - 17 */
+#define DIOCCLRSTATES _IOWR('D', 18, struct pfioc_state_kill)
+#define DIOCGETSTATE _IOWR('D', 19, struct pfioc_state)
+#define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if)
+#define DIOCGETSTATUS _IOWR('D', 21, struct pf_status)
+#define DIOCCLRSTATUS _IO ('D', 22)
+#define DIOCNATLOOK _IOWR('D', 23, struct pfioc_natlook)
+#define DIOCSETDEBUG _IOWR('D', 24, u_int32_t)
+#define DIOCGETSTATES _IOWR('D', 25, struct pfioc_states)
+#define DIOCCHANGERULE _IOWR('D', 26, struct pfioc_rule)
+/* XXX cut 26 - 28 */
+#define DIOCSETTIMEOUT _IOWR('D', 29, struct pfioc_tm)
+#define DIOCGETTIMEOUT _IOWR('D', 30, struct pfioc_tm)
+#define DIOCADDSTATE _IOWR('D', 37, struct pfioc_state)
+#define DIOCCLRRULECTRS _IO ('D', 38)
+#define DIOCGETLIMIT _IOWR('D', 39, struct pfioc_limit)
+#define DIOCSETLIMIT _IOWR('D', 40, struct pfioc_limit)
+#define DIOCKILLSTATES _IOWR('D', 41, struct pfioc_state_kill)
+#define DIOCSTARTALTQ _IO ('D', 42)
+#define DIOCSTOPALTQ _IO ('D', 43)
+#define DIOCADDALTQ _IOWR('D', 45, struct pfioc_altq)
+#define DIOCGETALTQS _IOWR('D', 47, struct pfioc_altq)
+#define DIOCGETALTQ _IOWR('D', 48, struct pfioc_altq)
+#define DIOCCHANGEALTQ _IOWR('D', 49, struct pfioc_altq)
+#define DIOCGETQSTATS _IOWR('D', 50, struct pfioc_qstats)
+#define DIOCBEGINADDRS _IOWR('D', 51, struct pfioc_pooladdr)
+#define DIOCADDADDR _IOWR('D', 52, struct pfioc_pooladdr)
+#define DIOCGETADDRS _IOWR('D', 53, struct pfioc_pooladdr)
+#define DIOCGETADDR _IOWR('D', 54, struct pfioc_pooladdr)
+#define DIOCCHANGEADDR _IOWR('D', 55, struct pfioc_pooladdr)
+/* XXX cut 55 - 57 */
+#define DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset)
+#define DIOCGETRULESET _IOWR('D', 59, struct pfioc_ruleset)
+#define DIOCRCLRTABLES _IOWR('D', 60, struct pfioc_table)
+#define DIOCRADDTABLES _IOWR('D', 61, struct pfioc_table)
+#define DIOCRDELTABLES _IOWR('D', 62, struct pfioc_table)
+#define DIOCRGETTABLES _IOWR('D', 63, struct pfioc_table)
+#define DIOCRGETTSTATS _IOWR('D', 64, struct pfioc_table)
+#define DIOCRCLRTSTATS _IOWR('D', 65, struct pfioc_table)
+#define DIOCRCLRADDRS _IOWR('D', 66, struct pfioc_table)
+#define DIOCRADDADDRS _IOWR('D', 67, struct pfioc_table)
+#define DIOCRDELADDRS _IOWR('D', 68, struct pfioc_table)
+#define DIOCRSETADDRS _IOWR('D', 69, struct pfioc_table)
+#define DIOCRGETADDRS _IOWR('D', 70, struct pfioc_table)
+#define DIOCRGETASTATS _IOWR('D', 71, struct pfioc_table)
+#define DIOCRCLRASTATS _IOWR('D', 72, struct pfioc_table)
+#define DIOCRTSTADDRS _IOWR('D', 73, struct pfioc_table)
+#define DIOCRSETTFLAGS _IOWR('D', 74, struct pfioc_table)
+#define DIOCRINADEFINE _IOWR('D', 77, struct pfioc_table)
+#define DIOCOSFPFLUSH _IO('D', 78)
+#define DIOCOSFPADD _IOWR('D', 79, struct pf_osfp_ioctl)
+#define DIOCOSFPGET _IOWR('D', 80, struct pf_osfp_ioctl)
+#define DIOCXBEGIN _IOWR('D', 81, struct pfioc_trans)
+#define DIOCXCOMMIT _IOWR('D', 82, struct pfioc_trans)
+#define DIOCXROLLBACK _IOWR('D', 83, struct pfioc_trans)
+#define DIOCGETSRCNODES _IOWR('D', 84, struct pfioc_src_nodes)
+#define DIOCCLRSRCNODES _IO('D', 85)
+#define DIOCSETHOSTID _IOWR('D', 86, u_int32_t)
+#define DIOCIGETIFACES _IOWR('D', 87, struct pfioc_iface)
+#define DIOCSETIFFLAG _IOWR('D', 89, struct pfioc_iface)
+#define DIOCCLRIFFLAG _IOWR('D', 90, struct pfioc_iface)
+#define DIOCKILLSRCNODES _IOWR('D', 91, struct pfioc_src_node_kill)
+#ifdef __FreeBSD__
+struct pf_ifspeed {
+ char ifname[IFNAMSIZ];
+ u_int32_t baudrate;
+};
+#define DIOCGIFSPEED _IOWR('D', 92, struct pf_ifspeed)
+#endif
+
+#ifdef _KERNEL
+RB_HEAD(pf_src_tree, pf_src_node);
+RB_PROTOTYPE(pf_src_tree, pf_src_node, entry, pf_src_compare);
+extern struct pf_src_tree tree_src_tracking;
+
+RB_HEAD(pf_state_tree_id, pf_state);
+RB_PROTOTYPE(pf_state_tree_id, pf_state,
+ entry_id, pf_state_compare_id);
+extern struct pf_state_tree_id tree_id;
+extern struct pf_state_queue state_list;
+
+TAILQ_HEAD(pf_poolqueue, pf_pool);
+extern struct pf_poolqueue pf_pools[2];
+TAILQ_HEAD(pf_altqqueue, pf_altq);
+extern struct pf_altqqueue pf_altqs[2];
+extern struct pf_palist pf_pabuf;
+
+extern u_int32_t ticket_altqs_active;
+extern u_int32_t ticket_altqs_inactive;
+extern int altqs_inactive_open;
+extern u_int32_t ticket_pabuf;
+extern struct pf_altqqueue *pf_altqs_active;
+extern struct pf_altqqueue *pf_altqs_inactive;
+extern struct pf_poolqueue *pf_pools_active;
+extern struct pf_poolqueue *pf_pools_inactive;
+extern int pf_tbladdr_setup(struct pf_ruleset *,
+ struct pf_addr_wrap *);
+extern void pf_tbladdr_remove(struct pf_addr_wrap *);
+extern void pf_tbladdr_copyout(struct pf_addr_wrap *);
+extern void pf_calc_skip_steps(struct pf_rulequeue *);
+#ifdef __FreeBSD__
+#ifdef ALTQ
+extern void pf_altq_ifnet_event(struct ifnet *, int);
+#endif
+extern uma_zone_t pf_src_tree_pl, pf_rule_pl;
+extern uma_zone_t pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+extern uma_zone_t pfr_ktable_pl, pfr_kentry_pl, pfr_kentry_pl2;
+extern uma_zone_t pf_cache_pl, pf_cent_pl;
+extern uma_zone_t pf_state_scrub_pl;
+extern uma_zone_t pfi_addr_pl;
+#else
+extern struct pool pf_src_tree_pl, pf_rule_pl;
+extern struct pool pf_state_pl, pf_altq_pl, pf_pooladdr_pl;
+extern struct pool pf_state_scrub_pl;
+#endif
+extern void pf_purge_thread(void *);
+#ifdef __FreeBSD__
+extern int pf_purge_expired_src_nodes(int);
+extern int pf_purge_expired_states(u_int32_t, int);
+#else
+extern void pf_purge_expired_src_nodes(int);
+extern void pf_purge_expired_states(u_int32_t);
+#endif
+extern void pf_unlink_state(struct pf_state *);
+extern void pf_free_state(struct pf_state *);
+extern int pf_insert_state(struct pfi_kif *,
+ struct pf_state *);
+extern int pf_insert_src_node(struct pf_src_node **,
+ struct pf_rule *, struct pf_addr *,
+ sa_family_t);
+void pf_src_tree_remove_state(struct pf_state *);
+extern struct pf_state *pf_find_state_byid(struct pf_state_cmp *);
+extern struct pf_state *pf_find_state_all(struct pf_state_cmp *key,
+ u_int8_t tree, int *more);
+extern void pf_print_state(struct pf_state *);
+extern void pf_print_flags(u_int8_t);
+extern u_int16_t pf_cksum_fixup(u_int16_t, u_int16_t, u_int16_t,
+ u_int8_t);
+
+extern struct ifnet *sync_ifp;
+extern struct pf_rule pf_default_rule;
+extern void pf_addrcpy(struct pf_addr *, struct pf_addr *,
+ u_int8_t);
+void pf_rm_rule(struct pf_rulequeue *,
+ struct pf_rule *);
+
+#ifdef INET
+#ifdef __FreeBSD__
+int pf_test(int, struct ifnet *, struct mbuf **, struct ether_header *,
+ struct inpcb *);
+#else
+int pf_test(int, struct ifnet *, struct mbuf **, struct ether_header *);
+#endif
+#endif /* INET */
+
+#ifdef INET6
+#ifdef __FreeBSD__
+int pf_test6(int, struct ifnet *, struct mbuf **, struct ether_header *,
+ struct inpcb *);
+#else
+int pf_test6(int, struct ifnet *, struct mbuf **, struct ether_header *);
+#endif
+void pf_poolmask(struct pf_addr *, struct pf_addr*,
+ struct pf_addr *, struct pf_addr *, u_int8_t);
+void pf_addr_inc(struct pf_addr *, sa_family_t);
+#endif /* INET6 */
+
+#ifdef __FreeBSD__
+u_int32_t pf_new_isn(struct pf_state *);
+#endif
+void *pf_pull_hdr(struct mbuf *, int, void *, int, u_short *, u_short *,
+ sa_family_t);
+void pf_change_a(void *, u_int16_t *, u_int32_t, u_int8_t);
+int pflog_packet(struct pfi_kif *, struct mbuf *, sa_family_t, u_int8_t,
+ u_int8_t, struct pf_rule *, struct pf_rule *, struct pf_ruleset *,
+ struct pf_pdesc *);
+int pf_match_addr(u_int8_t, struct pf_addr *, struct pf_addr *,
+ struct pf_addr *, sa_family_t);
+int pf_match(u_int8_t, u_int32_t, u_int32_t, u_int32_t);
+int pf_match_port(u_int8_t, u_int16_t, u_int16_t, u_int16_t);
+int pf_match_uid(u_int8_t, uid_t, uid_t, uid_t);
+int pf_match_gid(u_int8_t, gid_t, gid_t, gid_t);
+
+void pf_normalize_init(void);
+int pf_normalize_ip(struct mbuf **, int, struct pfi_kif *, u_short *,
+ struct pf_pdesc *);
+int pf_normalize_ip6(struct mbuf **, int, struct pfi_kif *, u_short *,
+ struct pf_pdesc *);
+int pf_normalize_tcp(int, struct pfi_kif *, struct mbuf *, int, int, void *,
+ struct pf_pdesc *);
+void pf_normalize_tcp_cleanup(struct pf_state *);
+int pf_normalize_tcp_init(struct mbuf *, int, struct pf_pdesc *,
+ struct tcphdr *, struct pf_state_peer *, struct pf_state_peer *);
+int pf_normalize_tcp_stateful(struct mbuf *, int, struct pf_pdesc *,
+ u_short *, struct tcphdr *, struct pf_state *,
+ struct pf_state_peer *, struct pf_state_peer *, int *);
+u_int32_t
+ pf_state_expires(const struct pf_state *);
+void pf_purge_expired_fragments(void);
+int pf_routable(struct pf_addr *addr, sa_family_t af, struct pfi_kif *);
+int pf_rtlabel_match(struct pf_addr *, sa_family_t, struct pf_addr_wrap *);
+#ifdef __FreeBSD__
+int pf_socket_lookup(int, struct pf_pdesc *, struct inpcb *);
+#else
+int pf_socket_lookup(int, struct pf_pdesc *);
+#endif
+void pfr_initialize(void);
+int pfr_match_addr(struct pfr_ktable *, struct pf_addr *, sa_family_t);
+void pfr_update_stats(struct pfr_ktable *, struct pf_addr *, sa_family_t,
+ u_int64_t, int, int, int);
+int pfr_pool_get(struct pfr_ktable *, int *, struct pf_addr *,
+ struct pf_addr **, struct pf_addr **, sa_family_t);
+void pfr_dynaddr_update(struct pfr_ktable *, struct pfi_dynaddr *);
+struct pfr_ktable *
+ pfr_attach_table(struct pf_ruleset *, char *);
+void pfr_detach_table(struct pfr_ktable *);
+int pfr_clr_tables(struct pfr_table *, int *, int);
+int pfr_add_tables(struct pfr_table *, int, int *, int);
+int pfr_del_tables(struct pfr_table *, int, int *, int);
+int pfr_get_tables(struct pfr_table *, struct pfr_table *, int *, int);
+int pfr_get_tstats(struct pfr_table *, struct pfr_tstats *, int *, int);
+int pfr_clr_tstats(struct pfr_table *, int, int *, int);
+int pfr_set_tflags(struct pfr_table *, int, int, int, int *, int *, int);
+int pfr_clr_addrs(struct pfr_table *, int *, int);
+int pfr_insert_kentry(struct pfr_ktable *, struct pfr_addr *, long);
+int pfr_add_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
+ int);
+int pfr_del_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
+ int);
+int pfr_set_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
+ int *, int *, int *, int, u_int32_t);
+int pfr_get_addrs(struct pfr_table *, struct pfr_addr *, int *, int);
+int pfr_get_astats(struct pfr_table *, struct pfr_astats *, int *, int);
+int pfr_clr_astats(struct pfr_table *, struct pfr_addr *, int, int *,
+ int);
+int pfr_tst_addrs(struct pfr_table *, struct pfr_addr *, int, int *,
+ int);
+int pfr_ina_begin(struct pfr_table *, u_int32_t *, int *, int);
+int pfr_ina_rollback(struct pfr_table *, u_int32_t, int *, int);
+int pfr_ina_commit(struct pfr_table *, u_int32_t, int *, int *, int);
+int pfr_ina_define(struct pfr_table *, struct pfr_addr *, int, int *,
+ int *, u_int32_t, int);
+
+extern struct pfi_statehead pfi_statehead;
+extern struct pfi_kif *pfi_all;
+
+void pfi_initialize(void);
+#ifdef __FreeBSD__
+void pfi_cleanup(void);
+#endif
+struct pfi_kif *pfi_kif_get(const char *);
+void pfi_kif_ref(struct pfi_kif *, enum pfi_kif_refs);
+void pfi_kif_unref(struct pfi_kif *, enum pfi_kif_refs);
+int pfi_kif_match(struct pfi_kif *, struct pfi_kif *);
+void pfi_attach_ifnet(struct ifnet *);
+void pfi_detach_ifnet(struct ifnet *);
+void pfi_attach_ifgroup(struct ifg_group *);
+void pfi_detach_ifgroup(struct ifg_group *);
+void pfi_group_change(const char *);
+int pfi_match_addr(struct pfi_dynaddr *, struct pf_addr *,
+ sa_family_t);
+int pfi_dynaddr_setup(struct pf_addr_wrap *, sa_family_t);
+void pfi_dynaddr_remove(struct pf_addr_wrap *);
+void pfi_dynaddr_copyout(struct pf_addr_wrap *);
+void pfi_fill_oldstatus(struct pf_status *);
+int pfi_clr_istats(const char *);
+int pfi_get_ifaces(const char *, struct pfi_kif *, int *);
+int pfi_set_flags(const char *, int);
+int pfi_clear_flags(const char *, int);
+
+u_int16_t pf_tagname2tag(char *);
+void pf_tag2tagname(u_int16_t, char *);
+void pf_tag_ref(u_int16_t);
+void pf_tag_unref(u_int16_t);
+int pf_tag_packet(struct mbuf *, struct pf_mtag *, int, int);
+u_int32_t pf_qname2qid(char *);
+void pf_qid2qname(u_int32_t, char *);
+void pf_qid_unref(u_int32_t);
+#ifndef __FreeBSD__
+struct pf_mtag *pf_find_mtag(struct mbuf *);
+struct pf_mtag *pf_get_mtag(struct mbuf *);
+#endif
+
+extern struct pf_status pf_status;
+
+#ifdef __FreeBSD__
+extern uma_zone_t pf_frent_pl, pf_frag_pl;
+extern struct sx pf_consistency_lock;
+#else
+extern struct pool pf_frent_pl, pf_frag_pl;
+extern struct rwlock pf_consistency_lock;
+#endif
+
+struct pf_pool_limit {
+ void *pp;
+ unsigned limit;
+};
+extern struct pf_pool_limit pf_pool_limits[PF_LIMIT_MAX];
+
+#ifdef __FreeBSD__
+struct pf_frent {
+ LIST_ENTRY(pf_frent) fr_next;
+ struct ip *fr_ip;
+ struct mbuf *fr_m;
+};
+
+struct pf_frcache {
+ LIST_ENTRY(pf_frcache) fr_next;
+ uint16_t fr_off;
+ uint16_t fr_end;
+};
+
+struct pf_fragment {
+ RB_ENTRY(pf_fragment) fr_entry;
+ TAILQ_ENTRY(pf_fragment) frag_next;
+ struct in_addr fr_src;
+ struct in_addr fr_dst;
+ u_int8_t fr_p; /* protocol of this fragment */
+ u_int8_t fr_flags; /* status flags */
+ u_int16_t fr_id; /* fragment id for reassemble */
+ u_int16_t fr_max; /* fragment data max */
+ u_int32_t fr_timeout;
+#define fr_queue fr_u.fru_queue
+#define fr_cache fr_u.fru_cache
+ union {
+ LIST_HEAD(pf_fragq, pf_frent) fru_queue; /* buffering */
+ LIST_HEAD(pf_cacheq, pf_frcache) fru_cache; /* non-buf */
+ } fr_u;
+};
+#endif /* (__FreeBSD__) */
+
+#endif /* _KERNEL */
+
+extern struct pf_anchor_global pf_anchors;
+extern struct pf_anchor pf_main_anchor;
+#define pf_main_ruleset pf_main_anchor.ruleset
+
+/* these ruleset functions can be linked into userland programs (pfctl) */
+int pf_get_ruleset_number(u_int8_t);
+void pf_init_ruleset(struct pf_ruleset *);
+int pf_anchor_setup(struct pf_rule *,
+ const struct pf_ruleset *, const char *);
+int pf_anchor_copyout(const struct pf_ruleset *,
+ const struct pf_rule *, struct pfioc_rule *);
+void pf_anchor_remove(struct pf_rule *);
+void pf_remove_if_empty_ruleset(struct pf_ruleset *);
+struct pf_anchor *pf_find_anchor(const char *);
+struct pf_ruleset *pf_find_ruleset(const char *);
+struct pf_ruleset *pf_find_or_create_ruleset(const char *);
+void pf_rs_initialize(void);
+
+#ifndef __FreeBSD__
+/* ?!? */
+#ifdef _KERNEL
+int pf_anchor_copyout(const struct pf_ruleset *,
+ const struct pf_rule *, struct pfioc_rule *);
+void pf_anchor_remove(struct pf_rule *);
+
+#endif /* _KERNEL */
+#endif
+
+/* The fingerprint functions can be linked into userland programs (tcpdump) */
+int pf_osfp_add(struct pf_osfp_ioctl *);
+#ifdef _KERNEL
+struct pf_osfp_enlist *
+ pf_osfp_fingerprint(struct pf_pdesc *, struct mbuf *, int,
+ const struct tcphdr *);
+#endif /* _KERNEL */
+struct pf_osfp_enlist *
+ pf_osfp_fingerprint_hdr(const struct ip *, const struct ip6_hdr *,
+ const struct tcphdr *);
+void pf_osfp_flush(void);
+int pf_osfp_get(struct pf_osfp_ioctl *);
+#ifdef __FreeBSD__
+int pf_osfp_initialize(void);
+void pf_osfp_cleanup(void);
+#else
+void pf_osfp_initialize(void);
+#endif
+int pf_osfp_match(struct pf_osfp_enlist *, pf_osfp_t);
+struct pf_os_fingerprint *
+ pf_osfp_validate(void);
+
+#endif /* _NET_PFVAR_HH_ */
diff --git a/freebsd/sys/contrib/pf/netinet/in4_cksum.c b/freebsd/sys/contrib/pf/netinet/in4_cksum.c
new file mode 100644
index 00000000..105f26f0
--- /dev/null
+++ b/freebsd/sys/contrib/pf/netinet/in4_cksum.c
@@ -0,0 +1,122 @@
+#include <freebsd/machine/rtems-bsd-config.h>
+
+/* $FreeBSD$ */
+/* $OpenBSD: in4_cksum.c,v 1.7 2003/06/02 23:28:13 millert Exp $ */
+/* $KAME: in4_cksum.c,v 1.10 2001/11/30 10:06:15 itojun Exp $ */
+/* $NetBSD: in_cksum.c,v 1.13 1996/10/13 02:03:03 christos Exp $ */
+
+/*
+ * Copyright (C) 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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) 1988, 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.
+ * 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.
+ *
+ * @(#)in_cksum.c 8.1 (Berkeley) 6/10/93
+ */
+
+#include <freebsd/sys/param.h>
+#include <freebsd/sys/systm.h>
+#include <freebsd/sys/mbuf.h>
+
+#include <freebsd/netinet/in.h>
+#include <freebsd/netinet/in_systm.h>
+#include <freebsd/netinet/ip.h>
+#include <freebsd/netinet/ip_var.h>
+
+#include <freebsd/machine/in_cksum.h>
+
+#define ADDCARRY(x) (x > 65535 ? x -= 65535 : x)
+#define REDUCE {l_util.l = sum; sum = l_util.s[0] + l_util.s[1]; ADDCARRY(sum);}
+
+int in4_cksum(struct mbuf *, u_int8_t, int, int);
+
+int
+in4_cksum(struct mbuf *m, u_int8_t nxt, int off, int len)
+{
+ union {
+ struct ipovly ipov;
+ u_int16_t w[10];
+ } u;
+ union {
+ u_int16_t s[2];
+ u_int32_t l;
+ } l_util;
+
+ u_int16_t *w;
+ int psum;
+ int sum = 0;
+
+ if (nxt != 0) {
+ /* pseudo header */
+ if (off < sizeof(struct ipovly))
+ panic("in4_cksum: offset too short");
+ if (m->m_len < sizeof(struct ip))
+ panic("in4_cksum: bad mbuf chain");
+ bzero(&u.ipov, sizeof(u.ipov));
+ u.ipov.ih_len = htons(len);
+ u.ipov.ih_pr = nxt;
+ u.ipov.ih_src = mtod(m, struct ip *)->ip_src;
+ u.ipov.ih_dst = mtod(m, struct ip *)->ip_dst;
+ w = u.w;
+ /* assumes sizeof(ipov) == 20 */
+ sum += w[0]; sum += w[1]; sum += w[2]; sum += w[3]; sum += w[4];
+ sum += w[5]; sum += w[6]; sum += w[7]; sum += w[8]; sum += w[9];
+ }
+
+ psum = in_cksum_skip(m, len + off, off);
+ psum = ~psum & 0xffff;
+ sum += psum;
+ REDUCE;
+ return (~sum & 0xffff);
+}
diff --git a/freebsd/sys/copyright.h b/freebsd/sys/copyright.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/copyright.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sys/cpuset.h b/freebsd/sys/cpuset.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/cpuset.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/crypto/blowfish/bf_ecb.c b/freebsd/sys/crypto/blowfish/bf_ecb.c
index 50f26508..50f26508 100644
--- a/freebsd/crypto/blowfish/bf_ecb.c
+++ b/freebsd/sys/crypto/blowfish/bf_ecb.c
diff --git a/freebsd/crypto/blowfish/bf_enc.c b/freebsd/sys/crypto/blowfish/bf_enc.c
index 59cb399b..59cb399b 100644
--- a/freebsd/crypto/blowfish/bf_enc.c
+++ b/freebsd/sys/crypto/blowfish/bf_enc.c
diff --git a/freebsd/crypto/blowfish/bf_locl.h b/freebsd/sys/crypto/blowfish/bf_locl.h
index 9314ff3c..9314ff3c 100644
--- a/freebsd/crypto/blowfish/bf_locl.h
+++ b/freebsd/sys/crypto/blowfish/bf_locl.h
diff --git a/freebsd/crypto/blowfish/bf_pi.h b/freebsd/sys/crypto/blowfish/bf_pi.h
index fdd5a27e..fdd5a27e 100644
--- a/freebsd/crypto/blowfish/bf_pi.h
+++ b/freebsd/sys/crypto/blowfish/bf_pi.h
diff --git a/freebsd/crypto/blowfish/bf_skey.c b/freebsd/sys/crypto/blowfish/bf_skey.c
index cc53ae55..cc53ae55 100644
--- a/freebsd/crypto/blowfish/bf_skey.c
+++ b/freebsd/sys/crypto/blowfish/bf_skey.c
diff --git a/freebsd/crypto/blowfish/blowfish.h b/freebsd/sys/crypto/blowfish/blowfish.h
index ecc14075..ecc14075 100644
--- a/freebsd/crypto/blowfish/blowfish.h
+++ b/freebsd/sys/crypto/blowfish/blowfish.h
diff --git a/freebsd/crypto/camellia/camellia-api.c b/freebsd/sys/crypto/camellia/camellia-api.c
index 1b749b48..1b749b48 100644
--- a/freebsd/crypto/camellia/camellia-api.c
+++ b/freebsd/sys/crypto/camellia/camellia-api.c
diff --git a/freebsd/crypto/camellia/camellia.c b/freebsd/sys/crypto/camellia/camellia.c
index 512dfd99..512dfd99 100644
--- a/freebsd/crypto/camellia/camellia.c
+++ b/freebsd/sys/crypto/camellia/camellia.c
diff --git a/freebsd/crypto/camellia/camellia.h b/freebsd/sys/crypto/camellia/camellia.h
index ab0ce57e..ab0ce57e 100644
--- a/freebsd/crypto/camellia/camellia.h
+++ b/freebsd/sys/crypto/camellia/camellia.h
diff --git a/freebsd/crypto/des/des.h b/freebsd/sys/crypto/des/des.h
index 81c7bfbe..81c7bfbe 100644
--- a/freebsd/crypto/des/des.h
+++ b/freebsd/sys/crypto/des/des.h
diff --git a/freebsd/crypto/des/des_ecb.c b/freebsd/sys/crypto/des/des_ecb.c
index 7c4c8386..7c4c8386 100644
--- a/freebsd/crypto/des/des_ecb.c
+++ b/freebsd/sys/crypto/des/des_ecb.c
diff --git a/freebsd/crypto/des/des_enc.c b/freebsd/sys/crypto/des/des_enc.c
index ec5f96dd..ec5f96dd 100644
--- a/freebsd/crypto/des/des_enc.c
+++ b/freebsd/sys/crypto/des/des_enc.c
diff --git a/freebsd/crypto/des/des_locl.h b/freebsd/sys/crypto/des/des_locl.h
index 6c92eb74..6c92eb74 100644
--- a/freebsd/crypto/des/des_locl.h
+++ b/freebsd/sys/crypto/des/des_locl.h
diff --git a/freebsd/crypto/des/des_setkey.c b/freebsd/sys/crypto/des/des_setkey.c
index 398a89d4..398a89d4 100644
--- a/freebsd/crypto/des/des_setkey.c
+++ b/freebsd/sys/crypto/des/des_setkey.c
diff --git a/freebsd/crypto/des/podd.h b/freebsd/sys/crypto/des/podd.h
index 0528b9ce..0528b9ce 100644
--- a/freebsd/crypto/des/podd.h
+++ b/freebsd/sys/crypto/des/podd.h
diff --git a/freebsd/crypto/des/sk.h b/freebsd/sys/crypto/des/sk.h
index d4aa3750..d4aa3750 100644
--- a/freebsd/crypto/des/sk.h
+++ b/freebsd/sys/crypto/des/sk.h
diff --git a/freebsd/crypto/des/spr.h b/freebsd/sys/crypto/des/spr.h
index 129b8277..129b8277 100644
--- a/freebsd/crypto/des/spr.h
+++ b/freebsd/sys/crypto/des/spr.h
diff --git a/freebsd/crypto/rc4/rc4.c b/freebsd/sys/crypto/rc4/rc4.c
index 417c3b44..417c3b44 100644
--- a/freebsd/crypto/rc4/rc4.c
+++ b/freebsd/sys/crypto/rc4/rc4.c
diff --git a/freebsd/crypto/rc4/rc4.h b/freebsd/sys/crypto/rc4/rc4.h
index 90723ddb..90723ddb 100644
--- a/freebsd/crypto/rc4/rc4.h
+++ b/freebsd/sys/crypto/rc4/rc4.h
diff --git a/freebsd/crypto/rijndael/rijndael-alg-fst.c b/freebsd/sys/crypto/rijndael/rijndael-alg-fst.c
index 351f6526..351f6526 100644
--- a/freebsd/crypto/rijndael/rijndael-alg-fst.c
+++ b/freebsd/sys/crypto/rijndael/rijndael-alg-fst.c
diff --git a/freebsd/crypto/rijndael/rijndael-api-fst.c b/freebsd/sys/crypto/rijndael/rijndael-api-fst.c
index d63997e5..d63997e5 100644
--- a/freebsd/crypto/rijndael/rijndael-api-fst.c
+++ b/freebsd/sys/crypto/rijndael/rijndael-api-fst.c
diff --git a/freebsd/crypto/rijndael/rijndael-api-fst.h b/freebsd/sys/crypto/rijndael/rijndael-api-fst.h
index f21cb790..f21cb790 100644
--- a/freebsd/crypto/rijndael/rijndael-api-fst.h
+++ b/freebsd/sys/crypto/rijndael/rijndael-api-fst.h
diff --git a/freebsd/crypto/rijndael/rijndael-api.c b/freebsd/sys/crypto/rijndael/rijndael-api.c
index 2134aa5c..2134aa5c 100644
--- a/freebsd/crypto/rijndael/rijndael-api.c
+++ b/freebsd/sys/crypto/rijndael/rijndael-api.c
diff --git a/freebsd/crypto/rijndael/rijndael.h b/freebsd/sys/crypto/rijndael/rijndael.h
index da855284..da855284 100644
--- a/freebsd/crypto/rijndael/rijndael.h
+++ b/freebsd/sys/crypto/rijndael/rijndael.h
diff --git a/freebsd/crypto/rijndael/rijndael_local.h b/freebsd/sys/crypto/rijndael/rijndael_local.h
index 7c765a2b..7c765a2b 100644
--- a/freebsd/crypto/rijndael/rijndael_local.h
+++ b/freebsd/sys/crypto/rijndael/rijndael_local.h
diff --git a/freebsd/crypto/sha1.c b/freebsd/sys/crypto/sha1.c
index 76b938af..76b938af 100644
--- a/freebsd/crypto/sha1.c
+++ b/freebsd/sys/crypto/sha1.c
diff --git a/freebsd/crypto/sha1.h b/freebsd/sys/crypto/sha1.h
index 18aedda0..18aedda0 100644
--- a/freebsd/crypto/sha1.h
+++ b/freebsd/sys/crypto/sha1.h
diff --git a/freebsd/crypto/sha2/sha2.c b/freebsd/sys/crypto/sha2/sha2.c
index 3303a318..3303a318 100644
--- a/freebsd/crypto/sha2/sha2.c
+++ b/freebsd/sys/crypto/sha2/sha2.c
diff --git a/freebsd/crypto/sha2/sha2.h b/freebsd/sys/crypto/sha2/sha2.h
index a2443ca1..a2443ca1 100644
--- a/freebsd/crypto/sha2/sha2.h
+++ b/freebsd/sys/crypto/sha2/sha2.h
diff --git a/freebsd/dev/bce/if_bce.c b/freebsd/sys/dev/bce/if_bce.c
index 646e6cbf..646e6cbf 100644
--- a/freebsd/dev/bce/if_bce.c
+++ b/freebsd/sys/dev/bce/if_bce.c
diff --git a/freebsd/dev/bce/if_bcefw.h b/freebsd/sys/dev/bce/if_bcefw.h
index c41ff10a..c41ff10a 100644
--- a/freebsd/dev/bce/if_bcefw.h
+++ b/freebsd/sys/dev/bce/if_bcefw.h
diff --git a/freebsd/dev/bce/if_bcereg.h b/freebsd/sys/dev/bce/if_bcereg.h
index 4ed5fdda..4ed5fdda 100644
--- a/freebsd/dev/bce/if_bcereg.h
+++ b/freebsd/sys/dev/bce/if_bcereg.h
diff --git a/freebsd/dev/bfe/if_bfe.c b/freebsd/sys/dev/bfe/if_bfe.c
index 7ce821b8..7ce821b8 100644
--- a/freebsd/dev/bfe/if_bfe.c
+++ b/freebsd/sys/dev/bfe/if_bfe.c
diff --git a/freebsd/dev/bfe/if_bfereg.h b/freebsd/sys/dev/bfe/if_bfereg.h
index b50627ed..b50627ed 100644
--- a/freebsd/dev/bfe/if_bfereg.h
+++ b/freebsd/sys/dev/bfe/if_bfereg.h
diff --git a/freebsd/dev/bge/if_bge.c b/freebsd/sys/dev/bge/if_bge.c
index 4ae441bd..4ae441bd 100644
--- a/freebsd/dev/bge/if_bge.c
+++ b/freebsd/sys/dev/bge/if_bge.c
diff --git a/freebsd/dev/bge/if_bgereg.h b/freebsd/sys/dev/bge/if_bgereg.h
index 6a9c2e81..6a9c2e81 100644
--- a/freebsd/dev/bge/if_bgereg.h
+++ b/freebsd/sys/dev/bge/if_bgereg.h
diff --git a/freebsd/dev/dc/dcphy.c b/freebsd/sys/dev/dc/dcphy.c
index 75ba2ce5..75ba2ce5 100644
--- a/freebsd/dev/dc/dcphy.c
+++ b/freebsd/sys/dev/dc/dcphy.c
diff --git a/freebsd/dev/dc/if_dc.c b/freebsd/sys/dev/dc/if_dc.c
index 512555b5..512555b5 100644
--- a/freebsd/dev/dc/if_dc.c
+++ b/freebsd/sys/dev/dc/if_dc.c
diff --git a/freebsd/dev/dc/if_dcreg.h b/freebsd/sys/dev/dc/if_dcreg.h
index b918ce49..b918ce49 100644
--- a/freebsd/dev/dc/if_dcreg.h
+++ b/freebsd/sys/dev/dc/if_dcreg.h
diff --git a/freebsd/dev/dc/pnphy.c b/freebsd/sys/dev/dc/pnphy.c
index d5837e54..d5837e54 100644
--- a/freebsd/dev/dc/pnphy.c
+++ b/freebsd/sys/dev/dc/pnphy.c
diff --git a/freebsd/dev/e1000/e1000_80003es2lan.c b/freebsd/sys/dev/e1000/e1000_80003es2lan.c
index bec2a8ac..bec2a8ac 100644
--- a/freebsd/dev/e1000/e1000_80003es2lan.c
+++ b/freebsd/sys/dev/e1000/e1000_80003es2lan.c
diff --git a/freebsd/dev/e1000/e1000_80003es2lan.h b/freebsd/sys/dev/e1000/e1000_80003es2lan.h
index 923d66b3..923d66b3 100644
--- a/freebsd/dev/e1000/e1000_80003es2lan.h
+++ b/freebsd/sys/dev/e1000/e1000_80003es2lan.h
diff --git a/freebsd/dev/e1000/e1000_82540.c b/freebsd/sys/dev/e1000/e1000_82540.c
index 2f2f0b08..2f2f0b08 100644
--- a/freebsd/dev/e1000/e1000_82540.c
+++ b/freebsd/sys/dev/e1000/e1000_82540.c
diff --git a/freebsd/dev/e1000/e1000_82541.c b/freebsd/sys/dev/e1000/e1000_82541.c
index 9faee5fd..9faee5fd 100644
--- a/freebsd/dev/e1000/e1000_82541.c
+++ b/freebsd/sys/dev/e1000/e1000_82541.c
diff --git a/freebsd/dev/e1000/e1000_82541.h b/freebsd/sys/dev/e1000/e1000_82541.h
index f730c3a4..f730c3a4 100644
--- a/freebsd/dev/e1000/e1000_82541.h
+++ b/freebsd/sys/dev/e1000/e1000_82541.h
diff --git a/freebsd/dev/e1000/e1000_82542.c b/freebsd/sys/dev/e1000/e1000_82542.c
index 96687ed4..96687ed4 100644
--- a/freebsd/dev/e1000/e1000_82542.c
+++ b/freebsd/sys/dev/e1000/e1000_82542.c
diff --git a/freebsd/dev/e1000/e1000_82543.c b/freebsd/sys/dev/e1000/e1000_82543.c
index 0836cf51..0836cf51 100644
--- a/freebsd/dev/e1000/e1000_82543.c
+++ b/freebsd/sys/dev/e1000/e1000_82543.c
diff --git a/freebsd/dev/e1000/e1000_82543.h b/freebsd/sys/dev/e1000/e1000_82543.h
index a95ad502..a95ad502 100644
--- a/freebsd/dev/e1000/e1000_82543.h
+++ b/freebsd/sys/dev/e1000/e1000_82543.h
diff --git a/freebsd/dev/e1000/e1000_82571.c b/freebsd/sys/dev/e1000/e1000_82571.c
index bb122d3e..bb122d3e 100644
--- a/freebsd/dev/e1000/e1000_82571.c
+++ b/freebsd/sys/dev/e1000/e1000_82571.c
diff --git a/freebsd/dev/e1000/e1000_82571.h b/freebsd/sys/dev/e1000/e1000_82571.h
index afccbf04..afccbf04 100644
--- a/freebsd/dev/e1000/e1000_82571.h
+++ b/freebsd/sys/dev/e1000/e1000_82571.h
diff --git a/freebsd/dev/e1000/e1000_82575.c b/freebsd/sys/dev/e1000/e1000_82575.c
index 5637832c..5637832c 100644
--- a/freebsd/dev/e1000/e1000_82575.c
+++ b/freebsd/sys/dev/e1000/e1000_82575.c
diff --git a/freebsd/dev/e1000/e1000_82575.h b/freebsd/sys/dev/e1000/e1000_82575.h
index 11a27b9b..11a27b9b 100644
--- a/freebsd/dev/e1000/e1000_82575.h
+++ b/freebsd/sys/dev/e1000/e1000_82575.h
diff --git a/freebsd/dev/e1000/e1000_api.c b/freebsd/sys/dev/e1000/e1000_api.c
index b7f72837..b7f72837 100644
--- a/freebsd/dev/e1000/e1000_api.c
+++ b/freebsd/sys/dev/e1000/e1000_api.c
diff --git a/freebsd/dev/e1000/e1000_api.h b/freebsd/sys/dev/e1000/e1000_api.h
index 94af19ce..94af19ce 100644
--- a/freebsd/dev/e1000/e1000_api.h
+++ b/freebsd/sys/dev/e1000/e1000_api.h
diff --git a/freebsd/dev/e1000/e1000_defines.h b/freebsd/sys/dev/e1000/e1000_defines.h
index 142903f9..142903f9 100644
--- a/freebsd/dev/e1000/e1000_defines.h
+++ b/freebsd/sys/dev/e1000/e1000_defines.h
diff --git a/freebsd/dev/e1000/e1000_hw.h b/freebsd/sys/dev/e1000/e1000_hw.h
index c51089f8..c51089f8 100644
--- a/freebsd/dev/e1000/e1000_hw.h
+++ b/freebsd/sys/dev/e1000/e1000_hw.h
diff --git a/freebsd/dev/e1000/e1000_ich8lan.c b/freebsd/sys/dev/e1000/e1000_ich8lan.c
index d8c02cb5..d8c02cb5 100644
--- a/freebsd/dev/e1000/e1000_ich8lan.c
+++ b/freebsd/sys/dev/e1000/e1000_ich8lan.c
diff --git a/freebsd/dev/e1000/e1000_ich8lan.h b/freebsd/sys/dev/e1000/e1000_ich8lan.h
index 9e87f4d5..9e87f4d5 100644
--- a/freebsd/dev/e1000/e1000_ich8lan.h
+++ b/freebsd/sys/dev/e1000/e1000_ich8lan.h
diff --git a/freebsd/dev/e1000/e1000_mac.c b/freebsd/sys/dev/e1000/e1000_mac.c
index 8b38ef9d..8b38ef9d 100644
--- a/freebsd/dev/e1000/e1000_mac.c
+++ b/freebsd/sys/dev/e1000/e1000_mac.c
diff --git a/freebsd/dev/e1000/e1000_mac.h b/freebsd/sys/dev/e1000/e1000_mac.h
index e1ec987e..e1ec987e 100644
--- a/freebsd/dev/e1000/e1000_mac.h
+++ b/freebsd/sys/dev/e1000/e1000_mac.h
diff --git a/freebsd/dev/e1000/e1000_manage.c b/freebsd/sys/dev/e1000/e1000_manage.c
index 4198425e..4198425e 100644
--- a/freebsd/dev/e1000/e1000_manage.c
+++ b/freebsd/sys/dev/e1000/e1000_manage.c
diff --git a/freebsd/dev/e1000/e1000_manage.h b/freebsd/sys/dev/e1000/e1000_manage.h
index 42f3bf2e..42f3bf2e 100644
--- a/freebsd/dev/e1000/e1000_manage.h
+++ b/freebsd/sys/dev/e1000/e1000_manage.h
diff --git a/freebsd/dev/e1000/e1000_mbx.c b/freebsd/sys/dev/e1000/e1000_mbx.c
index b30ede51..b30ede51 100644
--- a/freebsd/dev/e1000/e1000_mbx.c
+++ b/freebsd/sys/dev/e1000/e1000_mbx.c
diff --git a/freebsd/dev/e1000/e1000_mbx.h b/freebsd/sys/dev/e1000/e1000_mbx.h
index 4c705282..4c705282 100644
--- a/freebsd/dev/e1000/e1000_mbx.h
+++ b/freebsd/sys/dev/e1000/e1000_mbx.h
diff --git a/freebsd/dev/e1000/e1000_nvm.c b/freebsd/sys/dev/e1000/e1000_nvm.c
index cc2e9edc..cc2e9edc 100644
--- a/freebsd/dev/e1000/e1000_nvm.c
+++ b/freebsd/sys/dev/e1000/e1000_nvm.c
diff --git a/freebsd/dev/e1000/e1000_nvm.h b/freebsd/sys/dev/e1000/e1000_nvm.h
index 89b65a0f..89b65a0f 100644
--- a/freebsd/dev/e1000/e1000_nvm.h
+++ b/freebsd/sys/dev/e1000/e1000_nvm.h
diff --git a/freebsd/dev/e1000/e1000_osdep.c b/freebsd/sys/dev/e1000/e1000_osdep.c
index bf95d850..bf95d850 100644
--- a/freebsd/dev/e1000/e1000_osdep.c
+++ b/freebsd/sys/dev/e1000/e1000_osdep.c
diff --git a/freebsd/dev/e1000/e1000_osdep.h b/freebsd/sys/dev/e1000/e1000_osdep.h
index 64ea32e1..64ea32e1 100644
--- a/freebsd/dev/e1000/e1000_osdep.h
+++ b/freebsd/sys/dev/e1000/e1000_osdep.h
diff --git a/freebsd/dev/e1000/e1000_phy.c b/freebsd/sys/dev/e1000/e1000_phy.c
index 5b567f45..5b567f45 100644
--- a/freebsd/dev/e1000/e1000_phy.c
+++ b/freebsd/sys/dev/e1000/e1000_phy.c
diff --git a/freebsd/dev/e1000/e1000_phy.h b/freebsd/sys/dev/e1000/e1000_phy.h
index 7fd83969..7fd83969 100644
--- a/freebsd/dev/e1000/e1000_phy.h
+++ b/freebsd/sys/dev/e1000/e1000_phy.h
diff --git a/freebsd/dev/e1000/e1000_regs.h b/freebsd/sys/dev/e1000/e1000_regs.h
index 536f087f..536f087f 100644
--- a/freebsd/dev/e1000/e1000_regs.h
+++ b/freebsd/sys/dev/e1000/e1000_regs.h
diff --git a/freebsd/dev/e1000/e1000_vf.c b/freebsd/sys/dev/e1000/e1000_vf.c
index 943b24e7..943b24e7 100644
--- a/freebsd/dev/e1000/e1000_vf.c
+++ b/freebsd/sys/dev/e1000/e1000_vf.c
diff --git a/freebsd/dev/e1000/e1000_vf.h b/freebsd/sys/dev/e1000/e1000_vf.h
index 28bb4fde..28bb4fde 100644
--- a/freebsd/dev/e1000/e1000_vf.h
+++ b/freebsd/sys/dev/e1000/e1000_vf.h
diff --git a/freebsd/dev/e1000/if_em.c b/freebsd/sys/dev/e1000/if_em.c
index bc3ac3a3..bc3ac3a3 100644
--- a/freebsd/dev/e1000/if_em.c
+++ b/freebsd/sys/dev/e1000/if_em.c
diff --git a/freebsd/dev/e1000/if_em.h b/freebsd/sys/dev/e1000/if_em.h
index 19ccf0a6..19ccf0a6 100644
--- a/freebsd/dev/e1000/if_em.h
+++ b/freebsd/sys/dev/e1000/if_em.h
diff --git a/freebsd/dev/e1000/if_igb.c b/freebsd/sys/dev/e1000/if_igb.c
index 2653ccbb..2653ccbb 100644
--- a/freebsd/dev/e1000/if_igb.c
+++ b/freebsd/sys/dev/e1000/if_igb.c
diff --git a/freebsd/dev/e1000/if_igb.h b/freebsd/sys/dev/e1000/if_igb.h
index c77e9f17..c77e9f17 100644
--- a/freebsd/dev/e1000/if_igb.h
+++ b/freebsd/sys/dev/e1000/if_igb.h
diff --git a/freebsd/dev/e1000/if_lem.c b/freebsd/sys/dev/e1000/if_lem.c
index b0daee16..b0daee16 100644
--- a/freebsd/dev/e1000/if_lem.c
+++ b/freebsd/sys/dev/e1000/if_lem.c
diff --git a/freebsd/dev/e1000/if_lem.h b/freebsd/sys/dev/e1000/if_lem.h
index 21287b61..21287b61 100644
--- a/freebsd/dev/e1000/if_lem.h
+++ b/freebsd/sys/dev/e1000/if_lem.h
diff --git a/freebsd/dev/fxp/if_fxp.c b/freebsd/sys/dev/fxp/if_fxp.c
index 51ee51a9..51ee51a9 100644
--- a/freebsd/dev/fxp/if_fxp.c
+++ b/freebsd/sys/dev/fxp/if_fxp.c
diff --git a/freebsd/dev/fxp/if_fxpreg.h b/freebsd/sys/dev/fxp/if_fxpreg.h
index bb6a88b2..bb6a88b2 100644
--- a/freebsd/dev/fxp/if_fxpreg.h
+++ b/freebsd/sys/dev/fxp/if_fxpreg.h
diff --git a/freebsd/dev/fxp/if_fxpvar.h b/freebsd/sys/dev/fxp/if_fxpvar.h
index 5c2cf80b..5c2cf80b 100644
--- a/freebsd/dev/fxp/if_fxpvar.h
+++ b/freebsd/sys/dev/fxp/if_fxpvar.h
diff --git a/freebsd/dev/fxp/rcvbundl.h b/freebsd/sys/dev/fxp/rcvbundl.h
index 2510f420..2510f420 100644
--- a/freebsd/dev/fxp/rcvbundl.h
+++ b/freebsd/sys/dev/fxp/rcvbundl.h
diff --git a/freebsd/dev/led/led.c b/freebsd/sys/dev/led/led.c
index ae214909..ae214909 100644
--- a/freebsd/dev/led/led.c
+++ b/freebsd/sys/dev/led/led.c
diff --git a/freebsd/dev/led/led.h b/freebsd/sys/dev/led/led.h
index bbf301e5..bbf301e5 100644
--- a/freebsd/dev/led/led.h
+++ b/freebsd/sys/dev/led/led.h
diff --git a/freebsd/dev/mii/brgphy.c b/freebsd/sys/dev/mii/brgphy.c
index 9b53c83d..9b53c83d 100644
--- a/freebsd/dev/mii/brgphy.c
+++ b/freebsd/sys/dev/mii/brgphy.c
diff --git a/freebsd/dev/mii/brgphyreg.h b/freebsd/sys/dev/mii/brgphyreg.h
index fb8b65a5..fb8b65a5 100644
--- a/freebsd/dev/mii/brgphyreg.h
+++ b/freebsd/sys/dev/mii/brgphyreg.h
diff --git a/freebsd/dev/mii/icsphy.c b/freebsd/sys/dev/mii/icsphy.c
index a034eb36..a034eb36 100644
--- a/freebsd/dev/mii/icsphy.c
+++ b/freebsd/sys/dev/mii/icsphy.c
diff --git a/freebsd/dev/mii/icsphyreg.h b/freebsd/sys/dev/mii/icsphyreg.h
index a5754b7d..a5754b7d 100644
--- a/freebsd/dev/mii/icsphyreg.h
+++ b/freebsd/sys/dev/mii/icsphyreg.h
diff --git a/freebsd/dev/mii/mii.c b/freebsd/sys/dev/mii/mii.c
index c5aebad6..c5aebad6 100644
--- a/freebsd/dev/mii/mii.c
+++ b/freebsd/sys/dev/mii/mii.c
diff --git a/freebsd/dev/mii/mii.h b/freebsd/sys/dev/mii/mii.h
index 21c6b768..21c6b768 100644
--- a/freebsd/dev/mii/mii.h
+++ b/freebsd/sys/dev/mii/mii.h
diff --git a/freebsd/dev/mii/mii_physubr.c b/freebsd/sys/dev/mii/mii_physubr.c
index f5a278d6..f5a278d6 100644
--- a/freebsd/dev/mii/mii_physubr.c
+++ b/freebsd/sys/dev/mii/mii_physubr.c
diff --git a/freebsd/dev/mii/miivar.h b/freebsd/sys/dev/mii/miivar.h
index e8d467f7..e8d467f7 100644
--- a/freebsd/dev/mii/miivar.h
+++ b/freebsd/sys/dev/mii/miivar.h
diff --git a/freebsd/dev/pci/pci.c b/freebsd/sys/dev/pci/pci.c
index ebff0fff..ebff0fff 100644
--- a/freebsd/dev/pci/pci.c
+++ b/freebsd/sys/dev/pci/pci.c
diff --git a/freebsd/dev/pci/pci_pci.c b/freebsd/sys/dev/pci/pci_pci.c
index c2a829c8..c2a829c8 100644
--- a/freebsd/dev/pci/pci_pci.c
+++ b/freebsd/sys/dev/pci/pci_pci.c
diff --git a/freebsd/dev/pci/pci_private.h b/freebsd/sys/dev/pci/pci_private.h
index 93da2538..93da2538 100644
--- a/freebsd/dev/pci/pci_private.h
+++ b/freebsd/sys/dev/pci/pci_private.h
diff --git a/freebsd/dev/pci/pci_user.c b/freebsd/sys/dev/pci/pci_user.c
index c0b1eda0..c0b1eda0 100644
--- a/freebsd/dev/pci/pci_user.c
+++ b/freebsd/sys/dev/pci/pci_user.c
diff --git a/freebsd/dev/pci/pcib_private.h b/freebsd/sys/dev/pci/pcib_private.h
index 20f8da92..20f8da92 100644
--- a/freebsd/dev/pci/pcib_private.h
+++ b/freebsd/sys/dev/pci/pcib_private.h
diff --git a/freebsd/dev/pci/pcireg.h b/freebsd/sys/dev/pci/pcireg.h
index 9b4ad87b..9b4ad87b 100644
--- a/freebsd/dev/pci/pcireg.h
+++ b/freebsd/sys/dev/pci/pcireg.h
diff --git a/freebsd/dev/pci/pcivar.h b/freebsd/sys/dev/pci/pcivar.h
index a095db6d..a095db6d 100644
--- a/freebsd/dev/pci/pcivar.h
+++ b/freebsd/sys/dev/pci/pcivar.h
diff --git a/freebsd/dev/random/harvest.c b/freebsd/sys/dev/random/harvest.c
index 68c60676..68c60676 100644
--- a/freebsd/dev/random/harvest.c
+++ b/freebsd/sys/dev/random/harvest.c
diff --git a/freebsd/dev/random/randomdev_soft.h b/freebsd/sys/dev/random/randomdev_soft.h
index 489d45a3..489d45a3 100644
--- a/freebsd/dev/random/randomdev_soft.h
+++ b/freebsd/sys/dev/random/randomdev_soft.h
diff --git a/freebsd/dev/re/if_re.c b/freebsd/sys/dev/re/if_re.c
index 9424f670..9424f670 100644
--- a/freebsd/dev/re/if_re.c
+++ b/freebsd/sys/dev/re/if_re.c
diff --git a/freebsd/dev/smc/if_smc.c b/freebsd/sys/dev/smc/if_smc.c
index d943111f..d943111f 100644
--- a/freebsd/dev/smc/if_smc.c
+++ b/freebsd/sys/dev/smc/if_smc.c
diff --git a/freebsd/dev/smc/if_smcreg.h b/freebsd/sys/dev/smc/if_smcreg.h
index 50af8077..50af8077 100644
--- a/freebsd/dev/smc/if_smcreg.h
+++ b/freebsd/sys/dev/smc/if_smcreg.h
diff --git a/freebsd/dev/smc/if_smcvar.h b/freebsd/sys/dev/smc/if_smcvar.h
index a9e4a668..a9e4a668 100644
--- a/freebsd/dev/smc/if_smcvar.h
+++ b/freebsd/sys/dev/smc/if_smcvar.h
diff --git a/freebsd/dev/usb/controller/ehci.c b/freebsd/sys/dev/usb/controller/ehci.c
index 39221b7a..39221b7a 100644
--- a/freebsd/dev/usb/controller/ehci.c
+++ b/freebsd/sys/dev/usb/controller/ehci.c
diff --git a/freebsd/dev/usb/controller/ehci.h b/freebsd/sys/dev/usb/controller/ehci.h
index 26ba336e..26ba336e 100644
--- a/freebsd/dev/usb/controller/ehci.h
+++ b/freebsd/sys/dev/usb/controller/ehci.h
diff --git a/freebsd/dev/usb/controller/ehcireg.h b/freebsd/sys/dev/usb/controller/ehcireg.h
index 7677dfad..7677dfad 100644
--- a/freebsd/dev/usb/controller/ehcireg.h
+++ b/freebsd/sys/dev/usb/controller/ehcireg.h
diff --git a/freebsd/dev/usb/controller/ohci.c b/freebsd/sys/dev/usb/controller/ohci.c
index 28261d80..28261d80 100644
--- a/freebsd/dev/usb/controller/ohci.c
+++ b/freebsd/sys/dev/usb/controller/ohci.c
diff --git a/freebsd/dev/usb/controller/ohci.h b/freebsd/sys/dev/usb/controller/ohci.h
index 1affa420..1affa420 100644
--- a/freebsd/dev/usb/controller/ohci.h
+++ b/freebsd/sys/dev/usb/controller/ohci.h
diff --git a/freebsd/dev/usb/controller/ohcireg.h b/freebsd/sys/dev/usb/controller/ohcireg.h
index b3acb69b..b3acb69b 100644
--- a/freebsd/dev/usb/controller/ohcireg.h
+++ b/freebsd/sys/dev/usb/controller/ohcireg.h
diff --git a/freebsd/dev/usb/controller/usb_controller.c b/freebsd/sys/dev/usb/controller/usb_controller.c
index ee37c265..ee37c265 100644
--- a/freebsd/dev/usb/controller/usb_controller.c
+++ b/freebsd/sys/dev/usb/controller/usb_controller.c
diff --git a/freebsd/dev/usb/quirk/usb_quirk.c b/freebsd/sys/dev/usb/quirk/usb_quirk.c
index 8e597dea..8e597dea 100644
--- a/freebsd/dev/usb/quirk/usb_quirk.c
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.c
diff --git a/freebsd/dev/usb/quirk/usb_quirk.h b/freebsd/sys/dev/usb/quirk/usb_quirk.h
index e8cc0dbf..e8cc0dbf 100644
--- a/freebsd/dev/usb/quirk/usb_quirk.h
+++ b/freebsd/sys/dev/usb/quirk/usb_quirk.h
diff --git a/freebsd/dev/usb/storage/umass.c b/freebsd/sys/dev/usb/storage/umass.c
index b1867dc2..b1867dc2 100644
--- a/freebsd/dev/usb/storage/umass.c
+++ b/freebsd/sys/dev/usb/storage/umass.c
diff --git a/freebsd/dev/usb/ufm_ioctl.h b/freebsd/sys/dev/usb/ufm_ioctl.h
index 20a0b96e..20a0b96e 100644
--- a/freebsd/dev/usb/ufm_ioctl.h
+++ b/freebsd/sys/dev/usb/ufm_ioctl.h
diff --git a/freebsd/dev/usb/usb.h b/freebsd/sys/dev/usb/usb.h
index 9a6cb8f7..9a6cb8f7 100644
--- a/freebsd/dev/usb/usb.h
+++ b/freebsd/sys/dev/usb/usb.h
diff --git a/freebsd/dev/usb/usb_bus.h b/freebsd/sys/dev/usb/usb_bus.h
index b437fac0..b437fac0 100644
--- a/freebsd/dev/usb/usb_bus.h
+++ b/freebsd/sys/dev/usb/usb_bus.h
diff --git a/freebsd/dev/usb/usb_busdma.c b/freebsd/sys/dev/usb/usb_busdma.c
index 979136b8..979136b8 100644
--- a/freebsd/dev/usb/usb_busdma.c
+++ b/freebsd/sys/dev/usb/usb_busdma.c
diff --git a/freebsd/dev/usb/usb_busdma.h b/freebsd/sys/dev/usb/usb_busdma.h
index bd761819..bd761819 100644
--- a/freebsd/dev/usb/usb_busdma.h
+++ b/freebsd/sys/dev/usb/usb_busdma.h
diff --git a/freebsd/dev/usb/usb_cdc.h b/freebsd/sys/dev/usb/usb_cdc.h
index 632cfe9c..632cfe9c 100644
--- a/freebsd/dev/usb/usb_cdc.h
+++ b/freebsd/sys/dev/usb/usb_cdc.h
diff --git a/freebsd/dev/usb/usb_controller.h b/freebsd/sys/dev/usb/usb_controller.h
index 8f3f3de4..8f3f3de4 100644
--- a/freebsd/dev/usb/usb_controller.h
+++ b/freebsd/sys/dev/usb/usb_controller.h
diff --git a/freebsd/dev/usb/usb_core.c b/freebsd/sys/dev/usb/usb_core.c
index 17f9d903..17f9d903 100644
--- a/freebsd/dev/usb/usb_core.c
+++ b/freebsd/sys/dev/usb/usb_core.c
diff --git a/freebsd/dev/usb/usb_core.h b/freebsd/sys/dev/usb/usb_core.h
index 9d724171..9d724171 100644
--- a/freebsd/dev/usb/usb_core.h
+++ b/freebsd/sys/dev/usb/usb_core.h
diff --git a/freebsd/dev/usb/usb_debug.c b/freebsd/sys/dev/usb/usb_debug.c
index 907d31e1..907d31e1 100644
--- a/freebsd/dev/usb/usb_debug.c
+++ b/freebsd/sys/dev/usb/usb_debug.c
diff --git a/freebsd/dev/usb/usb_debug.h b/freebsd/sys/dev/usb/usb_debug.h
index aa3a5a49..aa3a5a49 100644
--- a/freebsd/dev/usb/usb_debug.h
+++ b/freebsd/sys/dev/usb/usb_debug.h
diff --git a/freebsd/dev/usb/usb_dev.c b/freebsd/sys/dev/usb/usb_dev.c
index 3517f7cc..3517f7cc 100644
--- a/freebsd/dev/usb/usb_dev.c
+++ b/freebsd/sys/dev/usb/usb_dev.c
diff --git a/freebsd/dev/usb/usb_dev.h b/freebsd/sys/dev/usb/usb_dev.h
index ccf873bd..ccf873bd 100644
--- a/freebsd/dev/usb/usb_dev.h
+++ b/freebsd/sys/dev/usb/usb_dev.h
diff --git a/freebsd/dev/usb/usb_device.c b/freebsd/sys/dev/usb/usb_device.c
index 1d5b5182..1d5b5182 100644
--- a/freebsd/dev/usb/usb_device.c
+++ b/freebsd/sys/dev/usb/usb_device.c
diff --git a/freebsd/dev/usb/usb_device.h b/freebsd/sys/dev/usb/usb_device.h
index eb6a3fcb..eb6a3fcb 100644
--- a/freebsd/dev/usb/usb_device.h
+++ b/freebsd/sys/dev/usb/usb_device.h
diff --git a/freebsd/dev/usb/usb_dynamic.c b/freebsd/sys/dev/usb/usb_dynamic.c
index 7651f97e..7651f97e 100644
--- a/freebsd/dev/usb/usb_dynamic.c
+++ b/freebsd/sys/dev/usb/usb_dynamic.c
diff --git a/freebsd/dev/usb/usb_dynamic.h b/freebsd/sys/dev/usb/usb_dynamic.h
index 32fc8362..32fc8362 100644
--- a/freebsd/dev/usb/usb_dynamic.h
+++ b/freebsd/sys/dev/usb/usb_dynamic.h
diff --git a/freebsd/dev/usb/usb_endian.h b/freebsd/sys/dev/usb/usb_endian.h
index 54c965d7..54c965d7 100644
--- a/freebsd/dev/usb/usb_endian.h
+++ b/freebsd/sys/dev/usb/usb_endian.h
diff --git a/freebsd/dev/usb/usb_error.c b/freebsd/sys/dev/usb/usb_error.c
index b9798a15..b9798a15 100644
--- a/freebsd/dev/usb/usb_error.c
+++ b/freebsd/sys/dev/usb/usb_error.c
diff --git a/freebsd/dev/usb/usb_freebsd.h b/freebsd/sys/dev/usb/usb_freebsd.h
index ed0f0356..ed0f0356 100644
--- a/freebsd/dev/usb/usb_freebsd.h
+++ b/freebsd/sys/dev/usb/usb_freebsd.h
diff --git a/freebsd/dev/usb/usb_generic.c b/freebsd/sys/dev/usb/usb_generic.c
index 89217a93..89217a93 100644
--- a/freebsd/dev/usb/usb_generic.c
+++ b/freebsd/sys/dev/usb/usb_generic.c
diff --git a/freebsd/dev/usb/usb_generic.h b/freebsd/sys/dev/usb/usb_generic.h
index 17506001..17506001 100644
--- a/freebsd/dev/usb/usb_generic.h
+++ b/freebsd/sys/dev/usb/usb_generic.h
diff --git a/freebsd/dev/usb/usb_handle_request.c b/freebsd/sys/dev/usb/usb_handle_request.c
index 40428d8b..40428d8b 100644
--- a/freebsd/dev/usb/usb_handle_request.c
+++ b/freebsd/sys/dev/usb/usb_handle_request.c
diff --git a/freebsd/dev/usb/usb_hid.c b/freebsd/sys/dev/usb/usb_hid.c
index b1780aff..b1780aff 100644
--- a/freebsd/dev/usb/usb_hid.c
+++ b/freebsd/sys/dev/usb/usb_hid.c
diff --git a/freebsd/dev/usb/usb_hub.c b/freebsd/sys/dev/usb/usb_hub.c
index 4f34f25e..4f34f25e 100644
--- a/freebsd/dev/usb/usb_hub.c
+++ b/freebsd/sys/dev/usb/usb_hub.c
diff --git a/freebsd/dev/usb/usb_hub.h b/freebsd/sys/dev/usb/usb_hub.h
index 6f4637da..6f4637da 100644
--- a/freebsd/dev/usb/usb_hub.h
+++ b/freebsd/sys/dev/usb/usb_hub.h
diff --git a/freebsd/dev/usb/usb_ioctl.h b/freebsd/sys/dev/usb/usb_ioctl.h
index 99e21f09..99e21f09 100644
--- a/freebsd/dev/usb/usb_ioctl.h
+++ b/freebsd/sys/dev/usb/usb_ioctl.h
diff --git a/freebsd/dev/usb/usb_lookup.c b/freebsd/sys/dev/usb/usb_lookup.c
index c730b6ba..c730b6ba 100644
--- a/freebsd/dev/usb/usb_lookup.c
+++ b/freebsd/sys/dev/usb/usb_lookup.c
diff --git a/freebsd/dev/usb/usb_mbuf.c b/freebsd/sys/dev/usb/usb_mbuf.c
index 5aa99df4..5aa99df4 100644
--- a/freebsd/dev/usb/usb_mbuf.c
+++ b/freebsd/sys/dev/usb/usb_mbuf.c
diff --git a/freebsd/dev/usb/usb_mbuf.h b/freebsd/sys/dev/usb/usb_mbuf.h
index 44dba71b..44dba71b 100644
--- a/freebsd/dev/usb/usb_mbuf.h
+++ b/freebsd/sys/dev/usb/usb_mbuf.h
diff --git a/freebsd/dev/usb/usb_msctest.c b/freebsd/sys/dev/usb/usb_msctest.c
index 0b773e29..0b773e29 100644
--- a/freebsd/dev/usb/usb_msctest.c
+++ b/freebsd/sys/dev/usb/usb_msctest.c
diff --git a/freebsd/dev/usb/usb_msctest.h b/freebsd/sys/dev/usb/usb_msctest.h
index 6ba2c3fd..6ba2c3fd 100644
--- a/freebsd/dev/usb/usb_msctest.h
+++ b/freebsd/sys/dev/usb/usb_msctest.h
diff --git a/freebsd/dev/usb/usb_parse.c b/freebsd/sys/dev/usb/usb_parse.c
index 8681a94a..8681a94a 100644
--- a/freebsd/dev/usb/usb_parse.c
+++ b/freebsd/sys/dev/usb/usb_parse.c
diff --git a/freebsd/dev/usb/usb_process.c b/freebsd/sys/dev/usb/usb_process.c
index cfaa5ee6..cfaa5ee6 100644
--- a/freebsd/dev/usb/usb_process.c
+++ b/freebsd/sys/dev/usb/usb_process.c
diff --git a/freebsd/dev/usb/usb_process.h b/freebsd/sys/dev/usb/usb_process.h
index 75c86ece..75c86ece 100644
--- a/freebsd/dev/usb/usb_process.h
+++ b/freebsd/sys/dev/usb/usb_process.h
diff --git a/freebsd/dev/usb/usb_request.c b/freebsd/sys/dev/usb/usb_request.c
index 61dafd7d..61dafd7d 100644
--- a/freebsd/dev/usb/usb_request.c
+++ b/freebsd/sys/dev/usb/usb_request.c
diff --git a/freebsd/dev/usb/usb_request.h b/freebsd/sys/dev/usb/usb_request.h
index 0cf882dc..0cf882dc 100644
--- a/freebsd/dev/usb/usb_request.h
+++ b/freebsd/sys/dev/usb/usb_request.h
diff --git a/freebsd/dev/usb/usb_transfer.c b/freebsd/sys/dev/usb/usb_transfer.c
index caf3d31b..caf3d31b 100644
--- a/freebsd/dev/usb/usb_transfer.c
+++ b/freebsd/sys/dev/usb/usb_transfer.c
diff --git a/freebsd/dev/usb/usb_transfer.h b/freebsd/sys/dev/usb/usb_transfer.h
index eb2abd0c..eb2abd0c 100644
--- a/freebsd/dev/usb/usb_transfer.h
+++ b/freebsd/sys/dev/usb/usb_transfer.h
diff --git a/freebsd/dev/usb/usb_util.c b/freebsd/sys/dev/usb/usb_util.c
index 3bd1f8c4..3bd1f8c4 100644
--- a/freebsd/dev/usb/usb_util.c
+++ b/freebsd/sys/dev/usb/usb_util.c
diff --git a/freebsd/dev/usb/usb_util.h b/freebsd/sys/dev/usb/usb_util.h
index 9e001088..9e001088 100644
--- a/freebsd/dev/usb/usb_util.h
+++ b/freebsd/sys/dev/usb/usb_util.h
diff --git a/freebsd/dev/usb/usbdi.h b/freebsd/sys/dev/usb/usbdi.h
index a3f0630f..a3f0630f 100644
--- a/freebsd/dev/usb/usbdi.h
+++ b/freebsd/sys/dev/usb/usbdi.h
diff --git a/freebsd/dev/usb/usbdi_util.h b/freebsd/sys/dev/usb/usbdi_util.h
index 32931e52..32931e52 100644
--- a/freebsd/dev/usb/usbdi_util.h
+++ b/freebsd/sys/dev/usb/usbdi_util.h
diff --git a/freebsd/dev/usb/usbhid.h b/freebsd/sys/dev/usb/usbhid.h
index 192a2359..192a2359 100644
--- a/freebsd/dev/usb/usbhid.h
+++ b/freebsd/sys/dev/usb/usbhid.h
diff --git a/freebsd/sys/errno.h b/freebsd/sys/errno.h
deleted file mode 100644
index 9b68014d..00000000
--- a/freebsd/sys/errno.h
+++ /dev/null
@@ -1,194 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)errno.h 8.5 (Berkeley) 1/21/94
- * $FreeBSD$
- */
-
-#ifndef _SYS_ERRNO_HH_
-#define _SYS_ERRNO_HH_
-
-#ifndef _KERNEL
-#include <freebsd/sys/cdefs.h>
-__BEGIN_DECLS
-int * __error(void);
-__END_DECLS
-#define errno (* __error())
-#endif
-
-#ifndef __rtems__
-#define EPERM 1 /* Operation not permitted */
-#define ENOENT 2 /* No such file or directory */
-#define ESRCH 3 /* No such process */
-#define EINTR 4 /* Interrupted system call */
-#define EIO 5 /* Input/output error */
-#define ENXIO 6 /* Device not configured */
-#define E2BIG 7 /* Argument list too long */
-#define ENOEXEC 8 /* Exec format error */
-#define EBADF 9 /* Bad file descriptor */
-#define ECHILD 10 /* No child processes */
-#define EDEADLK 11 /* Resource deadlock avoided */
- /* 11 was EAGAIN */
-#define ENOMEM 12 /* Cannot allocate memory */
-#define EACCES 13 /* Permission denied */
-#define EFAULT 14 /* Bad address */
-#ifndef _POSIX_SOURCE
-#define ENOTBLK 15 /* Block device required */
-#endif
-#define EBUSY 16 /* Device busy */
-#define EEXIST 17 /* File exists */
-#define EXDEV 18 /* Cross-device link */
-#define ENODEV 19 /* Operation not supported by device */
-#define ENOTDIR 20 /* Not a directory */
-#define EISDIR 21 /* Is a directory */
-#define EINVAL 22 /* Invalid argument */
-#define ENFILE 23 /* Too many open files in system */
-#define EMFILE 24 /* Too many open files */
-#define ENOTTY 25 /* Inappropriate ioctl for device */
-#ifndef _POSIX_SOURCE
-#define ETXTBSY 26 /* Text file busy */
-#endif
-#define EFBIG 27 /* File too large */
-#define ENOSPC 28 /* No space left on device */
-#define ESPIPE 29 /* Illegal seek */
-#define EROFS 30 /* Read-only filesystem */
-#define EMLINK 31 /* Too many links */
-#define EPIPE 32 /* Broken pipe */
-
-/* math software */
-#define EDOM 33 /* Numerical argument out of domain */
-#define ERANGE 34 /* Result too large */
-
-/* non-blocking and interrupt i/o */
-#define EAGAIN 35 /* Resource temporarily unavailable */
-#ifndef _POSIX_SOURCE
-#define EWOULDBLOCK EAGAIN /* Operation would block */
-#define EINPROGRESS 36 /* Operation now in progress */
-#define EALREADY 37 /* Operation already in progress */
-
-/* ipc/network software -- argument errors */
-#define ENOTSOCK 38 /* Socket operation on non-socket */
-#define EDESTADDRREQ 39 /* Destination address required */
-#define EMSGSIZE 40 /* Message too long */
-#define EPROTOTYPE 41 /* Protocol wrong type for socket */
-#define ENOPROTOOPT 42 /* Protocol not available */
-#define EPROTONOSUPPORT 43 /* Protocol not supported */
-#define ESOCKTNOSUPPORT 44 /* Socket type not supported */
-#define EOPNOTSUPP 45 /* Operation not supported */
-#define ENOTSUP EOPNOTSUPP /* Operation not supported */
-#define EPFNOSUPPORT 46 /* Protocol family not supported */
-#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */
-#define EADDRINUSE 48 /* Address already in use */
-#define EADDRNOTAVAIL 49 /* Can't assign requested address */
-
-/* ipc/network software -- operational errors */
-#define ENETDOWN 50 /* Network is down */
-#define ENETUNREACH 51 /* Network is unreachable */
-#define ENETRESET 52 /* Network dropped connection on reset */
-#define ECONNABORTED 53 /* Software caused connection abort */
-#define ECONNRESET 54 /* Connection reset by peer */
-#define ENOBUFS 55 /* No buffer space available */
-#define EISCONN 56 /* Socket is already connected */
-#define ENOTCONN 57 /* Socket is not connected */
-#define ESHUTDOWN 58 /* Can't send after socket shutdown */
-#define ETOOMANYREFS 59 /* Too many references: can't splice */
-#define ETIMEDOUT 60 /* Operation timed out */
-#define ECONNREFUSED 61 /* Connection refused */
-
-#define ELOOP 62 /* Too many levels of symbolic links */
-#endif /* _POSIX_SOURCE */
-#define ENAMETOOLONG 63 /* File name too long */
-
-/* should be rearranged */
-#ifndef _POSIX_SOURCE
-#define EHOSTDOWN 64 /* Host is down */
-#define EHOSTUNREACH 65 /* No route to host */
-#endif /* _POSIX_SOURCE */
-#define ENOTEMPTY 66 /* Directory not empty */
-
-/* quotas & mush */
-#ifndef _POSIX_SOURCE
-#define EPROCLIM 67 /* Too many processes */
-#define EUSERS 68 /* Too many users */
-#define EDQUOT 69 /* Disc quota exceeded */
-
-/* Network File System */
-#define ESTALE 70 /* Stale NFS file handle */
-#define EREMOTE 71 /* Too many levels of remote in path */
-#define EBADRPC 72 /* RPC struct is bad */
-#define ERPCMISMATCH 73 /* RPC version wrong */
-#define EPROGUNAVAIL 74 /* RPC prog. not avail */
-#define EPROGMISMATCH 75 /* Program version wrong */
-#define EPROCUNAVAIL 76 /* Bad procedure for program */
-#endif /* _POSIX_SOURCE */
-
-#define ENOLCK 77 /* No locks available */
-#define ENOSYS 78 /* Function not implemented */
-
-#ifndef _POSIX_SOURCE
-#define EFTYPE 79 /* Inappropriate file type or format */
-#define EAUTH 80 /* Authentication error */
-#define ENEEDAUTH 81 /* Need authenticator */
-#define EIDRM 82 /* Identifier removed */
-#define ENOMSG 83 /* No message of desired type */
-#define EOVERFLOW 84 /* Value too large to be stored in data type */
-#define ECANCELED 85 /* Operation canceled */
-#define EILSEQ 86 /* Illegal byte sequence */
-#define ENOATTR 87 /* Attribute not found */
-
-#define EDOOFUS 88 /* Programming error */
-#endif /* _POSIX_SOURCE */
-
-#define EBADMSG 89 /* Bad message */
-#define EMULTIHOP 90 /* Multihop attempted */
-#define ENOLINK 91 /* Link has been severed */
-#define EPROTO 92 /* Protocol error */
-
-#ifndef _POSIX_SOURCE
-#define ENOTCAPABLE 93 /* Capabilities insufficient */
-#endif /* _POSIX_SOURCE */
-
-#ifndef _POSIX_SOURCE
-#define ELAST 93 /* Must be equal largest errno */
-#endif /* _POSIX_SOURCE */
-#endif /* __rtems__ */
-
-#ifdef _KERNEL
-/* pseudo-errors returned inside kernel to modify return to process */
-#define ERESTART (-1) /* restart syscall */
-#define EJUSTRETURN (-2) /* don't modify regs, just return */
-#define ENOIOCTL (-3) /* ioctl not handled by this layer */
-#define EDIRIOCTL (-4) /* do direct ioctl in GEOM */
-#endif
-
-#endif
diff --git a/freebsd/sys/exec.h b/freebsd/sys/exec.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/exec.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sys/fail.h b/freebsd/sys/fail.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/fail.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/fs/devfs/devfs_int.h b/freebsd/sys/fs/devfs/devfs_int.h
index 723cbc22..723cbc22 100644
--- a/freebsd/fs/devfs/devfs_int.h
+++ b/freebsd/sys/fs/devfs/devfs_int.h
diff --git a/freebsd/powerpc/include/freebsd/machine/in_cksum.h b/freebsd/sys/h8300/include/machine/in_cksum.h
index 25634a6e..25634a6e 100644
--- a/freebsd/powerpc/include/freebsd/machine/in_cksum.h
+++ b/freebsd/sys/h8300/include/machine/in_cksum.h
diff --git a/freebsd/i386/i386/in_cksum.c b/freebsd/sys/i386/i386/in_cksum.c
index 0f663989..0f663989 100644
--- a/freebsd/i386/i386/in_cksum.c
+++ b/freebsd/sys/i386/i386/in_cksum.c
diff --git a/freebsd/i386/i386/legacy.c b/freebsd/sys/i386/i386/legacy.c
index 24021809..24021809 100644
--- a/freebsd/i386/i386/legacy.c
+++ b/freebsd/sys/i386/i386/legacy.c
diff --git a/freebsd/i386/include/freebsd/machine/cpufunc.h b/freebsd/sys/i386/include/machine/cpufunc.h
index 093e38a4..093e38a4 100644
--- a/freebsd/i386/include/freebsd/machine/cpufunc.h
+++ b/freebsd/sys/i386/include/machine/cpufunc.h
diff --git a/freebsd/sparc64/include/freebsd/machine/in_cksum.h b/freebsd/sys/i386/include/machine/in_cksum.h
index c121f46d..c121f46d 100644
--- a/freebsd/sparc64/include/freebsd/machine/in_cksum.h
+++ b/freebsd/sys/i386/include/machine/in_cksum.h
diff --git a/freebsd/i386/include/freebsd/machine/intr_machdep.h b/freebsd/sys/i386/include/machine/intr_machdep.h
index 0dbef09d..0dbef09d 100644
--- a/freebsd/i386/include/freebsd/machine/intr_machdep.h
+++ b/freebsd/sys/i386/include/machine/intr_machdep.h
diff --git a/freebsd/i386/include/freebsd/machine/md_var.h b/freebsd/sys/i386/include/machine/md_var.h
index 43bd0491..43bd0491 100644
--- a/freebsd/i386/include/freebsd/machine/md_var.h
+++ b/freebsd/sys/i386/include/machine/md_var.h
diff --git a/freebsd/i386/include/freebsd/machine/specialreg.h b/freebsd/sys/i386/include/machine/specialreg.h
index 4cbd0ec2..4cbd0ec2 100644
--- a/freebsd/i386/include/freebsd/machine/specialreg.h
+++ b/freebsd/sys/i386/include/machine/specialreg.h
diff --git a/freebsd/isa/isavar.h b/freebsd/sys/isa/isavar.h
index c27961d2..c27961d2 100644
--- a/freebsd/isa/isavar.h
+++ b/freebsd/sys/isa/isavar.h
diff --git a/freebsd/isa/pnpvar.h b/freebsd/sys/isa/pnpvar.h
index 8636ee5e..8636ee5e 100644
--- a/freebsd/isa/pnpvar.h
+++ b/freebsd/sys/isa/pnpvar.h
diff --git a/freebsd/kern/init_main.c b/freebsd/sys/kern/init_main.c
index 0225a246..0225a246 100644
--- a/freebsd/kern/init_main.c
+++ b/freebsd/sys/kern/init_main.c
diff --git a/freebsd/kern/kern_descrip.c b/freebsd/sys/kern/kern_descrip.c
index 0ba063f5..0ba063f5 100644
--- a/freebsd/kern/kern_descrip.c
+++ b/freebsd/sys/kern/kern_descrip.c
diff --git a/freebsd/kern/kern_environment.c b/freebsd/sys/kern/kern_environment.c
index faee420d..faee420d 100644
--- a/freebsd/kern/kern_environment.c
+++ b/freebsd/sys/kern/kern_environment.c
diff --git a/freebsd/kern/kern_event.c b/freebsd/sys/kern/kern_event.c
index 401f859e..401f859e 100644
--- a/freebsd/kern/kern_event.c
+++ b/freebsd/sys/kern/kern_event.c
diff --git a/freebsd/kern/kern_intr.c b/freebsd/sys/kern/kern_intr.c
index 982d5e82..982d5e82 100644
--- a/freebsd/kern/kern_intr.c
+++ b/freebsd/sys/kern/kern_intr.c
diff --git a/freebsd/kern/kern_linker.c b/freebsd/sys/kern/kern_linker.c
index 15141f22..15141f22 100644
--- a/freebsd/kern/kern_linker.c
+++ b/freebsd/sys/kern/kern_linker.c
diff --git a/freebsd/kern/kern_mbuf.c b/freebsd/sys/kern/kern_mbuf.c
index cca38078..cca38078 100644
--- a/freebsd/kern/kern_mbuf.c
+++ b/freebsd/sys/kern/kern_mbuf.c
diff --git a/freebsd/kern/kern_mib.c b/freebsd/sys/kern/kern_mib.c
index 0acf89e5..0acf89e5 100644
--- a/freebsd/kern/kern_mib.c
+++ b/freebsd/sys/kern/kern_mib.c
diff --git a/freebsd/kern/kern_module.c b/freebsd/sys/kern/kern_module.c
index 0476efef..0476efef 100644
--- a/freebsd/kern/kern_module.c
+++ b/freebsd/sys/kern/kern_module.c
diff --git a/freebsd/kern/kern_mtxpool.c b/freebsd/sys/kern/kern_mtxpool.c
index b2c0267a..b2c0267a 100644
--- a/freebsd/kern/kern_mtxpool.c
+++ b/freebsd/sys/kern/kern_mtxpool.c
diff --git a/freebsd/kern/kern_ntptime.c b/freebsd/sys/kern/kern_ntptime.c
index 33aa4908..33aa4908 100644
--- a/freebsd/kern/kern_ntptime.c
+++ b/freebsd/sys/kern/kern_ntptime.c
diff --git a/freebsd/kern/kern_proc.c b/freebsd/sys/kern/kern_proc.c
index a646aa35..a646aa35 100644
--- a/freebsd/kern/kern_proc.c
+++ b/freebsd/sys/kern/kern_proc.c
diff --git a/freebsd/kern/kern_prot.c b/freebsd/sys/kern/kern_prot.c
index e969dfa7..e969dfa7 100644
--- a/freebsd/kern/kern_prot.c
+++ b/freebsd/sys/kern/kern_prot.c
diff --git a/freebsd/kern/kern_resource.c b/freebsd/sys/kern/kern_resource.c
index 939a1d24..939a1d24 100644
--- a/freebsd/kern/kern_resource.c
+++ b/freebsd/sys/kern/kern_resource.c
diff --git a/freebsd/kern/kern_subr.c b/freebsd/sys/kern/kern_subr.c
index 9a28a7d9..9a28a7d9 100644
--- a/freebsd/kern/kern_subr.c
+++ b/freebsd/sys/kern/kern_subr.c
diff --git a/freebsd/kern/kern_sysctl.c b/freebsd/sys/kern/kern_sysctl.c
index 72da1f6d..72da1f6d 100644
--- a/freebsd/kern/kern_sysctl.c
+++ b/freebsd/sys/kern/kern_sysctl.c
diff --git a/freebsd/kern/kern_tc.c b/freebsd/sys/kern/kern_tc.c
index 1671145b..1671145b 100644
--- a/freebsd/kern/kern_tc.c
+++ b/freebsd/sys/kern/kern_tc.c
diff --git a/freebsd/kern/kern_time.c b/freebsd/sys/kern/kern_time.c
index 8c760b48..8c760b48 100644
--- a/freebsd/kern/kern_time.c
+++ b/freebsd/sys/kern/kern_time.c
diff --git a/freebsd/kern/kern_timeout.c b/freebsd/sys/kern/kern_timeout.c
index 536ca3f3..536ca3f3 100644
--- a/freebsd/kern/kern_timeout.c
+++ b/freebsd/sys/kern/kern_timeout.c
diff --git a/freebsd/kern/subr_bufring.c b/freebsd/sys/kern/subr_bufring.c
index 8ec8b9d7..8ec8b9d7 100644
--- a/freebsd/kern/subr_bufring.c
+++ b/freebsd/sys/kern/subr_bufring.c
diff --git a/freebsd/kern/subr_bus.c b/freebsd/sys/kern/subr_bus.c
index 9edbe777..9edbe777 100644
--- a/freebsd/kern/subr_bus.c
+++ b/freebsd/sys/kern/subr_bus.c
diff --git a/freebsd/kern/subr_eventhandler.c b/freebsd/sys/kern/subr_eventhandler.c
index af6c6295..af6c6295 100644
--- a/freebsd/kern/subr_eventhandler.c
+++ b/freebsd/sys/kern/subr_eventhandler.c
diff --git a/freebsd/kern/subr_hints.c b/freebsd/sys/kern/subr_hints.c
index dbd120e6..dbd120e6 100644
--- a/freebsd/kern/subr_hints.c
+++ b/freebsd/sys/kern/subr_hints.c
diff --git a/freebsd/kern/subr_kobj.c b/freebsd/sys/kern/subr_kobj.c
index 779fd905..779fd905 100644
--- a/freebsd/kern/subr_kobj.c
+++ b/freebsd/sys/kern/subr_kobj.c
diff --git a/freebsd/kern/subr_module.c b/freebsd/sys/kern/subr_module.c
index 95d4e196..95d4e196 100644
--- a/freebsd/kern/subr_module.c
+++ b/freebsd/sys/kern/subr_module.c
diff --git a/freebsd/kern/subr_rman.c b/freebsd/sys/kern/subr_rman.c
index 8561c0a4..8561c0a4 100644
--- a/freebsd/kern/subr_rman.c
+++ b/freebsd/sys/kern/subr_rman.c
diff --git a/freebsd/kern/subr_sbuf.c b/freebsd/sys/kern/subr_sbuf.c
index 3c7b5a20..3c7b5a20 100644
--- a/freebsd/kern/subr_sbuf.c
+++ b/freebsd/sys/kern/subr_sbuf.c
diff --git a/freebsd/kern/subr_unit.c b/freebsd/sys/kern/subr_unit.c
index 939c03f1..939c03f1 100644
--- a/freebsd/kern/subr_unit.c
+++ b/freebsd/sys/kern/subr_unit.c
diff --git a/freebsd/kern/sys_generic.c b/freebsd/sys/kern/sys_generic.c
index c90d632b..c90d632b 100644
--- a/freebsd/kern/sys_generic.c
+++ b/freebsd/sys/kern/sys_generic.c
diff --git a/freebsd/kern/uipc_accf.c b/freebsd/sys/kern/uipc_accf.c
index fd482e64..fd482e64 100644
--- a/freebsd/kern/uipc_accf.c
+++ b/freebsd/sys/kern/uipc_accf.c
diff --git a/freebsd/kern/uipc_domain.c b/freebsd/sys/kern/uipc_domain.c
index 30eff27c..30eff27c 100644
--- a/freebsd/kern/uipc_domain.c
+++ b/freebsd/sys/kern/uipc_domain.c
diff --git a/freebsd/kern/uipc_mbuf.c b/freebsd/sys/kern/uipc_mbuf.c
index 8e57835c..8e57835c 100644
--- a/freebsd/kern/uipc_mbuf.c
+++ b/freebsd/sys/kern/uipc_mbuf.c
diff --git a/freebsd/kern/uipc_mbuf2.c b/freebsd/sys/kern/uipc_mbuf2.c
index babdf020..babdf020 100644
--- a/freebsd/kern/uipc_mbuf2.c
+++ b/freebsd/sys/kern/uipc_mbuf2.c
diff --git a/freebsd/kern/uipc_sockbuf.c b/freebsd/sys/kern/uipc_sockbuf.c
index 3e331ee0..3e331ee0 100644
--- a/freebsd/kern/uipc_sockbuf.c
+++ b/freebsd/sys/kern/uipc_sockbuf.c
diff --git a/freebsd/kern/uipc_socket.c b/freebsd/sys/kern/uipc_socket.c
index a0ff9f53..a0ff9f53 100644
--- a/freebsd/kern/uipc_socket.c
+++ b/freebsd/sys/kern/uipc_socket.c
diff --git a/freebsd/libkern/arc4random.c b/freebsd/sys/libkern/arc4random.c
index a43218c1..a43218c1 100644
--- a/freebsd/libkern/arc4random.c
+++ b/freebsd/sys/libkern/arc4random.c
diff --git a/freebsd/libkern/fls.c b/freebsd/sys/libkern/fls.c
index e350c535..e350c535 100644
--- a/freebsd/libkern/fls.c
+++ b/freebsd/sys/libkern/fls.c
diff --git a/freebsd/libkern/inet_ntoa.c b/freebsd/sys/libkern/inet_ntoa.c
index 89da6a42..89da6a42 100644
--- a/freebsd/libkern/inet_ntoa.c
+++ b/freebsd/sys/libkern/inet_ntoa.c
diff --git a/freebsd/libkern/random.c b/freebsd/sys/libkern/random.c
index 87cc9591..87cc9591 100644
--- a/freebsd/libkern/random.c
+++ b/freebsd/sys/libkern/random.c
diff --git a/freebsd/sys/lock.h b/freebsd/sys/lock.h
deleted file mode 100644
index f86ec765..00000000
--- a/freebsd/sys/lock.h
+++ /dev/null
@@ -1,319 +0,0 @@
-/*-
- * Copyright (c) 1997 Berkeley Software Design, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Berkeley Software Design Inc's name may not be used to endorse or
- * promote products derived from this software without specific prior
- * written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY BERKELEY SOFTWARE DESIGN 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 BERKELEY SOFTWARE DESIGN 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.
- *
- * from BSDI $Id: mutex.h,v 2.7.2.35 2000/04/27 03:10:26 cp Exp $
- * $FreeBSD$
- */
-
-#ifndef _SYS_LOCK_HH_
-#define _SYS_LOCK_HH_
-
-#include <freebsd/sys/queue.h>
-#include <freebsd/sys/_lock.h>
-
-struct lock_list_entry;
-struct thread;
-
-/*
- * Lock classes. Each lock has a class which describes characteristics
- * common to all types of locks of a given class.
- *
- * Spin locks in general must always protect against preemption, as it is
- * an error to perform any type of context switch while holding a spin lock.
- * Also, for an individual lock to be recursable, its class must allow
- * recursion and the lock itself must explicitly allow recursion.
- *
- * The 'lc_ddb_show' function pointer is used to dump class-specific
- * data for the 'show lock' DDB command. The 'lc_lock' and
- * 'lc_unlock' function pointers are used in sleep(9) and cv_wait(9)
- * to lock and unlock locks while blocking on a sleep queue. The
- * return value of 'lc_unlock' will be passed to 'lc_lock' on resume
- * to allow communication of state between the two routines.
- */
-
-struct lock_class {
- const char *lc_name;
- u_int lc_flags;
- void (*lc_assert)(struct lock_object *lock, int what);
- void (*lc_ddb_show)(struct lock_object *lock);
- void (*lc_lock)(struct lock_object *lock, int how);
- int (*lc_owner)(struct lock_object *lock, struct thread **owner);
- int (*lc_unlock)(struct lock_object *lock);
-};
-
-#define LC_SLEEPLOCK 0x00000001 /* Sleep lock. */
-#define LC_SPINLOCK 0x00000002 /* Spin lock. */
-#define LC_SLEEPABLE 0x00000004 /* Sleeping allowed with this lock. */
-#define LC_RECURSABLE 0x00000008 /* Locks of this type may recurse. */
-#define LC_UPGRADABLE 0x00000010 /* Upgrades and downgrades permitted. */
-
-#define LO_CLASSFLAGS 0x0000ffff /* Class specific flags. */
-#define LO_INITIALIZED 0x00010000 /* Lock has been initialized. */
-#define LO_WITNESS 0x00020000 /* Should witness monitor this lock. */
-#define LO_QUIET 0x00040000 /* Don't log locking operations. */
-#define LO_RECURSABLE 0x00080000 /* Lock may recurse. */
-#define LO_SLEEPABLE 0x00100000 /* Lock may be held while sleeping. */
-#define LO_UPGRADABLE 0x00200000 /* Lock may be upgraded/downgraded. */
-#define LO_DUPOK 0x00400000 /* Don't check for duplicate acquires */
-#define LO_CLASSMASK 0x0f000000 /* Class index bitmask. */
-#define LO_NOPROFILE 0x10000000 /* Don't profile this lock */
-
-/*
- * Lock classes are statically assigned an index into the gobal lock_classes
- * array. Debugging code looks up the lock class for a given lock object
- * by indexing the array.
- */
-#define LO_CLASSSHIFT 24
-#define LO_CLASSINDEX(lock) ((((lock)->lo_flags) & LO_CLASSMASK) >> LO_CLASSSHIFT)
-#define LOCK_CLASS(lock) (lock_classes[LO_CLASSINDEX((lock))])
-#define LOCK_CLASS_MAX (LO_CLASSMASK >> LO_CLASSSHIFT)
-
-/*
- * Option flags passed to lock operations that witness also needs to know
- * about or that are generic across all locks.
- */
-#define LOP_NEWORDER 0x00000001 /* Define a new lock order. */
-#define LOP_QUIET 0x00000002 /* Don't log locking operations. */
-#define LOP_TRYLOCK 0x00000004 /* Don't check lock order. */
-#define LOP_EXCLUSIVE 0x00000008 /* Exclusive lock. */
-#define LOP_DUPOK 0x00000010 /* Don't check for duplicate acquires */
-
-/* Flags passed to witness_assert. */
-#define LA_MASKASSERT 0x000000ff /* Mask for witness defined asserts. */
-#define LA_UNLOCKED 0x00000000 /* Lock is unlocked. */
-#define LA_LOCKED 0x00000001 /* Lock is at least share locked. */
-#define LA_SLOCKED 0x00000002 /* Lock is exactly share locked. */
-#define LA_XLOCKED 0x00000004 /* Lock is exclusively locked. */
-#define LA_RECURSED 0x00000008 /* Lock is recursed. */
-#define LA_NOTRECURSED 0x00000010 /* Lock is not recursed. */
-
-#ifdef _KERNEL
-/*
- * If any of WITNESS, INVARIANTS, or KTR_LOCK KTR tracing has been enabled,
- * then turn on LOCK_DEBUG. When this option is on, extra debugging
- * facilities such as tracking the file and line number of lock operations
- * are enabled. Also, mutex locking operations are not inlined to avoid
- * bloat from all the extra debugging code. We also have to turn on all the
- * calling conventions for this debugging code in modules so that modules can
- * work with both debug and non-debug kernels.
- */
-#if defined(KLD_MODULE) || defined(WITNESS) || defined(INVARIANTS) || defined(INVARIANT_SUPPORT) || defined(KTR) || defined(LOCK_PROFILING)
-#define LOCK_DEBUG 1
-#else
-#define LOCK_DEBUG 0
-#endif
-
-/*
- * In the LOCK_DEBUG case, use the filename and line numbers for debugging
- * operations. Otherwise, use default values to avoid the unneeded bloat.
- */
-#if LOCK_DEBUG > 0
-#define LOCK_FILE __FILE__
-#define LOCK_LINE __LINE__
-#else
-#define LOCK_FILE NULL
-#define LOCK_LINE 0
-#endif
-
-/*
- * Macros for KTR_LOCK tracing.
- *
- * opname - name of this operation (LOCK/UNLOCK/SLOCK, etc.)
- * lo - struct lock_object * for this lock
- * flags - flags passed to the lock operation
- * recurse - this locks recursion level (or 0 if class is not recursable)
- * result - result of a try lock operation
- * file - file name
- * line - line number
- */
-#define LOCK_LOG_TEST(lo, flags) \
- (((flags) & LOP_QUIET) == 0 && ((lo)->lo_flags & LO_QUIET) == 0)
-
-#define LOCK_LOG_LOCK(opname, lo, flags, recurse, file, line) do { \
- if (LOCK_LOG_TEST((lo), (flags))) \
- CTR6(KTR_LOCK, opname " (%s) %s %p r = %d at %s:%d", \
- LOCK_CLASS(lo)->lc_name, (lo)->lo_name, \
- (lo), (u_int)(recurse), (file), (line)); \
-} while (0)
-
-#define LOCK_LOG_TRY(opname, lo, flags, result, file, line) do { \
- if (LOCK_LOG_TEST((lo), (flags))) \
- CTR6(KTR_LOCK, "TRY_" opname " (%s) %s %p result=%d at %s:%d",\
- LOCK_CLASS(lo)->lc_name, (lo)->lo_name, \
- (lo), (u_int)(result), (file), (line)); \
-} while (0)
-
-#define LOCK_LOG_INIT(lo, flags) do { \
- if (LOCK_LOG_TEST((lo), (flags))) \
- CTR4(KTR_LOCK, "%s: %p (%s) %s", __func__, (lo), \
- LOCK_CLASS(lo)->lc_name, (lo)->lo_name); \
-} while (0)
-
-#define LOCK_LOG_DESTROY(lo, flags) LOCK_LOG_INIT(lo, flags)
-
-#define lock_initalized(lo) ((lo)->lo_flags & LO_INITIALIZED)
-
-/*
- * Helpful macros for quickly coming up with assertions with informative
- * panic messages.
- */
-#define MPASS(ex) MPASS4(ex, #ex, __FILE__, __LINE__)
-#define MPASS2(ex, what) MPASS4(ex, what, __FILE__, __LINE__)
-#define MPASS3(ex, file, line) MPASS4(ex, #ex, file, line)
-#define MPASS4(ex, what, file, line) \
- KASSERT((ex), ("Assertion %s failed at %s:%d", what, file, line))
-
-extern struct lock_class lock_class_mtx_sleep;
-extern struct lock_class lock_class_mtx_spin;
-extern struct lock_class lock_class_sx;
-extern struct lock_class lock_class_rw;
-extern struct lock_class lock_class_rm;
-extern struct lock_class lock_class_lockmgr;
-
-extern struct lock_class *lock_classes[];
-
-void lock_init(struct lock_object *, struct lock_class *,
- const char *, const char *, int);
-void lock_destroy(struct lock_object *);
-void spinlock_enter(void);
-void spinlock_exit(void);
-void witness_init(struct lock_object *, const char *);
-void witness_destroy(struct lock_object *);
-int witness_defineorder(struct lock_object *, struct lock_object *);
-void witness_checkorder(struct lock_object *, int, const char *, int,
- struct lock_object *);
-void witness_lock(struct lock_object *, int, const char *, int);
-void witness_upgrade(struct lock_object *, int, const char *, int);
-void witness_downgrade(struct lock_object *, int, const char *, int);
-void witness_unlock(struct lock_object *, int, const char *, int);
-void witness_save(struct lock_object *, const char **, int *);
-void witness_restore(struct lock_object *, const char *, int);
-int witness_list_locks(struct lock_list_entry **,
- int (*)(const char *, ...));
-int witness_warn(int, struct lock_object *, const char *, ...);
-void witness_assert(struct lock_object *, int, const char *, int);
-void witness_display_spinlock(struct lock_object *, struct thread *,
- int (*)(const char *, ...));
-int witness_line(struct lock_object *);
-void witness_norelease(struct lock_object *);
-void witness_releaseok(struct lock_object *);
-const char *witness_file(struct lock_object *);
-void witness_thread_exit(struct thread *);
-
-#ifdef WITNESS
-
-/* Flags for witness_warn(). */
-#define WARN_GIANTOK 0x01 /* Giant is exempt from this check. */
-#define WARN_PANIC 0x02 /* Panic if check fails. */
-#define WARN_SLEEPOK 0x04 /* Sleepable locks are exempt from check. */
-
-#define WITNESS_INIT(lock, type) \
- witness_init((lock), (type))
-
-#define WITNESS_DESTROY(lock) \
- witness_destroy(lock)
-
-#define WITNESS_CHECKORDER(lock, flags, file, line, interlock) \
- witness_checkorder((lock), (flags), (file), (line), (interlock))
-
-#define WITNESS_DEFINEORDER(lock1, lock2) \
- witness_defineorder((struct lock_object *)(lock1), \
- (struct lock_object *)(lock2))
-
-#define WITNESS_LOCK(lock, flags, file, line) \
- witness_lock((lock), (flags), (file), (line))
-
-#define WITNESS_UPGRADE(lock, flags, file, line) \
- witness_upgrade((lock), (flags), (file), (line))
-
-#define WITNESS_DOWNGRADE(lock, flags, file, line) \
- witness_downgrade((lock), (flags), (file), (line))
-
-#define WITNESS_UNLOCK(lock, flags, file, line) \
- witness_unlock((lock), (flags), (file), (line))
-
-#define WITNESS_CHECK(flags, lock, fmt, ...) \
- witness_warn((flags), (lock), (fmt), ## __VA_ARGS__)
-
-#define WITNESS_WARN(flags, lock, fmt, ...) \
- witness_warn((flags), (lock), (fmt), ## __VA_ARGS__)
-
-#define WITNESS_SAVE_DECL(n) \
- const char * __CONCAT(n, __wf); \
- int __CONCAT(n, __wl)
-
-#define WITNESS_SAVE(lock, n) \
- witness_save((lock), &__CONCAT(n, __wf), &__CONCAT(n, __wl))
-
-#define WITNESS_RESTORE(lock, n) \
- witness_restore((lock), __CONCAT(n, __wf), __CONCAT(n, __wl))
-
-#define WITNESS_NORELEASE(lock) \
- witness_norelease(&(lock)->lock_object)
-
-#define WITNESS_RELEASEOK(lock) \
- witness_releaseok(&(lock)->lock_object)
-
-#define WITNESS_FILE(lock) \
- witness_file(lock)
-
-#define WITNESS_LINE(lock) \
- witness_line(lock)
-
-#else /* WITNESS */
-#define WITNESS_INIT(lock, type) (void)0
-#define WITNESS_DESTROY(lock) (void)0
-#define WITNESS_DEFINEORDER(lock1, lock2) 0
-#define WITNESS_CHECKORDER(lock, flags, file, line, interlock) (void)0
-#define WITNESS_LOCK(lock, flags, file, line) (void)0
-#define WITNESS_UPGRADE(lock, flags, file, line) (void)0
-#define WITNESS_DOWNGRADE(lock, flags, file, line) (void)0
-#define WITNESS_UNLOCK(lock, flags, file, line) (void)0
-#define WITNESS_CHECK(flags, lock, fmt, ...) 0
-#define WITNESS_WARN(flags, lock, fmt, ...) (void)0
-#define WITNESS_SAVE_DECL(n) (void)0
-#define WITNESS_SAVE(lock, n) (void)0
-#define WITNESS_RESTORE(lock, n) (void)0
-#define WITNESS_NORELEASE(lock) (void)0
-#define WITNESS_RELEASEOK(lock) (void)0
-#define WITNESS_FILE(lock) ("?")
-#define WITNESS_LINE(lock) (0)
-#endif /* WITNESS */
-
-/*
- * Helper macros to allow developers to add explicit lock order checks
- * wherever they please without having to actually grab a lock to do so.
- */
-#define witness_check(l) \
- WITNESS_CHECKORDER(&(l)->lock_object, LOP_EXCLUSIVE, LOCK_FILE, \
- LOCK_LINE, NULL)
-
-#define witness_check_shared(l) \
- WITNESS_CHECKORDER(&(l)->lock_object, 0, LOCK_FILE, LOCK_LINE, NULL)
-
-#endif /* _KERNEL */
-#endif /* _SYS_LOCK_HH_ */
diff --git a/freebsd/mips/include/freebsd/machine/cpufunc.h b/freebsd/sys/mips/include/machine/cpufunc.h
index f693dcba..f693dcba 100644
--- a/freebsd/mips/include/freebsd/machine/cpufunc.h
+++ b/freebsd/sys/mips/include/machine/cpufunc.h
diff --git a/freebsd/mips/include/freebsd/machine/cpuregs.h b/freebsd/sys/mips/include/machine/cpuregs.h
index db6450ff..db6450ff 100644
--- a/freebsd/mips/include/freebsd/machine/cpuregs.h
+++ b/freebsd/sys/mips/include/machine/cpuregs.h
diff --git a/freebsd/mips/mips/in_cksum.c b/freebsd/sys/mips/mips/in_cksum.c
index a519c729..a519c729 100644
--- a/freebsd/mips/mips/in_cksum.c
+++ b/freebsd/sys/mips/mips/in_cksum.c
diff --git a/freebsd/sys/namei.h b/freebsd/sys/namei.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/namei.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/net/bpf.c b/freebsd/sys/net/bpf.c
index 684c7343..684c7343 100644
--- a/freebsd/net/bpf.c
+++ b/freebsd/sys/net/bpf.c
diff --git a/freebsd/net/bpf.h b/freebsd/sys/net/bpf.h
index d9dd4289..d9dd4289 100644
--- a/freebsd/net/bpf.h
+++ b/freebsd/sys/net/bpf.h
diff --git a/freebsd/net/bpf_buffer.c b/freebsd/sys/net/bpf_buffer.c
index 623b4f8a..623b4f8a 100644
--- a/freebsd/net/bpf_buffer.c
+++ b/freebsd/sys/net/bpf_buffer.c
diff --git a/freebsd/net/bpf_buffer.h b/freebsd/sys/net/bpf_buffer.h
index 545ddb22..545ddb22 100644
--- a/freebsd/net/bpf_buffer.h
+++ b/freebsd/sys/net/bpf_buffer.h
diff --git a/freebsd/net/bpf_filter.c b/freebsd/sys/net/bpf_filter.c
index 3452cc4a..3452cc4a 100644
--- a/freebsd/net/bpf_filter.c
+++ b/freebsd/sys/net/bpf_filter.c
diff --git a/freebsd/net/bpf_jitter.c b/freebsd/sys/net/bpf_jitter.c
index bb373725..bb373725 100644
--- a/freebsd/net/bpf_jitter.c
+++ b/freebsd/sys/net/bpf_jitter.c
diff --git a/freebsd/net/bpf_jitter.h b/freebsd/sys/net/bpf_jitter.h
index c0dd7e04..c0dd7e04 100644
--- a/freebsd/net/bpf_jitter.h
+++ b/freebsd/sys/net/bpf_jitter.h
diff --git a/freebsd/net/bpf_zerocopy.h b/freebsd/sys/net/bpf_zerocopy.h
index 455bd41c..455bd41c 100644
--- a/freebsd/net/bpf_zerocopy.h
+++ b/freebsd/sys/net/bpf_zerocopy.h
diff --git a/freebsd/net/bpfdesc.h b/freebsd/sys/net/bpfdesc.h
index d28ecca2..d28ecca2 100644
--- a/freebsd/net/bpfdesc.h
+++ b/freebsd/sys/net/bpfdesc.h
diff --git a/freebsd/net/bridgestp.c b/freebsd/sys/net/bridgestp.c
index 2191be26..2191be26 100644
--- a/freebsd/net/bridgestp.c
+++ b/freebsd/sys/net/bridgestp.c
diff --git a/freebsd/net/bridgestp.h b/freebsd/sys/net/bridgestp.h
index 91328900..91328900 100644
--- a/freebsd/net/bridgestp.h
+++ b/freebsd/sys/net/bridgestp.h
diff --git a/freebsd/sys/net/ethernet.h b/freebsd/sys/net/ethernet.h
new file mode 100644
index 00000000..17d022b2
--- /dev/null
+++ b/freebsd/sys/net/ethernet.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/net/ethernet.h>
diff --git a/freebsd/net/fddi.h b/freebsd/sys/net/fddi.h
index 03deabff..03deabff 100644
--- a/freebsd/net/fddi.h
+++ b/freebsd/sys/net/fddi.h
diff --git a/freebsd/net/firewire.h b/freebsd/sys/net/firewire.h
index 5411dbf8..5411dbf8 100644
--- a/freebsd/net/firewire.h
+++ b/freebsd/sys/net/firewire.h
diff --git a/freebsd/net/flowtable.h b/freebsd/sys/net/flowtable.h
index c4a09659..c4a09659 100644
--- a/freebsd/net/flowtable.h
+++ b/freebsd/sys/net/flowtable.h
diff --git a/freebsd/net/ieee8023ad_lacp.c b/freebsd/sys/net/ieee8023ad_lacp.c
index 75c0d9ea..75c0d9ea 100644
--- a/freebsd/net/ieee8023ad_lacp.c
+++ b/freebsd/sys/net/ieee8023ad_lacp.c
diff --git a/freebsd/net/ieee8023ad_lacp.h b/freebsd/sys/net/ieee8023ad_lacp.h
index 9cebc591..9cebc591 100644
--- a/freebsd/net/ieee8023ad_lacp.h
+++ b/freebsd/sys/net/ieee8023ad_lacp.h
diff --git a/freebsd/net/if.c b/freebsd/sys/net/if.c
index 33d9ed9d..33d9ed9d 100644
--- a/freebsd/net/if.c
+++ b/freebsd/sys/net/if.c
diff --git a/freebsd/sys/net/if.h b/freebsd/sys/net/if.h
new file mode 100644
index 00000000..6fbbb34a
--- /dev/null
+++ b/freebsd/sys/net/if.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/net/if.h>
diff --git a/freebsd/net/if_arc.h b/freebsd/sys/net/if_arc.h
index 6be5d4e1..6be5d4e1 100644
--- a/freebsd/net/if_arc.h
+++ b/freebsd/sys/net/if_arc.h
diff --git a/freebsd/net/if_arcsubr.c b/freebsd/sys/net/if_arcsubr.c
index 8cd53a6d..8cd53a6d 100644
--- a/freebsd/net/if_arcsubr.c
+++ b/freebsd/sys/net/if_arcsubr.c
diff --git a/freebsd/sys/net/if_arp.h b/freebsd/sys/net/if_arp.h
new file mode 100644
index 00000000..2ad9fffb
--- /dev/null
+++ b/freebsd/sys/net/if_arp.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/net/if_arp.h>
diff --git a/freebsd/net/if_atm.h b/freebsd/sys/net/if_atm.h
index e8f69da0..e8f69da0 100644
--- a/freebsd/net/if_atm.h
+++ b/freebsd/sys/net/if_atm.h
diff --git a/freebsd/net/if_atmsubr.c b/freebsd/sys/net/if_atmsubr.c
index 7daa347f..7daa347f 100644
--- a/freebsd/net/if_atmsubr.c
+++ b/freebsd/sys/net/if_atmsubr.c
diff --git a/freebsd/net/if_bridge.c b/freebsd/sys/net/if_bridge.c
index de7aea04..de7aea04 100644
--- a/freebsd/net/if_bridge.c
+++ b/freebsd/sys/net/if_bridge.c
diff --git a/freebsd/net/if_bridgevar.h b/freebsd/sys/net/if_bridgevar.h
index 642cc98d..642cc98d 100644
--- a/freebsd/net/if_bridgevar.h
+++ b/freebsd/sys/net/if_bridgevar.h
diff --git a/freebsd/net/if_clone.c b/freebsd/sys/net/if_clone.c
index aca1276f..aca1276f 100644
--- a/freebsd/net/if_clone.c
+++ b/freebsd/sys/net/if_clone.c
diff --git a/freebsd/net/if_clone.h b/freebsd/sys/net/if_clone.h
index 67de320b..67de320b 100644
--- a/freebsd/net/if_clone.h
+++ b/freebsd/sys/net/if_clone.h
diff --git a/freebsd/net/if_dead.c b/freebsd/sys/net/if_dead.c
index dcceaf25..dcceaf25 100644
--- a/freebsd/net/if_dead.c
+++ b/freebsd/sys/net/if_dead.c
diff --git a/freebsd/net/if_disc.c b/freebsd/sys/net/if_disc.c
index 09918bb4..09918bb4 100644
--- a/freebsd/net/if_disc.c
+++ b/freebsd/sys/net/if_disc.c
diff --git a/freebsd/sys/net/if_dl.h b/freebsd/sys/net/if_dl.h
new file mode 100644
index 00000000..ad29f1de
--- /dev/null
+++ b/freebsd/sys/net/if_dl.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/net/if_dl.h>
diff --git a/freebsd/net/if_edsc.c b/freebsd/sys/net/if_edsc.c
index 89618ce5..89618ce5 100644
--- a/freebsd/net/if_edsc.c
+++ b/freebsd/sys/net/if_edsc.c
diff --git a/freebsd/net/if_ef.c b/freebsd/sys/net/if_ef.c
index 8114806c..8114806c 100644
--- a/freebsd/net/if_ef.c
+++ b/freebsd/sys/net/if_ef.c
diff --git a/freebsd/net/if_enc.c b/freebsd/sys/net/if_enc.c
index 6bbb6ceb..6bbb6ceb 100644
--- a/freebsd/net/if_enc.c
+++ b/freebsd/sys/net/if_enc.c
diff --git a/freebsd/net/if_enc.h b/freebsd/sys/net/if_enc.h
index 59a55fcf..59a55fcf 100644
--- a/freebsd/net/if_enc.h
+++ b/freebsd/sys/net/if_enc.h
diff --git a/freebsd/net/if_epair.c b/freebsd/sys/net/if_epair.c
index 65baeab8..65baeab8 100644
--- a/freebsd/net/if_epair.c
+++ b/freebsd/sys/net/if_epair.c
diff --git a/freebsd/net/if_ethersubr.c b/freebsd/sys/net/if_ethersubr.c
index d87ebbd0..d87ebbd0 100644
--- a/freebsd/net/if_ethersubr.c
+++ b/freebsd/sys/net/if_ethersubr.c
diff --git a/freebsd/net/if_faith.c b/freebsd/sys/net/if_faith.c
index c8989922..c8989922 100644
--- a/freebsd/net/if_faith.c
+++ b/freebsd/sys/net/if_faith.c
diff --git a/freebsd/net/if_fddisubr.c b/freebsd/sys/net/if_fddisubr.c
index fc9f27e1..fc9f27e1 100644
--- a/freebsd/net/if_fddisubr.c
+++ b/freebsd/sys/net/if_fddisubr.c
diff --git a/freebsd/net/if_fwsubr.c b/freebsd/sys/net/if_fwsubr.c
index d084bea4..d084bea4 100644
--- a/freebsd/net/if_fwsubr.c
+++ b/freebsd/sys/net/if_fwsubr.c
diff --git a/freebsd/net/if_gif.c b/freebsd/sys/net/if_gif.c
index be67500a..be67500a 100644
--- a/freebsd/net/if_gif.c
+++ b/freebsd/sys/net/if_gif.c
diff --git a/freebsd/net/if_gif.h b/freebsd/sys/net/if_gif.h
index 14f06fd6..14f06fd6 100644
--- a/freebsd/net/if_gif.h
+++ b/freebsd/sys/net/if_gif.h
diff --git a/freebsd/net/if_gre.c b/freebsd/sys/net/if_gre.c
index 4a42029b..4a42029b 100644
--- a/freebsd/net/if_gre.c
+++ b/freebsd/sys/net/if_gre.c
diff --git a/freebsd/net/if_gre.h b/freebsd/sys/net/if_gre.h
index ff9c63cf..ff9c63cf 100644
--- a/freebsd/net/if_gre.h
+++ b/freebsd/sys/net/if_gre.h
diff --git a/freebsd/net/if_iso88025subr.c b/freebsd/sys/net/if_iso88025subr.c
index 87d3eb87..87d3eb87 100644
--- a/freebsd/net/if_iso88025subr.c
+++ b/freebsd/sys/net/if_iso88025subr.c
diff --git a/freebsd/net/if_lagg.c b/freebsd/sys/net/if_lagg.c
index 47c72ca2..47c72ca2 100644
--- a/freebsd/net/if_lagg.c
+++ b/freebsd/sys/net/if_lagg.c
diff --git a/freebsd/net/if_lagg.h b/freebsd/sys/net/if_lagg.h
index 0034c617..0034c617 100644
--- a/freebsd/net/if_lagg.h
+++ b/freebsd/sys/net/if_lagg.h
diff --git a/freebsd/net/if_llatbl.c b/freebsd/sys/net/if_llatbl.c
index b9f78a71..b9f78a71 100644
--- a/freebsd/net/if_llatbl.c
+++ b/freebsd/sys/net/if_llatbl.c
diff --git a/freebsd/net/if_llatbl.h b/freebsd/sys/net/if_llatbl.h
index 9e12362b..9e12362b 100644
--- a/freebsd/net/if_llatbl.h
+++ b/freebsd/sys/net/if_llatbl.h
diff --git a/freebsd/net/if_llc.h b/freebsd/sys/net/if_llc.h
index b72f21bc..b72f21bc 100644
--- a/freebsd/net/if_llc.h
+++ b/freebsd/sys/net/if_llc.h
diff --git a/freebsd/net/if_loop.c b/freebsd/sys/net/if_loop.c
index d80bfdad..d80bfdad 100644
--- a/freebsd/net/if_loop.c
+++ b/freebsd/sys/net/if_loop.c
diff --git a/freebsd/net/if_media.c b/freebsd/sys/net/if_media.c
index 3da5090a..3da5090a 100644
--- a/freebsd/net/if_media.c
+++ b/freebsd/sys/net/if_media.c
diff --git a/freebsd/net/if_media.h b/freebsd/sys/net/if_media.h
index 26a3c417..26a3c417 100644
--- a/freebsd/net/if_media.h
+++ b/freebsd/sys/net/if_media.h
diff --git a/freebsd/net/if_mib.c b/freebsd/sys/net/if_mib.c
index ddc75df3..ddc75df3 100644
--- a/freebsd/net/if_mib.c
+++ b/freebsd/sys/net/if_mib.c
diff --git a/freebsd/net/if_mib.h b/freebsd/sys/net/if_mib.h
index e2b80c87..e2b80c87 100644
--- a/freebsd/net/if_mib.h
+++ b/freebsd/sys/net/if_mib.h
diff --git a/freebsd/net/if_sppp.h b/freebsd/sys/net/if_sppp.h
index ed406b55..ed406b55 100644
--- a/freebsd/net/if_sppp.h
+++ b/freebsd/sys/net/if_sppp.h
diff --git a/freebsd/net/if_spppfr.c b/freebsd/sys/net/if_spppfr.c
index fa912363..fa912363 100644
--- a/freebsd/net/if_spppfr.c
+++ b/freebsd/sys/net/if_spppfr.c
diff --git a/freebsd/net/if_spppsubr.c b/freebsd/sys/net/if_spppsubr.c
index 235ef7c0..235ef7c0 100644
--- a/freebsd/net/if_spppsubr.c
+++ b/freebsd/sys/net/if_spppsubr.c
diff --git a/freebsd/net/if_stf.c b/freebsd/sys/net/if_stf.c
index 1cf5c408..1cf5c408 100644
--- a/freebsd/net/if_stf.c
+++ b/freebsd/sys/net/if_stf.c
diff --git a/freebsd/net/if_stf.h b/freebsd/sys/net/if_stf.h
index 64fd30ee..64fd30ee 100644
--- a/freebsd/net/if_stf.h
+++ b/freebsd/sys/net/if_stf.h
diff --git a/freebsd/net/if_tap.c b/freebsd/sys/net/if_tap.c
index 206302bb..206302bb 100644
--- a/freebsd/net/if_tap.c
+++ b/freebsd/sys/net/if_tap.c
diff --git a/freebsd/net/if_tap.h b/freebsd/sys/net/if_tap.h
index e611884b..e611884b 100644
--- a/freebsd/net/if_tap.h
+++ b/freebsd/sys/net/if_tap.h
diff --git a/freebsd/net/if_tapvar.h b/freebsd/sys/net/if_tapvar.h
index 4a26fd87..4a26fd87 100644
--- a/freebsd/net/if_tapvar.h
+++ b/freebsd/sys/net/if_tapvar.h
diff --git a/freebsd/net/if_tun.c b/freebsd/sys/net/if_tun.c
index 7f90fa51..7f90fa51 100644
--- a/freebsd/net/if_tun.c
+++ b/freebsd/sys/net/if_tun.c
diff --git a/freebsd/net/if_tun.h b/freebsd/sys/net/if_tun.h
index 29718cda..29718cda 100644
--- a/freebsd/net/if_tun.h
+++ b/freebsd/sys/net/if_tun.h
diff --git a/freebsd/sys/net/if_types.h b/freebsd/sys/net/if_types.h
new file mode 100644
index 00000000..1d4f2b2a
--- /dev/null
+++ b/freebsd/sys/net/if_types.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/net/if_types.h>
diff --git a/freebsd/net/if_var.h b/freebsd/sys/net/if_var.h
index 913d62a9..913d62a9 100644
--- a/freebsd/net/if_var.h
+++ b/freebsd/sys/net/if_var.h
diff --git a/freebsd/net/if_vlan.c b/freebsd/sys/net/if_vlan.c
index 5ae5efd4..5ae5efd4 100644
--- a/freebsd/net/if_vlan.c
+++ b/freebsd/sys/net/if_vlan.c
diff --git a/freebsd/net/if_vlan_var.h b/freebsd/sys/net/if_vlan_var.h
index 045e2fa1..045e2fa1 100644
--- a/freebsd/net/if_vlan_var.h
+++ b/freebsd/sys/net/if_vlan_var.h
diff --git a/freebsd/net/iso88025.h b/freebsd/sys/net/iso88025.h
index 26e3ada6..26e3ada6 100644
--- a/freebsd/net/iso88025.h
+++ b/freebsd/sys/net/iso88025.h
diff --git a/freebsd/net/netisr.c b/freebsd/sys/net/netisr.c
index 4d34953a..4d34953a 100644
--- a/freebsd/net/netisr.c
+++ b/freebsd/sys/net/netisr.c
diff --git a/freebsd/net/netisr.h b/freebsd/sys/net/netisr.h
index b755332a..b755332a 100644
--- a/freebsd/net/netisr.h
+++ b/freebsd/sys/net/netisr.h
diff --git a/freebsd/net/pfil.c b/freebsd/sys/net/pfil.c
index 3a382bc5..3a382bc5 100644
--- a/freebsd/net/pfil.c
+++ b/freebsd/sys/net/pfil.c
diff --git a/freebsd/net/pfil.h b/freebsd/sys/net/pfil.h
index 78ab0518..78ab0518 100644
--- a/freebsd/net/pfil.h
+++ b/freebsd/sys/net/pfil.h
diff --git a/freebsd/net/pfkeyv2.h b/freebsd/sys/net/pfkeyv2.h
index f8e088e1..f8e088e1 100644
--- a/freebsd/net/pfkeyv2.h
+++ b/freebsd/sys/net/pfkeyv2.h
diff --git a/freebsd/net/ppp_defs.h b/freebsd/sys/net/ppp_defs.h
index e0690e94..e0690e94 100644
--- a/freebsd/net/ppp_defs.h
+++ b/freebsd/sys/net/ppp_defs.h
diff --git a/freebsd/net/radix.c b/freebsd/sys/net/radix.c
index c1881acb..c1881acb 100644
--- a/freebsd/net/radix.c
+++ b/freebsd/sys/net/radix.c
diff --git a/freebsd/net/radix.h b/freebsd/sys/net/radix.h
index ccd5f491..ccd5f491 100644
--- a/freebsd/net/radix.h
+++ b/freebsd/sys/net/radix.h
diff --git a/freebsd/net/radix_mpath.c b/freebsd/sys/net/radix_mpath.c
index 3c348249..3c348249 100644
--- a/freebsd/net/radix_mpath.c
+++ b/freebsd/sys/net/radix_mpath.c
diff --git a/freebsd/net/radix_mpath.h b/freebsd/sys/net/radix_mpath.h
index b6d8c16a..b6d8c16a 100644
--- a/freebsd/net/radix_mpath.h
+++ b/freebsd/sys/net/radix_mpath.h
diff --git a/freebsd/net/raw_cb.c b/freebsd/sys/net/raw_cb.c
index 2fd73dac..2fd73dac 100644
--- a/freebsd/net/raw_cb.c
+++ b/freebsd/sys/net/raw_cb.c
diff --git a/freebsd/net/raw_cb.h b/freebsd/sys/net/raw_cb.h
index 278b4235..278b4235 100644
--- a/freebsd/net/raw_cb.h
+++ b/freebsd/sys/net/raw_cb.h
diff --git a/freebsd/net/raw_usrreq.c b/freebsd/sys/net/raw_usrreq.c
index bdf3369e..bdf3369e 100644
--- a/freebsd/net/raw_usrreq.c
+++ b/freebsd/sys/net/raw_usrreq.c
diff --git a/freebsd/net/route.c b/freebsd/sys/net/route.c
index ee43c843..ee43c843 100644
--- a/freebsd/net/route.c
+++ b/freebsd/sys/net/route.c
diff --git a/freebsd/sys/net/route.h b/freebsd/sys/net/route.h
new file mode 100644
index 00000000..4375020f
--- /dev/null
+++ b/freebsd/sys/net/route.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/net/route.h>
diff --git a/freebsd/net/rtsock.c b/freebsd/sys/net/rtsock.c
index 287dd74d..287dd74d 100644
--- a/freebsd/net/rtsock.c
+++ b/freebsd/sys/net/rtsock.c
diff --git a/freebsd/net/slcompress.c b/freebsd/sys/net/slcompress.c
index be337c1f..be337c1f 100644
--- a/freebsd/net/slcompress.c
+++ b/freebsd/sys/net/slcompress.c
diff --git a/freebsd/net/slcompress.h b/freebsd/sys/net/slcompress.h
index 08c9042e..08c9042e 100644
--- a/freebsd/net/slcompress.h
+++ b/freebsd/sys/net/slcompress.h
diff --git a/freebsd/net/vnet.h b/freebsd/sys/net/vnet.h
index 7f6326fe..7f6326fe 100644
--- a/freebsd/net/vnet.h
+++ b/freebsd/sys/net/vnet.h
diff --git a/freebsd/net/zlib.c b/freebsd/sys/net/zlib.c
index a7a54740..a7a54740 100644
--- a/freebsd/net/zlib.c
+++ b/freebsd/sys/net/zlib.c
diff --git a/freebsd/net/zlib.h b/freebsd/sys/net/zlib.h
index 3da670fd..3da670fd 100644
--- a/freebsd/net/zlib.h
+++ b/freebsd/sys/net/zlib.h
diff --git a/freebsd/net80211/_ieee80211.h b/freebsd/sys/net80211/_ieee80211.h
index 764e5cf1..764e5cf1 100644
--- a/freebsd/net80211/_ieee80211.h
+++ b/freebsd/sys/net80211/_ieee80211.h
diff --git a/freebsd/net80211/ieee80211.c b/freebsd/sys/net80211/ieee80211.c
index 8770d452..8770d452 100644
--- a/freebsd/net80211/ieee80211.c
+++ b/freebsd/sys/net80211/ieee80211.c
diff --git a/freebsd/net80211/ieee80211.h b/freebsd/sys/net80211/ieee80211.h
index 6019e0ed..6019e0ed 100644
--- a/freebsd/net80211/ieee80211.h
+++ b/freebsd/sys/net80211/ieee80211.h
diff --git a/freebsd/net80211/ieee80211_acl.c b/freebsd/sys/net80211/ieee80211_acl.c
index 955989a6..955989a6 100644
--- a/freebsd/net80211/ieee80211_acl.c
+++ b/freebsd/sys/net80211/ieee80211_acl.c
diff --git a/freebsd/net80211/ieee80211_action.c b/freebsd/sys/net80211/ieee80211_action.c
index 4bd5c700..4bd5c700 100644
--- a/freebsd/net80211/ieee80211_action.c
+++ b/freebsd/sys/net80211/ieee80211_action.c
diff --git a/freebsd/net80211/ieee80211_action.h b/freebsd/sys/net80211/ieee80211_action.h
index 943d145b..943d145b 100644
--- a/freebsd/net80211/ieee80211_action.h
+++ b/freebsd/sys/net80211/ieee80211_action.h
diff --git a/freebsd/net80211/ieee80211_adhoc.c b/freebsd/sys/net80211/ieee80211_adhoc.c
index 44d91041..44d91041 100644
--- a/freebsd/net80211/ieee80211_adhoc.c
+++ b/freebsd/sys/net80211/ieee80211_adhoc.c
diff --git a/freebsd/net80211/ieee80211_adhoc.h b/freebsd/sys/net80211/ieee80211_adhoc.h
index 2fad984e..2fad984e 100644
--- a/freebsd/net80211/ieee80211_adhoc.h
+++ b/freebsd/sys/net80211/ieee80211_adhoc.h
diff --git a/freebsd/net80211/ieee80211_ageq.c b/freebsd/sys/net80211/ieee80211_ageq.c
index 2e838e35..2e838e35 100644
--- a/freebsd/net80211/ieee80211_ageq.c
+++ b/freebsd/sys/net80211/ieee80211_ageq.c
diff --git a/freebsd/net80211/ieee80211_ageq.h b/freebsd/sys/net80211/ieee80211_ageq.h
index 8aecae05..8aecae05 100644
--- a/freebsd/net80211/ieee80211_ageq.h
+++ b/freebsd/sys/net80211/ieee80211_ageq.h
diff --git a/freebsd/net80211/ieee80211_amrr.c b/freebsd/sys/net80211/ieee80211_amrr.c
index 33f6c5f3..33f6c5f3 100644
--- a/freebsd/net80211/ieee80211_amrr.c
+++ b/freebsd/sys/net80211/ieee80211_amrr.c
diff --git a/freebsd/net80211/ieee80211_amrr.h b/freebsd/sys/net80211/ieee80211_amrr.h
index b425e268..b425e268 100644
--- a/freebsd/net80211/ieee80211_amrr.h
+++ b/freebsd/sys/net80211/ieee80211_amrr.h
diff --git a/freebsd/net80211/ieee80211_crypto.c b/freebsd/sys/net80211/ieee80211_crypto.c
index c3a263c8..c3a263c8 100644
--- a/freebsd/net80211/ieee80211_crypto.c
+++ b/freebsd/sys/net80211/ieee80211_crypto.c
diff --git a/freebsd/net80211/ieee80211_crypto.h b/freebsd/sys/net80211/ieee80211_crypto.h
index b9e8e25b..b9e8e25b 100644
--- a/freebsd/net80211/ieee80211_crypto.h
+++ b/freebsd/sys/net80211/ieee80211_crypto.h
diff --git a/freebsd/net80211/ieee80211_crypto_ccmp.c b/freebsd/sys/net80211/ieee80211_crypto_ccmp.c
index 82443508..82443508 100644
--- a/freebsd/net80211/ieee80211_crypto_ccmp.c
+++ b/freebsd/sys/net80211/ieee80211_crypto_ccmp.c
diff --git a/freebsd/net80211/ieee80211_crypto_none.c b/freebsd/sys/net80211/ieee80211_crypto_none.c
index f9112a9f..f9112a9f 100644
--- a/freebsd/net80211/ieee80211_crypto_none.c
+++ b/freebsd/sys/net80211/ieee80211_crypto_none.c
diff --git a/freebsd/net80211/ieee80211_crypto_tkip.c b/freebsd/sys/net80211/ieee80211_crypto_tkip.c
index 6b0656e2..6b0656e2 100644
--- a/freebsd/net80211/ieee80211_crypto_tkip.c
+++ b/freebsd/sys/net80211/ieee80211_crypto_tkip.c
diff --git a/freebsd/net80211/ieee80211_crypto_wep.c b/freebsd/sys/net80211/ieee80211_crypto_wep.c
index 01b3c37d..01b3c37d 100644
--- a/freebsd/net80211/ieee80211_crypto_wep.c
+++ b/freebsd/sys/net80211/ieee80211_crypto_wep.c
diff --git a/freebsd/net80211/ieee80211_ddb.c b/freebsd/sys/net80211/ieee80211_ddb.c
index f3b30431..f3b30431 100644
--- a/freebsd/net80211/ieee80211_ddb.c
+++ b/freebsd/sys/net80211/ieee80211_ddb.c
diff --git a/freebsd/net80211/ieee80211_dfs.c b/freebsd/sys/net80211/ieee80211_dfs.c
index 803ed337..803ed337 100644
--- a/freebsd/net80211/ieee80211_dfs.c
+++ b/freebsd/sys/net80211/ieee80211_dfs.c
diff --git a/freebsd/net80211/ieee80211_dfs.h b/freebsd/sys/net80211/ieee80211_dfs.h
index 474b2078..474b2078 100644
--- a/freebsd/net80211/ieee80211_dfs.h
+++ b/freebsd/sys/net80211/ieee80211_dfs.h
diff --git a/freebsd/net80211/ieee80211_freebsd.c b/freebsd/sys/net80211/ieee80211_freebsd.c
index 4188f112..4188f112 100644
--- a/freebsd/net80211/ieee80211_freebsd.c
+++ b/freebsd/sys/net80211/ieee80211_freebsd.c
diff --git a/freebsd/net80211/ieee80211_freebsd.h b/freebsd/sys/net80211/ieee80211_freebsd.h
index 69efecd0..69efecd0 100644
--- a/freebsd/net80211/ieee80211_freebsd.h
+++ b/freebsd/sys/net80211/ieee80211_freebsd.h
diff --git a/freebsd/net80211/ieee80211_hostap.c b/freebsd/sys/net80211/ieee80211_hostap.c
index 892957be..892957be 100644
--- a/freebsd/net80211/ieee80211_hostap.c
+++ b/freebsd/sys/net80211/ieee80211_hostap.c
diff --git a/freebsd/net80211/ieee80211_hostap.h b/freebsd/sys/net80211/ieee80211_hostap.h
index fa35e220..fa35e220 100644
--- a/freebsd/net80211/ieee80211_hostap.h
+++ b/freebsd/sys/net80211/ieee80211_hostap.h
diff --git a/freebsd/net80211/ieee80211_ht.c b/freebsd/sys/net80211/ieee80211_ht.c
index 2b55c067..2b55c067 100644
--- a/freebsd/net80211/ieee80211_ht.c
+++ b/freebsd/sys/net80211/ieee80211_ht.c
diff --git a/freebsd/net80211/ieee80211_ht.h b/freebsd/sys/net80211/ieee80211_ht.h
index 552a4264..552a4264 100644
--- a/freebsd/net80211/ieee80211_ht.h
+++ b/freebsd/sys/net80211/ieee80211_ht.h
diff --git a/freebsd/net80211/ieee80211_hwmp.c b/freebsd/sys/net80211/ieee80211_hwmp.c
index f0a2cde9..f0a2cde9 100644
--- a/freebsd/net80211/ieee80211_hwmp.c
+++ b/freebsd/sys/net80211/ieee80211_hwmp.c
diff --git a/freebsd/net80211/ieee80211_input.c b/freebsd/sys/net80211/ieee80211_input.c
index 60803d2f..60803d2f 100644
--- a/freebsd/net80211/ieee80211_input.c
+++ b/freebsd/sys/net80211/ieee80211_input.c
diff --git a/freebsd/net80211/ieee80211_input.h b/freebsd/sys/net80211/ieee80211_input.h
index 778badb6..778badb6 100644
--- a/freebsd/net80211/ieee80211_input.h
+++ b/freebsd/sys/net80211/ieee80211_input.h
diff --git a/freebsd/net80211/ieee80211_ioctl.c b/freebsd/sys/net80211/ieee80211_ioctl.c
index 87d1acc5..87d1acc5 100644
--- a/freebsd/net80211/ieee80211_ioctl.c
+++ b/freebsd/sys/net80211/ieee80211_ioctl.c
diff --git a/freebsd/net80211/ieee80211_ioctl.h b/freebsd/sys/net80211/ieee80211_ioctl.h
index 109a27fb..109a27fb 100644
--- a/freebsd/net80211/ieee80211_ioctl.h
+++ b/freebsd/sys/net80211/ieee80211_ioctl.h
diff --git a/freebsd/net80211/ieee80211_mesh.c b/freebsd/sys/net80211/ieee80211_mesh.c
index 06bac89a..06bac89a 100644
--- a/freebsd/net80211/ieee80211_mesh.c
+++ b/freebsd/sys/net80211/ieee80211_mesh.c
diff --git a/freebsd/net80211/ieee80211_mesh.h b/freebsd/sys/net80211/ieee80211_mesh.h
index e90cd402..e90cd402 100644
--- a/freebsd/net80211/ieee80211_mesh.h
+++ b/freebsd/sys/net80211/ieee80211_mesh.h
diff --git a/freebsd/net80211/ieee80211_monitor.c b/freebsd/sys/net80211/ieee80211_monitor.c
index b87c1d37..b87c1d37 100644
--- a/freebsd/net80211/ieee80211_monitor.c
+++ b/freebsd/sys/net80211/ieee80211_monitor.c
diff --git a/freebsd/net80211/ieee80211_monitor.h b/freebsd/sys/net80211/ieee80211_monitor.h
index 09f95dba..09f95dba 100644
--- a/freebsd/net80211/ieee80211_monitor.h
+++ b/freebsd/sys/net80211/ieee80211_monitor.h
diff --git a/freebsd/net80211/ieee80211_node.c b/freebsd/sys/net80211/ieee80211_node.c
index 8b8335c1..8b8335c1 100644
--- a/freebsd/net80211/ieee80211_node.c
+++ b/freebsd/sys/net80211/ieee80211_node.c
diff --git a/freebsd/net80211/ieee80211_node.h b/freebsd/sys/net80211/ieee80211_node.h
index cf47a101..cf47a101 100644
--- a/freebsd/net80211/ieee80211_node.h
+++ b/freebsd/sys/net80211/ieee80211_node.h
diff --git a/freebsd/net80211/ieee80211_output.c b/freebsd/sys/net80211/ieee80211_output.c
index b7abe9ec..b7abe9ec 100644
--- a/freebsd/net80211/ieee80211_output.c
+++ b/freebsd/sys/net80211/ieee80211_output.c
diff --git a/freebsd/net80211/ieee80211_phy.c b/freebsd/sys/net80211/ieee80211_phy.c
index 5c5a2f55..5c5a2f55 100644
--- a/freebsd/net80211/ieee80211_phy.c
+++ b/freebsd/sys/net80211/ieee80211_phy.c
diff --git a/freebsd/net80211/ieee80211_phy.h b/freebsd/sys/net80211/ieee80211_phy.h
index af76e666..af76e666 100644
--- a/freebsd/net80211/ieee80211_phy.h
+++ b/freebsd/sys/net80211/ieee80211_phy.h
diff --git a/freebsd/net80211/ieee80211_power.c b/freebsd/sys/net80211/ieee80211_power.c
index f56a641f..f56a641f 100644
--- a/freebsd/net80211/ieee80211_power.c
+++ b/freebsd/sys/net80211/ieee80211_power.c
diff --git a/freebsd/net80211/ieee80211_power.h b/freebsd/sys/net80211/ieee80211_power.h
index 6cb0eab8..6cb0eab8 100644
--- a/freebsd/net80211/ieee80211_power.h
+++ b/freebsd/sys/net80211/ieee80211_power.h
diff --git a/freebsd/net80211/ieee80211_proto.c b/freebsd/sys/net80211/ieee80211_proto.c
index 70c5f299..70c5f299 100644
--- a/freebsd/net80211/ieee80211_proto.c
+++ b/freebsd/sys/net80211/ieee80211_proto.c
diff --git a/freebsd/net80211/ieee80211_proto.h b/freebsd/sys/net80211/ieee80211_proto.h
index f81a6433..f81a6433 100644
--- a/freebsd/net80211/ieee80211_proto.h
+++ b/freebsd/sys/net80211/ieee80211_proto.h
diff --git a/freebsd/net80211/ieee80211_radiotap.c b/freebsd/sys/net80211/ieee80211_radiotap.c
index f630ae99..f630ae99 100644
--- a/freebsd/net80211/ieee80211_radiotap.c
+++ b/freebsd/sys/net80211/ieee80211_radiotap.c
diff --git a/freebsd/net80211/ieee80211_radiotap.h b/freebsd/sys/net80211/ieee80211_radiotap.h
index 89eac4be..89eac4be 100644
--- a/freebsd/net80211/ieee80211_radiotap.h
+++ b/freebsd/sys/net80211/ieee80211_radiotap.h
diff --git a/freebsd/net80211/ieee80211_ratectl.c b/freebsd/sys/net80211/ieee80211_ratectl.c
index 8eede3cb..8eede3cb 100644
--- a/freebsd/net80211/ieee80211_ratectl.c
+++ b/freebsd/sys/net80211/ieee80211_ratectl.c
diff --git a/freebsd/net80211/ieee80211_ratectl.h b/freebsd/sys/net80211/ieee80211_ratectl.h
index be81781c..be81781c 100644
--- a/freebsd/net80211/ieee80211_ratectl.h
+++ b/freebsd/sys/net80211/ieee80211_ratectl.h
diff --git a/freebsd/net80211/ieee80211_ratectl_none.c b/freebsd/sys/net80211/ieee80211_ratectl_none.c
index 97f0749f..97f0749f 100644
--- a/freebsd/net80211/ieee80211_ratectl_none.c
+++ b/freebsd/sys/net80211/ieee80211_ratectl_none.c
diff --git a/freebsd/net80211/ieee80211_regdomain.c b/freebsd/sys/net80211/ieee80211_regdomain.c
index e83132c8..e83132c8 100644
--- a/freebsd/net80211/ieee80211_regdomain.c
+++ b/freebsd/sys/net80211/ieee80211_regdomain.c
diff --git a/freebsd/net80211/ieee80211_regdomain.h b/freebsd/sys/net80211/ieee80211_regdomain.h
index f71c1093..f71c1093 100644
--- a/freebsd/net80211/ieee80211_regdomain.h
+++ b/freebsd/sys/net80211/ieee80211_regdomain.h
diff --git a/freebsd/net80211/ieee80211_rssadapt.c b/freebsd/sys/net80211/ieee80211_rssadapt.c
index b50d2e66..b50d2e66 100644
--- a/freebsd/net80211/ieee80211_rssadapt.c
+++ b/freebsd/sys/net80211/ieee80211_rssadapt.c
diff --git a/freebsd/net80211/ieee80211_rssadapt.h b/freebsd/sys/net80211/ieee80211_rssadapt.h
index 26211ece..26211ece 100644
--- a/freebsd/net80211/ieee80211_rssadapt.h
+++ b/freebsd/sys/net80211/ieee80211_rssadapt.h
diff --git a/freebsd/net80211/ieee80211_scan.c b/freebsd/sys/net80211/ieee80211_scan.c
index bda486ec..bda486ec 100644
--- a/freebsd/net80211/ieee80211_scan.c
+++ b/freebsd/sys/net80211/ieee80211_scan.c
diff --git a/freebsd/net80211/ieee80211_scan.h b/freebsd/sys/net80211/ieee80211_scan.h
index 6273902d..6273902d 100644
--- a/freebsd/net80211/ieee80211_scan.h
+++ b/freebsd/sys/net80211/ieee80211_scan.h
diff --git a/freebsd/net80211/ieee80211_scan_sta.c b/freebsd/sys/net80211/ieee80211_scan_sta.c
index aa9d67ec..aa9d67ec 100644
--- a/freebsd/net80211/ieee80211_scan_sta.c
+++ b/freebsd/sys/net80211/ieee80211_scan_sta.c
diff --git a/freebsd/net80211/ieee80211_sta.c b/freebsd/sys/net80211/ieee80211_sta.c
index 67704469..67704469 100644
--- a/freebsd/net80211/ieee80211_sta.c
+++ b/freebsd/sys/net80211/ieee80211_sta.c
diff --git a/freebsd/net80211/ieee80211_sta.h b/freebsd/sys/net80211/ieee80211_sta.h
index 43316f5b..43316f5b 100644
--- a/freebsd/net80211/ieee80211_sta.h
+++ b/freebsd/sys/net80211/ieee80211_sta.h
diff --git a/freebsd/net80211/ieee80211_superg.c b/freebsd/sys/net80211/ieee80211_superg.c
index dd886e41..dd886e41 100644
--- a/freebsd/net80211/ieee80211_superg.c
+++ b/freebsd/sys/net80211/ieee80211_superg.c
diff --git a/freebsd/net80211/ieee80211_superg.h b/freebsd/sys/net80211/ieee80211_superg.h
index bda45dda..bda45dda 100644
--- a/freebsd/net80211/ieee80211_superg.h
+++ b/freebsd/sys/net80211/ieee80211_superg.h
diff --git a/freebsd/net80211/ieee80211_tdma.c b/freebsd/sys/net80211/ieee80211_tdma.c
index c41ca491..c41ca491 100644
--- a/freebsd/net80211/ieee80211_tdma.c
+++ b/freebsd/sys/net80211/ieee80211_tdma.c
diff --git a/freebsd/net80211/ieee80211_tdma.h b/freebsd/sys/net80211/ieee80211_tdma.h
index 989d6417..989d6417 100644
--- a/freebsd/net80211/ieee80211_tdma.h
+++ b/freebsd/sys/net80211/ieee80211_tdma.h
diff --git a/freebsd/net80211/ieee80211_var.h b/freebsd/sys/net80211/ieee80211_var.h
index 2ab54b78..2ab54b78 100644
--- a/freebsd/net80211/ieee80211_var.h
+++ b/freebsd/sys/net80211/ieee80211_var.h
diff --git a/freebsd/net80211/ieee80211_wds.c b/freebsd/sys/net80211/ieee80211_wds.c
index b0f5378d..b0f5378d 100644
--- a/freebsd/net80211/ieee80211_wds.c
+++ b/freebsd/sys/net80211/ieee80211_wds.c
diff --git a/freebsd/net80211/ieee80211_wds.h b/freebsd/sys/net80211/ieee80211_wds.h
index 200cba27..200cba27 100644
--- a/freebsd/net80211/ieee80211_wds.h
+++ b/freebsd/sys/net80211/ieee80211_wds.h
diff --git a/freebsd/net80211/ieee80211_xauth.c b/freebsd/sys/net80211/ieee80211_xauth.c
index 55318069..55318069 100644
--- a/freebsd/net80211/ieee80211_xauth.c
+++ b/freebsd/sys/net80211/ieee80211_xauth.c
diff --git a/freebsd/netatalk/aarp.c b/freebsd/sys/netatalk/aarp.c
index 63fabede..63fabede 100644
--- a/freebsd/netatalk/aarp.c
+++ b/freebsd/sys/netatalk/aarp.c
diff --git a/freebsd/netatalk/aarp.h b/freebsd/sys/netatalk/aarp.h
index 4d7e06ac..4d7e06ac 100644
--- a/freebsd/netatalk/aarp.h
+++ b/freebsd/sys/netatalk/aarp.h
diff --git a/freebsd/sys/netatalk/at.h b/freebsd/sys/netatalk/at.h
new file mode 100644
index 00000000..27e88acb
--- /dev/null
+++ b/freebsd/sys/netatalk/at.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netatalk/at.h>
diff --git a/freebsd/netatalk/at_control.c b/freebsd/sys/netatalk/at_control.c
index c03d2ad8..c03d2ad8 100644
--- a/freebsd/netatalk/at_control.c
+++ b/freebsd/sys/netatalk/at_control.c
diff --git a/freebsd/netatalk/at_extern.h b/freebsd/sys/netatalk/at_extern.h
index aebae73c..aebae73c 100644
--- a/freebsd/netatalk/at_extern.h
+++ b/freebsd/sys/netatalk/at_extern.h
diff --git a/freebsd/netatalk/at_proto.c b/freebsd/sys/netatalk/at_proto.c
index cc7902b0..cc7902b0 100644
--- a/freebsd/netatalk/at_proto.c
+++ b/freebsd/sys/netatalk/at_proto.c
diff --git a/freebsd/netatalk/at_rmx.c b/freebsd/sys/netatalk/at_rmx.c
index 54272ad7..54272ad7 100644
--- a/freebsd/netatalk/at_rmx.c
+++ b/freebsd/sys/netatalk/at_rmx.c
diff --git a/freebsd/netatalk/at_var.h b/freebsd/sys/netatalk/at_var.h
index ead90fb1..ead90fb1 100644
--- a/freebsd/netatalk/at_var.h
+++ b/freebsd/sys/netatalk/at_var.h
diff --git a/freebsd/netatalk/ddp.h b/freebsd/sys/netatalk/ddp.h
index f954b080..f954b080 100644
--- a/freebsd/netatalk/ddp.h
+++ b/freebsd/sys/netatalk/ddp.h
diff --git a/freebsd/netatalk/ddp_input.c b/freebsd/sys/netatalk/ddp_input.c
index 64eaac7d..64eaac7d 100644
--- a/freebsd/netatalk/ddp_input.c
+++ b/freebsd/sys/netatalk/ddp_input.c
diff --git a/freebsd/netatalk/ddp_output.c b/freebsd/sys/netatalk/ddp_output.c
index 0bb74123..0bb74123 100644
--- a/freebsd/netatalk/ddp_output.c
+++ b/freebsd/sys/netatalk/ddp_output.c
diff --git a/freebsd/netatalk/ddp_pcb.c b/freebsd/sys/netatalk/ddp_pcb.c
index 4faeb092..4faeb092 100644
--- a/freebsd/netatalk/ddp_pcb.c
+++ b/freebsd/sys/netatalk/ddp_pcb.c
diff --git a/freebsd/netatalk/ddp_pcb.h b/freebsd/sys/netatalk/ddp_pcb.h
index 4449c3ae..4449c3ae 100644
--- a/freebsd/netatalk/ddp_pcb.h
+++ b/freebsd/sys/netatalk/ddp_pcb.h
diff --git a/freebsd/netatalk/ddp_usrreq.c b/freebsd/sys/netatalk/ddp_usrreq.c
index 1d1990c4..1d1990c4 100644
--- a/freebsd/netatalk/ddp_usrreq.c
+++ b/freebsd/sys/netatalk/ddp_usrreq.c
diff --git a/freebsd/netatalk/ddp_var.h b/freebsd/sys/netatalk/ddp_var.h
index e0148a24..e0148a24 100644
--- a/freebsd/netatalk/ddp_var.h
+++ b/freebsd/sys/netatalk/ddp_var.h
diff --git a/freebsd/netatalk/endian.h b/freebsd/sys/netatalk/endian.h
index b15332c1..b15332c1 100644
--- a/freebsd/netatalk/endian.h
+++ b/freebsd/sys/netatalk/endian.h
diff --git a/freebsd/netatalk/phase2.h b/freebsd/sys/netatalk/phase2.h
index aaa3dd38..aaa3dd38 100644
--- a/freebsd/netatalk/phase2.h
+++ b/freebsd/sys/netatalk/phase2.h
diff --git a/freebsd/netinet/accf_data.c b/freebsd/sys/netinet/accf_data.c
index 15696daf..15696daf 100644
--- a/freebsd/netinet/accf_data.c
+++ b/freebsd/sys/netinet/accf_data.c
diff --git a/freebsd/netinet/accf_dns.c b/freebsd/sys/netinet/accf_dns.c
index f91cbb08..f91cbb08 100644
--- a/freebsd/netinet/accf_dns.c
+++ b/freebsd/sys/netinet/accf_dns.c
diff --git a/freebsd/netinet/accf_http.c b/freebsd/sys/netinet/accf_http.c
index ce21b1d1..ce21b1d1 100644
--- a/freebsd/netinet/accf_http.c
+++ b/freebsd/sys/netinet/accf_http.c
diff --git a/freebsd/sys/netinet/icmp6.h b/freebsd/sys/netinet/icmp6.h
new file mode 100644
index 00000000..bf61ac5b
--- /dev/null
+++ b/freebsd/sys/netinet/icmp6.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/icmp6.h>
diff --git a/freebsd/netinet/icmp_var.h b/freebsd/sys/netinet/icmp_var.h
index d55fc4d3..d55fc4d3 100644
--- a/freebsd/netinet/icmp_var.h
+++ b/freebsd/sys/netinet/icmp_var.h
diff --git a/freebsd/netinet/if_atm.c b/freebsd/sys/netinet/if_atm.c
index ea6c567d..ea6c567d 100644
--- a/freebsd/netinet/if_atm.c
+++ b/freebsd/sys/netinet/if_atm.c
diff --git a/freebsd/netinet/if_atm.h b/freebsd/sys/netinet/if_atm.h
index bd8b5143..bd8b5143 100644
--- a/freebsd/netinet/if_atm.h
+++ b/freebsd/sys/netinet/if_atm.h
diff --git a/freebsd/netinet/if_ether.c b/freebsd/sys/netinet/if_ether.c
index 2e40c0d2..2e40c0d2 100644
--- a/freebsd/netinet/if_ether.c
+++ b/freebsd/sys/netinet/if_ether.c
diff --git a/freebsd/sys/netinet/if_ether.h b/freebsd/sys/netinet/if_ether.h
new file mode 100644
index 00000000..e3c8d009
--- /dev/null
+++ b/freebsd/sys/netinet/if_ether.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/if_ether.h>
diff --git a/freebsd/netinet/igmp.c b/freebsd/sys/netinet/igmp.c
index 5f8893d7..5f8893d7 100644
--- a/freebsd/netinet/igmp.c
+++ b/freebsd/sys/netinet/igmp.c
diff --git a/freebsd/sys/netinet/igmp.h b/freebsd/sys/netinet/igmp.h
new file mode 100644
index 00000000..f328d21f
--- /dev/null
+++ b/freebsd/sys/netinet/igmp.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/igmp.h>
diff --git a/freebsd/netinet/igmp_var.h b/freebsd/sys/netinet/igmp_var.h
index e1abe6ab..e1abe6ab 100644
--- a/freebsd/netinet/igmp_var.h
+++ b/freebsd/sys/netinet/igmp_var.h
diff --git a/freebsd/netinet/in.c b/freebsd/sys/netinet/in.c
index 64e5d329..64e5d329 100644
--- a/freebsd/netinet/in.c
+++ b/freebsd/sys/netinet/in.c
diff --git a/freebsd/sys/netinet/in.h b/freebsd/sys/netinet/in.h
new file mode 100644
index 00000000..73c7ca1a
--- /dev/null
+++ b/freebsd/sys/netinet/in.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/in.h>
diff --git a/freebsd/netinet/in_gif.c b/freebsd/sys/netinet/in_gif.c
index 3613e214..3613e214 100644
--- a/freebsd/netinet/in_gif.c
+++ b/freebsd/sys/netinet/in_gif.c
diff --git a/freebsd/netinet/in_gif.h b/freebsd/sys/netinet/in_gif.h
index 1e42b01f..1e42b01f 100644
--- a/freebsd/netinet/in_gif.h
+++ b/freebsd/sys/netinet/in_gif.h
diff --git a/freebsd/netinet/in_mcast.c b/freebsd/sys/netinet/in_mcast.c
index ed2bcc12..ed2bcc12 100644
--- a/freebsd/netinet/in_mcast.c
+++ b/freebsd/sys/netinet/in_mcast.c
diff --git a/freebsd/netinet/in_pcb.c b/freebsd/sys/netinet/in_pcb.c
index 186a0f0a..186a0f0a 100644
--- a/freebsd/netinet/in_pcb.c
+++ b/freebsd/sys/netinet/in_pcb.c
diff --git a/freebsd/netinet/in_pcb.h b/freebsd/sys/netinet/in_pcb.h
index 8cd4a5f8..8cd4a5f8 100644
--- a/freebsd/netinet/in_pcb.h
+++ b/freebsd/sys/netinet/in_pcb.h
diff --git a/freebsd/netinet/in_proto.c b/freebsd/sys/netinet/in_proto.c
index 9be0b626..9be0b626 100644
--- a/freebsd/netinet/in_proto.c
+++ b/freebsd/sys/netinet/in_proto.c
diff --git a/freebsd/netinet/in_rmx.c b/freebsd/sys/netinet/in_rmx.c
index 25f99ea0..25f99ea0 100644
--- a/freebsd/netinet/in_rmx.c
+++ b/freebsd/sys/netinet/in_rmx.c
diff --git a/freebsd/sys/netinet/in_systm.h b/freebsd/sys/netinet/in_systm.h
new file mode 100644
index 00000000..68bb190e
--- /dev/null
+++ b/freebsd/sys/netinet/in_systm.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/in_systm.h>
diff --git a/freebsd/netinet/in_var.h b/freebsd/sys/netinet/in_var.h
index c921ad31..c921ad31 100644
--- a/freebsd/netinet/in_var.h
+++ b/freebsd/sys/netinet/in_var.h
diff --git a/freebsd/sys/netinet/ip.h b/freebsd/sys/netinet/ip.h
new file mode 100644
index 00000000..9d5d8a9c
--- /dev/null
+++ b/freebsd/sys/netinet/ip.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/ip.h>
diff --git a/freebsd/sys/netinet/ip6.h b/freebsd/sys/netinet/ip6.h
new file mode 100644
index 00000000..f30da6d1
--- /dev/null
+++ b/freebsd/sys/netinet/ip6.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/ip6.h>
diff --git a/freebsd/netinet/ip_carp.c b/freebsd/sys/netinet/ip_carp.c
index 25b20895..25b20895 100644
--- a/freebsd/netinet/ip_carp.c
+++ b/freebsd/sys/netinet/ip_carp.c
diff --git a/freebsd/netinet/ip_carp.h b/freebsd/sys/netinet/ip_carp.h
index 2f2b4f28..2f2b4f28 100644
--- a/freebsd/netinet/ip_carp.h
+++ b/freebsd/sys/netinet/ip_carp.h
diff --git a/freebsd/netinet/ip_divert.c b/freebsd/sys/netinet/ip_divert.c
index 13999825..13999825 100644
--- a/freebsd/netinet/ip_divert.c
+++ b/freebsd/sys/netinet/ip_divert.c
diff --git a/freebsd/netinet/ip_divert.h b/freebsd/sys/netinet/ip_divert.h
index eb9b33d4..eb9b33d4 100644
--- a/freebsd/netinet/ip_divert.h
+++ b/freebsd/sys/netinet/ip_divert.h
diff --git a/freebsd/netinet/ip_dummynet.h b/freebsd/sys/netinet/ip_dummynet.h
index 0bbc3263..0bbc3263 100644
--- a/freebsd/netinet/ip_dummynet.h
+++ b/freebsd/sys/netinet/ip_dummynet.h
diff --git a/freebsd/netinet/ip_ecn.c b/freebsd/sys/netinet/ip_ecn.c
index 97b32b2c..97b32b2c 100644
--- a/freebsd/netinet/ip_ecn.c
+++ b/freebsd/sys/netinet/ip_ecn.c
diff --git a/freebsd/netinet/ip_ecn.h b/freebsd/sys/netinet/ip_ecn.h
index 271c8a47..271c8a47 100644
--- a/freebsd/netinet/ip_ecn.h
+++ b/freebsd/sys/netinet/ip_ecn.h
diff --git a/freebsd/netinet/ip_encap.c b/freebsd/sys/netinet/ip_encap.c
index 45b0593c..45b0593c 100644
--- a/freebsd/netinet/ip_encap.c
+++ b/freebsd/sys/netinet/ip_encap.c
diff --git a/freebsd/netinet/ip_encap.h b/freebsd/sys/netinet/ip_encap.h
index 44dd1a0d..44dd1a0d 100644
--- a/freebsd/netinet/ip_encap.h
+++ b/freebsd/sys/netinet/ip_encap.h
diff --git a/freebsd/netinet/ip_fastfwd.c b/freebsd/sys/netinet/ip_fastfwd.c
index 6d406b2b..6d406b2b 100644
--- a/freebsd/netinet/ip_fastfwd.c
+++ b/freebsd/sys/netinet/ip_fastfwd.c
diff --git a/freebsd/netinet/ip_fw.h b/freebsd/sys/netinet/ip_fw.h
index cf5d8d03..cf5d8d03 100644
--- a/freebsd/netinet/ip_fw.h
+++ b/freebsd/sys/netinet/ip_fw.h
diff --git a/freebsd/netinet/ip_gre.c b/freebsd/sys/netinet/ip_gre.c
index 253376de..253376de 100644
--- a/freebsd/netinet/ip_gre.c
+++ b/freebsd/sys/netinet/ip_gre.c
diff --git a/freebsd/netinet/ip_gre.h b/freebsd/sys/netinet/ip_gre.h
index 1fb67d93..1fb67d93 100644
--- a/freebsd/netinet/ip_gre.h
+++ b/freebsd/sys/netinet/ip_gre.h
diff --git a/freebsd/netinet/ip_icmp.c b/freebsd/sys/netinet/ip_icmp.c
index b7a83128..b7a83128 100644
--- a/freebsd/netinet/ip_icmp.c
+++ b/freebsd/sys/netinet/ip_icmp.c
diff --git a/freebsd/sys/netinet/ip_icmp.h b/freebsd/sys/netinet/ip_icmp.h
new file mode 100644
index 00000000..903f033d
--- /dev/null
+++ b/freebsd/sys/netinet/ip_icmp.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/ip_icmp.h>
diff --git a/freebsd/netinet/ip_id.c b/freebsd/sys/netinet/ip_id.c
index ba99cdbb..ba99cdbb 100644
--- a/freebsd/netinet/ip_id.c
+++ b/freebsd/sys/netinet/ip_id.c
diff --git a/freebsd/netinet/ip_input.c b/freebsd/sys/netinet/ip_input.c
index 3964e886..3964e886 100644
--- a/freebsd/netinet/ip_input.c
+++ b/freebsd/sys/netinet/ip_input.c
diff --git a/freebsd/netinet/ip_ipsec.c b/freebsd/sys/netinet/ip_ipsec.c
index f19d5e0e..f19d5e0e 100644
--- a/freebsd/netinet/ip_ipsec.c
+++ b/freebsd/sys/netinet/ip_ipsec.c
diff --git a/freebsd/netinet/ip_ipsec.h b/freebsd/sys/netinet/ip_ipsec.h
index c4de1652..c4de1652 100644
--- a/freebsd/netinet/ip_ipsec.h
+++ b/freebsd/sys/netinet/ip_ipsec.h
diff --git a/freebsd/netinet/ip_mroute.c b/freebsd/sys/netinet/ip_mroute.c
index 2f7676ad..2f7676ad 100644
--- a/freebsd/netinet/ip_mroute.c
+++ b/freebsd/sys/netinet/ip_mroute.c
diff --git a/freebsd/netinet/ip_mroute.h b/freebsd/sys/netinet/ip_mroute.h
index 3bc7f52f..3bc7f52f 100644
--- a/freebsd/netinet/ip_mroute.h
+++ b/freebsd/sys/netinet/ip_mroute.h
diff --git a/freebsd/netinet/ip_options.c b/freebsd/sys/netinet/ip_options.c
index f8b31607..f8b31607 100644
--- a/freebsd/netinet/ip_options.c
+++ b/freebsd/sys/netinet/ip_options.c
diff --git a/freebsd/netinet/ip_options.h b/freebsd/sys/netinet/ip_options.h
index 9c08004d..9c08004d 100644
--- a/freebsd/netinet/ip_options.h
+++ b/freebsd/sys/netinet/ip_options.h
diff --git a/freebsd/netinet/ip_output.c b/freebsd/sys/netinet/ip_output.c
index 51132333..51132333 100644
--- a/freebsd/netinet/ip_output.c
+++ b/freebsd/sys/netinet/ip_output.c
diff --git a/freebsd/netinet/ip_var.h b/freebsd/sys/netinet/ip_var.h
index 2902174d..2902174d 100644
--- a/freebsd/netinet/ip_var.h
+++ b/freebsd/sys/netinet/ip_var.h
diff --git a/freebsd/netinet/ipfw/dn_heap.c b/freebsd/sys/netinet/ipfw/dn_heap.c
index 1e6133bc..1e6133bc 100644
--- a/freebsd/netinet/ipfw/dn_heap.c
+++ b/freebsd/sys/netinet/ipfw/dn_heap.c
diff --git a/freebsd/netinet/ipfw/dn_heap.h b/freebsd/sys/netinet/ipfw/dn_heap.h
index c95473ad..c95473ad 100644
--- a/freebsd/netinet/ipfw/dn_heap.h
+++ b/freebsd/sys/netinet/ipfw/dn_heap.h
diff --git a/freebsd/netinet/ipfw/dn_sched.h b/freebsd/sys/netinet/ipfw/dn_sched.h
index fe54b020..fe54b020 100644
--- a/freebsd/netinet/ipfw/dn_sched.h
+++ b/freebsd/sys/netinet/ipfw/dn_sched.h
diff --git a/freebsd/netinet/ipfw/dn_sched_fifo.c b/freebsd/sys/netinet/ipfw/dn_sched_fifo.c
index 6d5a4a12..6d5a4a12 100644
--- a/freebsd/netinet/ipfw/dn_sched_fifo.c
+++ b/freebsd/sys/netinet/ipfw/dn_sched_fifo.c
diff --git a/freebsd/netinet/ipfw/dn_sched_prio.c b/freebsd/sys/netinet/ipfw/dn_sched_prio.c
index c6b6027c..c6b6027c 100644
--- a/freebsd/netinet/ipfw/dn_sched_prio.c
+++ b/freebsd/sys/netinet/ipfw/dn_sched_prio.c
diff --git a/freebsd/netinet/ipfw/dn_sched_qfq.c b/freebsd/sys/netinet/ipfw/dn_sched_qfq.c
index 23890199..23890199 100644
--- a/freebsd/netinet/ipfw/dn_sched_qfq.c
+++ b/freebsd/sys/netinet/ipfw/dn_sched_qfq.c
diff --git a/freebsd/netinet/ipfw/dn_sched_rr.c b/freebsd/sys/netinet/ipfw/dn_sched_rr.c
index 4aa833f6..4aa833f6 100644
--- a/freebsd/netinet/ipfw/dn_sched_rr.c
+++ b/freebsd/sys/netinet/ipfw/dn_sched_rr.c
diff --git a/freebsd/netinet/ipfw/dn_sched_wf2q.c b/freebsd/sys/netinet/ipfw/dn_sched_wf2q.c
index c1e4c21d..c1e4c21d 100644
--- a/freebsd/netinet/ipfw/dn_sched_wf2q.c
+++ b/freebsd/sys/netinet/ipfw/dn_sched_wf2q.c
diff --git a/freebsd/netinet/ipfw/ip_dn_glue.c b/freebsd/sys/netinet/ipfw/ip_dn_glue.c
index 302c4d29..302c4d29 100644
--- a/freebsd/netinet/ipfw/ip_dn_glue.c
+++ b/freebsd/sys/netinet/ipfw/ip_dn_glue.c
diff --git a/freebsd/netinet/ipfw/ip_dn_io.c b/freebsd/sys/netinet/ipfw/ip_dn_io.c
index 7a2c46d4..7a2c46d4 100644
--- a/freebsd/netinet/ipfw/ip_dn_io.c
+++ b/freebsd/sys/netinet/ipfw/ip_dn_io.c
diff --git a/freebsd/netinet/ipfw/ip_dn_private.h b/freebsd/sys/netinet/ipfw/ip_dn_private.h
index 270f1881..270f1881 100644
--- a/freebsd/netinet/ipfw/ip_dn_private.h
+++ b/freebsd/sys/netinet/ipfw/ip_dn_private.h
diff --git a/freebsd/netinet/ipfw/ip_dummynet.c b/freebsd/sys/netinet/ipfw/ip_dummynet.c
index dca39d06..dca39d06 100644
--- a/freebsd/netinet/ipfw/ip_dummynet.c
+++ b/freebsd/sys/netinet/ipfw/ip_dummynet.c
diff --git a/freebsd/netinet/ipfw/ip_fw2.c b/freebsd/sys/netinet/ipfw/ip_fw2.c
index 682cced1..682cced1 100644
--- a/freebsd/netinet/ipfw/ip_fw2.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw2.c
diff --git a/freebsd/netinet/ipfw/ip_fw_log.c b/freebsd/sys/netinet/ipfw/ip_fw_log.c
index 0a5cd94c..0a5cd94c 100644
--- a/freebsd/netinet/ipfw/ip_fw_log.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_log.c
diff --git a/freebsd/netinet/ipfw/ip_fw_nat.c b/freebsd/sys/netinet/ipfw/ip_fw_nat.c
index e6c8bcec..e6c8bcec 100644
--- a/freebsd/netinet/ipfw/ip_fw_nat.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_nat.c
diff --git a/freebsd/netinet/ipfw/ip_fw_pfil.c b/freebsd/sys/netinet/ipfw/ip_fw_pfil.c
index 8759f409..8759f409 100644
--- a/freebsd/netinet/ipfw/ip_fw_pfil.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_pfil.c
diff --git a/freebsd/netinet/ipfw/ip_fw_private.h b/freebsd/sys/netinet/ipfw/ip_fw_private.h
index c29ae0ad..c29ae0ad 100644
--- a/freebsd/netinet/ipfw/ip_fw_private.h
+++ b/freebsd/sys/netinet/ipfw/ip_fw_private.h
diff --git a/freebsd/netinet/ipfw/ip_fw_sockopt.c b/freebsd/sys/netinet/ipfw/ip_fw_sockopt.c
index 6af09905..6af09905 100644
--- a/freebsd/netinet/ipfw/ip_fw_sockopt.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_sockopt.c
diff --git a/freebsd/netinet/ipfw/ip_fw_table.c b/freebsd/sys/netinet/ipfw/ip_fw_table.c
index 39a1dfcc..39a1dfcc 100644
--- a/freebsd/netinet/ipfw/ip_fw_table.c
+++ b/freebsd/sys/netinet/ipfw/ip_fw_table.c
diff --git a/freebsd/netinet/libalias/alias.c b/freebsd/sys/netinet/libalias/alias.c
index e5c5138d..e5c5138d 100644
--- a/freebsd/netinet/libalias/alias.c
+++ b/freebsd/sys/netinet/libalias/alias.c
diff --git a/freebsd/netinet/libalias/alias.h b/freebsd/sys/netinet/libalias/alias.h
index f835e1b7..f835e1b7 100644
--- a/freebsd/netinet/libalias/alias.h
+++ b/freebsd/sys/netinet/libalias/alias.h
diff --git a/freebsd/netinet/libalias/alias_cuseeme.c b/freebsd/sys/netinet/libalias/alias_cuseeme.c
index 90f2aaae..90f2aaae 100644
--- a/freebsd/netinet/libalias/alias_cuseeme.c
+++ b/freebsd/sys/netinet/libalias/alias_cuseeme.c
diff --git a/freebsd/netinet/libalias/alias_db.c b/freebsd/sys/netinet/libalias/alias_db.c
index 4b003366..4b003366 100644
--- a/freebsd/netinet/libalias/alias_db.c
+++ b/freebsd/sys/netinet/libalias/alias_db.c
diff --git a/freebsd/netinet/libalias/alias_dummy.c b/freebsd/sys/netinet/libalias/alias_dummy.c
index c5a316d4..c5a316d4 100644
--- a/freebsd/netinet/libalias/alias_dummy.c
+++ b/freebsd/sys/netinet/libalias/alias_dummy.c
diff --git a/freebsd/netinet/libalias/alias_ftp.c b/freebsd/sys/netinet/libalias/alias_ftp.c
index 4e8b7177..4e8b7177 100644
--- a/freebsd/netinet/libalias/alias_ftp.c
+++ b/freebsd/sys/netinet/libalias/alias_ftp.c
diff --git a/freebsd/netinet/libalias/alias_irc.c b/freebsd/sys/netinet/libalias/alias_irc.c
index 05db0f4f..05db0f4f 100644
--- a/freebsd/netinet/libalias/alias_irc.c
+++ b/freebsd/sys/netinet/libalias/alias_irc.c
diff --git a/freebsd/netinet/libalias/alias_local.h b/freebsd/sys/netinet/libalias/alias_local.h
index e24ece49..e24ece49 100644
--- a/freebsd/netinet/libalias/alias_local.h
+++ b/freebsd/sys/netinet/libalias/alias_local.h
diff --git a/freebsd/netinet/libalias/alias_mod.c b/freebsd/sys/netinet/libalias/alias_mod.c
index fa15b2e4..fa15b2e4 100644
--- a/freebsd/netinet/libalias/alias_mod.c
+++ b/freebsd/sys/netinet/libalias/alias_mod.c
diff --git a/freebsd/netinet/libalias/alias_mod.h b/freebsd/sys/netinet/libalias/alias_mod.h
index f5f98cc3..f5f98cc3 100644
--- a/freebsd/netinet/libalias/alias_mod.h
+++ b/freebsd/sys/netinet/libalias/alias_mod.h
diff --git a/freebsd/netinet/libalias/alias_nbt.c b/freebsd/sys/netinet/libalias/alias_nbt.c
index 31ee0006..31ee0006 100644
--- a/freebsd/netinet/libalias/alias_nbt.c
+++ b/freebsd/sys/netinet/libalias/alias_nbt.c
diff --git a/freebsd/netinet/libalias/alias_pptp.c b/freebsd/sys/netinet/libalias/alias_pptp.c
index f6c7f199..f6c7f199 100644
--- a/freebsd/netinet/libalias/alias_pptp.c
+++ b/freebsd/sys/netinet/libalias/alias_pptp.c
diff --git a/freebsd/netinet/libalias/alias_proxy.c b/freebsd/sys/netinet/libalias/alias_proxy.c
index f4f2b643..f4f2b643 100644
--- a/freebsd/netinet/libalias/alias_proxy.c
+++ b/freebsd/sys/netinet/libalias/alias_proxy.c
diff --git a/freebsd/netinet/libalias/alias_sctp.c b/freebsd/sys/netinet/libalias/alias_sctp.c
index cdec258c..cdec258c 100644
--- a/freebsd/netinet/libalias/alias_sctp.c
+++ b/freebsd/sys/netinet/libalias/alias_sctp.c
diff --git a/freebsd/netinet/libalias/alias_sctp.h b/freebsd/sys/netinet/libalias/alias_sctp.h
index 9ea21959..9ea21959 100644
--- a/freebsd/netinet/libalias/alias_sctp.h
+++ b/freebsd/sys/netinet/libalias/alias_sctp.h
diff --git a/freebsd/netinet/libalias/alias_skinny.c b/freebsd/sys/netinet/libalias/alias_skinny.c
index 4d311efe..4d311efe 100644
--- a/freebsd/netinet/libalias/alias_skinny.c
+++ b/freebsd/sys/netinet/libalias/alias_skinny.c
diff --git a/freebsd/netinet/libalias/alias_smedia.c b/freebsd/sys/netinet/libalias/alias_smedia.c
index 3d558a94..3d558a94 100644
--- a/freebsd/netinet/libalias/alias_smedia.c
+++ b/freebsd/sys/netinet/libalias/alias_smedia.c
diff --git a/freebsd/netinet/libalias/alias_util.c b/freebsd/sys/netinet/libalias/alias_util.c
index 1e0c95ae..1e0c95ae 100644
--- a/freebsd/netinet/libalias/alias_util.c
+++ b/freebsd/sys/netinet/libalias/alias_util.c
diff --git a/freebsd/netinet/pim.h b/freebsd/sys/netinet/pim.h
index 2f887cc2..2f887cc2 100644
--- a/freebsd/netinet/pim.h
+++ b/freebsd/sys/netinet/pim.h
diff --git a/freebsd/netinet/pim_var.h b/freebsd/sys/netinet/pim_var.h
index 9d80bbb2..9d80bbb2 100644
--- a/freebsd/netinet/pim_var.h
+++ b/freebsd/sys/netinet/pim_var.h
diff --git a/freebsd/netinet/raw_ip.c b/freebsd/sys/netinet/raw_ip.c
index fb90880f..fb90880f 100644
--- a/freebsd/netinet/raw_ip.c
+++ b/freebsd/sys/netinet/raw_ip.c
diff --git a/freebsd/netinet/sctp.h b/freebsd/sys/netinet/sctp.h
index bf188a23..bf188a23 100644
--- a/freebsd/netinet/sctp.h
+++ b/freebsd/sys/netinet/sctp.h
diff --git a/freebsd/netinet/sctp_asconf.c b/freebsd/sys/netinet/sctp_asconf.c
index 206cf600..206cf600 100644
--- a/freebsd/netinet/sctp_asconf.c
+++ b/freebsd/sys/netinet/sctp_asconf.c
diff --git a/freebsd/netinet/sctp_asconf.h b/freebsd/sys/netinet/sctp_asconf.h
index ff8cf378..ff8cf378 100644
--- a/freebsd/netinet/sctp_asconf.h
+++ b/freebsd/sys/netinet/sctp_asconf.h
diff --git a/freebsd/netinet/sctp_auth.c b/freebsd/sys/netinet/sctp_auth.c
index 6c2bf908..6c2bf908 100644
--- a/freebsd/netinet/sctp_auth.c
+++ b/freebsd/sys/netinet/sctp_auth.c
diff --git a/freebsd/netinet/sctp_auth.h b/freebsd/sys/netinet/sctp_auth.h
index da4dc09b..da4dc09b 100644
--- a/freebsd/netinet/sctp_auth.h
+++ b/freebsd/sys/netinet/sctp_auth.h
diff --git a/freebsd/netinet/sctp_bsd_addr.c b/freebsd/sys/netinet/sctp_bsd_addr.c
index 8782e681..8782e681 100644
--- a/freebsd/netinet/sctp_bsd_addr.c
+++ b/freebsd/sys/netinet/sctp_bsd_addr.c
diff --git a/freebsd/netinet/sctp_bsd_addr.h b/freebsd/sys/netinet/sctp_bsd_addr.h
index 67d65dc6..67d65dc6 100644
--- a/freebsd/netinet/sctp_bsd_addr.h
+++ b/freebsd/sys/netinet/sctp_bsd_addr.h
diff --git a/freebsd/netinet/sctp_cc_functions.c b/freebsd/sys/netinet/sctp_cc_functions.c
index 668fd673..668fd673 100644
--- a/freebsd/netinet/sctp_cc_functions.c
+++ b/freebsd/sys/netinet/sctp_cc_functions.c
diff --git a/freebsd/netinet/sctp_cc_functions.h b/freebsd/sys/netinet/sctp_cc_functions.h
index 3b95d7de..3b95d7de 100644
--- a/freebsd/netinet/sctp_cc_functions.h
+++ b/freebsd/sys/netinet/sctp_cc_functions.h
diff --git a/freebsd/netinet/sctp_constants.h b/freebsd/sys/netinet/sctp_constants.h
index c4f4be23..c4f4be23 100644
--- a/freebsd/netinet/sctp_constants.h
+++ b/freebsd/sys/netinet/sctp_constants.h
diff --git a/freebsd/netinet/sctp_crc32.c b/freebsd/sys/netinet/sctp_crc32.c
index aa4c08cf..aa4c08cf 100644
--- a/freebsd/netinet/sctp_crc32.c
+++ b/freebsd/sys/netinet/sctp_crc32.c
diff --git a/freebsd/netinet/sctp_crc32.h b/freebsd/sys/netinet/sctp_crc32.h
index 768b25d5..768b25d5 100644
--- a/freebsd/netinet/sctp_crc32.h
+++ b/freebsd/sys/netinet/sctp_crc32.h
diff --git a/freebsd/netinet/sctp_header.h b/freebsd/sys/netinet/sctp_header.h
index 141bfcda..141bfcda 100644
--- a/freebsd/netinet/sctp_header.h
+++ b/freebsd/sys/netinet/sctp_header.h
diff --git a/freebsd/netinet/sctp_indata.c b/freebsd/sys/netinet/sctp_indata.c
index 963b3205..963b3205 100644
--- a/freebsd/netinet/sctp_indata.c
+++ b/freebsd/sys/netinet/sctp_indata.c
diff --git a/freebsd/netinet/sctp_indata.h b/freebsd/sys/netinet/sctp_indata.h
index a231ecaf..a231ecaf 100644
--- a/freebsd/netinet/sctp_indata.h
+++ b/freebsd/sys/netinet/sctp_indata.h
diff --git a/freebsd/netinet/sctp_input.c b/freebsd/sys/netinet/sctp_input.c
index 080813b4..080813b4 100644
--- a/freebsd/netinet/sctp_input.c
+++ b/freebsd/sys/netinet/sctp_input.c
diff --git a/freebsd/netinet/sctp_input.h b/freebsd/sys/netinet/sctp_input.h
index 90cd098a..90cd098a 100644
--- a/freebsd/netinet/sctp_input.h
+++ b/freebsd/sys/netinet/sctp_input.h
diff --git a/freebsd/netinet/sctp_lock_bsd.h b/freebsd/sys/netinet/sctp_lock_bsd.h
index 81e4a35f..81e4a35f 100644
--- a/freebsd/netinet/sctp_lock_bsd.h
+++ b/freebsd/sys/netinet/sctp_lock_bsd.h
diff --git a/freebsd/netinet/sctp_os.h b/freebsd/sys/netinet/sctp_os.h
index c1a392f0..c1a392f0 100644
--- a/freebsd/netinet/sctp_os.h
+++ b/freebsd/sys/netinet/sctp_os.h
diff --git a/freebsd/netinet/sctp_os_bsd.h b/freebsd/sys/netinet/sctp_os_bsd.h
index cf29776f..cf29776f 100644
--- a/freebsd/netinet/sctp_os_bsd.h
+++ b/freebsd/sys/netinet/sctp_os_bsd.h
diff --git a/freebsd/netinet/sctp_output.c b/freebsd/sys/netinet/sctp_output.c
index 9acd3288..9acd3288 100644
--- a/freebsd/netinet/sctp_output.c
+++ b/freebsd/sys/netinet/sctp_output.c
diff --git a/freebsd/netinet/sctp_output.h b/freebsd/sys/netinet/sctp_output.h
index d9051ee7..d9051ee7 100644
--- a/freebsd/netinet/sctp_output.h
+++ b/freebsd/sys/netinet/sctp_output.h
diff --git a/freebsd/netinet/sctp_pcb.c b/freebsd/sys/netinet/sctp_pcb.c
index fccbda00..fccbda00 100644
--- a/freebsd/netinet/sctp_pcb.c
+++ b/freebsd/sys/netinet/sctp_pcb.c
diff --git a/freebsd/netinet/sctp_pcb.h b/freebsd/sys/netinet/sctp_pcb.h
index a4f4d30c..a4f4d30c 100644
--- a/freebsd/netinet/sctp_pcb.h
+++ b/freebsd/sys/netinet/sctp_pcb.h
diff --git a/freebsd/netinet/sctp_peeloff.c b/freebsd/sys/netinet/sctp_peeloff.c
index 7b859bba..7b859bba 100644
--- a/freebsd/netinet/sctp_peeloff.c
+++ b/freebsd/sys/netinet/sctp_peeloff.c
diff --git a/freebsd/netinet/sctp_peeloff.h b/freebsd/sys/netinet/sctp_peeloff.h
index 57fd5fef..57fd5fef 100644
--- a/freebsd/netinet/sctp_peeloff.h
+++ b/freebsd/sys/netinet/sctp_peeloff.h
diff --git a/freebsd/netinet/sctp_structs.h b/freebsd/sys/netinet/sctp_structs.h
index 2050c581..2050c581 100644
--- a/freebsd/netinet/sctp_structs.h
+++ b/freebsd/sys/netinet/sctp_structs.h
diff --git a/freebsd/netinet/sctp_sysctl.c b/freebsd/sys/netinet/sctp_sysctl.c
index b5700e4e..b5700e4e 100644
--- a/freebsd/netinet/sctp_sysctl.c
+++ b/freebsd/sys/netinet/sctp_sysctl.c
diff --git a/freebsd/netinet/sctp_sysctl.h b/freebsd/sys/netinet/sctp_sysctl.h
index 5f7f270d..5f7f270d 100644
--- a/freebsd/netinet/sctp_sysctl.h
+++ b/freebsd/sys/netinet/sctp_sysctl.h
diff --git a/freebsd/netinet/sctp_timer.c b/freebsd/sys/netinet/sctp_timer.c
index 090689b1..090689b1 100644
--- a/freebsd/netinet/sctp_timer.c
+++ b/freebsd/sys/netinet/sctp_timer.c
diff --git a/freebsd/netinet/sctp_timer.h b/freebsd/sys/netinet/sctp_timer.h
index 34abbace..34abbace 100644
--- a/freebsd/netinet/sctp_timer.h
+++ b/freebsd/sys/netinet/sctp_timer.h
diff --git a/freebsd/netinet/sctp_uio.h b/freebsd/sys/netinet/sctp_uio.h
index 734447ed..734447ed 100644
--- a/freebsd/netinet/sctp_uio.h
+++ b/freebsd/sys/netinet/sctp_uio.h
diff --git a/freebsd/netinet/sctp_usrreq.c b/freebsd/sys/netinet/sctp_usrreq.c
index bb60795c..bb60795c 100644
--- a/freebsd/netinet/sctp_usrreq.c
+++ b/freebsd/sys/netinet/sctp_usrreq.c
diff --git a/freebsd/netinet/sctp_var.h b/freebsd/sys/netinet/sctp_var.h
index 93b92038..93b92038 100644
--- a/freebsd/netinet/sctp_var.h
+++ b/freebsd/sys/netinet/sctp_var.h
diff --git a/freebsd/netinet/sctputil.c b/freebsd/sys/netinet/sctputil.c
index 7e8ac1ea..7e8ac1ea 100644
--- a/freebsd/netinet/sctputil.c
+++ b/freebsd/sys/netinet/sctputil.c
diff --git a/freebsd/netinet/sctputil.h b/freebsd/sys/netinet/sctputil.h
index b1bee3a4..b1bee3a4 100644
--- a/freebsd/netinet/sctputil.h
+++ b/freebsd/sys/netinet/sctputil.h
diff --git a/freebsd/sys/netinet/tcp.h b/freebsd/sys/netinet/tcp.h
new file mode 100644
index 00000000..19b1c57f
--- /dev/null
+++ b/freebsd/sys/netinet/tcp.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/tcp.h>
diff --git a/freebsd/netinet/tcp_debug.c b/freebsd/sys/netinet/tcp_debug.c
index 52a82193..52a82193 100644
--- a/freebsd/netinet/tcp_debug.c
+++ b/freebsd/sys/netinet/tcp_debug.c
diff --git a/freebsd/netinet/tcp_debug.h b/freebsd/sys/netinet/tcp_debug.h
index 0c103958..0c103958 100644
--- a/freebsd/netinet/tcp_debug.h
+++ b/freebsd/sys/netinet/tcp_debug.h
diff --git a/freebsd/netinet/tcp_fsm.h b/freebsd/sys/netinet/tcp_fsm.h
index 253e53d4..253e53d4 100644
--- a/freebsd/netinet/tcp_fsm.h
+++ b/freebsd/sys/netinet/tcp_fsm.h
diff --git a/freebsd/netinet/tcp_hostcache.c b/freebsd/sys/netinet/tcp_hostcache.c
index 07b78cfe..07b78cfe 100644
--- a/freebsd/netinet/tcp_hostcache.c
+++ b/freebsd/sys/netinet/tcp_hostcache.c
diff --git a/freebsd/netinet/tcp_hostcache.h b/freebsd/sys/netinet/tcp_hostcache.h
index a494ed03..a494ed03 100644
--- a/freebsd/netinet/tcp_hostcache.h
+++ b/freebsd/sys/netinet/tcp_hostcache.h
diff --git a/freebsd/netinet/tcp_input.c b/freebsd/sys/netinet/tcp_input.c
index 85daf203..85daf203 100644
--- a/freebsd/netinet/tcp_input.c
+++ b/freebsd/sys/netinet/tcp_input.c
diff --git a/freebsd/netinet/tcp_lro.c b/freebsd/sys/netinet/tcp_lro.c
index 6aaff4a5..6aaff4a5 100644
--- a/freebsd/netinet/tcp_lro.c
+++ b/freebsd/sys/netinet/tcp_lro.c
diff --git a/freebsd/netinet/tcp_lro.h b/freebsd/sys/netinet/tcp_lro.h
index 20cfb7cf..20cfb7cf 100644
--- a/freebsd/netinet/tcp_lro.h
+++ b/freebsd/sys/netinet/tcp_lro.h
diff --git a/freebsd/netinet/tcp_offload.c b/freebsd/sys/netinet/tcp_offload.c
index 9c73992b..9c73992b 100644
--- a/freebsd/netinet/tcp_offload.c
+++ b/freebsd/sys/netinet/tcp_offload.c
diff --git a/freebsd/netinet/tcp_offload.h b/freebsd/sys/netinet/tcp_offload.h
index f2a35a58..f2a35a58 100644
--- a/freebsd/netinet/tcp_offload.h
+++ b/freebsd/sys/netinet/tcp_offload.h
diff --git a/freebsd/netinet/tcp_output.c b/freebsd/sys/netinet/tcp_output.c
index bebab1f1..bebab1f1 100644
--- a/freebsd/netinet/tcp_output.c
+++ b/freebsd/sys/netinet/tcp_output.c
diff --git a/freebsd/netinet/tcp_reass.c b/freebsd/sys/netinet/tcp_reass.c
index aea58740..aea58740 100644
--- a/freebsd/netinet/tcp_reass.c
+++ b/freebsd/sys/netinet/tcp_reass.c
diff --git a/freebsd/netinet/tcp_sack.c b/freebsd/sys/netinet/tcp_sack.c
index 94bae57b..94bae57b 100644
--- a/freebsd/netinet/tcp_sack.c
+++ b/freebsd/sys/netinet/tcp_sack.c
diff --git a/freebsd/netinet/tcp_seq.h b/freebsd/sys/netinet/tcp_seq.h
index 8af7b0ab..8af7b0ab 100644
--- a/freebsd/netinet/tcp_seq.h
+++ b/freebsd/sys/netinet/tcp_seq.h
diff --git a/freebsd/netinet/tcp_subr.c b/freebsd/sys/netinet/tcp_subr.c
index 83777450..83777450 100644
--- a/freebsd/netinet/tcp_subr.c
+++ b/freebsd/sys/netinet/tcp_subr.c
diff --git a/freebsd/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index 78790cc8..78790cc8 100644
--- a/freebsd/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
diff --git a/freebsd/netinet/tcp_syncache.h b/freebsd/sys/netinet/tcp_syncache.h
index 96ba1535..96ba1535 100644
--- a/freebsd/netinet/tcp_syncache.h
+++ b/freebsd/sys/netinet/tcp_syncache.h
diff --git a/freebsd/netinet/tcp_timer.c b/freebsd/sys/netinet/tcp_timer.c
index 36e2bec2..36e2bec2 100644
--- a/freebsd/netinet/tcp_timer.c
+++ b/freebsd/sys/netinet/tcp_timer.c
diff --git a/freebsd/netinet/tcp_timer.h b/freebsd/sys/netinet/tcp_timer.h
index 1514a293..1514a293 100644
--- a/freebsd/netinet/tcp_timer.h
+++ b/freebsd/sys/netinet/tcp_timer.h
diff --git a/freebsd/netinet/tcp_timewait.c b/freebsd/sys/netinet/tcp_timewait.c
index 92643d0a..92643d0a 100644
--- a/freebsd/netinet/tcp_timewait.c
+++ b/freebsd/sys/netinet/tcp_timewait.c
diff --git a/freebsd/netinet/tcp_usrreq.c b/freebsd/sys/netinet/tcp_usrreq.c
index fc083e05..fc083e05 100644
--- a/freebsd/netinet/tcp_usrreq.c
+++ b/freebsd/sys/netinet/tcp_usrreq.c
diff --git a/freebsd/netinet/tcp_var.h b/freebsd/sys/netinet/tcp_var.h
index 77586144..77586144 100644
--- a/freebsd/netinet/tcp_var.h
+++ b/freebsd/sys/netinet/tcp_var.h
diff --git a/freebsd/netinet/tcpip.h b/freebsd/sys/netinet/tcpip.h
index 337c07a6..337c07a6 100644
--- a/freebsd/netinet/tcpip.h
+++ b/freebsd/sys/netinet/tcpip.h
diff --git a/freebsd/netinet/toedev.h b/freebsd/sys/netinet/toedev.h
index 4623845c..4623845c 100644
--- a/freebsd/netinet/toedev.h
+++ b/freebsd/sys/netinet/toedev.h
diff --git a/freebsd/sys/netinet/udp.h b/freebsd/sys/netinet/udp.h
new file mode 100644
index 00000000..e7010ac5
--- /dev/null
+++ b/freebsd/sys/netinet/udp.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/netinet/udp.h>
diff --git a/freebsd/netinet/udp_usrreq.c b/freebsd/sys/netinet/udp_usrreq.c
index f992f5f6..f992f5f6 100644
--- a/freebsd/netinet/udp_usrreq.c
+++ b/freebsd/sys/netinet/udp_usrreq.c
diff --git a/freebsd/netinet/udp_var.h b/freebsd/sys/netinet/udp_var.h
index 0bff6ea9..0bff6ea9 100644
--- a/freebsd/netinet/udp_var.h
+++ b/freebsd/sys/netinet/udp_var.h
diff --git a/freebsd/netinet6/dest6.c b/freebsd/sys/netinet6/dest6.c
index 6774dc86..6774dc86 100644
--- a/freebsd/netinet6/dest6.c
+++ b/freebsd/sys/netinet6/dest6.c
diff --git a/freebsd/netinet6/frag6.c b/freebsd/sys/netinet6/frag6.c
index bdb0f198..bdb0f198 100644
--- a/freebsd/netinet6/frag6.c
+++ b/freebsd/sys/netinet6/frag6.c
diff --git a/freebsd/netinet6/icmp6.c b/freebsd/sys/netinet6/icmp6.c
index 3df7f7b1..3df7f7b1 100644
--- a/freebsd/netinet6/icmp6.c
+++ b/freebsd/sys/netinet6/icmp6.c
diff --git a/freebsd/netinet6/icmp6.h b/freebsd/sys/netinet6/icmp6.h
index a6414efc..a6414efc 100644
--- a/freebsd/netinet6/icmp6.h
+++ b/freebsd/sys/netinet6/icmp6.h
diff --git a/freebsd/netinet6/in6.c b/freebsd/sys/netinet6/in6.c
index 826213af..826213af 100644
--- a/freebsd/netinet6/in6.c
+++ b/freebsd/sys/netinet6/in6.c
diff --git a/freebsd/netinet6/in6.h b/freebsd/sys/netinet6/in6.h
index 8d241116..8d241116 100644
--- a/freebsd/netinet6/in6.h
+++ b/freebsd/sys/netinet6/in6.h
diff --git a/freebsd/netinet6/in6_cksum.c b/freebsd/sys/netinet6/in6_cksum.c
index 1bd215b9..1bd215b9 100644
--- a/freebsd/netinet6/in6_cksum.c
+++ b/freebsd/sys/netinet6/in6_cksum.c
diff --git a/freebsd/netinet6/in6_gif.c b/freebsd/sys/netinet6/in6_gif.c
index 482181db..482181db 100644
--- a/freebsd/netinet6/in6_gif.c
+++ b/freebsd/sys/netinet6/in6_gif.c
diff --git a/freebsd/netinet6/in6_gif.h b/freebsd/sys/netinet6/in6_gif.h
index ed566112..ed566112 100644
--- a/freebsd/netinet6/in6_gif.h
+++ b/freebsd/sys/netinet6/in6_gif.h
diff --git a/freebsd/netinet6/in6_ifattach.c b/freebsd/sys/netinet6/in6_ifattach.c
index 7942d5af..7942d5af 100644
--- a/freebsd/netinet6/in6_ifattach.c
+++ b/freebsd/sys/netinet6/in6_ifattach.c
diff --git a/freebsd/netinet6/in6_ifattach.h b/freebsd/sys/netinet6/in6_ifattach.h
index d7db4e47..d7db4e47 100644
--- a/freebsd/netinet6/in6_ifattach.h
+++ b/freebsd/sys/netinet6/in6_ifattach.h
diff --git a/freebsd/netinet6/in6_mcast.c b/freebsd/sys/netinet6/in6_mcast.c
index a75a4ed3..a75a4ed3 100644
--- a/freebsd/netinet6/in6_mcast.c
+++ b/freebsd/sys/netinet6/in6_mcast.c
diff --git a/freebsd/netinet6/in6_pcb.c b/freebsd/sys/netinet6/in6_pcb.c
index 5faccefd..5faccefd 100644
--- a/freebsd/netinet6/in6_pcb.c
+++ b/freebsd/sys/netinet6/in6_pcb.c
diff --git a/freebsd/netinet6/in6_pcb.h b/freebsd/sys/netinet6/in6_pcb.h
index abc4a318..abc4a318 100644
--- a/freebsd/netinet6/in6_pcb.h
+++ b/freebsd/sys/netinet6/in6_pcb.h
diff --git a/freebsd/netinet6/in6_proto.c b/freebsd/sys/netinet6/in6_proto.c
index 0cd0858d..0cd0858d 100644
--- a/freebsd/netinet6/in6_proto.c
+++ b/freebsd/sys/netinet6/in6_proto.c
diff --git a/freebsd/netinet6/in6_rmx.c b/freebsd/sys/netinet6/in6_rmx.c
index de867c36..de867c36 100644
--- a/freebsd/netinet6/in6_rmx.c
+++ b/freebsd/sys/netinet6/in6_rmx.c
diff --git a/freebsd/netinet6/in6_src.c b/freebsd/sys/netinet6/in6_src.c
index a3914c3f..a3914c3f 100644
--- a/freebsd/netinet6/in6_src.c
+++ b/freebsd/sys/netinet6/in6_src.c
diff --git a/freebsd/netinet6/in6_var.h b/freebsd/sys/netinet6/in6_var.h
index f77a3271..f77a3271 100644
--- a/freebsd/netinet6/in6_var.h
+++ b/freebsd/sys/netinet6/in6_var.h
diff --git a/freebsd/netinet6/ip6.h b/freebsd/sys/netinet6/ip6.h
index 9eec13fb..9eec13fb 100644
--- a/freebsd/netinet6/ip6.h
+++ b/freebsd/sys/netinet6/ip6.h
diff --git a/freebsd/netinet6/ip6_ecn.h b/freebsd/sys/netinet6/ip6_ecn.h
index 27d3f34d..27d3f34d 100644
--- a/freebsd/netinet6/ip6_ecn.h
+++ b/freebsd/sys/netinet6/ip6_ecn.h
diff --git a/freebsd/netinet6/ip6_forward.c b/freebsd/sys/netinet6/ip6_forward.c
index f1d19737..f1d19737 100644
--- a/freebsd/netinet6/ip6_forward.c
+++ b/freebsd/sys/netinet6/ip6_forward.c
diff --git a/freebsd/netinet6/ip6_id.c b/freebsd/sys/netinet6/ip6_id.c
index 090e66fa..090e66fa 100644
--- a/freebsd/netinet6/ip6_id.c
+++ b/freebsd/sys/netinet6/ip6_id.c
diff --git a/freebsd/netinet6/ip6_input.c b/freebsd/sys/netinet6/ip6_input.c
index 323bb2a8..323bb2a8 100644
--- a/freebsd/netinet6/ip6_input.c
+++ b/freebsd/sys/netinet6/ip6_input.c
diff --git a/freebsd/netinet6/ip6_ipsec.c b/freebsd/sys/netinet6/ip6_ipsec.c
index a50c22c5..a50c22c5 100644
--- a/freebsd/netinet6/ip6_ipsec.c
+++ b/freebsd/sys/netinet6/ip6_ipsec.c
diff --git a/freebsd/netinet6/ip6_ipsec.h b/freebsd/sys/netinet6/ip6_ipsec.h
index e3049534..e3049534 100644
--- a/freebsd/netinet6/ip6_ipsec.h
+++ b/freebsd/sys/netinet6/ip6_ipsec.h
diff --git a/freebsd/netinet6/ip6_mroute.c b/freebsd/sys/netinet6/ip6_mroute.c
index 661cd1c0..661cd1c0 100644
--- a/freebsd/netinet6/ip6_mroute.c
+++ b/freebsd/sys/netinet6/ip6_mroute.c
diff --git a/freebsd/netinet6/ip6_mroute.h b/freebsd/sys/netinet6/ip6_mroute.h
index 198659fa..198659fa 100644
--- a/freebsd/netinet6/ip6_mroute.h
+++ b/freebsd/sys/netinet6/ip6_mroute.h
diff --git a/freebsd/netinet6/ip6_output.c b/freebsd/sys/netinet6/ip6_output.c
index 0d762cc0..0d762cc0 100644
--- a/freebsd/netinet6/ip6_output.c
+++ b/freebsd/sys/netinet6/ip6_output.c
diff --git a/freebsd/netinet6/ip6_var.h b/freebsd/sys/netinet6/ip6_var.h
index 50d8adcb..50d8adcb 100644
--- a/freebsd/netinet6/ip6_var.h
+++ b/freebsd/sys/netinet6/ip6_var.h
diff --git a/freebsd/netinet6/ip6protosw.h b/freebsd/sys/netinet6/ip6protosw.h
index ebb38c8d..ebb38c8d 100644
--- a/freebsd/netinet6/ip6protosw.h
+++ b/freebsd/sys/netinet6/ip6protosw.h
diff --git a/freebsd/netinet6/mld6.c b/freebsd/sys/netinet6/mld6.c
index a08f0f16..a08f0f16 100644
--- a/freebsd/netinet6/mld6.c
+++ b/freebsd/sys/netinet6/mld6.c
diff --git a/freebsd/netinet6/mld6.h b/freebsd/sys/netinet6/mld6.h
index 1839b4f7..1839b4f7 100644
--- a/freebsd/netinet6/mld6.h
+++ b/freebsd/sys/netinet6/mld6.h
diff --git a/freebsd/netinet6/mld6_var.h b/freebsd/sys/netinet6/mld6_var.h
index 40d70e51..40d70e51 100644
--- a/freebsd/netinet6/mld6_var.h
+++ b/freebsd/sys/netinet6/mld6_var.h
diff --git a/freebsd/netinet6/nd6.c b/freebsd/sys/netinet6/nd6.c
index bc7ed57e..bc7ed57e 100644
--- a/freebsd/netinet6/nd6.c
+++ b/freebsd/sys/netinet6/nd6.c
diff --git a/freebsd/netinet6/nd6.h b/freebsd/sys/netinet6/nd6.h
index 2da061df..2da061df 100644
--- a/freebsd/netinet6/nd6.h
+++ b/freebsd/sys/netinet6/nd6.h
diff --git a/freebsd/netinet6/nd6_nbr.c b/freebsd/sys/netinet6/nd6_nbr.c
index 44dd3cf1..44dd3cf1 100644
--- a/freebsd/netinet6/nd6_nbr.c
+++ b/freebsd/sys/netinet6/nd6_nbr.c
diff --git a/freebsd/netinet6/nd6_rtr.c b/freebsd/sys/netinet6/nd6_rtr.c
index 97aa15fb..97aa15fb 100644
--- a/freebsd/netinet6/nd6_rtr.c
+++ b/freebsd/sys/netinet6/nd6_rtr.c
diff --git a/freebsd/netinet6/pim6.h b/freebsd/sys/netinet6/pim6.h
index dec84cf2..dec84cf2 100644
--- a/freebsd/netinet6/pim6.h
+++ b/freebsd/sys/netinet6/pim6.h
diff --git a/freebsd/netinet6/pim6_var.h b/freebsd/sys/netinet6/pim6_var.h
index 8c63b5cc..8c63b5cc 100644
--- a/freebsd/netinet6/pim6_var.h
+++ b/freebsd/sys/netinet6/pim6_var.h
diff --git a/freebsd/netinet6/raw_ip6.c b/freebsd/sys/netinet6/raw_ip6.c
index 71a8add8..71a8add8 100644
--- a/freebsd/netinet6/raw_ip6.c
+++ b/freebsd/sys/netinet6/raw_ip6.c
diff --git a/freebsd/netinet6/raw_ip6.h b/freebsd/sys/netinet6/raw_ip6.h
index c4491d01..c4491d01 100644
--- a/freebsd/netinet6/raw_ip6.h
+++ b/freebsd/sys/netinet6/raw_ip6.h
diff --git a/freebsd/netinet6/route6.c b/freebsd/sys/netinet6/route6.c
index 72ad9fae..72ad9fae 100644
--- a/freebsd/netinet6/route6.c
+++ b/freebsd/sys/netinet6/route6.c
diff --git a/freebsd/netinet6/scope6.c b/freebsd/sys/netinet6/scope6.c
index d9a19d56..d9a19d56 100644
--- a/freebsd/netinet6/scope6.c
+++ b/freebsd/sys/netinet6/scope6.c
diff --git a/freebsd/netinet6/scope6_var.h b/freebsd/sys/netinet6/scope6_var.h
index a87aa57c..a87aa57c 100644
--- a/freebsd/netinet6/scope6_var.h
+++ b/freebsd/sys/netinet6/scope6_var.h
diff --git a/freebsd/netinet6/sctp6_usrreq.c b/freebsd/sys/netinet6/sctp6_usrreq.c
index 178f0d84..178f0d84 100644
--- a/freebsd/netinet6/sctp6_usrreq.c
+++ b/freebsd/sys/netinet6/sctp6_usrreq.c
diff --git a/freebsd/netinet6/sctp6_var.h b/freebsd/sys/netinet6/sctp6_var.h
index b692fdbd..b692fdbd 100644
--- a/freebsd/netinet6/sctp6_var.h
+++ b/freebsd/sys/netinet6/sctp6_var.h
diff --git a/freebsd/netinet6/tcp6_var.h b/freebsd/sys/netinet6/tcp6_var.h
index e0373b3d..e0373b3d 100644
--- a/freebsd/netinet6/tcp6_var.h
+++ b/freebsd/sys/netinet6/tcp6_var.h
diff --git a/freebsd/netinet6/udp6_usrreq.c b/freebsd/sys/netinet6/udp6_usrreq.c
index 735c795b..735c795b 100644
--- a/freebsd/netinet6/udp6_usrreq.c
+++ b/freebsd/sys/netinet6/udp6_usrreq.c
diff --git a/freebsd/netinet6/udp6_var.h b/freebsd/sys/netinet6/udp6_var.h
index f52503cd..f52503cd 100644
--- a/freebsd/netinet6/udp6_var.h
+++ b/freebsd/sys/netinet6/udp6_var.h
diff --git a/freebsd/netipsec/ah.h b/freebsd/sys/netipsec/ah.h
index 6a35089b..6a35089b 100644
--- a/freebsd/netipsec/ah.h
+++ b/freebsd/sys/netipsec/ah.h
diff --git a/freebsd/netipsec/ah_var.h b/freebsd/sys/netipsec/ah_var.h
index f82ea401..f82ea401 100644
--- a/freebsd/netipsec/ah_var.h
+++ b/freebsd/sys/netipsec/ah_var.h
diff --git a/freebsd/netipsec/esp.h b/freebsd/sys/netipsec/esp.h
index 282883b2..282883b2 100644
--- a/freebsd/netipsec/esp.h
+++ b/freebsd/sys/netipsec/esp.h
diff --git a/freebsd/netipsec/esp_var.h b/freebsd/sys/netipsec/esp_var.h
index eda4033b..eda4033b 100644
--- a/freebsd/netipsec/esp_var.h
+++ b/freebsd/sys/netipsec/esp_var.h
diff --git a/freebsd/netipsec/ipcomp.h b/freebsd/sys/netipsec/ipcomp.h
index a43bf2e8..a43bf2e8 100644
--- a/freebsd/netipsec/ipcomp.h
+++ b/freebsd/sys/netipsec/ipcomp.h
diff --git a/freebsd/netipsec/ipcomp_var.h b/freebsd/sys/netipsec/ipcomp_var.h
index bf4598f4..bf4598f4 100644
--- a/freebsd/netipsec/ipcomp_var.h
+++ b/freebsd/sys/netipsec/ipcomp_var.h
diff --git a/freebsd/netipsec/ipip_var.h b/freebsd/sys/netipsec/ipip_var.h
index 51d8a554..51d8a554 100644
--- a/freebsd/netipsec/ipip_var.h
+++ b/freebsd/sys/netipsec/ipip_var.h
diff --git a/freebsd/netipsec/ipsec.c b/freebsd/sys/netipsec/ipsec.c
index 95aefca3..95aefca3 100644
--- a/freebsd/netipsec/ipsec.c
+++ b/freebsd/sys/netipsec/ipsec.c
diff --git a/freebsd/netipsec/ipsec.h b/freebsd/sys/netipsec/ipsec.h
index ca9a52f3..ca9a52f3 100644
--- a/freebsd/netipsec/ipsec.h
+++ b/freebsd/sys/netipsec/ipsec.h
diff --git a/freebsd/netipsec/ipsec6.h b/freebsd/sys/netipsec/ipsec6.h
index 7213fce7..7213fce7 100644
--- a/freebsd/netipsec/ipsec6.h
+++ b/freebsd/sys/netipsec/ipsec6.h
diff --git a/freebsd/netipsec/ipsec_input.c b/freebsd/sys/netipsec/ipsec_input.c
index d8714348..d8714348 100644
--- a/freebsd/netipsec/ipsec_input.c
+++ b/freebsd/sys/netipsec/ipsec_input.c
diff --git a/freebsd/netipsec/ipsec_mbuf.c b/freebsd/sys/netipsec/ipsec_mbuf.c
index f888e60d..f888e60d 100644
--- a/freebsd/netipsec/ipsec_mbuf.c
+++ b/freebsd/sys/netipsec/ipsec_mbuf.c
diff --git a/freebsd/netipsec/ipsec_output.c b/freebsd/sys/netipsec/ipsec_output.c
index 5fdaa0e5..5fdaa0e5 100644
--- a/freebsd/netipsec/ipsec_output.c
+++ b/freebsd/sys/netipsec/ipsec_output.c
diff --git a/freebsd/netipsec/key.c b/freebsd/sys/netipsec/key.c
index 1bf41660..1bf41660 100644
--- a/freebsd/netipsec/key.c
+++ b/freebsd/sys/netipsec/key.c
diff --git a/freebsd/netipsec/key.h b/freebsd/sys/netipsec/key.h
index 4d2b3083..4d2b3083 100644
--- a/freebsd/netipsec/key.h
+++ b/freebsd/sys/netipsec/key.h
diff --git a/freebsd/netipsec/key_debug.c b/freebsd/sys/netipsec/key_debug.c
index b8d909b3..b8d909b3 100644
--- a/freebsd/netipsec/key_debug.c
+++ b/freebsd/sys/netipsec/key_debug.c
diff --git a/freebsd/netipsec/key_debug.h b/freebsd/sys/netipsec/key_debug.h
index 26dfdbcf..26dfdbcf 100644
--- a/freebsd/netipsec/key_debug.h
+++ b/freebsd/sys/netipsec/key_debug.h
diff --git a/freebsd/netipsec/key_var.h b/freebsd/sys/netipsec/key_var.h
index 127b6abf..127b6abf 100644
--- a/freebsd/netipsec/key_var.h
+++ b/freebsd/sys/netipsec/key_var.h
diff --git a/freebsd/netipsec/keydb.h b/freebsd/sys/netipsec/keydb.h
index 7fe8ab39..7fe8ab39 100644
--- a/freebsd/netipsec/keydb.h
+++ b/freebsd/sys/netipsec/keydb.h
diff --git a/freebsd/netipsec/keysock.c b/freebsd/sys/netipsec/keysock.c
index bd8d2170..bd8d2170 100644
--- a/freebsd/netipsec/keysock.c
+++ b/freebsd/sys/netipsec/keysock.c
diff --git a/freebsd/netipsec/keysock.h b/freebsd/sys/netipsec/keysock.h
index 2d147b7a..2d147b7a 100644
--- a/freebsd/netipsec/keysock.h
+++ b/freebsd/sys/netipsec/keysock.h
diff --git a/freebsd/netipsec/xform.h b/freebsd/sys/netipsec/xform.h
index d229e17d..d229e17d 100644
--- a/freebsd/netipsec/xform.h
+++ b/freebsd/sys/netipsec/xform.h
diff --git a/freebsd/netipsec/xform_ah.c b/freebsd/sys/netipsec/xform_ah.c
index 34014eef..34014eef 100644
--- a/freebsd/netipsec/xform_ah.c
+++ b/freebsd/sys/netipsec/xform_ah.c
diff --git a/freebsd/netipsec/xform_esp.c b/freebsd/sys/netipsec/xform_esp.c
index 3a550d17..3a550d17 100644
--- a/freebsd/netipsec/xform_esp.c
+++ b/freebsd/sys/netipsec/xform_esp.c
diff --git a/freebsd/netipsec/xform_ipcomp.c b/freebsd/sys/netipsec/xform_ipcomp.c
index a4a65953..a4a65953 100644
--- a/freebsd/netipsec/xform_ipcomp.c
+++ b/freebsd/sys/netipsec/xform_ipcomp.c
diff --git a/freebsd/netipsec/xform_ipip.c b/freebsd/sys/netipsec/xform_ipip.c
index cf89239a..cf89239a 100644
--- a/freebsd/netipsec/xform_ipip.c
+++ b/freebsd/sys/netipsec/xform_ipip.c
diff --git a/freebsd/netipsec/xform_tcp.c b/freebsd/sys/netipsec/xform_tcp.c
index 2b099639..2b099639 100644
--- a/freebsd/netipsec/xform_tcp.c
+++ b/freebsd/sys/netipsec/xform_tcp.c
diff --git a/freebsd/opencrypto/cast.c b/freebsd/sys/opencrypto/cast.c
index fde6352c..fde6352c 100644
--- a/freebsd/opencrypto/cast.c
+++ b/freebsd/sys/opencrypto/cast.c
diff --git a/freebsd/opencrypto/cast.h b/freebsd/sys/opencrypto/cast.h
index 25d6c763..25d6c763 100644
--- a/freebsd/opencrypto/cast.h
+++ b/freebsd/sys/opencrypto/cast.h
diff --git a/freebsd/opencrypto/castsb.h b/freebsd/sys/opencrypto/castsb.h
index ed13058c..ed13058c 100644
--- a/freebsd/opencrypto/castsb.h
+++ b/freebsd/sys/opencrypto/castsb.h
diff --git a/freebsd/opencrypto/criov.c b/freebsd/sys/opencrypto/criov.c
index 1e389c1d..1e389c1d 100644
--- a/freebsd/opencrypto/criov.c
+++ b/freebsd/sys/opencrypto/criov.c
diff --git a/freebsd/opencrypto/crypto.c b/freebsd/sys/opencrypto/crypto.c
index 597bbc94..597bbc94 100644
--- a/freebsd/opencrypto/crypto.c
+++ b/freebsd/sys/opencrypto/crypto.c
diff --git a/freebsd/opencrypto/cryptodev.c b/freebsd/sys/opencrypto/cryptodev.c
index fed4f5df..fed4f5df 100644
--- a/freebsd/opencrypto/cryptodev.c
+++ b/freebsd/sys/opencrypto/cryptodev.c
diff --git a/freebsd/opencrypto/cryptodev.h b/freebsd/sys/opencrypto/cryptodev.h
index 2ca71802..2ca71802 100644
--- a/freebsd/opencrypto/cryptodev.h
+++ b/freebsd/sys/opencrypto/cryptodev.h
diff --git a/freebsd/opencrypto/cryptosoft.c b/freebsd/sys/opencrypto/cryptosoft.c
index 69b2d656..69b2d656 100644
--- a/freebsd/opencrypto/cryptosoft.c
+++ b/freebsd/sys/opencrypto/cryptosoft.c
diff --git a/freebsd/opencrypto/cryptosoft.h b/freebsd/sys/opencrypto/cryptosoft.h
index 363fdbba..363fdbba 100644
--- a/freebsd/opencrypto/cryptosoft.h
+++ b/freebsd/sys/opencrypto/cryptosoft.h
diff --git a/freebsd/opencrypto/deflate.c b/freebsd/sys/opencrypto/deflate.c
index ddf8239e..ddf8239e 100644
--- a/freebsd/opencrypto/deflate.c
+++ b/freebsd/sys/opencrypto/deflate.c
diff --git a/freebsd/opencrypto/deflate.h b/freebsd/sys/opencrypto/deflate.h
index 732620b5..732620b5 100644
--- a/freebsd/opencrypto/deflate.h
+++ b/freebsd/sys/opencrypto/deflate.h
diff --git a/freebsd/opencrypto/rmd160.c b/freebsd/sys/opencrypto/rmd160.c
index 99f987ee..99f987ee 100644
--- a/freebsd/opencrypto/rmd160.c
+++ b/freebsd/sys/opencrypto/rmd160.c
diff --git a/freebsd/opencrypto/rmd160.h b/freebsd/sys/opencrypto/rmd160.h
index 60dce642..60dce642 100644
--- a/freebsd/opencrypto/rmd160.h
+++ b/freebsd/sys/opencrypto/rmd160.h
diff --git a/freebsd/opencrypto/skipjack.c b/freebsd/sys/opencrypto/skipjack.c
index ae06dc1b..ae06dc1b 100644
--- a/freebsd/opencrypto/skipjack.c
+++ b/freebsd/sys/opencrypto/skipjack.c
diff --git a/freebsd/opencrypto/skipjack.h b/freebsd/sys/opencrypto/skipjack.h
index 3e88418c..3e88418c 100644
--- a/freebsd/opencrypto/skipjack.h
+++ b/freebsd/sys/opencrypto/skipjack.h
diff --git a/freebsd/opencrypto/xform.c b/freebsd/sys/opencrypto/xform.c
index e54a6740..e54a6740 100644
--- a/freebsd/opencrypto/xform.c
+++ b/freebsd/sys/opencrypto/xform.c
diff --git a/freebsd/opencrypto/xform.h b/freebsd/sys/opencrypto/xform.h
index 7c70ca90..7c70ca90 100644
--- a/freebsd/opencrypto/xform.h
+++ b/freebsd/sys/opencrypto/xform.h
diff --git a/freebsd/sys/param.h b/freebsd/sys/param.h
deleted file mode 100644
index cd00ea4c..00000000
--- a/freebsd/sys/param.h
+++ /dev/null
@@ -1,332 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1989, 1993
- * The Regents of the University of California. All rights reserved.
- * (c) UNIX System Laboratories, Inc.
- * All or some portions of this file are derived from material licensed
- * to the University of California by American Telephone and Telegraph
- * Co. or Unix System Laboratories, Inc. and are reproduced herein with
- * the permission of UNIX System Laboratories, Inc.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)param.h 8.3 (Berkeley) 4/4/95
- * $FreeBSD$
- */
-
-#ifndef _SYS_PARAM_HH_
-#define _SYS_PARAM_HH_
-
-#include <freebsd/sys/_null.h>
-
-#define BSD 199506 /* System version (year & month). */
-#define BSD4_3 1
-#define BSD4_4 1
-
-/*
- * __FreeBSD_version numbers are documented in the Porter's Handbook.
- * If you bump the version for any reason, you should update the documentation
- * there.
- * Currently this lives here:
- *
- * doc/en_US.ISO8859-1/books/porters-handbook/book.sgml
- *
- * scheme is: <major><two digit minor>Rxx
- * 'R' is in the range 0 to 4 if this is a release branch or
- * x.0-CURRENT before RELENG_*_0 is created, otherwise 'R' is
- * in the range 5 to 9.
- */
-#undef __FreeBSD_version
-#define __FreeBSD_version 802000 /* Master, propagated to newvers */
-
-#ifdef _KERNEL
-#define P_OSREL_SIGSEGV 700004
-#define P_OSREL_MAP_ANON 800104
-#endif
-
-#ifndef LOCORE
-#include <freebsd/sys/types.h>
-#endif
-
-/*
- * Machine-independent constants (some used in following include files).
- * Redefined constants are from POSIX 1003.1 limits file.
- *
- * MAXCOMLEN should be >= sizeof(ac_comm) (see <acct.h>)
- * MAXLOGNAME should be == UT_NAMESIZE+1 (see <utmp.h>)
- */
-#include <freebsd/sys/syslimits.h>
-
-#define MAXCOMLEN 19 /* max command name remembered */
-#define MAXINTERP 32 /* max interpreter file name length */
-#define MAXLOGNAME 17 /* max login name length (incl. NUL) */
-#define MAXUPRC CHILD_MAX /* max simultaneous processes */
-#define NCARGS ARG_MAX /* max bytes for an exec function */
-#define NGROUPS (NGROUPS_MAX+1) /* max number groups */
-#define NOFILE OPEN_MAX /* max open files per process */
-#define NOGROUP 65535 /* marker for empty group set member */
-#define MAXHOSTNAMELEN 256 /* max hostname size */
-#define SPECNAMELEN 63 /* max length of devicename */
-
-/* More types and definitions used throughout the kernel. */
-#ifdef _KERNEL
-#include <freebsd/sys/cdefs.h>
-#include <freebsd/sys/errno.h>
-#ifndef LOCORE
-#include <freebsd/sys/time.h>
-#include <freebsd/sys/priority.h>
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef TRUE
-#define TRUE 1
-#endif
-#endif
-
-#ifndef _KERNEL
-/* Signals. */
-#include <freebsd/sys/signal.h>
-#endif
-
-/* Machine type dependent parameters. */
-#include <freebsd/machine/param.h>
-#ifndef _KERNEL
-#include <freebsd/sys/limits.h>
-#endif
-
-#ifndef _NO_NAMESPACE_POLLUTION
-
-#ifndef DEV_BSHIFT
-#define DEV_BSHIFT 9 /* log2(DEV_BSIZE) */
-#endif
-#define DEV_BSIZE (1<<DEV_BSHIFT)
-
-#ifndef BLKDEV_IOSIZE
-#define BLKDEV_IOSIZE PAGE_SIZE /* default block device I/O size */
-#endif
-#ifndef DFLTPHYS
-#define DFLTPHYS (64 * 1024) /* default max raw I/O transfer size */
-#endif
-#ifndef MAXPHYS
-#define MAXPHYS (128 * 1024) /* max raw I/O transfer size */
-#endif
-#ifndef MAXDUMPPGS
-#define MAXDUMPPGS (DFLTPHYS/PAGE_SIZE)
-#endif
-
-/*
- * Constants related to network buffer management.
- * MCLBYTES must be no larger than PAGE_SIZE.
- */
-#ifndef MSIZE
-#define MSIZE 256 /* size of an mbuf */
-#endif /* MSIZE */
-
-#ifndef MCLSHIFT
-#define MCLSHIFT 11 /* convert bytes to mbuf clusters */
-#endif /* MCLSHIFT */
-
-#define MCLBYTES (1 << MCLSHIFT) /* size of an mbuf cluster */
-
-#define MJUMPAGESIZE PAGE_SIZE /* jumbo cluster 4k */
-#define MJUM9BYTES (9 * 1024) /* jumbo cluster 9k */
-#define MJUM16BYTES (16 * 1024) /* jumbo cluster 16k */
-
-/*
- * Round p (pointer or byte index) up to a correctly-aligned value
- * for all data types (int, long, ...). The result is u_long and
- * must be cast to any desired pointer type.
- */
-#ifndef _ALIGNBYTES
-#define _ALIGNBYTES (sizeof(long) - 1)
-#endif
-#ifndef _ALIGN
-#define _ALIGN(p) (((uintptr_t)(p) + _ALIGNBYTES) &~ _ALIGNBYTES)
-#endif
-
-/*
- * Some macros for units conversion
- */
-
-/* clicks to bytes */
-#ifndef ctob
-#define ctob(x) ((x)<<PAGE_SHIFT)
-#endif
-
-/* bytes to clicks */
-#ifndef btoc
-#define btoc(x) (((vm_offset_t)(x)+PAGE_MASK)>>PAGE_SHIFT)
-#endif
-
-/*
- * btodb() is messy and perhaps slow because `bytes' may be an off_t. We
- * want to shift an unsigned type to avoid sign extension and we don't
- * want to widen `bytes' unnecessarily. Assume that the result fits in
- * a daddr_t.
- */
-#ifndef btodb
-#define btodb(bytes) /* calculates (bytes / DEV_BSIZE) */ \
- (sizeof (bytes) > sizeof(long) \
- ? (daddr_t)((unsigned long long)(bytes) >> DEV_BSHIFT) \
- : (daddr_t)((unsigned long)(bytes) >> DEV_BSHIFT))
-#endif
-
-#ifndef dbtob
-#define dbtob(db) /* calculates (db * DEV_BSIZE) */ \
- ((off_t)(db) << DEV_BSHIFT)
-#endif
-
-#endif /* _NO_NAMESPACE_POLLUTION */
-
-#define PRIMASK 0x0ff
-#define PCATCH 0x100 /* OR'd with pri for tsleep to check signals */
-#define PDROP 0x200 /* OR'd with pri to stop re-entry of interlock mutex */
-#define PBDRY 0x400 /* for PCATCH stop is done on the user boundary */
-
-#define NZERO 0 /* default "nice" */
-
-#define NBBY 8 /* number of bits in a byte */
-#define NBPW sizeof(int) /* number of bytes per word (integer) */
-
-#define CMASK 022 /* default file mask: S_IWGRP|S_IWOTH */
-
-#define NODEV (dev_t)(-1) /* non-existent device */
-
-/*
- * File system parameters and macros.
- *
- * MAXBSIZE - Filesystems are made out of blocks of at most MAXBSIZE bytes
- * per block. MAXBSIZE may be made larger without effecting
- * any existing filesystems as long as it does not exceed MAXPHYS,
- * and may be made smaller at the risk of not being able to use
- * filesystems which require a block size exceeding MAXBSIZE.
- *
- * BKVASIZE - Nominal buffer space per buffer, in bytes. BKVASIZE is the
- * minimum KVM memory reservation the kernel is willing to make.
- * Filesystems can of course request smaller chunks. Actual
- * backing memory uses a chunk size of a page (PAGE_SIZE).
- *
- * If you make BKVASIZE too small you risk seriously fragmenting
- * the buffer KVM map which may slow things down a bit. If you
- * make it too big the kernel will not be able to optimally use
- * the KVM memory reserved for the buffer cache and will wind
- * up with too-few buffers.
- *
- * The default is 16384, roughly 2x the block size used by a
- * normal UFS filesystem.
- */
-#define MAXBSIZE 65536 /* must be power of 2 */
-#define BKVASIZE 16384 /* must be power of 2 */
-#define BKVAMASK (BKVASIZE-1)
-
-/*
- * MAXPATHLEN defines the longest permissible path length after expanding
- * symbolic links. It is used to allocate a temporary buffer from the buffer
- * pool in which to do the name expansion, hence should be a power of two,
- * and must be less than or equal to MAXBSIZE. MAXSYMLINKS defines the
- * maximum number of symbolic links that may be expanded in a path name.
- * It should be set high enough to allow all legitimate uses, but halt
- * infinite loops reasonably quickly.
- */
-#define MAXPATHLEN PATH_MAX
-#define MAXSYMLINKS 32
-
-/* Bit map related macros. */
-#define setbit(a,i) (((unsigned char *)(a))[(i)/NBBY] |= 1<<((i)%NBBY))
-#define clrbit(a,i) (((unsigned char *)(a))[(i)/NBBY] &= ~(1<<((i)%NBBY)))
-#define isset(a,i) \
- (((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY)))
-#define isclr(a,i) \
- ((((const unsigned char *)(a))[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
-
-/* Macros for counting and rounding. */
-#ifndef howmany
-#define howmany(x, y) (((x)+((y)-1))/(y))
-#endif
-#define rounddown(x, y) (((x)/(y))*(y))
-#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
-#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
-#define powerof2(x) ((((x)-1)&(x))==0)
-
-/* Macros for min/max. */
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
-#ifdef _KERNEL
-/*
- * Basic byte order function prototypes for non-inline functions.
- */
-#ifndef LOCORE
-#ifndef _BYTEORDER_PROTOTYPED
-#define _BYTEORDER_PROTOTYPED
-__BEGIN_DECLS
-__uint32_t htonl(__uint32_t);
-__uint16_t htons(__uint16_t);
-__uint32_t ntohl(__uint32_t);
-__uint16_t ntohs(__uint16_t);
-__END_DECLS
-#endif
-#endif
-
-#ifndef lint
-#ifndef _BYTEORDER_FUNC_DEFINED
-#define _BYTEORDER_FUNC_DEFINED
-#define htonl(x) __htonl(x)
-#define htons(x) __htons(x)
-#define ntohl(x) __ntohl(x)
-#define ntohs(x) __ntohs(x)
-#endif /* !_BYTEORDER_FUNC_DEFINED */
-#endif /* lint */
-#endif /* _KERNEL */
-
-/*
- * Scale factor for scaled integers used to count %cpu time and load avgs.
- *
- * The number of CPU `tick's that map to a unique `%age' can be expressed
- * by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that
- * can be calculated (assuming 32 bits) can be closely approximated using
- * the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15).
- *
- * For the scheduler to maintain a 1:1 mapping of CPU `tick' to `%age',
- * FSHIFT must be at least 11; this gives us a maximum load avg of ~1024.
- */
-#define FSHIFT 11 /* bits to right of fixed binary point */
-#define FSCALE (1<<FSHIFT)
-
-#define dbtoc(db) /* calculates devblks to pages */ \
- ((db + (ctodb(1) - 1)) >> (PAGE_SHIFT - DEV_BSHIFT))
-
-#define ctodb(db) /* calculates pages to devblks */ \
- ((db) << (PAGE_SHIFT - DEV_BSHIFT))
-
-/*
- * Given the pointer x to the member m of the struct s, return
- * a pointer to the containing structure.
- */
-#define member2struct(s, m, x) \
- ((struct s *)(void *)((char *)(x) - offsetof(struct s, m)))
-
-#endif /* _SYS_PARAM_HH_ */
diff --git a/freebsd/pci/if_rlreg.h b/freebsd/sys/pci/if_rlreg.h
index 9de72170..9de72170 100644
--- a/freebsd/pci/if_rlreg.h
+++ b/freebsd/sys/pci/if_rlreg.h
diff --git a/freebsd/powerpc/include/freebsd/machine/cpufunc.h b/freebsd/sys/powerpc/include/machine/cpufunc.h
index 7c240e2e..7c240e2e 100644
--- a/freebsd/powerpc/include/freebsd/machine/cpufunc.h
+++ b/freebsd/sys/powerpc/include/machine/cpufunc.h
diff --git a/freebsd/powerpc/include/freebsd/machine/psl.h b/freebsd/sys/powerpc/include/machine/psl.h
index 4764c626..4764c626 100644
--- a/freebsd/powerpc/include/freebsd/machine/psl.h
+++ b/freebsd/sys/powerpc/include/machine/psl.h
diff --git a/freebsd/powerpc/include/freebsd/machine/spr.h b/freebsd/sys/powerpc/include/machine/spr.h
index b24a6ade..b24a6ade 100644
--- a/freebsd/powerpc/include/freebsd/machine/spr.h
+++ b/freebsd/sys/powerpc/include/machine/spr.h
diff --git a/freebsd/powerpc/powerpc/in_cksum.c b/freebsd/sys/powerpc/powerpc/in_cksum.c
index ede39fc3..ede39fc3 100644
--- a/freebsd/powerpc/powerpc/in_cksum.c
+++ b/freebsd/sys/powerpc/powerpc/in_cksum.c
diff --git a/freebsd/sys/resource.h b/freebsd/sys/resource.h
deleted file mode 100644
index 74a43c34..00000000
--- a/freebsd/sys/resource.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 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.
- *
- * @(#)resource.h 8.4 (Berkeley) 1/9/95
- * $FreeBSD$
- */
-
-#ifndef _SYS_RESOURCE_HH_
-#define _SYS_RESOURCE_HH_
-
-#include <freebsd/sys/cdefs.h>
-#include <freebsd/sys/_timeval.h>
-#include <freebsd/sys/_types.h>
-
-/*
- * Process priority specifications to get/setpriority.
- */
-#define PRIO_MIN -20
-#define PRIO_MAX 20
-
-#define PRIO_PROCESS 0
-#define PRIO_PGRP 1
-#define PRIO_USER 2
-
-/*
- * Resource utilization information.
- *
- * All fields are only modified by curthread and
- * no locks are required to read.
- */
-
-#define RUSAGE_SELF 0
-#define RUSAGE_CHILDREN -1
-#define RUSAGE_THREAD 1
-
-struct rusage {
- struct timeval ru_utime; /* user time used */
- struct timeval ru_stime; /* system time used */
- long ru_maxrss; /* max resident set size */
-#define ru_first ru_ixrss
- long ru_ixrss; /* integral shared memory size */
- long ru_idrss; /* integral unshared data " */
- long ru_isrss; /* integral unshared stack " */
- long ru_minflt; /* page reclaims */
- long ru_majflt; /* page faults */
- long ru_nswap; /* swaps */
- long ru_inblock; /* block input operations */
- long ru_oublock; /* block output operations */
- long ru_msgsnd; /* messages sent */
- long ru_msgrcv; /* messages received */
- long ru_nsignals; /* signals received */
- long ru_nvcsw; /* voluntary context switches */
- long ru_nivcsw; /* involuntary " */
-#define ru_last ru_nivcsw
-};
-
-/*
- * Resource limits
- */
-#define RLIMIT_CPU 0 /* maximum cpu time in seconds */
-#define RLIMIT_FSIZE 1 /* maximum file size */
-#define RLIMIT_DATA 2 /* data size */
-#define RLIMIT_STACK 3 /* stack size */
-#define RLIMIT_CORE 4 /* core file size */
-#define RLIMIT_RSS 5 /* resident set size */
-#define RLIMIT_MEMLOCK 6 /* locked-in-memory address space */
-#define RLIMIT_NPROC 7 /* number of processes */
-#define RLIMIT_NOFILE 8 /* number of open files */
-#define RLIMIT_SBSIZE 9 /* maximum size of all socket buffers */
-#define RLIMIT_VMEM 10 /* virtual process size (inclusive of mmap) */
-#define RLIMIT_AS RLIMIT_VMEM /* standard name for RLIMIT_VMEM */
-#define RLIMIT_NPTS 11 /* pseudo-terminals */
-#define RLIMIT_SWAP 12 /* swap used */
-
-#define RLIM_NLIMITS 13 /* number of resource limits */
-
-#define RLIM_INFINITY ((rlim_t)(((uint64_t)1 << 63) - 1))
-/* XXX Missing: RLIM_SAVED_MAX, RLIM_SAVED_CUR */
-
-
-/*
- * Resource limit string identifiers
- */
-
-#ifdef _RLIMIT_IDENT
-static char *rlimit_ident[RLIM_NLIMITS] = {
- "cpu",
- "fsize",
- "data",
- "stack",
- "core",
- "rss",
- "memlock",
- "nproc",
- "nofile",
- "sbsize",
- "vmem",
- "npts",
- "swap",
-};
-#endif
-
-#ifndef _RLIM_T_DECLARED
-typedef __rlim_t rlim_t;
-#define _RLIM_T_DECLARED
-#endif
-
-struct rlimit {
- rlim_t rlim_cur; /* current (soft) limit */
- rlim_t rlim_max; /* maximum value for rlim_cur */
-};
-
-#if __BSD_VISIBLE
-
-struct orlimit {
- __int32_t rlim_cur; /* current (soft) limit */
- __int32_t rlim_max; /* maximum value for rlim_cur */
-};
-
-struct loadavg {
- __fixpt_t ldavg[3];
- long fscale;
-};
-
-#define CP_USER 0
-#define CP_NICE 1
-#define CP_SYS 2
-#define CP_INTR 3
-#define CP_IDLE 4
-#define CPUSTATES 5
-
-#endif /* __BSD_VISIBLE */
-
-#ifdef _KERNEL
-
-extern struct loadavg averunnable;
-void read_cpu_time(long *cp_time); /* Writes array of CPUSTATES */
-
-#else
-
-__BEGIN_DECLS
-/* XXX 2nd arg to [gs]etpriority() should be an id_t */
-int getpriority(int, int);
-int getrlimit(int, struct rlimit *);
-int getrusage(int, struct rusage *);
-int setpriority(int, int, int);
-int setrlimit(int, const struct rlimit *);
-__END_DECLS
-
-#endif /* _KERNEL */
-#endif /* !_SYS_RESOURCE_HH_ */
diff --git a/freebsd/sys/rpc/types.h b/freebsd/sys/rpc/types.h
new file mode 100644
index 00000000..b476ada3
--- /dev/null
+++ b/freebsd/sys/rpc/types.h
@@ -0,0 +1,118 @@
+/* $NetBSD: types.h,v 1.13 2000/06/13 01:02:44 thorpej Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * from: @(#)types.h 1.18 87/07/24 SMI
+ * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC
+ * $FreeBSD$
+ */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef _RPC_TYPES_H
+#define _RPC_TYPES_H
+
+#include <sys/types.h>
+#include <sys/_null.h>
+
+typedef int32_t bool_t;
+typedef int32_t enum_t;
+
+typedef uint32_t rpcprog_t;
+typedef uint32_t rpcvers_t;
+typedef uint32_t rpcproc_t;
+typedef uint32_t rpcprot_t;
+typedef uint32_t rpcport_t;
+typedef int32_t rpc_inline_t;
+
+#define __dontcare__ -1
+
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (1)
+#endif
+
+#ifdef _KERNEL
+#ifdef _SYS_MALLOC_H_
+MALLOC_DECLARE(M_RPC);
+#endif
+#define mem_alloc(bsize) malloc(bsize, M_RPC, M_WAITOK|M_ZERO)
+#define mem_free(ptr, bsize) free(ptr, M_RPC)
+#else
+#define mem_alloc(bsize) calloc(1, bsize)
+#define mem_free(ptr, bsize) free(ptr)
+#endif
+
+#include <sys/time.h>
+#ifdef _KERNEL
+#include <rpc/netconfig.h>
+#else
+#include <netconfig.h>
+#endif
+
+/*
+ * The netbuf structure is defined here, because FreeBSD / NetBSD only use
+ * it inside the RPC code. It's in <xti.h> on SVR4, but it would be confusing
+ * to have an xti.h, since FreeBSD / NetBSD does not support XTI/TLI.
+ */
+
+/*
+ * The netbuf structure is used for transport-independent address storage.
+ */
+struct netbuf {
+ unsigned int maxlen;
+ unsigned int len;
+ void *buf;
+};
+
+/*
+ * The format of the addres and options arguments of the XTI t_bind call.
+ * Only provided for compatibility, it should not be used.
+ */
+
+struct t_bind {
+ struct netbuf addr;
+ unsigned int qlen;
+};
+
+/*
+ * Internal library and rpcbind use. This is not an exported interface, do
+ * not use.
+ */
+struct __rpc_sockinfo {
+ int si_af;
+ int si_proto;
+ int si_socktype;
+ int si_alen;
+};
+
+#endif /* !_RPC_TYPES_H */
diff --git a/freebsd/security/mac/mac_framework.h b/freebsd/sys/security/mac/mac_framework.h
index c827e713..c827e713 100644
--- a/freebsd/security/mac/mac_framework.h
+++ b/freebsd/sys/security/mac/mac_framework.h
diff --git a/freebsd/sys/sleepqueue.h b/freebsd/sys/sleepqueue.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/sleepqueue.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sparc64/include/freebsd/machine/asi.h b/freebsd/sys/sparc64/include/machine/asi.h
index 83a42ff3..83a42ff3 100644
--- a/freebsd/sparc64/include/freebsd/machine/asi.h
+++ b/freebsd/sys/sparc64/include/machine/asi.h
diff --git a/freebsd/sparc64/include/freebsd/machine/cpufunc.h b/freebsd/sys/sparc64/include/machine/cpufunc.h
index 7805abc4..7805abc4 100644
--- a/freebsd/sparc64/include/freebsd/machine/cpufunc.h
+++ b/freebsd/sys/sparc64/include/machine/cpufunc.h
diff --git a/freebsd/sparc64/include/freebsd/machine/pstate.h b/freebsd/sys/sparc64/include/machine/pstate.h
index 19d98be5..19d98be5 100644
--- a/freebsd/sparc64/include/freebsd/machine/pstate.h
+++ b/freebsd/sys/sparc64/include/machine/pstate.h
diff --git a/freebsd/sparc64/sparc64/in_cksum.c b/freebsd/sys/sparc64/sparc64/in_cksum.c
index 5490d005..5490d005 100644
--- a/freebsd/sparc64/sparc64/in_cksum.c
+++ b/freebsd/sys/sparc64/sparc64/in_cksum.c
diff --git a/freebsd/sys/_bus_dma.h b/freebsd/sys/sys/_bus_dma.h
index 8d60c957..8d60c957 100644
--- a/freebsd/sys/_bus_dma.h
+++ b/freebsd/sys/sys/_bus_dma.h
diff --git a/freebsd/sys/_lock.h b/freebsd/sys/sys/_lock.h
index eb13f2aa..eb13f2aa 100644
--- a/freebsd/sys/_lock.h
+++ b/freebsd/sys/sys/_lock.h
diff --git a/freebsd/sys/_lockmgr.h b/freebsd/sys/sys/_lockmgr.h
index 616cae4e..616cae4e 100644
--- a/freebsd/sys/_lockmgr.h
+++ b/freebsd/sys/sys/_lockmgr.h
diff --git a/freebsd/sys/_mutex.h b/freebsd/sys/sys/_mutex.h
index eac45780..eac45780 100644
--- a/freebsd/sys/_mutex.h
+++ b/freebsd/sys/sys/_mutex.h
diff --git a/freebsd/sys/sys/_null.h b/freebsd/sys/sys/_null.h
new file mode 100644
index 00000000..ed6804cc
--- /dev/null
+++ b/freebsd/sys/sys/_null.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2003 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef NULL
+
+#if !defined(__cplusplus)
+#define NULL ((void *)0)
+#else
+#if defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4
+#define NULL __null
+#else
+#if defined(__LP64__)
+#define NULL (0L)
+#else
+#define NULL 0
+#endif /* __LP64__ */
+#endif /* __GNUG__ */
+#endif /* !__cplusplus */
+
+#endif
diff --git a/freebsd/sys/_rmlock.h b/freebsd/sys/sys/_rmlock.h
index 87fe1ee8..87fe1ee8 100644
--- a/freebsd/sys/_rmlock.h
+++ b/freebsd/sys/sys/_rmlock.h
diff --git a/freebsd/sys/_rwlock.h b/freebsd/sys/sys/_rwlock.h
index 536ba1dd..536ba1dd 100644
--- a/freebsd/sys/_rwlock.h
+++ b/freebsd/sys/sys/_rwlock.h
diff --git a/freebsd/sys/_semaphore.h b/freebsd/sys/sys/_semaphore.h
index e0d5eff2..e0d5eff2 100644
--- a/freebsd/sys/_semaphore.h
+++ b/freebsd/sys/sys/_semaphore.h
diff --git a/freebsd/sys/_sigset.h b/freebsd/sys/sys/_sigset.h
index 52028110..52028110 100644
--- a/freebsd/sys/_sigset.h
+++ b/freebsd/sys/sys/_sigset.h
diff --git a/freebsd/sys/_sx.h b/freebsd/sys/sys/_sx.h
index ff8f821e..ff8f821e 100644
--- a/freebsd/sys/_sx.h
+++ b/freebsd/sys/sys/_sx.h
diff --git a/freebsd/sys/_task.h b/freebsd/sys/sys/_task.h
index efea7fc8..efea7fc8 100644
--- a/freebsd/sys/_task.h
+++ b/freebsd/sys/sys/_task.h
diff --git a/freebsd/sys/_timeval.h b/freebsd/sys/sys/_timeval.h
index 936ffd88..936ffd88 100644
--- a/freebsd/sys/_timeval.h
+++ b/freebsd/sys/sys/_timeval.h
diff --git a/freebsd/sys/acl.h b/freebsd/sys/sys/acl.h
index f8c20c73..f8c20c73 100644
--- a/freebsd/sys/acl.h
+++ b/freebsd/sys/sys/acl.h
diff --git a/freebsd/sys/aio.h b/freebsd/sys/sys/aio.h
index cff3d78c..cff3d78c 100644
--- a/freebsd/sys/aio.h
+++ b/freebsd/sys/sys/aio.h
diff --git a/freebsd/sys/ata.h b/freebsd/sys/sys/ata.h
index df4cea71..df4cea71 100644
--- a/freebsd/sys/ata.h
+++ b/freebsd/sys/sys/ata.h
diff --git a/freebsd/sys/bitstring.h b/freebsd/sys/sys/bitstring.h
index a2b70ba8..a2b70ba8 100644
--- a/freebsd/sys/bitstring.h
+++ b/freebsd/sys/sys/bitstring.h
diff --git a/freebsd/sys/buf.h b/freebsd/sys/sys/buf.h
index 88e55d95..88e55d95 100644
--- a/freebsd/sys/buf.h
+++ b/freebsd/sys/sys/buf.h
diff --git a/freebsd/sys/buf_ring.h b/freebsd/sys/sys/buf_ring.h
index dbdf6206..dbdf6206 100644
--- a/freebsd/sys/buf_ring.h
+++ b/freebsd/sys/sys/buf_ring.h
diff --git a/freebsd/sys/bufobj.h b/freebsd/sys/sys/bufobj.h
index 896e4ff8..896e4ff8 100644
--- a/freebsd/sys/bufobj.h
+++ b/freebsd/sys/sys/bufobj.h
diff --git a/freebsd/sys/bus.h b/freebsd/sys/sys/bus.h
index 8dc54d08..8dc54d08 100644
--- a/freebsd/sys/bus.h
+++ b/freebsd/sys/sys/bus.h
diff --git a/freebsd/sys/bus_dma.h b/freebsd/sys/sys/bus_dma.h
index 1bcde10a..1bcde10a 100644
--- a/freebsd/sys/bus_dma.h
+++ b/freebsd/sys/sys/bus_dma.h
diff --git a/freebsd/sys/callout.h b/freebsd/sys/sys/callout.h
index 4686a4db..4686a4db 100644
--- a/freebsd/sys/callout.h
+++ b/freebsd/sys/sys/callout.h
diff --git a/freebsd/sys/condvar.h b/freebsd/sys/sys/condvar.h
index 54cfe9eb..54cfe9eb 100644
--- a/freebsd/sys/condvar.h
+++ b/freebsd/sys/sys/condvar.h
diff --git a/freebsd/sys/conf.h b/freebsd/sys/sys/conf.h
index 86e29c4d..86e29c4d 100644
--- a/freebsd/sys/conf.h
+++ b/freebsd/sys/sys/conf.h
diff --git a/freebsd/sys/cpu.h b/freebsd/sys/sys/cpu.h
index 3e6729db..3e6729db 100644
--- a/freebsd/sys/cpu.h
+++ b/freebsd/sys/sys/cpu.h
diff --git a/freebsd/sys/ctype.h b/freebsd/sys/sys/ctype.h
index b7b4ad5a..b7b4ad5a 100644
--- a/freebsd/sys/ctype.h
+++ b/freebsd/sys/sys/ctype.h
diff --git a/freebsd/sys/domain.h b/freebsd/sys/sys/domain.h
index 0b44e9fd..0b44e9fd 100644
--- a/freebsd/sys/domain.h
+++ b/freebsd/sys/sys/domain.h
diff --git a/freebsd/sys/endian.h b/freebsd/sys/sys/endian.h
index 5c95d748..5c95d748 100644
--- a/freebsd/sys/endian.h
+++ b/freebsd/sys/sys/endian.h
diff --git a/freebsd/sys/event.h b/freebsd/sys/sys/event.h
index 1af716d7..1af716d7 100644
--- a/freebsd/sys/event.h
+++ b/freebsd/sys/sys/event.h
diff --git a/freebsd/sys/eventhandler.h b/freebsd/sys/sys/eventhandler.h
index 1472df18..1472df18 100644
--- a/freebsd/sys/eventhandler.h
+++ b/freebsd/sys/sys/eventhandler.h
diff --git a/freebsd/sys/eventvar.h b/freebsd/sys/sys/eventvar.h
index 8712cfdc..8712cfdc 100644
--- a/freebsd/sys/eventvar.h
+++ b/freebsd/sys/sys/eventvar.h
diff --git a/freebsd/sys/fcntl.h b/freebsd/sys/sys/fcntl.h
index 82646c7f..82646c7f 100644
--- a/freebsd/sys/fcntl.h
+++ b/freebsd/sys/sys/fcntl.h
diff --git a/freebsd/sys/file.h b/freebsd/sys/sys/file.h
index 21b8e413..21b8e413 100644
--- a/freebsd/sys/file.h
+++ b/freebsd/sys/sys/file.h
diff --git a/freebsd/sys/filedesc.h b/freebsd/sys/sys/filedesc.h
index fab6d93b..fab6d93b 100644
--- a/freebsd/sys/filedesc.h
+++ b/freebsd/sys/sys/filedesc.h
diff --git a/freebsd/sys/filio.h b/freebsd/sys/sys/filio.h
index 899d3458..899d3458 100644
--- a/freebsd/sys/filio.h
+++ b/freebsd/sys/sys/filio.h
diff --git a/freebsd/sys/fnv_hash.h b/freebsd/sys/sys/fnv_hash.h
index 2dbed339..2dbed339 100644
--- a/freebsd/sys/fnv_hash.h
+++ b/freebsd/sys/sys/fnv_hash.h
diff --git a/freebsd/sys/hash.h b/freebsd/sys/sys/hash.h
index 91dd4fcc..91dd4fcc 100644
--- a/freebsd/sys/hash.h
+++ b/freebsd/sys/sys/hash.h
diff --git a/freebsd/sys/interrupt.h b/freebsd/sys/sys/interrupt.h
index e43d0047..e43d0047 100644
--- a/freebsd/sys/interrupt.h
+++ b/freebsd/sys/sys/interrupt.h
diff --git a/freebsd/sys/jail.h b/freebsd/sys/sys/jail.h
index f501c0b2..f501c0b2 100644
--- a/freebsd/sys/jail.h
+++ b/freebsd/sys/sys/jail.h
diff --git a/freebsd/sys/kenv.h b/freebsd/sys/sys/kenv.h
index 497eb2f2..497eb2f2 100644
--- a/freebsd/sys/kenv.h
+++ b/freebsd/sys/sys/kenv.h
diff --git a/freebsd/sys/kernel.h b/freebsd/sys/sys/kernel.h
index 2bcc58ed..2bcc58ed 100644
--- a/freebsd/sys/kernel.h
+++ b/freebsd/sys/sys/kernel.h
diff --git a/freebsd/sys/kobj.h b/freebsd/sys/sys/kobj.h
index 385159aa..385159aa 100644
--- a/freebsd/sys/kobj.h
+++ b/freebsd/sys/sys/kobj.h
diff --git a/freebsd/sys/kthread.h b/freebsd/sys/sys/kthread.h
index 6fe442e3..6fe442e3 100644
--- a/freebsd/sys/kthread.h
+++ b/freebsd/sys/sys/kthread.h
diff --git a/freebsd/sys/ktr.h b/freebsd/sys/sys/ktr.h
index 3942b92e..3942b92e 100644
--- a/freebsd/sys/ktr.h
+++ b/freebsd/sys/sys/ktr.h
diff --git a/freebsd/sys/libkern.h b/freebsd/sys/sys/libkern.h
index 943ac34b..943ac34b 100644
--- a/freebsd/sys/libkern.h
+++ b/freebsd/sys/sys/libkern.h
diff --git a/freebsd/sys/sys/limits.h b/freebsd/sys/sys/limits.h
new file mode 100644
index 00000000..b2850e20
--- /dev/null
+++ b/freebsd/sys/sys/limits.h
@@ -0,0 +1,9 @@
+#include <sys/types.h>
+#include <limits.h>
+
+#define __FD_SETSIZE 1024
+#define FD_SETSIZE __FD_SETSIZE
+
+#define __CHAR_BIT CHAR_BIT /* number of bits in a char */
+
+
diff --git a/freebsd/sys/linker.h b/freebsd/sys/sys/linker.h
index 449fa1ec..449fa1ec 100644
--- a/freebsd/sys/linker.h
+++ b/freebsd/sys/sys/linker.h
diff --git a/freebsd/sys/linker_set.h b/freebsd/sys/sys/linker_set.h
index 2dd056bc..2dd056bc 100644
--- a/freebsd/sys/linker_set.h
+++ b/freebsd/sys/sys/linker_set.h
diff --git a/freebsd/sys/lock_profile.h b/freebsd/sys/sys/lock_profile.h
index 92eb512f..92eb512f 100644
--- a/freebsd/sys/lock_profile.h
+++ b/freebsd/sys/sys/lock_profile.h
diff --git a/freebsd/sys/lockmgr.h b/freebsd/sys/sys/lockmgr.h
index 2020eb83..2020eb83 100644
--- a/freebsd/sys/lockmgr.h
+++ b/freebsd/sys/sys/lockmgr.h
diff --git a/freebsd/sys/lockstat.h b/freebsd/sys/sys/lockstat.h
index ed9cffa9..ed9cffa9 100644
--- a/freebsd/sys/lockstat.h
+++ b/freebsd/sys/sys/lockstat.h
diff --git a/freebsd/sys/mac.h b/freebsd/sys/sys/mac.h
index f261c7ff..f261c7ff 100644
--- a/freebsd/sys/mac.h
+++ b/freebsd/sys/sys/mac.h
diff --git a/freebsd/sys/malloc.h b/freebsd/sys/sys/malloc.h
index faca480d..faca480d 100644
--- a/freebsd/sys/malloc.h
+++ b/freebsd/sys/sys/malloc.h
diff --git a/freebsd/sys/mbuf.h b/freebsd/sys/sys/mbuf.h
index 5988760e..5988760e 100644
--- a/freebsd/sys/mbuf.h
+++ b/freebsd/sys/sys/mbuf.h
diff --git a/freebsd/sys/md5.h b/freebsd/sys/sys/md5.h
index 9bf97cd6..9bf97cd6 100644
--- a/freebsd/sys/md5.h
+++ b/freebsd/sys/sys/md5.h
diff --git a/freebsd/sys/sys/mman.h b/freebsd/sys/sys/mman.h
new file mode 100644
index 00000000..2d90a14d
--- /dev/null
+++ b/freebsd/sys/sys/mman.h
@@ -0,0 +1,3 @@
+#include <freebsd/bsd.h>
+#include <freebsd/sys/mman.h>
+
diff --git a/freebsd/sys/module.h b/freebsd/sys/sys/module.h
index 3b67ad5a..3b67ad5a 100644
--- a/freebsd/sys/module.h
+++ b/freebsd/sys/sys/module.h
diff --git a/freebsd/sys/mount.h b/freebsd/sys/sys/mount.h
index 9ec6915d..9ec6915d 100644
--- a/freebsd/sys/mount.h
+++ b/freebsd/sys/sys/mount.h
diff --git a/freebsd/sys/mqueue.h b/freebsd/sys/sys/mqueue.h
index 80d40479..80d40479 100644
--- a/freebsd/sys/mqueue.h
+++ b/freebsd/sys/sys/mqueue.h
diff --git a/freebsd/sys/mutex.h b/freebsd/sys/sys/mutex.h
index 0e8e1739..0e8e1739 100644
--- a/freebsd/sys/mutex.h
+++ b/freebsd/sys/sys/mutex.h
diff --git a/freebsd/sys/sys/nlist_aout.h b/freebsd/sys/sys/nlist_aout.h
new file mode 100644
index 00000000..a4e11c39
--- /dev/null
+++ b/freebsd/sys/sys/nlist_aout.h
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 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.
+ *
+ * @(#)nlist.h 8.2 (Berkeley) 1/21/94
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_NLIST_AOUT_H_
+#define _SYS_NLIST_AOUT_H_
+
+/*
+ * Symbol table entries in a.out files.
+ */
+
+/*
+ * Layout of each symbol. The "#ifdef _AOUT_INCLUDE_" is so that
+ * programs including nlist.h can initialize nlist structures
+ * statically.
+ */
+struct nlist {
+#ifdef _AOUT_INCLUDE_
+ union {
+ char *n_name; /* symbol name (in memory) */
+ long n_strx; /* file string table offset (on disk) */
+ } n_un;
+#else
+ char *n_name; /* symbol name (in memory) */
+ int : 8 * (sizeof(long) > sizeof(char *) ?
+ sizeof(long) - sizeof(char *) : sizeof(char *) - sizeof(long));
+#endif
+ unsigned char n_type; /* type defines */
+ char n_other; /* ".type" and binding information */
+ short n_desc; /* used by stab entries */
+ unsigned long n_value; /* address/value of the symbol */
+};
+
+#define n_hash n_desc /* used internally by ld(1); XXX */
+
+/*
+ * Defines for n_type.
+ */
+#define N_UNDF 0x00 /* undefined */
+#define N_ABS 0x02 /* absolute address */
+#define N_TEXT 0x04 /* text segment */
+#define N_DATA 0x06 /* data segment */
+#define N_BSS 0x08 /* bss segment */
+#define N_INDR 0x0a /* alias definition */
+#define N_SIZE 0x0c /* pseudo type, defines a symbol's size */
+#define N_COMM 0x12 /* common reference */
+/* GNU extensions */
+#define N_SETA 0x14 /* Absolute set element symbol */
+#define N_SETT 0x16 /* Text set element symbol */
+#define N_SETD 0x18 /* Data set element symbol */
+#define N_SETB 0x1a /* Bss set element symbol */
+#define N_SETV 0x1c /* Pointer to set vector in data area. */
+/* end GNU extensions */
+#define N_FN 0x1e /* file name (N_EXT on) */
+#define N_WARN 0x1e /* warning message (N_EXT off) */
+
+#define N_EXT 0x01 /* external (global) bit, OR'ed in */
+#define N_TYPE 0x1e /* mask for all the type bits */
+#define N_STAB 0xe0 /* mask for debugger symbols -- stab(5) */
+
+/*
+ * Defines for n_other. It contains the ".type" (AUX) field in the least
+ * significant 4 bits, and the binding (for weak symbols) in the most
+ * significant 4 bits.
+ */
+#define N_AUX(p) ((p)->n_other & 0xf)
+#define N_BIND(p) (((unsigned int)(p)->n_other >> 4) & 0xf)
+#define N_OTHER(r, v) (((unsigned int)(r) << 4) | ((v) & 0xf))
+
+#define AUX_OBJECT 1 /* data object */
+#define AUX_FUNC 2 /* function */
+
+/*#define BIND_LOCAL 0 not used */
+/*#define BIND_GLOBAL 1 not used */
+#define BIND_WEAK 2 /* weak binding */
+
+#define N_FORMAT "%08x" /* namelist value format; XXX */
+
+#endif /* !_SYS_NLIST_AOUT_H_ */
diff --git a/freebsd/sys/osd.h b/freebsd/sys/sys/osd.h
index a1989de0..a1989de0 100644
--- a/freebsd/sys/osd.h
+++ b/freebsd/sys/sys/osd.h
diff --git a/freebsd/sys/pciio.h b/freebsd/sys/sys/pciio.h
index c4a5abf8..c4a5abf8 100644
--- a/freebsd/sys/pciio.h
+++ b/freebsd/sys/sys/pciio.h
diff --git a/freebsd/sys/pcpu.h b/freebsd/sys/sys/pcpu.h
index ce84f15a..ce84f15a 100644
--- a/freebsd/sys/pcpu.h
+++ b/freebsd/sys/sys/pcpu.h
diff --git a/freebsd/sys/poll.h b/freebsd/sys/sys/poll.h
index 1d09405a..1d09405a 100644
--- a/freebsd/sys/poll.h
+++ b/freebsd/sys/sys/poll.h
diff --git a/freebsd/sys/priority.h b/freebsd/sys/sys/priority.h
index dbaa5eaa..dbaa5eaa 100644
--- a/freebsd/sys/priority.h
+++ b/freebsd/sys/sys/priority.h
diff --git a/freebsd/sys/priv.h b/freebsd/sys/sys/priv.h
index 78342669..78342669 100644
--- a/freebsd/sys/priv.h
+++ b/freebsd/sys/sys/priv.h
diff --git a/freebsd/sys/proc.h b/freebsd/sys/sys/proc.h
index 43c2044c..43c2044c 100644
--- a/freebsd/sys/proc.h
+++ b/freebsd/sys/sys/proc.h
diff --git a/freebsd/sys/protosw.h b/freebsd/sys/sys/protosw.h
index 5b8e9f03..5b8e9f03 100644
--- a/freebsd/sys/protosw.h
+++ b/freebsd/sys/sys/protosw.h
diff --git a/freebsd/sys/queue.h b/freebsd/sys/sys/queue.h
index e303641a..e303641a 100644
--- a/freebsd/sys/queue.h
+++ b/freebsd/sys/sys/queue.h
diff --git a/freebsd/sys/random.h b/freebsd/sys/sys/random.h
index e5dea939..e5dea939 100644
--- a/freebsd/sys/random.h
+++ b/freebsd/sys/sys/random.h
diff --git a/freebsd/sys/reboot.h b/freebsd/sys/sys/reboot.h
index c2ffd30e..c2ffd30e 100644
--- a/freebsd/sys/reboot.h
+++ b/freebsd/sys/sys/reboot.h
diff --git a/freebsd/sys/refcount.h b/freebsd/sys/sys/refcount.h
index 6ec2417e..6ec2417e 100644
--- a/freebsd/sys/refcount.h
+++ b/freebsd/sys/sys/refcount.h
diff --git a/freebsd/sys/resourcevar.h b/freebsd/sys/sys/resourcevar.h
index 53901f39..53901f39 100644
--- a/freebsd/sys/resourcevar.h
+++ b/freebsd/sys/sys/resourcevar.h
diff --git a/freebsd/sys/rman.h b/freebsd/sys/sys/rman.h
index 3f909a22..3f909a22 100644
--- a/freebsd/sys/rman.h
+++ b/freebsd/sys/sys/rman.h
diff --git a/freebsd/sys/rmlock.h b/freebsd/sys/sys/rmlock.h
index ec676b74..ec676b74 100644
--- a/freebsd/sys/rmlock.h
+++ b/freebsd/sys/sys/rmlock.h
diff --git a/freebsd/sys/rtprio.h b/freebsd/sys/sys/rtprio.h
index 0694c119..0694c119 100644
--- a/freebsd/sys/rtprio.h
+++ b/freebsd/sys/sys/rtprio.h
diff --git a/freebsd/sys/runq.h b/freebsd/sys/sys/runq.h
index ce2dada1..ce2dada1 100644
--- a/freebsd/sys/runq.h
+++ b/freebsd/sys/sys/runq.h
diff --git a/freebsd/sys/rwlock.h b/freebsd/sys/sys/rwlock.h
index c3d6ee7a..c3d6ee7a 100644
--- a/freebsd/sys/rwlock.h
+++ b/freebsd/sys/sys/rwlock.h
diff --git a/freebsd/sys/sbuf.h b/freebsd/sys/sys/sbuf.h
index 6b270d3d..6b270d3d 100644
--- a/freebsd/sys/sbuf.h
+++ b/freebsd/sys/sys/sbuf.h
diff --git a/freebsd/sys/sdt.h b/freebsd/sys/sys/sdt.h
index eeae665c..eeae665c 100644
--- a/freebsd/sys/sdt.h
+++ b/freebsd/sys/sys/sdt.h
diff --git a/freebsd/sys/sys/select.h b/freebsd/sys/sys/select.h
new file mode 100644
index 00000000..03f7d851
--- /dev/null
+++ b/freebsd/sys/sys/select.h
@@ -0,0 +1,3 @@
+#include <freebsd/bsd.h>
+#include <freebsd/sys/select.h>
+
diff --git a/freebsd/sys/selinfo.h b/freebsd/sys/sys/selinfo.h
index da20189b..da20189b 100644
--- a/freebsd/sys/selinfo.h
+++ b/freebsd/sys/sys/selinfo.h
diff --git a/freebsd/sys/sf_buf.h b/freebsd/sys/sys/sf_buf.h
index 5dbcd5ef..5dbcd5ef 100644
--- a/freebsd/sys/sf_buf.h
+++ b/freebsd/sys/sys/sf_buf.h
diff --git a/freebsd/sys/sigio.h b/freebsd/sys/sys/sigio.h
index dc29d948..dc29d948 100644
--- a/freebsd/sys/sigio.h
+++ b/freebsd/sys/sys/sigio.h
diff --git a/freebsd/sys/smp.h b/freebsd/sys/sys/smp.h
index c73bec25..c73bec25 100644
--- a/freebsd/sys/smp.h
+++ b/freebsd/sys/sys/smp.h
diff --git a/freebsd/sys/sockbuf.h b/freebsd/sys/sys/sockbuf.h
index 5de6f6eb..5de6f6eb 100644
--- a/freebsd/sys/sockbuf.h
+++ b/freebsd/sys/sys/sockbuf.h
diff --git a/freebsd/sys/sys/socket.h b/freebsd/sys/sys/socket.h
new file mode 100644
index 00000000..39138881
--- /dev/null
+++ b/freebsd/sys/sys/socket.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/sys/socket.h>
diff --git a/freebsd/sys/sys/socketvar.h b/freebsd/sys/sys/socketvar.h
new file mode 100644
index 00000000..5c3a9b4d
--- /dev/null
+++ b/freebsd/sys/sys/socketvar.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/sys/socketvar.h>
diff --git a/freebsd/sys/sockio.h b/freebsd/sys/sys/sockio.h
index 319dc783..319dc783 100644
--- a/freebsd/sys/sockio.h
+++ b/freebsd/sys/sys/sockio.h
diff --git a/freebsd/sys/sockopt.h b/freebsd/sys/sys/sockopt.h
index 09dc5599..09dc5599 100644
--- a/freebsd/sys/sockopt.h
+++ b/freebsd/sys/sys/sockopt.h
diff --git a/freebsd/sys/sockstate.h b/freebsd/sys/sys/sockstate.h
index a6c4149d..a6c4149d 100644
--- a/freebsd/sys/sockstate.h
+++ b/freebsd/sys/sys/sockstate.h
diff --git a/freebsd/sys/stddef.h b/freebsd/sys/sys/stddef.h
index 85de99d8..85de99d8 100644
--- a/freebsd/sys/stddef.h
+++ b/freebsd/sys/sys/stddef.h
diff --git a/freebsd/sys/stdint.h b/freebsd/sys/sys/stdint.h
index 10bab732..10bab732 100644
--- a/freebsd/sys/stdint.h
+++ b/freebsd/sys/sys/stdint.h
diff --git a/freebsd/sys/sx.h b/freebsd/sys/sys/sx.h
index e6a22c13..e6a22c13 100644
--- a/freebsd/sys/sx.h
+++ b/freebsd/sys/sys/sx.h
diff --git a/freebsd/sys/sys/sysctl.h b/freebsd/sys/sys/sysctl.h
new file mode 100644
index 00000000..11ed653d
--- /dev/null
+++ b/freebsd/sys/sys/sysctl.h
@@ -0,0 +1,2 @@
+#include <freebsd/bsd.h>
+#include <freebsd/sys/sysctl.h>
diff --git a/freebsd/sys/sys/syslog.h b/freebsd/sys/sys/syslog.h
new file mode 100644
index 00000000..a4aba4a1
--- /dev/null
+++ b/freebsd/sys/sys/syslog.h
@@ -0,0 +1,203 @@
+/*-
+ * Copyright (c) 1982, 1986, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 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.
+ *
+ * @(#)syslog.h 8.1 (Berkeley) 6/2/93
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_SYSLOG_H_
+#define _SYS_SYSLOG_H_
+
+#define _PATH_LOG "/var/run/log"
+#define _PATH_LOG_PRIV "/var/run/logpriv"
+#define _PATH_OLDLOG "/dev/log" /* backward compatibility */
+
+/*
+ * priorities/facilities are encoded into a single 32-bit quantity, where the
+ * bottom 3 bits are the priority (0-7) and the top 28 bits are the facility
+ * (0-big number). Both the priorities and the facilities map roughly
+ * one-to-one to strings in the syslogd(8) source code. This mapping is
+ * included in this file.
+ *
+ * priorities (these are ordered)
+ */
+#define LOG_EMERG 0 /* system is unusable */
+#define LOG_ALERT 1 /* action must be taken immediately */
+#define LOG_CRIT 2 /* critical conditions */
+#define LOG_ERR 3 /* error conditions */
+#define LOG_WARNING 4 /* warning conditions */
+#define LOG_NOTICE 5 /* normal but significant condition */
+#define LOG_INFO 6 /* informational */
+#define LOG_DEBUG 7 /* debug-level messages */
+
+#define LOG_PRIMASK 0x07 /* mask to extract priority part (internal) */
+ /* extract priority */
+#define LOG_PRI(p) ((p) & LOG_PRIMASK)
+#define LOG_MAKEPRI(fac, pri) ((fac) | (pri))
+
+#ifdef SYSLOG_NAMES
+#define INTERNAL_NOPRI 0x10 /* the "no priority" priority */
+ /* mark "facility" */
+#define INTERNAL_MARK LOG_MAKEPRI((LOG_NFACILITIES<<3), 0)
+typedef struct _code {
+ const char *c_name;
+ int c_val;
+} CODE;
+
+CODE prioritynames[] = {
+ { "alert", LOG_ALERT, },
+ { "crit", LOG_CRIT, },
+ { "debug", LOG_DEBUG, },
+ { "emerg", LOG_EMERG, },
+ { "err", LOG_ERR, },
+ { "error", LOG_ERR, }, /* DEPRECATED */
+ { "info", LOG_INFO, },
+ { "none", INTERNAL_NOPRI, }, /* INTERNAL */
+ { "notice", LOG_NOTICE, },
+ { "panic", LOG_EMERG, }, /* DEPRECATED */
+ { "warn", LOG_WARNING, }, /* DEPRECATED */
+ { "warning", LOG_WARNING, },
+ { NULL, -1, }
+};
+#endif
+
+/* facility codes */
+#define LOG_KERN (0<<3) /* kernel messages */
+#define LOG_USER (1<<3) /* random user-level messages */
+#define LOG_MAIL (2<<3) /* mail system */
+#define LOG_DAEMON (3<<3) /* system daemons */
+#define LOG_AUTH (4<<3) /* authorization messages */
+#define LOG_SYSLOG (5<<3) /* messages generated internally by syslogd */
+#define LOG_LPR (6<<3) /* line printer subsystem */
+#define LOG_NEWS (7<<3) /* network news subsystem */
+#define LOG_UUCP (8<<3) /* UUCP subsystem */
+#define LOG_CRON (9<<3) /* clock daemon */
+#define LOG_AUTHPRIV (10<<3) /* authorization messages (private) */
+ /* Facility #10 clashes in DEC UNIX, where */
+ /* it's defined as LOG_MEGASAFE for AdvFS */
+ /* event logging. */
+#define LOG_FTP (11<<3) /* ftp daemon */
+#define LOG_NTP (12<<3) /* NTP subsystem */
+#define LOG_SECURITY (13<<3) /* security subsystems (firewalling, etc.) */
+#define LOG_CONSOLE (14<<3) /* /dev/console output */
+
+ /* other codes through 15 reserved for system use */
+#define LOG_LOCAL0 (16<<3) /* reserved for local use */
+#define LOG_LOCAL1 (17<<3) /* reserved for local use */
+#define LOG_LOCAL2 (18<<3) /* reserved for local use */
+#define LOG_LOCAL3 (19<<3) /* reserved for local use */
+#define LOG_LOCAL4 (20<<3) /* reserved for local use */
+#define LOG_LOCAL5 (21<<3) /* reserved for local use */
+#define LOG_LOCAL6 (22<<3) /* reserved for local use */
+#define LOG_LOCAL7 (23<<3) /* reserved for local use */
+
+#define LOG_NFACILITIES 24 /* current number of facilities */
+#define LOG_FACMASK 0x03f8 /* mask to extract facility part */
+ /* facility of pri */
+#define LOG_FAC(p) (((p) & LOG_FACMASK) >> 3)
+
+#ifdef SYSLOG_NAMES
+CODE facilitynames[] = {
+ { "auth", LOG_AUTH, },
+ { "authpriv", LOG_AUTHPRIV, },
+ { "console", LOG_CONSOLE, },
+ { "cron", LOG_CRON, },
+ { "daemon", LOG_DAEMON, },
+ { "ftp", LOG_FTP, },
+ { "kern", LOG_KERN, },
+ { "lpr", LOG_LPR, },
+ { "mail", LOG_MAIL, },
+ { "mark", INTERNAL_MARK, }, /* INTERNAL */
+ { "news", LOG_NEWS, },
+ { "ntp", LOG_NTP, },
+ { "security", LOG_SECURITY, },
+ { "syslog", LOG_SYSLOG, },
+ { "user", LOG_USER, },
+ { "uucp", LOG_UUCP, },
+ { "local0", LOG_LOCAL0, },
+ { "local1", LOG_LOCAL1, },
+ { "local2", LOG_LOCAL2, },
+ { "local3", LOG_LOCAL3, },
+ { "local4", LOG_LOCAL4, },
+ { "local5", LOG_LOCAL5, },
+ { "local6", LOG_LOCAL6, },
+ { "local7", LOG_LOCAL7, },
+ { NULL, -1, }
+};
+#endif
+
+#ifdef _KERNEL
+#define LOG_PRINTF -1 /* pseudo-priority to indicate use of printf */
+#endif
+
+/*
+ * arguments to setlogmask.
+ */
+#define LOG_MASK(pri) (1 << (pri)) /* mask for one priority */
+#define LOG_UPTO(pri) ((1 << ((pri)+1)) - 1) /* all priorities through pri */
+
+/*
+ * Option flags for openlog.
+ *
+ * LOG_ODELAY no longer does anything.
+ * LOG_NDELAY is the inverse of what it used to be.
+ */
+#define LOG_PID 0x01 /* log the pid with each message */
+#define LOG_CONS 0x02 /* log on the console if errors in sending */
+#define LOG_ODELAY 0x04 /* delay open until first syslog() (default) */
+#define LOG_NDELAY 0x08 /* don't delay open */
+#define LOG_NOWAIT 0x10 /* don't wait for console forks: DEPRECATED */
+#define LOG_PERROR 0x20 /* log to stderr as well */
+
+#ifdef _KERNEL
+
+#else /* not _KERNEL */
+
+/*
+ * Don't use va_list in the vsyslog() prototype. Va_list is typedef'd in two
+ * places (<machine/varargs.h> and <machine/stdarg.h>), so if we include one
+ * of them here we may collide with the utility's includes. It's unreasonable
+ * for utilities to have to include one of them to include syslog.h, so we get
+ * __va_list from <sys/_types.h> and use it.
+ */
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+__BEGIN_DECLS
+void closelog(void);
+void openlog(const char *, int, int);
+int setlogmask(int);
+void syslog(int, const char *, ...); /* JRS __printflike(2, 3); */
+#if __BSD_VISIBLE
+void vsyslog(int, const char *, __va_list); /* JRS __printflike(2, 0); */
+#endif
+__END_DECLS
+
+#endif /* !_KERNEL */
+
+#endif
diff --git a/freebsd/sys/systm.h b/freebsd/sys/sys/systm.h
index 731626ee..731626ee 100644
--- a/freebsd/sys/systm.h
+++ b/freebsd/sys/sys/systm.h
diff --git a/freebsd/sys/taskqueue.h b/freebsd/sys/sys/taskqueue.h
index d5da47a9..d5da47a9 100644
--- a/freebsd/sys/taskqueue.h
+++ b/freebsd/sys/sys/taskqueue.h
diff --git a/freebsd/sys/timepps.h b/freebsd/sys/sys/timepps.h
index 1e5e84fc..1e5e84fc 100644
--- a/freebsd/sys/timepps.h
+++ b/freebsd/sys/sys/timepps.h
diff --git a/freebsd/sys/timetc.h b/freebsd/sys/sys/timetc.h
index 6b1c9b91..6b1c9b91 100644
--- a/freebsd/sys/timetc.h
+++ b/freebsd/sys/sys/timetc.h
diff --git a/freebsd/sys/timex.h b/freebsd/sys/sys/timex.h
index 838a0e05..838a0e05 100644
--- a/freebsd/sys/timex.h
+++ b/freebsd/sys/sys/timex.h
diff --git a/freebsd/sys/tree.h b/freebsd/sys/sys/tree.h
index ed0b9a27..ed0b9a27 100644
--- a/freebsd/sys/tree.h
+++ b/freebsd/sys/sys/tree.h
diff --git a/freebsd/sys/tty.h b/freebsd/sys/sys/tty.h
index a56d38fb..a56d38fb 100644
--- a/freebsd/sys/tty.h
+++ b/freebsd/sys/sys/tty.h
diff --git a/freebsd/sys/ttycom.h b/freebsd/sys/sys/ttycom.h
index cf7cba42..cf7cba42 100644
--- a/freebsd/sys/ttycom.h
+++ b/freebsd/sys/sys/ttycom.h
diff --git a/freebsd/sys/ttydevsw.h b/freebsd/sys/sys/ttydevsw.h
index a4035585..a4035585 100644
--- a/freebsd/sys/ttydevsw.h
+++ b/freebsd/sys/sys/ttydevsw.h
diff --git a/freebsd/sys/ttydisc.h b/freebsd/sys/sys/ttydisc.h
index 00194988..00194988 100644
--- a/freebsd/sys/ttydisc.h
+++ b/freebsd/sys/sys/ttydisc.h
diff --git a/freebsd/sys/ttyhook.h b/freebsd/sys/sys/ttyhook.h
index a15fbbb7..a15fbbb7 100644
--- a/freebsd/sys/ttyhook.h
+++ b/freebsd/sys/sys/ttyhook.h
diff --git a/freebsd/sys/ttyqueue.h b/freebsd/sys/sys/ttyqueue.h
index b9228bdc..b9228bdc 100644
--- a/freebsd/sys/ttyqueue.h
+++ b/freebsd/sys/sys/ttyqueue.h
diff --git a/freebsd/sys/ucred.h b/freebsd/sys/sys/ucred.h
index 917cc750..917cc750 100644
--- a/freebsd/sys/ucred.h
+++ b/freebsd/sys/sys/ucred.h
diff --git a/freebsd/sys/sys/un.h b/freebsd/sys/sys/un.h
new file mode 100644
index 00000000..1f4731e6
--- /dev/null
+++ b/freebsd/sys/sys/un.h
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1982, 1986, 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.
+ *
+ * @(#)un.h 8.3 (Berkeley) 2/19/95
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_UN_H_
+#define _SYS_UN_H_
+
+#include <sys/cdefs.h>
+#include <sys/_types.h>
+
+#ifndef _SA_FAMILY_T_DECLARED
+typedef __sa_family_t sa_family_t;
+#define _SA_FAMILY_T_DECLARED
+#endif
+
+/*
+ * Definitions for UNIX IPC domain.
+ */
+struct sockaddr_un {
+ unsigned char sun_len; /* sockaddr len including null */
+ sa_family_t sun_family; /* AF_UNIX */
+ char sun_path[104]; /* path name (gag) */
+};
+
+#if __BSD_VISIBLE
+
+/* Socket options. */
+#define LOCAL_PEERCRED 0x001 /* retrieve peer credentials */
+#define LOCAL_CREDS 0x002 /* pass credentials to receiver */
+#define LOCAL_CONNWAIT 0x004 /* connects block until accepted */
+
+#ifndef _KERNEL
+
+/* actual length of an initialized sockaddr_un */
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+
+#endif /* !_KERNEL */
+
+#endif /* __BSD_VISIBLE */
+
+#endif /* !_SYS_UN_H_ */
diff --git a/freebsd/sys/user.h b/freebsd/sys/sys/user.h
index df788c06..df788c06 100644
--- a/freebsd/sys/user.h
+++ b/freebsd/sys/sys/user.h
diff --git a/freebsd/sys/vmmeter.h b/freebsd/sys/sys/vmmeter.h
index 3a470074..3a470074 100644
--- a/freebsd/sys/vmmeter.h
+++ b/freebsd/sys/sys/vmmeter.h
diff --git a/freebsd/sys/syscallsubr.h b/freebsd/sys/syscallsubr.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/syscallsubr.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sys/sysent.h b/freebsd/sys/sysent.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/sysent.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sys/sysproto.h b/freebsd/sys/sysproto.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/sysproto.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sys/time.h b/freebsd/sys/time.h
deleted file mode 100644
index f34af077..00000000
--- a/freebsd/sys/time.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 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.
- *
- * @(#)time.h 8.5 (Berkeley) 5/4/95
- * $FreeBSD$
- */
-
-#ifndef _SYS_TIME_HH_
-#define _SYS_TIME_HH_
-
-#include <freebsd/sys/_timeval.h>
-#include <freebsd/sys/types.h>
-#include <freebsd/sys/timespec.h>
-
-#ifndef __rtems__
-struct timezone {
- int tz_minuteswest; /* minutes west of Greenwich */
- int tz_dsttime; /* type of dst correction */
-};
-#endif
-
-#define DST_NONE 0 /* not on dst */
-#define DST_USA 1 /* USA style dst */
-#define DST_AUST 2 /* Australian style dst */
-#define DST_WET 3 /* Western European dst */
-#define DST_MET 4 /* Middle European dst */
-#define DST_EET 5 /* Eastern European dst */
-#define DST_CAN 6 /* Canada */
-
-#if __BSD_VISIBLE
-struct bintime {
- time_t sec;
- uint64_t frac;
-};
-
-static __inline void
-bintime_addx(struct bintime *bt, uint64_t x)
-{
- uint64_t u;
-
- u = bt->frac;
- bt->frac += x;
- if (u > bt->frac)
- bt->sec++;
-}
-
-static __inline void
-bintime_add(struct bintime *bt, const struct bintime *bt2)
-{
- uint64_t u;
-
- u = bt->frac;
- bt->frac += bt2->frac;
- if (u > bt->frac)
- bt->sec++;
- bt->sec += bt2->sec;
-}
-
-static __inline void
-bintime_sub(struct bintime *bt, const struct bintime *bt2)
-{
- uint64_t u;
-
- u = bt->frac;
- bt->frac -= bt2->frac;
- if (u < bt->frac)
- bt->sec--;
- bt->sec -= bt2->sec;
-}
-
-/*-
- * Background information:
- *
- * When converting between timestamps on parallel timescales of differing
- * resolutions it is historical and scientific practice to round down rather
- * than doing 4/5 rounding.
- *
- * The date changes at midnight, not at noon.
- *
- * Even at 15:59:59.999999999 it's not four'o'clock.
- *
- * time_second ticks after N.999999999 not after N.4999999999
- */
-
-static __inline void
-bintime2timespec(const struct bintime *bt, struct timespec *ts)
-{
-
- ts->tv_sec = bt->sec;
- ts->tv_nsec = ((uint64_t)1000000000 * (uint32_t)(bt->frac >> 32)) >> 32;
-}
-
-static __inline void
-timespec2bintime(const struct timespec *ts, struct bintime *bt)
-{
-
- bt->sec = ts->tv_sec;
- /* 18446744073 = int(2^64 / 1000000000) */
- bt->frac = ts->tv_nsec * (uint64_t)18446744073LL;
-}
-
-static __inline void
-bintime2timeval(const struct bintime *bt, struct timeval *tv)
-{
-
- tv->tv_sec = bt->sec;
- tv->tv_usec = ((uint64_t)1000000 * (uint32_t)(bt->frac >> 32)) >> 32;
-}
-
-static __inline void
-timeval2bintime(const struct timeval *tv, struct bintime *bt)
-{
-
- bt->sec = tv->tv_sec;
- /* 18446744073709 = int(2^64 / 1000000) */
- bt->frac = tv->tv_usec * (uint64_t)18446744073709LL;
-}
-#endif /* __BSD_VISIBLE */
-
-#ifdef _KERNEL
-
-/* Operations on timespecs */
-#define timespecclear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0)
-#define timespecisset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec)
-#define timespeccmp(tvp, uvp, cmp) \
- (((tvp)->tv_sec == (uvp)->tv_sec) ? \
- ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \
- ((tvp)->tv_sec cmp (uvp)->tv_sec))
-#define timespecadd(vvp, uvp) \
- do { \
- (vvp)->tv_sec += (uvp)->tv_sec; \
- (vvp)->tv_nsec += (uvp)->tv_nsec; \
- if ((vvp)->tv_nsec >= 1000000000) { \
- (vvp)->tv_sec++; \
- (vvp)->tv_nsec -= 1000000000; \
- } \
- } while (0)
-#define timespecsub(vvp, uvp) \
- do { \
- (vvp)->tv_sec -= (uvp)->tv_sec; \
- (vvp)->tv_nsec -= (uvp)->tv_nsec; \
- if ((vvp)->tv_nsec < 0) { \
- (vvp)->tv_sec--; \
- (vvp)->tv_nsec += 1000000000; \
- } \
- } while (0)
-
-/* Operations on timevals. */
-
-#define timevalclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
-#define timevalisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
-#define timevalcmp(tvp, uvp, cmp) \
- (((tvp)->tv_sec == (uvp)->tv_sec) ? \
- ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
- ((tvp)->tv_sec cmp (uvp)->tv_sec))
-
-/* timevaladd and timevalsub are not inlined */
-
-#endif /* _KERNEL */
-
-#ifndef _KERNEL /* NetBSD/OpenBSD compatible interfaces */
-
-#define timerclear(tvp) ((tvp)->tv_sec = (tvp)->tv_usec = 0)
-#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
-#ifndef __rtems__
-#define timercmp(tvp, uvp, cmp) \
- (((tvp)->tv_sec == (uvp)->tv_sec) ? \
- ((tvp)->tv_usec cmp (uvp)->tv_usec) : \
- ((tvp)->tv_sec cmp (uvp)->tv_sec))
-#define timeradd(tvp, uvp, vvp) \
- do { \
- (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec; \
- (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec; \
- if ((vvp)->tv_usec >= 1000000) { \
- (vvp)->tv_sec++; \
- (vvp)->tv_usec -= 1000000; \
- } \
- } while (0)
-#define timersub(tvp, uvp, vvp) \
- do { \
- (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec; \
- (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec; \
- if ((vvp)->tv_usec < 0) { \
- (vvp)->tv_sec--; \
- (vvp)->tv_usec += 1000000; \
- } \
- } while (0)
-#endif
-#endif
-
-/*
- * Names of the interval timers, and structure
- * defining a timer setting.
- */
-#define ITIMER_REAL 0
-#define ITIMER_VIRTUAL 1
-#define ITIMER_PROF 2
-
-#ifndef __rtems__
-struct itimerval {
- struct timeval it_interval; /* timer interval */
- struct timeval it_value; /* current value */
-};
-#endif
-
-/*
- * Getkerninfo clock information structure
- */
-struct clockinfo {
- int hz; /* clock frequency */
- int tick; /* micro-seconds per hz tick */
- int spare;
- int stathz; /* statistics clock frequency */
- int profhz; /* profiling clock frequency */
-};
-
-/* These macros are also in time.h. */
-#ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME 0
-#define CLOCK_VIRTUAL 1
-#define CLOCK_PROF 2
-#define CLOCK_MONOTONIC 4
-#define CLOCK_UPTIME 5 /* FreeBSD-specific. */
-#define CLOCK_UPTIME_PRECISE 7 /* FreeBSD-specific. */
-#define CLOCK_UPTIME_FAST 8 /* FreeBSD-specific. */
-#define CLOCK_REALTIME_PRECISE 9 /* FreeBSD-specific. */
-#define CLOCK_REALTIME_FAST 10 /* FreeBSD-specific. */
-#define CLOCK_MONOTONIC_PRECISE 11 /* FreeBSD-specific. */
-#define CLOCK_MONOTONIC_FAST 12 /* FreeBSD-specific. */
-#define CLOCK_SECOND 13 /* FreeBSD-specific. */
-#define CLOCK_THREAD_CPUTIME_ID 14
-#endif
-
-#ifndef TIMER_ABSTIME
-#define TIMER_RELTIME 0x0 /* relative timer */
-#define TIMER_ABSTIME 0x1 /* absolute timer */
-#endif
-
-#ifdef _KERNEL
-
-/*
- * Kernel to clock driver interface.
- */
-void inittodr(time_t base);
-void resettodr(void);
-
-extern time_t time_second;
-extern time_t time_uptime;
-extern struct timeval boottime;
-
-/*
- * Functions for looking at our clock: [get]{bin,nano,micro}[up]time()
- *
- * Functions without the "get" prefix returns the best timestamp
- * we can produce in the given format.
- *
- * "bin" == struct bintime == seconds + 64 bit fraction of seconds.
- * "nano" == struct timespec == seconds + nanoseconds.
- * "micro" == struct timeval == seconds + microseconds.
- *
- * Functions containing "up" returns time relative to boot and
- * should be used for calculating time intervals.
- *
- * Functions without "up" returns GMT time.
- *
- * Functions with the "get" prefix returns a less precise result
- * much faster than the functions without "get" prefix and should
- * be used where a precision of 10 msec is acceptable or where
- * performance is priority. (NB: "precision", _not_ "resolution" !)
- *
- */
-
-void binuptime(struct bintime *bt);
-void nanouptime(struct timespec *tsp);
-void microuptime(struct timeval *tvp);
-
-void bintime(struct bintime *bt);
-void nanotime(struct timespec *tsp);
-void microtime(struct timeval *tvp);
-
-void getbinuptime(struct bintime *bt);
-void getnanouptime(struct timespec *tsp);
-void getmicrouptime(struct timeval *tvp);
-
-void getbintime(struct bintime *bt);
-void getnanotime(struct timespec *tsp);
-void getmicrotime(struct timeval *tvp);
-
-/* Other functions */
-int itimerdecr(struct itimerval *itp, int usec);
-int itimerfix(struct timeval *tv);
-int ppsratecheck(struct timeval *, int *, int);
-int ratecheck(struct timeval *, const struct timeval *);
-void timevaladd(struct timeval *t1, const struct timeval *t2);
-void timevalsub(struct timeval *t1, const struct timeval *t2);
-int tvtohz(struct timeval *tv);
-#else /* !_KERNEL */
-#include <freebsd/time.h>
-
-#include <freebsd/sys/cdefs.h>
-#include <freebsd/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 futimesat(int, const char *, const struct timeval [2]);
-int lutimes(const char *, const struct timeval *);
-int settimeofday(const struct timeval *, const struct timezone *);
-#endif
-
-#ifndef __rtems__
-#if __XSI_VISIBLE
-int getitimer(int, struct itimerval *);
-int gettimeofday(struct timeval *, struct timezone *);
-#endif
-#endif
-
-__END_DECLS
-
-#endif /* !_KERNEL */
-
-#endif /* !_SYS_TIME_HH_ */
diff --git a/freebsd/sys/types.h b/freebsd/sys/types.h
deleted file mode 100644
index 38ae5c68..00000000
--- a/freebsd/sys/types.h
+++ /dev/null
@@ -1,360 +0,0 @@
-/*-
- * Copyright (c) 1982, 1986, 1991, 1993, 1994
- * 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.
- *
- * @(#)types.h 8.6 (Berkeley) 2/19/95
- * $FreeBSD$
- */
-
-#ifndef _SYS_TYPES_HH_
-#define _SYS_TYPES_HH_
-
-#include <freebsd/sys/cdefs.h>
-
-/* Machine type dependent parameters. */
-#include <freebsd/machine/endian.h>
-#include <freebsd/sys/_types.h>
-
-#include <freebsd/sys/_pthreadtypes.h>
-
-#if __BSD_VISIBLE
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-typedef unsigned int u_int;
-typedef unsigned long u_long;
-#ifndef _KERNEL
-typedef unsigned short ushort; /* Sys V compatibility */
-typedef unsigned int uint; /* Sys V compatibility */
-#endif
-#endif
-
-/*
- * XXX POSIX sized integrals that should appear only in <sys/stdint.h>.
- */
-#ifndef _INT8_T_DECLARED
-typedef __int8_t int8_t;
-#define _INT8_T_DECLARED
-#endif
-
-#ifndef _INT16_T_DECLARED
-typedef __int16_t int16_t;
-#define _INT16_T_DECLARED
-#endif
-
-#ifndef _INT32_T_DECLARED
-typedef __int32_t int32_t;
-#define _INT32_T_DECLARED
-#endif
-
-#ifndef _INT64_T_DECLARED
-typedef __int64_t int64_t;
-#define _INT64_T_DECLARED
-#endif
-
-#ifndef _UINT8_T_DECLARED
-typedef __uint8_t uint8_t;
-#define _UINT8_T_DECLARED
-#endif
-
-#ifndef _UINT16_T_DECLARED
-typedef __uint16_t uint16_t;
-#define _UINT16_T_DECLARED
-#endif
-
-#ifndef _UINT32_T_DECLARED
-typedef __uint32_t uint32_t;
-#define _UINT32_T_DECLARED
-#endif
-
-#ifndef _UINT64_T_DECLARED
-typedef __uint64_t uint64_t;
-#define _UINT64_T_DECLARED
-#endif
-
-#ifndef _INTPTR_T_DECLARED
-typedef __intptr_t intptr_t;
-typedef __uintptr_t uintptr_t;
-#define _INTPTR_T_DECLARED
-#endif
-
-#ifndef __rtems__
-typedef __uint8_t u_int8_t; /* unsigned integrals (deprecated) */
-typedef __uint16_t u_int16_t;
-typedef __uint32_t u_int32_t;
-typedef __uint64_t u_int64_t;
-
-typedef __uint64_t u_quad_t; /* quads (deprecated) */
-typedef __int64_t quad_t;
-typedef quad_t * qaddr_t;
-
-typedef char * caddr_t; /* core address */
-#endif /* __rtems__ */
-typedef __const char * c_caddr_t; /* core address, pointer to const */
-typedef __volatile char *v_caddr_t; /* core address, pointer to volatile */
-
-#ifndef _BLKSIZE_T_DECLARED
-typedef __blksize_t blksize_t;
-#define _BLKSIZE_T_DECLARED
-#endif
-
-typedef __cpuwhich_t cpuwhich_t;
-typedef __cpulevel_t cpulevel_t;
-typedef __cpusetid_t cpusetid_t;
-
-#ifndef _BLKCNT_T_DECLARED
-typedef __blkcnt_t blkcnt_t;
-#define _BLKCNT_T_DECLARED
-#endif
-
-#ifndef _CLOCK_T_DECLARED
-typedef __clock_t clock_t;
-#define _CLOCK_T_DECLARED
-#endif
-
-#ifndef _CLOCKID_T_DECLARED
-typedef __clockid_t clockid_t;
-#define _CLOCKID_T_DECLARED
-#endif
-
-typedef __cpumask_t cpumask_t;
-typedef __critical_t critical_t; /* Critical section value */
-#ifndef __rtems__
-typedef __int64_t daddr_t; /* disk address */
-#endif /* __rtems__ */
-
-#ifndef _DEV_T_DECLARED
-typedef __dev_t dev_t; /* device number or struct cdev */
-#define _DEV_T_DECLARED
-#endif
-
-#ifndef _FFLAGS_T_DECLARED
-typedef __fflags_t fflags_t; /* file flags */
-#define _FFLAGS_T_DECLARED
-#endif
-
-typedef __fixpt_t fixpt_t; /* fixed point number */
-
-#ifndef _FSBLKCNT_T_DECLARED /* for statvfs() */
-typedef __fsblkcnt_t fsblkcnt_t;
-typedef __fsfilcnt_t fsfilcnt_t;
-#define _FSBLKCNT_T_DECLARED
-#endif
-
-#ifndef _GID_T_DECLARED
-typedef __gid_t gid_t; /* group id */
-#define _GID_T_DECLARED
-#endif
-
-#ifndef _IN_ADDR_T_DECLARED
-typedef __uint32_t in_addr_t; /* base type for internet address */
-#define _IN_ADDR_T_DECLARED
-#endif
-
-#ifndef _IN_PORT_T_DECLARED
-typedef __uint16_t in_port_t;
-#define _IN_PORT_T_DECLARED
-#endif
-
-#ifndef _ID_T_DECLARED
-typedef __id_t id_t; /* can hold a uid_t or pid_t */
-#define _ID_T_DECLARED
-#endif
-
-#ifndef _INO_T_DECLARED
-typedef __ino_t ino_t; /* inode number */
-#define _INO_T_DECLARED
-#endif
-
-#ifndef _KEY_T_DECLARED
-typedef __key_t key_t; /* IPC key (for Sys V IPC) */
-#define _KEY_T_DECLARED
-#endif
-
-#ifndef _LWPID_T_DECLARED
-typedef __lwpid_t lwpid_t; /* Thread ID (a.k.a. LWP) */
-#define _LWPID_T_DECLARED
-#endif
-
-#ifndef _MODE_T_DECLARED
-typedef __mode_t mode_t; /* permissions */
-#define _MODE_T_DECLARED
-#endif
-
-#ifndef _ACCMODE_T_DECLARED
-typedef __accmode_t accmode_t; /* access permissions */
-#define _ACCMODE_T_DECLARED
-#endif
-
-#ifndef _NLINK_T_DECLARED
-typedef __nlink_t nlink_t; /* link count */
-#define _NLINK_T_DECLARED
-#endif
-
-#ifndef _OFF_T_DECLARED
-typedef __off_t off_t; /* file offset */
-#define _OFF_T_DECLARED
-#endif
-
-#ifndef _PID_T_DECLARED
-typedef __pid_t pid_t; /* process id */
-#define _PID_T_DECLARED
-#endif
-
-typedef __register_t register_t;
-
-#ifndef _RLIM_T_DECLARED
-typedef __rlim_t rlim_t; /* resource limit */
-#define _RLIM_T_DECLARED
-#endif
-
-typedef __segsz_t segsz_t; /* segment size (in pages) */
-
-#ifndef _SIZE_T_DECLARED
-typedef __size_t size_t;
-#define _SIZE_T_DECLARED
-#endif
-
-#ifndef _SSIZE_T_DECLARED
-typedef __ssize_t ssize_t;
-#define _SSIZE_T_DECLARED
-#endif
-
-#ifndef _SUSECONDS_T_DECLARED
-typedef __suseconds_t suseconds_t; /* microseconds (signed) */
-#define _SUSECONDS_T_DECLARED
-#endif
-
-#ifndef _TIME_T_DECLARED
-typedef __time_t time_t;
-#define _TIME_T_DECLARED
-#endif
-
-#ifndef _TIMER_T_DECLARED
-typedef __timer_t timer_t;
-#define _TIMER_T_DECLARED
-#endif
-
-#ifndef _MQD_T_DECLARED
-typedef __mqd_t mqd_t;
-#define _MQD_T_DECLARED
-#endif
-
-typedef __u_register_t u_register_t;
-
-#ifndef _UID_T_DECLARED
-typedef __uid_t uid_t; /* user id */
-#define _UID_T_DECLARED
-#endif
-
-#ifndef _USECONDS_T_DECLARED
-typedef __useconds_t useconds_t; /* microseconds (unsigned) */
-#define _USECONDS_T_DECLARED
-#endif
-
-typedef __vm_offset_t vm_offset_t;
-typedef __vm_ooffset_t vm_ooffset_t;
-typedef __vm_paddr_t vm_paddr_t;
-typedef __vm_pindex_t vm_pindex_t;
-typedef __vm_size_t vm_size_t;
-
-#ifdef _KERNEL
-typedef int boolean_t;
-typedef struct device *device_t;
-typedef __intfptr_t intfptr_t;
-
-/*-
- * XXX this is fixed width for historical reasons. It should have had type
- * __int_fast32_t. Fixed-width types should not be used unless binary
- * compatibility is essential. Least-width types should be used even less
- * since they provide smaller benefits.
- * XXX should be MD.
- * XXX this is bogus in -current, but still used for spl*().
- */
-typedef __uint32_t intrmask_t; /* Interrupt mask (spl, xxx_imask...) */
-
-typedef __uintfptr_t uintfptr_t;
-typedef __uint64_t uoff_t;
-typedef char vm_memattr_t; /* memory attribute codes */
-typedef struct vm_page *vm_page_t;
-
-#ifndef __rtems__
-#define offsetof(type, field) __offsetof(type, field)
-#endif /* __rtems__ */
-
-#endif /* !_KERNEL */
-
-/*
- * The following are all things that really shouldn't exist in this header,
- * since its purpose is to provide typedefs, not miscellaneous doodads.
- */
-#if __BSD_VISIBLE
-
-#include <freebsd/sys/select.h>
-
-/*
- * minor() gives a cookie instead of an index since we don't want to
- * change the meanings of bits 0-15 or waste time and space shifting
- * bits 16-31 for devices that don't use them.
- */
-#define major(x) ((int)(((u_int)(x) >> 8)&0xff)) /* major number */
-#define minor(x) ((int)((x)&0xffff00ff)) /* minor number */
-#define makedev(x,y) ((dev_t)(((x) << 8) | (y))) /* create dev_t */
-
-/*
- * These declarations belong elsewhere, but are repeated here and in
- * <stdio.h> to give broken programs a better chance of working with
- * 64-bit off_t's.
- */
-#ifndef _KERNEL
-__BEGIN_DECLS
-#ifndef _FTRUNCATE_DECLARED
-#define _FTRUNCATE_DECLARED
-int ftruncate(int, off_t);
-#endif
-#ifndef _LSEEK_DECLARED
-#define _LSEEK_DECLARED
-off_t lseek(int, off_t, int);
-#endif
-#ifndef _MMAP_DECLARED
-#define _MMAP_DECLARED
-void * mmap(void *, size_t, int, int, int, off_t);
-#endif
-#ifndef _TRUNCATE_DECLARED
-#define _TRUNCATE_DECLARED
-int truncate(const char *, off_t);
-#endif
-__END_DECLS
-#endif /* !_KERNEL */
-
-#endif /* __BSD_VISIBLE */
-
-#endif /* !_SYS_TYPES_HH_ */
diff --git a/freebsd/sys/ucontext.h b/freebsd/sys/ucontext.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/ucontext.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/sys/unistd.h b/freebsd/sys/unistd.h
deleted file mode 100644
index 2918d563..00000000
--- a/freebsd/sys/unistd.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/*-
- * Copyright (c) 1989, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 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.
- *
- * @(#)unistd.h 8.2 (Berkeley) 1/7/94
- * $FreeBSD$
- */
-
-#ifndef _SYS_UNISTD_HH_
-#define _SYS_UNISTD_HH_
-
-#include <freebsd/sys/cdefs.h>
-
-/*
- * POSIX options and option groups we unconditionally do or don't
- * implement. Those options which are implemented (or not) entirely
- * in user mode are defined in <unistd.h>. Please keep this list in
- * alphabetical order.
- *
- * Anything which is defined as zero below **must** have an
- * implementation for the corresponding sysconf() which is able to
- * determine conclusively whether or not the feature is supported.
- * Anything which is defined as other than -1 below **must** have
- * complete headers, types, and function declarations as specified by
- * the POSIX standard; however, if the relevant sysconf() function
- * returns -1, the functions may be stubbed out.
- */
-#define _POSIX_ADVISORY_INFO -1
-#define _POSIX_ASYNCHRONOUS_IO 0
-#define _POSIX_CHOWN_RESTRICTED 1
-#define _POSIX_CLOCK_SELECTION -1
-#define _POSIX_CPUTIME -1
-#define _POSIX_FSYNC 200112L
-#define _POSIX_IPV6 0
-#define _POSIX_JOB_CONTROL 1
-#define _POSIX_MAPPED_FILES 200112L
-#define _POSIX_MEMLOCK -1
-#define _POSIX_MEMLOCK_RANGE 200112L
-#define _POSIX_MEMORY_PROTECTION 200112L
-#define _POSIX_MESSAGE_PASSING 200112L
-#define _POSIX_MONOTONIC_CLOCK 200112L
-#define _POSIX_NO_TRUNC 1
-#define _POSIX_PRIORITIZED_IO -1
-#define _POSIX_PRIORITY_SCHEDULING 200112L
-#define _POSIX_RAW_SOCKETS 200112L
-#define _POSIX_REALTIME_SIGNALS 200112L
-#define _POSIX_SEMAPHORES -1
-#define _POSIX_SHARED_MEMORY_OBJECTS 200112L
-#define _POSIX_SPORADIC_SERVER -1
-#define _POSIX_SYNCHRONIZED_IO -1
-#define _POSIX_TIMEOUTS 200112L
-#define _POSIX_TIMERS 200112L
-#define _POSIX_TYPED_MEMORY_OBJECTS -1
-#define _POSIX_VDISABLE 0xff
-
-#if __XSI_VISIBLE
-#define _XOPEN_SHM 1
-#define _XOPEN_STREAMS -1
-#endif
-
-/*
- * Although we have saved user/group IDs, we do not use them in setuid
- * as described in POSIX 1003.1, because the feature does not work for
- * root. We use the saved IDs in seteuid/setegid, which are not currently
- * part of the POSIX 1003.1 specification. XXX revisit for 1003.1-2001
- * as this is now mandatory.
- */
-#ifdef _NOT_AVAILABLE
-#define _POSIX_SAVED_IDS 1 /* saved set-user-ID and set-group-ID */
-#endif
-
-/* Define the POSIX.1 version we target for compliance. */
-#define _POSIX_VERSION 200112L
-
-/* access function */
-#define F_OK 0 /* test for existence of file */
-#define X_OK 0x01 /* test for execute or search permission */
-#define W_OK 0x02 /* test for write permission */
-#define R_OK 0x04 /* test for read permission */
-
-/* whence values for lseek(2) */
-#ifndef SEEK_SET
-#define SEEK_SET 0 /* set file offset to offset */
-#define SEEK_CUR 1 /* set file offset to current plus offset */
-#define SEEK_END 2 /* set file offset to EOF plus offset */
-#endif
-#if __BSD_VISIBLE
-#define SEEK_DATA 3 /* set file offset to next data past offset */
-#define SEEK_HOLE 4 /* set file offset to next hole past offset */
-#endif
-
-#ifndef _POSIX_SOURCE
-/* whence values for lseek(2); renamed by POSIX 1003.1 */
-#define L_SET SEEK_SET
-#define L_INCR SEEK_CUR
-#define L_XTND SEEK_END
-#endif
-
-/* configurable pathname variables */
-#define _PC_LINK_MAX 1
-#define _PC_MAX_CANON 2
-#define _PC_MAX_INPUT 3
-#define _PC_NAME_MAX 4
-#define _PC_PATH_MAX 5
-#define _PC_PIPE_BUF 6
-#define _PC_CHOWN_RESTRICTED 7
-#define _PC_NO_TRUNC 8
-#define _PC_VDISABLE 9
-
-#if __POSIX_VISIBLE >= 199309
-#define _PC_ASYNC_IO 53
-#define _PC_PRIO_IO 54
-#define _PC_SYNC_IO 55
-#endif
-
-#if __POSIX_VISIBLE >= 200112
-#define _PC_ALLOC_SIZE_MIN 10
-#define _PC_FILESIZEBITS 12
-#define _PC_REC_INCR_XFER_SIZE 14
-#define _PC_REC_MAX_XFER_SIZE 15
-#define _PC_REC_MIN_XFER_SIZE 16
-#define _PC_REC_XFER_ALIGN 17
-#define _PC_SYMLINK_MAX 18
-#endif
-
-#if __BSD_VISIBLE
-#define _PC_ACL_EXTENDED 59
-#define _PC_ACL_PATH_MAX 60
-#define _PC_CAP_PRESENT 61
-#define _PC_INF_PRESENT 62
-#define _PC_MAC_PRESENT 63
-#define _PC_ACL_NFS4 64
-#endif
-
-/* From OpenSolaris, used by SEEK_DATA/SEEK_HOLE. */
-#define _PC_MIN_HOLE_SIZE 21
-
-#if __BSD_VISIBLE
-/*
- * rfork() options.
- *
- * XXX currently, some operations without RFPROC set are not supported.
- */
-#define RFNAMEG (1<<0) /* UNIMPL new plan9 `name space' */
-#define RFENVG (1<<1) /* UNIMPL copy plan9 `env space' */
-#define RFFDG (1<<2) /* copy fd table */
-#define RFNOTEG (1<<3) /* UNIMPL create new plan9 `note group' */
-#define RFPROC (1<<4) /* change child (else changes curproc) */
-#define RFMEM (1<<5) /* share `address space' */
-#define RFNOWAIT (1<<6) /* give child to init */
-#define RFCNAMEG (1<<10) /* UNIMPL zero plan9 `name space' */
-#define RFCENVG (1<<11) /* UNIMPL zero plan9 `env space' */
-#define RFCFDG (1<<12) /* close all fds, zero fd table */
-#define RFTHREAD (1<<13) /* enable kernel thread support */
-#define RFSIGSHARE (1<<14) /* share signal handlers */
-#define RFLINUXTHPN (1<<16) /* do linux clone exit parent notification */
-#define RFSTOPPED (1<<17) /* leave child in a stopped state */
-#define RFHIGHPID (1<<18) /* use a pid higher than 10 (idleproc) */
-#define RFPPWAIT (1<<31) /* parent sleeps until child exits (vfork) */
-#define RFKERNELONLY (RFSTOPPED | RFHIGHPID | RFPPWAIT)
-
-#endif /* __BSD_VISIBLE */
-
-#endif /* !_SYS_UNISTD_HH_ */
diff --git a/freebsd/vm/uma.h b/freebsd/sys/vm/uma.h
index b23ad453..b23ad453 100644
--- a/freebsd/vm/uma.h
+++ b/freebsd/sys/vm/uma.h
diff --git a/freebsd/vm/uma_core.c b/freebsd/sys/vm/uma_core.c
index a53fceb9..a53fceb9 100644
--- a/freebsd/vm/uma_core.c
+++ b/freebsd/sys/vm/uma_core.c
diff --git a/freebsd/vm/uma_dbg.h b/freebsd/sys/vm/uma_dbg.h
index 341cecbf..341cecbf 100644
--- a/freebsd/vm/uma_dbg.h
+++ b/freebsd/sys/vm/uma_dbg.h
diff --git a/freebsd/vm/uma_int.h b/freebsd/sys/vm/uma_int.h
index f3a99d78..f3a99d78 100644
--- a/freebsd/vm/uma_int.h
+++ b/freebsd/sys/vm/uma_int.h
diff --git a/freebsd/vm/vm.h b/freebsd/sys/vm/vm.h
index 037ac838..037ac838 100644
--- a/freebsd/vm/vm.h
+++ b/freebsd/sys/vm/vm.h
diff --git a/freebsd/sys/vnode.h b/freebsd/sys/vnode.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/sys/vnode.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/usr.bin/netstat/atalk.c b/freebsd/usr.bin/netstat/atalk.c
new file mode 100644
index 00000000..2c7e7a18
--- /dev/null
+++ b/freebsd/usr.bin/netstat/atalk.c
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)atalk.c 1.1 (Whistle) 6/6/96";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+
+#include <arpa/inet.h>
+#include <net/route.h>
+
+#include <netatalk/at.h>
+#include <netatalk/ddp_var.h>
+
+#include <errno.h>
+#include <nlist.h>
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "netstat.h"
+
+struct ddpcb ddpcb;
+struct socket sockb;
+
+static int first = 1;
+
+/*
+ * Print a summary of connections related to a Network Systems
+ * protocol. For XXX, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+
+static const char *
+at_pr_net(struct sockaddr_at *sat, int numeric)
+{
+static char mybuf[50];
+
+ if (!numeric) {
+ switch(sat->sat_addr.s_net) {
+ case 0xffff:
+ return "????";
+ case ATADDR_ANYNET:
+ return("*");
+ }
+ }
+ sprintf(mybuf,"%hu",ntohs(sat->sat_addr.s_net));
+ return mybuf;
+}
+
+static const char *
+at_pr_host(struct sockaddr_at *sat, int numeric)
+{
+static char mybuf[50];
+
+ if (!numeric) {
+ switch(sat->sat_addr.s_node) {
+ case ATADDR_BCAST:
+ return "bcast";
+ case ATADDR_ANYNODE:
+ return("*");
+ }
+ }
+ sprintf(mybuf,"%d",(unsigned int)sat->sat_addr.s_node);
+ return mybuf;
+}
+
+static const char *
+at_pr_port(struct sockaddr_at *sat)
+{
+static char mybuf[50];
+ struct servent *serv;
+
+ switch(sat->sat_port) {
+ case ATADDR_ANYPORT:
+ return("*");
+ case 0xff:
+ return "????";
+ default:
+ if (numeric_port) {
+ (void)snprintf(mybuf, sizeof(mybuf), "%d",
+ (unsigned int)sat->sat_port);
+ } else {
+ serv = getservbyport(sat->sat_port, "ddp");
+ if (serv == NULL)
+ (void)snprintf(mybuf, sizeof(mybuf), "%d",
+ (unsigned int) sat->sat_port);
+ else
+ (void) snprintf(mybuf, sizeof(mybuf), "%s",
+ serv->s_name);
+ }
+ }
+ return mybuf;
+}
+
+static char *
+at_pr_range(struct sockaddr_at *sat)
+{
+static char mybuf[50];
+
+ if(sat->sat_range.r_netrange.nr_firstnet
+ != sat->sat_range.r_netrange.nr_lastnet) {
+ sprintf(mybuf,"%d-%d",
+ ntohs(sat->sat_range.r_netrange.nr_firstnet),
+ ntohs(sat->sat_range.r_netrange.nr_lastnet));
+ } else {
+ sprintf(mybuf,"%d",
+ ntohs(sat->sat_range.r_netrange.nr_firstnet));
+ }
+ return mybuf;
+}
+
+
+/* what == 0 for addr only == 3 */
+/* 1 for net */
+/* 2 for host */
+/* 4 for port */
+/* 8 for numeric only */
+char *
+atalk_print(struct sockaddr *sa, int what)
+{
+ struct sockaddr_at *sat = (struct sockaddr_at *)sa;
+ static char mybuf[50];
+ int numeric = (what & 0x08);
+
+ mybuf[0] = 0;
+ switch (what & 0x13) {
+ case 0:
+ mybuf[0] = 0;
+ break;
+ case 1:
+ sprintf(mybuf,"%s",at_pr_net(sat, numeric));
+ break;
+ case 2:
+ sprintf(mybuf,"%s",at_pr_host(sat, numeric));
+ break;
+ case 3:
+ sprintf(mybuf,"%s.%s",
+ at_pr_net(sat, numeric),
+ at_pr_host(sat, numeric));
+ break;
+ case 0x10:
+ sprintf(mybuf,"%s", at_pr_range(sat));
+ }
+ if (what & 4) {
+ sprintf(mybuf+strlen(mybuf),".%s",at_pr_port(sat));
+ }
+ return mybuf;
+}
+
+char *
+atalk_print2(struct sockaddr *sa, struct sockaddr *mask, int what)
+{
+ int n;
+ static char buf[100];
+ struct sockaddr_at *sat1, *sat2;
+ struct sockaddr_at thesockaddr;
+ struct sockaddr *sa2;
+
+ sat1 = (struct sockaddr_at *)sa;
+ sat2 = (struct sockaddr_at *)mask;
+ sa2 = (struct sockaddr *)&thesockaddr;
+
+ thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net & sat2->sat_addr.s_net;
+ snprintf(buf, sizeof(buf), "%s", atalk_print(sa2, 1 |(what & 8)));
+ if(sat2->sat_addr.s_net != 0xFFFF) {
+ thesockaddr.sat_addr.s_net = sat1->sat_addr.s_net | ~sat2->sat_addr.s_net;
+ n = strlen(buf);
+ snprintf(buf + n, sizeof(buf) - n, "-%s", atalk_print(sa2, 1 |(what & 8)));
+ }
+ if(what & 2) {
+ n = strlen(buf);
+ snprintf(buf + n, sizeof(buf) - n, ".%s", atalk_print(sa, what & (~1)));
+ }
+ return(buf);
+}
+
+void
+atalkprotopr(u_long off __unused, const char *name, int af1 __unused,
+ int proto __unused)
+{
+ struct ddpcb *this, *next;
+
+ if (off == 0)
+ return;
+ kread(off, (char *)&this, sizeof (struct ddpcb *));
+ for ( ; this != NULL; this = next) {
+ kread((u_long)this, (char *)&ddpcb, sizeof (ddpcb));
+ next = ddpcb.ddp_next;
+#if 0
+ if (!aflag && atalk_nullhost(ddpcb.ddp_lsat) ) {
+ continue;
+ }
+#endif
+ kread((u_long)ddpcb.ddp_socket, (char *)&sockb, sizeof (sockb));
+ if (first) {
+ printf("Active ATALK connections");
+ if (aflag)
+ printf(" (including servers)");
+ putchar('\n');
+ if (Aflag)
+ printf("%-8.8s ", "PCB");
+ printf(Aflag ?
+ "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s %s\n" :
+ "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s %s\n",
+ "Proto", "Recv-Q", "Send-Q",
+ "Local Address", "Foreign Address", "(state)");
+ first = 0;
+ }
+ if (Aflag)
+ printf("%8lx ", (u_long) this);
+ printf("%-5.5s %6u %6u ", name, sockb.so_rcv.sb_cc,
+ sockb.so_snd.sb_cc);
+ printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
+ (struct sockaddr *)&ddpcb.ddp_lsat,7));
+ printf(Aflag?" %-18.18s":" %-22.22s", atalk_print(
+ (struct sockaddr *)&ddpcb.ddp_fsat,7));
+ putchar('\n');
+ }
+}
+
+#define ANY(x,y,z) if (x || sflag <= 1) \
+ printf("\t%lu %s%s%s\n",x,y,plural(x),z)
+
+/*
+ * Dump DDP statistics structure.
+ */
+void
+ddp_stats(u_long off __unused, const char *name, int af1 __unused,
+ int proto __unused)
+{
+ struct ddpstat ddpstat;
+
+ if (off == 0)
+ return;
+ kread(off, (char *)&ddpstat, sizeof (ddpstat));
+ printf("%s:\n", name);
+ ANY(ddpstat.ddps_short, "packet", " with short headers ");
+ ANY(ddpstat.ddps_long, "packet", " with long headers ");
+ ANY(ddpstat.ddps_nosum, "packet", " with no checksum ");
+ ANY(ddpstat.ddps_tooshort, "packet", " too short ");
+ ANY(ddpstat.ddps_badsum, "packet", " with bad checksum ");
+ ANY(ddpstat.ddps_toosmall, "packet", " with not enough data ");
+ ANY(ddpstat.ddps_forward, "packet", " forwarded ");
+ ANY(ddpstat.ddps_encap, "packet", " encapsulated ");
+ ANY(ddpstat.ddps_cantforward, "packet", " rcvd for unreachable dest ");
+ ANY(ddpstat.ddps_nosockspace, "packet", " dropped due to no socket space ");
+}
diff --git a/freebsd/usr.bin/netstat/bpf.c b/freebsd/usr.bin/netstat/bpf.c
new file mode 100644
index 00000000..3e3053d7
--- /dev/null
+++ b/freebsd/usr.bin/netstat/bpf.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 2005 Christian S.J. Peron
+ * 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/types.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/param.h>
+#ifndef __rtems__
+#include <sys/user.h>
+#endif
+
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#include <freebsd/net/bpf.h>
+#include <freebsd/net/bpfdesc.h>
+#else
+#include <net/if_var.h>
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+#endif
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "netstat.h"
+
+/* print bpf stats */
+
+static char *
+bpf_pidname(pid_t pid)
+{
+#ifdef __rtems__
+ return "rtems";
+#else
+ struct kinfo_proc newkp;
+ int error, mib[4];
+ size_t size;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PID;
+ mib[3] = pid;
+ size = sizeof(newkp);
+ error = sysctl(mib, 4, &newkp, &size, NULL, 0);
+ if (error < 0) {
+ warn("kern.proc.pid failed");
+ return (strdup("??????"));
+ }
+ return (strdup(newkp.ki_comm));
+#endif
+}
+
+static void
+bpf_flags(struct xbpf_d *bd, char *flagbuf)
+{
+
+ *flagbuf++ = bd->bd_promisc ? 'p' : '-';
+ *flagbuf++ = bd->bd_immediate ? 'i' : '-';
+ *flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f';
+ *flagbuf++ = (bd->bd_direction == BPF_D_IN) ? '-' :
+ ((bd->bd_direction == BPF_D_OUT) ? 'o' : 's');
+ *flagbuf++ = bd->bd_feedback ? 'b' : '-';
+ *flagbuf++ = bd->bd_async ? 'a' : '-';
+ *flagbuf++ = bd->bd_locked ? 'l' : '-';
+ *flagbuf++ = '\0';
+}
+
+void
+bpf_stats(char *ifname)
+{
+ struct xbpf_d *d, *bd, zerostat;
+ char *pname, flagbuf[12];
+ size_t size;
+
+ if (zflag) {
+ bzero(&zerostat, sizeof(zerostat));
+ if (sysctlbyname("net.bpf.stats", NULL, NULL,
+ &zerostat, sizeof(zerostat)) < 0)
+ warn("failed to zero bpf counters");
+ return;
+ }
+ if (sysctlbyname("net.bpf.stats", NULL, &size,
+ NULL, 0) < 0) {
+ warn("net.bpf.stats");
+ return;
+ }
+ if (size == 0)
+ return;
+ bd = malloc(size);
+ if (bd == NULL) {
+ warn("malloc failed");
+ return;
+ }
+ if (sysctlbyname("net.bpf.stats", bd, &size,
+ NULL, 0) < 0) {
+ warn("net.bpf.stats");
+ free(bd);
+ return;
+ }
+ (void) printf("%5s %6s %7s %9s %9s %9s %5s %5s %s\n",
+ "Pid", "Netif", "Flags", "Recv", "Drop", "Match", "Sblen",
+ "Hblen", "Command");
+ for (d = &bd[0]; d < &bd[size / sizeof(*d)]; d++) {
+ if (d->bd_structsize != sizeof(*d)) {
+ warnx("bpf_stats_extended: version mismatch");
+ return;
+ }
+ if (ifname && strcmp(ifname, d->bd_ifname) != 0)
+ continue;
+ bpf_flags(d, flagbuf);
+ pname = bpf_pidname(d->bd_pid);
+ (void) printf("%5d %6s %7s %9ju %9ju %9ju %5d %5d %s\n",
+ d->bd_pid, d->bd_ifname, flagbuf,
+ d->bd_rcount, d->bd_dcount, d->bd_fcount,
+ d->bd_slen, d->bd_hlen, pname);
+ free(pname);
+ }
+ free(bd);
+}
diff --git a/freebsd/usr.bin/netstat/if.c b/freebsd/usr.bin/netstat/if.c
new file mode 100644
index 00000000..2bf86b69
--- /dev/null
+++ b/freebsd/usr.bin/netstat/if.c
@@ -0,0 +1,752 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)if.c 8.3 (Berkeley) 4/28/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#include <sys/time.h>
+
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#else
+#include <net/if_var.h>
+#endif
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/ethernet.h>
+#ifdef __rtems__
+#include <freebsd/net/pfvar.h>
+#include <freebsd/net/if_pfsync.h>
+#include <netinet/in.h>
+#include <freebsd/netinet/in_var.h>
+/* IPX not on RTEMS */
+/* #include <netipx/ipx.h> */
+/* #include <netipx/ipx_if.h> */
+#else
+#include <net/pfvar.h>
+#include <net/if_pfsync.h>
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netipx/ipx.h>
+#include <netipx/ipx_if.h>
+#endif
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#include <libutil.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "netstat.h"
+
+#define YES 1
+#define NO 0
+
+static void sidewaysintpr(int, u_long);
+static void catchalarm(int);
+
+#ifdef INET6
+static char ntop_buf[INET6_ADDRSTRLEN]; /* for inet_ntop() */
+#endif
+
+/*
+ * Dump pfsync statistics structure.
+ */
+void
+pfsync_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct pfsyncstats pfsyncstat, zerostat;
+ size_t len = sizeof(struct pfsyncstats);
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.pfsync.stats", &pfsyncstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet.pfsync.stats");
+ return;
+ }
+ } else
+ kread(off, &pfsyncstat, len);
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (pfsyncstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)pfsyncstat.f, plural(pfsyncstat.f))
+#define p2(f, m) if (pfsyncstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)pfsyncstat.f)
+
+ p(pfsyncs_ipackets, "\t%ju packet%s received (IPv4)\n");
+ p(pfsyncs_ipackets6, "\t%ju packet%s received (IPv6)\n");
+ p(pfsyncs_badif, "\t\t%ju packet%s discarded for bad interface\n");
+ p(pfsyncs_badttl, "\t\t%ju packet%s discarded for bad ttl\n");
+ p(pfsyncs_hdrops, "\t\t%ju packet%s shorter than header\n");
+ p(pfsyncs_badver, "\t\t%ju packet%s discarded for bad version\n");
+ p(pfsyncs_badauth, "\t\t%ju packet%s discarded for bad HMAC\n");
+ p(pfsyncs_badact,"\t\t%ju packet%s discarded for bad action\n");
+ p(pfsyncs_badlen, "\t\t%ju packet%s discarded for short packet\n");
+ p(pfsyncs_badval, "\t\t%ju state%s discarded for bad values\n");
+ p(pfsyncs_stale, "\t\t%ju stale state%s\n");
+ p(pfsyncs_badstate, "\t\t%ju failed state lookup/insert%s\n");
+ p(pfsyncs_opackets, "\t%ju packet%s sent (IPv4)\n");
+ p(pfsyncs_opackets6, "\t%ju packet%s sent (IPv6)\n");
+ p2(pfsyncs_onomem, "\t\t%ju send failed due to mbuf memory error\n");
+ p2(pfsyncs_oerrors, "\t\t%ju send error\n");
+#undef p
+#undef p2
+}
+
+/*
+ * Display a formatted value, or a '-' in the same space.
+ */
+static void
+show_stat(const char *fmt, int width, u_long value, short showvalue)
+{
+ const char *lsep, *rsep;
+ char newfmt[32];
+
+ lsep = "";
+ if (strncmp(fmt, "LS", 2) == 0) {
+ lsep = " ";
+ fmt += 2;
+ }
+ rsep = " ";
+ if (strncmp(fmt, "NRS", 3) == 0) {
+ rsep = "";
+ fmt += 3;
+ }
+ if (showvalue == 0) {
+ /* Print just dash. */
+ sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
+ printf(newfmt, "-");
+ return;
+ }
+
+ if (hflag) {
+ char buf[5];
+
+ /* Format in human readable form. */
+ humanize_number(buf, sizeof(buf), (int64_t)value, "",
+ HN_AUTOSCALE, HN_NOSPACE | HN_DECIMAL);
+ sprintf(newfmt, "%s%%%ds%s", lsep, width, rsep);
+ printf(newfmt, buf);
+ } else {
+ /* Construct the format string. */
+ sprintf(newfmt, "%s%%%d%s%s", lsep, width, fmt, rsep);
+ printf(newfmt, value);
+ }
+}
+
+/*
+ * Print a description of the network interfaces.
+ */
+void
+intpr(int interval1, u_long ifnetaddr, void (*pfunc)(char *))
+{
+ struct ifnet ifnet;
+ struct ifnethead ifnethead;
+ union {
+ struct ifaddr ifa;
+ struct in_ifaddr in;
+#ifdef INET6
+ struct in6_ifaddr in6;
+#endif
+#ifndef __rtems__
+ struct ipx_ifaddr ipx;
+#endif
+ } ifaddr;
+ u_long ifaddraddr;
+ u_long ifaddrfound;
+ u_long ifnetfound;
+ u_long opackets;
+ u_long ipackets;
+ u_long obytes;
+ u_long ibytes;
+ u_long omcasts;
+ u_long imcasts;
+ u_long oerrors;
+ u_long ierrors;
+ u_long idrops;
+ u_long collisions;
+ short timer;
+ int drops;
+ struct sockaddr *sa = NULL;
+ char name[IFNAMSIZ];
+ short network_layer;
+ short link_layer;
+
+ if (ifnetaddr == 0) {
+ printf("ifnet: symbol not defined\n");
+ return;
+ }
+ if (interval1) {
+ sidewaysintpr(interval1, ifnetaddr);
+ return;
+ }
+ if (kread(ifnetaddr, (char *)&ifnethead, sizeof ifnethead) != 0)
+ return;
+ ifnetaddr = (u_long)TAILQ_FIRST(&ifnethead);
+ if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
+ return;
+
+ if (!pfunc) {
+ if (Wflag)
+ printf("%-7.7s", "Name");
+ else
+ printf("%-5.5s", "Name");
+ printf(" %5.5s %-13.13s %-17.17s %8.8s %5.5s %5.5s",
+ "Mtu", "Network", "Address", "Ipkts", "Ierrs", "Idrop");
+ if (bflag)
+ printf(" %10.10s","Ibytes");
+ printf(" %8.8s %5.5s", "Opkts", "Oerrs");
+ if (bflag)
+ printf(" %10.10s","Obytes");
+ printf(" %5s", "Coll");
+ if (tflag)
+ printf(" %s", "Time");
+ if (dflag)
+ printf(" %s", "Drop");
+ putchar('\n');
+ }
+ ifaddraddr = 0;
+ while (ifnetaddr || ifaddraddr) {
+ struct sockaddr_in *sockin;
+#ifdef INET6
+ struct sockaddr_in6 *sockin6;
+#endif
+ char *cp;
+ int n, m;
+
+ network_layer = 0;
+ link_layer = 0;
+
+ if (ifaddraddr == 0) {
+ ifnetfound = ifnetaddr;
+ if (kread(ifnetaddr, (char *)&ifnet, sizeof ifnet) != 0)
+ return;
+ strlcpy(name, ifnet.if_xname, sizeof(name));
+ ifnetaddr = (u_long)TAILQ_NEXT(&ifnet, if_link);
+ if (interface != 0 && strcmp(name, interface) != 0)
+ continue;
+ cp = index(name, '\0');
+
+ if (pfunc) {
+ (*pfunc)(name);
+ continue;
+ }
+
+ if ((ifnet.if_flags&IFF_UP) == 0)
+ *cp++ = '*';
+ *cp = '\0';
+ ifaddraddr = (u_long)TAILQ_FIRST(&ifnet.if_addrhead);
+ }
+ ifaddrfound = ifaddraddr;
+
+ /*
+ * Get the interface stats. These may get
+ * overriden below on a per-interface basis.
+ */
+ opackets = ifnet.if_opackets;
+ ipackets = ifnet.if_ipackets;
+ obytes = ifnet.if_obytes;
+ ibytes = ifnet.if_ibytes;
+ omcasts = ifnet.if_omcasts;
+ imcasts = ifnet.if_imcasts;
+ oerrors = ifnet.if_oerrors;
+ ierrors = ifnet.if_ierrors;
+ idrops = ifnet.if_iqdrops;
+ collisions = ifnet.if_collisions;
+ timer = ifnet.if_timer;
+ drops = ifnet.if_snd.ifq_drops;
+
+ if (ifaddraddr == 0) {
+ if (Wflag)
+ printf("%-7.7s", name);
+ else
+ printf("%-5.5s", name);
+ printf(" %5lu ", ifnet.if_mtu);
+ printf("%-13.13s ", "none");
+ printf("%-17.17s ", "none");
+ } else {
+ if (kread(ifaddraddr, (char *)&ifaddr, sizeof ifaddr)
+ != 0) {
+ ifaddraddr = 0;
+ continue;
+ }
+#define CP(x) ((char *)(x))
+ cp = (CP(ifaddr.ifa.ifa_addr) - CP(ifaddraddr)) +
+ CP(&ifaddr);
+ sa = (struct sockaddr *)cp;
+ if (af != AF_UNSPEC && sa->sa_family != af) {
+ ifaddraddr =
+ (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
+ continue;
+ }
+ if (Wflag)
+ printf("%-7.7s", name);
+ else
+ printf("%-5.5s", name);
+ printf(" %5lu ", ifnet.if_mtu);
+ switch (sa->sa_family) {
+ case AF_UNSPEC:
+ printf("%-13.13s ", "none");
+ printf("%-15.15s ", "none");
+ break;
+ case AF_INET:
+ sockin = (struct sockaddr_in *)sa;
+#ifdef notdef
+ /* can't use inet_makeaddr because kernel
+ * keeps nets unshifted.
+ */
+ in = inet_makeaddr(ifaddr.in.ia_subnet,
+ INADDR_ANY);
+ printf("%-13.13s ", netname(in.s_addr,
+ ifaddr.in.ia_subnetmask));
+#else
+ printf("%-13.13s ",
+ netname(htonl(ifaddr.in.ia_subnet),
+ ifaddr.in.ia_subnetmask));
+#endif
+ printf("%-17.17s ",
+ routename(sockin->sin_addr.s_addr));
+
+ network_layer = 1;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ sockin6 = (struct sockaddr_in6 *)sa;
+ printf("%-13.13s ",
+ netname6(&ifaddr.in6.ia_addr,
+ &ifaddr.in6.ia_prefixmask.sin6_addr));
+ printf("%-17.17s ",
+ inet_ntop(AF_INET6,
+ &sockin6->sin6_addr,
+ ntop_buf, sizeof(ntop_buf)));
+
+ network_layer = 1;
+ break;
+#endif /*INET6*/
+#ifndef __rtems__
+ case AF_IPX:
+ {
+ struct sockaddr_ipx *sipx =
+ (struct sockaddr_ipx *)sa;
+ u_long net;
+ char netnum[10];
+
+ *(union ipx_net *) &net = sipx->sipx_addr.x_net;
+ sprintf(netnum, "%lx", (u_long)ntohl(net));
+ printf("ipx:%-8s ", netnum);
+/* printf("ipx:%-8s ", netname(net, 0L)); */
+ printf("%-17s ",
+ ipx_phost((struct sockaddr *)sipx));
+ }
+
+ network_layer = 1;
+ break;
+#endif
+
+#ifndef __rtems__
+ case AF_APPLETALK:
+ printf("atalk:%-12.12s ",atalk_print(sa,0x10) );
+ printf("%-11.11s ",atalk_print(sa,0x0b) );
+ break;
+#endif
+ case AF_LINK:
+ {
+ struct sockaddr_dl *sdl =
+ (struct sockaddr_dl *)sa;
+ char linknum[10];
+ cp = (char *)LLADDR(sdl);
+ n = sdl->sdl_alen;
+ sprintf(linknum, "<Link#%d>", sdl->sdl_index);
+ m = printf("%-13.13s ", linknum);
+ }
+ goto hexprint;
+ default:
+ m = printf("(%d)", sa->sa_family);
+ for (cp = sa->sa_len + (char *)sa;
+ --cp > sa->sa_data && (*cp == 0);) {}
+ n = cp - sa->sa_data + 1;
+ cp = sa->sa_data;
+ hexprint:
+ while (--n >= 0)
+ m += printf("%02x%c", *cp++ & 0xff,
+ n > 0 ? ':' : ' ');
+ m = 32 - m;
+ while (m-- > 0)
+ putchar(' ');
+
+ link_layer = 1;
+ break;
+ }
+
+ /*
+ * Fixup the statistics for interfaces that
+ * update stats for their network addresses
+ */
+ if (network_layer) {
+ opackets = ifaddr.in.ia_ifa.if_opackets;
+ ipackets = ifaddr.in.ia_ifa.if_ipackets;
+ obytes = ifaddr.in.ia_ifa.if_obytes;
+ ibytes = ifaddr.in.ia_ifa.if_ibytes;
+ }
+
+ ifaddraddr = (u_long)TAILQ_NEXT(&ifaddr.ifa, ifa_link);
+ }
+
+ show_stat("lu", 8, ipackets, link_layer|network_layer);
+ show_stat("lu", 5, ierrors, link_layer);
+ show_stat("lu", 5, idrops, link_layer);
+ if (bflag)
+ show_stat("lu", 10, ibytes, link_layer|network_layer);
+
+ show_stat("lu", 8, opackets, link_layer|network_layer);
+ show_stat("lu", 5, oerrors, link_layer);
+ if (bflag)
+ show_stat("lu", 10, obytes, link_layer|network_layer);
+
+ show_stat("NRSlu", 5, collisions, link_layer);
+ if (tflag)
+ show_stat("LSd", 4, timer, link_layer);
+ if (dflag)
+ show_stat("LSd", 4, drops, link_layer);
+ putchar('\n');
+
+ if (aflag && ifaddrfound) {
+ /*
+ * Print family's multicast addresses
+ */
+ struct ifmultiaddr *multiaddr;
+ struct ifmultiaddr ifma;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#ifdef INET6
+ struct sockaddr_in6 in6;
+#endif /* INET6 */
+ struct sockaddr_dl dl;
+ } msa;
+ const char *fmt;
+
+ TAILQ_FOREACH(multiaddr, &ifnet.if_multiaddrs, ifma_link) {
+ if (kread((u_long)multiaddr, (char *)&ifma,
+ sizeof ifma) != 0)
+ break;
+ multiaddr = &ifma;
+ if (kread((u_long)ifma.ifma_addr, (char *)&msa,
+ sizeof msa) != 0)
+ break;
+ if (msa.sa.sa_family != sa->sa_family)
+ continue;
+
+ fmt = 0;
+ switch (msa.sa.sa_family) {
+ case AF_INET:
+ fmt = routename(msa.in.sin_addr.s_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ printf("%*s %-19.19s(refs: %d)\n",
+ Wflag ? 27 : 25, "",
+ inet_ntop(AF_INET6,
+ &msa.in6.sin6_addr,
+ ntop_buf,
+ sizeof(ntop_buf)),
+ ifma.ifma_refcount);
+ break;
+#endif /* INET6 */
+ case AF_LINK:
+ switch (msa.dl.sdl_type) {
+ case IFT_ETHER:
+ case IFT_FDDI:
+ fmt = ether_ntoa(
+ (struct ether_addr *)
+ LLADDR(&msa.dl));
+ break;
+ }
+ break;
+ }
+ if (fmt) {
+ printf("%*s %-17.17s",
+ Wflag ? 27 : 25, "", fmt);
+ if (msa.sa.sa_family == AF_LINK) {
+ printf(" %8lu", imcasts);
+ printf("%*s",
+ bflag ? 17 : 6, "");
+ printf(" %8lu", omcasts);
+ }
+ putchar('\n');
+ }
+ }
+ }
+ }
+}
+
+struct iftot {
+ SLIST_ENTRY(iftot) chain;
+ char ift_name[IFNAMSIZ]; /* interface name */
+ u_long ift_ip; /* input packets */
+ u_long ift_ie; /* input errors */
+ u_long ift_id; /* input drops */
+ u_long ift_op; /* output packets */
+ u_long ift_oe; /* output errors */
+ u_long ift_co; /* collisions */
+ u_int ift_dr; /* drops */
+ u_long ift_ib; /* input bytes */
+ u_long ift_ob; /* output bytes */
+};
+
+u_char signalled; /* set if alarm goes off "early" */
+
+/*
+ * Print a running summary of interface statistics.
+ * Repeat display every interval1 seconds, showing statistics
+ * collected over that interval. Assumes that interval1 is non-zero.
+ * First line printed at top of screen is always cumulative.
+ * XXX - should be rewritten to use ifmib(4).
+ */
+static void
+sidewaysintpr(int interval1, u_long off)
+{
+ struct ifnet ifnet;
+ u_long firstifnet;
+ struct ifnethead ifnethead;
+ struct itimerval interval_it;
+ struct iftot *iftot, *ip, *ipn, *total, *sum, *interesting;
+ int line;
+ int oldmask, first;
+ u_long interesting_off;
+
+ if (kread(off, (char *)&ifnethead, sizeof ifnethead) != 0)
+ return;
+ firstifnet = (u_long)TAILQ_FIRST(&ifnethead);
+
+ if ((iftot = malloc(sizeof(struct iftot))) == NULL) {
+ printf("malloc failed\n");
+ exit(1);
+ }
+ memset(iftot, 0, sizeof(struct iftot));
+
+ interesting = NULL;
+ interesting_off = 0;
+ for (off = firstifnet, ip = iftot; off;) {
+ char name[IFNAMSIZ];
+
+ if (kread(off, (char *)&ifnet, sizeof ifnet) != 0)
+ break;
+ strlcpy(name, ifnet.if_xname, sizeof(name));
+ if (interface && strcmp(name, interface) == 0) {
+ interesting = ip;
+ interesting_off = off;
+ }
+ snprintf(ip->ift_name, sizeof(ip->ift_name), "(%s)", name);;
+ if ((ipn = malloc(sizeof(struct iftot))) == NULL) {
+ printf("malloc failed\n");
+ exit(1);
+ }
+ memset(ipn, 0, sizeof(struct iftot));
+ SLIST_NEXT(ip, chain) = ipn;
+ ip = ipn;
+ off = (u_long)TAILQ_NEXT(&ifnet, if_link);
+ }
+ if (interface && interesting == NULL)
+ errx(1, "%s: unknown interface", interface);
+ if ((total = malloc(sizeof(struct iftot))) == NULL) {
+ printf("malloc failed\n");
+ exit(1);
+ }
+ memset(total, 0, sizeof(struct iftot));
+ if ((sum = malloc(sizeof(struct iftot))) == NULL) {
+ printf("malloc failed\n");
+ exit(1);
+ }
+ memset(sum, 0, sizeof(struct iftot));
+
+ (void)signal(SIGALRM, catchalarm);
+ signalled = NO;
+ interval_it.it_interval.tv_sec = interval1;
+ interval_it.it_interval.tv_usec = 0;
+ interval_it.it_value = interval_it.it_interval;
+ setitimer(ITIMER_REAL, &interval_it, NULL);
+ first = 1;
+banner:
+ printf("%17s %14s %16s", "input",
+ interesting ? interesting->ift_name : "(Total)", "output");
+ putchar('\n');
+ printf("%10s %5s %5s %10s %10s %5s %10s %5s",
+ "packets", "errs", "idrops", "bytes", "packets", "errs", "bytes",
+ "colls");
+ if (dflag)
+ printf(" %5.5s", "drops");
+ putchar('\n');
+ fflush(stdout);
+ line = 0;
+loop:
+ if (interesting != NULL) {
+ ip = interesting;
+ if (kread(interesting_off, (char *)&ifnet, sizeof ifnet) != 0) {
+ printf("???\n");
+ exit(1);
+ };
+ if (!first) {
+ show_stat("lu", 10, ifnet.if_ipackets - ip->ift_ip, 1);
+ show_stat("lu", 5, ifnet.if_ierrors - ip->ift_ie, 1);
+ show_stat("lu", 5, ifnet.if_iqdrops - ip->ift_id, 1);
+ show_stat("lu", 10, ifnet.if_ibytes - ip->ift_ib, 1);
+ show_stat("lu", 10, ifnet.if_opackets - ip->ift_op, 1);
+ show_stat("lu", 5, ifnet.if_oerrors - ip->ift_oe, 1);
+ show_stat("lu", 10, ifnet.if_obytes - ip->ift_ob, 1);
+ show_stat("NRSlu", 5,
+ ifnet.if_collisions - ip->ift_co, 1);
+ if (dflag)
+ show_stat("LSu", 5,
+ ifnet.if_snd.ifq_drops - ip->ift_dr, 1);
+ }
+ ip->ift_ip = ifnet.if_ipackets;
+ ip->ift_ie = ifnet.if_ierrors;
+ ip->ift_id = ifnet.if_iqdrops;
+ ip->ift_ib = ifnet.if_ibytes;
+ ip->ift_op = ifnet.if_opackets;
+ ip->ift_oe = ifnet.if_oerrors;
+ ip->ift_ob = ifnet.if_obytes;
+ ip->ift_co = ifnet.if_collisions;
+ ip->ift_dr = ifnet.if_snd.ifq_drops;
+ } else {
+ sum->ift_ip = 0;
+ sum->ift_ie = 0;
+ sum->ift_id = 0;
+ sum->ift_ib = 0;
+ sum->ift_op = 0;
+ sum->ift_oe = 0;
+ sum->ift_ob = 0;
+ sum->ift_co = 0;
+ sum->ift_dr = 0;
+ for (off = firstifnet, ip = iftot;
+ off && SLIST_NEXT(ip, chain) != NULL;
+ ip = SLIST_NEXT(ip, chain)) {
+ if (kread(off, (char *)&ifnet, sizeof ifnet) != 0) {
+ off = 0;
+ continue;
+ }
+ sum->ift_ip += ifnet.if_ipackets;
+ sum->ift_ie += ifnet.if_ierrors;
+ sum->ift_id += ifnet.if_iqdrops;
+ sum->ift_ib += ifnet.if_ibytes;
+ sum->ift_op += ifnet.if_opackets;
+ sum->ift_oe += ifnet.if_oerrors;
+ sum->ift_ob += ifnet.if_obytes;
+ sum->ift_co += ifnet.if_collisions;
+ sum->ift_dr += ifnet.if_snd.ifq_drops;
+ off = (u_long)TAILQ_NEXT(&ifnet, if_link);
+ }
+ if (!first) {
+ show_stat("lu", 10, sum->ift_ip - total->ift_ip, 1);
+ show_stat("lu", 5, sum->ift_ie - total->ift_ie, 1);
+ show_stat("lu", 5, sum->ift_id - total->ift_id, 1);
+ show_stat("lu", 10, sum->ift_ib - total->ift_ib, 1);
+ show_stat("lu", 10, sum->ift_op - total->ift_op, 1);
+ show_stat("lu", 5, sum->ift_oe - total->ift_oe, 1);
+ show_stat("lu", 10, sum->ift_ob - total->ift_ob, 1);
+ show_stat("NRSlu", 5, sum->ift_co - total->ift_co, 1);
+ if (dflag)
+ show_stat("LSu", 5,
+ sum->ift_dr - total->ift_dr, 1);
+ }
+ *total = *sum;
+ }
+ if (!first)
+ putchar('\n');
+ fflush(stdout);
+ if ((noutputs != 0) && (--noutputs == 0))
+ exit(0);
+#ifdef __rtems__
+ {
+ sigset_t oldmask, desired, empty;
+
+ sigemptyset(&empty);
+ sigemptyset(&desired);
+ sigaddset(&desired, SIGALRM);
+ sigprocmask(SIG_BLOCK, &desired, &oldmask);
+ while (!signalled)
+ sigsuspend(&desired);
+ signalled = NO;
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
+ }
+#else
+ oldmask = sigblock(sigmask(SIGALRM));
+ while (!signalled)
+ sigpause(0);
+ signalled = NO;
+ sigsetmask(oldmask);
+#endif
+ line++;
+ first = 0;
+ if (line == 21)
+ goto banner;
+ else
+ goto loop;
+ /*NOTREACHED*/
+}
+
+/*
+ * Set a flag to indicate that a signal from the periodic itimer has been
+ * caught.
+ */
+static void
+catchalarm(int signo __unused)
+{
+ signalled = YES;
+}
diff --git a/freebsd/usr.bin/netstat/inet.c b/freebsd/usr.bin/netstat/inet.c
new file mode 100644
index 00000000..f6d111f3
--- /dev/null
+++ b/freebsd/usr.bin/netstat/inet.c
@@ -0,0 +1,1312 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#ifdef __rtems__
+#include <freebsd/sys/domain.h>
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/domain.h>
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if_arp.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#ifdef __rtems__
+#include <freebsd/netinet/ip_carp.h>
+#else
+#include <netinet/ip_carp.h>
+#endif
+#ifdef INET6
+#include <netinet/ip6.h>
+#endif /* INET6 */
+#ifdef __rtems__
+#include <freebsd/netinet/in_pcb.h>
+#else
+#include <netinet/in_pcb.h>
+#endif
+#include <netinet/ip_icmp.h>
+#ifdef __rtems__
+#include <freebsd/netinet/icmp_var.h>
+#include <freebsd/netinet/igmp_var.h>
+#include <freebsd/netinet/ip_var.h>
+#include <freebsd/netinet/pim_var.h>
+#include <netinet/tcp.h>
+#include <freebsd/netinet/tcpip.h>
+#include <freebsd/netinet/tcp_seq.h>
+#define TCPSTATES
+#include <freebsd/netinet/tcp_fsm.h>
+#include <freebsd/netinet/tcp_timer.h>
+#include <freebsd/netinet/tcp_var.h>
+#include <freebsd/netinet/tcp_debug.h>
+#include <netinet/udp.h>
+#include <freebsd/netinet/udp_var.h>
+#else
+#include <netinet/icmp_var.h>
+#include <netinet/igmp_var.h>
+#include <netinet/ip_var.h>
+#include <netinet/pim_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+#include <netinet/tcp_seq.h>
+#define TCPSTATES
+#include <netinet/tcp_fsm.h>
+#include <netinet/tcp_timer.h>
+#include <netinet/tcp_var.h>
+#include <netinet/tcp_debug.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#endif
+
+#include <arpa/inet.h>
+#include <err.h>
+#include <errno.h>
+#include <libutil.h>
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+char *inetname(struct in_addr *);
+void inetprint(struct in_addr *, int, const char *, int);
+#ifdef INET6
+static int udp_done, tcp_done;
+#endif /* INET6 */
+
+static int
+pcblist_sysctl(int proto, char **bufp, int istcp)
+{
+ const char *mibvar;
+ char *buf;
+ size_t len;
+
+ switch (proto) {
+ case IPPROTO_TCP:
+ mibvar = "net.inet.tcp.pcblist";
+ break;
+ case IPPROTO_UDP:
+ mibvar = "net.inet.udp.pcblist";
+ break;
+ case IPPROTO_DIVERT:
+ mibvar = "net.inet.divert.pcblist";
+ break;
+ default:
+ mibvar = "net.inet.raw.pcblist";
+ break;
+ }
+
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ return (0);
+ }
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (0);
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ free(buf);
+ return (0);
+ }
+ *bufp = buf;
+ return (1);
+}
+
+/*
+ * Copied directly from uipc_socket2.c. We leave out some fields that are in
+ * nested structures that aren't used to avoid extra work.
+ */
+static void
+sbtoxsockbuf(struct sockbuf *sb, struct xsockbuf *xsb)
+{
+ xsb->sb_cc = sb->sb_cc;
+ xsb->sb_hiwat = sb->sb_hiwat;
+ xsb->sb_mbcnt = sb->sb_mbcnt;
+ xsb->sb_mcnt = sb->sb_mcnt;
+ xsb->sb_ccnt = sb->sb_ccnt;
+ xsb->sb_mbmax = sb->sb_mbmax;
+ xsb->sb_lowat = sb->sb_lowat;
+ xsb->sb_flags = sb->sb_flags;
+ xsb->sb_timeo = sb->sb_timeo;
+}
+
+int
+sotoxsocket(struct socket *so, struct xsocket *xso)
+{
+ struct protosw proto;
+ struct domain domain;
+
+ bzero(xso, sizeof *xso);
+ xso->xso_len = sizeof *xso;
+ xso->xso_so = so;
+ xso->so_type = so->so_type;
+ xso->so_options = so->so_options;
+ xso->so_linger = so->so_linger;
+ xso->so_state = so->so_state;
+ xso->so_pcb = so->so_pcb;
+ if (kread((uintptr_t)so->so_proto, &proto, sizeof(proto)) != 0)
+ return (-1);
+ xso->xso_protocol = proto.pr_protocol;
+ if (kread((uintptr_t)proto.pr_domain, &domain, sizeof(domain)) != 0)
+ return (-1);
+ xso->xso_family = domain.dom_family;
+ xso->so_qlen = so->so_qlen;
+ xso->so_incqlen = so->so_incqlen;
+ xso->so_qlimit = so->so_qlimit;
+ xso->so_timeo = so->so_timeo;
+ xso->so_error = so->so_error;
+ xso->so_oobmark = so->so_oobmark;
+ sbtoxsockbuf(&so->so_snd, &xso->so_snd);
+ sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
+ return (0);
+}
+
+static int
+pcblist_kvm(u_long off, char **bufp, int istcp)
+{
+ struct inpcbinfo pcbinfo;
+ struct inpcbhead listhead;
+ struct inpcb *inp;
+ struct xinpcb xi;
+ struct xinpgen xig;
+ struct xtcpcb xt;
+ struct socket so;
+ struct xsocket *xso;
+ char *buf, *p;
+ size_t len;
+
+ if (off == 0)
+ return (0);
+ kread(off, &pcbinfo, sizeof(pcbinfo));
+ if (istcp)
+ len = 2 * sizeof(xig) +
+ (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+ sizeof(struct xtcpcb);
+ else
+ len = 2 * sizeof(xig) +
+ (pcbinfo.ipi_count + pcbinfo.ipi_count / 8) *
+ sizeof(struct xinpcb);
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (0);
+ }
+ p = buf;
+
+#define COPYOUT(obj, size) do { \
+ if (len < (size)) { \
+ warnx("buffer size exceeded"); \
+ goto fail; \
+ } \
+ bcopy((obj), p, (size)); \
+ len -= (size); \
+ p += (size); \
+} while (0)
+
+#define KREAD(off, buf, len) do { \
+ if (kread((uintptr_t)(off), (buf), (len)) != 0) \
+ goto fail; \
+} while (0)
+
+ /* Write out header. */
+ xig.xig_len = sizeof xig;
+ xig.xig_count = pcbinfo.ipi_count;
+ xig.xig_gen = pcbinfo.ipi_gencnt;
+ xig.xig_sogen = 0;
+ COPYOUT(&xig, sizeof xig);
+
+ /* Walk the PCB list. */
+ xt.xt_len = sizeof xt;
+ xi.xi_len = sizeof xi;
+ if (istcp)
+ xso = &xt.xt_socket;
+ else
+ xso = &xi.xi_socket;
+ KREAD(pcbinfo.ipi_listhead, &listhead, sizeof(listhead));
+ LIST_FOREACH(inp, &listhead, inp_list) {
+ if (istcp) {
+ KREAD(inp, &xt.xt_inp, sizeof(*inp));
+ inp = &xt.xt_inp;
+ } else {
+ KREAD(inp, &xi.xi_inp, sizeof(*inp));
+ inp = &xi.xi_inp;
+ }
+
+ if (inp->inp_gencnt > pcbinfo.ipi_gencnt)
+ continue;
+
+ if (istcp) {
+ if (inp->inp_ppcb == NULL)
+ bzero(&xt.xt_tp, sizeof xt.xt_tp);
+ else if (inp->inp_flags & INP_TIMEWAIT) {
+ bzero(&xt.xt_tp, sizeof xt.xt_tp);
+ xt.xt_tp.t_state = TCPS_TIME_WAIT;
+ } else
+ KREAD(inp->inp_ppcb, &xt.xt_tp,
+ sizeof xt.xt_tp);
+ }
+ if (inp->inp_socket) {
+ KREAD(inp->inp_socket, &so, sizeof(so));
+ if (sotoxsocket(&so, xso) != 0)
+ goto fail;
+ } else {
+ bzero(xso, sizeof(*xso));
+ if (istcp)
+ xso->xso_protocol = IPPROTO_TCP;
+ }
+ if (istcp)
+ COPYOUT(&xt, sizeof xt);
+ else
+ COPYOUT(&xi, sizeof xi);
+ }
+
+ /* Reread the pcbinfo and write out the footer. */
+ kread(off, &pcbinfo, sizeof(pcbinfo));
+ xig.xig_count = pcbinfo.ipi_count;
+ xig.xig_gen = pcbinfo.ipi_gencnt;
+ COPYOUT(&xig, sizeof xig);
+
+ *bufp = buf;
+ return (1);
+
+fail:
+ free(buf);
+ return (0);
+#undef COPYOUT
+#undef KREAD
+}
+
+/*
+ * Print a summary of connections related to an Internet
+ * protocol. For TCP, also give state of connection.
+ * Listening processes (aflag) are suppressed unless the
+ * -a (all) flag is specified.
+ */
+void
+protopr(u_long off, const char *name, int af1, int proto)
+{
+ int istcp;
+ static int first = 1;
+ char *buf;
+ const char *vchar;
+ struct tcpcb *tp = NULL;
+ struct inpcb *inp;
+ struct xinpgen *xig, *oxig;
+ struct xsocket *so;
+
+ istcp = 0;
+ switch (proto) {
+ case IPPROTO_TCP:
+#ifdef INET6
+ if (tcp_done != 0)
+ return;
+ else
+ tcp_done = 1;
+#endif
+ istcp = 1;
+ break;
+ case IPPROTO_UDP:
+#ifdef INET6
+ if (udp_done != 0)
+ return;
+ else
+ udp_done = 1;
+#endif
+ break;
+ }
+ if (live) {
+ if (!pcblist_sysctl(proto, &buf, istcp))
+ return;
+ } else {
+ if (!pcblist_kvm(off, &buf, istcp))
+ return;
+ }
+
+ oxig = xig = (struct xinpgen *)buf;
+ for (xig = (struct xinpgen *)((char *)xig + xig->xig_len);
+ xig->xig_len > sizeof(struct xinpgen);
+ xig = (struct xinpgen *)((char *)xig + xig->xig_len)) {
+ if (istcp) {
+ tp = &((struct xtcpcb *)xig)->xt_tp;
+ inp = &((struct xtcpcb *)xig)->xt_inp;
+ so = &((struct xtcpcb *)xig)->xt_socket;
+ } else {
+ inp = &((struct xinpcb *)xig)->xi_inp;
+ so = &((struct xinpcb *)xig)->xi_socket;
+ }
+
+ /* Ignore sockets for protocols other than the desired one. */
+ if (so->xso_protocol != proto)
+ continue;
+
+ /* Ignore PCBs which were freed during copyout. */
+ if (inp->inp_gencnt > oxig->xig_gen)
+ continue;
+
+ if ((af1 == AF_INET && (inp->inp_vflag & INP_IPV4) == 0)
+#ifdef INET6
+ || (af1 == AF_INET6 && (inp->inp_vflag & INP_IPV6) == 0)
+#endif /* INET6 */
+ || (af1 == AF_UNSPEC && ((inp->inp_vflag & INP_IPV4) == 0
+#ifdef INET6
+ && (inp->inp_vflag & INP_IPV6) == 0
+#endif /* INET6 */
+ ))
+ )
+ continue;
+ if (!aflag &&
+ (
+ (istcp && tp->t_state == TCPS_LISTEN)
+ || (af1 == AF_INET &&
+ inet_lnaof(inp->inp_laddr) == INADDR_ANY)
+#ifdef INET6
+ || (af1 == AF_INET6 &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+#endif /* INET6 */
+ || (af1 == AF_UNSPEC &&
+ (((inp->inp_vflag & INP_IPV4) != 0 &&
+ inet_lnaof(inp->inp_laddr) == INADDR_ANY)
+#ifdef INET6
+ || ((inp->inp_vflag & INP_IPV6) != 0 &&
+ IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr))
+#endif
+ ))
+ ))
+ continue;
+
+ if (first) {
+ if (!Lflag) {
+ printf("Active Internet connections");
+ if (aflag)
+ printf(" (including servers)");
+ } else
+ printf(
+ "Current listen queue sizes (qlen/incqlen/maxqlen)");
+ putchar('\n');
+ if (Aflag)
+ printf("%-8.8s ", "Tcpcb");
+ if (Lflag)
+ printf("%-5.5s %-14.14s %-22.22s\n",
+ "Proto", "Listen", "Local Address");
+ else {
+ printf((Aflag && !Wflag) ?
+ "%-5.5s %-6.6s %-6.6s %-18.18s %-18.18s" :
+ "%-5.5s %-6.6s %-6.6s %-22.22s %-22.22s",
+ "Proto", "Recv-Q", "Send-Q",
+ "Local Address", "Foreign Address");
+ if (xflag)
+ printf("%-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %-6.6s %s\n",
+ "R-MBUF", "S-MBUF", "R-CLUS",
+ "S-CLUS", "R-HIWA", "S-HIWA",
+ "R-LOWA", "S-LOWA", "R-BCNT",
+ "S-BCNT", "R-BMAX", "S-BMAX",
+ "(state)");
+ else
+ printf("(state)\n");
+ }
+ first = 0;
+ }
+ if (Lflag && so->so_qlimit == 0)
+ continue;
+ if (Aflag) {
+ if (istcp)
+ printf("%8lx ", (u_long)inp->inp_ppcb);
+ else
+ printf("%8lx ", (u_long)so->so_pcb);
+ }
+#ifdef INET6
+ if ((inp->inp_vflag & INP_IPV6) != 0)
+ vchar = ((inp->inp_vflag & INP_IPV4) != 0) ?
+ "46" : "6 ";
+ else
+#endif
+ vchar = ((inp->inp_vflag & INP_IPV4) != 0) ?
+ "4 " : " ";
+ printf("%-3.3s%-2.2s ", name, vchar);
+ if (Lflag) {
+ char buf1[15];
+
+ snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
+ so->so_incqlen, so->so_qlimit);
+ printf("%-14.14s ", buf1);
+ } else {
+ printf("%6u %6u ", so->so_rcv.sb_cc, so->so_snd.sb_cc);
+ }
+ if (numeric_port) {
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+ name, 1);
+ if (!Lflag)
+ inetprint(&inp->inp_faddr,
+ (int)inp->inp_fport, name, 1);
+ }
+#ifdef INET6
+ else if (inp->inp_vflag & INP_IPV6) {
+ inet6print(&inp->in6p_laddr,
+ (int)inp->inp_lport, name, 1);
+ if (!Lflag)
+ inet6print(&inp->in6p_faddr,
+ (int)inp->inp_fport, name, 1);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ } else if (inp->inp_flags & INP_ANONPORT) {
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+ name, 1);
+ if (!Lflag)
+ inetprint(&inp->inp_faddr,
+ (int)inp->inp_fport, name, 0);
+ }
+#ifdef INET6
+ else if (inp->inp_vflag & INP_IPV6) {
+ inet6print(&inp->in6p_laddr,
+ (int)inp->inp_lport, name, 1);
+ if (!Lflag)
+ inet6print(&inp->in6p_faddr,
+ (int)inp->inp_fport, name, 0);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ } else {
+ if (inp->inp_vflag & INP_IPV4) {
+ inetprint(&inp->inp_laddr, (int)inp->inp_lport,
+ name, 0);
+ if (!Lflag)
+ inetprint(&inp->inp_faddr,
+ (int)inp->inp_fport, name,
+ inp->inp_lport != inp->inp_fport);
+ }
+#ifdef INET6
+ else if (inp->inp_vflag & INP_IPV6) {
+ inet6print(&inp->in6p_laddr,
+ (int)inp->inp_lport, name, 0);
+ if (!Lflag)
+ inet6print(&inp->in6p_faddr,
+ (int)inp->inp_fport, name,
+ inp->inp_lport != inp->inp_fport);
+ } /* else nothing printed now */
+#endif /* INET6 */
+ }
+ if (xflag) {
+ if (Lflag)
+ printf("%21s %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ",
+ " ",
+ so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
+ so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
+ so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
+ so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
+ so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
+ so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
+ else
+ printf("%6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u %6u ",
+ so->so_rcv.sb_mcnt, so->so_snd.sb_mcnt,
+ so->so_rcv.sb_ccnt, so->so_snd.sb_ccnt,
+ so->so_rcv.sb_hiwat, so->so_snd.sb_hiwat,
+ so->so_rcv.sb_lowat, so->so_snd.sb_lowat,
+ so->so_rcv.sb_mbcnt, so->so_snd.sb_mbcnt,
+ so->so_rcv.sb_mbmax, so->so_snd.sb_mbmax);
+ }
+ if (istcp && !Lflag) {
+ if (tp->t_state < 0 || tp->t_state >= TCP_NSTATES)
+ printf("%d", tp->t_state);
+ else {
+ printf("%s", tcpstates[tp->t_state]);
+#if defined(TF_NEEDSYN) && defined(TF_NEEDFIN)
+ /* Show T/TCP `hidden state' */
+ if (tp->t_flags & (TF_NEEDSYN|TF_NEEDFIN))
+ putchar('*');
+#endif /* defined(TF_NEEDSYN) && defined(TF_NEEDFIN) */
+ }
+ }
+ putchar('\n');
+ }
+ if (xig != oxig && xig->xig_gen != oxig->xig_gen) {
+ if (oxig->xig_count > xig->xig_count) {
+ printf("Some %s sockets may have been deleted.\n",
+ name);
+ } else if (oxig->xig_count < xig->xig_count) {
+ printf("Some %s sockets may have been created.\n",
+ name);
+ } else {
+ printf(
+ "Some %s sockets may have been created or deleted.\n",
+ name);
+ }
+ }
+ free(buf);
+}
+
+/*
+ * Dump TCP statistics structure.
+ */
+void
+tcp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct tcpstat tcpstat, zerostat;
+ size_t len = sizeof tcpstat;
+
+#ifdef INET6
+ if (tcp_done != 0)
+ return;
+ else
+ tcp_done = 1;
+#endif
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.tcp.stats", &tcpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.tcp.stats");
+ return;
+ }
+ } else
+ kread(off, &tcpstat, len);
+
+ printf ("%s:\n", name);
+
+#define p(f, m) if (tcpstat.f || sflag <= 1) \
+ printf(m, tcpstat.f, plural(tcpstat.f))
+#define p1a(f, m) if (tcpstat.f || sflag <= 1) \
+ printf(m, tcpstat.f)
+#define p2(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
+ printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2, plural(tcpstat.f2))
+#define p2a(f1, f2, m) if (tcpstat.f1 || tcpstat.f2 || sflag <= 1) \
+ printf(m, tcpstat.f1, plural(tcpstat.f1), tcpstat.f2)
+#define p3(f, m) if (tcpstat.f || sflag <= 1) \
+ printf(m, tcpstat.f, pluralies(tcpstat.f))
+
+ p(tcps_sndtotal, "\t%lu packet%s sent\n");
+ p2(tcps_sndpack,tcps_sndbyte, "\t\t%lu data packet%s (%lu byte%s)\n");
+ p2(tcps_sndrexmitpack, tcps_sndrexmitbyte,
+ "\t\t%lu data packet%s (%lu byte%s) retransmitted\n");
+ p(tcps_sndrexmitbad,
+ "\t\t%lu data packet%s unnecessarily retransmitted\n");
+ p(tcps_mturesent, "\t\t%lu resend%s initiated by MTU discovery\n");
+ p2a(tcps_sndacks, tcps_delack,
+ "\t\t%lu ack-only packet%s (%lu delayed)\n");
+ p(tcps_sndurg, "\t\t%lu URG only packet%s\n");
+ p(tcps_sndprobe, "\t\t%lu window probe packet%s\n");
+ p(tcps_sndwinup, "\t\t%lu window update packet%s\n");
+ p(tcps_sndctrl, "\t\t%lu control packet%s\n");
+ p(tcps_rcvtotal, "\t%lu packet%s received\n");
+ p2(tcps_rcvackpack, tcps_rcvackbyte,
+ "\t\t%lu ack%s (for %lu byte%s)\n");
+ p(tcps_rcvdupack, "\t\t%lu duplicate ack%s\n");
+ p(tcps_rcvacktoomuch, "\t\t%lu ack%s for unsent data\n");
+ p2(tcps_rcvpack, tcps_rcvbyte,
+ "\t\t%lu packet%s (%lu byte%s) received in-sequence\n");
+ p2(tcps_rcvduppack, tcps_rcvdupbyte,
+ "\t\t%lu completely duplicate packet%s (%lu byte%s)\n");
+ p(tcps_pawsdrop, "\t\t%lu old duplicate packet%s\n");
+ p2(tcps_rcvpartduppack, tcps_rcvpartdupbyte,
+ "\t\t%lu packet%s with some dup. data (%lu byte%s duped)\n");
+ p2(tcps_rcvoopack, tcps_rcvoobyte,
+ "\t\t%lu out-of-order packet%s (%lu byte%s)\n");
+ p2(tcps_rcvpackafterwin, tcps_rcvbyteafterwin,
+ "\t\t%lu packet%s (%lu byte%s) of data after window\n");
+ p(tcps_rcvwinprobe, "\t\t%lu window probe%s\n");
+ p(tcps_rcvwinupd, "\t\t%lu window update packet%s\n");
+ p(tcps_rcvafterclose, "\t\t%lu packet%s received after close\n");
+ p(tcps_rcvbadsum, "\t\t%lu discarded for bad checksum%s\n");
+ p(tcps_rcvbadoff, "\t\t%lu discarded for bad header offset field%s\n");
+ p1a(tcps_rcvshort, "\t\t%lu discarded because packet too short\n");
+ p1a(tcps_rcvmemdrop, "\t\t%lu discarded due to memory problems\n");
+ p(tcps_connattempt, "\t%lu connection request%s\n");
+ p(tcps_accepts, "\t%lu connection accept%s\n");
+ p(tcps_badsyn, "\t%lu bad connection attempt%s\n");
+ p(tcps_listendrop, "\t%lu listen queue overflow%s\n");
+ p(tcps_badrst, "\t%lu ignored RSTs in the window%s\n");
+ p(tcps_connects, "\t%lu connection%s established (including accepts)\n");
+ p2(tcps_closed, tcps_drops,
+ "\t%lu connection%s closed (including %lu drop%s)\n");
+ p(tcps_cachedrtt, "\t\t%lu connection%s updated cached RTT on close\n");
+ p(tcps_cachedrttvar,
+ "\t\t%lu connection%s updated cached RTT variance on close\n");
+ p(tcps_cachedssthresh,
+ "\t\t%lu connection%s updated cached ssthresh on close\n");
+ p(tcps_conndrops, "\t%lu embryonic connection%s dropped\n");
+ p2(tcps_rttupdated, tcps_segstimed,
+ "\t%lu segment%s updated rtt (of %lu attempt%s)\n");
+ p(tcps_rexmttimeo, "\t%lu retransmit timeout%s\n");
+ p(tcps_timeoutdrop, "\t\t%lu connection%s dropped by rexmit timeout\n");
+ p(tcps_persisttimeo, "\t%lu persist timeout%s\n");
+ p(tcps_persistdrop, "\t\t%lu connection%s dropped by persist timeout\n");
+ p(tcps_finwait2_drops,
+ "\t%lu Connection%s (fin_wait_2) dropped because of timeout\n");
+ p(tcps_keeptimeo, "\t%lu keepalive timeout%s\n");
+ p(tcps_keepprobe, "\t\t%lu keepalive probe%s sent\n");
+ p(tcps_keepdrops, "\t\t%lu connection%s dropped by keepalive\n");
+ p(tcps_predack, "\t%lu correct ACK header prediction%s\n");
+ p(tcps_preddat, "\t%lu correct data packet header prediction%s\n");
+
+ p3(tcps_sc_added, "\t%lu syncache entr%s added\n");
+ p1a(tcps_sc_retransmitted, "\t\t%lu retransmitted\n");
+ p1a(tcps_sc_dupsyn, "\t\t%lu dupsyn\n");
+ p1a(tcps_sc_dropped, "\t\t%lu dropped\n");
+ p1a(tcps_sc_completed, "\t\t%lu completed\n");
+ p1a(tcps_sc_bucketoverflow, "\t\t%lu bucket overflow\n");
+ p1a(tcps_sc_cacheoverflow, "\t\t%lu cache overflow\n");
+ p1a(tcps_sc_reset, "\t\t%lu reset\n");
+ p1a(tcps_sc_stale, "\t\t%lu stale\n");
+ p1a(tcps_sc_aborted, "\t\t%lu aborted\n");
+ p1a(tcps_sc_badack, "\t\t%lu badack\n");
+ p1a(tcps_sc_unreach, "\t\t%lu unreach\n");
+ p(tcps_sc_zonefail, "\t\t%lu zone failure%s\n");
+ p(tcps_sc_sendcookie, "\t%lu cookie%s sent\n");
+ p(tcps_sc_recvcookie, "\t%lu cookie%s received\n");
+
+ p(tcps_sack_recovery_episode, "\t%lu SACK recovery episode%s\n");
+ p(tcps_sack_rexmits,
+ "\t%lu segment rexmit%s in SACK recovery episodes\n");
+ p(tcps_sack_rexmit_bytes,
+ "\t%lu byte rexmit%s in SACK recovery episodes\n");
+ p(tcps_sack_rcv_blocks,
+ "\t%lu SACK option%s (SACK blocks) received\n");
+ p(tcps_sack_send_blocks, "\t%lu SACK option%s (SACK blocks) sent\n");
+ p1a(tcps_sack_sboverflow, "\t%lu SACK scoreboard overflow\n");
+
+ p(tcps_ecn_ce, "\t%lu packet%s with ECN CE bit set\n");
+ p(tcps_ecn_ect0, "\t%lu packet%s with ECN ECT(0) bit set\n");
+ p(tcps_ecn_ect1, "\t%lu packet%s with ECN ECT(1) bit set\n");
+ p(tcps_ecn_shs, "\t%lu successful ECN handshake%s\n");
+ p(tcps_ecn_rcwnd, "\t%lu time%s ECN reduced the congestion window\n");
+#undef p
+#undef p1a
+#undef p2
+#undef p2a
+#undef p3
+}
+
+/*
+ * Dump UDP statistics structure.
+ */
+void
+udp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct udpstat udpstat, zerostat;
+ size_t len = sizeof udpstat;
+ u_long delivered;
+
+#ifdef INET6
+ if (udp_done != 0)
+ return;
+ else
+ udp_done = 1;
+#endif
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.udp.stats", &udpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.udp.stats");
+ return;
+ }
+ } else
+ kread(off, &udpstat, len);
+
+ printf("%s:\n", name);
+#define p(f, m) if (udpstat.f || sflag <= 1) \
+ printf(m, udpstat.f, plural(udpstat.f))
+#define p1a(f, m) if (udpstat.f || sflag <= 1) \
+ printf(m, udpstat.f)
+ p(udps_ipackets, "\t%lu datagram%s received\n");
+ p1a(udps_hdrops, "\t%lu with incomplete header\n");
+ p1a(udps_badlen, "\t%lu with bad data length field\n");
+ p1a(udps_badsum, "\t%lu with bad checksum\n");
+ p1a(udps_nosum, "\t%lu with no checksum\n");
+ p1a(udps_noport, "\t%lu dropped due to no socket\n");
+ p(udps_noportbcast,
+ "\t%lu broadcast/multicast datagram%s undelivered\n");
+ p1a(udps_fullsock, "\t%lu dropped due to full socket buffers\n");
+ p1a(udpps_pcbhashmiss, "\t%lu not for hashed pcb\n");
+ delivered = udpstat.udps_ipackets -
+ udpstat.udps_hdrops -
+ udpstat.udps_badlen -
+ udpstat.udps_badsum -
+ udpstat.udps_noport -
+ udpstat.udps_noportbcast -
+ udpstat.udps_fullsock;
+ if (delivered || sflag <= 1)
+ printf("\t%lu delivered\n", delivered);
+ p(udps_opackets, "\t%lu datagram%s output\n");
+ /* the next statistic is cumulative in udps_noportbcast */
+ p(udps_filtermcast,
+ "\t%lu time%s multicast source filter matched\n");
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump CARP statistics structure.
+ */
+void
+carp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct carpstats carpstat, zerostat;
+ size_t len = sizeof(struct carpstats);
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.carp.stats", &carpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet.carp.stats");
+ return;
+ }
+ } else {
+ if (off == 0)
+ return;
+ kread(off, &carpstat, len);
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (carpstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)carpstat.f, plural(carpstat.f))
+#define p2(f, m) if (carpstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)carpstat.f)
+
+ p(carps_ipackets, "\t%ju packet%s received (IPv4)\n");
+ p(carps_ipackets6, "\t%ju packet%s received (IPv6)\n");
+ p(carps_badttl, "\t\t%ju packet%s discarded for wrong TTL\n");
+ p(carps_hdrops, "\t\t%ju packet%s shorter than header\n");
+ p(carps_badsum, "\t\t%ju discarded for bad checksum%s\n");
+ p(carps_badver, "\t\t%ju discarded packet%s with a bad version\n");
+ p2(carps_badlen, "\t\t%ju discarded because packet too short\n");
+ p2(carps_badauth, "\t\t%ju discarded for bad authentication\n");
+ p2(carps_badvhid, "\t\t%ju discarded for bad vhid\n");
+ p2(carps_badaddrs, "\t\t%ju discarded because of a bad address list\n");
+ p(carps_opackets, "\t%ju packet%s sent (IPv4)\n");
+ p(carps_opackets6, "\t%ju packet%s sent (IPv6)\n");
+ p2(carps_onomem, "\t\t%ju send failed due to mbuf memory error\n");
+#if notyet
+ p(carps_ostates, "\t\t%s state update%s sent\n");
+#endif
+#undef p
+#undef p2
+}
+
+/*
+ * Dump IP statistics structure.
+ */
+void
+ip_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct ipstat ipstat, zerostat;
+ size_t len = sizeof ipstat;
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.ip.stats", &ipstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.ip.stats");
+ return;
+ }
+ } else
+ kread(off, &ipstat, len);
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (ipstat.f || sflag <= 1) \
+ printf(m, ipstat.f, plural(ipstat.f))
+#define p1a(f, m) if (ipstat.f || sflag <= 1) \
+ printf(m, ipstat.f)
+
+ p(ips_total, "\t%lu total packet%s received\n");
+ p(ips_badsum, "\t%lu bad header checksum%s\n");
+ p1a(ips_toosmall, "\t%lu with size smaller than minimum\n");
+ p1a(ips_tooshort, "\t%lu with data size < data length\n");
+ p1a(ips_toolong, "\t%lu with ip length > max ip packet size\n");
+ p1a(ips_badhlen, "\t%lu with header length < data size\n");
+ p1a(ips_badlen, "\t%lu with data length < header length\n");
+ p1a(ips_badoptions, "\t%lu with bad options\n");
+ p1a(ips_badvers, "\t%lu with incorrect version number\n");
+ p(ips_fragments, "\t%lu fragment%s received\n");
+ p(ips_fragdropped, "\t%lu fragment%s dropped (dup or out of space)\n");
+ p(ips_fragtimeout, "\t%lu fragment%s dropped after timeout\n");
+ p(ips_reassembled, "\t%lu packet%s reassembled ok\n");
+ p(ips_delivered, "\t%lu packet%s for this host\n");
+ p(ips_noproto, "\t%lu packet%s for unknown/unsupported protocol\n");
+ p(ips_forward, "\t%lu packet%s forwarded");
+ p(ips_fastforward, " (%lu packet%s fast forwarded)");
+ if (ipstat.ips_forward || sflag <= 1)
+ putchar('\n');
+ p(ips_cantforward, "\t%lu packet%s not forwardable\n");
+ p(ips_notmember,
+ "\t%lu packet%s received for unknown multicast group\n");
+ p(ips_redirectsent, "\t%lu redirect%s sent\n");
+ p(ips_localout, "\t%lu packet%s sent from this host\n");
+ p(ips_rawout, "\t%lu packet%s sent with fabricated ip header\n");
+ p(ips_odropped,
+ "\t%lu output packet%s dropped due to no bufs, etc.\n");
+ p(ips_noroute, "\t%lu output packet%s discarded due to no route\n");
+ p(ips_fragmented, "\t%lu output datagram%s fragmented\n");
+ p(ips_ofragments, "\t%lu fragment%s created\n");
+ p(ips_cantfrag, "\t%lu datagram%s that can't be fragmented\n");
+ p(ips_nogif, "\t%lu tunneling packet%s that can't find gif\n");
+ p(ips_badaddr, "\t%lu datagram%s with bad address in header\n");
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump ARP statistics structure.
+ */
+void
+arp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct arpstat arpstat, zerostat;
+ size_t len = sizeof(arpstat);
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.link.ether.arp.stats", &arpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.link.ether.arp.stats");
+ return;
+ }
+ } else
+ kread(off, &arpstat, len);
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (arpstat.f || sflag <= 1) \
+ printf(m, arpstat.f, plural(arpstat.f))
+#define p2(f, m) if (arpstat.f || sflag <= 1) \
+ printf(m, arpstat.f, pluralies(arpstat.f))
+
+ p(txrequests, "\t%lu ARP request%s sent\n");
+ p2(txreplies, "\t%lu ARP repl%s sent\n");
+ p(rxrequests, "\t%lu ARP request%s received\n");
+ p2(rxreplies, "\t%lu ARP repl%s received\n");
+ p(received, "\t%lu ARP packet%s received\n");
+ p(dropped, "\t%lu total packet%s dropped due to no ARP entry\n");
+ p(timeouts, "\t%lu ARP entry%s timed out\n");
+ p(dupips, "\t%lu Duplicate IP%s seen\n");
+#undef p
+#undef p2
+}
+
+
+
+static const char *icmpnames[ICMP_MAXTYPE + 1] = {
+ "echo reply", /* RFC 792 */
+ "#1",
+ "#2",
+ "destination unreachable", /* RFC 792 */
+ "source quench", /* RFC 792 */
+ "routing redirect", /* RFC 792 */
+ "#6",
+ "#7",
+ "echo", /* RFC 792 */
+ "router advertisement", /* RFC 1256 */
+ "router solicitation", /* RFC 1256 */
+ "time exceeded", /* RFC 792 */
+ "parameter problem", /* RFC 792 */
+ "time stamp", /* RFC 792 */
+ "time stamp reply", /* RFC 792 */
+ "information request", /* RFC 792 */
+ "information request reply", /* RFC 792 */
+ "address mask request", /* RFC 950 */
+ "address mask reply", /* RFC 950 */
+ "#19",
+ "#20",
+ "#21",
+ "#22",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "#29",
+ "icmp traceroute", /* RFC 1393 */
+ "datagram conversion error", /* RFC 1475 */
+ "mobile host redirect",
+ "IPv6 where-are-you",
+ "IPv6 i-am-here",
+ "mobile registration req",
+ "mobile registration reply",
+ "domain name request", /* RFC 1788 */
+ "domain name reply", /* RFC 1788 */
+ "icmp SKIP",
+ "icmp photuris", /* RFC 2521 */
+};
+
+/*
+ * Dump ICMP statistics.
+ */
+void
+icmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct icmpstat icmpstat, zerostat;
+ int i, first;
+ size_t len;
+
+ len = sizeof icmpstat;
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.icmp.stats", &icmpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.icmp.stats");
+ return;
+ }
+ } else
+ kread(off, &icmpstat, len);
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (icmpstat.f || sflag <= 1) \
+ printf(m, icmpstat.f, plural(icmpstat.f))
+#define p1a(f, m) if (icmpstat.f || sflag <= 1) \
+ printf(m, icmpstat.f)
+#define p2(f, m) if (icmpstat.f || sflag <= 1) \
+ printf(m, icmpstat.f, plurales(icmpstat.f))
+
+ p(icps_error, "\t%lu call%s to icmp_error\n");
+ p(icps_oldicmp,
+ "\t%lu error%s not generated in response to an icmp message\n");
+ for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+ if (icmpstat.icps_outhist[i] != 0) {
+ if (first) {
+ printf("\tOutput histogram:\n");
+ first = 0;
+ }
+ if (icmpnames[i] != NULL)
+ printf("\t\t%s: %lu\n", icmpnames[i],
+ icmpstat.icps_outhist[i]);
+ else
+ printf("\t\tunknown ICMP #%d: %lu\n", i,
+ icmpstat.icps_outhist[i]);
+ }
+ p(icps_badcode, "\t%lu message%s with bad code fields\n");
+ p(icps_tooshort, "\t%lu message%s less than the minimum length\n");
+ p(icps_checksum, "\t%lu message%s with bad checksum\n");
+ p(icps_badlen, "\t%lu message%s with bad length\n");
+ p1a(icps_bmcastecho, "\t%lu multicast echo requests ignored\n");
+ p1a(icps_bmcasttstamp, "\t%lu multicast timestamp requests ignored\n");
+ for (first = 1, i = 0; i < ICMP_MAXTYPE + 1; i++)
+ if (icmpstat.icps_inhist[i] != 0) {
+ if (first) {
+ printf("\tInput histogram:\n");
+ first = 0;
+ }
+ if (icmpnames[i] != NULL)
+ printf("\t\t%s: %lu\n", icmpnames[i],
+ icmpstat.icps_inhist[i]);
+ else
+ printf("\t\tunknown ICMP #%d: %lu\n", i,
+ icmpstat.icps_inhist[i]);
+ }
+ p(icps_reflect, "\t%lu message response%s generated\n");
+ p2(icps_badaddr, "\t%lu invalid return address%s\n");
+ p(icps_noroute, "\t%lu no return route%s\n");
+#undef p
+#undef p1a
+#undef p2
+ if (live) {
+ len = sizeof i;
+ if (sysctlbyname("net.inet.icmp.maskrepl", &i, &len, NULL, 0) <
+ 0)
+ return;
+ printf("\tICMP address mask responses are %sabled\n",
+ i ? "en" : "dis");
+ }
+}
+
+#ifndef BURN_BRIDGES
+/*
+ * Dump IGMP statistics structure (pre 8.x kernel).
+ */
+static void
+igmp_stats_live_old(u_long off, const char *name)
+{
+ struct oigmpstat oigmpstat, zerostat;
+ size_t len = sizeof(oigmpstat);
+
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.igmp.stats", &oigmpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.igmp.stats");
+ return;
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (oigmpstat.f || sflag <= 1) \
+ printf(m, oigmpstat.f, plural(oigmpstat.f))
+#define py(f, m) if (oigmpstat.f || sflag <= 1) \
+ printf(m, oigmpstat.f, oigmpstat.f != 1 ? "ies" : "y")
+ p(igps_rcv_total, "\t%u message%s received\n");
+ p(igps_rcv_tooshort, "\t%u message%s received with too few bytes\n");
+ p(igps_rcv_badsum, "\t%u message%s received with bad checksum\n");
+ py(igps_rcv_queries, "\t%u membership quer%s received\n");
+ py(igps_rcv_badqueries,
+ "\t%u membership quer%s received with invalid field(s)\n");
+ p(igps_rcv_reports, "\t%u membership report%s received\n");
+ p(igps_rcv_badreports,
+ "\t%u membership report%s received with invalid field(s)\n");
+ p(igps_rcv_ourreports,
+"\t%u membership report%s received for groups to which we belong\n");
+ p(igps_snd_reports, "\t%u membership report%s sent\n");
+#undef p
+#undef py
+}
+#endif /* !BURN_BRIDGES */
+
+/*
+ * Dump IGMP statistics structure.
+ */
+void
+igmp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct igmpstat igmpstat, zerostat;
+ size_t len;
+
+#ifndef BURN_BRIDGES
+ if (live) {
+ /*
+ * Detect if we are being run against a pre-IGMPv3 kernel.
+ * We cannot do this for a core file as the legacy
+ * struct igmpstat has no size field, nor does it
+ * export it in any readily-available symbols.
+ */
+ len = 0;
+ if (sysctlbyname("net.inet.igmp.stats", NULL, &len, NULL,
+ 0) < 0) {
+ warn("sysctl: net.inet.igmp.stats");
+ return;
+ }
+ if (len < sizeof(igmpstat)) {
+ igmp_stats_live_old(off, name);
+ return;
+ }
+ }
+#endif /* !BURN_BRIDGES */
+
+ len = sizeof(igmpstat);
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.igmp.stats", &igmpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.igmp.stats");
+ return;
+ }
+ } else {
+ len = sizeof(igmpstat);
+ kread(off, &igmpstat, len);
+ }
+
+ if (igmpstat.igps_version != IGPS_VERSION_3) {
+ warnx("%s: version mismatch (%d != %d)", __func__,
+ igmpstat.igps_version, IGPS_VERSION_3);
+ }
+ if (igmpstat.igps_len != IGPS_VERSION3_LEN) {
+ warnx("%s: size mismatch (%d != %d)", __func__,
+ igmpstat.igps_len, IGPS_VERSION3_LEN);
+ }
+
+ printf("%s:\n", name);
+
+#define p64(f, m) if (igmpstat.f || sflag <= 1) \
+ printf(m, (uintmax_t) igmpstat.f, plural(igmpstat.f))
+#define py64(f, m) if (igmpstat.f || sflag <= 1) \
+ printf(m, (uintmax_t) igmpstat.f, pluralies(igmpstat.f))
+ p64(igps_rcv_total, "\t%ju message%s received\n");
+ p64(igps_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
+ p64(igps_rcv_badttl, "\t%ju message%s received with wrong TTL\n");
+ p64(igps_rcv_badsum, "\t%ju message%s received with bad checksum\n");
+ py64(igps_rcv_v1v2_queries, "\t%ju V1/V2 membership quer%s received\n");
+ py64(igps_rcv_v3_queries, "\t%ju V3 membership quer%s received\n");
+ py64(igps_rcv_badqueries,
+ "\t%ju membership quer%s received with invalid field(s)\n");
+ py64(igps_rcv_gen_queries, "\t%ju general quer%s received\n");
+ py64(igps_rcv_group_queries, "\t%ju group quer%s received\n");
+ py64(igps_rcv_gsr_queries, "\t%ju group-source quer%s received\n");
+ py64(igps_drop_gsr_queries, "\t%ju group-source quer%s dropped\n");
+ p64(igps_rcv_reports, "\t%ju membership report%s received\n");
+ p64(igps_rcv_badreports,
+ "\t%ju membership report%s received with invalid field(s)\n");
+ p64(igps_rcv_ourreports,
+"\t%ju membership report%s received for groups to which we belong\n");
+ p64(igps_rcv_nora, "\t%ju V3 report%s received without Router Alert\n");
+ p64(igps_snd_reports, "\t%ju membership report%s sent\n");
+#undef p64
+#undef py64
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim_stats(u_long off __unused, const char *name, int af1 __unused,
+ int proto __unused)
+{
+ struct pimstat pimstat, zerostat;
+ size_t len = sizeof pimstat;
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.pim.stats", &pimstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet.pim.stats");
+ return;
+ }
+ } else {
+ if (off == 0)
+ return;
+ kread(off, &pimstat, len);
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (pimstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)pimstat.f, plural(pimstat.f))
+#define py(f, m) if (pimstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)pimstat.f, pimstat.f != 1 ? "ies" : "y")
+ p(pims_rcv_total_msgs, "\t%ju message%s received\n");
+ p(pims_rcv_total_bytes, "\t%ju byte%s received\n");
+ p(pims_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
+ p(pims_rcv_badsum, "\t%ju message%s received with bad checksum\n");
+ p(pims_rcv_badversion, "\t%ju message%s received with bad version\n");
+ p(pims_rcv_registers_msgs, "\t%ju data register message%s received\n");
+ p(pims_rcv_registers_bytes, "\t%ju data register byte%s received\n");
+ p(pims_rcv_registers_wrongiif,
+ "\t%ju data register message%s received on wrong iif\n");
+ p(pims_rcv_badregisters, "\t%ju bad register%s received\n");
+ p(pims_snd_registers_msgs, "\t%ju data register message%s sent\n");
+ p(pims_snd_registers_bytes, "\t%ju data register byte%s sent\n");
+#undef p
+#undef py
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ */
+void
+inetprint(struct in_addr *in, int port, const char *proto, int num_port)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int width;
+
+ if (Wflag)
+ sprintf(line, "%s.", inetname(in));
+ else
+ sprintf(line, "%.*s.", (Aflag && !num_port) ? 12 : 16, inetname(in));
+ cp = index(line, '\0');
+ if (!num_port && port)
+ sp = getservbyport((int)port, proto);
+ if (sp || port == 0)
+ sprintf(cp, "%.15s ", sp ? sp->s_name : "*");
+ else
+ sprintf(cp, "%d ", ntohs((u_short)port));
+ width = (Aflag && !Wflag) ? 18 : 22;
+ if (Wflag)
+ printf("%-*s ", width, line);
+ else
+ printf("%-*.*s ", width, width, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+char *
+inetname(struct in_addr *inp)
+{
+ char *cp;
+ static char line[MAXHOSTNAMELEN];
+ struct hostent *hp;
+ struct netent *np;
+
+ cp = 0;
+ if (!numeric_addr && inp->s_addr != INADDR_ANY) {
+ int net = inet_netof(*inp);
+ int lna = inet_lnaof(*inp);
+
+ if (lna == INADDR_ANY) {
+ np = getnetbyaddr(net, AF_INET);
+ if (np)
+ cp = np->n_name;
+ }
+ if (cp == 0) {
+ hp = gethostbyaddr((char *)inp, sizeof (*inp), AF_INET);
+ if (hp) {
+ cp = hp->h_name;
+ trimdomain(cp, strlen(cp));
+ }
+ }
+ }
+ if (inp->s_addr == INADDR_ANY)
+ strcpy(line, "*");
+ else if (cp) {
+ strlcpy(line, cp, sizeof(line));
+ } else {
+ inp->s_addr = ntohl(inp->s_addr);
+#define C(x) ((u_int)((x) & 0xff))
+ sprintf(line, "%u.%u.%u.%u", C(inp->s_addr >> 24),
+ C(inp->s_addr >> 16), C(inp->s_addr >> 8), C(inp->s_addr));
+ }
+ return (line);
+}
diff --git a/freebsd/usr.bin/netstat/inet6.c b/freebsd/usr.bin/netstat/inet6.c
new file mode 100644
index 00000000..64b645ee
--- /dev/null
+++ b/freebsd/usr.bin/netstat/inet6.c
@@ -0,0 +1,1175 @@
+/* BSDI inet.c,v 2.3 1995/10/24 02:19:29 prb Exp */
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet6.c 8.4 (Berkeley) 4/20/94";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef __rtems__
+#include "port_before.h"
+#endif
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/ioctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#endif
+#include <sys/sysctl.h>
+
+#include <net/route.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#else
+#include <net/if_var.h>
+#endif
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+#include <netinet/icmp6.h>
+#include <netinet/in_systm.h>
+#ifdef __rtems__
+#include <freebsd/netinet6/in6_pcb.h>
+#include <freebsd/netinet6/in6_var.h>
+#include <freebsd/netinet6/ip6_var.h>
+#include <freebsd/netinet6/pim6_var.h>
+#include <freebsd/netinet6/raw_ip6.h>
+#else
+#include <netinet6/in6_pcb.h>
+#include <netinet6/in6_var.h>
+#include <netinet6/ip6_var.h>
+#include <netinet6/pim6_var.h>
+#include <netinet6/raw_ip6.h>
+#endif
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+struct socket sockb;
+
+char *inet6name(struct in6_addr *);
+
+static char ntop_buf[INET6_ADDRSTRLEN];
+
+static const char *ip6nh[] = {
+ "hop by hop",
+ "ICMP",
+ "IGMP",
+ "#3",
+ "IP",
+ "#5",
+ "TCP",
+ "#7",
+ "#8",
+ "#9",
+ "#10",
+ "#11",
+ "#12",
+ "#13",
+ "#14",
+ "#15",
+ "#16",
+ "UDP",
+ "#18",
+ "#19",
+ "#20",
+ "#21",
+ "IDP",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "TP",
+ "#30",
+ "#31",
+ "#32",
+ "#33",
+ "#34",
+ "#35",
+ "#36",
+ "#37",
+ "#38",
+ "#39",
+ "#40",
+ "IP6",
+ "#42",
+ "routing",
+ "fragment",
+ "#45",
+ "#46",
+ "#47",
+ "#48",
+ "#49",
+ "ESP",
+ "AH",
+ "#52",
+ "#53",
+ "#54",
+ "#55",
+ "#56",
+ "#57",
+ "ICMP6",
+ "no next header",
+ "destination option",
+ "#61",
+ "mobility",
+ "#63",
+ "#64",
+ "#65",
+ "#66",
+ "#67",
+ "#68",
+ "#69",
+ "#70",
+ "#71",
+ "#72",
+ "#73",
+ "#74",
+ "#75",
+ "#76",
+ "#77",
+ "#78",
+ "#79",
+ "ISOIP",
+ "#81",
+ "#82",
+ "#83",
+ "#84",
+ "#85",
+ "#86",
+ "#87",
+ "#88",
+ "OSPF",
+ "#80",
+ "#91",
+ "#92",
+ "#93",
+ "#94",
+ "#95",
+ "#96",
+ "Ethernet",
+ "#98",
+ "#99",
+ "#100",
+ "#101",
+ "#102",
+ "PIM",
+ "#104",
+ "#105",
+ "#106",
+ "#107",
+ "#108",
+ "#109",
+ "#110",
+ "#111",
+ "#112",
+ "#113",
+ "#114",
+ "#115",
+ "#116",
+ "#117",
+ "#118",
+ "#119",
+ "#120",
+ "#121",
+ "#122",
+ "#123",
+ "#124",
+ "#125",
+ "#126",
+ "#127",
+ "#128",
+ "#129",
+ "#130",
+ "#131",
+ "#132",
+ "#133",
+ "#134",
+ "#135",
+ "#136",
+ "#137",
+ "#138",
+ "#139",
+ "#140",
+ "#141",
+ "#142",
+ "#143",
+ "#144",
+ "#145",
+ "#146",
+ "#147",
+ "#148",
+ "#149",
+ "#150",
+ "#151",
+ "#152",
+ "#153",
+ "#154",
+ "#155",
+ "#156",
+ "#157",
+ "#158",
+ "#159",
+ "#160",
+ "#161",
+ "#162",
+ "#163",
+ "#164",
+ "#165",
+ "#166",
+ "#167",
+ "#168",
+ "#169",
+ "#170",
+ "#171",
+ "#172",
+ "#173",
+ "#174",
+ "#175",
+ "#176",
+ "#177",
+ "#178",
+ "#179",
+ "#180",
+ "#181",
+ "#182",
+ "#183",
+ "#184",
+ "#185",
+ "#186",
+ "#187",
+ "#188",
+ "#189",
+ "#180",
+ "#191",
+ "#192",
+ "#193",
+ "#194",
+ "#195",
+ "#196",
+ "#197",
+ "#198",
+ "#199",
+ "#200",
+ "#201",
+ "#202",
+ "#203",
+ "#204",
+ "#205",
+ "#206",
+ "#207",
+ "#208",
+ "#209",
+ "#210",
+ "#211",
+ "#212",
+ "#213",
+ "#214",
+ "#215",
+ "#216",
+ "#217",
+ "#218",
+ "#219",
+ "#220",
+ "#221",
+ "#222",
+ "#223",
+ "#224",
+ "#225",
+ "#226",
+ "#227",
+ "#228",
+ "#229",
+ "#230",
+ "#231",
+ "#232",
+ "#233",
+ "#234",
+ "#235",
+ "#236",
+ "#237",
+ "#238",
+ "#239",
+ "#240",
+ "#241",
+ "#242",
+ "#243",
+ "#244",
+ "#245",
+ "#246",
+ "#247",
+ "#248",
+ "#249",
+ "#250",
+ "#251",
+ "#252",
+ "#253",
+ "#254",
+ "#255",
+};
+
+static char *srcrule_str[] = {
+ "first candidate",
+ "same address",
+ "appropriate scope",
+ "deprecated address",
+ "home address",
+ "outgoing interface",
+ "matching label",
+ "public/temporary address",
+ "alive interface",
+ "preferred interface",
+ "rule #10",
+ "rule #11",
+ "rule #12",
+ "rule #13",
+ "longest match",
+ "rule #15",
+};
+
+/*
+ * Dump IP6 statistics structure.
+ */
+void
+ip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct ip6stat ip6stat;
+ int first, i;
+ size_t len;
+
+ len = sizeof ip6stat;
+ if (live) {
+ memset(&ip6stat, 0, len);
+ if (sysctlbyname("net.inet6.ip6.stats", &ip6stat, &len, NULL,
+ 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.ip6.stats");
+ return;
+ }
+ } else
+ kread(off, &ip6stat, len);
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (ip6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)ip6stat.f, plural(ip6stat.f))
+#define p1a(f, m) if (ip6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)ip6stat.f)
+
+ p(ip6s_total, "\t%ju total packet%s received\n");
+ p1a(ip6s_toosmall, "\t%ju with size smaller than minimum\n");
+ p1a(ip6s_tooshort, "\t%ju with data size < data length\n");
+ p1a(ip6s_badoptions, "\t%ju with bad options\n");
+ p1a(ip6s_badvers, "\t%ju with incorrect version number\n");
+ p(ip6s_fragments, "\t%ju fragment%s received\n");
+ p(ip6s_fragdropped, "\t%ju fragment%s dropped (dup or out of space)\n");
+ p(ip6s_fragtimeout, "\t%ju fragment%s dropped after timeout\n");
+ p(ip6s_fragoverflow, "\t%ju fragment%s that exceeded limit\n");
+ p(ip6s_reassembled, "\t%ju packet%s reassembled ok\n");
+ p(ip6s_delivered, "\t%ju packet%s for this host\n");
+ p(ip6s_forward, "\t%ju packet%s forwarded\n");
+ p(ip6s_cantforward, "\t%ju packet%s not forwardable\n");
+ p(ip6s_redirectsent, "\t%ju redirect%s sent\n");
+ p(ip6s_localout, "\t%ju packet%s sent from this host\n");
+ p(ip6s_rawout, "\t%ju packet%s sent with fabricated ip header\n");
+ p(ip6s_odropped, "\t%ju output packet%s dropped due to no bufs, etc.\n");
+ p(ip6s_noroute, "\t%ju output packet%s discarded due to no route\n");
+ p(ip6s_fragmented, "\t%ju output datagram%s fragmented\n");
+ p(ip6s_ofragments, "\t%ju fragment%s created\n");
+ p(ip6s_cantfrag, "\t%ju datagram%s that can't be fragmented\n");
+ p(ip6s_badscope, "\t%ju packet%s that violated scope rules\n");
+ p(ip6s_notmember, "\t%ju multicast packet%s which we don't join\n");
+ for (first = 1, i = 0; i < 256; i++)
+ if (ip6stat.ip6s_nxthist[i] != 0) {
+ if (first) {
+ printf("\tInput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %ju\n", ip6nh[i],
+ (uintmax_t)ip6stat.ip6s_nxthist[i]);
+ }
+ printf("\tMbuf statistics:\n");
+ printf("\t\t%ju one mbuf\n", (uintmax_t)ip6stat.ip6s_m1);
+ for (first = 1, i = 0; i < 32; i++) {
+ char ifbuf[IFNAMSIZ];
+ if (ip6stat.ip6s_m2m[i] != 0) {
+ if (first) {
+ printf("\t\ttwo or more mbuf:\n");
+ first = 0;
+ }
+ printf("\t\t\t%s= %ju\n",
+ if_indextoname(i, ifbuf),
+ (uintmax_t)ip6stat.ip6s_m2m[i]);
+ }
+ }
+ printf("\t\t%ju one ext mbuf\n",
+ (uintmax_t)ip6stat.ip6s_mext1);
+ printf("\t\t%ju two or more ext mbuf\n",
+ (uintmax_t)ip6stat.ip6s_mext2m);
+ p(ip6s_exthdrtoolong,
+ "\t%ju packet%s whose headers are not continuous\n");
+ p(ip6s_nogif, "\t%ju tunneling packet%s that can't find gif\n");
+ p(ip6s_toomanyhdr,
+ "\t%ju packet%s discarded because of too many headers\n");
+
+ /* for debugging source address selection */
+#define PRINT_SCOPESTAT(s,i) do {\
+ switch(i) { /* XXX hardcoding in each case */\
+ case 1:\
+ p(s, "\t\t%ju node-local%s\n");\
+ break;\
+ case 2:\
+ p(s,"\t\t%ju link-local%s\n");\
+ break;\
+ case 5:\
+ p(s,"\t\t%ju site-local%s\n");\
+ break;\
+ case 14:\
+ p(s,"\t\t%ju global%s\n");\
+ break;\
+ default:\
+ printf("\t\t%ju addresses scope=%x\n",\
+ (uintmax_t)ip6stat.s, i);\
+ }\
+ } while (0);
+
+ p(ip6s_sources_none,
+ "\t%ju failure%s of source address selection\n");
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat.ip6s_sources_sameif[i]) {
+ if (first) {
+ printf("\tsource addresses on an outgoing I/F\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_sameif[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat.ip6s_sources_otherif[i]) {
+ if (first) {
+ printf("\tsource addresses on a non-outgoing I/F\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_otherif[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat.ip6s_sources_samescope[i]) {
+ if (first) {
+ printf("\tsource addresses of same scope\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_samescope[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat.ip6s_sources_otherscope[i]) {
+ if (first) {
+ printf("\tsource addresses of a different scope\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_otherscope[i], i);
+ }
+ }
+ for (first = 1, i = 0; i < 16; i++) {
+ if (ip6stat.ip6s_sources_deprecated[i]) {
+ if (first) {
+ printf("\tdeprecated source addresses\n");
+ first = 0;
+ }
+ PRINT_SCOPESTAT(ip6s_sources_deprecated[i], i);
+ }
+ }
+
+ printf("\tSource addresses selection rule applied:\n");
+ for (i = 0; i < 16; i++) {
+ if (ip6stat.ip6s_sources_rule[i])
+ printf("\t\t%ju %s\n",
+ (uintmax_t)ip6stat.ip6s_sources_rule[i],
+ srcrule_str[i]);
+ }
+#undef p
+#undef p1a
+}
+
+/*
+ * Dump IPv6 per-interface statistics based on RFC 2465.
+ */
+void
+ip6_ifstats(char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+#define p(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)ifr.ifr_ifru.ifru_stat.f, plural(ifr.ifr_ifru.ifru_stat.f))
+#define p_5(f, m) if (ifr.ifr_ifru.ifru_stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)ip6stat.f)
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ strcpy(ifr.ifr_name, ifname);
+ printf("ip6 on %s:\n", ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFSTAT_IN6, (char *)&ifr) < 0) {
+ perror("Warning: ioctl(SIOCGIFSTAT_IN6)");
+ goto end;
+ }
+
+ p(ifs6_in_receive, "\t%ju total input datagram%s\n");
+ p(ifs6_in_hdrerr, "\t%ju datagram%s with invalid header received\n");
+ p(ifs6_in_toobig, "\t%ju datagram%s exceeded MTU received\n");
+ p(ifs6_in_noroute, "\t%ju datagram%s with no route received\n");
+ p(ifs6_in_addrerr, "\t%ju datagram%s with invalid dst received\n");
+ p(ifs6_in_protounknown, "\t%ju datagram%s with unknown proto received\n");
+ p(ifs6_in_truncated, "\t%ju truncated datagram%s received\n");
+ p(ifs6_in_discard, "\t%ju input datagram%s discarded\n");
+ p(ifs6_in_deliver,
+ "\t%ju datagram%s delivered to an upper layer protocol\n");
+ p(ifs6_out_forward, "\t%ju datagram%s forwarded to this interface\n");
+ p(ifs6_out_request,
+ "\t%ju datagram%s sent from an upper layer protocol\n");
+ p(ifs6_out_discard, "\t%ju total discarded output datagram%s\n");
+ p(ifs6_out_fragok, "\t%ju output datagram%s fragmented\n");
+ p(ifs6_out_fragfail, "\t%ju output datagram%s failed on fragment\n");
+ p(ifs6_out_fragcreat, "\t%ju output datagram%s succeeded on fragment\n");
+ p(ifs6_reass_reqd, "\t%ju incoming datagram%s fragmented\n");
+ p(ifs6_reass_ok, "\t%ju datagram%s reassembled\n");
+ p(ifs6_reass_fail, "\t%ju datagram%s failed on reassembly\n");
+ p(ifs6_in_mcast, "\t%ju multicast datagram%s received\n");
+ p(ifs6_out_mcast, "\t%ju multicast datagram%s sent\n");
+
+ end:
+ close(s);
+
+#undef p
+#undef p_5
+}
+
+static const char *icmp6names[] = {
+ "#0",
+ "unreach",
+ "packet too big",
+ "time exceed",
+ "parameter problem",
+ "#5",
+ "#6",
+ "#7",
+ "#8",
+ "#9",
+ "#10",
+ "#11",
+ "#12",
+ "#13",
+ "#14",
+ "#15",
+ "#16",
+ "#17",
+ "#18",
+ "#19",
+ "#20",
+ "#21",
+ "#22",
+ "#23",
+ "#24",
+ "#25",
+ "#26",
+ "#27",
+ "#28",
+ "#29",
+ "#30",
+ "#31",
+ "#32",
+ "#33",
+ "#34",
+ "#35",
+ "#36",
+ "#37",
+ "#38",
+ "#39",
+ "#40",
+ "#41",
+ "#42",
+ "#43",
+ "#44",
+ "#45",
+ "#46",
+ "#47",
+ "#48",
+ "#49",
+ "#50",
+ "#51",
+ "#52",
+ "#53",
+ "#54",
+ "#55",
+ "#56",
+ "#57",
+ "#58",
+ "#59",
+ "#60",
+ "#61",
+ "#62",
+ "#63",
+ "#64",
+ "#65",
+ "#66",
+ "#67",
+ "#68",
+ "#69",
+ "#70",
+ "#71",
+ "#72",
+ "#73",
+ "#74",
+ "#75",
+ "#76",
+ "#77",
+ "#78",
+ "#79",
+ "#80",
+ "#81",
+ "#82",
+ "#83",
+ "#84",
+ "#85",
+ "#86",
+ "#87",
+ "#88",
+ "#89",
+ "#80",
+ "#91",
+ "#92",
+ "#93",
+ "#94",
+ "#95",
+ "#96",
+ "#97",
+ "#98",
+ "#99",
+ "#100",
+ "#101",
+ "#102",
+ "#103",
+ "#104",
+ "#105",
+ "#106",
+ "#107",
+ "#108",
+ "#109",
+ "#110",
+ "#111",
+ "#112",
+ "#113",
+ "#114",
+ "#115",
+ "#116",
+ "#117",
+ "#118",
+ "#119",
+ "#120",
+ "#121",
+ "#122",
+ "#123",
+ "#124",
+ "#125",
+ "#126",
+ "#127",
+ "echo",
+ "echo reply",
+ "multicast listener query",
+ "MLDv1 listener report",
+ "MLDv1 listener done",
+ "router solicitation",
+ "router advertisement",
+ "neighbor solicitation",
+ "neighbor advertisement",
+ "redirect",
+ "router renumbering",
+ "node information request",
+ "node information reply",
+ "inverse neighbor solicitation",
+ "inverse neighbor advertisement",
+ "MLDv2 listener report",
+ "#144",
+ "#145",
+ "#146",
+ "#147",
+ "#148",
+ "#149",
+ "#150",
+ "#151",
+ "#152",
+ "#153",
+ "#154",
+ "#155",
+ "#156",
+ "#157",
+ "#158",
+ "#159",
+ "#160",
+ "#161",
+ "#162",
+ "#163",
+ "#164",
+ "#165",
+ "#166",
+ "#167",
+ "#168",
+ "#169",
+ "#170",
+ "#171",
+ "#172",
+ "#173",
+ "#174",
+ "#175",
+ "#176",
+ "#177",
+ "#178",
+ "#179",
+ "#180",
+ "#181",
+ "#182",
+ "#183",
+ "#184",
+ "#185",
+ "#186",
+ "#187",
+ "#188",
+ "#189",
+ "#180",
+ "#191",
+ "#192",
+ "#193",
+ "#194",
+ "#195",
+ "#196",
+ "#197",
+ "#198",
+ "#199",
+ "#200",
+ "#201",
+ "#202",
+ "#203",
+ "#204",
+ "#205",
+ "#206",
+ "#207",
+ "#208",
+ "#209",
+ "#210",
+ "#211",
+ "#212",
+ "#213",
+ "#214",
+ "#215",
+ "#216",
+ "#217",
+ "#218",
+ "#219",
+ "#220",
+ "#221",
+ "#222",
+ "#223",
+ "#224",
+ "#225",
+ "#226",
+ "#227",
+ "#228",
+ "#229",
+ "#230",
+ "#231",
+ "#232",
+ "#233",
+ "#234",
+ "#235",
+ "#236",
+ "#237",
+ "#238",
+ "#239",
+ "#240",
+ "#241",
+ "#242",
+ "#243",
+ "#244",
+ "#245",
+ "#246",
+ "#247",
+ "#248",
+ "#249",
+ "#250",
+ "#251",
+ "#252",
+ "#253",
+ "#254",
+ "#255",
+};
+
+/*
+ * Dump ICMP6 statistics.
+ */
+void
+icmp6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct icmp6stat icmp6stat;
+ int i, first;
+ size_t len;
+
+ len = sizeof icmp6stat;
+ if (live) {
+ memset(&icmp6stat, 0, len);
+ if (sysctlbyname("net.inet6.icmp6.stats", &icmp6stat, &len,
+ NULL, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.icmp6.stats");
+ return;
+ }
+ } else
+ kread(off, &icmp6stat, len);
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (icmp6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)icmp6stat.f, plural(icmp6stat.f))
+#define p_5(f, m) if (icmp6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)icmp6stat.f)
+
+ p(icp6s_error, "\t%ju call%s to icmp6_error\n");
+ p(icp6s_canterror,
+ "\t%ju error%s not generated in response to an icmp6 message\n");
+ p(icp6s_toofreq,
+ "\t%ju error%s not generated because of rate limitation\n");
+#define NELEM (int)(sizeof(icmp6stat.icp6s_outhist)/sizeof(icmp6stat.icp6s_outhist[0]))
+ for (first = 1, i = 0; i < NELEM; i++)
+ if (icmp6stat.icp6s_outhist[i] != 0) {
+ if (first) {
+ printf("\tOutput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %ju\n", icmp6names[i],
+ (uintmax_t)icmp6stat.icp6s_outhist[i]);
+ }
+#undef NELEM
+ p(icp6s_badcode, "\t%ju message%s with bad code fields\n");
+ p(icp6s_tooshort, "\t%ju message%s < minimum length\n");
+ p(icp6s_checksum, "\t%ju bad checksum%s\n");
+ p(icp6s_badlen, "\t%ju message%s with bad length\n");
+#define NELEM (int)(sizeof(icmp6stat.icp6s_inhist)/sizeof(icmp6stat.icp6s_inhist[0]))
+ for (first = 1, i = 0; i < NELEM; i++)
+ if (icmp6stat.icp6s_inhist[i] != 0) {
+ if (first) {
+ printf("\tInput histogram:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %ju\n", icmp6names[i],
+ (uintmax_t)icmp6stat.icp6s_inhist[i]);
+ }
+#undef NELEM
+ printf("\tHistogram of error messages to be generated:\n");
+ p_5(icp6s_odst_unreach_noroute, "\t\t%ju no route\n");
+ p_5(icp6s_odst_unreach_admin, "\t\t%ju administratively prohibited\n");
+ p_5(icp6s_odst_unreach_beyondscope, "\t\t%ju beyond scope\n");
+ p_5(icp6s_odst_unreach_addr, "\t\t%ju address unreachable\n");
+ p_5(icp6s_odst_unreach_noport, "\t\t%ju port unreachable\n");
+ p_5(icp6s_opacket_too_big, "\t\t%ju packet too big\n");
+ p_5(icp6s_otime_exceed_transit, "\t\t%ju time exceed transit\n");
+ p_5(icp6s_otime_exceed_reassembly, "\t\t%ju time exceed reassembly\n");
+ p_5(icp6s_oparamprob_header, "\t\t%ju erroneous header field\n");
+ p_5(icp6s_oparamprob_nextheader, "\t\t%ju unrecognized next header\n");
+ p_5(icp6s_oparamprob_option, "\t\t%ju unrecognized option\n");
+ p_5(icp6s_oredirect, "\t\t%ju redirect\n");
+ p_5(icp6s_ounknown, "\t\t%ju unknown\n");
+
+ p(icp6s_reflect, "\t%ju message response%s generated\n");
+ p(icp6s_nd_toomanyopt, "\t%ju message%s with too many ND options\n");
+ p(icp6s_nd_badopt, "\t%ju message%s with bad ND options\n");
+ p(icp6s_badns, "\t%ju bad neighbor solicitation message%s\n");
+ p(icp6s_badna, "\t%ju bad neighbor advertisement message%s\n");
+ p(icp6s_badrs, "\t%ju bad router solicitation message%s\n");
+ p(icp6s_badra, "\t%ju bad router advertisement message%s\n");
+ p(icp6s_badredirect, "\t%ju bad redirect message%s\n");
+ p(icp6s_pmtuchg, "\t%ju path MTU change%s\n");
+#undef p
+#undef p_5
+}
+
+/*
+ * Dump ICMPv6 per-interface statistics based on RFC 2466.
+ */
+void
+icmp6_ifstats(char *ifname)
+{
+ struct in6_ifreq ifr;
+ int s;
+#define p(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, plural(ifr.ifr_ifru.ifru_icmp6stat.f))
+#define p2(f, m) if (ifr.ifr_ifru.ifru_icmp6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)ifr.ifr_ifru.ifru_icmp6stat.f, pluralies(ifr.ifr_ifru.ifru_icmp6stat.f))
+
+ if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
+ perror("Warning: socket(AF_INET6)");
+ return;
+ }
+
+ strcpy(ifr.ifr_name, ifname);
+ printf("icmp6 on %s:\n", ifr.ifr_name);
+
+ if (ioctl(s, SIOCGIFSTAT_ICMP6, (char *)&ifr) < 0) {
+ perror("Warning: ioctl(SIOCGIFSTAT_ICMP6)");
+ goto end;
+ }
+
+ p(ifs6_in_msg, "\t%ju total input message%s\n");
+ p(ifs6_in_error, "\t%ju total input error message%s\n");
+ p(ifs6_in_dstunreach, "\t%ju input destination unreachable error%s\n");
+ p(ifs6_in_adminprohib, "\t%ju input administratively prohibited error%s\n");
+ p(ifs6_in_timeexceed, "\t%ju input time exceeded error%s\n");
+ p(ifs6_in_paramprob, "\t%ju input parameter problem error%s\n");
+ p(ifs6_in_pkttoobig, "\t%ju input packet too big error%s\n");
+ p(ifs6_in_echo, "\t%ju input echo request%s\n");
+ p2(ifs6_in_echoreply, "\t%ju input echo repl%s\n");
+ p(ifs6_in_routersolicit, "\t%ju input router solicitation%s\n");
+ p(ifs6_in_routeradvert, "\t%ju input router advertisement%s\n");
+ p(ifs6_in_neighborsolicit, "\t%ju input neighbor solicitation%s\n");
+ p(ifs6_in_neighboradvert, "\t%ju input neighbor advertisement%s\n");
+ p(ifs6_in_redirect, "\t%ju input redirect%s\n");
+ p2(ifs6_in_mldquery, "\t%ju input MLD quer%s\n");
+ p(ifs6_in_mldreport, "\t%ju input MLD report%s\n");
+ p(ifs6_in_mlddone, "\t%ju input MLD done%s\n");
+
+ p(ifs6_out_msg, "\t%ju total output message%s\n");
+ p(ifs6_out_error, "\t%ju total output error message%s\n");
+ p(ifs6_out_dstunreach, "\t%ju output destination unreachable error%s\n");
+ p(ifs6_out_adminprohib, "\t%ju output administratively prohibited error%s\n");
+ p(ifs6_out_timeexceed, "\t%ju output time exceeded error%s\n");
+ p(ifs6_out_paramprob, "\t%ju output parameter problem error%s\n");
+ p(ifs6_out_pkttoobig, "\t%ju output packet too big error%s\n");
+ p(ifs6_out_echo, "\t%ju output echo request%s\n");
+ p2(ifs6_out_echoreply, "\t%ju output echo repl%s\n");
+ p(ifs6_out_routersolicit, "\t%ju output router solicitation%s\n");
+ p(ifs6_out_routeradvert, "\t%ju output router advertisement%s\n");
+ p(ifs6_out_neighborsolicit, "\t%ju output neighbor solicitation%s\n");
+ p(ifs6_out_neighboradvert, "\t%ju output neighbor advertisement%s\n");
+ p(ifs6_out_redirect, "\t%ju output redirect%s\n");
+ p2(ifs6_out_mldquery, "\t%ju output MLD quer%s\n");
+ p(ifs6_out_mldreport, "\t%ju output MLD report%s\n");
+ p(ifs6_out_mlddone, "\t%ju output MLD done%s\n");
+
+ end:
+ close(s);
+#undef p
+}
+
+/*
+ * Dump PIM statistics structure.
+ */
+void
+pim6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct pim6stat pim6stat, zerostat;
+ size_t len = sizeof pim6stat;
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet6.pim.stats", &pim6stat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.pim.stats");
+ return;
+ }
+ } else {
+ if (off == 0)
+ return;
+ kread(off, &pim6stat, len);
+ }
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (pim6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)pim6stat.f, plural(pim6stat.f))
+ p(pim6s_rcv_total, "\t%ju message%s received\n");
+ p(pim6s_rcv_tooshort, "\t%ju message%s received with too few bytes\n");
+ p(pim6s_rcv_badsum, "\t%ju message%s received with bad checksum\n");
+ p(pim6s_rcv_badversion, "\t%ju message%s received with bad version\n");
+ p(pim6s_rcv_registers, "\t%ju register%s received\n");
+ p(pim6s_rcv_badregisters, "\t%ju bad register%s received\n");
+ p(pim6s_snd_registers, "\t%ju register%s sent\n");
+#undef p
+}
+
+/*
+ * Dump raw ip6 statistics structure.
+ */
+void
+rip6_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct rip6stat rip6stat;
+ u_quad_t delivered;
+ size_t len;
+
+ len = sizeof(rip6stat);
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.rip6stats", &rip6stat, &len,
+ NULL, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: net.inet6.ip6.rip6stats");
+ return;
+ }
+ } else
+ kread(off, &rip6stat, len);
+
+ printf("%s:\n", name);
+
+#define p(f, m) if (rip6stat.f || sflag <= 1) \
+ printf(m, (uintmax_t)rip6stat.f, plural(rip6stat.f))
+ p(rip6s_ipackets, "\t%ju message%s received\n");
+ p(rip6s_isum, "\t%ju checksum calculation%s on inbound\n");
+ p(rip6s_badsum, "\t%ju message%s with bad checksum\n");
+ p(rip6s_nosock, "\t%ju message%s dropped due to no socket\n");
+ p(rip6s_nosockmcast,
+ "\t%ju multicast message%s dropped due to no socket\n");
+ p(rip6s_fullsock,
+ "\t%ju message%s dropped due to full socket buffers\n");
+ delivered = rip6stat.rip6s_ipackets -
+ rip6stat.rip6s_badsum -
+ rip6stat.rip6s_nosock -
+ rip6stat.rip6s_nosockmcast -
+ rip6stat.rip6s_fullsock;
+ if (delivered || sflag <= 1)
+ printf("\t%ju delivered\n", (uintmax_t)delivered);
+ p(rip6s_opackets, "\t%ju datagram%s output\n");
+#undef p
+}
+
+/*
+ * Pretty print an Internet address (net address + port).
+ * Take numeric_addr and numeric_port into consideration.
+ */
+#define GETSERVBYPORT6(port, proto, ret)\
+{\
+ if (strcmp((proto), "tcp6") == 0)\
+ (ret) = getservbyport((int)(port), "tcp");\
+ else if (strcmp((proto), "udp6") == 0)\
+ (ret) = getservbyport((int)(port), "udp");\
+ else\
+ (ret) = getservbyport((int)(port), (proto));\
+};
+
+void
+inet6print(struct in6_addr *in6, int port, const char *proto, int numeric)
+{
+ struct servent *sp = 0;
+ char line[80], *cp;
+ int width;
+
+ sprintf(line, "%.*s.", Wflag ? 39 :
+ (Aflag && !numeric) ? 12 : 16, inet6name(in6));
+ cp = index(line, '\0');
+ if (!numeric && port)
+ GETSERVBYPORT6(port, proto, sp);
+ if (sp || port == 0)
+ sprintf(cp, "%.15s", sp ? sp->s_name : "*");
+ else
+ sprintf(cp, "%d", ntohs((u_short)port));
+ width = Wflag ? 45 : Aflag ? 18 : 22;
+ printf("%-*.*s ", width, width, line);
+}
+
+/*
+ * Construct an Internet address representation.
+ * If the numeric_addr has been supplied, give
+ * numeric value, otherwise try for symbolic name.
+ */
+
+char *
+inet6name(struct in6_addr *in6p)
+{
+ char *cp;
+ static char line[50];
+ struct hostent *hp;
+ static char domain[MAXHOSTNAMELEN];
+ static int first = 1;
+
+ if (first && !numeric_addr) {
+ first = 0;
+ if (gethostname(domain, MAXHOSTNAMELEN) == 0 &&
+ (cp = index(domain, '.')))
+ (void) strcpy(domain, cp + 1);
+ else
+ domain[0] = 0;
+ }
+ cp = 0;
+ if (!numeric_addr && !IN6_IS_ADDR_UNSPECIFIED(in6p)) {
+ hp = gethostbyaddr((char *)in6p, sizeof(*in6p), AF_INET6);
+ if (hp) {
+ if ((cp = index(hp->h_name, '.')) &&
+ !strcmp(cp + 1, domain))
+ *cp = 0;
+ cp = hp->h_name;
+ }
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED(in6p))
+ strcpy(line, "*");
+ else if (cp)
+ strcpy(line, cp);
+ else
+ sprintf(line, "%s",
+ inet_ntop(AF_INET6, (void *)in6p, ntop_buf,
+ sizeof(ntop_buf)));
+ return (line);
+}
+#endif /*INET6*/
diff --git a/freebsd/usr.bin/netstat/ipsec.c b/freebsd/usr.bin/netstat/ipsec.c
new file mode 100644
index 00000000..a6ef510c
--- /dev/null
+++ b/freebsd/usr.bin/netstat/ipsec.c
@@ -0,0 +1,481 @@
+/* $KAME: ipsec.c,v 1.33 2003/07/25 09:54:32 itojun Exp $ */
+
+/*-
+ * Copyright (c) 2005 NTT Multimedia Communications Laboratories, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 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.
+ */
+/*-
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef IPSEC
+#ifdef __rtems__
+#include <freebsd/netipsec/ipsec.h>
+#include <freebsd/netipsec/ah_var.h>
+#include <freebsd/netipsec/esp_var.h>
+#include <freebsd/netipsec/ipcomp_var.h>
+#else
+#include <netipsec/ipsec.h>
+#include <netipsec/ah_var.h>
+#include <netipsec/esp_var.h>
+#include <netipsec/ipcomp_var.h>
+#endif
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#ifdef IPSEC
+struct val2str {
+ int val;
+ const char *str;
+};
+
+static struct val2str ipsec_ahnames[] = {
+ { SADB_AALG_NONE, "none", },
+ { SADB_AALG_MD5HMAC, "hmac-md5", },
+ { SADB_AALG_SHA1HMAC, "hmac-sha1", },
+ { SADB_X_AALG_MD5, "md5", },
+ { SADB_X_AALG_SHA, "sha", },
+ { SADB_X_AALG_NULL, "null", },
+#ifdef SADB_X_AALG_SHA2_256
+ { SADB_X_AALG_SHA2_256, "hmac-sha2-256", },
+#endif
+#ifdef SADB_X_AALG_SHA2_384
+ { SADB_X_AALG_SHA2_384, "hmac-sha2-384", },
+#endif
+#ifdef SADB_X_AALG_SHA2_512
+ { SADB_X_AALG_SHA2_512, "hmac-sha2-512", },
+#endif
+#ifdef SADB_X_AALG_RIPEMD160HMAC
+ { SADB_X_AALG_RIPEMD160HMAC, "hmac-ripemd160", },
+#endif
+#ifdef SADB_X_AALG_AES_XCBC_MAC
+ { SADB_X_AALG_AES_XCBC_MAC, "aes-xcbc-mac", },
+#endif
+ { -1, NULL },
+};
+
+static struct val2str ipsec_espnames[] = {
+ { SADB_EALG_NONE, "none", },
+ { SADB_EALG_DESCBC, "des-cbc", },
+ { SADB_EALG_3DESCBC, "3des-cbc", },
+ { SADB_EALG_NULL, "null", },
+ { SADB_X_EALG_CAST128CBC, "cast128-cbc", },
+ { SADB_X_EALG_BLOWFISHCBC, "blowfish-cbc", },
+#ifdef SADB_X_EALG_RIJNDAELCBC
+ { SADB_X_EALG_RIJNDAELCBC, "rijndael-cbc", },
+#endif
+#ifdef SADB_X_EALG_AESCTR
+ { SADB_X_EALG_AESCTR, "aes-ctr", },
+#endif
+ { -1, NULL },
+};
+
+static struct val2str ipsec_compnames[] = {
+ { SADB_X_CALG_NONE, "none", },
+ { SADB_X_CALG_OUI, "oui", },
+ { SADB_X_CALG_DEFLATE, "deflate", },
+ { SADB_X_CALG_LZS, "lzs", },
+ { -1, NULL },
+};
+
+static void ipsec_hist(const u_quad_t *hist, size_t histmax,
+ const struct val2str *name, const char *title);
+static void print_ipsecstats(const struct ipsecstat *ipsecstat);
+
+
+/*
+ * Dump IPSEC statistics structure.
+ */
+static void
+ipsec_hist(const u_quad_t *hist, size_t histmax, const struct val2str *name,
+ const char *title)
+{
+ int first;
+ size_t proto;
+ const struct val2str *p;
+
+ first = 1;
+ for (proto = 0; proto < histmax; proto++) {
+ if (hist[proto] <= 0)
+ continue;
+ if (first) {
+ printf("\t%s histogram:\n", title);
+ first = 0;
+ }
+ for (p = name; p && p->str; p++) {
+ if (p->val == (int)proto)
+ break;
+ }
+ if (p && p->str) {
+ printf("\t\t%s: %ju\n", p->str, (uintmax_t)hist[proto]);
+ } else {
+ printf("\t\t#%ld: %ju\n", (long)proto,
+ (uintmax_t)hist[proto]);
+ }
+ }
+}
+
+static void
+print_ipsecstats(const struct ipsecstat *ipsecstat)
+{
+#define p(f, m) if (ipsecstat->f || sflag <= 1) \
+ printf(m, (uintmax_t)ipsecstat->f, plural(ipsecstat->f))
+#define pes(f, m) if (ipsecstat->f || sflag <= 1) \
+ printf(m, (uintmax_t)ipsecstat->f, plurales(ipsecstat->f))
+#define hist(f, n, t) \
+ ipsec_hist((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+ p(in_success, "\t%ju inbound packet%s processed successfully\n");
+ p(in_polvio, "\t%ju inbound packet%s violated process security "
+ "policy\n");
+ p(in_nosa, "\t%ju inbound packet%s with no SA available\n");
+ p(in_inval, "\t%ju invalid inbound packet%s\n");
+ p(in_nomem, "\t%ju inbound packet%s failed due to insufficient memory\n");
+ p(in_badspi, "\t%ju inbound packet%s failed getting SPI\n");
+ p(in_ahreplay, "\t%ju inbound packet%s failed on AH replay check\n");
+ p(in_espreplay, "\t%ju inbound packet%s failed on ESP replay check\n");
+ p(in_ahauthsucc, "\t%ju inbound packet%s considered authentic\n");
+ p(in_ahauthfail, "\t%ju inbound packet%s failed on authentication\n");
+ hist(ipsecstat->in_ahhist, ipsec_ahnames, "AH input");
+ hist(ipsecstat->in_esphist, ipsec_espnames, "ESP input");
+ hist(ipsecstat->in_comphist, ipsec_compnames, "IPComp input");
+
+ p(out_success, "\t%ju outbound packet%s processed successfully\n");
+ p(out_polvio, "\t%ju outbound packet%s violated process security "
+ "policy\n");
+ p(out_nosa, "\t%ju outbound packet%s with no SA available\n");
+ p(out_inval, "\t%ju invalid outbound packet%s\n");
+ p(out_nomem, "\t%ju outbound packet%s failed due to insufficient memory\n");
+ p(out_noroute, "\t%ju outbound packet%s with no route\n");
+ hist(ipsecstat->out_ahhist, ipsec_ahnames, "AH output");
+ hist(ipsecstat->out_esphist, ipsec_espnames, "ESP output");
+ hist(ipsecstat->out_comphist, ipsec_compnames, "IPComp output");
+ p(spdcachelookup, "\t%ju SPD cache lookup%s\n");
+ pes(spdcachemiss, "\t%ju SPD cache miss%s\n");
+#undef pes
+#undef hist
+ p(ips_in_polvio, "\t%ju inbound packet%s violated process "
+ "security policy\n");
+ p(ips_out_polvio, "\t%ju outbound packet%s violated process "
+ "security policy\n");
+ p(ips_out_nosa, "\t%ju outbound packet%s with no SA available\n");
+ p(ips_out_nomem, "\t%ju outbound packet%s failed due to "
+ "insufficient memory\n");
+ p(ips_out_noroute, "\t%ju outbound packet%s with no route "
+ "available\n");
+ p(ips_out_inval, "\t%ju invalid outbound packet%s\n");
+ p(ips_out_bundlesa, "\t%ju outbound packet%s with bundled SAs\n");
+ p(ips_mbcoalesced, "\t%ju mbuf%s coalesced during clone\n");
+ p(ips_clcoalesced, "\t%ju cluster%s coalesced during clone\n");
+ p(ips_clcopied, "\t%ju cluster%s copied during clone\n");
+ p(ips_mbinserted, "\t%ju mbuf%s inserted during makespace\n");
+#undef p
+}
+
+void
+ipsec_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct ipsecstat ipsecstat;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&ipsecstat, sizeof(ipsecstat));
+
+ print_ipsecstats(&ipsecstat);
+}
+
+
+static void ipsec_hist_new(const u_int32_t *hist, size_t histmax,
+ const struct val2str *name, const char *title);
+static void print_ahstats(const struct ahstat *ahstat);
+static void print_espstats(const struct espstat *espstat);
+static void print_ipcompstats(const struct ipcompstat *ipcompstat);
+
+/*
+ * Dump IPSEC statistics structure.
+ */
+static void
+ipsec_hist_new(const u_int32_t *hist, size_t histmax,
+ const struct val2str *name, const char *title)
+{
+ int first;
+ size_t proto;
+ const struct val2str *p;
+
+ first = 1;
+ for (proto = 0; proto < histmax; proto++) {
+ if (hist[proto] <= 0)
+ continue;
+ if (first) {
+ printf("\t%s histogram:\n", title);
+ first = 0;
+ }
+ for (p = name; p && p->str; p++) {
+ if (p->val == (int)proto)
+ break;
+ }
+ if (p && p->str) {
+ printf("\t\t%s: %u\n", p->str, hist[proto]);
+ } else {
+ printf("\t\t#%lu: %u\n", (unsigned long)proto,
+ hist[proto]);
+ }
+ }
+}
+
+static void
+print_ahstats(const struct ahstat *ahstat)
+{
+#define p32(f, m) if (ahstat->f || sflag <= 1) \
+ printf("\t%u" m, (unsigned int)ahstat->f, plural(ahstat->f))
+#define p64(f, m) if (ahstat->f || sflag <= 1) \
+ printf("\t%ju" m, (uintmax_t)ahstat->f, plural(ahstat->f))
+#define hist(f, n, t) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+ p32(ahs_hdrops, " packet%s shorter than header shows\n");
+ p32(ahs_nopf, " packet%s dropped; protocol family not supported\n");
+ p32(ahs_notdb, " packet%s dropped; no TDB\n");
+ p32(ahs_badkcr, " packet%s dropped; bad KCR\n");
+ p32(ahs_qfull, " packet%s dropped; queue full\n");
+ p32(ahs_noxform, " packet%s dropped; no transform\n");
+ p32(ahs_wrap, " replay counter wrap%s\n");
+ p32(ahs_badauth, " packet%s dropped; bad authentication detected\n");
+ p32(ahs_badauthl, " packet%s dropped; bad authentication length\n");
+ p32(ahs_replay, " possible replay packet%s detected\n");
+ p32(ahs_input, " packet%s in\n");
+ p32(ahs_output, " packet%s out\n");
+ p32(ahs_invalid, " packet%s dropped; invalid TDB\n");
+ p64(ahs_ibytes, " byte%s in\n");
+ p64(ahs_obytes, " byte%s out\n");
+ p32(ahs_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+ p32(ahs_pdrops, " packet%s blocked due to policy\n");
+ p32(ahs_crypto, " crypto processing failure%s\n");
+ p32(ahs_tunnel, " tunnel sanity check failure%s\n");
+ hist(ahstat->ahs_hist, ipsec_ahnames, "AH output");
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+ah_stats(u_long off, const char *name, int family __unused, int proto __unused)
+{
+ struct ahstat ahstat;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&ahstat, sizeof(ahstat));
+
+ print_ahstats(&ahstat);
+}
+
+static void
+print_espstats(const struct espstat *espstat)
+{
+#define p32(f, m) if (espstat->f || sflag <= 1) \
+ printf("\t%u" m, (unsigned int)espstat->f, plural(espstat->f))
+#define p64(f, m) if (espstat->f || sflag <= 1) \
+ printf("\t%ju" m, (uintmax_t)espstat->f, plural(espstat->f))
+#define hist(f, n, t) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+ p32(esps_hdrops, " packet%s shorter than header shows\n");
+ p32(esps_nopf, " packet%s dropped; protocol family not supported\n");
+ p32(esps_notdb, " packet%s dropped; no TDB\n");
+ p32(esps_badkcr, " packet%s dropped; bad KCR\n");
+ p32(esps_qfull, " packet%s dropped; queue full\n");
+ p32(esps_noxform, " packet%s dropped; no transform\n");
+ p32(esps_badilen, " packet%s dropped; bad ilen\n");
+ p32(esps_wrap, " replay counter wrap%s\n");
+ p32(esps_badenc, " packet%s dropped; bad encryption detected\n");
+ p32(esps_badauth, " packet%s dropped; bad authentication detected\n");
+ p32(esps_replay, " possible replay packet%s detected\n");
+ p32(esps_input, " packet%s in\n");
+ p32(esps_output, " packet%s out\n");
+ p32(esps_invalid, " packet%s dropped; invalid TDB\n");
+ p64(esps_ibytes, " byte%s in\n");
+ p64(esps_obytes, " byte%s out\n");
+ p32(esps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+ p32(esps_pdrops, " packet%s blocked due to policy\n");
+ p32(esps_crypto, " crypto processing failure%s\n");
+ p32(esps_tunnel, " tunnel sanity check failure%s\n");
+ hist(espstat->esps_hist, ipsec_espnames, "ESP output");
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+esp_stats(u_long off, const char *name, int family __unused, int proto __unused)
+{
+ struct espstat espstat;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&espstat, sizeof(espstat));
+
+ print_espstats(&espstat);
+}
+
+static void
+print_ipcompstats(const struct ipcompstat *ipcompstat)
+{
+ uint32_t version;
+#define p32(f, m) if (ipcompstat->f || sflag <= 1) \
+ printf("\t%u" m, (unsigned int)ipcompstat->f, plural(ipcompstat->f))
+#define p64(f, m) if (ipcompstat->f || sflag <= 1) \
+ printf("\t%ju" m, (uintmax_t)ipcompstat->f, plural(ipcompstat->f))
+#define hist(f, n, t) \
+ ipsec_hist_new((f), sizeof(f)/sizeof(f[0]), (n), (t));
+
+#ifndef IPCOMPSTAT_VERSION
+ version = 0;
+#else
+ version = ipcompstat->version;
+#endif
+ p32(ipcomps_hdrops, " packet%s shorter than header shows\n");
+ p32(ipcomps_nopf, " packet%s dropped; protocol family not supported\n");
+ p32(ipcomps_notdb, " packet%s dropped; no TDB\n");
+ p32(ipcomps_badkcr, " packet%s dropped; bad KCR\n");
+ p32(ipcomps_qfull, " packet%s dropped; queue full\n");
+ p32(ipcomps_noxform, " packet%s dropped; no transform\n");
+ p32(ipcomps_wrap, " replay counter wrap%s\n");
+ p32(ipcomps_input, " packet%s in\n");
+ p32(ipcomps_output, " packet%s out\n");
+ p32(ipcomps_invalid, " packet%s dropped; invalid TDB\n");
+ p64(ipcomps_ibytes, " byte%s in\n");
+ p64(ipcomps_obytes, " byte%s out\n");
+ p32(ipcomps_toobig, " packet%s dropped; larger than IP_MAXPACKET\n");
+ p32(ipcomps_pdrops, " packet%s blocked due to policy\n");
+ p32(ipcomps_crypto, " crypto processing failure%s\n");
+ hist(ipcompstat->ipcomps_hist, ipsec_compnames, "COMP output");
+ if (version >= 1) {
+ p32(ipcomps_threshold, " packet%s sent uncompressed; size < compr. algo. threshold\n");
+ p32(ipcomps_uncompr, " packet%s sent uncompressed; compression was useless\n");
+ }
+
+#undef p32
+#undef p64
+#undef hist
+}
+
+void
+ipcomp_stats(u_long off, const char *name, int family __unused,
+ int proto __unused)
+{
+ struct ipcompstat ipcompstat;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&ipcompstat, sizeof(ipcompstat));
+
+ print_ipcompstats(&ipcompstat);
+}
+
+#endif /*IPSEC*/
diff --git a/freebsd/usr.bin/netstat/main.c b/freebsd/usr.bin/netstat/main.c
new file mode 100644
index 00000000..1c2461b0
--- /dev/null
+++ b/freebsd/usr.bin/netstat/main.c
@@ -0,0 +1,1229 @@
+#ifdef __rtems__
+#define __need_getopt_newlib
+#include <getopt.h>
+#endif
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * 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.
+ */
+
+#ifndef lint
+char const copyright[] =
+"@(#) Copyright (c) 1983, 1988, 1993\n\
+ Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)main.c 8.4 (Berkeley) 3/1/94";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/file.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef NETGRAPH
+#include <netgraph/ng_socket.h>
+#endif
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <kvm.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nlist.h>
+#include <paths.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+static struct nlist nl[] = {
+#define N_IFNET 0
+ { .n_name = "_ifnet" },
+#define N_RTSTAT 1
+ { .n_name = "_rtstat" },
+#define N_RTREE 2
+ { .n_name = "_rt_tables"},
+#define N_MRTSTAT 3
+ { .n_name = "_mrtstat" },
+#define N_MFCHASHTBL 4
+ { .n_name = "_mfchashtbl" },
+#define N_VIFTABLE 5
+ { .n_name = "_viftable" },
+#define N_IPX 6
+ { .n_name = "_ipxpcb_list"},
+#define N_IPXSTAT 7
+ { .n_name = "_ipxstat"},
+#define N_SPXSTAT 8
+ { .n_name = "_spx_istat"},
+#define N_DDPSTAT 9
+ { .n_name = "_ddpstat"},
+#define N_DDPCB 10
+ { .n_name = "_ddpcb"},
+#define N_NGSOCKS 11
+ { .n_name = "_ngsocklist"},
+#define N_IP6STAT 12
+ { .n_name = "_ip6stat" },
+#define N_ICMP6STAT 13
+ { .n_name = "_icmp6stat" },
+#define N_IPSECSTAT 14
+ { .n_name = "_ipsec4stat" },
+#define N_IPSEC6STAT 15
+ { .n_name = "_ipsec6stat" },
+#define N_PIM6STAT 16
+ { .n_name = "_pim6stat" },
+#define N_MRT6STAT 17
+ { .n_name = "_mrt6stat" },
+#define N_MF6CTABLE 18
+ { .n_name = "_mf6ctable" },
+#define N_MIF6TABLE 19
+ { .n_name = "_mif6table" },
+#define N_PFKEYSTAT 20
+ { .n_name = "_pfkeystat" },
+#define N_MBSTAT 21
+ { .n_name = "_mbstat" },
+#define N_MBTYPES 22
+ { .n_name = "_mbtypes" },
+#define N_NMBCLUSTERS 23
+ { .n_name = "_nmbclusters" },
+#define N_NMBUFS 24
+ { .n_name = "_nmbufs" },
+#define N_MBHI 25
+ { .n_name = "_mbuf_hiwm" },
+#define N_CLHI 26
+ { .n_name = "_clust_hiwm" },
+#define N_NCPUS 27
+ { .n_name = "_smp_cpus" },
+#define N_PAGESZ 28
+ { .n_name = "_pagesize" },
+#define N_MBPSTAT 29
+ { .n_name = "_mb_statpcpu" },
+#define N_RTTRASH 30
+ { .n_name = "_rttrash" },
+#define N_MBLO 31
+ { .n_name = "_mbuf_lowm" },
+#define N_CLLO 32
+ { .n_name = "_clust_lowm" },
+#define N_CARPSTAT 33
+ { .n_name = "_carpstats" },
+#define N_PFSYNCSTAT 34
+ { .n_name = "_pfsyncstats" },
+#define N_AHSTAT 35
+ { .n_name = "_ahstat" },
+#define N_ESPSTAT 36
+ { .n_name = "_espstat" },
+#define N_IPCOMPSTAT 37
+ { .n_name = "_ipcompstat" },
+#define N_TCPSTAT 38
+ { .n_name = "_tcpstat" },
+#define N_UDPSTAT 39
+ { .n_name = "_udpstat" },
+#define N_IPSTAT 40
+ { .n_name = "_ipstat" },
+#define N_ICMPSTAT 41
+ { .n_name = "_icmpstat" },
+#define N_IGMPSTAT 42
+ { .n_name = "_igmpstat" },
+#define N_PIMSTAT 43
+ { .n_name = "_pimstat" },
+#define N_TCBINFO 44
+ { .n_name = "_tcbinfo" },
+#define N_UDBINFO 45
+ { .n_name = "_udbinfo" },
+#define N_DIVCBINFO 46
+ { .n_name = "_divcbinfo" },
+#define N_RIPCBINFO 47
+ { .n_name = "_ripcbinfo" },
+#define N_UNP_COUNT 48
+ { .n_name = "_unp_count" },
+#define N_UNP_GENCNT 49
+ { .n_name = "_unp_gencnt" },
+#define N_UNP_DHEAD 50
+ { .n_name = "_unp_dhead" },
+#define N_UNP_SHEAD 51
+ { .n_name = "_unp_shead" },
+#define N_RIP6STAT 52
+ { .n_name = "_rip6stat" },
+#define N_SCTPSTAT 53
+ { .n_name = "_sctpstat" },
+#define N_MFCTABLESIZE 54
+ { .n_name = "_mfctablesize" },
+#define N_ARPSTAT 55
+ { .n_name = "_arpstat" },
+ { .n_name = NULL },
+};
+
+struct protox {
+ int pr_index; /* index into nlist of cb head */
+ int pr_sindex; /* index into nlist of stat block */
+ u_char pr_wanted; /* 1 if wanted, 0 otherwise */
+ void (*pr_cblocks)(u_long, const char *, int, int);
+ /* control blocks printing routine */
+ void (*pr_stats)(u_long, const char *, int, int);
+ /* statistics printing routine */
+ void (*pr_istats)(char *); /* per/if statistics printing routine */
+ const char *pr_name; /* well-known name */
+ int pr_usesysctl; /* non-zero if we use sysctl, not kvm */
+ int pr_protocol;
+} protox[] = {
+ { N_TCBINFO, N_TCPSTAT, 1, protopr,
+ tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ { N_UDBINFO, N_UDPSTAT, 1, protopr,
+ udp_stats, NULL, "udp", 1, IPPROTO_UDP },
+#ifdef SCTP
+ { -1, N_SCTPSTAT, 1, sctp_protopr,
+ sctp_stats, NULL, "sctp", 1, IPPROTO_SCTP },
+#endif
+ { N_DIVCBINFO, -1, 1, protopr,
+ NULL, NULL, "divert", 1, IPPROTO_DIVERT },
+ { N_RIPCBINFO, N_IPSTAT, 1, protopr,
+ ip_stats, NULL, "ip", 1, IPPROTO_RAW },
+ { N_RIPCBINFO, N_ICMPSTAT, 1, protopr,
+ icmp_stats, NULL, "icmp", 1, IPPROTO_ICMP },
+ { N_RIPCBINFO, N_IGMPSTAT, 1, protopr,
+ igmp_stats, NULL, "igmp", 1, IPPROTO_IGMP },
+#ifdef IPSEC
+ { -1, N_IPSECSTAT, 1, NULL, /* keep as compat */
+ ipsec_stats, NULL, "ipsec", 0, 0},
+ { -1, N_AHSTAT, 1, NULL,
+ ah_stats, NULL, "ah", 0, 0},
+ { -1, N_ESPSTAT, 1, NULL,
+ esp_stats, NULL, "esp", 0, 0},
+ { -1, N_IPCOMPSTAT, 1, NULL,
+ ipcomp_stats, NULL, "ipcomp", 0, 0},
+#endif
+ { N_RIPCBINFO, N_PIMSTAT, 1, protopr,
+ pim_stats, NULL, "pim", 1, IPPROTO_PIM },
+ { -1, N_CARPSTAT, 1, NULL,
+ carp_stats, NULL, "carp", 1, 0 },
+ { -1, N_PFSYNCSTAT, 1, NULL,
+ pfsync_stats, NULL, "pfsync", 1, 0 },
+ { -1, N_ARPSTAT, 1, NULL,
+ arp_stats, NULL, "arp", 1, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+
+#ifdef INET6
+struct protox ip6protox[] = {
+ { N_TCBINFO, N_TCPSTAT, 1, protopr,
+ tcp_stats, NULL, "tcp", 1, IPPROTO_TCP },
+ { N_UDBINFO, N_UDPSTAT, 1, protopr,
+ udp_stats, NULL, "udp", 1, IPPROTO_UDP },
+ { N_RIPCBINFO, N_IP6STAT, 1, protopr,
+ ip6_stats, ip6_ifstats, "ip6", 1, IPPROTO_RAW },
+ { N_RIPCBINFO, N_ICMP6STAT, 1, protopr,
+ icmp6_stats, icmp6_ifstats, "icmp6", 1, IPPROTO_ICMPV6 },
+#ifdef IPSEC
+ { -1, N_IPSEC6STAT, 1, NULL,
+ ipsec_stats, NULL, "ipsec6", 0, 0 },
+#endif
+#ifdef notyet
+ { -1, N_PIM6STAT, 1, NULL,
+ pim6_stats, NULL, "pim6", 1, 0 },
+#endif
+ { -1, N_RIP6STAT, 1, NULL,
+ rip6_stats, NULL, "rip6", 1, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+#endif /*INET6*/
+
+#ifdef IPSEC
+struct protox pfkeyprotox[] = {
+ { -1, N_PFKEYSTAT, 1, NULL,
+ pfkey_stats, NULL, "pfkey", 0, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+#endif
+
+#ifndef __rtems__
+struct protox atalkprotox[] = {
+ { N_DDPCB, N_DDPSTAT, 1, atalkprotopr,
+ ddp_stats, NULL, "ddp", 0, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+#endif
+#ifdef NETGRAPH
+struct protox netgraphprotox[] = {
+ { N_NGSOCKS, -1, 1, netgraphprotopr,
+ NULL, NULL, "ctrl", 0, 0 },
+ { N_NGSOCKS, -1, 1, netgraphprotopr,
+ NULL, NULL, "data", 0, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, NULL, 0, 0 }
+};
+#endif
+#ifdef IPX
+struct protox ipxprotox[] = {
+ { N_IPX, N_IPXSTAT, 1, ipxprotopr,
+ ipx_stats, NULL, "ipx", 0, 0 },
+ { N_IPX, N_SPXSTAT, 1, ipxprotopr,
+ spx_stats, NULL, "spx", 0, 0 },
+ { -1, -1, 0, NULL,
+ NULL, NULL, 0, 0, 0 }
+};
+#endif
+
+struct protox *protoprotox[] = {
+ protox,
+#ifdef INET6
+ ip6protox,
+#endif
+#ifdef IPSEC
+ pfkeyprotox,
+#endif
+#ifdef IPX
+ ipxprotox,
+#endif
+#ifndef __rtems__
+ atalkprotox, NULL };
+#else
+ NULL };
+#endif
+
+static void printproto(struct protox *, const char *);
+static void usage(void);
+static struct protox *name2protox(const char *);
+static struct protox *knownname(const char *);
+
+static kvm_t *kvmd;
+static char *nlistf = NULL, *memf = NULL;
+
+int Aflag; /* show addresses of protocol control block */
+int aflag; /* show all sockets (including servers) */
+int Bflag; /* show information about bpf consumers */
+int bflag; /* show i/f total bytes in/out */
+int dflag; /* show i/f dropped packets */
+int gflag; /* show group (multicast) routing or stats */
+int hflag; /* show counters in human readable format */
+int iflag; /* show interfaces */
+int Lflag; /* show size of listen queues */
+int mflag; /* show memory stats */
+int noutputs = 0; /* how much outputs before we exit */
+int numeric_addr; /* show addresses numerically */
+int numeric_port; /* show ports numerically */
+static int pflag; /* show given protocol */
+int rflag; /* show routing tables (or routing stats) */
+int sflag; /* show protocol statistics */
+int tflag; /* show i/f watchdog timers */
+int Wflag; /* wide display */
+int xflag; /* extra information, includes all socket buffer info */
+int zflag; /* zero stats */
+
+int interval; /* repeat interval for i/f stats */
+
+char *interface; /* desired i/f for stats, or NULL for all i/fs */
+int unit; /* unit number for above */
+
+int af; /* address family */
+int live; /* true if we are examining a live system */
+
+
+#ifdef __rtems__
+static int main_netstat(int argc, char *argv[]);
+static int rtems_shell_main_netstat(int argc, char *argv[])
+{
+ int i;
+ rtems_shell_globals_t netstat_globals;
+ rtems_shell_globals = &netstat_globals;
+ memset (rtems_shell_globals, 0, sizeof (netstat_globals));
+
+ i = 0;
+ protox[i].pr_index = N_TCBINFO;
+ protox[i].pr_sindex = N_TCPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = protopr;
+ protox[i].pr_stats = tcp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "tcp";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_TCP;
+ i++;
+ protox[i].pr_index = N_UDBINFO;
+ protox[i].pr_sindex = N_UDPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = protopr;
+ protox[i].pr_stats = udp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "udp";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_UDP;
+ i++;
+#ifdef SCTP
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_SCTPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = sctp_protopr;
+ protox[i].pr_stats = sctp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "sctp";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_SCTP;
+ i++;
+#endif
+ protox[i].pr_index = N_DIVCBINFO;
+ protox[i].pr_sindex = -1;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = protopr;
+ protox[i].pr_stats = NULL;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "divert";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_DIVERT;
+ i++;
+ protox[i].pr_index = N_RIPCBINFO;
+ protox[i].pr_sindex = N_IPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = protopr;
+ protox[i].pr_stats = ip_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "ip";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_RAW;
+ i++;
+ protox[i].pr_index = N_RIPCBINFO;
+ protox[i].pr_sindex = N_ICMPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = protopr;
+ protox[i].pr_stats = icmp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "icmp";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_ICMP;
+ i++;
+ protox[i].pr_index = N_RIPCBINFO;
+ protox[i].pr_sindex = N_IGMPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = protopr;
+ protox[i].pr_stats = igmp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "igmp";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_IGMP;
+ i++;
+#ifdef IPSEC
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_IPSECSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = ipsec_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "ipsec";
+ protox[i].pr_usesysctl = 0;
+ protox[i].pr_protocol = 0;
+ i++;
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_AHSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = ah_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "ah";
+ protox[i].pr_usesysctl = 0;
+ protox[i].pr_protocol = 0;
+ i++;
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_ESPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = esp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "esp";
+ protox[i].pr_usesysctl = 0;
+ protox[i].pr_protocol = 0;
+ i++;
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_IPCOMPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = ipcomp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "ipcomp";
+ protox[i].pr_usesysctl = 0;
+ protox[i].pr_protocol = 0;
+ i++;
+#endif
+ protox[i].pr_index = N_RIPCBINFO;
+ protox[i].pr_sindex = N_PIMSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = protopr;
+ protox[i].pr_stats = pim_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "pim";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = IPPROTO_PIM;
+ i++;
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_CARPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = carp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "carp";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = 0;
+ i++;
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_PFSYNCSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = pfsync_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "pfsync";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = 0;
+ i++;
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = N_ARPSTAT;
+ protox[i].pr_wanted = 1;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = arp_stats;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = "arp";
+ protox[i].pr_usesysctl = 1;
+ protox[i].pr_protocol = 0;
+ i++;
+ protox[i].pr_index = -1;
+ protox[i].pr_sindex = -1;
+ protox[i].pr_wanted = 0;
+ protox[i].pr_cblocks = NULL;
+ protox[i].pr_stats = NULL;
+ protox[i].pr_istats = NULL;
+ protox[i].pr_name = NULL;
+ protox[i].pr_usesysctl = 0;
+ protox[i].pr_protocol = 0;
+
+#ifdef INET6
+ i=0;
+ ip6protox[i].pr_index = N_TCBINFO;
+ ip6protox[i].pr_sindex = N_TCPSTAT;
+ ip6protox[i].pr_wanted = 1;
+ ip6protox[i].pr_cblocks = protopr;
+ ip6protox[i].pr_stats = tcp_stats;
+ ip6protox[i].pr_istats = NULL;
+ ip6protox[i].pr_name = "tcp";
+ ip6protox[i].pr_usesysctl = 1;
+ ip6protox[i].pr_protocol = IPPROTO_TCP;
+ i++;
+ ip6protox[i].pr_index = N_UDBINFO;
+ ip6protox[i].pr_sindex = N_UDPSTAT;
+ ip6protox[i].pr_wanted = 1;
+ ip6protox[i].pr_cblocks = protopr;
+ ip6protox[i].pr_stats = udp_stats;
+ ip6protox[i].pr_istats = NULL;
+ ip6protox[i].pr_name = "udp";
+ ip6protox[i].pr_usesysctl = 1;
+ ip6protox[i].pr_protocol = IPPROTO_UDP;
+ i++;
+ ip6protox[i].pr_index = N_RIPCBINFO;
+ ip6protox[i].pr_sindex = N_IP6STAT;
+ ip6protox[i].pr_wanted = 1;
+ ip6protox[i].pr_cblocks = protopr;
+ ip6protox[i].pr_stats = ip6_stats;
+ ip6protox[i].pr_istats = ip6_ifstats;
+ ip6protox[i].pr_name = "ip6";
+ ip6protox[i].pr_usesysctl = 1;
+ ip6protox[i].pr_protocol = IPPROTO_RAW;
+ i++;
+ ip6protox[i].pr_index = N_RIPCBINFO;
+ ip6protox[i].pr_sindex = N_ICMP6STAT;
+ ip6protox[i].pr_wanted = 1;
+ ip6protox[i].pr_cblocks = protopr;
+ ip6protox[i].pr_stats = icmp6_stats;
+ ip6protox[i].pr_istats = icmp6_ifstats;
+ ip6protox[i].pr_name = "icmp6";
+ ip6protox[i].pr_usesysctl = 1;
+ ip6protox[i].pr_protocol = IPPROTO_ICMPV6;
+ i++;
+#ifdef IPSEC
+ ip6protox[i].pr_index = -1;
+ ip6protox[i].pr_sindex = N_IPSEC6STAT;
+ ip6protox[i].pr_wanted = 1;
+ ip6protox[i].pr_cblocks = NULL;
+ ip6protox[i].pr_stats = ipsec_stats;
+ ip6protox[i].pr_istats = NULL;
+ ip6protox[i].pr_name = "ipsec6";
+ ip6protox[i].pr_usesysctl = 0;
+ ip6protox[i].pr_protocol = 0;
+ i++;
+#endif
+#ifdef notyet
+ ip6protox[i].pr_index = -1;
+ ip6protox[i].pr_sindex = N_PIM6STAT;
+ ip6protox[i].pr_wanted = 1;
+ ip6protox[i].pr_cblocks = NULL;
+ ip6protox[i].pr_stats = pim6_stats;
+ ip6protox[i].pr_istats = NULL;
+ ip6protox[i].pr_name = "pim6";
+ ip6protox[i].pr_usesysctl = 1;
+ ip6protox[i].pr_protocol = 0;
+ i++;
+#endif
+ ip6protox[i].pr_index = -1;
+ ip6protox[i].pr_sindex = N_RIP6STAT;
+ ip6protox[i].pr_wanted = 1;
+ ip6protox[i].pr_cblocks = NULL;
+ ip6protox[i].pr_stats = rip6_stats;
+ ip6protox[i].pr_istats = NULL;
+ ip6protox[i].pr_name = "rip6";
+ ip6protox[i].pr_usesysctl = 1;
+ ip6protox[i].pr_protocol = 0;
+ i++;
+ ip6protox[i].pr_index = -1;
+ ip6protox[i].pr_sindex = -1;
+ ip6protox[i].pr_wanted = 0;
+ ip6protox[i].pr_cblocks = NULL;
+ ip6protox[i].pr_stats = NULL;
+ ip6protox[i].pr_istats = NULL;
+ ip6protox[i].pr_name = NULL;
+ ip6protox[i].pr_usesysctl = 0;
+ ip6protox[i].pr_protocol = 0;
+ i++;
+#endif /*INET6*/
+
+#ifdef IPSEC
+ i=0;
+ pfkeyprotox[i].pr_index = -1;
+ pfkeyprotox[i].pr_sindex = N_PFKEYSTAT;
+ pfkeyprotox[i].pr_wanted = 1;
+ pfkeyprotox[i].pr_cblocks = NULL;
+ pfkeyprotox[i].pr_stats = pfkey_stats;
+ pfkeyprotox[i].pr_istats = NULL;
+ pfkeyprotox[i].pr_name = "pfkey";
+ pfkeyprotox[i].pr_usesysctl = 0;
+ pfkeyprotox[i].pr_protocol = 0;
+ i++;
+ pfkeyprotox[i].pr_index = -1;
+ pfkeyprotox[i].pr_sindex = -1;
+ pfkeyprotox[i].pr_wanted = 0;
+ pfkeyprotox[i].pr_cblocks = NULL;
+ pfkeyprotox[i].pr_stats = NULL;
+ pfkeyprotox[i].pr_istats = NULL;
+ pfkeyprotox[i].pr_name = NULL;
+ pfkeyprotox[i].pr_usesysctl = 0;
+ pfkeyprotox[i].pr_protocol = 0;
+#endif
+
+#ifdef NETGRAPH
+ netgraphprotox[i].pr_index = N_NGSOCKS;
+ netgraphprotox[i].pr_sindex = -1;
+ netgraphprotox[i].pr_wanted = 1;
+ netgraphprotox[i].pr_cblocks = netgraphprotopr;
+ netgraphprotox[i].pr_stats = NULL;
+ netgraphprotox[i].pr_istats = NULL;
+ netgraphprotox[i].pr_name = "ctrl";
+ netgraphprotox[i].pr_usesysctl = 0;
+ netgraphprotox[i].pr_protocol = 0;
+ i++;
+ netgraphprotox[i].pr_index = N_NGSOCKS;
+ netgraphprotox[i].pr_sindex = -1;
+ netgraphprotox[i].pr_wanted = 1;
+ netgraphprotox[i].pr_cblocks = netgraphprotopr;
+ netgraphprotox[i].pr_stats = NULL;
+ netgraphprotox[i].pr_istats = NULL;
+ netgraphprotox[i].pr_name = "data";
+ netgraphprotox[i].pr_usesysctl = 0;
+ netgraphprotox[i].pr_protocol = 0;
+ i++;
+ netgraphprotox[i].pr_index = -1;
+ netgraphprotox[i].pr_sindex = -1;
+ netgraphprotox[i].pr_wanted = 0;
+ netgraphprotox[i].pr_cblocks = NULL;
+ netgraphprotox[i].pr_stats = NULL;
+ netgraphprotox[i].pr_istats = NULL;
+ netgraphprotox[i].pr_name = NULL;
+ netgraphprotox[i].pr_usesysctl = 0;
+ netgraphprotox[i].pr_protocol = 0;
+#endif
+#ifdef IPX
+ i=0;
+ ipxprotox[i].pr_index = N_IPX;
+ ipxprotox[i].pr_sindex = N_IPXSTAT;
+ ipxprotox[i].pr_wanted = 1;
+ ipxprotox[i].pr_cblocks = ipxprotopr;
+ ipxprotox[i].pr_stats = ipx_stats;
+ ipxprotox[i].pr_istats = NULL;
+ ipxprotox[i].pr_name = "ipx";
+ ipxprotox[i].pr_usesysctl = 0;
+ ipxprotox[i].pr_protocol = 0;
+ i++;
+ ipxprotox[i].pr_index = N_IPX;
+ ipxprotox[i].pr_sindex = N_SPXSTAT;
+ ipxprotox[i].pr_wanted = 1;
+ ipxprotox[i].pr_cblocks = ipxprotopr;
+ ipxprotox[i].pr_stats = spx_stats;
+ ipxprotox[i].pr_istats = NULL;
+ ipxprotox[i].pr_name = "spx";
+ ipxprotox[i].pr_usesysctl = 0;
+ ipxprotox[i].pr_protocol = 0;
+ i++;
+ ipxprotox[i].pr_index = -1;
+ ipxprotox[i].pr_sindex = -1;
+ ipxprotox[i].pr_wanted = 0;
+ ipxprotox[i].pr_cblocks = NULL;
+ ipxprotox[i].pr_stats = NULL;
+ ipxprotox[i].pr_istats = NULL;
+ ipxprotox[i].pr_name = 0;
+ ipxprotox[i].pr_usesysctl = 0;
+ ipxprotox[i].pr_protocol = 0;
+ i++;
+#endif
+
+ i=0;
+ protoprotox[i] = protox;
+ i++;
+#ifdef INET6
+ protoprotox[i] = ip6protox,
+ i++;
+#endif
+#ifdef IPSEC
+ protoprotox[i] = pfkeyprotox,
+ i++;
+#endif
+#ifdef IPX
+ protoprotox[i] = ipxprotox,
+#endif
+ noutputs = 0;
+
+ netstat_globals.exit_code = 1;
+ if (setjmp (netstat_globals.exit_jmp) == 0)
+ return main_netstat (argc, argv);
+ return netstat_globals.exit_code;
+}
+#endif
+
+int
+#ifdef __rtems__
+main_netstat(int argc, char *argv[])
+#else
+main(int argc, char *argv[])
+#endif
+{
+ struct protox *tp = NULL; /* for printing cblocks & stats */
+ int ch;
+#ifdef __rtems__
+ struct getopt_data getopt_reent;
+#define optind getopt_reent.optind
+#define optarg getopt_reent.optarg
+#define opterr getopt_reent.opterr
+#define optopt getopt_reent.optopt
+#endif
+
+ af = AF_UNSPEC;
+
+#ifdef __rtems__
+ memset(&getopt_reent, 0, sizeof(getopt_data));
+ while ((ch = getopt_r(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz", &getopt_reent)) != -1)
+#else
+ while ((ch = getopt(argc, argv, "AaBbdf:ghI:iLlM:mN:np:q:rSstuWw:xz")) != -1)
+#endif
+ switch(ch) {
+ case 'A':
+ Aflag = 1;
+ break;
+ case 'a':
+ aflag = 1;
+ break;
+ case 'B':
+ Bflag = 1;
+ break;
+ case 'b':
+ bflag = 1;
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'f':
+ if (strcmp(optarg, "ipx") == 0)
+ af = AF_IPX;
+ else if (strcmp(optarg, "inet") == 0)
+ af = AF_INET;
+#ifdef INET6
+ else if (strcmp(optarg, "inet6") == 0)
+ af = AF_INET6;
+#endif
+#ifdef IPSEC
+ else if (strcmp(optarg, "pfkey") == 0)
+ af = PF_KEY;
+#endif
+ else if (strcmp(optarg, "unix") == 0)
+ af = AF_UNIX;
+ else if (strcmp(optarg, "atalk") == 0)
+ af = AF_APPLETALK;
+#ifdef NETGRAPH
+ else if (strcmp(optarg, "ng") == 0
+ || strcmp(optarg, "netgraph") == 0)
+ af = AF_NETGRAPH;
+#endif
+ else if (strcmp(optarg, "link") == 0)
+ af = AF_LINK;
+ else {
+ errx(1, "%s: unknown address family", optarg);
+ }
+ break;
+ case 'g':
+ gflag = 1;
+ break;
+ case 'h':
+ hflag = 1;
+ break;
+ case 'I': {
+ char *cp;
+
+ iflag = 1;
+ for (cp = interface = optarg; isalpha(*cp); cp++)
+ continue;
+ unit = atoi(cp);
+ break;
+ }
+ case 'i':
+ iflag = 1;
+ break;
+ case 'L':
+ Lflag = 1;
+ break;
+ case 'M':
+ memf = optarg;
+ break;
+ case 'm':
+ mflag = 1;
+ break;
+ case 'N':
+ nlistf = optarg;
+ break;
+ case 'n':
+ numeric_addr = numeric_port = 1;
+ break;
+ case 'p':
+ if ((tp = name2protox(optarg)) == NULL) {
+ errx(1,
+ "%s: unknown or uninstrumented protocol",
+ optarg);
+ }
+ pflag = 1;
+ break;
+ case 'q':
+ noutputs = atoi(optarg);
+ if (noutputs != 0)
+ noutputs++;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ ++sflag;
+ break;
+ case 'S':
+ numeric_addr = 1;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'u':
+ af = AF_UNIX;
+ break;
+ case 'W':
+ case 'l':
+ Wflag = 1;
+ break;
+ case 'w':
+ interval = atoi(optarg);
+ iflag = 1;
+ break;
+ case 'x':
+ xflag = 1;
+ break;
+ case 'z':
+ zflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argv += optind;
+ argc -= optind;
+
+#define BACKWARD_COMPATIBILITY
+#ifdef BACKWARD_COMPATIBILITY
+ if (*argv) {
+ if (isdigit(**argv)) {
+ interval = atoi(*argv);
+ if (interval <= 0)
+ usage();
+ ++argv;
+ iflag = 1;
+ }
+ if (*argv) {
+ nlistf = *argv;
+ if (*++argv)
+ memf = *argv;
+ }
+ }
+#endif
+
+ /*
+ * Discard setgid privileges if not the running kernel so that bad
+ * guys can't print interesting stuff from kernel memory.
+ */
+ live = (nlistf == NULL && memf == NULL);
+ if (!live)
+ setgid(getgid());
+
+ if (Bflag) {
+ if (!live)
+ usage();
+ bpf_stats(interface);
+ exit(0);
+ }
+ if (mflag) {
+ if (!live) {
+ if (kread(0, NULL, 0) == 0)
+ mbpr(kvmd, nl[N_MBSTAT].n_value);
+ } else
+ mbpr(NULL, 0);
+ exit(0);
+ }
+#if 0
+ /*
+ * Keep file descriptors open to avoid overhead
+ * of open/close on each call to get* routines.
+ */
+ sethostent(1);
+ setnetent(1);
+#else
+ /*
+ * This does not make sense any more with DNS being default over
+ * the files. Doing a setXXXXent(1) causes a tcp connection to be
+ * used for the queries, which is slower.
+ */
+#endif
+ kread(0, NULL, 0);
+ if (iflag && !sflag) {
+ intpr(interval, nl[N_IFNET].n_value, NULL);
+ exit(0);
+ }
+ if (rflag) {
+ if (sflag)
+ rt_stats(nl[N_RTSTAT].n_value, nl[N_RTTRASH].n_value);
+ else
+ routepr(nl[N_RTREE].n_value);
+ exit(0);
+ }
+ if (gflag) {
+ if (sflag) {
+ if (af == AF_INET || af == AF_UNSPEC)
+ mrt_stats(nl[N_MRTSTAT].n_value);
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ mrt6_stats(nl[N_MRT6STAT].n_value);
+#endif
+ } else {
+ if (af == AF_INET || af == AF_UNSPEC)
+ 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)
+ mroute6pr(nl[N_MF6CTABLE].n_value,
+ nl[N_MIF6TABLE].n_value);
+#endif
+ }
+ exit(0);
+ }
+
+ if (tp) {
+ printproto(tp, tp->pr_name);
+ exit(0);
+ }
+ if (af == AF_INET || af == AF_UNSPEC)
+ for (tp = protox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#ifdef INET6
+ if (af == AF_INET6 || af == AF_UNSPEC)
+ for (tp = ip6protox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#endif /*INET6*/
+#ifdef IPSEC
+ if (af == PF_KEY || af == AF_UNSPEC)
+ for (tp = pfkeyprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#endif /*IPSEC*/
+#ifdef IPX
+ if (af == AF_IPX || af == AF_UNSPEC) {
+ for (tp = ipxprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+ }
+#endif /* IPX */
+#ifndef __rtems__
+ if (af == AF_APPLETALK || af == AF_UNSPEC)
+ for (tp = atalkprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#endif
+#ifdef NETGRAPH
+ if (af == AF_NETGRAPH || af == AF_UNSPEC)
+ for (tp = netgraphprotox; tp->pr_name; tp++)
+ printproto(tp, tp->pr_name);
+#endif /* NETGRAPH */
+#ifndef __rtems__
+ if ((af == AF_UNIX || af == AF_UNSPEC) && !sflag)
+ unixpr(nl[N_UNP_COUNT].n_value, nl[N_UNP_GENCNT].n_value,
+ nl[N_UNP_DHEAD].n_value, nl[N_UNP_SHEAD].n_value);
+#endif
+ exit(0);
+}
+
+/*
+ * Print out protocol statistics or control blocks (per sflag).
+ * If the interface was not specifically requested, and the symbol
+ * is not in the namelist, ignore this one.
+ */
+static void
+printproto(tp, name)
+ struct protox *tp;
+ const char *name;
+{
+ void (*pr)(u_long, const char *, int, int);
+ u_long off;
+
+ if (sflag) {
+ if (iflag) {
+ if (tp->pr_istats)
+ intpr(interval, nl[N_IFNET].n_value,
+ tp->pr_istats);
+ else if (pflag)
+ printf("%s: no per-interface stats routine\n",
+ tp->pr_name);
+ return;
+ } else {
+ pr = tp->pr_stats;
+ if (!pr) {
+ if (pflag)
+ printf("%s: no stats routine\n",
+ tp->pr_name);
+ return;
+ }
+ if (tp->pr_usesysctl && live)
+ off = 0;
+ else if (tp->pr_sindex < 0) {
+ if (pflag)
+ printf(
+ "%s: stats routine doesn't work on cores\n",
+ tp->pr_name);
+ return;
+ } else
+ off = nl[tp->pr_sindex].n_value;
+ }
+ } else {
+ pr = tp->pr_cblocks;
+ if (!pr) {
+ if (pflag)
+ printf("%s: no PCB routine\n", tp->pr_name);
+ return;
+ }
+ if (tp->pr_usesysctl && live)
+ off = 0;
+ else if (tp->pr_index < 0) {
+ if (pflag)
+ printf(
+ "%s: PCB routine doesn't work on cores\n",
+ tp->pr_name);
+ return;
+ } else
+ off = nl[tp->pr_index].n_value;
+ }
+ if (pr != NULL && (off || (live && tp->pr_usesysctl) ||
+ af != AF_UNSPEC))
+ (*pr)(off, name, af, tp->pr_protocol);
+}
+
+#ifdef __rtems__
+#define _POSIX2_LINE_MAX 128
+#endif
+
+/*
+ * Read kernel memory, return 0 on success.
+ */
+int
+kread(u_long addr, void *buf, size_t size)
+{
+ char errbuf[_POSIX2_LINE_MAX];
+#ifdef __rtems__
+ /* printf( "kread( %p to %p for %d)\n", (void *)addr, buf, size ); */
+#endif
+
+ if (kvmd == NULL) {
+ kvmd = kvm_openfiles(nlistf, memf, NULL, O_RDONLY, errbuf);
+ setgid(getgid());
+ if (kvmd != NULL) {
+ if (kvm_nlist(kvmd, nl) < 0) {
+ if (nlistf)
+ errx(1, "%s: kvm_nlist: %s", nlistf,
+ kvm_geterr(kvmd));
+ else
+ errx(1, "kvm_nlist: %s", kvm_geterr(kvmd));
+ }
+
+ if (nl[0].n_type == 0) {
+ if (nlistf)
+ errx(1, "%s: no namelist", nlistf);
+ else
+ errx(1, "no namelist");
+ }
+ } else {
+ warnx("kvm not available: %s", errbuf);
+ return(-1);
+ }
+ }
+ if (!buf)
+ return (0);
+ if (kvm_read(kvmd, addr, buf, size) != (ssize_t)size) {
+ warnx("%s", kvm_geterr(kvmd));
+ return (-1);
+ }
+ return (0);
+}
+
+const char *
+plural(uintmax_t n)
+{
+ return (n != 1 ? "s" : "");
+}
+
+const char *
+plurales(uintmax_t n)
+{
+ return (n != 1 ? "es" : "");
+}
+
+const char *
+pluralies(uintmax_t n)
+{
+ return (n != 1 ? "ies" : "y");
+}
+
+/*
+ * Find the protox for the given "well-known" name.
+ */
+static struct protox *
+knownname(const char *name)
+{
+ struct protox **tpp, *tp;
+
+ for (tpp = protoprotox; *tpp; tpp++)
+ for (tp = *tpp; tp->pr_name; tp++)
+ if (strcmp(tp->pr_name, name) == 0)
+ return (tp);
+ return (NULL);
+}
+
+/*
+ * Find the protox corresponding to name.
+ */
+static struct protox *
+name2protox(const char *name)
+{
+ struct protox *tp;
+ char **alias; /* alias from p->aliases */
+ struct protoent *p;
+
+ /*
+ * Try to find the name in the list of "well-known" names. If that
+ * fails, check if name is an alias for an Internet protocol.
+ */
+ if ((tp = knownname(name)) != NULL)
+ return (tp);
+
+ setprotoent(1); /* make protocol lookup cheaper */
+ while ((p = getprotoent()) != NULL) {
+ /* assert: name not same as p->name */
+ for (alias = p->p_aliases; *alias; alias++)
+ if (strcmp(name, *alias) == 0) {
+ endprotoent();
+ return (knownname(p->p_name));
+ }
+ }
+ endprotoent();
+ return (NULL);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
+"usage: netstat [-AaLnSWx] [-f protocol_family | -p protocol]\n"
+" [-M core] [-N system]",
+" netstat -i | -I interface [-abdhntW] [-f address_family]\n"
+" [-M core] [-N system]",
+" netstat -w wait [-I interface] [-d] [-M core] [-N system] [-q howmany]",
+" netstat -s [-s] [-z] [-f protocol_family | -p protocol]\n"
+" [-M core] [-N system]",
+" netstat -i | -I interface -s [-f protocol_family | -p protocol]\n"
+" [-M core] [-N system]",
+" netstat -m [-M core] [-N system]",
+" netstat -B [-I interface]",
+" netstat -r [-AanW] [-f address_family] [-M core] [-N system]",
+" netstat -rs [-s] [-M core] [-N system]",
+" netstat -g [-W] [-f address_family] [-M core] [-N system]",
+" netstat -gs [-s] [-f address_family] [-M core] [-N system]");
+ exit(1);
+}
+
+#ifdef __rtems__
+ #include <rtems/shell.h>
+
+ rtems_shell_cmd_t rtems_shell_NETSTAT_Command = {
+ "netstat", /* name */
+ "netstat [args]", /* usage */
+ "net", /* topic */
+ rtems_shell_main_netstat, /* command */
+ NULL, /* alias */
+ NULL /* next */
+ };
+#endif
diff --git a/freebsd/usr.bin/netstat/mbuf.c b/freebsd/usr.bin/netstat/mbuf.c
new file mode 100644
index 00000000..418c761b
--- /dev/null
+++ b/freebsd/usr.bin/netstat/mbuf.c
@@ -0,0 +1,323 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California.
+ * Copyright (c) 2005 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
+ * 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)mbuf.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#ifdef __rtems__
+#include <stdint.h>
+#include <freebsd/sys/mbuf.h>
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/mbuf.h>
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <kvm.h>
+#include <memstat.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netstat.h"
+
+/*
+ * Print mbuf statistics.
+ */
+void
+mbpr(void *kvmd, u_long mbaddr)
+{
+ struct memory_type_list *mtlp;
+ struct memory_type *mtp;
+ uintmax_t mbuf_count, mbuf_bytes, mbuf_free, mbuf_failures, mbuf_size;
+ uintmax_t cluster_count, cluster_bytes, cluster_limit, cluster_free;
+ uintmax_t cluster_failures, cluster_size;
+ uintmax_t packet_count, packet_bytes, packet_free, packet_failures;
+ uintmax_t tag_count, tag_bytes;
+ uintmax_t jumbop_count, jumbop_bytes, jumbop_limit, jumbop_free;
+ uintmax_t jumbop_failures, jumbop_size;
+ uintmax_t jumbo9_count, jumbo9_bytes, jumbo9_limit, jumbo9_free;
+ uintmax_t jumbo9_failures, jumbo9_size;
+ uintmax_t jumbo16_count, jumbo16_bytes, jumbo16_limit, jumbo16_free;
+ uintmax_t jumbo16_failures, jumbo16_size;
+ uintmax_t bytes_inuse, bytes_incache, bytes_total;
+ int nsfbufs, nsfbufspeak, nsfbufsused;
+ struct mbstat mbstat;
+ size_t mlen;
+ int error;
+
+ mtlp = memstat_mtl_alloc();
+ if (mtlp == NULL) {
+ warn("memstat_mtl_alloc");
+ return;
+ }
+
+ /*
+ * Use memstat_*_all() because some mbuf-related memory is in uma(9),
+ * and some malloc(9).
+ */
+ if (live) {
+ if (memstat_sysctl_all(mtlp, 0) < 0) {
+ warnx("memstat_sysctl_all: %s",
+ memstat_strerror(memstat_mtl_geterror(mtlp)));
+ goto out;
+ }
+ } else {
+#ifndef __rtems__
+ if (memstat_kvm_all(mtlp, kvmd) < 0) {
+ error = memstat_mtl_geterror(mtlp);
+ if (error == MEMSTAT_ERROR_KVM)
+ warnx("memstat_kvm_all: %s",
+ kvm_geterr(kvmd));
+ else
+ warnx("memstat_kvm_all: %s",
+ memstat_strerror(error));
+ goto out;
+ }
+#else
+ ;
+#endif
+ }
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_MEM_NAME);
+ if (mtp == NULL) {
+ warnx("memstat_mtl_find: zone %s not found", MBUF_MEM_NAME);
+ goto out;
+ }
+ mbuf_count = memstat_get_count(mtp);
+ mbuf_bytes = memstat_get_bytes(mtp);
+ mbuf_free = memstat_get_free(mtp);
+ mbuf_failures = memstat_get_failures(mtp);
+ mbuf_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_PACKET_MEM_NAME);
+ if (mtp == NULL) {
+ warnx("memstat_mtl_find: zone %s not found",
+ MBUF_PACKET_MEM_NAME);
+ goto out;
+ }
+ packet_count = memstat_get_count(mtp);
+ packet_bytes = memstat_get_bytes(mtp);
+ packet_free = memstat_get_free(mtp);
+ packet_failures = memstat_get_failures(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_CLUSTER_MEM_NAME);
+ if (mtp == NULL) {
+ warnx("memstat_mtl_find: zone %s not found",
+ MBUF_CLUSTER_MEM_NAME);
+ goto out;
+ }
+ cluster_count = memstat_get_count(mtp);
+ cluster_bytes = memstat_get_bytes(mtp);
+ cluster_limit = memstat_get_countlimit(mtp);
+ cluster_free = memstat_get_free(mtp);
+ cluster_failures = memstat_get_failures(mtp);
+ cluster_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_MALLOC, MBUF_TAG_MEM_NAME);
+ if (mtp == NULL) {
+ warnx("memstat_mtl_find: malloc type %s not found",
+ MBUF_TAG_MEM_NAME);
+ goto out;
+ }
+ tag_count = memstat_get_count(mtp);
+ tag_bytes = memstat_get_bytes(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBOP_MEM_NAME);
+ if (mtp == NULL) {
+ warnx("memstat_mtl_find: zone %s not found",
+ MBUF_JUMBOP_MEM_NAME);
+ goto out;
+ }
+ jumbop_count = memstat_get_count(mtp);
+ jumbop_bytes = memstat_get_bytes(mtp);
+ jumbop_limit = memstat_get_countlimit(mtp);
+ jumbop_free = memstat_get_free(mtp);
+ jumbop_failures = memstat_get_failures(mtp);
+ jumbop_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO9_MEM_NAME);
+ if (mtp == NULL) {
+ warnx("memstat_mtl_find: zone %s not found",
+ MBUF_JUMBO9_MEM_NAME);
+ goto out;
+ }
+ jumbo9_count = memstat_get_count(mtp);
+ jumbo9_bytes = memstat_get_bytes(mtp);
+ jumbo9_limit = memstat_get_countlimit(mtp);
+ jumbo9_free = memstat_get_free(mtp);
+ jumbo9_failures = memstat_get_failures(mtp);
+ jumbo9_size = memstat_get_size(mtp);
+
+ mtp = memstat_mtl_find(mtlp, ALLOCATOR_UMA, MBUF_JUMBO16_MEM_NAME);
+ if (mtp == NULL) {
+ warnx("memstat_mtl_find: zone %s not found",
+ MBUF_JUMBO16_MEM_NAME);
+ goto out;
+ }
+ jumbo16_count = memstat_get_count(mtp);
+ jumbo16_bytes = memstat_get_bytes(mtp);
+ jumbo16_limit = memstat_get_countlimit(mtp);
+ jumbo16_free = memstat_get_free(mtp);
+ jumbo16_failures = memstat_get_failures(mtp);
+ jumbo16_size = memstat_get_size(mtp);
+
+ printf("%ju/%ju/%ju mbufs in use (current/cache/total)\n",
+ mbuf_count + packet_count, mbuf_free + packet_free,
+ mbuf_count + packet_count + mbuf_free + packet_free);
+
+ printf("%ju/%ju/%ju/%ju mbuf clusters in use "
+ "(current/cache/total/max)\n",
+ cluster_count - packet_free, cluster_free + packet_free,
+ cluster_count + cluster_free, cluster_limit);
+
+ printf("%ju/%ju mbuf+clusters out of packet secondary zone in use "
+ "(current/cache)\n",
+ packet_count, packet_free);
+
+ printf("%ju/%ju/%ju/%ju %juk (page size) jumbo clusters in use "
+ "(current/cache/total/max)\n",
+ jumbop_count, jumbop_free, jumbop_count + jumbop_free,
+ jumbop_limit, jumbop_size / 1024);
+
+ printf("%ju/%ju/%ju/%ju 9k jumbo clusters in use "
+ "(current/cache/total/max)\n",
+ jumbo9_count, jumbo9_free, jumbo9_count + jumbo9_free,
+ jumbo9_limit);
+
+ printf("%ju/%ju/%ju/%ju 16k jumbo clusters in use "
+ "(current/cache/total/max)\n",
+ jumbo16_count, jumbo16_free, jumbo16_count + jumbo16_free,
+ jumbo16_limit);
+
+#if 0
+ printf("%ju mbuf tags in use\n", tag_count);
+#endif
+
+ /*-
+ * Calculate in-use bytes as:
+ * - straight mbuf memory
+ * - mbuf memory in packets
+ * - the clusters attached to packets
+ * - and the rest of the non-packet-attached clusters.
+ * - m_tag memory
+ * This avoids counting the clusters attached to packets in the cache.
+ * This currently excludes sf_buf space.
+ */
+ bytes_inuse =
+ mbuf_bytes + /* straight mbuf memory */
+ packet_bytes + /* mbufs in packets */
+ (packet_count * cluster_size) + /* clusters in packets */
+ /* other clusters */
+ ((cluster_count - packet_count - packet_free) * cluster_size) +
+ tag_bytes +
+ (jumbop_count * jumbop_size) + /* jumbo clusters */
+ (jumbo9_count * jumbo9_size) +
+ (jumbo16_count * jumbo16_size);
+
+ /*
+ * Calculate in-cache bytes as:
+ * - cached straught mbufs
+ * - cached packet mbufs
+ * - cached packet clusters
+ * - cached straight clusters
+ * This currently excludes sf_buf space.
+ */
+ bytes_incache =
+ (mbuf_free * mbuf_size) + /* straight free mbufs */
+ (packet_free * mbuf_size) + /* mbufs in free packets */
+ (packet_free * cluster_size) + /* clusters in free packets */
+ (cluster_free * cluster_size) + /* free clusters */
+ (jumbop_free * jumbop_size) + /* jumbo clusters */
+ (jumbo9_free * jumbo9_size) +
+ (jumbo16_free * jumbo16_size);
+
+ /*
+ * Total is bytes in use + bytes in cache. This doesn't take into
+ * account various other misc data structures, overhead, etc, but
+ * gives the user something useful despite that.
+ */
+ bytes_total = bytes_inuse + bytes_incache;
+
+ printf("%juK/%juK/%juK bytes allocated to network "
+ "(current/cache/total)\n", bytes_inuse / 1024,
+ bytes_incache / 1024, bytes_total / 1024);
+
+ printf("%ju/%ju/%ju requests for mbufs denied (mbufs/clusters/"
+ "mbuf+clusters)\n", mbuf_failures, cluster_failures,
+ packet_failures);
+
+ printf("%ju/%ju/%ju requests for jumbo clusters denied "
+ "(%juk/9k/16k)\n", jumbop_failures, jumbo9_failures,
+ jumbo16_failures, jumbop_size / 1024);
+
+ if (live) {
+ mlen = sizeof(nsfbufs);
+ if (!sysctlbyname("kern.ipc.nsfbufs", &nsfbufs, &mlen, NULL,
+ 0) &&
+ !sysctlbyname("kern.ipc.nsfbufsused", &nsfbufsused,
+ &mlen, NULL, 0) &&
+ !sysctlbyname("kern.ipc.nsfbufspeak", &nsfbufspeak,
+ &mlen, NULL, 0))
+ printf("%d/%d/%d sfbufs in use (current/peak/max)\n",
+ nsfbufsused, nsfbufspeak, nsfbufs);
+ mlen = sizeof(mbstat);
+ if (sysctlbyname("kern.ipc.mbstat", &mbstat, &mlen, NULL, 0)) {
+ warn("kern.ipc.mbstat");
+ goto out;
+ }
+ } else {
+ if (kread(mbaddr, (char *)&mbstat, sizeof mbstat) != 0)
+ goto out;
+ }
+ printf("%lu requests for sfbufs denied\n", mbstat.sf_allocfail);
+ printf("%lu requests for sfbufs delayed\n", mbstat.sf_allocwait);
+ printf("%lu requests for I/O initiated by sendfile\n",
+ mbstat.sf_iocnt);
+ printf("%lu calls to protocol drain routines\n", mbstat.m_drain);
+out:
+ memstat_mtl_free(mtlp);
+}
diff --git a/freebsd/usr.bin/netstat/mroute.c b/freebsd/usr.bin/netstat/mroute.c
new file mode 100644
index 00000000..7669ff07
--- /dev/null
+++ b/freebsd/usr.bin/netstat/mroute.c
@@ -0,0 +1,391 @@
+/*-
+ * Copyright (c) 1989 Stephen Deering
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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.
+ *
+ * @(#)mroute.c 8.2 (Berkeley) 4/28/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Print multicast routing structures and statistics.
+ *
+ * MROUTING 1.0
+ */
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#ifdef __rtems__
+#include <freebsd/sys/mbuf.h>
+#else
+#include <sys/mbuf.h>
+#endif
+#include <sys/time.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/igmp.h>
+#include <net/route.h>
+
+#define _KERNEL 1
+#ifdef __rtems__
+#include <freebsd/netinet/ip_mroute.h>
+#else
+#include <netinet/ip_mroute.h>
+#endif
+#undef _KERNEL
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "netstat.h"
+
+
+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)
+{
+ char s0[256], s1[256], s2[256], s3[256];
+ struct timeval now, end, delta;
+
+ gettimeofday(&now, NULL);
+
+ if (! *banner_printed) {
+ printf(" Bandwidth Meters\n");
+ printf(" %-30s", "Measured(Start|Packets|Bytes)");
+ printf(" %s", "Type");
+ printf(" %-30s", "Thresh(Interval|Packets|Bytes)");
+ printf(" Remain");
+ printf("\n");
+ *banner_printed = 1;
+ }
+
+ /* The measured values */
+ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
+ sprintf(s1, "%ju", (uintmax_t)bw_meter->bm_measured.b_packets);
+ else
+ sprintf(s1, "?");
+ if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
+ sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_measured.b_bytes);
+ else
+ sprintf(s2, "?");
+ sprintf(s0, "%lu.%lu|%s|%s",
+ (u_long)bw_meter->bm_start_time.tv_sec,
+ (u_long)bw_meter->bm_start_time.tv_usec,
+ s1, s2);
+ printf(" %-30s", s0);
+
+ /* The type of entry */
+ sprintf(s0, "%s", "?");
+ if (bw_meter->bm_flags & BW_METER_GEQ)
+ sprintf(s0, "%s", ">=");
+ else if (bw_meter->bm_flags & BW_METER_LEQ)
+ sprintf(s0, "%s", "<=");
+ printf(" %-3s", s0);
+
+ /* The threshold values */
+ if (bw_meter->bm_flags & BW_METER_UNIT_PACKETS)
+ sprintf(s1, "%ju", (uintmax_t)bw_meter->bm_threshold.b_packets);
+ else
+ sprintf(s1, "?");
+ if (bw_meter->bm_flags & BW_METER_UNIT_BYTES)
+ sprintf(s2, "%ju", (uintmax_t)bw_meter->bm_threshold.b_bytes);
+ else
+ sprintf(s2, "?");
+ sprintf(s0, "%lu.%lu|%s|%s",
+ (u_long)bw_meter->bm_threshold.b_time.tv_sec,
+ (u_long)bw_meter->bm_threshold.b_time.tv_usec,
+ s1, s2);
+ printf(" %-30s", s0);
+
+ /* Remaining time */
+ timeradd(&bw_meter->bm_start_time,
+ &bw_meter->bm_threshold.b_time, &end);
+ if (timercmp(&now, &end, <=)) {
+ timersub(&end, &now, &delta);
+ sprintf(s3, "%lu.%lu",
+ (u_long)delta.tv_sec,
+ (u_long)delta.tv_usec);
+ } else {
+ /* Negative time */
+ timersub(&now, &end, &delta);
+ sprintf(s3, "-%lu.%lu",
+ (u_long)delta.tv_sec,
+ (u_long)delta.tv_usec);
+ }
+ printf(" %s", s3);
+
+ 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)
+{
+ struct mrtstat mrtstat;
+ size_t len = sizeof mrtstat;
+
+ if (live) {
+ if (sysctlbyname("net.inet.ip.mrtstat", &mrtstat, &len, NULL,
+ 0) < 0) {
+ warn("sysctl: net.inet.ip.mrtstat");
+ return;
+ }
+ } else
+ kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
+
+ printf("IPv4 multicast forwarding:\n");
+
+#define p(f, m) if (mrtstat.f || sflag <= 1) \
+ printf(m, mrtstat.f, plural(mrtstat.f))
+#define p2(f, m) if (mrtstat.f || sflag <= 1) \
+ printf(m, mrtstat.f, plurales(mrtstat.f))
+
+ p(mrts_mfc_lookups, "\t%lu multicast forwarding cache lookup%s\n");
+ p2(mrts_mfc_misses, "\t%lu multicast forwarding cache miss%s\n");
+ p(mrts_upcalls, "\t%lu upcall%s to multicast routing daemon\n");
+ p(mrts_upq_ovflw, "\t%lu upcall queue overflow%s\n");
+ p(mrts_upq_sockfull,
+ "\t%lu upcall%s dropped due to full socket buffer\n");
+ p(mrts_cache_cleanups, "\t%lu cache cleanup%s\n");
+ p(mrts_no_route, "\t%lu datagram%s with no route for origin\n");
+ p(mrts_bad_tunnel, "\t%lu datagram%s arrived with bad tunneling\n");
+ p(mrts_cant_tunnel, "\t%lu datagram%s could not be tunneled\n");
+ p(mrts_wrong_if, "\t%lu datagram%s arrived on wrong interface\n");
+ p(mrts_drop_sel, "\t%lu datagram%s selectively dropped\n");
+ p(mrts_q_overflow, "\t%lu datagram%s dropped due to queue overflow\n");
+ p(mrts_pkt2large, "\t%lu datagram%s dropped for being too large\n");
+
+#undef p2
+#undef p
+}
diff --git a/freebsd/usr.bin/netstat/mroute6.c b/freebsd/usr.bin/netstat/mroute6.c
new file mode 100644
index 00000000..4fff5462
--- /dev/null
+++ b/freebsd/usr.bin/netstat/mroute6.c
@@ -0,0 +1,279 @@
+/*-
+ * Copyright (C) 1998 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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) 1989 Stephen Deering
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Stephen Deering of Stanford University.
+ *
+ * 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.
+ *
+ * @(#)mroute.c 8.2 (Berkeley) 4/28/95
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef __rtems__
+#include "port_before.h"
+#endif
+#ifdef INET6
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#ifdef __rtems__
+#include <freebsd/sys/mbuf.h>
+#else
+#include <sys/mbuf.h>
+#endif
+#include <sys/time.h>
+
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#else
+#include <net/if_var.h>
+#endif
+#include <net/route.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define KERNEL 1
+#ifdef __rtems__
+#include <freebsd/netinet6/ip6_mroute.h>
+#else
+#include <netinet6/ip6_mroute.h>
+#endif
+#undef KERNEL
+
+#include "netstat.h"
+
+#define WID_ORG (Wflag ? 39 : (numeric_addr ? 29 : 18)) /* width of origin column */
+#define WID_GRP (Wflag ? 18 : (numeric_addr ? 16 : 18)) /* width of group column */
+
+void
+mroute6pr(u_long mfcaddr, u_long mifaddr)
+{
+ struct mf6c *mf6ctable[MF6CTBLSIZ], *mfcp;
+ struct mif6 mif6table[MAXMIFS];
+ struct mf6c mfc;
+ struct rtdetq rte, *rtep;
+ struct mif6 *mifp;
+ mifi_t mifi;
+ int i;
+ int banner_printed;
+ int saved_numeric_addr;
+ mifi_t maxmif = 0;
+ long int waitings;
+ size_t len;
+
+ len = sizeof(mif6table);
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.mif6table", mif6table, &len,
+ NULL, 0) < 0) {
+ warn("sysctl: net.inet6.ip6.mif6table");
+ return;
+ }
+ } else
+ kread(mifaddr, (char *)mif6table, sizeof(mif6table));
+
+ saved_numeric_addr = numeric_addr;
+ numeric_addr = 1;
+ banner_printed = 0;
+
+ for (mifi = 0, mifp = mif6table; mifi < MAXMIFS; ++mifi, ++mifp) {
+ struct ifnet ifnet;
+ char ifname[IFNAMSIZ];
+
+ if (mifp->m6_ifp == NULL)
+ continue;
+
+ /* XXX KVM */
+ kread((u_long)mifp->m6_ifp, (char *)&ifnet, sizeof(ifnet));
+
+ maxmif = mifi;
+ if (!banner_printed) {
+ printf("\nIPv6 Multicast Interface Table\n"
+ " Mif Rate PhyIF "
+ "Pkts-In Pkts-Out\n");
+ banner_printed = 1;
+ }
+
+ printf(" %2u %4d",
+ mifi, mifp->m6_rate_limit);
+ printf(" %5s", (mifp->m6_flags & MIFF_REGISTER) ?
+ "reg0" : if_indextoname(ifnet.if_index, ifname));
+
+ printf(" %9ju %9ju\n", (uintmax_t)mifp->m6_pkt_in,
+ (uintmax_t)mifp->m6_pkt_out);
+ }
+ if (!banner_printed)
+ printf("\nIPv6 Multicast Interface Table is empty\n");
+
+ len = sizeof(mf6ctable);
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.mf6ctable", mf6ctable, &len,
+ NULL, 0) < 0) {
+ warn("sysctl: net.inet6.ip6.mf6ctable");
+ return;
+ }
+ } else
+ kread(mfcaddr, (char *)mf6ctable, sizeof(mf6ctable));
+
+ banner_printed = 0;
+
+ for (i = 0; i < MF6CTBLSIZ; ++i) {
+ mfcp = mf6ctable[i];
+ while(mfcp) {
+ kread((u_long)mfcp, (char *)&mfc, sizeof(mfc));
+ if (!banner_printed) {
+ printf ("\nIPv6 Multicast Forwarding Cache\n");
+ printf(" %-*.*s %-*.*s %s",
+ WID_ORG, WID_ORG, "Origin",
+ WID_GRP, WID_GRP, "Group",
+ " Packets Waits In-Mif Out-Mifs\n");
+ banner_printed = 1;
+ }
+
+ printf(" %-*.*s", WID_ORG, WID_ORG,
+ routename6(&mfc.mf6c_origin));
+ printf(" %-*.*s", WID_GRP, WID_GRP,
+ routename6(&mfc.mf6c_mcastgrp));
+ printf(" %9ju", (uintmax_t)mfc.mf6c_pkt_cnt);
+
+ for (waitings = 0, rtep = mfc.mf6c_stall; rtep; ) {
+ waitings++;
+ /* XXX KVM */
+ kread((u_long)rtep, (char *)&rte, sizeof(rte));
+ rtep = rte.next;
+ }
+ printf(" %3ld", waitings);
+
+ if (mfc.mf6c_parent == MF6C_INCOMPLETE_PARENT)
+ printf(" --- ");
+ else
+ printf(" %3d ", mfc.mf6c_parent);
+ for (mifi = 0; mifi <= maxmif; mifi++) {
+ if (IF_ISSET(mifi, &mfc.mf6c_ifset))
+ printf(" %u", mifi);
+ }
+ printf("\n");
+
+ mfcp = mfc.mf6c_next;
+ }
+ }
+ if (!banner_printed)
+ printf("\nIPv6 Multicast Forwarding Table is empty\n");
+
+ printf("\n");
+ numeric_addr = saved_numeric_addr;
+}
+
+void
+mrt6_stats(u_long mstaddr)
+{
+ struct mrt6stat mrtstat;
+ size_t len = sizeof mrtstat;
+
+ if (live) {
+ if (sysctlbyname("net.inet6.ip6.mrt6stat", &mrtstat, &len,
+ NULL, 0) < 0) {
+ warn("sysctl: net.inet6.ip6.mrt6stat");
+ return;
+ }
+ } else
+ kread(mstaddr, (char *)&mrtstat, sizeof(mrtstat));
+
+ printf("IPv6 multicast forwarding:\n");
+
+#define p(f, m) if (mrtstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)mrtstat.f, plural(mrtstat.f))
+#define p2(f, m) if (mrtstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)mrtstat.f, plurales(mrtstat.f))
+
+ p(mrt6s_mfc_lookups, "\t%ju multicast forwarding cache lookup%s\n");
+ p2(mrt6s_mfc_misses, "\t%ju multicast forwarding cache miss%s\n");
+ p(mrt6s_upcalls, "\t%ju upcall%s to multicast routing daemon\n");
+ p(mrt6s_upq_ovflw, "\t%ju upcall queue overflow%s\n");
+ p(mrt6s_upq_sockfull,
+ "\t%ju upcall%s dropped due to full socket buffer\n");
+ p(mrt6s_cache_cleanups, "\t%ju cache cleanup%s\n");
+ p(mrt6s_no_route, "\t%ju datagram%s with no route for origin\n");
+ p(mrt6s_bad_tunnel, "\t%ju datagram%s arrived with bad tunneling\n");
+ p(mrt6s_cant_tunnel, "\t%ju datagram%s could not be tunneled\n");
+ p(mrt6s_wrong_if, "\t%ju datagram%s arrived on wrong interface\n");
+ p(mrt6s_drop_sel, "\t%ju datagram%s selectively dropped\n");
+ p(mrt6s_q_overflow,
+ "\t%ju datagram%s dropped due to queue overflow\n");
+ p(mrt6s_pkt2large, "\t%ju datagram%s dropped for being too large\n");
+
+#undef p2
+#undef p
+}
+#endif /*INET6*/
diff --git a/freebsd/usr.bin/netstat/netstat.h b/freebsd/usr.bin/netstat/netstat.h
new file mode 100644
index 00000000..c7564c6f
--- /dev/null
+++ b/freebsd/usr.bin/netstat/netstat.h
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * 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.
+ *
+ * @(#)netstat.h 8.2 (Berkeley) 1/4/94
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+#ifdef __rtems__
+#define __BSD_VISIBLE 1
+#include <freebsd/sys/types.h>
+
+#define rt_tables netstat_rt_tables
+#endif
+
+extern int Aflag; /* show addresses of protocol control block */
+extern int aflag; /* show all sockets (including servers) */
+extern int bflag; /* show i/f total bytes in/out */
+extern int dflag; /* show i/f dropped packets */
+extern int gflag; /* show group (multicast) routing or stats */
+extern int hflag; /* show counters in human readable format */
+extern int iflag; /* show interfaces */
+extern int Lflag; /* show size of listen queues */
+extern int mflag; /* show memory stats */
+extern int noutputs; /* how much outputs before we exit */
+extern int numeric_addr; /* show addresses numerically */
+extern int numeric_port; /* show ports numerically */
+extern int rflag; /* show routing tables (or routing stats) */
+extern int sflag; /* show protocol statistics */
+extern int tflag; /* show i/f watchdog timers */
+extern int Wflag; /* wide display */
+extern int xflag; /* extended display, includes all socket buffer info */
+extern int zflag; /* zero stats */
+
+extern int interval; /* repeat interval for i/f stats */
+
+extern char *interface; /* desired i/f for stats, or NULL for all i/fs */
+extern int unit; /* unit number for above */
+
+extern int af; /* address family */
+extern int live; /* true if we are examining a live system */
+
+int kread(u_long addr, void *buf, size_t size);
+const char *plural(uintmax_t);
+const char *plurales(uintmax_t);
+const char *pluralies(uintmax_t);
+
+int sotoxsocket(struct socket *, struct xsocket *);
+void protopr(u_long, const char *, int, int);
+void tcp_stats(u_long, const char *, int, int);
+void udp_stats(u_long, const char *, int, int);
+#ifdef SCTP
+void sctp_protopr(u_long, const char *, int, int);
+void sctp_stats(u_long, const char *, int, int);
+#endif
+void arp_stats(u_long, const char *, int, int);
+void ip_stats(u_long, const char *, int, int);
+void icmp_stats(u_long, const char *, int, int);
+void igmp_stats(u_long, const char *, int, int);
+void pim_stats(u_long, const char *, int, int);
+void carp_stats(u_long, const char *, int, int);
+void pfsync_stats(u_long, const char *, int, int);
+#ifdef IPSEC
+void ipsec_stats(u_long, const char *, int, int);
+void esp_stats(u_long, const char *, int, int);
+void ah_stats(u_long, const char *, int, int);
+void ipcomp_stats(u_long, const char *, int, int);
+#endif
+
+#ifdef INET6
+void ip6_stats(u_long, const char *, int, int);
+void ip6_ifstats(char *);
+void icmp6_stats(u_long, const char *, int, int);
+void icmp6_ifstats(char *);
+void pim6_stats(u_long, const char *, int, int);
+void rip6_stats(u_long, const char *, int, int);
+void mroute6pr(u_long, u_long);
+void mrt6_stats(u_long);
+
+struct sockaddr_in6;
+struct in6_addr;
+char *routename6(struct sockaddr_in6 *);
+const char *netname6(struct sockaddr_in6 *, struct in6_addr *);
+void inet6print(struct in6_addr *, int, const char *, int);
+#endif /*INET6*/
+
+#ifdef IPSEC
+void pfkey_stats(u_long, const char *, int, int);
+#endif
+
+void mbpr(void *, u_long);
+
+void hostpr(u_long, u_long);
+void impstats(u_long, u_long);
+
+void intpr(int, u_long, void (*)(char *));
+
+void pr_rthdr(int);
+void pr_family(int);
+void rt_stats(u_long, u_long);
+char *ipx_pnet(struct sockaddr *);
+char *ipx_phost(struct sockaddr *);
+char *ns_phost(struct sockaddr *);
+void upHex(char *);
+
+#ifdef __rtems__
+#define routename rtems_shell_netstats_routername
+#define netname rtems_shell_netstats_netname
+#define sotoxsocket rtems_shell_netstats_sotoxsocket
+#endif
+
+char *routename(in_addr_t);
+char *netname(in_addr_t, u_long);
+char *atalk_print(struct sockaddr *, int);
+char *atalk_print2(struct sockaddr *, struct sockaddr *, int);
+char *ipx_print(struct sockaddr *);
+char *ns_print(struct sockaddr *);
+void routepr(u_long);
+
+void ipxprotopr(u_long, const char *, int, int);
+void spx_stats(u_long, const char *, int, int);
+void ipx_stats(u_long, const char *, int, int);
+void ipxerr_stats(u_long, const char *, int, int);
+
+void nsprotopr(u_long, const char *, int, int);
+void spp_stats(u_long, const char *, int, int);
+void idp_stats(u_long, const char *, int, int);
+void nserr_stats(u_long, const char *, int, int);
+
+void atalkprotopr(u_long, const char *, int, int);
+void ddp_stats(u_long, const char *, int, int);
+
+#ifdef NETGRAPH
+void netgraphprotopr(u_long, const char *, int, int);
+#endif
+
+void unixpr(u_long, u_long, u_long, u_long);
+
+void esis_stats(u_long, const char *, int, int);
+void clnp_stats(u_long, const char *, int, int);
+void cltp_stats(u_long, const char *, int, int);
+void iso_protopr(u_long, const char *, int, int);
+void iso_protopr1(u_long, int);
+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, u_long);
+void mrt_stats(u_long);
+void bpf_stats(char *);
diff --git a/freebsd/usr.bin/netstat/pfkey.c b/freebsd/usr.bin/netstat/pfkey.c
new file mode 100644
index 00000000..7c5af07b
--- /dev/null
+++ b/freebsd/usr.bin/netstat/pfkey.c
@@ -0,0 +1,184 @@
+/* $NetBSD: inet.c,v 1.35.2.1 1999/04/29 14:57:08 perry Exp $ */
+/* $KAME: ipsec.c,v 1.25 2001/03/12 09:04:39 itojun Exp $ */
+/*-
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * 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 project 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 PROJECT 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 PROJECT 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) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)inet.c 8.5 (Berkeley) 5/24/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+
+#include <netinet/in.h>
+
+#ifdef IPSEC
+#ifdef __rtems__
+#include <freebsd/netipsec/keysock.h>
+#else
+#include <netipsec/keysock.h>
+#endif
+#endif
+
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#ifdef IPSEC
+
+static const char *pfkey_msgtypenames[] = {
+ "reserved", "getspi", "update", "add", "delete",
+ "get", "acquire", "register", "expire", "flush",
+ "dump", "x_promisc", "x_pchange", "x_spdupdate", "x_spdadd",
+ "x_spddelete", "x_spdget", "x_spdacquire", "x_spddump", "x_spdflush",
+ "x_spdsetidx", "x_spdexpire", "x_spddelete2"
+};
+
+static const char *pfkey_msgtype_names (int);
+
+
+static const char *
+pfkey_msgtype_names(int x)
+{
+ const int max =
+ sizeof(pfkey_msgtypenames)/sizeof(pfkey_msgtypenames[0]);
+ static char buf[20];
+
+ if (x < max && pfkey_msgtypenames[x])
+ return pfkey_msgtypenames[x];
+ snprintf(buf, sizeof(buf), "#%d", x);
+ return buf;
+}
+
+void
+pfkey_stats(u_long off, const char *name, int family __unused,
+ int proto __unused)
+{
+ struct pfkeystat pfkeystat;
+ unsigned first, type;
+
+ if (off == 0)
+ return;
+ printf ("%s:\n", name);
+ kread(off, (char *)&pfkeystat, sizeof(pfkeystat));
+
+#define p(f, m) if (pfkeystat.f || sflag <= 1) \
+ printf(m, (uintmax_t)pfkeystat.f, plural(pfkeystat.f))
+
+ /* userland -> kernel */
+ p(out_total, "\t%ju request%s sent from userland\n");
+ p(out_bytes, "\t%ju byte%s sent from userland\n");
+ for (first = 1, type = 0;
+ type < sizeof(pfkeystat.out_msgtype)/sizeof(pfkeystat.out_msgtype[0]);
+ type++) {
+ if (pfkeystat.out_msgtype[type] <= 0)
+ continue;
+ if (first) {
+ printf("\thistogram by message type:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %ju\n", pfkey_msgtype_names(type),
+ (uintmax_t)pfkeystat.out_msgtype[type]);
+ }
+ p(out_invlen, "\t%ju message%s with invalid length field\n");
+ p(out_invver, "\t%ju message%s with invalid version field\n");
+ p(out_invmsgtype, "\t%ju message%s with invalid message type field\n");
+ p(out_tooshort, "\t%ju message%s too short\n");
+ p(out_nomem, "\t%ju message%s with memory allocation failure\n");
+ p(out_dupext, "\t%ju message%s with duplicate extension\n");
+ p(out_invexttype, "\t%ju message%s with invalid extension type\n");
+ p(out_invsatype, "\t%ju message%s with invalid sa type\n");
+ p(out_invaddr, "\t%ju message%s with invalid address extension\n");
+
+ /* kernel -> userland */
+ p(in_total, "\t%ju request%s sent to userland\n");
+ p(in_bytes, "\t%ju byte%s sent to userland\n");
+ for (first = 1, type = 0;
+ type < sizeof(pfkeystat.in_msgtype)/sizeof(pfkeystat.in_msgtype[0]);
+ type++) {
+ if (pfkeystat.in_msgtype[type] <= 0)
+ continue;
+ if (first) {
+ printf("\thistogram by message type:\n");
+ first = 0;
+ }
+ printf("\t\t%s: %ju\n", pfkey_msgtype_names(type),
+ (uintmax_t)pfkeystat.in_msgtype[type]);
+ }
+ p(in_msgtarget[KEY_SENDUP_ONE],
+ "\t%ju message%s toward single socket\n");
+ p(in_msgtarget[KEY_SENDUP_ALL],
+ "\t%ju message%s toward all sockets\n");
+ p(in_msgtarget[KEY_SENDUP_REGISTERED],
+ "\t%ju message%s toward registered sockets\n");
+ p(in_nomem, "\t%ju message%s with memory allocation failure\n");
+#undef p
+}
+#endif /* IPSEC */
diff --git a/freebsd/usr.bin/netstat/route.c b/freebsd/usr.bin/netstat/route.c
new file mode 100644
index 00000000..55042814
--- /dev/null
+++ b/freebsd/usr.bin/netstat/route.c
@@ -0,0 +1,1173 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "From: @(#)route.c 8.6 (Berkeley) 4/28/95";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/time.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#ifdef __rtems__
+#include <freebsd/net/if_var.h>
+#else
+#include <net/if_var.h>
+#endif
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#ifdef __rtems__
+#include <freebsd/net/radix.h>
+#else
+#include <net/radix.h>
+#endif
+#include <net/route.h>
+
+#include <netinet/in.h>
+#ifdef __rtems__
+/* no IPX on RTEMS */
+/* no AppleTalk on RTEMS */
+#else
+#include <netipx/ipx.h>
+#include <netatalk/at.h>
+#endif
+#ifdef __rtems__
+/* why isn't this protected by a NETGRAPH define */
+#else
+#include <netgraph/ng_socket.h>
+#endif
+
+#include <sys/sysctl.h>
+
+#include <arpa/inet.h>
+#ifdef __rtems__
+/* apparently libutil.h is not needed */
+#else
+#include <libutil.h>
+#endif
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <err.h>
+#include "netstat.h"
+
+#define kget(p, d) (kread((u_long)(p), (char *)&(d), sizeof (d)))
+
+/*
+ * Definitions for showing gateway flags.
+ */
+struct bits {
+ u_long b_mask;
+ char b_val;
+} bits[] = {
+ { RTF_UP, 'U' },
+ { RTF_GATEWAY, 'G' },
+ { RTF_HOST, 'H' },
+ { RTF_REJECT, 'R' },
+ { RTF_DYNAMIC, 'D' },
+ { RTF_MODIFIED, 'M' },
+ { RTF_DONE, 'd' }, /* Completed -- for routing messages only */
+ { RTF_XRESOLVE, 'X' },
+ { RTF_STATIC, 'S' },
+ { RTF_PROTO1, '1' },
+ { RTF_PROTO2, '2' },
+ { RTF_PRCLONING,'c' },
+ { RTF_PROTO3, '3' },
+ { RTF_BLACKHOLE,'B' },
+ { RTF_BROADCAST,'b' },
+#ifdef RTF_LLINFO
+ { RTF_LLINFO, 'L' },
+#endif
+#ifdef RTF_WASCLONED
+ { RTF_WASCLONED,'W' },
+#endif
+#ifdef RTF_CLONING
+ { RTF_CLONING, 'C' },
+#endif
+ { 0 , 0 }
+};
+
+typedef union {
+ long dummy; /* Helps align structure. */
+ struct sockaddr u_sa;
+ u_short u_data[128];
+} sa_u;
+
+static sa_u pt_u;
+
+int fibnum;
+int do_rtent = 0;
+struct rtentry rtentry;
+struct radix_node rnode;
+struct radix_mask rmask;
+struct radix_node_head **rt_tables;
+
+int NewTree = 0;
+
+struct timespec uptime;
+
+static struct sockaddr *kgetsa(struct sockaddr *);
+static void size_cols(int ef, struct radix_node *rn);
+static void size_cols_tree(struct radix_node *rn);
+static void size_cols_rtentry(struct rtentry *rt);
+static void p_tree(struct radix_node *);
+static void p_rtnode(void);
+static void ntreestuff(void);
+static void np_rtentry(struct rt_msghdr *);
+static void p_sockaddr(struct sockaddr *, struct sockaddr *, int, int);
+static const char *fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask,
+ int flags);
+static void p_flags(int, const char *);
+static const char *fmt_flags(int f);
+static void p_rtentry(struct rtentry *);
+static void domask(char *, in_addr_t, u_long);
+
+/*
+ * Print routing tables.
+ */
+void
+routepr(u_long rtree)
+{
+ struct radix_node_head **rnhp, *rnh, head;
+ size_t intsize;
+ int i;
+ int numfibs;
+
+ intsize = sizeof(int);
+ if (sysctlbyname("net.my_fibnum", &fibnum, &intsize, NULL, 0) == -1)
+ fibnum = 0;
+ if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1)
+ numfibs = 1;
+ rt_tables = calloc(numfibs * (AF_MAX+1),
+ sizeof(struct radix_node_head *));
+ if (rt_tables == NULL)
+ err(EX_OSERR, "memory allocation failed");
+ /*
+ * Since kernel & userland use different timebase
+ * (time_uptime vs time_second) and we are reading kernel memory
+ * directly we should do rt_rmx.rmx_expire --> expire_time conversion.
+ */
+#ifdef __rtems__
+ {
+ rtems_clock_get_uptime(&uptime);
+ }
+#else
+ if (clock_gettime(CLOCK_UPTIME, &uptime) < 0)
+ err(EX_OSERR, "clock_gettime() failed");
+#endif
+
+ printf("Routing tables\n");
+
+ if (Aflag == 0 && NewTree)
+ ntreestuff();
+ else {
+ if (rtree == 0) {
+ printf("rt_tables: symbol not in namelist\n");
+ return;
+ }
+
+ if (kread((u_long)(rtree), (char *)(rt_tables), (numfibs *
+ (AF_MAX+1) * sizeof(struct radix_node_head *))) != 0)
+ return;
+ for (i = 0; i <= AF_MAX; i++) {
+ int tmpfib;
+ if (i != AF_INET)
+ tmpfib = 0;
+ else
+ tmpfib = fibnum;
+ rnhp = (struct radix_node_head **)*rt_tables;
+ /* Calculate the in-kernel address. */
+ rnhp += tmpfib * (AF_MAX+1) + i;
+ /* Read the in kernel rhn pointer. */
+ if (kget(rnhp, rnh) != 0)
+ continue;
+ if (rnh == NULL)
+ continue;
+#ifdef __rtems__
+ /* printf( "rnh %p %p\n", (void *)rnhp, (void *)rnh ); */
+ /* We get a 1 here on some fields. Why? XXX */
+#endif
+ /* Read the rnh data. */
+ if (kget(rnh, head) != 0)
+ continue;
+ if (i == AF_UNSPEC) {
+ if (Aflag && af == 0) {
+ printf("Netmasks:\n");
+ p_tree(head.rnh_treetop);
+ }
+ } else if (af == AF_UNSPEC || af == i) {
+ size_cols(i, head.rnh_treetop);
+ pr_family(i);
+ do_rtent = 1;
+ pr_rthdr(i);
+ p_tree(head.rnh_treetop);
+ }
+ }
+ }
+}
+
+/*
+ * Print address family header before a section of the routing table.
+ */
+void
+pr_family(int af1)
+{
+ const char *afname;
+
+ switch (af1) {
+ case AF_INET:
+ afname = "Internet";
+ break;
+#ifdef INET6
+ case AF_INET6:
+ afname = "Internet6";
+ break;
+#endif /*INET6*/
+ case AF_IPX:
+ afname = "IPX";
+ break;
+ case AF_ISO:
+ afname = "ISO";
+ break;
+ case AF_APPLETALK:
+ afname = "AppleTalk";
+ break;
+ case AF_CCITT:
+ afname = "X.25";
+ break;
+ case AF_NETGRAPH:
+ afname = "Netgraph";
+ break;
+ default:
+ afname = NULL;
+ break;
+ }
+ if (afname)
+ printf("\n%s:\n", afname);
+ else
+ printf("\nProtocol Family %d:\n", af1);
+}
+
+/* column widths; each followed by one space */
+#ifndef INET6
+#define WID_DST_DEFAULT(af) 18 /* width of destination column */
+#define WID_GW_DEFAULT(af) 18 /* width of gateway column */
+#define WID_IF_DEFAULT(af) (Wflag ? 8 : 6) /* width of netif column */
+#else
+#define WID_DST_DEFAULT(af) \
+ ((af) == AF_INET6 ? (numeric_addr ? 33: 18) : 18)
+#define WID_GW_DEFAULT(af) \
+ ((af) == AF_INET6 ? (numeric_addr ? 29 : 18) : 18)
+#define WID_IF_DEFAULT(af) ((af) == AF_INET6 ? 8 : (Wflag ? 8 : 6))
+#endif /*INET6*/
+
+static int wid_dst;
+static int wid_gw;
+static int wid_flags;
+static int wid_refs;
+static int wid_use;
+static int wid_mtu;
+static int wid_if;
+static int wid_expire;
+
+static void
+size_cols(int ef __unused, struct radix_node *rn)
+{
+ wid_dst = WID_DST_DEFAULT(ef);
+ wid_gw = WID_GW_DEFAULT(ef);
+ wid_flags = 6;
+ wid_refs = 6;
+ wid_use = 8;
+ wid_mtu = 6;
+ wid_if = WID_IF_DEFAULT(ef);
+ wid_expire = 6;
+
+ if (Wflag)
+ size_cols_tree(rn);
+}
+
+static void
+size_cols_tree(struct radix_node *rn)
+{
+again:
+ if (kget(rn, rnode) != 0)
+ return;
+ if (!(rnode.rn_flags & RNF_ACTIVE))
+ return;
+ if (rnode.rn_bit < 0) {
+ if ((rnode.rn_flags & RNF_ROOT) == 0) {
+ if (kget(rn, rtentry) != 0)
+ return;
+ size_cols_rtentry(&rtentry);
+ }
+ if ((rn = rnode.rn_dupedkey))
+ goto again;
+ } else {
+ rn = rnode.rn_right;
+ size_cols_tree(rnode.rn_left);
+ size_cols_tree(rn);
+ }
+}
+
+static void
+size_cols_rtentry(struct rtentry *rt)
+{
+ static struct ifnet ifnet, *lastif;
+ static char buffer[100];
+ const char *bp;
+ struct sockaddr *sa;
+ sa_u addr, mask;
+ int len;
+
+ bzero(&addr, sizeof(addr));
+ if ((sa = kgetsa(rt_key(rt))))
+ bcopy(sa, &addr, sa->sa_len);
+ bzero(&mask, sizeof(mask));
+ if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
+ bcopy(sa, &mask, sa->sa_len);
+ bp = fmt_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags);
+ len = strlen(bp);
+ wid_dst = MAX(len, wid_dst);
+
+ bp = fmt_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST);
+ len = strlen(bp);
+ wid_gw = MAX(len, wid_gw);
+
+ bp = fmt_flags(rt->rt_flags);
+ len = strlen(bp);
+ wid_flags = MAX(len, wid_flags);
+
+ if (addr.u_sa.sa_family == AF_INET || Wflag) {
+ len = snprintf(buffer, sizeof(buffer), "%d", rt->rt_refcnt);
+ wid_refs = MAX(len, wid_refs);
+ len = snprintf(buffer, sizeof(buffer), "%lu", rt->rt_use);
+ wid_use = MAX(len, wid_use);
+ if (Wflag && rt->rt_rmx.rmx_mtu != 0) {
+ len = snprintf(buffer, sizeof(buffer),
+ "%lu", rt->rt_rmx.rmx_mtu);
+ wid_mtu = MAX(len, wid_mtu);
+ }
+ }
+ if (rt->rt_ifp) {
+ if (rt->rt_ifp != lastif) {
+ if (kget(rt->rt_ifp, ifnet) == 0)
+ len = strlen(ifnet.if_xname);
+ else
+ len = strlen("---");
+ lastif = rt->rt_ifp;
+ wid_if = MAX(len, wid_if);
+ }
+ if (rt->rt_rmx.rmx_expire) {
+ time_t expire_time;
+
+ if ((expire_time =
+ rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0) {
+ len = snprintf(buffer, sizeof(buffer), "%d",
+ (int)expire_time);
+ wid_expire = MAX(len, wid_expire);
+ }
+ }
+ }
+}
+
+
+/*
+ * Print header for routing table columns.
+ */
+void
+pr_rthdr(int af1)
+{
+
+ if (Aflag)
+ printf("%-8.8s ","Address");
+ if (af1 == AF_INET || Wflag) {
+ if (Wflag) {
+ printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*.*s %*s\n",
+ wid_dst, wid_dst, "Destination",
+ wid_gw, wid_gw, "Gateway",
+ wid_flags, wid_flags, "Flags",
+ wid_refs, wid_refs, "Refs",
+ wid_use, wid_use, "Use",
+ wid_mtu, wid_mtu, "Mtu",
+ wid_if, wid_if, "Netif",
+ wid_expire, "Expire");
+ } else {
+ printf("%-*.*s %-*.*s %-*.*s %*.*s %*.*s %*.*s %*s\n",
+ wid_dst, wid_dst, "Destination",
+ wid_gw, wid_gw, "Gateway",
+ wid_flags, wid_flags, "Flags",
+ wid_refs, wid_refs, "Refs",
+ wid_use, wid_use, "Use",
+ wid_if, wid_if, "Netif",
+ wid_expire, "Expire");
+ }
+ } else {
+ printf("%-*.*s %-*.*s %-*.*s %*.*s %*s\n",
+ wid_dst, wid_dst, "Destination",
+ wid_gw, wid_gw, "Gateway",
+ wid_flags, wid_flags, "Flags",
+ wid_if, wid_if, "Netif",
+ wid_expire, "Expire");
+ }
+}
+
+static struct sockaddr *
+kgetsa(struct sockaddr *dst)
+{
+
+ if (kget(dst, pt_u.u_sa) != 0)
+ return (NULL);
+ if (pt_u.u_sa.sa_len > sizeof (pt_u.u_sa))
+ kread((u_long)dst, (char *)pt_u.u_data, pt_u.u_sa.sa_len);
+ return (&pt_u.u_sa);
+}
+
+static void
+p_tree(struct radix_node *rn)
+{
+
+again:
+ if (kget(rn, rnode) != 0)
+ return;
+ if (!(rnode.rn_flags & RNF_ACTIVE))
+ return;
+ if (rnode.rn_bit < 0) {
+ if (Aflag)
+ printf("%-8.8lx ", (u_long)rn);
+ if (rnode.rn_flags & RNF_ROOT) {
+ if (Aflag)
+ printf("(root node)%s",
+ rnode.rn_dupedkey ? " =>\n" : "\n");
+ } else if (do_rtent) {
+ if (kget(rn, rtentry) == 0) {
+ p_rtentry(&rtentry);
+ if (Aflag)
+ p_rtnode();
+ }
+ } else {
+ p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_key),
+ NULL, 0, 44);
+ putchar('\n');
+ }
+ if ((rn = rnode.rn_dupedkey))
+ goto again;
+ } else {
+ if (Aflag && do_rtent) {
+ printf("%-8.8lx ", (u_long)rn);
+ p_rtnode();
+ }
+ rn = rnode.rn_right;
+ p_tree(rnode.rn_left);
+ p_tree(rn);
+ }
+}
+
+char nbuf[20];
+
+static void
+p_rtnode(void)
+{
+ struct radix_mask *rm = rnode.rn_mklist;
+
+ if (rnode.rn_bit < 0) {
+ if (rnode.rn_mask) {
+ printf("\t mask ");
+ p_sockaddr(kgetsa((struct sockaddr *)rnode.rn_mask),
+ NULL, 0, -1);
+ } else if (rm == 0)
+ return;
+ } else {
+ sprintf(nbuf, "(%d)", rnode.rn_bit);
+ printf("%6.6s %8.8lx : %8.8lx", nbuf, (u_long)rnode.rn_left, (u_long)rnode.rn_right);
+ }
+ while (rm) {
+ if (kget(rm, rmask) != 0)
+ break;
+ sprintf(nbuf, " %d refs, ", rmask.rm_refs);
+ printf(" mk = %8.8lx {(%d),%s",
+ (u_long)rm, -1 - rmask.rm_bit, rmask.rm_refs ? nbuf : " ");
+ if (rmask.rm_flags & RNF_NORMAL) {
+ struct radix_node rnode_aux;
+ printf(" <normal>, ");
+ if (kget(rmask.rm_leaf, rnode_aux) == 0)
+ p_sockaddr(kgetsa((struct sockaddr *)rnode_aux.rn_mask),
+ NULL, 0, -1);
+ else
+ p_sockaddr(NULL, NULL, 0, -1);
+ } else
+ p_sockaddr(kgetsa((struct sockaddr *)rmask.rm_mask),
+ NULL, 0, -1);
+ putchar('}');
+ if ((rm = rmask.rm_mklist))
+ printf(" ->");
+ }
+ putchar('\n');
+}
+
+static void
+ntreestuff(void)
+{
+ size_t needed;
+ int mib[6];
+ char *buf, *next, *lim;
+ struct rt_msghdr *rtm;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = 0;
+ mib[4] = NET_RT_DUMP;
+ mib[5] = 0;
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) {
+ err(1, "sysctl: net.route.0.0.dump estimate");
+ }
+
+ if ((buf = malloc(needed)) == 0) {
+ errx(2, "malloc(%lu)", (unsigned long)needed);
+ }
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ err(1, "sysctl: net.route.0.0.dump");
+ }
+ lim = buf + needed;
+ for (next = buf; next < lim; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)next;
+ np_rtentry(rtm);
+ }
+}
+
+static void
+np_rtentry(struct rt_msghdr *rtm)
+{
+ struct sockaddr *sa = (struct sockaddr *)(rtm + 1);
+#ifdef notdef
+ static int masks_done, banner_printed;
+#endif
+ static int old_af;
+ int af1 = 0, interesting = RTF_UP | RTF_GATEWAY | RTF_HOST;
+
+#ifdef notdef
+ /* for the moment, netmasks are skipped over */
+ if (!banner_printed) {
+ printf("Netmasks:\n");
+ banner_printed = 1;
+ }
+ if (masks_done == 0) {
+ if (rtm->rtm_addrs != RTA_DST ) {
+ masks_done = 1;
+ af1 = sa->sa_family;
+ }
+ } else
+#endif
+ af1 = sa->sa_family;
+ if (af1 != old_af) {
+ pr_family(af1);
+ old_af = af1;
+ }
+ if (rtm->rtm_addrs == RTA_DST)
+ p_sockaddr(sa, NULL, 0, 36);
+ else {
+ p_sockaddr(sa, NULL, rtm->rtm_flags, 16);
+ sa = (struct sockaddr *)(SA_SIZE(sa) + (char *)sa);
+ p_sockaddr(sa, NULL, 0, 18);
+ }
+ p_flags(rtm->rtm_flags & interesting, "%-6.6s ");
+ putchar('\n');
+}
+
+static void
+p_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags, int width)
+{
+ const char *cp;
+
+ cp = fmt_sockaddr(sa, mask, flags);
+
+ if (width < 0 )
+ printf("%s ", cp);
+ else {
+ if (numeric_addr)
+ printf("%-*s ", width, cp);
+ else
+ printf("%-*.*s ", width, width, cp);
+ }
+}
+
+static const char *
+fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
+{
+ static char workbuf[128];
+ const char *cp;
+
+ if (sa == NULL)
+ return ("null");
+
+ switch(sa->sa_family) {
+ case AF_INET:
+ {
+ struct sockaddr_in *sockin = (struct sockaddr_in *)sa;
+
+ if ((sockin->sin_addr.s_addr == INADDR_ANY) &&
+ mask &&
+ ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr)
+ ==0L)
+ cp = "default" ;
+ else if (flags & RTF_HOST)
+ cp = routename(sockin->sin_addr.s_addr);
+ else if (mask)
+ cp = netname(sockin->sin_addr.s_addr,
+ ntohl(((struct sockaddr_in *)mask)
+ ->sin_addr.s_addr));
+ else
+ cp = netname(sockin->sin_addr.s_addr, 0L);
+ break;
+ }
+
+#ifdef INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
+ struct in6_addr *in6 = &sa6->sin6_addr;
+
+ /*
+ * XXX: This is a special workaround for KAME kernels.
+ * sin6_scope_id field of SA should be set in the future.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(in6) ||
+ IN6_IS_ADDR_MC_LINKLOCAL(in6)) {
+ /* XXX: override is ok? */
+ sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
+ *(u_short *)&in6->s6_addr[2] = 0;
+ }
+
+ if (flags & RTF_HOST)
+ cp = routename6(sa6);
+ else if (mask)
+ cp = netname6(sa6,
+ &((struct sockaddr_in6 *)mask)->sin6_addr);
+ else {
+ cp = netname6(sa6, NULL);
+ }
+ break;
+ }
+#endif /*INET6*/
+
+#ifndef __rtems__
+ case AF_IPX:
+ {
+ struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
+ if (ipx_nullnet(satoipx_addr(work)))
+ cp = "default";
+ else
+ cp = ipx_print(sa);
+ break;
+ }
+ case AF_APPLETALK:
+ {
+ if (!(flags & RTF_HOST) && mask)
+ cp = atalk_print2(sa,mask,9);
+ else
+ cp = atalk_print(sa,11);
+ break;
+ }
+#endif
+ case AF_NETGRAPH:
+ {
+#ifdef __rtems__
+ /* netgraph not supported yet */
+ err(EX_OSERR, "memory allocation failed");
+#else
+ strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data,
+ sizeof(workbuf));
+ cp = workbuf;
+#endif
+ break;
+ }
+
+ case AF_LINK:
+ {
+ struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;
+
+ if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
+ sdl->sdl_slen == 0) {
+ (void) sprintf(workbuf, "link#%d", sdl->sdl_index);
+ cp = workbuf;
+ } else
+ switch (sdl->sdl_type) {
+
+ case IFT_ETHER:
+ case IFT_L2VLAN:
+ case IFT_BRIDGE:
+ if (sdl->sdl_alen == ETHER_ADDR_LEN) {
+ cp = ether_ntoa((struct ether_addr *)
+ (sdl->sdl_data + sdl->sdl_nlen));
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ cp = link_ntoa(sdl);
+ break;
+ }
+ break;
+ }
+
+ default:
+ {
+ u_char *s = (u_char *)sa->sa_data, *slim;
+ char *cq, *cqlim;
+
+ cq = workbuf;
+ slim = sa->sa_len + (u_char *) sa;
+ cqlim = cq + sizeof(workbuf) - 6;
+ cq += sprintf(cq, "(%d)", sa->sa_family);
+ while (s < slim && cq < cqlim) {
+ cq += sprintf(cq, " %02x", *s++);
+ if (s < slim)
+ cq += sprintf(cq, "%02x", *s++);
+ }
+ cp = workbuf;
+ }
+ }
+
+ return (cp);
+}
+
+static void
+p_flags(int f, const char *format)
+{
+ printf(format, fmt_flags(f));
+}
+
+static const char *
+fmt_flags(int f)
+{
+ static char name[33];
+ char *flags;
+ struct bits *p = bits;
+
+ for (flags = name; p->b_mask; p++)
+ if (p->b_mask & f)
+ *flags++ = p->b_val;
+ *flags = '\0';
+ return (name);
+}
+
+static void
+p_rtentry(struct rtentry *rt)
+{
+ static struct ifnet ifnet, *lastif;
+ static char buffer[128];
+ static char prettyname[128];
+ struct sockaddr *sa;
+ sa_u addr, mask;
+
+ bzero(&addr, sizeof(addr));
+ if ((sa = kgetsa(rt_key(rt))))
+ bcopy(sa, &addr, sa->sa_len);
+ bzero(&mask, sizeof(mask));
+ if (rt_mask(rt) && (sa = kgetsa(rt_mask(rt))))
+ bcopy(sa, &mask, sa->sa_len);
+ p_sockaddr(&addr.u_sa, &mask.u_sa, rt->rt_flags, wid_dst);
+ p_sockaddr(kgetsa(rt->rt_gateway), NULL, RTF_HOST, wid_gw);
+ snprintf(buffer, sizeof(buffer), "%%-%d.%ds ", wid_flags, wid_flags);
+ p_flags(rt->rt_flags, buffer);
+ if (addr.u_sa.sa_family == AF_INET || Wflag) {
+ printf("%*d %*lu ", wid_refs, rt->rt_refcnt,
+ wid_use, rt->rt_use);
+ if (Wflag) {
+ if (rt->rt_rmx.rmx_mtu != 0)
+ printf("%*lu ", wid_mtu, rt->rt_rmx.rmx_mtu);
+ else
+ printf("%*s ", wid_mtu, "");
+ }
+ }
+ if (rt->rt_ifp) {
+ if (rt->rt_ifp != lastif) {
+ if (kget(rt->rt_ifp, ifnet) == 0)
+ strlcpy(prettyname, ifnet.if_xname,
+ sizeof(prettyname));
+ else
+ strlcpy(prettyname, "---", sizeof(prettyname));
+ lastif = rt->rt_ifp;
+ }
+ printf("%*.*s", wid_if, wid_if, prettyname);
+ if (rt->rt_rmx.rmx_expire) {
+ time_t expire_time;
+
+ if ((expire_time =
+ rt->rt_rmx.rmx_expire - uptime.tv_sec) > 0)
+ printf(" %*d", wid_expire, (int)expire_time);
+ }
+ if (rt->rt_nodes[0].rn_dupedkey)
+ printf(" =>");
+ }
+ putchar('\n');
+}
+
+char *
+routename(in_addr_t in)
+{
+ char *cp;
+ static char line[MAXHOSTNAMELEN];
+ struct hostent *hp;
+
+ cp = 0;
+ if (!numeric_addr) {
+ hp = gethostbyaddr(&in, sizeof (struct in_addr), AF_INET);
+ if (hp) {
+ cp = hp->h_name;
+ trimdomain(cp, strlen(cp));
+ }
+ }
+ if (cp) {
+ strlcpy(line, cp, sizeof(line));
+ } else {
+#define C(x) ((x) & 0xff)
+ in = ntohl(in);
+ sprintf(line, "%u.%u.%u.%u",
+ C(in >> 24), C(in >> 16), C(in >> 8), C(in));
+ }
+ return (line);
+}
+
+#define NSHIFT(m) ( \
+ (m) == IN_CLASSA_NET ? IN_CLASSA_NSHIFT : \
+ (m) == IN_CLASSB_NET ? IN_CLASSB_NSHIFT : \
+ (m) == IN_CLASSC_NET ? IN_CLASSC_NSHIFT : \
+ 0)
+
+static void
+domask(char *dst, in_addr_t addr __unused, u_long mask)
+{
+ int b, i;
+
+ if (mask == 0 || (!numeric_addr && NSHIFT(mask) != 0)) {
+ *dst = '\0';
+ return;
+ }
+ i = 0;
+ for (b = 0; b < 32; b++)
+ if (mask & (1 << b)) {
+ int bb;
+
+ i = b;
+ for (bb = b+1; bb < 32; bb++)
+ if (!(mask & (1 << bb))) {
+ i = -1; /* noncontig */
+ break;
+ }
+ break;
+ }
+ if (i == -1)
+ sprintf(dst, "&0x%lx", mask);
+ else
+ sprintf(dst, "/%d", 32-i);
+}
+
+/*
+ * Return the name of the network whose address is given.
+ * The address is assumed to be that of a net or subnet, not a host.
+ */
+char *
+netname(in_addr_t in, u_long mask)
+{
+ char *cp = 0;
+ static char line[MAXHOSTNAMELEN];
+ struct netent *np = 0;
+ in_addr_t i;
+
+ i = ntohl(in);
+ if (!numeric_addr && i) {
+ np = getnetbyaddr(i >> NSHIFT(mask), AF_INET);
+ if (np != NULL) {
+ cp = np->n_name;
+ trimdomain(cp, strlen(cp));
+ }
+ }
+ if (cp != NULL) {
+ strlcpy(line, cp, sizeof(line));
+ } else {
+ inet_ntop(AF_INET, &in, line, sizeof(line) - 1);
+ }
+ domask(line + strlen(line), i, mask);
+ return (line);
+}
+
+#undef NSHIFT
+
+#ifdef INET6
+const char *
+netname6(struct sockaddr_in6 *sa6, struct in6_addr *mask)
+{
+ static char line[MAXHOSTNAMELEN];
+ u_char *p = (u_char *)mask;
+ u_char *lim;
+ int masklen, illegal = 0, flag = 0;
+
+ if (mask) {
+ for (masklen = 0, lim = p + 16; p < lim; p++) {
+ switch (*p) {
+ case 0xff:
+ masklen += 8;
+ break;
+ case 0xfe:
+ masklen += 7;
+ break;
+ case 0xfc:
+ masklen += 6;
+ break;
+ case 0xf8:
+ masklen += 5;
+ break;
+ case 0xf0:
+ masklen += 4;
+ break;
+ case 0xe0:
+ masklen += 3;
+ break;
+ case 0xc0:
+ masklen += 2;
+ break;
+ case 0x80:
+ masklen += 1;
+ break;
+ case 0x00:
+ break;
+ default:
+ illegal ++;
+ break;
+ }
+ }
+ if (illegal)
+ fprintf(stderr, "illegal prefixlen\n");
+ }
+ else
+ masklen = 128;
+
+ if (masklen == 0 && IN6_IS_ADDR_UNSPECIFIED(&sa6->sin6_addr))
+ return("default");
+
+ if (numeric_addr)
+ flag |= NI_NUMERICHOST;
+ getnameinfo((struct sockaddr *)sa6, sa6->sin6_len, line, sizeof(line),
+ NULL, 0, flag);
+
+ if (numeric_addr)
+ sprintf(&line[strlen(line)], "/%d", masklen);
+
+ return line;
+}
+
+char *
+routename6(struct sockaddr_in6 *sa6)
+{
+ static char line[MAXHOSTNAMELEN];
+ int flag = 0;
+ /* use local variable for safety */
+ struct sockaddr_in6 sa6_local;
+
+ sa6_local.sin6_family = AF_INET6;
+ sa6_local.sin6_len = sizeof(sa6_local);
+ sa6_local.sin6_addr = sa6->sin6_addr;
+ sa6_local.sin6_scope_id = sa6->sin6_scope_id;
+
+ if (numeric_addr)
+ flag |= NI_NUMERICHOST;
+
+ getnameinfo((struct sockaddr *)&sa6_local, sa6_local.sin6_len,
+ line, sizeof(line), NULL, 0, flag);
+
+ return line;
+}
+#endif /*INET6*/
+
+/*
+ * Print routing statistics
+ */
+void
+rt_stats(u_long rtsaddr, u_long rttaddr)
+{
+ struct rtstat rtstat;
+ int rttrash;
+
+ if (rtsaddr == 0) {
+ printf("rtstat: symbol not in namelist\n");
+ return;
+ }
+ if (rttaddr == 0) {
+ printf("rttrash: symbol not in namelist\n");
+ return;
+ }
+ kread(rtsaddr, (char *)&rtstat, sizeof (rtstat));
+ kread(rttaddr, (char *)&rttrash, sizeof (rttrash));
+ printf("routing:\n");
+
+#define p(f, m) if (rtstat.f || sflag <= 1) \
+ printf(m, rtstat.f, plural(rtstat.f))
+
+ p(rts_badredirect, "\t%hu bad routing redirect%s\n");
+ p(rts_dynamic, "\t%hu dynamically created route%s\n");
+ p(rts_newgateway, "\t%hu new gateway%s due to redirects\n");
+ p(rts_unreach, "\t%hu destination%s found unreachable\n");
+ p(rts_wildcard, "\t%hu use%s of a wildcard route\n");
+#undef p
+
+ if (rttrash || sflag <= 1)
+ printf("\t%u route%s not in table but not freed\n",
+ rttrash, plural(rttrash));
+}
+
+#ifndef __rtems__
+char *
+ipx_print(struct sockaddr *sa)
+{
+ u_short port;
+ struct servent *sp = 0;
+ const char *net = "", *host = "";
+ char *p;
+ u_char *q;
+ struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
+ static char mybuf[50];
+ char cport[10], chost[15], cnet[15];
+
+ port = ntohs(work.x_port);
+
+ if (ipx_nullnet(work) && ipx_nullhost(work)) {
+
+ if (port) {
+ if (sp)
+ sprintf(mybuf, "*.%s", sp->s_name);
+ else
+ sprintf(mybuf, "*.%x", port);
+ } else
+ sprintf(mybuf, "*.*");
+
+ return (mybuf);
+ }
+
+ if (ipx_wildnet(work))
+ net = "any";
+ else if (ipx_nullnet(work))
+ net = "*";
+ else {
+ q = work.x_net.c_net;
+ sprintf(cnet, "%02x%02x%02x%02x",
+ q[0], q[1], q[2], q[3]);
+ for (p = cnet; *p == '0' && p < cnet + 8; p++)
+ continue;
+ net = p;
+ }
+
+ if (ipx_wildhost(work))
+ host = "any";
+ else if (ipx_nullhost(work))
+ host = "*";
+ else {
+ q = work.x_host.c_host;
+ sprintf(chost, "%02x%02x%02x%02x%02x%02x",
+ q[0], q[1], q[2], q[3], q[4], q[5]);
+ for (p = chost; *p == '0' && p < chost + 12; p++)
+ continue;
+ host = p;
+ }
+
+ if (port) {
+ if (strcmp(host, "*") == 0)
+ host = "";
+ if (sp)
+ snprintf(cport, sizeof(cport),
+ "%s%s", *host ? "." : "", sp->s_name);
+ else
+ snprintf(cport, sizeof(cport),
+ "%s%x", *host ? "." : "", port);
+ } else
+ *cport = 0;
+
+ snprintf(mybuf, sizeof(mybuf), "%s.%s%s", net, host, cport);
+ return(mybuf);
+}
+
+char *
+ipx_phost(struct sockaddr *sa)
+{
+ struct sockaddr_ipx *sipx = (struct sockaddr_ipx *)sa;
+ struct sockaddr_ipx work;
+ static union ipx_net ipx_zeronet;
+ char *p;
+ struct ipx_addr in;
+
+ work = *sipx;
+ in = work.sipx_addr;
+
+ work.sipx_addr.x_port = 0;
+ work.sipx_addr.x_net = ipx_zeronet;
+ p = ipx_print((struct sockaddr *)&work);
+ if (strncmp("*.", p, 2) == 0) p += 2;
+
+ return(p);
+}
+#endif
+
+void
+upHex(char *p0)
+{
+ char *p = p0;
+
+ for (; *p; p++)
+ switch (*p) {
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ *p += ('A' - 'a');
+ break;
+ }
+}
diff --git a/freebsd/usr.bin/netstat/sctp.c b/freebsd/usr.bin/netstat/sctp.c
new file mode 100644
index 00000000..0c02db9f
--- /dev/null
+++ b/freebsd/usr.bin/netstat/sctp.c
@@ -0,0 +1,703 @@
+/*-
+ * Copyright (c) 2001-2007, by 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:
+ *
+ * a) Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * b) 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.
+ *
+ * c) Neither the name of Cisco Systems, Inc. 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.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)sctp.c 0.1 (Berkeley) 4/18/2007";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/sysctl.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+
+#include <netinet/in.h>
+#ifdef __rtems__
+#include <freebsd/netinet/sctp.h>
+#include <freebsd/netinet/sctp_constants.h>
+#else
+#include <netinet/sctp.h>
+#include <netinet/sctp_constants.h>
+#endif
+#include <arpa/inet.h>
+
+#include <err.h>
+#include <errno.h>
+#ifdef __rtems__
+/* apparently libutil.h is not needed */
+#else
+#include <libutil.h>
+#endif
+#include <netdb.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "netstat.h"
+
+#ifdef SCTP
+
+void inetprint(struct in_addr *, int, const char *, int);
+static void sctp_statesprint(uint32_t state);
+
+#define NETSTAT_SCTP_STATES_CLOSED 0x0
+#define NETSTAT_SCTP_STATES_BOUND 0x1
+#define NETSTAT_SCTP_STATES_LISTEN 0x2
+#define NETSTAT_SCTP_STATES_COOKIE_WAIT 0x3
+#define NETSTAT_SCTP_STATES_COOKIE_ECHOED 0x4
+#define NETSTAT_SCTP_STATES_ESTABLISHED 0x5
+#define NETSTAT_SCTP_STATES_SHUTDOWN_SENT 0x6
+#define NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED 0x7
+#define NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT 0x8
+#define NETSTAT_SCTP_STATES_SHUTDOWN_PENDING 0x9
+
+char *sctpstates[] = {
+ "CLOSED",
+ "BOUND",
+ "LISTEN",
+ "COOKIE_WAIT",
+ "COOKIE_ECHOED",
+ "ESTABLISHED",
+ "SHUTDOWN_SENT",
+ "SHUTDOWN_RECEIVED",
+ "SHUTDOWN_ACK_SENT",
+ "SHUTDOWN_PENDING"
+};
+
+LIST_HEAD(xladdr_list, xladdr_entry) xladdr_head;
+struct xladdr_entry {
+ struct xsctp_laddr *xladdr;
+ LIST_ENTRY(xladdr_entry) xladdr_entries;
+};
+
+LIST_HEAD(xraddr_list, xraddr_entry) xraddr_head;
+struct xraddr_entry {
+ struct xsctp_raddr *xraddr;
+ LIST_ENTRY(xraddr_entry) xraddr_entries;
+};
+
+static int
+sctp_skip_xinpcb_ifneed(char *buf, const size_t buflen, size_t *offset)
+{
+ int exist_tcb = 0;
+ struct xsctp_tcb *xstcb;
+ struct xsctp_raddr *xraddr;
+ struct xsctp_laddr *xladdr;
+
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+ }
+
+ while (*offset < buflen) {
+ xstcb = (struct xsctp_tcb *)(buf + *offset);
+ *offset += sizeof(struct xsctp_tcb);
+ if (xstcb->last == 1)
+ break;
+
+ exist_tcb = 1;
+
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+ }
+
+ while (*offset < buflen) {
+ xraddr = (struct xsctp_raddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_raddr);
+ if (xraddr->last == 1)
+ break;
+ }
+ }
+
+ /*
+ * If Lflag is set, we don't care about the return value.
+ */
+ if (Lflag)
+ return 0;
+
+ return exist_tcb;
+}
+
+static void
+sctp_process_tcb(struct xsctp_tcb *xstcb, const char *name,
+ char *buf, const size_t buflen, size_t *offset, int *indent)
+{
+ int i, xl_total = 0, xr_total = 0, x_max;
+ struct sockaddr *sa;
+ struct xsctp_raddr *xraddr;
+ struct xsctp_laddr *xladdr;
+ struct xladdr_entry *prev_xl = NULL, *xl = NULL, *xl_tmp;
+ struct xraddr_entry *prev_xr = NULL, *xr = NULL, *xr_tmp;
+#ifdef INET6
+ struct sockaddr_in6 *in6;
+#endif
+
+ LIST_INIT(&xladdr_head);
+ LIST_INIT(&xraddr_head);
+
+ /*
+ * Make `struct xladdr_list' list and `struct xraddr_list' list
+ * to handle the address flexibly.
+ */
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+
+ prev_xl = xl;
+ xl = malloc(sizeof(struct xladdr_entry));
+ if (xl == NULL) {
+ warnx("malloc %lu bytes",
+ (u_long)sizeof(struct xladdr_entry));
+ goto out;
+ }
+ xl->xladdr = xladdr;
+ if (prev_xl == NULL)
+ LIST_INSERT_HEAD(&xladdr_head, xl, xladdr_entries);
+ else
+ LIST_INSERT_AFTER(prev_xl, xl, xladdr_entries);
+ xl_total++;
+ }
+
+ while (*offset < buflen) {
+ xraddr = (struct xsctp_raddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_raddr);
+ if (xraddr->last == 1)
+ break;
+
+ prev_xr = xr;
+ xr = malloc(sizeof(struct xraddr_entry));
+ if (xr == NULL) {
+ warnx("malloc %lu bytes",
+ (u_long)sizeof(struct xraddr_entry));
+ goto out;
+ }
+ xr->xraddr = xraddr;
+ if (prev_xr == NULL)
+ LIST_INSERT_HEAD(&xraddr_head, xr, xraddr_entries);
+ else
+ LIST_INSERT_AFTER(prev_xr, xr, xraddr_entries);
+ xr_total++;
+ }
+
+ /*
+ * Let's print the address infos.
+ */
+ xl = LIST_FIRST(&xladdr_head);
+ xr = LIST_FIRST(&xraddr_head);
+ x_max = (xl_total > xr_total) ? xl_total : xr_total;
+ for (i = 0; i < x_max; i++) {
+ if (((*indent == 0) && i > 0) || *indent > 0)
+ printf("%-11s ", " ");
+
+ if (xl != NULL) {
+ sa = &(xl->xladdr->address.sa);
+ if ((sa->sa_family) == AF_INET)
+ inetprint(&((struct sockaddr_in *)sa)->sin_addr,
+ htons(xstcb->local_port),
+ name, numeric_port);
+#ifdef INET6
+ else {
+ in6 = (struct sockaddr_in6 *)sa;
+ inet6print(&in6->sin6_addr,
+ htons(xstcb->local_port),
+ name, numeric_port);
+ }
+#endif
+ }
+
+ if (xr != NULL && !Lflag) {
+ sa = &(xr->xraddr->address.sa);
+ if ((sa->sa_family) == AF_INET)
+ inetprint(&((struct sockaddr_in *)sa)->sin_addr,
+ htons(xstcb->remote_port),
+ name, numeric_port);
+#ifdef INET6
+ else {
+ in6 = (struct sockaddr_in6 *)sa;
+ inet6print(&in6->sin6_addr,
+ htons(xstcb->remote_port),
+ name, numeric_port);
+ }
+#endif
+ }
+
+ if (xl != NULL)
+ xl = LIST_NEXT(xl, xladdr_entries);
+ if (xr != NULL)
+ xr = LIST_NEXT(xr, xraddr_entries);
+
+ if (i == 0 && !Lflag)
+ sctp_statesprint(xstcb->state);
+
+ if (i < x_max)
+ putchar('\n');
+ }
+
+out:
+ /*
+ * Free the list which be used to handle the address.
+ */
+ xl = LIST_FIRST(&xladdr_head);
+ while (xl != NULL) {
+ xl_tmp = LIST_NEXT(xl, xladdr_entries);
+ free(xl);
+ xl = xl_tmp;
+ }
+
+ xr = LIST_FIRST(&xraddr_head);
+ while (xr != NULL) {
+ xr_tmp = LIST_NEXT(xr, xraddr_entries);
+ free(xr);
+ xr = xr_tmp;
+ }
+}
+
+#ifdef SCTP_DEBUG
+uint32_t sctp_pdup[64];
+int sctp_pcnt = 0;
+#endif
+
+static void
+sctp_process_inpcb(struct xsctp_inpcb *xinpcb, const char *name,
+ char *buf, const size_t buflen, size_t *offset)
+{
+ int offset_backup, indent = 0, xladdr_total = 0, is_listening = 0;
+ static int first = 1;
+ char *tname;
+ struct xsctp_tcb *xstcb;
+ struct xsctp_laddr *xladdr;
+ struct sockaddr *sa;
+#ifdef INET6
+ struct sockaddr_in6 *in6;
+#endif
+
+ if ((xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE) ==
+ SCTP_PCB_FLAGS_TCPTYPE && xinpcb->maxqlen > 0)
+ is_listening = 1;
+
+ if (!Lflag && !is_listening &&
+ !(xinpcb->flags & SCTP_PCB_FLAGS_CONNECTED)) {
+#ifdef SCTP_DEBUG
+ int i, found = 0;
+
+ for (i = 0; i < sctp_pcnt; i++) {
+ if (sctp_pdup[i] == xinpcb->flags) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ sctp_pdup[sctp_pcnt++] = xinpcb->flags;
+ if (sctp_pcnt >= 64)
+ sctp_pcnt = 0;
+ printf("[0x%08x]", xinpcb->flags);
+ }
+#endif
+ offset_backup = *offset;
+ if (!sctp_skip_xinpcb_ifneed(buf, buflen, offset))
+ return;
+ *offset = offset_backup;
+ }
+
+ if (first) {
+ if (!Lflag) {
+ printf("Active SCTP associations");
+ if (aflag)
+ printf(" (including servers)");
+ } else
+ printf("Current listen queue sizes (qlen/maxqlen)");
+ putchar('\n');
+ if (Aflag)
+ printf("%-8.8s ", "Socket");
+ if (Lflag)
+ printf("%-5.5s %-5.5s %-8.8s %-22.22s\n",
+ "Proto", "Type", "Listen", "Local Address");
+ else
+ printf((Aflag && !Wflag) ?
+ "%-5.5s %-5.5s %-18.18s %-18.18s %s\n" :
+ "%-5.5s %-5.5s %-22.22s %-22.22s %s\n",
+ "Proto", "Type",
+ "Local Address", "Foreign Address",
+ "(state)");
+ first = 0;
+ }
+ if (Lflag && xinpcb->maxqlen == 0) {
+ (int)sctp_skip_xinpcb_ifneed(buf, buflen, offset);
+ return;
+ }
+ if (Aflag)
+ printf("%8lx ", (u_long)xinpcb);
+
+ printf("%-5.5s ", name);
+
+ if (xinpcb->flags & SCTP_PCB_FLAGS_TCPTYPE)
+ tname = "1to1";
+ else if (xinpcb->flags & SCTP_PCB_FLAGS_UDPTYPE)
+ tname = "1toN";
+ else
+ return;
+
+ printf("%-5.5s ", tname);
+
+ if (Lflag) {
+ char buf1[9];
+
+ snprintf(buf1, 9, "%hu/%hu", xinpcb->qlen, xinpcb->maxqlen);
+ printf("%-8.8s ", buf1);
+ }
+ /*
+ * process the local address. This routine are used for Lflag.
+ */
+ while (*offset < buflen) {
+ xladdr = (struct xsctp_laddr *)(buf + *offset);
+ *offset += sizeof(struct xsctp_laddr);
+ if (xladdr->last == 1)
+ break;
+
+ if (!Lflag && !is_listening)
+ continue;
+
+ if (xladdr_total != 0)
+ putchar('\n');
+ if (xladdr_total > 0)
+ printf((Lflag) ?
+ "%-20.20s " : "%-11.11s ", " ");
+
+ sa = &(xladdr->address.sa);
+ if ((sa->sa_family) == AF_INET)
+ inetprint(&((struct sockaddr_in *)sa)->sin_addr,
+ htons(xinpcb->local_port), name, numeric_port);
+#ifdef INET6
+ else {
+ in6 = (struct sockaddr_in6 *)sa;
+ inet6print(&in6->sin6_addr,
+ htons(xinpcb->local_port), name, numeric_port);
+ }
+#endif
+
+ if (!Lflag && xladdr_total == 0 && is_listening == 1)
+ printf("%-22.22s LISTEN", " ");
+
+ xladdr_total++;
+ }
+
+ xstcb = (struct xsctp_tcb *)(buf + *offset);
+ *offset += sizeof(struct xsctp_tcb);
+ while (xstcb->last == 0 && *offset < buflen) {
+ sctp_process_tcb(xstcb, name, buf, buflen, offset, &indent);
+ indent++;
+ xstcb = (struct xsctp_tcb *)(buf + *offset);
+ *offset += sizeof(struct xsctp_tcb);
+ }
+
+ putchar('\n');
+}
+
+/*
+ * Print a summary of SCTP connections related to an Internet
+ * protocol.
+ */
+void
+sctp_protopr(u_long off __unused,
+ const char *name, int af1, int proto)
+{
+ char *buf;
+ const char *mibvar = "net.inet.sctp.assoclist";
+ size_t offset = 0;
+ size_t len = 0;
+ struct xsctp_inpcb *xinpcb;
+
+ if (proto != IPPROTO_SCTP)
+ return;
+
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ return;
+ }
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return;
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ free(buf);
+ return;
+ }
+
+ xinpcb = (struct xsctp_inpcb *)(buf + offset);
+ offset += sizeof(struct xsctp_inpcb);
+ while (xinpcb->last == 0 && offset < len) {
+ sctp_process_inpcb(xinpcb, name, buf, (const size_t)len,
+ &offset);
+
+ xinpcb = (struct xsctp_inpcb *)(buf + offset);
+ offset += sizeof(struct xsctp_inpcb);
+ }
+
+ free(buf);
+}
+
+static void
+sctp_statesprint(uint32_t state)
+{
+ int idx;
+
+ switch (state) {
+ case SCTP_STATE_COOKIE_WAIT:
+ idx = NETSTAT_SCTP_STATES_COOKIE_WAIT;
+ break;
+ case SCTP_STATE_COOKIE_ECHOED:
+ idx = NETSTAT_SCTP_STATES_COOKIE_ECHOED;
+ break;
+ case SCTP_STATE_OPEN:
+ idx = NETSTAT_SCTP_STATES_ESTABLISHED;
+ break;
+ case SCTP_STATE_SHUTDOWN_SENT:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_SENT;
+ break;
+ case SCTP_STATE_SHUTDOWN_RECEIVED:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_RECEIVED;
+ break;
+ case SCTP_STATE_SHUTDOWN_ACK_SENT:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_ACK_SENT;
+ break;
+ case SCTP_STATE_SHUTDOWN_PENDING:
+ idx = NETSTAT_SCTP_STATES_SHUTDOWN_PENDING;
+ break;
+ default:
+ printf("UNKNOWN 0x%08x", state);
+ return;
+ }
+
+ printf("%s", sctpstates[idx]);
+}
+
+/*
+ * Dump SCTP statistics structure.
+ */
+void
+sctp_stats(u_long off, const char *name, int af1 __unused, int proto __unused)
+{
+ struct sctpstat sctpstat, zerostat;
+ size_t len = sizeof(sctpstat);
+
+ if (live) {
+ if (zflag)
+ memset(&zerostat, 0, len);
+ if (sysctlbyname("net.inet.sctp.stats", &sctpstat, &len,
+ zflag ? &zerostat : NULL, zflag ? len : 0) < 0) {
+ warn("sysctl: net.inet.sctp.stats");
+ return;
+ }
+ } else
+ kread(off, &sctpstat, len);
+
+ printf ("%s:\n", name);
+
+#define p(f, m) if (sctpstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)sctpstat.f, plural(sctpstat.f))
+#define p1a(f, m) if (sctpstat.f || sflag <= 1) \
+ printf(m, (uintmax_t)sctpstat.f)
+
+ /*
+ * input statistics
+ */
+ p(sctps_recvpackets, "\t%ju input packet%s\n");
+ p(sctps_recvdatagrams, "\t\t%ju datagram%s\n");
+ p(sctps_recvpktwithdata, "\t\t%ju packet%s that had data\n");
+ p(sctps_recvsacks, "\t\t%ju input SACK chunk%s\n");
+ p(sctps_recvdata, "\t\t%ju input DATA chunk%s\n");
+ p(sctps_recvdupdata, "\t\t%ju duplicate DATA chunk%s\n");
+ p(sctps_recvheartbeat, "\t\t%ju input HB chunk%s\n");
+ p(sctps_recvheartbeatack, "\t\t%ju HB-ACK chunk%s\n");
+ p(sctps_recvecne, "\t\t%ju input ECNE chunk%s\n");
+ p(sctps_recvauth, "\t\t%ju input AUTH chunk%s\n");
+ p(sctps_recvauthmissing, "\t\t%ju chunk%s missing AUTH\n");
+ p(sctps_recvivalhmacid, "\t\t%ju invalid HMAC id%s received\n");
+ p(sctps_recvivalkeyid, "\t\t%ju invalid secret id%s received\n");
+ p1a(sctps_recvauthfailed, "\t\t%ju auth failed\n");
+ p1a(sctps_recvexpress, "\t\t%ju fast path receives all one chunk\n");
+ p1a(sctps_recvexpressm, "\t\t%ju fast path multi-part data\n");
+
+ /*
+ * output statistics
+ */
+ p(sctps_sendpackets, "\t%ju output packet%s\n");
+ p(sctps_sendsacks, "\t\t%ju output SACK%s\n");
+ p(sctps_senddata, "\t\t%ju output DATA chunk%s\n");
+ p(sctps_sendretransdata, "\t\t%ju retransmitted DATA chunk%s\n");
+ p(sctps_sendfastretrans, "\t\t%ju fast retransmitted DATA chunk%s\n");
+ p(sctps_sendmultfastretrans, "\t\t%ju FR'%s that happened more "
+ "than once to same chunk\n");
+ p(sctps_sendheartbeat, "\t\t%ju intput HB chunk%s\n");
+ p(sctps_sendecne, "\t\t%ju output ECNE chunk%s\n");
+ p(sctps_sendauth, "\t\t%ju output AUTH chunk%s\n");
+ p1a(sctps_senderrors, "\t\t%ju ip_output error counter\n");
+
+ /*
+ * PCKDROPREP statistics
+ */
+ printf("\tPacket drop statistics:\n");
+ p1a(sctps_pdrpfmbox, "\t\t%ju from middle box\n");
+ p1a(sctps_pdrpfehos, "\t\t%ju from end host\n");
+ p1a(sctps_pdrpmbda, "\t\t%ju with data\n");
+ p1a(sctps_pdrpmbct, "\t\t%ju non-data, non-endhost\n");
+ p1a(sctps_pdrpbwrpt, "\t\t%ju non-endhost, bandwidth rep only\n");
+ p1a(sctps_pdrpcrupt, "\t\t%ju not enough for chunk header\n");
+ p1a(sctps_pdrpnedat, "\t\t%ju not enough data to confirm\n");
+ p1a(sctps_pdrppdbrk, "\t\t%ju where process_chunk_drop said break\n");
+ p1a(sctps_pdrptsnnf, "\t\t%ju failed to find TSN\n");
+ p1a(sctps_pdrpdnfnd, "\t\t%ju attempt reverse TSN lookup\n");
+ p1a(sctps_pdrpdiwnp, "\t\t%ju e-host confirms zero-rwnd\n");
+ p1a(sctps_pdrpdizrw, "\t\t%ju midbox confirms no space\n");
+ p1a(sctps_pdrpbadd, "\t\t%ju data did not match TSN\n");
+ p(sctps_pdrpmark, "\t\t%ju TSN'%s marked for Fast Retran\n");
+
+ /*
+ * Timeouts
+ */
+ printf("\tTimeouts:\n");
+ p(sctps_timoiterator, "\t\t%ju iterator timer%s fired\n");
+ p(sctps_timodata, "\t\t%ju T3 data time out%s\n");
+ p(sctps_timowindowprobe, "\t\t%ju window probe (T3) timer%s fired\n");
+ p(sctps_timoinit, "\t\t%ju INIT timer%s fired\n");
+ p(sctps_timosack, "\t\t%ju sack timer%s fired\n");
+ p(sctps_timoshutdown, "\t\t%ju shutdown timer%s fired\n");
+ p(sctps_timoheartbeat, "\t\t%ju heartbeat timer%s fired\n");
+ p1a(sctps_timocookie, "\t\t%ju a cookie timeout fired\n");
+ p1a(sctps_timosecret, "\t\t%ju an endpoint changed its cookie"
+ "secret\n");
+ p(sctps_timopathmtu, "\t\t%ju PMTU timer%s fired\n");
+ p(sctps_timoshutdownack, "\t\t%ju shutdown ack timer%s fired\n");
+ p(sctps_timoshutdownguard, "\t\t%ju shutdown guard timer%s fired\n");
+ p(sctps_timostrmrst, "\t\t%ju stream reset timer%s fired\n");
+ p(sctps_timoearlyfr, "\t\t%ju early FR timer%s fired\n");
+ p1a(sctps_timoasconf, "\t\t%ju an asconf timer fired\n");
+ p1a(sctps_timoautoclose, "\t\t%ju auto close timer fired\n");
+ p(sctps_timoassockill, "\t\t%ju asoc free timer%s expired\n");
+ p(sctps_timoinpkill, "\t\t%ju inp free timer%s expired\n");
+
+#if 0
+ /*
+ * Early fast retransmission counters
+ */
+ p(sctps_earlyfrstart, "\t%ju TODO:sctps_earlyfrstart\n");
+ p(sctps_earlyfrstop, "\t%ju TODO:sctps_earlyfrstop\n");
+ p(sctps_earlyfrmrkretrans, "\t%ju TODO:sctps_earlyfrmrkretrans\n");
+ p(sctps_earlyfrstpout, "\t%ju TODO:sctps_earlyfrstpout\n");
+ p(sctps_earlyfrstpidsck1, "\t%ju TODO:sctps_earlyfrstpidsck1\n");
+ p(sctps_earlyfrstpidsck2, "\t%ju TODO:sctps_earlyfrstpidsck2\n");
+ p(sctps_earlyfrstpidsck3, "\t%ju TODO:sctps_earlyfrstpidsck3\n");
+ p(sctps_earlyfrstpidsck4, "\t%ju TODO:sctps_earlyfrstpidsck4\n");
+ p(sctps_earlyfrstrid, "\t%ju TODO:sctps_earlyfrstrid\n");
+ p(sctps_earlyfrstrout, "\t%ju TODO:sctps_earlyfrstrout\n");
+ p(sctps_earlyfrstrtmr, "\t%ju TODO:sctps_earlyfrstrtmr\n");
+#endif
+
+ /*
+ * Others
+ */
+ p1a(sctps_hdrops, "\t%ju packet shorter than header\n");
+ p1a(sctps_badsum, "\t%ju checksum error\n");
+ p1a(sctps_noport, "\t%ju no endpoint for port\n");
+ p1a(sctps_badvtag, "\t%ju bad v-tag\n");
+ p1a(sctps_badsid, "\t%ju bad SID\n");
+ p1a(sctps_nomem, "\t%ju no memory\n");
+ p1a(sctps_fastretransinrtt, "\t%ju number of multiple FR in a RTT "
+ "window\n");
+#if 0
+ p(sctps_markedretrans, "\t%ju TODO:sctps_markedretrans\n");
+#endif
+ p1a(sctps_naglesent, "\t%ju RFC813 allowed sending\n");
+ p1a(sctps_naglequeued, "\t%ju RFC813 does not allow sending\n");
+ p1a(sctps_maxburstqueued, "\t%ju times max burst prohibited sending\n");
+ p1a(sctps_ifnomemqueued, "\t%ju look ahead tells us no memory in "
+ "interface\n");
+ p(sctps_windowprobed, "\t%ju number%s of window probes sent\n");
+ p(sctps_lowlevelerr, "\t%ju time%s an output error to clamp "
+ "down on next user send\n");
+ p(sctps_lowlevelerrusr, "\t%ju time%s sctp_senderrors were "
+ "caused from a user\n");
+ p(sctps_datadropchklmt, "\t%ju number of in data drop%s due to "
+ "chunk limit reached\n");
+ p(sctps_datadroprwnd, "\t%ju number of in data drop%s due to rwnd "
+ "limit reached\n");
+ p(sctps_ecnereducedcwnd, "\t%ju time%s a ECN reduced "
+ "the cwnd\n");
+ p1a(sctps_vtagexpress, "\t%ju used express lookup via vtag\n");
+ p1a(sctps_vtagbogus, "\t%ju collision in express lookup\n");
+ p(sctps_primary_randry, "\t%ju time%s the sender ran dry "
+ "of user data on primary\n");
+ p1a(sctps_cmt_randry, "\t%ju same for above\n");
+ p(sctps_slowpath_sack, "\t%ju sack%s the slow way\n");
+ p(sctps_wu_sacks_sent, "\t%ju window update only sack%s sent\n");
+ p(sctps_sends_with_flags, "\t%ju send%s with sinfo_flags !=0\n");
+ p(sctps_sends_with_unord, "\t%ju unordered send%s\n");
+ p(sctps_sends_with_eof, "\t%ju send%s with EOF flag set\n");
+ p(sctps_sends_with_abort, "\t%ju send%s with ABORT flag set\n");
+ p(sctps_protocol_drain_calls, "\t%ju time%s protocol drain called\n");
+ p(sctps_protocol_drains_done, "\t%ju time%s we did a protocol "
+ "drain\n");
+ p(sctps_read_peeks, "\t%ju time%s recv was called with peek\n");
+ p(sctps_cached_chk, "\t%ju cached chunk%s used\n");
+ p1a(sctps_cached_strmoq, "\t%ju cached stream oq's used\n");
+ p(sctps_left_abandon, "\t%ju unread message%s abandonded by close\n");
+ p1a(sctps_send_burst_avoid, "\t%ju send burst avoidance, already "
+ "max burst inflight to net\n");
+ p1a(sctps_send_cwnd_avoid, "\t%ju send cwnd full avoidance, already "
+ "max burst inflight to net\n");
+ p(sctps_fwdtsn_map_over, "\t%ju number of map array over-run%s via "
+ "fwd-tsn's\n");
+
+#undef p
+#undef p1a
+}
+
+#endif /* SCTP */
diff --git a/freebsd/usr.bin/netstat/unix.c b/freebsd/usr.bin/netstat/unix.c
new file mode 100644
index 00000000..15bea05c
--- /dev/null
+++ b/freebsd/usr.bin/netstat/unix.c
@@ -0,0 +1,302 @@
+/*-
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)unix.c 8.1 (Berkeley) 6/6/93";
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Display protocol blocks in the unix domain.
+ */
+#include <sys/param.h>
+#include <sys/queue.h>
+#ifdef __rtems__
+#include <freebsd/sys/protosw.h>
+#else
+#include <sys/protosw.h>
+#endif
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#ifdef __rtems__
+#include <freebsd/sys/mbuf.h>
+#else
+#include <sys/mbuf.h>
+#endif
+#include <sys/sysctl.h>
+#include <sys/un.h>
+#ifndef __rtems__
+#include <sys/unpcb.h>
+#endif
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <err.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <kvm.h>
+#include "netstat.h"
+
+static void unixdomainpr(struct xunpcb *, struct xsocket *);
+
+static const char *const socktype[] =
+ { "#0", "stream", "dgram", "raw", "rdm", "seqpacket" };
+
+static int
+pcblist_sysctl(int type, char **bufp)
+{
+ char *buf;
+ size_t len;
+ char mibvar[sizeof "net.local.seqpacket.pcblist"];
+
+ sprintf(mibvar, "net.local.%s.pcblist", socktype[type]);
+
+ len = 0;
+ if (sysctlbyname(mibvar, 0, &len, 0, 0) < 0) {
+ if (errno != ENOENT)
+ warn("sysctl: %s", mibvar);
+ return (-1);
+ }
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (-2);
+ }
+ if (sysctlbyname(mibvar, buf, &len, 0, 0) < 0) {
+ warn("sysctl: %s", mibvar);
+ free(buf);
+ return (-2);
+ }
+ *bufp = buf;
+ return (0);
+}
+
+#ifndef __rtems__
+static int
+pcblist_kvm(u_long count_off, u_long gencnt_off, u_long head_off, char **bufp)
+{
+ struct unp_head head;
+ struct unpcb *unp, unp_conn;
+ u_char sun_len;
+ struct socket so;
+ struct xunpgen xug;
+ struct xunpcb xu;
+ unp_gen_t unp_gencnt;
+ u_int unp_count;
+ char *buf, *p;
+ size_t len;
+
+ if (count_off == 0 || gencnt_off == 0)
+ return (-2);
+ if (head_off == 0)
+ return (-1);
+ kread(count_off, &unp_count, sizeof(unp_count));
+ len = 2 * sizeof(xug) + (unp_count + unp_count / 8) * sizeof(xu);
+ if ((buf = malloc(len)) == 0) {
+ warnx("malloc %lu bytes", (u_long)len);
+ return (-2);
+ }
+ p = buf;
+
+#define COPYOUT(obj, size) do { \
+ if (len < (size)) { \
+ warnx("buffer size exceeded"); \
+ goto fail; \
+ } \
+ bcopy((obj), p, (size)); \
+ len -= (size); \
+ p += (size); \
+} while (0)
+
+#define KREAD(off, buf, len) do { \
+ if (kread((uintptr_t)(off), (buf), (len)) != 0) \
+ goto fail; \
+} while (0)
+
+ /* Write out header. */
+ kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+ xug.xug_len = sizeof xug;
+ xug.xug_count = unp_count;
+ xug.xug_gen = unp_gencnt;
+ xug.xug_sogen = 0;
+ COPYOUT(&xug, sizeof xug);
+
+ /* Walk the PCB list. */
+ xu.xu_len = sizeof xu;
+ KREAD(head_off, &head, sizeof(head));
+ LIST_FOREACH(unp, &head, unp_link) {
+ xu.xu_unpp = unp;
+ KREAD(unp, &xu.xu_unp, sizeof (*unp));
+ unp = &xu.xu_unp;
+
+ if (unp->unp_gencnt > unp_gencnt)
+ continue;
+ if (unp->unp_addr != NULL) {
+ KREAD(unp->unp_addr, &sun_len, sizeof(sun_len));
+ KREAD(unp->unp_addr, &xu.xu_addr, sun_len);
+ }
+ if (unp->unp_conn != NULL) {
+ KREAD(unp->unp_conn, &unp_conn, sizeof(unp_conn));
+ if (unp_conn.unp_addr != NULL) {
+ KREAD(unp_conn.unp_addr, &sun_len,
+ sizeof(sun_len));
+ KREAD(unp_conn.unp_addr, &xu.xu_caddr, sun_len);
+ }
+ }
+ KREAD(unp->unp_socket, &so, sizeof(so));
+ if (sotoxsocket(&so, &xu.xu_socket) != 0)
+ goto fail;
+ COPYOUT(&xu, sizeof(xu));
+ }
+
+ /* Reread the counts and write the footer. */
+ kread(count_off, &unp_count, sizeof(unp_count));
+ kread(gencnt_off, &unp_gencnt, sizeof(unp_gencnt));
+ xug.xug_count = unp_count;
+ xug.xug_gen = unp_gencnt;
+ COPYOUT(&xug, sizeof xug);
+
+ *bufp = buf;
+ return (0);
+
+fail:
+ free(buf);
+ return (-1);
+#undef COPYOUT
+#undef KREAD
+}
+#endif
+
+#ifndef __rtems__
+void
+unixpr(u_long count_off, u_long gencnt_off, u_long dhead_off, u_long shead_off)
+{
+ char *buf;
+ int ret, type;
+ struct xsocket *so;
+ struct xunpgen *xug, *oxug;
+ struct xunpcb *xunp;
+
+ for (type = SOCK_STREAM; type <= SOCK_SEQPACKET; type++) {
+ if (live)
+ ret = pcblist_sysctl(type, &buf);
+ else
+ ret = pcblist_kvm(count_off, gencnt_off,
+ type == SOCK_STREAM ? shead_off :
+ (type == SOCK_DGRAM ? dhead_off : 0), &buf);
+ if (ret == -1)
+ continue;
+ if (ret < 0)
+ return;
+
+ oxug = xug = (struct xunpgen *)buf;
+ for (xug = (struct xunpgen *)((char *)xug + xug->xug_len);
+ xug->xug_len > sizeof(struct xunpgen);
+ xug = (struct xunpgen *)((char *)xug + xug->xug_len)) {
+ xunp = (struct xunpcb *)xug;
+ so = &xunp->xu_socket;
+
+ /* Ignore PCBs which were freed during copyout. */
+ if (xunp->xu_unp.unp_gencnt > oxug->xug_gen)
+ continue;
+ unixdomainpr(xunp, so);
+ }
+ if (xug != oxug && xug->xug_gen != oxug->xug_gen) {
+ if (oxug->xug_count > xug->xug_count) {
+ printf("Some %s sockets may have been deleted.\n",
+ socktype[type]);
+ } else if (oxug->xug_count < xug->xug_count) {
+ printf("Some %s sockets may have been created.\n",
+ socktype[type]);
+ } else {
+ printf("Some %s sockets may have been created or deleted",
+ socktype[type]);
+ }
+ }
+ free(buf);
+ }
+}
+#endif
+
+#ifndef __rtems__
+static void
+unixdomainpr(struct xunpcb *xunp, struct xsocket *so)
+{
+ struct unpcb *unp;
+ struct sockaddr_un *sa;
+ static int first = 1;
+ char buf1[15];
+
+ unp = &xunp->xu_unp;
+ if (unp->unp_addr)
+ sa = &xunp->xu_addr;
+ else
+ sa = (struct sockaddr_un *)0;
+
+ if (first && !Lflag) {
+ printf("Active UNIX domain sockets\n");
+ printf(
+"%-8.8s %-6.6s %-6.6s %-6.6s %8.8s %8.8s %8.8s %8.8s Addr\n",
+ "Address", "Type", "Recv-Q", "Send-Q",
+ "Inode", "Conn", "Refs", "Nextref");
+ first = 0;
+ }
+
+ if (Lflag && so->so_qlimit == 0)
+ return;
+
+ if (Lflag) {
+ snprintf(buf1, 15, "%d/%d/%d", so->so_qlen,
+ so->so_incqlen, so->so_qlimit);
+ printf("unix %-14.14s", buf1);
+ } else {
+ printf("%8lx %-6.6s %6u %6u %8lx %8lx %8lx %8lx",
+ (long)so->so_pcb, socktype[so->so_type], so->so_rcv.sb_cc,
+ so->so_snd.sb_cc, (long)unp->unp_vnode, (long)unp->unp_conn,
+ (long)LIST_FIRST(&unp->unp_refs),
+ (long)LIST_NEXT(unp, unp_reflink));
+ }
+ if (sa)
+ printf(" %.*s",
+ (int)(sa->sun_len - offsetof(struct sockaddr_un, sun_path)),
+ sa->sun_path);
+ putchar('\n');
+}
+#endif
diff --git a/freebsd/vm/pmap.h b/freebsd/vm/pmap.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/vm/pmap.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/vm/vm_map.h b/freebsd/vm/vm_map.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/vm/vm_map.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */
diff --git a/freebsd/vm/vm_param.h b/freebsd/vm/vm_param.h
deleted file mode 100644
index 936ffd88..00000000
--- a/freebsd/vm/vm_param.h
+++ /dev/null
@@ -1 +0,0 @@
-/* EMPTY */