summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCameron Katri <me@cameronkatri.com>2021-05-10 14:55:20 -0400
committerCameron Katri <me@cameronkatri.com>2021-05-10 14:55:20 -0400
commitd88d199f23088ac1c3d7696374b0a1c1c1c18358 (patch)
tree977307e478f76c5de5ca141268cf8ce0309a09eb
parent5fd83771641d15c418f747bd343ba6738d3875f7 (diff)
downloadapple_cmds-d88d199f23088ac1c3d7696374b0a1c1c1c18358.tar.gz
apple_cmds-d88d199f23088ac1c3d7696374b0a1c1c1c18358.tar.zst
apple_cmds-d88d199f23088ac1c3d7696374b0a1c1c1c18358.zip
libpcap-98.40.1
-rw-r--r--lib/libpcap/Makefile51
-rw-r--r--lib/libpcap/README3
-rw-r--r--lib/libpcap/gen_libpcap_version/print_libpcap_version.c16
-rw-r--r--lib/libpcap/libpcap.plist22
-rw-r--r--lib/libpcap/libpcap.xcodeproj/project.pbxproj2943
-rw-r--r--lib/libpcap/libpcap/CHANGES988
-rw-r--r--lib/libpcap/libpcap/CMakeLists.txt2371
-rw-r--r--lib/libpcap/libpcap/CONTRIBUTING.md29
-rw-r--r--lib/libpcap/libpcap/CREDITS186
-rwxr-xr-xlib/libpcap/libpcap/ChmodBPF/ChmodBPF33
-rw-r--r--lib/libpcap/libpcap/ChmodBPF/StartupParameters.plist4
-rw-r--r--lib/libpcap/libpcap/GenVersion.bat23
-rw-r--r--lib/libpcap/libpcap/INSTALL.md352
-rw-r--r--lib/libpcap/libpcap/LICENSE19
-rw-r--r--lib/libpcap/libpcap/Makefile774
-rw-r--r--lib/libpcap/libpcap/Makefile-devel-adds22
-rw-r--r--lib/libpcap/libpcap/Makefile.in774
-rw-r--r--lib/libpcap/libpcap/README.md93
-rw-r--r--lib/libpcap/libpcap/TODO35
-rw-r--r--lib/libpcap/libpcap/VERSION1
-rw-r--r--lib/libpcap/libpcap/Win32/Prj/wpcap.sln28
-rw-r--r--lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj233
-rw-r--r--lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj.filters107
-rw-r--r--lib/libpcap/libpcap/aclocal.m41079
-rw-r--r--lib/libpcap/libpcap/arcnet.h50
-rw-r--r--lib/libpcap/libpcap/atmuni31.h85
-rw-r--r--lib/libpcap/libpcap/bpf_dump.c62
-rw-r--r--lib/libpcap/libpcap/bpf_filter.c548
-rw-r--r--lib/libpcap/libpcap/bpf_image.c332
-rwxr-xr-xlib/libpcap/libpcap/chmod_bpf19
-rw-r--r--lib/libpcap/libpcap/cmake/Modules/FindDAG.cmake32
-rw-r--r--lib/libpcap/libpcap/cmake/Modules/FindFseeko.cmake85
-rw-r--r--lib/libpcap/libpcap/cmake/Modules/FindLFS.cmake153
-rw-r--r--lib/libpcap/libpcap/cmake/Modules/FindPacket.cmake88
-rw-r--r--lib/libpcap/libpcap/cmake/Modules/FindSNF.cmake24
-rw-r--r--lib/libpcap/libpcap/cmake/Modules/FindTC.cmake24
-rw-r--r--lib/libpcap/libpcap/cmake/have_siocglifconf.c6
-rw-r--r--lib/libpcap/libpcap/cmake/preconfigure.cmake0
-rw-r--r--lib/libpcap/libpcap/cmake_uninstall.cmake.in21
-rw-r--r--lib/libpcap/libpcap/cmakeconfig.h.in381
-rwxr-xr-xlib/libpcap/libpcap/config.guess1476
-rw-r--r--lib/libpcap/libpcap/config.h387
-rw-r--r--lib/libpcap/libpcap/config.h.in386
-rw-r--r--lib/libpcap/libpcap/config.log6539
-rwxr-xr-xlib/libpcap/libpcap/config.status1136
-rwxr-xr-xlib/libpcap/libpcap/config.sub1808
-rwxr-xr-xlib/libpcap/libpcap/configure12456
-rw-r--r--lib/libpcap/libpcap/configure.ac2465
-rw-r--r--lib/libpcap/libpcap/diag-control.h219
-rw-r--r--lib/libpcap/libpcap/dlpisubs.c398
-rw-r--r--lib/libpcap/libpcap/dlpisubs.h38
-rw-r--r--lib/libpcap/libpcap/doc/DLT_ALLOCATE_HOWTO.md29
-rw-r--r--lib/libpcap/libpcap/doc/README.Win32.md3
-rw-r--r--lib/libpcap/libpcap/doc/README.aix88
-rw-r--r--lib/libpcap/libpcap/doc/README.dag122
-rw-r--r--lib/libpcap/libpcap/doc/README.hpux254
-rw-r--r--lib/libpcap/libpcap/doc/README.linux.md108
-rw-r--r--lib/libpcap/libpcap/doc/README.macos74
-rw-r--r--lib/libpcap/libpcap/doc/README.septel50
-rw-r--r--lib/libpcap/libpcap/doc/README.sita64
-rw-r--r--lib/libpcap/libpcap/doc/README.tru6449
-rw-r--r--lib/libpcap/libpcap/etherent.c168
-rw-r--r--lib/libpcap/libpcap/ethertype.h123
-rw-r--r--lib/libpcap/libpcap/extract.h225
-rw-r--r--lib/libpcap/libpcap/fad-getad.c280
-rw-r--r--lib/libpcap/libpcap/fad-gifc.c431
-rw-r--r--lib/libpcap/libpcap/fad-glifc.c346
-rw-r--r--lib/libpcap/libpcap/fmtutils.c214
-rw-r--r--lib/libpcap/libpcap/fmtutils.h55
-rw-r--r--lib/libpcap/libpcap/ftmacros.h109
-rw-r--r--lib/libpcap/libpcap/gencode.c9991
-rw-r--r--lib/libpcap/libpcap/gencode.h388
-rw-r--r--lib/libpcap/libpcap/grammar.y799
-rw-r--r--lib/libpcap/libpcap/ieee80211.h146
-rwxr-xr-xlib/libpcap/libpcap/install-sh250
-rw-r--r--lib/libpcap/libpcap/lbl/os-aix4.h23
-rw-r--r--lib/libpcap/libpcap/lbl/os-aix7.h23
-rw-r--r--lib/libpcap/libpcap/lbl/os-hpux11.h23
-rw-r--r--lib/libpcap/libpcap/lbl/os-osf4.h26
-rw-r--r--lib/libpcap/libpcap/lbl/os-osf5.h30
-rw-r--r--lib/libpcap/libpcap/lbl/os-solaris2.h24
-rw-r--r--lib/libpcap/libpcap/lbl/os-sunos4.h211
-rw-r--r--lib/libpcap/libpcap/lbl/os-ultrix4.h36
-rw-r--r--lib/libpcap/libpcap/libpcap.pc.in18
-rw-r--r--lib/libpcap/libpcap/llc.h98
-rw-r--r--lib/libpcap/libpcap/missing/asprintf.c101
-rw-r--r--lib/libpcap/libpcap/missing/getopt.c123
-rw-r--r--lib/libpcap/libpcap/missing/getopt.h7
-rw-r--r--lib/libpcap/libpcap/missing/snprintf.c631
-rw-r--r--lib/libpcap/libpcap/missing/strlcat.c61
-rw-r--r--lib/libpcap/libpcap/missing/strlcpy.c56
-rw-r--r--lib/libpcap/libpcap/missing/strtok_r.c87
-rw-r--r--lib/libpcap/libpcap/missing/win_asprintf.c51
-rw-r--r--lib/libpcap/libpcap/missing/win_snprintf.c43
-rwxr-xr-xlib/libpcap/libpcap/mkdep112
-rw-r--r--lib/libpcap/libpcap/msdos/bin2c.c43
-rw-r--r--lib/libpcap/libpcap/msdos/common.dj0
-rw-r--r--lib/libpcap/libpcap/msdos/makefile180
-rw-r--r--lib/libpcap/libpcap/msdos/makefile.dj127
-rw-r--r--lib/libpcap/libpcap/msdos/makefile.wc132
-rw-r--r--lib/libpcap/libpcap/msdos/ndis2.c0
-rw-r--r--lib/libpcap/libpcap/msdos/ndis2.h0
-rw-r--r--lib/libpcap/libpcap/msdos/ndis_0.asm0
-rw-r--r--lib/libpcap/libpcap/msdos/pkt_rx0.asm197
-rw-r--r--lib/libpcap/libpcap/msdos/pkt_rx1.s155
-rw-r--r--lib/libpcap/libpcap/msdos/pktdrvr.c1436
-rw-r--r--lib/libpcap/libpcap/msdos/pktdrvr.h153
-rw-r--r--lib/libpcap/libpcap/msdos/readme.dos166
-rw-r--r--lib/libpcap/libpcap/nametoaddr.c800
-rw-r--r--lib/libpcap/libpcap/nametoaddr.h48
-rw-r--r--lib/libpcap/libpcap/nlpid.h56
-rw-r--r--lib/libpcap/libpcap/nomkdep6
-rw-r--r--lib/libpcap/libpcap/optimize.c2664
-rw-r--r--lib/libpcap/libpcap/optimize.h28
-rw-r--r--lib/libpcap/libpcap/org.tcpdump.chmod_bpf.plist16
-rw-r--r--lib/libpcap/libpcap/pcap-bpf.c3435
-rw-r--r--lib/libpcap/libpcap/pcap-bpf.h45
-rw-r--r--lib/libpcap/libpcap/pcap-bt-linux.c423
-rw-r--r--lib/libpcap/libpcap/pcap-bt-linux.h38
-rw-r--r--lib/libpcap/libpcap/pcap-bt-monitor-linux.c273
-rw-r--r--lib/libpcap/libpcap/pcap-bt-monitor-linux.h32
-rw-r--r--lib/libpcap/libpcap/pcap-common.c1592
-rw-r--r--lib/libpcap/libpcap/pcap-common.h58
-rw-r--r--lib/libpcap/libpcap/pcap-config89
-rw-r--r--lib/libpcap/libpcap/pcap-config.172
-rw-r--r--lib/libpcap/libpcap/pcap-config.in94
-rw-r--r--lib/libpcap/libpcap/pcap-dag.c1467
-rw-r--r--lib/libpcap/libpcap/pcap-dag.h12
-rw-r--r--lib/libpcap/libpcap/pcap-darwin.c1428
-rw-r--r--lib/libpcap/libpcap/pcap-dbus.c351
-rw-r--r--lib/libpcap/libpcap/pcap-dbus.h2
-rw-r--r--lib/libpcap/libpcap/pcap-dll.rc36
-rw-r--r--lib/libpcap/libpcap/pcap-dlpi.c1909
-rw-r--r--lib/libpcap/libpcap/pcap-dos.c1536
-rw-r--r--lib/libpcap/libpcap/pcap-dos.h225
-rw-r--r--lib/libpcap/libpcap/pcap-enet.c231
-rw-r--r--lib/libpcap/libpcap/pcap-filter.manmisc1052
-rw-r--r--lib/libpcap/libpcap/pcap-filter.manmisc.in1052
-rw-r--r--lib/libpcap/libpcap/pcap-int.h599
-rw-r--r--lib/libpcap/libpcap/pcap-libdlpi.c495
-rw-r--r--lib/libpcap/libpcap/pcap-linktype.manmisc48
-rw-r--r--lib/libpcap/libpcap/pcap-linktype.manmisc.in48
-rw-r--r--lib/libpcap/libpcap/pcap-linux.c7534
-rw-r--r--lib/libpcap/libpcap/pcap-namedb.h40
-rw-r--r--lib/libpcap/libpcap/pcap-netfilter-linux.c761
-rw-r--r--lib/libpcap/libpcap/pcap-netfilter-linux.h35
-rw-r--r--lib/libpcap/libpcap/pcap-netmap.c306
-rw-r--r--lib/libpcap/libpcap/pcap-netmap.h2
-rw-r--r--lib/libpcap/libpcap/pcap-new.c465
-rw-r--r--lib/libpcap/libpcap/pcap-nit.c417
-rw-r--r--lib/libpcap/libpcap/pcap-npf.c2114
-rw-r--r--lib/libpcap/libpcap/pcap-null.c65
-rw-r--r--lib/libpcap/libpcap/pcap-pf.c683
-rw-r--r--lib/libpcap/libpcap/pcap-pktap.h55
-rw-r--r--lib/libpcap/libpcap/pcap-rdmasniff.c436
-rw-r--r--lib/libpcap/libpcap/pcap-rdmasniff.h2
-rw-r--r--lib/libpcap/libpcap/pcap-rpcap-int.h75
-rw-r--r--lib/libpcap/libpcap/pcap-rpcap.c3233
-rw-r--r--lib/libpcap/libpcap/pcap-rpcap.h49
-rw-r--r--lib/libpcap/libpcap/pcap-savefile.manfile133
-rw-r--r--lib/libpcap/libpcap/pcap-savefile.manfile.in133
-rw-r--r--lib/libpcap/libpcap/pcap-septel.c354
-rw-r--r--lib/libpcap/libpcap/pcap-septel.h13
-rw-r--r--lib/libpcap/libpcap/pcap-sita.c1087
-rw-r--r--lib/libpcap/libpcap/pcap-sita.h8
-rw-r--r--lib/libpcap/libpcap/pcap-sita.html943
-rw-r--r--lib/libpcap/libpcap/pcap-snf.c621
-rw-r--r--lib/libpcap/libpcap/pcap-snf.h2
-rw-r--r--lib/libpcap/libpcap/pcap-snit.c506
-rw-r--r--lib/libpcap/libpcap/pcap-snoop.c467
-rw-r--r--lib/libpcap/libpcap/pcap-tc.c1292
-rw-r--r--lib/libpcap/libpcap/pcap-tc.h54
-rw-r--r--lib/libpcap/libpcap/pcap-tstamp.manmisc168
-rw-r--r--lib/libpcap/libpcap/pcap-tstamp.manmisc.in168
-rw-r--r--lib/libpcap/libpcap/pcap-types.h50
-rw-r--r--lib/libpcap/libpcap/pcap-usb-linux.c1363
-rw-r--r--lib/libpcap/libpcap/pcap-usb-linux.h38
-rw-r--r--lib/libpcap/libpcap/pcap-util.c437
-rw-r--r--lib/libpcap/libpcap/pcap-util.h137
-rw-r--r--lib/libpcap/libpcap/pcap.3pcap982
-rw-r--r--lib/libpcap/libpcap/pcap.3pcap.in982
-rw-r--r--lib/libpcap/libpcap/pcap.c4134
-rw-r--r--lib/libpcap/libpcap/pcap.h43
-rw-r--r--lib/libpcap/libpcap/pcap/bluetooth.h56
-rw-r--r--lib/libpcap/libpcap/pcap/bpf.h259
-rw-r--r--lib/libpcap/libpcap/pcap/can_socketcan.h56
-rw-r--r--lib/libpcap/libpcap/pcap/compiler-tests.h163
-rw-r--r--lib/libpcap/libpcap/pcap/dlt.h1438
-rw-r--r--lib/libpcap/libpcap/pcap/funcattrs.h263
-rw-r--r--lib/libpcap/libpcap/pcap/ipnet.h43
-rw-r--r--lib/libpcap/libpcap/pcap/namedb.h83
-rw-r--r--lib/libpcap/libpcap/pcap/nflog.h94
-rw-r--r--lib/libpcap/libpcap/pcap/pcap-inttypes.h128
-rw-r--r--lib/libpcap/libpcap/pcap/pcap-ng.h563
-rw-r--r--lib/libpcap/libpcap/pcap/pcap.h995
-rw-r--r--lib/libpcap/libpcap/pcap/sll.h149
-rw-r--r--lib/libpcap/libpcap/pcap/socket.h93
-rw-r--r--lib/libpcap/libpcap/pcap/usb.h143
-rw-r--r--lib/libpcap/libpcap/pcap/vlan.h46
-rw-r--r--lib/libpcap/libpcap/pcap_activate.3pcap122
-rw-r--r--lib/libpcap/libpcap/pcap_breakloop.3pcap115
-rw-r--r--lib/libpcap/libpcap/pcap_can_set_rfmon.3pcap72
-rw-r--r--lib/libpcap/libpcap/pcap_close.3pcap39
-rw-r--r--lib/libpcap/libpcap/pcap_compile.3pcap89
-rw-r--r--lib/libpcap/libpcap/pcap_compile.3pcap.in89
-rw-r--r--lib/libpcap/libpcap/pcap_create.3pcap72
-rw-r--r--lib/libpcap/libpcap/pcap_datalink.3pcap68
-rw-r--r--lib/libpcap/libpcap/pcap_datalink.3pcap.in68
-rw-r--r--lib/libpcap/libpcap/pcap_datalink_name_to_val.3pcap49
-rw-r--r--lib/libpcap/libpcap/pcap_datalink_val_to_name.3pcap66
-rw-r--r--lib/libpcap/libpcap/pcap_dump.3pcap50
-rw-r--r--lib/libpcap/libpcap/pcap_dump_close.3pcap37
-rw-r--r--lib/libpcap/libpcap/pcap_dump_file.3pcap38
-rw-r--r--lib/libpcap/libpcap/pcap_dump_flush.3pcap45
-rw-r--r--lib/libpcap/libpcap/pcap_dump_ftell.3pcap58
-rw-r--r--lib/libpcap/libpcap/pcap_dump_open.3pcap103
-rw-r--r--lib/libpcap/libpcap/pcap_dump_open.3pcap.in103
-rw-r--r--lib/libpcap/libpcap/pcap_file.3pcap59
-rw-r--r--lib/libpcap/libpcap/pcap_fileno.3pcap65
-rw-r--r--lib/libpcap/libpcap/pcap_findalldevs.3pcap231
-rw-r--r--lib/libpcap/libpcap/pcap_freecode.3pcap43
-rw-r--r--lib/libpcap/libpcap/pcap_get_required_select_timeout.3pcap98
-rw-r--r--lib/libpcap/libpcap/pcap_get_selectable_fd.3pcap151
-rw-r--r--lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap56
-rw-r--r--lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap.in56
-rw-r--r--lib/libpcap/libpcap/pcap_geterr.3pcap51
-rw-r--r--lib/libpcap/libpcap/pcap_inject.3pcap94
-rw-r--r--lib/libpcap/libpcap/pcap_is_swapped.3pcap51
-rw-r--r--lib/libpcap/libpcap/pcap_lib_version.3pcap39
-rw-r--r--lib/libpcap/libpcap/pcap_list_datalinks.3pcap73
-rw-r--r--lib/libpcap/libpcap/pcap_list_datalinks.3pcap.in73
-rw-r--r--lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap81
-rw-r--r--lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap.in81
-rw-r--r--lib/libpcap/libpcap/pcap_lookupdev.3pcap79
-rw-r--r--lib/libpcap/libpcap/pcap_lookupnet.3pcap66
-rw-r--r--lib/libpcap/libpcap/pcap_loop.3pcap206
-rw-r--r--lib/libpcap/libpcap/pcap_major_version.3pcap54
-rw-r--r--lib/libpcap/libpcap/pcap_next_ex.3pcap144
-rw-r--r--lib/libpcap/libpcap/pcap_ng.3625
-rw-r--r--lib/libpcap/libpcap/pcap_offline_filter.3pcap55
-rw-r--r--lib/libpcap/libpcap/pcap_open_dead.3pcap78
-rw-r--r--lib/libpcap/libpcap/pcap_open_dead.3pcap.in78
-rw-r--r--lib/libpcap/libpcap/pcap_open_live.3pcap90
-rw-r--r--lib/libpcap/libpcap/pcap_open_offline.3pcap116
-rw-r--r--lib/libpcap/libpcap/pcap_open_offline.3pcap.in116
-rw-r--r--lib/libpcap/libpcap/pcap_set_buffer_size.3pcap45
-rw-r--r--lib/libpcap/libpcap/pcap_set_datalink.3pcap53
-rw-r--r--lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap95
-rw-r--r--lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap.in95
-rw-r--r--lib/libpcap/libpcap/pcap_set_promisc.3pcap46
-rw-r--r--lib/libpcap/libpcap/pcap_set_protocol_linux.3pcap68
-rw-r--r--lib/libpcap/libpcap/pcap_set_rfmon.3pcap47
-rw-r--r--lib/libpcap/libpcap/pcap_set_snaplen.3pcap44
-rw-r--r--lib/libpcap/libpcap/pcap_set_timeout.3pcap53
-rw-r--r--lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap66
-rw-r--r--lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap.in66
-rw-r--r--lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap70
-rw-r--r--lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap.in70
-rw-r--r--lib/libpcap/libpcap/pcap_setdirection.3pcap72
-rw-r--r--lib/libpcap/libpcap/pcap_setfilter.3pcap55
-rw-r--r--lib/libpcap/libpcap/pcap_setnonblock.3pcap85
-rw-r--r--lib/libpcap/libpcap/pcap_snapshot.3pcap52
-rw-r--r--lib/libpcap/libpcap/pcap_stats.3pcap100
-rw-r--r--lib/libpcap/libpcap/pcap_statustostr.3pcap41
-rw-r--r--lib/libpcap/libpcap/pcap_strerror.3pcap40
-rw-r--r--lib/libpcap/libpcap/pcap_tstamp_type_name_to_val.3pcap48
-rw-r--r--lib/libpcap/libpcap/pcap_tstamp_type_val_to_name.3pcap52
-rw-r--r--lib/libpcap/libpcap/pcapng-private.h78
-rw-r--r--lib/libpcap/libpcap/pcapng.c1405
-rw-r--r--lib/libpcap/libpcap/portability.h177
-rw-r--r--lib/libpcap/libpcap/ppp.h57
-rw-r--r--lib/libpcap/libpcap/rpcap-protocol.c195
-rw-r--r--lib/libpcap/libpcap/rpcap-protocol.h423
-rw-r--r--lib/libpcap/libpcap/rpcapd/CMakeLists.txt163
-rw-r--r--lib/libpcap/libpcap/rpcapd/Makefile141
-rw-r--r--lib/libpcap/libpcap/rpcapd/Makefile.in141
-rw-r--r--lib/libpcap/libpcap/rpcapd/config_params.h56
-rw-r--r--lib/libpcap/libpcap/rpcapd/daemon.c2747
-rw-r--r--lib/libpcap/libpcap/rpcapd/daemon.h46
-rw-r--r--lib/libpcap/libpcap/rpcapd/fileconf.c557
-rw-r--r--lib/libpcap/libpcap/rpcapd/fileconf.h39
-rw-r--r--lib/libpcap/libpcap/rpcapd/log.c260
-rw-r--r--lib/libpcap/libpcap/rpcapd/log.h34
-rw-r--r--lib/libpcap/libpcap/rpcapd/org.tcpdump.rpcapd.plist30
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile78
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile.in78
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.c1359
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.h44
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.inetd.conf1
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.manadmin233
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.manadmin.in233
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.rc39
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.socket9
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd.xinetd.conf8
-rw-r--r--lib/libpcap/libpcap/rpcapd/rpcapd@.service6
-rw-r--r--lib/libpcap/libpcap/rpcapd/win32-svc.c169
-rw-r--r--lib/libpcap/libpcap/rpcapd/win32-svc.h33
-rw-r--r--lib/libpcap/libpcap/savefile.c724
-rw-r--r--lib/libpcap/libpcap/scanner.l522
-rw-r--r--lib/libpcap/libpcap/sf-pcap.c1324
-rw-r--r--lib/libpcap/libpcap/sf-pcap.h42
-rw-r--r--lib/libpcap/libpcap/sf-pcapng.c1888
-rw-r--r--lib/libpcap/libpcap/sf-pcapng.h42
-rw-r--r--lib/libpcap/libpcap/sockutils.c1637
-rw-r--r--lib/libpcap/libpcap/sockutils.h162
-rw-r--r--lib/libpcap/libpcap/sunatmpos.h43
-rw-r--r--lib/libpcap/libpcap/testprogs/CMakeLists.txt40
-rw-r--r--lib/libpcap/libpcap/testprogs/Makefile144
-rw-r--r--lib/libpcap/libpcap/testprogs/Makefile.in144
-rw-r--r--lib/libpcap/libpcap/testprogs/can_set_rfmon_test.c96
-rw-r--r--lib/libpcap/libpcap/testprogs/capturetest.c299
-rw-r--r--lib/libpcap/libpcap/testprogs/filtertest.c359
-rw-r--r--lib/libpcap/libpcap/testprogs/findalldevstest.c311
-rw-r--r--lib/libpcap/libpcap/testprogs/opentest.c236
-rw-r--r--lib/libpcap/libpcap/testprogs/reactivatetest.c88
-rw-r--r--lib/libpcap/libpcap/testprogs/selpolltest.c443
-rw-r--r--lib/libpcap/libpcap/testprogs/threadsignaltest.c393
-rw-r--r--lib/libpcap/libpcap/testprogs/unix.h58
-rw-r--r--lib/libpcap/libpcap/testprogs/valgrindtest.c427
-rw-r--r--lib/libpcap/libpcap/tests/hex_and_ascii_print.c64
-rw-r--r--lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c700
-rw-r--r--lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.179
-rw-r--r--lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c702
-rw-r--r--lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.179
-rw-r--r--lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c710
-rw-r--r--lib/libpcap/libpcap/tests/nonblocktest.c226
-rw-r--r--lib/libpcap/libpcap/tests/offlinereadtest.c95
-rw-r--r--lib/libpcap/libpcap/tests/shb-option-too-long.pcapngbin0 -> 180 bytes
-rw-r--r--lib/libpcap/libpcap/varattrs.h59
-rw-r--r--lib/libpcap/patches/pcap-bpf.c.diff11
330 files changed, 140003 insertions, 0 deletions
diff --git a/lib/libpcap/Makefile b/lib/libpcap/Makefile
new file mode 100644
index 0000000..1f3e3f4
--- /dev/null
+++ b/lib/libpcap/Makefile
@@ -0,0 +1,51 @@
+Project = libpcap
+ProjectVersion = 1.0.0
+Patches = Makefile.in.diff configure.diff pcap-config.in.diff pcap-bpf.c.diff
+
+include $(MAKEFILEPATH)/CoreOS/ReleaseControl/Common.make
+
+# Extract the source.
+install_source::
+ $(RMDIR) $(SRCROOT)/$(Project) $(SRCROOT)/$(Project)-$(ProjVersion)
+ $(TAR) -C $(SRCROOT) -xf $(SRCROOT)/$(Project)-$(ProjectVersion).tar.gz
+ $(MV) $(SRCROOT)/$(Project)-$(ProjectVersion) $(SRCROOT)/$(Project)
+ @set -x && \
+ cd $(SRCROOT)/$(Project) && \
+ for file in $(Patches); do \
+ patch -p0 -F0 -i $(SRCROOT)/patches/$$file; \
+ done
+
+install_headers::
+ $(INSTALL_DIRECTORY) $(DSTROOT)/usr/include/pcap
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap-bpf.h $(DSTROOT)/usr/include
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap-namedb.h $(DSTROOT)/usr/include
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap.h $(DSTROOT)/usr/include
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap/bpf.h $(DSTROOT)/usr/include/pcap
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap/namedb.h $(DSTROOT)/usr/include/pcap
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap/pcap.h $(DSTROOT)/usr/include/pcap
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap/sll.h $(DSTROOT)/usr/include/pcap
+ $(INSTALL_FILE) $(SRCROOT)/$(Project)/pcap/usb.h $(DSTROOT)/usr/include/pcap
+
+OSV = $(DSTROOT)/usr/local/OpenSourceVersions
+OSL = $(DSTROOT)/usr/local/OpenSourceLicenses
+
+install::
+ cd $(OBJROOT) && CFLAGS="$(CFLAGS)" $(SRCROOT)/$(Project)/configure --prefix=/usr --enable-ipv6
+
+ $(MAKE) -C $(OBJROOT)
+ $(CC) $(LDFLAGS) -dynamiclib -compatibility_version 1 -current_version 1 -all_load -install_name /usr/lib/libpcap.A.dylib -o $(OBJROOT)/libpcap.A.dylib $(OBJROOT)/libpcap.a
+
+ $(MAKE) -C $(OBJROOT) install DESTDIR=$(DSTROOT)
+ $(INSTALL_DYLIB) $(OBJROOT)/libpcap.A.dylib $(DSTROOT)/usr/lib
+ $(LN) -s libpcap.A.dylib $(DSTROOT)/usr/lib/libpcap.dylib
+
+ $(RM) $(DSTROOT)/usr/lib/libpcap.a
+
+ $(CP) $(DSTROOT)/usr/lib/libpcap.A.dylib $(SYMROOT)
+ $(STRIP) -S $(DSTROOT)/usr/lib/libpcap.A.dylib
+
+ $(MKDIR) $(OSV) $(OSL)
+ $(INSTALL_FILE) $(SRCROOT)/$(ProjectName).plist $(OSV)/$(ProjectName).plist
+ $(INSTALL_FILE) $(SRCROOT)/$(ProjectName)/LICENSE $(OSL)/$(ProjectName).txt
+
+ @$(MAKE) compress_man_pages
diff --git a/lib/libpcap/README b/lib/libpcap/README
new file mode 100644
index 0000000..07fbfc3
--- /dev/null
+++ b/lib/libpcap/README
@@ -0,0 +1,3 @@
+The libpcap sources have been configured with the following flags:
+--prefix=/usr
+--enable-ipv6
diff --git a/lib/libpcap/gen_libpcap_version/print_libpcap_version.c b/lib/libpcap/gen_libpcap_version/print_libpcap_version.c
new file mode 100644
index 0000000..e6cbc40
--- /dev/null
+++ b/lib/libpcap/gen_libpcap_version/print_libpcap_version.c
@@ -0,0 +1,16 @@
+//
+// gen_libpcap_version.c
+//
+// Created by Vincent Lubet on 2/2/17.
+//
+//
+
+#include <stdio.h>
+
+#include "pcap_version.h"
+
+int main(int argc, const char * argv[]) {
+ // insert code here...
+ printf("%s\n", pcap_version_string);
+ return 0;
+}
diff --git a/lib/libpcap/libpcap.plist b/lib/libpcap/libpcap.plist
new file mode 100644
index 0000000..5f1b96c
--- /dev/null
+++ b/lib/libpcap/libpcap.plist
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>OpenSourceImportDate</key>
+ <string>2017-02-01</string>
+ <key>OpenSourceLicense</key>
+ <string>BSD</string>
+ <key>OpenSourceLicenseFile</key>
+ <string>LICENSE</string>
+ <key>OpenSourceProject</key>
+ <string>libpcap</string>
+ <key>OpenSourceSHA1</key>
+ <string>32d7526dde8f8a2f75baf40c01670602aeef7e39</string>
+ <key>OpenSourceURL</key>
+ <string>http://www.tcpdump.org/release/libpcap-1.8.1.tar.gz</string>
+ <key>OpenSourceVersion</key>
+ <string>1.8.1</string>
+ <key>OpenSourceWebsiteURL</key>
+ <string>http://www.tcpdump.org/</string>
+</dict>
+</plist>
diff --git a/lib/libpcap/libpcap.xcodeproj/project.pbxproj b/lib/libpcap/libpcap.xcodeproj/project.pbxproj
new file mode 100644
index 0000000..c19fffa
--- /dev/null
+++ b/lib/libpcap/libpcap.xcodeproj/project.pbxproj
@@ -0,0 +1,2943 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 46;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 72441EE415D323A7007A9F70 /* tests */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 72441EE515D323A7007A9F70 /* Build configuration list for PBXAggregateTarget "tests" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 72E2E252162743E8004E347B /* PBXTargetDependency */,
+ 725D5845234532D90023A8CB /* PBXTargetDependency */,
+ 72B903741CE00F24008DB2D2 /* PBXTargetDependency */,
+ 724B3DB815D3277800DAC815 /* PBXTargetDependency */,
+ 724B3DBA15D3277800DAC815 /* PBXTargetDependency */,
+ 72C5298D2025453A005DB7E4 /* PBXTargetDependency */,
+ 727B12FD1628C6240039A877 /* PBXTargetDependency */,
+ 72E2E250162743E8004E347B /* PBXTargetDependency */,
+ 72C5298F2025453A005DB7E4 /* PBXTargetDependency */,
+ 724B3DBE15D3277800DAC815 /* PBXTargetDependency */,
+ 724B3DC015D3277800DAC815 /* PBXTargetDependency */,
+ 724B3DC215D3277800DAC815 /* PBXTargetDependency */,
+ 725D5847234533020023A8CB /* PBXTargetDependency */,
+ 725D5849234533020023A8CB /* PBXTargetDependency */,
+ );
+ name = tests;
+ productName = tests;
+ };
+ 727B12E61627AF810039A877 /* all */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 727B12E71627AF810039A877 /* Build configuration list for PBXAggregateTarget "all" */;
+ buildPhases = (
+ );
+ dependencies = (
+ 727B12EB1627AF8F0039A877 /* PBXTargetDependency */,
+ 727B12ED1627AF8F0039A877 /* PBXTargetDependency */,
+ );
+ name = all;
+ productName = all;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+
+
+ 72011B262356B3C6003A5F22 /* unix.h in Headers */ = {isa = PBXBuildFile; fileRef = 725D580523452FBD0023A8CB /* unix.h */; };
+ 7208CF912403399200AA0E42 /* pcapng-private.h in Headers */ = {isa = PBXBuildFile; fileRef = 7208CF902403399200AA0E42 /* pcapng-private.h */; };
+ 720914CC234562EE003B403A /* fmtutils.c in Sources */ = {isa = PBXBuildFile; fileRef = 721769222344379500731290 /* fmtutils.c */; };
+ 721463AC1F6898C200D74814 /* hex_and_ascii_print.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D13B1B16BDF7D2009B01B1 /* hex_and_ascii_print.c */; };
+ 721463AE1F6898CF00D74814 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 7217691D23442F2500731290 /* sf-pcapng.h in Headers */ = {isa = PBXBuildFile; fileRef = 7217691C23442F2500731290 /* sf-pcapng.h */; };
+ 7217691F23442F5A00731290 /* sf-pcapng.c in Sources */ = {isa = PBXBuildFile; fileRef = 7217691E23442F5A00731290 /* sf-pcapng.c */; };
+ 721769212344333200731290 /* bpf_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 721769202344333200731290 /* bpf_filter.c */; };
+ 721769262344379500731290 /* ftmacros.h in Headers */ = {isa = PBXBuildFile; fileRef = 721769232344379500731290 /* ftmacros.h */; };
+ 721769272344379500731290 /* fmtutils.h in Headers */ = {isa = PBXBuildFile; fileRef = 721769242344379500731290 /* fmtutils.h */; };
+ 7244CBE11624FC8C00141ECF /* bpf_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3589103676CF00CC3DD8 /* bpf_dump.c */; };
+ 7244CBE41624FCC600141ECF /* sf-pcap.c in Sources */ = {isa = PBXBuildFile; fileRef = 724FC91C1233226B003B8C19 /* sf-pcap.c */; };
+ 7244CBE51624FCC600141ECF /* pcap-common.c in Sources */ = {isa = PBXBuildFile; fileRef = 724FC91512331FCE003B8C19 /* pcap-common.c */; };
+ 7244CBE61624FCC600141ECF /* bpf_image.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358B103676CF00CC3DD8 /* bpf_image.c */; };
+ 7244CBE71624FCC600141ECF /* etherent.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358C103676CF00CC3DD8 /* etherent.c */; };
+ 7244CBE81624FCC600141ECF /* fad-getad.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358D103676CF00CC3DD8 /* fad-getad.c */; };
+ 7244CBEB1624FCC600141ECF /* nametoaddr.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3591103676CF00CC3DD8 /* nametoaddr.c */; };
+ 7244CBEC1624FCC600141ECF /* optimize.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3592103676CF00CC3DD8 /* optimize.c */; };
+ 7244CBED1624FCC600141ECF /* pcap-bpf.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3593103676CF00CC3DD8 /* pcap-bpf.c */; };
+ 7244CBEE1624FCC600141ECF /* pcap.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3594103676CF00CC3DD8 /* pcap.c */; };
+ 7244CBEF1624FCC600141ECF /* savefile.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3595103676CF00CC3DD8 /* savefile.c */; };
+ 7244CBF01624FCC600141ECF /* scanner.l in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3596103676CF00CC3DD8 /* scanner.l */; };
+ 724FC91612331FCE003B8C19 /* pcap-common.c in Sources */ = {isa = PBXBuildFile; fileRef = 724FC91512331FCE003B8C19 /* pcap-common.c */; };
+ 724FC91812331FDD003B8C19 /* pcap-common.h in Headers */ = {isa = PBXBuildFile; fileRef = 724FC91712331FDD003B8C19 /* pcap-common.h */; };
+ 724FC91D1233226B003B8C19 /* sf-pcap.c in Sources */ = {isa = PBXBuildFile; fileRef = 724FC91C1233226B003B8C19 /* sf-pcap.c */; };
+ 724FC92312332337003B8C19 /* sf-pcap.h in Headers */ = {isa = PBXBuildFile; fileRef = 724FC92212332337003B8C19 /* sf-pcap.h */; };
+ 724FC92512332462003B8C19 /* pcap-int.h in Headers */ = {isa = PBXBuildFile; fileRef = 724FC92412332462003B8C19 /* pcap-int.h */; };
+
+ 725D57F9234523E60023A8CB /* bpf_filter.c in Sources */ = {isa = PBXBuildFile; fileRef = 721769202344333200731290 /* bpf_filter.c */; };
+ 725D57FA234523E60023A8CB /* fmtutils.c in Sources */ = {isa = PBXBuildFile; fileRef = 721769222344379500731290 /* fmtutils.c */; };
+ 725D57FB234523E60023A8CB /* sf-pcapng.c in Sources */ = {isa = PBXBuildFile; fileRef = 7217691E23442F5A00731290 /* sf-pcapng.c */; };
+ 725D58202345301B0023A8CB /* can_set_rfmon_test.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580723452FBD0023A8CB /* can_set_rfmon_test.c */; };
+ 725D5821234530230023A8CB /* capturetest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580423452FBD0023A8CB /* capturetest.c */; };
+ 725D58222345302B0023A8CB /* filtertest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580823452FBD0023A8CB /* filtertest.c */; };
+ 725D5823234530330023A8CB /* findalldevstest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580923452FBD0023A8CB /* findalldevstest.c */; };
+ 725D5824234531580023A8CB /* opentest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580A23452FBD0023A8CB /* opentest.c */; };
+ 725D5825234531600023A8CB /* reactivatetest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580323452FBD0023A8CB /* reactivatetest.c */; };
+ 725D5826234531690023A8CB /* selpolltest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580623452FBD0023A8CB /* selpolltest.c */; };
+ 725D58412345320F0023A8CB /* threadsignaltest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580123452FBD0023A8CB /* threadsignaltest.c */; };
+ 725D5842234532160023A8CB /* valgrindtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D580223452FBD0023A8CB /* valgrindtest.c */; };
+ 725D5843234532260023A8CB /* offlinereadtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 725D5833234531D10023A8CB /* offlinereadtest.c */; };
+ 725D584A2345336C0023A8CB /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 725D584B2345348B0023A8CB /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 725D584C2345349B0023A8CB /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72717798234C0C8E000D8DF1 /* funcattrs.h in Headers */ = {isa = PBXBuildFile; fileRef = 72717797234C0C8E000D8DF1 /* funcattrs.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 7271779A234C0CBD000D8DF1 /* pcap-inttypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 72717799234C0CBC000D8DF1 /* pcap-inttypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 7271779C234C110E000D8DF1 /* compiler-tests.h in Headers */ = {isa = PBXBuildFile; fileRef = 7271779B234C110D000D8DF1 /* compiler-tests.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 7271779E234C11C0000D8DF1 /* socket.h in Headers */ = {isa = PBXBuildFile; fileRef = 7271779D234C11C0000D8DF1 /* socket.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 727A86A916CEECB700048C5E /* pcap-util.c in Sources */ = {isa = PBXBuildFile; fileRef = 727A86A816CEECB700048C5E /* pcap-util.c */; };
+ 727A86AA16CEECB700048C5E /* pcap-util.c in Sources */ = {isa = PBXBuildFile; fileRef = 727A86A816CEECB700048C5E /* pcap-util.c */; };
+ 727A86AC16CEF6D700048C5E /* pcap-util.h in Headers */ = {isa = PBXBuildFile; fileRef = 727A86AB16CEECD100048C5E /* pcap-util.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 727B12D9162745460039A877 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 727B12E116278ACD0039A877 /* pcap-ng.h in Headers */ = {isa = PBXBuildFile; fileRef = 727B12DF16278ACD0039A877 /* pcap-ng.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 727B12E416278AEF0039A877 /* pcapng.c in Sources */ = {isa = PBXBuildFile; fileRef = 727B12E316278AEF0039A877 /* pcapng.c */; };
+ 727B12E51627A9080039A877 /* pcapng.c in Sources */ = {isa = PBXBuildFile; fileRef = 727B12E316278AEF0039A877 /* pcapng.c */; };
+ 727B12FB1628C06F0039A877 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 729DE1E416CB05F700195247 /* pcap-darwin.c in Sources */ = {isa = PBXBuildFile; fileRef = 729DE1E316CB05F700195247 /* pcap-darwin.c */; };
+ 729DE1E516CB05F700195247 /* pcap-darwin.c in Sources */ = {isa = PBXBuildFile; fileRef = 729DE1E316CB05F700195247 /* pcap-darwin.c */; };
+ 72B903661CE00DB2008DB2D2 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72B903691CE00EA9008DB2D2 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72B9036A1CE00EBF008DB2D2 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72B9036E1CE00EED008DB2D2 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72B903701CE00EFB008DB2D2 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72B903721CE00F07008DB2D2 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72B903761CE0145A008DB2D2 /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B903751CE0145A008DB2D2 /* config.h */; };
+ 72B903781CE01476008DB2D2 /* gencode.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B903771CE01476008DB2D2 /* gencode.h */; };
+ 72B9037A1CE014B0008DB2D2 /* arcnet.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B903791CE014B0008DB2D2 /* arcnet.h */; };
+ 72B9037C1CE014C9008DB2D2 /* atmuni31.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B9037B1CE014C9008DB2D2 /* atmuni31.h */; };
+ 72B9037E1CE014FC008DB2D2 /* ethertype.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B9037D1CE014FC008DB2D2 /* ethertype.h */; };
+ 72B903801CE01511008DB2D2 /* ieee80211.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B9037F1CE01511008DB2D2 /* ieee80211.h */; };
+ 72B903821CE01527008DB2D2 /* llc.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B903811CE01527008DB2D2 /* llc.h */; };
+ 72B903841CE01544008DB2D2 /* nlpid.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B903831CE01544008DB2D2 /* nlpid.h */; };
+ 72B903861CE015A0008DB2D2 /* ppp.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B903851CE015A0008DB2D2 /* ppp.h */; };
+ 72B903881CE015BB008DB2D2 /* sunatmpos.h in Headers */ = {isa = PBXBuildFile; fileRef = 72B903871CE015BB008DB2D2 /* sunatmpos.h */; };
+ 72C5299820254567005DB7E4 /* libpcap_static.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7244CBDD1624FBE400141ECF /* libpcap_static.a */; };
+ 72C529A5202545A4005DB7E4 /* ngdumppktap.c in Sources */ = {isa = PBXBuildFile; fileRef = 72C5298A2025441A005DB7E4 /* ngdumppktap.c */; };
+ 72D13B3916BDF98B009B01B1 /* hex_and_ascii_print.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D13B1B16BDF7D2009B01B1 /* hex_and_ascii_print.c */; };
+ 72D13B3A16BDF98B009B01B1 /* ngdumptest.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D13B1E16BDF7D2009B01B1 /* ngdumptest.c */; };
+ 72D13B3B16BDF994009B01B1 /* hex_and_ascii_print.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D13B1B16BDF7D2009B01B1 /* hex_and_ascii_print.c */; };
+ 72D13B3C16BDF994009B01B1 /* ngofflinereadtest.c in Sources */ = {isa = PBXBuildFile; fileRef = 72D13B2116BDF7D2009B01B1 /* ngofflinereadtest.c */; };
+ 72E2AB531E43F0B900AEFE80 /* gencode.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358E103676CF00CC3DD8 /* gencode.c */; };
+ 72E2AB561E44085E00AEFE80 /* print_libpcap_version.c in Sources */ = {isa = PBXBuildFile; fileRef = 72E2AB541E44085E00AEFE80 /* print_libpcap_version.c */; };
+ 72E2AB581E45022C00AEFE80 /* pcap-pktap.h in Headers */ = {isa = PBXBuildFile; fileRef = 72E2AB571E45022C00AEFE80 /* pcap-pktap.h */; };
+ 72E2AB621E456FE600AEFE80 /* bluetooth.h in Headers */ = {isa = PBXBuildFile; fileRef = 72E2AB5C1E456FE600AEFE80 /* bluetooth.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 72E2AB631E456FE600AEFE80 /* can_socketcan.h in Headers */ = {isa = PBXBuildFile; fileRef = 72E2AB5D1E456FE600AEFE80 /* can_socketcan.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 72E2AB651E456FE600AEFE80 /* ipnet.h in Headers */ = {isa = PBXBuildFile; fileRef = 72E2AB5F1E456FE600AEFE80 /* ipnet.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 72E2AB661E456FE600AEFE80 /* nflog.h in Headers */ = {isa = PBXBuildFile; fileRef = 72E2AB601E456FE600AEFE80 /* nflog.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 72E2AB671E456FE600AEFE80 /* vlan.h in Headers */ = {isa = PBXBuildFile; fileRef = 72E2AB611E456FE600AEFE80 /* vlan.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ 72E2AB681E4570C000AEFE80 /* dlt.h in Headers */ = {isa = PBXBuildFile; fileRef = 72E2AB4B1E43E9A700AEFE80 /* dlt.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ FC293B26103695150055686E /* pcap.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE3680103681F900CC3DD8 /* pcap.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ FC293B301036978A0055686E /* pcap.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE368C1036822200CC3DD8 /* pcap.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FCDE3597103676CF00CC3DD8 /* bpf_dump.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3589103676CF00CC3DD8 /* bpf_dump.c */; };
+ FCDE3599103676CF00CC3DD8 /* bpf_image.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358B103676CF00CC3DD8 /* bpf_image.c */; };
+ FCDE359A103676CF00CC3DD8 /* etherent.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358C103676CF00CC3DD8 /* etherent.c */; };
+ FCDE359B103676CF00CC3DD8 /* fad-getad.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358D103676CF00CC3DD8 /* fad-getad.c */; };
+ FCDE359C103676CF00CC3DD8 /* gencode.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE358E103676CF00CC3DD8 /* gencode.c */; };
+ FCDE359F103676CF00CC3DD8 /* nametoaddr.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3591103676CF00CC3DD8 /* nametoaddr.c */; };
+ FCDE35A0103676CF00CC3DD8 /* optimize.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3592103676CF00CC3DD8 /* optimize.c */; };
+ FCDE35A1103676CF00CC3DD8 /* pcap-bpf.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3593103676CF00CC3DD8 /* pcap-bpf.c */; };
+ FCDE35A2103676CF00CC3DD8 /* pcap.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3594103676CF00CC3DD8 /* pcap.c */; };
+ FCDE35A3103676CF00CC3DD8 /* savefile.c in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3595103676CF00CC3DD8 /* savefile.c */; };
+ FCDE35A4103676CF00CC3DD8 /* scanner.l in Sources */ = {isa = PBXBuildFile; fileRef = FCDE3596103676CF00CC3DD8 /* scanner.l */; };
+ FCDE364E103680B800CC3DD8 /* version.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE364C103680B800CC3DD8 /* version.h */; settings = {ATTRIBUTES = (); }; };
+ FCDE3683103681F900CC3DD8 /* bpf.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE367E103681F900CC3DD8 /* bpf.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ FCDE3684103681F900CC3DD8 /* namedb.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE367F103681F900CC3DD8 /* namedb.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ FCDE3686103681F900CC3DD8 /* sll.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE3681103681F900CC3DD8 /* sll.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ FCDE3687103681F900CC3DD8 /* usb.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE3682103681F900CC3DD8 /* usb.h */; settings = {ATTRIBUTES = (Private, ); }; };
+ FCDE368D1036822200CC3DD8 /* pcap-bpf.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE368A1036822200CC3DD8 /* pcap-bpf.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ FCDE368E1036822200CC3DD8 /* pcap-namedb.h in Headers */ = {isa = PBXBuildFile; fileRef = FCDE368B1036822200CC3DD8 /* pcap-namedb.h */; settings = {ATTRIBUTES = (Public, ); }; };
+/* End PBXBuildFile section */
+
+/* Begin PBXBuildRule section */
+ 7244CBF21624FD8600141ECF /* PBXBuildRule */ = {
+ isa = PBXBuildRule;
+ compilerSpec = com.apple.compilers.proxy.script;
+ fileType = sourcecode.lex;
+ inputFiles = (
+ );
+ isEditable = 1;
+ outputFiles = (
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/grammar.h",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/scanner.h",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/grammar.c",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/scanner.c",
+ );
+ script = "xcrun bison --yacc --name-prefix=pcap_ -d \"$INPUT_FILE_DIR/grammar.y\" --output-file=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/grammar.c\" --defines=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/grammar.h\"\nxcrun flex -Ppcap_ --header-file=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/scanner.h\" --nounput -o\"$DERIVED_FILES_DIR/$CURRENT_ARCH/$INPUT_FILE_BASE.c\" \"$INPUT_FILE_PATH\"";
+ };
+ 7250331415F6E80800BDA576 /* PBXBuildRule */ = {
+ isa = PBXBuildRule;
+ compilerSpec = com.apple.compilers.proxy.script;
+ fileType = sourcecode.lex;
+ inputFiles = (
+ );
+ isEditable = 1;
+ outputFiles = (
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/tokdefs.h",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/grammar.c",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/$(INPUT_FILE_BASE).c",
+ );
+ script = "xcrun bison --yacc --name-prefix=pcap_ -d \"$INPUT_FILE_DIR/grammar.y\" --output-file=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/grammar.c\" --defines=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/tokdefs.h\"\nxcrun flex -Ppcap_ -o\"$DERIVED_FILES_DIR/$CURRENT_ARCH/$INPUT_FILE_BASE.c\" \"$INPUT_FILE_PATH\"";
+ };
+ FCDE361910367FAA00CC3DD8 /* PBXBuildRule */ = {
+ isa = PBXBuildRule;
+ compilerSpec = com.apple.compilers.proxy.script;
+ fileType = sourcecode.lex;
+ inputFiles = (
+ );
+ isEditable = 1;
+ outputFiles = (
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/grammar.h",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/scanner.h",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/grammar.c",
+ "$(DERIVED_FILES_DIR)/$(CURRENT_ARCH)/scanner.c",
+ );
+ script = "xcrun bison --yacc --name-prefix=pcap_ -d \"$INPUT_FILE_DIR/grammar.y\" --output-file=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/grammar.c\" --defines=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/grammar.h\"\nxcrun flex -Ppcap_ --header-file=\"$DERIVED_FILES_DIR/$CURRENT_ARCH/scanner.h\" --nounput -o\"$DERIVED_FILES_DIR/$CURRENT_ARCH/$INPUT_FILE_BASE.c\" \"$INPUT_FILE_PATH\"";
+ };
+/* End PBXBuildRule section */
+
+/* Begin PBXContainerItemProxy section */
+ 724B3DB715D3277800DAC815 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72441E9315D322C1007A9F70;
+ remoteInfo = filtertest;
+ };
+ 724B3DB915D3277800DAC815 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72441EA115D32317007A9F70;
+ remoteInfo = findalldevs;
+ };
+ 724B3DBD15D3277800DAC815 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72441EBB15D3233B007A9F70;
+ remoteInfo = opentest;
+ };
+ 724B3DBF15D3277800DAC815 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72441EC815D3234A007A9F70;
+ remoteInfo = reactivatetest;
+ };
+ 724B3DC115D3277800DAC815 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72441ED515D32357007A9F70;
+ remoteInfo = selpolltest;
+ };
+ 725D5844234532D90023A8CB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 725D5818234530040023A8CB;
+ remoteInfo = can_set_rfmon_test;
+ };
+ 725D5846234533020023A8CB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 725D582A234531AF0023A8CB;
+ remoteInfo = threadsignaltest;
+ };
+ 725D5848234533020023A8CB /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 725D5839234531FC0023A8CB;
+ remoteInfo = valgrindtest;
+ };
+ 727B12EA1627AF8F0039A877 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = D2AAC0620554660B00DB518D;
+ remoteInfo = libpcap;
+ };
+ 727B12EC1627AF8F0039A877 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72441EE415D323A7007A9F70;
+ remoteInfo = tests;
+ };
+ 727B12FC1628C6240039A877 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 727B12F11628BF800039A877;
+ remoteInfo = ngdumptest;
+ };
+ 72B903731CE00F24008DB2D2 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72B9035D1CE00CEC008DB2D2;
+ remoteInfo = capturetest;
+ };
+ 72C5298C2025453A005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72C52982202543F2005DB7E4;
+ remoteInfo = ngdumppkap;
+ };
+ 72C5298E2025453A005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 721463A21F68984600D74814;
+ remoteInfo = offlinereadtest;
+ };
+ 72C5299020254553005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C529922025455A005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C529942025455E005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C5299620254563005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C529992025456C005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C5299D20254579005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C5299F2025457D005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C529A120254583005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72C529A32025458F005DB7E4 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = libpcap_static;
+ };
+ 72E2AB491E43C1FE00AEFE80 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72E2AB3F1E43BD4E00AEFE80;
+ remoteInfo = make_version_files;
+ };
+ 72E2AB501E43EEDB00AEFE80 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 72E2AB3F1E43BD4E00AEFE80;
+ remoteInfo = make_version_files;
+ };
+ 72E2E24D16274394004E347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = pcap_static;
+ };
+ 72E2E24F162743E8004E347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 725032EF15F6E5BF00BDA576;
+ remoteInfo = ngofflinereadtest;
+ };
+ 72E2E251162743E8004E347B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7244CBDC1624FBE400141ECF;
+ remoteInfo = pcap_static;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 721463A11F68984600D74814 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72441E9215D322C1007A9F70 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72441EA015D32317007A9F70 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72441EBA15D3233B007A9F70 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72441EC715D3234A007A9F70 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72441ED415D32357007A9F70 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 725D5817234530040023A8CB /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 725D5829234531AF0023A8CB /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 725D5838234531FC0023A8CB /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 727B12F01628BF800039A877 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72B9035C1CE00CEC008DB2D2 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72C52981202543F2005DB7E4 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ 72E2AB3E1E43BD4E00AEFE80 /* CopyFiles */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = /usr/share/man/man1/;
+ dstSubfolderSpec = 0;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 568DEF0D14BE09EC005DEBAE /* pcap_ng.3 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_ng.3; path = libpcap/pcap_ng.3; sourceTree = "<group>"; };
+
+
+ 7208CF902403399200AA0E42 /* pcapng-private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcapng-private.h"; path = "libpcap/pcapng-private.h"; sourceTree = "<group>"; };
+ 721463A31F68984600D74814 /* offlinereadtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = offlinereadtest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7217691C23442F2500731290 /* sf-pcapng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sf-pcapng.h"; path = "libpcap/sf-pcapng.h"; sourceTree = "<group>"; };
+ 7217691E23442F5A00731290 /* sf-pcapng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "sf-pcapng.c"; path = "libpcap/sf-pcapng.c"; sourceTree = "<group>"; };
+ 721769202344333200731290 /* bpf_filter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bpf_filter.c; path = libpcap/bpf_filter.c; sourceTree = "<group>"; };
+ 721769222344379500731290 /* fmtutils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = fmtutils.c; path = libpcap/fmtutils.c; sourceTree = "<group>"; };
+ 721769232344379500731290 /* ftmacros.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ftmacros.h; path = libpcap/ftmacros.h; sourceTree = "<group>"; };
+ 721769242344379500731290 /* fmtutils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fmtutils.h; path = libpcap/fmtutils.h; sourceTree = "<group>"; };
+ 72441E9415D322C1007A9F70 /* filtertest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = filtertest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72441EA215D32317007A9F70 /* findalldevs */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = findalldevs; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72441EBC15D3233B007A9F70 /* opentest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = opentest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72441EC915D3234A007A9F70 /* reactivatetest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = reactivatetest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72441ED615D32357007A9F70 /* selpolltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = selpolltest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7244CBDD1624FBE400141ECF /* libpcap_static.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpcap_static.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 724B3DA615D3269F00DAC815 /* libpcap.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpcap.dylib; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/lib/libpcap.dylib; sourceTree = DEVELOPER_DIR; };
+ 724FC91512331FCE003B8C19 /* pcap-common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "pcap-common.c"; path = "libpcap/pcap-common.c"; sourceTree = "<group>"; };
+ 724FC91712331FDD003B8C19 /* pcap-common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcap-common.h"; path = "libpcap/pcap-common.h"; sourceTree = "<group>"; };
+ 724FC91C1233226B003B8C19 /* sf-pcap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "sf-pcap.c"; path = "libpcap/sf-pcap.c"; sourceTree = "<group>"; };
+ 724FC92212332337003B8C19 /* sf-pcap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "sf-pcap.h"; path = "libpcap/sf-pcap.h"; sourceTree = "<group>"; };
+ 724FC92412332462003B8C19 /* pcap-int.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcap-int.h"; path = "libpcap/pcap-int.h"; sourceTree = "<group>"; };
+ 725032F015F6E5BF00BDA576 /* ngofflinereadtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ngofflinereadtest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 725D580123452FBD0023A8CB /* threadsignaltest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = threadsignaltest.c; path = libpcap/testprogs/threadsignaltest.c; sourceTree = SOURCE_ROOT; };
+ 725D580223452FBD0023A8CB /* valgrindtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = valgrindtest.c; path = libpcap/testprogs/valgrindtest.c; sourceTree = SOURCE_ROOT; };
+ 725D580323452FBD0023A8CB /* reactivatetest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = reactivatetest.c; path = libpcap/testprogs/reactivatetest.c; sourceTree = SOURCE_ROOT; };
+ 725D580423452FBD0023A8CB /* capturetest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = capturetest.c; path = libpcap/testprogs/capturetest.c; sourceTree = SOURCE_ROOT; };
+ 725D580523452FBD0023A8CB /* unix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unix.h; path = libpcap/testprogs/unix.h; sourceTree = SOURCE_ROOT; };
+ 725D580623452FBD0023A8CB /* selpolltest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = selpolltest.c; path = libpcap/testprogs/selpolltest.c; sourceTree = SOURCE_ROOT; };
+ 725D580723452FBD0023A8CB /* can_set_rfmon_test.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = can_set_rfmon_test.c; path = libpcap/testprogs/can_set_rfmon_test.c; sourceTree = SOURCE_ROOT; };
+ 725D580823452FBD0023A8CB /* filtertest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = filtertest.c; path = libpcap/testprogs/filtertest.c; sourceTree = SOURCE_ROOT; };
+ 725D580923452FBD0023A8CB /* findalldevstest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = findalldevstest.c; path = libpcap/testprogs/findalldevstest.c; sourceTree = SOURCE_ROOT; };
+ 725D580A23452FBD0023A8CB /* opentest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = opentest.c; path = libpcap/testprogs/opentest.c; sourceTree = SOURCE_ROOT; };
+ 725D5819234530040023A8CB /* can_set_rfmon_test */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = can_set_rfmon_test; sourceTree = BUILT_PRODUCTS_DIR; };
+ 725D582B234531AF0023A8CB /* threadsignaltest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = threadsignaltest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 725D582D234531AF0023A8CB /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
+ 725D5832234531D10023A8CB /* nonblocktest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = nonblocktest.c; sourceTree = "<group>"; };
+ 725D5833234531D10023A8CB /* offlinereadtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = offlinereadtest.c; sourceTree = "<group>"; };
+ 725D583A234531FC0023A8CB /* valgrindtest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = valgrindtest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 725D583C234531FC0023A8CB /* main.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
+ 725D584D234535730023A8CB /* pcap_get_required_select_timeout.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_get_required_select_timeout.3pcap; path = libpcap/pcap_get_required_select_timeout.3pcap; sourceTree = "<group>"; };
+ 725D584E234535AB0023A8CB /* pcap_set_immediate_mode.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_immediate_mode.3pcap.in; path = libpcap/pcap_set_immediate_mode.3pcap.in; sourceTree = "<group>"; };
+ 725D584F234535AB0023A8CB /* pcap_set_protocol_linux.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_protocol_linux.3pcap; path = libpcap/pcap_set_protocol_linux.3pcap; sourceTree = "<group>"; };
+ 72717797234C0C8E000D8DF1 /* funcattrs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = funcattrs.h; path = libpcap/pcap/funcattrs.h; sourceTree = "<group>"; };
+ 72717799234C0CBC000D8DF1 /* pcap-inttypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcap-inttypes.h"; path = "libpcap/pcap/pcap-inttypes.h"; sourceTree = "<group>"; };
+ 7271779B234C110D000D8DF1 /* compiler-tests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "compiler-tests.h"; path = "libpcap/pcap/compiler-tests.h"; sourceTree = "<group>"; };
+ 7271779D234C11C0000D8DF1 /* socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = socket.h; path = libpcap/pcap/socket.h; sourceTree = "<group>"; };
+ 727A86A816CEECB700048C5E /* pcap-util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "pcap-util.c"; path = "libpcap/pcap-util.c"; sourceTree = "<group>"; };
+ 727A86AB16CEECD100048C5E /* pcap-util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "pcap-util.h"; path = "libpcap/pcap-util.h"; sourceTree = "<group>"; };
+ 727B12DF16278ACD0039A877 /* pcap-ng.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcap-ng.h"; path = "libpcap/pcap/pcap-ng.h"; sourceTree = "<group>"; };
+ 727B12E316278AEF0039A877 /* pcapng.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pcapng.c; path = libpcap/pcapng.c; sourceTree = "<group>"; };
+ 727B12F21628BF800039A877 /* ngdumptest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ngdumptest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 729DE1E316CB05F700195247 /* pcap-darwin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "pcap-darwin.c"; path = "libpcap/pcap-darwin.c"; sourceTree = "<group>"; };
+ 72B9035E1CE00CEC008DB2D2 /* capturetest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = capturetest; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72B903751CE0145A008DB2D2 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = config.h; path = libpcap/config.h; sourceTree = "<group>"; };
+ 72B903771CE01476008DB2D2 /* gencode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = gencode.h; path = libpcap/gencode.h; sourceTree = "<group>"; };
+ 72B903791CE014B0008DB2D2 /* arcnet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = arcnet.h; path = libpcap/arcnet.h; sourceTree = "<group>"; };
+ 72B9037B1CE014C9008DB2D2 /* atmuni31.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = atmuni31.h; path = libpcap/atmuni31.h; sourceTree = "<group>"; };
+ 72B9037D1CE014FC008DB2D2 /* ethertype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ethertype.h; path = libpcap/ethertype.h; sourceTree = "<group>"; };
+ 72B9037F1CE01511008DB2D2 /* ieee80211.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ieee80211.h; path = libpcap/ieee80211.h; sourceTree = "<group>"; };
+ 72B903811CE01527008DB2D2 /* llc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = llc.h; path = libpcap/llc.h; sourceTree = "<group>"; };
+ 72B903831CE01544008DB2D2 /* nlpid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nlpid.h; path = libpcap/nlpid.h; sourceTree = "<group>"; };
+ 72B903851CE015A0008DB2D2 /* ppp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ppp.h; path = libpcap/ppp.h; sourceTree = "<group>"; };
+ 72B903871CE015BB008DB2D2 /* sunatmpos.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sunatmpos.h; path = libpcap/sunatmpos.h; sourceTree = "<group>"; };
+ 72B903891CE015DD008DB2D2 /* pcap_compile.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_compile.3pcap; path = libpcap/pcap_compile.3pcap; sourceTree = "<group>"; };
+ 72B9038A1CE015DD008DB2D2 /* pcap_datalink.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_datalink.3pcap; path = libpcap/pcap_datalink.3pcap; sourceTree = "<group>"; };
+ 72B9038B1CE015DD008DB2D2 /* pcap_dump_open.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_dump_open.3pcap; path = libpcap/pcap_dump_open.3pcap; sourceTree = "<group>"; };
+ 72B9038C1CE015DD008DB2D2 /* pcap_get_tstamp_precision.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_get_tstamp_precision.3pcap; path = libpcap/pcap_get_tstamp_precision.3pcap; sourceTree = "<group>"; };
+ 72B9038D1CE015DD008DB2D2 /* pcap_get_tstamp_precision.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_get_tstamp_precision.3pcap.in; path = libpcap/pcap_get_tstamp_precision.3pcap.in; sourceTree = "<group>"; };
+ 72B9038E1CE015DD008DB2D2 /* pcap_list_datalinks.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_list_datalinks.3pcap; path = libpcap/pcap_list_datalinks.3pcap; sourceTree = "<group>"; };
+ 72B9038F1CE015DD008DB2D2 /* pcap_list_tstamp_types.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_list_tstamp_types.3pcap; path = libpcap/pcap_list_tstamp_types.3pcap; sourceTree = "<group>"; };
+ 72B903901CE015DD008DB2D2 /* pcap_list_tstamp_types.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_list_tstamp_types.3pcap.in; path = libpcap/pcap_list_tstamp_types.3pcap.in; sourceTree = "<group>"; };
+ 72B903911CE015DD008DB2D2 /* pcap_open_dead.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_open_dead.3pcap; path = libpcap/pcap_open_dead.3pcap; sourceTree = "<group>"; };
+ 72B903921CE015DD008DB2D2 /* pcap_open_offline.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_open_offline.3pcap; path = libpcap/pcap_open_offline.3pcap; sourceTree = "<group>"; };
+ 72B903931CE015DD008DB2D2 /* pcap_set_immediate_mode.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_immediate_mode.3pcap; path = libpcap/pcap_set_immediate_mode.3pcap; sourceTree = "<group>"; };
+ 72B903941CE015DD008DB2D2 /* pcap_set_tstamp_precision.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_tstamp_precision.3pcap; path = libpcap/pcap_set_tstamp_precision.3pcap; sourceTree = "<group>"; };
+ 72B903951CE015DD008DB2D2 /* pcap_set_tstamp_precision.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_tstamp_precision.3pcap.in; path = libpcap/pcap_set_tstamp_precision.3pcap.in; sourceTree = "<group>"; };
+ 72B903961CE015DD008DB2D2 /* pcap_set_tstamp_type.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_tstamp_type.3pcap; path = libpcap/pcap_set_tstamp_type.3pcap; sourceTree = "<group>"; };
+ 72B903971CE015DD008DB2D2 /* pcap_set_tstamp_type.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_tstamp_type.3pcap.in; path = libpcap/pcap_set_tstamp_type.3pcap.in; sourceTree = "<group>"; };
+ 72B903981CE015DD008DB2D2 /* pcap_tstamp_type_name_to_val.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_tstamp_type_name_to_val.3pcap; path = libpcap/pcap_tstamp_type_name_to_val.3pcap; sourceTree = "<group>"; };
+ 72B903991CE015DD008DB2D2 /* pcap_tstamp_type_val_to_name.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_tstamp_type_val_to_name.3pcap; path = libpcap/pcap_tstamp_type_val_to_name.3pcap; sourceTree = "<group>"; };
+ 72B9039B1CE01C0F008DB2D2 /* libpcap.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = libpcap.plist; sourceTree = "<group>"; };
+ 72C52983202543F2005DB7E4 /* ngdumppkap */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ngdumppkap; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72C5298A2025441A005DB7E4 /* ngdumppktap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ngdumppktap.c; path = ngdumppktap/ngdumppktap.c; sourceTree = "<group>"; };
+ 72D13B1B16BDF7D2009B01B1 /* hex_and_ascii_print.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hex_and_ascii_print.c; sourceTree = "<group>"; };
+ 72D13B1D16BDF7D2009B01B1 /* ngdumptest.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = ngdumptest.1; sourceTree = "<group>"; };
+ 72D13B1E16BDF7D2009B01B1 /* ngdumptest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngdumptest.c; sourceTree = "<group>"; };
+ 72D13B2016BDF7D2009B01B1 /* ngofflinereadtest.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; path = ngofflinereadtest.1; sourceTree = "<group>"; };
+ 72D13B2116BDF7D2009B01B1 /* ngofflinereadtest.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ngofflinereadtest.c; sourceTree = "<group>"; };
+ 72E2AB401E43BD4E00AEFE80 /* gen_libpcap_version */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = gen_libpcap_version; sourceTree = BUILT_PRODUCTS_DIR; };
+ 72E2AB4B1E43E9A700AEFE80 /* dlt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dlt.h; path = libpcap/pcap/dlt.h; sourceTree = "<group>"; };
+ 72E2AB4C1E43EC4500AEFE80 /* fad-helpers.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "fad-helpers.c"; path = "libpcap/fad-helpers.c"; sourceTree = "<group>"; };
+ 72E2AB541E44085E00AEFE80 /* print_libpcap_version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = print_libpcap_version.c; path = gen_libpcap_version/print_libpcap_version.c; sourceTree = SOURCE_ROOT; };
+ 72E2AB571E45022C00AEFE80 /* pcap-pktap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcap-pktap.h"; path = "libpcap/pcap-pktap.h"; sourceTree = "<group>"; };
+ 72E2AB5C1E456FE600AEFE80 /* bluetooth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bluetooth.h; path = libpcap/pcap/bluetooth.h; sourceTree = "<group>"; };
+ 72E2AB5D1E456FE600AEFE80 /* can_socketcan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = can_socketcan.h; path = libpcap/pcap/can_socketcan.h; sourceTree = "<group>"; };
+ 72E2AB5F1E456FE600AEFE80 /* ipnet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ipnet.h; path = libpcap/pcap/ipnet.h; sourceTree = "<group>"; };
+ 72E2AB601E456FE600AEFE80 /* nflog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nflog.h; path = libpcap/pcap/nflog.h; sourceTree = "<group>"; };
+ 72E2AB611E456FE600AEFE80 /* vlan.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vlan.h; path = libpcap/pcap/vlan.h; sourceTree = "<group>"; };
+ D2AAC0630554660B00DB518D /* libpcap.A.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libpcap.A.dylib; sourceTree = BUILT_PRODUCTS_DIR; };
+ FCDE3589103676CF00CC3DD8 /* bpf_dump.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bpf_dump.c; path = libpcap/bpf_dump.c; sourceTree = "<group>"; };
+ FCDE358B103676CF00CC3DD8 /* bpf_image.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = bpf_image.c; path = libpcap/bpf_image.c; sourceTree = "<group>"; };
+ FCDE358C103676CF00CC3DD8 /* etherent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = etherent.c; path = libpcap/etherent.c; sourceTree = "<group>"; };
+ FCDE358D103676CF00CC3DD8 /* fad-getad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "fad-getad.c"; path = "libpcap/fad-getad.c"; sourceTree = "<group>"; };
+ FCDE358E103676CF00CC3DD8 /* gencode.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = gencode.c; path = libpcap/gencode.c; sourceTree = "<group>"; };
+ FCDE358F103676CF00CC3DD8 /* grammar.y */ = {isa = PBXFileReference; explicitFileType = sourcecode.yacc; fileEncoding = 4; name = grammar.y; path = libpcap/grammar.y; sourceTree = "<group>"; };
+ FCDE3590103676CF00CC3DD8 /* inet.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = inet.c; path = libpcap/inet.c; sourceTree = "<group>"; };
+ FCDE3591103676CF00CC3DD8 /* nametoaddr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = nametoaddr.c; path = libpcap/nametoaddr.c; sourceTree = "<group>"; };
+ FCDE3592103676CF00CC3DD8 /* optimize.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = optimize.c; path = libpcap/optimize.c; sourceTree = "<group>"; };
+ FCDE3593103676CF00CC3DD8 /* pcap-bpf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "pcap-bpf.c"; path = "libpcap/pcap-bpf.c"; sourceTree = "<group>"; };
+ FCDE3594103676CF00CC3DD8 /* pcap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = pcap.c; path = libpcap/pcap.c; sourceTree = "<group>"; };
+ FCDE3595103676CF00CC3DD8 /* savefile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = savefile.c; path = libpcap/savefile.c; sourceTree = "<group>"; };
+ FCDE3596103676CF00CC3DD8 /* scanner.l */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.lex; name = scanner.l; path = libpcap/scanner.l; sourceTree = "<group>"; };
+ FCDE364B103680B800CC3DD8 /* version.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = version.c; path = libpcap/version.c; sourceTree = "<group>"; };
+ FCDE364C103680B800CC3DD8 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = libpcap/version.h; sourceTree = "<group>"; };
+ FCDE367E103681F900CC3DD8 /* bpf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bpf.h; path = libpcap/pcap/bpf.h; sourceTree = "<group>"; };
+ FCDE367F103681F900CC3DD8 /* namedb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = namedb.h; path = libpcap/pcap/namedb.h; sourceTree = "<group>"; };
+ FCDE3680103681F900CC3DD8 /* pcap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pcap.h; path = libpcap/pcap/pcap.h; sourceTree = "<group>"; };
+ FCDE3681103681F900CC3DD8 /* sll.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = sll.h; path = libpcap/pcap/sll.h; sourceTree = "<group>"; };
+ FCDE3682103681F900CC3DD8 /* usb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = usb.h; path = libpcap/pcap/usb.h; sourceTree = "<group>"; };
+ FCDE368A1036822200CC3DD8 /* pcap-bpf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcap-bpf.h"; path = "libpcap/pcap-bpf.h"; sourceTree = "<group>"; };
+ FCDE368B1036822200CC3DD8 /* pcap-namedb.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "pcap-namedb.h"; path = "libpcap/pcap-namedb.h"; sourceTree = "<group>"; };
+ FCDE368C1036822200CC3DD8 /* pcap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pcap.h; path = libpcap/pcap.h; sourceTree = "<group>"; };
+ FCDE369B103682D400CC3DD8 /* pcap_activate.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_activate.3pcap; path = libpcap/pcap_activate.3pcap; sourceTree = "<group>"; };
+ FCDE369C103682D400CC3DD8 /* pcap_breakloop.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_breakloop.3pcap; path = libpcap/pcap_breakloop.3pcap; sourceTree = "<group>"; };
+ FCDE369D103682D400CC3DD8 /* pcap_can_set_rfmon.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_can_set_rfmon.3pcap; path = libpcap/pcap_can_set_rfmon.3pcap; sourceTree = "<group>"; };
+ FCDE369E103682D400CC3DD8 /* pcap_close.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_close.3pcap; path = libpcap/pcap_close.3pcap; sourceTree = "<group>"; };
+ FCDE369F103682D400CC3DD8 /* pcap_compile.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_compile.3pcap.in; path = libpcap/pcap_compile.3pcap.in; sourceTree = "<group>"; };
+ FCDE36A0103682D400CC3DD8 /* pcap_create.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_create.3pcap; path = libpcap/pcap_create.3pcap; sourceTree = "<group>"; };
+ FCDE36A1103682D400CC3DD8 /* pcap_datalink_name_to_val.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_datalink_name_to_val.3pcap; path = libpcap/pcap_datalink_name_to_val.3pcap; sourceTree = "<group>"; };
+ FCDE36A2103682D400CC3DD8 /* pcap_datalink_val_to_name.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_datalink_val_to_name.3pcap; path = libpcap/pcap_datalink_val_to_name.3pcap; sourceTree = "<group>"; };
+ FCDE36A3103682D400CC3DD8 /* pcap_datalink.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_datalink.3pcap.in; path = libpcap/pcap_datalink.3pcap.in; sourceTree = "<group>"; };
+ FCDE36A4103682D400CC3DD8 /* pcap_dump_close.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_dump_close.3pcap; path = libpcap/pcap_dump_close.3pcap; sourceTree = "<group>"; };
+ FCDE36A5103682D400CC3DD8 /* pcap_dump_file.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_dump_file.3pcap; path = libpcap/pcap_dump_file.3pcap; sourceTree = "<group>"; };
+ FCDE36A6103682D400CC3DD8 /* pcap_dump_flush.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_dump_flush.3pcap; path = libpcap/pcap_dump_flush.3pcap; sourceTree = "<group>"; };
+ FCDE36A7103682D400CC3DD8 /* pcap_dump_ftell.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_dump_ftell.3pcap; path = libpcap/pcap_dump_ftell.3pcap; sourceTree = "<group>"; };
+ FCDE36A8103682D400CC3DD8 /* pcap_dump_open.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_dump_open.3pcap.in; path = libpcap/pcap_dump_open.3pcap.in; sourceTree = "<group>"; };
+ FCDE36A9103682D400CC3DD8 /* pcap_dump.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_dump.3pcap; path = libpcap/pcap_dump.3pcap; sourceTree = "<group>"; };
+ FCDE36AA103682D400CC3DD8 /* pcap_file.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_file.3pcap; path = libpcap/pcap_file.3pcap; sourceTree = "<group>"; };
+ FCDE36AB103682D400CC3DD8 /* pcap_fileno.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_fileno.3pcap; path = libpcap/pcap_fileno.3pcap; sourceTree = "<group>"; };
+ FCDE36AC103682D400CC3DD8 /* pcap_findalldevs.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_findalldevs.3pcap; path = libpcap/pcap_findalldevs.3pcap; sourceTree = "<group>"; };
+ FCDE36AF103682D400CC3DD8 /* pcap_freecode.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_freecode.3pcap; path = libpcap/pcap_freecode.3pcap; sourceTree = "<group>"; };
+ FCDE36B0103682D400CC3DD8 /* pcap_get_selectable_fd.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_get_selectable_fd.3pcap; path = libpcap/pcap_get_selectable_fd.3pcap; sourceTree = "<group>"; };
+ FCDE36B1103682D400CC3DD8 /* pcap_geterr.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_geterr.3pcap; path = libpcap/pcap_geterr.3pcap; sourceTree = "<group>"; };
+ FCDE36B2103682D400CC3DD8 /* pcap_inject.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_inject.3pcap; path = libpcap/pcap_inject.3pcap; sourceTree = "<group>"; };
+ FCDE36B3103682D400CC3DD8 /* pcap_is_swapped.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_is_swapped.3pcap; path = libpcap/pcap_is_swapped.3pcap; sourceTree = "<group>"; };
+ FCDE36B4103682D400CC3DD8 /* pcap_lib_version.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_lib_version.3pcap; path = libpcap/pcap_lib_version.3pcap; sourceTree = "<group>"; };
+ FCDE36B5103682D400CC3DD8 /* pcap_list_datalinks.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_list_datalinks.3pcap.in; path = libpcap/pcap_list_datalinks.3pcap.in; sourceTree = "<group>"; };
+ FCDE36B6103682D400CC3DD8 /* pcap_lookupdev.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_lookupdev.3pcap; path = libpcap/pcap_lookupdev.3pcap; sourceTree = "<group>"; };
+ FCDE36B7103682D400CC3DD8 /* pcap_lookupnet.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_lookupnet.3pcap; path = libpcap/pcap_lookupnet.3pcap; sourceTree = "<group>"; };
+ FCDE36B8103682D400CC3DD8 /* pcap_loop.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_loop.3pcap; path = libpcap/pcap_loop.3pcap; sourceTree = "<group>"; };
+ FCDE36B9103682D400CC3DD8 /* pcap_major_version.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_major_version.3pcap; path = libpcap/pcap_major_version.3pcap; sourceTree = "<group>"; };
+ FCDE36BA103682D400CC3DD8 /* pcap_next_ex.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_next_ex.3pcap; path = libpcap/pcap_next_ex.3pcap; sourceTree = "<group>"; };
+ FCDE36BB103682D400CC3DD8 /* pcap_offline_filter.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_offline_filter.3pcap; path = libpcap/pcap_offline_filter.3pcap; sourceTree = "<group>"; };
+ FCDE36BC103682D400CC3DD8 /* pcap_open_dead.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_open_dead.3pcap.in; path = libpcap/pcap_open_dead.3pcap.in; sourceTree = "<group>"; };
+ FCDE36BD103682D400CC3DD8 /* pcap_open_live.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_open_live.3pcap; path = libpcap/pcap_open_live.3pcap; sourceTree = "<group>"; };
+ FCDE36BE103682D400CC3DD8 /* pcap_open_offline.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_open_offline.3pcap.in; path = libpcap/pcap_open_offline.3pcap.in; sourceTree = "<group>"; };
+ FCDE36BF103682D400CC3DD8 /* pcap_set_buffer_size.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_buffer_size.3pcap; path = libpcap/pcap_set_buffer_size.3pcap; sourceTree = "<group>"; };
+ FCDE36C0103682D400CC3DD8 /* pcap_set_datalink.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_datalink.3pcap; path = libpcap/pcap_set_datalink.3pcap; sourceTree = "<group>"; };
+ FCDE36C1103682D400CC3DD8 /* pcap_set_promisc.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_promisc.3pcap; path = libpcap/pcap_set_promisc.3pcap; sourceTree = "<group>"; };
+ FCDE36C2103682D400CC3DD8 /* pcap_set_rfmon.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_rfmon.3pcap; path = libpcap/pcap_set_rfmon.3pcap; sourceTree = "<group>"; };
+ FCDE36C3103682D400CC3DD8 /* pcap_set_snaplen.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_snaplen.3pcap; path = libpcap/pcap_set_snaplen.3pcap; sourceTree = "<group>"; };
+ FCDE36C4103682D400CC3DD8 /* pcap_set_timeout.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_set_timeout.3pcap; path = libpcap/pcap_set_timeout.3pcap; sourceTree = "<group>"; };
+ FCDE36C5103682D400CC3DD8 /* pcap_setdirection.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_setdirection.3pcap; path = libpcap/pcap_setdirection.3pcap; sourceTree = "<group>"; };
+ FCDE36C6103682D400CC3DD8 /* pcap_setfilter.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_setfilter.3pcap; path = libpcap/pcap_setfilter.3pcap; sourceTree = "<group>"; };
+ FCDE36C7103682D400CC3DD8 /* pcap_setnonblock.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_setnonblock.3pcap; path = libpcap/pcap_setnonblock.3pcap; sourceTree = "<group>"; };
+ FCDE36C8103682D400CC3DD8 /* pcap_snapshot.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_snapshot.3pcap; path = libpcap/pcap_snapshot.3pcap; sourceTree = "<group>"; };
+ FCDE36C9103682D400CC3DD8 /* pcap_stats.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_stats.3pcap; path = libpcap/pcap_stats.3pcap; sourceTree = "<group>"; };
+ FCDE36CA103682D400CC3DD8 /* pcap_statustostr.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_statustostr.3pcap; path = libpcap/pcap_statustostr.3pcap; sourceTree = "<group>"; };
+ FCDE36CB103682D400CC3DD8 /* pcap_strerror.3pcap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap_strerror.3pcap; path = libpcap/pcap_strerror.3pcap; sourceTree = "<group>"; };
+ FCDE36CC103682D400CC3DD8 /* pcap-config.1 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.man; name = "pcap-config.1"; path = "libpcap/pcap-config.1"; sourceTree = "<group>"; };
+ FCDE36CD103682D400CC3DD8 /* pcap.3pcap.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = pcap.3pcap.in; path = libpcap/pcap.3pcap.in; sourceTree = "<group>"; };
+ FCDE37061036836500CC3DD8 /* pcap-savefile.manfile.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pcap-savefile.manfile.in"; path = "libpcap/pcap-savefile.manfile.in"; sourceTree = "<group>"; };
+ FCDE37091036837700CC3DD8 /* pcap-filter.manmisc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pcap-filter.manmisc.in"; path = "libpcap/pcap-filter.manmisc.in"; sourceTree = "<group>"; };
+ FCDE370C1036838C00CC3DD8 /* pcap-linktype.manmisc.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = "pcap-linktype.manmisc.in"; path = "libpcap/pcap-linktype.manmisc.in"; sourceTree = "<group>"; };
+ FCDE370F103683C100CC3DD8 /* pcap-config.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = "pcap-config.in"; path = "libpcap/pcap-config.in"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 721463A01F68984600D74814 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 721463AE1F6898CF00D74814 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441E9115D322C1007A9F70 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72B903691CE00EA9008DB2D2 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441E9F15D32317007A9F70 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72B9036A1CE00EBF008DB2D2 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441EB915D3233B007A9F70 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72B9036E1CE00EED008DB2D2 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441EC615D3234A007A9F70 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72B903701CE00EFB008DB2D2 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441ED315D32357007A9F70 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72B903721CE00F07008DB2D2 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725032ED15F6E5BF00BDA576 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 727B12D9162745460039A877 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725D5816234530040023A8CB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D584A2345336C0023A8CB /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725D5828234531AF0023A8CB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D584B2345348B0023A8CB /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725D5837234531FC0023A8CB /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D584C2345349B0023A8CB /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 727B12EF1628BF800039A877 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 727B12FB1628C06F0039A877 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72B9035B1CE00CEC008DB2D2 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72B903661CE00DB2008DB2D2 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72C52980202543F2005DB7E4 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72C5299820254567005DB7E4 /* libpcap_static.a in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72E2AB3D1E43BD4E00AEFE80 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D289988505E68E00004EDB86 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 08FB7794FE84155DC02AAC07 /* libpcap */ = {
+ isa = PBXGroup;
+ children = (
+ 724B3DA615D3269F00DAC815 /* libpcap.dylib */,
+ FCDE36951036824D00CC3DD8 /* Headers */,
+ 08FB7795FE84155DC02AAC07 /* libpcap */,
+ 72E2AB411E43BD4E00AEFE80 /* gen_libpcap_version */,
+ 725D580023452FA00023A8CB /* testprogs */,
+ 72D13B1816BDF7D2009B01B1 /* tests */,
+ FCDE36981036827700CC3DD8 /* Documentation */,
+ 72B9039A1CE01BD7008DB2D2 /* Resources */,
+ 725D582C234531AF0023A8CB /* threadsignaltest */,
+ 725D583B234531FC0023A8CB /* valgrindtest */,
+ 1AB674ADFE9D54B511CA2CBB /* Products */,
+ 721463AD1F6898CF00D74814 /* Frameworks */,
+ );
+ name = libpcap;
+ sourceTree = "<group>";
+ };
+ 08FB7795FE84155DC02AAC07 /* libpcap */ = {
+ isa = PBXGroup;
+ children = (
+ FCDE3589103676CF00CC3DD8 /* bpf_dump.c */,
+ 721769202344333200731290 /* bpf_filter.c */,
+ FCDE358B103676CF00CC3DD8 /* bpf_image.c */,
+ FCDE358C103676CF00CC3DD8 /* etherent.c */,
+ FCDE358D103676CF00CC3DD8 /* fad-getad.c */,
+ 72E2AB4C1E43EC4500AEFE80 /* fad-helpers.c */,
+ 721769222344379500731290 /* fmtutils.c */,
+ FCDE358E103676CF00CC3DD8 /* gencode.c */,
+ FCDE358F103676CF00CC3DD8 /* grammar.y */,
+ FCDE3590103676CF00CC3DD8 /* inet.c */,
+ FCDE3591103676CF00CC3DD8 /* nametoaddr.c */,
+ FCDE3592103676CF00CC3DD8 /* optimize.c */,
+ FCDE3593103676CF00CC3DD8 /* pcap-bpf.c */,
+ 724FC91512331FCE003B8C19 /* pcap-common.c */,
+ 729DE1E316CB05F700195247 /* pcap-darwin.c */,
+
+ 727A86A816CEECB700048C5E /* pcap-util.c */,
+ 7208CF902403399200AA0E42 /* pcapng-private.h */,
+ FCDE3594103676CF00CC3DD8 /* pcap.c */,
+ 727B12E316278AEF0039A877 /* pcapng.c */,
+ FCDE3595103676CF00CC3DD8 /* savefile.c */,
+ 724FC91C1233226B003B8C19 /* sf-pcap.c */,
+ 7217691E23442F5A00731290 /* sf-pcapng.c */,
+ FCDE3596103676CF00CC3DD8 /* scanner.l */,
+ FCDE364B103680B800CC3DD8 /* version.c */,
+ FCDE370F103683C100CC3DD8 /* pcap-config.in */,
+ );
+ name = libpcap;
+ sourceTree = "<group>";
+ };
+ 1AB674ADFE9D54B511CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ D2AAC0630554660B00DB518D /* libpcap.A.dylib */,
+ 72441E9415D322C1007A9F70 /* filtertest */,
+ 72441EA215D32317007A9F70 /* findalldevs */,
+ 72441EBC15D3233B007A9F70 /* opentest */,
+ 72441EC915D3234A007A9F70 /* reactivatetest */,
+ 72441ED615D32357007A9F70 /* selpolltest */,
+ 725032F015F6E5BF00BDA576 /* ngofflinereadtest */,
+ 7244CBDD1624FBE400141ECF /* libpcap_static.a */,
+ 727B12F21628BF800039A877 /* ngdumptest */,
+ 72B9035E1CE00CEC008DB2D2 /* capturetest */,
+ 72E2AB401E43BD4E00AEFE80 /* gen_libpcap_version */,
+ 721463A31F68984600D74814 /* offlinereadtest */,
+ 72C52983202543F2005DB7E4 /* ngdumppkap */,
+ 725D5819234530040023A8CB /* can_set_rfmon_test */,
+ 725D582B234531AF0023A8CB /* threadsignaltest */,
+ 725D583A234531FC0023A8CB /* valgrindtest */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 721463AD1F6898CF00D74814 /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 725D580023452FA00023A8CB /* testprogs */ = {
+ isa = PBXGroup;
+ children = (
+ 725D580723452FBD0023A8CB /* can_set_rfmon_test.c */,
+ 725D580423452FBD0023A8CB /* capturetest.c */,
+ 725D580823452FBD0023A8CB /* filtertest.c */,
+ 725D580923452FBD0023A8CB /* findalldevstest.c */,
+ 725D580A23452FBD0023A8CB /* opentest.c */,
+ 725D580323452FBD0023A8CB /* reactivatetest.c */,
+ 725D580623452FBD0023A8CB /* selpolltest.c */,
+ 725D580123452FBD0023A8CB /* threadsignaltest.c */,
+ 725D580523452FBD0023A8CB /* unix.h */,
+ 725D580223452FBD0023A8CB /* valgrindtest.c */,
+ );
+ name = testprogs;
+ path = libpcap/tests;
+ sourceTree = "<group>";
+ };
+ 725D582C234531AF0023A8CB /* threadsignaltest */ = {
+ isa = PBXGroup;
+ children = (
+ 725D582D234531AF0023A8CB /* main.c */,
+ );
+ path = threadsignaltest;
+ sourceTree = "<group>";
+ };
+ 725D583B234531FC0023A8CB /* valgrindtest */ = {
+ isa = PBXGroup;
+ children = (
+ 725D583C234531FC0023A8CB /* main.c */,
+ );
+ path = valgrindtest;
+ sourceTree = "<group>";
+ };
+ 72B9039A1CE01BD7008DB2D2 /* Resources */ = {
+ isa = PBXGroup;
+ children = (
+ 72B9039B1CE01C0F008DB2D2 /* libpcap.plist */,
+ );
+ name = Resources;
+ sourceTree = "<group>";
+ };
+ 72C5297E202543BF005DB7E4 /* ngdumppktap */ = {
+ isa = PBXGroup;
+ children = (
+ 72C5298A2025441A005DB7E4 /* ngdumppktap.c */,
+ );
+ name = ngdumppktap;
+ sourceTree = "<group>";
+ };
+ 72D13B1816BDF7D2009B01B1 /* tests */ = {
+ isa = PBXGroup;
+ children = (
+ 725D5832234531D10023A8CB /* nonblocktest.c */,
+ 725D5833234531D10023A8CB /* offlinereadtest.c */,
+ 72D13B1B16BDF7D2009B01B1 /* hex_and_ascii_print.c */,
+ 72C5297E202543BF005DB7E4 /* ngdumppktap */,
+ 72D13B1C16BDF7D2009B01B1 /* ngdumptest */,
+ 72D13B1F16BDF7D2009B01B1 /* ngofflinereadtest */,
+ );
+ name = tests;
+ path = libpcap/tests;
+ sourceTree = "<group>";
+ };
+ 72D13B1C16BDF7D2009B01B1 /* ngdumptest */ = {
+ isa = PBXGroup;
+ children = (
+ 72D13B1D16BDF7D2009B01B1 /* ngdumptest.1 */,
+ 72D13B1E16BDF7D2009B01B1 /* ngdumptest.c */,
+ );
+ path = ngdumptest;
+ sourceTree = "<group>";
+ };
+ 72D13B1F16BDF7D2009B01B1 /* ngofflinereadtest */ = {
+ isa = PBXGroup;
+ children = (
+ 72D13B2016BDF7D2009B01B1 /* ngofflinereadtest.1 */,
+ 72D13B2116BDF7D2009B01B1 /* ngofflinereadtest.c */,
+ );
+ path = ngofflinereadtest;
+ sourceTree = "<group>";
+ };
+ 72E2AB411E43BD4E00AEFE80 /* gen_libpcap_version */ = {
+ isa = PBXGroup;
+ children = (
+ 72E2AB541E44085E00AEFE80 /* print_libpcap_version.c */,
+ );
+ name = gen_libpcap_version;
+ path = make_version_files;
+ sourceTree = "<group>";
+ };
+ 72E2AB5B1E456FAB00AEFE80 /* pcap */ = {
+ isa = PBXGroup;
+ children = (
+ FCDE367E103681F900CC3DD8 /* bpf.h */,
+ 72E2AB5C1E456FE600AEFE80 /* bluetooth.h */,
+ 72E2AB5D1E456FE600AEFE80 /* can_socketcan.h */,
+ 7271779B234C110D000D8DF1 /* compiler-tests.h */,
+ 72717797234C0C8E000D8DF1 /* funcattrs.h */,
+ 72E2AB4B1E43E9A700AEFE80 /* dlt.h */,
+ 72E2AB5F1E456FE600AEFE80 /* ipnet.h */,
+ FCDE367F103681F900CC3DD8 /* namedb.h */,
+ 72E2AB601E456FE600AEFE80 /* nflog.h */,
+ 72717799234C0CBC000D8DF1 /* pcap-inttypes.h */,
+ 727B12DF16278ACD0039A877 /* pcap-ng.h */,
+ FCDE3680103681F900CC3DD8 /* pcap.h */,
+ 7271779D234C11C0000D8DF1 /* socket.h */,
+ FCDE3681103681F900CC3DD8 /* sll.h */,
+ FCDE3682103681F900CC3DD8 /* usb.h */,
+ 72E2AB611E456FE600AEFE80 /* vlan.h */,
+ );
+ name = pcap;
+ sourceTree = "<group>";
+ };
+ FCDE36951036824D00CC3DD8 /* Headers */ = {
+ isa = PBXGroup;
+ children = (
+ 72E2AB5B1E456FAB00AEFE80 /* pcap */,
+ 72B903791CE014B0008DB2D2 /* arcnet.h */,
+ 72B9037B1CE014C9008DB2D2 /* atmuni31.h */,
+ 72B903751CE0145A008DB2D2 /* config.h */,
+ 72B9037D1CE014FC008DB2D2 /* ethertype.h */,
+ 72B903771CE01476008DB2D2 /* gencode.h */,
+ 721769232344379500731290 /* ftmacros.h */,
+ 721769242344379500731290 /* fmtutils.h */,
+ 72B9037F1CE01511008DB2D2 /* ieee80211.h */,
+ 72B903811CE01527008DB2D2 /* llc.h */,
+ 72B903831CE01544008DB2D2 /* nlpid.h */,
+ FCDE368A1036822200CC3DD8 /* pcap-bpf.h */,
+ 724FC91712331FDD003B8C19 /* pcap-common.h */,
+ 724FC92412332462003B8C19 /* pcap-int.h */,
+ FCDE368B1036822200CC3DD8 /* pcap-namedb.h */,
+ 72E2AB571E45022C00AEFE80 /* pcap-pktap.h */,
+
+ 727A86AB16CEECD100048C5E /* pcap-util.h */,
+ FCDE368C1036822200CC3DD8 /* pcap.h */,
+ 72B903851CE015A0008DB2D2 /* ppp.h */,
+ 724FC92212332337003B8C19 /* sf-pcap.h */,
+ 7217691C23442F2500731290 /* sf-pcapng.h */,
+ 72B903871CE015BB008DB2D2 /* sunatmpos.h */,
+ FCDE364C103680B800CC3DD8 /* version.h */,
+ );
+ name = Headers;
+ sourceTree = "<group>";
+ };
+ FCDE36981036827700CC3DD8 /* Documentation */ = {
+ isa = PBXGroup;
+ children = (
+ FCDE36CC103682D400CC3DD8 /* pcap-config.1 */,
+ FCDE37091036837700CC3DD8 /* pcap-filter.manmisc.in */,
+ FCDE370C1036838C00CC3DD8 /* pcap-linktype.manmisc.in */,
+ FCDE37061036836500CC3DD8 /* pcap-savefile.manfile.in */,
+ FCDE36CD103682D400CC3DD8 /* pcap.3pcap.in */,
+ FCDE369B103682D400CC3DD8 /* pcap_activate.3pcap */,
+ FCDE369C103682D400CC3DD8 /* pcap_breakloop.3pcap */,
+ FCDE369D103682D400CC3DD8 /* pcap_can_set_rfmon.3pcap */,
+ FCDE369E103682D400CC3DD8 /* pcap_close.3pcap */,
+ 72B903891CE015DD008DB2D2 /* pcap_compile.3pcap */,
+ FCDE369F103682D400CC3DD8 /* pcap_compile.3pcap.in */,
+ FCDE36A0103682D400CC3DD8 /* pcap_create.3pcap */,
+ 72B9038A1CE015DD008DB2D2 /* pcap_datalink.3pcap */,
+ FCDE36A3103682D400CC3DD8 /* pcap_datalink.3pcap.in */,
+ FCDE36A1103682D400CC3DD8 /* pcap_datalink_name_to_val.3pcap */,
+ FCDE36A2103682D400CC3DD8 /* pcap_datalink_val_to_name.3pcap */,
+ FCDE36A9103682D400CC3DD8 /* pcap_dump.3pcap */,
+ FCDE36A4103682D400CC3DD8 /* pcap_dump_close.3pcap */,
+ FCDE36A5103682D400CC3DD8 /* pcap_dump_file.3pcap */,
+ FCDE36A6103682D400CC3DD8 /* pcap_dump_flush.3pcap */,
+ FCDE36A7103682D400CC3DD8 /* pcap_dump_ftell.3pcap */,
+ 72B9038B1CE015DD008DB2D2 /* pcap_dump_open.3pcap */,
+ FCDE36A8103682D400CC3DD8 /* pcap_dump_open.3pcap.in */,
+ FCDE36AA103682D400CC3DD8 /* pcap_file.3pcap */,
+ FCDE36AB103682D400CC3DD8 /* pcap_fileno.3pcap */,
+ FCDE36AC103682D400CC3DD8 /* pcap_findalldevs.3pcap */,
+ FCDE36AF103682D400CC3DD8 /* pcap_freecode.3pcap */,
+ 725D584D234535730023A8CB /* pcap_get_required_select_timeout.3pcap */,
+ FCDE36B0103682D400CC3DD8 /* pcap_get_selectable_fd.3pcap */,
+ 72B9038C1CE015DD008DB2D2 /* pcap_get_tstamp_precision.3pcap */,
+ 72B9038D1CE015DD008DB2D2 /* pcap_get_tstamp_precision.3pcap.in */,
+ FCDE36B1103682D400CC3DD8 /* pcap_geterr.3pcap */,
+ FCDE36B2103682D400CC3DD8 /* pcap_inject.3pcap */,
+ FCDE36B3103682D400CC3DD8 /* pcap_is_swapped.3pcap */,
+ FCDE36B4103682D400CC3DD8 /* pcap_lib_version.3pcap */,
+ 72B9038E1CE015DD008DB2D2 /* pcap_list_datalinks.3pcap */,
+ FCDE36B5103682D400CC3DD8 /* pcap_list_datalinks.3pcap.in */,
+ 72B9038F1CE015DD008DB2D2 /* pcap_list_tstamp_types.3pcap */,
+ 72B903901CE015DD008DB2D2 /* pcap_list_tstamp_types.3pcap.in */,
+ FCDE36B6103682D400CC3DD8 /* pcap_lookupdev.3pcap */,
+ FCDE36B7103682D400CC3DD8 /* pcap_lookupnet.3pcap */,
+ FCDE36B8103682D400CC3DD8 /* pcap_loop.3pcap */,
+ FCDE36B9103682D400CC3DD8 /* pcap_major_version.3pcap */,
+ 568DEF0D14BE09EC005DEBAE /* pcap_ng.3 */,
+ FCDE36BA103682D400CC3DD8 /* pcap_next_ex.3pcap */,
+ FCDE36BB103682D400CC3DD8 /* pcap_offline_filter.3pcap */,
+ 72B903911CE015DD008DB2D2 /* pcap_open_dead.3pcap */,
+ FCDE36BC103682D400CC3DD8 /* pcap_open_dead.3pcap.in */,
+ FCDE36BD103682D400CC3DD8 /* pcap_open_live.3pcap */,
+ 72B903921CE015DD008DB2D2 /* pcap_open_offline.3pcap */,
+ FCDE36BE103682D400CC3DD8 /* pcap_open_offline.3pcap.in */,
+ FCDE36BF103682D400CC3DD8 /* pcap_set_buffer_size.3pcap */,
+ FCDE36C0103682D400CC3DD8 /* pcap_set_datalink.3pcap */,
+ 72B903931CE015DD008DB2D2 /* pcap_set_immediate_mode.3pcap */,
+ 725D584E234535AB0023A8CB /* pcap_set_immediate_mode.3pcap.in */,
+ 725D584F234535AB0023A8CB /* pcap_set_protocol_linux.3pcap */,
+ FCDE36C1103682D400CC3DD8 /* pcap_set_promisc.3pcap */,
+ FCDE36C2103682D400CC3DD8 /* pcap_set_rfmon.3pcap */,
+ FCDE36C3103682D400CC3DD8 /* pcap_set_snaplen.3pcap */,
+ FCDE36C4103682D400CC3DD8 /* pcap_set_timeout.3pcap */,
+ 72B903941CE015DD008DB2D2 /* pcap_set_tstamp_precision.3pcap */,
+ 72B903951CE015DD008DB2D2 /* pcap_set_tstamp_precision.3pcap.in */,
+ 72B903961CE015DD008DB2D2 /* pcap_set_tstamp_type.3pcap */,
+ 72B903971CE015DD008DB2D2 /* pcap_set_tstamp_type.3pcap.in */,
+ FCDE36C5103682D400CC3DD8 /* pcap_setdirection.3pcap */,
+ FCDE36C6103682D400CC3DD8 /* pcap_setfilter.3pcap */,
+ FCDE36C7103682D400CC3DD8 /* pcap_setnonblock.3pcap */,
+ FCDE36C8103682D400CC3DD8 /* pcap_snapshot.3pcap */,
+ FCDE36C9103682D400CC3DD8 /* pcap_stats.3pcap */,
+ FCDE36CA103682D400CC3DD8 /* pcap_statustostr.3pcap */,
+ FCDE36CB103682D400CC3DD8 /* pcap_strerror.3pcap */,
+ 72B903981CE015DD008DB2D2 /* pcap_tstamp_type_name_to_val.3pcap */,
+ 72B903991CE015DD008DB2D2 /* pcap_tstamp_type_val_to_name.3pcap */,
+ );
+ name = Documentation;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ D2AAC0600554660B00DB518D /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FC293B301036978A0055686E /* pcap.h in Headers */,
+ FCDE368D1036822200CC3DD8 /* pcap-bpf.h in Headers */,
+ 72E2AB621E456FE600AEFE80 /* bluetooth.h in Headers */,
+ FCDE3683103681F900CC3DD8 /* bpf.h in Headers */,
+ 72E2AB631E456FE600AEFE80 /* can_socketcan.h in Headers */,
+ 7271779C234C110E000D8DF1 /* compiler-tests.h in Headers */,
+ 72E2AB681E4570C000AEFE80 /* dlt.h in Headers */,
+ 72717798234C0C8E000D8DF1 /* funcattrs.h in Headers */,
+ 72E2AB651E456FE600AEFE80 /* ipnet.h in Headers */,
+ FCDE3684103681F900CC3DD8 /* namedb.h in Headers */,
+ FCDE368E1036822200CC3DD8 /* pcap-namedb.h in Headers */,
+ 72E2AB661E456FE600AEFE80 /* nflog.h in Headers */,
+ FC293B26103695150055686E /* pcap.h in Headers */,
+ 7271779A234C0CBD000D8DF1 /* pcap-inttypes.h in Headers */,
+ 7208CF912403399200AA0E42 /* pcapng-private.h in Headers */,
+ 727B12E116278ACD0039A877 /* pcap-ng.h in Headers */,
+ 727A86AC16CEF6D700048C5E /* pcap-util.h in Headers */,
+ FCDE3686103681F900CC3DD8 /* sll.h in Headers */,
+ 7271779E234C11C0000D8DF1 /* socket.h in Headers */,
+ 72B9037A1CE014B0008DB2D2 /* arcnet.h in Headers */,
+ 72E2AB671E456FE600AEFE80 /* vlan.h in Headers */,
+ FCDE3687103681F900CC3DD8 /* usb.h in Headers */,
+ 72B9037C1CE014C9008DB2D2 /* atmuni31.h in Headers */,
+ 72B903761CE0145A008DB2D2 /* config.h in Headers */,
+ 72B9037E1CE014FC008DB2D2 /* ethertype.h in Headers */,
+ 721769272344379500731290 /* fmtutils.h in Headers */,
+ 721769262344379500731290 /* ftmacros.h in Headers */,
+ 72B903781CE01476008DB2D2 /* gencode.h in Headers */,
+ 72B903801CE01511008DB2D2 /* ieee80211.h in Headers */,
+ 72B903821CE01527008DB2D2 /* llc.h in Headers */,
+ 72B903841CE01544008DB2D2 /* nlpid.h in Headers */,
+ 724FC92512332462003B8C19 /* pcap-int.h in Headers */,
+ 724FC91812331FDD003B8C19 /* pcap-common.h in Headers */,
+ 72E2AB581E45022C00AEFE80 /* pcap-pktap.h in Headers */,
+
+ 72B903861CE015A0008DB2D2 /* ppp.h in Headers */,
+ 724FC92312332337003B8C19 /* sf-pcap.h in Headers */,
+ 7217691D23442F2500731290 /* sf-pcapng.h in Headers */,
+ 72B903881CE015BB008DB2D2 /* sunatmpos.h in Headers */,
+ 72011B262356B3C6003A5F22 /* unix.h in Headers */,
+ FCDE364E103680B800CC3DD8 /* version.h in Headers */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 721463A21F68984600D74814 /* offlinereadtest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 721463A91F68984600D74814 /* Build configuration list for PBXNativeTarget "offlinereadtest" */;
+ buildPhases = (
+ 7214639F1F68984600D74814 /* Sources */,
+ 721463A01F68984600D74814 /* Frameworks */,
+ 721463A11F68984600D74814 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C5299E20254579005DB7E4 /* PBXTargetDependency */,
+ );
+ name = offlinereadtest;
+ productName = offlinereadtest;
+ productReference = 721463A31F68984600D74814 /* offlinereadtest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72441E9315D322C1007A9F70 /* filtertest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72441E9B15D322C1007A9F70 /* Build configuration list for PBXNativeTarget "filtertest" */;
+ buildPhases = (
+ 72441E9015D322C1007A9F70 /* Sources */,
+ 72441E9115D322C1007A9F70 /* Frameworks */,
+ 72441E9215D322C1007A9F70 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C529932025455A005DB7E4 /* PBXTargetDependency */,
+ );
+ name = filtertest;
+ productName = filtertest;
+ productReference = 72441E9415D322C1007A9F70 /* filtertest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72441EA115D32317007A9F70 /* findalldevs */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72441EA915D32317007A9F70 /* Build configuration list for PBXNativeTarget "findalldevs" */;
+ buildPhases = (
+ 72441E9E15D32317007A9F70 /* Sources */,
+ 72441E9F15D32317007A9F70 /* Frameworks */,
+ 72441EA015D32317007A9F70 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C529952025455E005DB7E4 /* PBXTargetDependency */,
+ );
+ name = findalldevs;
+ productName = findalldevs;
+ productReference = 72441EA215D32317007A9F70 /* findalldevs */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72441EBB15D3233B007A9F70 /* opentest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72441EC315D3233B007A9F70 /* Build configuration list for PBXNativeTarget "opentest" */;
+ buildPhases = (
+ 72441EB815D3233B007A9F70 /* Sources */,
+ 72441EB915D3233B007A9F70 /* Frameworks */,
+ 72441EBA15D3233B007A9F70 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C529A02025457D005DB7E4 /* PBXTargetDependency */,
+ );
+ name = opentest;
+ productName = opentest;
+ productReference = 72441EBC15D3233B007A9F70 /* opentest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72441EC815D3234A007A9F70 /* reactivatetest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72441ED015D3234A007A9F70 /* Build configuration list for PBXNativeTarget "reactivatetest" */;
+ buildPhases = (
+ 72441EC515D3234A007A9F70 /* Sources */,
+ 72441EC615D3234A007A9F70 /* Frameworks */,
+ 72441EC715D3234A007A9F70 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C529A220254583005DB7E4 /* PBXTargetDependency */,
+ );
+ name = reactivatetest;
+ productName = reactivatetest;
+ productReference = 72441EC915D3234A007A9F70 /* reactivatetest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72441ED515D32357007A9F70 /* selpolltest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72441EDD15D32357007A9F70 /* Build configuration list for PBXNativeTarget "selpolltest" */;
+ buildPhases = (
+ 72441ED215D32357007A9F70 /* Sources */,
+ 72441ED315D32357007A9F70 /* Frameworks */,
+ 72441ED415D32357007A9F70 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C529A42025458F005DB7E4 /* PBXTargetDependency */,
+ );
+ name = selpolltest;
+ productName = selpolltest;
+ productReference = 72441ED615D32357007A9F70 /* selpolltest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 7244CBDC1624FBE400141ECF /* libpcap_static */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7244CBDE1624FBE400141ECF /* Build configuration list for PBXNativeTarget "libpcap_static" */;
+ buildPhases = (
+ 7244CBD91624FBE400141ECF /* Sources */,
+ );
+ buildRules = (
+ 7244CBF21624FD8600141ECF /* PBXBuildRule */,
+ );
+ dependencies = (
+ 72E2AB511E43EEDB00AEFE80 /* PBXTargetDependency */,
+ );
+ name = libpcap_static;
+ productName = libpcap.a;
+ productReference = 7244CBDD1624FBE400141ECF /* libpcap_static.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 725032EF15F6E5BF00BDA576 /* ngofflinereadtest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 725032F715F6E5C000BDA576 /* Build configuration list for PBXNativeTarget "ngofflinereadtest" */;
+ buildPhases = (
+ 725032EC15F6E5BF00BDA576 /* Sources */,
+ 725032ED15F6E5BF00BDA576 /* Frameworks */,
+ );
+ buildRules = (
+ 7250331415F6E80800BDA576 /* PBXBuildRule */,
+ );
+ dependencies = (
+ 72E2E24E16274394004E347B /* PBXTargetDependency */,
+ );
+ name = ngofflinereadtest;
+ productName = ngofflinereadtest;
+ productReference = 725032F015F6E5BF00BDA576 /* ngofflinereadtest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 725D5818234530040023A8CB /* can_set_rfmon_test */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 725D581D234530040023A8CB /* Build configuration list for PBXNativeTarget "can_set_rfmon_test" */;
+ buildPhases = (
+ 725D5815234530040023A8CB /* Sources */,
+ 725D5816234530040023A8CB /* Frameworks */,
+ 725D5817234530040023A8CB /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = can_set_rfmon_test;
+ productName = can_set_rfmon_test;
+ productReference = 725D5819234530040023A8CB /* can_set_rfmon_test */;
+ productType = "com.apple.product-type.tool";
+ };
+ 725D582A234531AF0023A8CB /* threadsignaltest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 725D582F234531AF0023A8CB /* Build configuration list for PBXNativeTarget "threadsignaltest" */;
+ buildPhases = (
+ 725D5827234531AF0023A8CB /* Sources */,
+ 725D5828234531AF0023A8CB /* Frameworks */,
+ 725D5829234531AF0023A8CB /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = threadsignaltest;
+ productName = threadsignaltest;
+ productReference = 725D582B234531AF0023A8CB /* threadsignaltest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 725D5839234531FC0023A8CB /* valgrindtest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 725D583E234531FC0023A8CB /* Build configuration list for PBXNativeTarget "valgrindtest" */;
+ buildPhases = (
+ 725D5836234531FC0023A8CB /* Sources */,
+ 725D5837234531FC0023A8CB /* Frameworks */,
+ 725D5838234531FC0023A8CB /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = valgrindtest;
+ productName = valgrindtest;
+ productReference = 725D583A234531FC0023A8CB /* valgrindtest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 727B12F11628BF800039A877 /* ngdumptest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 727B12F81628BF800039A877 /* Build configuration list for PBXNativeTarget "ngdumptest" */;
+ buildPhases = (
+ 727B12EE1628BF800039A877 /* Sources */,
+ 727B12EF1628BF800039A877 /* Frameworks */,
+ 727B12F01628BF800039A877 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C5299A2025456C005DB7E4 /* PBXTargetDependency */,
+ );
+ name = ngdumptest;
+ productName = ngdumptest;
+ productReference = 727B12F21628BF800039A877 /* ngdumptest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72B9035D1CE00CEC008DB2D2 /* capturetest */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72B903621CE00CEC008DB2D2 /* Build configuration list for PBXNativeTarget "capturetest" */;
+ buildPhases = (
+ 72B9035A1CE00CEC008DB2D2 /* Sources */,
+ 72B9035B1CE00CEC008DB2D2 /* Frameworks */,
+ 72B9035C1CE00CEC008DB2D2 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C5299120254553005DB7E4 /* PBXTargetDependency */,
+ );
+ name = capturetest;
+ productName = capturetest;
+ productReference = 72B9035E1CE00CEC008DB2D2 /* capturetest */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72C52982202543F2005DB7E4 /* ngdumppkap */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72C52987202543F2005DB7E4 /* Build configuration list for PBXNativeTarget "ngdumppkap" */;
+ buildPhases = (
+ 72C5297F202543F2005DB7E4 /* Sources */,
+ 72C52980202543F2005DB7E4 /* Frameworks */,
+ 72C52981202543F2005DB7E4 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 72C5299720254563005DB7E4 /* PBXTargetDependency */,
+ );
+ name = ngdumppkap;
+ productName = ngdumppkap;
+ productReference = 72C52983202543F2005DB7E4 /* ngdumppkap */;
+ productType = "com.apple.product-type.tool";
+ };
+ 72E2AB3F1E43BD4E00AEFE80 /* gen_libpcap_version */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 72E2AB461E43BD4E00AEFE80 /* Build configuration list for PBXNativeTarget "gen_libpcap_version" */;
+ buildPhases = (
+ 72E2AB471E43BD9500AEFE80 /* ShellScript */,
+ 72E2AB3C1E43BD4E00AEFE80 /* Sources */,
+ 72E2AB3D1E43BD4E00AEFE80 /* Frameworks */,
+ 72E2AB3E1E43BD4E00AEFE80 /* CopyFiles */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = gen_libpcap_version;
+ productName = make_version_files;
+ productReference = 72E2AB401E43BD4E00AEFE80 /* gen_libpcap_version */;
+ productType = "com.apple.product-type.tool";
+ };
+ D2AAC0620554660B00DB518D /* libpcap */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "libpcap" */;
+ buildPhases = (
+ D2AAC0600554660B00DB518D /* Headers */,
+ D2AAC0610554660B00DB518D /* Sources */,
+ D289988505E68E00004EDB86 /* Frameworks */,
+ FCDE37291036849300CC3DD8 /* ShellScript */,
+ );
+ buildRules = (
+ FCDE361910367FAA00CC3DD8 /* PBXBuildRule */,
+ );
+ dependencies = (
+ 72E2AB4A1E43C1FE00AEFE80 /* PBXTargetDependency */,
+ );
+ name = libpcap;
+ productName = libpcap;
+ productReference = D2AAC0630554660B00DB518D /* libpcap.A.dylib */;
+ productType = "com.apple.product-type.library.dynamic";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 08FB7793FE84155DC02AAC07 /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 0830;
+ TargetAttributes = {
+ 721463A21F68984600D74814 = {
+ CreatedOnToolsVersion = 9.0;
+ ProvisioningStyle = Automatic;
+ };
+ 725D5818234530040023A8CB = {
+ CreatedOnToolsVersion = 11.0;
+ ProvisioningStyle = Automatic;
+ };
+ 725D582A234531AF0023A8CB = {
+ CreatedOnToolsVersion = 11.0;
+ ProvisioningStyle = Automatic;
+ };
+ 725D5839234531FC0023A8CB = {
+ CreatedOnToolsVersion = 11.0;
+ ProvisioningStyle = Automatic;
+ };
+ 72B9035D1CE00CEC008DB2D2 = {
+ CreatedOnToolsVersion = 7.1;
+ };
+ 72C52982202543F2005DB7E4 = {
+ CreatedOnToolsVersion = 9.3;
+ ProvisioningStyle = Automatic;
+ };
+ 72E2AB3F1E43BD4E00AEFE80 = {
+ CreatedOnToolsVersion = 8.3;
+ ProvisioningStyle = Automatic;
+ };
+ };
+ };
+ buildConfigurationList = 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "libpcap" */;
+ compatibilityVersion = "Xcode 3.2";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ English,
+ en,
+ );
+ mainGroup = 08FB7794FE84155DC02AAC07 /* libpcap */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ D2AAC0620554660B00DB518D /* libpcap */,
+ 72E2AB3F1E43BD4E00AEFE80 /* gen_libpcap_version */,
+ 727B12E61627AF810039A877 /* all */,
+ 72441EE415D323A7007A9F70 /* tests */,
+ 7244CBDC1624FBE400141ECF /* libpcap_static */,
+ 725D5818234530040023A8CB /* can_set_rfmon_test */,
+ 72B9035D1CE00CEC008DB2D2 /* capturetest */,
+ 72441E9315D322C1007A9F70 /* filtertest */,
+ 72441EA115D32317007A9F70 /* findalldevs */,
+ 72C52982202543F2005DB7E4 /* ngdumppkap */,
+ 727B12F11628BF800039A877 /* ngdumptest */,
+ 725032EF15F6E5BF00BDA576 /* ngofflinereadtest */,
+ 721463A21F68984600D74814 /* offlinereadtest */,
+ 72441EBB15D3233B007A9F70 /* opentest */,
+ 72441EC815D3234A007A9F70 /* reactivatetest */,
+ 72441ED515D32357007A9F70 /* selpolltest */,
+ 725D582A234531AF0023A8CB /* threadsignaltest */,
+ 725D5839234531FC0023A8CB /* valgrindtest */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 72E2AB471E43BD9500AEFE80 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "print_libpcap_version()\n{\n plutil -p libpcap.plist |grep OpenSourceVersion | awk '{ print $3 }'|tr -d \"\\\"\"\n}\n\n\nprint_darwin_version()\n{\n darwin_version=\"${RC_ProjectSourceVersion}\"\n if [ -z ${darwin_version} ]; then\n darwin_version=\"`git branch|grep '* '|awk '{ print $2 }'` (`date '+%Y-%m-%d %H:%M:%S'`)\"\n fi\n echo ${darwin_version}\n}\n\nversion_string=\"libpcap version `print_libpcap_version` -- Apple version `print_darwin_version`\"\n\nmkdir -p \"${SHARED_DERIVED_FILE_DIR}\"\n\necho \"static const char pcap_version_string[] = \\\"${version_string}\\\";\" > \"${SHARED_DERIVED_FILE_DIR}/pcap_version.h\"\n\nexit 0\n";
+ };
+ FCDE37291036849300CC3DD8 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ );
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "# exit immediately on failure\nset -e\n\necho \"# PROJECT_DIR: ${PROJECT_DIR}\"\n\nif [ ${EUID} -ne 0 ]; then\n\texec sudo -E $0 $*\nfi\n\nMANDIR=/usr/share/man\n\nln -sf libpcap.A.dylib \"$DSTROOT\"/usr/lib/libpcap.dylib\n\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/usr/bin\ninstall -c -o root -g wheel -m 0755 \"$PROJECT_DIR\"/libpcap/pcap-config \"$DSTROOT\"/usr/bin/pcap-config\n\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/\"$MANDIR\"/man1\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/\"$MANDIR\"/man3\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/\"$MANDIR\"/man5\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/\"$MANDIR\"/man7\n\n\ninstall -c -o root -g wheel -m 0644 \"$PROJECT_DIR\"/libpcap/pcap-config.1 \"$DSTROOT\"/\"$MANDIR\"/man1\n\ninstall -c -o root -g wheel -m 0644 \"$PROJECT_DIR\"/libpcap/*.3pcap \"$DSTROOT\"/\"$MANDIR\"/man3\n\n# Some man pages require special processing:\n# @MAN_MISC_INFO@ -> 7\n# .manmisc.in -> .7\n# @MAN_FILE_FORMATS@ -> 5\n# .manfile.in -> .5\n\nfunction FixManPages() {\n OLD_DIR=\"$1\"\n OLD_SUFFIX=\"$2\"\n NEW_DIR=\"$3\"\n NEW_SUFFIX=\"$4\"\n for INPUT_FILE_PATH in \"$OLD_DIR\"/*\"$OLD_SUFFIX\" ; do\n INPUT_FILE_BASE=`basename \"$INPUT_FILE_PATH\" \"$OLD_SUFFIX\"`\n OUTPUT_FILE_PATH=\"$NEW_DIR/$INPUT_FILE_BASE$NEW_SUFFIX\"\n cat \"$INPUT_FILE_PATH\" | sed -e 's,@MAN_MISC_INFO@,7,g' | sed -e 's,@MAN_FILE_FORMATS,5,g' > \"$OUTPUT_FILE_PATH\"\n chmod 0644 \"$OUTPUT_FILE_PATH\"\n chown root:wheel \"$OUTPUT_FILE_PATH\"\n done\n}\n\nFixManPages \"$PROJECT_DIR\"/libpcap .3pcap.in \"$DSTROOT\"/\"$MANDIR\"/man3 .3pcap\nFixManPages \"$PROJECT_DIR\"/libpcap .manfile.in \"$DSTROOT\"/\"$MANDIR\"/man5 .5\nFixManPages \"$PROJECT_DIR\"/libpcap .manmisc.in \"$DSTROOT\"/\"$MANDIR\"/man7 .7\n\n# Some man pages are links\nfunction ManPageLink() {\n TARGET=\"$1\"\n LINK=\"$2\"\n OUTPUT_FILE_PATH=\"$DSTROOT/\"$MANDIR\"/man3/$LINK\"\n echo \".so man3/$TARGET\" > \"$OUTPUT_FILE_PATH\"\n chmod 0644 \"$OUTPUT_FILE_PATH\"\n chown root:wheel \"$OUTPUT_FILE_PATH\"\n}\n\nManPageLink pcap_datalink_val_to_name.3pcap pcap_compile.3pcap.in\nManPageLink pcap_loop.3pcap pcap_dispatch.3pcap\nManPageLink pcap_dump_open.3pcap pcap_dump_fopen.3pcap\nManPageLink pcap_open_offline.3pcap pcap_fopen_offline.3pcap\nManPageLink pcap_setnonblock.3pcap pcap_getnonblock.3pcap\nManPageLink pcap_major_version.3pcap pcap_minor_version.3pcap\nManPageLink pcap_next_ex.3pcap pcap_next.3pcap\nManPageLink pcap_geterr.3pcap pcap_perror.3pcap\nManPageLink pcap_inject.3pcap pcap_sendpacket.3pcap\nManPageLink pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap\nManPageLink pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap\n\n# Install private man pages\nMANDIR=/usr/local/share/man\n\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/\"$MANDIR\"/man3\n \ninstall -c -o root -g wheel -m 0644 \"$PROJECT_DIR\"/libpcap/*.3 \"$DSTROOT\"/\"$MANDIR\"/man3\nManPageLink pcap_ng.3 pcap_ng_dump_open.3\nManPageLink pcap_ng.3 pcap_ng_dump_fopen.3\nManPageLink pcap_ng.3 pcap_ng_dump.3\nManPageLink pcap_ng.3 pcap_ng_dump_close.3\n \n# Install open source information\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/usr/local/OpenSourceVersions\ninstall -c -o root -g wheel -m 0444 \"$PROJECT_DIR\"/libpcap.plist \"$DSTROOT\"/usr/local/OpenSourceVersions\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/usr/local/OpenSourceLicenses\ninstall -c -o root -g wheel -m 0444 \"$PROJECT_DIR\"/libpcap/LICENSE \"$DSTROOT\"/usr/local/OpenSourceLicenses/libpcap.txt\n\n# Post processing to separate public headers and private headers\nSYSPRIVDIR=/System/Library/Frameworks/System.framework/Versions/B/PrivateHeaders\n\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/\"$SYSPRIVDIR\"\ninstall -d -o root -g wheel -m 0755 \"$DSTROOT\"/\"$SYSPRIVDIR\"/pcap\n\npushd \"$DSTROOT\"/\"$PUBLIC_HEADERS_FOLDER_PATH\"\nfor item in `find . -type f`\ndo\n install -c -o root -g wheel -m 0644 \"$item\" \"$DSTROOT\"/\"$SYSPRIVDIR\"/\"$item\"\n # unifdef returns non zero value on success\n set +e\n unifdef -UPRIVATE -o \"$item\" \"$item\"\n unifdef -DPRIVATE -o \"$DSTROOT\"/\"$SYSPRIVDIR\"/\"$item\" \"$DSTROOT\"/\"$SYSPRIVDIR\"/\"$item\"\n set -e\ndone\n# Remove header that need to be kept private\nrm ./pcap/pcap-ng.h\npopd\n";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 7214639F1F68984600D74814 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D5843234532260023A8CB /* offlinereadtest.c in Sources */,
+ 721463AC1F6898C200D74814 /* hex_and_ascii_print.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441E9015D322C1007A9F70 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D58222345302B0023A8CB /* filtertest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441E9E15D32317007A9F70 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D5823234530330023A8CB /* findalldevstest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441EB815D3233B007A9F70 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D5824234531580023A8CB /* opentest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441EC515D3234A007A9F70 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D5825234531600023A8CB /* reactivatetest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72441ED215D32357007A9F70 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D5826234531690023A8CB /* selpolltest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 7244CBD91624FBE400141ECF /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7244CBE11624FC8C00141ECF /* bpf_dump.c in Sources */,
+ 725D57F9234523E60023A8CB /* bpf_filter.c in Sources */,
+ 7244CBE61624FCC600141ECF /* bpf_image.c in Sources */,
+ 7244CBE71624FCC600141ECF /* etherent.c in Sources */,
+ 7244CBE81624FCC600141ECF /* fad-getad.c in Sources */,
+ 725D57FA234523E60023A8CB /* fmtutils.c in Sources */,
+ 72E2AB531E43F0B900AEFE80 /* gencode.c in Sources */,
+ 7244CBEB1624FCC600141ECF /* nametoaddr.c in Sources */,
+ 7244CBEC1624FCC600141ECF /* optimize.c in Sources */,
+ 7244CBED1624FCC600141ECF /* pcap-bpf.c in Sources */,
+ 7244CBE51624FCC600141ECF /* pcap-common.c in Sources */,
+ 729DE1E516CB05F700195247 /* pcap-darwin.c in Sources */,
+
+ 727A86AA16CEECB700048C5E /* pcap-util.c in Sources */,
+ 7244CBEE1624FCC600141ECF /* pcap.c in Sources */,
+ 727B12E51627A9080039A877 /* pcapng.c in Sources */,
+ 7244CBEF1624FCC600141ECF /* savefile.c in Sources */,
+ 7244CBF01624FCC600141ECF /* scanner.l in Sources */,
+ 7244CBE41624FCC600141ECF /* sf-pcap.c in Sources */,
+ 725D57FB234523E60023A8CB /* sf-pcapng.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725032EC15F6E5BF00BDA576 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72D13B3B16BDF994009B01B1 /* hex_and_ascii_print.c in Sources */,
+ 72D13B3C16BDF994009B01B1 /* ngofflinereadtest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725D5815234530040023A8CB /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D58202345301B0023A8CB /* can_set_rfmon_test.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725D5827234531AF0023A8CB /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D58412345320F0023A8CB /* threadsignaltest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 725D5836234531FC0023A8CB /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D5842234532160023A8CB /* valgrindtest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 727B12EE1628BF800039A877 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72D13B3916BDF98B009B01B1 /* hex_and_ascii_print.c in Sources */,
+ 72D13B3A16BDF98B009B01B1 /* ngdumptest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72B9035A1CE00CEC008DB2D2 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 725D5821234530230023A8CB /* capturetest.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72C5297F202543F2005DB7E4 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72C529A5202545A4005DB7E4 /* ngdumppktap.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 72E2AB3C1E43BD4E00AEFE80 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 72E2AB561E44085E00AEFE80 /* print_libpcap_version.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ D2AAC0610554660B00DB518D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ FCDE3597103676CF00CC3DD8 /* bpf_dump.c in Sources */,
+ 721769212344333200731290 /* bpf_filter.c in Sources */,
+ FCDE3599103676CF00CC3DD8 /* bpf_image.c in Sources */,
+ FCDE359A103676CF00CC3DD8 /* etherent.c in Sources */,
+ FCDE359B103676CF00CC3DD8 /* fad-getad.c in Sources */,
+ 720914CC234562EE003B403A /* fmtutils.c in Sources */,
+ FCDE359C103676CF00CC3DD8 /* gencode.c in Sources */,
+ FCDE359F103676CF00CC3DD8 /* nametoaddr.c in Sources */,
+ FCDE35A0103676CF00CC3DD8 /* optimize.c in Sources */,
+ FCDE35A1103676CF00CC3DD8 /* pcap-bpf.c in Sources */,
+ 724FC91612331FCE003B8C19 /* pcap-common.c in Sources */,
+ 729DE1E416CB05F700195247 /* pcap-darwin.c in Sources */,
+
+ 727A86A916CEECB700048C5E /* pcap-util.c in Sources */,
+ FCDE35A2103676CF00CC3DD8 /* pcap.c in Sources */,
+ 727B12E416278AEF0039A877 /* pcapng.c in Sources */,
+ FCDE35A3103676CF00CC3DD8 /* savefile.c in Sources */,
+ FCDE35A4103676CF00CC3DD8 /* scanner.l in Sources */,
+ 724FC91D1233226B003B8C19 /* sf-pcap.c in Sources */,
+ 7217691F23442F5A00731290 /* sf-pcapng.c in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 724B3DB815D3277800DAC815 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72441E9315D322C1007A9F70 /* filtertest */;
+ targetProxy = 724B3DB715D3277800DAC815 /* PBXContainerItemProxy */;
+ };
+ 724B3DBA15D3277800DAC815 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72441EA115D32317007A9F70 /* findalldevs */;
+ targetProxy = 724B3DB915D3277800DAC815 /* PBXContainerItemProxy */;
+ };
+ 724B3DBE15D3277800DAC815 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72441EBB15D3233B007A9F70 /* opentest */;
+ targetProxy = 724B3DBD15D3277800DAC815 /* PBXContainerItemProxy */;
+ };
+ 724B3DC015D3277800DAC815 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72441EC815D3234A007A9F70 /* reactivatetest */;
+ targetProxy = 724B3DBF15D3277800DAC815 /* PBXContainerItemProxy */;
+ };
+ 724B3DC215D3277800DAC815 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72441ED515D32357007A9F70 /* selpolltest */;
+ targetProxy = 724B3DC115D3277800DAC815 /* PBXContainerItemProxy */;
+ };
+ 725D5845234532D90023A8CB /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 725D5818234530040023A8CB /* can_set_rfmon_test */;
+ targetProxy = 725D5844234532D90023A8CB /* PBXContainerItemProxy */;
+ };
+ 725D5847234533020023A8CB /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 725D582A234531AF0023A8CB /* threadsignaltest */;
+ targetProxy = 725D5846234533020023A8CB /* PBXContainerItemProxy */;
+ };
+ 725D5849234533020023A8CB /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 725D5839234531FC0023A8CB /* valgrindtest */;
+ targetProxy = 725D5848234533020023A8CB /* PBXContainerItemProxy */;
+ };
+ 727B12EB1627AF8F0039A877 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = D2AAC0620554660B00DB518D /* libpcap */;
+ targetProxy = 727B12EA1627AF8F0039A877 /* PBXContainerItemProxy */;
+ };
+ 727B12ED1627AF8F0039A877 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72441EE415D323A7007A9F70 /* tests */;
+ targetProxy = 727B12EC1627AF8F0039A877 /* PBXContainerItemProxy */;
+ };
+ 727B12FD1628C6240039A877 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 727B12F11628BF800039A877 /* ngdumptest */;
+ targetProxy = 727B12FC1628C6240039A877 /* PBXContainerItemProxy */;
+ };
+ 72B903741CE00F24008DB2D2 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72B9035D1CE00CEC008DB2D2 /* capturetest */;
+ targetProxy = 72B903731CE00F24008DB2D2 /* PBXContainerItemProxy */;
+ };
+ 72C5298D2025453A005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72C52982202543F2005DB7E4 /* ngdumppkap */;
+ targetProxy = 72C5298C2025453A005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C5298F2025453A005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 721463A21F68984600D74814 /* offlinereadtest */;
+ targetProxy = 72C5298E2025453A005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C5299120254553005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C5299020254553005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C529932025455A005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C529922025455A005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C529952025455E005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C529942025455E005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C5299720254563005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C5299620254563005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C5299A2025456C005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C529992025456C005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C5299E20254579005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C5299D20254579005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C529A02025457D005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C5299F2025457D005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C529A220254583005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C529A120254583005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72C529A42025458F005DB7E4 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72C529A32025458F005DB7E4 /* PBXContainerItemProxy */;
+ };
+ 72E2AB4A1E43C1FE00AEFE80 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72E2AB3F1E43BD4E00AEFE80 /* gen_libpcap_version */;
+ targetProxy = 72E2AB491E43C1FE00AEFE80 /* PBXContainerItemProxy */;
+ };
+ 72E2AB511E43EEDB00AEFE80 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 72E2AB3F1E43BD4E00AEFE80 /* gen_libpcap_version */;
+ targetProxy = 72E2AB501E43EEDB00AEFE80 /* PBXContainerItemProxy */;
+ };
+ 72E2E24E16274394004E347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72E2E24D16274394004E347B /* PBXContainerItemProxy */;
+ };
+ 72E2E250162743E8004E347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 725032EF15F6E5BF00BDA576 /* ngofflinereadtest */;
+ targetProxy = 72E2E24F162743E8004E347B /* PBXContainerItemProxy */;
+ };
+ 72E2E252162743E8004E347B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7244CBDC1624FBE400141ECF /* libpcap_static */;
+ targetProxy = 72E2E251162743E8004E347B /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 1DEB914C08733D8E0010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ "$(SHARED_DERIVED_FILE_DIR)",
+ );
+ INSTALL_PATH = /usr/lib;
+ IS_ZIPPERED = YES;
+ ONLY_ACTIVE_ARCH = NO;
+ OTHER_LDFLAGS = "-all_load";
+ PRIVATE_HEADERS_FOLDER_PATH = /usr/include/pcap;
+ PRODUCT_NAME = libpcap.A;
+ };
+ name = Release;
+ };
+ 1DEB915008733D8E0010E9CD /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPRESSION = "respect-asset-catalog";
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ HAVE_CONFIG_H,
+ "_U_=__attribute__((unused))",
+ "yylval=pcap_lval",
+ PRIVATE,
+ HAVE_PKTAP_API,
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = libpcap;
+ PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include;
+ PUBLIC_HEADERS_FOLDER_PATH = /usr/include;
+ SDKROOT = macosx.internal;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
+ USER_HEADER_SEARCH_PATHS = "$(SHARED_DERIVED_FILE_DIR)";
+ USE_HEADERMAP = NO;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+ 721463A71F68984600D74814 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 721463A81F68984600D74814 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 72441E9C15D322C1007A9F70 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 72441EAA15D32317007A9F70 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 72441EC415D3233B007A9F70 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 72441ED115D3234A007A9F70 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 72441EDE15D32357007A9F70 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 72441EE615D323A7007A9F70 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 7244CBDF1624FBE400141ECF /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ EXECUTABLE_PREFIX = "";
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ "$(SHARED_DERIVED_FILE_DIR)",
+ );
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 7244CBE01624FBE400141ECF /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ EXECUTABLE_PREFIX = "";
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ "$(SHARED_DERIVED_FILE_DIR)",
+ );
+ ONLY_ACTIVE_ARCH = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 725032F815F6E5C000BDA576 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ HEADER_SEARCH_PATHS = libpcap;
+ PRIVATE_HEADERS_FOLDER_PATH = /usr/include/pcap;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 725032F915F6E5C000BDA576 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ HEADER_SEARCH_PATHS = libpcap;
+ PRIVATE_HEADERS_FOLDER_PATH = /usr/include/pcap;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 7257836A15D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ ASSETCATALOG_COMPRESSION = lossless;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ CODE_SIGN_IDENTITY = "-";
+ COPY_PHASE_STRIP = NO;
+ CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ HAVE_CONFIG_H,
+ "_U_=__attribute__((unused))",
+ "yylval=pcap_lval",
+ PRIVATE,
+ HAVE_PKTAP_API,
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ HEADER_SEARCH_PATHS = libpcap;
+ ONLY_ACTIVE_ARCH = YES;
+ PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include;
+ PUBLIC_HEADERS_FOLDER_PATH = /usr/include;
+ SDKROOT = macosx.internal;
+ SUPPORTED_PLATFORMS = "iphonesimulator iphoneos macosx";
+ USER_HEADER_SEARCH_PATHS = "$(SHARED_DERIVED_FILE_DIR)";
+ USE_HEADERMAP = NO;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 7257836B15D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = NO;
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ "$(SHARED_DERIVED_FILE_DIR)",
+ );
+ INSTALL_PATH = /usr/lib;
+ IS_ZIPPERED = YES;
+ ONLY_ACTIVE_ARCH = NO;
+ OTHER_LDFLAGS = "-all_load";
+ PRIVATE_HEADERS_FOLDER_PATH = /usr/include/pcap;
+ PRODUCT_NAME = libpcap.A;
+ };
+ name = Debug;
+ };
+ 7257836C15D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 7257836D15D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 7257836E15D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 7257837015D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 7257837115D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 7257837215D333E800712E55 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_ENABLE_OBJC_EXCEPTIONS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 725D581E234530040023A8CB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 725D581F234530040023A8CB /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 725D5830234531AF0023A8CB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 725D5831234531AF0023A8CB /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 725D583F234531FC0023A8CB /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ 725D5840234531FC0023A8CB /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ MACOSX_DEPLOYMENT_TARGET = 10.15;
+ MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+ MTL_FAST_MATH = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ 727B12E81627AF810039A877 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 727B12E91627AF810039A877 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 727B12F91628BF800039A877 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ HEADER_SEARCH_PATHS = (
+ "$(PROJECT_DIR)/libpcap",
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 727B12FA1628BF800039A877 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = (
+ "$(PROJECT_DIR)/libpcap",
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ );
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 72B903631CE00CEC008DB2D2 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 72B903641CE00CEC008DB2D2 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 72C52988202543F2005DB7E4 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ );
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ 72C52989202543F2005DB7E4 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_ENABLE_OBJC_WEAK = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+ CODE_SIGN_STYLE = Automatic;
+ GCC_C_LANGUAGE_STANDARD = gnu11;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SDKROOT)/System/Library/Frameworks/System.framework/PrivateHeaders",
+ );
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 72E2AB441E43BD4E00AEFE80 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ COPY_PHASE_STRIP = NO;
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SHARED_DERIVED_FILE_DIR)",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ };
+ name = Release;
+ };
+ 72E2AB451E43BD4E00AEFE80 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ HEADER_SEARCH_PATHS = (
+ libpcap,
+ "$(SHARED_DERIVED_FILE_DIR)",
+ );
+ MACOSX_DEPLOYMENT_TARGET = 10.12;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SKIP_INSTALL = YES;
+ };
+ name = Debug;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 1DEB914A08733D8E0010E9CD /* Build configuration list for PBXNativeTarget "libpcap" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB914C08733D8E0010E9CD /* Release */,
+ 7257836B15D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 1DEB914E08733D8E0010E9CD /* Build configuration list for PBXProject "libpcap" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 1DEB915008733D8E0010E9CD /* Release */,
+ 7257836A15D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 721463A91F68984600D74814 /* Build configuration list for PBXNativeTarget "offlinereadtest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 721463A71F68984600D74814 /* Release */,
+ 721463A81F68984600D74814 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72441E9B15D322C1007A9F70 /* Build configuration list for PBXNativeTarget "filtertest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72441E9C15D322C1007A9F70 /* Release */,
+ 7257836D15D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72441EA915D32317007A9F70 /* Build configuration list for PBXNativeTarget "findalldevs" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72441EAA15D32317007A9F70 /* Release */,
+ 7257836E15D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72441EC315D3233B007A9F70 /* Build configuration list for PBXNativeTarget "opentest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72441EC415D3233B007A9F70 /* Release */,
+ 7257837015D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72441ED015D3234A007A9F70 /* Build configuration list for PBXNativeTarget "reactivatetest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72441ED115D3234A007A9F70 /* Release */,
+ 7257837115D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72441EDD15D32357007A9F70 /* Build configuration list for PBXNativeTarget "selpolltest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72441EDE15D32357007A9F70 /* Release */,
+ 7257837215D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72441EE515D323A7007A9F70 /* Build configuration list for PBXAggregateTarget "tests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72441EE615D323A7007A9F70 /* Release */,
+ 7257836C15D333E800712E55 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 7244CBDE1624FBE400141ECF /* Build configuration list for PBXNativeTarget "libpcap_static" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 7244CBDF1624FBE400141ECF /* Release */,
+ 7244CBE01624FBE400141ECF /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 725032F715F6E5C000BDA576 /* Build configuration list for PBXNativeTarget "ngofflinereadtest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 725032F815F6E5C000BDA576 /* Release */,
+ 725032F915F6E5C000BDA576 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 725D581D234530040023A8CB /* Build configuration list for PBXNativeTarget "can_set_rfmon_test" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 725D581E234530040023A8CB /* Release */,
+ 725D581F234530040023A8CB /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 725D582F234531AF0023A8CB /* Build configuration list for PBXNativeTarget "threadsignaltest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 725D5830234531AF0023A8CB /* Release */,
+ 725D5831234531AF0023A8CB /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 725D583E234531FC0023A8CB /* Build configuration list for PBXNativeTarget "valgrindtest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 725D583F234531FC0023A8CB /* Release */,
+ 725D5840234531FC0023A8CB /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 727B12E71627AF810039A877 /* Build configuration list for PBXAggregateTarget "all" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 727B12E81627AF810039A877 /* Release */,
+ 727B12E91627AF810039A877 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 727B12F81628BF800039A877 /* Build configuration list for PBXNativeTarget "ngdumptest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 727B12F91628BF800039A877 /* Release */,
+ 727B12FA1628BF800039A877 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72B903621CE00CEC008DB2D2 /* Build configuration list for PBXNativeTarget "capturetest" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72B903631CE00CEC008DB2D2 /* Release */,
+ 72B903641CE00CEC008DB2D2 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72C52987202543F2005DB7E4 /* Build configuration list for PBXNativeTarget "ngdumppkap" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72C52988202543F2005DB7E4 /* Release */,
+ 72C52989202543F2005DB7E4 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 72E2AB461E43BD4E00AEFE80 /* Build configuration list for PBXNativeTarget "gen_libpcap_version" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 72E2AB441E43BD4E00AEFE80 /* Release */,
+ 72E2AB451E43BD4E00AEFE80 /* Debug */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
+}
diff --git a/lib/libpcap/libpcap/CHANGES b/lib/libpcap/libpcap/CHANGES
new file mode 100644
index 0000000..89e739c
--- /dev/null
+++ b/lib/libpcap/libpcap/CHANGES
@@ -0,0 +1,988 @@
+Sunday, July 22, 2018
+ Summary for 1.9.1 libpcap release
+ Mention pcap_get_required_select_timeout() in the main pcap man page
+ Fix pcap-usb-linux.c build on systems with musl
+ Fix assorted man page and other documentation issues
+ Plug assorted memory leaks
+ Documentation changes to use https:
+ Changes to how time stamp calculations are done
+ Lots of tweaks to make newer compilers happier and warning-free and
+ to fix instances of C undefined behavior
+ Warn if AC_PROG_CC_C99 can't enable C99 support
+ Rename pcap_set_protocol() to pcap_set_protocol_linux().
+ Align pcap_t private data on an 8-byte boundary.
+ Fix various error messages
+ Use 64-bit clean API in dag_findalldevs()
+ Fix cleaning up after some errors
+ Work around some ethtool ioctl bugs in newer Linux kernels (GitHub
+ issue #689)
+ Add backwards compatibility sections to some man pages (GitHub issue
+ #745)
+ Fix autotool configuration on AIX and macOS
+ Don't export bpf_filter_with_aux_data() or struct bpf_aux_data;
+ they're internal-only and subject to change
+ Fix pcapng block size checking
+ On macOS, don't build rpcapd or test programs any fatter than they
+ need to be
+ Fix reading of capture statistics for Linux USB
+ Fix packet size values for Linux USB packets (GitHub issue #808)
+ Check only VID in VLAN test in filterss (GitHub issue #461)
+ Fix pcap_list_datalinks on 802.11 devices on macOS
+ Fix overflows with very large snapshot length in pcap file
+ Improve parsing of rpcapd configuration file (GitHub issue #767)
+ Handle systems without strlcpy() or strlcat() better
+ Fix crashes and other errors with invalid filter expressions
+ Fix use of uninitialized file descriptor in remote capture
+ Fix some CMake issues
+ Fix some divide-by-zero issues with the filter compiler
+ Work around a GNU libc bug in pcap_nametonetaddr()
+ Add support for DLT_LINUX_SLL2
+ Fix handling of the packet-count argument for Myricom SNF devices
+ Fix --disable-rdma in configure script (GitHub issue #782)
+ Fix compilation of TurboCap support (GitHub issue #764)
+ Constify first argument to pcap_findalldevs_ex()
+ Fix a number of issues when running rpcapd as an inetd-style daemon
+ Fix CMake issues with D-Bus libraries
+ In rpcapd, clean up termination of a capture session
+ Redo remote capture protocol negotiation
+ In rpcapd, report the same error for "invalid user name" and
+ "invalid password", to make brute-forcing harder
+ For remote captures, add an error code for "the server requires TLS"
+ Fix pcap_dump_fopen() on Windows to avoid clashes between
+ {Win,N}Pcap and application C runtimes
+ Fix exporting of functions from Windows DLLs (GitHub issue #810)
+ Fix building as part of Npcap
+ Allow rpcapd to rebind more rapidly
+ Fix building shared libpcap library on midipix (midipix.org)
+ Fix hack to detect UTF-16LE adapter names on Windows not to go past
+ the end of the string
+ Fix handling of "wireless WAN" (mobile phone network modems) on
+ Windows with WinPcap/Npcap (GitHub issue #824)
+ Have pcap_dump_open_append() create the dump file if it doesn't
+ exists (GitHub issue #247)
+ Fix the maxmum snapshot length for DLT_USBPCAP
+ Use -fPIC when building for 64-bit SPARC on Linux (GitHub issue #837)
+ Fix CMake 64-bit library installation directory on some Linux
+ distributions
+ Boost the TPACKET_V3 timeout to the maximum if a timeout of 0 was
+ specified
+ Five CVE-2019-15161, CVE-2019-15162, CVE-2019-15163, CVE-2019-15164, CVE-2019-15165
+ Fixes for CVE-2018-16301, errors in pcapng reading.
+ PCAPNG reader applies some sanity checks before doing malloc().
+
+Sunday, June 24, 2018, by mcr@sandelman.ca
+ Summary for 1.9.0 libpcap release
+ Added testing system to libpcap, independent of tcpdump
+ Changes to how pcap_t is activated
+ Adding support for Large stream buffers on Endace DAG cards
+ Changes to BSD 3-clause license to 2-clause licence
+ Additions to TCP header parsing, per RFC3168
+ Add CMake build process (extensive number of changes)
+ Assign a value for OpenBSD DLT_OPENFLOW.
+ Support setting non-blocking mode before activating.
+ Extensive build support for Windows VS2010 and MINGW (many many changes, over many months)
+ Added RPCAPD support when --enable-remote (default no)
+ Add the rpcap daemon source and build instructions.
+ Put back the greasy "save the capture filter string so we can tweak it"
+ hack, that keeps libpcap from capturing rpcap traffic.
+ Fixes for captures on MacOS, utun0
+ fixes so that non-AF_INET addresses, are not ==AF_INET6 addresses.
+ Add a linktype for IBM SDLC frames containing SNA PDUs.
+ pcap_compile() in 1.8.0 and later is newly thread-safe.
+ bound snaplen for linux tpacket_v2 to ~64k
+ Make VLAN filter handle both metadata and inline tags
+ D-Bus captures can now be up to 128MB in size
+ Added LORATAP DLT value
+ Added DLT_VSOCK for http://qemu-project.org/Features/VirtioVsock
+ probe_devices() fixes not to overrun buffer for name of device
+ Add linux-specific pcap_set_protocol_linux() to allow specifying a specific capture protocol.
+ RDMA sniffing support for pcap
+ Add Nordic Semiconductor Bluetooth LE sniffer link-layer header type.
+ fixes for reading /etc/ethers
+ Make it possible to build on Windows without packet.dll.
+ Add tests for large file support on UN*X.
+ Solaris fixes to work with 2.8.6
+ configuration test now looks for header files, not capture devices present
+ Fix to work with Berkeley YACC.
+ fixes for DragonBSD compilation of pcap-netmap.c
+ Clean up the ether_hostton() stuff.
+ Add an option to disable Linux memory-mapped capture support.
+ Add DAG API support checks.
+ Add Septel, Myricom SNF, and Riverbed TurboCap checks.
+ Add checks for Linux USB, Linux Bluetooth, D-Bus, and RDMA sniffing support.
+ Add a check for hardware time stamping on Linux.
+ Don't bother supporting pre-2005 Visual Studio.
+ Increased minimum autoconf version requirement to 2.64
+ Add DLT value 273 for XRA-31 sniffer
+ Clean up handing of signal interrupts in pcap_read_nocb_remote().
+ Use the XPG 4.2 versions of the networking APIs in Solaris.
+ Fix, and better explain, the "IPv6 means IPv6, not IPv4" option setting.
+ Explicitly warn that negative packet buffer timeouts should not be used.
+ rpcapd: Add support inetd-likes, including xinetd.conf, and systemd units
+ Rename DLT_IEEE802_15_4 to DLT_IEEE802_15_4_WITHFCS.
+ Add DISPLAYPORT AUX link type
+ Remove the sunos4 kernel modules and all references to them.
+ Add more interface flags to pcap_findalldevs().
+ Summary for 1.9.0 libpcap release (to 2017-01-25 by guy@alum.mit.edu)
+ Man page improvements
+ Fix Linux cooked mode userspace filtering (GitHub pull request #429)
+ Fix compilation if IPv6 support not enabled
+ Fix some Linux memory-mapped capture buffer size issues
+ Don't fail if kernel filter can't be set on Linux (GitHub issue
+ #549)
+ Improve sorting of interfaces for pcap_findalldevs()
+ Don't list Linux usbmon devices if usbmon module isn't loaded
+ Report PCAP_ERROR_PERM_DENIED if no permission to open Linux usbmon
+ devices
+ Fix DLT_ type for Solaris IPNET devices
+ Always return an error message for errors finding DAG or Myricom
+ devices
+ If possible, don't require that a device be openable when
+ enumerating them for pcap_findalldevs()
+ Don't put incompletely-initialized addresses in the address list for
+ When finding Myricom devices, update description for regular
+ interfaces that are Myricom devices and handle SNF_FLAGS=0x2(port
+ aggregation enabled)
+ Fix compilation error in DAG support
+ Fix issues with CMake configuration
+ Add support for stream buffers larger than 2GB on newer DAG cards
+ Remove support for building against DAG versions without STREAMS
+ support (before dag-3.0.0 2007)
+
+Tuesday, Oct. 25, 2016 mcr@sandelman.ca
+ Summary for 1.8.1 libpcap release
+ Add a target in Makefile.in for Exuberant Ctags use: 'extags'.
+ Rename configure.in to configure.ac: autoconf 2.59
+ Clean up the name-to-DLT mapping table.
+ Add some newer DLT_ values: IPMI_HPM_2,ZWAVE_R1_R2,ZWAVE_R3,WATTSTOPPER_DLM,ISO_14443,RDS
+ Clarify what the return values are for both success and failure.
+ Many changes to build on windows
+ Check for the "break the loop" condition in the inner loop for TPACKET_V3.
+ Fix handling of packet count in the TPACKET_V3 inner loop: GitHub issue #493.
+ Filter out duplicate looped back CAN frames.
+ Fix the handling of loopback filters for IPv6 packets.
+ Add a link-layer header type for RDS (IEC 62106) groups.
+ Use different intermediate folders for x86 and x64 builds on Windows.
+ On Linux, handle all CAN captures with pcap-linux.c, in cooked mode.
+ Removes the need for the "host-endian" link-layer header type.
+ Compile with '-Wused-but-marked-unused' in devel mode if supported
+ Have separate DLTs for big-endian and host-endian SocketCAN headers.
+ Reflect version.h being renamed to pcap_version.h.
+ Require that version.h be generated: all build procedures we support generate version.h (autoconf, CMake, MSVC)!
+ Properly check for sock_recv() errors.
+ Re-impose some of Winsock's limitations on sock_recv().
+ Replace sprintf() with pcap_snprintf().
+ Fix signature of pcap_stats_ex_remote().
+ Initial cmake support for remote packet capture.
+ Have rpcap_remoteact_getsock() return a SOCKET and supply an "is active" flag.
+ Clean up {DAG, Septel, Myricom SNF}-only builds.
+ Do UTF-16-to-ASCII conversion into the right place.
+ pcap_create_interface() needs the interface name on Linux.
+ Clean up hardware time stamp support: the "any" device does not support any time stamp types.
+ Add support for capturing on FreeBSD usbusN interfaces.
+ Add a LINKTYPE/DLT_ value for FreeBSD USB.
+ Go back to using PCAP_API on Windows.
+ CMake support
+ Add TurboCap support from WinPcap.
+ Recognize 802.1ad nested VLAN tag in vlan filter.
+
+Thursday Sep. 3, 2015 guy@alum.mit.edu
+ Summary for 1.7.5 libpcap release
+ Man page cleanups.
+ Add some allocation failure checks.
+ Fix a number of Linux/ucLinux configure/build issues.
+ Fix some memory leaks.
+ Recognize 802.1ad nested VLAN tag in vlan filter.
+ Fix building Bluetooth Linux Monitor support with BlueZ 5.1+
+
+Saturday Jun. 27, 2015 mcr@sandelman.ca
+ Summary for 1.7.4 libpcap release
+ Include fix for GitHub issue #424 -- out of tree builds.
+
+Friday Apr. 10, 2015 guy@alum.mit.edu
+ Summary for 1.7.3 libpcap release
+ Work around a Linux bonding driver bug.
+
+Thursday Feb. 12, 2015 guy@alum.mit.edu/mcr@sandelman.ca
+ Summary for 1.7.2 libpcap release
+ Support for filtering Geneve encapsulated packets.
+ Generalize encapsulation handling, fixing some bugs.
+ Don't add null addresses to address lists.
+ Add pcap_dump_open_append() to open for appending.
+ Fix the swapping of isochronous descriptors in Linux USB.
+ Attempt to handle TPACKET_V1 with 32-bit userland and 64-bit kernel.
+
+Wednesday Nov. 12, 2014 guy@alum.mit.edu/mcr@sandelman.ca
+ Summary for 1.7.0 libpcap release
+ Fix handling of zones for BPF on Solaris
+ new DLT for ZWAVE
+ clarifications for read timeouts.
+ Use BPF extensions in compiled filters, fixing VLAN filters
+ some fixes to compilation without stdint.h
+ EBUSY can now be returned by SNFv3 code.
+ Fix the range checks in BPF loads
+ Various DAG fixes.
+ Various Linux fixes.
+
+Monday Aug. 12, 2014 guy@alum.mit.edu
+ Summary for 1.6.2 libpcap release
+ Don't crash on filters testing a non-existent link-layer type
+ field.
+ Fix sending in non-blocking mode on Linux with memory-mapped
+ capture.
+ Fix timestamps when reading pcap-ng files on big-endian
+ machines.
+
+Saturday Jul. 19, 2014 mcr@sandelman.ca
+ Summary for 1.6.1 libpcap release
+ some fixes for the any device
+ changes for how --enable-XXX (--enable-sniffing, --enable-can) works
+
+Wednesday Jul. 2, 2014 mcr@sandelman.ca
+ Summary for 1.6.0 libpcap release
+ Don't support D-Bus sniffing on OS X
+ fixes for byte order issues with NFLOG captures
+ Handle using cooked mode for DLT_NETLINK in activate_new().
+ on platforms where you can not capture on down interfaces, do not list them
+ but: do list interfaces which are down, if you can capture on them!
+
+Wednesday December 18, 2013 guy@alum.mit.edu
+Summary for 1.5.3 libpcap release
+ Don't let packets that don't match the current filter get to the
+ application when TPACKET_V3 is used. (GitHub issue #331)
+ Fix handling of pcap_loop()/pcap_dispatch() with a packet count
+ of 0 on some platforms (including Linux with TPACKET_V3).
+ (GitHub issue #333)
+ Work around TPACKET_V3 deficiency that causes packets to be lost
+ when a timeout of 0 is specified. (GitHub issue #335)
+ Man page formatting fixes.
+
+Wednesday December 4, 2013 guy@alum.mit.edu
+Summary for 1.5.2 libpcap release
+ Fix libpcap to work when compiled with TPACKET_V3 support and
+ running on a kernel without TPACKET_V3 support. (GitHub
+ issue #329)
+
+Wednesday November 20, 2013 guy@alum.mit.edu
+Summary for 1.5.1 libpcap release
+ Report an error, rather than crashing, if an IPv6 address is
+ used for link-layer filtering. (Wireshark bug 9376)
+
+Wednesday October 30, 2013 guy@alum.mit.edu
+Summary for 1.5.0 libpcap release
+ TPACKET_V3 support added for Linux
+ Point users to the the-tcpdump-group repository on GitHub rather
+ than the mcr repository
+ Checks added for malloc()/realloc()/etc. failures
+ Fixed build on Solaris 11
+ Support filtering filtering E1 SS7 traffic on MTP2 layer Annex A
+ Use "ln -s" to link man pages by default
+ Add support for getting nanosecond-resolution time stamps when
+ capturing and reading capture files
+ Many changes to autoconf to deal better with non-GCC compilers
+ added many new DLT types
+
+Saturday April 6, 2013 guy@alum.mit.edu
+Summary for 1.4.0 libpcap release
+ Add netfilter/nfqueue interface.
+ If we don't have support for IPv6 address resolution, support,
+ in filter expressions, what IPv6 stuff we can.
+ Fix pcap-config to include -lpthread if canusb support is
+ present
+ Try to fix "pcap_parse not defined" problems when --without-flex
+ and --without-bison are used when you have Flex and Bison
+ Fix some issues with the pcap_loop man page.
+ Fix pcap_getnonblock() and pcap_setnonblock() to fill in the
+ supplied error message buffer
+ Fix typo that, it appeared, would cause pcap-libdlpi.c not to
+ compile (perhaps systems with libdlpi also have BPF and use
+ that instead)
+ Catch attempts to call pcap_compile() on a non-activated pcap_t
+ Fix crash on Linux with CAN-USB support without usbfs
+ Fix addition of VLAN tags for Linux cooked captures
+ Check for both EOPNOTSUPP and EINVAL after SIOCETHTOOL ioctl, so
+ that the driver can report either one if it doesn't support
+ SIOCETHTOOL
+ Add DLT_INFINIBAND and DLT_SCTP
+ Describe "proto XXX" and "protochain XXX" in the pcap-filter man
+ page
+ Handle either directories, or symlinks to directories, that
+ correspond to interfaces in /sys/class/net
+ Fix handling of VLAN tag insertion to check, on Linux 3.x
+ kernels, for VLAN tag valid flag
+ Clean up some man pages
+ Support libnl3 as well as libnl1 and libnl2 on Linux
+ Fix handling of Bluetooth devices on 3.x Linux kernels
+
+Friday March 30, 2012. mcr@sandelman.ca
+Summary for 1.3.0 libpcap release
+ Handle DLT_PFSYNC in {FreeBSD, other *BSD+Mac OS X, other}.
+ Linux: Don't fail if netfilter isn't enabled in the kernel.
+ Add new link-layer type for NFC Forum LLCP.
+ Put the CANUSB stuff into EXTRA_DIST, so it shows up in the release tarball.
+ Add LINKTYPE_NG40/DLT_NG40.
+ Add DLT_MPEG_2_TS/LINKTYPE_MPEG_2_TS for MPEG-2 transport streams.
+ [PATCH] Fix AIX-3.5 crash with read failure during stress
+ AIX fixes.
+ Introduce --disable-shared configure option.
+ Added initial support for canusb devices.
+ Include the pcap(3PCAP) additions as 1.2.1 changes.
+ many updates to documentation: pcap.3pcap.in
+ Improve 'inbound'/'outbound' capture filters under Linux.
+ Note the cleanup of handling of new DLT_/LINKTYPE_ values.
+ On Lion, don't build for PPC.
+ For mac80211 devices we need to clean up monitor mode on exit.
+
+Friday December 9, 2011. guy@alum.mit.edu.
+Summary for 1.2.1 libpcap release
+ Update README file.
+ Fix typoes in README.linux file.
+ Clean up some compiler warnings.
+ Fix Linux compile problems and tests for ethtool.h.
+ Treat Debian/kFreeBSD and GNU/Hurd as systems with GNU
+ toolchains.
+ Support 802.1 QinQ as a form of VLAN in filters.
+ Treat "carp" as equivalent to "vrrp" in filters.
+ Fix code generated for "ip6 protochain".
+ Add some new link-layer header types.
+ Support capturing NetFilter log messages on Linux.
+ Clean up some error messages.
+ Turn off monitor mode on exit for mac80211 interfaces on Linux.
+ Fix problems turning monitor mode on for non-mac80211 interfaces
+ on Linux.
+ Properly fail if /sys/class/net or /proc/net/dev exist but can't
+ be opened.
+ Fail if pcap_activate() is called on an already-activated
+ pcap_t, and add a test program for that.
+ Fix filtering in pcap-ng files.
+ Don't build for PowerPC on Mac OS X Lion.
+ Simplify handling of new DLT_/LINKTYPE_ values.
+ Expand pcap(3PCAP) man page.
+
+Sunday July 24, 2011. mcr@sandelman.ca.
+Summary for 1.2 libpcap release
+ All of the changes listed below for 1.1.1 and 1.1.2.
+ Changes to error handling for pcap_findalldevs().
+ Fix the calculation of the frame size in memory-mapped captures.
+ Add a link-layer header type for STANAG 5066 D_PDUs.
+ Add a link-layer type for a variant of 3GPP TS 27.010.
+ Noted real nature of LINKTYPE_ARCNET.
+ Add a link-layer type for DVB-CI.
+ Fix configure-script discovery of VLAN acceleration support.
+ see http://netoptimizer.blogspot.com/2010/09/tcpdump-vs-vlan-tags.html
+ Linux, HP-UX, AIX, NetBSD and OpenBSD compilation/conflict fixes.
+ Protect against including AIX 5.x's <net/bpf.h> having been included.
+ Add DLT_DBUS, for raw D-Bus messages.
+ Treat either EPERM or EACCES as "no soup for you".
+ Changes to permissions on DLPI systems.
+ Add DLT_IEEE802_15_4_NOFCS for 802.15.4 interfaces.
+
+Fri. August 6, 2010. guy@alum.mit.edu.
+Summary for 1.1.2 libpcap release
+ Return DLT_ values, not raw LINKTYPE_ values from
+ pcap_datalink() when reading pcap-ng files
+ Add support for "wlan ra" and "wlan ta", to check the RA and TA
+ of WLAN frames that have them
+ Don't crash if "wlan addr{1,2,3,4}" are used without 802.11
+ headers
+ Do filtering on USB and Bluetooth capturing
+ On FreeBSD/SPARC64, use -fPIC - it's apparently necessary
+ Check for valid port numbers (fit in a 16-bit unsigned field) in
+ "port" filters
+ Reject attempts to put savefiles into non-blocking mode
+ Check for "no such device" for the "get the media types" ioctl
+ in *BSD
+ Improve error messages from bpf_open(), and let it do the error
+ handling
+ Return more specific errors from pcap_can_set_rfmon(); fix
+ documentation
+ Update description fetching code for FreeBSD, fix code for
+ OpenBSD
+ Ignore /sys/net/dev files if we get ENODEV for them, not just
+ ENXIO; fixes handling of bonding devices on Linux
+ Fix check for a constant 0 argument to BPF_DIV
+ Use the right version of ar when cross-building
+ Free any filter set on a savefile when the savefile is closed
+ Include the CFLAGS setting when configure was run in the
+ compiler flags
+ Add support for 802.15.4 interfaces on Linux
+
+Thu. April 1, 2010. guy@alum.mit.edu.
+Summary for 1.1.1 libpcap release
+ Update CHANGES to reflect more of the changes in 1.1.0.
+ Fix build on RHEL5.
+ Fix shared library build on AIX.
+
+Thu. March 11, 2010. ken@netfunctional.ca/guy@alum.mit.edu.
+Summary for 1.1.0 libpcap release
+ Add SocketCAN capture support
+ Add Myricom SNF API support
+ Update Endace DAG and ERF support
+ Add support for shared libraries on Solaris, HP-UX, and AIX
+ Build, install, and un-install shared libraries by default;
+ don't build/install shared libraries on platforms we don't support
+ Fix building from a directory other than the source directory
+ Fix compiler warnings and builds on some platforms
+ Update config.guess and config.sub
+ Support monitor mode on mac80211 devices on Linux
+ Fix USB memory-mapped capturing on Linux; it requires a new DLT_
+ value
+ On Linux, scan /sys/class/net for devices if we have it; scan
+ it, or /proc/net/dev if we don't have /sys/class/net, even if
+ we have getifaddrs(), as it'll find interfaces with no
+ addresses
+ Add limited support for reading pcap-ng files
+ Fix BPF driver-loading error handling on AIX
+ Support getting the full-length interface description on FreeBSD
+ In the lexical analyzer, free up any addrinfo structure we got back
+ from getaddrinfo().
+ Add support for BPF and libdlpi in OpenSolaris (and SXCE)
+ Hyphenate "link-layer" everywhere
+ Add /sys/kernel/debug/usb/usbmon to the list of usbmon locations
+ In pcap_read_linux_mmap(), if there are no frames available, call
+ poll() even if we're in non-blocking mode, so we pick up
+ errors, and check for the errors in question.
+ Note that poll() works on BPF devices is Snow Leopard
+ If an ENXIO or ENETDOWN is received, it may mean the device has
+ gone away. Deal with it.
+ For BPF, raise the default capture buffer size to from 32k to 512k
+ Support ps_ifdrop on Linux
+ Added a bunch of #ifdef directives to make wpcap.dll (WinPcap) compile
+ under cygwin.
+ Changes to Linux mmapped captures.
+ Fix bug where create_ring would fail for particular snaplen and
+ buffer size combinations
+ Update pcap-config so that it handles libpcap requiring
+ additional libraries
+ Add workaround for threadsafeness on Windows
+ Add missing mapping for DLT_ENC <-> LINKTYPE_ENC
+ DLT: Add DLT_CAN_SOCKETCAN
+ DLT: Add Solaris ipnet
+ Don't check for DLT_IPNET if it's not defined
+ Add link-layer types for Fibre Channel FC-2
+ Add link-layer types for Wireless HART
+ Add link-layer types for AOS
+ Add link-layer types for DECT
+ Autoconf fixes (AIX, HP-UX, OSF/1, Tru64 cleanups)
+ Install headers unconditionally, and include vlan.h/bluetooth.h if
+ enabled
+ Autoconf fixes+cleanup
+ Support enabling/disabling bluetooth (--{en,dis}able-bluetooth)
+ Support disabling SITA support (--without-sita)
+ Return -1 on failure to create packet ring (if supported but
+ creation failed)
+ Fix handling of 'any' device, so that it can be opened, and no longer
+ attempt to open it in Monitor mode
+ Add support for snapshot length for USB Memory-Mapped Interface
+ Fix configure and build on recent Linux kernels
+ Fix memory-mapped Linux capture to support pcap_next() and
+ pcap_next_ex()
+ Fixes for Linux USB capture
+ DLT: Add DLT_LINUX_EVDEV
+ DLT: Add DLT_GSMTAP_UM
+ DLT: Add DLT_GSMTAP_ABIS
+
+Mon. October 27, 2008. ken@netfunctional.ca. Summary for 1.0.0 libpcap release
+ Compile with IPv6 support by default
+ Compile with large file support on by default
+ Add pcap-config script, which deals with -I/-L flags for compiling
+ DLT: Add IPMB
+ DLT: Add LAPD
+ DLT: Add AX25 (AX.25 w/KISS header)
+ DLT: Add JUNIPER_ST
+ 802.15.4 support
+ Variable length 802.11 header support
+ X2E data type support
+ SITA ACN Interface support - see README.sita
+ Support for memory-mapped capture on Linux
+ Support for zerocopy BPF on platforms that support it
+ Support for setting buffer size when opening devices
+ Support for setting monitor mode when opening 802.11 devices
+ Better support for dealing with VLAN tagging/stripping on Linux
+ Fix dynamic library support on OSX
+ Return PCAP_ERROR_IFACE_NOT_UP if the interface isn't 'UP', so applications
+ can print better diagnostic information
+ Return PCAP_ERROR_PERM_DENIED if we don't have permission to open a device, so
+ applications can tell the user they need to go play with permissions
+ On Linux, ignore ENETDOWN so we can continue to capture packets if the
+ interface goes down and comes back up again.
+ On Linux, support new tpacket frame headers (2.6.27+)
+ On Mac OS X, add scripts for changing permissions on /dev/bpf* and launchd plist
+ On Solaris, support 'passive mode' on systems that support it
+ Fixes to autoconf and general build environment
+ Man page reorganization + cleanup
+ Autogenerate VERSION numbers better
+
+Mon. September 10, 2007. ken@xelerance.com. Summary for 0.9.8 libpcap release
+ Change build process to put public libpcap headers into pcap subir
+ DLT: Add value for IPMI IPMB packets
+ DLT: Add value for u10 Networks boards
+ Require <net/pfvar.h> for pf definitions - allows reading of pflog formatted
+ libpcap files on an OS other than where the file was generated
+
+Wed. April 25, 2007. ken@xelerance.com. Summary for 0.9.6 libpcap release
+
+ Put the public libpcap headers into a pcap subdirectory in both the
+ source directory and the target include directory, and have include
+ files at the top-level directory to include those headers, for
+ backwards compatibility.
+ Add Bluetooth support
+ Add USB capturing support on Linux
+ Add support for the binary USB sniffing interface in Linux
+ Add support for new FreeBSD BIOCSDIRECTION ioctl
+ Add additional filter operations for 802.11 frame types
+ Add support for filtering on MTP2 frame types
+ Propagate some changes from the main branch, so the x.9 branch has
+ all the DLT_ and LINKTYPE_ values that the main branch does
+ Reserved a DLT_ and SAVEFILE_ value for PPI (Per Packet Info)
+ encapsulated packets
+ Add LINKTYPE_ for IEEE 802.15.4, with address fields padded as done
+ by Linux drivers
+ Add LINKTYPE_ value corresponding to DLT_IEEE802_16_MAC_CPS.
+ Add DLT for IEEE 802.16 (WiMAX) MAC Common Part Sublayer
+ Add DLT for Bluetooth HCI UART transport layer
+ When building a shared library, build with "-fPIC" on Linux to support x86_64
+ Link with "$(CC) -shared" rather than "ld -shared" when building a
+ ".so" shared library
+ Add support for autoconf 2.60
+ Fixes to discard unread packets when changing filters
+ Changes to handle name changes in the DAG library resulting from
+ switching to libtool.
+ Add support for new DAG ERF types.
+ Add an explicit "-ldag" when building the shared library, so the DAG
+ library dependency is explicit.
+ Mac OSX fixes for dealing with "wlt" devices
+ Fixes in add_or_find_if() & pcap_findalldevs() to optimize generating
+ device lists
+ Fixed a bug in pcap_open_live(). The return value of PacketSetHwFilter
+ was not checked.
+
+Tue. September 19, 2006. ken@xelerance.com. Summary for 0.9.5 libpcap release
+
+ Support for LAPD frames with vISDN
+ Support for ERF on channelized T1/E1 cards via DAG API
+ Fix capitalization that caused issues crossc compiling on Linux
+ Better failure detection on PacketGetAdapterNames()
+ Fixes for MPLS packet generation (link layer)
+ OP_PACKET now matches the beginning of the packet, instead of
+ beginning+link-layer
+ Add DLT/LINKTYPE for carrying FRF.16 Multi-link Frame Relay
+ Fix allocation of buffer for list of link-layer types
+ Added a new DLT and LINKTYPE value for ARINC 653 Interpartition Communcation Messages
+ Fixed a typo in a DLT value: it should start with DLT_ and not LINKTYPE_
+ Redefined DLT_CAN20B and LINKTYPE_CAN20B as #190 (as this is the right value for CAN).
+ Added definition for DLT_A429 and LINKTYPE_A429 as #184.
+ Added a new DLT and LINKTYPE value for CAN v2.0B frames.
+ Add support for DLT_JUNIPER_VP.
+ Don't double-count received packets on Linux systems that
+ support the PACKET_STATISTICS getsockopt() argument on
+ PF_PACKET sockets.
+ Add support for DLT_IEEE802_11 and DLT_IEEE802_11_RADIO link
+ layers in Windows
+ Add support to build libpcap.lib and wpcap.dll under Cygnus and
+ MingW32.
+
+Mon. September 5, 2005. ken@xelerance.com. Summary for 0.9.4 libpcap release
+
+ Support for radiotap on Linux (Mike Kershaw)
+ Fixes for HP-UX
+ Support for additional Juniper link-layer types
+ Fixes for filters on MPLS-encapsulated packets
+ "vlan" filter fixed
+ "pppoed" and "pppoes" filters added; the latter modifies later
+ parts of the filter expression to look at the PPP headers and
+ headers in the PPP payload
+
+Tue. July 5, 2005. ken@xelerance.com. Summary for 0.9.3 libpcap release
+
+ Fixes for compiling on nearly every platform,
+ including improved 64bit support
+ MSDOS Support
+ Add support for sending packets
+ OpenBSD pf format support
+ IrDA capture (Linux only)
+
+Tue. March 30, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.3 release
+
+ Fixed minor problem in gencode.c that would appear on 64-bit
+ platforms.
+ Version number is now sane.
+
+Mon. March 29, 2004. mcr@sandelman.ottawa.on.ca. Summary for 3.8.2 release
+
+ updates for autoconf 2.5
+ fixes for ppp interfaces for freebsd 4.1
+ pcap gencode can generate code for 802.11, IEEE1394, and pflog.
+
+Wed. November 12, 2003. mcr@sandelman.ottawa.on.ca. Summary for 0.8 release
+
+ added pcap_findalldevs()
+ Win32 patches from NetGroup, Politecnico di Torino (Italy)
+ OpenBSD pf, DLT_PFLOG added
+ Many changes to ATM support.
+ lookup pcap_lookupnet()
+ Added DLT_ARCNET_LINUX, DLT_ENC, DLT_IEEE802_11_RADIO, DLT_SUNATM,
+ DLT_IP_OVER_FC, DLT_FRELAY, others.
+ Sigh. More AIX wonderfulness.
+ Document updates.
+ Changes to API: pcap_next_ex(), pcap_breakloop(), pcap_dump_flush(),
+ pcap_list_datalinks(), pcap_set_datalink(),
+ pcap_lib_version(), pcap_datalink_val_to_name(),
+ pcap_datalink_name_to_val(), new error returns.
+
+Tuesday, February 25, 2003. fenner@research.att.com. 0.7.2 release
+
+ Support link types that use 802.2 always, never, and sometimes.
+ Don't decrease the size of the BPF buffer from the default.
+ Support frame relay.
+ Handle 32-bit timestamps in DLPI, and pass the right buffer size.
+ Handle Linux systems with modern kernel but without
+ SOL_PACKET in the userland headers.
+ Linux support for ARPHRD_RAWHDLC.
+ Handle 32-bit timestamps in snoop.
+ Support eg (Octane/O2xxx/O3xxx Gigabit) devices.
+ Add new reserved DLT types.
+
+Monday October 23, 2001. mcr@sandelman.ottawa.on.ca. Summary for 0.7 release
+
+ Added pcap_findalldevs() call to get list of interfaces in a MI way.
+
+ pcap_stats() has been documented as to what its counters mean on
+ each platform.
+
+Tuesday January 9, 2001. guy@alum.mit.edu. Summary for 0.6 release
+
+ New Linux libpcap implementation, which, in 2.2 and later
+ kernels, uses PF_PACKET sockets and supports kernel packet
+ filtering (if compiled into the kernel), and supports the "any"
+ device for capturing on all interfaces. Cleans up promiscuous
+ mode better on pre-2.2 kernels, and has various other fixes
+ (handles 2.4 ARPHRD_IEEE802_TR, handles ISDN devices better,
+ doesn't show duplicate packets on loopback interface, etc.).
+
+ Fixed HP-UX libpcap implementation to correctly get the PPA for
+ an interface, to allow interfaces to be opened by interface name.
+
+ libpcap savefiles have system-independent link-layer type values
+ in the header, rather than sometimes platform-dependent DLT_
+ values, to make it easier to exchange capture files between
+ different OSes.
+
+ Non-standard capture files produced by some Linux tcpdumps, e.g.
+ the one from Red Hat Linux 6.2 and later, can now be read.
+
+ Updated autoconf stock files.
+
+ Filter expressions can filter on VLAN IDs and various OSI
+ protocols, and work on Token Ring (with non-source-routed
+ packets).
+
+ "pcap_open_dead()" added to allow compiling filter expressions
+ to pcap code without opening a capture device or capture file.
+
+ Header files fixed to allow use in C++ programs.
+
+ Removed dependancy on native headers for packet layout.
+ Removed Linux specific headers that were shipped.
+
+ Security fixes: Strcpy replaced with strlcpy, sprintf replaced
+ with snprintf.
+
+ Fixed bug that could cause subsequent "pcap_compile()"s to fail
+ erroneously after one compile failed.
+
+ Assorted other bug fixes.
+
+ README.aix and README.linux files added to describe
+ platform-specific issues.
+
+ "getifaddrs()" rather than SIOCGIFCONF used, if available.
+
+v0.5 Sat Jun 10 11:09:15 PDT 2000
+
+itojun@iijlab.net
+- Brought in KAME IPv6/IPsec bpf compiler.
+- Fixes for NetBSD.
+- Support added for OpenBSD DLT_LOOP and BSD/OS DLT_C_HDLC (Cisco HDLC),
+ and changes to work around different BSDs having different DLT_ types
+ with the same numeric value.
+
+Assar Westerlund <assar@sics.se>
+- Building outside the source code tree fixed.
+- Changed to write out time stamps with 32-bit seconds and microseconds
+ fields, regardless of whether those fields are 32 bits or 64 bits in
+ the OS's native "struct timeval".
+- Changed "pcap_lookupdev()" to dynamically grow the buffer into which
+ the list of interfaces is read as necessary in order to hold the
+ entire list.
+
+Greg Troxel <gdt@ir.bbn.com>
+- Added a new "pcap_compile_nopcap()", which lets you compile a filter
+ expression into a BPF program without having an open live capture or
+ capture file.
+
+v0.4 Sat Jul 25 12:40:09 PDT 1998
+
+- Fix endian problem with DLT_NULL devices. From FreeBSD via Bill
+ Fenner (fenner@parc.xerox.com)
+
+- Fix alignment problem with FDDI under DLPI. This was causing core
+ dumps under Solaris.
+
+- Added configure options to disable flex and bison. Resulted from a
+ bug report by barnett@grymoire.crd.ge.com (Bruce Barnett). Also added
+ options to disable gcc and to force a particular packet capture type.
+
+- Added support for Fore ATM interfaces (qaa and fa) under IRIX. Thanks
+ to John Hawkinson (jhawk@mit.edu)
+
+- Change Linux PPP and SLIP to use DLT_RAW since the kernel does not
+ supply any "link layer" data.
+
+- Change Linux to use SIOCGIFHWADDR ioctl to determine link layer type.
+ Thanks to Thomas Sailer (sailer@ife.ee.ethz.ch)
+
+- Change IRIX PPP to use DLT_RAW since the kernel does not supply any
+ "link layer" data.
+
+- Modified to support the new BSD/OS 2.1 PPP and SLIP link layer header
+ formats.
+
+- Added some new SGI snoop interface types. Thanks to Steve Alexander
+ (sca@refugee.engr.sgi.com)
+
+- Fixes for HP-UX 10.20 (which is similar to HP-UX 9). Thanks to
+ Richard Allen (ra@hp.is) and Steinar Haug (sthaug@nethelp.no)
+
+- Fddi supports broadcast as reported by Jeff Macdonald
+ (jeff@iacnet.com). Also correct ieee802 and arcnet.
+
+- Determine Linux pcap buffer size at run time or else it might not be
+ big enough for some interface types (e.g. FDDI). Thanks to Jes
+ Sorensen (Jes.Sorensen@cern.ch)
+
+- Fix some linux alignment problems.
+
+- Document promisc argument to pcap_open_live(). Reported by Ian Marsh
+ (ianm@sics.se)
+
+- Support Metricom radio packets under Linux. Thanks to Kevin Lai
+ (laik@gunpowder.stanford.edu)
+
+- Bind to interface name under Linux to avoid packets from multiple
+ interfaces on multi-homed hosts. Thanks to Kevin Lai
+ (laik@gunpowder.stanford.edu)
+
+- Change L_SET to SEEK_SET for HP-UX. Thanks to Roland Roberts
+ (rroberts@muller.com)
+
+- Fixed an uninitialized memory reference found by Kent Vander Velden
+ (graphix@iastate.edu)
+
+- Fixed lex pattern for IDs to allow leading digits. As reported by
+ Theo de Raadt (deraadt@cvs.openbsd.org)
+
+- Fixed Linux include file problems when using GNU libc.
+
+- Ifdef ARPHRD_FDDI since not all versions of the Linux kernel have it.
+ Reported reported by Eric Jacksch (jacksch@tenebris.ca)
+
+- Fixed bug in pcap_dispatch() that kept it from returning on packet
+ timeouts.
+
+- Changed ISLOOPBACK() macro when IFF_LOOPBACK isn't available to check
+ for "lo" followed by an eos or digit (newer versions of Linux
+ apparently call the loopback "lo" instead of "lo0").
+
+- Fixed Linux networking include files to use ints instead of longs to
+ avoid problems with 64 bit longs on the alpha. Thanks to Cristian
+ Gafton (gafton@redhat.com)
+
+v0.3 Sat Nov 30 20:56:27 PST 1996
+
+- Added Linux support.
+
+- Fixed savefile bugs.
+
+- Solaris x86 fix from Tim Rylance (t.rylance@elsevier.nl)
+
+- Add support for bpf kernel port filters.
+
+- Remove duplicate atalk protocol table entry. Thanks to Christian
+ Hopps (chopps@water.emich.edu)
+
+- Fixed pcap_lookupdev() to ignore nonexistent devices. This was
+ reported to happen under BSD/OS by David Vincenzetti
+ (vince@cryptonet.it)
+
+- Avoid solaris compiler warnings. Thanks to Bruce Barnett
+ (barnett@grymoire.crd.ge.com)
+
+v0.2.1 Sun Jul 14 03:02:26 PDT 1996
+
+- Fixes for HP-UX 10. Thanks in part to to Thomas Wolfram
+ (wolf@prz.tu-berlin.de) and Rick Jones (raj@hpisrdq.cup.hp.com)
+
+- Added support for SINIX. Thanks to Andrej Borsenkow
+ (borsenkow.msk@sni.de)
+
+- Fixes for AIX (although this system is not yet supported). Thanks to
+ John Hawkinson (jhawk@mit.edu)
+
+- Use autoconf's idea of the top level directory in install targets.
+ Thanks to John Hawkinson.
+
+- Add missing autoconf packet capture result message. Thanks to Bill
+ Fenner (fenner@parc.xerox.com)
+
+- Fixed padding problems in the pf module.
+
+- Fixed some more alignment problems on the alpha.
+
+- Added explicit netmask support. Thanks to Steve Nuchia
+ (steve@research.oknet.com)
+
+- Fixed to handle raw ip addresses such as 0.0.0.1 without "left
+ justifing"
+
+- Add "sca" keyword (for DEC cluster services) as suggested by Terry
+ Kennedy (terry@spcvxa.spc.edu)
+
+- Add "atalk" keyword as suggested by John Hawkinson.
+
+- Add "igrp" keyword.
+
+- Fixed HID definition in grammar.y to be a string, not a value.
+
+- Use $CC when checking gcc version. Thanks to Carl Lindberg
+ (carl_lindberg@blacksmith.com)
+
+- Removed obsolete reference to pcap_immediate() from the man page.
+ Michael Stolarchuk (mts@terminator.rs.itd.umich.edu)
+
+- DLT_NULL has a 4 byte family header. Thanks to Jeffrey Honig
+ (jch@bsdi.com)
+
+v0.2 Sun Jun 23 02:28:42 PDT 1996
+
+- Add support for HP-UX. Resulted from code contributed by Tom Murray
+ (tmurray@hpindck.cup.hp.com) and Philippe-Andri Prindeville
+ (philipp@res.enst.fr)
+
+- Update INSTALL with a reminder to install include files. Thanks to
+ Mark Andrews (mandrews@aw.sgi.com)
+
+- Fix bpf compiler alignment bug on the alpha.
+
+- Use autoconf to detect architectures that can't handle misaligned
+ accesses.
+
+- Added loopback support for snoop. Resulted from report Steve
+ Alexander (sca@engr.sgi.com)
+
+v0.1 Fri Apr 28 18:11:03 PDT 1995
+
+- Fixed compiler and optimizer bugs. The BPF filter engine uses unsigned
+ comparison operators, while the code generator and optimizer assumed
+ signed semantics in several places. Thanks to Charlie Slater
+ (cslater@imatek.com) for pointing this out.
+
+- Removed FDDI ifdef's, they aren't really needed. Resulted from report
+ by Gary Veum (veum@boa.gsfc.nasa.gov).
+
+- Add pcap-null.c which allows offline use of libpcap on systems that
+ don't support live package capture. This feature resulting from a
+ request from Jan van Oorschot (j.p.m.voorschot@et.tudelft.nl).
+
+- Make bpf_compile() reentrant. Fix thanks to Pascal Hennequin
+ (Pascal.Hennequin@hugo.int-evry.fr).
+
+- Port to GNU autoconf.
+
+- Fix pcap-dlpi.c to work with isdn. Resulted from report by Flemming
+ Johansen (fsj@csd.cri.dk).
+
+- Handle multi-digit interface unit numbers (aka ppa's) under dlpi.
+ Resulted from report by Daniel Ehrlich (ehrlich@cse.psu.edu).
+
+- Fix pcap-dlpi.c to work in non-promiscuous mode. Resulted from report
+ by Jeff Murphy (jcmurphy@acsu.buffalo.edu).
+
+- Add support for "long jumps". Thanks to Jeffrey Mogul
+ (mogul@pa.dec.com).
+
+- Fix minor problems when compiling with BDEBUG as noticed by Scott
+ Bertilson (scott@unet.umn.edu).
+
+- Declare sys_errlist "const char *const" to avoid problems under
+ FreeBSD. Resulted from report by jher@eden.com.
+
+v0.0.6 Fri Apr 28 04:07:13 PDT 1995
+
+- Add missing variable declaration missing from 0.0.6
+
+v0.0.5 Fri Apr 28 00:22:21 PDT 1995
+
+- Workaround for problems when pcap_read() returns 0 due to the timeout
+ expiring.
+
+v0.0.4 Thu Apr 20 20:41:48 PDT 1995
+
+- Change configuration to not use gcc v2 flags with gcc v1.
+
+- Fixed a bug in pcap_next(); if pcap_dispatch() returns 0, pcap_next()
+ should also return 0. Thanks to Richard Stevens (rstevens@noao.edu).
+
+- Fixed configure to test for snoop before dlpi to avoid problems under
+ IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com).
+
+- Hack around deficiency in Ultrix's make.
+
+- Fix two bugs related to the Solaris pre-5.3.2 bufmod bug; handle
+ savefiles that have more than snapshot bytes of data in them (so we
+ can read old savefiles) and avoid writing such files.
+
+- Added checkioctl which is used with gcc to check that the
+ "fixincludes" script has been run.
+
+v0.0.3 Tue Oct 18 18:13:46 PDT 1994
+
+- Fixed configure to test for snoop before dlpi to avoid problems under
+ IRIX 5. Thanks to J. Eric Townsend (jet@abulafia.genmagic.com).
+
+v0.0.2 Wed Oct 12 20:56:37 PDT 1994
+
+- Implement timeout in the dlpi pcap_open_live(). Thanks to Richard
+ Stevens.
+
+- Determine pcap link type from dlpi media type. Resulted from report
+ by Mahesh Jethanandani (mahesh@npix.com).
+
+v0.0.1 Fri Jun 24 14:50:57 PDT 1994
+
+- Fixed bug in nit_setflags() in pcap-snit.c. The streams ioctl timeout
+ wasn't being initialized sometimes resulting in an "NIOCSFLAGS:
+ Invalid argument" error under OSF/1. Reported by Matt Day
+ (mday@artisoft.com) and Danny Mitzel (dmitzel@whitney.hitc.com).
+
+- Turn on FDDI support by default.
+
+v0.0 Mon Jun 20 19:20:16 PDT 1994
+
+- Initial release.
+
+- Fixed bug with greater/less keywords, reported by Mark Andrews
+ (mandrews@alias.com).
+
+- Fix bug where '|' was defined as BPF_AND instead of BPF_OR, reported
+ by Elan Amir (elan@leeb.cs.berkeley.edu).
+
+- Machines with little-endian byte ordering are supported thanks to
+ Jeff Mogul.
+
+- Add hack for version 2.3 savefiles which don't have caplen and len
+ swapped thanks to Vern Paxson.
+
+- Added "&&" and "||" aliases for "and" and "or" thanks to Vern Paxson.
+
+- Added length, inbound and outbound keywords.
diff --git a/lib/libpcap/libpcap/CMakeLists.txt b/lib/libpcap/libpcap/CMakeLists.txt
new file mode 100644
index 0000000..b26e273
--- /dev/null
+++ b/lib/libpcap/libpcap/CMakeLists.txt
@@ -0,0 +1,2371 @@
+cmake_minimum_required(VERSION 2.8.6)
+
+#
+# Apple doesn't build with an install_name starting with @rpath, and
+# neither do we with autotools; don't do so with CMake, either, and
+# suppress warnings about that.
+#
+if(POLICY CMP0042)
+ cmake_policy(SET CMP0042 OLD)
+endif()
+
+set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules)
+
+project(pcap)
+
+#
+# Try to enable as many C99 features as we can.
+# At minimum, we want C++/C99-style // comments.
+#
+# Newer versions of compilers might default to supporting C99, but older
+# versions may require a special flag.
+#
+# Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect,
+# so, unless and until we require CMake 3.1 or later, we have to do it
+# ourselves on pre-3.1 CMake, so we just do it ourselves on all versions
+# of CMake.
+#
+# Note: with CMake 3.1 through 3.5, the only compilers for which CMake
+# handles CMAKE_C_STANDARD are GCC and Clang. 3.6 adds support only
+# for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and
+# 3.10 adds support for Cray C and IAR C, but no version of CMake has
+# support for HP C. Therefore, even if we use CMAKE_C_STANDARD with
+# compilers for which CMake supports it, we may still have to do it
+# ourselves on other compilers.
+#
+# See the CMake documentation for the CMAKE_<LANG>_COMPILER_ID variables
+# for a list of compiler IDs.
+#
+# We don't worry about MSVC; it doesn't have such a flag - either it
+# doesn't support the C99 features we need at all, or it supports them
+# regardless of the compiler flag.
+#
+# XXX - this just tests whether the option works and adds it if it does.
+# We don't test whether it's necessary in order to get the C99 features
+# that we use; if we ever have a user who tries to compile with a compiler
+# that can't be made to support those features, we can add a test to make
+# sure we actually *have* C99 support.
+#
+include(CheckCCompilerFlag)
+macro(check_and_add_compiler_option _option)
+ message(STATUS "Checking C compiler flag ${_option}")
+ string(REPLACE "=" "-" _temp_option_variable ${_option})
+ string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable})
+ check_c_compiler_flag("${_option}" ${_option_variable})
+ if(${${_option_variable}})
+ set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}")
+ endif()
+endmacro()
+
+set(C_ADDITIONAL_FLAGS "")
+if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR
+ CMAKE_C_COMPILER_ID MATCHES "Clang")
+ check_and_add_compiler_option("-std=gnu99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "XL")
+ #
+ # We want support for extensions picked up for GNU C compatibility,
+ # so we use -qlanglvl=extc99.
+ #
+ check_and_add_compiler_option("-qlanglvl=extc99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "HP")
+ check_and_add_compiler_option("-AC99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "Sun")
+ check_and_add_compiler_option("-xc99")
+elseif(CMAKE_C_COMPILER_ID MATCHES "Intel")
+ check_and_add_compiler_option("-c99")
+endif()
+
+#
+# Build all runtimes in the top-level binary directory; that way,
+# on Windows, the executables will be in the same directory as
+# the DLLs, so the system will find pcap.dll when any of the
+# executables are run.
+#
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/run)
+
+###################################################################
+# Parameters
+###################################################################
+
+if(WIN32)
+ #
+ # On Windows, allow the library name to be overridden, for the
+ # benefit of projects that combine libpcap with their own
+ # kernel-mode code to support capturing.
+ #
+ set(LIBRARY_NAME pcap CACHE STRING "Library name")
+else()
+ #
+ # On UN*X, it's always been libpcap.
+ #
+ set(LIBRARY_NAME pcap)
+endif()
+
+option(INET6 "Enable IPv6" ON)
+if(WIN32)
+ option(USE_STATIC_RT "Use static Runtime" ON)
+endif(WIN32)
+option(BUILD_SHARED_LIBS "Build shared libraries" ON)
+if(WIN32)
+ set(PACKET_DLL_DIR "" CACHE PATH "Path to directory with include and lib subdirectories for packet.dll")
+endif(WIN32)
+
+# To pacify those who hate the protochain instruction
+option(NO_PROTOCHAIN "Disable protochain instruction" OFF)
+
+#
+# Start out with the capture mechanism type unspecified; the user
+# can explicitly specify it and, if they don't, we'll pick an
+# appropriate one.
+#
+set(PCAP_TYPE "" CACHE STRING "Packet capture type")
+
+#
+# Default to having remote capture support on Windows and, for now, to
+# not having it on UN*X.
+#
+if(WIN32)
+ option(ENABLE_REMOTE "Enable remote capture" ON)
+else()
+ option(ENABLE_REMOTE "Enable remote capture" OFF)
+endif(WIN32)
+
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ option(PCAP_SUPPORT_PACKET_RING "Enable Linux packet ring support" ON)
+ option(BUILD_WITH_LIBNL "Build with libnl" ON)
+endif()
+
+#
+# Additional capture modules.
+#
+option(DISABLE_USB "Disable USB sniffing support" OFF)
+option(DISABLE_BLUETOOTH "Disable Bluetooth sniffing support" OFF)
+option(DISABLE_NETMAP "Disable netmap support" OFF)
+#
+# We don't support D-Bus sniffing on macOS; see
+#
+# https://bugs.freedesktop.org/show_bug.cgi?id=74029
+#
+if(APPLE)
+ option(DISABLE_DBUS "Disable D-Bus sniffing support" ON)
+else(APPLE)
+ option(DISABLE_DBUS "Disable D-Bus sniffing support" OFF)
+endif(APPLE)
+option(DISABLE_RDMA "Disable RDMA sniffing support" OFF)
+
+option(DISABLE_DAG "Disable Endace DAG card support" OFF)
+
+option(DISABLE_SEPTEL "Disable Septel card support" OFF)
+set(SEPTEL_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../septel" CACHE PATH "Path to directory with include and lib subdirectories for Septel API")
+
+option(DISABLE_SNF "Disable Myricom SNF support" OFF)
+
+option(DISABLE_TC "Disable Riverbed TurboCap support" OFF)
+
+#
+# Debugging options.
+#
+option(BDEBUG "Build optimizer debugging code" OFF)
+option(YYDEBUG "Build parser debugging code" OFF)
+
+###################################################################
+# Versioning
+###################################################################
+
+# Get, parse, format and set pcap's version string from [pcap_root]/VERSION
+# for later use.
+
+# Get MAJOR, MINOR, PATCH & SUFFIX
+file(STRINGS ${pcap_SOURCE_DIR}/VERSION
+ PACKAGE_VERSION
+ LIMIT_COUNT 1 # Read only the first line
+)
+
+# Get "just" MAJOR
+string(REGEX MATCH "^([0-9]+)" PACKAGE_VERSION_MAJOR "${PACKAGE_VERSION}")
+
+# Get MAJOR, MINOR & PATCH
+string(REGEX MATCH "^([0-9]+.)?([0-9]+.)?([0-9]+)" PACKAGE_VERSION_NOSUFFIX "${PACKAGE_VERSION}")
+
+if(WIN32)
+ # Convert PCAP_VERSION_NOSUFFIX to Windows preferred version format
+ string(REPLACE "." "," PACKAGE_VERSION_PREDLL ${PACKAGE_VERSION_NOSUFFIX})
+
+ # Append NANO (used for Windows internal versioning) to PCAP_VERSION_PREDLL
+ # 0 means unused.
+ set(PACKAGE_VERSION_DLL ${PACKAGE_VERSION_PREDLL},0)
+endif(WIN32)
+
+set(PACKAGE_NAME "${LIBRARY_NAME}")
+set(PACKAGE_STRING "${LIBRARY_NAME} ${PACKAGE_VERSION}")
+
+######################################
+# Project settings
+######################################
+
+add_definitions(-DHAVE_CONFIG_H)
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${pcap_SOURCE_DIR}
+)
+
+include(CheckFunctionExists)
+include(CMakePushCheckState)
+include(CheckSymbolExists)
+
+if(WIN32)
+
+ if(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
+ include_directories(${CMAKE_HOME_DIRECTORY}/../../Common)
+ endif(IS_DIRECTORY ${CMAKE_HOME_DIRECTORY}/../../Common)
+
+ find_package(Packet)
+ if(PACKET_FOUND)
+ set(HAVE_PACKET32 TRUE)
+ include_directories(${PACKET_INCLUDE_DIRS})
+ #
+ # Check whether we have the NPcap PacketIsLoopbackAdapter()
+ # function.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES ${PACKET_LIBRARIES})
+ check_function_exists(PacketIsLoopbackAdapter HAVE_PACKET_IS_LOOPBACK_ADAPTER)
+ cmake_pop_check_state()
+ endif(PACKET_FOUND)
+
+ message(STATUS "checking for Npcap's version.h")
+ check_symbol_exists(WINPCAP_PRODUCT_NAME "../../version.h" HAVE_VERSION_H)
+ if(HAVE_VERSION_H)
+ message(STATUS "HAVE version.h")
+ else(HAVE_VERSION_H)
+ message(STATUS "MISSING version.h")
+ endif(HAVE_VERSION_H)
+
+endif(WIN32)
+
+if(MSVC)
+ add_definitions(-D__STDC__)
+ add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+endif(MSVC)
+
+if(USE_STATIC_RT)
+ message(STATUS "Use STATIC runtime")
+ if(MSVC)
+ foreach(RT_FLAG
+ CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
+ CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
+ CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
+ CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
+ string(REGEX REPLACE "/MD" "/MT" ${RT_FLAG} "${${RT_FLAG}}")
+ endforeach(RT_FLAG)
+ elseif(MINGW)
+ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc")
+ endif()
+else (USE_STATIC_RT)
+ message(STATUS "Use DYNAMIC runtime")
+endif(USE_STATIC_RT)
+
+###################################################################
+# Detect available platform features
+###################################################################
+
+include(CheckIncludeFile)
+include(CheckIncludeFiles)
+include(CheckStructHasMember)
+include(CheckTypeSize)
+
+#
+# Tests are a bit expensive with Visual Studio on Windows, so, on
+# Windows, we skip tests for UN*X-only headers and functions.
+#
+
+#
+# Header files.
+#
+check_include_file(inttypes.h HAVE_INTTYPES_H)
+check_include_file(stdint.h HAVE_STDINT_H)
+check_include_file(unistd.h HAVE_UNISTD_H)
+if(NOT HAVE_UNISTD_H)
+ add_definitions(-DYY_NO_UNISTD_H)
+endif(NOT HAVE_UNISTD_H)
+check_include_file(bitypes.h HAVE_SYS_BITYPES_H)
+if(NOT WIN32)
+ check_include_file(sys/ioccom.h HAVE_SYS_IOCCOM_H)
+ check_include_file(sys/sockio.h HAVE_SYS_SOCKIO_H)
+ check_include_file(sys/select.h HAVE_SYS_SELECT_H)
+endif(NOT WIN32)
+check_include_file(limits.h HAVE_LIMITS_H)
+if(NOT WIN32)
+ check_include_file(netpacket/packet.h HAVE_NETPACKET_PACKET_H)
+ check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h" HAVE_NET_PFVAR_H)
+ if(HAVE_NET_PFVAR_H)
+ #
+ # Check for various PF actions.
+ #
+ check_c_source_compiles(
+"#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/pfvar.h>
+
+int
+main(void)
+{
+ return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
+}
+"
+ HAVE_PF_NAT_THROUGH_PF_NORDR)
+ endif(HAVE_NET_PFVAR_H)
+ check_include_file(netinet/if_ether.h HAVE_NETINET_IF_ETHER_H)
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ check_include_file(linux/sockios.h HAVE_LINUX_SOCKIOS_H)
+ #
+ # linux/if_bonding.h requires sys/socket.h.
+ #
+ check_include_files("sys/socket.h;linux/if_bonding.h" HAVE_LINUX_IF_BONDING_H)
+ endif()
+endif(NOT WIN32)
+
+#
+# Functions.
+#
+check_function_exists(strerror HAVE_STRERROR)
+check_function_exists(strerror_r HAVE_STRERROR_R)
+if(HAVE_STRERROR_R)
+ #
+ # We have strerror_r; if we define _GNU_SOURCE, is it a
+ # POSIX-compliant strerror_r() or a GNU strerror_r()?
+ #
+ check_c_source_compiles(
+"#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+ return 0;
+}
+"
+ HAVE_GNU_STRERROR_R)
+ if(NOT HAVE_GNU_STRERROR_R)
+ set(HAVE_POSIX_STRERROR_R YES)
+ endif(NOT HAVE_GNU_STRERROR_R)
+else(HAVE_STRERROR_R)
+ #
+ # We don't have strerror_r; do we have strerror_s?
+ #
+ check_function_exists(strerror_s HAVE_STRERROR_S)
+endif(HAVE_STRERROR_R)
+check_function_exists(strlcpy HAVE_STRLCPY)
+check_function_exists(strlcat HAVE_STRLCAT)
+check_function_exists(snprintf HAVE_SNPRINTF)
+check_function_exists(vsnprintf HAVE_VSNPRINTF)
+check_function_exists(asprintf HAVE_ASPRINTF)
+check_function_exists(vasprintf HAVE_VASPRINTF)
+check_function_exists(strtok_r HAVE_STRTOK_R)
+if(NOT WIN32)
+ check_function_exists(vsyslog HAVE_VSYSLOG)
+endif()
+
+#
+# These tests are for network applications that need socket functions
+# and getaddrinfo()/getnameinfo()-ish functions. We now require
+# getaddrinfo() and getnameinfo(). On UN*X systems, we also prefer
+# versions of recvmsg() that conform to the Single UNIX Specification,
+# so that we can check whether a datagram received with recvmsg() was
+# truncated when received due to the buffer being too small.
+#
+# On Windows, getaddrinfo() is in the ws2_32 library.
+
+# On most UN*X systems, they're available in the system library.
+#
+# Under Solaris, we need to link with libsocket and libnsl to get
+# getaddrinfo() and getnameinfo() and, if we have libxnet, we need to
+# link with libxnet before libsocket to get a version of recvmsg()
+# that conforms to the Single UNIX Specification.
+#
+# We use getaddrinfo() because we want a portable thread-safe way
+# of getting information for a host name or port; there exist _r
+# versions of gethostbyname() and getservbyname() on some platforms,
+# but not on all platforms.
+#
+# NOTE: if you hand check_library_exists as its last argument a variable
+# that's been set, it skips the test, so we need different variables.
+#
+set(PCAP_LINK_LIBRARIES "")
+include(CheckLibraryExists)
+if(WIN32)
+ #
+ # We need winsock2.h and ws2tcpip.h.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES ws2_32)
+ check_symbol_exists(getaddrinfo "winsock2.h;ws2tcpip.h" LIBWS2_32_HAS_GETADDRINFO)
+ cmake_pop_check_state()
+ if(LIBWS2_32_HAS_GETADDRINFO)
+ set(PCAP_LINK_LIBRARIES ws2_32 ${PCAP_LINK_LIBRARIES})
+ else(LIBWS2_32_HAS_GETADDRINFO)
+ message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
+ endif(LIBWS2_32_HAS_GETADDRINFO)
+else(WIN32)
+ #
+ # UN*X. First try the system libraries, then try the libraries
+ # for Solaris and possibly other systems that picked up the
+ # System V library split.
+ #
+ check_function_exists(getaddrinfo STDLIBS_HAVE_GETADDRINFO)
+ if(NOT STDLIBS_HAVE_GETADDRINFO)
+ #
+ # Not found in the standard system libraries.
+ # Try libsocket, which requires libnsl.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES nsl)
+ check_library_exists(socket getaddrinfo "" LIBSOCKET_HAS_GETADDRINFO)
+ cmake_pop_check_state()
+ if(LIBSOCKET_HAS_GETADDRINFO)
+ #
+ # OK, we found it in libsocket.
+ #
+ set(PCAP_LINK_LIBRARIES socket nsl ${PCAP_LINK_LIBRARIES})
+ else(LIBSOCKET_HAS_GETADDRINFO)
+ #
+ # We didn't find it.
+ #
+ message(FATAL_ERROR "getaddrinfo is required, but wasn't found")
+ endif(LIBSOCKET_HAS_GETADDRINFO)
+
+ #
+ # OK, do we have recvmsg() in libxnet?
+ # We also link with libsocket and libnsl.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES socket nsl)
+ check_library_exists(xnet recvmsg "" LIBXNET_HAS_RECVMSG)
+ cmake_pop_check_state()
+ if(LIBXNET_HAS_RECVMSG)
+ #
+ # Yes - link with it as well.
+ #
+ set(PCAP_LINK_LIBRARIES xnet ${PCAP_LINK_LIBRARIES})
+ endif(LIBXNET_HAS_RECVMSG)
+ endif(NOT STDLIBS_HAVE_GETADDRINFO)
+
+ # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+ check_function_exists(putmsg STDLIBS_HAVE_PUTMSG)
+ if(NOT STDLIBS_HAVE_PUTMSG)
+ check_library_exists(str putmsg "" LIBSTR_HAS_PUTMSG)
+ if(LIBSTR_HAS_PUTMSG)
+ set(PCAP_LINK_LIBRARIES str ${PCAP_LINK_LIBRARIES})
+ endif(LIBSTR_HAS_PUTMSG)
+ endif(NOT STDLIBS_HAVE_PUTMSG)
+endif(WIN32)
+
+#
+# Check for reentrant versions of getnetbyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getnetbyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getnetbyname_r();
+# without it, we can't check which API it has. (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+cmake_push_check_state()
+set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+check_symbol_exists(getnetbyname_r netdb.h NETDB_H_DECLARES_GETNETBYNAME_R)
+if(NETDB_H_DECLARES_GETNETBYNAME_R)
+ check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+ struct netent netent_buf;
+ char buf[1024];
+ struct netent *resultp;
+ int h_errnoval;
+
+ return getnetbyname_r((const char *)0, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+}
+"
+ HAVE_LINUX_GETNETBYNAME_R)
+ if(NOT HAVE_LINUX_GETNETBYNAME_R)
+ check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+ struct netent netent_buf;
+ char buf[1024];
+
+ return getnetbyname_r((const char *)0, &netent_buf, buf, (int)sizeof buf) != NULL;
+}
+"
+ HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+ if(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+ check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+ struct netent netent_buf;
+ struct netent_data net_data;
+
+ return getnetbyname_r((const char *)0, &netent_buf, &net_data);
+}
+"
+ HAVE_AIX_GETNETBYNAME_R)
+ endif(NOT HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+ endif(NOT HAVE_LINUX_GETNETBYNAME_R)
+endif(NETDB_H_DECLARES_GETNETBYNAME_R)
+cmake_pop_check_state()
+
+#
+# Check for reentrant versions of getprotobyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getprotobyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getprotobyname_r();
+# without it, we can't check which API it has. (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+cmake_push_check_state()
+set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+check_symbol_exists(getprotobyname_r netdb.h NETDB_H_DECLARES_GETPROTOBYNAME_R)
+if(NETDB_H_DECLARES_GETPROTOBYNAME_R)
+ check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+ struct protoent protoent_buf;
+ char buf[1024];
+ struct protoent *resultp;
+
+ return getprotobyname_r((const char *)0, &protoent_buf, buf, sizeof buf, &resultp);
+}
+"
+ HAVE_LINUX_GETPROTOBYNAME_R)
+ if(NOT HAVE_LINUX_GETPROTOBYNAME_R)
+ check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+ struct protoent protoent_buf;
+ char buf[1024];
+
+ return getprotobyname_r((const char *)0, &protoent_buf, buf, (int)sizeof buf) != NULL;
+}
+"
+ HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+ if(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+ check_c_source_compiles(
+"#include <netdb.h>
+
+int
+main(void)
+{
+ struct protoent protoent_buf;
+ struct protoent_data proto_data;
+
+ return getprotobyname_r((const char *)0, &protoent_buf, &proto_data);
+}
+"
+ HAVE_AIX_GETPROTOBYNAME_R)
+ endif(NOT HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R)
+ endif(NOT HAVE_LINUX_GETPROTOBYNAME_R)
+endif(NETDB_H_DECLARES_GETPROTOBYNAME_R)
+cmake_pop_check_state()
+
+#
+# Data types.
+#
+# XXX - there's no check_type() macro that's like check_type_size()
+# except that it only checks for the existence of the structure type,
+# so we use check_type_size() and ignore the size.
+#
+cmake_push_check_state()
+if(WIN32)
+ set(CMAKE_EXTRA_INCLUDE_FILES winsock2.h)
+else(WIN32)
+ set(CMAKE_EXTRA_INCLUDE_FILES unistd.h sys/socket.h)
+endif(WIN32)
+check_type_size("struct sockaddr_storage" STRUCT_SOCKADDR_STORAGE)
+check_type_size("socklen_t" SOCKLEN_T)
+cmake_pop_check_state()
+
+#
+# Structure fields.
+#
+if(WIN32)
+ check_struct_has_member("struct sockaddr" sa_len winsock2.h HAVE_STRUCT_SOCKADDR_SA_LEN)
+else(WIN32)
+ check_struct_has_member("struct sockaddr" sa_len sys/socket.h HAVE_STRUCT_SOCKADDR_SA_LEN)
+endif(WIN32)
+
+#
+# Do we have ffs(), and is it declared in <strings.h>?
+#
+check_function_exists(ffs HAVE_FFS)
+if(HAVE_FFS)
+ #
+ # OK, we have ffs(). Is it declared in <strings.h>?
+ #
+ # This test fails if we don't have <strings.h> or if we do
+ # but it doesn't declare ffs().
+ #
+ check_symbol_exists(ffs strings.h STRINGS_H_DECLARES_FFS)
+endif()
+
+#
+# This requires the libraries that we require, as ether_hostton might be
+# in one of those libraries. That means we have to do this after
+# we check for those libraries.
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it and declare it in <net/ethernet.h>.
+# Some might have it and declare it in <netinet/ether.h>
+# Some might have it and declare it in <sys/ethernet.h>.
+# Some might have it and declare it in <arpa/inet.h>.
+# Some might have it and declare it in <netinet/if_ether.h>.
+# Some might have it and not declare it in any header file.
+#
+# Before you is a C compiler.
+#
+cmake_push_check_state()
+set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+check_function_exists(ether_hostton HAVE_ETHER_HOSTTON)
+if(HAVE_ETHER_HOSTTON)
+ #
+ # OK, we have ether_hostton(). Is it declared in <net/ethernet.h>?
+ #
+ # This test fails if we don't have <net/ethernet.h> or if we do
+ # but it doesn't declare ether_hostton().
+ #
+ check_symbol_exists(ether_hostton net/ethernet.h NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+ if(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+ #
+ # Yes - we have it declared.
+ #
+ set(HAVE_DECL_ETHER_HOSTTON TRUE)
+ endif()
+ #
+ # Did that succeed?
+ #
+ if(NOT HAVE_DECL_ETHER_HOSTTON)
+ #
+ # No - how about <netinet/ether.h>, as on Linux?
+ #
+ # This test fails if we don't have <netinet/ether.h>
+ # or if we do but it doesn't declare ether_hostton().
+ #
+ check_symbol_exists(ether_hostton netinet/ether.h NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
+ if(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
+ #
+ # Yes - we have it declared.
+ #
+ set(HAVE_DECL_ETHER_HOSTTON TRUE)
+ endif()
+ endif()
+ #
+ # Did that succeed?
+ #
+ if(NOT HAVE_DECL_ETHER_HOSTTON)
+ #
+ # No - how about <sys/ethernet.h>, as on Solaris 10 and later?
+ #
+ # This test fails if we don't have <sys/ethernet.h>
+ # or if we do but it doesn't declare ether_hostton().
+ #
+ check_symbol_exists(ether_hostton sys/ethernet.h SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+ if(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+ #
+ # Yes - we have it declared.
+ #
+ set(HAVE_DECL_ETHER_HOSTTON TRUE)
+ endif()
+ endif()
+ #
+ # Did that succeed?
+ #
+ if(NOT HAVE_DECL_ETHER_HOSTTON)
+ #
+ # No, how about <arpa/inet.h>, as on AIX?
+ #
+ # This test fails if we don't have <arpa/inet.h>
+ # or if we do but it doesn't declare ether_hostton().
+ #
+ check_symbol_exists(ether_hostton arpa/inet.h ARPA_INET_H_DECLARES_ETHER_HOSTTON)
+ if(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
+ #
+ # Yes - we have it declared.
+ #
+ set(HAVE_DECL_ETHER_HOSTTON TRUE)
+ endif()
+ endif()
+ #
+ # Did that succeed?
+ #
+ if(NOT HAVE_DECL_ETHER_HOSTTON)
+ #
+ # No, how about <netinet/if_ether.h>?
+ # On some platforms, it requires <net/if.h> and
+ # <netinet/in.h>, and we always include it with
+ # both of them, so test it with both of them.
+ #
+ # This test fails if we don't have <netinet/if_ether.h>
+ # and the headers we include before it, or if we do but
+ # <netinet/if_ether.h> doesn't declare ether_hostton().
+ #
+ check_symbol_exists(ether_hostton "sys/types.h;sys/socket.h;net/if.h;netinet/in.h;netinet/if_ether.h" NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
+ if(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
+ #
+ # Yes - we have it declared.
+ #
+ set(HAVE_DECL_ETHER_HOSTTON TRUE)
+ endif()
+ endif()
+ #
+ # After all that, is ether_hostton() declared?
+ #
+ if(NOT HAVE_DECL_ETHER_HOSTTON)
+ #
+ # No, we'll have to declare it ourselves.
+ # Do we have "struct ether_addr" if we include <netinet/if_ether.h>?
+ #
+ # XXX - there's no check_type() macro that's like check_type_size()
+ # except that it only checks for the existence of the structure type,
+ # so we use check_type_size() and ignore the size.
+ #
+ cmake_push_check_state()
+ set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/socket.h net/if.h netinet/in.h netinet/if_ether.h)
+ check_type_size("struct ether_addr" STRUCT_ETHER_ADDR)
+ cmake_pop_check_state()
+ endif()
+endif()
+cmake_pop_check_state()
+
+#
+# Large file support on UN*X, a/k/a LFS.
+#
+if(NOT WIN32)
+ include(FindLFS)
+ if(LFS_FOUND)
+ #
+ # Add the required #defines.
+ #
+ add_definitions(${LFS_DEFINITIONS})
+ endif()
+
+ #
+ # Check for fseeko as well.
+ #
+ include(FindFseeko)
+ if(FSEEKO_FOUND)
+ set(HAVE_FSEEKO ON)
+
+ #
+ # Add the required #defines.
+ #
+ add_definitions(${FSEEKO_DEFINITIONS})
+ endif()
+endif()
+
+if(INET6)
+ message(STATUS "Support IPv6")
+endif(INET6)
+
+#
+# Pthreads.
+# We might need them, because some libraries we use might use them,
+# but we don't necessarily need them.
+# That's only on UN*X; on Windows, if they use threads, we assume
+# they're native Windows threads.
+#
+if(NOT WIN32)
+ set(CMAKE_THREAD_PREFER_PTHREAD ON)
+ find_package(Threads)
+ if(NOT CMAKE_USE_PTHREADS_INIT)
+ #
+ # If it's not pthreads, we won't use it; we use it for libraries
+ # that require it.
+ #
+ set(CMAKE_THREAD_LIBS_INIT "")
+ endif(NOT CMAKE_USE_PTHREADS_INIT)
+endif(NOT WIN32)
+
+######################################
+# Input files
+######################################
+
+set(PROJECT_SOURCE_LIST_C
+ bpf_dump.c
+ bpf_filter.c
+ bpf_image.c
+ etherent.c
+ fmtutils.c
+ gencode.c
+ nametoaddr.c
+ optimize.c
+ pcap-common.c
+ pcap.c
+ savefile.c
+ sf-pcapng.c
+ sf-pcap.c
+)
+
+if(WIN32)
+ #
+ # For now, we assume we don't have snprintf() or that it's not one
+ # that behaves enough like C99's snprintf() for our purposes (i.e.,
+ # it doesn't null-terminate the string if it truncates it to fit in
+ # the buffer), so we have to provide our own (a wrapper around
+ # _snprintf() that null-terminates the buffer).
+ #
+ # We also assume we don't have asprintf(), and provide an implementation
+ # that uses _vscprintf() to determine how big the string needs to be.
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
+ missing/win_snprintf.c missing/win_asprintf.c)
+else()
+ #
+ # Either:
+ #
+ # we have snprintf() and vsnprintf(), and have asprintf() and
+ # vasprintf();
+ #
+ # we have snprintf() and vsnprintf(), but don't have asprintf()
+ # or vasprintf();
+ #
+ # we have neither snprintf() nor vsnprintf(), and don't have
+ # asprintf() or vasprintf(), either.
+ #
+ # We assume that if we have asprintf() we have vasprintf(), as well
+ # as snprintf() and vsnprintf(), and that if we have snprintf() we
+ # have vsnprintf().
+ #
+ # For the first case, we don't need any replacement routines.
+ # For the second case, we need replacement asprintf()/vasprintf()
+ # routines.
+ # For the third case, we need replacement snprintf()/vsnprintf() and
+ # asprintf()/vasprintf() routines.
+ #
+ if(NOT HAVE_SNPRINTF)
+ #
+ # We assume we have none of them; missing/snprintf.c supplies
+ # all of them.
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/snprintf.c)
+ elif(NOT HAVE_ASPRINTF)
+ #
+ # We assume we have snprintf()/vsnprintf() but lack
+ # asprintf()/vasprintf(); missing/asprintf.c supplies
+ # the latter (using vsnprintf()).
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/asprintf.c)
+ endif()
+ if(NOT HAVE_STRLCAT)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcat.c)
+ endif(NOT HAVE_STRLCAT)
+ if(NOT HAVE_STRLCPY)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strlcpy.c)
+ endif(NOT HAVE_STRLCPY)
+ if(NOT HAVE_STRTOK_R)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} missing/strtok_r.c)
+ endif(NOT HAVE_STRTOK_R)
+endif(WIN32)
+
+#
+# Determine the main pcap-XXX.c file to use, and the libraries with
+# which we need to link libpcap, if any.
+#
+if(WIN32)
+ #
+ # Windows.
+ #
+ # Has the user explicitly specified a capture type?
+ #
+ if(PCAP_TYPE STREQUAL "")
+ #
+ # The user didn't explicitly specify a capture mechanism.
+ # Check whether we have packet.dll.
+ #
+ if(HAVE_PACKET32)
+ #
+ # We have packet.dll.
+ # Set the capture type to NPF.
+ #
+ set(PCAP_TYPE npf)
+ else()
+ #
+ # We don't have any capture type we know about, so just use
+ # the null capture type, and only support reading (and writing)
+ # capture files.
+ #
+ set(PCAP_TYPE null)
+ endif()
+ endif()
+else()
+ #
+ # UN*X.
+ #
+ # Figure out what type of packet capture mechanism we have, and
+ # what libraries we'd need to link libpcap with, if any.
+ #
+
+ #
+ # Has the user explicitly specified a capture type?
+ #
+ if(PCAP_TYPE STREQUAL "")
+ #
+ # Check for a bunch of headers for various packet capture mechanisms.
+ #
+ check_include_files("sys/types.h;net/bpf.h" HAVE_NET_BPF_H)
+ if(HAVE_NET_BPF_H)
+ #
+ # Does it define BIOCSETIF?
+ # I.e., is it a header for an LBL/BSD-style capture
+ # mechanism, or is it just a header for a BPF filter
+ # engine? Some versions of Arch Linux, for example,
+ # have a net/bpf.h that doesn't define BIOCSETIF;
+ # as it's a Linux, it should use packet sockets,
+ # instead.
+ #
+ # We need:
+ #
+ # sys/types.h, because FreeBSD 10's net/bpf.h
+ # requires that various BSD-style integer types
+ # be defined;
+ #
+ # sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+ # doesn't include it but does use struct timeval
+ # in ioctl definitions;
+ #
+ # sys/ioctl.h and, if we have it, sys/ioccom.h,
+ # because net/bpf.h defines ioctls;
+ #
+ # net/if.h, because it defines some structures
+ # used in ioctls defined by net/bpf.h;
+ #
+ # sys/socket.h, because OpenBSD 5.9's net/bpf.h
+ # defines some structure fields as being
+ # struct sockaddrs;
+ #
+ # and net/bpf.h doesn't necessarily include all
+ # of those headers itself.
+ #
+ if(HAVE_SYS_IOCCOM_H)
+ check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;sys/ioccom.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
+ else(HAVE_SYS_IOCCOM_H)
+ check_symbol_exists(BIOCSETIF "sys/types.h;sys/time.h;sys/ioctl.h;sys/socket.h;net/bpf.h;net/if.h" BPF_H_DEFINES_BIOCSETIF)
+ endif(HAVE_SYS_IOCCOM_H)
+ endif(HAVE_NET_BPF_H)
+ check_include_file(net/pfilt.h HAVE_NET_PFILT_H)
+ check_include_file(net/enet.h HAVE_NET_ENET_H)
+ check_include_file(net/nit.h HAVE_NET_NIT_H)
+ check_include_file(sys/net/nit.h HAVE_SYS_NET_NIT_H)
+ check_include_file(linux/socket.h HAVE_LINUX_SOCKET_H)
+ check_include_file(net/raw.h HAVE_NET_RAW_H)
+ check_include_file(sys/dlpi.h HAVE_SYS_DLPI_H)
+
+ if(BPF_H_DEFINES_BIOCSETIF)
+ #
+ # BPF.
+ # Check this before DLPI, so that we pick BPF on
+ # Solaris 11 and later.
+ #
+ set(PCAP_TYPE bpf)
+ elseif(HAVE_LINUX_SOCKET_H)
+ #
+ # No prizes for guessing this one.
+ #
+ set(PCAP_TYPE linux)
+ elseif(HAVE_NET_PFILT_H)
+ #
+ # DEC OSF/1, Digital UNIX, Tru64 UNIX
+ #
+ set(PCAP_TYPE pf)
+ elseif(HAVE_NET_ENET_H)
+ #
+ # Stanford Enetfilter.
+ #
+ set(PCAP_TYPE enet)
+ elseif(HAVE_NET_NIT_H)
+ #
+ # SunOS 4.x STREAMS NIT.
+ #
+ set(PCAP_TYPE snit)
+ elseif(HAVE_SYS_NET_NIT_H)
+ #
+ # Pre-SunOS 4.x non-STREAMS NIT.
+ #
+ set(PCAP_TYPE nit)
+ elseif(HAVE_NET_RAW_H)
+ #
+ # IRIX snoop.
+ #
+ set(PCAP_TYPE snoop)
+ elseif(HAVE_SYS_DLPI_H)
+ #
+ # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+ #
+ set(PCAP_TYPE dlpi)
+ else()
+ #
+ # Nothing we support.
+ #
+ set(PCAP_TYPE null)
+ endif()
+ endif()
+endif(WIN32)
+message(STATUS "Packet capture mechanism type: ${PCAP_TYPE}")
+
+#
+# Do capture-mechanism-dependent tests.
+#
+if(WIN32)
+ if(PCAP_TYPE STREQUAL "npf")
+ #
+ # Link with packet.dll before WinSock2.
+ #
+ set(PCAP_LINK_LIBRARIES ${PACKET_LIBRARIES} ${PCAP_LINK_LIBRARIES})
+ elseif(PCAP_TYPE STREQUAL "null")
+ else()
+ message(ERROR "${PCAP_TYPE} is not a valid pcap type")
+ endif()
+else(WIN32)
+ if(PCAP_TYPE STREQUAL "dlpi")
+ #
+ # Needed for common functions used by pcap-[dlpi,libdlpi].c
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} dlpisubs.c)
+
+ #
+ # Checks for some header files.
+ #
+ check_include_file(sys/bufmod.h HAVE_SYS_BUFMOD_H)
+ check_include_file(sys/dlpi_ext.h HAVE_SYS_DLPI_EXT_H)
+
+ #
+ # Checks to see if Solaris has the public libdlpi(3LIB) library.
+ # Note: The existence of /usr/include/libdlpi.h does not mean it is the
+ # public libdlpi(3LIB) version. Before libdlpi was made public, a
+ # private version also existed, which did not have the same APIs.
+ # Due to a gcc bug, the default search path for 32-bit libraries does
+ # not include /lib, we add it explicitly here.
+ # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
+ # Also, due to the bug above applications that link to libpcap with
+ # libdlpi will have to add "-L/lib" option to "configure".
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_FLAGS "-L/lib")
+ set(CMAKE_REQUIRED_LIBRARIES dlpi)
+ check_function_exists(dlpi_walk HAVE_LIBDLPI)
+ cmake_pop_check_state()
+ if(HAVE_LIBDLPI)
+ #
+ # XXX - add -L/lib
+ #
+ set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} dlpi)
+ set(PCAP_TYPE libdlpi)
+ endif()
+
+ #
+ # This check is for Solaris with DLPI support for passive modes.
+ # See dlpi(7P) for more details.
+ #
+ # XXX - there's no check_type() macro that's like check_type_size()
+ # except that it only checks for the existence of the structure type,
+ # so we use check_type_size() and ignore the size.
+ #
+ cmake_push_check_state()
+ set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/dlpi.h)
+ check_type_size(dl_passive_req_t DL_PASSIVE_REQ_T)
+ cmake_pop_check_state()
+ elseif(PCAP_TYPE STREQUAL "linux")
+ #
+ # Do we have the wireless extensions?
+ # linux/wireless.h requires sys/socket.h.
+ #
+ check_include_files("sys/socket.h;linux/wireless.h" HAVE_LINUX_WIRELESS_H)
+
+ #
+ # Do we have libnl?
+ #
+ if(BUILD_WITH_LIBNL)
+ #
+ # Try libnl 3.x first.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES nl-3)
+ check_function_exists(nl_socket_alloc HAVE_LIBNL)
+ cmake_pop_check_state()
+ if(HAVE_LIBNL)
+ #
+ # Yes, we have libnl 3.x.
+ #
+ set(PCAP_LINK_LIBRARIES nl-genl-3 nl-3 ${PCAP_LINK_LIBRARIES})
+ set(HAVE_LIBNL_3_x ON)
+ set(HAVE_LIBNL_NLE ON)
+ set(HAVE_LIBNL_SOCKETS ON)
+ include_directories("/usr/include/libnl3")
+ else()
+ #
+ # Try libnl 2.x.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES nl)
+ check_function_exists(nl_socket_alloc HAVE_LIBNL)
+ cmake_pop_check_state()
+ if(HAVE_LIBNL)
+ #
+ # Yes, we have libnl 2.x.
+ #
+ set(PCAP_LINK_LIBRARIES nl-genl nl ${PCAP_LINK_LIBRARIES})
+ set(HAVE_LIBNL_2_x ON)
+ set(HAVE_LIBNL_NLE ON)
+ set(HAVE_LIBNL_SOCKETS ON)
+ else()
+ #
+ # No, we don't; do we have libnl 1.x?
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES nl)
+ check_function_exists(nl_handle_alloc HAVE_LIBNL)
+ cmake_pop_check_state()
+ if(HAVE_LIBNL)
+ set(PCAP_LINK_LIBRARIES nl ${PCAP_LINK_LIBRARIES})
+ endif()
+ endif()
+ endif()
+ endif()
+
+ check_include_file(linux/ethtool.h HAVE_LINUX_ETHTOOL_H)
+
+ #
+ # Checks to see if tpacket_stats is defined in linux/if_packet.h
+ # If so then pcap-linux.c can use this to report proper statistics.
+ #
+ # XXX - there's no check_type() macro that's like check_type_size()
+ # except that it only checks for the existence of the structure type,
+ # so we use check_type_size() and ignore the size.
+ #
+ cmake_push_check_state()
+ set(CMAKE_EXTRA_INCLUDE_FILES linux/if_packet.h)
+ check_type_size("struct tpacket_stats" STRUCT_TPACKET_STATS)
+ cmake_pop_check_state()
+
+ check_struct_has_member("struct tpacket_auxdata" tp_vlan_tci linux/if_packet.h HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
+ elseif(PCAP_TYPE STREQUAL "bpf")
+ #
+ # Check whether we have the *BSD-style ioctls.
+ #
+ check_include_files("sys/types.h;net/if_media.h" HAVE_NET_IF_MEDIA_H)
+
+ #
+ # Check whether we have struct BPF_TIMEVAL.
+ #
+ # XXX - there's no check_type() macro that's like check_type_size()
+ # except that it only checks for the existence of the structure type,
+ # so we use check_type_size() and ignore the size.
+ #
+ cmake_push_check_state()
+ if(HAVE_SYS_IOCCOM_H)
+ set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/ioccom.h net/bpf.h)
+ check_type_size("struct BPF_TIMEVAL" STRUCT_BPF_TIMEVAL)
+ else()
+ set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h net/bpf.h)
+ check_type_size("struct BPF_TIMEVAL" STRUCT_BPF_TIMEVAL)
+ endif()
+ cmake_pop_check_state()
+ elseif(PCAP_TYPE STREQUAL "null")
+ else()
+ message(FATAL_ERROR "${PCAP_TYPE} is not a valid pcap type")
+ endif()
+endif(WIN32)
+
+set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-${PCAP_TYPE}.c)
+
+#
+# Now figure out how we get a list of interfaces and addresses,
+# if we support capturing. Don't bother if we don't support
+# capturing.
+#
+if(NOT WIN32)
+ #
+ # UN*X - figure out what type of interface list mechanism we
+ # have.
+ #
+ # If the capture type is null, that means we can't capture,
+ # so we can't open any capture devices, so we won't return
+ # any interfaces.
+ #
+ if(NOT PCAP_TYPE STREQUAL "null")
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LINK_LIBRARIES})
+ check_function_exists(getifaddrs HAVE_GETIFADDRS)
+ cmake_pop_check_state()
+ if(NOT HAVE_GETIFADDRS)
+ #
+ # It's not in the libraries that, at this point, we've
+ # found we need to link libpcap with.
+ #
+ # It's in libsocket on Solaris and possibly other OSes;
+ # as long as we're not linking with libxnet, check there.
+ #
+ # NOTE: if you hand check_library_exists as its last
+ # argument a variable that's been set, it skips the test,
+ # so we need different variables.
+ #
+ if(NOT LIBXNET_HAS_GETHOSTBYNAME)
+ check_library_exists(socket getifaddrs "" SOCKET_HAS_GETIFADDRS)
+ if(SOCKET_HAS_GETIFADDRS)
+ set(PCAP_LINK_LIBRARIES socket ${PCAP_LINK_LIBRARIES})
+ set(HAVE_GETIFADDRS TRUE)
+ endif()
+ endif()
+ endif()
+ if(HAVE_GETIFADDRS)
+ #
+ # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+ # as well, just in case some platform is really weird.
+ # It may require that sys/types.h be included first,
+ # so include it first.
+ #
+ check_include_files("sys/types.h;ifaddrs.h" HAVE_IFADDRS_H)
+ if(HAVE_IFADDRS_H)
+ #
+ # We have the header, so we use "getifaddrs()" to
+ # get the list of interfaces.
+ #
+ set(FINDALLDEVS_TYPE getad)
+ else()
+ #
+ # We don't have the header - give up.
+ # XXX - we could also fall back on some other
+ # mechanism, but, for now, this'll catch this
+ # problem so that we can at least try to figure
+ # out something to do on systems with "getifaddrs()"
+ # but without "ifaddrs.h", if there is something
+ # we can do on those systems.
+ #
+ message(FATAL_ERROR "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.")
+ endif()
+ else()
+ #
+ # Well, we don't have "getifaddrs()", at least not with the
+ # libraries with which we've decided we need to link
+ # libpcap with, so we have to use some other mechanism.
+ #
+ # Note that this may happen on Solaris, which has
+ # getifaddrs(), but in -lsocket, not in -lxnet, so we
+ # won't find it if we link with -lxnet, which we want
+ # to do for other reasons.
+ #
+ # For now, we use either the SIOCGIFCONF ioctl or the
+ # SIOCGLIFCONF ioctl, preferring the latter if we have
+ # it; the latter is a Solarisism that first appeared
+ # in Solaris 8. (Solaris's getifaddrs() appears to
+ # be built atop SIOCGLIFCONF; using it directly
+ # avoids a not-all-that-useful middleman.)
+ #
+ try_compile(HAVE_SIOCGLIFCONF ${CMAKE_CURRENT_BINARY_DIR} "${pcap_SOURCE_DIR}/cmake/have_siocglifconf.c" )
+ if(HAVE_SIOCGLIFCONF)
+ set(FINDALLDEVS_TYPE glifc)
+ else()
+ set(FINDALLDEVS_TYPE gifc)
+ endif()
+ endif()
+ message(STATUS "Find-interfaces mechanism type: ${FINDALLDEVS_TYPE}")
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} fad-${FINDALLDEVS_TYPE}.c)
+ endif()
+endif()
+
+# Check for hardware timestamp support.
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ check_include_file(linux/net_tstamp.h HAVE_LINUX_NET_TSTAMP_H)
+endif()
+
+#
+# Check for additional native sniffing capabilities.
+#
+
+# Check for USB sniffing support on Linux.
+# On FreeBSD, it uses BPF, so we don't need to do anything special here.
+if(NOT DISABLE_USB)
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ set(PCAP_SUPPORT_USB TRUE)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-usb-linux.c)
+ set(LINUX_USB_MON_DEV /dev/usbmon)
+ #
+ # Do we have a version of <linux/compiler.h> available?
+ # If so, we might need it for <linux/usbdevice_fs.h>.
+ #
+ check_include_files("linux/compiler.h" HAVE_LINUX_COMPILER_H)
+ if(HAVE_LINUX_COMPILER_H)
+ #
+ # Yes - include it when testing for <linux/usbdevice_fs.h>.
+ #
+ check_include_files("linux/compiler.h;linux/usbdevice_fs.h" HAVE_LINUX_USBDEVICE_FS_H)
+ else(HAVE_LINUX_COMPILER_H)
+ check_include_files("linux/usbdevice_fs.h" HAVE_LINUX_USBDEVICE_FS_H)
+ endif(HAVE_LINUX_COMPILER_H)
+ if(HAVE_LINUX_USBDEVICE_FS_H)
+ #
+ # OK, does it define bRequestType? Older versions of the kernel
+ # define fields with names like "requesttype, "request", and
+ # "value", rather than "bRequestType", "bRequest", and
+ # "wValue".
+ #
+ if(HAVE_LINUX_COMPILER_H)
+ check_struct_has_member("struct usbdevfs_ctrltransfer" bRequestType "linux/compiler.h;linux/usbdevice_fs.h" HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE)
+ else(HAVE_LINUX_COMPILER_H)
+ check_struct_has_member("struct usbdevfs_ctrltransfer" bRequestType "linux/usbdevice_fs.h" HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE)
+ endif(HAVE_LINUX_COMPILER_H)
+ endif()
+ endif()
+endif()
+
+# Check for netfilter sniffing support.
+if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ #
+ # Life's too short to deal with trying to get this to compile
+ # if you don't get the right types defined with
+ # __KERNEL_STRICT_NAMES getting defined by some other include.
+ #
+ # Check whether the includes Just Work. If not, don't turn on
+ # netfilter support.
+ #
+ check_c_source_compiles(
+"#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+
+int
+main(void)
+{
+ return 0;
+}
+"
+ PCAP_SUPPORT_NETFILTER)
+ if(PCAP_SUPPORT_NETFILTER)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-netfilter-linux.c)
+ endif(PCAP_SUPPORT_NETFILTER)
+endif()
+
+# Check for netmap sniffing support.
+if(NOT DISABLE_NETMAP)
+ #
+ # Check whether net/netmap_user.h is usable if NETMAP_WITH_LIBS is
+ # defined; it's not usable on DragonFly BSD 4.6 if NETMAP_WITH_LIBS
+ # is defined, for example, as it includes a non-existent malloc.h
+ # header.
+ #
+ check_c_source_compiles(
+"#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+int
+main(void)
+{
+ return 0;
+}
+"
+ PCAP_SUPPORT_NETMAP)
+ if(PCAP_SUPPORT_NETMAP)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-netmap.c)
+ endif(PCAP_SUPPORT_NETMAP)
+endif()
+
+# Check for Bluetooth sniffing support
+if(NOT DISABLE_BLUETOOTH)
+ if(CMAKE_SYSTEM_NAME STREQUAL "Linux")
+ check_include_file(bluetooth/bluetooth.h HAVE_BLUETOOTH_BLUETOOTH_H)
+ if(HAVE_BLUETOOTH_BLUETOOTH_H)
+ set(PCAP_SUPPORT_BT TRUE)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-bt-linux.c)
+ #
+ # OK, does struct sockaddr_hci have an hci_channel
+ # member?
+ #
+ check_struct_has_member("struct sockaddr_hci" hci_channel "bluetooth/bluetooth.h;bluetooth/hci.h" HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
+ if(HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
+ #
+ # OK, is HCI_CHANNEL_MONITOR defined?
+ #
+ check_c_source_compiles(
+"#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+int
+main(void)
+{
+ u_int i = HCI_CHANNEL_MONITOR;
+ return 0;
+}
+"
+ PCAP_SUPPORT_BT_MONITOR)
+ if(PCAP_SUPPORT_BT_MONITOR)
+ #
+ # Yes, so we can also support Bluetooth monitor
+ # sniffing.
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-bt-monitor-linux.c)
+ endif(PCAP_SUPPORT_BT_MONITOR)
+ endif(HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL)
+ endif(HAVE_BLUETOOTH_BLUETOOTH_H)
+ endif()
+endif()
+
+# Check for Bluetooth sniffing support
+if(NOT DISABLE_DBUS)
+ #
+ # We don't support D-Bus sniffing on macOS; see
+ #
+ # https://bugs.freedesktop.org/show_bug.cgi?id=74029
+ #
+ if(APPLE)
+ message(FATAL_ERROR "Due to freedesktop.org bug 74029, D-Bus capture support is not available on macOS")
+ endif(APPLE)
+ include(FindPkgConfig)
+ pkg_check_modules(DBUS dbus-1)
+ if(DBUS_FOUND)
+ set(PCAP_SUPPORT_DBUS TRUE)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dbus.c)
+ include_directories(${DBUS_INCLUDE_DIRS})
+
+ #
+ # This "helpfully" supplies DBUS_LIBRARIES as a bunch of
+ # library names - not paths - and DBUS_LIBRARY_DIRS as
+ # a bunch of directories.
+ #
+ # CMake *really* doesn't like the notion of specifying "here are
+ # the directories in which to look for libraries" except in
+ # find_library() calls; it *really* prefers using full paths to
+ # library files, rather than library names.
+ #
+ # Find the libraries and add their full paths.
+ #
+ set(DBUS_LIBRARY_FULLPATHS)
+ foreach(_lib IN LISTS DBUS_LIBRARIES)
+ #
+ # Try to find this library, so we get its full path.
+ #
+ find_library(_libfullpath ${_lib} HINTS ${DBUS_LIBRARY_DIRS})
+ list(APPEND DBUS_LIBRARY_FULLPATHS ${_libfullpath})
+ endforeach()
+ set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DBUS_LIBRARY_FULLPATHS})
+ endif(DBUS_FOUND)
+endif(NOT DISABLE_DBUS)
+
+# Check for RDMA sniffing support
+if(NOT DISABLE_RDMA)
+ check_library_exists(ibverbs ibv_get_device_list "" LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
+ if(LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
+ check_include_file(infiniband/verbs.h HAVE_INFINIBAND_VERBS_H)
+ if(HAVE_INFINIBAND_VERBS_H)
+ check_symbol_exists(ibv_create_flow infiniband/verbs.h PCAP_SUPPORT_RDMASNIFF)
+ if(PCAP_SUPPORT_RDMASNIFF)
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-rdmasniff.c)
+ set(PCAP_LINK_LIBRARIES ibverbs ${PCAP_LINK_LIBRARIES})
+ endif(PCAP_SUPPORT_RDMASNIFF)
+ endif(HAVE_INFINIBAND_VERBS_H)
+ endif(LIBIBVERBS_HAS_IBV_GET_DEVICE_LIST)
+endif(NOT DISABLE_RDMA)
+
+#
+# Check for sniffing capabilities using third-party APIs.
+#
+
+# Check for Endace DAG card support.
+if(NOT DISABLE_DAG)
+ #
+ # Try to find the DAG header file and library.
+ #
+ find_package(DAG)
+
+ #
+ # Did we succeed?
+ #
+ if(DAG_FOUND)
+ #
+ # Yes.
+ # Check for various DAG API functions.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES ${DAG_INCLUDE_DIRS})
+ set(CMAKE_REQUIRED_LIBRARIES ${DAG_LIBRARIES})
+ check_function_exists(dag_attach_stream HAVE_DAG_STREAMS_API)
+ if(NOT HAVE_DAG_STREAMS_API)
+ message(FATAL_ERROR "DAG library lacks streams support")
+ endif()
+ check_function_exists(dag_attach_stream64 HAVE_DAG_LARGE_STREAMS_API)
+ check_function_exists(dag_get_erf_types HAVE_DAG_GET_ERF_TYPES)
+ check_function_exists(dag_get_stream_erf_types HAVE_DAG_GET_STREAM_ERF_TYPES)
+ cmake_pop_check_state()
+
+ include_directories(AFTER ${DAG_INCLUDE_DIRS})
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-dag.c)
+ set(HAVE_DAG_API TRUE)
+ set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${DAG_LIBRARIES})
+
+ if(HAVE_DAG_LARGE_STREAMS_API)
+ get_filename_component(DAG_LIBRARY_DIR ${DAG_LIBRARY} PATH)
+ check_library_exists(vdag vdag_set_device_info ${DAG_LIBRARY_DIR} HAVE_DAG_VDAG)
+ if(HAVE_DAG_VDAG)
+ set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+ endif()
+ endif()
+ endif()
+endif()
+
+# Check for Septel card support.
+set(PROJECT_EXTERNAL_OBJECT_LIST "")
+if(NOT DISABLE_SEPTEL)
+ #
+ # Do we have the msg.h header?
+ #
+ set(SEPTEL_INCLUDE_DIRS "${SEPTEL_ROOT}/INC")
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES ${SEPTEL_INCLUDE_DIRS})
+ check_include_file(msg.h HAVE_INC_MSG_H)
+ cmake_pop_check_state()
+ if(HAVE_INC_MSG_H)
+ #
+ # Yes.
+ #
+ include_directories(AFTER ${SEPTEL_INCLUDE_DIRS})
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-septel.c)
+ set(PROJECT_EXTERNAL_OBJECT_LIST ${PROJECT_EXTERNAL_OBJECT_LIST} "${SEPTEL_ROOT}/asciibin.o ${SEPTEL_ROOT}/bit2byte.o ${SEPTEL_ROOT}/confirm.o ${SEPTEL_ROOT}/fmtmsg.o ${SEPTEL_ROOT}/gct_unix.o ${SEPTEL_ROOT}/hqueue.o ${SEPTEL_ROOT}/ident.o ${SEPTEL_ROOT}/mem.o ${SEPTEL_ROOT}/pack.o ${SEPTEL_ROOT}/parse.o ${SEPTEL_ROOT}/pool.o ${SEPTEL_ROOT}/sdlsig.o ${SEPTEL_ROOT}/strtonum.o ${SEPTEL_ROOT}/timer.o ${SEPTEL_ROOT}/trace.o")
+ set(HAVE_SEPTEL_API TRUE)
+ endif()
+endif()
+
+# Check for Myricom SNF support.
+if(NOT DISABLE_SNF)
+ #
+ # Try to find the SNF header file and library.
+ #
+ find_package(SNF)
+
+ #
+ # Did we succeed?
+ #
+ if(SNF_FOUND)
+ #
+ # Yes.
+ #
+ include_directories(AFTER ${SNF_INCLUDE_DIRS})
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-snf.c)
+ set(HAVE_SNF_API TRUE)
+ set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} ${SNF_LIBRARIES})
+ endif()
+endif()
+
+# Check for Riverbed TurboCap support.
+if(NOT DISABLE_TC)
+ #
+ # Try to find the TurboCap header file and library.
+ #
+ find_package(TC)
+
+ #
+ # Did we succeed?
+ #
+ if(TC_FOUND)
+ #
+ # Yes.
+ #
+ include_directories(AFTER ${TC_INCLUDE_DIRS})
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} pcap-tc.c)
+ set(HAVE_TC_API TRUE)
+ set(PCAP_LINK_LIBRARIES "${PCAP_LINK_LIBRARIES} ${TC_LIBRARIES} ${CMAKE_USE_PTHREADS_INIT} stdc++")
+ endif()
+endif()
+
+#
+# Remote capture support.
+#
+
+if(ENABLE_REMOTE)
+ #
+ # Check for various members of struct msghdr.
+ # We need to include ftmacros.h on some platforms, to make sure we
+ # get the POSIX/Single USER Specification version of struct msghdr,
+ # which has those members, rather than the backwards-compatible
+ # version, which doesn't. That's not a system header file, and
+ # at least some versions of CMake include it as <ftmacros.h>, which
+ # won't check the current directory, so we add the top-level
+ # source directory to the list of include directories when we do
+ # the check.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
+ check_struct_has_member("struct msghdr" msg_control "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_CONTROL)
+ check_struct_has_member("struct msghdr" msg_flags "ftmacros.h;sys/socket.h" HAVE_STRUCT_MSGHDR_MSG_FLAGS)
+ cmake_pop_check_state()
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C}
+ pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c)
+endif(ENABLE_REMOTE)
+
+###################################################################
+# Warning options
+###################################################################
+
+#
+# Check and add warning options if we have a .devel file.
+#
+if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel)
+ #
+ # Warning options.
+ #
+ if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
+ #
+ # MSVC, with Microsoft's front end and code generator.
+ # "MSVC" is also set for Microsoft's compiler with a Clang
+ # front end and their code generator ("Clang/C2"), so we
+ # check for clang.exe and treat that differently.
+ #
+ check_and_add_compiler_option(-Wall)
+ #
+ # Disable some pointless warnings that /Wall turns on.
+ #
+ # Unfortunately, MSVC does not appear to have an equivalent
+ # to "__attribute__((unused))" to mark a particular function
+ # parameter as being known to be unused, so that the compiler
+ # won't warn about it (for example, the function might have
+ # that parameter because a pointer to it is being used, and
+ # the signature of that function includes that parameter).
+ # C++ lets you give a parameter a type but no name, but C
+ # doesn't have that.
+ #
+ check_and_add_compiler_option(-wd4100)
+ #
+ # In theory, we care whether somebody uses f() rather than
+ # f(void) to declare a function with no arguments, but, in
+ # practice, there are places in the Windows header files
+ # that appear to do that, so we squelch that warning.
+ #
+ check_and_add_compiler_option(-wd4255)
+ #
+ # Windows FD_SET() generates this, so we suppress it.
+ #
+ check_and_add_compiler_option(-wd4548)
+ #
+ # Perhaps testing something #defined to be 0 with #ifdef is an
+ # error, and it should be tested with #if, but perhaps it's
+ # not, and Microsoft does that in its headers, so we squelch
+ # that warning.
+ #
+ check_and_add_compiler_option(-wd4574)
+ #
+ # The Windows headers also test not-defined values in #if, so
+ # we don't want warnings about that, either.
+ #
+ check_and_add_compiler_option(-wd4668)
+ #
+ # We do *not* care whether some function is, or isn't, going to be
+ # expanded inline.
+ #
+ check_and_add_compiler_option(-wd4710)
+ check_and_add_compiler_option(-wd4711)
+ #
+ # We do *not* care whether we're adding padding bytes after
+ # structure members.
+ #
+ check_and_add_compiler_option(-wd4820)
+ else()
+ #
+ # Other compilers, including MSVC with a Clang front end and
+ # Microsoft's code generator. We currently treat them as if
+ # they might support GCC-style -W options.
+ #
+ check_and_add_compiler_option(-Wall)
+ check_and_add_compiler_option(-Wsign-compare)
+ check_and_add_compiler_option(-Wmissing-prototypes)
+ check_and_add_compiler_option(-Wstrict-prototypes)
+ check_and_add_compiler_option(-Wshadow)
+ check_and_add_compiler_option(-Wdeclaration-after-statement)
+ check_and_add_compiler_option(-Wused-but-marked-unused)
+ check_and_add_compiler_option(-Wdocumentation)
+ check_and_add_compiler_option(-Wcomma)
+ check_and_add_compiler_option(-Wmissing-noreturn)
+ # Warns about safeguards added in case the enums are extended
+ # check_and_add_compiler_option(-Wcovered-switch-default)
+ check_and_add_compiler_option(-Wmissing-variable-declarations)
+ check_and_add_compiler_option(-Wunused-parameter)
+ check_and_add_compiler_option(-Wformat-nonliteral)
+ check_and_add_compiler_option(-Wunreachable-code)
+ endif()
+endif()
+
+#
+# Suppress some warnings we get with MSVC even without /Wall.
+#
+if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*")
+ #
+ # Yes, we have some functions that never return but that
+ # have a non-void return type. That's because, on some
+ # platforms, they *do* return values but, on other
+ # platforms, including Windows, they just fail and
+ # longjmp out by calling bpf_error().
+ #
+ check_and_add_compiler_option(-wd4646)
+endif()
+
+file(GLOB PROJECT_SOURCE_LIST_H
+ *.h
+ pcap/*.h
+)
+
+#
+# Try to have the compiler default to hiding symbols, so that only
+# symbols explicitly exported with PCAP_API will be visible outside
+# (shared) libraries.
+#
+# Not necessary with MSVC, as that's the default.
+#
+# XXX - we don't use ADD_COMPILER_EXPORT_FLAGS, because, as of CMake
+# 2.8.12.2, it doesn't know about Sun C/Oracle Studio, and, as of
+# CMake 2.8.6, it only sets the C++ compiler flags, rather than
+# allowing an arbitrary variable to be set with the "hide symbols
+# not explicitly exported" flag.
+#
+if(NOT MSVC)
+ if(CMAKE_C_COMPILER_ID MATCHES "SunPro")
+ #
+ # Sun C/Oracle Studio.
+ #
+ check_and_add_compiler_option(-xldscope=hidden)
+ else()
+ #
+ # Try this for all other compilers; it's what GCC uses,
+ # and a number of other compilers, such as Clang and Intel C,
+ # use it as well.
+ #
+ check_and_add_compiler_option(-fvisibility=hidden)
+ endif()
+endif(NOT MSVC)
+
+#
+# Flex/Lex and YACC/Berkeley YACC/Bison.
+# From a mail message to the CMake mailing list by Andy Cedilnik of
+# Kitware.
+#
+
+#
+# Try to find Flex, a Windows version of Flex, or Lex.
+#
+find_program(LEX_EXECUTABLE NAMES flex win_flex lex)
+if(LEX_EXECUTABLE STREQUAL "LEX_EXECUTABLE-NOTFOUND")
+ message(FATAL_ERROR "Neither flex nor win_flex nor lex was found.")
+endif()
+message(STATUS "Lexical analyzer generator: ${LEX_EXECUTABLE}")
+
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
+ SOURCE ${pcap_SOURCE_DIR}/scanner.l
+ COMMAND ${LEX_EXECUTABLE} -P pcap_ --header-file=scanner.h --nounput -o${CMAKE_CURRENT_BINARY_DIR}/scanner.c ${pcap_SOURCE_DIR}/scanner.l
+ DEPENDS ${pcap_SOURCE_DIR}/scanner.l
+)
+
+#
+# Since scanner.c does not exist yet when cmake is run, mark
+# it as generated.
+#
+# Since scanner.c includes grammar.h, mark that as a dependency.
+#
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/scanner.c PROPERTIES
+ GENERATED TRUE
+ OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
+)
+
+#
+# Add scanner.c to the list of sources.
+#
+#set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/scanner.c)
+
+#
+# Try to find YACC or Bison.
+#
+find_program(YACC_EXECUTABLE NAMES bison win_bison byacc yacc)
+if(YACC_EXECUTABLE STREQUAL "YACC_EXECUTABLE-NOTFOUND")
+ message(FATAL_ERROR "Neither bison nor win_bison nor byacc nor yacc was found.")
+endif()
+message(STATUS "Parser generator: ${YACC_EXECUTABLE}")
+
+#
+# Create custom command for the scanner.
+# Find out whether it's Bison or not by looking at the last component
+# of the path (without a .exe extension, if this is Windows).
+#
+get_filename_component(YACC_NAME ${YACC_EXECUTABLE} NAME_WE)
+if("${YACC_NAME}" STREQUAL "bison" OR "${YACC_NAME}" STREQUAL "win_bison")
+ set(YACC_COMPATIBILITY_FLAG "-y")
+endif()
+add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/grammar.c ${CMAKE_CURRENT_BINARY_DIR}/grammar.h
+ SOURCE ${pcap_SOURCE_DIR}/grammar.y
+ COMMAND ${YACC_EXECUTABLE} ${YACC_COMPATIBILITY_FLAG} -p pcap_ -o ${CMAKE_CURRENT_BINARY_DIR}/grammar.c -d ${pcap_SOURCE_DIR}/grammar.y
+ DEPENDS ${pcap_SOURCE_DIR}/grammar.y
+)
+
+#
+# Since grammar.c does not exists yet when cmake is run, mark
+# it as generated.
+#
+set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/grammar.c PROPERTIES
+ GENERATED TRUE
+ OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/scanner.h
+)
+
+#
+# Add grammar.c to the list of sources.
+#
+#set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${CMAKE_CURRENT_BINARY_DIR}/grammar.c)
+
+#
+# Assume, by default, no support for shared libraries and V7/BSD
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8). Individual cases can override this.
+# Individual cases can override this.
+#
+set(MAN_DEVICES 4)
+set(MAN_FILE_FORMATS 5)
+set(MAN_MISC_INFO 7)
+set(MAN_ADMIN_COMMANDS 8)
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+ # Workaround to enable certain features
+ set(_SUN TRUE)
+ if(PCAP_TYPE STREQUAL "bpf")
+ #
+ # If we're using BPF, we need libodm and libcfg, as
+ # we use them to load the BPF module.
+ #
+ set(PCAP_LINK_LIBRARIES ${PCAP_LINK_LIBRARIES} odm cfg)
+ endif()
+elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
+ if(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*9\.[0-9]*")
+ #
+ # HP-UX 9.x.
+ #
+ set(HAVE_HPUX9 TRUE)
+ elseif(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*10\.0")
+ #
+ # HP-UX 10.0.
+ #
+ elseif(CMAKE_SYSTEM_VERSION MATCHES "[A-Z.]*10\.1")
+ #
+ # HP-UX 10.1.
+ #
+ else()
+ #
+ # HP-UX 10.20 and later.
+ #
+ set(HAVE_HPUX10_20_OR_LATER TRUE)
+ endif()
+
+ #
+ # Use System V conventions for man pages.
+ #
+ set(MAN_ADMIN_COMMANDS 1m)
+ set(MAN_FILE_FORMATS 4)
+ set(MAN_MISC_INFO 5)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "IRIX" OR CMAKE_SYSTEM_NAME STREQUAL "IRIX64")
+ #
+ # Use IRIX conventions for man pages; they're the same as the
+ # System V conventions, except that they use section 8 for
+ # administrative commands and daemons.
+ #
+ set(MAN_FILE_FORMATS 4)
+ set(MAN_MISC_INFO 5)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF1")
+ #
+ # DEC OSF/1, a/k/a Digial UNIX, a/k/a Tru64 UNIX.
+ # Use Tru64 UNIX conventions for man pages; they're the same as the
+ # System V conventions except that they use section 8 for
+ # administrative commands and daemons.
+ #
+ set(MAN_FILE_FORMATS 4)
+ set(MAN_MISC_INFO 5)
+ set(MAN_DEVICES 7)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
+ #
+ # SunOS 5.x.
+ #
+ set(HAVE_SOLARIS TRUE)
+ #
+ # Make sure errno is thread-safe, in case we're called in
+ # a multithreaded program. We don't guarantee that two
+ # threads can use the *same* pcap_t safely, but the
+ # current version does guarantee that you can use different
+ # pcap_t's in different threads, and even that pcap_compile()
+ # is thread-safe (it wasn't thread-safe in some older versions).
+ #
+ add_definitions(-D_TS_ERRNO)
+
+ if(CMAKE_SYSTEM_VERSION STREQUAL "5.12")
+ else()
+ #
+ # Use System V conventions for man pages.
+ #
+ set(MAN_ADMIN_COMMANDS 1m)
+ set(MAN_FILE_FORMATS 4)
+ set(MAN_MISC_INFO 5)
+ set(MAN_DEVICES 7D)
+ endif()
+endif()
+
+source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C})
+source_group("Header Files" FILES ${PROJECT_SOURCE_LIST_H})
+
+if(WIN32)
+ #
+ # Add pcap-dll.rc to the list of sources.
+ #
+ set(PROJECT_SOURCE_LIST_C ${PROJECT_SOURCE_LIST_C} ${pcap_SOURCE_DIR}/pcap-dll.rc)
+endif(WIN32)
+
+#
+# Add subdirectories after we've set various variables, so they pick up
+# pick up those variables.
+#
+if(ENABLE_REMOTE)
+ add_subdirectory(rpcapd)
+endif(ENABLE_REMOTE)
+add_subdirectory(testprogs)
+
+######################################
+# Register targets
+######################################
+
+#
+# Special target to serialize the building of the generated source.
+#
+# See
+#
+# http://public.kitware.com/pipermail/cmake/2013-August/055510.html
+#
+add_custom_target(SerializeTarget
+ DEPENDS
+ ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
+ ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
+)
+
+set_source_files_properties(${PROJECT_EXTERNAL_OBJECT_LIST} PROPERTIES
+ EXTERNAL_OBJECT TRUE)
+
+if(BUILD_SHARED_LIBS)
+ add_library(${LIBRARY_NAME} SHARED
+ ${PROJECT_SOURCE_LIST_C}
+ ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
+ ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
+ ${PROJECT_EXTERNAL_OBJECT_LIST}
+ )
+ add_dependencies(${LIBRARY_NAME} SerializeTarget)
+ set_target_properties(${LIBRARY_NAME} PROPERTIES
+ COMPILE_DEFINITIONS BUILDING_PCAP)
+ #
+ # No matter what the library is called - it might be called "wpcap"
+ # in a Windows build - the symbol to define to indicate that we're
+ # building the library, rather than a program using the library,
+ # and thus that we're exporting functions defined in our public
+ # header files, rather than importing those functions, is
+ # pcap_EXPORTS.
+ #
+ set_target_properties(${LIBRARY_NAME} PROPERTIES
+ DEFINE_SYMBOL pcap_EXPORTS)
+endif(BUILD_SHARED_LIBS)
+
+add_library(${LIBRARY_NAME}_static STATIC
+ ${PROJECT_SOURCE_LIST_C}
+ ${CMAKE_CURRENT_BINARY_DIR}/grammar.c
+ ${CMAKE_CURRENT_BINARY_DIR}/scanner.c
+ ${PROJECT_EXTERNAL_OBJECT_LIST}
+)
+add_dependencies(${LIBRARY_NAME}_static SerializeTarget)
+set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+ COMPILE_DEFINITIONS BUILDING_PCAP)
+
+if(WIN32)
+ if(BUILD_SHARED_LIBS)
+ set_target_properties(${LIBRARY_NAME} PROPERTIES
+ VERSION ${PACKAGE_VERSION_NOSUFFIX} # only MAJOR and MINOR are needed
+ )
+ endif(BUILD_SHARED_LIBS)
+ if(MSVC)
+ # XXX For DLLs, the TARGET_PDB_FILE generator expression can be used to locate
+ # its PDB file's output directory for installation.
+ # cmake doesn't offer a generator expression for PDB files generated by the
+ # compiler (static libraries).
+ # So instead of considering any possible output there is (there are many),
+ # this will search for the PDB file in the compiler's initial output directory,
+ # which is always ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles\wpcap_static.dir
+ # regardless of architecture, build generator etc.
+ # Quite hackish indeed.
+ set(CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY $<TARGET_FILE_DIR:${LIBRARY_NAME}_static>)
+ set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+ COMPILE_PDB_NAME ${LIBRARY_NAME}_static
+ OUTPUT_NAME "${LIBRARY_NAME}_static"
+ )
+ elseif(MINGW)
+ #
+ # For compatibility, build the shared library without the "lib" prefix on
+ # MinGW as well.
+ #
+ set_target_properties(${LIBRARY_NAME} PROPERTIES
+ PREFIX ""
+ OUTPUT_NAME "${LIBRARY_NAME}"
+ )
+ set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+ OUTPUT_NAME "${LIBRARY_NAME}"
+ )
+ endif()
+else(WIN32) # UN*X
+ if(BUILD_SHARED_LIBS)
+ if(APPLE)
+ set_target_properties(${LIBRARY_NAME} PROPERTIES
+ VERSION ${PACKAGE_VERSION}
+ SOVERSION A
+ )
+ else(APPLE)
+ set_target_properties(${LIBRARY_NAME} PROPERTIES
+ VERSION ${PACKAGE_VERSION}
+ SOVERSION ${PACKAGE_VERSION_MAJOR}
+ )
+ endif(APPLE)
+ endif(BUILD_SHARED_LIBS)
+ set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+ OUTPUT_NAME "${LIBRARY_NAME}"
+ )
+endif(WIN32)
+
+if(BUILD_SHARED_LIBS)
+ if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+ set_target_properties(${LIBRARY_NAME} PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+ endif()
+ target_link_libraries(${LIBRARY_NAME} ${PCAP_LINK_LIBRARIES})
+endif(BUILD_SHARED_LIBS)
+
+if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+ set_target_properties(${LIBRARY_NAME}_static PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+endif()
+
+#
+# On macOS, build libpcap for the appropriate architectures, if
+# CMAKE_OSX_ARCHITECTURES isn't set (if it is, let that control
+# the architectures for which to build it).
+#
+if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
+ #
+ # Get the major version of Darwin.
+ #
+ string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
+
+ if(SYSTEM_VERSION_MAJOR LESS 8)
+ #
+ # Pre-Tiger. Build only for 32-bit PowerPC.
+ #
+ set(OSX_LIBRARY_ARCHITECTURES "ppc")
+ elseif(SYSTEM_VERSION_MAJOR EQUAL 8)
+ #
+ # Tiger. Is this prior to, or with, Intel support?
+ #
+ # Get the minor version of Darwin.
+ #
+ string(REPLACE "${SYSTEM_VERSION_MAJOR}." "" SYSTEM_MINOR_AND_PATCH_VERSION ${CMAKE_SYSTEM_VERSION})
+ string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MINOR "${SYSTEM_MINOR_AND_PATCH_VERSION}")
+ if(SYSTEM_VERSION_MINOR LESS 4)
+ #
+ # Prior to Intel support. Build for 32-bit
+ # PowerPC and 64-bit PowerPC, with 32-bit PowerPC
+ # first. (I'm guessing that's what Apple does.)
+ #
+ set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64")
+ elseif(SYSTEM_VERSION_MINOR LESS 7)
+ #
+ # With Intel support but prior to x86-64 support.
+ # Build for 32-bit PowerPC, 64-bit PowerPC, and 32-bit x86,
+ # with 32-bit PowerPC first.
+ # (I'm guessing that's what Apple does.)
+ #
+ set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386")
+ else()
+ #
+ # With Intel support including x86-64 support.
+ # Build for 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+ # and x86-64, with 32-bit PowerPC first.
+ # (I'm guessing that's what Apple does.)
+ #
+ set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+ endif()
+ elseif(SYSTEM_VERSION_MAJOR EQUAL 9)
+ #
+ # Leopard. Build for 32-bit PowerPC, 64-bit
+ # PowerPC, 32-bit x86, and x86-64, with 32-bit PowerPC
+ # first. (That's what Apple does.)
+ #
+ set(OSX_LIBRARY_ARCHITECTURES "ppc;ppc64;i386;x86_64")
+ elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
+ #
+ # Snow Leopard. Build for x86-64, 32-bit x86, and
+ # 32-bit PowerPC, with x86-64 first. (That's
+ # what Apple does, even though Snow Leopard
+ # doesn't run on PPC, so PPC libpcap runs under
+ # Rosetta, and Rosetta doesn't support BPF
+ # ioctls, so PPC programs can't do live
+ # captures.)
+ #
+ set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386;ppc")
+ else()
+ #
+ # Post-Snow Leopard. Build for x86-64 and 32-bit x86,
+ # with x86-64 first. (That's what Apple does)
+ # XXX - update if and when Apple drops support
+ # for 32-bit x86 code and if and when Apple adds
+ # ARM-based Macs. (You're on your own for iOS etc.)
+ #
+ # XXX - check whether we *can* build for i386 and, if not,
+ # suggest that the user install the /usr/include headers if
+ # they want to build fat.
+ #
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_FLAGS "-arch i386")
+ check_c_source_compiles(
+"int
+main(void)
+{
+ return 0;
+}
+"
+ X86_32_BIT_SUPPORTED)
+ cmake_pop_check_state()
+ if(X86_32_BIT_SUPPORTED)
+ set(OSX_LIBRARY_ARCHITECTURES "x86_64;i386")
+ else()
+ set(OSX_LIBRARY_ARCHITECTURES "x86_64")
+ if(SYSTEM_VERSION_MAJOR LESS 18)
+ #
+ # Pre-Mojave; the command-line tools should be sufficient to
+ # enable 32-bit x86 builds.
+ #
+ message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools")
+ else()
+ message(WARNING "Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package")
+ endif()
+ endif()
+ endif()
+ if(BUILD_SHARED_LIBS)
+ set_target_properties(${LIBRARY_NAME} PROPERTIES
+ OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
+ endif(BUILD_SHARED_LIBS)
+ set_target_properties(${LIBRARY_NAME}_static PROPERTIES
+ OSX_ARCHITECTURES "${OSX_LIBRARY_ARCHITECTURES}")
+endif()
+
+######################################
+# Write out the config.h file
+######################################
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmakeconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+
+######################################
+# Install pcap library, include files, and man pages
+######################################
+
+#
+# "Define GNU standard installation directories", which actually
+# are also defined, to some degree, by autotools, and at least
+# some of which are general UN*X conventions.
+#
+include(GNUInstallDirs)
+
+set(LIBRARY_NAME_STATIC ${LIBRARY_NAME}_static)
+
+function(install_manpage_symlink SOURCE TARGET MANDIR)
+ if(MINGW)
+ find_program(LINK_EXECUTABLE ln)
+ if(LINK_EXECUTABLE)
+ set(LINK_COMMAND "\"${LINK_EXECUTABLE}\" \"-s\" \"${SOURCE}\" \"${TARGET}\"")
+ else(LINK_EXECUTABLE)
+ message(FATAL_ERROR "ln (http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html) not found.")
+ endif(LINK_EXECUTABLE)
+ else(MINGW)
+ set(LINK_COMMAND "\"${CMAKE_COMMAND}\" \"-E\" \"create_symlink\" \"${SOURCE}\" \"${TARGET}\"")
+ endif(MINGW)
+
+ install(CODE
+ "message(STATUS \"Symlinking: ${CMAKE_INSTALL_PREFIX}/${MANDIR}/${SOURCE} to ${TARGET}\")
+ execute_process(
+ COMMAND \"${CMAKE_COMMAND}\" \"-E\" \"remove\" \"${TARGET}\"
+ WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${MANDIR}
+ )
+ execute_process(
+ COMMAND ${LINK_COMMAND}
+ WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}/${MANDIR}
+ RESULT_VARIABLE EXIT_STATUS
+ )
+ if(NOT EXIT_STATUS EQUAL 0)
+ message(FATAL_ERROR \"Could not create symbolic link from ${CMAKE_INSTALL_PREFIX}/${MANDIR}/${SOURCE} to ${TARGET}\")
+ endif()
+ set(CMAKE_INSTALL_MANIFEST_FILES \${CMAKE_INSTALL_MANIFEST_FILES} ${CMAKE_INSTALL_PREFIX}/${MANDIR}/${TARGET})")
+endfunction(install_manpage_symlink)
+
+set(MAN1_NOEXPAND pcap-config.1)
+set(MAN3PCAP_EXPAND
+ pcap.3pcap.in
+ pcap_compile.3pcap.in
+ pcap_datalink.3pcap.in
+ pcap_dump_open.3pcap.in
+ pcap_get_tstamp_precision.3pcap.in
+ pcap_list_datalinks.3pcap.in
+ pcap_list_tstamp_types.3pcap.in
+ pcap_open_dead.3pcap.in
+ pcap_open_offline.3pcap.in
+ pcap_set_immediate_mode.3pcap.in
+ pcap_set_tstamp_precision.3pcap.in
+ pcap_set_tstamp_type.3pcap.in
+)
+set(MAN3PCAP_NOEXPAND
+ pcap_activate.3pcap
+ pcap_breakloop.3pcap
+ pcap_can_set_rfmon.3pcap
+ pcap_close.3pcap
+ pcap_create.3pcap
+ pcap_datalink_name_to_val.3pcap
+ pcap_datalink_val_to_name.3pcap
+ pcap_dump.3pcap
+ pcap_dump_close.3pcap
+ pcap_dump_file.3pcap
+ pcap_dump_flush.3pcap
+ pcap_dump_ftell.3pcap
+ pcap_file.3pcap
+ pcap_fileno.3pcap
+ pcap_findalldevs.3pcap
+ pcap_freecode.3pcap
+ pcap_get_required_select_timeout.3pcap
+ pcap_get_selectable_fd.3pcap
+ pcap_geterr.3pcap
+ pcap_inject.3pcap
+ pcap_is_swapped.3pcap
+ pcap_lib_version.3pcap
+ pcap_lookupdev.3pcap
+ pcap_lookupnet.3pcap
+ pcap_loop.3pcap
+ pcap_major_version.3pcap
+ pcap_next_ex.3pcap
+ pcap_offline_filter.3pcap
+ pcap_open_live.3pcap
+ pcap_set_buffer_size.3pcap
+ pcap_set_datalink.3pcap
+ pcap_set_promisc.3pcap
+ pcap_set_protocol_linux.3pcap
+ pcap_set_rfmon.3pcap
+ pcap_set_snaplen.3pcap
+ pcap_set_timeout.3pcap
+ pcap_setdirection.3pcap
+ pcap_setfilter.3pcap
+ pcap_setnonblock.3pcap
+ pcap_snapshot.3pcap
+ pcap_stats.3pcap
+ pcap_statustostr.3pcap
+ pcap_strerror.3pcap
+ pcap_tstamp_type_name_to_val.3pcap
+ pcap_tstamp_type_val_to_name.3pcap
+)
+set(MANFILE_EXPAND pcap-savefile.manfile.in)
+set(MANMISC_EXPAND
+ pcap-filter.manmisc.in
+ pcap-linktype.manmisc.in
+ pcap-tstamp.manmisc.in
+)
+
+if(NOT BUILD_SHARED_LIBS)
+ unset(LIBRARY_NAME)
+endif(NOT BUILD_SHARED_LIBS)
+
+ if(WIN32)
+ if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ #
+ # Install 64-bit code built with MSVC in the amd64 subdirectories,
+ # as that's where it expects it to be.
+ #
+ install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC}
+ RUNTIME DESTINATION bin/amd64
+ LIBRARY DESTINATION lib/amd64
+ ARCHIVE DESTINATION lib/amd64)
+ if(NOT MINGW)
+ install(FILES $<TARGET_FILE_DIR:${LIBRARY_NAME_STATIC}>/${LIBRARY_NAME_STATIC}.pdb
+ DESTINATION bin/amd64 OPTIONAL)
+ if(BUILD_SHARED_LIBS)
+ install(FILES $<TARGET_PDB_FILE:${LIBRARY_NAME}>
+ DESTINATION bin/amd64 OPTIONAL)
+ endif(BUILD_SHARED_LIBS)
+ endif(NOT MINGW)
+ else(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ #
+ # Install 32-bit code, and 64-bit code not built with MSVC
+ # in the top-level directories, as those are where they
+ # expect it to be.
+ #
+ install(TARGETS ${LIBRARY_NAME} ${LIBRARY_NAME_STATIC}
+ RUNTIME DESTINATION bin
+ LIBRARY DESTINATION lib
+ ARCHIVE DESTINATION lib)
+ if(NOT MINGW)
+ install(FILES $<TARGET_FILE_DIR:${LIBRARY_NAME_STATIC}>/${LIBRARY_NAME_STATIC}.pdb
+ DESTINATION bin OPTIONAL)
+ if(BUILD_SHARED_LIBS)
+ install(FILES $<TARGET_PDB_FILE:${LIBRARY_NAME}>
+ DESTINATION bin OPTIONAL)
+ endif(BUILD_SHARED_LIBS)
+ endif(NOT MINGW)
+ endif(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ else(WIN32)
+ target_link_libraries(${_executable}
+ ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+ endif(WIN32)
+ add_dependencies(testprogs ${_executable})
+endmacro()
+
+add_test_executable(can_set_rfmon_test)
+add_test_executable(capturetest)
+add_test_executable(filtertest)
+add_test_executable(findalldevstest)
+add_test_executable(opentest)
+add_test_executable(reactivatetest)
+
+if(NOT WIN32)
+ add_test_executable(selpolltest)
+endif()
+
+add_test_executable(threadsignaltest ${CMAKE_THREAD_LIBS_INIT})
+
+if(NOT WIN32)
+ add_test_executable(valgrindtest)
+endif()
diff --git a/lib/libpcap/libpcap/CONTRIBUTING.md b/lib/libpcap/libpcap/CONTRIBUTING.md
new file mode 100644
index 0000000..69b5972
--- /dev/null
+++ b/lib/libpcap/libpcap/CONTRIBUTING.md
@@ -0,0 +1,29 @@
+Guidelines for contributing
+===========================
+
+To report a security issue (segfault, buffer overflow, infinite loop, arbitrary
+code execution etc) please send an e-mail to security@tcpdump.org, do not use
+the bug tracker!
+
+To report a non-security problem (failure to compile, failure to capture packets
+properly, missing support for a network interface type or DLT) please check
+first that it reproduces with the latest stable release of libpcap. If it does,
+please check that the problem reproduces with the current git master branch of
+libpcap. If it does (and it is not a security-related problem, otherwise see
+above), please navigate to https://github.com/the-tcpdump-group/libpcap/issues
+and check if the problem has already been reported. If it has not, please open
+a new issue and provide the following details:
+
+* libpcap version (e.g. from tcpdump --version)
+* operating system name and version and any other details that may be relevant
+ (uname -a, compiler name and version, CPU type etc.)
+* configure flags if any were used
+* statement of the problem
+* steps to reproduce
+
+Please note that if you know exactly how to solve the problem and the solution
+would not be too intrusive, it would be best to contribute some development time
+and open a pull request instead.
+
+Still not sure how to do? Feel free to [subscribe](https://www.tcpdump.org/#mailing-lists)
+to the mailing list tcpdump-workers@lists.tcpdump.org and ask!
diff --git a/lib/libpcap/libpcap/CREDITS b/lib/libpcap/libpcap/CREDITS
new file mode 100644
index 0000000..7ba4762
--- /dev/null
+++ b/lib/libpcap/libpcap/CREDITS
@@ -0,0 +1,186 @@
+This file lists people who have contributed to libpcap.
+
+The current maintainers (in alphabetical order):
+ Denis Ovsienko <denis at ovsienko dot info>
+ Francois-Xavier Le Bail <devel dot fx dot lebail at orange dot fr>
+ Guy Harris <guy at alum dot mit dot edu>
+ Michael Richardson <mcr at sandelman dot ottawa dot on dot ca>
+
+Additional people who have contributed patches (in alphabetical order):
+ Akos Vandra <axos88 at gmail dot com>
+ Alan Bawden <Alan at LCS dot MIT dot EDU>
+ Albert Chin <china at thewrittenword dot com>
+ Alexander 'Leo' Bergolth <Leo dot Bergolth at wu-wien dot ac dot at>
+ Alexey Kuznetsov <kuznet at ms2 dot inr dot ac dot ru>
+ Ali Abdulkadir <autostart dot ini at gmail dot com>
+ Alon Bar-Lev <alonbl at sourceforge dot net>
+ Andres Perera <andres dot p at zoho dot com>
+ Andrew Brown <atatat at atatdot dot net>
+ <andy-1 at sourceforge dot net>
+ Ani Sinha <ani at aristanetworks dot com>
+ Antti Kantee <pooka at netbsd dot org>
+ Arien Vijn <arienvijn at sourceforge dot net>
+ Arkadiusz Miskiewicz <misiek at pld dot org dot pl>
+ Armando L. Caro Jr. <acaro at mail dot eecis dot udel dot edu>
+ Assar Westerlund <assar at sics dot se>
+ Bill Parker <wp02855 at gmail dot com>
+ Brent Cook <brent at boundary dot com>
+ Brian Ginsbach <ginsbach at cray dot com>
+ Charles M. Hannum <mycroft at netbsd dot org>
+ Chris G. Demetriou <cgd at netbsd dot org>
+ Chris Lightfoot <cwrl at users dot sourceforge dot net>
+ Chris Maynard <Chris dot Maynard at gtech dot com>
+ Chris Pepper <pepper at mail dot reppep dot com>
+ Christian Bell <csbell at myri dot com>
+ Christian Peron <csjp at freebsd dot org>
+ Christian Svensson <blue at cmd dot nu>
+ Daniele Orlandi <daniele at orlandi dot com>
+ Darren Lim <darren dot lim at endace dot com>
+ Darren Reed <darrenr at sun dot com>
+ David Clark <david dot clark at datasoft dot com>
+ David Kaelbling <drk at sgi dot com>
+ David Ward <david dot ward at ll dot mit dot edu>
+ David Young <dyoung at ojctech dot com>
+ Dean Gaudet <dean at arctic dot org>
+ dhruv <rsrivat at sourceforge dot net>
+ Don Ebright <Don dot Ebright at compuware dot com>
+ Dug Song <dugsong at monkey dot org>
+ Dustin Spicuzza <dustin at virtualroadside dot com>
+ dzejarczech <dzejarczech at sourceforge dot net>
+ Edward Sheldrake <ejs1920 at sourceforge dot net>
+ Eric Anderson <anderse at hpl dot hp dot com>
+ Erik de Castro Lopo <erik dot de dot castro dot lopo at sensorynetworks dot com>
+ Felix Obenhuber <felix at obenhuber dot de>
+ Florent Drouin <Florent dot Drouin at alcatel-lucent dot fr>
+ Franz Schaefer <schaefer at mond dot at>
+ frederich <frederich at sourceforge dot net>
+ Fulko Hew <fulko dot hew at gmail dot com>
+ Fumiyuki Shimizu <fumifumi at abacustech dot jp>
+ Gabor Tatarka <gabor dot tatarka at ericsson dot com>
+ Garrett Cooper <yaberauneya at sourceforge dot net>
+ George Neville-Neil <gnn at freebsd dot org>
+ Gerard Garcia <nouboh at gmail dot com>
+ Gianluca Varenni <gianluca dot varenni at gmail dot com>
+ Gilbert Hoyek <gil_hoyek at hotmail dot com>
+ Gisle Vanem <gvanem at yahoo dot no>
+ Graeme Hewson <ghewson at cix dot compulink dot co dot uk>
+ Gregor Maier <gregor at net dot in dot tum dot de>
+ Greg Stark <gsstark at mit dot edu>
+ Greg Troxel <gdt at ir dot bbn dot com>
+ Guillaume Pelat <endymion_ at users dot sourceforge dot net>
+ Gustavo Zacarias <gustavo at zacarias dot com dot ar>
+ Hagen Paul Pfeifer <hagen at jauu dot net>
+ Henri Doreau <hdoreau at sourceforge dot net>
+ Hyung Sik Yoon <hsyn at kr dot ibm dot com>
+ Igor Khristophorov <igor at atdot dot org>
+ Jakub Zawadzki <darkjames at darkjames dot pl>
+ Jan-Philip Velders <jpv at veldersjes dot net>
+ Jason R. Thorpe <thorpej at netbsd dot org>
+ Javier Achirica <achirica at ttd dot net>
+ Jean-Louis Charton <Jean-Louis dot CHARTON at oikialog dot com>
+ Jean Tourrilhes <jt at hpl dot hp dot com>
+ Jefferson Ogata <jogata at nodc dot noaa dot gov>
+ Jesper Dangaard Brouer <hawk at comx dot dk>
+ Jesper Peterson <jesper at endace dot com>
+ Jesse Gross <jesse at nicira dot com>
+ Jiri Slaby <jirislaby at gmail dot com>
+ Joerg Mayer <jmayer at loplof dot de>
+ John Bankier <jbankier at rainfinity dot com>
+ Jon Lindgren <jonl at yubyub dot net>
+ Jon Smirl <jonsmirl at gmail dot com>
+ Jorge Boncompte [DTI2] <jorge at dti2 dot net>
+ Juergen Schoenwaelder <schoenw at ibr dot cs dot tu-bs dot de>
+ Julien Moutinho <julm at savines dot alpes dot fr dot eu dot org>
+ Jung-uk Kim <jkim at FreeBSD dot org>
+ Kazushi Sugyo <sugyo at pb dot jp dot nec dot com>
+ Klaus Klein <kleink at netbsd dot org>
+ Koryn Grant <koryn at endace dot com>
+ Kris Katterjohn <katterjohn at gmail dot com>
+ Krzysztof Halasa <khc at pm dot waw dot pl>
+ Lennert Buytenhek <buytenh at wantstofly dot org>
+ Lorenzo Cavallaro <sullivan at sikurezza dot org>
+ Loris Degioanni <loris at netgroup-serv dot polito dot it>
+ Love Hörnquist-Åstrand <lha at stacken dot kth dot se>
+ Luis MartinGarcia <luis dot mgarc at gmail dot com>
+ Maciej W. Rozycki <macro at ds2 dot pg dot gda dot pl>
+ Mansour Behabadi <mansour at oxplot dot com>
+ Marcus Felipe Pereira <marcus at task dot com dot br>
+ Mark C. Brown <mbrown at hp dot com>
+ Mark Johnston <markjdb at gmail dot com>
+ Mark Pizzolato <List-tcpdump-workers at subscriptions dot pizzolato dot net>
+ Markus Mayer <markus_mayer at sourceforge dot net>
+ Martin Husemann <martin at netbsd dot org>
+ Márton Németh <nm127 at freemail dot hu>
+ Matthew Luckie <mjl at luckie dot org dot nz>
+ Max Laier <max at love2party dot net>
+ Michal Kubecek <mkubecek at suse dot cz>
+ Michal Labedzki <michal dot labedzki at tieto dot com>
+ Michal Sekletar <msekleta at redhat dot com>
+ Mike Frysinger <vapier at gmail dot com>
+ Mike Kershaw <dragorn at kismetwireless dot net>
+ Mike Wiacek <mike at iroot dot net>
+ Miroslav Lichvar <mlichvar at redhat dot com>
+ Monroe Williams <monroe at pobox dot com>
+ Nicolas Dade <ndade at nsd dot dyndns dot org>
+ Niko Delarich <niko dot delarich at gmail dot com>
+ N. Leiten <nleiten at sourceforge dot net>
+ <nvercamm at sourceforge dot net>
+ Octavian Cerna <tavy at ylabs dot com>
+ Olaf Kirch <okir at caldera dot de>
+ Ollie Wild <aaw at users dot sourceforge dot net>
+ Onno van der Linden <onno at simplex dot nl>
+ Paolo Abeni <pabeni at redhat dot com>
+ Patrick Marie <mycroft at virgaria dot org>
+ Patrick McHardy <kaber at trash not net>
+ Paul Mundt <lethal at linux-sh dot org>
+ Pavel Kankovsky <kan at dcit dot cz>
+ Pawel Pokrywka <publicpp at gmail dot com>
+ Peter Fales <peter at fales-lorenz dot net>
+ Peter Jeremy <peter dot jeremy at alcatel dot com dot au>
+ Peter Volkov <pva at gentoo dot org>
+ Phil Wood <cpw at lanl dot gov>
+ Rafal Maszkowski <rzm at icm dot edu dot pl>
+ <rcb-isis at users dot sourceforge dot net>
+ Richard Stearn <richard at rns-stearn dot demon dot co dot uk>
+ Rick Jones <raj at cup dot hp dot com>
+ Robert Edmonds <stu-42 at sourceforge dot net>
+ Roberto Mariani <jelot-tcpdump at jelot dot it>
+ Rongxi Li <rongxi dot li at chaitin dot com>
+ Roland Dreier <roland at purestorage dot com>
+ Romain Francoise <rfrancoise at debian dot org>
+ Sagun Shakya <sagun dot shakya at sun dot com>
+ Scott Barron <sb125499 at ohiou dot edu>
+ Scott Gifford <sgifford at tir dot com>
+ Scott Mcmillan <scott dot a dot mcmillan at intel dot com>
+ Sebastian Krahmer <krahmer at cs dot uni-potsdam dot de>
+ Sebastien Roy <Sebastien dot Roy at Sun dot COM>
+ Sepherosa Ziehau <sepherosa at gmail dot com>
+ Shaun Clowes <delius at progsoc dot uts dot edu dot au>
+ Solomon Peachy <pizza at shaftnet dot org>
+ Stefan Hudson <hudson at mbay dot net>
+ Stephen Donnelly <stephen at endace dot com>
+ Takashi Yamamoto <yamt at mwd dot biglobe dot ne dot jp>
+ Tanaka Shin-ya <zstanaka at archer dot livedoor dot com>
+ Tobias Poschwatta <posch at sourceforge dot net>
+ Tony Li <tli at procket dot com>
+ Torsten Landschoff <torsten at debian dot org>
+ Uns Lider <unslider at miranda dot org>
+ Uwe Girlich <Uwe dot Girlich at philosys dot de>
+ Wesley Shields <wxs at FreeBSD dot org>
+ Xianjie Zhang <xzhang at cup dot hp dot com>
+ Xin Li <delphij at FreeBSD dot org>
+ Xue Jiang Qing <xuejianqing at star-net dot cn>
+ Yen Yen Lim
+ Yoann Vandoorselaere <yoann at prelude-ids dot org>
+ Yvan Vanhullebus <vanhu at sourceforge dot net>
+
+The original LBL crew:
+ Steve McCanne
+ Craig Leres
+ Van Jacobson
+
+Past maintainers (in alphabetical order):
+ Bill Fenner <fenner at research dot att dot com>
+ Fulvio Risso <risso at polito dot it>
+ Hannes Gredler <hannes at gredler dot at>
+ Jun-ichiro itojun Hagino <itojun at iijlab dot net> Also see: http://www.wide.ad.jp/itojun-award/
diff --git a/lib/libpcap/libpcap/ChmodBPF/ChmodBPF b/lib/libpcap/libpcap/ChmodBPF/ChmodBPF
new file mode 100755
index 0000000..ee37121
--- /dev/null
+++ b/lib/libpcap/libpcap/ChmodBPF/ChmodBPF
@@ -0,0 +1,33 @@
+#! /bin/sh
+
+. /etc/rc.common
+
+StartService ()
+{
+ #
+ # Unfortunately, Mac OS X's devfs is based on the old FreeBSD
+ # one, not the current one, so there's no way to configure it
+ # to create BPF devices with particular owners or groups.
+ # This startup item will make it owned by the admin group,
+ # with permissions rw-rw----, so that anybody in the admin
+ # group can use programs that capture or send raw packets.
+ #
+ # Change this as appropriate for your site, e.g. to make
+ # it owned by a particular user without changing the permissions,
+ # so only that user and the super-user can capture or send raw
+ # packets, or give it the permissions rw-r-----, so that
+ # only the super-user can send raw packets but anybody in the
+ # admin group can capture packets.
+ #
+ chgrp admin /dev/bpf*
+ chmod g+rw /dev/bpf*
+}
+
+StopService ()
+{
+ return 0;
+}
+
+RestartService () { StartService; }
+
+RunService "$1"
diff --git a/lib/libpcap/libpcap/ChmodBPF/StartupParameters.plist b/lib/libpcap/libpcap/ChmodBPF/StartupParameters.plist
new file mode 100644
index 0000000..cba2166
--- /dev/null
+++ b/lib/libpcap/libpcap/ChmodBPF/StartupParameters.plist
@@ -0,0 +1,4 @@
+{
+ Description = "Change BPF permissions";
+ Provides = ("ChmodBPF");
+}
diff --git a/lib/libpcap/libpcap/GenVersion.bat b/lib/libpcap/libpcap/GenVersion.bat
new file mode 100644
index 0000000..babf373
--- /dev/null
+++ b/lib/libpcap/libpcap/GenVersion.bat
@@ -0,0 +1,23 @@
+REM
+REM Automatically generate pcap_version.h based on pcap_version.h.in
+REM for Windows
+REM The version string comes from VERSION
+REM @echo off
+REM
+
+setlocal enableextensions disabledelayedexpansion
+
+set "search=%%%%LIBPCAP_VERSION%%%%"
+set /p replace=<%1
+
+if exist %3 del %3 2>nul
+
+for /f "delims=" %%i in ('type %2' ) do (
+ set "line=%%i"
+ setlocal enabledelayedexpansion
+ set "line=!line:%search%=%replace%!"
+ >>%3 echo(!line!
+ endlocal
+)
+
+echo pcap_version.h generated
diff --git a/lib/libpcap/libpcap/INSTALL.md b/lib/libpcap/libpcap/INSTALL.md
new file mode 100644
index 0000000..3a303fe
--- /dev/null
+++ b/lib/libpcap/libpcap/INSTALL.md
@@ -0,0 +1,352 @@
+To build libpcap, run "./configure" (a shell script). The configure
+script will determine your system attributes and generate an
+appropriate Makefile from Makefile.in. Next run "make". If everything
+goes well you can su to root and run "make install". However, you need
+not install libpcap if you just want to build tcpdump; just make sure
+the tcpdump and libpcap directory trees have the same parent
+directory.
+
+If configure says:
+
+ configure: warning: cannot determine packet capture interface
+ configure: warning: (see INSTALL for more info)
+
+then your system either does not support packet capture or your system
+does support packet capture but libpcap does not support that
+particular type. (If you have HP-UX, see below.) If your system uses a
+packet capture not supported by libpcap, please send us patches; don't
+forget to include an autoconf fragment suitable for use in
+configure.ac.
+
+It is possible to override the default packet capture type, although
+the circumstance where this works are limited. For example if you have
+installed bpf under SunOS 4 and wish to build a snit libpcap:
+
+ ./configure --with-pcap=snit
+
+Another example is to force a supported packet capture type in the case
+where the configure scripts fails to detect it.
+
+You will need an ANSI C compiler to build libpcap. The configure script
+will abort if your compiler is not ANSI compliant. If this happens, use
+the generally available GNU C compiler (GCC).
+
+You will need either Flex 2.5.31 or later, or a version of Lex
+compatible with it (if any exist), to build libpcap. The configure
+script will abort if there isn't any such program. If you have an older
+version of Flex, or don't have a compatible version of Lex, the current
+version of flex is available at flex.sourceforge.net.
+
+You will need either Bison, Berkeley YACC, or a version of YACC
+compatible with them (if any exist), to build libpcap. The configure
+script will abort if there isn't any such program. If you don't have
+any such program, the current version of Bison can be found at
+http://ftp.gnu.org/gnu/bison/ and the current version of Berkeley YACC
+can be found at http://invisible-island.net/byacc/.
+
+Sometimes the stock C compiler does not interact well with Flex and
+Bison. The list of problems includes undefined references for alloca.
+You can get around this by installing GCC.
+
+If you use Solaris, there is a bug with bufmod(7) that is fixed in
+Solaris 2.3.2 (aka SunOS 5.3.2). Setting a snapshot length with the
+broken bufmod(7) results in data be truncated from the FRONT of the
+packet instead of the end. The work around is to not set a snapshot
+length but this results in performance problems since the entire packet
+is copied to user space. If you must run an older version of Solaris,
+there is a patch available from Sun; ask for bugid 1149065. After
+installing the patch, use "setenv BUFMOD_FIXED" to enable use of
+bufmod(7). However, we recommend you run a more current release of
+Solaris.
+
+If you use the SPARCompiler, you must be careful to not use the
+/usr/ucb/cc interface. If you do, you will get bogus warnings and
+perhaps errors. Either make sure your path has /opt/SUNWspro/bin
+before /usr/ucb or else:
+
+ setenv CC /opt/SUNWspro/bin/cc
+
+before running configure. (You might have to do a "make distclean"
+if you already ran configure once).
+
+If you are trying to do packet capture with a FORE ATM card, you may or
+may not be able to. They usually only release their driver in object
+code so unless their driver supports packet capture, there's not much
+libpcap can do.
+
+If you get an error like:
+
+ tcpdump: recv_ack: bind error 0x???
+
+when using DLPI, look for the DL_ERROR_ACK error return values, usually
+in /usr/include/sys/dlpi.h, and find the corresponding value.
+
+Under {DEC OSF/1, Digital UNIX, Tru64 UNIX}, packet capture must be
+enabled before it can be used. For instructions on how to enable packet
+filter support, see:
+
+ ftp://ftp.digital.com/pub/Digital/dec-faq/Digital-UNIX
+
+Look for the "How do I configure the Berkeley Packet Filter and capture
+tcpdump traces?" item.
+
+Once you enable packet filter support, your OSF system will support bpf
+natively.
+
+Under Ultrix, packet capture must be enabled before it can be used. For
+instructions on how to enable packet filter support, see:
+
+ ftp://ftp.digital.com/pub/Digital/dec-faq/ultrix
+
+If you use HP-UX, you must have at least version 9 and either the
+version of cc that supports ANSI C (cc -Aa) or else use the GNU C
+compiler. You must also buy the optional streams package. If you don't
+have:
+
+ /usr/include/sys/dlpi.h
+ /usr/include/sys/dlpi_ext.h
+
+then you don't have the streams package. In addition, we believe you
+need to install the "9.X LAN and DLPI drivers cumulative" patch
+(PHNE_6855) to make the version 9 DLPI work with libpcap.
+
+The DLPI streams package is standard starting with HP-UX 10.
+
+The HP implementation of DLPI is a little bit eccentric. Unlike
+Solaris, you must attach /dev/dlpi instead of the specific /dev/*
+network pseudo device entry in order to capture packets. The PPA is
+based on the ifnet "index" number. Under HP-UX 9, it is necessary to
+read /dev/kmem and the kernel symbol file (/hp-ux). Under HP-UX 10,
+DLPI can provide information for determining the PPA. It does not seem
+to be possible to trace the loopback interface. Unlike other DLPI
+implementations, PHYS implies MULTI and SAP and you get an error if you
+try to enable more than one promiscuous mode at a time.
+
+It is impossible to capture outbound packets on HP-UX 9. To do so on
+HP-UX 10, you will, apparently, need a late "LAN products cumulative
+patch" (at one point, it was claimed that this would be PHNE_18173 for
+s700/10.20; at another point, it was claimed that the required patches
+were PHNE_20892, PHNE_20725 and PHCO_10947, or newer patches), and to do
+so on HP-UX 11 you will, apparently, need the latest lancommon/DLPI
+patches and the latest driver patch for the interface(s) in use on HP-UX
+11 (at one point, it was claimed that patches PHNE_19766, PHNE_19826,
+PHNE_20008, and PHNE_20735 did the trick).
+
+Furthermore, on HP-UX 10, you will need to turn on a kernel switch by
+doing
+
+ echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem
+
+You would have to arrange that this happen on reboots; the right way to
+do that would probably be to put it into an executable script file
+"/sbin/init.d/outbound_promisc" and making
+"/sbin/rc2.d/S350outbound_promisc" a symbolic link to that script.
+
+Finally, testing shows that there can't be more than one simultaneous
+DLPI user per network interface.
+
+If you use Linux, this version of libpcap is known to compile and run
+under Red Hat 4.0 with the 2.0.25 kernel. It may work with earlier 2.X
+versions but is guaranteed not to work with 1.X kernels. Running more
+than one libpcap program at a time, on a system with a 2.0.X kernel, can
+cause problems since promiscuous mode is implemented by twiddling the
+interface flags from the libpcap application; the packet capture
+mechanism in the 2.2 and later kernels doesn't have this problem. Also,
+packet timestamps aren't very good. This appears to be due to haphazard
+handling of the timestamp in the kernel.
+
+Note well: there is rumoured to be a version of tcpdump floating around
+called 3.0.3 that includes libpcap and is supposed to support Linux.
+You should be advised that neither the Network Research Group at LBNL
+nor the Tcpdump Group ever generated a release with this version number.
+The LBNL Network Research Group notes with interest that a standard
+cracker trick to get people to install trojans is to distribute bogus
+packages that have a version number higher than the current release.
+They also noted with annoyance that 90% of the Linux related bug reports
+they got are due to changes made to unofficial versions of their page.
+If you are having trouble but aren't using a version that came from
+tcpdump.org, please try that before submitting a bug report!
+
+On Linux, libpcap will not work if the kernel does not have the packet
+socket option enabled; see the README.linux file for information about
+this.
+
+If you use AIX, you may not be able to build libpcap from this release.
+We do not have an AIX system in house so it's impossible for us to test
+AIX patches submitted to us. We are told that you must link against
+/lib/pse.exp, that you must use AIX cc or a GNU C compiler newer than
+2.7.2, and that you may need to run strload before running a libpcap
+application.
+
+Read the README.aix file for information on installing libpcap and
+configuring your system to be able to support libpcap.
+
+If you use NeXTSTEP, you will not be able to build libpcap from this
+release.
+
+If you use SINIX, you should be able to build libpcap from this
+release. It is known to compile and run on SINIX-Y/N 5.42 with the C-DS
+V1.0 or V1.1 compiler. But note that in some releases of SINIX, yacc
+emits incorrect code; if grammar.y fails to compile, change every
+occurence of:
+
+ #ifdef YYDEBUG
+
+to:
+ #if YYDEBUG
+
+Another workaround is to use flex and bison.
+
+If you use SCO, you might have trouble building libpcap from this
+release. We do not have a machine running SCO and have not had reports
+of anyone successfully building on it; the current release of libpcap
+does not compile on SCO OpenServer 5. Although SCO apparently supports
+DLPI to some extent, the DLPI in OpenServer 5 is very non-standard, and
+it appears that completely new code would need to be written to capture
+network traffic. SCO do not appear to provide tcpdump binaries for
+OpenServer 5 or OpenServer 6 as part of SCO Skunkware:
+
+ http://www.sco.com/skunkware/
+
+If you use UnixWare, you might be able to build libpcap from this
+release, or you might not. We do not have a machine running UnixWare,
+so we have not tested it; however, SCO provide packages for libpcap
+0.6.2 and tcpdump 3.7.1 in the UnixWare 7/Open UNIX 8 part of SCO
+Skunkware, and the source package for libpcap 0.6.2 is not changed from
+the libpcap 0.6.2 source release, so this release of libpcap might also
+build without changes on UnixWare 7.
+
+If linking tcpdump fails with "Undefined: _alloca" when using bison on
+a Sun4, your version of Bison is broken. In any case version 1.16 or
+higher is recommended (1.14 is known to cause problems 1.16 is known to
+work). Either pick up a current version from:
+
+ http://ftp.gnu.org/gnu/bison/
+
+or hack around it by inserting the lines:
+
+ #ifdef __GNUC__
+ #define alloca __builtin_alloca
+ #else
+ #ifdef sparc
+ #include <alloca.h>
+ #else
+ char *alloca ();
+ #endif
+ #endif
+
+right after the (100 line!) GNU license comment in bison.simple, remove
+grammar.[co] and fire up make again.
+
+If you use SunOS 4, your kernel must support streams NIT. If you run a
+libpcap program and it dies with:
+
+ /dev/nit: No such device
+
+You must add streams NIT support to your kernel configuration, run
+config and boot the new kernel.
+
+FILES
+-----
+CHANGES - description of differences between releases
+ChmodBPF/* - macOS startup item to set ownership and permissions
+ on /dev/bpf*
+CMakeLists.txt - CMake file
+CONTRIBUTING - guidelines for contributing
+CREDITS - people that have helped libpcap along
+INSTALL.md - this file
+LICENSE - the license under which tcpdump is distributed
+Makefile.in - compilation rules (input to the configure script)
+README.md - description of distribution
+doc/README.aix - notes on using libpcap on AIX
+doc/README.dag - notes on using libpcap to capture on Endace DAG devices
+doc/README.hpux - notes on using libpcap on HP-UX
+doc/README.linux.md - notes on using libpcap on Linux
+doc/README.macos - notes on using libpcap on macOS
+doc/README.septel - notes on using libpcap to capture on Intel/Septel devices
+doc/README.sita - notes on using libpcap to capture on SITA devices
+doc/README.tru64 - notes on using libpcap on Digital/Tru64 UNIX
+doc/README.Win32 - notes on using libpcap on Win32 systems (with Npcap)
+VERSION - version of this release
+acconfig.h - support for post-2.13 autoconf
+aclocal.m4 - autoconf macros
+arcnet.h - ARCNET definitions
+atmuni31.h - ATM Q.2931 definitions
+bpf_dump.c - BPF program printing routines
+bpf_filter.c - BPF filtering routines
+bpf_image.c - BPF disassembly routine
+config.guess - autoconf support
+config.h.in - autoconf input
+config.sub - autoconf support
+configure - configure script (run this first)
+configure.ac - configure script source
+dlpisubs.c - DLPI-related functions for pcap-dlpi.c and pcap-libdlpi.c
+dlpisubs.h - DLPI-related function declarations
+etherent.c - /etc/ethers support routines
+ethertype.h - Ethernet protocol types and names definitions
+fad-getad.c - pcap_findalldevs() for systems with getifaddrs()
+fad-gifc.c - pcap_findalldevs() for systems with only SIOCGIFLIST
+fad-glifc.c - pcap_findalldevs() for systems with SIOCGLIFCONF
+filtertest.c - test program for BPF compiler
+findalldevstest.c - test program for pcap_findalldevs()
+gencode.c - BPF code generation routines
+gencode.h - BPF code generation definitions
+grammar.y - filter string grammar
+ieee80211.h - 802.11 definitions
+install-sh - BSD style install script
+lbl/os-*.h - OS-dependent defines and prototypes
+llc.h - 802.2 LLC SAP definitions
+missing/* - replacements for missing library functions
+mkdep - construct Makefile dependency list
+msdos/* - drivers for MS-DOS capture support
+nametoaddr.c - hostname to address routines
+nlpid.h - OSI network layer protocol identifier definitions
+net - symlink to bpf/net
+optimize.c - BPF optimization routines
+pcap/bluetooth.h - public definition of DLT_BLUETOOTH_HCI_H4_WITH_PHDR header
+pcap/bpf.h - BPF definitions
+pcap/namedb.h - public libpcap name database definitions
+pcap/pcap.h - public libpcap definitions
+pcap/sll.h - public definition of DLT_LINUX_SLL header
+pcap/usb.h - public definition of DLT_USB header
+pcap-bpf.c - BSD Packet Filter support
+pcap-bpf.h - header for backwards compatibility
+pcap-bt-linux.c - Bluetooth capture support for Linux
+pcap-bt-linux.h - Bluetooth capture support for Linux
+pcap-dag.c - Endace DAG device capture support
+pcap-dag.h - Endace DAG device capture support
+pcap-dlpi.c - Data Link Provider Interface support
+pcap-dos.c - MS-DOS capture support
+pcap-dos.h - headers for MS-DOS capture support
+pcap-enet.c - enet support
+pcap-int.h - internal libpcap definitions
+pcap-libdlpi.c - Data Link Provider Interface support for systems with libdlpi
+pcap-linux.c - Linux packet socket support
+pcap-namedb.h - header for backwards compatibility
+pcap-nit.c - SunOS Network Interface Tap support
+pcap-nit.h - SunOS Network Interface Tap definitions
+pcap-npf.c - WinPcap capture support
+pcap-null.c - dummy monitor support (allows offline use of libpcap)
+pcap-pf.c - Ultrix and Digital/Tru64 UNIX Packet Filter support
+pcap-pf.h - Ultrix and Digital/Tru64 UNIX Packet Filter definitions
+pcap-septel.c - Intel/Septel device capture support
+pcap-septel.h - Intel/Septel device capture support
+pcap-sita.c - SITA device capture support
+pcap-sita.h - SITA device capture support
+pcap-sita.html - SITA device capture documentation
+pcap-stdinc.h - includes and #defines for compiling on Win32 systems
+pcap-snit.c - SunOS 4.x STREAMS-based Network Interface Tap support
+pcap-snoop.c - IRIX Snoop network monitoring support
+pcap-usb-linux.c - USB capture support for Linux
+pcap-usb-linux.h - USB capture support for Linux
+pcap.3pcap - manual entry for the library
+pcap.c - pcap utility routines
+pcap.h - header for backwards compatibility
+pcap_*.3pcap - manual entries for library functions
+pcap-filter.4 - manual entry for filter syntax
+pcap-linktype.4 - manual entry for link-layer header types
+ppp.h - Point to Point Protocol definitions
+savefile.c - offline support
+scanner.l - filter string scanner
+sunatmpos.h - definitions for SunATM capturing
+Win32 - headers and routines for building on Win32 systems
diff --git a/lib/libpcap/libpcap/LICENSE b/lib/libpcap/libpcap/LICENSE
new file mode 100644
index 0000000..a10474d
--- /dev/null
+++ b/lib/libpcap/libpcap/LICENSE
@@ -0,0 +1,19 @@
+License: BSD
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/lib/libpcap/libpcap/Makefile b/lib/libpcap/libpcap/Makefile
new file mode 100644
index 0000000..589e226
--- /dev/null
+++ b/lib/libpcap/libpcap/Makefile
@@ -0,0 +1,774 @@
+# Copyright (c) 1993, 1994, 1995, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = /usr/local
+exec_prefix = ${prefix}
+datarootdir = ${prefix}/share
+# Pathname of directory to install the configure program
+bindir = ${exec_prefix}/bin
+# Pathname of directory to install the rpcapd daemon
+sbindir = ${exec_prefix}/sbin
+# Pathname of directory to install the include files
+includedir = ${prefix}/include
+# Pathname of directory to install the library
+libdir = ${exec_prefix}/lib
+# Pathname of directory to install the man pages
+mandir = ${datarootdir}/man
+
+# VPATH
+srcdir = .
+
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = gcc
+AR = ar
+LN_S = ln -s
+MKDEP =
+CCOPT = -fvisibility=hidden -fno-common
+SHLIB_CCOPT =
+INCLS = -I. -I/usr/local/include
+DEFS = -DBUILDING_PCAP -Dpcap_EXPORTS -DHAVE_CONFIG_H
+ADDLOBJS =
+ADDLARCHIVEOBJS =
+LIBS =
+CROSSFLAGS=
+CFLAGS = -g -O2 ${CROSSFLAGS}
+LDFLAGS = ${CROSSFLAGS}
+DYEXT = dylib
+V_RPATH_OPT =
+DEPENDENCY_CFLAG =
+PROG=libpcap
+PTHREAD_LIBS=
+BUILD_RPCAPD=
+INSTALL_RPCAPD=
+EXTRA_NETWORK_LIBS=
+
+# Standard CFLAGS for building members of a shared library
+FULL_CFLAGS = $(CCOPT) -arch x86_64 -arch i386 $(SHLIB_CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+RANLIB = ranlib
+
+LEX = flex
+YACC = bison -y
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+ @rm -f $@
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+PSRC = pcap-bpf.c
+FSRC = fad-getad.c
+SSRC =
+CSRC = pcap.c gencode.c optimize.c nametoaddr.c etherent.c \
+ fmtutils.c \
+ savefile.c sf-pcap.c sf-pcapng.c pcap-common.c \
+ bpf_image.c bpf_filter.c bpf_dump.c
+GENSRC = scanner.c grammar.c
+LIBOBJS =
+
+SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC)
+
+# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
+# hack the extra indirection
+OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
+PUBHDR = \
+ pcap.h \
+ pcap-bpf.h \
+ pcap-namedb.h \
+ pcap/bpf.h \
+ pcap/bluetooth.h \
+ pcap/can_socketcan.h \
+ pcap/compiler-tests.h \
+ pcap/dlt.h \
+ pcap/funcattrs.h \
+ pcap/pcap-inttypes.h \
+ pcap/ipnet.h \
+ pcap/namedb.h \
+ pcap/nflog.h \
+ pcap/pcap.h \
+ pcap/sll.h \
+ pcap/socket.h \
+ pcap/vlan.h \
+ pcap/usb.h
+
+HDR = $(PUBHDR) \
+ arcnet.h \
+ atmuni31.h \
+ diag-control.h \
+ ethertype.h \
+ extract.h \
+ fmtutils.h \
+ ftmacros.h \
+ gencode.h \
+ ieee80211.h \
+ llc.h \
+ nametoaddr.h \
+ nlpid.h \
+ optimize.h \
+ pcap-common.h \
+ pcap-int.h \
+ pcap-rpcap.h \
+ pcap-types.h \
+ portability.h \
+ ppp.h \
+ rpcap-protocol.h \
+ sf-pcap.h \
+ sf-pcapng.h \
+ sunatmpos.h \
+ varattrs.h
+
+GENHDR = \
+ scanner.h grammar.h
+
+TAGFILES = \
+ $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) libpcap.a libpcap.so.`cat $(srcdir)/VERSION` \
+ $(PROG)-`cat $(srcdir)/VERSION`.tar.gz $(GENSRC) $(GENHDR) \
+ lex.yy.c pcap-config libpcap.pc
+
+MAN1 = pcap-config.1
+
+MAN3PCAP_EXPAND = \
+ pcap.3pcap.in \
+ pcap_compile.3pcap.in \
+ pcap_datalink.3pcap.in \
+ pcap_dump_open.3pcap.in \
+ pcap_get_tstamp_precision.3pcap.in \
+ pcap_list_datalinks.3pcap.in \
+ pcap_list_tstamp_types.3pcap.in \
+ pcap_open_dead.3pcap.in \
+ pcap_open_offline.3pcap.in \
+ pcap_set_immediate_mode.3pcap.in \
+ pcap_set_tstamp_precision.3pcap.in \
+ pcap_set_tstamp_type.3pcap.in
+
+MAN3PCAP_NOEXPAND = \
+ pcap_activate.3pcap \
+ pcap_breakloop.3pcap \
+ pcap_can_set_rfmon.3pcap \
+ pcap_close.3pcap \
+ pcap_create.3pcap \
+ pcap_datalink_name_to_val.3pcap \
+ pcap_datalink_val_to_name.3pcap \
+ pcap_dump.3pcap \
+ pcap_dump_close.3pcap \
+ pcap_dump_file.3pcap \
+ pcap_dump_flush.3pcap \
+ pcap_dump_ftell.3pcap \
+ pcap_file.3pcap \
+ pcap_fileno.3pcap \
+ pcap_findalldevs.3pcap \
+ pcap_freecode.3pcap \
+ pcap_get_required_select_timeout.3pcap \
+ pcap_get_selectable_fd.3pcap \
+ pcap_geterr.3pcap \
+ pcap_inject.3pcap \
+ pcap_is_swapped.3pcap \
+ pcap_lib_version.3pcap \
+ pcap_lookupdev.3pcap \
+ pcap_lookupnet.3pcap \
+ pcap_loop.3pcap \
+ pcap_major_version.3pcap \
+ pcap_next_ex.3pcap \
+ pcap_offline_filter.3pcap \
+ pcap_open_live.3pcap \
+ pcap_set_buffer_size.3pcap \
+ pcap_set_datalink.3pcap \
+ pcap_set_promisc.3pcap \
+ pcap_set_protocol_linux.3pcap \
+ pcap_set_rfmon.3pcap \
+ pcap_set_snaplen.3pcap \
+ pcap_set_timeout.3pcap \
+ pcap_setdirection.3pcap \
+ pcap_setfilter.3pcap \
+ pcap_setnonblock.3pcap \
+ pcap_snapshot.3pcap \
+ pcap_stats.3pcap \
+ pcap_statustostr.3pcap \
+ pcap_strerror.3pcap \
+ pcap_tstamp_type_name_to_val.3pcap \
+ pcap_tstamp_type_val_to_name.3pcap
+
+MAN3PCAP = $(MAN3PCAP_NOEXPAND) $(MAN3PCAP_EXPAND:.in=)
+
+MANFILE = \
+ pcap-savefile.manfile.in
+
+MANMISC = \
+ pcap-filter.manmisc.in \
+ pcap-linktype.manmisc.in \
+ pcap-tstamp.manmisc.in
+
+EXTRA_DIST = \
+ CHANGES \
+ ChmodBPF/ChmodBPF \
+ ChmodBPF/StartupParameters.plist \
+ CREDITS \
+ CMakeLists.txt \
+ INSTALL.md \
+ LICENSE \
+ Makefile.in \
+ Makefile-devel-adds \
+ README.md \
+ doc \
+ CONTRIBUTING.md \
+ TODO \
+ VERSION \
+ aclocal.m4 \
+ chmod_bpf \
+ cmake_uninstall.cmake.in \
+ cmakeconfig.h.in \
+ cmake/Modules/FindDAG.cmake \
+ cmake/Modules/FindFseeko.cmake \
+ cmake/Modules/FindLFS.cmake \
+ cmake/Modules/FindPacket.cmake \
+ cmake/Modules/FindSNF.cmake \
+ cmake/Modules/FindTC.cmake \
+ cmake/have_siocglifconf.c \
+ config.guess \
+ config.h.in \
+ config.sub \
+ configure \
+ configure.ac \
+ dlpisubs.c \
+ dlpisubs.h \
+ fad-getad.c \
+ fad-gifc.c \
+ fad-glifc.c \
+ grammar.y \
+ install-sh \
+ lbl/os-aix4.h \
+ lbl/os-aix7.h \
+ lbl/os-hpux11.h \
+ lbl/os-osf4.h \
+ lbl/os-osf5.h \
+ lbl/os-solaris2.h \
+ lbl/os-sunos4.h \
+ lbl/os-ultrix4.h \
+ libpcap.pc.in \
+ missing/asprintf.c \
+ missing/getopt.c \
+ missing/getopt.h \
+ missing/snprintf.c \
+ missing/strlcat.c \
+ missing/strlcpy.c \
+ missing/strtok_r.c \
+ missing/win_asprintf.c \
+ missing/win_snprintf.c \
+ mkdep \
+ msdos/bin2c.c \
+ msdos/makefile \
+ msdos/makefile.dj \
+ msdos/makefile.wc \
+ msdos/pkt_rx0.asm \
+ msdos/pkt_rx1.s \
+ msdos/pktdrvr.c \
+ msdos/pktdrvr.h \
+ msdos/readme.dos \
+ nomkdep \
+ org.tcpdump.chmod_bpf.plist \
+ pcap-bpf.c \
+ pcap-bt-linux.c \
+ pcap-bt-linux.h \
+ pcap-bt-monitor-linux.c \
+ pcap-bt-monitor-linux.h \
+ pcap-config.in \
+ pcap-dag.c \
+ pcap-dag.h \
+ pcap-dbus.c \
+ pcap-dbus.h \
+ pcap-dll.rc \
+ pcap-dlpi.c \
+ pcap-dos.c \
+ pcap-dos.h \
+ pcap-enet.c \
+ pcap-int.h \
+ pcap-libdlpi.c \
+ pcap-linux.c \
+ pcap-namedb.h \
+ pcap-new.c \
+ pcap-netfilter-linux.c \
+ pcap-netfilter-linux.h \
+ pcap-netmap.c \
+ pcap-netmap.h \
+ pcap-nit.c \
+ pcap-npf.c \
+ pcap-null.c \
+ pcap-pf.c \
+ pcap-rdmasniff.c \
+ pcap-rdmasniff.h \
+ pcap-rpcap.c \
+ pcap-rpcap-int.h \
+ pcap-septel.c \
+ pcap-septel.h \
+ pcap-sita.h \
+ pcap-sita.c \
+ pcap-sita.html \
+ pcap-snf.c \
+ pcap-snf.h \
+ pcap-snit.c \
+ pcap-snoop.c \
+ pcap-tc.c \
+ pcap-tc.h \
+ pcap-usb-linux.c \
+ pcap-usb-linux.h \
+ rpcap-protocol.c \
+ rpcapd/CMakeLists.txt \
+ rpcapd/Makefile.in \
+ rpcapd/config_params.h \
+ rpcapd/daemon.h \
+ rpcapd/daemon.c \
+ rpcapd/fileconf.c \
+ rpcapd/fileconf.h \
+ rpcapd/log.h \
+ rpcapd/log.c \
+ rpcapd/org.tcpdump.rpcapd.plist \
+ rpcapd/rpcapd.c \
+ rpcapd/rpcapd.h \
+ rpcapd/rpcapd.inetd.conf \
+ rpcapd/rpcapd.manadmin.in \
+ rpcapd/rpcapd-config.manfile.in \
+ rpcapd/rpcapd.rc \
+ rpcapd/rpcapd.socket \
+ rpcapd/rpcapd.xinetd.conf \
+ rpcapd/rpcapd@.service \
+ rpcapd/win32-svc.c \
+ rpcapd/win32-svc.h \
+ sockutils.c \
+ sockutils.h \
+ scanner.l \
+ testprogs/CMakeLists.txt \
+ testprogs/Makefile.in \
+ testprogs/can_set_rfmon_test.c \
+ testprogs/capturetest.c \
+ testprogs/filtertest.c \
+ testprogs/findalldevstest.c \
+ testprogs/opentest.c \
+ testprogs/reactivatetest.c \
+ testprogs/selpolltest.c \
+ testprogs/threadsignaltest.c \
+ testprogs/unix.h \
+ testprogs/valgrindtest.c \
+ tests/shb-option-too-long.pcapng \
+ Win32/Prj/wpcap.sln \
+ Win32/Prj/wpcap.vcxproj \
+ Win32/Prj/wpcap.vcxproj.filters
+
+all: libpcap.a shared $(BUILD_RPCAPD) libpcap.pc pcap-config
+
+libpcap.a: $(OBJ)
+ @rm -f $@
+ $(AR) rc $@ $(OBJ) $(ADDLARCHIVEOBJS)
+ $(RANLIB) $@
+
+shared: libpcap.$(DYEXT)
+
+libpcap.so: $(OBJ)
+ @rm -f $@
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ $(CC) $(LDFLAGS) -shared $@.$$MAJOR_VER \
+ -o $@.$$VER $(OBJ) $(ADDLOBJS) $(LIBS)
+
+#
+# The following rule succeeds, but the result is untested.
+#
+# In macOS, the libpcap dylib has the name "libpcap.A.dylib", with its
+# full path as the install_name, and with the compatibility and current
+# version both set to 1. The compatibility version is set to 1 so that
+# programs built with a newer version of the library will run against
+# older versions if they don't use APIs available in the newer version
+# but not in the older version.
+#
+# We also use "A" as the major version, and 1 as the compatibility version,
+# but set the current version to the value in VERSION, with any non-numeric
+# stuff stripped off (the compatibility and current version must be of the
+# form X[.Y[.Z]], with Y and Z possibly absent, and with all components
+# numeric).
+#
+libpcap.dylib: $(OBJ)
+ rm -f libpcap*.dylib
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=A; \
+ COMPAT_VER=1; \
+ CURRENT_VER=`sed 's/[^0-9.].*$$//' $(srcdir)/VERSION`; \
+ $(CC) -dynamiclib -undefined error $(LDFLAGS) -arch x86_64 -arch i386 \
+ -o libpcap.$$VER.dylib $(OBJ) $(ADDLOBJS) $(LIBS) \
+ -install_name $(libdir)/libpcap.$$MAJOR_VER.dylib \
+ -compatibility_version $$COMPAT_VER \
+ -current_version $$CURRENT_VER
+
+#
+# The HP-UX linker manual says that the convention for a versioned library
+# is libXXX.{number}, not libXXX.sl.{number}. That appears to be the case
+# on at least one HP-UX 11.00 system; libXXX.sl is a symlink to
+# libXXX.{number}.
+#
+# The manual also says "library-level versioning" (think "sonames") was
+# added in HP-UX 10.0.
+#
+# XXX - this assumes we're using the HP linker, rather than the GNU
+# linker, even with GCC.
+#
+libpcap.sl: $(OBJ)
+ @MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ rm -f libpcap.$$MAJOR_VER
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ ld -b $(LDFLAGS) -o libpcap.$$MAJOR_VER +h libpcap.$$MAJOR_VER \
+ $(OBJ) $(ADDLOBJS) $(LIBS)
+
+#
+# AIX is different from everybody else. A shared library is an archive
+# library with one or more shared-object components. We still build a
+# normal static archive library on AIX, for the benefit of the traditional
+# scheme of building libpcap and tcpdump in subdirectories of the
+# same directory, with tcpdump statically linked with the libpcap
+# in question, but we also build a shared library as "libpcap.shareda"
+# and install *it*, rather than the static library, as "libpcap.a".
+#
+libpcap.shareda: $(OBJ)
+ @rm -f $@ shr.o
+ $(CC) $(LDFLAGS) -shared -o shr.o $(OBJ) $(ADDLOBJS) $(LIBS)
+ $(AR) rc $@ shr.o
+
+#
+# For platforms that don't support shared libraries (or on which we
+# don't support shared libraries).
+#
+libpcap.none:
+
+scanner.c: $(srcdir)/scanner.l
+ $(LEX) -P pcap_ --header-file=scanner.h --nounput -o scanner.c $<
+scanner.h: scanner.c
+## Recover from the removal of $@
+ @if test -f $@; then :; else \
+ rm -f scanner.c; \
+ $(MAKE) $(MAKEFLAGS) scanner.c; \
+ fi
+
+scanner.o: scanner.c grammar.h
+ $(CC) $(FULL_CFLAGS) -c scanner.c
+
+grammar.c: $(srcdir)/grammar.y
+ $(YACC) -p pcap_ -o grammar.c -d $<
+grammar.h: grammar.c
+## Recover from the removal of $@
+ @if test -f $@; then :; else \
+ rm -f grammar.c; \
+ $(MAKE) $(MAKEFLAGS) grammar.c; \
+ fi
+
+grammar.o: grammar.c scanner.h
+ $(CC) $(FULL_CFLAGS) -c grammar.c
+
+gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
+
+asprintf.o: $(srcdir)/missing/asprintf.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/asprintf.c
+
+snprintf.o: $(srcdir)/missing/snprintf.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
+
+strlcat.o: $(srcdir)/missing/strlcat.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcat.c
+
+strlcpy.o: $(srcdir)/missing/strlcpy.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcpy.c
+
+strtok_r.o: $(srcdir)/missing/strtok_r.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strtok_r.c
+
+#
+# Generate the libpcap.pc file.
+#
+# Some Makes, e.g. AIX Make and Solaris Make, can't handle "--file=$@.tmp:$<";
+# for example, the Solaris 9 make man page says
+#
+# Because make assigns $< and $* as it would for implicit rules
+# (according to the suffixes list and the directory contents),
+# they may be unreliable when used within explicit target entries.
+#
+# and this is an explicit target entry.
+#
+# Therefore, instead of using $<, we explicitly put in $(srcdir)/libpcap.pc.in.
+#
+libpcap.pc: $(srcdir)/libpcap.pc.in ./config.status
+ @rm -f $@ $@.tmp
+ ./config.status --file=$@.tmp:$(srcdir)/libpcap.pc.in
+ mv $@.tmp $@
+ chmod a+x $@
+
+#
+# Generate the pcap-config script. See above.
+#
+pcap-config: $(srcdir)/pcap-config.in ./config.status
+ @rm -f $@ $@.tmp
+ ./config.status --file=$@.tmp:$(srcdir)/pcap-config.in
+ mv $@.tmp $@
+ chmod a+x $@
+
+#
+# Remote pcap daemon.
+#
+build-rpcapd: libpcap.a
+ cd rpcapd; $(MAKE)
+
+#
+# Test programs - not built by default, and not installed.
+#
+testprogs: FORCE
+ cd testprogs; $(MAKE)
+
+FORCE:
+
+install: install-shared install-archive libpcap.pc pcap-config
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ [ -d $(DESTDIR)$(includedir) ] || \
+ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir))
+ [ -d $(DESTDIR)$(includedir)/pcap ] || \
+ (mkdir -p $(DESTDIR)$(includedir)/pcap; chmod 755 $(DESTDIR)$(includedir)/pcap)
+ [ -d $(DESTDIR)$(mandir)/man1 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1)
+ [ -d $(DESTDIR)$(mandir)/man3 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3)
+ [ -d $(DESTDIR)$(mandir)/man5 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man5; chmod 755 $(DESTDIR)$(mandir)/man5)
+ [ -d $(DESTDIR)$(mandir)/man7 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man7; chmod 755 $(DESTDIR)$(mandir)/man7)
+ for i in $(PUBHDR); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(includedir)/$$i; done
+ [ -d $(DESTDIR)$(bindir) ] || \
+ (mkdir -p $(DESTDIR)$(bindir); chmod 755 $(DESTDIR)$(bindir))
+ $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config
+ [ -d $(DESTDIR)$(libdir)/pkgconfig ] || \
+ (mkdir -p $(DESTDIR)$(libdir)/pkgconfig; chmod 755 $(DESTDIR)$(libdir)/pkgconfig)
+ $(INSTALL_DATA) libpcap.pc $(DESTDIR)$(libdir)/pkgconfig/libpcap.pc
+ for i in $(MAN1); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(mandir)/man1/$$i; done
+ for i in $(MAN3PCAP_NOEXPAND); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(mandir)/man3/$$i; done
+ for i in $(MAN3PCAP_EXPAND:.in=); do \
+ $(INSTALL_DATA) $$i \
+ $(DESTDIR)$(mandir)/man3/$$i; done
+ (cd $(DESTDIR)$(mandir)/man3 && \
+ rm -f pcap_datalink_val_to_description.3pcap && \
+ $(LN_S) pcap_datalink_val_to_name.3pcap \
+ pcap_datalink_val_to_description.3pcap && \
+ rm -f pcap_datalink_val_to_description_or_dlt.3pcap && \
+ $(LN_S) pcap_datalink_val_to_name.3pcap \
+ pcap_datalink_val_to_description_or_dlt.3pcap && \
+ rm -f pcap_dump_fopen.3pcap && \
+ $(LN_S) pcap_dump_open.3pcap pcap_dump_fopen.3pcap && \
+ rm -f pcap_freealldevs.3pcap && \
+ $(LN_S) pcap_findalldevs.3pcap pcap_freealldevs.3pcap && \
+ rm -f pcap_perror.3pcap && \
+ $(LN_S) pcap_geterr.3pcap pcap_perror.3pcap && \
+ rm -f pcap_sendpacket.3pcap && \
+ $(LN_S) pcap_inject.3pcap pcap_sendpacket.3pcap && \
+ rm -f pcap_free_datalinks.3pcap && \
+ $(LN_S) pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap && \
+ rm -f pcap_free_tstamp_types.3pcap && \
+ $(LN_S) pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap && \
+ rm -f pcap_dispatch.3pcap && \
+ $(LN_S) pcap_loop.3pcap pcap_dispatch.3pcap && \
+ rm -f pcap_minor_version.3pcap && \
+ $(LN_S) pcap_major_version.3pcap pcap_minor_version.3pcap && \
+ rm -f pcap_next.3pcap && \
+ $(LN_S) pcap_next_ex.3pcap pcap_next.3pcap && \
+ rm -f pcap_open_dead_with_tstamp_precision.3pcap && \
+ $(LN_S) pcap_open_dead.3pcap \
+ pcap_open_dead_with_tstamp_precision.3pcap && \
+ rm -f pcap_open_offline_with_tstamp_precision.3pcap && \
+ $(LN_S) pcap_open_offline.3pcap pcap_open_offline_with_tstamp_precision.3pcap && \
+ rm -f pcap_fopen_offline.3pcap && \
+ $(LN_S) pcap_open_offline.3pcap pcap_fopen_offline.3pcap && \
+ rm -f pcap_fopen_offline_with_tstamp_precision.3pcap && \
+ $(LN_S) pcap_open_offline.3pcap pcap_fopen_offline_with_tstamp_precision.3pcap && \
+ rm -f pcap_tstamp_type_val_to_description.3pcap && \
+ $(LN_S) pcap_tstamp_type_val_to_name.3pcap pcap_tstamp_type_val_to_description.3pcap && \
+ rm -f pcap_getnonblock.3pcap && \
+ $(LN_S) pcap_setnonblock.3pcap pcap_getnonblock.3pcap)
+ for i in $(MANFILE); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+ $(DESTDIR)$(mandir)/man5/`echo $$i | sed 's/.manfile.in/.5/'`; done
+ for i in $(MANMISC); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manmisc.in/.manmisc/'` \
+ $(DESTDIR)$(mandir)/man7/`echo $$i | sed 's/.manmisc.in/.7/'`; done
+
+install-shared: install-shared-$(DYEXT)
+install-shared-so: libpcap.so
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ $(INSTALL_PROGRAM) libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
+ ln -sf libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
+ ln -sf libpcap.so.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.so
+install-shared-dylib: libpcap.dylib
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=A; \
+ $(INSTALL_PROGRAM) libpcap.$$VER.dylib $(DESTDIR)$(libdir)/libpcap.$$VER.dylib; \
+ ln -sf libpcap.$$VER.dylib $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER.dylib; \
+ ln -sf libpcap.$$MAJOR_VER.dylib $(DESTDIR)$(libdir)/libpcap.dylib
+install-shared-sl: libpcap.sl
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ $(INSTALL_PROGRAM) libpcap.$$MAJOR_VER $(DESTDIR)$(libdir)
+ ln -sf libpcap.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.sl
+install-shared-shareda: libpcap.shareda
+ #
+ # AIX shared libraries are weird. They're archive libraries
+ # with one or more shared object components.
+ #
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ $(INSTALL_PROGRAM) libpcap.shareda $(DESTDIR)$(libdir)/libpcap.a
+install-shared-none:
+
+install-archive: install-archive-$(DYEXT)
+install-archive-so install-archive-dylib install-archive-sl install-archive-none: libpcap.a
+ #
+ # Most platforms have separate suffixes for shared and
+ # archive libraries, so we install both.
+ #
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a
+ $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a
+install-archive-shareda:
+ #
+ # AIX, however, doesn't, so we don't install the archive
+ # library on AIX.
+ #
+
+install-rpcapd:
+ cd rpcapd; $(MAKE) DESTDIR=$(DESTDIR) install
+
+uninstall: uninstall-shared uninstall-rpcapd
+ rm -f $(DESTDIR)$(libdir)/libpcap.a
+ for i in $(PUBHDR); do \
+ rm -f $(DESTDIR)$(includedir)/$$i; done
+ -rmdir $(DESTDIR)$(includedir)/pcap
+ rm -f $(DESTDIR)/$(libdir)/pkgconfig/libpcap.pc
+ rm -f $(DESTDIR)/$(bindir)/pcap-config
+ for i in $(MAN1); do \
+ rm -f $(DESTDIR)$(mandir)/man1/$$i; done
+ for i in $(MAN3PCAP); do \
+ rm -f $(DESTDIR)$(mandir)/man3/$$i; done
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_free_datalinks.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_free_tstamp_types.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_open_dead_with_tstamp_precision.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_open_offline_with_tstamp_precision.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline_with_tstamp_precision.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_tstamp_type_val_to_description.3pcap
+ for i in $(MANFILE); do \
+ rm -f $(DESTDIR)$(mandir)/man5/`echo $$i | sed 's/.manfile.in/.5/'`; done
+ for i in $(MANMISC); do \
+ rm -f $(DESTDIR)$(mandir)/man7/`echo $$i | sed 's/.manmisc.in/.7/'`; done
+
+uninstall-shared: uninstall-shared-$(DYEXT)
+uninstall-shared-so:
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.so
+uninstall-shared-dylib:
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=A; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.$$VER.dylib; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER.dylib; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.dylib
+uninstall-shared-sl:
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.sl
+uninstall-shared-shareda:
+ rm -f $(DESTDIR)$(libdir)/libpcap.a
+uninstall-shared-none:
+
+uninstall-rpcapd:
+ cd rpcapd; $(MAKE) DESTDIR=$(DESTDIR) uninstall
+
+clean:
+ rm -f $(CLEANFILES)
+ cd rpcapd; $(MAKE) clean
+ cd testprogs; $(MAKE) clean
+
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
+ config.h gnuc.h net os-proto.h libpcap.pc \
+ pcap-config stamp-h stamp-h.in
+ rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
+ rm -rf autom4te.cache
+ cd rpcapd; $(MAKE) distclean
+ cd testprogs; $(MAKE) distclean
+
+extags: $(TAGFILES)
+ ctags $(TAGFILES)
+
+tags: $(TAGFILES)
+ ctags -wtd $(TAGFILES)
+
+releasetar:
+ @cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
+ mkdir $$name; \
+ tar -c --exclude='*~' -f - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
+ $(MAN3PCAP_NOEXPAND) $(MANFILE) $(MANMISC) $(EXTRA_DIST) | \
+ (cd $$name; tar xf -); \
+ tar -c -z -f $$name.tar.gz $$name; \
+ rm -rf $$name
+
+depend: $(GENSRC) $(GENHDR)
+ $(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
+ cd rpcapd; $(MAKE) depend
+ cd testprogs; $(MAKE) depend
diff --git a/lib/libpcap/libpcap/Makefile-devel-adds b/lib/libpcap/libpcap/Makefile-devel-adds
new file mode 100644
index 0000000..fea63bb
--- /dev/null
+++ b/lib/libpcap/libpcap/Makefile-devel-adds
@@ -0,0 +1,22 @@
+#
+# Auto-regenerate configure script or Makefile when things change.
+# From autoconf.info . Works best with GNU Make.
+#
+${srcdir}/configure: configure.ac aclocal.m4
+ cd ${srcdir} && autoconf
+
+# autoheader might not change config.h.in, so touch a stamp file.
+${srcdir}/config.h.in: ${srcdir}/stamp-h.in
+${srcdir}/stamp-h.in: configure.ac aclocal.m4
+ cd ${srcdir} && autoheader
+ echo timestamp > ${srcdir}/stamp-h.in
+
+config.h: stamp-h
+stamp-h: ${srcdir}/config.h.in config.status
+ ./config.status
+
+Makefile: Makefile.in config.status
+ ./config.status
+
+config.status: ${srcdir}/configure
+ ./config.status --recheck
diff --git a/lib/libpcap/libpcap/Makefile.in b/lib/libpcap/libpcap/Makefile.in
new file mode 100644
index 0000000..5a6b165
--- /dev/null
+++ b/lib/libpcap/libpcap/Makefile.in
@@ -0,0 +1,774 @@
+# Copyright (c) 1993, 1994, 1995, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+# Pathname of directory to install the configure program
+bindir = @bindir@
+# Pathname of directory to install the rpcapd daemon
+sbindir = @sbindir@
+# Pathname of directory to install the include files
+includedir = @includedir@
+# Pathname of directory to install the library
+libdir = @libdir@
+# Pathname of directory to install the man pages
+mandir = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = @CC@
+AR = @AR@
+LN_S = @LN_S@
+MKDEP = @MKDEP@
+CCOPT = @V_CCOPT@
+SHLIB_CCOPT = @V_SHLIB_CCOPT@
+INCLS = -I. @V_INCLS@
+DEFS = -DBUILDING_PCAP -Dpcap_EXPORTS @DEFS@ @V_DEFS@
+ADDLOBJS = @ADDLOBJS@
+ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
+LIBS = @LIBS@
+CROSSFLAGS=
+CFLAGS = @CFLAGS@ ${CROSSFLAGS}
+LDFLAGS = @LDFLAGS@ ${CROSSFLAGS}
+DYEXT = @DYEXT@
+V_RPATH_OPT = @V_RPATH_OPT@
+DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
+PROG=libpcap
+PTHREAD_LIBS=@PTHREAD_LIBS@
+BUILD_RPCAPD=@BUILD_RPCAPD@
+INSTALL_RPCAPD=@INSTALL_RPCAPD@
+EXTRA_NETWORK_LIBS=@EXTRA_NETWORK_LIBS@
+
+# Standard CFLAGS for building members of a shared library
+FULL_CFLAGS = $(CCOPT) @V_LIB_CCOPT_FAT@ $(SHLIB_CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+RANLIB = @RANLIB@
+
+LEX = @LEX@
+YACC = @YACC@
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+ @rm -f $@
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+PSRC = pcap-@V_PCAP@.c @USB_SRC@ @BT_SRC@ @BT_MONITOR_SRC@ @NETFILTER_SRC@ @DBUS_SRC@ @NETMAP_SRC@ @RDMA_SRC@
+FSRC = @V_FINDALLDEVS@
+SSRC = @SSRC@
+CSRC = pcap.c gencode.c optimize.c nametoaddr.c etherent.c \
+ fmtutils.c \
+ savefile.c sf-pcap.c sf-pcapng.c pcap-common.c \
+ bpf_image.c bpf_filter.c bpf_dump.c
+GENSRC = scanner.c grammar.c
+LIBOBJS = @LIBOBJS@
+
+SRC = $(PSRC) $(FSRC) $(CSRC) $(SSRC) $(GENSRC)
+
+# We would like to say "OBJ = $(SRC:.c=.o)" but Ultrix's make cannot
+# hack the extra indirection
+OBJ = $(PSRC:.c=.o) $(FSRC:.c=.o) $(CSRC:.c=.o) $(SSRC:.c=.o) $(GENSRC:.c=.o) $(LIBOBJS)
+PUBHDR = \
+ pcap.h \
+ pcap-bpf.h \
+ pcap-namedb.h \
+ pcap/bpf.h \
+ pcap/bluetooth.h \
+ pcap/can_socketcan.h \
+ pcap/compiler-tests.h \
+ pcap/dlt.h \
+ pcap/funcattrs.h \
+ pcap/pcap-inttypes.h \
+ pcap/ipnet.h \
+ pcap/namedb.h \
+ pcap/nflog.h \
+ pcap/pcap.h \
+ pcap/sll.h \
+ pcap/socket.h \
+ pcap/vlan.h \
+ pcap/usb.h
+
+HDR = $(PUBHDR) \
+ arcnet.h \
+ atmuni31.h \
+ diag-control.h \
+ ethertype.h \
+ extract.h \
+ fmtutils.h \
+ ftmacros.h \
+ gencode.h \
+ ieee80211.h \
+ llc.h \
+ nametoaddr.h \
+ nlpid.h \
+ optimize.h \
+ pcap-common.h \
+ pcap-int.h \
+ pcap-rpcap.h \
+ pcap-types.h \
+ portability.h \
+ ppp.h \
+ rpcap-protocol.h \
+ sf-pcap.h \
+ sf-pcapng.h \
+ sunatmpos.h \
+ varattrs.h
+
+GENHDR = \
+ scanner.h grammar.h
+
+TAGFILES = \
+ $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) libpcap.a libpcap.so.`cat $(srcdir)/VERSION` \
+ $(PROG)-`cat $(srcdir)/VERSION`.tar.gz $(GENSRC) $(GENHDR) \
+ lex.yy.c pcap-config libpcap.pc
+
+MAN1 = pcap-config.1
+
+MAN3PCAP_EXPAND = \
+ pcap.3pcap.in \
+ pcap_compile.3pcap.in \
+ pcap_datalink.3pcap.in \
+ pcap_dump_open.3pcap.in \
+ pcap_get_tstamp_precision.3pcap.in \
+ pcap_list_datalinks.3pcap.in \
+ pcap_list_tstamp_types.3pcap.in \
+ pcap_open_dead.3pcap.in \
+ pcap_open_offline.3pcap.in \
+ pcap_set_immediate_mode.3pcap.in \
+ pcap_set_tstamp_precision.3pcap.in \
+ pcap_set_tstamp_type.3pcap.in
+
+MAN3PCAP_NOEXPAND = \
+ pcap_activate.3pcap \
+ pcap_breakloop.3pcap \
+ pcap_can_set_rfmon.3pcap \
+ pcap_close.3pcap \
+ pcap_create.3pcap \
+ pcap_datalink_name_to_val.3pcap \
+ pcap_datalink_val_to_name.3pcap \
+ pcap_dump.3pcap \
+ pcap_dump_close.3pcap \
+ pcap_dump_file.3pcap \
+ pcap_dump_flush.3pcap \
+ pcap_dump_ftell.3pcap \
+ pcap_file.3pcap \
+ pcap_fileno.3pcap \
+ pcap_findalldevs.3pcap \
+ pcap_freecode.3pcap \
+ pcap_get_required_select_timeout.3pcap \
+ pcap_get_selectable_fd.3pcap \
+ pcap_geterr.3pcap \
+ pcap_inject.3pcap \
+ pcap_is_swapped.3pcap \
+ pcap_lib_version.3pcap \
+ pcap_lookupdev.3pcap \
+ pcap_lookupnet.3pcap \
+ pcap_loop.3pcap \
+ pcap_major_version.3pcap \
+ pcap_next_ex.3pcap \
+ pcap_offline_filter.3pcap \
+ pcap_open_live.3pcap \
+ pcap_set_buffer_size.3pcap \
+ pcap_set_datalink.3pcap \
+ pcap_set_promisc.3pcap \
+ pcap_set_protocol_linux.3pcap \
+ pcap_set_rfmon.3pcap \
+ pcap_set_snaplen.3pcap \
+ pcap_set_timeout.3pcap \
+ pcap_setdirection.3pcap \
+ pcap_setfilter.3pcap \
+ pcap_setnonblock.3pcap \
+ pcap_snapshot.3pcap \
+ pcap_stats.3pcap \
+ pcap_statustostr.3pcap \
+ pcap_strerror.3pcap \
+ pcap_tstamp_type_name_to_val.3pcap \
+ pcap_tstamp_type_val_to_name.3pcap
+
+MAN3PCAP = $(MAN3PCAP_NOEXPAND) $(MAN3PCAP_EXPAND:.in=)
+
+MANFILE = \
+ pcap-savefile.manfile.in
+
+MANMISC = \
+ pcap-filter.manmisc.in \
+ pcap-linktype.manmisc.in \
+ pcap-tstamp.manmisc.in
+
+EXTRA_DIST = \
+ CHANGES \
+ ChmodBPF/ChmodBPF \
+ ChmodBPF/StartupParameters.plist \
+ CREDITS \
+ CMakeLists.txt \
+ INSTALL.md \
+ LICENSE \
+ Makefile.in \
+ Makefile-devel-adds \
+ README.md \
+ doc \
+ CONTRIBUTING.md \
+ TODO \
+ VERSION \
+ aclocal.m4 \
+ chmod_bpf \
+ cmake_uninstall.cmake.in \
+ cmakeconfig.h.in \
+ cmake/Modules/FindDAG.cmake \
+ cmake/Modules/FindFseeko.cmake \
+ cmake/Modules/FindLFS.cmake \
+ cmake/Modules/FindPacket.cmake \
+ cmake/Modules/FindSNF.cmake \
+ cmake/Modules/FindTC.cmake \
+ cmake/have_siocglifconf.c \
+ config.guess \
+ config.h.in \
+ config.sub \
+ configure \
+ configure.ac \
+ dlpisubs.c \
+ dlpisubs.h \
+ fad-getad.c \
+ fad-gifc.c \
+ fad-glifc.c \
+ grammar.y \
+ install-sh \
+ lbl/os-aix4.h \
+ lbl/os-aix7.h \
+ lbl/os-hpux11.h \
+ lbl/os-osf4.h \
+ lbl/os-osf5.h \
+ lbl/os-solaris2.h \
+ lbl/os-sunos4.h \
+ lbl/os-ultrix4.h \
+ libpcap.pc.in \
+ missing/asprintf.c \
+ missing/getopt.c \
+ missing/getopt.h \
+ missing/snprintf.c \
+ missing/strlcat.c \
+ missing/strlcpy.c \
+ missing/strtok_r.c \
+ missing/win_asprintf.c \
+ missing/win_snprintf.c \
+ mkdep \
+ msdos/bin2c.c \
+ msdos/makefile \
+ msdos/makefile.dj \
+ msdos/makefile.wc \
+ msdos/pkt_rx0.asm \
+ msdos/pkt_rx1.s \
+ msdos/pktdrvr.c \
+ msdos/pktdrvr.h \
+ msdos/readme.dos \
+ nomkdep \
+ org.tcpdump.chmod_bpf.plist \
+ pcap-bpf.c \
+ pcap-bt-linux.c \
+ pcap-bt-linux.h \
+ pcap-bt-monitor-linux.c \
+ pcap-bt-monitor-linux.h \
+ pcap-config.in \
+ pcap-dag.c \
+ pcap-dag.h \
+ pcap-dbus.c \
+ pcap-dbus.h \
+ pcap-dll.rc \
+ pcap-dlpi.c \
+ pcap-dos.c \
+ pcap-dos.h \
+ pcap-enet.c \
+ pcap-int.h \
+ pcap-libdlpi.c \
+ pcap-linux.c \
+ pcap-namedb.h \
+ pcap-new.c \
+ pcap-netfilter-linux.c \
+ pcap-netfilter-linux.h \
+ pcap-netmap.c \
+ pcap-netmap.h \
+ pcap-nit.c \
+ pcap-npf.c \
+ pcap-null.c \
+ pcap-pf.c \
+ pcap-rdmasniff.c \
+ pcap-rdmasniff.h \
+ pcap-rpcap.c \
+ pcap-rpcap-int.h \
+ pcap-septel.c \
+ pcap-septel.h \
+ pcap-sita.h \
+ pcap-sita.c \
+ pcap-sita.html \
+ pcap-snf.c \
+ pcap-snf.h \
+ pcap-snit.c \
+ pcap-snoop.c \
+ pcap-tc.c \
+ pcap-tc.h \
+ pcap-usb-linux.c \
+ pcap-usb-linux.h \
+ rpcap-protocol.c \
+ rpcapd/CMakeLists.txt \
+ rpcapd/Makefile.in \
+ rpcapd/config_params.h \
+ rpcapd/daemon.h \
+ rpcapd/daemon.c \
+ rpcapd/fileconf.c \
+ rpcapd/fileconf.h \
+ rpcapd/log.h \
+ rpcapd/log.c \
+ rpcapd/org.tcpdump.rpcapd.plist \
+ rpcapd/rpcapd.c \
+ rpcapd/rpcapd.h \
+ rpcapd/rpcapd.inetd.conf \
+ rpcapd/rpcapd.manadmin.in \
+ rpcapd/rpcapd-config.manfile.in \
+ rpcapd/rpcapd.rc \
+ rpcapd/rpcapd.socket \
+ rpcapd/rpcapd.xinetd.conf \
+ rpcapd/rpcapd@.service \
+ rpcapd/win32-svc.c \
+ rpcapd/win32-svc.h \
+ sockutils.c \
+ sockutils.h \
+ scanner.l \
+ testprogs/CMakeLists.txt \
+ testprogs/Makefile.in \
+ testprogs/can_set_rfmon_test.c \
+ testprogs/capturetest.c \
+ testprogs/filtertest.c \
+ testprogs/findalldevstest.c \
+ testprogs/opentest.c \
+ testprogs/reactivatetest.c \
+ testprogs/selpolltest.c \
+ testprogs/threadsignaltest.c \
+ testprogs/unix.h \
+ testprogs/valgrindtest.c \
+ tests/shb-option-too-long.pcapng \
+ Win32/Prj/wpcap.sln \
+ Win32/Prj/wpcap.vcxproj \
+ Win32/Prj/wpcap.vcxproj.filters
+
+all: libpcap.a shared $(BUILD_RPCAPD) libpcap.pc pcap-config
+
+libpcap.a: $(OBJ)
+ @rm -f $@
+ $(AR) rc $@ $(OBJ) $(ADDLARCHIVEOBJS)
+ $(RANLIB) $@
+
+shared: libpcap.$(DYEXT)
+
+libpcap.so: $(OBJ)
+ @rm -f $@
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ @V_SHLIB_CMD@ $(LDFLAGS) @V_SHLIB_OPT@ @V_SONAME_OPT@$@.$$MAJOR_VER \
+ -o $@.$$VER $(OBJ) $(ADDLOBJS) $(LIBS)
+
+#
+# The following rule succeeds, but the result is untested.
+#
+# In macOS, the libpcap dylib has the name "libpcap.A.dylib", with its
+# full path as the install_name, and with the compatibility and current
+# version both set to 1. The compatibility version is set to 1 so that
+# programs built with a newer version of the library will run against
+# older versions if they don't use APIs available in the newer version
+# but not in the older version.
+#
+# We also use "A" as the major version, and 1 as the compatibility version,
+# but set the current version to the value in VERSION, with any non-numeric
+# stuff stripped off (the compatibility and current version must be of the
+# form X[.Y[.Z]], with Y and Z possibly absent, and with all components
+# numeric).
+#
+libpcap.dylib: $(OBJ)
+ rm -f libpcap*.dylib
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=A; \
+ COMPAT_VER=1; \
+ CURRENT_VER=`sed 's/[^0-9.].*$$//' $(srcdir)/VERSION`; \
+ $(CC) -dynamiclib -undefined error $(LDFLAGS) @V_LIB_LDFLAGS_FAT@ \
+ -o libpcap.$$VER.dylib $(OBJ) $(ADDLOBJS) $(LIBS) \
+ -install_name $(libdir)/libpcap.$$MAJOR_VER.dylib \
+ -compatibility_version $$COMPAT_VER \
+ -current_version $$CURRENT_VER
+
+#
+# The HP-UX linker manual says that the convention for a versioned library
+# is libXXX.{number}, not libXXX.sl.{number}. That appears to be the case
+# on at least one HP-UX 11.00 system; libXXX.sl is a symlink to
+# libXXX.{number}.
+#
+# The manual also says "library-level versioning" (think "sonames") was
+# added in HP-UX 10.0.
+#
+# XXX - this assumes we're using the HP linker, rather than the GNU
+# linker, even with GCC.
+#
+libpcap.sl: $(OBJ)
+ @MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ rm -f libpcap.$$MAJOR_VER
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ ld -b $(LDFLAGS) -o libpcap.$$MAJOR_VER +h libpcap.$$MAJOR_VER \
+ $(OBJ) $(ADDLOBJS) $(LIBS)
+
+#
+# AIX is different from everybody else. A shared library is an archive
+# library with one or more shared-object components. We still build a
+# normal static archive library on AIX, for the benefit of the traditional
+# scheme of building libpcap and tcpdump in subdirectories of the
+# same directory, with tcpdump statically linked with the libpcap
+# in question, but we also build a shared library as "libpcap.shareda"
+# and install *it*, rather than the static library, as "libpcap.a".
+#
+libpcap.shareda: $(OBJ)
+ @rm -f $@ shr.o
+ $(CC) $(LDFLAGS) @V_SHLIB_OPT@ -o shr.o $(OBJ) $(ADDLOBJS) $(LIBS)
+ $(AR) rc $@ shr.o
+
+#
+# For platforms that don't support shared libraries (or on which we
+# don't support shared libraries).
+#
+libpcap.none:
+
+scanner.c: $(srcdir)/scanner.l
+ $(LEX) -P pcap_ --header-file=scanner.h --nounput -o scanner.c $<
+scanner.h: scanner.c
+## Recover from the removal of $@
+ @if test -f $@; then :; else \
+ rm -f scanner.c; \
+ $(MAKE) $(MAKEFLAGS) scanner.c; \
+ fi
+
+scanner.o: scanner.c grammar.h
+ $(CC) $(FULL_CFLAGS) -c scanner.c
+
+grammar.c: $(srcdir)/grammar.y
+ $(YACC) -p pcap_ -o grammar.c -d $<
+grammar.h: grammar.c
+## Recover from the removal of $@
+ @if test -f $@; then :; else \
+ rm -f grammar.c; \
+ $(MAKE) $(MAKEFLAGS) grammar.c; \
+ fi
+
+grammar.o: grammar.c scanner.h
+ $(CC) $(FULL_CFLAGS) -c grammar.c
+
+gencode.o: $(srcdir)/gencode.c grammar.h scanner.h
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/gencode.c
+
+asprintf.o: $(srcdir)/missing/asprintf.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/asprintf.c
+
+snprintf.o: $(srcdir)/missing/snprintf.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/snprintf.c
+
+strlcat.o: $(srcdir)/missing/strlcat.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcat.c
+
+strlcpy.o: $(srcdir)/missing/strlcpy.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strlcpy.c
+
+strtok_r.o: $(srcdir)/missing/strtok_r.c
+ $(CC) $(FULL_CFLAGS) -o $@ -c $(srcdir)/missing/strtok_r.c
+
+#
+# Generate the libpcap.pc file.
+#
+# Some Makes, e.g. AIX Make and Solaris Make, can't handle "--file=$@.tmp:$<";
+# for example, the Solaris 9 make man page says
+#
+# Because make assigns $< and $* as it would for implicit rules
+# (according to the suffixes list and the directory contents),
+# they may be unreliable when used within explicit target entries.
+#
+# and this is an explicit target entry.
+#
+# Therefore, instead of using $<, we explicitly put in $(srcdir)/libpcap.pc.in.
+#
+libpcap.pc: $(srcdir)/libpcap.pc.in ./config.status
+ @rm -f $@ $@.tmp
+ ./config.status --file=$@.tmp:$(srcdir)/libpcap.pc.in
+ mv $@.tmp $@
+ chmod a+x $@
+
+#
+# Generate the pcap-config script. See above.
+#
+pcap-config: $(srcdir)/pcap-config.in ./config.status
+ @rm -f $@ $@.tmp
+ ./config.status --file=$@.tmp:$(srcdir)/pcap-config.in
+ mv $@.tmp $@
+ chmod a+x $@
+
+#
+# Remote pcap daemon.
+#
+build-rpcapd: libpcap.a
+ cd rpcapd; $(MAKE)
+
+#
+# Test programs - not built by default, and not installed.
+#
+testprogs: FORCE
+ cd testprogs; $(MAKE)
+
+FORCE:
+
+install: install-shared install-archive libpcap.pc pcap-config @INSTALL_RPCAPD@
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ [ -d $(DESTDIR)$(includedir) ] || \
+ (mkdir -p $(DESTDIR)$(includedir); chmod 755 $(DESTDIR)$(includedir))
+ [ -d $(DESTDIR)$(includedir)/pcap ] || \
+ (mkdir -p $(DESTDIR)$(includedir)/pcap; chmod 755 $(DESTDIR)$(includedir)/pcap)
+ [ -d $(DESTDIR)$(mandir)/man1 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man1; chmod 755 $(DESTDIR)$(mandir)/man1)
+ [ -d $(DESTDIR)$(mandir)/man3 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man3; chmod 755 $(DESTDIR)$(mandir)/man3)
+ [ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@)
+ [ -d $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@ ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@)
+ for i in $(PUBHDR); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(includedir)/$$i; done
+ [ -d $(DESTDIR)$(bindir) ] || \
+ (mkdir -p $(DESTDIR)$(bindir); chmod 755 $(DESTDIR)$(bindir))
+ $(INSTALL_PROGRAM) pcap-config $(DESTDIR)$(bindir)/pcap-config
+ [ -d $(DESTDIR)$(libdir)/pkgconfig ] || \
+ (mkdir -p $(DESTDIR)$(libdir)/pkgconfig; chmod 755 $(DESTDIR)$(libdir)/pkgconfig)
+ $(INSTALL_DATA) libpcap.pc $(DESTDIR)$(libdir)/pkgconfig/libpcap.pc
+ for i in $(MAN1); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(mandir)/man1/$$i; done
+ for i in $(MAN3PCAP_NOEXPAND); do \
+ $(INSTALL_DATA) $(srcdir)/$$i \
+ $(DESTDIR)$(mandir)/man3/$$i; done
+ for i in $(MAN3PCAP_EXPAND:.in=); do \
+ $(INSTALL_DATA) $$i \
+ $(DESTDIR)$(mandir)/man3/$$i; done
+ (cd $(DESTDIR)$(mandir)/man3 && \
+ rm -f pcap_datalink_val_to_description.3pcap && \
+ $(LN_S) pcap_datalink_val_to_name.3pcap \
+ pcap_datalink_val_to_description.3pcap && \
+ rm -f pcap_datalink_val_to_description_or_dlt.3pcap && \
+ $(LN_S) pcap_datalink_val_to_name.3pcap \
+ pcap_datalink_val_to_description_or_dlt.3pcap && \
+ rm -f pcap_dump_fopen.3pcap && \
+ $(LN_S) pcap_dump_open.3pcap pcap_dump_fopen.3pcap && \
+ rm -f pcap_freealldevs.3pcap && \
+ $(LN_S) pcap_findalldevs.3pcap pcap_freealldevs.3pcap && \
+ rm -f pcap_perror.3pcap && \
+ $(LN_S) pcap_geterr.3pcap pcap_perror.3pcap && \
+ rm -f pcap_sendpacket.3pcap && \
+ $(LN_S) pcap_inject.3pcap pcap_sendpacket.3pcap && \
+ rm -f pcap_free_datalinks.3pcap && \
+ $(LN_S) pcap_list_datalinks.3pcap pcap_free_datalinks.3pcap && \
+ rm -f pcap_free_tstamp_types.3pcap && \
+ $(LN_S) pcap_list_tstamp_types.3pcap pcap_free_tstamp_types.3pcap && \
+ rm -f pcap_dispatch.3pcap && \
+ $(LN_S) pcap_loop.3pcap pcap_dispatch.3pcap && \
+ rm -f pcap_minor_version.3pcap && \
+ $(LN_S) pcap_major_version.3pcap pcap_minor_version.3pcap && \
+ rm -f pcap_next.3pcap && \
+ $(LN_S) pcap_next_ex.3pcap pcap_next.3pcap && \
+ rm -f pcap_open_dead_with_tstamp_precision.3pcap && \
+ $(LN_S) pcap_open_dead.3pcap \
+ pcap_open_dead_with_tstamp_precision.3pcap && \
+ rm -f pcap_open_offline_with_tstamp_precision.3pcap && \
+ $(LN_S) pcap_open_offline.3pcap pcap_open_offline_with_tstamp_precision.3pcap && \
+ rm -f pcap_fopen_offline.3pcap && \
+ $(LN_S) pcap_open_offline.3pcap pcap_fopen_offline.3pcap && \
+ rm -f pcap_fopen_offline_with_tstamp_precision.3pcap && \
+ $(LN_S) pcap_open_offline.3pcap pcap_fopen_offline_with_tstamp_precision.3pcap && \
+ rm -f pcap_tstamp_type_val_to_description.3pcap && \
+ $(LN_S) pcap_tstamp_type_val_to_name.3pcap pcap_tstamp_type_val_to_description.3pcap && \
+ rm -f pcap_getnonblock.3pcap && \
+ $(LN_S) pcap_setnonblock.3pcap pcap_getnonblock.3pcap)
+ for i in $(MANFILE); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+ $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+ for i in $(MANMISC); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manmisc.in/.manmisc/'` \
+ $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
+
+install-shared: install-shared-$(DYEXT)
+install-shared-so: libpcap.so
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ $(INSTALL_PROGRAM) libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
+ ln -sf libpcap.so.$$VER $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
+ ln -sf libpcap.so.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.so
+install-shared-dylib: libpcap.dylib
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=A; \
+ $(INSTALL_PROGRAM) libpcap.$$VER.dylib $(DESTDIR)$(libdir)/libpcap.$$VER.dylib; \
+ ln -sf libpcap.$$VER.dylib $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER.dylib; \
+ ln -sf libpcap.$$MAJOR_VER.dylib $(DESTDIR)$(libdir)/libpcap.dylib
+install-shared-sl: libpcap.sl
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ $(INSTALL_PROGRAM) libpcap.$$MAJOR_VER $(DESTDIR)$(libdir)
+ ln -sf libpcap.$$MAJOR_VER $(DESTDIR)$(libdir)/libpcap.sl
+install-shared-shareda: libpcap.shareda
+ #
+ # AIX shared libraries are weird. They're archive libraries
+ # with one or more shared object components.
+ #
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ $(INSTALL_PROGRAM) libpcap.shareda $(DESTDIR)$(libdir)/libpcap.a
+install-shared-none:
+
+install-archive: install-archive-$(DYEXT)
+install-archive-so install-archive-dylib install-archive-sl install-archive-none: libpcap.a
+ #
+ # Most platforms have separate suffixes for shared and
+ # archive libraries, so we install both.
+ #
+ [ -d $(DESTDIR)$(libdir) ] || \
+ (mkdir -p $(DESTDIR)$(libdir); chmod 755 $(DESTDIR)$(libdir))
+ $(INSTALL_DATA) libpcap.a $(DESTDIR)$(libdir)/libpcap.a
+ $(RANLIB) $(DESTDIR)$(libdir)/libpcap.a
+install-archive-shareda:
+ #
+ # AIX, however, doesn't, so we don't install the archive
+ # library on AIX.
+ #
+
+install-rpcapd:
+ cd rpcapd; $(MAKE) DESTDIR=$(DESTDIR) install
+
+uninstall: uninstall-shared uninstall-rpcapd
+ rm -f $(DESTDIR)$(libdir)/libpcap.a
+ for i in $(PUBHDR); do \
+ rm -f $(DESTDIR)$(includedir)/$$i; done
+ -rmdir $(DESTDIR)$(includedir)/pcap
+ rm -f $(DESTDIR)/$(libdir)/pkgconfig/libpcap.pc
+ rm -f $(DESTDIR)/$(bindir)/pcap-config
+ for i in $(MAN1); do \
+ rm -f $(DESTDIR)$(mandir)/man1/$$i; done
+ for i in $(MAN3PCAP); do \
+ rm -f $(DESTDIR)$(mandir)/man3/$$i; done
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_datalink_val_to_description.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_dump_fopen.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_freealldevs.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_perror.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_sendpacket.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_free_datalinks.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_free_tstamp_types.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_dispatch.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_minor_version.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_next.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_open_dead_with_tstamp_precision.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_open_offline_with_tstamp_precision.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_fopen_offline_with_tstamp_precision.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_getnonblock.3pcap
+ rm -f $(DESTDIR)$(mandir)/man3/pcap_tstamp_type_val_to_description.3pcap
+ for i in $(MANFILE); do \
+ rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+ for i in $(MANMISC); do \
+ rm -f $(DESTDIR)$(mandir)/man@MAN_MISC_INFO@/`echo $$i | sed 's/.manmisc.in/.@MAN_MISC_INFO@/'`; done
+
+uninstall-shared: uninstall-shared-$(DYEXT)
+uninstall-shared-so:
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.so.$$VER; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.so.$$MAJOR_VER; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.so
+uninstall-shared-dylib:
+ VER=`cat $(srcdir)/VERSION`; \
+ MAJOR_VER=A; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.$$VER.dylib; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER.dylib; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.dylib
+uninstall-shared-sl:
+ MAJOR_VER=`sed 's/\([0-9][0-9]*\)\..*/\1/' $(srcdir)/VERSION`; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.$$MAJOR_VER; \
+ rm -f $(DESTDIR)$(libdir)/libpcap.sl
+uninstall-shared-shareda:
+ rm -f $(DESTDIR)$(libdir)/libpcap.a
+uninstall-shared-none:
+
+uninstall-rpcapd:
+ cd rpcapd; $(MAKE) DESTDIR=$(DESTDIR) uninstall
+
+clean:
+ rm -f $(CLEANFILES)
+ cd rpcapd; $(MAKE) clean
+ cd testprogs; $(MAKE) clean
+
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
+ config.h gnuc.h net os-proto.h libpcap.pc \
+ pcap-config stamp-h stamp-h.in
+ rm -f $(MAN3PCAP_EXPAND:.in=) $(MANFILE:.in=) $(MANMISC:.in=)
+ rm -rf autom4te.cache
+ cd rpcapd; $(MAKE) distclean
+ cd testprogs; $(MAKE) distclean
+
+extags: $(TAGFILES)
+ ctags $(TAGFILES)
+
+tags: $(TAGFILES)
+ ctags -wtd $(TAGFILES)
+
+releasetar:
+ @cwd=`pwd` ; dir=`basename $$cwd` ; name=$(PROG)-`cat VERSION` ; \
+ mkdir $$name; \
+ tar -c --exclude='*~' -f - $(CSRC) $(HDR) $(MAN1) $(MAN3PCAP_EXPAND) \
+ $(MAN3PCAP_NOEXPAND) $(MANFILE) $(MANMISC) $(EXTRA_DIST) | \
+ (cd $$name; tar xf -); \
+ tar -c -z -f $$name.tar.gz $$name; \
+ rm -rf $$name
+
+depend: $(GENSRC) $(GENHDR)
+ $(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
+ cd rpcapd; $(MAKE) depend
+ cd testprogs; $(MAKE) depend
diff --git a/lib/libpcap/libpcap/README.md b/lib/libpcap/libpcap/README.md
new file mode 100644
index 0000000..78cc3c4
--- /dev/null
+++ b/lib/libpcap/libpcap/README.md
@@ -0,0 +1,93 @@
+To report a security issue please send an e-mail to security@tcpdump.org.
+
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+[CONTRIBUTING](CONTRIBUTING.md) in the libpcap source tree root.
+
+The directory doc/ has README files about specific operating systems and
+options.
+
+LIBPCAP 1.x.y
+Now maintained by "The Tcpdump Group"
+https://www.tcpdump.org
+
+Anonymous Git is available via:
+ https://github.com/the-tcpdump-group/libpcap.git
+
+formerly from Lawrence Berkeley National Laboratory
+ Network Research Group <libpcap@ee.lbl.gov>
+ ftp://ftp.ee.lbl.gov/old/libpcap-0.4a7.tar.Z
+
+This directory contains source code for libpcap, a system-independent
+interface for user-level packet capture. libpcap provides a portable
+framework for low-level network monitoring. Applications include
+network statistics collection, security monitoring, network debugging,
+etc. Since almost every system vendor provides a different interface
+for packet capture, and since we've developed several tools that
+require this functionality, we've created this system-independent API
+to ease in porting and to alleviate the need for several
+system-dependent packet capture modules in each application.
+
+For some platforms there are README.{system} files that discuss issues
+with the OS's interface for packet capture on those platforms, such as
+how to enable support for that interface in the OS, if it's not built in
+by default.
+
+The libpcap interface supports a filtering mechanism based on the
+architecture in the BSD packet filter. BPF is described in the 1993
+Winter Usenix paper ``The BSD Packet Filter: A New Architecture for
+User-level Packet Capture''. A compressed PostScript version can be
+found at
+
+ ftp://ftp.ee.lbl.gov/papers/bpf-usenix93.ps.Z
+
+or
+
+ https://www.tcpdump.org/papers/bpf-usenix93.ps.Z
+
+and a gzipped version can be found at
+
+ https://www.tcpdump.org/papers/bpf-usenix93.ps.gz
+
+A PDF version can be found at
+
+ https://www.tcpdump.org/papers/bpf-usenix93.pdf
+
+Although most packet capture interfaces support in-kernel filtering,
+libpcap utilizes in-kernel filtering only for the BPF interface.
+On systems that don't have BPF, all packets are read into user-space
+and the BPF filters are evaluated in the libpcap library, incurring
+added overhead (especially, for selective filters). Ideally, libpcap
+would translate BPF filters into a filter program that is compatible
+with the underlying kernel subsystem, but this is not yet implemented.
+
+BPF is standard in 4.4BSD, BSD/OS, NetBSD, FreeBSD, OpenBSD, DragonFly
+BSD, and macOS; an older, modified and undocumented version is standard
+in AIX. {DEC OSF/1, Digital UNIX, Tru64 UNIX} uses the packetfilter
+interface but has been extended to accept BPF filters (which libpcap
+utilizes). Also, you can add BPF filter support to Ultrix using the
+kernel source and/or object patches available in:
+
+ https://www.tcpdump.org/other/bpfext42.tar.Z
+
+Linux has a number of BPF based systems, and libpcap does not support
+any of the eBPF mechanisms as yet, although it supports many of the
+memory mapped receive mechanisms.
+See the [README.linux](doc/README.linux.md) file for more information.
+
+Note to Linux distributions and *BSD systems that include libpcap:
+
+There's now a rule to make a shared library, which should work on Linux
+and *BSD, among other platforms.
+
+It sets the soname of the library to "libpcap.so.1"; this is what it
+should be, *NOT* libpcap.so.1.x or libpcap.so.1.x.y or something such as
+that.
+
+We've been maintaining binary compatibility between libpcap releases for
+quite a while; there's no reason to tie a binary linked with libpcap to
+a particular release of libpcap.
+
+Current versions can be found at https://www.tcpdump.org.
+
+ - The TCPdump group
diff --git a/lib/libpcap/libpcap/TODO b/lib/libpcap/libpcap/TODO
new file mode 100644
index 0000000..aae24c2
--- /dev/null
+++ b/lib/libpcap/libpcap/TODO
@@ -0,0 +1,35 @@
+ TODO list for libpcap
+=======================
+
+Important stuff (to be done before the next release)
+---------------
+
+General
+
+- configure should not be in Git. Most open source projects have an
+ autogen.sh script to run autoconf etc. after checkout. I think we
+ should stick to the standard.
+
+- The source files should be better documented. There is no official
+ design guideline for what is done where. There should be a common coding
+ style (okay, you can guess that by looking at the code) and a guide for
+ what needs to be documented.
+
+Less urgent items
+-----------------
+
+- Better documentation and cleanup of the interface. I am seeing a few
+ problems at the first glance which needs fixing:
+ + pcap_lookupnet makes little to no sense with protocols != IPv4
+ + not very well suited for interactive programs (think ethereal). There
+ should be a way for the application to get a file descriptor which it
+ has to monitor and a callback in pcap which has to be called on
+ activity (XXX - "pcap_fileno()" handles the first part, although
+ "select()" and "poll()" don't work on BPF devices on most BSDs, and
+ you can call "pcap_dispatch()" as the dispatch routine after putting
+ the descriptor into non-blocking mode)
+ + too many functions. There are a lot of functions for everything which
+ violates the KISS principle. Why do we need pcap_strerror, pcap_perror
+ and pcap_geterr?
+ + the manpage has a brief description of each function but where is the
+ big picture? Seems like you need to buy UNP for that...
diff --git a/lib/libpcap/libpcap/VERSION b/lib/libpcap/libpcap/VERSION
new file mode 100644
index 0000000..9ab8337
--- /dev/null
+++ b/lib/libpcap/libpcap/VERSION
@@ -0,0 +1 @@
+1.9.1
diff --git a/lib/libpcap/libpcap/Win32/Prj/wpcap.sln b/lib/libpcap/libpcap/Win32/Prj/wpcap.sln
new file mode 100644
index 0000000..30ad620
--- /dev/null
+++ b/lib/libpcap/libpcap/Win32/Prj/wpcap.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.40629.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "wpcap", "wpcap.vcxproj", "{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Debug|x64 = Debug|x64
+ Release|Win32 = Release|Win32
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|Win32.Build.0 = Debug|Win32
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|x64.ActiveCfg = Debug|x64
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Debug|x64.Build.0 = Debug|x64
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|Win32.ActiveCfg = Release|Win32
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|Win32.Build.0 = Release|Win32
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|x64.ActiveCfg = Release|x64
+ {8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj b/lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj
new file mode 100644
index 0000000..bebc7fc
--- /dev/null
+++ b/lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <SccProjectName />
+ <SccLocalPath />
+ <ProjectGuid>{8E92D840-6A36-452A-A13C-6E1BA5A2C5A9}</ProjectGuid>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <PlatformToolset>v120</PlatformToolset>
+ <UseOfMfc>false</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.Cpp.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <OutDir>.\Release\</OutDir>
+ <IntDir>.\Release\</IntDir>
+ <LinkIncremental>false</LinkIncremental>
+ <IncludePath>../../../;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <LinkIncremental>false</LinkIncremental>
+ <IncludePath>../../../;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <OutDir>.\Debug\</OutDir>
+ <IntDir>.\Debug\</IntDir>
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>../../../;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <LinkIncremental>true</LinkIncremental>
+ <IncludePath>../../../;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <Optimization>MaxSpeed</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;NDEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <StringPooling>true</StringPooling>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <Optimization>MaxSpeed</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;NDEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\x64\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <MinimalRebuild>true</MinimalRebuild>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;_DEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ </ClCompile>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+ <ClCompile>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <InlineFunctionExpansion>Default</InlineFunctionExpansion>
+ <FunctionLevelLinking>false</FunctionLevelLinking>
+ <Optimization>Disabled</Optimization>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ <AdditionalIncludeDirectories>../../;../../lbl/;../../bpf/;../include/;../../../../common;../../../../dag/include;../../../../dag/drv/windows;../../../Win32-Extensions;./;Win32-Extensions;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>HAVE_VERSION_H;__STDC_VERSION__=199901L;HAVE_PACKET_IS_LOOPBACK_ADAPTER;_DEBUG;YY_NEVER_INTERACTIVE;_USRDLL;pcap_EXPORTS;HAVE_STRERROR;__STDC__;INET6;_WINDOWS;ENABLE_REMOTE;WIN32;_U_=;YY_NO_UNISTD_H;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ </ClCompile>
+ <ResourceCompile>
+ <Culture>0x0409</Culture>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>ws2_32.lib;..\..\..\..\packetWin7\Dll\Project\x64\Release No NetMon and AirPcap\Packet.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ <PreBuildEvent>
+ <Command>call ..\..\GenVersion.bat ..\..\VERSION ..\..\pcap_version.h.in ..\..\pcap_version.h
+win_flex -Ppcap_ -7 --outfile=..\..\scanner.c --header-file=..\..\scanner.h ..\..\scanner.l
+win_bison -ppcap_ --yacc --output=..\..\grammar.c --defines ..\..\grammar.y</Command>
+ </PreBuildEvent>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\..\bpf\net\bpf_filter.c" />
+ <ClCompile Include="..\..\bpf_dump.c" />
+ <ClCompile Include="..\..\bpf_image.c" />
+ <ClCompile Include="..\..\etherent.c" />
+ <ClCompile Include="..\..\gencode.c" />
+ <ClCompile Include="..\..\grammar.c" />
+ <ClCompile Include="..\..\inet.c" />
+ <ClCompile Include="..\..\missing\win_snprintf.c" />
+ <ClCompile Include="..\..\nametoaddr.c" />
+ <ClCompile Include="..\..\optimize.c" />
+ <ClCompile Include="..\..\pcap-common.c" />
+ <ClCompile Include="..\..\pcap-new.c" />
+ <ClCompile Include="..\..\pcap-rpcap.c" />
+ <ClCompile Include="..\..\pcap-win32.c" />
+ <ClCompile Include="..\..\pcap.c" />
+ <ClCompile Include="..\..\savefile.c" />
+ <ClCompile Include="..\..\scanner.c" />
+ <ClCompile Include="..\..\sf-pcapng.c" />
+ <ClCompile Include="..\..\sf-pcap.c" />
+ <ClCompile Include="..\..\sockutils.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\pcap-common.h" />
+ <ClInclude Include="..\..\pcap-int.h" />
+ <ClInclude Include="..\..\pcap-rpcap.h" />
+ <ClInclude Include="..\..\pcap-stdinc.h" />
+ <ClInclude Include="..\..\pcap.h" />
+ <ClInclude Include="..\..\remote-ext.h" />
+ <ClInclude Include="..\..\sockutils.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\Win32-Extensions\version.rc" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj.filters b/lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj.filters
new file mode 100644
index 0000000..9bb60e2
--- /dev/null
+++ b/lib/libpcap/libpcap/Win32/Prj/wpcap.vcxproj.filters
@@ -0,0 +1,107 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <ClCompile Include="..\..\bpf_dump.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\bpf\net\bpf_filter.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\bpf_image.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\etherent.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\gencode.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\grammar.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\inet.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\nametoaddr.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\optimize.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\pcap.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\pcap-win32.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\savefile.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\scanner.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\sf-pcap.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\sf-pcapng.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\pcap-common.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\fad-helpers.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\missing\win_snprintf.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\pcap-new.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\pcap-rpcap.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="..\..\sockutils.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{c51dce5e-0da9-4e33-a235-d5c76c76485c}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{5ec9fd4b-10b5-4527-b249-56b53d844fb1}</UniqueIdentifier>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{c90886f0-8973-436b-a7a1-b9e881544f9a}</UniqueIdentifier>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="..\..\pcap-stdinc.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\pcap-common.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\pcap.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\pcap-int.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\pcap-rpcap.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\remote-ext.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="..\..\sockutils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\..\..\Win32-Extensions\version.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
diff --git a/lib/libpcap/libpcap/aclocal.m4 b/lib/libpcap/libpcap/aclocal.m4
new file mode 100644
index 0000000..b2cb3e5
--- /dev/null
+++ b/lib/libpcap/libpcap/aclocal.m4
@@ -0,0 +1,1079 @@
+dnl Copyright (c) 1995, 1996, 1997, 1998
+dnl The Regents of the University of California. All rights reserved.
+dnl
+dnl Redistribution and use in source and binary forms, with or without
+dnl modification, are permitted provided that: (1) source code distributions
+dnl retain the above copyright notice and this paragraph in its entirety, (2)
+dnl distributions including binary code include the above copyright notice and
+dnl this paragraph in its entirety in the documentation or other materials
+dnl provided with the distribution, and (3) all advertising materials mentioning
+dnl features or use of this software display the following acknowledgement:
+dnl ``This product includes software developed by the University of California,
+dnl Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+dnl the University nor the names of its contributors may be used to endorse
+dnl or promote products derived from this software without specific prior
+dnl written permission.
+dnl THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+dnl WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+dnl MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+dnl
+dnl LBL autoconf macros
+dnl
+
+dnl
+dnl Do whatever AC_LBL_C_INIT work is necessary before using AC_PROG_CC.
+dnl
+dnl It appears that newer versions of autoconf (2.64 and later) will,
+dnl if you use AC_TRY_COMPILE in a macro, stick AC_PROG_CC at the
+dnl beginning of the macro, even if the macro itself calls AC_PROG_CC.
+dnl See the "Prerequisite Macros" and "Expanded Before Required" sections
+dnl in the Autoconf documentation.
+dnl
+dnl This causes a steaming heap of fail in our case, as we were, in
+dnl AC_LBL_C_INIT, doing the tests we now do in AC_LBL_C_INIT_BEFORE_CC,
+dnl calling AC_PROG_CC, and then doing the tests we now do in
+dnl AC_LBL_C_INIT. Now, we run AC_LBL_C_INIT_BEFORE_CC, AC_PROG_CC,
+dnl and AC_LBL_C_INIT at the top level.
+dnl
+AC_DEFUN(AC_LBL_C_INIT_BEFORE_CC,
+[
+ AC_BEFORE([$0], [AC_LBL_C_INIT])
+ AC_BEFORE([$0], [AC_PROG_CC])
+ AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
+ AC_BEFORE([$0], [AC_LBL_DEVEL])
+ AC_ARG_WITH(gcc, [ --without-gcc don't use gcc])
+ $1=""
+ if test "${srcdir}" != "." ; then
+ $1="-I\$(srcdir)"
+ fi
+ if test "${CFLAGS+set}" = set; then
+ LBL_CFLAGS="$CFLAGS"
+ fi
+ if test -z "$CC" ; then
+ case "$host_os" in
+
+ bsdi*)
+ AC_CHECK_PROG(SHLICC2, shlicc2, yes, no)
+ if test $SHLICC2 = yes ; then
+ CC=shlicc2
+ export CC
+ fi
+ ;;
+ esac
+ fi
+ if test -z "$CC" -a "$with_gcc" = no ; then
+ CC=cc
+ export CC
+ fi
+])
+
+dnl
+dnl Determine which compiler we're using (cc or gcc)
+dnl If using gcc, determine the version number
+dnl If using cc:
+dnl require that it support ansi prototypes
+dnl use -O (AC_PROG_CC will use -g -O2 on gcc, so we don't need to
+dnl do that ourselves for gcc)
+dnl add -g flags, as appropriate
+dnl explicitly specify /usr/local/include
+dnl
+dnl NOTE WELL: with newer versions of autoconf, "gcc" means any compiler
+dnl that defines __GNUC__, which means clang, for example, counts as "gcc".
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_C_INIT(copt, incls)
+dnl
+dnl results:
+dnl
+dnl $1 (copt set)
+dnl $2 (incls set)
+dnl CC
+dnl LDFLAGS
+dnl LBL_CFLAGS
+dnl
+AC_DEFUN(AC_LBL_C_INIT,
+[
+ AC_BEFORE([$0], [AC_LBL_FIXINCLUDES])
+ AC_BEFORE([$0], [AC_LBL_DEVEL])
+ AC_BEFORE([$0], [AC_LBL_SHLIBS_INIT])
+ if test "$GCC" = yes ; then
+ #
+ # -Werror forces warnings to be errors.
+ #
+ ac_lbl_cc_force_warning_errors=-Werror
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+ AC_LBL_CHECK_COMPILER_OPT($1, -fvisibility=hidden)
+ else
+ $2="$$2 -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+ case "$host_os" in
+
+ darwin*)
+ #
+ # This is assumed either to be GCC or clang, both
+ # of which use -Werror to force warnings to be errors.
+ #
+ ac_lbl_cc_force_warning_errors=-Werror
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+ AC_LBL_CHECK_COMPILER_OPT($1, -fvisibility=hidden)
+ ;;
+
+ hpux*)
+ #
+ # HP C, which is what we presume we're using, doesn't
+ # exit with a non-zero exit status if we hand it an
+ # invalid -W flag, can't be forced to do so even with
+ # +We, and doesn't handle GCC-style -W flags, so we
+ # don't want to try using GCC-style -W flags.
+ #
+ ac_lbl_cc_dont_try_gcc_dashW=yes
+ ;;
+
+ irix*)
+ #
+ # MIPS C, which is what we presume we're using, doesn't
+ # necessarily exit with a non-zero exit status if we
+ # hand it an invalid -W flag, can't be forced to do
+ # so, and doesn't handle GCC-style -W flags, so we
+ # don't want to try using GCC-style -W flags.
+ #
+ ac_lbl_cc_dont_try_gcc_dashW=yes
+ #
+ # It also, apparently, defaults to "char" being
+ # unsigned, unlike most other C implementations;
+ # I suppose we could say "signed char" whenever
+ # we want to guarantee a signed "char", but let's
+ # just force signed chars.
+ #
+ # -xansi is normally the default, but the
+ # configure script was setting it; perhaps -cckr
+ # was the default in the Old Days. (Then again,
+ # that would probably be for backwards compatibility
+ # in the days when ANSI C was Shiny and New, i.e.
+ # 1989 and the early '90's, so maybe we can just
+ # drop support for those compilers.)
+ #
+ # -g is equivalent to -g2, which turns off
+ # optimization; we choose -g3, which generates
+ # debugging information but doesn't turn off
+ # optimization (even if the optimization would
+ # cause inaccuracies in debugging).
+ #
+ $1="$$1 -xansi -signed -g3"
+ ;;
+
+ osf*)
+ #
+ # Presumed to be DEC OSF/1, Digital UNIX, or
+ # Tru64 UNIX.
+ #
+ # The DEC C compiler, which is what we presume we're
+ # using, doesn't exit with a non-zero exit status if we
+ # hand it an invalid -W flag, can't be forced to do
+ # so, and doesn't handle GCC-style -W flags, so we
+ # don't want to try using GCC-style -W flags.
+ #
+ ac_lbl_cc_dont_try_gcc_dashW=yes
+ #
+ # -g is equivalent to -g2, which turns off
+ # optimization; we choose -g3, which generates
+ # debugging information but doesn't turn off
+ # optimization (even if the optimization would
+ # cause inaccuracies in debugging).
+ #
+ $1="$$1 -g3"
+ ;;
+
+ solaris*)
+ #
+ # Assumed to be Sun C, which requires -errwarn to force
+ # warnings to be treated as errors.
+ #
+ ac_lbl_cc_force_warning_errors=-errwarn
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+ AC_LBL_CHECK_COMPILER_OPT($1, -xldscope=hidden)
+ ;;
+
+ ultrix*)
+ AC_MSG_CHECKING(that Ultrix $CC hacks const in prototypes)
+ AC_CACHE_VAL(ac_cv_lbl_cc_const_proto,
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>],
+ [struct a { int b; };
+ void c(const struct a *)],
+ ac_cv_lbl_cc_const_proto=yes,
+ ac_cv_lbl_cc_const_proto=no))
+ AC_MSG_RESULT($ac_cv_lbl_cc_const_proto)
+ if test $ac_cv_lbl_cc_const_proto = no ; then
+ AC_DEFINE(const,[],
+ [to handle Ultrix compilers that don't support const in prototypes])
+ fi
+ ;;
+ esac
+ $1="$$1 -O"
+ fi
+])
+
+dnl
+dnl Check whether, if you pass an unknown warning option to the
+dnl compiler, it fails or just prints a warning message and succeeds.
+dnl Set ac_lbl_unknown_warning_option_error to the appropriate flag
+dnl to force an error if it would otherwise just print a warning message
+dnl and succeed.
+dnl
+AC_DEFUN(AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR,
+ [
+ AC_MSG_CHECKING([whether the compiler fails when given an unknown warning option])
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wxyzzy-this-will-never-succeed-xyzzy"
+ AC_TRY_COMPILE(
+ [],
+ [return 0],
+ [
+ AC_MSG_RESULT([no])
+ #
+ # We're assuming this is clang, where
+ # -Werror=unknown-warning-option is the appropriate
+ # option to force the compiler to fail.
+ #
+ ac_lbl_unknown_warning_option_error="-Werror=unknown-warning-option"
+ ],
+ [
+ AC_MSG_RESULT([yes])
+ ])
+ CFLAGS="$save_CFLAGS"
+ ])
+
+dnl
+dnl Check whether the compiler option specified as the second argument
+dnl is supported by the compiler and, if so, add it to the macro
+dnl specified as the first argument
+dnl
+dnl If a third argument is supplied, treat it as C code to be compiled
+dnl with the flag in question, and the "treat warnings as errors" flag
+dnl set, and don't add the flag to the first argument if the compile
+dnl fails; this is for warning options cause problems that can't be
+dnl worked around. If a third argument is supplied, a fourth argument
+dnl should also be supplied; it's a message desribing what the test
+dnl program is checking.
+dnl
+AC_DEFUN(AC_LBL_CHECK_COMPILER_OPT,
+ [
+ AC_MSG_CHECKING([whether the compiler supports the $2 option])
+ save_CFLAGS="$CFLAGS"
+ if expr "x$2" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error $2"
+ elif expr "x$2" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror $2"
+ elif expr "x$2" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror $2"
+ else
+ CFLAGS="$CFLAGS $2"
+ fi
+ AC_TRY_COMPILE(
+ [],
+ [return 0],
+ [
+ AC_MSG_RESULT([yes])
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x$4" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ AC_MSG_CHECKING(whether $2 $4)
+ AC_COMPILE_IFELSE(
+ [AC_LANG_SOURCE($3)],
+ [
+ #
+ # Not a problem.
+ #
+ AC_MSG_RESULT(no)
+ ],
+ [
+ #
+ # A problem.
+ #
+ AC_MSG_RESULT(yes)
+ can_add_to_cflags=no
+ ])
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ $1="$$1 $2"
+ fi
+ ],
+ [
+ AC_MSG_RESULT([no])
+ CFLAGS="$save_CFLAGS"
+ ])
+ ])
+
+dnl
+dnl Check whether the compiler supports an option to generate
+dnl Makefile-style dependency lines
+dnl
+dnl GCC uses -M for this. Non-GCC compilers that support this
+dnl use a variety of flags, including but not limited to -M.
+dnl
+dnl We test whether the flag in question is supported, as older
+dnl versions of compilers might not support it.
+dnl
+dnl We don't try all the possible flags, just in case some flag means
+dnl "generate dependencies" on one compiler but means something else
+dnl on another compiler.
+dnl
+dnl Most compilers that support this send the output to the standard
+dnl output by default. IBM's XLC, however, supports -M but sends
+dnl the output to {sourcefile-basename}.u, and AIX has no /dev/stdout
+dnl to work around that, so we don't bother with XLC.
+dnl
+AC_DEFUN(AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT,
+ [
+ AC_MSG_CHECKING([whether the compiler supports generating dependencies])
+ if test "$GCC" = yes ; then
+ #
+ # GCC, or a compiler deemed to be GCC by AC_PROG_CC (even
+ # though it's not); we assume that, in this case, the flag
+ # would be -M.
+ #
+ ac_lbl_dependency_flag="-M"
+ else
+ #
+ # Not GCC or a compiler deemed to be GCC; what platform is
+ # this? (We're assuming that if the compiler isn't GCC
+ # it's the compiler from the vendor of the OS; that won't
+ # necessarily be true for x86 platforms, where it might be
+ # the Intel C compiler.)
+ #
+ case "$host_os" in
+
+ irix*|osf*|darwin*)
+ #
+ # MIPS C for IRIX, DEC C, and clang all use -M.
+ #
+ ac_lbl_dependency_flag="-M"
+ ;;
+
+ solaris*)
+ #
+ # Sun C uses -xM.
+ #
+ ac_lbl_dependency_flag="-xM"
+ ;;
+
+ hpux*)
+ #
+ # HP's older C compilers don't support this.
+ # HP's newer C compilers support this with
+ # either +M or +Make; the older compilers
+ # interpret +M as something completely
+ # different, so we use +Make so we don't
+ # think it works with the older compilers.
+ #
+ ac_lbl_dependency_flag="+Make"
+ ;;
+
+ *)
+ #
+ # Not one of the above; assume no support for
+ # generating dependencies.
+ #
+ ac_lbl_dependency_flag=""
+ ;;
+ esac
+ fi
+
+ #
+ # Is ac_lbl_dependency_flag defined and, if so, does the compiler
+ # complain about it?
+ #
+ # Note: clang doesn't seem to exit with an error status when handed
+ # an unknown non-warning error, even if you pass it
+ # -Werror=unknown-warning-option. However, it always supports
+ # -M, so the fact that this test always succeeds with clang
+ # isn't an issue.
+ #
+ if test ! -z "$ac_lbl_dependency_flag"; then
+ AC_LANG_CONFTEST(
+ [AC_LANG_SOURCE([[int main(void) { return 0; }]])])
+ if AC_RUN_LOG([eval "$CC $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1"]); then
+ AC_MSG_RESULT([yes, with $ac_lbl_dependency_flag])
+ DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
+ MKDEP='${srcdir}/mkdep'
+ else
+ AC_MSG_RESULT([no])
+ #
+ # We can't run mkdep, so have "make depend" do
+ # nothing.
+ #
+ MKDEP='${srcdir}/nomkdep'
+ fi
+ rm -rf conftest*
+ else
+ AC_MSG_RESULT([no])
+ #
+ # We can't run mkdep, so have "make depend" do
+ # nothing.
+ #
+ MKDEP='${srcdir}/nomkdep'
+ fi
+ AC_SUBST(DEPENDENCY_CFLAG)
+ AC_SUBST(MKDEP)
+ ])
+
+dnl
+dnl Determine what options are needed to build a shared library
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_SHLIBS_INIT
+dnl
+dnl results:
+dnl
+dnl V_SHLIB_CCOPT (modified to build position-independent code)
+dnl V_SHLIB_CMD
+dnl V_SHLIB_OPT
+dnl V_SONAME_OPT
+dnl V_RPATH_OPT
+dnl
+AC_DEFUN(AC_LBL_SHLIBS_INIT,
+ [AC_PREREQ(2.50)
+ if test "$GCC" = yes ; then
+ #
+ # On platforms where we build a shared library:
+ #
+ # add options to generate position-independent code,
+ # if necessary (it's the default in AIX and Darwin/macOS);
+ #
+ # define option to set the soname of the shared library,
+ # if the OS supports that;
+ #
+ # add options to specify, at link time, a directory to
+ # add to the run-time search path, if that's necessary.
+ #
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-shared"
+ case "$host_os" in
+
+ aix*)
+ ;;
+
+ freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*|midipix*)
+ #
+ # Platforms where the linker is the GNU linker
+ # or accepts command-line arguments like
+ # those the GNU linker accepts.
+ #
+ # Some instruction sets require -fPIC on some
+ # operating systems. Check for them. If you
+ # have a combination that requires it, add it
+ # here.
+ #
+ PIC_OPT=-fpic
+ case "$host_cpu" in
+
+ sparc64*)
+ case "$host_os" in
+
+ freebsd*|openbsd*|linux*)
+ PIC_OPT=-fPIC
+ ;;
+ esac
+ ;;
+ esac
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT $PIC_OPT"
+ V_SONAME_OPT="-Wl,-soname,"
+ V_RPATH_OPT="-Wl,-rpath,"
+ ;;
+
+ hpux*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
+ #
+ # XXX - this assumes GCC is using the HP linker,
+ # rather than the GNU linker, and that the "+h"
+ # option is used on all HP-UX platforms, both .sl
+ # and .so.
+ #
+ V_SONAME_OPT="-Wl,+h,"
+ #
+ # By default, directories specifed with -L
+ # are added to the run-time search path, so
+ # we don't add them in pcap-config.
+ #
+ ;;
+
+ solaris*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
+ #
+ # XXX - this assumes GCC is using the Sun linker,
+ # rather than the GNU linker.
+ #
+ V_SONAME_OPT="-Wl,-h,"
+ V_RPATH_OPT="-Wl,-R,"
+ ;;
+ esac
+ else
+ #
+ # Set the appropriate compiler flags and, on platforms
+ # where we build a shared library:
+ #
+ # add options to generate position-independent code,
+ # if necessary (it's the default in Darwin/macOS);
+ #
+ # if we generate ".so" shared libraries, define the
+ # appropriate options for building the shared library;
+ #
+ # add options to specify, at link time, a directory to
+ # add to the run-time search path, if that's necessary.
+ #
+ # Note: spaces after V_SONAME_OPT are significant; on
+ # some platforms the soname is passed with a GCC-like
+ # "-Wl,-soname,{soname}" option, with the soname part
+ # of the option, while on other platforms the C compiler
+ # driver takes it as a regular option with the soname
+ # following the option. The same applies to V_RPATH_OPT.
+ #
+ case "$host_os" in
+
+ aix*)
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-G -bnoentry -bexpall"
+ ;;
+
+ freebsd*|netbsd*|openbsd*|dragonfly*|linux*)
+ #
+ # "cc" is GCC.
+ #
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-shared"
+ V_SONAME_OPT="-Wl,-soname,"
+ V_RPATH_OPT="-Wl,-rpath,"
+ ;;
+
+ hpux*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT +z"
+ V_SHLIB_CMD="\$(LD)"
+ V_SHLIB_OPT="-b"
+ V_SONAME_OPT="+h "
+ #
+ # By default, directories specifed with -L
+ # are added to the run-time search path, so
+ # we don't add them in pcap-config.
+ #
+ ;;
+
+ osf*)
+ #
+ # Presumed to be DEC OSF/1, Digital UNIX, or
+ # Tru64 UNIX.
+ #
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-shared"
+ V_SONAME_OPT="-soname "
+ V_RPATH_OPT="-rpath "
+ ;;
+
+ solaris*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -Kpic"
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-G"
+ V_SONAME_OPT="-h "
+ V_RPATH_OPT="-R"
+ ;;
+ esac
+ fi
+])
+
+#
+# Try compiling a sample of the type of code that appears in
+# gencode.c with "inline", "__inline__", and "__inline".
+#
+# Autoconf's AC_C_INLINE, at least in autoconf 2.13, isn't good enough,
+# as it just tests whether a function returning "int" can be inlined;
+# at least some versions of HP's C compiler can inline that, but can't
+# inline a function that returns a struct pointer.
+#
+# Make sure we use the V_CCOPT flags, because some of those might
+# disable inlining.
+#
+AC_DEFUN(AC_LBL_C_INLINE,
+ [AC_MSG_CHECKING(for inline)
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$V_CCOPT"
+ AC_CACHE_VAL(ac_cv_lbl_inline, [
+ ac_cv_lbl_inline=""
+ ac_lbl_cc_inline=no
+ for ac_lbl_inline in inline __inline__ __inline
+ do
+ AC_TRY_COMPILE(
+ [#define inline $ac_lbl_inline
+ static inline struct iltest *foo(void);
+ struct iltest {
+ int iltest1;
+ int iltest2;
+ };
+
+ static inline struct iltest *
+ foo()
+ {
+ static struct iltest xxx;
+
+ return &xxx;
+ }],,ac_lbl_cc_inline=yes,)
+ if test "$ac_lbl_cc_inline" = yes ; then
+ break;
+ fi
+ done
+ if test "$ac_lbl_cc_inline" = yes ; then
+ ac_cv_lbl_inline=$ac_lbl_inline
+ fi])
+ CFLAGS="$save_CFLAGS"
+ if test ! -z "$ac_cv_lbl_inline" ; then
+ AC_MSG_RESULT($ac_cv_lbl_inline)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ AC_DEFINE_UNQUOTED(inline, $ac_cv_lbl_inline, [Define as token for inline if inlining supported])])
+
+dnl
+dnl If using gcc, make sure we have ANSI ioctl definitions
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_FIXINCLUDES
+dnl
+AC_DEFUN(AC_LBL_FIXINCLUDES,
+ [if test "$GCC" = yes ; then
+ AC_MSG_CHECKING(for ANSI ioctl definitions)
+ AC_CACHE_VAL(ac_cv_lbl_gcc_fixincludes,
+ AC_TRY_COMPILE(
+ [/*
+ * This generates a "duplicate case value" when fixincludes
+ * has not be run.
+ */
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/ioctl.h>
+# ifdef HAVE_SYS_IOCCOM_H
+# include <sys/ioccom.h>
+# endif],
+ [switch (0) {
+ case _IO('A', 1):;
+ case _IO('B', 1):;
+ }],
+ ac_cv_lbl_gcc_fixincludes=yes,
+ ac_cv_lbl_gcc_fixincludes=no))
+ AC_MSG_RESULT($ac_cv_lbl_gcc_fixincludes)
+ if test $ac_cv_lbl_gcc_fixincludes = no ; then
+ # Don't cache failure
+ unset ac_cv_lbl_gcc_fixincludes
+ AC_MSG_ERROR(see the INSTALL for more info)
+ fi
+ fi])
+
+dnl
+dnl Checks to see if union wait is used with WEXITSTATUS()
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_UNION_WAIT
+dnl
+dnl results:
+dnl
+dnl DECLWAITSTATUS (defined)
+dnl
+AC_DEFUN(AC_LBL_UNION_WAIT,
+ [AC_MSG_CHECKING(if union wait is used)
+ AC_CACHE_VAL(ac_cv_lbl_union_wait,
+ AC_TRY_COMPILE([
+# include <sys/types.h>
+# include <sys/wait.h>],
+ [int status;
+ u_int i = WEXITSTATUS(status);
+ u_int j = waitpid(0, &status, 0);],
+ ac_cv_lbl_union_wait=no,
+ ac_cv_lbl_union_wait=yes))
+ AC_MSG_RESULT($ac_cv_lbl_union_wait)
+ if test $ac_cv_lbl_union_wait = yes ; then
+ AC_DEFINE(DECLWAITSTATUS,union wait,[type for wait])
+ else
+ AC_DEFINE(DECLWAITSTATUS,int,[type for wait])
+ fi])
+
+dnl
+dnl Checks to see if -R is used
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_HAVE_RUN_PATH
+dnl
+dnl results:
+dnl
+dnl ac_cv_lbl_have_run_path (yes or no)
+dnl
+AC_DEFUN(AC_LBL_HAVE_RUN_PATH,
+ [AC_MSG_CHECKING(for ${CC-cc} -R)
+ AC_CACHE_VAL(ac_cv_lbl_have_run_path,
+ [echo 'main(){}' > conftest.c
+ ${CC-cc} -o conftest conftest.c -R/a1/b2/c3 >conftest.out 2>&1
+ if test ! -s conftest.out ; then
+ ac_cv_lbl_have_run_path=yes
+ else
+ ac_cv_lbl_have_run_path=no
+ fi
+ rm -f -r conftest*])
+ AC_MSG_RESULT($ac_cv_lbl_have_run_path)
+ ])
+
+dnl
+dnl Checks to see if unaligned memory accesses fail
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_UNALIGNED_ACCESS
+dnl
+dnl results:
+dnl
+dnl LBL_ALIGN (DEFINED)
+dnl
+AC_DEFUN(AC_LBL_UNALIGNED_ACCESS,
+ [AC_MSG_CHECKING(if unaligned accesses fail)
+ AC_CACHE_VAL(ac_cv_lbl_unaligned_fail,
+ [case "$host_cpu" in
+
+ #
+ # These are CPU types where:
+ #
+ # the CPU faults on an unaligned access, but at least some
+ # OSes that support that CPU catch the fault and simulate
+ # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) -
+ # the simulation is slow, so we don't want to use it;
+ #
+ # the CPU, I infer (from the old
+ #
+ # XXX: should also check that they don't do weird things (like on arm)
+ #
+ # comment) doesn't fault on unaligned accesses, but doesn't
+ # do a normal unaligned fetch, either (e.g., presumably, ARM);
+ #
+ # for whatever reason, the test program doesn't work
+ # (this has been claimed to be the case for several of those
+ # CPUs - I don't know what the problem is; the problem
+ # was reported as "the test program dumps core" for SuperH,
+ # but that's what the test program is *supposed* to do -
+ # it dumps core before it writes anything, so the test
+ # for an empty output file should find an empty output
+ # file and conclude that unaligned accesses don't work).
+ #
+ # This run-time test won't work if you're cross-compiling, so
+ # in order to support cross-compiling for a particular CPU,
+ # we have to wire in the list of CPU types anyway, as far as
+ # I know, so perhaps we should just have a set of CPUs on
+ # which we know it doesn't work, a set of CPUs on which we
+ # know it does work, and have the script just fail on other
+ # cpu types and update it when such a failure occurs.
+ #
+ alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
+ ac_cv_lbl_unaligned_fail=yes
+ ;;
+
+ *)
+ cat >conftest.c <<EOF
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <stdio.h>
+ unsigned char a[[5]] = { 1, 2, 3, 4, 5 };
+ main() {
+ unsigned int i;
+ pid_t pid;
+ int status;
+ /* avoid "core dumped" message */
+ pid = fork();
+ if (pid < 0)
+ exit(2);
+ if (pid > 0) {
+ /* parent */
+ pid = waitpid(pid, &status, 0);
+ if (pid < 0)
+ exit(3);
+ exit(!WIFEXITED(status));
+ }
+ /* child */
+ i = *(unsigned int *)&a[[1]];
+ printf("%d\n", i);
+ exit(0);
+ }
+EOF
+ ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
+ conftest.c $LIBS >/dev/null 2>&1
+ if test ! -x conftest ; then
+ dnl failed to compile for some reason
+ ac_cv_lbl_unaligned_fail=yes
+ else
+ ./conftest >conftest.out
+ if test ! -s conftest.out ; then
+ ac_cv_lbl_unaligned_fail=yes
+ else
+ ac_cv_lbl_unaligned_fail=no
+ fi
+ fi
+ rm -f -r conftest* core core.conftest
+ ;;
+ esac])
+ AC_MSG_RESULT($ac_cv_lbl_unaligned_fail)
+ if test $ac_cv_lbl_unaligned_fail = yes ; then
+ AC_DEFINE(LBL_ALIGN,1,[if unaligned access fails])
+ fi])
+
+dnl
+dnl If the file .devel exists:
+dnl Add some warning flags if the compiler supports them
+dnl If an os prototype include exists, symlink os-proto.h to it
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_DEVEL(copt)
+dnl
+dnl results:
+dnl
+dnl $1 (copt appended)
+dnl HAVE_OS_PROTO_H (defined)
+dnl os-proto.h (symlinked)
+dnl
+AC_DEFUN(AC_LBL_DEVEL,
+ [rm -f os-proto.h
+ if test "${LBL_CFLAGS+set}" = set; then
+ $1="$$1 ${LBL_CFLAGS}"
+ fi
+ if test -f .devel ; then
+ #
+ # Skip all the warning option stuff on some compilers.
+ #
+ if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
+ AC_LBL_CHECK_UNKNOWN_WARNING_OPTION_ERROR()
+ AC_LBL_CHECK_COMPILER_OPT($1, -W)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wall)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wcomma)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wdeclaration-after-statement)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wdocumentation)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wformat-nonliteral)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-noreturn)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-prototypes)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wmissing-variable-declarations)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wshadow)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wsign-compare)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wstrict-prototypes)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wunused-parameter)
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wused-but-marked-unused)
+ # Warns about safeguards added in case the enums are
+ # extended
+ # AC_LBL_CHECK_COMPILER_OPT($1, -Wcovered-switch-default)
+ #
+ # This can cause problems with ntohs(), ntohl(),
+ # htons(), and htonl() on some platforms, such
+ # as OpenBSD 6.3 with Clang 5.0.1. I guess the
+ # problem is that the macro that ultimately does
+ # the byte-swapping involves a conditional
+ # expression that tests whether the value being
+ # swapped is a compile-time constant or not,
+ # using __builtin_constant_p(), and, depending
+ # on whether it is, does a compile-time swap or
+ # a run-time swap; perhaps the compiler always
+ # considers one of the two results of the
+ # conditional expressin is never evaluated,
+ # because the conditional check is done at
+ # compile time, and thus always says "that
+ # expression is never executed".
+ #
+ # (Perhaps there should be a way of flagging
+ # an expression that you *want* evaluated at
+ # compile time, so that the compiler 1) warns
+ # if it *can't* be evaluated at compile time
+ # and 2) *doesn't* warn that the true or false
+ # branch will never be reached.)
+ #
+ AC_LBL_CHECK_COMPILER_OPT($1, -Wunreachable-code,
+ [
+#include <arpa/inet.h>
+
+unsigned short
+testme(unsigned short a)
+{
+ return ntohs(a);
+}
+ ],
+ [generates warnings from ntohs()])
+ fi
+ AC_LBL_CHECK_DEPENDENCY_GENERATION_OPT()
+ #
+ # We used to set -n32 for IRIX 6 when not using GCC (presumed
+ # to mean that we're using MIPS C or MIPSpro C); it specified
+ # the "new" faster 32-bit ABI, introduced in IRIX 6.2. I'm
+ # not sure why that would be something to do *only* with a
+ # .devel file; why should the ABI for which we produce code
+ # depend on .devel?
+ #
+ os=`echo $host_os | sed -e 's/\([[0-9]][[0-9]]*\)[[^0-9]].*$/\1/'`
+ name="lbl/os-$os.h"
+ if test -f $name ; then
+ ln -s $name os-proto.h
+ AC_DEFINE(HAVE_OS_PROTO_H, 1,
+ [if there's an os_proto.h for this platform, to use additional prototypes])
+ else
+ AC_MSG_WARN(can't find $name)
+ fi
+ fi])
+
+dnl
+dnl Improved version of AC_CHECK_LIB
+dnl
+dnl Thanks to John Hawkinson (jhawk@mit.edu)
+dnl
+dnl usage:
+dnl
+dnl AC_LBL_CHECK_LIB(LIBRARY, FUNCTION [, ACTION-IF-FOUND [,
+dnl ACTION-IF-NOT-FOUND [, OTHER-LIBRARIES]]])
+dnl
+dnl results:
+dnl
+dnl LIBS
+dnl
+dnl XXX - "AC_LBL_LIBRARY_NET" was redone to use "AC_SEARCH_LIBS"
+dnl rather than "AC_LBL_CHECK_LIB", so this isn't used any more.
+dnl We keep it around for reference purposes in case it's ever
+dnl useful in the future.
+dnl
+
+define(AC_LBL_CHECK_LIB,
+[AC_MSG_CHECKING([for $2 in -l$1])
+dnl Use a cache variable name containing the library, function
+dnl name, and extra libraries to link with, because the test really is
+dnl for library $1 defining function $2, when linked with potinal
+dnl library $5, not just for library $1. Separate tests with the same
+dnl $1 and different $2's or $5's may have different results.
+ac_lib_var=`echo $1['_']$2['_']$5 | sed 'y%./+- %__p__%'`
+AC_CACHE_VAL(ac_cv_lbl_lib_$ac_lib_var,
+[ac_save_LIBS="$LIBS"
+LIBS="-l$1 $5 $LIBS"
+AC_TRY_LINK(dnl
+ifelse([$2], [main], , dnl Avoid conflicting decl of main.
+[/* Override any gcc2 internal prototype to avoid an error. */
+]ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
+extern "C"
+#endif
+])dnl
+[/* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+char $2();
+]),
+ [$2()],
+ eval "ac_cv_lbl_lib_$ac_lib_var=yes",
+ eval "ac_cv_lbl_lib_$ac_lib_var=no")
+LIBS="$ac_save_LIBS"
+])dnl
+if eval "test \"`echo '$ac_cv_lbl_lib_'$ac_lib_var`\" = yes"; then
+ AC_MSG_RESULT(yes)
+ ifelse([$3], ,
+[changequote(, )dnl
+ ac_tr_lib=HAVE_LIB`echo $1 | sed -e 's/[^a-zA-Z0-9_]/_/g' \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/'`
+changequote([, ])dnl
+ AC_DEFINE_UNQUOTED($ac_tr_lib)
+ LIBS="-l$1 $LIBS"
+], [$3])
+else
+ AC_MSG_RESULT(no)
+ifelse([$4], , , [$4
+])dnl
+fi
+])
+
+dnl
+dnl AC_LBL_LIBRARY_NET
+dnl
+dnl This test is for network applications that need socket functions and
+dnl getaddrinfo()/getnameinfo()-ish functions. We now require
+dnl getaddrinfo() and getnameinfo(). We also prefer versions of
+dnl recvmsg() that conform to the Single UNIX Specification, so that we
+dnl can check whether a datagram received with recvmsg() was truncated
+dnl when received due to the buffer being too small.
+dnl
+dnl On most operating systems, they're available in the system library.
+dnl
+dnl Under Solaris, we need to link with libsocket and libnsl to get
+dnl getaddrinfo() and getnameinfo() and, if we have libxnet, we need to
+dnl link with libxnet before libsocket to get a version of recvmsg()
+dnl that conforms to the Single UNIX Specification.
+dnl
+dnl We use getaddrinfo() because we want a portable thread-safe way
+dnl of getting information for a host name or port; there exist _r
+dnl versions of gethostbyname() and getservbyname() on some platforms,
+dnl but not on all platforms.
+dnl
+AC_DEFUN(AC_LBL_LIBRARY_NET, [
+ #
+ # Most operating systems have getaddrinfo() in the default searched
+ # libraries (i.e. libc). Check there first.
+ #
+ AC_CHECK_FUNC(getaddrinfo,,
+ [
+ #
+ # Not found in the standard system libraries.
+ # Try libsocket, which requires libnsl.
+ #
+ AC_CHECK_LIB(socket, getaddrinfo,
+ [
+ #
+ # OK, we found it in libsocket.
+ #
+ LIBS="-lsocket -lnsl $LIBS"
+ ],
+ [
+ #
+ # We didn't find it.
+ #
+ AC_MSG_ERROR([getaddrinfo is required, but wasn't found])
+ ], -lnsl)
+
+ #
+ # OK, do we have recvmsg() in libxnet?
+ # We also link with libsocket and libnsl.
+ #
+ AC_CHECK_LIB(xnet, recvmsg,
+ [
+ #
+ # Yes - link with it as well.
+ #
+ LIBS="-lxnet $LIBS"
+ ], , -lsocket -lnsl)
+ ])
+ # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+ AC_SEARCH_LIBS(putmsg, str)
+ ])
diff --git a/lib/libpcap/libpcap/arcnet.h b/lib/libpcap/libpcap/arcnet.h
new file mode 100644
index 0000000..5869098
--- /dev/null
+++ b/lib/libpcap/libpcap/arcnet.h
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ * 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: NetBSD: if_arc.h,v 1.13 1999/11/19 20:41:19 thorpej Exp
+ */
+
+/* RFC 1051 */
+#define ARCTYPE_IP_OLD 240 /* IP protocol */
+#define ARCTYPE_ARP_OLD 241 /* address resolution protocol */
+
+/* RFC 1201 */
+#define ARCTYPE_IP 212 /* IP protocol */
+#define ARCTYPE_ARP 213 /* address resolution protocol */
+#define ARCTYPE_REVARP 214 /* reverse addr resolution protocol */
+
+#define ARCTYPE_ATALK 221 /* Appletalk */
+#define ARCTYPE_BANIAN 247 /* Banyan Vines */
+#define ARCTYPE_IPX 250 /* Novell IPX */
+
+#define ARCTYPE_INET6 0xc4 /* IPng */
+#define ARCTYPE_DIAGNOSE 0x80 /* as per ANSI/ATA 878.1 */
diff --git a/lib/libpcap/libpcap/atmuni31.h b/lib/libpcap/libpcap/atmuni31.h
new file mode 100644
index 0000000..0f85430
--- /dev/null
+++ b/lib/libpcap/libpcap/atmuni31.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 1997 Yen Yen Lim and North Dakota State University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Yen Yen Lim and
+ North Dakota State University
+ * 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.
+ */
+
+/* Based on UNI3.1 standard by ATM Forum */
+
+/* ATM traffic types based on VPI=0 and (the following VCI */
+#define VCI_PPC 0x05 /* Point-to-point signal msg */
+#define VCI_BCC 0x02 /* Broadcast signal msg */
+#define VCI_OAMF4SC 0x03 /* Segment OAM F4 flow cell */
+#define VCI_OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */
+#define VCI_METAC 0x01 /* Meta signal msg */
+#define VCI_ILMIC 0x10 /* ILMI msg */
+
+/* Q.2931 signalling messages */
+#define CALL_PROCEED 0x02 /* call proceeding */
+#define CONNECT 0x07 /* connect */
+#define CONNECT_ACK 0x0f /* connect_ack */
+#define SETUP 0x05 /* setup */
+#define RELEASE 0x4d /* release */
+#define RELEASE_DONE 0x5a /* release_done */
+#define RESTART 0x46 /* restart */
+#define RESTART_ACK 0x4e /* restart ack */
+#define STATUS 0x7d /* status */
+#define STATUS_ENQ 0x75 /* status ack */
+#define ADD_PARTY 0x80 /* add party */
+#define ADD_PARTY_ACK 0x81 /* add party ack */
+#define ADD_PARTY_REJ 0x82 /* add party rej */
+#define DROP_PARTY 0x83 /* drop party */
+#define DROP_PARTY_ACK 0x84 /* drop party ack */
+
+/* Information Element Parameters in the signalling messages */
+#define CAUSE 0x08 /* cause */
+#define ENDPT_REF 0x54 /* endpoint reference */
+#define AAL_PARA 0x58 /* ATM adaptation layer parameters */
+#define TRAFF_DESCRIP 0x59 /* atm traffic descriptors */
+#define CONNECT_ID 0x5a /* connection identifier */
+#define QOS_PARA 0x5c /* quality of service parameters */
+#define B_HIGHER 0x5d /* broadband higher layer information */
+#define B_BEARER 0x5e /* broadband bearer capability */
+#define B_LOWER 0x5f /* broadband lower information */
+#define CALLING_PARTY 0x6c /* calling party number */
+#define CALLED_PARTY 0x70 /* called party nmber */
+
+#define Q2931 0x09
+
+/* Q.2931 signalling general messages format */
+#define PROTO_POS 0 /* offset of protocol discriminator */
+#define CALL_REF_POS 2 /* offset of call reference value */
+#define MSG_TYPE_POS 5 /* offset of message type */
+#define MSG_LEN_POS 7 /* offset of mesage length */
+#define IE_BEGIN_POS 9 /* offset of first information element */
+
+/* format of signalling messages */
+#define TYPE_POS 0
+#define LEN_POS 2
+#define FIELD_BEGIN_POS 4
diff --git a/lib/libpcap/libpcap/bpf_dump.c b/lib/libpcap/libpcap/bpf_dump.c
new file mode 100644
index 0000000..a9c9116
--- /dev/null
+++ b/lib/libpcap/libpcap/bpf_dump.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+
+#include "optimize.h"
+
+void
+bpf_dump(const struct bpf_program *p, int option)
+{
+ const struct bpf_insn *insn;
+ int i;
+ int n = p->bf_len;
+
+ insn = p->bf_insns;
+ if (option > 2) {
+ printf("%d\n", n);
+ for (i = 0; i < n; ++insn, ++i) {
+ printf("%u %u %u %u\n", insn->code,
+ insn->jt, insn->jf, insn->k);
+ }
+ return ;
+ }
+ if (option > 1) {
+ for (i = 0; i < n; ++insn, ++i)
+ printf("{ 0x%x, %d, %d, 0x%08x },\n",
+ insn->code, insn->jt, insn->jf, insn->k);
+ return;
+ }
+ for (i = 0; i < n; ++insn, ++i) {
+#ifdef BDEBUG
+ if (i < NBIDS && bids[i] > 0)
+ printf("[%02d]", bids[i] - 1);
+ else
+ printf(" -- ");
+#endif
+ puts(bpf_image(insn, i));
+ }
+}
diff --git a/lib/libpcap/libpcap/bpf_filter.c b/lib/libpcap/libpcap/bpf_filter.c
new file mode 100644
index 0000000..33872ff
--- /dev/null
+++ b/lib/libpcap/libpcap/bpf_filter.c
@@ -0,0 +1,548 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.c 7.5 (Berkeley) 7/15/91
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap/pcap-inttypes.h>
+#include "pcap-types.h"
+
+#ifndef _WIN32
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#endif /* _WIN32 */
+
+#include <pcap-int.h>
+
+#include <stdlib.h>
+
+#define int32 bpf_int32
+#define u_int32 bpf_u_int32
+
+#ifndef LBL_ALIGN
+/*
+ * XXX - IA-64? If not, this probably won't work on Win64 IA-64
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ * XXX - SuperH? If not, this probably won't work on WinCE SuperH
+ * systems, unless LBL_ALIGN is defined elsewhere for them.
+ */
+#if defined(sparc) || defined(__sparc__) || defined(mips) || \
+ defined(ibm032) || defined(__alpha) || defined(__hpux) || \
+ defined(__arm__)
+#define LBL_ALIGN
+#endif
+#endif
+
+#ifndef LBL_ALIGN
+#ifndef _WIN32
+#include <netinet/in.h>
+#endif
+
+#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p))
+#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p))
+#else
+#define EXTRACT_SHORT(p)\
+ ((u_short)\
+ ((u_short)*((u_char *)p+0)<<8|\
+ (u_short)*((u_char *)p+1)<<0))
+#define EXTRACT_LONG(p)\
+ ((u_int32)*((u_char *)p+0)<<24|\
+ (u_int32)*((u_char *)p+1)<<16|\
+ (u_int32)*((u_char *)p+2)<<8|\
+ (u_int32)*((u_char *)p+3)<<0)
+#endif
+
+#ifdef __linux__
+#include <linux/types.h>
+#include <linux/if_packet.h>
+#include <linux/filter.h>
+#endif
+
+enum {
+ BPF_S_ANC_NONE,
+ BPF_S_ANC_VLAN_TAG,
+ BPF_S_ANC_VLAN_TAG_PRESENT,
+};
+
+/*
+ * Execute the filter program starting at pc on the packet p
+ * wirelen is the length of the original packet
+ * buflen is the amount of data present
+ * aux_data is auxiliary data, currently used only when interpreting
+ * filters intended for the Linux kernel in cases where the kernel
+ * rejects the filter; it contains VLAN tag information
+ * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0,
+ * in all other cases, p is a pointer to a buffer and buflen is its size.
+ *
+ * Thanks to Ani Sinha <ani@arista.com> for providing initial implementation
+ */
+u_int
+bpf_filter_with_aux_data(const struct bpf_insn *pc, const u_char *p,
+ u_int wirelen, u_int buflen, const struct bpf_aux_data *aux_data)
+{
+ register u_int32 A, X;
+ register bpf_u_int32 k;
+ u_int32 mem[BPF_MEMWORDS];
+
+ if (pc == 0)
+ /*
+ * No filter means accept all.
+ */
+ return (u_int)-1;
+ A = 0;
+ X = 0;
+ --pc;
+ for (;;) {
+ ++pc;
+ switch (pc->code) {
+
+ default:
+ abort();
+ case BPF_RET|BPF_K:
+ return (u_int)pc->k;
+
+ case BPF_RET|BPF_A:
+ return (u_int)A;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ k = pc->k;
+ if (k > buflen || sizeof(int32_t) > buflen - k) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ k = pc->k;
+ if (k > buflen || sizeof(int16_t) > buflen - k) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ switch (pc->k) {
+
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
+ case SKF_AD_OFF + SKF_AD_VLAN_TAG:
+ if (!aux_data)
+ return 0;
+ A = aux_data->vlan_tag;
+ break;
+
+ case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT:
+ if (!aux_data)
+ return 0;
+ A = aux_data->vlan_tag_present;
+ break;
+#endif
+ default:
+ k = pc->k;
+ if (k >= buflen) {
+ return 0;
+ }
+ A = p[k];
+ break;
+ }
+ continue;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ A = wirelen;
+ continue;
+
+ case BPF_LDX|BPF_W|BPF_LEN:
+ X = wirelen;
+ continue;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ k = X + pc->k;
+ if (pc->k > buflen || X > buflen - pc->k ||
+ sizeof(int32_t) > buflen - k) {
+ return 0;
+ }
+ A = EXTRACT_LONG(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ k = X + pc->k;
+ if (X > buflen || pc->k > buflen - X ||
+ sizeof(int16_t) > buflen - k) {
+ return 0;
+ }
+ A = EXTRACT_SHORT(&p[k]);
+ continue;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ k = X + pc->k;
+ if (pc->k >= buflen || X >= buflen - pc->k) {
+ return 0;
+ }
+ A = p[k];
+ continue;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ k = pc->k;
+ if (k >= buflen) {
+ return 0;
+ }
+ X = (p[pc->k] & 0xf) << 2;
+ continue;
+
+ case BPF_LD|BPF_IMM:
+ A = pc->k;
+ continue;
+
+ case BPF_LDX|BPF_IMM:
+ X = pc->k;
+ continue;
+
+ case BPF_LD|BPF_MEM:
+ A = mem[pc->k];
+ continue;
+
+ case BPF_LDX|BPF_MEM:
+ X = mem[pc->k];
+ continue;
+
+ case BPF_ST:
+ mem[pc->k] = A;
+ continue;
+
+ case BPF_STX:
+ mem[pc->k] = X;
+ continue;
+
+ case BPF_JMP|BPF_JA:
+ /*
+ * XXX - we currently implement "ip6 protochain"
+ * with backward jumps, so sign-extend pc->k.
+ */
+ pc += (bpf_int32)pc->k;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ pc += (A > pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ pc += (A >= pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ pc += (A == pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ pc += (A & pc->k) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ pc += (A > X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ pc += (A >= X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ pc += (A == X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ pc += (A & X) ? pc->jt : pc->jf;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ A += X;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ A -= X;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ A *= X;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ if (X == 0)
+ return 0;
+ A /= X;
+ continue;
+
+ case BPF_ALU|BPF_MOD|BPF_X:
+ if (X == 0)
+ return 0;
+ A %= X;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ A &= X;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ A |= X;
+ continue;
+
+ case BPF_ALU|BPF_XOR|BPF_X:
+ A ^= X;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ if (X < 32)
+ A <<= X;
+ else
+ A = 0;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ if (X < 32)
+ A >>= X;
+ else
+ A = 0;
+ continue;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ A += pc->k;
+ continue;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ A -= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ A *= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ A /= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_MOD|BPF_K:
+ A %= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ A &= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ A |= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_XOR|BPF_K:
+ A ^= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ A <<= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ A >>= pc->k;
+ continue;
+
+ case BPF_ALU|BPF_NEG:
+ /*
+ * Most BPF arithmetic is unsigned, but negation
+ * can't be unsigned; respecify it as subtracting
+ * the accumulator from 0U, so that 1) we don't
+ * get compiler warnings about negating an unsigned
+ * value and 2) don't get UBSan warnings about
+ * the result of negating 0x80000000 being undefined.
+ */
+ A = (0U - A);
+ continue;
+
+ case BPF_MISC|BPF_TAX:
+ X = A;
+ continue;
+
+ case BPF_MISC|BPF_TXA:
+ A = X;
+ continue;
+ }
+ }
+}
+
+u_int
+bpf_filter(const struct bpf_insn *pc, const u_char *p, u_int wirelen,
+ u_int buflen)
+{
+ return bpf_filter_with_aux_data(pc, p, wirelen, buflen, NULL);
+}
+
+
+/*
+ * Return true if the 'fcode' is a valid filter program.
+ * The constraints are that each jump be forward and to a valid
+ * code, that memory accesses are within valid ranges (to the
+ * extent that this can be checked statically; loads of packet
+ * data have to be, and are, also checked at run time), and that
+ * the code terminates with either an accept or reject.
+ *
+ * The kernel needs to be able to verify an application's filter code.
+ * Otherwise, a bogus program could easily crash the system.
+ */
+int
+bpf_validate(const struct bpf_insn *f, int len)
+{
+ u_int i, from;
+ const struct bpf_insn *p;
+
+ if (len < 1)
+ return 0;
+
+ for (i = 0; i < (u_int)len; ++i) {
+ p = &f[i];
+ switch (BPF_CLASS(p->code)) {
+ /*
+ * Check that memory operations use valid addresses.
+ */
+ case BPF_LD:
+ case BPF_LDX:
+ switch (BPF_MODE(p->code)) {
+ case BPF_IMM:
+ break;
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ /*
+ * There's no maximum packet data size
+ * in userland. The runtime packet length
+ * check suffices.
+ */
+ break;
+ case BPF_MEM:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_LEN:
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_ST:
+ case BPF_STX:
+ if (p->k >= BPF_MEMWORDS)
+ return 0;
+ break;
+ case BPF_ALU:
+ switch (BPF_OP(p->code)) {
+ case BPF_ADD:
+ case BPF_SUB:
+ case BPF_MUL:
+ case BPF_OR:
+ case BPF_AND:
+ case BPF_XOR:
+ case BPF_LSH:
+ case BPF_RSH:
+ case BPF_NEG:
+ break;
+ case BPF_DIV:
+ case BPF_MOD:
+ /*
+ * Check for constant division or modulus
+ * by 0.
+ */
+ if (BPF_SRC(p->code) == BPF_K && p->k == 0)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_JMP:
+ /*
+ * Check that jumps are within the code block,
+ * and that unconditional branches don't go
+ * backwards as a result of an overflow.
+ * Unconditional branches have a 32-bit offset,
+ * so they could overflow; we check to make
+ * sure they don't. Conditional branches have
+ * an 8-bit offset, and the from address is <=
+ * BPF_MAXINSNS, and we assume that BPF_MAXINSNS
+ * is sufficiently small that adding 255 to it
+ * won't overflow.
+ *
+ * We know that len is <= BPF_MAXINSNS, and we
+ * assume that BPF_MAXINSNS is < the maximum size
+ * of a u_int, so that i + 1 doesn't overflow.
+ *
+ * For userland, we don't know that the from
+ * or len are <= BPF_MAXINSNS, but we know that
+ * from <= len, and, except on a 64-bit system,
+ * it's unlikely that len, if it truly reflects
+ * the size of the program we've been handed,
+ * will be anywhere near the maximum size of
+ * a u_int. We also don't check for backward
+ * branches, as we currently support them in
+ * userland for the protochain operation.
+ */
+ from = i + 1;
+ switch (BPF_OP(p->code)) {
+ case BPF_JA:
+ if (from + p->k >= (u_int)len)
+ return 0;
+ break;
+ case BPF_JEQ:
+ case BPF_JGT:
+ case BPF_JGE:
+ case BPF_JSET:
+ if (from + p->jt >= (u_int)len || from + p->jf >= (u_int)len)
+ return 0;
+ break;
+ default:
+ return 0;
+ }
+ break;
+ case BPF_RET:
+ break;
+ case BPF_MISC:
+ break;
+ default:
+ return 0;
+ }
+ }
+ return BPF_CLASS(f[len - 1].code) == BPF_RET;
+}
diff --git a/lib/libpcap/libpcap/bpf_image.c b/lib/libpcap/libpcap/bpf_image.c
new file mode 100644
index 0000000..ab41d1e
--- /dev/null
+++ b/lib/libpcap/libpcap/bpf_image.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+char *
+bpf_image(const struct bpf_insn *p, int n)
+{
+ const char *op;
+ static char image[256];
+ char operand_buf[64];
+ const char *operand;
+
+ switch (p->code) {
+
+ default:
+ op = "unimp";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "0x%x", p->code);
+ operand = operand_buf;
+ break;
+
+ case BPF_RET|BPF_K:
+ op = "ret";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_RET|BPF_A:
+ op = "ret";
+ operand = "";
+ break;
+
+ case BPF_LD|BPF_W|BPF_ABS:
+ op = "ld";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LD|BPF_H|BPF_ABS:
+ op = "ldh";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LD|BPF_B|BPF_ABS:
+ op = "ldb";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[%d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LD|BPF_W|BPF_LEN:
+ op = "ld";
+ operand = "#pktlen";
+ break;
+
+ case BPF_LD|BPF_W|BPF_IND:
+ op = "ld";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LD|BPF_H|BPF_IND:
+ op = "ldh";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LD|BPF_B|BPF_IND:
+ op = "ldb";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "[x + %d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LD|BPF_IMM:
+ op = "ld";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LDX|BPF_IMM:
+ op = "ldx";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ op = "ldxb";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "4*([%d]&0xf)", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LD|BPF_MEM:
+ op = "ld";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_LDX|BPF_MEM:
+ op = "ldx";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ST:
+ op = "st";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_STX:
+ op = "stx";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "M[%d]", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_JMP|BPF_JA:
+ op = "ja";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "%d", n + 1 + p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_K:
+ op = "jgt";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_K:
+ op = "jge";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_K:
+ op = "jeq";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_K:
+ op = "jset";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_JMP|BPF_JGT|BPF_X:
+ op = "jgt";
+ operand = "x";
+ break;
+
+ case BPF_JMP|BPF_JGE|BPF_X:
+ op = "jge";
+ operand = "x";
+ break;
+
+ case BPF_JMP|BPF_JEQ|BPF_X:
+ op = "jeq";
+ operand = "x";
+ break;
+
+ case BPF_JMP|BPF_JSET|BPF_X:
+ op = "jset";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ op = "add";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_X:
+ op = "sub";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_X:
+ op = "mul";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_X:
+ op = "div";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_MOD|BPF_X:
+ op = "mod";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_X:
+ op = "and";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_X:
+ op = "or";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_XOR|BPF_X:
+ op = "xor";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_X:
+ op = "lsh";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_X:
+ op = "rsh";
+ operand = "x";
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ op = "add";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_SUB|BPF_K:
+ op = "sub";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_MUL|BPF_K:
+ op = "mul";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_DIV|BPF_K:
+ op = "div";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_MOD|BPF_K:
+ op = "mod";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_AND|BPF_K:
+ op = "and";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_OR|BPF_K:
+ op = "or";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_XOR|BPF_K:
+ op = "xor";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#0x%x", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_LSH|BPF_K:
+ op = "lsh";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_RSH|BPF_K:
+ op = "rsh";
+ (void)pcap_snprintf(operand_buf, sizeof operand_buf, "#%d", p->k);
+ operand = operand_buf;
+ break;
+
+ case BPF_ALU|BPF_NEG:
+ op = "neg";
+ operand = "";
+ break;
+
+ case BPF_MISC|BPF_TAX:
+ op = "tax";
+ operand = "";
+ break;
+
+ case BPF_MISC|BPF_TXA:
+ op = "txa";
+ operand = "";
+ break;
+ }
+ if (BPF_CLASS(p->code) == BPF_JMP && BPF_OP(p->code) != BPF_JA) {
+ (void)pcap_snprintf(image, sizeof image,
+ "(%03d) %-8s %-16s jt %d\tjf %d",
+ n, op, operand, n + 1 + p->jt, n + 1 + p->jf);
+ } else {
+ (void)pcap_snprintf(image, sizeof image,
+ "(%03d) %-8s %s",
+ n, op, operand);
+ }
+ return image;
+}
diff --git a/lib/libpcap/libpcap/chmod_bpf b/lib/libpcap/libpcap/chmod_bpf
new file mode 100755
index 0000000..946fec3
--- /dev/null
+++ b/lib/libpcap/libpcap/chmod_bpf
@@ -0,0 +1,19 @@
+#! /bin/sh
+
+#
+# Unfortunately, macOS's devfs is based on the old FreeBSD
+# one, not the current one, so there's no way to configure it
+# to create BPF devices with particular owners or groups.
+# This startup item will make it owned by the admin group,
+# with permissions rw-rw----, so that anybody in the admin
+# group can use programs that capture or send raw packets.
+#
+# Change this as appropriate for your site, e.g. to make
+# it owned by a particular user without changing the permissions,
+# so only that user and the super-user can capture or send raw
+# packets, or give it the permissions rw-r-----, so that
+# only the super-user can send raw packets but anybody in the
+# admin group can capture packets.
+#
+chgrp admin /dev/bpf*
+chmod g+rw /dev/bpf*
diff --git a/lib/libpcap/libpcap/cmake/Modules/FindDAG.cmake b/lib/libpcap/libpcap/cmake/Modules/FindDAG.cmake
new file mode 100644
index 0000000..ef13528
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/Modules/FindDAG.cmake
@@ -0,0 +1,32 @@
+#
+# Try to find the Endace DAG library.
+#
+
+# Try to find the header
+find_path(DAG_INCLUDE_DIR dagapi.h)
+
+#
+# Try to find the libraries
+#
+# We assume that if we have libdag we have libdagconf, as they're
+# installed at the same time from the same package.
+#
+find_library(DAG_LIBRARY dag)
+find_library(DAGCONF_LIBRARY dagconf)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(DAG
+ DEFAULT_MSG
+ DAG_INCLUDE_DIR
+ DAG_LIBRARY
+ DAGCONF_LIBRARY
+)
+
+mark_as_advanced(
+ DAG_INCLUDE_DIR
+ DAG_LIBRARY
+ DAGCONF_LIBRARY
+)
+
+set(DAG_INCLUDE_DIRS ${DAG_INCLUDE_DIR})
+set(DAG_LIBRARIES ${DAG_LIBRARY} ${DAGCONF_LIBRARY})
diff --git a/lib/libpcap/libpcap/cmake/Modules/FindFseeko.cmake b/lib/libpcap/libpcap/cmake/Modules/FindFseeko.cmake
new file mode 100644
index 0000000..ca53a5a
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/Modules/FindFseeko.cmake
@@ -0,0 +1,85 @@
+# CMake support for fseeko
+#
+# Based on FindLFS.cmake by
+# Copyright (C) 2016 Julian Andres Klode <jak@debian.org>.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# This defines the following variables
+#
+# FSEEKO_DEFINITIONS - List of definitions to pass to add_definitions()
+# FSEEKO_COMPILE_OPTIONS - List of definitions to pass to add_compile_options()
+# FSEEKO_LIBRARIES - List of libraries and linker flags
+# FSEEKO_FOUND - If there is Large files support
+#
+
+include(CheckCSourceCompiles)
+include(FindPackageHandleStandardArgs)
+include(CMakePushCheckState)
+
+# Check for the availability of fseeko()
+# The cases handled are:
+#
+# * Native fseeko()
+# * Preprocessor flag -D_LARGEFILE_SOURCE
+#
+function(_fseeko_check)
+ set(_fseeko_cppflags)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_QUIET 1)
+ set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS})
+ message(STATUS "Looking for native fseeko support")
+ check_symbol_exists(fseeko stdio.h fseeko_native)
+ cmake_pop_check_state()
+ if (fseeko_native)
+ message(STATUS "Looking for native fseeko support - found")
+ set(FSEEKO_FOUND TRUE)
+ else()
+ message(STATUS "Looking for native fseeko support - not found")
+ endif()
+
+ if (NOT FSEEKO_FOUND)
+ # See if it's available with _LARGEFILE_SOURCE.
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_QUIET 1)
+ set(CMAKE_REQUIRED_DEFINITIONS ${LFS_DEFINITIONS} "-D_LARGEFILE_SOURCE")
+ check_symbol_exists(fseeko stdio.h fseeko_need_largefile_source)
+ cmake_pop_check_state()
+ if (fseeko_need_largefile_source)
+ message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - found")
+ set(FSEEKO_FOUND TRUE)
+ set(_fseeko_cppflags "-D_LARGEFILE_SOURCE")
+ else()
+ message(STATUS "Looking for fseeko support with _LARGEFILE_SOURCE - not found")
+ endif()
+ endif()
+
+ set(FSEEKO_DEFINITIONS ${_fseeko_cppflags} CACHE STRING "Extra definitions for fseeko support")
+ set(FSEEKO_COMPILE_OPTIONS "" CACHE STRING "Extra compiler options for fseeko support")
+ set(FSEEKO_LIBRARIES "" CACHE STRING "Extra definitions for fseeko support")
+ set(FSEEKO_FOUND ${FSEEKO_FOUND} CACHE INTERNAL "Found fseeko")
+endfunction()
+
+if (NOT FSEEKO_FOUND)
+ _fseeko_check()
+endif()
+
+find_package_handle_standard_args(FSEEKO "Could not find fseeko. Set FSEEKO_DEFINITIONS, FSEEKO_COMPILE_OPTIONS, FSEEKO_LIBRARIES." FSEEKO_FOUND)
diff --git a/lib/libpcap/libpcap/cmake/Modules/FindLFS.cmake b/lib/libpcap/libpcap/cmake/Modules/FindLFS.cmake
new file mode 100644
index 0000000..be5f0d4
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/Modules/FindLFS.cmake
@@ -0,0 +1,153 @@
+# CMake support for large files
+#
+# Copyright (C) 2016 Julian Andres Klode <jak@debian.org>.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sublicense, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# This defines the following variables
+#
+# LFS_DEFINITIONS - List of definitions to pass to add_definitions()
+# LFS_COMPILE_OPTIONS - List of definitions to pass to add_compile_options()
+# LFS_LIBRARIES - List of libraries and linker flags
+# LFS_FOUND - If there is Large files support
+#
+
+include(CheckCSourceCompiles)
+include(FindPackageHandleStandardArgs)
+include(CMakePushCheckState)
+
+# Test program to check for LFS. Requires that off_t has at least 8 byte large
+set(_lfs_test_source
+ "
+ #include <sys/types.h>
+ typedef char my_static_assert[sizeof(off_t) >= 8 ? 1 : -1];
+ int main(void) { return 0; }
+ "
+)
+
+# Check if the given options are needed
+#
+# This appends to the variables _lfs_cppflags, _lfs_cflags, and _lfs_ldflags,
+# it also sets LFS_FOUND to 1 if it works.
+function(_lfs_check_compiler_option var options definitions libraries)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_QUIET 1)
+ set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} ${options})
+ set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${definitions})
+ set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_DEFINITIONS} ${libraries})
+
+ message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries}")
+ check_c_source_compiles("${_lfs_test_source}" ${var})
+ cmake_pop_check_state()
+
+ if(${var})
+ message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - found")
+ set(_lfs_cppflags ${_lfs_cppflags} ${definitions} PARENT_SCOPE)
+ set(_lfs_cflags ${_lfs_cflags} ${options} PARENT_SCOPE)
+ set(_lfs_ldflags ${_lfs_ldflags} ${libraries} PARENT_SCOPE)
+ set(LFS_FOUND TRUE PARENT_SCOPE)
+ else()
+ message(STATUS "Looking for LFS support using ${options} ${definitions} ${libraries} - not found")
+ endif()
+endfunction()
+
+# Check for the availability of LFS.
+# The cases handled are:
+#
+# * Native LFS
+# * Output of getconf LFS_CFLAGS; getconf LFS_LIBS; getconf LFS_LDFLAGS
+# * Preprocessor flag -D_FILE_OFFSET_BITS=64
+# * Preprocessor flag -D_LARGE_FILES
+#
+function(_lfs_check)
+ set(_lfs_cflags)
+ set(_lfs_cppflags)
+ set(_lfs_ldflags)
+ set(_lfs_libs)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_QUIET 1)
+ message(STATUS "Looking for native LFS support")
+ check_c_source_compiles("${_lfs_test_source}" lfs_native)
+ cmake_pop_check_state()
+ if (lfs_native)
+ message(STATUS "Looking for native LFS support - found")
+ set(LFS_FOUND TRUE)
+ else()
+ message(STATUS "Looking for native LFS support - not found")
+ endif()
+
+ if (NOT LFS_FOUND)
+ # Check using getconf. If getconf fails, don't worry, the check in
+ # _lfs_check_compiler_option will fail as well.
+ execute_process(COMMAND getconf LFS_CFLAGS
+ OUTPUT_VARIABLE _lfs_cflags_raw
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
+ execute_process(COMMAND getconf LFS_LIBS
+ OUTPUT_VARIABLE _lfs_libs_tmp
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
+ execute_process(COMMAND getconf LFS_LDFLAGS
+ OUTPUT_VARIABLE _lfs_ldflags_tmp
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ ERROR_QUIET)
+
+ separate_arguments(_lfs_cflags_raw)
+ separate_arguments(_lfs_ldflags_tmp)
+ separate_arguments(_lfs_libs_tmp)
+
+ # Move -D flags to the place they are supposed to be
+ foreach(flag ${_lfs_cflags_raw})
+ if (flag MATCHES "-D.*")
+ list(APPEND _lfs_cppflags_tmp ${flag})
+ else()
+ list(APPEND _lfs_cflags_tmp ${flag})
+ endif()
+ endforeach()
+
+ # Check if the flags we received (if any) produce working LFS support
+ _lfs_check_compiler_option(lfs_getconf_works
+ "${_lfs_cflags_tmp}"
+ "${_lfs_cppflags_tmp}"
+ "${_lfs_libs_tmp};${_lfs_ldflags_tmp}")
+ endif()
+
+ if(NOT LFS_FOUND) # IRIX stuff
+ _lfs_check_compiler_option(lfs_need_n32 "-n32" "" "")
+ endif()
+ if(NOT LFS_FOUND) # Linux and friends
+ _lfs_check_compiler_option(lfs_need_file_offset_bits "" "-D_FILE_OFFSET_BITS=64" "")
+ endif()
+ if(NOT LFS_FOUND) # AIX
+ _lfs_check_compiler_option(lfs_need_large_files "" "-D_LARGE_FILES=1" "")
+ endif()
+
+ set(LFS_DEFINITIONS ${_lfs_cppflags} CACHE STRING "Extra definitions for large file support")
+ set(LFS_COMPILE_OPTIONS ${_lfs_cflags} CACHE STRING "Extra definitions for large file support")
+ set(LFS_LIBRARIES ${_lfs_libs} ${_lfs_ldflags} CACHE STRING "Extra definitions for large file support")
+ set(LFS_FOUND ${LFS_FOUND} CACHE INTERNAL "Found LFS")
+endfunction()
+
+if (NOT LFS_FOUND)
+ _lfs_check()
+endif()
+
+find_package_handle_standard_args(LFS "Could not find LFS. Set LFS_DEFINITIONS, LFS_COMPILE_OPTIONS, LFS_LIBRARIES." LFS_FOUND)
diff --git a/lib/libpcap/libpcap/cmake/Modules/FindPacket.cmake b/lib/libpcap/libpcap/cmake/Modules/FindPacket.cmake
new file mode 100644
index 0000000..f114875
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/Modules/FindPacket.cmake
@@ -0,0 +1,88 @@
+#
+# Copyright (C) 2017 Ali Abdulkadir <autostart.ini@gmail.com>.
+#
+# Permission is hereby granted, free of charge, to any person
+# obtaining a copy of this software and associated documentation files
+# (the "Software"), to deal in the Software without restriction,
+# including without limitation the rights to use, copy, modify, merge,
+# publish, distribute, sub-license, and/or sell copies of the Software,
+# and to permit persons to whom the Software is furnished to do so,
+# subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+# FindPacket
+# ==========
+#
+# Find the Packet library and include files.
+#
+# This module defines the following variables:
+#
+# PACKET_INCLUDE_DIR - absolute path to the directory containing Packet32.h.
+#
+# PACKET_LIBRARY - relative or absolute path to the Packet library to
+# link with. An absolute path is will be used if the
+# Packet library is not located in the compiler's
+# default search path. See e.g. PACKET_DLL_DIR
+# variable below.
+
+# PACKET_FOUND - TRUE if the Packet library *and* header are found.
+#
+# Hints and Backward Compatibility
+# ================================
+#
+# To tell this module where to look, a user may set the environment variable
+# PACKET_DLL_DIR to point cmake to the *root* of a directory with include and
+# lib subdirectories for packet.dll (e.g WpdPack/npcap-sdk).
+# Alternatively, PACKET_DLL_DIR may also be set from cmake command line or GUI
+# (e.g cmake -DPACKET_DLL_DIR=/path/to/packet [...])
+#
+
+# The 64-bit Packet.lib is located under /x64
+if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+ #
+ # For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level
+ # directory contains 32-bit libraries; the 64-bit libraries are in the
+ # Lib/x64 directory.
+ #
+ # The only way to *FORCE* CMake to look in the Lib/x64 directory
+ # without searching in the Lib directory first appears to be to set
+ # CMAKE_LIBRARY_ARCHITECTURE to "x64".
+ #
+ set(CMAKE_LIBRARY_ARCHITECTURE "x64")
+endif()
+
+# Find the header
+find_path(PACKET_INCLUDE_DIR Packet32.h
+ HINTS "${PACKET_DLL_DIR}" ENV PACKET_DLL_DIR
+ PATH_SUFFIXES include Include
+)
+
+# Find the library
+find_library(PACKET_LIBRARY
+ NAMES Packet packet
+ HINTS "${PACKET_DLL_DIR}" ENV PACKET_DLL_DIR
+)
+
+# Set PACKET_FOUND to TRUE if PACKET_INCLUDE_DIR and PACKET_LIBRARY are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(PACKET
+ DEFAULT_MSG
+ PACKET_INCLUDE_DIR
+ PACKET_LIBRARY
+)
+
+mark_as_advanced(PACKET_INCLUDE_DIR PACKET_LIBRARY)
+
+set(PACKET_INCLUDE_DIRS ${PACKET_INCLUDE_DIR})
+set(PACKET_LIBRARIES ${PACKET_LIBRARY})
diff --git a/lib/libpcap/libpcap/cmake/Modules/FindSNF.cmake b/lib/libpcap/libpcap/cmake/Modules/FindSNF.cmake
new file mode 100644
index 0000000..76dcced
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/Modules/FindSNF.cmake
@@ -0,0 +1,24 @@
+#
+# Try to find the Myricom SNF library.
+#
+
+# Try to find the header
+find_path(SNF_INCLUDE_DIR snf.h /opt/snf)
+
+# Try to find the library
+find_library(SNF_LIBRARY snf /opt/snf)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SNF
+ DEFAULT_MSG
+ SNF_INCLUDE_DIR
+ SNF_LIBRARY
+)
+
+mark_as_advanced(
+ SNF_INCLUDE_DIR
+ SNF_LIBRARY
+)
+
+set(SNF_INCLUDE_DIRS ${SNF_INCLUDE_DIR})
+set(SNF_LIBRARIES ${SNF_LIBRARY})
diff --git a/lib/libpcap/libpcap/cmake/Modules/FindTC.cmake b/lib/libpcap/libpcap/cmake/Modules/FindTC.cmake
new file mode 100644
index 0000000..bb24c66
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/Modules/FindTC.cmake
@@ -0,0 +1,24 @@
+#
+# Try to find the Riverbed TurboCap library.
+#
+
+# Try to find the header
+find_path(TC_INCLUDE_DIR TcApi.h)
+
+# Try to find the library
+find_library(TC_LIBRARY TcApi)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(TC
+ DEFAULT_MSG
+ TC_INCLUDE_DIR
+ TC_LIBRARY
+)
+
+mark_as_advanced(
+ TC_INCLUDE_DIR
+ TC_LIBRARY
+)
+
+set(TC_INCLUDE_DIRS ${TC_INCLUDE_DIR})
+set(TC_LIBRARIES ${TC_LIBRARY})
diff --git a/lib/libpcap/libpcap/cmake/have_siocglifconf.c b/lib/libpcap/libpcap/cmake/have_siocglifconf.c
new file mode 100644
index 0000000..5a67abc
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/have_siocglifconf.c
@@ -0,0 +1,6 @@
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+int main() {
+ ioctl(0, SIOCGLIFCONF, (char *)0);
+}
diff --git a/lib/libpcap/libpcap/cmake/preconfigure.cmake b/lib/libpcap/libpcap/cmake/preconfigure.cmake
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake/preconfigure.cmake
diff --git a/lib/libpcap/libpcap/cmake_uninstall.cmake.in b/lib/libpcap/libpcap/cmake_uninstall.cmake.in
new file mode 100644
index 0000000..2037e36
--- /dev/null
+++ b/lib/libpcap/libpcap/cmake_uninstall.cmake.in
@@ -0,0 +1,21 @@
+if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+ message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+string(REGEX REPLACE "\n" ";" files "${files}")
+foreach(file ${files})
+ message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
+ if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ exec_program(
+ "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+ OUTPUT_VARIABLE rm_out
+ RETURN_VALUE rm_retval
+ )
+ if(NOT "${rm_retval}" STREQUAL 0)
+ message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
+ endif(NOT "${rm_retval}" STREQUAL 0)
+ else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+ message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
+ endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
+endforeach(file)
diff --git a/lib/libpcap/libpcap/cmakeconfig.h.in b/lib/libpcap/libpcap/cmakeconfig.h.in
new file mode 100644
index 0000000..1639925
--- /dev/null
+++ b/lib/libpcap/libpcap/cmakeconfig.h.in
@@ -0,0 +1,381 @@
+/* cmakeconfig.h.in */
+
+/* Define to 1 if arpa/inet.h declares `ether_hostton' */
+#cmakedefine ARPA_INET_H_DECLARES_ETHER_HOSTTON 1
+
+/* Enable optimizer debugging */
+#cmakedefine BDEBUG 1
+
+/* Define to 1 if remote packet capture is to be supported */
+#cmakedefine ENABLE_REMOTE 1
+
+/* define if we have the AIX getnetbyname_r() */
+#cmakedefine HAVE_AIX_GETNETBYNAME_R 1
+
+/* define if we have the AIX getprotobyname_r() */
+#cmakedefine HAVE_AIX_GETPROTOBYNAME_R 1
+
+/* Define to 1 if you have the `asprintf' function. */
+#cmakedefine HAVE_ASPRINTF 1
+
+/* define if you have the DAG API */
+#cmakedefine HAVE_DAG_API 1
+
+/* define if you have dag_get_erf_types() */
+#cmakedefine HAVE_DAG_GET_ERF_TYPES 1
+
+/* define if you have dag_get_stream_erf_types() */
+#cmakedefine HAVE_DAG_GET_STREAM_ERF_TYPES 1
+
+/* define if you have large streams capable DAG API */
+#cmakedefine HAVE_DAG_LARGE_STREAMS_API 1
+
+/* define if you have vdag_set_device_info() */
+#cmakedefine HAVE_DAG_VDAG 1
+
+/* Define to 1 if you have the declaration of `ether_hostton' */
+#cmakedefine HAVE_DECL_ETHER_HOSTTON 1
+
+/* Define to 1 if `dl_module_id_1' is a member of `dl_hp_ppa_info_t'. */
+#cmakedefine HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1 1
+
+/* Define to 1 if the system has the type `dl_passive_req_t'. */
+#cmakedefine HAVE_DL_PASSIVE_REQ_T 1
+
+/* Define to 1 if you have the `ether_hostton' function. */
+#cmakedefine HAVE_ETHER_HOSTTON 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#cmakedefine HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `getspnam' function. */
+#cmakedefine HAVE_GETSPNAM 1
+
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#cmakedefine HAVE_GNU_STRERROR_R 1
+
+/* on HP-UX 10.20 or later */
+#cmakedefine HAVE_HPUX10_20_OR_LATER 1
+
+/* on HP-UX 9.x */
+#cmakedefine HAVE_HPUX9 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#cmakedefine HAVE_INTTYPES_H 1
+
+/* if libdlpi exists */
+#cmakedefine HAVE_LIBDLPI 1
+
+/* if libnl exists */
+#cmakedefine HAVE_LIBNL 1
+
+/* if libnl exists and is version 2.x */
+#cmakedefine HAVE_LIBNL_2_x 1
+
+/* if libnl exists and is version 3.x */
+#cmakedefine HAVE_LIBNL_3_x 1
+
+/* libnl has NLE_FAILURE */
+#cmakedefine HAVE_LIBNL_NLE 1
+
+/* libnl has new-style socket api */
+#cmakedefine HAVE_LIBNL_SOCKETS 1
+
+/* Define to 1 if you have the <limits.h> header file. */
+#cmakedefine HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+#cmakedefine HAVE_LINUX_COMPILER_H 1
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+#cmakedefine HAVE_LINUX_ETHTOOL_H 1
+
+/* define if we have the Linux getnetbyname_r() */
+#cmakedefine HAVE_LINUX_GETNETBYNAME_R 1
+
+/* define if we have the Linux getprotobyname_r() */
+#cmakedefine HAVE_LINUX_GETPROTOBYNAME_R 1
+
+/* Define to 1 if you have the <linux/if_bonding.h> header file. */
+#cmakedefine HAVE_LINUX_IF_BONDING_H 1
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+#cmakedefine HAVE_LINUX_NET_TSTAMP_H 1
+
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#cmakedefine HAVE_LINUX_SOCKET_H 1
+
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+#cmakedefine HAVE_LINUX_SOCKIOS_H 1
+
+/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
+#cmakedefine HAVE_LINUX_USBDEVICE_FS_H 1
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+#cmakedefine HAVE_LINUX_WIRELESS_H 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#cmakedefine HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netpacket/packet.h> header file. */
+#cmakedefine HAVE_NETPACKET_PACKET_H 1
+
+/* Define to 1 if you have the <net/bpf.h> header file. */
+#cmakedefine HAVE_NET_BPF_H 1
+
+/* Define to 1 if you have the <net/enet.h> header file. */
+#cmakedefine HAVE_NET_ENET_H 1
+
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#cmakedefine HAVE_NET_IF_MEDIA_H 1
+
+/* Define to 1 if you have the <net/nit.h> header file. */
+#cmakedefine HAVE_NET_NIT_H 1
+
+/* Define to 1 if you have the <net/pfilt.h> header file. */
+#cmakedefine HAVE_NET_PFILT_H 1
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+#cmakedefine HAVE_NET_PFVAR_H 1
+
+/* Define to 1 if you have the <net/raw.h> header file. */
+#cmakedefine HAVE_NET_RAW_H 1
+
+/* if there's an os_proto.h for this platform, to use additional prototypes */
+#cmakedefine HAVE_OS_PROTO_H 1
+
+/* Define to 1 if Packet32 API (Npcap driver) is available */
+#cmakedefine HAVE_PACKET32 1
+
+/* Define to 1 if NPcap's version.h is available */
+#cmakedefine HAVE_VERSION_H 1
+
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#cmakedefine HAVE_POSIX_STRERROR_R 1
+
+/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
+#cmakedefine HAVE_PF_NAT_THROUGH_PF_NORDR 1
+
+/* define if you have the Septel API */
+#cmakedefine HAVE_SEPTEL_API 1
+
+/* define if you have the Myricom SNF API */
+#cmakedefine HAVE_SNF_API 1
+
+/* Define to 1 if you have the `snprintf' function. */
+#cmakedefine HAVE_SNPRINTF 1
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#cmakedefine HAVE_SOCKLEN_T 1
+
+/* On solaris */
+#cmakedefine HAVE_SOLARIS 1
+
+/* define if we have the Solaris/IRIX getnetbyname_r() */
+#cmakedefine HAVE_SOLARIS_IRIX_GETNETBYNAME_R 1
+
+/* define if we have the Solaris/IRIX getprotobyname_r() */
+#cmakedefine HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#cmakedefine HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#cmakedefine HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#cmakedefine HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strerror_s' function. */
+#cmakedefine HAVE_STRERROR_S 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#cmakedefine HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#cmakedefine HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcat' function. */
+#cmakedefine HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#cmakedefine HAVE_STRLCPY 1
+
+/* Define to 1 if you have the `strtok_r' function. */
+#cmakedefine HAVE_STRTOK_R 1
+
+/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
+#cmakedefine HAVE_STRUCT_BPF_TIMEVAL 1
+
+/* Define to 1 if the system has the type `struct ether_addr'. */
+#cmakedefine HAVE_STRUCT_ETHER_ADDR 1
+
+/* Define to 1 if `msg_control' is a member of `struct msghdr'. */
+#cmakedefine HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
+
+/* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
+#cmakedefine HAVE_STRUCT_MSGHDR_MSG_FLAGS 1
+
+/* Define to 1 if `hci_channel' is a member of `struct sockaddr_hci'. */
+#cmakedefine HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL 1
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#cmakedefine HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#cmakedefine HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
+#cmakedefine HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI 1
+
+/* Define to 1 if the system has the type `struct tpacket_stats'. */
+#cmakedefine HAVE_STRUCT_TPACKET_STATS 1
+
+/* Define to 1 if `bRequestType' is a member of `struct
+ usbdevfs_ctrltransfer'. */
+#cmakedefine HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
+
+/* Define to 1 if you have the <sys/bufmod.h> header file. */
+#cmakedefine HAVE_SYS_BUFMOD_H 1
+
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
+#cmakedefine HAVE_SYS_DLPI_EXT_H 1
+
+/* Define to 1 if you have the <sys/dlpi.h> header file. */
+#cmakedefine HAVE_SYS_DLPI_H 1
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#cmakedefine HAVE_SYS_IOCCOM_H 1
+
+/* Define to 1 if you have the <sys/net/nit.h> header file. */
+#cmakedefine HAVE_SYS_NET_NIT_H 1
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#cmakedefine HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#cmakedefine HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#cmakedefine HAVE_SYS_TYPES_H 1
+
+/* define if you have the TurboCap API */
+#cmakedefine HAVE_TC_API 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#cmakedefine HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#cmakedefine HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#cmakedefine HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
+
+/* Define to 1 if you have the `PacketIsLoopbackAdapter' function. */
+#cmakedefine HAVE_PACKET_IS_LOOPBACK_ADAPTER 1
+
+/* IPv6 */
+#cmakedefine INET6 1
+
+/* if unaligned access fails */
+#cmakedefine LBL_ALIGN 1
+
+/* path for device for USB sniffing */
+#cmakedefine LINUX_USB_MON_DEV "@LINUX_USB_MON_DEV@"
+
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+#cmakedefine NETINET_ETHER_H_DECLARES_ETHER_HOSTTON 1
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+#cmakedefine NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON 1
+
+/* Define to 1 if net/ethernet.h declares `ether_hostton' */
+#cmakedefine NET_ETHERNET_H_DECLARES_ETHER_HOSTTON 1
+
+/* do not use protochain */
+#cmakedefine NO_PROTOCHAIN 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#cmakedefine PACKAGE_BUGREPORT 1
+
+/* Define to the DLL-preferred version string of of this package. */
+#cmakedefine PACKAGE_VERSION_DLL @PACKAGE_VERSION_DLL@
+
+/* Define to the full name of this package. */
+#cmakedefine PACKAGE_NAME "@PACKAGE_NAME@"
+
+/* Define to the full name and version of this package. */
+#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
+
+/* Define to the one symbol short name of this package. */
+#cmakedefine PACKAGE_TARNAME 1
+
+/* Define to the home page for this package. */
+#cmakedefine PACKAGE_URL 1
+
+/* Define to the version of this package. */
+#cmakedefine PACKAGE_VERSION "@PACKAGE_VERSION@"
+
+/* target host supports Bluetooth sniffing */
+#cmakedefine PCAP_SUPPORT_BT 1
+
+/* target host supports Bluetooth Monitor */
+#cmakedefine PCAP_SUPPORT_BT_MONITOR 1
+
+/* support D-Bus sniffing */
+#cmakedefine PCAP_SUPPORT_DBUS 1
+
+/* target host supports netfilter sniffing */
+#cmakedefine PCAP_SUPPORT_NETFILTER 1
+
+/* target host supports netmap */
+#cmakedefine PCAP_SUPPORT_NETMAP 1
+
+/* use packet ring capture support on Linux if available */
+#cmakedefine PCAP_SUPPORT_PACKET_RING 1
+
+/* target host supports RDMA sniffing */
+#cmakedefine PCAP_SUPPORT_RDMASNIFF 1
+
+/* target host supports USB sniffing */
+#cmakedefine PCAP_SUPPORT_USB 1
+
+/* include ACN support */
+#cmakedefine SITA 1
+
+/* Define to 1 if you have the ANSI C header files. */
+#cmakedefine STDC_HEADERS 1
+
+/* Define to 1 if strings.h declares `ffs' */
+#cmakedefine STRINGS_H_DECLARES_FFS 1
+
+/* Define to 1 if sys/ethernet.h declares `ether_hostton' */
+#cmakedefine SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON 1
+
+/* Enable parser debugging */
+#cmakedefine YYDEBUG 1
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#cmakedefine _FILE_OFFSET_BITS 1
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#cmakedefine _LARGEFILE_SOURCE 1
+
+/* Define for large files, on AIX-style hosts. */
+#cmakedefine _LARGE_FILES 1
+
+/* define on AIX to get certain functions */
+#cmakedefine _SUN 1
+
+#if 0
+/* on sinix */
+#cmakedefine sinix 1
+#endif
diff --git a/lib/libpcap/libpcap/config.guess b/lib/libpcap/libpcap/config.guess
new file mode 100755
index 0000000..2b79f6d
--- /dev/null
+++ b/lib/libpcap/libpcap/config.guess
@@ -0,0 +1,1476 @@
+#! /bin/sh
+# Attempt to guess a canonical system name.
+# Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-07-06'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help" >&2
+ exit 1 ;;
+ * )
+ break ;;
+ esac
+done
+
+if test $# != 0; then
+ echo "$me: too many arguments$help" >&2
+ exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp 2>/dev/null) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
+ ,,) echo "int x;" > "$dummy.c" ;
+ for c in cc gcc c89 c99 ; do
+ if ($c -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
+ CC_FOR_BUILD="$c"; break ;
+ fi ;
+ done ;
+ if test x"$CC_FOR_BUILD" = x ; then
+ CC_FOR_BUILD=no_compiler_found ;
+ fi
+ ;;
+ ,,*) CC_FOR_BUILD=$CC ;;
+ ,*,*) CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+ PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "$UNAME_SYSTEM" in
+Linux|GNU|GNU/*)
+ # If the system lacks a compiler, then just pick glibc.
+ # We could probably try harder.
+ LIBC=gnu
+
+ eval "$set_cc_for_build"
+ cat <<-EOF > "$dummy.c"
+ #include <features.h>
+ #if defined(__UCLIBC__)
+ LIBC=uclibc
+ #elif defined(__dietlibc__)
+ LIBC=dietlibc
+ #else
+ LIBC=gnu
+ #endif
+ EOF
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`"
+
+ # If ldd exists, use it to detect musl libc.
+ if command -v ldd >/dev/null && \
+ ldd --version 2>&1 | grep -q ^musl
+ then
+ LIBC=musl
+ fi
+ ;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
+ *:NetBSD:*:*)
+ # NetBSD (nbsd) targets should (where applicable) match one or
+ # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+ # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
+ # switched to ELF, *-*-netbsd* would select the old
+ # object file format. This provides both forward
+ # compatibility and a consistent mechanism for selecting the
+ # object file format.
+ #
+ # Note: NetBSD doesn't particularly care about the vendor
+ # portion of the name. We always set it to "unknown".
+ sysctl="sysctl -n hw.machine_arch"
+ UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+ "/sbin/$sysctl" 2>/dev/null || \
+ "/usr/sbin/$sysctl" 2>/dev/null || \
+ echo unknown)`
+ case "$UNAME_MACHINE_ARCH" in
+ armeb) machine=armeb-unknown ;;
+ arm*) machine=arm-unknown ;;
+ sh3el) machine=shl-unknown ;;
+ sh3eb) machine=sh-unknown ;;
+ sh5el) machine=sh5le-unknown ;;
+ earmv*)
+ arch=`echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+ endian=`echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p'`
+ machine="${arch}${endian}"-unknown
+ ;;
+ *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
+ esac
+ # The Operating System including object format, if it has switched
+ # to ELF recently (or will in the future) and ABI.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ os=netbsdelf
+ ;;
+ arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+ eval "$set_cc_for_build"
+ if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ELF__
+ then
+ # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+ # Return netbsd for either. FIX?
+ os=netbsd
+ else
+ os=netbsdelf
+ fi
+ ;;
+ *)
+ os=netbsd
+ ;;
+ esac
+ # Determine ABI tags.
+ case "$UNAME_MACHINE_ARCH" in
+ earm*)
+ expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+ abi=`echo "$UNAME_MACHINE_ARCH" | sed -e "$expr"`
+ ;;
+ esac
+ # The OS release
+ # Debian GNU/NetBSD machines have a different userland, and
+ # thus, need a distinct triplet. However, they do not need
+ # kernel version information, so it can be replaced with a
+ # suitable tag, in the style of linux-gnu.
+ case "$UNAME_VERSION" in
+ Debian*)
+ release='-gnu'
+ ;;
+ *)
+ release=`echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2`
+ ;;
+ esac
+ # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+ # contains redundant information, the shorter form:
+ # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+ echo "$machine-${os}${release}${abi-}"
+ exit ;;
+ *:Bitrig:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
+ exit ;;
+ *:OpenBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
+ exit ;;
+ *:LibertyBSD:*:*)
+ UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+ echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
+ exit ;;
+ *:MidnightBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
+ exit ;;
+ *:ekkoBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
+ exit ;;
+ *:SolidBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
+ exit ;;
+ macppc:MirBSD:*:*)
+ echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
+ exit ;;
+ *:MirBSD:*:*)
+ echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
+ exit ;;
+ *:Sortix:*:*)
+ echo "$UNAME_MACHINE"-unknown-sortix
+ exit ;;
+ *:Redox:*:*)
+ echo "$UNAME_MACHINE"-unknown-redox
+ exit ;;
+ mips:OSF1:*.*)
+ echo mips-dec-osf1
+ exit ;;
+ alpha:OSF1:*:*)
+ case $UNAME_RELEASE in
+ *4.0)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+ ;;
+ *5.*)
+ UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+ ;;
+ esac
+ # According to Compaq, /usr/sbin/psrinfo has been available on
+ # OSF/1 and Tru64 systems produced since 1995. I hope that
+ # covers most systems running today. This code pipes the CPU
+ # types through head -n 1, so we only detect the type of CPU 0.
+ ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+ case "$ALPHA_CPU_TYPE" in
+ "EV4 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "EV4.5 (21064)")
+ UNAME_MACHINE=alpha ;;
+ "LCA4 (21066/21068)")
+ UNAME_MACHINE=alpha ;;
+ "EV5 (21164)")
+ UNAME_MACHINE=alphaev5 ;;
+ "EV5.6 (21164A)")
+ UNAME_MACHINE=alphaev56 ;;
+ "EV5.6 (21164PC)")
+ UNAME_MACHINE=alphapca56 ;;
+ "EV5.7 (21164PC)")
+ UNAME_MACHINE=alphapca57 ;;
+ "EV6 (21264)")
+ UNAME_MACHINE=alphaev6 ;;
+ "EV6.7 (21264A)")
+ UNAME_MACHINE=alphaev67 ;;
+ "EV6.8CB (21264C)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8AL (21264B)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.8CX (21264D)")
+ UNAME_MACHINE=alphaev68 ;;
+ "EV6.9A (21264/EV69A)")
+ UNAME_MACHINE=alphaev69 ;;
+ "EV7 (21364)")
+ UNAME_MACHINE=alphaev7 ;;
+ "EV7.9 (21364A)")
+ UNAME_MACHINE=alphaev79 ;;
+ esac
+ # A Pn.n version is a patched version.
+ # A Vn.n version is a released version.
+ # A Tn.n version is a released field test version.
+ # A Xn.n version is an unreleased experimental baselevel.
+ # 1.2 uses "1.2" for uname -r.
+ echo "$UNAME_MACHINE"-dec-osf"`echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`"
+ # Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+ exitcode=$?
+ trap '' 0
+ exit $exitcode ;;
+ Amiga*:UNIX_System_V:4.0:*)
+ echo m68k-unknown-sysv4
+ exit ;;
+ *:[Aa]miga[Oo][Ss]:*:*)
+ echo "$UNAME_MACHINE"-unknown-amigaos
+ exit ;;
+ *:[Mm]orph[Oo][Ss]:*:*)
+ echo "$UNAME_MACHINE"-unknown-morphos
+ exit ;;
+ *:OS/390:*:*)
+ echo i370-ibm-openedition
+ exit ;;
+ *:z/VM:*:*)
+ echo s390-ibm-zvmoe
+ exit ;;
+ *:OS400:*:*)
+ echo powerpc-ibm-os400
+ exit ;;
+ arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+ echo arm-acorn-riscix"$UNAME_RELEASE"
+ exit ;;
+ arm*:riscos:*:*|arm*:RISCOS:*:*)
+ echo arm-unknown-riscos
+ exit ;;
+ SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+ echo hppa1.1-hitachi-hiuxmpp
+ exit ;;
+ Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+ # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+ if test "`(/bin/universe) 2>/dev/null`" = att ; then
+ echo pyramid-pyramid-sysv3
+ else
+ echo pyramid-pyramid-bsd
+ fi
+ exit ;;
+ NILE*:*:*:dcosx)
+ echo pyramid-pyramid-svr4
+ exit ;;
+ DRS?6000:unix:4.0:6*)
+ echo sparc-icl-nx6
+ exit ;;
+ DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+ case `/usr/bin/uname -p` in
+ sparc) echo sparc-icl-nx7; exit ;;
+ esac ;;
+ s390x:SunOS:*:*)
+ echo "$UNAME_MACHINE"-ibm-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4H:SunOS:5.*:*)
+ echo sparc-hal-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+ echo sparc-sun-solaris2"`echo "$UNAME_RELEASE" | sed -e 's/[^.]*//'`"
+ exit ;;
+ i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+ echo i386-pc-auroraux"$UNAME_RELEASE"
+ exit ;;
+ i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+ eval "$set_cc_for_build"
+ SUN_ARCH=i386
+ # If there is a compiler, see if it is configured for 64-bit objects.
+ # Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+ # This test works for both compilers.
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ SUN_ARCH=x86_64
+ fi
+ fi
+ echo "$SUN_ARCH"-pc-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4*:SunOS:6*:*)
+ # According to config.sub, this is the proper way to canonicalize
+ # SunOS6. Hard to guess exactly what SunOS6 will be like, but
+ # it's likely to be more like Solaris than SunOS4.
+ echo sparc-sun-solaris3"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ sun4*:SunOS:*:*)
+ case "`/usr/bin/arch -k`" in
+ Series*|S4*)
+ UNAME_RELEASE=`uname -v`
+ ;;
+ esac
+ # Japanese Language versions have a version number like `4.1.3-JL'.
+ echo sparc-sun-sunos"`echo "$UNAME_RELEASE"|sed -e 's/-/_/'`"
+ exit ;;
+ sun3*:SunOS:*:*)
+ echo m68k-sun-sunos"$UNAME_RELEASE"
+ exit ;;
+ sun*:*:4.2BSD:*)
+ UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+ test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
+ case "`/bin/arch`" in
+ sun3)
+ echo m68k-sun-sunos"$UNAME_RELEASE"
+ ;;
+ sun4)
+ echo sparc-sun-sunos"$UNAME_RELEASE"
+ ;;
+ esac
+ exit ;;
+ aushp:SunOS:*:*)
+ echo sparc-auspex-sunos"$UNAME_RELEASE"
+ exit ;;
+ # The situation for MiNT is a little confusing. The machine name
+ # can be virtually everything (everything which is not
+ # "atarist" or "atariste" at least should have a processor
+ # > m68000). The system name ranges from "MiNT" over "FreeMiNT"
+ # to the lowercase version "mint" (or "freemint"). Finally
+ # the system name "TOS" denotes a system which is actually not
+ # MiNT. But MiNT is downward compatible to TOS, so this should
+ # be no problem.
+ atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint"$UNAME_RELEASE"
+ exit ;;
+ atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+ echo m68k-atari-mint"$UNAME_RELEASE"
+ exit ;;
+ *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+ echo m68k-atari-mint"$UNAME_RELEASE"
+ exit ;;
+ milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+ echo m68k-milan-mint"$UNAME_RELEASE"
+ exit ;;
+ hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+ echo m68k-hades-mint"$UNAME_RELEASE"
+ exit ;;
+ *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+ echo m68k-unknown-mint"$UNAME_RELEASE"
+ exit ;;
+ m68k:machten:*:*)
+ echo m68k-apple-machten"$UNAME_RELEASE"
+ exit ;;
+ powerpc:machten:*:*)
+ echo powerpc-apple-machten"$UNAME_RELEASE"
+ exit ;;
+ RISC*:Mach:*:*)
+ echo mips-dec-mach_bsd4.3
+ exit ;;
+ RISC*:ULTRIX:*:*)
+ echo mips-dec-ultrix"$UNAME_RELEASE"
+ exit ;;
+ VAX*:ULTRIX*:*:*)
+ echo vax-dec-ultrix"$UNAME_RELEASE"
+ exit ;;
+ 2020:CLIX:*:* | 2430:CLIX:*:*)
+ echo clipper-intergraph-clix"$UNAME_RELEASE"
+ exit ;;
+ mips:*:*:UMIPS | mips:*:*:RISCos)
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+#ifdef __cplusplus
+#include <stdio.h> /* for printf() prototype */
+ int main (int argc, char *argv[]) {
+#else
+ int main (argc, argv) int argc; char *argv[]; {
+#endif
+ #if defined (host_mips) && defined (MIPSEB)
+ #if defined (SYSTYPE_SYSV)
+ printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_SVR4)
+ printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
+ #endif
+ #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+ printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
+ #endif
+ #endif
+ exit (-1);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
+ dummyarg=`echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+ SYSTEM_NAME=`"$dummy" "$dummyarg"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo mips-mips-riscos"$UNAME_RELEASE"
+ exit ;;
+ Motorola:PowerMAX_OS:*:*)
+ echo powerpc-motorola-powermax
+ exit ;;
+ Motorola:*:4.3:PL8-*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+ echo powerpc-harris-powermax
+ exit ;;
+ Night_Hawk:Power_UNIX:*:*)
+ echo powerpc-harris-powerunix
+ exit ;;
+ m88k:CX/UX:7*:*)
+ echo m88k-harris-cxux7
+ exit ;;
+ m88k:*:4*:R4*)
+ echo m88k-motorola-sysv4
+ exit ;;
+ m88k:*:3*:R3*)
+ echo m88k-motorola-sysv3
+ exit ;;
+ AViiON:dgux:*:*)
+ # DG/UX returns AViiON for all architectures
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ if [ "$UNAME_PROCESSOR" = mc88100 ] || [ "$UNAME_PROCESSOR" = mc88110 ]
+ then
+ if [ "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx ] || \
+ [ "$TARGET_BINARY_INTERFACE"x = x ]
+ then
+ echo m88k-dg-dgux"$UNAME_RELEASE"
+ else
+ echo m88k-dg-dguxbcs"$UNAME_RELEASE"
+ fi
+ else
+ echo i586-dg-dgux"$UNAME_RELEASE"
+ fi
+ exit ;;
+ M88*:DolphinOS:*:*) # DolphinOS (SVR3)
+ echo m88k-dolphin-sysv3
+ exit ;;
+ M88*:*:R3*:*)
+ # Delta 88k system running SVR3
+ echo m88k-motorola-sysv3
+ exit ;;
+ XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+ echo m88k-tektronix-sysv3
+ exit ;;
+ Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+ echo m68k-tektronix-bsd
+ exit ;;
+ *:IRIX*:*:*)
+ echo mips-sgi-irix"`echo "$UNAME_RELEASE"|sed -e 's/-/_/g'`"
+ exit ;;
+ ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+ echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id
+ exit ;; # Note that: echo "'`uname -s`'" gives 'AIX '
+ i*86:AIX:*:*)
+ echo i386-ibm-aix
+ exit ;;
+ ia64:AIX:*:*)
+ if [ -x /usr/bin/oslevel ] ; then
+ IBM_REV=`/usr/bin/oslevel`
+ else
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ fi
+ echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
+ exit ;;
+ *:AIX:2:3)
+ if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <sys/systemcfg.h>
+
+ main()
+ {
+ if (!__power_pc())
+ exit(1);
+ puts("powerpc-ibm-aix3.2.5");
+ exit(0);
+ }
+EOF
+ if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"`
+ then
+ echo "$SYSTEM_NAME"
+ else
+ echo rs6000-ibm-aix3.2.5
+ fi
+ elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+ echo rs6000-ibm-aix3.2.4
+ else
+ echo rs6000-ibm-aix3.2
+ fi
+ exit ;;
+ *:AIX:*:[4567])
+ IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+ if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
+ IBM_ARCH=rs6000
+ else
+ IBM_ARCH=powerpc
+ fi
+ if [ -x /usr/bin/lslpp ] ; then
+ IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+ awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+ else
+ IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
+ fi
+ echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
+ exit ;;
+ *:AIX:*:*)
+ echo rs6000-ibm-aix
+ exit ;;
+ ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
+ echo romp-ibm-bsd4.4
+ exit ;;
+ ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and
+ echo romp-ibm-bsd"$UNAME_RELEASE" # 4.3 with uname added to
+ exit ;; # report: romp-ibm BSD 4.3
+ *:BOSX:*:*)
+ echo rs6000-bull-bosx
+ exit ;;
+ DPX/2?00:B.O.S.:*:*)
+ echo m68k-bull-sysv3
+ exit ;;
+ 9000/[34]??:4.3bsd:1.*:*)
+ echo m68k-hp-bsd
+ exit ;;
+ hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+ echo m68k-hp-bsd4.4
+ exit ;;
+ 9000/[34678]??:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ case "$UNAME_MACHINE" in
+ 9000/31?) HP_ARCH=m68000 ;;
+ 9000/[34]??) HP_ARCH=m68k ;;
+ 9000/[678][0-9][0-9])
+ if [ -x /usr/bin/getconf ]; then
+ sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+ sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+ case "$sc_cpu_version" in
+ 523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+ 528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+ 532) # CPU_PA_RISC2_0
+ case "$sc_kernel_bits" in
+ 32) HP_ARCH=hppa2.0n ;;
+ 64) HP_ARCH=hppa2.0w ;;
+ '') HP_ARCH=hppa2.0 ;; # HP-UX 10.20
+ esac ;;
+ esac
+ fi
+ if [ "$HP_ARCH" = "" ]; then
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+
+ #define _HPUX_SOURCE
+ #include <stdlib.h>
+ #include <unistd.h>
+
+ int main ()
+ {
+ #if defined(_SC_KERNEL_BITS)
+ long bits = sysconf(_SC_KERNEL_BITS);
+ #endif
+ long cpu = sysconf (_SC_CPU_VERSION);
+
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+ case CPU_PA_RISC2_0:
+ #if defined(_SC_KERNEL_BITS)
+ switch (bits)
+ {
+ case 64: puts ("hppa2.0w"); break;
+ case 32: puts ("hppa2.0n"); break;
+ default: puts ("hppa2.0"); break;
+ } break;
+ #else /* !defined(_SC_KERNEL_BITS) */
+ puts ("hppa2.0"); break;
+ #endif
+ default: puts ("hppa1.0"); break;
+ }
+ exit (0);
+ }
+EOF
+ (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=`"$dummy"`
+ test -z "$HP_ARCH" && HP_ARCH=hppa
+ fi ;;
+ esac
+ if [ "$HP_ARCH" = hppa2.0w ]
+ then
+ eval "$set_cc_for_build"
+
+ # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+ # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler
+ # generating 64-bit code. GNU and HP use different nomenclature:
+ #
+ # $ CC_FOR_BUILD=cc ./config.guess
+ # => hppa2.0w-hp-hpux11.23
+ # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+ # => hppa64-hp-hpux11.23
+
+ if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+ grep -q __LP64__
+ then
+ HP_ARCH=hppa2.0w
+ else
+ HP_ARCH=hppa64
+ fi
+ fi
+ echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
+ exit ;;
+ ia64:HP-UX:*:*)
+ HPUX_REV=`echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//'`
+ echo ia64-hp-hpux"$HPUX_REV"
+ exit ;;
+ 3050*:HI-UX:*:*)
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+ #include <unistd.h>
+ int
+ main ()
+ {
+ long cpu = sysconf (_SC_CPU_VERSION);
+ /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+ true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct
+ results, however. */
+ if (CPU_IS_PA_RISC (cpu))
+ {
+ switch (cpu)
+ {
+ case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+ case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+ default: puts ("hppa-hitachi-hiuxwe2"); break;
+ }
+ }
+ else if (CPU_IS_HP_MC68K (cpu))
+ puts ("m68k-hitachi-hiuxwe2");
+ else puts ("unknown-hitachi-hiuxwe2");
+ exit (0);
+ }
+EOF
+ $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=`"$dummy"` &&
+ { echo "$SYSTEM_NAME"; exit; }
+ echo unknown-hitachi-hiuxwe2
+ exit ;;
+ 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
+ echo hppa1.1-hp-bsd
+ exit ;;
+ 9000/8??:4.3bsd:*:*)
+ echo hppa1.0-hp-bsd
+ exit ;;
+ *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+ echo hppa1.0-hp-mpeix
+ exit ;;
+ hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
+ echo hppa1.1-hp-osf
+ exit ;;
+ hp8??:OSF1:*:*)
+ echo hppa1.0-hp-osf
+ exit ;;
+ i*86:OSF1:*:*)
+ if [ -x /usr/sbin/sysversion ] ; then
+ echo "$UNAME_MACHINE"-unknown-osf1mk
+ else
+ echo "$UNAME_MACHINE"-unknown-osf1
+ fi
+ exit ;;
+ parisc*:Lites*:*:*)
+ echo hppa1.1-hp-lites
+ exit ;;
+ C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+ echo c1-convex-bsd
+ exit ;;
+ C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+ if getsysinfo -f scalar_acc
+ then echo c32-convex-bsd
+ else echo c2-convex-bsd
+ fi
+ exit ;;
+ C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+ echo c34-convex-bsd
+ exit ;;
+ C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+ echo c38-convex-bsd
+ exit ;;
+ C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+ echo c4-convex-bsd
+ exit ;;
+ CRAY*Y-MP:*:*:*)
+ echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*[A-Z]90:*:*:*)
+ echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
+ | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+ -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+ -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*TS:*:*:*)
+ echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*T3E:*:*:*)
+ echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ CRAY*SV1:*:*:*)
+ echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ *:UNICOS/mp:*:*)
+ echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
+ exit ;;
+ F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+ FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | sed -e 's/ /_/'`
+ echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ 5000:UNIX_System_V:4.*:*)
+ FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+ FUJITSU_REL=`echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+ echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+ exit ;;
+ i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+ echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
+ exit ;;
+ sparc*:BSD/OS:*:*)
+ echo sparc-unknown-bsdi"$UNAME_RELEASE"
+ exit ;;
+ *:BSD/OS:*:*)
+ echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
+ exit ;;
+ *:FreeBSD:*:*)
+ UNAME_PROCESSOR=`/usr/bin/uname -p`
+ case "$UNAME_PROCESSOR" in
+ amd64)
+ UNAME_PROCESSOR=x86_64 ;;
+ i386)
+ UNAME_PROCESSOR=i586 ;;
+ esac
+ echo "$UNAME_PROCESSOR"-unknown-freebsd"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+ exit ;;
+ i*:CYGWIN*:*)
+ echo "$UNAME_MACHINE"-pc-cygwin
+ exit ;;
+ *:MINGW64*:*)
+ echo "$UNAME_MACHINE"-pc-mingw64
+ exit ;;
+ *:MINGW*:*)
+ echo "$UNAME_MACHINE"-pc-mingw32
+ exit ;;
+ *:MSYS*:*)
+ echo "$UNAME_MACHINE"-pc-msys
+ exit ;;
+ i*:PW*:*)
+ echo "$UNAME_MACHINE"-pc-pw32
+ exit ;;
+ *:Interix*:*)
+ case "$UNAME_MACHINE" in
+ x86)
+ echo i586-pc-interix"$UNAME_RELEASE"
+ exit ;;
+ authenticamd | genuineintel | EM64T)
+ echo x86_64-unknown-interix"$UNAME_RELEASE"
+ exit ;;
+ IA64)
+ echo ia64-unknown-interix"$UNAME_RELEASE"
+ exit ;;
+ esac ;;
+ i*:UWIN*:*)
+ echo "$UNAME_MACHINE"-pc-uwin
+ exit ;;
+ amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+ echo x86_64-unknown-cygwin
+ exit ;;
+ prep*:SunOS:5.*:*)
+ echo powerpcle-unknown-solaris2"`echo "$UNAME_RELEASE"|sed -e 's/[^.]*//'`"
+ exit ;;
+ *:GNU:*:*)
+ # the GNU system
+ echo "`echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,'`-unknown-$LIBC`echo "$UNAME_RELEASE"|sed -e 's,/.*$,,'`"
+ exit ;;
+ *:GNU/*:*:*)
+ # other systems with GNU libc and userland
+ echo "$UNAME_MACHINE-unknown-`echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`-$LIBC"
+ exit ;;
+ *:Minix:*:*)
+ echo "$UNAME_MACHINE"-unknown-minix
+ exit ;;
+ aarch64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ aarch64_be:Linux:*:*)
+ UNAME_MACHINE=aarch64_be
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ alpha:Linux:*:*)
+ case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+ EV5) UNAME_MACHINE=alphaev5 ;;
+ EV56) UNAME_MACHINE=alphaev56 ;;
+ PCA56) UNAME_MACHINE=alphapca56 ;;
+ PCA57) UNAME_MACHINE=alphapca56 ;;
+ EV6) UNAME_MACHINE=alphaev6 ;;
+ EV67) UNAME_MACHINE=alphaev67 ;;
+ EV68*) UNAME_MACHINE=alphaev68 ;;
+ esac
+ objdump --private-headers /bin/sh | grep -q ld.so.1
+ if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ arc:Linux:*:* | arceb:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ arm*:Linux:*:*)
+ eval "$set_cc_for_build"
+ if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_EABI__
+ then
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ else
+ if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+ | grep -q __ARM_PCS_VFP
+ then
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
+ else
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
+ fi
+ fi
+ exit ;;
+ avr32*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ cris:Linux:*:*)
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+ exit ;;
+ crisv32:Linux:*:*)
+ echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
+ exit ;;
+ e2k:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ frv:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ hexagon:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ i*86:Linux:*:*)
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+ exit ;;
+ ia64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ k1om:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ m32r*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ m68*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ mips:Linux:*:* | mips64:Linux:*:*)
+ eval "$set_cc_for_build"
+ sed 's/^ //' << EOF > "$dummy.c"
+ #undef CPU
+ #undef ${UNAME_MACHINE}
+ #undef ${UNAME_MACHINE}el
+ #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+ CPU=${UNAME_MACHINE}el
+ #else
+ #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+ CPU=${UNAME_MACHINE}
+ #else
+ CPU=
+ #endif
+ #endif
+EOF
+ eval "`$CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU'`"
+ test "x$CPU" != x && { echo "$CPU-unknown-linux-$LIBC"; exit; }
+ ;;
+ mips64el:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ openrisc*:Linux:*:*)
+ echo or1k-unknown-linux-"$LIBC"
+ exit ;;
+ or32:Linux:*:* | or1k*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ padre:Linux:*:*)
+ echo sparc-unknown-linux-"$LIBC"
+ exit ;;
+ parisc64:Linux:*:* | hppa64:Linux:*:*)
+ echo hppa64-unknown-linux-"$LIBC"
+ exit ;;
+ parisc:Linux:*:* | hppa:Linux:*:*)
+ # Look for CPU level
+ case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+ PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
+ PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
+ *) echo hppa-unknown-linux-"$LIBC" ;;
+ esac
+ exit ;;
+ ppc64:Linux:*:*)
+ echo powerpc64-unknown-linux-"$LIBC"
+ exit ;;
+ ppc:Linux:*:*)
+ echo powerpc-unknown-linux-"$LIBC"
+ exit ;;
+ ppc64le:Linux:*:*)
+ echo powerpc64le-unknown-linux-"$LIBC"
+ exit ;;
+ ppcle:Linux:*:*)
+ echo powerpcle-unknown-linux-"$LIBC"
+ exit ;;
+ riscv32:Linux:*:* | riscv64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ s390:Linux:*:* | s390x:Linux:*:*)
+ echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
+ exit ;;
+ sh64*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ sh*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ sparc:Linux:*:* | sparc64:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ tile*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ vax:Linux:*:*)
+ echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
+ exit ;;
+ x86_64:Linux:*:*)
+ echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
+ exit ;;
+ xtensa*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+ i*86:DYNIX/ptx:4*:*)
+ # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+ # earlier versions are messed up and put the nodename in both
+ # sysname and nodename.
+ echo i386-sequent-sysv4
+ exit ;;
+ i*86:UNIX_SV:4.2MP:2.*)
+ # Unixware is an offshoot of SVR4, but it has its own version
+ # number series starting with 2...
+ # I am not positive that other SVR4 systems won't match this,
+ # I just have to hope. -- rms.
+ # Use sysv4.2uw... so that sysv4* matches it.
+ echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
+ exit ;;
+ i*86:OS/2:*:*)
+ # If we were able to find `uname', then EMX Unix compatibility
+ # is probably installed.
+ echo "$UNAME_MACHINE"-pc-os2-emx
+ exit ;;
+ i*86:XTS-300:*:STOP)
+ echo "$UNAME_MACHINE"-unknown-stop
+ exit ;;
+ i*86:atheos:*:*)
+ echo "$UNAME_MACHINE"-unknown-atheos
+ exit ;;
+ i*86:syllable:*:*)
+ echo "$UNAME_MACHINE"-pc-syllable
+ exit ;;
+ i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+ echo i386-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ i*86:*DOS:*:*)
+ echo "$UNAME_MACHINE"-pc-msdosdjgpp
+ exit ;;
+ i*86:*:4.*:*)
+ UNAME_REL=`echo "$UNAME_RELEASE" | sed 's/\/MP$//'`
+ if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+ echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
+ else
+ echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
+ fi
+ exit ;;
+ i*86:*:5:[678]*)
+ # UnixWare 7.x, OpenUNIX and OpenServer 6.
+ case `/bin/uname -X | grep "^Machine"` in
+ *486*) UNAME_MACHINE=i486 ;;
+ *Pentium) UNAME_MACHINE=i586 ;;
+ *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+ esac
+ echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}{$UNAME_VERSION}"
+ exit ;;
+ i*86:*:3.2:*)
+ if test -f /usr/options/cb.name; then
+ UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+ echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
+ elif /bin/uname -X 2>/dev/null >/dev/null ; then
+ UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+ (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+ (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+ && UNAME_MACHINE=i586
+ (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+ && UNAME_MACHINE=i686
+ (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+ && UNAME_MACHINE=i686
+ echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
+ else
+ echo "$UNAME_MACHINE"-pc-sysv32
+ fi
+ exit ;;
+ pc:*:*:*)
+ # Left here for compatibility:
+ # uname -m prints for DJGPP always 'pc', but it prints nothing about
+ # the processor, so we play safe by assuming i586.
+ # Note: whatever this is, it MUST be the same as what config.sub
+ # prints for the "djgpp" host, or else GDB configure will decide that
+ # this is a cross-build.
+ echo i586-pc-msdosdjgpp
+ exit ;;
+ Intel:Mach:3*:*)
+ echo i386-pc-mach3
+ exit ;;
+ paragon:*:*:*)
+ echo i860-intel-osf1
+ exit ;;
+ i860:*:4.*:*) # i860-SVR4
+ if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+ echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
+ else # Add other i860-SVR4 vendors below as they are discovered.
+ echo i860-unknown-sysv"$UNAME_RELEASE" # Unknown i860-SVR4
+ fi
+ exit ;;
+ mini*:CTIX:SYS*5:*)
+ # "miniframe"
+ echo m68010-convergent-sysv
+ exit ;;
+ mc68k:UNIX:SYSTEM5:3.51m)
+ echo m68k-convergent-sysv
+ exit ;;
+ M680?0:D-NIX:5.3:*)
+ echo m68k-diab-dnix
+ exit ;;
+ M68*:*:R3V[5678]*:*)
+ test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+ 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+ OS_REL=''
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4; exit; } ;;
+ NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+ OS_REL='.3'
+ test -r /etc/.relid \
+ && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+ /bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+ && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
+ /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+ && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
+ m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+ echo m68k-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ mc68030:UNIX_System_V:4.*:*)
+ echo m68k-atari-sysv4
+ exit ;;
+ TSUNAMI:LynxOS:2.*:*)
+ echo sparc-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ rs6000:LynxOS:2.*:*)
+ echo rs6000-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+ echo powerpc-unknown-lynxos"$UNAME_RELEASE"
+ exit ;;
+ SM[BE]S:UNIX_SV:*:*)
+ echo mips-dde-sysv"$UNAME_RELEASE"
+ exit ;;
+ RM*:ReliantUNIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ RM*:SINIX-*:*:*)
+ echo mips-sni-sysv4
+ exit ;;
+ *:SINIX-*:*:*)
+ if uname -p 2>/dev/null >/dev/null ; then
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ echo "$UNAME_MACHINE"-sni-sysv4
+ else
+ echo ns32k-sni-sysv
+ fi
+ exit ;;
+ PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+ # says <Richard.M.Bartel@ccMail.Census.GOV>
+ echo i586-unisys-sysv4
+ exit ;;
+ *:UNIX_System_V:4*:FTX*)
+ # From Gerald Hewes <hewes@openmarket.com>.
+ # How about differentiating between stratus architectures? -djm
+ echo hppa1.1-stratus-sysv4
+ exit ;;
+ *:*:*:FTX*)
+ # From seanf@swdc.stratus.com.
+ echo i860-stratus-sysv4
+ exit ;;
+ i*86:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo "$UNAME_MACHINE"-stratus-vos
+ exit ;;
+ *:VOS:*:*)
+ # From Paul.Green@stratus.com.
+ echo hppa1.1-stratus-vos
+ exit ;;
+ mc68*:A/UX:*:*)
+ echo m68k-apple-aux"$UNAME_RELEASE"
+ exit ;;
+ news*:NEWS-OS:6*:*)
+ echo mips-sony-newsos6
+ exit ;;
+ R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+ if [ -d /usr/nec ]; then
+ echo mips-nec-sysv"$UNAME_RELEASE"
+ else
+ echo mips-unknown-sysv"$UNAME_RELEASE"
+ fi
+ exit ;;
+ BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
+ echo powerpc-be-beos
+ exit ;;
+ BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only.
+ echo powerpc-apple-beos
+ exit ;;
+ BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
+ echo i586-pc-beos
+ exit ;;
+ BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
+ echo i586-pc-haiku
+ exit ;;
+ x86_64:Haiku:*:*)
+ echo x86_64-unknown-haiku
+ exit ;;
+ SX-4:SUPER-UX:*:*)
+ echo sx4-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-5:SUPER-UX:*:*)
+ echo sx5-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-6:SUPER-UX:*:*)
+ echo sx6-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-7:SUPER-UX:*:*)
+ echo sx7-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-8:SUPER-UX:*:*)
+ echo sx8-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-8R:SUPER-UX:*:*)
+ echo sx8r-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ SX-ACE:SUPER-UX:*:*)
+ echo sxace-nec-superux"$UNAME_RELEASE"
+ exit ;;
+ Power*:Rhapsody:*:*)
+ echo powerpc-apple-rhapsody"$UNAME_RELEASE"
+ exit ;;
+ *:Rhapsody:*:*)
+ echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
+ exit ;;
+ *:Darwin:*:*)
+ UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+ eval "$set_cc_for_build"
+ if test "$UNAME_PROCESSOR" = unknown ; then
+ UNAME_PROCESSOR=powerpc
+ fi
+ if test "`echo "$UNAME_RELEASE" | sed -e 's/\..*//'`" -le 10 ; then
+ if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+ if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_64BIT_ARCH >/dev/null
+ then
+ case $UNAME_PROCESSOR in
+ i386) UNAME_PROCESSOR=x86_64 ;;
+ powerpc) UNAME_PROCESSOR=powerpc64 ;;
+ esac
+ fi
+ # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
+ if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
+ (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+ grep IS_PPC >/dev/null
+ then
+ UNAME_PROCESSOR=powerpc
+ fi
+ fi
+ elif test "$UNAME_PROCESSOR" = i386 ; then
+ # Avoid executing cc on OS X 10.9, as it ships with a stub
+ # that puts up a graphical alert prompting to install
+ # developer tools. Any system running Mac OS X 10.7 or
+ # later (Darwin 11 and later) is required to have a 64-bit
+ # processor. This is not true of the ARM version of Darwin
+ # that Apple uses in portable devices.
+ UNAME_PROCESSOR=x86_64
+ fi
+ echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
+ exit ;;
+ *:procnto*:*:* | *:QNX:[0123456789]*:*)
+ UNAME_PROCESSOR=`uname -p`
+ if test "$UNAME_PROCESSOR" = x86; then
+ UNAME_PROCESSOR=i386
+ UNAME_MACHINE=pc
+ fi
+ echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
+ exit ;;
+ *:QNX:*:4*)
+ echo i386-pc-qnx
+ exit ;;
+ NEO-*:NONSTOP_KERNEL:*:*)
+ echo neo-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSE-*:NONSTOP_KERNEL:*:*)
+ echo nse-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSR-*:NONSTOP_KERNEL:*:*)
+ echo nsr-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSV-*:NONSTOP_KERNEL:*:*)
+ echo nsv-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ NSX-*:NONSTOP_KERNEL:*:*)
+ echo nsx-tandem-nsk"$UNAME_RELEASE"
+ exit ;;
+ *:NonStop-UX:*:*)
+ echo mips-compaq-nonstopux
+ exit ;;
+ BS2000:POSIX*:*:*)
+ echo bs2000-siemens-sysv
+ exit ;;
+ DS/*:UNIX_System_V:*:*)
+ echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
+ exit ;;
+ *:Plan9:*:*)
+ # "uname -m" is not consistent, so use $cputype instead. 386
+ # is converted to i386 for consistency with other x86
+ # operating systems.
+ if test "$cputype" = 386; then
+ UNAME_MACHINE=i386
+ else
+ UNAME_MACHINE="$cputype"
+ fi
+ echo "$UNAME_MACHINE"-unknown-plan9
+ exit ;;
+ *:TOPS-10:*:*)
+ echo pdp10-unknown-tops10
+ exit ;;
+ *:TENEX:*:*)
+ echo pdp10-unknown-tenex
+ exit ;;
+ KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+ echo pdp10-dec-tops20
+ exit ;;
+ XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+ echo pdp10-xkl-tops20
+ exit ;;
+ *:TOPS-20:*:*)
+ echo pdp10-unknown-tops20
+ exit ;;
+ *:ITS:*:*)
+ echo pdp10-unknown-its
+ exit ;;
+ SEI:*:*:SEIUX)
+ echo mips-sei-seiux"$UNAME_RELEASE"
+ exit ;;
+ *:DragonFly:*:*)
+ echo "$UNAME_MACHINE"-unknown-dragonfly"`echo "$UNAME_RELEASE"|sed -e 's/[-(].*//'`"
+ exit ;;
+ *:*VMS:*:*)
+ UNAME_MACHINE=`(uname -p) 2>/dev/null`
+ case "$UNAME_MACHINE" in
+ A*) echo alpha-dec-vms ; exit ;;
+ I*) echo ia64-dec-vms ; exit ;;
+ V*) echo vax-dec-vms ; exit ;;
+ esac ;;
+ *:XENIX:*:SysV)
+ echo i386-pc-xenix
+ exit ;;
+ i*86:skyos:*:*)
+ echo "$UNAME_MACHINE"-pc-skyos"`echo "$UNAME_RELEASE" | sed -e 's/ .*$//'`"
+ exit ;;
+ i*86:rdos:*:*)
+ echo "$UNAME_MACHINE"-pc-rdos
+ exit ;;
+ i*86:AROS:*:*)
+ echo "$UNAME_MACHINE"-pc-aros
+ exit ;;
+ x86_64:VMkernel:*:*)
+ echo "$UNAME_MACHINE"-unknown-esx
+ exit ;;
+ amd64:Isilon\ OneFS:*:*)
+ echo x86_64-unknown-onefs
+ exit ;;
+esac
+
+echo "$0: unable to guess system type" >&2
+
+case "$UNAME_MACHINE:$UNAME_SYSTEM" in
+ mips:Linux | mips64:Linux)
+ # If we got here on MIPS GNU/Linux, output extra information.
+ cat >&2 <<EOF
+
+NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
+the system type. Please install a C compiler and try again.
+EOF
+ ;;
+esac
+
+cat >&2 <<EOF
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite *all*
+copies of config.guess and config.sub with the latest versions from:
+
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+ https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo = `(hostinfo) 2>/dev/null`
+/bin/universe = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = "$UNAME_MACHINE"
+UNAME_RELEASE = "$UNAME_RELEASE"
+UNAME_SYSTEM = "$UNAME_SYSTEM"
+UNAME_VERSION = "$UNAME_VERSION"
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/lib/libpcap/libpcap/config.h b/lib/libpcap/libpcap/config.h
new file mode 100644
index 0000000..1e0aa08
--- /dev/null
+++ b/lib/libpcap/libpcap/config.h
@@ -0,0 +1,387 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if arpa/inet.h declares `ether_hostton' */
+/* #undef ARPA_INET_H_DECLARES_ETHER_HOSTTON */
+
+/* Enable optimizer debugging */
+/* #undef BDEBUG */
+
+/* Define to 1 if remote packet capture is to be supported */
+/* #undef ENABLE_REMOTE */
+
+/* define if we have the AIX getnetbyname_r() */
+/* #undef HAVE_AIX_GETNETBYNAME_R */
+
+/* define if we have the AIX getprotobyname_r() */
+/* #undef HAVE_AIX_GETPROTOBYNAME_R */
+
+/* Define to 1 if you have the `asprintf' function. */
+#define HAVE_ASPRINTF 1
+
+/* Define to 1 if you have the <dagapi.h> header file. */
+/* #undef HAVE_DAGAPI_H */
+
+/* define if you have the DAG API */
+/* #undef HAVE_DAG_API */
+
+/* define if you have dag_get_erf_types() */
+/* #undef HAVE_DAG_GET_ERF_TYPES */
+
+/* define if you have dag_get_stream_erf_types() */
+/* #undef HAVE_DAG_GET_STREAM_ERF_TYPES */
+
+/* define if you have large streams capable DAG API */
+/* #undef HAVE_DAG_LARGE_STREAMS_API */
+
+/* define if you have vdag_set_device_info() */
+/* #undef HAVE_DAG_VDAG */
+
+/* Define to 1 if you have the declaration of `ether_hostton' */
+#define HAVE_DECL_ETHER_HOSTTON 1
+
+/* Define to 1 if `dl_module_id_1' is a member of `dl_hp_ppa_info_t'. */
+/* #undef HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1 */
+
+/* Define to 1 if the system has the type `dl_passive_req_t'. */
+/* #undef HAVE_DL_PASSIVE_REQ_T */
+
+/* Define to 1 if you have the `ether_hostton' function. */
+#define HAVE_ETHER_HOSTTON 1
+
+/* Define to 1 if you have the `ffs' function. */
+#define HAVE_FFS 1
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#define HAVE_FSEEKO 1
+
+/* Define to 1 if you have the `getspnam' function. */
+/* #undef HAVE_GETSPNAM */
+
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+/* #undef HAVE_GNU_STRERROR_R */
+
+/* on HP-UX 10.20 or later */
+/* #undef HAVE_HPUX10_20_OR_LATER */
+
+/* on HP-UX 9.x */
+/* #undef HAVE_HPUX9 */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `dag' library (-ldag). */
+/* #undef HAVE_LIBDAG */
+
+/* if libdlpi exists */
+/* #undef HAVE_LIBDLPI */
+
+/* if libnl exists */
+/* #undef HAVE_LIBNL */
+
+/* if libnl exists and is version 2.x */
+/* #undef HAVE_LIBNL_2_x */
+
+/* if libnl exists and is version 3.x */
+/* #undef HAVE_LIBNL_3_x */
+
+/* libnl has NLE_FAILURE */
+/* #undef HAVE_LIBNL_NLE */
+
+/* libnl has new-style socket api */
+/* #undef HAVE_LIBNL_SOCKETS */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+/* #undef HAVE_LINUX_COMPILER_H */
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+/* #undef HAVE_LINUX_ETHTOOL_H */
+
+/* define if we have the Linux getnetbyname_r() */
+/* #undef HAVE_LINUX_GETNETBYNAME_R */
+
+/* define if we have the Linux getprotobyname_r() */
+/* #undef HAVE_LINUX_GETPROTOBYNAME_R */
+
+/* Define to 1 if you have the <linux/if_bonding.h> header file. */
+/* #undef HAVE_LINUX_IF_BONDING_H */
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+/* #undef HAVE_LINUX_NET_TSTAMP_H */
+
+/* Define to 1 if you have the <linux/socket.h> header file. */
+/* #undef HAVE_LINUX_SOCKET_H */
+
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+/* #undef HAVE_LINUX_SOCKIOS_H */
+
+/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
+/* #undef HAVE_LINUX_USBDEVICE_FS_H */
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+/* #undef HAVE_LINUX_WIRELESS_H */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the <netpacket/packet.h> header file. */
+/* #undef HAVE_NETPACKET_PACKET_H */
+
+/* Define to 1 if you have the <net/bpf.h> header file. */
+#define HAVE_NET_BPF_H 1
+
+/* Define to 1 if you have the <net/enet.h> header file. */
+/* #undef HAVE_NET_ENET_H */
+
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#define HAVE_NET_IF_MEDIA_H 1
+
+/* Define to 1 if you have the <net/nit.h> header file. */
+/* #undef HAVE_NET_NIT_H */
+
+/* Define to 1 if you have the <net/pfilt.h> header file. */
+/* #undef HAVE_NET_PFILT_H */
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+/* #undef HAVE_NET_PFVAR_H */
+
+/* Define to 1 if you have the <net/raw.h> header file. */
+/* #undef HAVE_NET_RAW_H */
+
+/* if there's an os_proto.h for this platform, to use additional prototypes */
+/* #undef HAVE_OS_PROTO_H */
+
+/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
+/* #undef HAVE_PF_NAT_THROUGH_PF_NORDR */
+
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#define HAVE_POSIX_STRERROR_R /**/
+
+/* define if you have the Septel API */
+/* #undef HAVE_SEPTEL_API */
+
+/* define if you have the Myricom SNF API */
+/* #undef HAVE_SNF_API */
+
+/* Define to 1 if you have the `snprintf' function. */
+#define HAVE_SNPRINTF 1
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#define HAVE_SOCKLEN_T 1
+
+/* On solaris */
+/* #undef HAVE_SOLARIS */
+
+/* define if we have the Solaris/IRIX getnetbyname_r() */
+/* #undef HAVE_SOLARIS_IRIX_GETNETBYNAME_R */
+
+/* define if we have the Solaris/IRIX getprotobyname_r() */
+/* #undef HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R */
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strerror_s' function. */
+/* #undef HAVE_STRERROR_S */
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strlcat' function. */
+#define HAVE_STRLCAT 1
+
+/* Define to 1 if you have the `strlcpy' function. */
+#define HAVE_STRLCPY 1
+
+/* Define to 1 if you have the `strtok_r' function. */
+#define HAVE_STRTOK_R 1
+
+/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
+#define HAVE_STRUCT_BPF_TIMEVAL 1
+
+/* Define to 1 if the system has the type `struct ether_addr'. */
+/* #undef HAVE_STRUCT_ETHER_ADDR */
+
+/* Define to 1 if `msg_control' is a member of `struct msghdr'. */
+/* #undef HAVE_STRUCT_MSGHDR_MSG_CONTROL */
+
+/* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
+/* #undef HAVE_STRUCT_MSGHDR_MSG_FLAGS */
+
+/* Define to 1 if `hci_channel' is a member of `struct sockaddr_hci'. */
+/* #undef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL */
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+/* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
+/* #undef HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI */
+
+/* Define to 1 if the system has the type `struct tpacket_stats'. */
+/* #undef HAVE_STRUCT_TPACKET_STATS */
+
+/* Define to 1 if `bRequestType' is a member of `struct
+ usbdevfs_ctrltransfer'. */
+/* #undef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE */
+
+/* Define to 1 if you have the <sys/bufmod.h> header file. */
+/* #undef HAVE_SYS_BUFMOD_H */
+
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
+/* #undef HAVE_SYS_DLPI_EXT_H */
+
+/* Define to 1 if you have the <sys/dlpi.h> header file. */
+/* #undef HAVE_SYS_DLPI_H */
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#define HAVE_SYS_IOCCOM_H 1
+
+/* Define to 1 if you have the <sys/net/nit.h> header file. */
+/* #undef HAVE_SYS_NET_NIT_H */
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#define HAVE_SYS_SOCKIO_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* define if you have the TurboCap API */
+/* #undef HAVE_TC_API */
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vasprintf' function. */
+#define HAVE_VASPRINTF 1
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#define HAVE_VSNPRINTF 1
+
+/* Define to 1 if you have the `vsyslog' function. */
+#define HAVE_VSYSLOG 1
+
+/* IPv6 */
+#define INET6 1
+
+/* if unaligned access fails */
+/* #undef LBL_ALIGN */
+
+/* path for device for USB sniffing */
+/* #undef LINUX_USB_MON_DEV */
+
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+/* #undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON */
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+/* #undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON */
+
+/* Define to 1 if net/ethernet.h declares `ether_hostton' */
+#define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+
+/* do not use protochain */
+/* #undef NO_PROTOCHAIN */
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "pcap"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "pcap 1.9.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "pcap"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.9.1"
+
+/* target host supports Bluetooth sniffing */
+/* #undef PCAP_SUPPORT_BT */
+
+/* target host supports Bluetooth Monitor */
+/* #undef PCAP_SUPPORT_BT_MONITOR */
+
+/* support D-Bus sniffing */
+/* #undef PCAP_SUPPORT_DBUS */
+
+/* target host supports netfilter sniffing */
+/* #undef PCAP_SUPPORT_NETFILTER */
+
+/* target host supports netmap */
+/* #undef PCAP_SUPPORT_NETMAP */
+
+/* use packet ring capture support on Linux if available */
+#define PCAP_SUPPORT_PACKET_RING 1
+
+/* target host supports RDMA sniffing */
+/* #undef PCAP_SUPPORT_RDMASNIFF */
+
+/* target host supports USB sniffing */
+/* #undef PCAP_SUPPORT_USB */
+
+/* include ACN support */
+/* #undef SITA */
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if strings.h declares `ffs' */
+#define STRINGS_H_DECLARES_FFS /**/
+
+/* Define to 1 if sys/ethernet.h declares `ether_hostton' */
+/* #undef SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON */
+
+/* Enable parser debugging */
+/* #undef YYDEBUG */
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+/* #undef _LARGEFILE_SOURCE */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+/* define on AIX to get certain functions */
+/* #undef _SUN */
+
+/* to handle Ultrix compilers that don't support const in prototypes */
+/* #undef const */
+
+/* Define as token for inline if inlining supported */
+#define inline inline
+
+/* on sinix */
+/* #undef sinix */
diff --git a/lib/libpcap/libpcap/config.h.in b/lib/libpcap/libpcap/config.h.in
new file mode 100644
index 0000000..94db7bb
--- /dev/null
+++ b/lib/libpcap/libpcap/config.h.in
@@ -0,0 +1,386 @@
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if arpa/inet.h declares `ether_hostton' */
+#undef ARPA_INET_H_DECLARES_ETHER_HOSTTON
+
+/* Enable optimizer debugging */
+#undef BDEBUG
+
+/* Define to 1 if remote packet capture is to be supported */
+#undef ENABLE_REMOTE
+
+/* define if we have the AIX getnetbyname_r() */
+#undef HAVE_AIX_GETNETBYNAME_R
+
+/* define if we have the AIX getprotobyname_r() */
+#undef HAVE_AIX_GETPROTOBYNAME_R
+
+/* Define to 1 if you have the `asprintf' function. */
+#undef HAVE_ASPRINTF
+
+/* Define to 1 if you have the <dagapi.h> header file. */
+#undef HAVE_DAGAPI_H
+
+/* define if you have the DAG API */
+#undef HAVE_DAG_API
+
+/* define if you have dag_get_erf_types() */
+#undef HAVE_DAG_GET_ERF_TYPES
+
+/* define if you have dag_get_stream_erf_types() */
+#undef HAVE_DAG_GET_STREAM_ERF_TYPES
+
+/* define if you have large streams capable DAG API */
+#undef HAVE_DAG_LARGE_STREAMS_API
+
+/* define if you have vdag_set_device_info() */
+#undef HAVE_DAG_VDAG
+
+/* Define to 1 if you have the declaration of `ether_hostton' */
+#undef HAVE_DECL_ETHER_HOSTTON
+
+/* Define to 1 if `dl_module_id_1' is a member of `dl_hp_ppa_info_t'. */
+#undef HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1
+
+/* Define to 1 if the system has the type `dl_passive_req_t'. */
+#undef HAVE_DL_PASSIVE_REQ_T
+
+/* Define to 1 if you have the `ether_hostton' function. */
+#undef HAVE_ETHER_HOSTTON
+
+/* Define to 1 if you have the `ffs' function. */
+#undef HAVE_FFS
+
+/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */
+#undef HAVE_FSEEKO
+
+/* Define to 1 if you have the `getspnam' function. */
+#undef HAVE_GETSPNAM
+
+/* Define to 1 if you have a GNU-style `strerror_r' function. */
+#undef HAVE_GNU_STRERROR_R
+
+/* on HP-UX 10.20 or later */
+#undef HAVE_HPUX10_20_OR_LATER
+
+/* on HP-UX 9.x */
+#undef HAVE_HPUX9
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `dag' library (-ldag). */
+#undef HAVE_LIBDAG
+
+/* if libdlpi exists */
+#undef HAVE_LIBDLPI
+
+/* if libnl exists */
+#undef HAVE_LIBNL
+
+/* if libnl exists and is version 2.x */
+#undef HAVE_LIBNL_2_x
+
+/* if libnl exists and is version 3.x */
+#undef HAVE_LIBNL_3_x
+
+/* libnl has NLE_FAILURE */
+#undef HAVE_LIBNL_NLE
+
+/* libnl has new-style socket api */
+#undef HAVE_LIBNL_SOCKETS
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if you have the <linux/compiler.h> header file. */
+#undef HAVE_LINUX_COMPILER_H
+
+/* Define to 1 if you have the <linux/ethtool.h> header file. */
+#undef HAVE_LINUX_ETHTOOL_H
+
+/* define if we have the Linux getnetbyname_r() */
+#undef HAVE_LINUX_GETNETBYNAME_R
+
+/* define if we have the Linux getprotobyname_r() */
+#undef HAVE_LINUX_GETPROTOBYNAME_R
+
+/* Define to 1 if you have the <linux/if_bonding.h> header file. */
+#undef HAVE_LINUX_IF_BONDING_H
+
+/* Define to 1 if you have the <linux/net_tstamp.h> header file. */
+#undef HAVE_LINUX_NET_TSTAMP_H
+
+/* Define to 1 if you have the <linux/socket.h> header file. */
+#undef HAVE_LINUX_SOCKET_H
+
+/* Define to 1 if you have the <linux/sockios.h> header file. */
+#undef HAVE_LINUX_SOCKIOS_H
+
+/* Define to 1 if you have the <linux/usbdevice_fs.h> header file. */
+#undef HAVE_LINUX_USBDEVICE_FS_H
+
+/* Define to 1 if you have the <linux/wireless.h> header file. */
+#undef HAVE_LINUX_WIRELESS_H
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the <netpacket/packet.h> header file. */
+#undef HAVE_NETPACKET_PACKET_H
+
+/* Define to 1 if you have the <net/bpf.h> header file. */
+#undef HAVE_NET_BPF_H
+
+/* Define to 1 if you have the <net/enet.h> header file. */
+#undef HAVE_NET_ENET_H
+
+/* Define to 1 if you have the <net/if_media.h> header file. */
+#undef HAVE_NET_IF_MEDIA_H
+
+/* Define to 1 if you have the <net/nit.h> header file. */
+#undef HAVE_NET_NIT_H
+
+/* Define to 1 if you have the <net/pfilt.h> header file. */
+#undef HAVE_NET_PFILT_H
+
+/* Define to 1 if you have the <net/pfvar.h> header file. */
+#undef HAVE_NET_PFVAR_H
+
+/* Define to 1 if you have the <net/raw.h> header file. */
+#undef HAVE_NET_RAW_H
+
+/* if there's an os_proto.h for this platform, to use additional prototypes */
+#undef HAVE_OS_PROTO_H
+
+/* define if net/pfvar.h defines PF_NAT through PF_NORDR */
+#undef HAVE_PF_NAT_THROUGH_PF_NORDR
+
+/* Define to 1 if you have a POSIX-style `strerror_r' function. */
+#undef HAVE_POSIX_STRERROR_R
+
+/* define if you have the Septel API */
+#undef HAVE_SEPTEL_API
+
+/* define if you have the Myricom SNF API */
+#undef HAVE_SNF_API
+
+/* Define to 1 if you have the `snprintf' function. */
+#undef HAVE_SNPRINTF
+
+/* Define to 1 if the system has the type `socklen_t'. */
+#undef HAVE_SOCKLEN_T
+
+/* On solaris */
+#undef HAVE_SOLARIS
+
+/* define if we have the Solaris/IRIX getnetbyname_r() */
+#undef HAVE_SOLARIS_IRIX_GETNETBYNAME_R
+
+/* define if we have the Solaris/IRIX getprotobyname_r() */
+#undef HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strerror' function. */
+#undef HAVE_STRERROR
+
+/* Define to 1 if you have the `strerror_s' function. */
+#undef HAVE_STRERROR_S
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
+/* Define to 1 if you have the `strtok_r' function. */
+#undef HAVE_STRTOK_R
+
+/* Define to 1 if the system has the type `struct BPF_TIMEVAL'. */
+#undef HAVE_STRUCT_BPF_TIMEVAL
+
+/* Define to 1 if the system has the type `struct ether_addr'. */
+#undef HAVE_STRUCT_ETHER_ADDR
+
+/* Define to 1 if `msg_control' is a member of `struct msghdr'. */
+#undef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+
+/* Define to 1 if `msg_flags' is a member of `struct msghdr'. */
+#undef HAVE_STRUCT_MSGHDR_MSG_FLAGS
+
+/* Define to 1 if `hci_channel' is a member of `struct sockaddr_hci'. */
+#undef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL
+
+/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */
+#undef HAVE_STRUCT_SOCKADDR_SA_LEN
+
+/* Define to 1 if the system has the type `struct sockaddr_storage'. */
+#undef HAVE_STRUCT_SOCKADDR_STORAGE
+
+/* Define to 1 if `tp_vlan_tci' is a member of `struct tpacket_auxdata'. */
+#undef HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI
+
+/* Define to 1 if the system has the type `struct tpacket_stats'. */
+#undef HAVE_STRUCT_TPACKET_STATS
+
+/* Define to 1 if `bRequestType' is a member of `struct
+ usbdevfs_ctrltransfer'. */
+#undef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+
+/* Define to 1 if you have the <sys/bufmod.h> header file. */
+#undef HAVE_SYS_BUFMOD_H
+
+/* Define to 1 if you have the <sys/dlpi_ext.h> header file. */
+#undef HAVE_SYS_DLPI_EXT_H
+
+/* Define to 1 if you have the <sys/dlpi.h> header file. */
+#undef HAVE_SYS_DLPI_H
+
+/* Define to 1 if you have the <sys/ioccom.h> header file. */
+#undef HAVE_SYS_IOCCOM_H
+
+/* Define to 1 if you have the <sys/net/nit.h> header file. */
+#undef HAVE_SYS_NET_NIT_H
+
+/* Define to 1 if you have the <sys/sockio.h> header file. */
+#undef HAVE_SYS_SOCKIO_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* define if you have the TurboCap API */
+#undef HAVE_TC_API
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to 1 if you have the `vasprintf' function. */
+#undef HAVE_VASPRINTF
+
+/* Define to 1 if you have the `vsnprintf' function. */
+#undef HAVE_VSNPRINTF
+
+/* Define to 1 if you have the `vsyslog' function. */
+#undef HAVE_VSYSLOG
+
+/* IPv6 */
+#undef INET6
+
+/* if unaligned access fails */
+#undef LBL_ALIGN
+
+/* path for device for USB sniffing */
+#undef LINUX_USB_MON_DEV
+
+/* Define to 1 if netinet/ether.h declares `ether_hostton' */
+#undef NETINET_ETHER_H_DECLARES_ETHER_HOSTTON
+
+/* Define to 1 if netinet/if_ether.h declares `ether_hostton' */
+#undef NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON
+
+/* Define to 1 if net/ethernet.h declares `ether_hostton' */
+#undef NET_ETHERNET_H_DECLARES_ETHER_HOSTTON
+
+/* do not use protochain */
+#undef NO_PROTOCHAIN
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* target host supports Bluetooth sniffing */
+#undef PCAP_SUPPORT_BT
+
+/* target host supports Bluetooth Monitor */
+#undef PCAP_SUPPORT_BT_MONITOR
+
+/* support D-Bus sniffing */
+#undef PCAP_SUPPORT_DBUS
+
+/* target host supports netfilter sniffing */
+#undef PCAP_SUPPORT_NETFILTER
+
+/* target host supports netmap */
+#undef PCAP_SUPPORT_NETMAP
+
+/* use packet ring capture support on Linux if available */
+#undef PCAP_SUPPORT_PACKET_RING
+
+/* target host supports RDMA sniffing */
+#undef PCAP_SUPPORT_RDMASNIFF
+
+/* target host supports USB sniffing */
+#undef PCAP_SUPPORT_USB
+
+/* include ACN support */
+#undef SITA
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define to 1 if strings.h declares `ffs' */
+#undef STRINGS_H_DECLARES_FFS
+
+/* Define to 1 if sys/ethernet.h declares `ether_hostton' */
+#undef SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON
+
+/* Enable parser debugging */
+#undef YYDEBUG
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+ `char[]'. */
+#undef YYTEXT_POINTER
+
+/* Enable large inode numbers on Mac OS X 10.5. */
+#ifndef _DARWIN_USE_64_BIT_INODE
+# define _DARWIN_USE_64_BIT_INODE 1
+#endif
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+#undef _FILE_OFFSET_BITS
+
+/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */
+#undef _LARGEFILE_SOURCE
+
+/* Define for large files, on AIX-style hosts. */
+#undef _LARGE_FILES
+
+/* define on AIX to get certain functions */
+#undef _SUN
+
+/* to handle Ultrix compilers that don't support const in prototypes */
+#undef const
+
+/* Define as token for inline if inlining supported */
+#undef inline
+
+/* on sinix */
+#undef sinix
diff --git a/lib/libpcap/libpcap/config.log b/lib/libpcap/libpcap/config.log
new file mode 100644
index 0000000..a851854
--- /dev/null
+++ b/lib/libpcap/libpcap/config.log
@@ -0,0 +1,6539 @@
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by pcap configure 1.9.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ ./configure
+
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = lubet1.local
+uname -m = x86_64
+uname -r = 19.0.0
+uname -s = Darwin
+uname -v = Darwin Kernel Version 19.0.0: Wed Sep 25 20:18:50 PDT 2019; root:xnu-6153.11.26~2/DEVELOPMENT_X86_64
+
+/usr/bin/uname -p = i386
+/bin/uname -X = unknown
+
+/bin/arch = unknown
+/usr/bin/arch -k = unknown
+/usr/convex/getsysinfo = unknown
+/usr/bin/hostinfo = Mach kernel version:
+ Darwin Kernel Version 19.0.0: Wed Sep 25 20:18:50 PDT 2019; root:xnu-6153.11.26~2/DEVELOPMENT_X86_64
+Kernel configured for up to 8 processors.
+4 processors are physically available.
+8 processors are logically available.
+Processor type: x86_64h (Intel x86-64h Haswell)
+Processors active: 0 1 2 3 4 5 6 7
+Primary memory available: 16.00 gigabytes
+Default processor set: 475 tasks, 1846 threads, 8 processors
+Load average: 1.91, Mach factor: 6.08
+/bin/machine = unknown
+/usr/bin/oslevel = unknown
+/bin/universe = unknown
+
+PATH: /opt/local/bin
+PATH: /opt/local/sbin
+PATH: /Users/local/bin
+PATH: /usr/local/bin
+PATH: /usr/bin
+PATH: /bin
+PATH: /usr/sbin
+PATH: /sbin
+PATH: /Library/Apple/usr/bin
+PATH: /Library/Apple/bin
+PATH: /opt/appleinternal/bin
+PATH: /opt/apple/bin
+PATH: /opt/xbs/bin
+PATH: /opt/X11/bin
+PATH: /Applications/Wireshark.app/Contents/MacOS
+PATH: ~/Library/Application Support/PurpleSerf/purpleserf/bin
+PATH: ~/Library/Python/2.7/bin
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+configure:2446: checking build system type
+configure:2460: result: x86_64-apple-darwin19.0.0
+configure:2480: checking host system type
+configure:2493: result: x86_64-apple-darwin19.0.0
+configure:2513: checking target system type
+configure:2526: result: x86_64-apple-darwin19.0.0
+configure:2678: checking for gcc
+configure:2694: found /usr/bin/gcc
+configure:2705: result: gcc
+configure:2934: checking for C compiler version
+configure:2943: gcc --version >&5
+Apple clang version 11.0.0 (clang-1100.0.32.5)
+Target: x86_64-apple-darwin19.0.0
+Thread model: posix
+InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
+Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include/c++/4.2.1
+configure:2954: $? = 0
+configure:2943: gcc -v >&5
+Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include/c++/4.2.1
+Apple clang version 11.0.0 (clang-1100.0.32.5)
+Target: x86_64-apple-darwin19.0.0
+Thread model: posix
+InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
+configure:2954: $? = 0
+configure:2943: gcc -V >&5
+clang: error: unsupported option '-V -Wno-framework-include-private-from-public'
+clang: error: no input files
+configure:2954: $? = 1
+configure:2943: gcc -qversion >&5
+clang: error: unknown argument '-qversion', did you mean '--version'?
+clang: error: no input files
+configure:2954: $? = 1
+configure:2974: checking whether the C compiler works
+configure:2996: gcc conftest.c >&5
+configure:3000: $? = 0
+configure:3048: result: yes
+configure:3051: checking for C compiler default output file name
+configure:3053: result: a.out
+configure:3059: checking for suffix of executables
+configure:3066: gcc -o conftest conftest.c >&5
+configure:3070: $? = 0
+configure:3092: result:
+configure:3114: checking whether we are cross compiling
+configure:3122: gcc -o conftest conftest.c >&5
+configure:3126: $? = 0
+configure:3133: ./conftest
+configure:3137: $? = 0
+configure:3152: result: no
+configure:3157: checking for suffix of object files
+configure:3179: gcc -c conftest.c >&5
+configure:3183: $? = 0
+configure:3204: result: o
+configure:3208: checking whether we are using the GNU C compiler
+configure:3227: gcc -c conftest.c >&5
+configure:3227: $? = 0
+configure:3236: result: yes
+configure:3245: checking whether gcc accepts -g
+configure:3265: gcc -c -g conftest.c >&5
+configure:3265: $? = 0
+configure:3306: result: yes
+configure:3323: checking for gcc option to accept ISO C89
+configure:3386: gcc -c -g -O2 conftest.c >&5
+configure:3386: $? = 0
+configure:3399: result: none needed
+configure:3419: checking for gcc option to accept ISO C99
+configure:3568: gcc -c -g -O2 conftest.c >&5
+configure:3568: $? = 0
+configure:3581: result: none needed
+configure:3617: checking whether the compiler supports the -fvisibility=hidden option
+configure:3643: gcc -c -g -O2 -Werror -fvisibility=hidden conftest.c >&5
+configure:3643: $? = 0
+configure:3645: result: yes
+configure:4147: checking for inline
+configure:4183: gcc -c -fvisibility=hidden conftest.c >&5
+configure:4183: $? = 0
+configure:4198: result: inline
+configure:4220: checking for special C compiler options needed for large files
+configure:4265: result: no
+configure:4271: checking for _FILE_OFFSET_BITS value needed for large files
+configure:4296: gcc -c -g -O2 conftest.c >&5
+configure:4296: $? = 0
+configure:4328: result: no
+configure:4413: checking for _LARGEFILE_SOURCE value needed for large files
+configure:4432: gcc -o conftest -g -O2 conftest.c >&5
+configure:4432: $? = 0
+configure:4460: result: no
+configure:4487: checking how to run the C preprocessor
+configure:4518: gcc -E conftest.c
+configure:4518: $? = 0
+configure:4532: gcc -E conftest.c
+conftest.c:11:10: fatal error: 'ac_nonexistent.h' file not found
+#include <ac_nonexistent.h>
+ ^~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:4532: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:4557: result: gcc -E
+configure:4577: gcc -E conftest.c
+configure:4577: $? = 0
+configure:4591: gcc -E conftest.c
+conftest.c:11:10: fatal error: 'ac_nonexistent.h' file not found
+#include <ac_nonexistent.h>
+ ^~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:4591: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:4620: checking for grep that handles long lines and -e
+configure:4678: result: /usr/bin/grep
+configure:4683: checking for egrep
+configure:4745: result: /usr/bin/grep -E
+configure:4750: checking for ANSI C header files
+configure:4770: gcc -c -g -O2 conftest.c >&5
+configure:4770: $? = 0
+configure:4843: gcc -o conftest -g -O2 conftest.c >&5
+configure:4843: $? = 0
+configure:4843: ./conftest
+configure:4843: $? = 0
+configure:4854: result: yes
+configure:4867: checking for sys/types.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for sys/stat.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for stdlib.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for string.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for memory.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for strings.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for inttypes.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for stdint.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4867: checking for unistd.h
+configure:4867: gcc -c -g -O2 conftest.c >&5
+configure:4867: $? = 0
+configure:4867: result: yes
+configure:4882: checking sys/ioccom.h usability
+configure:4882: gcc -c -g -O2 conftest.c >&5
+configure:4882: $? = 0
+configure:4882: result: yes
+configure:4882: checking sys/ioccom.h presence
+configure:4882: gcc -E conftest.c
+configure:4882: $? = 0
+configure:4882: result: yes
+configure:4882: checking for sys/ioccom.h
+configure:4882: result: yes
+configure:4882: checking sys/sockio.h usability
+configure:4882: gcc -c -g -O2 conftest.c >&5
+configure:4882: $? = 0
+configure:4882: result: yes
+configure:4882: checking sys/sockio.h presence
+configure:4882: gcc -E conftest.c
+configure:4882: $? = 0
+configure:4882: result: yes
+configure:4882: checking for sys/sockio.h
+configure:4882: result: yes
+configure:4882: checking limits.h usability
+configure:4882: gcc -c -g -O2 conftest.c >&5
+configure:4882: $? = 0
+configure:4882: result: yes
+configure:4882: checking limits.h presence
+configure:4882: gcc -E conftest.c
+configure:4882: $? = 0
+configure:4882: result: yes
+configure:4882: checking for limits.h
+configure:4882: result: yes
+configure:4894: checking netpacket/packet.h usability
+configure:4894: gcc -c -g -O2 conftest.c >&5
+conftest.c:57:10: fatal error: 'netpacket/packet.h' file not found
+#include <netpacket/packet.h>
+ ^~~~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:4894: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <netpacket/packet.h>
+configure:4894: result: no
+configure:4894: checking netpacket/packet.h presence
+configure:4894: gcc -E conftest.c
+conftest.c:24:10: fatal error: 'netpacket/packet.h' file not found
+#include <netpacket/packet.h>
+ ^~~~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:4894: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| /* end confdefs.h. */
+| #include <netpacket/packet.h>
+configure:4894: result: no
+configure:4894: checking for netpacket/packet.h
+configure:4894: result: no
+configure:4906: checking for net/pfvar.h
+configure:4906: gcc -c -g -O2 conftest.c >&5
+conftest.c:28:10: fatal error: 'net/pfvar.h' file not found
+#include <net/pfvar.h>
+ ^~~~~~~~~~~~~
+1 error generated.
+configure:4906: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| /* end confdefs.h. */
+| #include <sys/types.h>
+| #include <sys/socket.h>
+| #include <net/if.h>
+|
+| #include <net/pfvar.h>
+configure:4906: result: no
+configure:4977: checking for ANSI ioctl definitions
+configure:5005: gcc -c -g -O2 conftest.c >&5
+conftest.c:37:9: warning: no case matching constant switch condition '0'
+switch (0) {
+ ^
+1 warning generated.
+configure:5005: $? = 0
+configure:5013: result: yes
+configure:5024: checking for strerror
+configure:5024: gcc -o conftest -g -O2 conftest.c >&5
+conftest.c:47:6: warning: incompatible redeclaration of library function 'strerror' [-Wincompatible-library-redeclaration]
+char strerror ();
+ ^
+conftest.c:47:6: note: 'strerror' is a builtin with type 'char *(int)'
+1 warning generated.
+configure:5024: $? = 0
+configure:5024: result: yes
+configure:5033: checking for strerror_r
+configure:5033: gcc -o conftest -g -O2 conftest.c >&5
+configure:5033: $? = 0
+configure:5033: result: yes
+configure:5040: checking whether strerror_r is GNU-style
+configure:5059: gcc -c -g -O2 conftest.c >&5
+conftest.c:30:14: error: conflicting types for 'strerror_r'
+extern char *strerror_r(int, char *, size_t);
+ ^
+/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.15.sdk/usr/include/string.h:116:6: note: previous declaration is here
+int strerror_r(int __errnum, char *__strerrbuf, size_t __buflen);
+ ^
+1 error generated.
+configure:5059: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| /* end confdefs.h. */
+|
+| #define _GNU_SOURCE
+| #include <string.h>
+|
+| /* Define it GNU-style; that will cause an error if it's not GNU-style */
+| extern char *strerror_r(int, char *, size_t);
+|
+| int
+| main(void)
+| {
+| return 0;
+| }
+|
+|
+configure:5070: result: no
+configure:5104: checking for vsyslog
+configure:5104: gcc -o conftest -g -O2 conftest.c >&5
+configure:5104: $? = 0
+configure:5104: result: yes
+configure:5140: checking for vsnprintf
+configure:5140: gcc -o conftest -g -O2 conftest.c >&5
+conftest.c:50:6: warning: incompatible redeclaration of library function 'vsnprintf' [-Wincompatible-library-redeclaration]
+char vsnprintf ();
+ ^
+conftest.c:50:6: note: 'vsnprintf' is a builtin with type 'int (char *, unsigned long, const char *, struct __va_list_tag *)'
+1 warning generated.
+configure:5140: $? = 0
+configure:5140: result: yes
+configure:5140: checking for snprintf
+configure:5140: gcc -o conftest -g -O2 conftest.c >&5
+conftest.c:51:6: warning: incompatible redeclaration of library function 'snprintf' [-Wincompatible-library-redeclaration]
+char snprintf ();
+ ^
+conftest.c:51:6: note: 'snprintf' is a builtin with type 'int (char *, unsigned long, const char *, ...)'
+1 warning generated.
+configure:5140: $? = 0
+configure:5140: result: yes
+configure:5155: checking for vasprintf
+configure:5155: gcc -o conftest -g -O2 conftest.c >&5
+conftest.c:63:19: warning: format string missing [-Wformat]
+return vasprintf ();
+ ~~~~~~~~~ ^
+1 warning generated.
+configure:5155: $? = 0
+configure:5155: result: yes
+configure:5155: checking for asprintf
+configure:5155: gcc -o conftest -g -O2 conftest.c >&5
+conftest.c:64:18: warning: format string missing [-Wformat]
+return asprintf ();
+ ~~~~~~~~ ^
+1 warning generated.
+configure:5155: $? = 0
+configure:5155: result: yes
+configure:5194: checking for strlcat
+configure:5194: gcc -o conftest -g -O2 conftest.c >&5
+conftest.c:54:6: warning: incompatible redeclaration of library function 'strlcat' [-Wincompatible-library-redeclaration]
+char strlcat ();
+ ^
+conftest.c:54:6: note: 'strlcat' is a builtin with type 'unsigned long (char *, const char *, unsigned long)'
+1 warning generated.
+configure:5194: $? = 0
+configure:5194: result: yes
+configure:5217: checking for strlcpy
+configure:5217: gcc -o conftest -g -O2 conftest.c >&5
+conftest.c:55:6: warning: incompatible redeclaration of library function 'strlcpy' [-Wincompatible-library-redeclaration]
+char strlcpy ();
+ ^
+conftest.c:55:6: note: 'strlcpy' is a builtin with type 'unsigned long (char *, const char *, unsigned long)'
+1 warning generated.
+configure:5217: $? = 0
+configure:5217: result: yes
+configure:5240: checking for strtok_r
+configure:5240: gcc -o conftest -g -O2 conftest.c >&5
+configure:5240: $? = 0
+configure:5240: result: yes
+configure:5265: checking for ffs
+configure:5265: gcc -o conftest -g -O2 conftest.c >&5
+configure:5265: $? = 0
+configure:5265: result: yes
+configure:5281: checking whether ffs is declared
+configure:5281: gcc -c -g -O2 conftest.c >&5
+configure:5281: $? = 0
+configure:5281: result: yes
+configure:5304: checking for getaddrinfo
+configure:5304: gcc -o conftest -g -O2 conftest.c >&5
+configure:5304: $? = 0
+configure:5304: result: yes
+configure:5419: checking for library containing putmsg
+configure:5450: gcc -o conftest -g -O2 conftest.c >&5
+Undefined symbols for architecture x86_64:
+ "_putmsg", referenced from:
+ _main in conftest-bbb895.o
+ld: symbol(s) not found for architecture x86_64
+clang: error: linker command failed with exit code 1 (use -v to see invocation)
+configure:5450: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char putmsg ();
+| int
+| main ()
+| {
+| return putmsg ();
+| ;
+| return 0;
+| }
+configure:5450: gcc -o conftest -g -O2 conftest.c -lstr >&5
+ld: library not found for -lstr
+clang: error: linker command failed with exit code 1 (use -v to see invocation)
+configure:5450: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char putmsg ();
+| int
+| main ()
+| {
+| return putmsg ();
+| ;
+| return 0;
+| }
+configure:5467: result: no
+configure:5490: checking whether getnetbyname_r is declared
+configure:5490: gcc -c -g -O2 conftest.c >&5
+conftest.c:45:10: error: use of undeclared identifier 'getnetbyname_r'
+ (void) getnetbyname_r;
+ ^
+1 error generated.
+configure:5490: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| /* end confdefs.h. */
+| #include <netdb.h>
+|
+| int
+| main ()
+| {
+| #ifndef getnetbyname_r
+| #ifdef __cplusplus
+| (void) getnetbyname_r;
+| #else
+| (void) getnetbyname_r;
+| #endif
+| #endif
+|
+| ;
+| return 0;
+| }
+configure:5490: result: no
+configure:5617: checking whether getprotobyname_r is declared
+configure:5617: gcc -c -g -O2 conftest.c >&5
+conftest.c:45:10: error: use of undeclared identifier 'getprotobyname_r'
+ (void) getprotobyname_r;
+ ^
+1 error generated.
+configure:5617: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| /* end confdefs.h. */
+| #include <netdb.h>
+|
+| int
+| main ()
+| {
+| #ifndef getprotobyname_r
+| #ifdef __cplusplus
+| (void) getprotobyname_r;
+| #else
+| (void) getprotobyname_r;
+| #endif
+| #endif
+|
+| ;
+| return 0;
+| }
+configure:5617: result: no
+configure:5744: checking for ether_hostton
+configure:5744: gcc -o conftest -g -O2 conftest.c >&5
+configure:5744: $? = 0
+configure:5744: result: yes
+configure:5760: checking whether ether_hostton is declared
+configure:5760: gcc -c -g -O2 conftest.c >&5
+configure:5760: $? = 0
+configure:5760: result: yes
+configure:5935: checking pthread.h usability
+configure:5935: gcc -c -g -O2 conftest.c >&5
+configure:5935: $? = 0
+configure:5935: result: yes
+configure:5935: checking pthread.h presence
+configure:5935: gcc -E conftest.c
+configure:5935: $? = 0
+configure:5935: result: yes
+configure:5935: checking for pthread.h
+configure:5935: result: yes
+configure:5942: checking for pthread_create
+configure:5942: gcc -o conftest -g -O2 conftest.c >&5
+configure:5942: $? = 0
+configure:5942: result: yes
+configure:6076: checking if --disable-protochain option is specified
+configure:6094: result: enabled
+configure:6138: checking net/bpf.h usability
+configure:6138: gcc -c -g -O2 conftest.c >&5
+configure:6138: $? = 0
+configure:6138: result: yes
+configure:6138: checking net/bpf.h presence
+configure:6138: gcc -E conftest.c
+configure:6138: $? = 0
+configure:6138: result: yes
+configure:6138: checking for net/bpf.h
+configure:6138: result: yes
+configure:6181: checking if net/bpf.h defines BIOCSETIF
+configure:6207: gcc -c -g -O2 conftest.c >&5
+configure:6207: $? = 0
+configure:6215: result: yes
+configure:6221: checking net/pfilt.h usability
+configure:6221: gcc -c -g -O2 conftest.c >&5
+conftest.c:73:10: fatal error: 'net/pfilt.h' file not found
+#include <net/pfilt.h>
+ ^~~~~~~~~~~~~
+1 error generated.
+configure:6221: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <net/pfilt.h>
+configure:6221: result: no
+configure:6221: checking net/pfilt.h presence
+configure:6221: gcc -E conftest.c
+conftest.c:40:10: fatal error: 'net/pfilt.h' file not found
+#include <net/pfilt.h>
+ ^~~~~~~~~~~~~
+1 error generated.
+configure:6221: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <net/pfilt.h>
+configure:6221: result: no
+configure:6221: checking for net/pfilt.h
+configure:6221: result: no
+configure:6221: checking net/enet.h usability
+configure:6221: gcc -c -g -O2 conftest.c >&5
+conftest.c:73:10: fatal error: 'net/enet.h' file not found
+#include <net/enet.h>
+ ^~~~~~~~~~~~
+1 error generated.
+configure:6221: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <net/enet.h>
+configure:6221: result: no
+configure:6221: checking net/enet.h presence
+configure:6221: gcc -E conftest.c
+conftest.c:40:10: fatal error: 'net/enet.h' file not found
+#include <net/enet.h>
+ ^~~~~~~~~~~~
+1 error generated.
+configure:6221: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <net/enet.h>
+configure:6221: result: no
+configure:6221: checking for net/enet.h
+configure:6221: result: no
+configure:6234: checking net/nit.h usability
+configure:6234: gcc -c -g -O2 conftest.c >&5
+conftest.c:73:10: fatal error: 'net/nit.h' file not found
+#include <net/nit.h>
+ ^~~~~~~~~~~
+1 error generated.
+configure:6234: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <net/nit.h>
+configure:6234: result: no
+configure:6234: checking net/nit.h presence
+configure:6234: gcc -E conftest.c
+conftest.c:40:10: fatal error: 'net/nit.h' file not found
+#include <net/nit.h>
+ ^~~~~~~~~~~
+1 error generated.
+configure:6234: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <net/nit.h>
+configure:6234: result: no
+configure:6234: checking for net/nit.h
+configure:6234: result: no
+configure:6234: checking sys/net/nit.h usability
+configure:6234: gcc -c -g -O2 conftest.c >&5
+conftest.c:73:10: fatal error: 'sys/net/nit.h' file not found
+#include <sys/net/nit.h>
+ ^~~~~~~~~~~~~~~
+1 error generated.
+configure:6234: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/net/nit.h>
+configure:6234: result: no
+configure:6234: checking sys/net/nit.h presence
+configure:6234: gcc -E conftest.c
+conftest.c:40:10: fatal error: 'sys/net/nit.h' file not found
+#include <sys/net/nit.h>
+ ^~~~~~~~~~~~~~~
+1 error generated.
+configure:6234: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <sys/net/nit.h>
+configure:6234: result: no
+configure:6234: checking for sys/net/nit.h
+configure:6234: result: no
+configure:6247: checking linux/socket.h usability
+configure:6247: gcc -c -g -O2 conftest.c >&5
+conftest.c:73:10: fatal error: 'linux/socket.h' file not found
+#include <linux/socket.h>
+ ^~~~~~~~~~~~~~~~
+1 error generated.
+configure:6247: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <linux/socket.h>
+configure:6247: result: no
+configure:6247: checking linux/socket.h presence
+configure:6247: gcc -E conftest.c
+conftest.c:40:10: fatal error: 'linux/socket.h' file not found
+#include <linux/socket.h>
+ ^~~~~~~~~~~~~~~~
+1 error generated.
+configure:6247: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <linux/socket.h>
+configure:6247: result: no
+configure:6247: checking for linux/socket.h
+configure:6247: result: no
+configure:6247: checking net/raw.h usability
+configure:6247: gcc -c -g -O2 conftest.c >&5
+conftest.c:73:10: fatal error: 'net/raw.h' file not found
+#include <net/raw.h>
+ ^~~~~~~~~~~
+1 error generated.
+configure:6247: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <net/raw.h>
+configure:6247: result: no
+configure:6247: checking net/raw.h presence
+configure:6247: gcc -E conftest.c
+conftest.c:40:10: fatal error: 'net/raw.h' file not found
+#include <net/raw.h>
+ ^~~~~~~~~~~
+1 error generated.
+configure:6247: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <net/raw.h>
+configure:6247: result: no
+configure:6247: checking for net/raw.h
+configure:6247: result: no
+configure:6247: checking sys/dlpi.h usability
+configure:6247: gcc -c -g -O2 conftest.c >&5
+conftest.c:73:10: fatal error: 'sys/dlpi.h' file not found
+#include <sys/dlpi.h>
+ ^~~~~~~~~~~~
+1 error generated.
+configure:6247: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/dlpi.h>
+configure:6247: result: no
+configure:6247: checking sys/dlpi.h presence
+configure:6247: gcc -E conftest.c
+conftest.c:40:10: fatal error: 'sys/dlpi.h' file not found
+#include <sys/dlpi.h>
+ ^~~~~~~~~~~~
+1 error generated.
+configure:6247: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| /* end confdefs.h. */
+| #include <sys/dlpi.h>
+configure:6247: result: no
+configure:6247: checking for sys/dlpi.h
+configure:6247: result: no
+configure:6329: checking packet capture type
+configure:6331: result: bpf
+configure:6797: checking net/if_media.h usability
+configure:6797: gcc -c -g -O2 conftest.c >&5
+configure:6797: $? = 0
+configure:6797: result: yes
+configure:6797: checking net/if_media.h presence
+configure:6797: gcc -E conftest.c
+configure:6797: $? = 0
+configure:6797: result: yes
+configure:6797: checking for net/if_media.h
+configure:6797: result: yes
+configure:6811: checking for struct BPF_TIMEVAL
+configure:6811: gcc -c -g -O2 conftest.c >&5
+configure:6811: $? = 0
+configure:6811: gcc -c -g -O2 conftest.c >&5
+conftest.c:53:33: error: expected expression
+if (sizeof ((struct BPF_TIMEVAL)))
+ ^
+1 error generated.
+configure:6811: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| /* end confdefs.h. */
+|
+| #include <sys/types.h>
+| #include <sys/ioctl.h>
+| #ifdef HAVE_SYS_IOCCOM_H
+| #include <sys/ioccom.h>
+| #endif
+| #include <net/bpf.h>
+|
+|
+| int
+| main ()
+| {
+| if (sizeof ((struct BPF_TIMEVAL)))
+| return 0;
+| ;
+| return 0;
+| }
+configure:6811: result: yes
+configure:6868: checking for getifaddrs
+configure:6868: gcc -o conftest -g -O2 conftest.c >&5
+configure:6868: $? = 0
+configure:6868: result: yes
+configure:6875: checking ifaddrs.h usability
+configure:6875: gcc -c -g -O2 conftest.c >&5
+configure:6875: $? = 0
+configure:6875: result: yes
+configure:6875: checking ifaddrs.h presence
+configure:6875: gcc -E conftest.c
+configure:6875: $? = 0
+configure:6875: result: yes
+configure:6875: checking for ifaddrs.h
+configure:6875: result: yes
+configure:6979: no hardware timestamp support implemented for darwin19.0.0
+configure:7002: checking for socklen_t
+configure:7002: gcc -c -g -O2 conftest.c >&5
+configure:7002: $? = 0
+configure:7002: gcc -c -g -O2 conftest.c >&5
+conftest.c:51:24: error: expected expression
+if (sizeof ((socklen_t)))
+ ^
+1 error generated.
+configure:7002: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| /* end confdefs.h. */
+|
+| #include <sys/types.h>
+| #include <sys/socket.h>
+|
+|
+| int
+| main ()
+| {
+| if (sizeof ((socklen_t)))
+| return 0;
+| ;
+| return 0;
+| }
+configure:7002: result: yes
+configure:7114: checking dagapi.h usability
+configure:7114: gcc -c -g -O2 conftest.c >&5
+conftest.c:78:10: fatal error: 'dagapi.h' file not found
+#include <dagapi.h>
+ ^~~~~~~~~~
+1 error generated.
+configure:7114: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <dagapi.h>
+configure:7114: result: no
+configure:7114: checking dagapi.h presence
+configure:7114: gcc -E conftest.c
+conftest.c:45:10: fatal error: 'dagapi.h' file not found
+#include <dagapi.h>
+ ^~~~~~~~~~
+1 error generated.
+configure:7114: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| /* end confdefs.h. */
+| #include <dagapi.h>
+configure:7114: result: no
+configure:7114: checking for dagapi.h
+configure:7114: result: no
+configure:7436: checking whether we have Septel API headers
+configure:7467: result: no
+configure:7547: checking whether we have Myricom Sniffer API
+configure:7629: result: no
+configure:7682: checking whether TurboCap is supported
+configure:7710: gcc -c -g -O2 conftest.c >&5
+conftest.c:46:15: fatal error: 'TcApi.h' file not found
+ #include <TcApi.h>
+ ^~~~~~~~~
+1 error generated.
+configure:7710: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| /* end confdefs.h. */
+|
+| #include <TcApi.h>
+|
+| int
+| main ()
+| {
+|
+| TC_INSTANCE a; TC_PORT b; TC_BOARD c;
+| TC_INSTANCE i;
+| (void)TcInstanceCreateByName("foo", &i);
+|
+| ;
+| return 0;
+| }
+configure:7728: result: no
+configure:7738: checking whether to enable remote packet capture
+configure:7879: result: no
+configure:7884: checking whether to build optimizer debugging code
+configure:7896: result: no
+configure:7899: checking whether to build parser debugging code
+configure:7911: result: no
+configure:7921: checking for flex
+configure:7937: found /usr/bin/flex
+configure:7948: result: flex
+configure:7986: flex conftest.l
+configure:7990: $? = 0
+configure:7992: checking lex output file root
+configure:8006: result: lex.yy
+configure:8011: checking lex library
+configure:8025: gcc -o conftest -g -O2 conftest.c >&5
+Undefined symbols for architecture x86_64:
+ "_yywrap", referenced from:
+ _yylex in conftest-1382f7.o
+ _main in conftest-1382f7.o
+ld: symbol(s) not found for architecture x86_64
+clang: error: linker command failed with exit code 1 (use -v to see invocation)
+configure:8025: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| /* end confdefs.h. */
+|
+| #line 3 "lex.yy.c"
+|
+| #define YY_INT_ALIGNED short int
+|
+| /* A lexical scanner generated by flex */
+|
+| #define FLEX_SCANNER
+| #define YY_FLEX_MAJOR_VERSION 2
+| #define YY_FLEX_MINOR_VERSION 5
+| #define YY_FLEX_SUBMINOR_VERSION 35
+| #if YY_FLEX_SUBMINOR_VERSION > 0
+| #define FLEX_BETA
+| #endif
+|
+| /* First, we deal with platform-specific or compiler-specific issues. */
+|
+| /* begin standard C headers. */
+| #include <stdio.h>
+| #include <string.h>
+| #include <errno.h>
+| #include <stdlib.h>
+|
+| /* end standard C headers. */
+|
+| /* flex integer type definitions */
+|
+| #ifndef FLEXINT_H
+| #define FLEXINT_H
+|
+| /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+|
+| #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+|
+| /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+| * if you want the limit (max/min) macros for int types.
+| */
+| #ifndef __STDC_LIMIT_MACROS
+| #define __STDC_LIMIT_MACROS 1
+| #endif
+|
+| #include <inttypes.h>
+| typedef int8_t flex_int8_t;
+| typedef uint8_t flex_uint8_t;
+| typedef int16_t flex_int16_t;
+| typedef uint16_t flex_uint16_t;
+| typedef int32_t flex_int32_t;
+| typedef uint32_t flex_uint32_t;
+| typedef uint64_t flex_uint64_t;
+| #else
+| typedef signed char flex_int8_t;
+| typedef short int flex_int16_t;
+| typedef int flex_int32_t;
+| typedef unsigned char flex_uint8_t;
+| typedef unsigned short int flex_uint16_t;
+| typedef unsigned int flex_uint32_t;
+| #endif /* ! C99 */
+|
+| /* Limits of integral types. */
+| #ifndef INT8_MIN
+| #define INT8_MIN (-128)
+| #endif
+| #ifndef INT16_MIN
+| #define INT16_MIN (-32767-1)
+| #endif
+| #ifndef INT32_MIN
+| #define INT32_MIN (-2147483647-1)
+| #endif
+| #ifndef INT8_MAX
+| #define INT8_MAX (127)
+| #endif
+| #ifndef INT16_MAX
+| #define INT16_MAX (32767)
+| #endif
+| #ifndef INT32_MAX
+| #define INT32_MAX (2147483647)
+| #endif
+| #ifndef UINT8_MAX
+| #define UINT8_MAX (255U)
+| #endif
+| #ifndef UINT16_MAX
+| #define UINT16_MAX (65535U)
+| #endif
+| #ifndef UINT32_MAX
+| #define UINT32_MAX (4294967295U)
+| #endif
+|
+| #endif /* ! FLEXINT_H */
+|
+| #ifdef __cplusplus
+|
+| /* The "const" storage-class-modifier is valid. */
+| #define YY_USE_CONST
+|
+| #else /* ! __cplusplus */
+|
+| /* C99 requires __STDC__ to be defined as 1. */
+| #if defined (__STDC__)
+|
+| #define YY_USE_CONST
+|
+| #endif /* defined (__STDC__) */
+| #endif /* ! __cplusplus */
+|
+| #ifdef YY_USE_CONST
+| #define yyconst const
+| #else
+| #define yyconst
+| #endif
+|
+| /* Returned upon end-of-file. */
+| #define YY_NULL 0
+|
+| /* Promotes a possibly negative, possibly signed char to an unsigned
+| * integer for use as an array index. If the signed char is negative,
+| * we want to instead treat it as an 8-bit unsigned char, hence the
+| * double cast.
+| */
+| #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+|
+| /* Enter a start condition. This macro really ought to take a parameter,
+| * but we do it the disgusting crufty way forced on us by the ()-less
+| * definition of BEGIN.
+| */
+| #define BEGIN (yy_start) = 1 + 2 *
+|
+| /* Translate the current start state into a value that can be later handed
+| * to BEGIN to return to the state. The YYSTATE alias is for lex
+| * compatibility.
+| */
+| #define YY_START (((yy_start) - 1) / 2)
+| #define YYSTATE YY_START
+|
+| /* Action number for EOF rule of a given start state. */
+| #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+|
+| /* Special action meaning "start processing a new file". */
+| #define YY_NEW_FILE yyrestart(yyin )
+|
+| #define YY_END_OF_BUFFER_CHAR 0
+|
+| /* Size of default input buffer. */
+| #ifndef YY_BUF_SIZE
+| #define YY_BUF_SIZE 16384
+| #endif
+|
+| /* The state buf must be large enough to hold one state per character in the main buffer.
+| */
+| #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+|
+| #ifndef YY_TYPEDEF_YY_BUFFER_STATE
+| #define YY_TYPEDEF_YY_BUFFER_STATE
+| typedef struct yy_buffer_state *YY_BUFFER_STATE;
+| #endif
+|
+| #ifndef YY_TYPEDEF_YY_SIZE_T
+| #define YY_TYPEDEF_YY_SIZE_T
+| typedef size_t yy_size_t;
+| #endif
+|
+| extern yy_size_t yyleng;
+|
+| extern FILE *yyin, *yyout;
+|
+| #define EOB_ACT_CONTINUE_SCAN 0
+| #define EOB_ACT_END_OF_FILE 1
+| #define EOB_ACT_LAST_MATCH 2
+|
+| #define YY_LESS_LINENO(n)
+|
+| /* Return all but the first "n" matched characters back to the input stream. */
+| #define yyless(n) \
+| do \
+| { \
+| /* Undo effects of setting up yytext. */ \
+| int yyless_macro_arg = (n); \
+| YY_LESS_LINENO(yyless_macro_arg);\
+| *yy_cp = (yy_hold_char); \
+| YY_RESTORE_YY_MORE_OFFSET \
+| (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+| YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+| } \
+| while ( 0 )
+|
+| #define unput(c) yyunput( c, (yytext_ptr) )
+|
+| #ifndef YY_STRUCT_YY_BUFFER_STATE
+| #define YY_STRUCT_YY_BUFFER_STATE
+| struct yy_buffer_state
+| {
+| FILE *yy_input_file;
+|
+| char *yy_ch_buf; /* input buffer */
+| char *yy_buf_pos; /* current position in input buffer */
+|
+| /* Size of input buffer in bytes, not including room for EOB
+| * characters.
+| */
+| yy_size_t yy_buf_size;
+|
+| /* Number of characters read into yy_ch_buf, not including EOB
+| * characters.
+| */
+| yy_size_t yy_n_chars;
+|
+| /* Whether we "own" the buffer - i.e., we know we created it,
+| * and can realloc() it to grow it, and should free() it to
+| * delete it.
+| */
+| int yy_is_our_buffer;
+|
+| /* Whether this is an "interactive" input source; if so, and
+| * if we're using stdio for input, then we want to use getc()
+| * instead of fread(), to make sure we stop fetching input after
+| * each newline.
+| */
+| int yy_is_interactive;
+|
+| /* Whether we're considered to be at the beginning of a line.
+| * If so, '^' rules will be active on the next match, otherwise
+| * not.
+| */
+| int yy_at_bol;
+|
+| int yy_bs_lineno; /**< The line count. */
+| int yy_bs_column; /**< The column count. */
+|
+| /* Whether to try to fill the input buffer when we reach the
+| * end of it.
+| */
+| int yy_fill_buffer;
+|
+| int yy_buffer_status;
+|
+| #define YY_BUFFER_NEW 0
+| #define YY_BUFFER_NORMAL 1
+| /* When an EOF's been seen but there's still some text to process
+| * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+| * shouldn't try reading from the input source any more. We might
+| * still have a bunch of tokens to match, though, because of
+| * possible backing-up.
+| *
+| * When we actually see the EOF, we change the status to "new"
+| * (via yyrestart()), so that the user can continue scanning by
+| * just pointing yyin at a new input file.
+| */
+| #define YY_BUFFER_EOF_PENDING 2
+|
+| };
+| #endif /* !YY_STRUCT_YY_BUFFER_STATE */
+|
+| /* Stack of input buffers. */
+| static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+| static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+| static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+|
+| /* We provide macros for accessing buffer states in case in the
+| * future we want to put the buffer states in a more general
+| * "scanner state".
+| *
+| * Returns the top of the stack, or NULL.
+| */
+| #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+| ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+| : NULL)
+|
+| /* Same as previous macro, but useful when we know that the buffer stack is not
+| * NULL or when we need an lvalue. For internal use only.
+| */
+| #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+|
+| /* yy_hold_char holds the character lost when yytext is formed. */
+| static char yy_hold_char;
+| static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */
+| yy_size_t yyleng;
+|
+| /* Points to current character in buffer. */
+| static char *yy_c_buf_p = (char *) 0;
+| static int yy_init = 0; /* whether we need to initialize */
+| static int yy_start = 0; /* start state number */
+|
+| /* Flag which is used to allow yywrap()'s to do buffer switches
+| * instead of setting up a fresh yyin. A bit of a hack ...
+| */
+| static int yy_did_buffer_switch_on_eof;
+|
+| void yyrestart (FILE *input_file );
+| void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+| YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+| void yy_delete_buffer (YY_BUFFER_STATE b );
+| void yy_flush_buffer (YY_BUFFER_STATE b );
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+| void yypop_buffer_state (void );
+|
+| static void yyensure_buffer_stack (void );
+| static void yy_load_buffer_state (void );
+| static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
+|
+| #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+|
+| YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+| YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+| YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
+|
+| void *yyalloc (yy_size_t );
+| void *yyrealloc (void *,yy_size_t );
+| void yyfree (void * );
+|
+| #define yy_new_buffer yy_create_buffer
+|
+| #define yy_set_interactive(is_interactive) \
+| { \
+| if ( ! YY_CURRENT_BUFFER ){ \
+| yyensure_buffer_stack (); \
+| YY_CURRENT_BUFFER_LVALUE = \
+| yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| } \
+| YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+| }
+|
+| #define yy_set_bol(at_bol) \
+| { \
+| if ( ! YY_CURRENT_BUFFER ){\
+| yyensure_buffer_stack (); \
+| YY_CURRENT_BUFFER_LVALUE = \
+| yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| } \
+| YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+| }
+|
+| #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+|
+| /* Begin user sect3 */
+|
+| typedef unsigned char YY_CHAR;
+|
+| FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+|
+| typedef int yy_state_type;
+|
+| extern int yylineno;
+|
+| int yylineno = 1;
+|
+| extern char *yytext;
+| #define yytext_ptr yytext
+|
+| static yy_state_type yy_get_previous_state (void );
+| static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+| static int yy_get_next_buffer (void );
+| static void yy_fatal_error (yyconst char msg[] );
+|
+| /* Done after the current pattern has been matched and before the
+| * corresponding action - sets up yytext.
+| */
+| #define YY_DO_BEFORE_ACTION \
+| (yytext_ptr) = yy_bp; \
+| (yytext_ptr) -= (yy_more_len); \
+| yyleng = (yy_size_t) (yy_cp - (yytext_ptr)); \
+| (yy_hold_char) = *yy_cp; \
+| *yy_cp = '\0'; \
+| (yy_c_buf_p) = yy_cp;
+|
+| #define YY_NUM_RULES 8
+| #define YY_END_OF_BUFFER 9
+| /* This struct is not used in this scanner,
+| but its presence is necessary. */
+| struct yy_trans_info
+| {
+| flex_int32_t yy_verify;
+| flex_int32_t yy_nxt;
+| };
+| static yyconst flex_int16_t yy_acclist[23] =
+| { 0,
+| 9, 7, 8, 8, 1, 7, 8, 2, 7, 8,
+| 3, 7, 8, 4, 7, 8, 5, 7, 8, 6,
+| 7, 8
+| } ;
+|
+| static yyconst flex_int16_t yy_accept[14] =
+| { 0,
+| 1, 1, 1, 2, 4, 5, 8, 11, 14, 17,
+| 20, 23, 23
+| } ;
+|
+| static yyconst flex_int32_t yy_ec[256] =
+| { 0,
+| 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+| 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, 3, 4, 5, 6,
+|
+| 7, 8, 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,
+| 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
+| } ;
+|
+| static yyconst flex_int32_t yy_meta[9] =
+| { 0,
+| 1, 1, 1, 1, 1, 1, 1, 1
+| } ;
+|
+| static yyconst flex_int16_t yy_base[13] =
+| { 0,
+| 0, 0, 9, 10, 10, 10, 10, 10, 10, 10,
+| 10, 10
+| } ;
+|
+| static yyconst flex_int16_t yy_def[13] =
+| { 0,
+| 12, 1, 12, 12, 12, 12, 12, 12, 12, 12,
+| 12, 0
+| } ;
+|
+| static yyconst flex_int16_t yy_nxt[19] =
+| { 0,
+| 4, 5, 6, 7, 8, 9, 10, 11, 12, 3,
+| 12, 12, 12, 12, 12, 12, 12, 12
+| } ;
+|
+| static yyconst flex_int16_t yy_chk[19] =
+| { 0,
+| 1, 1, 1, 1, 1, 1, 1, 1, 3, 12,
+| 12, 12, 12, 12, 12, 12, 12, 12
+| } ;
+|
+| extern int yy_flex_debug;
+| int yy_flex_debug = 0;
+|
+| static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
+| static char *yy_full_match;
+| static int yy_lp;
+| #define REJECT \
+| { \
+| *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \
+| yy_cp = (yy_full_match); /* restore poss. backed-over text */ \
+| ++(yy_lp); \
+| goto find_rule; \
+| }
+|
+| static int yy_more_flag = 0;
+| static int yy_more_len = 0;
+| #define yymore() ((yy_more_flag) = 1)
+| #define YY_MORE_ADJ (yy_more_len)
+| #define YY_RESTORE_YY_MORE_OFFSET
+| char *yytext;
+| #line 1 "conftest.l"
+| #line 469 "lex.yy.c"
+|
+| #define INITIAL 0
+|
+| #ifndef YY_NO_UNISTD_H
+| /* Special case for "unistd.h", since it is non-ANSI. We include it way
+| * down here because we want the user's section 1 to have been scanned first.
+| * The user has a chance to override it with an option.
+| */
+| #include <unistd.h>
+| #endif
+|
+| #ifndef YY_EXTRA_TYPE
+| #define YY_EXTRA_TYPE void *
+| #endif
+|
+| static int yy_init_globals (void );
+|
+| /* Accessor methods to globals.
+| These are made visible to non-reentrant scanners for convenience. */
+|
+| int yylex_destroy (void );
+|
+| int yyget_debug (void );
+|
+| void yyset_debug (int debug_flag );
+|
+| YY_EXTRA_TYPE yyget_extra (void );
+|
+| void yyset_extra (YY_EXTRA_TYPE user_defined );
+|
+| FILE *yyget_in (void );
+|
+| void yyset_in (FILE * in_str );
+|
+| FILE *yyget_out (void );
+|
+| void yyset_out (FILE * out_str );
+|
+| yy_size_t yyget_leng (void );
+|
+| char *yyget_text (void );
+|
+| int yyget_lineno (void );
+|
+| void yyset_lineno (int line_number );
+|
+| /* Macros after this point can all be overridden by user definitions in
+| * section 1.
+| */
+|
+| #ifndef YY_SKIP_YYWRAP
+| #ifdef __cplusplus
+| extern "C" int yywrap (void );
+| #else
+| extern int yywrap (void );
+| #endif
+| #endif
+|
+| static void yyunput (int c,char *buf_ptr );
+|
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char *,yyconst char *,int );
+| #endif
+|
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * );
+| #endif
+|
+| #ifndef YY_NO_INPUT
+|
+| #ifdef __cplusplus
+| static int yyinput (void );
+| #else
+| static int input (void );
+| #endif
+|
+| #endif
+|
+| /* Amount of stuff to slurp up with each read. */
+| #ifndef YY_READ_BUF_SIZE
+| #define YY_READ_BUF_SIZE 8192
+| #endif
+|
+| /* Copy whatever the last rule matched to the standard output. */
+| #ifndef ECHO
+| /* This used to be an fputs(), but since the string might contain NUL's,
+| * we now use fwrite().
+| */
+| #define ECHO fwrite( yytext, yyleng, 1, yyout )
+| #endif
+|
+| /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+| * is returned in "result".
+| */
+| #ifndef YY_INPUT
+| #define YY_INPUT(buf,result,max_size) \
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+| { \
+| int c = '*'; \
+| yy_size_t n; \
+| for ( n = 0; n < max_size && \
+| (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+| buf[n] = (char) c; \
+| if ( c == '\n' ) \
+| buf[n++] = (char) c; \
+| if ( c == EOF && ferror( yyin ) ) \
+| YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| result = n; \
+| } \
+| else \
+| { \
+| errno=0; \
+| while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+| { \
+| if( errno != EINTR) \
+| { \
+| YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| break; \
+| } \
+| errno=0; \
+| clearerr(yyin); \
+| } \
+| }\
+| \
+|
+| #endif
+|
+| /* No semi-colon after return; correct usage is to write "yyterminate();" -
+| * we don't want an extra ';' after the "return" because that will cause
+| * some compilers to complain about unreachable statements.
+| */
+| #ifndef yyterminate
+| #define yyterminate() return YY_NULL
+| #endif
+|
+| /* Number of entries by which start-condition stack grows. */
+| #ifndef YY_START_STACK_INCR
+| #define YY_START_STACK_INCR 25
+| #endif
+|
+| /* Report a fatal error. */
+| #ifndef YY_FATAL_ERROR
+| #define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+| #endif
+|
+| /* end tables serialization structures and prototypes */
+|
+| /* Default declaration of generated scanner - a define so the user can
+| * easily add parameters.
+| */
+| #ifndef YY_DECL
+| #define YY_DECL_IS_OURS 1
+|
+| extern int yylex (void);
+|
+| #define YY_DECL int yylex (void)
+| #endif /* !YY_DECL */
+|
+| /* Code executed at the beginning of each rule, after yytext and yyleng
+| * have been set up.
+| */
+| #ifndef YY_USER_ACTION
+| #define YY_USER_ACTION
+| #endif
+|
+| /* Code executed at the end of each rule. */
+| #ifndef YY_BREAK
+| #define YY_BREAK break;
+| #endif
+|
+| #define YY_RULE_SETUP \
+| YY_USER_ACTION
+|
+| /** The main scanner function which does all the work.
+| */
+| YY_DECL
+| {
+| register yy_state_type yy_current_state;
+| register char *yy_cp, *yy_bp;
+| register int yy_act;
+|
+| #line 1 "conftest.l"
+|
+| #line 653 "lex.yy.c"
+|
+| if ( !(yy_init) )
+| {
+| (yy_init) = 1;
+|
+| #ifdef YY_USER_INIT
+| YY_USER_INIT;
+| #endif
+|
+| /* Create the reject buffer large enough to save one state per allowed character. */
+| if ( ! (yy_state_buf) )
+| (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE );
+| if ( ! (yy_state_buf) )
+| YY_FATAL_ERROR( "out of dynamic memory in yylex()" );
+|
+| if ( ! (yy_start) )
+| (yy_start) = 1; /* first start state */
+|
+| if ( ! yyin )
+| yyin = stdin;
+|
+| if ( ! yyout )
+| yyout = stdout;
+|
+| if ( ! YY_CURRENT_BUFFER ) {
+| yyensure_buffer_stack ();
+| YY_CURRENT_BUFFER_LVALUE =
+| yy_create_buffer(yyin,YY_BUF_SIZE );
+| }
+|
+| yy_load_buffer_state( );
+| }
+|
+| while ( 1 ) /* loops until end-of-file is reached */
+| {
+| (yy_more_len) = 0;
+| if ( (yy_more_flag) )
+| {
+| (yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+| (yy_more_flag) = 0;
+| }
+| yy_cp = (yy_c_buf_p);
+|
+| /* Support of yytext. */
+| *yy_cp = (yy_hold_char);
+|
+| /* yy_bp points to the position in yy_ch_buf of the start of
+| * the current run.
+| */
+| yy_bp = yy_cp;
+|
+| yy_current_state = (yy_start);
+|
+| (yy_state_ptr) = (yy_state_buf);
+| *(yy_state_ptr)++ = yy_current_state;
+|
+| yy_match:
+| do
+| {
+| register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| {
+| yy_current_state = (int) yy_def[yy_current_state];
+| if ( yy_current_state >= 13 )
+| yy_c = yy_meta[(unsigned int) yy_c];
+| }
+| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| *(yy_state_ptr)++ = yy_current_state;
+| ++yy_cp;
+| }
+| while ( yy_base[yy_current_state] != 10 );
+|
+| yy_find_action:
+| yy_current_state = *--(yy_state_ptr);
+| (yy_lp) = yy_accept[yy_current_state];
+| goto find_rule; /* Shut up GCC warning -Wall */
+| find_rule: /* we branch to this label when backing up */
+| for ( ; ; ) /* until we find what rule we matched */
+| {
+| if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] )
+| {
+| yy_act = yy_acclist[(yy_lp)];
+| {
+| (yy_full_match) = yy_cp;
+| break;
+| }
+| }
+| --yy_cp;
+| yy_current_state = *--(yy_state_ptr);
+| (yy_lp) = yy_accept[yy_current_state];
+| }
+|
+| YY_DO_BEFORE_ACTION;
+|
+| do_action: /* This label is used only to access EOF actions. */
+|
+| switch ( yy_act )
+| { /* beginning of action switch */
+| case 1:
+| YY_RULE_SETUP
+| #line 2 "conftest.l"
+| { ECHO; }
+| YY_BREAK
+| case 2:
+| YY_RULE_SETUP
+| #line 3 "conftest.l"
+| { REJECT; }
+| YY_BREAK
+| case 3:
+| YY_RULE_SETUP
+| #line 4 "conftest.l"
+| { yymore (); }
+| YY_BREAK
+| case 4:
+| YY_RULE_SETUP
+| #line 5 "conftest.l"
+| { yyless (1); }
+| YY_BREAK
+| case 5:
+| YY_RULE_SETUP
+| #line 6 "conftest.l"
+| { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */
+| yyless ((input () != 0)); }
+| YY_BREAK
+| case 6:
+| YY_RULE_SETUP
+| #line 8 "conftest.l"
+| { unput (yytext[0]); }
+| YY_BREAK
+| case 7:
+| YY_RULE_SETUP
+| #line 9 "conftest.l"
+| { BEGIN INITIAL; }
+| YY_BREAK
+| case 8:
+| YY_RULE_SETUP
+| #line 10 "conftest.l"
+| ECHO;
+| YY_BREAK
+| #line 793 "lex.yy.c"
+| case YY_STATE_EOF(INITIAL):
+| yyterminate();
+|
+| case YY_END_OF_BUFFER:
+| {
+| /* Amount of text matched not including the EOB char. */
+| int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+|
+| /* Undo the effects of YY_DO_BEFORE_ACTION. */
+| *yy_cp = (yy_hold_char);
+| YY_RESTORE_YY_MORE_OFFSET
+|
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+| {
+| /* We're scanning a new file or input source. It's
+| * possible that this happened because the user
+| * just pointed yyin at a new source and called
+| * yylex(). If so, then we have to assure
+| * consistency between YY_CURRENT_BUFFER and our
+| * globals. Here is the right place to do so, because
+| * this is the first action (other than possibly a
+| * back-up) that will match for the new input source.
+| */
+| (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+| YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+| }
+|
+| /* Note that here we test for yy_c_buf_p "<=" to the position
+| * of the first EOB in the buffer, since yy_c_buf_p will
+| * already have been incremented past the NUL character
+| * (since all states make transitions on EOB to the
+| * end-of-buffer state). Contrast this with the test
+| * in input().
+| */
+| if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| { /* This was really a NUL. */
+| yy_state_type yy_next_state;
+|
+| (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+|
+| yy_current_state = yy_get_previous_state( );
+|
+| /* Okay, we're now positioned to make the NUL
+| * transition. We couldn't have
+| * yy_get_previous_state() go ahead and do it
+| * for us because it doesn't know how to deal
+| * with the possibility of jamming (and we don't
+| * want to build jamming into it because then it
+| * will run more slowly).
+| */
+|
+| yy_next_state = yy_try_NUL_trans( yy_current_state );
+|
+| yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+|
+| if ( yy_next_state )
+| {
+| /* Consume the NUL. */
+| yy_cp = ++(yy_c_buf_p);
+| yy_current_state = yy_next_state;
+| goto yy_match;
+| }
+|
+| else
+| {
+| yy_cp = (yy_c_buf_p);
+| goto yy_find_action;
+| }
+| }
+|
+| else switch ( yy_get_next_buffer( ) )
+| {
+| case EOB_ACT_END_OF_FILE:
+| {
+| (yy_did_buffer_switch_on_eof) = 0;
+|
+| if ( yywrap( ) )
+| {
+| /* Note: because we've taken care in
+| * yy_get_next_buffer() to have set up
+| * yytext, we can now set up
+| * yy_c_buf_p so that if some total
+| * hoser (like flex itself) wants to
+| * call the scanner after we return the
+| * YY_NULL, it'll still work - another
+| * YY_NULL will get returned.
+| */
+| (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+|
+| yy_act = YY_STATE_EOF(YY_START);
+| goto do_action;
+| }
+|
+| else
+| {
+| if ( ! (yy_did_buffer_switch_on_eof) )
+| YY_NEW_FILE;
+| }
+| break;
+| }
+|
+| case EOB_ACT_CONTINUE_SCAN:
+| (yy_c_buf_p) =
+| (yytext_ptr) + yy_amount_of_matched_text;
+|
+| yy_current_state = yy_get_previous_state( );
+|
+| yy_cp = (yy_c_buf_p);
+| yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| goto yy_match;
+|
+| case EOB_ACT_LAST_MATCH:
+| (yy_c_buf_p) =
+| &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+|
+| yy_current_state = yy_get_previous_state( );
+|
+| yy_cp = (yy_c_buf_p);
+| yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| goto yy_find_action;
+| }
+| break;
+| }
+|
+| default:
+| YY_FATAL_ERROR(
+| "fatal flex scanner internal error--no action found" );
+| } /* end of action switch */
+| } /* end of scanning one token */
+| } /* end of yylex */
+|
+| /* yy_get_next_buffer - try to read in a new buffer
+| *
+| * Returns a code representing an action:
+| * EOB_ACT_LAST_MATCH -
+| * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+| * EOB_ACT_END_OF_FILE - end of file
+| */
+| static int yy_get_next_buffer (void)
+| {
+| register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+| register char *source = (yytext_ptr);
+| register int number_to_move, i;
+| int ret_val;
+|
+| if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+| YY_FATAL_ERROR(
+| "fatal flex scanner internal error--end of buffer missed" );
+|
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+| { /* Don't try to fill the buffer, so this is an EOF. */
+| if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+| {
+| /* We matched a single character, the EOB, so
+| * treat this as a final EOF.
+| */
+| return EOB_ACT_END_OF_FILE;
+| }
+|
+| else
+| {
+| /* We matched some text prior to the EOB, first
+| * process it.
+| */
+| return EOB_ACT_LAST_MATCH;
+| }
+| }
+|
+| /* Try to read more data. */
+|
+| /* First move last chars to start of buffer. */
+| number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+|
+| for ( i = 0; i < number_to_move; ++i )
+| *(dest++) = *(source++);
+|
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+| /* don't do the read, it's not guaranteed to return an EOF,
+| * just force an EOF
+| */
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+|
+| else
+| {
+| yy_size_t num_to_read =
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+|
+| while ( num_to_read <= 0 )
+| { /* Not enough room in the buffer - grow it. */
+|
+| YY_FATAL_ERROR(
+| "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+|
+| }
+|
+| if ( num_to_read > YY_READ_BUF_SIZE )
+| num_to_read = YY_READ_BUF_SIZE;
+|
+| /* Read in more data. */
+| YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+| (yy_n_chars), num_to_read );
+|
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| }
+|
+| if ( (yy_n_chars) == 0 )
+| {
+| if ( number_to_move == YY_MORE_ADJ )
+| {
+| ret_val = EOB_ACT_END_OF_FILE;
+| yyrestart(yyin );
+| }
+|
+| else
+| {
+| ret_val = EOB_ACT_LAST_MATCH;
+| YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+| YY_BUFFER_EOF_PENDING;
+| }
+| }
+|
+| else
+| ret_val = EOB_ACT_CONTINUE_SCAN;
+|
+| if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+| /* Extend the array by 50%, plus the number we really need. */
+| yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+| YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+| if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+| }
+|
+| (yy_n_chars) += number_to_move;
+| YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+| YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+|
+| (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+|
+| return ret_val;
+| }
+|
+| /* yy_get_previous_state - get the state just before the EOB char was reached */
+|
+| static yy_state_type yy_get_previous_state (void)
+| {
+| register yy_state_type yy_current_state;
+| register char *yy_cp;
+|
+| yy_current_state = (yy_start);
+|
+| (yy_state_ptr) = (yy_state_buf);
+| *(yy_state_ptr)++ = yy_current_state;
+|
+| for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+| {
+| register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| {
+| yy_current_state = (int) yy_def[yy_current_state];
+| if ( yy_current_state >= 13 )
+| yy_c = yy_meta[(unsigned int) yy_c];
+| }
+| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| *(yy_state_ptr)++ = yy_current_state;
+| }
+|
+| return yy_current_state;
+| }
+|
+| /* yy_try_NUL_trans - try to make a transition on the NUL character
+| *
+| * synopsis
+| * next_state = yy_try_NUL_trans( current_state );
+| */
+| static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+| {
+| register int yy_is_jam;
+|
+| register YY_CHAR yy_c = 1;
+| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| {
+| yy_current_state = (int) yy_def[yy_current_state];
+| if ( yy_current_state >= 13 )
+| yy_c = yy_meta[(unsigned int) yy_c];
+| }
+| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| yy_is_jam = (yy_current_state == 12);
+| if ( ! yy_is_jam )
+| *(yy_state_ptr)++ = yy_current_state;
+|
+| return yy_is_jam ? 0 : yy_current_state;
+| }
+|
+| static void yyunput (int c, register char * yy_bp )
+| {
+| register char *yy_cp;
+|
+| yy_cp = (yy_c_buf_p);
+|
+| /* undo effects of setting up yytext */
+| *yy_cp = (yy_hold_char);
+|
+| if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| { /* need to shift things up to make room */
+| /* +2 for EOB chars. */
+| register yy_size_t number_to_move = (yy_n_chars) + 2;
+| register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+| register char *source =
+| &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+|
+| while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| *--dest = *--source;
+|
+| yy_cp += (int) (dest - source);
+| yy_bp += (int) (dest - source);
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+| (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+|
+| if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| YY_FATAL_ERROR( "flex scanner push-back overflow" );
+| }
+|
+| *--yy_cp = (char) c;
+|
+| (yytext_ptr) = yy_bp;
+| (yy_hold_char) = *yy_cp;
+| (yy_c_buf_p) = yy_cp;
+| }
+|
+| #ifndef YY_NO_INPUT
+| #ifdef __cplusplus
+| static int yyinput (void)
+| #else
+| static int input (void)
+| #endif
+|
+| {
+| int c;
+|
+| *(yy_c_buf_p) = (yy_hold_char);
+|
+| if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+| {
+| /* yy_c_buf_p now points to the character we want to return.
+| * If this occurs *before* the EOB characters, then it's a
+| * valid NUL; if not, then we've hit the end of the buffer.
+| */
+| if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| /* This was really a NUL. */
+| *(yy_c_buf_p) = '\0';
+|
+| else
+| { /* need more input */
+| yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
+| ++(yy_c_buf_p);
+|
+| switch ( yy_get_next_buffer( ) )
+| {
+| case EOB_ACT_LAST_MATCH:
+| /* This happens because yy_g_n_b()
+| * sees that we've accumulated a
+| * token and flags that we need to
+| * try matching the token before
+| * proceeding. But for input(),
+| * there's no matching to consider.
+| * So convert the EOB_ACT_LAST_MATCH
+| * to EOB_ACT_END_OF_FILE.
+| */
+|
+| /* Reset buffer status. */
+| yyrestart(yyin );
+|
+| /*FALLTHROUGH*/
+|
+| case EOB_ACT_END_OF_FILE:
+| {
+| if ( yywrap( ) )
+| return 0;
+|
+| if ( ! (yy_did_buffer_switch_on_eof) )
+| YY_NEW_FILE;
+| #ifdef __cplusplus
+| return yyinput();
+| #else
+| return input();
+| #endif
+| }
+|
+| case EOB_ACT_CONTINUE_SCAN:
+| (yy_c_buf_p) = (yytext_ptr) + offset;
+| break;
+| }
+| }
+| }
+|
+| c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+| *(yy_c_buf_p) = '\0'; /* preserve yytext */
+| (yy_hold_char) = *++(yy_c_buf_p);
+|
+| return c;
+| }
+| #endif /* ifndef YY_NO_INPUT */
+|
+| /** Immediately switch to a different input stream.
+| * @param input_file A readable stream.
+| *
+| * @note This function does not reset the start condition to @c INITIAL .
+| */
+| void yyrestart (FILE * input_file )
+| {
+|
+| if ( ! YY_CURRENT_BUFFER ){
+| yyensure_buffer_stack ();
+| YY_CURRENT_BUFFER_LVALUE =
+| yy_create_buffer(yyin,YY_BUF_SIZE );
+| }
+|
+| yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+| yy_load_buffer_state( );
+| }
+|
+| /** Switch to a different input buffer.
+| * @param new_buffer The new input buffer.
+| *
+| */
+| void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+| {
+|
+| /* TODO. We should be able to replace this entire function body
+| * with
+| * yypop_buffer_state();
+| * yypush_buffer_state(new_buffer);
+| */
+| yyensure_buffer_stack ();
+| if ( YY_CURRENT_BUFFER == new_buffer )
+| return;
+|
+| if ( YY_CURRENT_BUFFER )
+| {
+| /* Flush out information for old buffer. */
+| *(yy_c_buf_p) = (yy_hold_char);
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| }
+|
+| YY_CURRENT_BUFFER_LVALUE = new_buffer;
+| yy_load_buffer_state( );
+|
+| /* We don't actually know whether we did this switch during
+| * EOF (yywrap()) processing, but the only time this flag
+| * is looked at is after yywrap() is called, so it's safe
+| * to go ahead and always set it.
+| */
+| (yy_did_buffer_switch_on_eof) = 1;
+| }
+|
+| static void yy_load_buffer_state (void)
+| {
+| (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+| yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+| (yy_hold_char) = *(yy_c_buf_p);
+| }
+|
+| /** Allocate and initialize an input buffer state.
+| * @param file A readable stream.
+| * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+| *
+| * @return the allocated buffer state.
+| */
+| YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+| {
+| YY_BUFFER_STATE b;
+|
+| b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+| if ( ! b )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+|
+| b->yy_buf_size = size;
+|
+| /* yy_ch_buf has to be 2 characters longer than the size given because
+| * we need to put in 2 end-of-buffer characters.
+| */
+| b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+| if ( ! b->yy_ch_buf )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+|
+| b->yy_is_our_buffer = 1;
+|
+| yy_init_buffer(b,file );
+|
+| return b;
+| }
+|
+| /** Destroy the buffer.
+| * @param b a buffer created with yy_create_buffer()
+| *
+| */
+| void yy_delete_buffer (YY_BUFFER_STATE b )
+| {
+|
+| if ( ! b )
+| return;
+|
+| if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+| YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+|
+| if ( b->yy_is_our_buffer )
+| yyfree((void *) b->yy_ch_buf );
+|
+| yyfree((void *) b );
+| }
+|
+| #ifndef __cplusplus
+| extern int isatty (int );
+| #endif /* __cplusplus */
+|
+| /* Initializes or reinitializes a buffer.
+| * This function is sometimes called more than once on the same buffer,
+| * such as during a yyrestart() or at EOF.
+| */
+| static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+|
+| {
+| int oerrno = errno;
+|
+| yy_flush_buffer(b );
+|
+| b->yy_input_file = file;
+| b->yy_fill_buffer = 1;
+|
+| /* If b is the current buffer, then yy_init_buffer was _probably_
+| * called from yyrestart() or through yy_get_next_buffer.
+| * In that case, we don't want to reset the lineno or column.
+| */
+| if (b != YY_CURRENT_BUFFER){
+| b->yy_bs_lineno = 1;
+| b->yy_bs_column = 0;
+| }
+|
+| b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+|
+| errno = oerrno;
+| }
+|
+| /** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+| * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+| *
+| */
+| void yy_flush_buffer (YY_BUFFER_STATE b )
+| {
+| if ( ! b )
+| return;
+|
+| b->yy_n_chars = 0;
+|
+| /* We always need two end-of-buffer characters. The first causes
+| * a transition to the end-of-buffer state. The second causes
+| * a jam in that state.
+| */
+| b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+| b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+|
+| b->yy_buf_pos = &b->yy_ch_buf[0];
+|
+| b->yy_at_bol = 1;
+| b->yy_buffer_status = YY_BUFFER_NEW;
+|
+| if ( b == YY_CURRENT_BUFFER )
+| yy_load_buffer_state( );
+| }
+|
+| /** Pushes the new state onto the stack. The new state becomes
+| * the current state. This function will allocate the stack
+| * if necessary.
+| * @param new_buffer The new state.
+| *
+| */
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+| {
+| if (new_buffer == NULL)
+| return;
+|
+| yyensure_buffer_stack();
+|
+| /* This block is copied from yy_switch_to_buffer. */
+| if ( YY_CURRENT_BUFFER )
+| {
+| /* Flush out information for old buffer. */
+| *(yy_c_buf_p) = (yy_hold_char);
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| }
+|
+| /* Only push if top exists. Otherwise, replace top. */
+| if (YY_CURRENT_BUFFER)
+| (yy_buffer_stack_top)++;
+| YY_CURRENT_BUFFER_LVALUE = new_buffer;
+|
+| /* copied from yy_switch_to_buffer. */
+| yy_load_buffer_state( );
+| (yy_did_buffer_switch_on_eof) = 1;
+| }
+|
+| /** Removes and deletes the top of the stack, if present.
+| * The next element becomes the new top.
+| *
+| */
+| void yypop_buffer_state (void)
+| {
+| if (!YY_CURRENT_BUFFER)
+| return;
+|
+| yy_delete_buffer(YY_CURRENT_BUFFER );
+| YY_CURRENT_BUFFER_LVALUE = NULL;
+| if ((yy_buffer_stack_top) > 0)
+| --(yy_buffer_stack_top);
+|
+| if (YY_CURRENT_BUFFER) {
+| yy_load_buffer_state( );
+| (yy_did_buffer_switch_on_eof) = 1;
+| }
+| }
+|
+| /* Allocates the stack if it does not exist.
+| * Guarantees space for at least one push.
+| */
+| static void yyensure_buffer_stack (void)
+| {
+| yy_size_t num_to_alloc;
+|
+| if (!(yy_buffer_stack)) {
+|
+| /* First allocation is just for 2 elements, since we don't know if this
+| * scanner will even need a stack. We use 2 instead of 1 to avoid an
+| * immediate realloc on the next call.
+| */
+| num_to_alloc = 1;
+| (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+| (num_to_alloc * sizeof(struct yy_buffer_state*)
+| );
+| if ( ! (yy_buffer_stack) )
+| YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+|
+| memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+|
+| (yy_buffer_stack_max) = num_to_alloc;
+| (yy_buffer_stack_top) = 0;
+| return;
+| }
+|
+| if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+|
+| /* Increase the buffer to prepare for a possible push. */
+| int grow_size = 8 /* arbitrary grow size */;
+|
+| num_to_alloc = (yy_buffer_stack_max) + grow_size;
+| (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+| ((yy_buffer_stack),
+| num_to_alloc * sizeof(struct yy_buffer_state*)
+| );
+| if ( ! (yy_buffer_stack) )
+| YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+|
+| /* zero only the new slots.*/
+| memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+| (yy_buffer_stack_max) = num_to_alloc;
+| }
+| }
+|
+| /** Setup the input buffer state to scan directly from a user-specified character buffer.
+| * @param base the character buffer
+| * @param size the size in bytes of the character buffer
+| *
+| * @return the newly allocated buffer state object.
+| */
+| YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+| {
+| YY_BUFFER_STATE b;
+|
+| if ( size < 2 ||
+| base[size-2] != YY_END_OF_BUFFER_CHAR ||
+| base[size-1] != YY_END_OF_BUFFER_CHAR )
+| /* They forgot to leave room for the EOB's. */
+| return 0;
+|
+| b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+| if ( ! b )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+|
+| b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+| b->yy_buf_pos = b->yy_ch_buf = base;
+| b->yy_is_our_buffer = 0;
+| b->yy_input_file = 0;
+| b->yy_n_chars = b->yy_buf_size;
+| b->yy_is_interactive = 0;
+| b->yy_at_bol = 1;
+| b->yy_fill_buffer = 0;
+| b->yy_buffer_status = YY_BUFFER_NEW;
+|
+| yy_switch_to_buffer(b );
+|
+| return b;
+| }
+|
+| /** Setup the input buffer state to scan a string. The next call to yylex() will
+| * scan from a @e copy of @a str.
+| * @param yystr a NUL-terminated string to scan
+| *
+| * @return the newly allocated buffer state object.
+| * @note If you want to scan bytes that may contain NUL values, then use
+| * yy_scan_bytes() instead.
+| */
+| YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+| {
+|
+| return yy_scan_bytes(yystr,strlen(yystr) );
+| }
+|
+| /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+| * scan from a @e copy of @a bytes.
+| * @param bytes the byte buffer to scan
+| * @param len the number of bytes in the buffer pointed to by @a bytes.
+| *
+| * @return the newly allocated buffer state object.
+| */
+| YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
+| {
+| YY_BUFFER_STATE b;
+| char *buf;
+| yy_size_t n, i;
+|
+| /* Get memory for full buffer, including space for trailing EOB's. */
+| n = _yybytes_len + 2;
+| buf = (char *) yyalloc(n );
+| if ( ! buf )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+|
+| for ( i = 0; i < _yybytes_len; ++i )
+| buf[i] = yybytes[i];
+|
+| buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+|
+| b = yy_scan_buffer(buf,n );
+| if ( ! b )
+| YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+|
+| /* It's okay to grow etc. this buffer, and we should throw it
+| * away when we're done.
+| */
+| b->yy_is_our_buffer = 1;
+|
+| return b;
+| }
+|
+| #ifndef YY_EXIT_FAILURE
+| #define YY_EXIT_FAILURE 2
+| #endif
+|
+| static void yy_fatal_error (yyconst char* msg )
+| {
+| (void) fprintf( stderr, "%s\n", msg );
+| exit( YY_EXIT_FAILURE );
+| }
+|
+| /* Redefine yyless() so it works in section 3 code. */
+|
+| #undef yyless
+| #define yyless(n) \
+| do \
+| { \
+| /* Undo effects of setting up yytext. */ \
+| int yyless_macro_arg = (n); \
+| YY_LESS_LINENO(yyless_macro_arg);\
+| yytext[yyleng] = (yy_hold_char); \
+| (yy_c_buf_p) = yytext + yyless_macro_arg; \
+| (yy_hold_char) = *(yy_c_buf_p); \
+| *(yy_c_buf_p) = '\0'; \
+| yyleng = yyless_macro_arg; \
+| } \
+| while ( 0 )
+|
+| /* Accessor methods (get/set functions) to struct members. */
+|
+| /** Get the current line number.
+| *
+| */
+| int yyget_lineno (void)
+| {
+|
+| return yylineno;
+| }
+|
+| /** Get the input stream.
+| *
+| */
+| FILE *yyget_in (void)
+| {
+| return yyin;
+| }
+|
+| /** Get the output stream.
+| *
+| */
+| FILE *yyget_out (void)
+| {
+| return yyout;
+| }
+|
+| /** Get the length of the current token.
+| *
+| */
+| yy_size_t yyget_leng (void)
+| {
+| return yyleng;
+| }
+|
+| /** Get the current token.
+| *
+| */
+|
+| char *yyget_text (void)
+| {
+| return yytext;
+| }
+|
+| /** Set the current line number.
+| * @param line_number
+| *
+| */
+| void yyset_lineno (int line_number )
+| {
+|
+| yylineno = line_number;
+| }
+|
+| /** Set the input stream. This does not discard the current
+| * input buffer.
+| * @param in_str A readable stream.
+| *
+| * @see yy_switch_to_buffer
+| */
+| void yyset_in (FILE * in_str )
+| {
+| yyin = in_str ;
+| }
+|
+| void yyset_out (FILE * out_str )
+| {
+| yyout = out_str ;
+| }
+|
+| int yyget_debug (void)
+| {
+| return yy_flex_debug;
+| }
+|
+| void yyset_debug (int bdebug )
+| {
+| yy_flex_debug = bdebug ;
+| }
+|
+| static int yy_init_globals (void)
+| {
+| /* Initialization is the same as for the non-reentrant scanner.
+| * This function is called from yylex_destroy(), so don't allocate here.
+| */
+|
+| (yy_buffer_stack) = 0;
+| (yy_buffer_stack_top) = 0;
+| (yy_buffer_stack_max) = 0;
+| (yy_c_buf_p) = (char *) 0;
+| (yy_init) = 0;
+| (yy_start) = 0;
+|
+| (yy_state_buf) = 0;
+| (yy_state_ptr) = 0;
+| (yy_full_match) = 0;
+| (yy_lp) = 0;
+|
+| /* Defined in main.c */
+| #ifdef YY_STDINIT
+| yyin = stdin;
+| yyout = stdout;
+| #else
+| yyin = (FILE *) 0;
+| yyout = (FILE *) 0;
+| #endif
+|
+| /* For future reference: Set errno on error, since we are called by
+| * yylex_init()
+| */
+| return 0;
+| }
+|
+| /* yylex_destroy is for both reentrant and non-reentrant scanners. */
+| int yylex_destroy (void)
+| {
+|
+| /* Pop the buffer stack, destroying each element. */
+| while(YY_CURRENT_BUFFER){
+| yy_delete_buffer(YY_CURRENT_BUFFER );
+| YY_CURRENT_BUFFER_LVALUE = NULL;
+| yypop_buffer_state();
+| }
+|
+| /* Destroy the stack itself. */
+| yyfree((yy_buffer_stack) );
+| (yy_buffer_stack) = NULL;
+|
+| yyfree ( (yy_state_buf) );
+| (yy_state_buf) = NULL;
+|
+| /* Reset the globals. This is important in a non-reentrant scanner so the next time
+| * yylex() is called, initialization will occur. */
+| yy_init_globals( );
+|
+| return 0;
+| }
+|
+| /*
+| * Internal utility routines.
+| */
+|
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+| {
+| register int i;
+| for ( i = 0; i < n; ++i )
+| s1[i] = s2[i];
+| }
+| #endif
+|
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * s )
+| {
+| register int n;
+| for ( n = 0; s[n]; ++n )
+| ;
+|
+| return n;
+| }
+| #endif
+|
+| void *yyalloc (yy_size_t size )
+| {
+| return (void *) malloc( size );
+| }
+|
+| void *yyrealloc (void * ptr, yy_size_t size )
+| {
+| /* The cast to (char *) in the following accommodates both
+| * implementations that use char* generic pointers, and those
+| * that use void* generic pointers. It works with the latter
+| * because both ANSI C and C++ allow castless assignment from
+| * any pointer type to void*, and deal with argument conversions
+| * as though doing an assignment.
+| */
+| return (void *) realloc( (char *) ptr, size );
+| }
+|
+| void yyfree (void * ptr )
+| {
+| free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+| }
+|
+| #define YYTABLES_NAME "yytables"
+|
+| #line 10 "conftest.l"
+|
+|
+| #ifdef YYTEXT_POINTER
+| extern char *yytext;
+| #endif
+| int
+| main (void)
+| {
+| return ! yylex () + ! yywrap ();
+| }
+configure:8025: gcc -o conftest -g -O2 conftest.c -lfl >&5
+ld: library not found for -lfl
+clang: error: linker command failed with exit code 1 (use -v to see invocation)
+configure:8025: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| /* end confdefs.h. */
+|
+| #line 3 "lex.yy.c"
+|
+| #define YY_INT_ALIGNED short int
+|
+| /* A lexical scanner generated by flex */
+|
+| #define FLEX_SCANNER
+| #define YY_FLEX_MAJOR_VERSION 2
+| #define YY_FLEX_MINOR_VERSION 5
+| #define YY_FLEX_SUBMINOR_VERSION 35
+| #if YY_FLEX_SUBMINOR_VERSION > 0
+| #define FLEX_BETA
+| #endif
+|
+| /* First, we deal with platform-specific or compiler-specific issues. */
+|
+| /* begin standard C headers. */
+| #include <stdio.h>
+| #include <string.h>
+| #include <errno.h>
+| #include <stdlib.h>
+|
+| /* end standard C headers. */
+|
+| /* flex integer type definitions */
+|
+| #ifndef FLEXINT_H
+| #define FLEXINT_H
+|
+| /* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+|
+| #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+|
+| /* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+| * if you want the limit (max/min) macros for int types.
+| */
+| #ifndef __STDC_LIMIT_MACROS
+| #define __STDC_LIMIT_MACROS 1
+| #endif
+|
+| #include <inttypes.h>
+| typedef int8_t flex_int8_t;
+| typedef uint8_t flex_uint8_t;
+| typedef int16_t flex_int16_t;
+| typedef uint16_t flex_uint16_t;
+| typedef int32_t flex_int32_t;
+| typedef uint32_t flex_uint32_t;
+| typedef uint64_t flex_uint64_t;
+| #else
+| typedef signed char flex_int8_t;
+| typedef short int flex_int16_t;
+| typedef int flex_int32_t;
+| typedef unsigned char flex_uint8_t;
+| typedef unsigned short int flex_uint16_t;
+| typedef unsigned int flex_uint32_t;
+| #endif /* ! C99 */
+|
+| /* Limits of integral types. */
+| #ifndef INT8_MIN
+| #define INT8_MIN (-128)
+| #endif
+| #ifndef INT16_MIN
+| #define INT16_MIN (-32767-1)
+| #endif
+| #ifndef INT32_MIN
+| #define INT32_MIN (-2147483647-1)
+| #endif
+| #ifndef INT8_MAX
+| #define INT8_MAX (127)
+| #endif
+| #ifndef INT16_MAX
+| #define INT16_MAX (32767)
+| #endif
+| #ifndef INT32_MAX
+| #define INT32_MAX (2147483647)
+| #endif
+| #ifndef UINT8_MAX
+| #define UINT8_MAX (255U)
+| #endif
+| #ifndef UINT16_MAX
+| #define UINT16_MAX (65535U)
+| #endif
+| #ifndef UINT32_MAX
+| #define UINT32_MAX (4294967295U)
+| #endif
+|
+| #endif /* ! FLEXINT_H */
+|
+| #ifdef __cplusplus
+|
+| /* The "const" storage-class-modifier is valid. */
+| #define YY_USE_CONST
+|
+| #else /* ! __cplusplus */
+|
+| /* C99 requires __STDC__ to be defined as 1. */
+| #if defined (__STDC__)
+|
+| #define YY_USE_CONST
+|
+| #endif /* defined (__STDC__) */
+| #endif /* ! __cplusplus */
+|
+| #ifdef YY_USE_CONST
+| #define yyconst const
+| #else
+| #define yyconst
+| #endif
+|
+| /* Returned upon end-of-file. */
+| #define YY_NULL 0
+|
+| /* Promotes a possibly negative, possibly signed char to an unsigned
+| * integer for use as an array index. If the signed char is negative,
+| * we want to instead treat it as an 8-bit unsigned char, hence the
+| * double cast.
+| */
+| #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+|
+| /* Enter a start condition. This macro really ought to take a parameter,
+| * but we do it the disgusting crufty way forced on us by the ()-less
+| * definition of BEGIN.
+| */
+| #define BEGIN (yy_start) = 1 + 2 *
+|
+| /* Translate the current start state into a value that can be later handed
+| * to BEGIN to return to the state. The YYSTATE alias is for lex
+| * compatibility.
+| */
+| #define YY_START (((yy_start) - 1) / 2)
+| #define YYSTATE YY_START
+|
+| /* Action number for EOF rule of a given start state. */
+| #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+|
+| /* Special action meaning "start processing a new file". */
+| #define YY_NEW_FILE yyrestart(yyin )
+|
+| #define YY_END_OF_BUFFER_CHAR 0
+|
+| /* Size of default input buffer. */
+| #ifndef YY_BUF_SIZE
+| #define YY_BUF_SIZE 16384
+| #endif
+|
+| /* The state buf must be large enough to hold one state per character in the main buffer.
+| */
+| #define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+|
+| #ifndef YY_TYPEDEF_YY_BUFFER_STATE
+| #define YY_TYPEDEF_YY_BUFFER_STATE
+| typedef struct yy_buffer_state *YY_BUFFER_STATE;
+| #endif
+|
+| #ifndef YY_TYPEDEF_YY_SIZE_T
+| #define YY_TYPEDEF_YY_SIZE_T
+| typedef size_t yy_size_t;
+| #endif
+|
+| extern yy_size_t yyleng;
+|
+| extern FILE *yyin, *yyout;
+|
+| #define EOB_ACT_CONTINUE_SCAN 0
+| #define EOB_ACT_END_OF_FILE 1
+| #define EOB_ACT_LAST_MATCH 2
+|
+| #define YY_LESS_LINENO(n)
+|
+| /* Return all but the first "n" matched characters back to the input stream. */
+| #define yyless(n) \
+| do \
+| { \
+| /* Undo effects of setting up yytext. */ \
+| int yyless_macro_arg = (n); \
+| YY_LESS_LINENO(yyless_macro_arg);\
+| *yy_cp = (yy_hold_char); \
+| YY_RESTORE_YY_MORE_OFFSET \
+| (yy_c_buf_p) = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+| YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+| } \
+| while ( 0 )
+|
+| #define unput(c) yyunput( c, (yytext_ptr) )
+|
+| #ifndef YY_STRUCT_YY_BUFFER_STATE
+| #define YY_STRUCT_YY_BUFFER_STATE
+| struct yy_buffer_state
+| {
+| FILE *yy_input_file;
+|
+| char *yy_ch_buf; /* input buffer */
+| char *yy_buf_pos; /* current position in input buffer */
+|
+| /* Size of input buffer in bytes, not including room for EOB
+| * characters.
+| */
+| yy_size_t yy_buf_size;
+|
+| /* Number of characters read into yy_ch_buf, not including EOB
+| * characters.
+| */
+| yy_size_t yy_n_chars;
+|
+| /* Whether we "own" the buffer - i.e., we know we created it,
+| * and can realloc() it to grow it, and should free() it to
+| * delete it.
+| */
+| int yy_is_our_buffer;
+|
+| /* Whether this is an "interactive" input source; if so, and
+| * if we're using stdio for input, then we want to use getc()
+| * instead of fread(), to make sure we stop fetching input after
+| * each newline.
+| */
+| int yy_is_interactive;
+|
+| /* Whether we're considered to be at the beginning of a line.
+| * If so, '^' rules will be active on the next match, otherwise
+| * not.
+| */
+| int yy_at_bol;
+|
+| int yy_bs_lineno; /**< The line count. */
+| int yy_bs_column; /**< The column count. */
+|
+| /* Whether to try to fill the input buffer when we reach the
+| * end of it.
+| */
+| int yy_fill_buffer;
+|
+| int yy_buffer_status;
+|
+| #define YY_BUFFER_NEW 0
+| #define YY_BUFFER_NORMAL 1
+| /* When an EOF's been seen but there's still some text to process
+| * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+| * shouldn't try reading from the input source any more. We might
+| * still have a bunch of tokens to match, though, because of
+| * possible backing-up.
+| *
+| * When we actually see the EOF, we change the status to "new"
+| * (via yyrestart()), so that the user can continue scanning by
+| * just pointing yyin at a new input file.
+| */
+| #define YY_BUFFER_EOF_PENDING 2
+|
+| };
+| #endif /* !YY_STRUCT_YY_BUFFER_STATE */
+|
+| /* Stack of input buffers. */
+| static size_t yy_buffer_stack_top = 0; /**< index of top of stack. */
+| static size_t yy_buffer_stack_max = 0; /**< capacity of stack. */
+| static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
+|
+| /* We provide macros for accessing buffer states in case in the
+| * future we want to put the buffer states in a more general
+| * "scanner state".
+| *
+| * Returns the top of the stack, or NULL.
+| */
+| #define YY_CURRENT_BUFFER ( (yy_buffer_stack) \
+| ? (yy_buffer_stack)[(yy_buffer_stack_top)] \
+| : NULL)
+|
+| /* Same as previous macro, but useful when we know that the buffer stack is not
+| * NULL or when we need an lvalue. For internal use only.
+| */
+| #define YY_CURRENT_BUFFER_LVALUE (yy_buffer_stack)[(yy_buffer_stack_top)]
+|
+| /* yy_hold_char holds the character lost when yytext is formed. */
+| static char yy_hold_char;
+| static yy_size_t yy_n_chars; /* number of characters read into yy_ch_buf */
+| yy_size_t yyleng;
+|
+| /* Points to current character in buffer. */
+| static char *yy_c_buf_p = (char *) 0;
+| static int yy_init = 0; /* whether we need to initialize */
+| static int yy_start = 0; /* start state number */
+|
+| /* Flag which is used to allow yywrap()'s to do buffer switches
+| * instead of setting up a fresh yyin. A bit of a hack ...
+| */
+| static int yy_did_buffer_switch_on_eof;
+|
+| void yyrestart (FILE *input_file );
+| void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer );
+| YY_BUFFER_STATE yy_create_buffer (FILE *file,int size );
+| void yy_delete_buffer (YY_BUFFER_STATE b );
+| void yy_flush_buffer (YY_BUFFER_STATE b );
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer );
+| void yypop_buffer_state (void );
+|
+| static void yyensure_buffer_stack (void );
+| static void yy_load_buffer_state (void );
+| static void yy_init_buffer (YY_BUFFER_STATE b,FILE *file );
+|
+| #define YY_FLUSH_BUFFER yy_flush_buffer(YY_CURRENT_BUFFER )
+|
+| YY_BUFFER_STATE yy_scan_buffer (char *base,yy_size_t size );
+| YY_BUFFER_STATE yy_scan_string (yyconst char *yy_str );
+| YY_BUFFER_STATE yy_scan_bytes (yyconst char *bytes,yy_size_t len );
+|
+| void *yyalloc (yy_size_t );
+| void *yyrealloc (void *,yy_size_t );
+| void yyfree (void * );
+|
+| #define yy_new_buffer yy_create_buffer
+|
+| #define yy_set_interactive(is_interactive) \
+| { \
+| if ( ! YY_CURRENT_BUFFER ){ \
+| yyensure_buffer_stack (); \
+| YY_CURRENT_BUFFER_LVALUE = \
+| yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| } \
+| YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+| }
+|
+| #define yy_set_bol(at_bol) \
+| { \
+| if ( ! YY_CURRENT_BUFFER ){\
+| yyensure_buffer_stack (); \
+| YY_CURRENT_BUFFER_LVALUE = \
+| yy_create_buffer(yyin,YY_BUF_SIZE ); \
+| } \
+| YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+| }
+|
+| #define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+|
+| /* Begin user sect3 */
+|
+| typedef unsigned char YY_CHAR;
+|
+| FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
+|
+| typedef int yy_state_type;
+|
+| extern int yylineno;
+|
+| int yylineno = 1;
+|
+| extern char *yytext;
+| #define yytext_ptr yytext
+|
+| static yy_state_type yy_get_previous_state (void );
+| static yy_state_type yy_try_NUL_trans (yy_state_type current_state );
+| static int yy_get_next_buffer (void );
+| static void yy_fatal_error (yyconst char msg[] );
+|
+| /* Done after the current pattern has been matched and before the
+| * corresponding action - sets up yytext.
+| */
+| #define YY_DO_BEFORE_ACTION \
+| (yytext_ptr) = yy_bp; \
+| (yytext_ptr) -= (yy_more_len); \
+| yyleng = (yy_size_t) (yy_cp - (yytext_ptr)); \
+| (yy_hold_char) = *yy_cp; \
+| *yy_cp = '\0'; \
+| (yy_c_buf_p) = yy_cp;
+|
+| #define YY_NUM_RULES 8
+| #define YY_END_OF_BUFFER 9
+| /* This struct is not used in this scanner,
+| but its presence is necessary. */
+| struct yy_trans_info
+| {
+| flex_int32_t yy_verify;
+| flex_int32_t yy_nxt;
+| };
+| static yyconst flex_int16_t yy_acclist[23] =
+| { 0,
+| 9, 7, 8, 8, 1, 7, 8, 2, 7, 8,
+| 3, 7, 8, 4, 7, 8, 5, 7, 8, 6,
+| 7, 8
+| } ;
+|
+| static yyconst flex_int16_t yy_accept[14] =
+| { 0,
+| 1, 1, 1, 2, 4, 5, 8, 11, 14, 17,
+| 20, 23, 23
+| } ;
+|
+| static yyconst flex_int32_t yy_ec[256] =
+| { 0,
+| 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
+| 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, 3, 4, 5, 6,
+|
+| 7, 8, 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,
+| 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
+| } ;
+|
+| static yyconst flex_int32_t yy_meta[9] =
+| { 0,
+| 1, 1, 1, 1, 1, 1, 1, 1
+| } ;
+|
+| static yyconst flex_int16_t yy_base[13] =
+| { 0,
+| 0, 0, 9, 10, 10, 10, 10, 10, 10, 10,
+| 10, 10
+| } ;
+|
+| static yyconst flex_int16_t yy_def[13] =
+| { 0,
+| 12, 1, 12, 12, 12, 12, 12, 12, 12, 12,
+| 12, 0
+| } ;
+|
+| static yyconst flex_int16_t yy_nxt[19] =
+| { 0,
+| 4, 5, 6, 7, 8, 9, 10, 11, 12, 3,
+| 12, 12, 12, 12, 12, 12, 12, 12
+| } ;
+|
+| static yyconst flex_int16_t yy_chk[19] =
+| { 0,
+| 1, 1, 1, 1, 1, 1, 1, 1, 3, 12,
+| 12, 12, 12, 12, 12, 12, 12, 12
+| } ;
+|
+| extern int yy_flex_debug;
+| int yy_flex_debug = 0;
+|
+| static yy_state_type *yy_state_buf=0, *yy_state_ptr=0;
+| static char *yy_full_match;
+| static int yy_lp;
+| #define REJECT \
+| { \
+| *yy_cp = (yy_hold_char); /* undo effects of setting up yytext */ \
+| yy_cp = (yy_full_match); /* restore poss. backed-over text */ \
+| ++(yy_lp); \
+| goto find_rule; \
+| }
+|
+| static int yy_more_flag = 0;
+| static int yy_more_len = 0;
+| #define yymore() ((yy_more_flag) = 1)
+| #define YY_MORE_ADJ (yy_more_len)
+| #define YY_RESTORE_YY_MORE_OFFSET
+| char *yytext;
+| #line 1 "conftest.l"
+| #line 469 "lex.yy.c"
+|
+| #define INITIAL 0
+|
+| #ifndef YY_NO_UNISTD_H
+| /* Special case for "unistd.h", since it is non-ANSI. We include it way
+| * down here because we want the user's section 1 to have been scanned first.
+| * The user has a chance to override it with an option.
+| */
+| #include <unistd.h>
+| #endif
+|
+| #ifndef YY_EXTRA_TYPE
+| #define YY_EXTRA_TYPE void *
+| #endif
+|
+| static int yy_init_globals (void );
+|
+| /* Accessor methods to globals.
+| These are made visible to non-reentrant scanners for convenience. */
+|
+| int yylex_destroy (void );
+|
+| int yyget_debug (void );
+|
+| void yyset_debug (int debug_flag );
+|
+| YY_EXTRA_TYPE yyget_extra (void );
+|
+| void yyset_extra (YY_EXTRA_TYPE user_defined );
+|
+| FILE *yyget_in (void );
+|
+| void yyset_in (FILE * in_str );
+|
+| FILE *yyget_out (void );
+|
+| void yyset_out (FILE * out_str );
+|
+| yy_size_t yyget_leng (void );
+|
+| char *yyget_text (void );
+|
+| int yyget_lineno (void );
+|
+| void yyset_lineno (int line_number );
+|
+| /* Macros after this point can all be overridden by user definitions in
+| * section 1.
+| */
+|
+| #ifndef YY_SKIP_YYWRAP
+| #ifdef __cplusplus
+| extern "C" int yywrap (void );
+| #else
+| extern int yywrap (void );
+| #endif
+| #endif
+|
+| static void yyunput (int c,char *buf_ptr );
+|
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char *,yyconst char *,int );
+| #endif
+|
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * );
+| #endif
+|
+| #ifndef YY_NO_INPUT
+|
+| #ifdef __cplusplus
+| static int yyinput (void );
+| #else
+| static int input (void );
+| #endif
+|
+| #endif
+|
+| /* Amount of stuff to slurp up with each read. */
+| #ifndef YY_READ_BUF_SIZE
+| #define YY_READ_BUF_SIZE 8192
+| #endif
+|
+| /* Copy whatever the last rule matched to the standard output. */
+| #ifndef ECHO
+| /* This used to be an fputs(), but since the string might contain NUL's,
+| * we now use fwrite().
+| */
+| #define ECHO fwrite( yytext, yyleng, 1, yyout )
+| #endif
+|
+| /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+| * is returned in "result".
+| */
+| #ifndef YY_INPUT
+| #define YY_INPUT(buf,result,max_size) \
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+| { \
+| int c = '*'; \
+| yy_size_t n; \
+| for ( n = 0; n < max_size && \
+| (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+| buf[n] = (char) c; \
+| if ( c == '\n' ) \
+| buf[n++] = (char) c; \
+| if ( c == EOF && ferror( yyin ) ) \
+| YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| result = n; \
+| } \
+| else \
+| { \
+| errno=0; \
+| while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+| { \
+| if( errno != EINTR) \
+| { \
+| YY_FATAL_ERROR( "input in flex scanner failed" ); \
+| break; \
+| } \
+| errno=0; \
+| clearerr(yyin); \
+| } \
+| }\
+| \
+|
+| #endif
+|
+| /* No semi-colon after return; correct usage is to write "yyterminate();" -
+| * we don't want an extra ';' after the "return" because that will cause
+| * some compilers to complain about unreachable statements.
+| */
+| #ifndef yyterminate
+| #define yyterminate() return YY_NULL
+| #endif
+|
+| /* Number of entries by which start-condition stack grows. */
+| #ifndef YY_START_STACK_INCR
+| #define YY_START_STACK_INCR 25
+| #endif
+|
+| /* Report a fatal error. */
+| #ifndef YY_FATAL_ERROR
+| #define YY_FATAL_ERROR(msg) yy_fatal_error( msg )
+| #endif
+|
+| /* end tables serialization structures and prototypes */
+|
+| /* Default declaration of generated scanner - a define so the user can
+| * easily add parameters.
+| */
+| #ifndef YY_DECL
+| #define YY_DECL_IS_OURS 1
+|
+| extern int yylex (void);
+|
+| #define YY_DECL int yylex (void)
+| #endif /* !YY_DECL */
+|
+| /* Code executed at the beginning of each rule, after yytext and yyleng
+| * have been set up.
+| */
+| #ifndef YY_USER_ACTION
+| #define YY_USER_ACTION
+| #endif
+|
+| /* Code executed at the end of each rule. */
+| #ifndef YY_BREAK
+| #define YY_BREAK break;
+| #endif
+|
+| #define YY_RULE_SETUP \
+| YY_USER_ACTION
+|
+| /** The main scanner function which does all the work.
+| */
+| YY_DECL
+| {
+| register yy_state_type yy_current_state;
+| register char *yy_cp, *yy_bp;
+| register int yy_act;
+|
+| #line 1 "conftest.l"
+|
+| #line 653 "lex.yy.c"
+|
+| if ( !(yy_init) )
+| {
+| (yy_init) = 1;
+|
+| #ifdef YY_USER_INIT
+| YY_USER_INIT;
+| #endif
+|
+| /* Create the reject buffer large enough to save one state per allowed character. */
+| if ( ! (yy_state_buf) )
+| (yy_state_buf) = (yy_state_type *)yyalloc(YY_STATE_BUF_SIZE );
+| if ( ! (yy_state_buf) )
+| YY_FATAL_ERROR( "out of dynamic memory in yylex()" );
+|
+| if ( ! (yy_start) )
+| (yy_start) = 1; /* first start state */
+|
+| if ( ! yyin )
+| yyin = stdin;
+|
+| if ( ! yyout )
+| yyout = stdout;
+|
+| if ( ! YY_CURRENT_BUFFER ) {
+| yyensure_buffer_stack ();
+| YY_CURRENT_BUFFER_LVALUE =
+| yy_create_buffer(yyin,YY_BUF_SIZE );
+| }
+|
+| yy_load_buffer_state( );
+| }
+|
+| while ( 1 ) /* loops until end-of-file is reached */
+| {
+| (yy_more_len) = 0;
+| if ( (yy_more_flag) )
+| {
+| (yy_more_len) = (yy_c_buf_p) - (yytext_ptr);
+| (yy_more_flag) = 0;
+| }
+| yy_cp = (yy_c_buf_p);
+|
+| /* Support of yytext. */
+| *yy_cp = (yy_hold_char);
+|
+| /* yy_bp points to the position in yy_ch_buf of the start of
+| * the current run.
+| */
+| yy_bp = yy_cp;
+|
+| yy_current_state = (yy_start);
+|
+| (yy_state_ptr) = (yy_state_buf);
+| *(yy_state_ptr)++ = yy_current_state;
+|
+| yy_match:
+| do
+| {
+| register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| {
+| yy_current_state = (int) yy_def[yy_current_state];
+| if ( yy_current_state >= 13 )
+| yy_c = yy_meta[(unsigned int) yy_c];
+| }
+| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| *(yy_state_ptr)++ = yy_current_state;
+| ++yy_cp;
+| }
+| while ( yy_base[yy_current_state] != 10 );
+|
+| yy_find_action:
+| yy_current_state = *--(yy_state_ptr);
+| (yy_lp) = yy_accept[yy_current_state];
+| goto find_rule; /* Shut up GCC warning -Wall */
+| find_rule: /* we branch to this label when backing up */
+| for ( ; ; ) /* until we find what rule we matched */
+| {
+| if ( (yy_lp) && (yy_lp) < yy_accept[yy_current_state + 1] )
+| {
+| yy_act = yy_acclist[(yy_lp)];
+| {
+| (yy_full_match) = yy_cp;
+| break;
+| }
+| }
+| --yy_cp;
+| yy_current_state = *--(yy_state_ptr);
+| (yy_lp) = yy_accept[yy_current_state];
+| }
+|
+| YY_DO_BEFORE_ACTION;
+|
+| do_action: /* This label is used only to access EOF actions. */
+|
+| switch ( yy_act )
+| { /* beginning of action switch */
+| case 1:
+| YY_RULE_SETUP
+| #line 2 "conftest.l"
+| { ECHO; }
+| YY_BREAK
+| case 2:
+| YY_RULE_SETUP
+| #line 3 "conftest.l"
+| { REJECT; }
+| YY_BREAK
+| case 3:
+| YY_RULE_SETUP
+| #line 4 "conftest.l"
+| { yymore (); }
+| YY_BREAK
+| case 4:
+| YY_RULE_SETUP
+| #line 5 "conftest.l"
+| { yyless (1); }
+| YY_BREAK
+| case 5:
+| YY_RULE_SETUP
+| #line 6 "conftest.l"
+| { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */
+| yyless ((input () != 0)); }
+| YY_BREAK
+| case 6:
+| YY_RULE_SETUP
+| #line 8 "conftest.l"
+| { unput (yytext[0]); }
+| YY_BREAK
+| case 7:
+| YY_RULE_SETUP
+| #line 9 "conftest.l"
+| { BEGIN INITIAL; }
+| YY_BREAK
+| case 8:
+| YY_RULE_SETUP
+| #line 10 "conftest.l"
+| ECHO;
+| YY_BREAK
+| #line 793 "lex.yy.c"
+| case YY_STATE_EOF(INITIAL):
+| yyterminate();
+|
+| case YY_END_OF_BUFFER:
+| {
+| /* Amount of text matched not including the EOB char. */
+| int yy_amount_of_matched_text = (int) (yy_cp - (yytext_ptr)) - 1;
+|
+| /* Undo the effects of YY_DO_BEFORE_ACTION. */
+| *yy_cp = (yy_hold_char);
+| YY_RESTORE_YY_MORE_OFFSET
+|
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+| {
+| /* We're scanning a new file or input source. It's
+| * possible that this happened because the user
+| * just pointed yyin at a new source and called
+| * yylex(). If so, then we have to assure
+| * consistency between YY_CURRENT_BUFFER and our
+| * globals. Here is the right place to do so, because
+| * this is the first action (other than possibly a
+| * back-up) that will match for the new input source.
+| */
+| (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+| YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+| }
+|
+| /* Note that here we test for yy_c_buf_p "<=" to the position
+| * of the first EOB in the buffer, since yy_c_buf_p will
+| * already have been incremented past the NUL character
+| * (since all states make transitions on EOB to the
+| * end-of-buffer state). Contrast this with the test
+| * in input().
+| */
+| if ( (yy_c_buf_p) <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| { /* This was really a NUL. */
+| yy_state_type yy_next_state;
+|
+| (yy_c_buf_p) = (yytext_ptr) + yy_amount_of_matched_text;
+|
+| yy_current_state = yy_get_previous_state( );
+|
+| /* Okay, we're now positioned to make the NUL
+| * transition. We couldn't have
+| * yy_get_previous_state() go ahead and do it
+| * for us because it doesn't know how to deal
+| * with the possibility of jamming (and we don't
+| * want to build jamming into it because then it
+| * will run more slowly).
+| */
+|
+| yy_next_state = yy_try_NUL_trans( yy_current_state );
+|
+| yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+|
+| if ( yy_next_state )
+| {
+| /* Consume the NUL. */
+| yy_cp = ++(yy_c_buf_p);
+| yy_current_state = yy_next_state;
+| goto yy_match;
+| }
+|
+| else
+| {
+| yy_cp = (yy_c_buf_p);
+| goto yy_find_action;
+| }
+| }
+|
+| else switch ( yy_get_next_buffer( ) )
+| {
+| case EOB_ACT_END_OF_FILE:
+| {
+| (yy_did_buffer_switch_on_eof) = 0;
+|
+| if ( yywrap( ) )
+| {
+| /* Note: because we've taken care in
+| * yy_get_next_buffer() to have set up
+| * yytext, we can now set up
+| * yy_c_buf_p so that if some total
+| * hoser (like flex itself) wants to
+| * call the scanner after we return the
+| * YY_NULL, it'll still work - another
+| * YY_NULL will get returned.
+| */
+| (yy_c_buf_p) = (yytext_ptr) + YY_MORE_ADJ;
+|
+| yy_act = YY_STATE_EOF(YY_START);
+| goto do_action;
+| }
+|
+| else
+| {
+| if ( ! (yy_did_buffer_switch_on_eof) )
+| YY_NEW_FILE;
+| }
+| break;
+| }
+|
+| case EOB_ACT_CONTINUE_SCAN:
+| (yy_c_buf_p) =
+| (yytext_ptr) + yy_amount_of_matched_text;
+|
+| yy_current_state = yy_get_previous_state( );
+|
+| yy_cp = (yy_c_buf_p);
+| yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| goto yy_match;
+|
+| case EOB_ACT_LAST_MATCH:
+| (yy_c_buf_p) =
+| &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)];
+|
+| yy_current_state = yy_get_previous_state( );
+|
+| yy_cp = (yy_c_buf_p);
+| yy_bp = (yytext_ptr) + YY_MORE_ADJ;
+| goto yy_find_action;
+| }
+| break;
+| }
+|
+| default:
+| YY_FATAL_ERROR(
+| "fatal flex scanner internal error--no action found" );
+| } /* end of action switch */
+| } /* end of scanning one token */
+| } /* end of yylex */
+|
+| /* yy_get_next_buffer - try to read in a new buffer
+| *
+| * Returns a code representing an action:
+| * EOB_ACT_LAST_MATCH -
+| * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+| * EOB_ACT_END_OF_FILE - end of file
+| */
+| static int yy_get_next_buffer (void)
+| {
+| register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+| register char *source = (yytext_ptr);
+| register int number_to_move, i;
+| int ret_val;
+|
+| if ( (yy_c_buf_p) > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] )
+| YY_FATAL_ERROR(
+| "fatal flex scanner internal error--end of buffer missed" );
+|
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+| { /* Don't try to fill the buffer, so this is an EOF. */
+| if ( (yy_c_buf_p) - (yytext_ptr) - YY_MORE_ADJ == 1 )
+| {
+| /* We matched a single character, the EOB, so
+| * treat this as a final EOF.
+| */
+| return EOB_ACT_END_OF_FILE;
+| }
+|
+| else
+| {
+| /* We matched some text prior to the EOB, first
+| * process it.
+| */
+| return EOB_ACT_LAST_MATCH;
+| }
+| }
+|
+| /* Try to read more data. */
+|
+| /* First move last chars to start of buffer. */
+| number_to_move = (int) ((yy_c_buf_p) - (yytext_ptr)) - 1;
+|
+| for ( i = 0; i < number_to_move; ++i )
+| *(dest++) = *(source++);
+|
+| if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+| /* don't do the read, it's not guaranteed to return an EOF,
+| * just force an EOF
+| */
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars) = 0;
+|
+| else
+| {
+| yy_size_t num_to_read =
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+|
+| while ( num_to_read <= 0 )
+| { /* Not enough room in the buffer - grow it. */
+|
+| YY_FATAL_ERROR(
+| "input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+|
+| }
+|
+| if ( num_to_read > YY_READ_BUF_SIZE )
+| num_to_read = YY_READ_BUF_SIZE;
+|
+| /* Read in more data. */
+| YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+| (yy_n_chars), num_to_read );
+|
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| }
+|
+| if ( (yy_n_chars) == 0 )
+| {
+| if ( number_to_move == YY_MORE_ADJ )
+| {
+| ret_val = EOB_ACT_END_OF_FILE;
+| yyrestart(yyin );
+| }
+|
+| else
+| {
+| ret_val = EOB_ACT_LAST_MATCH;
+| YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+| YY_BUFFER_EOF_PENDING;
+| }
+| }
+|
+| else
+| ret_val = EOB_ACT_CONTINUE_SCAN;
+|
+| if ((yy_size_t) ((yy_n_chars) + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) {
+| /* Extend the array by 50%, plus the number we really need. */
+| yy_size_t new_size = (yy_n_chars) + number_to_move + ((yy_n_chars) >> 1);
+| YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size );
+| if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" );
+| }
+|
+| (yy_n_chars) += number_to_move;
+| YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] = YY_END_OF_BUFFER_CHAR;
+| YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars) + 1] = YY_END_OF_BUFFER_CHAR;
+|
+| (yytext_ptr) = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+|
+| return ret_val;
+| }
+|
+| /* yy_get_previous_state - get the state just before the EOB char was reached */
+|
+| static yy_state_type yy_get_previous_state (void)
+| {
+| register yy_state_type yy_current_state;
+| register char *yy_cp;
+|
+| yy_current_state = (yy_start);
+|
+| (yy_state_ptr) = (yy_state_buf);
+| *(yy_state_ptr)++ = yy_current_state;
+|
+| for ( yy_cp = (yytext_ptr) + YY_MORE_ADJ; yy_cp < (yy_c_buf_p); ++yy_cp )
+| {
+| register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| {
+| yy_current_state = (int) yy_def[yy_current_state];
+| if ( yy_current_state >= 13 )
+| yy_c = yy_meta[(unsigned int) yy_c];
+| }
+| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| *(yy_state_ptr)++ = yy_current_state;
+| }
+|
+| return yy_current_state;
+| }
+|
+| /* yy_try_NUL_trans - try to make a transition on the NUL character
+| *
+| * synopsis
+| * next_state = yy_try_NUL_trans( current_state );
+| */
+| static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state )
+| {
+| register int yy_is_jam;
+|
+| register YY_CHAR yy_c = 1;
+| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+| {
+| yy_current_state = (int) yy_def[yy_current_state];
+| if ( yy_current_state >= 13 )
+| yy_c = yy_meta[(unsigned int) yy_c];
+| }
+| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+| yy_is_jam = (yy_current_state == 12);
+| if ( ! yy_is_jam )
+| *(yy_state_ptr)++ = yy_current_state;
+|
+| return yy_is_jam ? 0 : yy_current_state;
+| }
+|
+| static void yyunput (int c, register char * yy_bp )
+| {
+| register char *yy_cp;
+|
+| yy_cp = (yy_c_buf_p);
+|
+| /* undo effects of setting up yytext */
+| *yy_cp = (yy_hold_char);
+|
+| if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| { /* need to shift things up to make room */
+| /* +2 for EOB chars. */
+| register yy_size_t number_to_move = (yy_n_chars) + 2;
+| register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+| register char *source =
+| &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+|
+| while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+| *--dest = *--source;
+|
+| yy_cp += (int) (dest - source);
+| yy_bp += (int) (dest - source);
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+| (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+|
+| if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+| YY_FATAL_ERROR( "flex scanner push-back overflow" );
+| }
+|
+| *--yy_cp = (char) c;
+|
+| (yytext_ptr) = yy_bp;
+| (yy_hold_char) = *yy_cp;
+| (yy_c_buf_p) = yy_cp;
+| }
+|
+| #ifndef YY_NO_INPUT
+| #ifdef __cplusplus
+| static int yyinput (void)
+| #else
+| static int input (void)
+| #endif
+|
+| {
+| int c;
+|
+| *(yy_c_buf_p) = (yy_hold_char);
+|
+| if ( *(yy_c_buf_p) == YY_END_OF_BUFFER_CHAR )
+| {
+| /* yy_c_buf_p now points to the character we want to return.
+| * If this occurs *before* the EOB characters, then it's a
+| * valid NUL; if not, then we've hit the end of the buffer.
+| */
+| if ( (yy_c_buf_p) < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[(yy_n_chars)] )
+| /* This was really a NUL. */
+| *(yy_c_buf_p) = '\0';
+|
+| else
+| { /* need more input */
+| yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
+| ++(yy_c_buf_p);
+|
+| switch ( yy_get_next_buffer( ) )
+| {
+| case EOB_ACT_LAST_MATCH:
+| /* This happens because yy_g_n_b()
+| * sees that we've accumulated a
+| * token and flags that we need to
+| * try matching the token before
+| * proceeding. But for input(),
+| * there's no matching to consider.
+| * So convert the EOB_ACT_LAST_MATCH
+| * to EOB_ACT_END_OF_FILE.
+| */
+|
+| /* Reset buffer status. */
+| yyrestart(yyin );
+|
+| /*FALLTHROUGH*/
+|
+| case EOB_ACT_END_OF_FILE:
+| {
+| if ( yywrap( ) )
+| return 0;
+|
+| if ( ! (yy_did_buffer_switch_on_eof) )
+| YY_NEW_FILE;
+| #ifdef __cplusplus
+| return yyinput();
+| #else
+| return input();
+| #endif
+| }
+|
+| case EOB_ACT_CONTINUE_SCAN:
+| (yy_c_buf_p) = (yytext_ptr) + offset;
+| break;
+| }
+| }
+| }
+|
+| c = *(unsigned char *) (yy_c_buf_p); /* cast for 8-bit char's */
+| *(yy_c_buf_p) = '\0'; /* preserve yytext */
+| (yy_hold_char) = *++(yy_c_buf_p);
+|
+| return c;
+| }
+| #endif /* ifndef YY_NO_INPUT */
+|
+| /** Immediately switch to a different input stream.
+| * @param input_file A readable stream.
+| *
+| * @note This function does not reset the start condition to @c INITIAL .
+| */
+| void yyrestart (FILE * input_file )
+| {
+|
+| if ( ! YY_CURRENT_BUFFER ){
+| yyensure_buffer_stack ();
+| YY_CURRENT_BUFFER_LVALUE =
+| yy_create_buffer(yyin,YY_BUF_SIZE );
+| }
+|
+| yy_init_buffer(YY_CURRENT_BUFFER,input_file );
+| yy_load_buffer_state( );
+| }
+|
+| /** Switch to a different input buffer.
+| * @param new_buffer The new input buffer.
+| *
+| */
+| void yy_switch_to_buffer (YY_BUFFER_STATE new_buffer )
+| {
+|
+| /* TODO. We should be able to replace this entire function body
+| * with
+| * yypop_buffer_state();
+| * yypush_buffer_state(new_buffer);
+| */
+| yyensure_buffer_stack ();
+| if ( YY_CURRENT_BUFFER == new_buffer )
+| return;
+|
+| if ( YY_CURRENT_BUFFER )
+| {
+| /* Flush out information for old buffer. */
+| *(yy_c_buf_p) = (yy_hold_char);
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| }
+|
+| YY_CURRENT_BUFFER_LVALUE = new_buffer;
+| yy_load_buffer_state( );
+|
+| /* We don't actually know whether we did this switch during
+| * EOF (yywrap()) processing, but the only time this flag
+| * is looked at is after yywrap() is called, so it's safe
+| * to go ahead and always set it.
+| */
+| (yy_did_buffer_switch_on_eof) = 1;
+| }
+|
+| static void yy_load_buffer_state (void)
+| {
+| (yy_n_chars) = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+| (yytext_ptr) = (yy_c_buf_p) = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+| yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+| (yy_hold_char) = *(yy_c_buf_p);
+| }
+|
+| /** Allocate and initialize an input buffer state.
+| * @param file A readable stream.
+| * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+| *
+| * @return the allocated buffer state.
+| */
+| YY_BUFFER_STATE yy_create_buffer (FILE * file, int size )
+| {
+| YY_BUFFER_STATE b;
+|
+| b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+| if ( ! b )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+|
+| b->yy_buf_size = size;
+|
+| /* yy_ch_buf has to be 2 characters longer than the size given because
+| * we need to put in 2 end-of-buffer characters.
+| */
+| b->yy_ch_buf = (char *) yyalloc(b->yy_buf_size + 2 );
+| if ( ! b->yy_ch_buf )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" );
+|
+| b->yy_is_our_buffer = 1;
+|
+| yy_init_buffer(b,file );
+|
+| return b;
+| }
+|
+| /** Destroy the buffer.
+| * @param b a buffer created with yy_create_buffer()
+| *
+| */
+| void yy_delete_buffer (YY_BUFFER_STATE b )
+| {
+|
+| if ( ! b )
+| return;
+|
+| if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+| YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+|
+| if ( b->yy_is_our_buffer )
+| yyfree((void *) b->yy_ch_buf );
+|
+| yyfree((void *) b );
+| }
+|
+| #ifndef __cplusplus
+| extern int isatty (int );
+| #endif /* __cplusplus */
+|
+| /* Initializes or reinitializes a buffer.
+| * This function is sometimes called more than once on the same buffer,
+| * such as during a yyrestart() or at EOF.
+| */
+| static void yy_init_buffer (YY_BUFFER_STATE b, FILE * file )
+|
+| {
+| int oerrno = errno;
+|
+| yy_flush_buffer(b );
+|
+| b->yy_input_file = file;
+| b->yy_fill_buffer = 1;
+|
+| /* If b is the current buffer, then yy_init_buffer was _probably_
+| * called from yyrestart() or through yy_get_next_buffer.
+| * In that case, we don't want to reset the lineno or column.
+| */
+| if (b != YY_CURRENT_BUFFER){
+| b->yy_bs_lineno = 1;
+| b->yy_bs_column = 0;
+| }
+|
+| b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+|
+| errno = oerrno;
+| }
+|
+| /** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+| * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+| *
+| */
+| void yy_flush_buffer (YY_BUFFER_STATE b )
+| {
+| if ( ! b )
+| return;
+|
+| b->yy_n_chars = 0;
+|
+| /* We always need two end-of-buffer characters. The first causes
+| * a transition to the end-of-buffer state. The second causes
+| * a jam in that state.
+| */
+| b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+| b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+|
+| b->yy_buf_pos = &b->yy_ch_buf[0];
+|
+| b->yy_at_bol = 1;
+| b->yy_buffer_status = YY_BUFFER_NEW;
+|
+| if ( b == YY_CURRENT_BUFFER )
+| yy_load_buffer_state( );
+| }
+|
+| /** Pushes the new state onto the stack. The new state becomes
+| * the current state. This function will allocate the stack
+| * if necessary.
+| * @param new_buffer The new state.
+| *
+| */
+| void yypush_buffer_state (YY_BUFFER_STATE new_buffer )
+| {
+| if (new_buffer == NULL)
+| return;
+|
+| yyensure_buffer_stack();
+|
+| /* This block is copied from yy_switch_to_buffer. */
+| if ( YY_CURRENT_BUFFER )
+| {
+| /* Flush out information for old buffer. */
+| *(yy_c_buf_p) = (yy_hold_char);
+| YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = (yy_c_buf_p);
+| YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
+| }
+|
+| /* Only push if top exists. Otherwise, replace top. */
+| if (YY_CURRENT_BUFFER)
+| (yy_buffer_stack_top)++;
+| YY_CURRENT_BUFFER_LVALUE = new_buffer;
+|
+| /* copied from yy_switch_to_buffer. */
+| yy_load_buffer_state( );
+| (yy_did_buffer_switch_on_eof) = 1;
+| }
+|
+| /** Removes and deletes the top of the stack, if present.
+| * The next element becomes the new top.
+| *
+| */
+| void yypop_buffer_state (void)
+| {
+| if (!YY_CURRENT_BUFFER)
+| return;
+|
+| yy_delete_buffer(YY_CURRENT_BUFFER );
+| YY_CURRENT_BUFFER_LVALUE = NULL;
+| if ((yy_buffer_stack_top) > 0)
+| --(yy_buffer_stack_top);
+|
+| if (YY_CURRENT_BUFFER) {
+| yy_load_buffer_state( );
+| (yy_did_buffer_switch_on_eof) = 1;
+| }
+| }
+|
+| /* Allocates the stack if it does not exist.
+| * Guarantees space for at least one push.
+| */
+| static void yyensure_buffer_stack (void)
+| {
+| yy_size_t num_to_alloc;
+|
+| if (!(yy_buffer_stack)) {
+|
+| /* First allocation is just for 2 elements, since we don't know if this
+| * scanner will even need a stack. We use 2 instead of 1 to avoid an
+| * immediate realloc on the next call.
+| */
+| num_to_alloc = 1;
+| (yy_buffer_stack) = (struct yy_buffer_state**)yyalloc
+| (num_to_alloc * sizeof(struct yy_buffer_state*)
+| );
+| if ( ! (yy_buffer_stack) )
+| YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+|
+| memset((yy_buffer_stack), 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+|
+| (yy_buffer_stack_max) = num_to_alloc;
+| (yy_buffer_stack_top) = 0;
+| return;
+| }
+|
+| if ((yy_buffer_stack_top) >= ((yy_buffer_stack_max)) - 1){
+|
+| /* Increase the buffer to prepare for a possible push. */
+| int grow_size = 8 /* arbitrary grow size */;
+|
+| num_to_alloc = (yy_buffer_stack_max) + grow_size;
+| (yy_buffer_stack) = (struct yy_buffer_state**)yyrealloc
+| ((yy_buffer_stack),
+| num_to_alloc * sizeof(struct yy_buffer_state*)
+| );
+| if ( ! (yy_buffer_stack) )
+| YY_FATAL_ERROR( "out of dynamic memory in yyensure_buffer_stack()" );
+|
+| /* zero only the new slots.*/
+| memset((yy_buffer_stack) + (yy_buffer_stack_max), 0, grow_size * sizeof(struct yy_buffer_state*));
+| (yy_buffer_stack_max) = num_to_alloc;
+| }
+| }
+|
+| /** Setup the input buffer state to scan directly from a user-specified character buffer.
+| * @param base the character buffer
+| * @param size the size in bytes of the character buffer
+| *
+| * @return the newly allocated buffer state object.
+| */
+| YY_BUFFER_STATE yy_scan_buffer (char * base, yy_size_t size )
+| {
+| YY_BUFFER_STATE b;
+|
+| if ( size < 2 ||
+| base[size-2] != YY_END_OF_BUFFER_CHAR ||
+| base[size-1] != YY_END_OF_BUFFER_CHAR )
+| /* They forgot to leave room for the EOB's. */
+| return 0;
+|
+| b = (YY_BUFFER_STATE) yyalloc(sizeof( struct yy_buffer_state ) );
+| if ( ! b )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" );
+|
+| b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+| b->yy_buf_pos = b->yy_ch_buf = base;
+| b->yy_is_our_buffer = 0;
+| b->yy_input_file = 0;
+| b->yy_n_chars = b->yy_buf_size;
+| b->yy_is_interactive = 0;
+| b->yy_at_bol = 1;
+| b->yy_fill_buffer = 0;
+| b->yy_buffer_status = YY_BUFFER_NEW;
+|
+| yy_switch_to_buffer(b );
+|
+| return b;
+| }
+|
+| /** Setup the input buffer state to scan a string. The next call to yylex() will
+| * scan from a @e copy of @a str.
+| * @param yystr a NUL-terminated string to scan
+| *
+| * @return the newly allocated buffer state object.
+| * @note If you want to scan bytes that may contain NUL values, then use
+| * yy_scan_bytes() instead.
+| */
+| YY_BUFFER_STATE yy_scan_string (yyconst char * yystr )
+| {
+|
+| return yy_scan_bytes(yystr,strlen(yystr) );
+| }
+|
+| /** Setup the input buffer state to scan the given bytes. The next call to yylex() will
+| * scan from a @e copy of @a bytes.
+| * @param bytes the byte buffer to scan
+| * @param len the number of bytes in the buffer pointed to by @a bytes.
+| *
+| * @return the newly allocated buffer state object.
+| */
+| YY_BUFFER_STATE yy_scan_bytes (yyconst char * yybytes, yy_size_t _yybytes_len )
+| {
+| YY_BUFFER_STATE b;
+| char *buf;
+| yy_size_t n, i;
+|
+| /* Get memory for full buffer, including space for trailing EOB's. */
+| n = _yybytes_len + 2;
+| buf = (char *) yyalloc(n );
+| if ( ! buf )
+| YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" );
+|
+| for ( i = 0; i < _yybytes_len; ++i )
+| buf[i] = yybytes[i];
+|
+| buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+|
+| b = yy_scan_buffer(buf,n );
+| if ( ! b )
+| YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" );
+|
+| /* It's okay to grow etc. this buffer, and we should throw it
+| * away when we're done.
+| */
+| b->yy_is_our_buffer = 1;
+|
+| return b;
+| }
+|
+| #ifndef YY_EXIT_FAILURE
+| #define YY_EXIT_FAILURE 2
+| #endif
+|
+| static void yy_fatal_error (yyconst char* msg )
+| {
+| (void) fprintf( stderr, "%s\n", msg );
+| exit( YY_EXIT_FAILURE );
+| }
+|
+| /* Redefine yyless() so it works in section 3 code. */
+|
+| #undef yyless
+| #define yyless(n) \
+| do \
+| { \
+| /* Undo effects of setting up yytext. */ \
+| int yyless_macro_arg = (n); \
+| YY_LESS_LINENO(yyless_macro_arg);\
+| yytext[yyleng] = (yy_hold_char); \
+| (yy_c_buf_p) = yytext + yyless_macro_arg; \
+| (yy_hold_char) = *(yy_c_buf_p); \
+| *(yy_c_buf_p) = '\0'; \
+| yyleng = yyless_macro_arg; \
+| } \
+| while ( 0 )
+|
+| /* Accessor methods (get/set functions) to struct members. */
+|
+| /** Get the current line number.
+| *
+| */
+| int yyget_lineno (void)
+| {
+|
+| return yylineno;
+| }
+|
+| /** Get the input stream.
+| *
+| */
+| FILE *yyget_in (void)
+| {
+| return yyin;
+| }
+|
+| /** Get the output stream.
+| *
+| */
+| FILE *yyget_out (void)
+| {
+| return yyout;
+| }
+|
+| /** Get the length of the current token.
+| *
+| */
+| yy_size_t yyget_leng (void)
+| {
+| return yyleng;
+| }
+|
+| /** Get the current token.
+| *
+| */
+|
+| char *yyget_text (void)
+| {
+| return yytext;
+| }
+|
+| /** Set the current line number.
+| * @param line_number
+| *
+| */
+| void yyset_lineno (int line_number )
+| {
+|
+| yylineno = line_number;
+| }
+|
+| /** Set the input stream. This does not discard the current
+| * input buffer.
+| * @param in_str A readable stream.
+| *
+| * @see yy_switch_to_buffer
+| */
+| void yyset_in (FILE * in_str )
+| {
+| yyin = in_str ;
+| }
+|
+| void yyset_out (FILE * out_str )
+| {
+| yyout = out_str ;
+| }
+|
+| int yyget_debug (void)
+| {
+| return yy_flex_debug;
+| }
+|
+| void yyset_debug (int bdebug )
+| {
+| yy_flex_debug = bdebug ;
+| }
+|
+| static int yy_init_globals (void)
+| {
+| /* Initialization is the same as for the non-reentrant scanner.
+| * This function is called from yylex_destroy(), so don't allocate here.
+| */
+|
+| (yy_buffer_stack) = 0;
+| (yy_buffer_stack_top) = 0;
+| (yy_buffer_stack_max) = 0;
+| (yy_c_buf_p) = (char *) 0;
+| (yy_init) = 0;
+| (yy_start) = 0;
+|
+| (yy_state_buf) = 0;
+| (yy_state_ptr) = 0;
+| (yy_full_match) = 0;
+| (yy_lp) = 0;
+|
+| /* Defined in main.c */
+| #ifdef YY_STDINIT
+| yyin = stdin;
+| yyout = stdout;
+| #else
+| yyin = (FILE *) 0;
+| yyout = (FILE *) 0;
+| #endif
+|
+| /* For future reference: Set errno on error, since we are called by
+| * yylex_init()
+| */
+| return 0;
+| }
+|
+| /* yylex_destroy is for both reentrant and non-reentrant scanners. */
+| int yylex_destroy (void)
+| {
+|
+| /* Pop the buffer stack, destroying each element. */
+| while(YY_CURRENT_BUFFER){
+| yy_delete_buffer(YY_CURRENT_BUFFER );
+| YY_CURRENT_BUFFER_LVALUE = NULL;
+| yypop_buffer_state();
+| }
+|
+| /* Destroy the stack itself. */
+| yyfree((yy_buffer_stack) );
+| (yy_buffer_stack) = NULL;
+|
+| yyfree ( (yy_state_buf) );
+| (yy_state_buf) = NULL;
+|
+| /* Reset the globals. This is important in a non-reentrant scanner so the next time
+| * yylex() is called, initialization will occur. */
+| yy_init_globals( );
+|
+| return 0;
+| }
+|
+| /*
+| * Internal utility routines.
+| */
+|
+| #ifndef yytext_ptr
+| static void yy_flex_strncpy (char* s1, yyconst char * s2, int n )
+| {
+| register int i;
+| for ( i = 0; i < n; ++i )
+| s1[i] = s2[i];
+| }
+| #endif
+|
+| #ifdef YY_NEED_STRLEN
+| static int yy_flex_strlen (yyconst char * s )
+| {
+| register int n;
+| for ( n = 0; s[n]; ++n )
+| ;
+|
+| return n;
+| }
+| #endif
+|
+| void *yyalloc (yy_size_t size )
+| {
+| return (void *) malloc( size );
+| }
+|
+| void *yyrealloc (void * ptr, yy_size_t size )
+| {
+| /* The cast to (char *) in the following accommodates both
+| * implementations that use char* generic pointers, and those
+| * that use void* generic pointers. It works with the latter
+| * because both ANSI C and C++ allow castless assignment from
+| * any pointer type to void*, and deal with argument conversions
+| * as though doing an assignment.
+| */
+| return (void *) realloc( (char *) ptr, size );
+| }
+|
+| void yyfree (void * ptr )
+| {
+| free( (char *) ptr ); /* see yyrealloc() for (char *) cast */
+| }
+|
+| #define YYTABLES_NAME "yytables"
+|
+| #line 10 "conftest.l"
+|
+|
+| #ifdef YYTEXT_POINTER
+| extern char *yytext;
+| #endif
+| int
+| main (void)
+| {
+| return ! yylex () + ! yywrap ();
+| }
+configure:8025: gcc -o conftest -g -O2 conftest.c -ll >&5
+configure:8025: $? = 0
+configure:8035: result: -ll
+configure:8041: checking whether yytext is a pointer
+configure:8058: gcc -o conftest -g -O2 conftest.c -ll >&5
+configure:8058: $? = 0
+configure:8066: result: yes
+configure:8084: checking for capable lex
+configure:8095: result: yes
+configure:8109: checking for bison
+configure:8125: found /usr/bin/bison
+configure:8136: result: bison -y
+configure:8153: checking for capable yacc/bison
+configure:8164: result: yes
+configure:8351: checking whether building for 32-bit x86 is supported
+configure:8366: gcc -c -g -O2 -arch i386 conftest.c >&5
+configure:8366: $? = 0
+configure:8368: result: yes
+configure:8620: checking for ranlib
+configure:8636: found /usr/bin/ranlib
+configure:8647: result: ranlib
+configure:8712: checking for ar
+configure:8728: found /usr/bin/ar
+configure:8739: result: ar
+configure:8762: checking whether ln -s works
+configure:8766: result: yes
+configure:10211: checking for struct sockaddr.sa_len
+configure:10211: gcc -c -g -O2 conftest.c >&5
+configure:10211: $? = 0
+configure:10211: result: yes
+configure:10229: checking for struct sockaddr_storage
+configure:10229: gcc -c -g -O2 conftest.c >&5
+configure:10229: $? = 0
+configure:10229: gcc -c -g -O2 conftest.c >&5
+conftest.c:55:38: error: expected expression
+if (sizeof ((struct sockaddr_storage)))
+ ^
+1 error generated.
+configure:10229: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| #define YYTEXT_POINTER 1
+| #define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+| /* end confdefs.h. */
+|
+| #include <sys/types.h>
+| #include <sys/socket.h>
+|
+|
+| int
+| main ()
+| {
+| if (sizeof ((struct sockaddr_storage)))
+| return 0;
+| ;
+| return 0;
+| }
+configure:10229: result: yes
+configure:10255: checking for dl_hp_ppa_info_t.dl_module_id_1
+configure:10255: gcc -c -g -O2 conftest.c >&5
+conftest.c:50:11: fatal error: 'sys/dlpi.h' file not found
+ #include <sys/dlpi.h>
+ ^~~~~~~~~~~~
+1 error generated.
+configure:10255: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| #define YYTEXT_POINTER 1
+| #define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+| #define HAVE_STRUCT_SOCKADDR_STORAGE 1
+| /* end confdefs.h. */
+|
+| #include <sys/types.h>
+| #include <sys/dlpi.h>
+| #include <sys/dlpi_ext.h>
+|
+|
+| int
+| main ()
+| {
+| static dl_hp_ppa_info_t ac_aggr;
+| if (ac_aggr.dl_module_id_1)
+| return 0;
+| ;
+| return 0;
+| }
+configure:10255: gcc -c -g -O2 conftest.c >&5
+conftest.c:50:11: fatal error: 'sys/dlpi.h' file not found
+ #include <sys/dlpi.h>
+ ^~~~~~~~~~~~
+1 error generated.
+configure:10255: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| #define YYTEXT_POINTER 1
+| #define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+| #define HAVE_STRUCT_SOCKADDR_STORAGE 1
+| /* end confdefs.h. */
+|
+| #include <sys/types.h>
+| #include <sys/dlpi.h>
+| #include <sys/dlpi_ext.h>
+|
+|
+| int
+| main ()
+| {
+| static dl_hp_ppa_info_t ac_aggr;
+| if (sizeof ac_aggr.dl_module_id_1)
+| return 0;
+| ;
+| return 0;
+| }
+configure:10255: result: no
+configure:10271: checking if unaligned accesses fail
+configure:10358: result: no
+configure:10411: checking for USB sniffing support
+configure:10515: result: no
+configure:10524: checking whether the platform could support netfilter sniffing
+configure:10582: result: no
+configure:10605: checking whether we can compile the netmap support
+configure:10624: gcc -c -g -O2 conftest.c >&5
+conftest.c:83:10: fatal error: 'net/netmap_user.h' file not found
+#include <net/netmap_user.h>
+ ^~~~~~~~~~~~~~~~~~~
+1 error generated.
+configure:10624: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| #define YYTEXT_POINTER 1
+| #define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+| #define HAVE_STRUCT_SOCKADDR_STORAGE 1
+| /* end confdefs.h. */
+|
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #define NETMAP_WITH_LIBS
+| #include <net/netmap_user.h>
+| int
+| main ()
+| {
+|
+| ;
+| return 0;
+| }
+configure:10632: result: no
+configure:10760: no Bluetooth sniffing support implemented for darwin19.0.0
+configure:10935: checking for ibv_get_device_list in -libverbs
+configure:10960: gcc -o conftest -g -O2 conftest.c -libverbs >&5
+ld: library not found for -libverbs
+clang: error: linker command failed with exit code 1 (use -v to see invocation)
+configure:10960: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "pcap"
+| #define PACKAGE_TARNAME "pcap"
+| #define PACKAGE_VERSION "1.9.1"
+| #define PACKAGE_STRING "pcap 1.9.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define inline inline
+| #define HAVE_FSEEKO 1
+| #define STDC_HEADERS 1
+| #define HAVE_SYS_TYPES_H 1
+| #define HAVE_SYS_STAT_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_MEMORY_H 1
+| #define HAVE_STRINGS_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_UNISTD_H 1
+| #define HAVE_SYS_IOCCOM_H 1
+| #define HAVE_SYS_SOCKIO_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STRERROR 1
+| #define HAVE_POSIX_STRERROR_R /**/
+| #define HAVE_VSYSLOG 1
+| #define HAVE_VSNPRINTF 1
+| #define HAVE_SNPRINTF 1
+| #define HAVE_VASPRINTF 1
+| #define HAVE_ASPRINTF 1
+| #define HAVE_STRLCAT 1
+| #define HAVE_STRLCPY 1
+| #define HAVE_STRTOK_R 1
+| #define HAVE_FFS 1
+| #define STRINGS_H_DECLARES_FFS /**/
+| #define HAVE_ETHER_HOSTTON 1
+| #define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+| #define HAVE_DECL_ETHER_HOSTTON 1
+| #define HAVE_NET_BPF_H 1
+| #define HAVE_NET_IF_MEDIA_H 1
+| #define HAVE_STRUCT_BPF_TIMEVAL 1
+| #define PCAP_SUPPORT_PACKET_RING 1
+| #define HAVE_SOCKLEN_T 1
+| #define INET6 1
+| #define YYTEXT_POINTER 1
+| #define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+| #define HAVE_STRUCT_SOCKADDR_STORAGE 1
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char ibv_get_device_list ();
+| int
+| main ()
+| {
+| return ibv_get_device_list ();
+| ;
+| return 0;
+| }
+configure:10969: result: no
+configure:11049: checking for a BSD-compatible install
+configure:11117: result: /usr/bin/install -c
+configure:11250: creating ./config.status
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by pcap config.status 1.9.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status
+
+on lubet1.local
+
+config.status:930: creating Makefile
+config.status:930: creating pcap-filter.manmisc
+config.status:930: creating pcap-linktype.manmisc
+config.status:930: creating pcap-tstamp.manmisc
+config.status:930: creating pcap-savefile.manfile
+config.status:930: creating pcap.3pcap
+config.status:930: creating pcap_compile.3pcap
+config.status:930: creating pcap_datalink.3pcap
+config.status:930: creating pcap_dump_open.3pcap
+config.status:930: creating pcap_get_tstamp_precision.3pcap
+config.status:930: creating pcap_list_datalinks.3pcap
+config.status:930: creating pcap_list_tstamp_types.3pcap
+config.status:930: creating pcap_open_dead.3pcap
+config.status:930: creating pcap_open_offline.3pcap
+config.status:930: creating pcap_set_immediate_mode.3pcap
+config.status:930: creating pcap_set_tstamp_precision.3pcap
+config.status:930: creating pcap_set_tstamp_type.3pcap
+config.status:930: creating rpcapd/Makefile
+config.status:930: creating rpcapd/rpcapd.manadmin
+config.status:930: creating rpcapd/rpcapd-config.manfile
+config.status:930: creating testprogs/Makefile
+config.status:930: creating config.h
+config.status:1119: executing default-1 commands
+
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+
+ac_cv_build=x86_64-apple-darwin19.0.0
+ac_cv_c_compiler_gnu=yes
+ac_cv_env_CC_set=
+ac_cv_env_CC_value=
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_LIBS_set=
+ac_cv_env_LIBS_value=
+ac_cv_env_YACC_set=
+ac_cv_env_YACC_value=
+ac_cv_env_YFLAGS_set=
+ac_cv_env_YFLAGS_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=
+ac_cv_env_host_alias_value=
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_func_asprintf=yes
+ac_cv_func_ether_hostton=yes
+ac_cv_func_ffs=yes
+ac_cv_func_getaddrinfo=yes
+ac_cv_func_getifaddrs=yes
+ac_cv_func_pthread_create=yes
+ac_cv_func_snprintf=yes
+ac_cv_func_strerror=yes
+ac_cv_func_strerror_r=yes
+ac_cv_func_strlcat=yes
+ac_cv_func_strlcpy=yes
+ac_cv_func_strtok_r=yes
+ac_cv_func_vasprintf=yes
+ac_cv_func_vsnprintf=yes
+ac_cv_func_vsyslog=yes
+ac_cv_have_decl_ether_hostton=yes
+ac_cv_have_decl_ffs=yes
+ac_cv_have_decl_getnetbyname_r=no
+ac_cv_have_decl_getprotobyname_r=no
+ac_cv_header_dagapi_h=no
+ac_cv_header_ifaddrs_h=yes
+ac_cv_header_inttypes_h=yes
+ac_cv_header_limits_h=yes
+ac_cv_header_linux_socket_h=no
+ac_cv_header_memory_h=yes
+ac_cv_header_net_bpf_h=yes
+ac_cv_header_net_enet_h=no
+ac_cv_header_net_if_media_h=yes
+ac_cv_header_net_nit_h=no
+ac_cv_header_net_pfilt_h=no
+ac_cv_header_net_pfvar_h=no
+ac_cv_header_net_raw_h=no
+ac_cv_header_netpacket_packet_h=no
+ac_cv_header_pthread_h=yes
+ac_cv_header_stdc=yes
+ac_cv_header_stdint_h=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=yes
+ac_cv_header_sys_dlpi_h=no
+ac_cv_header_sys_ioccom_h=yes
+ac_cv_header_sys_net_nit_h=no
+ac_cv_header_sys_sockio_h=yes
+ac_cv_header_sys_stat_h=yes
+ac_cv_header_sys_types_h=yes
+ac_cv_header_unistd_h=yes
+ac_cv_host=x86_64-apple-darwin19.0.0
+ac_cv_lbl_bpf_h_defines_biocsetif=yes
+ac_cv_lbl_gcc_fixincludes=yes
+ac_cv_lbl_inline=inline
+ac_cv_lbl_septel_api=no
+ac_cv_lbl_snf_api=no
+ac_cv_lbl_turbocap_api=no
+ac_cv_lbl_unaligned_fail=no
+ac_cv_lib_ibverbs_ibv_get_device_list=no
+ac_cv_lib_lex=-ll
+ac_cv_member_dl_hp_ppa_info_t_dl_module_id_1=no
+ac_cv_member_struct_sockaddr_sa_len=yes
+ac_cv_net_netmap_user_can_compile=no
+ac_cv_objext=o
+ac_cv_path_EGREP='/usr/bin/grep -E'
+ac_cv_path_GREP=/usr/bin/grep
+ac_cv_path_install='/usr/bin/install -c'
+ac_cv_prog_CPP='gcc -E'
+ac_cv_prog_LEX=flex
+ac_cv_prog_YACC='bison -y'
+ac_cv_prog_ac_ct_AR=ar
+ac_cv_prog_ac_ct_CC=gcc
+ac_cv_prog_ac_ct_RANLIB=ranlib
+ac_cv_prog_cc_c89=
+ac_cv_prog_cc_c99=
+ac_cv_prog_cc_g=yes
+ac_cv_prog_lex_root=lex.yy
+ac_cv_prog_lex_yytext_pointer=yes
+ac_cv_search_putmsg=no
+ac_cv_sys_file_offset_bits=no
+ac_cv_sys_largefile_CC=no
+ac_cv_sys_largefile_source=no
+ac_cv_target=x86_64-apple-darwin19.0.0
+ac_cv_type_socklen_t=yes
+ac_cv_type_struct_BPF_TIMEVAL=yes
+ac_cv_type_struct_sockaddr_storage=yes
+tcpdump_cv_capable_lex=yes
+tcpdump_cv_capable_yacc=yes
+
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+
+ADDLARCHIVEOBJS=''
+ADDLOBJS=''
+AR='ar'
+BT_MONITOR_SRC=''
+BT_SRC=''
+BUILD_RPCAPD=''
+CC='gcc'
+CFLAGS='-g -O2'
+CPP='gcc -E'
+CPPFLAGS=''
+DBUS_SRC=''
+DEFS='-DHAVE_CONFIG_H'
+DEPENDENCY_CFLAG=''
+DYEXT='dylib'
+ECHO_C='\c'
+ECHO_N=''
+ECHO_T=''
+EGREP='/usr/bin/grep -E'
+EXEEXT=''
+EXTRA_NETWORK_LIBS=''
+GREP='/usr/bin/grep'
+INSTALL_DATA='${INSTALL} -m 644'
+INSTALL_PROGRAM='${INSTALL}'
+INSTALL_RPCAPD=''
+INSTALL_SCRIPT='${INSTALL}'
+LDFLAGS=''
+LEX='flex'
+LEXLIB='-ll'
+LEX_OUTPUT_ROOT='lex.yy'
+LIBOBJS=''
+LIBS=''
+LN_S='ln -s'
+LTLIBOBJS=''
+MAN_ADMIN_COMMANDS='8'
+MAN_DEVICES='4'
+MAN_FILE_FORMATS='5'
+MAN_MISC_INFO='7'
+MKDEP=''
+NETFILTER_SRC=''
+NETMAP_SRC=''
+OBJEXT='o'
+PACKAGE_BUGREPORT=''
+PACKAGE_NAME='pcap'
+PACKAGE_STRING='pcap 1.9.1'
+PACKAGE_TARNAME='pcap'
+PACKAGE_URL=''
+PACKAGE_VERSION='1.9.1'
+PATH_SEPARATOR=':'
+PCAP_SUPPORT_BT=''
+PCAP_SUPPORT_DBUS=''
+PCAP_SUPPORT_NETFILTER=''
+PCAP_SUPPORT_NETMAP=''
+PCAP_SUPPORT_PACKET_RING=''
+PCAP_SUPPORT_RDMASNIFF=''
+PCAP_SUPPORT_USB=''
+PKGCONFIG=''
+PTHREAD_LIBS=''
+RANLIB='ranlib'
+RDMA_SRC=''
+RPCAPD_LIBS=''
+SHELL='/bin/sh'
+SHLICC2=''
+SSRC=''
+USB_SRC=''
+VALGRINDTEST_SRC='valgrindtest.c'
+V_CCOPT=' -fvisibility=hidden -fno-common'
+V_DEFS=''
+V_FINDALLDEVS='fad-getad.c'
+V_INCLS=' -I/usr/local/include'
+V_LEX=''
+V_LIB_CCOPT_FAT='-arch x86_64 -arch i386'
+V_LIB_LDFLAGS_FAT='-arch x86_64 -arch i386'
+V_PCAP='bpf'
+V_PROG_CCOPT_FAT=''
+V_PROG_LDFLAGS_FAT=''
+V_RPATH_OPT=''
+V_SHLIB_CCOPT=''
+V_SHLIB_CMD='$(CC)'
+V_SHLIB_OPT='-shared'
+V_SONAME_OPT=''
+V_YACC=''
+YACC='bison -y'
+YFLAGS=''
+ac_ct_CC='gcc'
+bindir='${exec_prefix}/bin'
+build='x86_64-apple-darwin19.0.0'
+build_alias=''
+build_cpu='x86_64'
+build_os='darwin19.0.0'
+build_vendor='apple'
+datadir='${datarootdir}'
+datarootdir='${prefix}/share'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+dvidir='${docdir}'
+exec_prefix='${prefix}'
+host='x86_64-apple-darwin19.0.0'
+host_alias=''
+host_cpu='x86_64'
+host_os='darwin19.0.0'
+host_vendor='apple'
+htmldir='${docdir}'
+includedir='${prefix}/include'
+infodir='${datarootdir}/info'
+libdir='${exec_prefix}/lib'
+libexecdir='${exec_prefix}/libexec'
+localedir='${datarootdir}/locale'
+localstatedir='${prefix}/var'
+mandir='${datarootdir}/man'
+oldincludedir='/usr/include'
+pdfdir='${docdir}'
+prefix='/usr/local'
+program_transform_name='s,x,x,'
+psdir='${docdir}'
+runstatedir='${localstatedir}/run'
+sbindir='${exec_prefix}/sbin'
+sharedstatedir='${prefix}/com'
+sysconfdir='${prefix}/etc'
+target='x86_64-apple-darwin19.0.0'
+target_alias=''
+target_cpu='x86_64'
+target_os='darwin19.0.0'
+target_vendor='apple'
+
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+
+/* confdefs.h */
+#define PACKAGE_NAME "pcap"
+#define PACKAGE_TARNAME "pcap"
+#define PACKAGE_VERSION "1.9.1"
+#define PACKAGE_STRING "pcap 1.9.1"
+#define PACKAGE_BUGREPORT ""
+#define PACKAGE_URL ""
+#define inline inline
+#define HAVE_FSEEKO 1
+#define STDC_HEADERS 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_SYS_STAT_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_MEMORY_H 1
+#define HAVE_STRINGS_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_UNISTD_H 1
+#define HAVE_SYS_IOCCOM_H 1
+#define HAVE_SYS_SOCKIO_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_STRERROR 1
+#define HAVE_POSIX_STRERROR_R /**/
+#define HAVE_VSYSLOG 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_SNPRINTF 1
+#define HAVE_VASPRINTF 1
+#define HAVE_ASPRINTF 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRTOK_R 1
+#define HAVE_FFS 1
+#define STRINGS_H_DECLARES_FFS /**/
+#define HAVE_ETHER_HOSTTON 1
+#define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/
+#define HAVE_DECL_ETHER_HOSTTON 1
+#define HAVE_NET_BPF_H 1
+#define HAVE_NET_IF_MEDIA_H 1
+#define HAVE_STRUCT_BPF_TIMEVAL 1
+#define PCAP_SUPPORT_PACKET_RING 1
+#define HAVE_SOCKLEN_T 1
+#define INET6 1
+#define YYTEXT_POINTER 1
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+
+configure: exit 0
diff --git a/lib/libpcap/libpcap/config.status b/lib/libpcap/libpcap/config.status
new file mode 100755
index 0000000..451d42b
--- /dev/null
+++ b/lib/libpcap/libpcap/config.status
@@ -0,0 +1,1136 @@
+#! /bin/sh
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by pcap $as_me 1.9.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+# Files that config.status was made for.
+config_files=" Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_immediate_mode.3pcap pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin rpcapd/rpcapd-config.manfile testprogs/Makefile"
+config_headers=" config.h"
+config_commands=" default-1"
+
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+ac_cs_config=""
+ac_cs_version="\
+pcap config.status 1.9.1
+configured by ./configure, generated by GNU Autoconf 2.69,
+ with options \"$ac_cs_config\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='/Users/local/Downloads/Problem 55855678/libpcap-1.9.1'
+srcdir='.'
+INSTALL='/usr/bin/install -c'
+test -n "$AWK" || AWK=awk
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+if $ac_cs_recheck; then
+ set X /bin/sh './configure' $ac_configure_extra_args --no-create --no-recursion
+ shift
+ $as_echo "running CONFIG_SHELL=/bin/sh $*" >&6
+ CONFIG_SHELL='/bin/sh'
+ export CONFIG_SHELL
+ exec "$@"
+fi
+
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+#
+# INIT-COMMANDS
+#
+
+
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "pcap-filter.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-filter.manmisc" ;;
+ "pcap-linktype.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-linktype.manmisc" ;;
+ "pcap-tstamp.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-tstamp.manmisc" ;;
+ "pcap-savefile.manfile") CONFIG_FILES="$CONFIG_FILES pcap-savefile.manfile" ;;
+ "pcap.3pcap") CONFIG_FILES="$CONFIG_FILES pcap.3pcap" ;;
+ "pcap_compile.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_compile.3pcap" ;;
+ "pcap_datalink.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_datalink.3pcap" ;;
+ "pcap_dump_open.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_dump_open.3pcap" ;;
+ "pcap_get_tstamp_precision.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_get_tstamp_precision.3pcap" ;;
+ "pcap_list_datalinks.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_datalinks.3pcap" ;;
+ "pcap_list_tstamp_types.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_tstamp_types.3pcap" ;;
+ "pcap_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;;
+ "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;;
+ "pcap_set_immediate_mode.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_immediate_mode.3pcap" ;;
+ "pcap_set_tstamp_precision.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_precision.3pcap" ;;
+ "pcap_set_tstamp_type.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_type.3pcap" ;;
+ "rpcapd/Makefile") CONFIG_FILES="$CONFIG_FILES rpcapd/Makefile" ;;
+ "rpcapd/rpcapd.manadmin") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd.manadmin" ;;
+ "rpcapd/rpcapd-config.manfile") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd-config.manfile" ;;
+ "testprogs/Makefile") CONFIG_FILES="$CONFIG_FILES testprogs/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+cat >>"$ac_tmp/subs1.awk" <<\_ACAWK &&
+S["LTLIBOBJS"]=""
+S["INSTALL_DATA"]="${INSTALL} -m 644"
+S["INSTALL_SCRIPT"]="${INSTALL}"
+S["INSTALL_PROGRAM"]="${INSTALL}"
+S["RDMA_SRC"]=""
+S["PCAP_SUPPORT_RDMASNIFF"]=""
+S["DBUS_SRC"]=""
+S["PCAP_SUPPORT_DBUS"]=""
+S["PKGCONFIG"]=""
+S["BT_MONITOR_SRC"]=""
+S["BT_SRC"]=""
+S["PCAP_SUPPORT_BT"]=""
+S["NETMAP_SRC"]=""
+S["PCAP_SUPPORT_NETMAP"]=""
+S["NETFILTER_SRC"]=""
+S["PCAP_SUPPORT_NETFILTER"]=""
+S["USB_SRC"]=""
+S["PCAP_SUPPORT_USB"]=""
+S["EXTRA_NETWORK_LIBS"]=""
+S["RPCAPD_LIBS"]=""
+S["INSTALL_RPCAPD"]=""
+S["BUILD_RPCAPD"]=""
+S["PTHREAD_LIBS"]=""
+S["MAN_ADMIN_COMMANDS"]="8"
+S["MAN_MISC_INFO"]="7"
+S["MAN_FILE_FORMATS"]="5"
+S["MAN_DEVICES"]="4"
+S["DYEXT"]="dylib"
+S["SSRC"]=""
+S["ADDLARCHIVEOBJS"]=""
+S["ADDLOBJS"]=""
+S["V_YACC"]=""
+S["V_RPATH_OPT"]=""
+S["V_SONAME_OPT"]=""
+S["V_SHLIB_OPT"]="-shared"
+S["V_SHLIB_CMD"]="$(CC)"
+S["V_SHLIB_CCOPT"]=""
+S["V_PCAP"]="bpf"
+S["V_LEX"]=""
+S["V_INCLS"]=" -I/usr/local/include"
+S["V_FINDALLDEVS"]="fad-getad.c"
+S["V_DEFS"]=""
+S["V_PROG_LDFLAGS_FAT"]=""
+S["V_PROG_CCOPT_FAT"]=""
+S["V_LIB_LDFLAGS_FAT"]="-arch x86_64 -arch i386"
+S["V_LIB_CCOPT_FAT"]="-arch x86_64 -arch i386"
+S["V_CCOPT"]=" -fvisibility=hidden -fno-common"
+S["MKDEP"]=""
+S["DEPENDENCY_CFLAG"]=""
+S["LN_S"]="ln -s"
+S["AR"]="ar"
+S["RANLIB"]="ranlib"
+S["YFLAGS"]=""
+S["YACC"]="bison -y"
+S["LEXLIB"]="-ll"
+S["LEX_OUTPUT_ROOT"]="lex.yy"
+S["LEX"]="flex"
+S["PCAP_SUPPORT_PACKET_RING"]=""
+S["VALGRINDTEST_SRC"]="valgrindtest.c"
+S["LIBOBJS"]=""
+S["EGREP"]="/usr/bin/grep -E"
+S["GREP"]="/usr/bin/grep"
+S["CPP"]="gcc -E"
+S["OBJEXT"]="o"
+S["EXEEXT"]=""
+S["ac_ct_CC"]="gcc"
+S["CPPFLAGS"]=""
+S["LDFLAGS"]=""
+S["CFLAGS"]="-g -O2"
+S["CC"]="gcc"
+S["SHLICC2"]=""
+S["target_os"]="darwin19.0.0"
+S["target_vendor"]="apple"
+S["target_cpu"]="x86_64"
+S["target"]="x86_64-apple-darwin19.0.0"
+S["host_os"]="darwin19.0.0"
+S["host_vendor"]="apple"
+S["host_cpu"]="x86_64"
+S["host"]="x86_64-apple-darwin19.0.0"
+S["build_os"]="darwin19.0.0"
+S["build_vendor"]="apple"
+S["build_cpu"]="x86_64"
+S["build"]="x86_64-apple-darwin19.0.0"
+S["target_alias"]=""
+S["host_alias"]=""
+S["build_alias"]=""
+S["LIBS"]=""
+S["ECHO_T"]=""
+S["ECHO_N"]=""
+S["ECHO_C"]="\\c"
+S["DEFS"]="-DHAVE_CONFIG_H"
+S["mandir"]="${datarootdir}/man"
+S["localedir"]="${datarootdir}/locale"
+S["libdir"]="${exec_prefix}/lib"
+S["psdir"]="${docdir}"
+S["pdfdir"]="${docdir}"
+S["dvidir"]="${docdir}"
+S["htmldir"]="${docdir}"
+S["infodir"]="${datarootdir}/info"
+S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}"
+S["oldincludedir"]="/usr/include"
+S["includedir"]="${prefix}/include"
+S["runstatedir"]="${localstatedir}/run"
+S["localstatedir"]="${prefix}/var"
+S["sharedstatedir"]="${prefix}/com"
+S["sysconfdir"]="${prefix}/etc"
+S["datadir"]="${datarootdir}"
+S["datarootdir"]="${prefix}/share"
+S["libexecdir"]="${exec_prefix}/libexec"
+S["sbindir"]="${exec_prefix}/sbin"
+S["bindir"]="${exec_prefix}/bin"
+S["program_transform_name"]="s,x,x,"
+S["prefix"]="/usr/local"
+S["exec_prefix"]="${prefix}"
+S["PACKAGE_URL"]=""
+S["PACKAGE_BUGREPORT"]=""
+S["PACKAGE_STRING"]="pcap 1.9.1"
+S["PACKAGE_VERSION"]="1.9.1"
+S["PACKAGE_TARNAME"]="pcap"
+S["PACKAGE_NAME"]="pcap"
+S["PATH_SEPARATOR"]=":"
+S["SHELL"]="/bin/sh"
+_ACAWK
+cat >>"$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+D["PACKAGE_NAME"]=" \"pcap\""
+D["PACKAGE_TARNAME"]=" \"pcap\""
+D["PACKAGE_VERSION"]=" \"1.9.1\""
+D["PACKAGE_STRING"]=" \"pcap 1.9.1\""
+D["PACKAGE_BUGREPORT"]=" \"\""
+D["PACKAGE_URL"]=" \"\""
+D["inline"]=" inline"
+D["HAVE_FSEEKO"]=" 1"
+D["STDC_HEADERS"]=" 1"
+D["HAVE_SYS_TYPES_H"]=" 1"
+D["HAVE_SYS_STAT_H"]=" 1"
+D["HAVE_STDLIB_H"]=" 1"
+D["HAVE_STRING_H"]=" 1"
+D["HAVE_MEMORY_H"]=" 1"
+D["HAVE_STRINGS_H"]=" 1"
+D["HAVE_INTTYPES_H"]=" 1"
+D["HAVE_STDINT_H"]=" 1"
+D["HAVE_UNISTD_H"]=" 1"
+D["HAVE_SYS_IOCCOM_H"]=" 1"
+D["HAVE_SYS_SOCKIO_H"]=" 1"
+D["HAVE_LIMITS_H"]=" 1"
+D["HAVE_STRERROR"]=" 1"
+D["HAVE_POSIX_STRERROR_R"]=" /**/"
+D["HAVE_VSYSLOG"]=" 1"
+D["HAVE_VSNPRINTF"]=" 1"
+D["HAVE_SNPRINTF"]=" 1"
+D["HAVE_VASPRINTF"]=" 1"
+D["HAVE_ASPRINTF"]=" 1"
+D["HAVE_STRLCAT"]=" 1"
+D["HAVE_STRLCPY"]=" 1"
+D["HAVE_STRTOK_R"]=" 1"
+D["HAVE_FFS"]=" 1"
+D["STRINGS_H_DECLARES_FFS"]=" /**/"
+D["HAVE_ETHER_HOSTTON"]=" 1"
+D["NET_ETHERNET_H_DECLARES_ETHER_HOSTTON"]=" /**/"
+D["HAVE_DECL_ETHER_HOSTTON"]=" 1"
+D["HAVE_NET_BPF_H"]=" 1"
+D["HAVE_NET_IF_MEDIA_H"]=" 1"
+D["HAVE_STRUCT_BPF_TIMEVAL"]=" 1"
+D["PCAP_SUPPORT_PACKET_RING"]=" 1"
+D["HAVE_SOCKLEN_T"]=" 1"
+D["INET6"]=" 1"
+D["YYTEXT_POINTER"]=" 1"
+D["HAVE_STRUCT_SOCKADDR_SA_LEN"]=" 1"
+D["HAVE_STRUCT_SOCKADDR_STORAGE"]=" 1"
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*([\t (]|$)/ {
+ line = $ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ ac_datarootdir_hack='
+ s&@datadir@&${datarootdir}&g
+ s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+ s&@infodir@&${datarootdir}/info&g
+ s&@localedir@&${datarootdir}/locale&g
+ s&@mandir@&${datarootdir}/man&g
+ s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+ac_sed_extra="/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "default-1":C) if test -f .devel; then
+ echo timestamp > stamp-h
+ cat $srcdir/Makefile-devel-adds >> Makefile
+ make depend
+fi ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
diff --git a/lib/libpcap/libpcap/config.sub b/lib/libpcap/libpcap/config.sub
new file mode 100755
index 0000000..c95acc6
--- /dev/null
+++ b/lib/libpcap/libpcap/config.sub
@@ -0,0 +1,1808 @@
+#! /bin/sh
+# Configuration validation subroutine script.
+# Copyright 1992-2018 Free Software Foundation, Inc.
+
+timestamp='2018-07-03'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <https://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program. This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# https://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support. The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Options:
+ -h, --help print this help, then exit
+ -t, --time-stamp print date of last modification, then exit
+ -v, --version print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2018 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+ case $1 in
+ --time-stamp | --time* | -t )
+ echo "$timestamp" ; exit ;;
+ --version | -v )
+ echo "$version" ; exit ;;
+ --help | --h* | -h )
+ echo "$usage"; exit ;;
+ -- ) # Stop option processing
+ shift; break ;;
+ - ) # Use stdin as input.
+ break ;;
+ -* )
+ echo "$me: invalid option $1$help"
+ exit 1 ;;
+
+ *local*)
+ # First pass through any local machine types.
+ echo "$1"
+ exit ;;
+
+ * )
+ break ;;
+ esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+ exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+ exit 1;;
+esac
+
+# Split fields of configuration type
+IFS="-" read -r field1 field2 field3 field4 <<EOF
+$1
+EOF
+
+# Separate into logical components for further validation
+case $1 in
+ *-*-*-*-*)
+ echo Invalid configuration \`"$1"\': more than four components >&2
+ exit 1
+ ;;
+ *-*-*-*)
+ basic_machine=$field1-$field2
+ os=$field3-$field4
+ ;;
+ *-*-*)
+ # Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
+ # parts
+ maybe_os=$field2-$field3
+ case $maybe_os in
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc \
+ | linux-newlib* | linux-musl* | linux-uclibc* | uclinux-uclibc* \
+ | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
+ | netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
+ | storm-chaos* | os2-emx* | rtmk-nova*)
+ basic_machine=$field1
+ os=$maybe_os
+ ;;
+ android-linux)
+ basic_machine=$field1-unknown
+ os=linux-android
+ ;;
+ *)
+ basic_machine=$field1-$field2
+ os=$field3
+ ;;
+ esac
+ ;;
+ *-*)
+ # Second component is usually, but not always the OS
+ case $field2 in
+ # Prevent following clause from handling this valid os
+ sun*os*)
+ basic_machine=$field1
+ os=$field2
+ ;;
+ # Manufacturers
+ dec* | mips* | sequent* | encore* | pc532* | sgi* | sony* \
+ | att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
+ | unicom* | ibm* | next | hp | isi* | apollo | altos* \
+ | convergent* | ncr* | news | 32* | 3600* | 3100* | hitachi* \
+ | c[123]* | convex* | sun | crds | omron* | dg | ultra | tti* \
+ | harris | dolphin | highlevel | gould | cbm | ns | masscomp \
+ | apple | axis | knuth | cray | microblaze* \
+ | sim | cisco | oki | wec | wrs | winbond)
+ basic_machine=$field1-$field2
+ os=
+ ;;
+ *)
+ basic_machine=$field1
+ os=$field2
+ ;;
+ esac
+ ;;
+ *)
+ # Convert single-component short-hands not valid as part of
+ # multi-component configurations.
+ case $field1 in
+ 386bsd)
+ basic_machine=i386-pc
+ os=bsd
+ ;;
+ a29khif)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ adobe68k)
+ basic_machine=m68010-adobe
+ os=scout
+ ;;
+ am29k)
+ basic_machine=a29k-none
+ os=bsd
+ ;;
+ amdahl)
+ basic_machine=580-amdahl
+ os=sysv
+ ;;
+ amigaos | amigados)
+ basic_machine=m68k-unknown
+ os=amigaos
+ ;;
+ amigaunix | amix)
+ basic_machine=m68k-unknown
+ os=sysv4
+ ;;
+ apollo68)
+ basic_machine=m68k-apollo
+ os=sysv
+ ;;
+ apollo68bsd)
+ basic_machine=m68k-apollo
+ os=bsd
+ ;;
+ aros)
+ basic_machine=i386-pc
+ os=aros
+ ;;
+ aux)
+ basic_machine=m68k-apple
+ os=aux
+ ;;
+ balance)
+ basic_machine=ns32k-sequent
+ os=dynix
+ ;;
+ blackfin)
+ basic_machine=bfin-unknown
+ os=linux
+ ;;
+ cegcc)
+ basic_machine=arm-unknown
+ os=cegcc
+ ;;
+ cray)
+ basic_machine=j90-cray
+ os=unicos
+ ;;
+ craynv)
+ basic_machine=craynv-cray
+ os=unicosmp
+ ;;
+ delta88)
+ basic_machine=m88k-motorola
+ os=sysv3
+ ;;
+ dicos)
+ basic_machine=i686-pc
+ os=dicos
+ ;;
+ djgpp)
+ basic_machine=i586-pc
+ os=msdosdjgpp
+ ;;
+ ebmon29k)
+ basic_machine=a29k-amd
+ os=ebmon
+ ;;
+ es1800 | OSE68k | ose68k | ose | OSE)
+ basic_machine=m68k-ericsson
+ os=ose
+ ;;
+ gmicro)
+ basic_machine=tron-gmicro
+ os=sysv
+ ;;
+ go32)
+ basic_machine=i386-pc
+ os=go32
+ ;;
+ h8300hms)
+ basic_machine=h8300-hitachi
+ os=hms
+ ;;
+ h8300xray)
+ basic_machine=h8300-hitachi
+ os=xray
+ ;;
+ h8500hms)
+ basic_machine=h8500-hitachi
+ os=hms
+ ;;
+ harris)
+ basic_machine=m88k-harris
+ os=sysv3
+ ;;
+ hp300bsd)
+ basic_machine=m68k-hp
+ os=bsd
+ ;;
+ hp300hpux)
+ basic_machine=m68k-hp
+ os=hpux
+ ;;
+ hppaosf)
+ basic_machine=hppa1.1-hp
+ os=osf
+ ;;
+ hppro)
+ basic_machine=hppa1.1-hp
+ os=proelf
+ ;;
+ i386mach)
+ basic_machine=i386-mach
+ os=mach
+ ;;
+ vsta)
+ basic_machine=i386-unknown
+ os=vsta
+ ;;
+ isi68 | isi)
+ basic_machine=m68k-isi
+ os=sysv
+ ;;
+ m68knommu)
+ basic_machine=m68k-unknown
+ os=linux
+ ;;
+ magnum | m3230)
+ basic_machine=mips-mips
+ os=sysv
+ ;;
+ merlin)
+ basic_machine=ns32k-utek
+ os=sysv
+ ;;
+ mingw64)
+ basic_machine=x86_64-pc
+ os=mingw64
+ ;;
+ mingw32)
+ basic_machine=i686-pc
+ os=mingw32
+ ;;
+ mingw32ce)
+ basic_machine=arm-unknown
+ os=mingw32ce
+ ;;
+ monitor)
+ basic_machine=m68k-rom68k
+ os=coff
+ ;;
+ morphos)
+ basic_machine=powerpc-unknown
+ os=morphos
+ ;;
+ moxiebox)
+ basic_machine=moxie-unknown
+ os=moxiebox
+ ;;
+ msdos)
+ basic_machine=i386-pc
+ os=msdos
+ ;;
+ msys)
+ basic_machine=i686-pc
+ os=msys
+ ;;
+ mvs)
+ basic_machine=i370-ibm
+ os=mvs
+ ;;
+ nacl)
+ basic_machine=le32-unknown
+ os=nacl
+ ;;
+ ncr3000)
+ basic_machine=i486-ncr
+ os=sysv4
+ ;;
+ netbsd386)
+ basic_machine=i386-unknown
+ os=netbsd
+ ;;
+ netwinder)
+ basic_machine=armv4l-rebel
+ os=linux
+ ;;
+ news | news700 | news800 | news900)
+ basic_machine=m68k-sony
+ os=newsos
+ ;;
+ news1000)
+ basic_machine=m68030-sony
+ os=newsos
+ ;;
+ necv70)
+ basic_machine=v70-nec
+ os=sysv
+ ;;
+ nh3000)
+ basic_machine=m68k-harris
+ os=cxux
+ ;;
+ nh[45]000)
+ basic_machine=m88k-harris
+ os=cxux
+ ;;
+ nindy960)
+ basic_machine=i960-intel
+ os=nindy
+ ;;
+ mon960)
+ basic_machine=i960-intel
+ os=mon960
+ ;;
+ nonstopux)
+ basic_machine=mips-compaq
+ os=nonstopux
+ ;;
+ os400)
+ basic_machine=powerpc-ibm
+ os=os400
+ ;;
+ OSE68000 | ose68000)
+ basic_machine=m68000-ericsson
+ os=ose
+ ;;
+ os68k)
+ basic_machine=m68k-none
+ os=os68k
+ ;;
+ paragon)
+ basic_machine=i860-intel
+ os=osf
+ ;;
+ parisc)
+ basic_machine=hppa-unknown
+ os=linux
+ ;;
+ pw32)
+ basic_machine=i586-unknown
+ os=pw32
+ ;;
+ rdos | rdos64)
+ basic_machine=x86_64-pc
+ os=rdos
+ ;;
+ rdos32)
+ basic_machine=i386-pc
+ os=rdos
+ ;;
+ rom68k)
+ basic_machine=m68k-rom68k
+ os=coff
+ ;;
+ sa29200)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ sei)
+ basic_machine=mips-sei
+ os=seiux
+ ;;
+ sps7)
+ basic_machine=m68k-bull
+ os=sysv2
+ ;;
+ stratus)
+ basic_machine=i860-stratus
+ os=sysv4
+ ;;
+ sun2os3)
+ basic_machine=m68000-sun
+ os=sunos3
+ ;;
+ sun2os4)
+ basic_machine=m68000-sun
+ os=sunos4
+ ;;
+ sun3os3)
+ basic_machine=m68k-sun
+ os=sunos3
+ ;;
+ sun3os4)
+ basic_machine=m68k-sun
+ os=sunos4
+ ;;
+ sun4os3)
+ basic_machine=sparc-sun
+ os=sunos3
+ ;;
+ sun4os4)
+ basic_machine=sparc-sun
+ os=sunos4
+ ;;
+ sun4sol2)
+ basic_machine=sparc-sun
+ os=solaris2
+ ;;
+ sv1)
+ basic_machine=sv1-cray
+ os=unicos
+ ;;
+ symmetry)
+ basic_machine=i386-sequent
+ os=dynix
+ ;;
+ t3e)
+ basic_machine=alphaev5-cray
+ os=unicos
+ ;;
+ t90)
+ basic_machine=t90-cray
+ os=unicos
+ ;;
+ toad1)
+ basic_machine=pdp10-xkl
+ os=tops20
+ ;;
+ tpf)
+ basic_machine=s390x-ibm
+ os=tpf
+ ;;
+ udi29k)
+ basic_machine=a29k-amd
+ os=udi
+ ;;
+ ultra3)
+ basic_machine=a29k-nyu
+ os=sym1
+ ;;
+ v810 | necv810)
+ basic_machine=v810-nec
+ os=none
+ ;;
+ vaxv)
+ basic_machine=vax-dec
+ os=sysv
+ ;;
+ vms)
+ basic_machine=vax-dec
+ os=vms
+ ;;
+ vxworks960)
+ basic_machine=i960-wrs
+ os=vxworks
+ ;;
+ vxworks68)
+ basic_machine=m68k-wrs
+ os=vxworks
+ ;;
+ vxworks29k)
+ basic_machine=a29k-wrs
+ os=vxworks
+ ;;
+ xbox)
+ basic_machine=i686-pc
+ os=mingw32
+ ;;
+ ymp)
+ basic_machine=ymp-cray
+ os=unicos
+ ;;
+ *)
+ basic_machine=$1
+ os=
+ ;;
+ esac
+ ;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+ # Recognize the basic CPU types without company name.
+ # Some are omitted here because they have special meanings below.
+ 1750a | 580 \
+ | a29k \
+ | aarch64 | aarch64_be \
+ | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+ | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+ | am33_2.0 \
+ | arc | arceb \
+ | arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv6m | armv[78][arm] \
+ | avr | avr32 \
+ | ba \
+ | be32 | be64 \
+ | bfin \
+ | c4x | c8051 | clipper | csky \
+ | d10v | d30v | dlx | dsp16xx \
+ | e2k | epiphany \
+ | fido | fr30 | frv | ft32 \
+ | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+ | hexagon \
+ | i370 | i860 | i960 | ia16 | ia64 \
+ | ip2k | iq2000 \
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
+ | m32c | m32r | m32rle | m68000 | m68k | m88k \
+ | maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+ | mips | mipsbe | mipseb | mipsel | mipsle \
+ | mips16 \
+ | mips64 | mips64el \
+ | mips64octeon | mips64octeonel \
+ | mips64orion | mips64orionel \
+ | mips64r5900 | mips64r5900el \
+ | mips64vr | mips64vrel \
+ | mips64vr4100 | mips64vr4100el \
+ | mips64vr4300 | mips64vr4300el \
+ | mips64vr5000 | mips64vr5000el \
+ | mips64vr5900 | mips64vr5900el \
+ | mipsisa32 | mipsisa32el \
+ | mipsisa32r2 | mipsisa32r2el \
+ | mipsisa32r6 | mipsisa32r6el \
+ | mipsisa64 | mipsisa64el \
+ | mipsisa64r2 | mipsisa64r2el \
+ | mipsisa64r6 | mipsisa64r6el \
+ | mipsisa64sb1 | mipsisa64sb1el \
+ | mipsisa64sr71k | mipsisa64sr71kel \
+ | mipsr5900 | mipsr5900el \
+ | mipstx39 | mipstx39el \
+ | mn10200 | mn10300 \
+ | moxie \
+ | mt \
+ | msp430 \
+ | nds32 | nds32le | nds32be \
+ | nfp \
+ | nios | nios2 | nios2eb | nios2el \
+ | ns16k | ns32k \
+ | open8 | or1k | or1knd | or32 \
+ | pdp10 | pj | pjl \
+ | powerpc | powerpc64 | powerpc64le | powerpcle \
+ | pru \
+ | pyramid \
+ | riscv | riscv32 | riscv64 \
+ | rl78 | rx \
+ | score \
+ | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+ | sh64 | sh64le \
+ | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+ | sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+ | spu \
+ | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+ | ubicom32 \
+ | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+ | visium \
+ | wasm32 \
+ | x86 | xc16x | xstormy16 | xtensa \
+ | z8k | z80)
+ basic_machine=$basic_machine-unknown
+ ;;
+ c54x)
+ basic_machine=tic54x-unknown
+ ;;
+ c55x)
+ basic_machine=tic55x-unknown
+ ;;
+ c6x)
+ basic_machine=tic6x-unknown
+ ;;
+ leon|leon[3-9])
+ basic_machine=sparc-$basic_machine
+ ;;
+ m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+ basic_machine=$basic_machine-unknown
+ os=${os:-none}
+ ;;
+ m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65)
+ ;;
+ m9s12z | m68hcs12z | hcs12z | s12z)
+ basic_machine=s12z-unknown
+ os=${os:-none}
+ ;;
+ ms1)
+ basic_machine=mt-unknown
+ ;;
+ strongarm | thumb | xscale)
+ basic_machine=arm-unknown
+ ;;
+ xgate)
+ basic_machine=$basic_machine-unknown
+ os=${os:-none}
+ ;;
+ xscaleeb)
+ basic_machine=armeb-unknown
+ ;;
+
+ xscaleel)
+ basic_machine=armel-unknown
+ ;;
+
+ # We use `pc' rather than `unknown'
+ # because (1) that's what they normally are, and
+ # (2) the word "unknown" tends to confuse beginning users.
+ i*86 | x86_64)
+ basic_machine=$basic_machine-pc
+ ;;
+ # Recognize the basic CPU types with company name.
+ 580-* \
+ | a29k-* \
+ | aarch64-* | aarch64_be-* \
+ | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+ | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+ | alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+ | arm-* | armbe-* | armle-* | armeb-* | armv*-* \
+ | avr-* | avr32-* \
+ | ba-* \
+ | be32-* | be64-* \
+ | bfin-* | bs2000-* \
+ | c[123]* | c30-* | [cjt]90-* | c4x-* \
+ | c8051-* | clipper-* | craynv-* | csky-* | cydra-* \
+ | d10v-* | d30v-* | dlx-* \
+ | e2k-* | elxsi-* \
+ | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+ | h8300-* | h8500-* \
+ | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+ | hexagon-* \
+ | i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+ | ip2k-* | iq2000-* \
+ | k1om-* \
+ | le32-* | le64-* \
+ | lm32-* \
+ | m32c-* | m32r-* | m32rle-* \
+ | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+ | m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+ | microblaze-* | microblazeel-* \
+ | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+ | mips16-* \
+ | mips64-* | mips64el-* \
+ | mips64octeon-* | mips64octeonel-* \
+ | mips64orion-* | mips64orionel-* \
+ | mips64r5900-* | mips64r5900el-* \
+ | mips64vr-* | mips64vrel-* \
+ | mips64vr4100-* | mips64vr4100el-* \
+ | mips64vr4300-* | mips64vr4300el-* \
+ | mips64vr5000-* | mips64vr5000el-* \
+ | mips64vr5900-* | mips64vr5900el-* \
+ | mipsisa32-* | mipsisa32el-* \
+ | mipsisa32r2-* | mipsisa32r2el-* \
+ | mipsisa32r6-* | mipsisa32r6el-* \
+ | mipsisa64-* | mipsisa64el-* \
+ | mipsisa64r2-* | mipsisa64r2el-* \
+ | mipsisa64r6-* | mipsisa64r6el-* \
+ | mipsisa64sb1-* | mipsisa64sb1el-* \
+ | mipsisa64sr71k-* | mipsisa64sr71kel-* \
+ | mipsr5900-* | mipsr5900el-* \
+ | mipstx39-* | mipstx39el-* \
+ | mmix-* \
+ | mt-* \
+ | msp430-* \
+ | nds32-* | nds32le-* | nds32be-* \
+ | nfp-* \
+ | nios-* | nios2-* | nios2eb-* | nios2el-* \
+ | none-* | np1-* | ns16k-* | ns32k-* \
+ | open8-* \
+ | or1k*-* \
+ | orion-* \
+ | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+ | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+ | pru-* \
+ | pyramid-* \
+ | riscv-* | riscv32-* | riscv64-* \
+ | rl78-* | romp-* | rs6000-* | rx-* \
+ | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+ | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+ | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+ | sparclite-* \
+ | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+ | tahoe-* \
+ | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+ | tile*-* \
+ | tron-* \
+ | ubicom32-* \
+ | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+ | vax-* \
+ | visium-* \
+ | wasm32-* \
+ | we32k-* \
+ | x86-* | x86_64-* | xc16x-* | xps100-* \
+ | xstormy16-* | xtensa*-* \
+ | ymp-* \
+ | z8k-* | z80-*)
+ ;;
+ # Recognize the basic CPU types without company name, with glob match.
+ xtensa*)
+ basic_machine=$basic_machine-unknown
+ ;;
+ # Recognize the various machine names and aliases which stand
+ # for a CPU type and a company and sometimes even an OS.
+ 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+ basic_machine=m68000-att
+ ;;
+ 3b*)
+ basic_machine=we32k-att
+ ;;
+ abacus)
+ basic_machine=abacus-unknown
+ ;;
+ alliant | fx80)
+ basic_machine=fx80-alliant
+ ;;
+ altos | altos3068)
+ basic_machine=m68k-altos
+ ;;
+ amd64)
+ basic_machine=x86_64-pc
+ ;;
+ amd64-*)
+ basic_machine=x86_64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ amiga | amiga-*)
+ basic_machine=m68k-unknown
+ ;;
+ asmjs)
+ basic_machine=asmjs-unknown
+ ;;
+ blackfin-*)
+ basic_machine=bfin-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=linux
+ ;;
+ bluegene*)
+ basic_machine=powerpc-ibm
+ os=cnk
+ ;;
+ c54x-*)
+ basic_machine=tic54x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ c55x-*)
+ basic_machine=tic55x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ c6x-*)
+ basic_machine=tic6x-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ c90)
+ basic_machine=c90-cray
+ os=${os:-unicos}
+ ;;
+ convex-c1)
+ basic_machine=c1-convex
+ os=bsd
+ ;;
+ convex-c2)
+ basic_machine=c2-convex
+ os=bsd
+ ;;
+ convex-c32)
+ basic_machine=c32-convex
+ os=bsd
+ ;;
+ convex-c34)
+ basic_machine=c34-convex
+ os=bsd
+ ;;
+ convex-c38)
+ basic_machine=c38-convex
+ os=bsd
+ ;;
+ cr16 | cr16-*)
+ basic_machine=cr16-unknown
+ os=${os:-elf}
+ ;;
+ crds | unos)
+ basic_machine=m68k-crds
+ ;;
+ crisv32 | crisv32-* | etraxfs*)
+ basic_machine=crisv32-axis
+ ;;
+ cris | cris-* | etrax*)
+ basic_machine=cris-axis
+ ;;
+ crx)
+ basic_machine=crx-unknown
+ os=${os:-elf}
+ ;;
+ da30 | da30-*)
+ basic_machine=m68k-da30
+ ;;
+ decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+ basic_machine=mips-dec
+ ;;
+ decsystem10* | dec10*)
+ basic_machine=pdp10-dec
+ os=tops10
+ ;;
+ decsystem20* | dec20*)
+ basic_machine=pdp10-dec
+ os=tops20
+ ;;
+ delta | 3300 | motorola-3300 | motorola-delta \
+ | 3300-motorola | delta-motorola)
+ basic_machine=m68k-motorola
+ ;;
+ dpx20 | dpx20-*)
+ basic_machine=rs6000-bull
+ os=${os:-bosx}
+ ;;
+ dpx2*)
+ basic_machine=m68k-bull
+ os=sysv3
+ ;;
+ e500v[12])
+ basic_machine=powerpc-unknown
+ os=$os"spe"
+ ;;
+ e500v[12]-*)
+ basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=$os"spe"
+ ;;
+ encore | umax | mmax)
+ basic_machine=ns32k-encore
+ ;;
+ elxsi)
+ basic_machine=elxsi-elxsi
+ os=${os:-bsd}
+ ;;
+ fx2800)
+ basic_machine=i860-alliant
+ ;;
+ genix)
+ basic_machine=ns32k-ns
+ ;;
+ h3050r* | hiux*)
+ basic_machine=hppa1.1-hitachi
+ os=hiuxwe2
+ ;;
+ hp300-*)
+ basic_machine=m68k-hp
+ ;;
+ hp3k9[0-9][0-9] | hp9[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k2[0-9][0-9] | hp9k31[0-9])
+ basic_machine=m68000-hp
+ ;;
+ hp9k3[2-9][0-9])
+ basic_machine=m68k-hp
+ ;;
+ hp9k6[0-9][0-9] | hp6[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ hp9k7[0-79][0-9] | hp7[0-79][0-9])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k78[0-9] | hp78[0-9])
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+ # FIXME: really hppa2.0-hp
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][13679] | hp8[0-9][13679])
+ basic_machine=hppa1.1-hp
+ ;;
+ hp9k8[0-9][0-9] | hp8[0-9][0-9])
+ basic_machine=hppa1.0-hp
+ ;;
+ i370-ibm* | ibm*)
+ basic_machine=i370-ibm
+ ;;
+ i*86v32)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=sysv32
+ ;;
+ i*86v4*)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=sysv4
+ ;;
+ i*86v)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=sysv
+ ;;
+ i*86sol2)
+ basic_machine=`echo "$1" | sed -e 's/86.*/86-pc/'`
+ os=solaris2
+ ;;
+ j90 | j90-cray)
+ basic_machine=j90-cray
+ os=${os:-unicos}
+ ;;
+ iris | iris4d)
+ basic_machine=mips-sgi
+ case $os in
+ irix*)
+ ;;
+ *)
+ os=irix4
+ ;;
+ esac
+ ;;
+ leon-*|leon[3-9]-*)
+ basic_machine=sparc-`echo "$basic_machine" | sed 's/-.*//'`
+ ;;
+ m68knommu-*)
+ basic_machine=m68k-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=linux
+ ;;
+ microblaze*)
+ basic_machine=microblaze-xilinx
+ ;;
+ miniframe)
+ basic_machine=m68000-convergent
+ ;;
+ *mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
+ basic_machine=m68k-atari
+ os=mint
+ ;;
+ mips3*-*)
+ basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`
+ ;;
+ mips3*)
+ basic_machine=`echo "$basic_machine" | sed -e 's/mips3/mips64/'`-unknown
+ ;;
+ ms1-*)
+ basic_machine=`echo "$basic_machine" | sed -e 's/ms1-/mt-/'`
+ ;;
+ news-3600 | risc-news)
+ basic_machine=mips-sony
+ os=newsos
+ ;;
+ next | m*-next)
+ basic_machine=m68k-next
+ case $os in
+ nextstep* )
+ ;;
+ ns2*)
+ os=nextstep2
+ ;;
+ *)
+ os=nextstep3
+ ;;
+ esac
+ ;;
+ np1)
+ basic_machine=np1-gould
+ ;;
+ neo-tandem)
+ basic_machine=neo-tandem
+ ;;
+ nse-tandem)
+ basic_machine=nse-tandem
+ ;;
+ nsr-tandem)
+ basic_machine=nsr-tandem
+ ;;
+ nsv-tandem)
+ basic_machine=nsv-tandem
+ ;;
+ nsx-tandem)
+ basic_machine=nsx-tandem
+ ;;
+ op50n-* | op60c-*)
+ basic_machine=hppa1.1-oki
+ os=proelf
+ ;;
+ openrisc | openrisc-*)
+ basic_machine=or32-unknown
+ ;;
+ pa-hitachi)
+ basic_machine=hppa1.1-hitachi
+ os=hiuxwe2
+ ;;
+ parisc-*)
+ basic_machine=hppa-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ os=linux
+ ;;
+ pbd)
+ basic_machine=sparc-tti
+ ;;
+ pbb)
+ basic_machine=m68k-tti
+ ;;
+ pc532 | pc532-*)
+ basic_machine=ns32k-pc532
+ ;;
+ pc98)
+ basic_machine=i386-pc
+ ;;
+ pc98-*)
+ basic_machine=i386-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentium | p5 | k5 | k6 | nexgen | viac3)
+ basic_machine=i586-pc
+ ;;
+ pentiumpro | p6 | 6x86 | athlon | athlon_*)
+ basic_machine=i686-pc
+ ;;
+ pentiumii | pentium2 | pentiumiii | pentium3)
+ basic_machine=i686-pc
+ ;;
+ pentium4)
+ basic_machine=i786-pc
+ ;;
+ pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+ basic_machine=i586-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentiumpro-* | p6-* | 6x86-* | athlon-*)
+ basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+ basic_machine=i686-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pentium4-*)
+ basic_machine=i786-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ pn)
+ basic_machine=pn-gould
+ ;;
+ power) basic_machine=power-ibm
+ ;;
+ ppc | ppcbe) basic_machine=powerpc-unknown
+ ;;
+ ppc-* | ppcbe-*)
+ basic_machine=powerpc-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ppcle | powerpclittle)
+ basic_machine=powerpcle-unknown
+ ;;
+ ppcle-* | powerpclittle-*)
+ basic_machine=powerpcle-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ppc64) basic_machine=powerpc64-unknown
+ ;;
+ ppc64-*) basic_machine=powerpc64-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ppc64le | powerpc64little)
+ basic_machine=powerpc64le-unknown
+ ;;
+ ppc64le-* | powerpc64little-*)
+ basic_machine=powerpc64le-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ ps2)
+ basic_machine=i386-ibm
+ ;;
+ rm[46]00)
+ basic_machine=mips-siemens
+ ;;
+ rtpc | rtpc-*)
+ basic_machine=romp-ibm
+ ;;
+ s390 | s390-*)
+ basic_machine=s390-ibm
+ ;;
+ s390x | s390x-*)
+ basic_machine=s390x-ibm
+ ;;
+ sb1)
+ basic_machine=mipsisa64sb1-unknown
+ ;;
+ sb1el)
+ basic_machine=mipsisa64sb1el-unknown
+ ;;
+ sde)
+ basic_machine=mipsisa32-sde
+ os=${os:-elf}
+ ;;
+ sequent)
+ basic_machine=i386-sequent
+ ;;
+ sh5el)
+ basic_machine=sh5le-unknown
+ ;;
+ simso-wrs)
+ basic_machine=sparclite-wrs
+ os=vxworks
+ ;;
+ spur)
+ basic_machine=spur-unknown
+ ;;
+ st2000)
+ basic_machine=m68k-tandem
+ ;;
+ strongarm-* | thumb-*)
+ basic_machine=arm-`echo "$basic_machine" | sed 's/^[^-]*-//'`
+ ;;
+ sun2)
+ basic_machine=m68000-sun
+ ;;
+ sun3 | sun3-*)
+ basic_machine=m68k-sun
+ ;;
+ sun4)
+ basic_machine=sparc-sun
+ ;;
+ sun386 | sun386i | roadrunner)
+ basic_machine=i386-sun
+ ;;
+ tile*)
+ basic_machine=$basic_machine-unknown
+ os=linux-gnu
+ ;;
+ tx39)
+ basic_machine=mipstx39-unknown
+ ;;
+ tx39el)
+ basic_machine=mipstx39el-unknown
+ ;;
+ tower | tower-32)
+ basic_machine=m68k-ncr
+ ;;
+ vpp*|vx|vx-*)
+ basic_machine=f301-fujitsu
+ ;;
+ w65*)
+ basic_machine=w65-wdc
+ os=none
+ ;;
+ w89k-*)
+ basic_machine=hppa1.1-winbond
+ os=proelf
+ ;;
+ x64)
+ basic_machine=x86_64-pc
+ ;;
+ xps | xps100)
+ basic_machine=xps100-honeywell
+ ;;
+ xscale-* | xscalee[bl]-*)
+ basic_machine=`echo "$basic_machine" | sed 's/^xscale/arm/'`
+ ;;
+ none)
+ basic_machine=none-none
+ os=${os:-none}
+ ;;
+
+# Here we handle the default manufacturer of certain CPU types. It is in
+# some cases the only manufacturer, in others, it is the most popular.
+ w89k)
+ basic_machine=hppa1.1-winbond
+ ;;
+ op50n)
+ basic_machine=hppa1.1-oki
+ ;;
+ op60c)
+ basic_machine=hppa1.1-oki
+ ;;
+ romp)
+ basic_machine=romp-ibm
+ ;;
+ mmix)
+ basic_machine=mmix-knuth
+ ;;
+ rs6000)
+ basic_machine=rs6000-ibm
+ ;;
+ vax)
+ basic_machine=vax-dec
+ ;;
+ pdp11)
+ basic_machine=pdp11-dec
+ ;;
+ we32k)
+ basic_machine=we32k-att
+ ;;
+ sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+ basic_machine=sh-unknown
+ ;;
+ cydra)
+ basic_machine=cydra-cydrome
+ ;;
+ orion)
+ basic_machine=orion-highlevel
+ ;;
+ orion105)
+ basic_machine=clipper-highlevel
+ ;;
+ mac | mpw | mac-mpw)
+ basic_machine=m68k-apple
+ ;;
+ pmac | pmac-mpw)
+ basic_machine=powerpc-apple
+ ;;
+ *-unknown)
+ # Make sure to match an already-canonicalized machine name.
+ ;;
+ *)
+ echo Invalid configuration \`"$1"\': machine \`"$basic_machine"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+ *-digital*)
+ basic_machine=`echo "$basic_machine" | sed 's/digital.*/dec/'`
+ ;;
+ *-commodore*)
+ basic_machine=`echo "$basic_machine" | sed 's/commodore.*/cbm/'`
+ ;;
+ *)
+ ;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x$os != x ]
+then
+case $os in
+ # First match some system type aliases that might get confused
+ # with valid system types.
+ # solaris* is a basic system type, with this one exception.
+ auroraux)
+ os=auroraux
+ ;;
+ bluegene*)
+ os=cnk
+ ;;
+ solaris1 | solaris1.*)
+ os=`echo $os | sed -e 's|solaris1|sunos4|'`
+ ;;
+ solaris)
+ os=solaris2
+ ;;
+ unixware*)
+ os=sysv4.2uw
+ ;;
+ gnu/linux*)
+ os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+ ;;
+ # es1800 is here to avoid being matched by es* (a different OS)
+ es1800*)
+ os=ose
+ ;;
+ # Some version numbers need modification
+ chorusos*)
+ os=chorusos
+ ;;
+ isc)
+ os=isc2.2
+ ;;
+ sco6)
+ os=sco5v6
+ ;;
+ sco5)
+ os=sco3.2v5
+ ;;
+ sco4)
+ os=sco3.2v4
+ ;;
+ sco3.2.[4-9]*)
+ os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+ ;;
+ sco3.2v[4-9]* | sco5v6*)
+ # Don't forget version if it is 3.2v4 or newer.
+ ;;
+ scout)
+ # Don't match below
+ ;;
+ sco*)
+ os=sco3.2v2
+ ;;
+ psos*)
+ os=psos
+ ;;
+ # Now accept the basic system types.
+ # The portable systems comes first.
+ # Each alternative MUST end in a * to match a version number.
+ # sysv* is not here because it comes later, after sysvr4.
+ gnu* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
+ | *vms* | esix* | aix* | cnk* | sunos | sunos[34]*\
+ | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
+ | sym* | kopensolaris* | plan9* \
+ | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
+ | aos* | aros* | cloudabi* | sortix* \
+ | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
+ | clix* | riscos* | uniplus* | iris* | rtu* | xenix* \
+ | knetbsd* | mirbsd* | netbsd* \
+ | bitrig* | openbsd* | solidbsd* | libertybsd* \
+ | ekkobsd* | kfreebsd* | freebsd* | riscix* | lynxos* \
+ | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
+ | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
+ | udi* | eabi* | lites* | ieee* | go32* | aux* | hcos* \
+ | chorusrdb* | cegcc* | glidix* \
+ | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
+ | midipix* | mingw32* | mingw64* | linux-gnu* | linux-android* \
+ | linux-newlib* | linux-musl* | linux-uclibc* \
+ | uxpv* | beos* | mpeix* | udk* | moxiebox* \
+ | interix* | uwin* | mks* | rhapsody* | darwin* \
+ | openstep* | oskit* | conix* | pw32* | nonstopux* \
+ | storm-chaos* | tops10* | tenex* | tops20* | its* \
+ | os2* | vos* | palmos* | uclinux* | nucleus* \
+ | morphos* | superux* | rtmk* | windiss* \
+ | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
+ | skyos* | haiku* | rdos* | toppers* | drops* | es* \
+ | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
+ | midnightbsd*)
+ # Remember, each alternative MUST END IN *, to match a version number.
+ ;;
+ qnx*)
+ case $basic_machine in
+ x86-* | i*86-*)
+ ;;
+ *)
+ os=nto-$os
+ ;;
+ esac
+ ;;
+ hiux*)
+ os=hiuxwe2
+ ;;
+ nto-qnx*)
+ ;;
+ nto*)
+ os=`echo $os | sed -e 's|nto|nto-qnx|'`
+ ;;
+ sim | xray | os68k* | v88r* \
+ | windows* | osx | abug | netware* | os9* \
+ | macos* | mpw* | magic* | mmixware* | mon960* | lnews*)
+ ;;
+ linux-dietlibc)
+ os=linux-dietlibc
+ ;;
+ linux*)
+ os=`echo $os | sed -e 's|linux|linux-gnu|'`
+ ;;
+ lynx*178)
+ os=lynxos178
+ ;;
+ lynx*5)
+ os=lynxos5
+ ;;
+ lynx*)
+ os=lynxos
+ ;;
+ mac*)
+ os=`echo "$os" | sed -e 's|mac|macos|'`
+ ;;
+ opened*)
+ os=openedition
+ ;;
+ os400*)
+ os=os400
+ ;;
+ sunos5*)
+ os=`echo "$os" | sed -e 's|sunos5|solaris2|'`
+ ;;
+ sunos6*)
+ os=`echo "$os" | sed -e 's|sunos6|solaris3|'`
+ ;;
+ wince*)
+ os=wince
+ ;;
+ utek*)
+ os=bsd
+ ;;
+ dynix*)
+ os=bsd
+ ;;
+ acis*)
+ os=aos
+ ;;
+ atheos*)
+ os=atheos
+ ;;
+ syllable*)
+ os=syllable
+ ;;
+ 386bsd)
+ os=bsd
+ ;;
+ ctix* | uts*)
+ os=sysv
+ ;;
+ nova*)
+ os=rtmk-nova
+ ;;
+ ns2)
+ os=nextstep2
+ ;;
+ nsk*)
+ os=nsk
+ ;;
+ # Preserve the version number of sinix5.
+ sinix5.*)
+ os=`echo $os | sed -e 's|sinix|sysv|'`
+ ;;
+ sinix*)
+ os=sysv4
+ ;;
+ tpf*)
+ os=tpf
+ ;;
+ triton*)
+ os=sysv3
+ ;;
+ oss*)
+ os=sysv3
+ ;;
+ svr4*)
+ os=sysv4
+ ;;
+ svr3)
+ os=sysv3
+ ;;
+ sysvr4)
+ os=sysv4
+ ;;
+ # This must come after sysvr4.
+ sysv*)
+ ;;
+ ose*)
+ os=ose
+ ;;
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ os=mint
+ ;;
+ zvmoe)
+ os=zvmoe
+ ;;
+ dicos*)
+ os=dicos
+ ;;
+ pikeos*)
+ # Until real need of OS specific support for
+ # particular features comes up, bare metal
+ # configurations are quite functional.
+ case $basic_machine in
+ arm*)
+ os=eabi
+ ;;
+ *)
+ os=elf
+ ;;
+ esac
+ ;;
+ nacl*)
+ ;;
+ ios)
+ ;;
+ none)
+ ;;
+ *-eabi)
+ ;;
+ *)
+ echo Invalid configuration \`"$1"\': system \`"$os"\' not recognized 1>&2
+ exit 1
+ ;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system. Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+ score-*)
+ os=elf
+ ;;
+ spu-*)
+ os=elf
+ ;;
+ *-acorn)
+ os=riscix1.2
+ ;;
+ arm*-rebel)
+ os=linux
+ ;;
+ arm*-semi)
+ os=aout
+ ;;
+ c4x-* | tic4x-*)
+ os=coff
+ ;;
+ c8051-*)
+ os=elf
+ ;;
+ clipper-intergraph)
+ os=clix
+ ;;
+ hexagon-*)
+ os=elf
+ ;;
+ tic54x-*)
+ os=coff
+ ;;
+ tic55x-*)
+ os=coff
+ ;;
+ tic6x-*)
+ os=coff
+ ;;
+ # This must come before the *-dec entry.
+ pdp10-*)
+ os=tops20
+ ;;
+ pdp11-*)
+ os=none
+ ;;
+ *-dec | vax-*)
+ os=ultrix4.2
+ ;;
+ m68*-apollo)
+ os=domain
+ ;;
+ i386-sun)
+ os=sunos4.0.2
+ ;;
+ m68000-sun)
+ os=sunos3
+ ;;
+ m68*-cisco)
+ os=aout
+ ;;
+ mep-*)
+ os=elf
+ ;;
+ mips*-cisco)
+ os=elf
+ ;;
+ mips*-*)
+ os=elf
+ ;;
+ or32-*)
+ os=coff
+ ;;
+ *-tti) # must be before sparc entry or we get the wrong os.
+ os=sysv3
+ ;;
+ sparc-* | *-sun)
+ os=sunos4.1.1
+ ;;
+ pru-*)
+ os=elf
+ ;;
+ *-be)
+ os=beos
+ ;;
+ *-ibm)
+ os=aix
+ ;;
+ *-knuth)
+ os=mmixware
+ ;;
+ *-wec)
+ os=proelf
+ ;;
+ *-winbond)
+ os=proelf
+ ;;
+ *-oki)
+ os=proelf
+ ;;
+ *-hp)
+ os=hpux
+ ;;
+ *-hitachi)
+ os=hiux
+ ;;
+ i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+ os=sysv
+ ;;
+ *-cbm)
+ os=amigaos
+ ;;
+ *-dg)
+ os=dgux
+ ;;
+ *-dolphin)
+ os=sysv3
+ ;;
+ m68k-ccur)
+ os=rtu
+ ;;
+ m88k-omron*)
+ os=luna
+ ;;
+ *-next)
+ os=nextstep
+ ;;
+ *-sequent)
+ os=ptx
+ ;;
+ *-crds)
+ os=unos
+ ;;
+ *-ns)
+ os=genix
+ ;;
+ i370-*)
+ os=mvs
+ ;;
+ *-gould)
+ os=sysv
+ ;;
+ *-highlevel)
+ os=bsd
+ ;;
+ *-encore)
+ os=bsd
+ ;;
+ *-sgi)
+ os=irix
+ ;;
+ *-siemens)
+ os=sysv4
+ ;;
+ *-masscomp)
+ os=rtu
+ ;;
+ f30[01]-fujitsu | f700-fujitsu)
+ os=uxpv
+ ;;
+ *-rom68k)
+ os=coff
+ ;;
+ *-*bug)
+ os=coff
+ ;;
+ *-apple)
+ os=macos
+ ;;
+ *-atari*)
+ os=mint
+ ;;
+ *-wrs)
+ os=vxworks
+ ;;
+ *)
+ os=none
+ ;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer. We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+ *-unknown)
+ case $os in
+ riscix*)
+ vendor=acorn
+ ;;
+ sunos*)
+ vendor=sun
+ ;;
+ cnk*|-aix*)
+ vendor=ibm
+ ;;
+ beos*)
+ vendor=be
+ ;;
+ hpux*)
+ vendor=hp
+ ;;
+ mpeix*)
+ vendor=hp
+ ;;
+ hiux*)
+ vendor=hitachi
+ ;;
+ unos*)
+ vendor=crds
+ ;;
+ dgux*)
+ vendor=dg
+ ;;
+ luna*)
+ vendor=omron
+ ;;
+ genix*)
+ vendor=ns
+ ;;
+ clix*)
+ vendor=intergraph
+ ;;
+ mvs* | opened*)
+ vendor=ibm
+ ;;
+ os400*)
+ vendor=ibm
+ ;;
+ ptx*)
+ vendor=sequent
+ ;;
+ tpf*)
+ vendor=ibm
+ ;;
+ vxsim* | vxworks* | windiss*)
+ vendor=wrs
+ ;;
+ aux*)
+ vendor=apple
+ ;;
+ hms*)
+ vendor=hitachi
+ ;;
+ mpw* | macos*)
+ vendor=apple
+ ;;
+ *mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
+ vendor=atari
+ ;;
+ vos*)
+ vendor=stratus
+ ;;
+ esac
+ basic_machine=`echo "$basic_machine" | sed "s/unknown/$vendor/"`
+ ;;
+esac
+
+echo "$basic_machine-$os"
+exit
+
+# Local variables:
+# eval: (add-hook 'before-save-hook 'time-stamp)
+# time-stamp-start: "timestamp='"
+# time-stamp-format: "%:y-%02m-%02d"
+# time-stamp-end: "'"
+# End:
diff --git a/lib/libpcap/libpcap/configure b/lib/libpcap/libpcap/configure
new file mode 100755
index 0000000..fa15fc7
--- /dev/null
+++ b/lib/libpcap/libpcap/configure
@@ -0,0 +1,12456 @@
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for pcap 1.9.1.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='pcap'
+PACKAGE_TARNAME='pcap'
+PACKAGE_VERSION='1.9.1'
+PACKAGE_STRING='pcap 1.9.1'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="pcap.c"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+INSTALL_DATA
+INSTALL_SCRIPT
+INSTALL_PROGRAM
+RDMA_SRC
+PCAP_SUPPORT_RDMASNIFF
+DBUS_SRC
+PCAP_SUPPORT_DBUS
+PKGCONFIG
+BT_MONITOR_SRC
+BT_SRC
+PCAP_SUPPORT_BT
+NETMAP_SRC
+PCAP_SUPPORT_NETMAP
+NETFILTER_SRC
+PCAP_SUPPORT_NETFILTER
+USB_SRC
+PCAP_SUPPORT_USB
+EXTRA_NETWORK_LIBS
+RPCAPD_LIBS
+INSTALL_RPCAPD
+BUILD_RPCAPD
+PTHREAD_LIBS
+MAN_ADMIN_COMMANDS
+MAN_MISC_INFO
+MAN_FILE_FORMATS
+MAN_DEVICES
+DYEXT
+SSRC
+ADDLARCHIVEOBJS
+ADDLOBJS
+V_YACC
+V_RPATH_OPT
+V_SONAME_OPT
+V_SHLIB_OPT
+V_SHLIB_CMD
+V_SHLIB_CCOPT
+V_PCAP
+V_LEX
+V_INCLS
+V_FINDALLDEVS
+V_DEFS
+V_PROG_LDFLAGS_FAT
+V_PROG_CCOPT_FAT
+V_LIB_LDFLAGS_FAT
+V_LIB_CCOPT_FAT
+V_CCOPT
+MKDEP
+DEPENDENCY_CFLAG
+LN_S
+AR
+RANLIB
+YFLAGS
+YACC
+LEXLIB
+LEX_OUTPUT_ROOT
+LEX
+PCAP_SUPPORT_PACKET_RING
+VALGRINDTEST_SRC
+LIBOBJS
+EGREP
+GREP
+CPP
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+SHLICC2
+target_os
+target_vendor
+target_cpu
+target
+host_os
+host_vendor
+host_cpu
+host
+build_os
+build_vendor
+build_cpu
+build
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+runstatedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_gcc
+enable_largefile
+enable_protochain
+with_sita
+with_pcap
+with_libnl
+enable_packet_ring
+enable_ipv6
+with_dag
+with_dag_includes
+with_dag_libraries
+with_septel
+with_snf
+with_snf_includes
+with_snf_libraries
+with_turbocap
+enable_remote
+enable_optimizer_dbg
+enable_yydebug
+enable_universal
+enable_shared
+enable_usb
+enable_netmap
+enable_bluetooth
+enable_dbus
+enable_rdma
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP
+YACC
+YFLAGS'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+runstatedir='${localstatedir}/run'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -runstatedir | --runstatedir | --runstatedi | --runstated \
+ | --runstate | --runstat | --runsta | --runst | --runs \
+ | --run | --ru | --r)
+ ac_prev=runstatedir ;;
+ -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \
+ | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \
+ | --run=* | --ru=* | --r=*)
+ runstatedir=$ac_optarg ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir runstatedir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures pcap 1.9.1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/pcap]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+
+System types:
+ --build=BUILD configure for building on BUILD [guessed]
+ --host=HOST cross-compile to build programs to run on HOST [BUILD]
+ --target=TARGET configure for building compilers for TARGET [HOST]
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of pcap 1.9.1:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Features:
+ --disable-option-checking ignore unrecognized --enable/--with options
+ --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no)
+ --enable-FEATURE[=ARG] include FEATURE [ARG=yes]
+ --disable-largefile omit support for large files
+ --disable-protochain disable \"protochain\" insn
+ --enable-packet-ring enable packet ring support on Linux [default=yes]
+ --enable-ipv6 build IPv6-capable version [default=yes]
+ --enable-remote enable remote packet capture [default=no]
+ --disable-remote disable remote packet capture
+ --enable-optimizer-dbg build optimizer debugging code
+ --enable-yydebug build parser debugging code
+ --disable-universal don't build universal on macOS
+ --enable-shared build shared libraries [default=yes, if support
+ available]
+ --enable-usb enable USB capture support [default=yes, if support
+ available]
+ --enable-netmap enable netmap support [default=yes, if support
+ available]
+ --enable-bluetooth enable Bluetooth support [default=yes, if support
+ available]
+ --enable-dbus enable D-Bus capture support [default=yes, if
+ support available]
+ --enable-rdma enable RDMA capture support [default=yes, if support
+ available]
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --without-gcc don't use gcc
+ --with-sita include SITA support
+ --with-pcap=TYPE use packet capture TYPE
+ --without-libnl disable libnl support [default=yes, on Linux, if
+ present]
+ --with-dag[=DIR] include Endace DAG support (located in directory
+ DIR, if supplied). [default=yes, if present]
+ --with-dag-includes=IDIR
+ Endace DAG include directory, if not DIR/include
+ --with-dag-libraries=LDIR
+ Endace DAG library directory, if not DIR/lib
+ --with-septel[=DIR] include Septel support (located in directory DIR, if
+ supplied). [default=yes, if present]
+ --with-snf[=DIR] include Myricom SNF support (located in directory
+ DIR, if supplied). [default=yes, if present]
+ --with-snf-includes=IDIR
+ Myricom SNF include directory, if not DIR/include
+ --with-snf-libraries=LDIR
+ Myricom SNF library directory, if not DIR/lib
+ --with-turbocap[=DIR] include Riverbed TurboCap support (located in
+ directory DIR, if supplied). [default=yes, if
+ present]
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+ YACC The `Yet Another Compiler Compiler' implementation to use.
+ Defaults to the first program found out of: `bison -y', `byacc',
+ `yacc'.
+ YFLAGS The list of arguments that will be passed by default to $YACC.
+ This script will default YFLAGS to the empty string to avoid a
+ default value of `-d' given by some make applications.
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+pcap configure 1.9.1
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+
+# ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
+# ---------------------------------------------
+# Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
+# accordingly.
+ac_fn_c_check_decl ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ as_decl_name=`echo $2|sed 's/ *(.*//'`
+ as_decl_use=`echo $2|sed -e 's/(/((/' -e 's/)/) 0&/' -e 's/,/) 0& (/g'`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $as_decl_name is declared" >&5
+$as_echo_n "checking whether $as_decl_name is declared... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+#ifndef $as_decl_name
+#ifdef __cplusplus
+ (void) $as_decl_use;
+#else
+ (void) $as_decl_name;
+#endif
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_decl
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES
+# ----------------------------------------------------
+# Tries to find if the field MEMBER exists in type AGGR, after including
+# INCLUDES, setting cache variable VAR accordingly.
+ac_fn_c_check_member ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5
+$as_echo_n "checking for $2.$3... " >&6; }
+if eval \${$4+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$5
+int
+main ()
+{
+static $2 ac_aggr;
+if (sizeof ac_aggr.$3)
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$4=yes"
+else
+ eval "$4=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$4
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_member
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by pcap $as_me 1.9.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+
+ac_aux_dir=
+for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
+ if test -f "$ac_dir/install-sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install-sh -c"
+ break
+ elif test -f "$ac_dir/install.sh"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/install.sh -c"
+ break
+ elif test -f "$ac_dir/shtool"; then
+ ac_aux_dir=$ac_dir
+ ac_install_sh="$ac_aux_dir/shtool install -c"
+ break
+ fi
+done
+if test -z "$ac_aux_dir"; then
+ as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5
+fi
+
+# These three variables are undocumented and unsupported,
+# and are intended to be withdrawn in a future Autoconf release.
+# They can cause serious problems if a builder's source tree is in a directory
+# whose full name contains unusual characters.
+ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var.
+ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var.
+ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var.
+
+
+# Make sure we can run config.sub.
+$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 ||
+ as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5
+$as_echo_n "checking build system type... " >&6; }
+if ${ac_cv_build+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_build_alias=$build_alias
+test "x$ac_build_alias" = x &&
+ ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"`
+test "x$ac_build_alias" = x &&
+ as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5
+ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5
+$as_echo "$ac_cv_build" >&6; }
+case $ac_cv_build in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;;
+esac
+build=$ac_cv_build
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_build
+shift
+build_cpu=$1
+build_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+build_os=$*
+IFS=$ac_save_IFS
+case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5
+$as_echo_n "checking host system type... " >&6; }
+if ${ac_cv_host+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$host_alias" = x; then
+ ac_cv_host=$ac_cv_build
+else
+ ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5
+$as_echo "$ac_cv_host" >&6; }
+case $ac_cv_host in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;;
+esac
+host=$ac_cv_host
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_host
+shift
+host_cpu=$1
+host_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+host_os=$*
+IFS=$ac_save_IFS
+case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking target system type" >&5
+$as_echo_n "checking target system type... " >&6; }
+if ${ac_cv_target+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "x$target_alias" = x; then
+ ac_cv_target=$ac_cv_host
+else
+ ac_cv_target=`$SHELL "$ac_aux_dir/config.sub" $target_alias` ||
+ as_fn_error $? "$SHELL $ac_aux_dir/config.sub $target_alias failed" "$LINENO" 5
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_target" >&5
+$as_echo "$ac_cv_target" >&6; }
+case $ac_cv_target in
+*-*-*) ;;
+*) as_fn_error $? "invalid value of canonical target" "$LINENO" 5;;
+esac
+target=$ac_cv_target
+ac_save_IFS=$IFS; IFS='-'
+set x $ac_cv_target
+shift
+target_cpu=$1
+target_vendor=$2
+shift; shift
+# Remember, the first character of IFS is used to create $*,
+# except with old shells:
+target_os=$*
+IFS=$ac_save_IFS
+case $target_os in *\ *) target_os=`echo "$target_os" | sed 's/ /-/g'`;; esac
+
+
+# The aliases save the names the user supplied, while $host etc.
+# will get canonicalized.
+test -n "$target_alias" &&
+ test "$program_prefix$program_suffix$program_transform_name" = \
+ NONENONEs,x,x, &&
+ program_prefix=${target_alias}-
+
+
+
+
+
+
+
+
+# Check whether --with-gcc was given.
+if test "${with_gcc+set}" = set; then :
+ withval=$with_gcc;
+fi
+
+ V_CCOPT=""
+ if test "${srcdir}" != "." ; then
+ V_CCOPT="-I\$(srcdir)"
+ fi
+ if test "${CFLAGS+set}" = set; then
+ LBL_CFLAGS="$CFLAGS"
+ fi
+ if test -z "$CC" ; then
+ case "$host_os" in
+
+ bsdi*)
+ # Extract the first word of "shlicc2", so it can be a program name with args.
+set dummy shlicc2; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_SHLICC2+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$SHLICC2"; then
+ ac_cv_prog_SHLICC2="$SHLICC2" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_SHLICC2="yes"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_SHLICC2" && ac_cv_prog_SHLICC2="no"
+fi
+fi
+SHLICC2=$ac_cv_prog_SHLICC2
+if test -n "$SHLICC2"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SHLICC2" >&5
+$as_echo "$SHLICC2" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test $SHLICC2 = yes ; then
+ CC=shlicc2
+ export CC
+ fi
+ ;;
+ esac
+ fi
+ if test -z "$CC" -a "$with_gcc" = no ; then
+ CC=cc
+ export CC
+ fi
+
+#
+# Try to enable as many C99 features as we can.
+# At minimum, we want C++/C99-style // comments.
+#
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C99" >&5
+$as_echo_n "checking for $CC option to accept ISO C99... " >&6; }
+if ${ac_cv_prog_cc_c99+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c99=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <stdio.h>
+
+// Check varargs macros. These examples are taken from C99 6.10.3.5.
+#define debug(...) fprintf (stderr, __VA_ARGS__)
+#define showlist(...) puts (#__VA_ARGS__)
+#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))
+static void
+test_varargs_macros (void)
+{
+ int x = 1234;
+ int y = 5678;
+ debug ("Flag");
+ debug ("X = %d\n", x);
+ showlist (The first, second, and third items.);
+ report (x>y, "x is %d but y is %d", x, y);
+}
+
+// Check long long types.
+#define BIG64 18446744073709551615ull
+#define BIG32 4294967295ul
+#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)
+#if !BIG_OK
+ your preprocessor is broken;
+#endif
+#if BIG_OK
+#else
+ your preprocessor is broken;
+#endif
+static long long int bignum = -9223372036854775807LL;
+static unsigned long long int ubignum = BIG64;
+
+struct incomplete_array
+{
+ int datasize;
+ double data[];
+};
+
+struct named_init {
+ int number;
+ const wchar_t *name;
+ double average;
+};
+
+typedef const char *ccp;
+
+static inline int
+test_restrict (ccp restrict text)
+{
+ // See if C++-style comments work.
+ // Iterate through items via the restricted pointer.
+ // Also check for declarations in for loops.
+ for (unsigned int i = 0; *(text+i) != '\0'; ++i)
+ continue;
+ return 0;
+}
+
+// Check varargs and va_copy.
+static void
+test_varargs (const char *format, ...)
+{
+ va_list args;
+ va_start (args, format);
+ va_list args_copy;
+ va_copy (args_copy, args);
+
+ const char *str;
+ int number;
+ float fnumber;
+
+ while (*format)
+ {
+ switch (*format++)
+ {
+ case 's': // string
+ str = va_arg (args_copy, const char *);
+ break;
+ case 'd': // int
+ number = va_arg (args_copy, int);
+ break;
+ case 'f': // float
+ fnumber = va_arg (args_copy, double);
+ break;
+ default:
+ break;
+ }
+ }
+ va_end (args_copy);
+ va_end (args);
+}
+
+int
+main ()
+{
+
+ // Check bool.
+ _Bool success = false;
+
+ // Check restrict.
+ if (test_restrict ("String literal") == 0)
+ success = true;
+ char *restrict newvar = "Another string";
+
+ // Check varargs.
+ test_varargs ("s, d' f .", "string", 65, 34.234);
+ test_varargs_macros ();
+
+ // Check flexible array members.
+ struct incomplete_array *ia =
+ malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));
+ ia->datasize = 10;
+ for (int i = 0; i < ia->datasize; ++i)
+ ia->data[i] = i * 1.234;
+
+ // Check named initializers.
+ struct named_init ni = {
+ .number = 34,
+ .name = L"Test wide string",
+ .average = 543.34343,
+ };
+
+ ni.number = 58;
+
+ int dynamic_array[ni.number];
+ dynamic_array[ni.number - 1] = 543;
+
+ // work around unused variable warnings
+ return (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == 'x'
+ || dynamic_array[ni.number - 1] != 543);
+
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -std=gnu99 -std=c99 -c99 -AC99 -D_STDC_C99= -qlanglvl=extc99
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c99=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c99" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c99" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c99"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99" >&5
+$as_echo "$ac_cv_prog_cc_c99" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c99" != xno; then :
+
+fi
+
+
+if test "$ac_cv_prog_cc_c99" = "no"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: The C compiler does not support C99; there may be compiler errors" >&5
+$as_echo "$as_me: WARNING: The C compiler does not support C99; there may be compiler errors" >&2;}
+fi
+
+
+
+
+
+ if test "$GCC" = yes ; then
+ #
+ # -Werror forces warnings to be errors.
+ #
+ ac_lbl_cc_force_warning_errors=-Werror
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -fvisibility=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -fvisibility=hidden option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-fvisibility=hidden" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ else
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fvisibility=hidden " >&5
+$as_echo_n "checking whether -fvisibility=hidden ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -fvisibility=hidden"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ else
+ V_INCLS="$V_INCLS -I/usr/local/include"
+ LDFLAGS="$LDFLAGS -L/usr/local/lib"
+
+ case "$host_os" in
+
+ darwin*)
+ #
+ # This is assumed either to be GCC or clang, both
+ # of which use -Werror to force warnings to be errors.
+ #
+ ac_lbl_cc_force_warning_errors=-Werror
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -fvisibility=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -fvisibility=hidden option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-fvisibility=hidden" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ elif expr "x-fvisibility=hidden" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -fvisibility=hidden"
+ else
+ CFLAGS="$CFLAGS -fvisibility=hidden"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -fvisibility=hidden " >&5
+$as_echo_n "checking whether -fvisibility=hidden ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -fvisibility=hidden"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ ;;
+
+ hpux*)
+ #
+ # HP C, which is what we presume we're using, doesn't
+ # exit with a non-zero exit status if we hand it an
+ # invalid -W flag, can't be forced to do so even with
+ # +We, and doesn't handle GCC-style -W flags, so we
+ # don't want to try using GCC-style -W flags.
+ #
+ ac_lbl_cc_dont_try_gcc_dashW=yes
+ ;;
+
+ irix*)
+ #
+ # MIPS C, which is what we presume we're using, doesn't
+ # necessarily exit with a non-zero exit status if we
+ # hand it an invalid -W flag, can't be forced to do
+ # so, and doesn't handle GCC-style -W flags, so we
+ # don't want to try using GCC-style -W flags.
+ #
+ ac_lbl_cc_dont_try_gcc_dashW=yes
+ #
+ # It also, apparently, defaults to "char" being
+ # unsigned, unlike most other C implementations;
+ # I suppose we could say "signed char" whenever
+ # we want to guarantee a signed "char", but let's
+ # just force signed chars.
+ #
+ # -xansi is normally the default, but the
+ # configure script was setting it; perhaps -cckr
+ # was the default in the Old Days. (Then again,
+ # that would probably be for backwards compatibility
+ # in the days when ANSI C was Shiny and New, i.e.
+ # 1989 and the early '90's, so maybe we can just
+ # drop support for those compilers.)
+ #
+ # -g is equivalent to -g2, which turns off
+ # optimization; we choose -g3, which generates
+ # debugging information but doesn't turn off
+ # optimization (even if the optimization would
+ # cause inaccuracies in debugging).
+ #
+ V_CCOPT="$V_CCOPT -xansi -signed -g3"
+ ;;
+
+ osf*)
+ #
+ # Presumed to be DEC OSF/1, Digital UNIX, or
+ # Tru64 UNIX.
+ #
+ # The DEC C compiler, which is what we presume we're
+ # using, doesn't exit with a non-zero exit status if we
+ # hand it an invalid -W flag, can't be forced to do
+ # so, and doesn't handle GCC-style -W flags, so we
+ # don't want to try using GCC-style -W flags.
+ #
+ ac_lbl_cc_dont_try_gcc_dashW=yes
+ #
+ # -g is equivalent to -g2, which turns off
+ # optimization; we choose -g3, which generates
+ # debugging information but doesn't turn off
+ # optimization (even if the optimization would
+ # cause inaccuracies in debugging).
+ #
+ V_CCOPT="$V_CCOPT -g3"
+ ;;
+
+ solaris*)
+ #
+ # Assumed to be Sun C, which requires -errwarn to force
+ # warnings to be treated as errors.
+ #
+ ac_lbl_cc_force_warning_errors=-errwarn
+
+ #
+ # Try to have the compiler default to hiding symbols,
+ # so that only symbols explicitly exported with
+ # PCAP_API will be visible outside (shared) libraries.
+ #
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -xldscope=hidden option" >&5
+$as_echo_n "checking whether the compiler supports the -xldscope=hidden option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-xldscope=hidden" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -xldscope=hidden"
+ elif expr "x-xldscope=hidden" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -xldscope=hidden"
+ elif expr "x-xldscope=hidden" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -xldscope=hidden"
+ else
+ CFLAGS="$CFLAGS -xldscope=hidden"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -xldscope=hidden " >&5
+$as_echo_n "checking whether -xldscope=hidden ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -xldscope=hidden"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ ;;
+
+ ultrix*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking that Ultrix $CC hacks const in prototypes" >&5
+$as_echo_n "checking that Ultrix $CC hacks const in prototypes... " >&6; }
+ if ${ac_cv_lbl_cc_const_proto+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+int
+main ()
+{
+struct a { int b; };
+ void c(const struct a *)
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_lbl_cc_const_proto=yes
+else
+ ac_cv_lbl_cc_const_proto=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_cc_const_proto" >&5
+$as_echo "$ac_cv_lbl_cc_const_proto" >&6; }
+ if test $ac_cv_lbl_cc_const_proto = no ; then
+
+$as_echo "#define const /**/" >>confdefs.h
+
+ fi
+ ;;
+ esac
+ V_CCOPT="$V_CCOPT -O"
+ fi
+
+
+ if test "$GCC" = yes ; then
+ #
+ # On platforms where we build a shared library:
+ #
+ # add options to generate position-independent code,
+ # if necessary (it's the default in AIX and Darwin/macOS);
+ #
+ # define option to set the soname of the shared library,
+ # if the OS supports that;
+ #
+ # add options to specify, at link time, a directory to
+ # add to the run-time search path, if that's necessary.
+ #
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-shared"
+ case "$host_os" in
+
+ aix*)
+ ;;
+
+ freebsd*|netbsd*|openbsd*|dragonfly*|linux*|osf*|midipix*)
+ #
+ # Platforms where the linker is the GNU linker
+ # or accepts command-line arguments like
+ # those the GNU linker accepts.
+ #
+ # Some instruction sets require -fPIC on some
+ # operating systems. Check for them. If you
+ # have a combination that requires it, add it
+ # here.
+ #
+ PIC_OPT=-fpic
+ case "$host_cpu" in
+
+ sparc64*)
+ case "$host_os" in
+
+ freebsd*|openbsd*|linux*)
+ PIC_OPT=-fPIC
+ ;;
+ esac
+ ;;
+ esac
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT $PIC_OPT"
+ V_SONAME_OPT="-Wl,-soname,"
+ V_RPATH_OPT="-Wl,-rpath,"
+ ;;
+
+ hpux*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
+ #
+ # XXX - this assumes GCC is using the HP linker,
+ # rather than the GNU linker, and that the "+h"
+ # option is used on all HP-UX platforms, both .sl
+ # and .so.
+ #
+ V_SONAME_OPT="-Wl,+h,"
+ #
+ # By default, directories specifed with -L
+ # are added to the run-time search path, so
+ # we don't add them in pcap-config.
+ #
+ ;;
+
+ solaris*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
+ #
+ # XXX - this assumes GCC is using the Sun linker,
+ # rather than the GNU linker.
+ #
+ V_SONAME_OPT="-Wl,-h,"
+ V_RPATH_OPT="-Wl,-R,"
+ ;;
+ esac
+ else
+ #
+ # Set the appropriate compiler flags and, on platforms
+ # where we build a shared library:
+ #
+ # add options to generate position-independent code,
+ # if necessary (it's the default in Darwin/macOS);
+ #
+ # if we generate ".so" shared libraries, define the
+ # appropriate options for building the shared library;
+ #
+ # add options to specify, at link time, a directory to
+ # add to the run-time search path, if that's necessary.
+ #
+ # Note: spaces after V_SONAME_OPT are significant; on
+ # some platforms the soname is passed with a GCC-like
+ # "-Wl,-soname,{soname}" option, with the soname part
+ # of the option, while on other platforms the C compiler
+ # driver takes it as a regular option with the soname
+ # following the option. The same applies to V_RPATH_OPT.
+ #
+ case "$host_os" in
+
+ aix*)
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-G -bnoentry -bexpall"
+ ;;
+
+ freebsd*|netbsd*|openbsd*|dragonfly*|linux*)
+ #
+ # "cc" is GCC.
+ #
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -fpic"
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-shared"
+ V_SONAME_OPT="-Wl,-soname,"
+ V_RPATH_OPT="-Wl,-rpath,"
+ ;;
+
+ hpux*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT +z"
+ V_SHLIB_CMD="\$(LD)"
+ V_SHLIB_OPT="-b"
+ V_SONAME_OPT="+h "
+ #
+ # By default, directories specifed with -L
+ # are added to the run-time search path, so
+ # we don't add them in pcap-config.
+ #
+ ;;
+
+ osf*)
+ #
+ # Presumed to be DEC OSF/1, Digital UNIX, or
+ # Tru64 UNIX.
+ #
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-shared"
+ V_SONAME_OPT="-soname "
+ V_RPATH_OPT="-rpath "
+ ;;
+
+ solaris*)
+ V_SHLIB_CCOPT="$V_SHLIB_CCOPT -Kpic"
+ V_SHLIB_CMD="\$(CC)"
+ V_SHLIB_OPT="-G"
+ V_SONAME_OPT="-h "
+ V_RPATH_OPT="-R"
+ ;;
+ esac
+ fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5
+$as_echo_n "checking for inline... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$V_CCOPT"
+ if ${ac_cv_lbl_inline+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ac_cv_lbl_inline=""
+ ac_lbl_cc_inline=no
+ for ac_lbl_inline in inline __inline__ __inline
+ do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define inline $ac_lbl_inline
+ static inline struct iltest *foo(void);
+ struct iltest {
+ int iltest1;
+ int iltest2;
+ };
+
+ static inline struct iltest *
+ foo()
+ {
+ static struct iltest xxx;
+
+ return &xxx;
+ }
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_lbl_cc_inline=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test "$ac_lbl_cc_inline" = yes ; then
+ break;
+ fi
+ done
+ if test "$ac_lbl_cc_inline" = yes ; then
+ ac_cv_lbl_inline=$ac_lbl_inline
+ fi
+fi
+
+ CFLAGS="$save_CFLAGS"
+ if test ! -z "$ac_cv_lbl_inline" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_inline" >&5
+$as_echo "$ac_cv_lbl_inline" >&6; }
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define inline $ac_cv_lbl_inline
+_ACEOF
+
+
+#
+# Try to arrange for large file support.
+#
+# Check whether --enable-largefile was given.
+if test "${enable_largefile+set}" = set; then :
+ enableval=$enable_largefile;
+fi
+
+if test "$enable_largefile" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5
+$as_echo_n "checking for special C compiler options needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_sys_largefile_CC=no
+ if test "$GCC" != yes; then
+ ac_save_CC=$CC
+ while :; do
+ # IRIX 6.2 and later do not support large files by default,
+ # so use the C compiler's -n32 option if that helps.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ if ac_fn_c_try_compile "$LINENO"; then :
+ break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ CC="$CC -n32"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_largefile_CC=' -n32'; break
+fi
+rm -f core conftest.err conftest.$ac_objext
+ break
+ done
+ CC=$ac_save_CC
+ rm -f conftest.$ac_ext
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5
+$as_echo "$ac_cv_sys_largefile_CC" >&6; }
+ if test "$ac_cv_sys_largefile_CC" != no; then
+ CC=$CC$ac_cv_sys_largefile_CC
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5
+$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; }
+if ${ac_cv_sys_file_offset_bits+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _FILE_OFFSET_BITS 64
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_file_offset_bits=64; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_file_offset_bits=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5
+$as_echo "$ac_cv_sys_file_offset_bits" >&6; }
+case $ac_cv_sys_file_offset_bits in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ if test $ac_cv_sys_file_offset_bits = unknown; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5
+$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; }
+if ${ac_cv_sys_large_files+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGE_FILES 1
+#include <sys/types.h>
+ /* Check that off_t can represent 2**63 - 1 correctly.
+ We can't simply define LARGE_OFF_T to be 9223372036854775807,
+ since some C++ compilers masquerading as C compilers
+ incorrectly reject 9223372036854775807. */
+#define LARGE_OFF_T ((((off_t) 1 << 31) << 31) - 1 + (((off_t) 1 << 31) << 31))
+ int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721
+ && LARGE_OFF_T % 2147483647 == 1)
+ ? 1 : -1];
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_large_files=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_cv_sys_large_files=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5
+$as_echo "$ac_cv_sys_large_files" >&6; }
+case $ac_cv_sys_large_files in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGE_FILES $ac_cv_sys_large_files
+_ACEOF
+;;
+esac
+rm -rf conftest*
+ fi
+
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGEFILE_SOURCE value needed for large files" >&5
+$as_echo_n "checking for _LARGEFILE_SOURCE value needed for large files... " >&6; }
+if ${ac_cv_sys_largefile_source+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ while :; do
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h> /* for off_t */
+ #include <stdio.h>
+int
+main ()
+{
+int (*fp) (FILE *, off_t, int) = fseeko;
+ return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_sys_largefile_source=no; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#define _LARGEFILE_SOURCE 1
+#include <sys/types.h> /* for off_t */
+ #include <stdio.h>
+int
+main ()
+{
+int (*fp) (FILE *, off_t, int) = fseeko;
+ return fseeko (stdin, 0, 0) && fp (stdin, 0, 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_sys_largefile_source=1; break
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ ac_cv_sys_largefile_source=unknown
+ break
+done
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_source" >&5
+$as_echo "$ac_cv_sys_largefile_source" >&6; }
+case $ac_cv_sys_largefile_source in #(
+ no | unknown) ;;
+ *)
+cat >>confdefs.h <<_ACEOF
+#define _LARGEFILE_SOURCE $ac_cv_sys_largefile_source
+_ACEOF
+;;
+esac
+rm -rf conftest*
+
+# We used to try defining _XOPEN_SOURCE=500 too, to work around a bug
+# in glibc 2.1.3, but that breaks too many other things.
+# If you want fseeko and ftello with glibc, upgrade to a fixed glibc.
+if test $ac_cv_sys_largefile_source != unknown; then
+
+$as_echo "#define HAVE_FSEEKO 1" >>confdefs.h
+
+fi
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+for ac_header in sys/ioccom.h sys/sockio.h limits.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in netpacket/packet.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "netpacket/packet.h" "ac_cv_header_netpacket_packet_h" "$ac_includes_default"
+if test "x$ac_cv_header_netpacket_packet_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NETPACKET_PACKET_H 1
+_ACEOF
+
+fi
+
+done
+
+for ac_header in net/pfvar.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "net/pfvar.h" "ac_cv_header_net_pfvar_h" "#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+"
+if test "x$ac_cv_header_net_pfvar_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_PFVAR_H 1
+_ACEOF
+
+fi
+
+done
+
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+ #
+ # Check for various PF actions.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether net/pfvar.h defines PF_NAT through PF_NORDR" >&5
+$as_echo_n "checking whether net/pfvar.h defines PF_NAT through PF_NORDR... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <net/pfvar.h>
+int
+main ()
+{
+return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_PF_NAT_THROUGH_PF_NORDR 1" >>confdefs.h
+
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+case "$host_os" in
+linux*|uclinux*)
+ for ac_header in linux/sockios.h linux/if_bonding.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "
+#include <sys/socket.h>
+#include <linux/if.h>
+
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ ;;
+esac
+
+if test "$GCC" = yes ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI ioctl definitions" >&5
+$as_echo_n "checking for ANSI ioctl definitions... " >&6; }
+ if ${ac_cv_lbl_gcc_fixincludes+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/*
+ * This generates a "duplicate case value" when fixincludes
+ * has not be run.
+ */
+# include <sys/types.h>
+# include <sys/time.h>
+# include <sys/ioctl.h>
+# ifdef HAVE_SYS_IOCCOM_H
+# include <sys/ioccom.h>
+# endif
+int
+main ()
+{
+switch (0) {
+ case _IO('A', 1):;
+ case _IO('B', 1):;
+ }
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_lbl_gcc_fixincludes=yes
+else
+ ac_cv_lbl_gcc_fixincludes=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_gcc_fixincludes" >&5
+$as_echo "$ac_cv_lbl_gcc_fixincludes" >&6; }
+ if test $ac_cv_lbl_gcc_fixincludes = no ; then
+ # Don't cache failure
+ unset ac_cv_lbl_gcc_fixincludes
+ as_fn_error $? "see the INSTALL for more info" "$LINENO" 5
+ fi
+ fi
+
+for ac_func in strerror
+do :
+ ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
+if test "x$ac_cv_func_strerror" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRERROR 1
+_ACEOF
+
+fi
+done
+
+ac_fn_c_check_func "$LINENO" "strerror_r" "ac_cv_func_strerror_r"
+if test "x$ac_cv_func_strerror_r" = xyes; then :
+
+ #
+ # We have strerror_r; if we define _GNU_SOURCE, is it a
+ # POSIX-compliant strerror_r() or a GNU strerror_r()?
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether strerror_r is GNU-style" >&5
+$as_echo_n "checking whether strerror_r is GNU-style... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+ return 0;
+}
+
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # GNU-style
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_GNU_STRERROR_R /**/" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+$as_echo "#define HAVE_POSIX_STRERROR_R /**/" >>confdefs.h
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+else
+
+ #
+ # We don't have strerror_r; do we have strerror_s?
+ #
+ for ac_func in strerror_s
+do :
+ ac_fn_c_check_func "$LINENO" "strerror_s" "ac_cv_func_strerror_s"
+if test "x$ac_cv_func_strerror_s" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRERROR_S 1
+_ACEOF
+
+fi
+done
+
+
+fi
+
+
+#
+# Thanks, IBM, for not providing vsyslog() in AIX!
+#
+for ac_func in vsyslog
+do :
+ ac_fn_c_check_func "$LINENO" "vsyslog" "ac_cv_func_vsyslog"
+if test "x$ac_cv_func_vsyslog" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_VSYSLOG 1
+_ACEOF
+
+fi
+done
+
+
+#
+# Either:
+#
+# we have snprintf() and vsnprintf(), and have asprintf() and
+# vasprintf();
+#
+# we have snprintf() and vsnprintf(), but don't have asprintf()
+# or vasprintf();
+#
+# we have neither snprintf() nor vsnprintf(), and don't have
+# asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
+needsnprintf=no
+for ac_func in vsnprintf snprintf
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ needsnprintf=yes
+fi
+done
+
+needasprintf=no
+for ac_func in vasprintf asprintf
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+else
+ needasprintf=yes
+fi
+done
+
+if test $needsnprintf = yes; then
+ #
+ # We assume we have none of them; missing/snprintf.c supplies
+ # all of them.
+ #
+ case " $LIBOBJS " in
+ *" snprintf.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS snprintf.$ac_objext"
+ ;;
+esac
+
+elif test $needasprintf = yes; then
+ #
+ # We assume we have snprintf()/vsnprintf() but lack
+ # asprintf()/vasprintf(); missing/asprintf.c supplies
+ # the latter (using vsnprintf()).
+ #
+ case " $LIBOBJS " in
+ *" asprintf.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS asprintf.$ac_objext"
+ ;;
+esac
+
+fi
+
+needstrlcat=no
+for ac_func in strlcat
+do :
+ ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
+if test "x$ac_cv_func_strlcat" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRLCAT 1
+_ACEOF
+
+else
+ needstrlcat=yes
+fi
+done
+
+if test $needstrlcat = yes; then
+ case " $LIBOBJS " in
+ *" strlcat.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strlcat.$ac_objext"
+ ;;
+esac
+
+fi
+
+needstrlcpy=no
+for ac_func in strlcpy
+do :
+ ac_fn_c_check_func "$LINENO" "strlcpy" "ac_cv_func_strlcpy"
+if test "x$ac_cv_func_strlcpy" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRLCPY 1
+_ACEOF
+
+else
+ needstrlcpy=yes
+fi
+done
+
+if test $needstrlcpy = yes; then
+ case " $LIBOBJS " in
+ *" strlcpy.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strlcpy.$ac_objext"
+ ;;
+esac
+
+fi
+
+needstrtok_r=no
+for ac_func in strtok_r
+do :
+ ac_fn_c_check_func "$LINENO" "strtok_r" "ac_cv_func_strtok_r"
+if test "x$ac_cv_func_strtok_r" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STRTOK_R 1
+_ACEOF
+
+else
+ needstrtok_r=yes
+fi
+done
+
+if test $needstrtok_r = yes; then
+ case " $LIBOBJS " in
+ *" strtok_r.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS strtok_r.$ac_objext"
+ ;;
+esac
+
+fi
+
+#
+# Do we have ffs(), and is it declared in <strings.h>?
+#
+for ac_func in ffs
+do :
+ ac_fn_c_check_func "$LINENO" "ffs" "ac_cv_func_ffs"
+if test "x$ac_cv_func_ffs" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_FFS 1
+_ACEOF
+
+fi
+done
+
+if test "$ac_cv_func_ffs" = yes; then
+ #
+ # We have ffs(); is it declared in <strings.h>?
+ #
+ # This test fails if we don't have <strings.h> or if we do
+ # but it doesn't declare ffs().
+ #
+ ac_fn_c_check_decl "$LINENO" "ffs" "ac_cv_have_decl_ffs" "
+#include <strings.h>
+
+"
+if test "x$ac_cv_have_decl_ffs" = xyes; then :
+
+
+$as_echo "#define STRINGS_H_DECLARES_FFS /**/" >>confdefs.h
+
+
+fi
+
+fi
+
+#
+# Do this before checking for ether_hostton(), as it's a
+# "getaddrinfo()-ish function".
+#
+
+ #
+ # Most operating systems have getaddrinfo() in the default searched
+ # libraries (i.e. libc). Check there first.
+ #
+ ac_fn_c_check_func "$LINENO" "getaddrinfo" "ac_cv_func_getaddrinfo"
+if test "x$ac_cv_func_getaddrinfo" = xyes; then :
+
+else
+
+ #
+ # Not found in the standard system libraries.
+ # Try libsocket, which requires libnsl.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo in -lsocket" >&5
+$as_echo_n "checking for getaddrinfo in -lsocket... " >&6; }
+if ${ac_cv_lib_socket_getaddrinfo+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char getaddrinfo ();
+int
+main ()
+{
+return getaddrinfo ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_socket_getaddrinfo=yes
+else
+ ac_cv_lib_socket_getaddrinfo=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_getaddrinfo" >&5
+$as_echo "$ac_cv_lib_socket_getaddrinfo" >&6; }
+if test "x$ac_cv_lib_socket_getaddrinfo" = xyes; then :
+
+ #
+ # OK, we found it in libsocket.
+ #
+ LIBS="-lsocket -lnsl $LIBS"
+
+else
+
+ #
+ # We didn't find it.
+ #
+ as_fn_error $? "getaddrinfo is required, but wasn't found" "$LINENO" 5
+
+fi
+
+
+ #
+ # OK, do we have recvmsg() in libxnet?
+ # We also link with libsocket and libnsl.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for recvmsg in -lxnet" >&5
+$as_echo_n "checking for recvmsg in -lxnet... " >&6; }
+if ${ac_cv_lib_xnet_recvmsg+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lxnet -lsocket -lnsl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char recvmsg ();
+int
+main ()
+{
+return recvmsg ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_xnet_recvmsg=yes
+else
+ ac_cv_lib_xnet_recvmsg=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_xnet_recvmsg" >&5
+$as_echo "$ac_cv_lib_xnet_recvmsg" >&6; }
+if test "x$ac_cv_lib_xnet_recvmsg" = xyes; then :
+
+ #
+ # Yes - link with it as well.
+ #
+ LIBS="-lxnet $LIBS"
+
+fi
+
+
+fi
+
+ # DLPI needs putmsg under HPUX so test for -lstr while we're at it
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing putmsg" >&5
+$as_echo_n "checking for library containing putmsg... " >&6; }
+if ${ac_cv_search_putmsg+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char putmsg ();
+int
+main ()
+{
+return putmsg ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' str; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_putmsg=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_putmsg+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_putmsg+:} false; then :
+
+else
+ ac_cv_search_putmsg=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_putmsg" >&5
+$as_echo "$ac_cv_search_putmsg" >&6; }
+ac_res=$ac_cv_search_putmsg
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+
+#
+# Check for reentrant versions of getnetbyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getnetbyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getnetbyname_r();
+# without it, we can't check which API it has. (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+ac_fn_c_check_decl "$LINENO" "getnetbyname_r" "ac_cv_have_decl_getnetbyname_r" "#include <netdb.h>
+"
+if test "x$ac_cv_have_decl_getnetbyname_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getnetbyname_r()" >&5
+$as_echo_n "checking for the Linux getnetbyname_r()... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <netdb.h>
+int
+main ()
+{
+
+ struct netent netent_buf;
+ char buf[1024];
+ struct netent *resultp;
+ int h_errnoval;
+
+ return getnetbyname_r((const char *)0, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LINUX_GETNETBYNAME_R 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/IRIX getnetbyname_r()" >&5
+$as_echo_n "checking for Solaris/IRIX getnetbyname_r()... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <netdb.h>
+int
+main ()
+{
+
+ struct netent netent_buf;
+ char buf[1024];
+
+ return getnetbyname_r((const char *)0, &netent_buf, buf, (int)sizeof buf) != NULL;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SOLARIS_IRIX_GETNETBYNAME_R 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX getnetbyname_r()" >&5
+$as_echo_n "checking for AIX getnetbyname_r()... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <netdb.h>
+int
+main ()
+{
+
+ struct netent netent_buf;
+ struct netent_data net_data;
+
+ return getnetbyname_r((const char *)0, &netent_buf, &net_data);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_AIX_GETNETBYNAME_R 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+#
+# Check for reentrant versions of getprotobyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getprotobyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getprotobyname_r();
+# without it, we can't check which API it has. (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+ac_fn_c_check_decl "$LINENO" "getprotobyname_r" "ac_cv_have_decl_getprotobyname_r" "#include <netdb.h>
+"
+if test "x$ac_cv_have_decl_getprotobyname_r" = xyes; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for the Linux getprotobyname_r()" >&5
+$as_echo_n "checking for the Linux getprotobyname_r()... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <netdb.h>
+int
+main ()
+{
+
+ struct protoent protoent_buf;
+ char buf[1024];
+ struct protoent *resultp;
+
+ return getprotobyname_r((const char *)0, &protoent_buf, buf, sizeof buf, &resultp);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_LINUX_GETPROTOBYNAME_R 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for Solaris/IRIX getprotobyname_r()" >&5
+$as_echo_n "checking for Solaris/IRIX getprotobyname_r()... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <netdb.h>
+int
+main ()
+{
+
+ struct protoent protoent_buf;
+ char buf[1024];
+
+ return getprotobyname_r((const char *)0, &protoent_buf, buf, (int)sizeof buf) != NULL;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for AIX getprotobyname_r()" >&5
+$as_echo_n "checking for AIX getprotobyname_r()... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <netdb.h>
+int
+main ()
+{
+
+ struct protoent protoent_buf;
+ struct protoent_data proto_data;
+
+ return getprotobyname_r((const char *)0, &protoent_buf, &proto_data);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_AIX_GETPROTOBYNAME_R 1" >>confdefs.h
+
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it and declare it in <net/ethernet.h>.
+# Some might have it and declare it in <netinet/ether.h>
+# Some might have it and declare it in <sys/ethernet.h>.
+# Some might have it and declare it in <arpa/inet.h>.
+# Some might have it and declare it in <netinet/if_ether.h>.
+# Some might have it and not declare it in any header file.
+#
+# Before you is a C compiler.
+#
+for ac_func in ether_hostton
+do :
+ ac_fn_c_check_func "$LINENO" "ether_hostton" "ac_cv_func_ether_hostton"
+if test "x$ac_cv_func_ether_hostton" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_ETHER_HOSTTON 1
+_ACEOF
+
+fi
+done
+
+if test "$ac_cv_func_ether_hostton" = yes; then
+ #
+ # OK, we have ether_hostton(). Is it declared in <net/ethernet.h>?
+ #
+ # This test fails if we don't have <net/ethernet.h> or if we do
+ # but it doesn't declare ether_hostton().
+ #
+ ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <net/ethernet.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define NET_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <netinet/ether.h>, as on Linux?
+ #
+ # This test fails if we don't have <netinet/ether.h>
+ # or if we do but it doesn't declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <netinet/ether.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define NETINET_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <sys/ethernet.h>, as on Solaris 10
+ # and later?
+ #
+ # This test fails if we don't have <sys/ethernet.h>
+ # or if we do but it doesn't declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <sys/ethernet.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <arpa/inet.h>, as in AIX?
+ #
+ # This test fails if we don't have <arpa/inet.h>
+ # (if we have ether_hostton(), we should have
+ # networking, and if we have networking, we should
+ # have <arapa/inet.h>) or if we do but it doesn't
+ # declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <arpa/inet.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define ARPA_INET_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <netinet/if_ether.h>?
+ # On some platforms, it requires <net/if.h> and
+ # <netinet/in.h>, and we always include it with
+ # both of them, so test it with both of them.
+ #
+ # This test fails if we don't have <netinet/if_ether.h>
+ # and the headers we include before it, or if we do but
+ # <netinet/if_ether.h> doesn't declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ ac_fn_c_check_decl "$LINENO" "ether_hostton" "ac_cv_have_decl_ether_hostton" "
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+"
+if test "x$ac_cv_have_decl_ether_hostton" = xyes; then :
+
+
+$as_echo "#define NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON /**/" >>confdefs.h
+
+
+fi
+
+ fi
+ #
+ # After all that, is ether_hostton() declared?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" = yes; then
+ #
+ # Yes.
+ #
+
+$as_echo "#define HAVE_DECL_ETHER_HOSTTON 1" >>confdefs.h
+
+ else
+ #
+ # No, we'll have to declare it ourselves.
+ # Do we have "struct ether_addr" if we include
+ # <netinet/if_ether.h>?
+ #
+ ac_fn_c_check_type "$LINENO" "struct ether_addr" "ac_cv_type_struct_ether_addr" "
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <netinet/in.h>
+ #include <netinet/if_ether.h>
+
+"
+if test "x$ac_cv_type_struct_ether_addr" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_ETHER_ADDR 1
+_ACEOF
+
+
+fi
+
+ fi
+fi
+
+#
+# For various things that might use pthreads.
+#
+ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default"
+if test "x$ac_cv_header_pthread_h" = xyes; then :
+
+ #
+ # OK, we have pthread.h. Do we have pthread_create in the
+ # system libraries?
+ #
+ ac_fn_c_check_func "$LINENO" "pthread_create" "ac_cv_func_pthread_create"
+if test "x$ac_cv_func_pthread_create" = xyes; then :
+
+ #
+ # Yes.
+ #
+ ac_lbl_have_pthreads="found"
+
+else
+
+ #
+ # No - do we have it in -lpthreads?
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthreads" >&5
+$as_echo_n "checking for pthread_create in -lpthreads... " >&6; }
+if ${ac_cv_lib_pthreads_pthread_create+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthreads $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthreads_pthread_create=yes
+else
+ ac_cv_lib_pthreads_pthread_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthreads_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthreads_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthreads_pthread_create" = xyes; then :
+
+ #
+ # Yes - add -lpthreads.
+ #
+ ac_lbl_have_pthreads="found"
+ PTHREAD_LIBS="$PTHREAD_LIBS -lpthreads"
+
+else
+
+ #
+ # No - do we have it in -lpthread?
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for pthread_create in -lpthread" >&5
+$as_echo_n "checking for pthread_create in -lpthread... " >&6; }
+if ${ac_cv_lib_pthread_pthread_create+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lpthread $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char pthread_create ();
+int
+main ()
+{
+return pthread_create ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_pthread_pthread_create=yes
+else
+ ac_cv_lib_pthread_pthread_create=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_pthread_create" >&5
+$as_echo "$ac_cv_lib_pthread_pthread_create" >&6; }
+if test "x$ac_cv_lib_pthread_pthread_create" = xyes; then :
+
+ #
+ # Yes - add -lpthread.
+ #
+ ac_lbl_have_pthreads="found"
+ PTHREAD_LIBS="$PTHREAD_LIBS -lpthread"
+
+else
+
+ #
+ # No.
+ #
+ ac_lbl_have_pthreads="not found"
+
+fi
+
+
+fi
+
+
+fi
+
+
+else
+
+ #
+ # We didn't find pthread.h.
+ #
+ ac_lbl_have_pthreads="not found"
+
+
+fi
+
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-protochain option is specified" >&5
+$as_echo_n "checking if --disable-protochain option is specified... " >&6; }
+# Check whether --enable-protochain was given.
+if test "${enable_protochain+set}" = set; then :
+ enableval=$enable_protochain;
+fi
+
+case "x$enable_protochain" in
+xyes) enable_protochain=enabled ;;
+xno) enable_protochain=disabled ;;
+x) enable_protochain=enabled ;;
+esac
+
+if test "$enable_protochain" = "disabled"; then
+
+$as_echo "#define NO_PROTOCHAIN 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_protochain}" >&5
+$as_echo "${enable_protochain}" >&6; }
+
+#
+# valgrindtest directly uses the native capture mechanism, but
+# only tests with BPF and PF_PACKET sockets; only enable it if
+# we have BPF or PF_PACKET sockets.
+#
+VALGRINDTEST_SRC=
+
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+
+# Check whether --with-sita was given.
+if test "${with_sita+set}" = set; then :
+ withval=$with_sita;
+ if test ! "x$withval" = "xno" ; then
+
+$as_echo "#define SITA 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Enabling SITA ACN support" >&5
+$as_echo "$as_me: Enabling SITA ACN support" >&6;}
+ V_PCAP=sita
+ fi
+
+else
+
+
+# Check whether --with-pcap was given.
+if test "${with_pcap+set}" = set; then :
+ withval=$with_pcap;
+fi
+
+if test ! -z "$with_pcap" ; then
+ V_PCAP="$withval"
+else
+ #
+ # Check for a bunch of headers for various packet
+ # capture mechanisms.
+ #
+ for ac_header in net/bpf.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "net/bpf.h" "ac_cv_header_net_bpf_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_bpf_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_BPF_H 1
+_ACEOF
+
+fi
+
+done
+
+ if test "$ac_cv_header_net_bpf_h" = yes; then
+ #
+ # Does it define BIOCSETIF?
+ # I.e., is it a header for an LBL/BSD-style capture
+ # mechanism, or is it just a header for a BPF filter
+ # engine? Some versions of Arch Linux, for example,
+ # have a net/bpf.h that doesn't define BIOCSETIF;
+ # as it's a Linux, it should use packet sockets,
+ # instead.
+ #
+ # We need:
+ #
+ # sys/types.h, because FreeBSD 10's net/bpf.h
+ # requires that various BSD-style integer types
+ # be defined;
+ #
+ # sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+ # doesn't include it but does use struct timeval
+ # in ioctl definitions;
+ #
+ # sys/ioctl.h and, if we have it, sys/ioccom.h,
+ # because net/bpf.h defines ioctls;
+ #
+ # net/if.h, because it defines some structures
+ # used in ioctls defined by net/bpf.h;
+ #
+ # sys/socket.h, because OpenBSD 5.9's net/bpf.h
+ # defines some structure fields as being
+ # struct sockaddrs;
+ #
+ # and net/bpf.h doesn't necessarily include all
+ # of those headers itself.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if net/bpf.h defines BIOCSETIF" >&5
+$as_echo_n "checking if net/bpf.h defines BIOCSETIF... " >&6; }
+ if ${ac_cv_lbl_bpf_h_defines_biocsetif+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <net/bpf.h>
+#include <net/if.h>
+
+int
+main ()
+{
+u_int i = BIOCSETIF;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_lbl_bpf_h_defines_biocsetif=yes
+else
+ ac_cv_lbl_bpf_h_defines_biocsetif=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_bpf_h_defines_biocsetif" >&5
+$as_echo "$ac_cv_lbl_bpf_h_defines_biocsetif" >&6; }
+ fi
+ for ac_header in net/pfilt.h net/enet.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ for ac_header in net/nit.h sys/net/nit.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+ for ac_header in linux/socket.h net/raw.h sys/dlpi.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ if test "$ac_cv_lbl_bpf_h_defines_biocsetif" = yes; then
+ #
+ # BPF.
+ # Check this before DLPI, so that we pick BPF on
+ # Solaris 11 and later.
+ #
+ V_PCAP=bpf
+
+ #
+ # We have BPF, so build valgrindtest with "make test"
+ # on macOS and FreeBSD (add your OS once there's a
+ # valgrind for it).
+ #
+ case "$host_os" in
+
+ freebsd*|darwin*|linux*)
+ VALGRINDTEST_SRC=valgrindtest.c
+ ;;
+ esac
+ elif test "$ac_cv_header_linux_socket_h" = yes; then
+ #
+ # No prizes for guessing this one.
+ #
+ V_PCAP=linux
+
+ #
+ # XXX - this won't work with older kernels that have
+ # SOCK_PACKET sockets but not PF_PACKET sockets.
+ #
+ VALGRINDTEST_SRC=valgrindtest.c
+ elif test "$ac_cv_header_net_pfilt_h" = yes; then
+ #
+ # DEC OSF/1, Digital UNIX, Tru64 UNIX
+ #
+ V_PCAP=pf
+ elif test "$ac_cv_header_net_enet_h" = yes; then
+ #
+ # Stanford Enetfilter.
+ #
+ V_PCAP=enet
+ elif test "$ac_cv_header_net_nit_h" = yes; then
+ #
+ # SunOS 4.x STREAMS NIT.
+ #
+ V_PCAP=snit
+ elif test "$ac_cv_header_sys_net_nit_h" = yes; then
+ #
+ # Pre-SunOS 4.x non-STREAMS NIT.
+ #
+ V_PCAP=nit
+ elif test "$ac_cv_header_net_raw_h" = yes; then
+ #
+ # IRIX snoop.
+ #
+ V_PCAP=snoop
+ elif test "$ac_cv_header_sys_dlpi_h" = yes; then
+ #
+ # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+ #
+ V_PCAP=dlpi
+ else
+ #
+ # Nothing we support.
+ #
+ V_PCAP=null
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cannot determine packet capture interface" >&5
+$as_echo "$as_me: WARNING: cannot determine packet capture interface" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: (see the INSTALL doc for more info)" >&5
+$as_echo "$as_me: WARNING: (see the INSTALL doc for more info)" >&2;}
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking packet capture type" >&5
+$as_echo_n "checking packet capture type... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $V_PCAP" >&5
+$as_echo "$V_PCAP" >&6; }
+
+
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+ #
+ # Needed for common functions used by pcap-[dlpi,libdlpi].c
+ #
+ SSRC="dlpisubs.c"
+
+ #
+ # Checks for some header files.
+ #
+ for ac_header in sys/bufmod.h sys/dlpi_ext.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ #
+ # Checks to see if Solaris has the public libdlpi(3LIB) library.
+ # Note: The existence of /usr/include/libdlpi.h does not mean it is the
+ # public libdlpi(3LIB) version. Before libdlpi was made public, a
+ # private version also existed, which did not have the same APIs.
+ # Due to a gcc bug, the default search path for 32-bit libraries does
+ # not include /lib, we add it explicitly here.
+ # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
+ # Also, due to the bug above applications that link to libpcap with
+ # libdlpi will have to add "-L/lib" option to "configure".
+ #
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="$LIBS -L/lib"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlpi_walk in -ldlpi" >&5
+$as_echo_n "checking for dlpi_walk in -ldlpi... " >&6; }
+if ${ac_cv_lib_dlpi_dlpi_walk+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldlpi $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dlpi_walk ();
+int
+main ()
+{
+return dlpi_walk ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dlpi_dlpi_walk=yes
+else
+ ac_cv_lib_dlpi_dlpi_walk=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dlpi_dlpi_walk" >&5
+$as_echo "$ac_cv_lib_dlpi_dlpi_walk" >&6; }
+if test "x$ac_cv_lib_dlpi_dlpi_walk" = xyes; then :
+
+ LIBS="-ldlpi $LIBS"
+ V_PCAP=libdlpi
+
+$as_echo "#define HAVE_LIBDLPI 1" >>confdefs.h
+
+
+else
+ V_PCAP=dlpi
+fi
+
+ LDFLAGS=$saved_ldflags
+
+ #
+ # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+ # versions of DLPI.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether <sys/dlpi.h> is usable" >&5
+$as_echo_n "checking whether <sys/dlpi.h> is usable... " >&6; }
+ if ${ac_cv_sys_dlpi_usable+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/dlpi.h>
+
+int
+main ()
+{
+int i = DL_PROMISC_PHYS;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_sys_dlpi_usable=yes
+else
+ ac_cv_sys_dlpi_usable=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_dlpi_usable" >&5
+$as_echo "$ac_cv_sys_dlpi_usable" >&6; }
+ if test $ac_cv_sys_dlpi_usable = no ; then
+ as_fn_error $? "<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI" "$LINENO" 5
+ fi
+
+ #
+ # Check to see if Solaris has the dl_passive_req_t struct defined
+ # in <sys/dlpi.h>.
+ # This check is for DLPI support for passive modes.
+ # See dlpi(7P) for more details.
+ #
+ ac_fn_c_check_type "$LINENO" "dl_passive_req_t" "ac_cv_type_dl_passive_req_t" "
+ #include <sys/types.h>
+ #include <sys/dlpi.h>
+
+"
+if test "x$ac_cv_type_dl_passive_req_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DL_PASSIVE_REQ_T 1
+_ACEOF
+
+
+fi
+
+ ;;
+
+linux)
+ #
+ # Do we have the wireless extensions?
+ #
+ for ac_header in linux/wireless.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "linux/wireless.h" "ac_cv_header_linux_wireless_h" "
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/types.h>
+
+"
+if test "x$ac_cv_header_linux_wireless_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_WIRELESS_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ #
+ # Do we have libnl?
+ #
+
+# Check whether --with-libnl was given.
+if test "${with_libnl+set}" = set; then :
+ withval=$with_libnl; with_libnl=$withval
+else
+ with_libnl=if_available
+fi
+
+
+ if test x$with_libnl != xno ; then
+ have_any_nl="no"
+
+ incdir=-I/usr/include/libnl3
+ libnldir=
+ case "$with_libnl" in
+
+ yes|if_available)
+ ;;
+
+ *)
+ if test -d $withval; then
+ libnldir=-L${withval}/lib/.libs
+ incdir=-I${withval}/include
+ fi
+ ;;
+ esac
+
+ #
+ # Try libnl 3.x first.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl-3" >&5
+$as_echo_n "checking for nl_socket_alloc in -lnl-3... " >&6; }
+if ${ac_cv_lib_nl_3_nl_socket_alloc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl-3 ${incdir} ${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_socket_alloc ();
+int
+main ()
+{
+return nl_socket_alloc ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_nl_3_nl_socket_alloc=yes
+else
+ ac_cv_lib_nl_3_nl_socket_alloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_3_nl_socket_alloc" >&5
+$as_echo "$ac_cv_lib_nl_3_nl_socket_alloc" >&6; }
+if test "x$ac_cv_lib_nl_3_nl_socket_alloc" = xyes; then :
+
+ #
+ # Yes, we have libnl 3.x.
+ #
+ LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
+
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_3_x 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
+
+ V_INCLS="$V_INCLS ${incdir}"
+ have_any_nl="yes"
+
+fi
+
+
+ if test x$have_any_nl = xno ; then
+ #
+ # Try libnl 2.x
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_socket_alloc in -lnl" >&5
+$as_echo_n "checking for nl_socket_alloc in -lnl... " >&6; }
+if ${ac_cv_lib_nl_nl_socket_alloc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_socket_alloc ();
+int
+main ()
+{
+return nl_socket_alloc ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_nl_nl_socket_alloc=yes
+else
+ ac_cv_lib_nl_nl_socket_alloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_socket_alloc" >&5
+$as_echo "$ac_cv_lib_nl_nl_socket_alloc" >&6; }
+if test "x$ac_cv_lib_nl_nl_socket_alloc" = xyes; then :
+
+ #
+ # Yes, we have libnl 2.x.
+ #
+ LIBS="${libnldir} -lnl-genl -lnl $LIBS"
+
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_2_x 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_NLE 1" >>confdefs.h
+
+
+$as_echo "#define HAVE_LIBNL_SOCKETS 1" >>confdefs.h
+
+ have_any_nl="yes"
+
+fi
+
+ fi
+
+ if test x$have_any_nl = xno ; then
+ #
+ # No, we don't; do we have libnl 1.x?
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for nl_handle_alloc in -lnl" >&5
+$as_echo_n "checking for nl_handle_alloc in -lnl... " >&6; }
+if ${ac_cv_lib_nl_nl_handle_alloc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lnl $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char nl_handle_alloc ();
+int
+main ()
+{
+return nl_handle_alloc ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_nl_nl_handle_alloc=yes
+else
+ ac_cv_lib_nl_nl_handle_alloc=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nl_nl_handle_alloc" >&5
+$as_echo "$ac_cv_lib_nl_nl_handle_alloc" >&6; }
+if test "x$ac_cv_lib_nl_nl_handle_alloc" = xyes; then :
+
+ #
+ # Yes.
+ #
+ LIBS="${libnldir} -lnl $LIBS"
+
+$as_echo "#define HAVE_LIBNL 1" >>confdefs.h
+
+ have_any_nl="yes"
+
+fi
+
+ fi
+
+ if test x$have_any_nl = xno ; then
+ #
+ # No, we don't have libnl at all.
+ #
+ if test x$with_libnl = xyes ; then
+ as_fn_error $? "libnl support requested but libnl not found" "$LINENO" 5
+ fi
+ fi
+ fi
+
+ for ac_header in linux/ethtool.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "linux/ethtool.h" "ac_cv_header_linux_ethtool_h" "
+$ac_includes_default
+#include <linux/types.h>
+
+"
+if test "x$ac_cv_header_linux_ethtool_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_ETHTOOL_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ #
+ # Check to see if struct tpacket_stats is defined in
+ # <linux/if_packet.h>. If so, then pcap-linux.c can use this
+ # to report proper statistics.
+ #
+ # -Scott Barron
+ #
+ ac_fn_c_check_type "$LINENO" "struct tpacket_stats" "ac_cv_type_struct_tpacket_stats" "
+ #include <linux/if_packet.h>
+
+"
+if test "x$ac_cv_type_struct_tpacket_stats" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TPACKET_STATS 1
+_ACEOF
+
+
+fi
+
+
+ #
+ # Check to see if the tpacket_auxdata struct has a tp_vlan_tci member.
+ #
+ # NOTE: any failure means we conclude that it doesn't have that
+ # member, so if we don't have tpacket_auxdata, we conclude it
+ # doesn't have that member (which is OK, as either we won't be
+ # using code that would use that member, or we wouldn't compile
+ # in any case).
+ ac_fn_c_check_member "$LINENO" "struct tpacket_auxdata" "tp_vlan_tci" "ac_cv_member_struct_tpacket_auxdata_tp_vlan_tci" "
+ #include <sys/types.h>
+ #include <linux/if_packet.h>
+
+"
+if test "x$ac_cv_member_struct_tpacket_auxdata_tp_vlan_tci" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI 1
+_ACEOF
+
+
+fi
+
+ ;;
+
+bpf)
+ #
+ # Check whether we have the *BSD-style ioctls.
+ #
+ for ac_header in net/if_media.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "net/if_media.h" "ac_cv_header_net_if_media_h" "$ac_includes_default"
+if test "x$ac_cv_header_net_if_media_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_NET_IF_MEDIA_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ #
+ # Check whether we have struct BPF_TIMEVAL.
+ #
+ ac_fn_c_check_type "$LINENO" "struct BPF_TIMEVAL" "ac_cv_type_struct_BPF_TIMEVAL" "
+ #include <sys/types.h>
+ #include <sys/ioctl.h>
+ #ifdef HAVE_SYS_IOCCOM_H
+ #include <sys/ioccom.h>
+ #endif
+ #include <net/bpf.h>
+
+"
+if test "x$ac_cv_type_struct_BPF_TIMEVAL" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_BPF_TIMEVAL 1
+_ACEOF
+
+
+fi
+
+ ;;
+
+dag)
+ #
+ # --with-pcap=dag is the only way to get here, and it means
+ # "DAG support but nothing else"
+ #
+ V_DEFS="$V_DEFS -DDAG_ONLY"
+ xxx_only=yes
+ ;;
+
+septel)
+ #
+ # --with-pcap=septel is the only way to get here, and it means
+ # "Septel support but nothing else"
+ #
+ V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+ xxx_only=yes
+ ;;
+
+snf)
+ #
+ # --with-pcap=snf is the only way to get here, and it means
+ # "SNF support but nothing else"
+ #
+ V_DEFS="$V_DEFS -DSNF_ONLY"
+ xxx_only=yes
+ ;;
+
+null)
+ ;;
+
+*)
+ as_fn_error $? "$V_PCAP is not a valid pcap type" "$LINENO" 5
+ ;;
+esac
+
+if test "$V_PCAP" != null
+then
+ ac_fn_c_check_func "$LINENO" "getifaddrs" "ac_cv_func_getifaddrs"
+if test "x$ac_cv_func_getifaddrs" = xyes; then :
+
+ #
+ # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+ # as well, just in case some platform is really weird.
+ #
+ ac_fn_c_check_header_mongrel "$LINENO" "ifaddrs.h" "ac_cv_header_ifaddrs_h" "$ac_includes_default"
+if test "x$ac_cv_header_ifaddrs_h" = xyes; then :
+
+ #
+ # We have the header, so we use "getifaddrs()" to
+ # get the list of interfaces.
+ #
+ V_FINDALLDEVS=fad-getad.c
+
+else
+
+ #
+ # We don't have the header - give up.
+ # XXX - we could also fall back on some other
+ # mechanism, but, for now, this'll catch this
+ # problem so that we can at least try to figure
+ # out something to do on systems with "getifaddrs()"
+ # but without "ifaddrs.h", if there is something
+ # we can do on those systems.
+ #
+ as_fn_error $? "Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>." "$LINENO" 5
+
+fi
+
+
+
+else
+
+ #
+ # Well, we don't have "getifaddrs()", at least not with the
+ # libraries with which we've decided we need to link
+ # libpcap with, so we have to use some other mechanism.
+ #
+ # Note that this may happen on Solaris, which has
+ # getifaddrs(), but in -lsocket, not in -lxnet, so we
+ # won't find it if we link with -lxnet, which we want
+ # to do for other reasons.
+ #
+ # For now, we use either the SIOCGIFCONF ioctl or the
+ # SIOCGLIFCONF ioctl, preferring the latter if we have
+ # it; the latter is a Solarisism that first appeared
+ # in Solaris 8. (Solaris's getifaddrs() appears to
+ # be built atop SIOCGLIFCONF; using it directly
+ # avoids a not-all-that-useful middleman.)
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have SIOCGLIFCONF" >&5
+$as_echo_n "checking whether we have SIOCGLIFCONF... " >&6; }
+ if ${ac_cv_lbl_have_siocglifconf+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/param.h>
+ #include <sys/file.h>
+ #include <sys/ioctl.h>
+ #include <sys/socket.h>
+ #include <sys/sockio.h>
+int
+main ()
+{
+ioctl(0, SIOCGLIFCONF, (char *)0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_lbl_have_siocglifconf=yes
+else
+ ac_cv_lbl_have_siocglifconf=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_have_siocglifconf" >&5
+$as_echo "$ac_cv_lbl_have_siocglifconf" >&6; }
+ if test $ac_cv_lbl_have_siocglifconf = yes ; then
+ V_FINDALLDEVS=fad-glifc.c
+ else
+ V_FINDALLDEVS=fad-gifc.c
+ fi
+
+fi
+
+fi
+
+fi
+
+
+case "$host_os" in
+linux*)
+ for ac_header in linux/net_tstamp.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "linux/net_tstamp.h" "ac_cv_header_linux_net_tstamp_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_net_tstamp_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_NET_TSTAMP_H 1
+_ACEOF
+
+fi
+
+done
+
+ ;;
+*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: no hardware timestamp support implemented for $host_os" >&5
+$as_echo "$as_me: no hardware timestamp support implemented for $host_os" >&6;}
+ ;;
+esac
+
+# Check whether --enable-packet-ring was given.
+if test "${enable_packet_ring+set}" = set; then :
+ enableval=$enable_packet_ring;
+else
+ enable_packet_ring=yes
+fi
+
+
+if test "x$enable_packet_ring" != "xno" ; then
+
+$as_echo "#define PCAP_SUPPORT_PACKET_RING 1" >>confdefs.h
+
+
+fi
+
+#
+# Check for socklen_t.
+#
+ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+"
+if test "x$ac_cv_type_socklen_t" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SOCKLEN_T 1
+_ACEOF
+
+
+fi
+
+
+# Check whether --enable-ipv6 was given.
+if test "${enable_ipv6+set}" = set; then :
+ enableval=$enable_ipv6;
+else
+ enable_ipv6=yes
+fi
+
+if test "$enable_ipv6" != "no"; then
+ #
+ # We've already made sure we have getaddrinfo above in
+ # AC_LBL_LIBRARY_NET.
+ #
+
+$as_echo "#define INET6 1" >>confdefs.h
+
+fi
+
+# Check for Endace DAG card support.
+
+# Check whether --with-dag was given.
+if test "${with_dag+set}" = set; then :
+ withval=$with_dag;
+ if test "$withval" = no
+ then
+ # User doesn't want DAG support.
+ want_dag=no
+ elif test "$withval" = yes
+ then
+ # User wants DAG support but hasn't specified a directory.
+ want_dag=yes
+ else
+ # User wants DAG support and has specified a directory, so use the provided value.
+ want_dag=yes
+ dag_root=$withval
+ fi
+
+else
+
+ if test "$V_PCAP" = dag; then
+ # User requested DAG-only libpcap, so we'd better have
+ # the DAG API.
+ want_dag=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want DAG support.
+ want_dag=no
+ else
+ #
+ # Use DAG API if present, otherwise don't
+ #
+ want_dag=ifpresent
+ fi
+
+fi
+
+
+
+# Check whether --with-dag-includes was given.
+if test "${with_dag_includes+set}" = set; then :
+ withval=$with_dag_includes;
+ # User wants DAG support and has specified a header directory, so use the provided value.
+ want_dag=yes
+ dag_include_dir=$withval
+
+fi
+
+
+
+# Check whether --with-dag-libraries was given.
+if test "${with_dag_libraries+set}" = set; then :
+ withval=$with_dag_libraries;
+ # User wants DAG support and has specified a library directory, so use the provided value.
+ want_dag=yes
+ dag_lib_dir=$withval
+
+fi
+
+
+if test "$want_dag" != no; then
+
+ # If necessary, set default paths for DAG API headers and libraries.
+ if test -z "$dag_root"; then
+ dag_root=/usr/local
+ fi
+
+ if test -z "$dag_include_dir"; then
+ dag_include_dir="$dag_root/include"
+ fi
+
+ if test -z "$dag_lib_dir"; then
+ dag_lib_dir="$dag_root/lib"
+ fi
+
+ V_INCLS="$V_INCLS -I$dag_include_dir"
+
+ for ac_header in dagapi.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "dagapi.h" "ac_cv_header_dagapi_h" "$ac_includes_default"
+if test "x$ac_cv_header_dagapi_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_DAGAPI_H 1
+_ACEOF
+
+fi
+
+done
+
+
+ if test "$ac_cv_header_dagapi_h" = yes; then
+
+ if test $V_PCAP != dag ; then
+ SSRC="$SSRC pcap-dag.c"
+ fi
+
+ # Check for various DAG API functions.
+ # Don't need to save and restore LIBS to prevent -ldag being
+ # included if there's a found-action (arg 3).
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="-L$dag_lib_dir"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream in -ldag" >&5
+$as_echo_n "checking for dag_attach_stream in -ldag... " >&6; }
+if ${ac_cv_lib_dag_dag_attach_stream+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_attach_stream ();
+int
+main ()
+{
+return dag_attach_stream ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dag_dag_attach_stream=yes
+else
+ ac_cv_lib_dag_dag_attach_stream=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_attach_stream" >&5
+$as_echo "$ac_cv_lib_dag_dag_attach_stream" >&6; }
+if test "x$ac_cv_lib_dag_dag_attach_stream" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBDAG 1
+_ACEOF
+
+ LIBS="-ldag $LIBS"
+
+else
+ as_fn_error $? "DAG library lacks streams support" "$LINENO" 5
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_attach_stream64 in -ldag" >&5
+$as_echo_n "checking for dag_attach_stream64 in -ldag... " >&6; }
+if ${ac_cv_lib_dag_dag_attach_stream64+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_attach_stream64 ();
+int
+main ()
+{
+return dag_attach_stream64 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dag_dag_attach_stream64=yes
+else
+ ac_cv_lib_dag_dag_attach_stream64=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_attach_stream64" >&5
+$as_echo "$ac_cv_lib_dag_dag_attach_stream64" >&6; }
+if test "x$ac_cv_lib_dag_dag_attach_stream64" = xyes; then :
+ dag_large_streams="1"
+else
+ dag_large_streams="0"
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_erf_types in -ldag" >&5
+$as_echo_n "checking for dag_get_erf_types in -ldag... " >&6; }
+if ${ac_cv_lib_dag_dag_get_erf_types+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_get_erf_types ();
+int
+main ()
+{
+return dag_get_erf_types ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dag_dag_get_erf_types=yes
+else
+ ac_cv_lib_dag_dag_get_erf_types=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_erf_types" >&5
+$as_echo "$ac_cv_lib_dag_dag_get_erf_types" >&6; }
+if test "x$ac_cv_lib_dag_dag_get_erf_types" = xyes; then :
+
+
+$as_echo "#define HAVE_DAG_GET_ERF_TYPES 1" >>confdefs.h
+
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dag_get_stream_erf_types in -ldag" >&5
+$as_echo_n "checking for dag_get_stream_erf_types in -ldag... " >&6; }
+if ${ac_cv_lib_dag_dag_get_stream_erf_types+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-ldag $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char dag_get_stream_erf_types ();
+int
+main ()
+{
+return dag_get_stream_erf_types ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_dag_dag_get_stream_erf_types=yes
+else
+ ac_cv_lib_dag_dag_get_stream_erf_types=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dag_dag_get_stream_erf_types" >&5
+$as_echo "$ac_cv_lib_dag_dag_get_stream_erf_types" >&6; }
+if test "x$ac_cv_lib_dag_dag_get_stream_erf_types" = xyes; then :
+
+
+$as_echo "#define HAVE_DAG_GET_STREAM_ERF_TYPES 1" >>confdefs.h
+
+fi
+
+
+ LDFLAGS=$saved_ldflags
+
+ #
+ # We assume that if we have libdag we have libdagconf,
+ # as they're installed at the same time from the same
+ # package.
+ #
+ LIBS="$LIBS -ldag -ldagconf"
+ LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+
+ if test "$dag_large_streams" = 1; then
+
+$as_echo "#define HAVE_DAG_LARGE_STREAMS_API 1" >>confdefs.h
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vdag_set_device_info in -lvdag" >&5
+$as_echo_n "checking for vdag_set_device_info in -lvdag... " >&6; }
+if ${ac_cv_lib_vdag_vdag_set_device_info+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lvdag $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char vdag_set_device_info ();
+int
+main ()
+{
+return vdag_set_device_info ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_vdag_vdag_set_device_info=yes
+else
+ ac_cv_lib_vdag_vdag_set_device_info=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_vdag_vdag_set_device_info" >&5
+$as_echo "$ac_cv_lib_vdag_vdag_set_device_info" >&6; }
+if test "x$ac_cv_lib_vdag_vdag_set_device_info" = xyes; then :
+ ac_dag_have_vdag="1"
+else
+ ac_dag_have_vdag="0"
+fi
+
+ if test "$ac_dag_have_vdag" = 1; then
+
+$as_echo "#define HAVE_DAG_VDAG 1" >>confdefs.h
+
+ if test "$ac_lbl_have_pthreads" != "found"; then
+ as_fn_error $? "DAG requires pthreads, but we didn't find them" "$LINENO" 5
+ fi
+ LIBS="$LIBS $PTHREAD_LIBS"
+ fi
+ fi
+
+
+$as_echo "#define HAVE_DAG_API 1" >>confdefs.h
+
+ else
+
+ if test "$V_PCAP" = dag; then
+ # User requested "dag" capture type but we couldn't
+ # find the DAG API support.
+ as_fn_error $? "DAG support requested with --with-pcap=dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support" "$LINENO" 5
+ fi
+
+ if test "$want_dag" = yes; then
+ # User wanted DAG support but we couldn't find it.
+ as_fn_error $? "DAG support requested with --with-dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support" "$LINENO" 5
+ fi
+ fi
+fi
+
+
+# Check whether --with-septel was given.
+if test "${with_septel+set}" = set; then :
+ withval=$with_septel;
+ if test "$withval" = no
+ then
+ want_septel=no
+ elif test "$withval" = yes
+ then
+ want_septel=yes
+ septel_root=
+ else
+ want_septel=yes
+ septel_root=$withval
+ fi
+
+else
+
+ if test "$V_PCAP" = septel; then
+ # User requested Septel-only libpcap, so we'd better have
+ # the Septel API.
+ want_septel=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Septel support.
+ want_septel=no
+ else
+ #
+ # Use Septel API if present, otherwise don't
+ #
+ want_septel=ifpresent
+ fi
+
+fi
+
+
+ac_cv_lbl_septel_api=no
+if test "$with_septel" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Septel API headers" >&5
+$as_echo_n "checking whether we have Septel API headers... " >&6; }
+
+ # If necessary, set default paths for Septel API headers and libraries.
+ if test -z "$septel_root"; then
+ septel_root=$srcdir/../septel
+ fi
+
+ septel_tools_dir="$septel_root"
+ septel_include_dir="$septel_root/INC"
+
+ if test -r "$septel_include_dir/msg.h"; then
+ ac_cv_lbl_septel_api=yes
+ fi
+
+ if test "$ac_cv_lbl_septel_api" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($septel_include_dir)" >&5
+$as_echo "yes ($septel_include_dir)" >&6; }
+
+ V_INCLS="$V_INCLS -I$septel_include_dir"
+ ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+ ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+
+ if test "$V_PCAP" != septel ; then
+ SSRC="$SSRC pcap-septel.c"
+ fi
+
+
+$as_echo "#define HAVE_SEPTEL_API 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test "$V_PCAP" = septel; then
+ # User requested "septel" capture type but
+ # we couldn't find the Septel API support.
+ as_fn_error $? "Septel support requested with --with-pcap=septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support" "$LINENO" 5
+ fi
+
+ if test "$want_septel" = yes; then
+ # User wanted Septel support but we couldn't find it.
+ as_fn_error $? "Septel support requested with --with-septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support" "$LINENO" 5
+ fi
+ fi
+fi
+
+# Check for Myricom SNF support.
+
+# Check whether --with-snf was given.
+if test "${with_snf+set}" = set; then :
+ withval=$with_snf;
+ if test "$withval" = no
+ then
+ # User explicitly doesn't want SNF
+ want_snf=no
+ elif test "$withval" = yes
+ then
+ # User wants SNF support but hasn't specified a directory.
+ want_snf=yes
+ else
+ # User wants SNF support with a specified directory.
+ want_snf=yes
+ snf_root=$withval
+ fi
+
+else
+
+ if test "$V_PCAP" = snf; then
+ # User requested Sniffer-only libpcap, so we'd better have
+ # the Sniffer API.
+ want_snf=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want SNF support.
+ want_snf=no
+ else
+ #
+ # Use Sniffer API if present, otherwise don't
+ #
+ want_snf=ifpresent
+ fi
+
+fi
+
+
+
+# Check whether --with-snf-includes was given.
+if test "${with_snf_includes+set}" = set; then :
+ withval=$with_snf_includes;
+ # User wants SNF with specific header directory
+ want_snf=yes
+ snf_include_dir=$withval
+
+fi
+
+
+
+# Check whether --with-snf-libraries was given.
+if test "${with_snf_libraries+set}" = set; then :
+ withval=$with_snf_libraries;
+ # User wants SNF with specific lib directory
+ want_snf=yes
+ snf_lib_dir=$withval
+
+fi
+
+
+ac_cv_lbl_snf_api=no
+if test "$with_snf" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we have Myricom Sniffer API" >&5
+$as_echo_n "checking whether we have Myricom Sniffer API... " >&6; }
+
+ # If necessary, set default paths for Sniffer headers and libraries.
+ if test -z "$snf_root"; then
+ snf_root=/opt/snf
+ fi
+
+ if test -z "$snf_include_dir"; then
+ snf_include_dir="$snf_root/include"
+ fi
+
+ if test -z "$snf_lib_dir"; then
+ snf_lib_dir="$snf_root/lib"
+ fi
+
+ if test -f "$snf_include_dir/snf.h"; then
+ # We found a header; make sure we can link with the library
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for snf_init in -lsnf" >&5
+$as_echo_n "checking for snf_init in -lsnf... " >&6; }
+if ${ac_cv_lib_snf_snf_init+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lsnf $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char snf_init ();
+int
+main ()
+{
+return snf_init ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_snf_snf_init=yes
+else
+ ac_cv_lib_snf_snf_init=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_snf_snf_init" >&5
+$as_echo "$ac_cv_lib_snf_snf_init" >&6; }
+if test "x$ac_cv_lib_snf_snf_init" = xyes; then :
+ ac_cv_lbl_snf_api="yes"
+fi
+
+ LDFLAGS="$saved_ldflags"
+ if test "$ac_cv_lbl_snf_api" = no; then
+ as_fn_error $? "SNF API cannot correctly be linked; check config.log" "$LINENO" 5
+ fi
+ fi
+
+ if test "$ac_cv_lbl_snf_api" = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes ($snf_root)" >&5
+$as_echo "yes ($snf_root)" >&6; }
+
+ V_INCLS="$V_INCLS -I$snf_include_dir"
+ LIBS="$LIBS -lsnf"
+ LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+
+ if test "$V_PCAP" != snf ; then
+ SSRC="$SSRC pcap-snf.c"
+ fi
+
+
+$as_echo "#define HAVE_SNF_API 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test "$want_snf" = yes; then
+ # User requested "snf" capture type but
+ # we couldn't find the Sniffer API support.
+ as_fn_error $? "Myricom Sniffer support requested with --with-pcap=snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support" "$LINENO" 5
+ fi
+
+ if test "$want_snf" = yes; then
+ as_fn_error $? "Myricom Sniffer support requested with --with-snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support" "$LINENO" 5
+ fi
+ fi
+fi
+
+# Check for Riverbed TurboCap support.
+
+# Check whether --with-turbocap was given.
+if test "${with_turbocap+set}" = set; then :
+ withval=$with_turbocap;
+ if test "$withval" = no
+ then
+ # User explicitly doesn't want TurboCap
+ want_turbocap=no
+ elif test "$withval" = yes
+ then
+ # User wants TurboCap support but hasn't specified a directory.
+ want_turbocap=yes
+ else
+ # User wants TurboCap support with a specified directory.
+ want_turbocap=yes
+ turbocap_root=$withval
+ fi
+
+else
+
+ if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want TurboCap support.
+ want_turbocap=no
+ else
+ #
+ # Use TurboCap API if present, otherwise don't
+ #
+ want_turbocap=ifpresent
+ fi
+
+fi
+
+
+ac_cv_lbl_turbocap_api=no
+if test "$want_turbocap" != no; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether TurboCap is supported" >&5
+$as_echo_n "checking whether TurboCap is supported... " >&6; }
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ if test ! -z "$turbocap_root"; then
+ TURBOCAP_CFLAGS="-I$turbocap_root/include"
+ TURBOCAP_LIBS="-L$turbocap_root/lib"
+ CFLAGS="$CFLAGS $TURBOCAP_CFLAGS"
+ fi
+
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <TcApi.h>
+
+int
+main ()
+{
+
+ TC_INSTANCE a; TC_PORT b; TC_BOARD c;
+ TC_INSTANCE i;
+ (void)TcInstanceCreateByName("foo", &i);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_lbl_turbocap_api=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ CFLAGS="$save_CFLAGS"
+ if test $ac_cv_lbl_turbocap_api = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+ SSRC="$SSRC pcap-tc.c"
+ V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
+ LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
+
+
+$as_echo "#define HAVE_TC_API 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+ if test "$want_turbocap" = yes; then
+ # User wanted Turbo support but we couldn't find it.
+ as_fn_error $? "TurboCap support requested with --with-turbocap, but the TurboCap headers weren't found: make sure the TurboCap support is installed or don't request TurboCap support" "$LINENO" 5
+ fi
+ fi
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable remote packet capture" >&5
+$as_echo_n "checking whether to enable remote packet capture... " >&6; }
+# Check whether --enable-remote was given.
+if test "${enable_remote+set}" = set; then :
+ enableval=$enable_remote;
+else
+ enableval=no
+fi
+
+case "$enableval" in
+yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Remote packet capture may expose libpcap-based applications" >&5
+$as_echo "$as_me: WARNING: Remote packet capture may expose libpcap-based applications" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: to attacks by malicious remote capture servers!" >&5
+$as_echo "$as_me: WARNING: to attacks by malicious remote capture servers!" >&2;}
+ #
+ # rpcapd requires pthreads on UN*X.
+ #
+ if test "$ac_lbl_have_pthreads" != "found"; then
+ as_fn_error $? "rpcapd requires pthreads, but we didn't find them" "$LINENO" 5
+ fi
+ #
+ # It also requires crypt().
+ # Do we have it in the system libraries?
+ #
+ ac_fn_c_check_func "$LINENO" "crypt" "ac_cv_func_crypt"
+if test "x$ac_cv_func_crypt" = xyes; then :
+
+else
+
+ #
+ # No. Do we have it in -lcrypt?
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for crypt in -lcrypt" >&5
+$as_echo_n "checking for crypt in -lcrypt... " >&6; }
+if ${ac_cv_lib_crypt_crypt+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcrypt $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char crypt ();
+int
+main ()
+{
+return crypt ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_crypt_crypt=yes
+else
+ ac_cv_lib_crypt_crypt=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_crypt_crypt" >&5
+$as_echo "$ac_cv_lib_crypt_crypt" >&6; }
+if test "x$ac_cv_lib_crypt_crypt" = xyes; then :
+
+ #
+ # Yes; add -lcrypt to the libraries for rpcapd.
+ #
+ RPCAPD_LIBS="$RPCAPD_LIBS -lcrypt"
+
+else
+
+ as_fn_error $? "rpcapd requires crypt(), but we didn't find it" "$LINENO" 5
+
+fi
+
+
+fi
+
+
+ #
+ # OK, we have crypt(). Do we have getspnam()?
+ #
+ for ac_func in getspnam
+do :
+ ac_fn_c_check_func "$LINENO" "getspnam" "ac_cv_func_getspnam"
+if test "x$ac_cv_func_getspnam" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_GETSPNAM 1
+_ACEOF
+
+fi
+done
+
+
+ #
+ # Check for various members of struct msghdr.
+ #
+ ac_fn_c_check_member "$LINENO" "struct msghdr" "msg_control" "ac_cv_member_struct_msghdr_msg_control" "
+ #include \"ftmacros.h\"
+ #include <sys/socket.h>
+
+"
+if test "x$ac_cv_member_struct_msghdr_msg_control" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MSGHDR_MSG_CONTROL 1
+_ACEOF
+
+
+fi
+
+ ac_fn_c_check_member "$LINENO" "struct msghdr" "msg_flags" "ac_cv_member_struct_msghdr_msg_flags" "
+ #include \"ftmacros.h\"
+ #include <sys/socket.h>
+
+"
+if test "x$ac_cv_member_struct_msghdr_msg_flags" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_MSGHDR_MSG_FLAGS 1
+_ACEOF
+
+
+fi
+
+
+
+$as_echo "#define ENABLE_REMOTE /**/" >>confdefs.h
+
+ SSRC="$SSRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c"
+ BUILD_RPCAPD=build-rpcapd
+ INSTALL_RPCAPD=install-rpcapd
+ ;;
+*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ;;
+esac
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build optimizer debugging code" >&5
+$as_echo_n "checking whether to build optimizer debugging code... " >&6; }
+# Check whether --enable-optimizer-dbg was given.
+if test "${enable_optimizer_dbg+set}" = set; then :
+ enableval=$enable_optimizer_dbg;
+fi
+
+if test "$enable_optimizer_dbg" = "yes"; then
+
+$as_echo "#define BDEBUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_optimizer_dbg-no}" >&5
+$as_echo "${enable_optimizer_dbg-no}" >&6; }
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build parser debugging code" >&5
+$as_echo_n "checking whether to build parser debugging code... " >&6; }
+# Check whether --enable-yydebug was given.
+if test "${enable_yydebug+set}" = set; then :
+ enableval=$enable_yydebug;
+fi
+
+if test "$enable_yydebug" = "yes"; then
+
+$as_echo "#define YYDEBUG 1" >>confdefs.h
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${enable_yydebug-no}" >&5
+$as_echo "${enable_yydebug-no}" >&6; }
+
+#
+# Look for {f}lex.
+#
+for ac_prog in flex lex
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_LEX+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$LEX"; then
+ ac_cv_prog_LEX="$LEX" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_LEX="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+LEX=$ac_cv_prog_LEX
+if test -n "$LEX"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LEX" >&5
+$as_echo "$LEX" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$LEX" && break
+done
+test -n "$LEX" || LEX=":"
+
+if test "x$LEX" != "x:"; then
+ cat >conftest.l <<_ACEOF
+%%
+a { ECHO; }
+b { REJECT; }
+c { yymore (); }
+d { yyless (1); }
+e { /* IRIX 6.5 flex 2.5.4 underquotes its yyless argument. */
+ yyless ((input () != 0)); }
+f { unput (yytext[0]); }
+. { BEGIN INITIAL; }
+%%
+#ifdef YYTEXT_POINTER
+extern char *yytext;
+#endif
+int
+main (void)
+{
+ return ! yylex () + ! yywrap ();
+}
+_ACEOF
+{ { ac_try="$LEX conftest.l"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$LEX conftest.l") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking lex output file root" >&5
+$as_echo_n "checking lex output file root... " >&6; }
+if ${ac_cv_prog_lex_root+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+if test -f lex.yy.c; then
+ ac_cv_prog_lex_root=lex.yy
+elif test -f lexyy.c; then
+ ac_cv_prog_lex_root=lexyy
+else
+ as_fn_error $? "cannot find output from $LEX; giving up" "$LINENO" 5
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_root" >&5
+$as_echo "$ac_cv_prog_lex_root" >&6; }
+LEX_OUTPUT_ROOT=$ac_cv_prog_lex_root
+
+if test -z "${LEXLIB+set}"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking lex library" >&5
+$as_echo_n "checking lex library... " >&6; }
+if ${ac_cv_lib_lex+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+
+ ac_save_LIBS=$LIBS
+ ac_cv_lib_lex='none needed'
+ for ac_lib in '' -lfl -ll; do
+ LIBS="$ac_lib $ac_save_LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_lex=$ac_lib
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ test "$ac_cv_lib_lex" != 'none needed' && break
+ done
+ LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lex" >&5
+$as_echo "$ac_cv_lib_lex" >&6; }
+ test "$ac_cv_lib_lex" != 'none needed' && LEXLIB=$ac_cv_lib_lex
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether yytext is a pointer" >&5
+$as_echo_n "checking whether yytext is a pointer... " >&6; }
+if ${ac_cv_prog_lex_yytext_pointer+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # POSIX says lex can declare yytext either as a pointer or an array; the
+# default is implementation-dependent. Figure out which it is, since
+# not all implementations provide the %pointer and %array declarations.
+ac_cv_prog_lex_yytext_pointer=no
+ac_save_LIBS=$LIBS
+LIBS="$LEXLIB $ac_save_LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #define YYTEXT_POINTER 1
+`cat $LEX_OUTPUT_ROOT.c`
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_prog_lex_yytext_pointer=yes
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_save_LIBS
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_lex_yytext_pointer" >&5
+$as_echo "$ac_cv_prog_lex_yytext_pointer" >&6; }
+if test $ac_cv_prog_lex_yytext_pointer = yes; then
+
+$as_echo "#define YYTEXT_POINTER 1" >>confdefs.h
+
+fi
+rm -f conftest.l $LEX_OUTPUT_ROOT.c
+
+fi
+if test "$LEX" = ":"; then
+ as_fn_error $? "Neither flex nor lex was found." "$LINENO" 5
+fi
+
+#
+# Make sure {f}lex supports the -P, --header-file, and --nounput flags
+# and supports processing our scanner.l.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable lex" >&5
+$as_echo_n "checking for capable lex... " >&6; }
+if ${tcpdump_cv_capable_lex+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $LEX -P pcap_ --header-file=/dev/null --nounput -t $srcdir/scanner.l > /dev/null 2>&1; then
+ tcpdump_cv_capable_lex=yes
+ else
+ tcpdump_cv_capable_lex=insufficient
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_lex" >&5
+$as_echo "$tcpdump_cv_capable_lex" >&6; }
+if test $tcpdump_cv_capable_lex = insufficient ; then
+ as_fn_error $? "$LEX is insufficient to compile libpcap.
+ libpcap requires Flex 2.5.31 or later, or a compatible version of lex." "$LINENO" 5
+fi
+
+#
+# Look for yacc/bison/byacc.
+#
+for ac_prog in 'bison -y' byacc
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_YACC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$YACC"; then
+ ac_cv_prog_YACC="$YACC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_YACC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+YACC=$ac_cv_prog_YACC
+if test -n "$YACC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $YACC" >&5
+$as_echo "$YACC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$YACC" && break
+done
+test -n "$YACC" || YACC="yacc"
+
+
+#
+# Make sure it supports the -p flag and supports processing our
+# grammar.y.
+#
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for capable yacc/bison" >&5
+$as_echo_n "checking for capable yacc/bison... " >&6; }
+if ${tcpdump_cv_capable_yacc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if $YACC -p pcap_ -o /dev/null $srcdir/grammar.y >/dev/null 2>&1; then
+ tcpdump_cv_capable_yacc=yes
+ else
+ tcpdump_cv_capable_yacc=insufficient
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $tcpdump_cv_capable_yacc" >&5
+$as_echo "$tcpdump_cv_capable_yacc" >&6; }
+if test $tcpdump_cv_capable_yacc = insufficient ; then
+ as_fn_error $? "$YACC is insufficient to compile libpcap.
+ libpcap requires Bison, a newer version of Berkeley YACC with support
+ for reentrant parsers, or another YACC compatible with them." "$LINENO" 5
+fi
+
+#
+# Do various checks for various OSes and versions of those OSes.
+#
+# Assume, by default, no support for shared libraries and V7/BSD
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8). Individual cases can override this.
+#
+DYEXT="none"
+MAN_DEVICES=4
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
+MAN_ADMIN_COMMANDS=8
+case "$host_os" in
+
+aix*)
+
+$as_echo "#define _SUN 1" >>confdefs.h
+
+
+ #
+ # AIX makes it fun to build shared and static libraries,
+ # because they're *both* ".a" archive libraries. We
+ # build the static library for the benefit of the traditional
+ # scheme of building libpcap and tcpdump in subdirectories of
+ # the same directory, with tcpdump statically linked with the
+ # libpcap in question, but we also build a shared library as
+ # "libpcap.shareda" and install *it*, rather than the static
+ # library, as "libpcap.a".
+ #
+ DYEXT="shareda"
+
+ case "$V_PCAP" in
+
+ dlpi)
+ #
+ # If we're using DLPI, applications will need to
+ # use /lib/pse.exp if present, as we use the
+ # STREAMS routines.
+ #
+ pseexe="/lib/pse.exp"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $pseexe" >&5
+$as_echo_n "checking for $pseexe... " >&6; }
+ if test -f $pseexe ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ LIBS="-I:$pseexe"
+ fi
+ ;;
+
+ bpf)
+ #
+ # If we're using BPF, we need "-lodm" and "-lcfg", as
+ # we use them to load the BPF module.
+ #
+ LIBS="-lodm -lcfg"
+ ;;
+ esac
+ ;;
+
+darwin*)
+ DYEXT="dylib"
+ V_CCOPT="$V_CCOPT -fno-common"
+ # Check whether --enable-universal was given.
+if test "${enable_universal+set}" = set; then :
+ enableval=$enable_universal;
+fi
+
+ if test "$enable_universal" != "no"; then
+ case "$host_os" in
+
+ darwin[0-7].*)
+ #
+ # Pre-Tiger. Build only for 32-bit PowerPC; no
+ # need for any special compiler or linker flags.
+ #
+ ;;
+
+ darwin8.[0123]|darwin8.[0123].*)
+ #
+ # Tiger, prior to Intel support. Build
+ # libraries and executables for 32-bit PowerPC
+ # and 64-bit PowerPC, with 32-bit PowerPC first.
+ # (I'm guessing that's what Apple does.)
+ #
+ # (The double brackets are needed because
+ # autotools/m4 use brackets as a quoting
+ # character; the double brackets turn into
+ # single brackets in the generated configure
+ # file.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64"
+ V_PROG_CCOPT_FAT="-arch ppc -arch ppc64"
+ V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64"
+ ;;
+
+ darwin8.[456]|darwin.[456].*)
+ #
+ # Tiger, subsequent to Intel support but prior
+ # to x86-64 support. Build libraries and
+ # executables for 32-bit PowerPC, 64-bit
+ # PowerPC, and 32-bit x86, with 32-bit PowerPC
+ # first. (I'm guessing that's what Apple does.)
+ #
+ # (The double brackets are needed because
+ # autotools/m4 use brackets as a quoting
+ # character; the double brackets turn into
+ # single brackets in the generated configure
+ # file.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+ V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+ V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+ ;;
+
+ darwin8.*)
+ #
+ # All other Tiger, so subsequent to x86-64
+ # support. Build libraries and executables for
+ # 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+ # and x86-64, with 32-bit PowerPC first. (I'm
+ # guessing that's what Apple does.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ ;;
+
+ darwin9.*)
+ #
+ # Leopard. Build libraries for 32-bit PowerPC,
+ # 64-bit PowerPC, 32-bit x86, and x86-64, with
+ # 32-bit PowerPC first, and build executables
+ # for 32-bit x86 and 32-bit PowerPC, with 32-bit
+ # x86 first. (That's what Apple does.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_PROG_CCOPT_FAT="-arch i386 -arch ppc"
+ V_PROG_LDFLAGS_FAT="-arch i386 -arch ppc"
+ ;;
+
+ darwin10.*)
+ #
+ # Snow Leopard. Build libraries for x86-64,
+ # 32-bit x86, and 32-bit PowerPC, with x86-64
+ # first, and build executables for x86-64 and
+ # 32-bit x86, with x86-64 first. (That's what
+ # Apple does, even though Snow Leopard doesn't
+ # run on PPC, so PPC libpcap runs under Rosetta,
+ # and Rosetta doesn't support BPF ioctls, so PPC
+ # programs can't do live captures.)
+ #
+ V_LIB_CCOPT_FAT="-arch x86_64 -arch i386 -arch ppc"
+ V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386 -arch ppc"
+ V_PROG_CCOPT_FAT="-arch x86_64 -arch i386"
+ V_PROG_LDFLAGS_FAT="-arch x86_64 -arch i386"
+ ;;
+
+ darwin*)
+ #
+ # Post-Snow Leopard. Build libraries for x86-64
+ # and 32-bit x86, with x86-64 first, and build
+ # executables only for x86-64. (That's what
+ # Apple does.) This requires no special flags
+ # for programs.
+ # XXX - update if and when Apple drops support
+ # for 32-bit x86 code and if and when Apple adds
+ # ARM-based Macs. (You're on your own for iOS
+ # etc.)
+ #
+ # XXX - check whether we *can* build for
+ # i386 and, if not, suggest that the user
+ # install the /usr/include headers if they
+ # want to build fat.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether building for 32-bit x86 is supported" >&5
+$as_echo_n "checking whether building for 32-bit x86 is supported... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -arch i386"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ V_LIB_CCOPT_FAT="-arch x86_64 -arch i386"
+ V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ V_LIB_CCOPT_FAT="-arch x86_64"
+ V_LIB_LDFLAGS_FAT="-arch x86_64"
+ case "$host_os" in
+
+ darwin18.*)
+ #
+ # Mojave; you need to install the
+ # /usr/include headers to get
+ # 32-bit x86 builds to work.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package" >&5
+$as_echo "$as_me: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package" >&2;}
+ ;;
+
+ *)
+ #
+ # Pre-Mojave; the command-line
+ # tools should be sufficient to
+ # enable 32-bit x86 builds.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools" >&5
+$as_echo "$as_me: WARNING: Compiling for 32-bit x86 gives an error; try installing the command-line tools" >&2;}
+ ;;
+ esac
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+ ;;
+ esac
+ fi
+ ;;
+
+hpux9*)
+
+$as_echo "#define HAVE_HPUX9 1" >>confdefs.h
+
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+hpux10.0*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+hpux10.1*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+hpux*)
+
+$as_echo "#define HAVE_HPUX10_20_OR_LATER 1" >>confdefs.h
+
+ if test "`uname -m`" = "ia64"; then
+ DYEXT="so"
+ else
+ DYEXT="sl"
+ fi
+
+ #
+ # "-b" builds a shared library; "+h" sets the soname.
+ #
+ SHLIB_OPT="-b"
+ SONAME_OPT="+h"
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+irix*)
+ #
+ # Use IRIX conventions for man pages; they're the same as the
+ # System V conventions, except that they use section 8 for
+ # administrative commands and daemons.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*|midipix*)
+ DYEXT="so"
+
+ #
+ # Compiler assumed to be GCC; run-time linker may require a -R
+ # flag.
+ #
+ if test "$libdir" != "/usr/lib"; then
+ V_RFLAGS=-Wl,-R$libdir
+ fi
+ ;;
+
+osf*)
+ DYEXT="so"
+
+ #
+ # DEC OSF/1, a/k/a Digial UNIX, a/k/a Tru64 UNIX.
+ # Use Tru64 UNIX conventions for man pages; they're the same as
+ # the System V conventions except that they use section 8 for
+ # administrative commands and daemons.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ MAN_DEVICES=7
+ ;;
+
+sinix*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if SINIX compiler defines sinix" >&5
+$as_echo_n "checking if SINIX compiler defines sinix... " >&6; }
+ if ${ac_cv_cc_sinix_defined+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+int i = sinix;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_cc_sinix_defined=yes
+else
+ ac_cv_cc_sinix_defined=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cc_sinix_defined" >&5
+$as_echo "$ac_cv_cc_sinix_defined" >&6; }
+ if test $ac_cv_cc_sinix_defined = no ; then
+
+$as_echo "#define sinix 1" >>confdefs.h
+
+ fi
+ ;;
+
+solaris*)
+
+$as_echo "#define HAVE_SOLARIS 1" >>confdefs.h
+
+
+ DYEXT="so"
+
+ #
+ # Make sure errno is thread-safe, in case we're called in
+ # a multithreaded program. We don't guarantee that two
+ # threads can use the *same* pcap_t safely, but the
+ # current version does guarantee that you can use different
+ # pcap_t's in different threads, and even that pcap_compile()
+ # is thread-safe (it wasn't thread-safe in some older versions).
+ #
+ V_CCOPT="$V_CCOPT -D_TS_ERRNO"
+
+ case "`uname -r`" in
+
+ 5.12)
+ ;;
+
+ *)
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ MAN_DEVICES=7D
+ esac
+ ;;
+esac
+
+# Check whether --enable-shared was given.
+if test "${enable_shared+set}" = set; then :
+ enableval=$enable_shared;
+fi
+
+test "x$enable_shared" = "xno" && DYEXT="none"
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$AR"; then
+ ac_cv_prog_AR="$AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_AR="${ac_tool_prefix}ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+AR=$ac_cv_prog_AR
+if test -n "$AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5
+$as_echo "$AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_AR"; then
+ ac_ct_AR=$AR
+ # Extract the first word of "ar", so it can be a program name with args.
+set dummy ar; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_AR+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_AR"; then
+ ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_AR="ar"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_AR=$ac_cv_prog_ac_ct_AR
+if test -n "$ac_ct_AR"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5
+$as_echo "$ac_ct_AR" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_AR" = x; then
+ AR=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ AR=$ac_ct_AR
+ fi
+else
+ AR="$ac_cv_prog_AR"
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5
+$as_echo_n "checking whether ln -s works... " >&6; }
+LN_S=$as_ln_s
+if test "$LN_S" = "ln -s"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5
+$as_echo "no, using $LN_S" >&6; }
+fi
+
+
+
+rm -f os-proto.h
+ if test "${LBL_CFLAGS+set}" = set; then
+ V_CCOPT="$V_CCOPT ${LBL_CFLAGS}"
+ fi
+ if test -f .devel ; then
+ #
+ # Skip all the warning option stuff on some compilers.
+ #
+ if test "$ac_lbl_cc_dont_try_gcc_dashW" != yes; then
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler fails when given an unknown warning option" >&5
+$as_echo_n "checking whether the compiler fails when given an unknown warning option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -Wxyzzy-this-will-never-succeed-xyzzy"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ #
+ # We're assuming this is clang, where
+ # -Werror=unknown-warning-option is the appropriate
+ # option to force the compiler to fail.
+ #
+ ac_lbl_unknown_warning_option_error="-Werror=unknown-warning-option"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -W option" >&5
+$as_echo_n "checking whether the compiler supports the -W option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-W" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -W"
+ elif expr "x-W" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -W"
+ elif expr "x-W" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -W"
+ else
+ CFLAGS="$CFLAGS -W"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -W " >&5
+$as_echo_n "checking whether -W ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -W"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wall option" >&5
+$as_echo_n "checking whether the compiler supports the -Wall option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wall" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wall"
+ elif expr "x-Wall" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wall"
+ elif expr "x-Wall" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wall"
+ else
+ CFLAGS="$CFLAGS -Wall"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wall " >&5
+$as_echo_n "checking whether -Wall ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wall"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wcomma option" >&5
+$as_echo_n "checking whether the compiler supports the -Wcomma option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wcomma" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wcomma"
+ elif expr "x-Wcomma" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wcomma"
+ elif expr "x-Wcomma" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wcomma"
+ else
+ CFLAGS="$CFLAGS -Wcomma"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wcomma " >&5
+$as_echo_n "checking whether -Wcomma ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wcomma"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wdeclaration-after-statement option" >&5
+$as_echo_n "checking whether the compiler supports the -Wdeclaration-after-statement option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wdeclaration-after-statement" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wdeclaration-after-statement"
+ elif expr "x-Wdeclaration-after-statement" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wdeclaration-after-statement"
+ elif expr "x-Wdeclaration-after-statement" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wdeclaration-after-statement"
+ else
+ CFLAGS="$CFLAGS -Wdeclaration-after-statement"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wdeclaration-after-statement " >&5
+$as_echo_n "checking whether -Wdeclaration-after-statement ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wdeclaration-after-statement"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wdocumentation option" >&5
+$as_echo_n "checking whether the compiler supports the -Wdocumentation option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wdocumentation" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wdocumentation"
+ elif expr "x-Wdocumentation" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wdocumentation"
+ elif expr "x-Wdocumentation" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wdocumentation"
+ else
+ CFLAGS="$CFLAGS -Wdocumentation"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wdocumentation " >&5
+$as_echo_n "checking whether -Wdocumentation ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wdocumentation"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wformat-nonliteral option" >&5
+$as_echo_n "checking whether the compiler supports the -Wformat-nonliteral option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wformat-nonliteral" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wformat-nonliteral"
+ elif expr "x-Wformat-nonliteral" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+ elif expr "x-Wformat-nonliteral" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wformat-nonliteral"
+ else
+ CFLAGS="$CFLAGS -Wformat-nonliteral"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wformat-nonliteral " >&5
+$as_echo_n "checking whether -Wformat-nonliteral ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wformat-nonliteral"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-noreturn option" >&5
+$as_echo_n "checking whether the compiler supports the -Wmissing-noreturn option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wmissing-noreturn" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-noreturn"
+ elif expr "x-Wmissing-noreturn" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-noreturn"
+ elif expr "x-Wmissing-noreturn" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-noreturn"
+ else
+ CFLAGS="$CFLAGS -Wmissing-noreturn"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-noreturn " >&5
+$as_echo_n "checking whether -Wmissing-noreturn ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wmissing-noreturn"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-prototypes option" >&5
+$as_echo_n "checking whether the compiler supports the -Wmissing-prototypes option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wmissing-prototypes" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-prototypes"
+ elif expr "x-Wmissing-prototypes" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+ elif expr "x-Wmissing-prototypes" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-prototypes"
+ else
+ CFLAGS="$CFLAGS -Wmissing-prototypes"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-prototypes " >&5
+$as_echo_n "checking whether -Wmissing-prototypes ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wmissing-prototypes"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wmissing-variable-declarations option" >&5
+$as_echo_n "checking whether the compiler supports the -Wmissing-variable-declarations option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wmissing-variable-declarations" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wmissing-variable-declarations"
+ elif expr "x-Wmissing-variable-declarations" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-variable-declarations"
+ elif expr "x-Wmissing-variable-declarations" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wmissing-variable-declarations"
+ else
+ CFLAGS="$CFLAGS -Wmissing-variable-declarations"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wmissing-variable-declarations " >&5
+$as_echo_n "checking whether -Wmissing-variable-declarations ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wmissing-variable-declarations"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wshadow option" >&5
+$as_echo_n "checking whether the compiler supports the -Wshadow option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wshadow" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wshadow"
+ elif expr "x-Wshadow" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wshadow"
+ elif expr "x-Wshadow" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wshadow"
+ else
+ CFLAGS="$CFLAGS -Wshadow"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wshadow " >&5
+$as_echo_n "checking whether -Wshadow ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wshadow"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wsign-compare option" >&5
+$as_echo_n "checking whether the compiler supports the -Wsign-compare option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wsign-compare" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wsign-compare"
+ elif expr "x-Wsign-compare" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wsign-compare"
+ elif expr "x-Wsign-compare" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wsign-compare"
+ else
+ CFLAGS="$CFLAGS -Wsign-compare"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wsign-compare " >&5
+$as_echo_n "checking whether -Wsign-compare ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wsign-compare"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wstrict-prototypes option" >&5
+$as_echo_n "checking whether the compiler supports the -Wstrict-prototypes option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wstrict-prototypes" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wstrict-prototypes"
+ elif expr "x-Wstrict-prototypes" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wstrict-prototypes"
+ elif expr "x-Wstrict-prototypes" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wstrict-prototypes"
+ else
+ CFLAGS="$CFLAGS -Wstrict-prototypes"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wstrict-prototypes " >&5
+$as_echo_n "checking whether -Wstrict-prototypes ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wstrict-prototypes"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunused-parameter option" >&5
+$as_echo_n "checking whether the compiler supports the -Wunused-parameter option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wunused-parameter" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wunused-parameter"
+ elif expr "x-Wunused-parameter" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wunused-parameter"
+ elif expr "x-Wunused-parameter" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wunused-parameter"
+ else
+ CFLAGS="$CFLAGS -Wunused-parameter"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wunused-parameter " >&5
+$as_echo_n "checking whether -Wunused-parameter ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wunused-parameter"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wused-but-marked-unused option" >&5
+$as_echo_n "checking whether the compiler supports the -Wused-but-marked-unused option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wused-but-marked-unused" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wused-but-marked-unused"
+ elif expr "x-Wused-but-marked-unused" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
+ elif expr "x-Wused-but-marked-unused" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wused-but-marked-unused"
+ else
+ CFLAGS="$CFLAGS -Wused-but-marked-unused"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "x" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wused-but-marked-unused " >&5
+$as_echo_n "checking whether -Wused-but-marked-unused ... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wused-but-marked-unused"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ # Warns about safeguards added in case the enums are
+ # extended
+ # AC_LBL_CHECK_COMPILER_OPT(V_CCOPT, -Wcovered-switch-default)
+ #
+ # This can cause problems with ntohs(), ntohl(),
+ # htons(), and htonl() on some platforms, such
+ # as OpenBSD 6.3 with Clang 5.0.1. I guess the
+ # problem is that the macro that ultimately does
+ # the byte-swapping involves a conditional
+ # expression that tests whether the value being
+ # swapped is a compile-time constant or not,
+ # using __builtin_constant_p(), and, depending
+ # on whether it is, does a compile-time swap or
+ # a run-time swap; perhaps the compiler always
+ # considers one of the two results of the
+ # conditional expressin is never evaluated,
+ # because the conditional check is done at
+ # compile time, and thus always says "that
+ # expression is never executed".
+ #
+ # (Perhaps there should be a way of flagging
+ # an expression that you *want* evaluated at
+ # compile time, so that the compiler 1) warns
+ # if it *can't* be evaluated at compile time
+ # and 2) *doesn't* warn that the true or false
+ # branch will never be reached.)
+ #
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports the -Wunreachable-code option" >&5
+$as_echo_n "checking whether the compiler supports the -Wunreachable-code option... " >&6; }
+ save_CFLAGS="$CFLAGS"
+ if expr "x-Wunreachable-code" : "x-W.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS $ac_lbl_unknown_warning_option_error -Wunreachable-code"
+ elif expr "x-Wunreachable-code" : "x-f.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wunreachable-code"
+ elif expr "x-Wunreachable-code" : "x-m.*" >/dev/null
+ then
+ CFLAGS="$CFLAGS -Werror -Wunreachable-code"
+ else
+ CFLAGS="$CFLAGS -Wunreachable-code"
+ fi
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+return 0
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=yes
+ #
+ # The compile supports this; do we have some C code for
+ # which the warning should *not* appear?
+ # We test the fourth argument because the third argument
+ # could contain quotes, breaking the test.
+ #
+ if test "xgenerates warnings from ntohs()" != "x"
+ then
+ CFLAGS="$CFLAGS $ac_lbl_cc_force_warning_errors"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -Wunreachable-code generates warnings from ntohs()" >&5
+$as_echo_n "checking whether -Wunreachable-code generates warnings from ntohs()... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <arpa/inet.h>
+
+unsigned short
+testme(unsigned short a)
+{
+ return ntohs(a);
+}
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ #
+ # Not a problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+else
+
+ #
+ # A problem.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ can_add_to_cflags=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ CFLAGS="$save_CFLAGS"
+ if test x"$can_add_to_cflags" = "xyes"
+ then
+ V_CCOPT="$V_CCOPT -Wunreachable-code"
+ fi
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ CFLAGS="$save_CFLAGS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+ fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the compiler supports generating dependencies" >&5
+$as_echo_n "checking whether the compiler supports generating dependencies... " >&6; }
+ if test "$GCC" = yes ; then
+ #
+ # GCC, or a compiler deemed to be GCC by AC_PROG_CC (even
+ # though it's not); we assume that, in this case, the flag
+ # would be -M.
+ #
+ ac_lbl_dependency_flag="-M"
+ else
+ #
+ # Not GCC or a compiler deemed to be GCC; what platform is
+ # this? (We're assuming that if the compiler isn't GCC
+ # it's the compiler from the vendor of the OS; that won't
+ # necessarily be true for x86 platforms, where it might be
+ # the Intel C compiler.)
+ #
+ case "$host_os" in
+
+ irix*|osf*|darwin*)
+ #
+ # MIPS C for IRIX, DEC C, and clang all use -M.
+ #
+ ac_lbl_dependency_flag="-M"
+ ;;
+
+ solaris*)
+ #
+ # Sun C uses -xM.
+ #
+ ac_lbl_dependency_flag="-xM"
+ ;;
+
+ hpux*)
+ #
+ # HP's older C compilers don't support this.
+ # HP's newer C compilers support this with
+ # either +M or +Make; the older compilers
+ # interpret +M as something completely
+ # different, so we use +Make so we don't
+ # think it works with the older compilers.
+ #
+ ac_lbl_dependency_flag="+Make"
+ ;;
+
+ *)
+ #
+ # Not one of the above; assume no support for
+ # generating dependencies.
+ #
+ ac_lbl_dependency_flag=""
+ ;;
+ esac
+ fi
+
+ #
+ # Is ac_lbl_dependency_flag defined and, if so, does the compiler
+ # complain about it?
+ #
+ # Note: clang doesn't seem to exit with an error status when handed
+ # an unknown non-warning error, even if you pass it
+ # -Werror=unknown-warning-option. However, it always supports
+ # -M, so the fact that this test always succeeds with clang
+ # isn't an issue.
+ #
+ if test ! -z "$ac_lbl_dependency_flag"; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int main(void) { return 0; }
+_ACEOF
+ if { { $as_echo "$as_me:${as_lineno-$LINENO}: eval \"\$CC \$ac_lbl_dependency_flag conftest.c >/dev/null 2>&1\""; } >&5
+ (eval "$CC $ac_lbl_dependency_flag conftest.c >/dev/null 2>&1") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, with $ac_lbl_dependency_flag" >&5
+$as_echo "yes, with $ac_lbl_dependency_flag" >&6; }
+ DEPENDENCY_CFLAG="$ac_lbl_dependency_flag"
+ MKDEP='${srcdir}/mkdep'
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ #
+ # We can't run mkdep, so have "make depend" do
+ # nothing.
+ #
+ MKDEP='${srcdir}/nomkdep'
+ fi
+ rm -rf conftest*
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ #
+ # We can't run mkdep, so have "make depend" do
+ # nothing.
+ #
+ MKDEP='${srcdir}/nomkdep'
+ fi
+
+
+
+ #
+ # We used to set -n32 for IRIX 6 when not using GCC (presumed
+ # to mean that we're using MIPS C or MIPSpro C); it specified
+ # the "new" faster 32-bit ABI, introduced in IRIX 6.2. I'm
+ # not sure why that would be something to do *only* with a
+ # .devel file; why should the ABI for which we produce code
+ # depend on .devel?
+ #
+ os=`echo $host_os | sed -e 's/\([0-9][0-9]*\)[^0-9].*$/\1/'`
+ name="lbl/os-$os.h"
+ if test -f $name ; then
+ ln -s $name os-proto.h
+
+$as_echo "#define HAVE_OS_PROTO_H 1" >>confdefs.h
+
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: can't find $name" >&5
+$as_echo "$as_me: WARNING: can't find $name" >&2;}
+ fi
+ fi
+
+#
+# Check to see if the sockaddr struct has the 4.4 BSD sa_len member.
+#
+ac_fn_c_check_member "$LINENO" "struct sockaddr" "sa_len" "ac_cv_member_struct_sockaddr_sa_len" "
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+"
+if test "x$ac_cv_member_struct_sockaddr_sa_len" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_SA_LEN 1
+_ACEOF
+
+
+fi
+
+
+#
+# Check to see if there's a sockaddr_storage structure.
+#
+ac_fn_c_check_type "$LINENO" "struct sockaddr_storage" "ac_cv_type_struct_sockaddr_storage" "
+ #include <sys/types.h>
+ #include <sys/socket.h>
+
+"
+if test "x$ac_cv_type_struct_sockaddr_storage" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_STORAGE 1
+_ACEOF
+
+
+fi
+
+
+#
+# Check to see if the dl_hp_ppa_info_t struct has the HP-UX 11.00
+# dl_module_id_1 member.
+#
+# NOTE: any failure means we conclude that it doesn't have that member,
+# so if we don't have DLPI, don't have a <sys/dlpi_ext.h> header, or
+# have one that doesn't declare a dl_hp_ppa_info_t type, we conclude
+# it doesn't have that member (which is OK, as either we won't be
+# using code that would use that member, or we wouldn't compile in
+# any case).
+#
+ac_fn_c_check_member "$LINENO" "dl_hp_ppa_info_t" "dl_module_id_1" "ac_cv_member_dl_hp_ppa_info_t_dl_module_id_1" "
+ #include <sys/types.h>
+ #include <sys/dlpi.h>
+ #include <sys/dlpi_ext.h>
+
+"
+if test "x$ac_cv_member_dl_hp_ppa_info_t_dl_module_id_1" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1 1
+_ACEOF
+
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if unaligned accesses fail" >&5
+$as_echo_n "checking if unaligned accesses fail... " >&6; }
+ if ${ac_cv_lbl_unaligned_fail+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case "$host_cpu" in
+
+ #
+ # These are CPU types where:
+ #
+ # the CPU faults on an unaligned access, but at least some
+ # OSes that support that CPU catch the fault and simulate
+ # the unaligned access (e.g., Alpha/{Digital,Tru64} UNIX) -
+ # the simulation is slow, so we don't want to use it;
+ #
+ # the CPU, I infer (from the old
+ #
+ # XXX: should also check that they don't do weird things (like on arm)
+ #
+ # comment) doesn't fault on unaligned accesses, but doesn't
+ # do a normal unaligned fetch, either (e.g., presumably, ARM);
+ #
+ # for whatever reason, the test program doesn't work
+ # (this has been claimed to be the case for several of those
+ # CPUs - I don't know what the problem is; the problem
+ # was reported as "the test program dumps core" for SuperH,
+ # but that's what the test program is *supposed* to do -
+ # it dumps core before it writes anything, so the test
+ # for an empty output file should find an empty output
+ # file and conclude that unaligned accesses don't work).
+ #
+ # This run-time test won't work if you're cross-compiling, so
+ # in order to support cross-compiling for a particular CPU,
+ # we have to wire in the list of CPU types anyway, as far as
+ # I know, so perhaps we should just have a set of CPUs on
+ # which we know it doesn't work, a set of CPUs on which we
+ # know it does work, and have the script just fail on other
+ # cpu types and update it when such a failure occurs.
+ #
+ alpha*|arm*|bfin*|hp*|mips*|sh*|sparc*|ia64|nv1)
+ ac_cv_lbl_unaligned_fail=yes
+ ;;
+
+ *)
+ cat >conftest.c <<EOF
+# include <sys/types.h>
+# include <sys/wait.h>
+# include <stdio.h>
+ unsigned char a[5] = { 1, 2, 3, 4, 5 };
+ main() {
+ unsigned int i;
+ pid_t pid;
+ int status;
+ /* avoid "core dumped" message */
+ pid = fork();
+ if (pid < 0)
+ exit(2);
+ if (pid > 0) {
+ /* parent */
+ pid = waitpid(pid, &status, 0);
+ if (pid < 0)
+ exit(3);
+ exit(!WIFEXITED(status));
+ }
+ /* child */
+ i = *(unsigned int *)&a[1];
+ printf("%d\n", i);
+ exit(0);
+ }
+EOF
+ ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS \
+ conftest.c $LIBS >/dev/null 2>&1
+ if test ! -x conftest ; then
+ ac_cv_lbl_unaligned_fail=yes
+ else
+ ./conftest >conftest.out
+ if test ! -s conftest.out ; then
+ ac_cv_lbl_unaligned_fail=yes
+ else
+ ac_cv_lbl_unaligned_fail=no
+ fi
+ fi
+ rm -f -r conftest* core core.conftest
+ ;;
+ esac
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lbl_unaligned_fail" >&5
+$as_echo "$ac_cv_lbl_unaligned_fail" >&6; }
+ if test $ac_cv_lbl_unaligned_fail = yes ; then
+
+$as_echo "#define LBL_ALIGN 1" >>confdefs.h
+
+ fi
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+# Check whether --enable-usb was given.
+if test "${enable_usb+set}" = set; then :
+ enableval=$enable_usb;
+else
+ enable_usb=yes
+fi
+
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want USB support.
+ enable_usb=no
+fi
+
+if test "x$enable_usb" != "xno" ; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for USB sniffing support" >&5
+$as_echo_n "checking for USB sniffing support... " >&6; }
+ case "$host_os" in
+ linux*)
+
+$as_echo "#define PCAP_SUPPORT_USB 1" >>confdefs.h
+
+ USB_SRC=pcap-usb-linux.c
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+ if test $? -ne 0 ; then
+ ac_usb_dev_name="usbmon"
+ fi
+
+cat >>confdefs.h <<_ACEOF
+#define LINUX_USB_MON_DEV "/dev/$ac_usb_dev_name"
+_ACEOF
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Device for USB sniffing is /dev/$ac_usb_dev_name" >&5
+$as_echo "$as_me: Device for USB sniffing is /dev/$ac_usb_dev_name" >&6;}
+ #
+ # Do we have a version of <linux/compiler.h> available?
+ # If so, we might need it for <linux/usbdevice_fs.h>.
+ #
+ for ac_header in linux/compiler.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "linux/compiler.h" "ac_cv_header_linux_compiler_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_compiler_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_COMPILER_H 1
+_ACEOF
+
+fi
+
+done
+
+ if test "$ac_cv_header_linux_compiler_h" = yes; then
+ #
+ # Yes - include it when testing for <linux/usbdevice_fs.h>.
+ #
+ for ac_header in linux/usbdevice_fs.h
+do :
+ ac_fn_c_check_header_compile "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "#include <linux/compiler.h>
+"
+if test "x$ac_cv_header_linux_usbdevice_fs_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_USBDEVICE_FS_H 1
+_ACEOF
+
+fi
+
+done
+
+ else
+ for ac_header in linux/usbdevice_fs.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "linux/usbdevice_fs.h" "ac_cv_header_linux_usbdevice_fs_h" "$ac_includes_default"
+if test "x$ac_cv_header_linux_usbdevice_fs_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LINUX_USBDEVICE_FS_H 1
+_ACEOF
+
+fi
+
+done
+
+ fi
+ if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
+ #
+ # OK, does it define bRequestType? Older versions of the kernel
+ # define fields with names like "requesttype, "request", and
+ # "value", rather than "bRequestType", "bRequest", and
+ # "wValue".
+ #
+ ac_fn_c_check_member "$LINENO" "struct usbdevfs_ctrltransfer" "bRequestType" "ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" "
+ $ac_includes_default
+ #ifdef HAVE_LINUX_COMPILER_H
+ #include <linux/compiler.h>
+ #endif
+ #include <linux/usbdevice_fs.h>
+
+"
+if test "x$ac_cv_member_struct_usbdevfs_ctrltransfer_bRequestType" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE 1
+_ACEOF
+
+
+fi
+
+ fi
+ ;;
+ freebsd*)
+ #
+ # This just uses BPF in FreeBSD 8.4 and later; we don't need
+ # to check for anything special for capturing.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes, in FreeBSD 8.4 and later" >&5
+$as_echo "yes, in FreeBSD 8.4 and later" >&6; }
+ ;;
+
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ;;
+esac
+fi
+
+
+
+if test "xxx_only" != yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the platform could support netfilter sniffing" >&5
+$as_echo_n "checking whether the platform could support netfilter sniffing... " >&6; }
+ case "$host_os" in
+ linux*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ #
+ # Life's too short to deal with trying to get this to compile
+ # if you don't get the right types defined with
+ # __KERNEL_STRICT_NAMES getting defined by some other include.
+ #
+ # Check whether the includes Just Work. If not, don't turn on
+ # netfilter support.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netfilter support" >&5
+$as_echo_n "checking whether we can compile the netfilter support... " >&6; }
+ if ${ac_cv_netfilter_can_compile+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+$ac_includes_default
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_netfilter_can_compile=yes
+else
+ ac_cv_netfilter_can_compile=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_netfilter_can_compile" >&5
+$as_echo "$ac_cv_netfilter_can_compile" >&6; }
+ if test $ac_cv_netfilter_can_compile = yes ; then
+
+$as_echo "#define PCAP_SUPPORT_NETFILTER 1" >>confdefs.h
+
+ NETFILTER_SRC=pcap-netfilter-linux.c
+ fi
+ ;;
+ *)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ ;;
+ esac
+fi
+
+
+
+# Check whether --enable-netmap was given.
+if test "${enable_netmap+set}" = set; then :
+ enableval=$enable_netmap;
+else
+ enable_netmap=yes
+fi
+
+
+if test "x$enable_netmap" != "xno" ; then
+ #
+ # Check whether net/netmap_user.h is usable if NETMAP_WITH_LIBS is
+ # defined; it's not usable on DragonFly BSD 4.6 if NETMAP_WITH_LIBS
+ # is defined, for example, as it includes a non-existent malloc.h
+ # header.
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we can compile the netmap support" >&5
+$as_echo_n "checking whether we can compile the netmap support... " >&6; }
+ if ${ac_cv_net_netmap_user_can_compile+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+$ac_includes_default
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_net_netmap_user_can_compile=yes
+else
+ ac_cv_net_netmap_user_can_compile=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_net_netmap_user_can_compile" >&5
+$as_echo "$ac_cv_net_netmap_user_can_compile" >&6; }
+ if test $ac_cv_net_netmap_user_can_compile = yes ; then
+
+$as_echo "#define PCAP_SUPPORT_NETMAP 1" >>confdefs.h
+
+ NETMAP_SRC=pcap-netmap.c
+ fi
+
+
+fi
+
+
+# Check whether --enable-bluetooth was given.
+if test "${enable_bluetooth+set}" = set; then :
+ enableval=$enable_bluetooth;
+else
+ enable_bluetooth=ifsupportavailable
+fi
+
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Bluetooth support.
+ enable_bluetooth=no
+fi
+
+if test "x$enable_bluetooth" != "xno" ; then
+ case "$host_os" in
+ linux*)
+ ac_fn_c_check_header_mongrel "$LINENO" "bluetooth/bluetooth.h" "ac_cv_header_bluetooth_bluetooth_h" "$ac_includes_default"
+if test "x$ac_cv_header_bluetooth_bluetooth_h" = xyes; then :
+
+ #
+ # We have bluetooth.h, so we support Bluetooth
+ # sniffing.
+ #
+
+$as_echo "#define PCAP_SUPPORT_BT 1" >>confdefs.h
+
+ BT_SRC=pcap-bt-linux.c
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is supported" >&5
+$as_echo "$as_me: Bluetooth sniffing is supported" >&6;}
+ ac_lbl_bluetooth_available=yes
+
+ #
+ # OK, does struct sockaddr_hci have an hci_channel
+ # member?
+ #
+ ac_fn_c_check_member "$LINENO" "struct sockaddr_hci" "hci_channel" "ac_cv_member_struct_sockaddr_hci_hci_channel" "
+ #include <bluetooth/bluetooth.h>
+ #include <bluetooth/hci.h>
+
+"
+if test "x$ac_cv_member_struct_sockaddr_hci_hci_channel" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL 1
+_ACEOF
+
+
+ #
+ # Yes; is HCI_CHANNEL_MONITOR defined?
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking if HCI_CHANNEL_MONITOR is defined" >&5
+$as_echo_n "checking if HCI_CHANNEL_MONITOR is defined... " >&6; }
+ if ${ac_cv_lbl_hci_channel_monitor_is_defined+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <bluetooth/bluetooth.h>
+ #include <bluetooth/hci.h>
+
+int
+main ()
+{
+
+ u_int i = HCI_CHANNEL_MONITOR;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define PCAP_SUPPORT_BT_MONITOR /**/" >>confdefs.h
+
+ BT_MONITOR_SRC=pcap-bt-monitor-linux.c
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+
+
+fi
+
+
+else
+
+ #
+ # We don't have bluetooth.h, so we don't support
+ # Bluetooth sniffing.
+ #
+ if test "x$enable_bluetooth" = "xyes" ; then
+ as_fn_error $? "Bluetooth sniffing is not supported; install bluez-lib devel to enable it" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&5
+$as_echo "$as_me: Bluetooth sniffing is not supported; install bluez-lib devel to enable it" >&6;}
+ fi
+
+fi
+
+
+ ;;
+ *)
+ if test "x$enable_bluetooth" = "xyes" ; then
+ as_fn_error $? "no Bluetooth sniffing support implemented for $host_os" "$LINENO" 5
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: no Bluetooth sniffing support implemented for $host_os" >&5
+$as_echo "$as_me: no Bluetooth sniffing support implemented for $host_os" >&6;}
+ fi
+ ;;
+ esac
+
+
+
+fi
+
+# Check whether --enable-dbus was given.
+if test "${enable_dbus+set}" = set; then :
+ enableval=$enable_dbus;
+else
+ enable_dbus=ifavailable
+fi
+
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want D-Bus support.
+ enable_dbus=no
+fi
+
+if test "x$enable_dbus" != "xno"; then
+ if test "x$enable_dbus" = "xyes"; then
+ case "$host_os" in
+
+ darwin*)
+ #
+ # We don't support D-Bus sniffing on macOS; see
+ #
+ # https://bugs.freedesktop.org/show_bug.cgi?id=74029
+ #
+ # The user requested it, so fail.
+ #
+ as_fn_error $? "Due to freedesktop.org bug 74029, D-Bus capture support is not available on macOS" "$LINENO" 5
+ esac
+ else
+ case "$host_os" in
+
+ darwin*)
+ #
+ # We don't support D-Bus sniffing on macOS; see
+ #
+ # https://bugs.freedesktop.org/show_bug.cgi?id=74029
+ #
+ # The user dind't explicitly request it, so just
+ # silently refuse to enable it.
+ #
+ enable_dbus="no"
+ ;;
+ esac
+ fi
+fi
+
+if test "x$enable_dbus" != "xno"; then
+ # Extract the first word of "pkg-config", so it can be a program name with args.
+set dummy pkg-config; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_PKGCONFIG+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$PKGCONFIG"; then
+ ac_cv_prog_PKGCONFIG="$PKGCONFIG" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_PKGCONFIG="pkg-config"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_prog_PKGCONFIG" && ac_cv_prog_PKGCONFIG="no"
+fi
+fi
+PKGCONFIG=$ac_cv_prog_PKGCONFIG
+if test -n "$PKGCONFIG"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKGCONFIG" >&5
+$as_echo "$PKGCONFIG" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ if test "x$PKGCONFIG" != "xno"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for D-Bus" >&5
+$as_echo_n "checking for D-Bus... " >&6; }
+ if "$PKGCONFIG" dbus-1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ DBUS_CFLAGS=`"$PKGCONFIG" --cflags dbus-1`
+ DBUS_LIBS=`"$PKGCONFIG" --libs dbus-1`
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $DBUS_CFLAGS"
+ LIBS="$LIBS $DBUS_LIBS"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the D-Bus library defines dbus_connection_read_write" >&5
+$as_echo_n "checking whether the D-Bus library defines dbus_connection_read_write... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+ #include <time.h>
+ #include <sys/time.h>
+
+ #include <dbus/dbus.h>
+int
+main ()
+{
+return dbus_connection_read_write(NULL, 0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define PCAP_SUPPORT_DBUS 1" >>confdefs.h
+
+ DBUS_SRC=pcap-dbus.c
+ V_INCLS="$V_INCLS $DBUS_CFLAGS"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ if test "x$enable_dbus" = "xyes"; then
+ as_fn_error $? "--enable-dbus was given, but the D-Bus library doesn't define dbus_connection_read_write()" "$LINENO" 5
+ fi
+ LIBS="$save_LIBS"
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ CFLAGS="$save_CFLAGS"
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ if test "x$enable_dbus" = "xyes"; then
+ as_fn_error $? "--enable-dbus was given, but the dbus-1 package is not installed" "$LINENO" 5
+ fi
+ fi
+ fi
+
+
+fi
+
+# Check whether --enable-rdma was given.
+if test "${enable_rdma+set}" = set; then :
+ enableval=$enable_rdma;
+else
+ enable_rdma=ifavailable
+fi
+
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want RDMA support.
+ enable_rdma=no
+fi
+
+if test "x$enable_rdma" != "xno"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ibv_get_device_list in -libverbs" >&5
+$as_echo_n "checking for ibv_get_device_list in -libverbs... " >&6; }
+if ${ac_cv_lib_ibverbs_ibv_get_device_list+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-libverbs $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char ibv_get_device_list ();
+int
+main ()
+{
+return ibv_get_device_list ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_ibverbs_ibv_get_device_list=yes
+else
+ ac_cv_lib_ibverbs_ibv_get_device_list=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_ibverbs_ibv_get_device_list" >&5
+$as_echo "$ac_cv_lib_ibverbs_ibv_get_device_list" >&6; }
+if test "x$ac_cv_lib_ibverbs_ibv_get_device_list" = xyes; then :
+
+ ac_fn_c_check_header_mongrel "$LINENO" "infiniband/verbs.h" "ac_cv_header_infiniband_verbs_h" "$ac_includes_default"
+if test "x$ac_cv_header_infiniband_verbs_h" = xyes; then :
+
+ #
+ # ibv_create_flow may be defined as a static inline
+ # function in infiniband/verbs.h, so we can't
+ # use AC_CHECK_LIB.
+ #
+ # Too bad autoconf has no AC_SYMBOL_EXISTS()
+ # macro that works like CMake's check_symbol_exists()
+ # function, to check do a compile check like
+ # this (they do a clever trick to avoid having
+ # to know the function's signature).
+ #
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether libibverbs defines ibv_create_flow" >&5
+$as_echo_n "checking whether libibverbs defines ibv_create_flow... " >&6; }
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+ #include <infiniband/verbs.h>
+
+int
+main ()
+{
+
+ (void) ibv_create_flow((struct ibv_qp *) NULL,
+ (struct ibv_flow_attr *) NULL);
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define PCAP_SUPPORT_RDMASNIFF /**/" >>confdefs.h
+
+ RDMA_SRC=pcap-rdmasniff.c
+ LIBS="-libverbs $LIBS"
+
+else
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+
+fi
+
+
+
+fi
+
+
+
+fi
+
+# Find a good install program. We prefer a C program (faster),
+# so one script is as good as another. But avoid the broken or
+# incompatible versions:
+# SysV /etc/install, /usr/sbin/install
+# SunOS /usr/etc/install
+# IRIX /sbin/install
+# AIX /bin/install
+# AmigaOS /C/install, which installs bootblocks on floppy discs
+# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag
+# AFS /usr/afsws/bin/install, which mishandles nonexistent args
+# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff"
+# OS/2's system install, which has a completely different semantic
+# ./install, which can be erroneously created by make from ./install.sh.
+# Reject install programs that cannot install multiple files.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5
+$as_echo_n "checking for a BSD-compatible install... " >&6; }
+if test -z "$INSTALL"; then
+if ${ac_cv_path_install+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ # Account for people who put trailing slashes in PATH elements.
+case $as_dir/ in #((
+ ./ | .// | /[cC]/* | \
+ /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \
+ ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \
+ /usr/ucb/* ) ;;
+ *)
+ # OSF1 and SCO ODT 3.0 have their own names for install.
+ # Don't use installbsd from OSF since it installs stuff as root
+ # by default.
+ for ac_prog in ginstall scoinst install; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then
+ if test $ac_prog = install &&
+ grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # AIX install. It has an incompatible calling convention.
+ :
+ elif test $ac_prog = install &&
+ grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then
+ # program-specific install script used by HP pwplus--don't use.
+ :
+ else
+ rm -rf conftest.one conftest.two conftest.dir
+ echo one > conftest.one
+ echo two > conftest.two
+ mkdir conftest.dir
+ if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" &&
+ test -s conftest.one && test -s conftest.two &&
+ test -s conftest.dir/conftest.one &&
+ test -s conftest.dir/conftest.two
+ then
+ ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c"
+ break 3
+ fi
+ fi
+ fi
+ done
+ done
+ ;;
+esac
+
+ done
+IFS=$as_save_IFS
+
+rm -rf conftest.one conftest.two conftest.dir
+
+fi
+ if test "${ac_cv_path_install+set}" = set; then
+ INSTALL=$ac_cv_path_install
+ else
+ # As a last resort, use the slow shell script. Don't cache a
+ # value for INSTALL within a source directory, because that will
+ # break other packages using the cache if that directory is
+ # removed, or if the value is a relative name.
+ INSTALL=$ac_install_sh
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5
+$as_echo "$INSTALL" >&6; }
+
+# Use test -z because SunOS4 sh mishandles braces in ${var-val}.
+# It thinks the first close brace ends the variable substitution.
+test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}'
+
+test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}'
+
+test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644'
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_config_commands="$ac_config_commands default-1"
+
+ac_config_files="$ac_config_files Makefile pcap-filter.manmisc pcap-linktype.manmisc pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap pcap_open_offline.3pcap pcap_set_immediate_mode.3pcap pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap rpcapd/Makefile rpcapd/rpcapd.manadmin rpcapd/rpcapd-config.manfile testprogs/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by pcap $as_me 1.9.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+config_commands="$ac_config_commands"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Configuration commands:
+$config_commands
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+pcap config.status 1.9.1
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+INSTALL='$INSTALL'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+#
+# INIT-COMMANDS
+#
+
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "default-1") CONFIG_COMMANDS="$CONFIG_COMMANDS default-1" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "pcap-filter.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-filter.manmisc" ;;
+ "pcap-linktype.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-linktype.manmisc" ;;
+ "pcap-tstamp.manmisc") CONFIG_FILES="$CONFIG_FILES pcap-tstamp.manmisc" ;;
+ "pcap-savefile.manfile") CONFIG_FILES="$CONFIG_FILES pcap-savefile.manfile" ;;
+ "pcap.3pcap") CONFIG_FILES="$CONFIG_FILES pcap.3pcap" ;;
+ "pcap_compile.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_compile.3pcap" ;;
+ "pcap_datalink.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_datalink.3pcap" ;;
+ "pcap_dump_open.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_dump_open.3pcap" ;;
+ "pcap_get_tstamp_precision.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_get_tstamp_precision.3pcap" ;;
+ "pcap_list_datalinks.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_datalinks.3pcap" ;;
+ "pcap_list_tstamp_types.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_list_tstamp_types.3pcap" ;;
+ "pcap_open_dead.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_dead.3pcap" ;;
+ "pcap_open_offline.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_open_offline.3pcap" ;;
+ "pcap_set_immediate_mode.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_immediate_mode.3pcap" ;;
+ "pcap_set_tstamp_precision.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_precision.3pcap" ;;
+ "pcap_set_tstamp_type.3pcap") CONFIG_FILES="$CONFIG_FILES pcap_set_tstamp_type.3pcap" ;;
+ "rpcapd/Makefile") CONFIG_FILES="$CONFIG_FILES rpcapd/Makefile" ;;
+ "rpcapd/rpcapd.manadmin") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd.manadmin" ;;
+ "rpcapd/rpcapd-config.manfile") CONFIG_FILES="$CONFIG_FILES rpcapd/rpcapd-config.manfile" ;;
+ "testprogs/Makefile") CONFIG_FILES="$CONFIG_FILES testprogs/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+ test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = ""
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = ""
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS"
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+ case $INSTALL in
+ [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;;
+ *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;;
+ esac
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+s&@INSTALL@&$ac_INSTALL&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+ :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5
+$as_echo "$as_me: executing $ac_file commands" >&6;}
+ ;;
+ esac
+
+
+ case $ac_file$ac_mode in
+ "default-1":C) if test -f .devel; then
+ echo timestamp > stamp-h
+ cat $srcdir/Makefile-devel-adds >> Makefile
+ make depend
+fi ;;
+
+ esac
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
+exit 0
diff --git a/lib/libpcap/libpcap/configure.ac b/lib/libpcap/libpcap/configure.ac
new file mode 100644
index 0000000..eba2723
--- /dev/null
+++ b/lib/libpcap/libpcap/configure.ac
@@ -0,0 +1,2465 @@
+dnl
+dnl Copyright (c) 1994, 1995, 1996, 1997
+dnl The Regents of the University of California. All rights reserved.
+dnl
+dnl Process this file with autoconf to produce a configure script.
+dnl
+
+#
+# See
+#
+# http://ftp.gnu.org/gnu/config/README
+#
+# for the URLs to use to fetch new versions of config.guess and
+# config.sub.
+#
+
+AC_PREREQ(2.64)
+
+AC_INIT(pcap, m4_esyscmd_s([cat VERSION]))
+AC_CONFIG_SRCDIR(pcap.c)
+AC_SUBST(PACKAGE_NAME)
+
+AC_CANONICAL_SYSTEM
+
+AC_LBL_C_INIT_BEFORE_CC(V_CCOPT, V_INCLS)
+#
+# Try to enable as many C99 features as we can.
+# At minimum, we want C++/C99-style // comments.
+#
+AC_PROG_CC_C99
+if test "$ac_cv_prog_cc_c99" = "no"; then
+ AC_MSG_WARN([The C compiler does not support C99; there may be compiler errors])
+fi
+AC_LBL_C_INIT(V_CCOPT, V_INCLS)
+AC_LBL_SHLIBS_INIT
+AC_LBL_C_INLINE
+
+#
+# Try to arrange for large file support.
+#
+AC_SYS_LARGEFILE
+AC_FUNC_FSEEKO
+
+dnl
+dnl Even if <net/bpf.h> were, on all OSes that support BPF, fixed to
+dnl include <sys/ioccom.h>, and we were to drop support for older
+dnl releases without that fix, so that pcap-bpf.c doesn't need to
+dnl include <sys/ioccom.h>, the test program in "AC_LBL_FIXINCLUDES"
+dnl in "aclocal.m4" uses it, so we would still have to test for it
+dnl and set "HAVE_SYS_IOCCOM_H" if we have it, otherwise
+dnl "AC_LBL_FIXINCLUDES" wouldn't work on some platforms such as Solaris.
+dnl
+AC_CHECK_HEADERS(sys/ioccom.h sys/sockio.h limits.h)
+AC_CHECK_HEADERS(netpacket/packet.h)
+AC_CHECK_HEADERS(net/pfvar.h, , , [#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>])
+if test "$ac_cv_header_net_pfvar_h" = yes; then
+ #
+ # Check for various PF actions.
+ #
+ AC_MSG_CHECKING(whether net/pfvar.h defines PF_NAT through PF_NORDR)
+ AC_TRY_COMPILE(
+ [#include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <net/pfvar.h>],
+ [return PF_NAT+PF_NONAT+PF_BINAT+PF_NOBINAT+PF_RDR+PF_NORDR;],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_PF_NAT_THROUGH_PF_NORDR, 1,
+ [define if net/pfvar.h defines PF_NAT through PF_NORDR])
+ ],
+ AC_MSG_RESULT(no))
+fi
+
+case "$host_os" in
+linux*|uclinux*)
+ AC_CHECK_HEADERS(linux/sockios.h linux/if_bonding.h,,,
+ [
+#include <sys/socket.h>
+#include <linux/if.h>
+ ])
+ ;;
+esac
+
+AC_LBL_FIXINCLUDES
+
+AC_CHECK_FUNCS(strerror)
+AC_CHECK_FUNC(strerror_r,
+ [
+ #
+ # We have strerror_r; if we define _GNU_SOURCE, is it a
+ # POSIX-compliant strerror_r() or a GNU strerror_r()?
+ #
+ AC_MSG_CHECKING(whether strerror_r is GNU-style)
+ AC_COMPILE_IFELSE(
+ [
+ AC_LANG_SOURCE(
+#define _GNU_SOURCE
+#include <string.h>
+
+/* Define it GNU-style; that will cause an error if it's not GNU-style */
+extern char *strerror_r(int, char *, size_t);
+
+int
+main(void)
+{
+ return 0;
+}
+)
+ ],
+ [
+ # GNU-style
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_GNU_STRERROR_R,,
+ [Define to 1 if you have a GNU-style `strerror_r' function.])
+ ],
+ [
+ AC_MSG_RESULT(no)
+ AC_DEFINE(HAVE_POSIX_STRERROR_R,,
+ [Define to 1 if you have a POSIX-style `strerror_r' function.])
+ ])
+ ],
+ [
+ #
+ # We don't have strerror_r; do we have strerror_s?
+ #
+ AC_CHECK_FUNCS(strerror_s)
+ ])
+
+#
+# Thanks, IBM, for not providing vsyslog() in AIX!
+#
+AC_CHECK_FUNCS(vsyslog)
+
+#
+# Either:
+#
+# we have snprintf() and vsnprintf(), and have asprintf() and
+# vasprintf();
+#
+# we have snprintf() and vsnprintf(), but don't have asprintf()
+# or vasprintf();
+#
+# we have neither snprintf() nor vsnprintf(), and don't have
+# asprintf() or vasprintf(), either.
+#
+# We assume that if we have asprintf() we have vasprintf(), as well
+# as snprintf() and vsnprintf(), and that if we have snprintf() we
+# have vsnprintf().
+#
+# For the first case, we don't need any replacement routines.
+# For the second case, we need replacement asprintf()/vasprintf()
+# routines.
+# For the third case, we need replacement snprintf()/vsnprintf() and
+# asprintf()/vasprintf() routines.
+#
+needsnprintf=no
+AC_CHECK_FUNCS(vsnprintf snprintf,,
+ [needsnprintf=yes])
+needasprintf=no
+AC_CHECK_FUNCS(vasprintf asprintf,,
+ [needasprintf=yes])
+if test $needsnprintf = yes; then
+ #
+ # We assume we have none of them; missing/snprintf.c supplies
+ # all of them.
+ #
+ AC_LIBOBJ([snprintf])
+elif test $needasprintf = yes; then
+ #
+ # We assume we have snprintf()/vsnprintf() but lack
+ # asprintf()/vasprintf(); missing/asprintf.c supplies
+ # the latter (using vsnprintf()).
+ #
+ AC_LIBOBJ([asprintf])
+fi
+
+needstrlcat=no
+AC_CHECK_FUNCS(strlcat,,
+ [needstrlcat=yes])
+if test $needstrlcat = yes; then
+ AC_LIBOBJ([strlcat])
+fi
+
+needstrlcpy=no
+AC_CHECK_FUNCS(strlcpy,,
+ [needstrlcpy=yes])
+if test $needstrlcpy = yes; then
+ AC_LIBOBJ([strlcpy])
+fi
+
+needstrtok_r=no
+AC_CHECK_FUNCS(strtok_r,,
+ [needstrtok_r=yes])
+if test $needstrtok_r = yes; then
+ AC_LIBOBJ([strtok_r])
+fi
+
+#
+# Do we have ffs(), and is it declared in <strings.h>?
+#
+AC_CHECK_FUNCS(ffs)
+if test "$ac_cv_func_ffs" = yes; then
+ #
+ # We have ffs(); is it declared in <strings.h>?
+ #
+ # This test fails if we don't have <strings.h> or if we do
+ # but it doesn't declare ffs().
+ #
+ AC_CHECK_DECL(ffs,
+ [
+ AC_DEFINE(STRINGS_H_DECLARES_FFS,,
+ [Define to 1 if strings.h declares `ffs'])
+ ],,
+ [
+#include <strings.h>
+ ])
+fi
+
+#
+# Do this before checking for ether_hostton(), as it's a
+# "getaddrinfo()-ish function".
+#
+AC_LBL_LIBRARY_NET
+
+#
+# Check for reentrant versions of getnetbyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getnetbyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getnetbyname_r();
+# without it, we can't check which API it has. (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+AC_CHECK_DECL(getnetbyname_r,
+ [
+ AC_MSG_CHECKING([for the Linux getnetbyname_r()])
+ AC_TRY_LINK(
+ [#include <netdb.h>],
+ [
+ struct netent netent_buf;
+ char buf[1024];
+ struct netent *resultp;
+ int h_errnoval;
+
+ return getnetbyname_r((const char *)0, &netent_buf, buf, sizeof buf, &resultp, &h_errnoval);
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LINUX_GETNETBYNAME_R, 1,
+ [define if we have the Linux getnetbyname_r()])
+ ],
+ [
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([for Solaris/IRIX getnetbyname_r()])
+ AC_TRY_LINK(
+ [#include <netdb.h>],
+ [
+ struct netent netent_buf;
+ char buf[1024];
+
+ return getnetbyname_r((const char *)0, &netent_buf, buf, (int)sizeof buf) != NULL;
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SOLARIS_IRIX_GETNETBYNAME_R, 1,
+ [define if we have the Solaris/IRIX getnetbyname_r()])
+ ],
+ [
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([for AIX getnetbyname_r()])
+ AC_TRY_LINK(
+ [#include <netdb.h>],
+ [
+ struct netent netent_buf;
+ struct netent_data net_data;
+
+ return getnetbyname_r((const char *)0, &netent_buf, &net_data);
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_AIX_GETNETBYNAME_R, 1,
+ [define if we have the AIX getnetbyname_r()])
+ ],
+ [
+ AC_MSG_RESULT(no)
+ ])
+ ])
+ ])
+ ],,[#include <netdb.h>])
+
+#
+# Check for reentrant versions of getprotobyname_r(), as provided by
+# Linux (glibc), Solaris/IRIX, and AIX (with three different APIs!).
+# If we don't find one, we just use getprotobyname(), which uses
+# thread-specific data on many platforms, but doesn't use it on
+# NetBSD or OpenBSD, and may not use it on older versions of other
+# platforms.
+#
+# Only do the check if we have a declaration of getprotobyname_r();
+# without it, we can't check which API it has. (We assume that
+# if there's a declaration, it has a prototype, so that the API
+# can be checked.)
+#
+AC_CHECK_DECL(getprotobyname_r,
+ [
+ AC_MSG_CHECKING([for the Linux getprotobyname_r()])
+ AC_TRY_LINK(
+ [#include <netdb.h>],
+ [
+ struct protoent protoent_buf;
+ char buf[1024];
+ struct protoent *resultp;
+
+ return getprotobyname_r((const char *)0, &protoent_buf, buf, sizeof buf, &resultp);
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_LINUX_GETPROTOBYNAME_R, 1,
+ [define if we have the Linux getprotobyname_r()])
+ ],
+ [
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([for Solaris/IRIX getprotobyname_r()])
+ AC_TRY_LINK(
+ [#include <netdb.h>],
+ [
+ struct protoent protoent_buf;
+ char buf[1024];
+
+ return getprotobyname_r((const char *)0, &protoent_buf, buf, (int)sizeof buf) != NULL;
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_SOLARIS_IRIX_GETPROTOBYNAME_R, 1,
+ [define if we have the Solaris/IRIX getprotobyname_r()])
+ ],
+ [
+ AC_MSG_RESULT(no)
+
+ AC_MSG_CHECKING([for AIX getprotobyname_r()])
+ AC_TRY_LINK(
+ [#include <netdb.h>],
+ [
+ struct protoent protoent_buf;
+ struct protoent_data proto_data;
+
+ return getprotobyname_r((const char *)0, &protoent_buf, &proto_data);
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_AIX_GETPROTOBYNAME_R, 1,
+ [define if we have the AIX getprotobyname_r()])
+ ],
+ [
+ AC_MSG_RESULT(no)
+ ])
+ ])
+ ])
+ ],,[#include <netdb.h>])
+
+#
+# You are in a twisty little maze of UN*Xes, all different.
+# Some might not have ether_hostton().
+# Some might have it and declare it in <net/ethernet.h>.
+# Some might have it and declare it in <netinet/ether.h>
+# Some might have it and declare it in <sys/ethernet.h>.
+# Some might have it and declare it in <arpa/inet.h>.
+# Some might have it and declare it in <netinet/if_ether.h>.
+# Some might have it and not declare it in any header file.
+#
+# Before you is a C compiler.
+#
+AC_CHECK_FUNCS(ether_hostton)
+if test "$ac_cv_func_ether_hostton" = yes; then
+ #
+ # OK, we have ether_hostton(). Is it declared in <net/ethernet.h>?
+ #
+ # This test fails if we don't have <net/ethernet.h> or if we do
+ # but it doesn't declare ether_hostton().
+ #
+ AC_CHECK_DECL(ether_hostton,
+ [
+ AC_DEFINE(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON,,
+ [Define to 1 if net/ethernet.h declares `ether_hostton'])
+ ],,
+ [
+#include <net/ethernet.h>
+ ])
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <netinet/ether.h>, as on Linux?
+ #
+ # This test fails if we don't have <netinet/ether.h>
+ # or if we do but it doesn't declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ AC_CHECK_DECL(ether_hostton,
+ [
+ AC_DEFINE(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON,,
+ [Define to 1 if netinet/ether.h declares `ether_hostton'])
+ ],,
+ [
+#include <netinet/ether.h>
+ ])
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <sys/ethernet.h>, as on Solaris 10
+ # and later?
+ #
+ # This test fails if we don't have <sys/ethernet.h>
+ # or if we do but it doesn't declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ AC_CHECK_DECL(ether_hostton,
+ [
+ AC_DEFINE(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON,,
+ [Define to 1 if sys/ethernet.h declares `ether_hostton'])
+ ],,
+ [
+#include <sys/ethernet.h>
+ ])
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <arpa/inet.h>, as in AIX?
+ #
+ # This test fails if we don't have <arpa/inet.h>
+ # (if we have ether_hostton(), we should have
+ # networking, and if we have networking, we should
+ # have <arapa/inet.h>) or if we do but it doesn't
+ # declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ AC_CHECK_DECL(ether_hostton,
+ [
+ AC_DEFINE(ARPA_INET_H_DECLARES_ETHER_HOSTTON,,
+ [Define to 1 if arpa/inet.h declares `ether_hostton'])
+ ],,
+ [
+#include <arpa/inet.h>
+ ])
+ fi
+ #
+ # Did that succeed?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" != yes; then
+ #
+ # No, how about <netinet/if_ether.h>?
+ # On some platforms, it requires <net/if.h> and
+ # <netinet/in.h>, and we always include it with
+ # both of them, so test it with both of them.
+ #
+ # This test fails if we don't have <netinet/if_ether.h>
+ # and the headers we include before it, or if we do but
+ # <netinet/if_ether.h> doesn't declare ether_hostton().
+ #
+ # Unset ac_cv_have_decl_ether_hostton so we don't
+ # treat the previous failure as a cached value and
+ # suppress the next test.
+ #
+ unset ac_cv_have_decl_ether_hostton
+ AC_CHECK_DECL(ether_hostton,
+ [
+ AC_DEFINE(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON,,
+ [Define to 1 if netinet/if_ether.h declares `ether_hostton'])
+ ],,
+ [
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+ ])
+ fi
+ #
+ # After all that, is ether_hostton() declared?
+ #
+ if test "$ac_cv_have_decl_ether_hostton" = yes; then
+ #
+ # Yes.
+ #
+ AC_DEFINE(HAVE_DECL_ETHER_HOSTTON, 1,
+ [Define to 1 if you have the declaration of `ether_hostton'])
+ else
+ #
+ # No, we'll have to declare it ourselves.
+ # Do we have "struct ether_addr" if we include
+ # <netinet/if_ether.h>?
+ #
+ AC_CHECK_TYPES(struct ether_addr,,,
+ [
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <net/if.h>
+ #include <netinet/in.h>
+ #include <netinet/if_ether.h>
+ ])
+ fi
+fi
+
+#
+# For various things that might use pthreads.
+#
+AC_CHECK_HEADER(pthread.h,
+ [
+ #
+ # OK, we have pthread.h. Do we have pthread_create in the
+ # system libraries?
+ #
+ AC_CHECK_FUNC(pthread_create,
+ [
+ #
+ # Yes.
+ #
+ ac_lbl_have_pthreads="found"
+ ],
+ [
+ #
+ # No - do we have it in -lpthreads?
+ #
+ AC_CHECK_LIB(pthreads, pthread_create,
+ [
+ #
+ # Yes - add -lpthreads.
+ #
+ ac_lbl_have_pthreads="found"
+ PTHREAD_LIBS="$PTHREAD_LIBS -lpthreads"
+ ],
+ [
+ #
+ # No - do we have it in -lpthread?
+ #
+ AC_CHECK_LIB(pthread, pthread_create,
+ [
+ #
+ # Yes - add -lpthread.
+ #
+ ac_lbl_have_pthreads="found"
+ PTHREAD_LIBS="$PTHREAD_LIBS -lpthread"
+ ],
+ [
+ #
+ # No.
+ #
+ ac_lbl_have_pthreads="not found"
+ ])
+ ])
+ ])
+ ],
+ [
+ #
+ # We didn't find pthread.h.
+ #
+ ac_lbl_have_pthreads="not found"
+ ]
+)
+
+dnl to pacify those who hate protochain insn
+AC_MSG_CHECKING(if --disable-protochain option is specified)
+AC_ARG_ENABLE(protochain,
+AC_HELP_STRING([--disable-protochain],[disable \"protochain\" insn]))
+case "x$enable_protochain" in
+xyes) enable_protochain=enabled ;;
+xno) enable_protochain=disabled ;;
+x) enable_protochain=enabled ;;
+esac
+
+if test "$enable_protochain" = "disabled"; then
+ AC_DEFINE(NO_PROTOCHAIN,1,[do not use protochain])
+fi
+AC_MSG_RESULT(${enable_protochain})
+
+#
+# valgrindtest directly uses the native capture mechanism, but
+# only tests with BPF and PF_PACKET sockets; only enable it if
+# we have BPF or PF_PACKET sockets.
+#
+VALGRINDTEST_SRC=
+
+#
+# SITA support is mutually exclusive with native capture support;
+# "--with-sita" selects SITA support.
+#
+AC_ARG_WITH(sita,
+AC_HELP_STRING([--with-sita],[include SITA support]),
+[
+ if test ! "x$withval" = "xno" ; then
+ AC_DEFINE(SITA,1,[include ACN support])
+ AC_MSG_NOTICE(Enabling SITA ACN support)
+ V_PCAP=sita
+ fi
+],
+[
+AC_ARG_WITH(pcap,
+AC_HELP_STRING([--with-pcap=TYPE],[use packet capture TYPE]))
+if test ! -z "$with_pcap" ; then
+ V_PCAP="$withval"
+else
+ #
+ # Check for a bunch of headers for various packet
+ # capture mechanisms.
+ #
+ AC_CHECK_HEADERS(net/bpf.h)
+ if test "$ac_cv_header_net_bpf_h" = yes; then
+ #
+ # Does it define BIOCSETIF?
+ # I.e., is it a header for an LBL/BSD-style capture
+ # mechanism, or is it just a header for a BPF filter
+ # engine? Some versions of Arch Linux, for example,
+ # have a net/bpf.h that doesn't define BIOCSETIF;
+ # as it's a Linux, it should use packet sockets,
+ # instead.
+ #
+ # We need:
+ #
+ # sys/types.h, because FreeBSD 10's net/bpf.h
+ # requires that various BSD-style integer types
+ # be defined;
+ #
+ # sys/time.h, because AIX 5.2 and 5.3's net/bpf.h
+ # doesn't include it but does use struct timeval
+ # in ioctl definitions;
+ #
+ # sys/ioctl.h and, if we have it, sys/ioccom.h,
+ # because net/bpf.h defines ioctls;
+ #
+ # net/if.h, because it defines some structures
+ # used in ioctls defined by net/bpf.h;
+ #
+ # sys/socket.h, because OpenBSD 5.9's net/bpf.h
+ # defines some structure fields as being
+ # struct sockaddrs;
+ #
+ # and net/bpf.h doesn't necessarily include all
+ # of those headers itself.
+ #
+ AC_MSG_CHECKING(if net/bpf.h defines BIOCSETIF)
+ AC_CACHE_VAL(ac_cv_lbl_bpf_h_defines_biocsetif,
+ AC_TRY_COMPILE(
+[
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <net/bpf.h>
+#include <net/if.h>
+],
+ [u_int i = BIOCSETIF;],
+ ac_cv_lbl_bpf_h_defines_biocsetif=yes,
+ ac_cv_lbl_bpf_h_defines_biocsetif=no))
+ AC_MSG_RESULT($ac_cv_lbl_bpf_h_defines_biocsetif)
+ fi
+ AC_CHECK_HEADERS(net/pfilt.h net/enet.h)
+ AC_CHECK_HEADERS(net/nit.h sys/net/nit.h)
+ AC_CHECK_HEADERS(linux/socket.h net/raw.h sys/dlpi.h)
+
+ if test "$ac_cv_lbl_bpf_h_defines_biocsetif" = yes; then
+ #
+ # BPF.
+ # Check this before DLPI, so that we pick BPF on
+ # Solaris 11 and later.
+ #
+ V_PCAP=bpf
+
+ #
+ # We have BPF, so build valgrindtest with "make test"
+ # on macOS and FreeBSD (add your OS once there's a
+ # valgrind for it).
+ #
+ case "$host_os" in
+
+ freebsd*|darwin*|linux*)
+ VALGRINDTEST_SRC=valgrindtest.c
+ ;;
+ esac
+ elif test "$ac_cv_header_linux_socket_h" = yes; then
+ #
+ # No prizes for guessing this one.
+ #
+ V_PCAP=linux
+
+ #
+ # XXX - this won't work with older kernels that have
+ # SOCK_PACKET sockets but not PF_PACKET sockets.
+ #
+ VALGRINDTEST_SRC=valgrindtest.c
+ elif test "$ac_cv_header_net_pfilt_h" = yes; then
+ #
+ # DEC OSF/1, Digital UNIX, Tru64 UNIX
+ #
+ V_PCAP=pf
+ elif test "$ac_cv_header_net_enet_h" = yes; then
+ #
+ # Stanford Enetfilter.
+ #
+ V_PCAP=enet
+ elif test "$ac_cv_header_net_nit_h" = yes; then
+ #
+ # SunOS 4.x STREAMS NIT.
+ #
+ V_PCAP=snit
+ elif test "$ac_cv_header_sys_net_nit_h" = yes; then
+ #
+ # Pre-SunOS 4.x non-STREAMS NIT.
+ #
+ V_PCAP=nit
+ elif test "$ac_cv_header_net_raw_h" = yes; then
+ #
+ # IRIX snoop.
+ #
+ V_PCAP=snoop
+ elif test "$ac_cv_header_sys_dlpi_h" = yes; then
+ #
+ # DLPI on pre-Solaris 11 SunOS 5, HP-UX, possibly others.
+ #
+ V_PCAP=dlpi
+ else
+ #
+ # Nothing we support.
+ #
+ V_PCAP=null
+ AC_MSG_WARN(cannot determine packet capture interface)
+ AC_MSG_WARN((see the INSTALL doc for more info))
+ fi
+fi
+AC_MSG_CHECKING(packet capture type)
+AC_MSG_RESULT($V_PCAP)
+AC_SUBST(VALGRINDTEST_SRC)
+
+#
+# Do capture-mechanism-dependent tests.
+#
+case "$V_PCAP" in
+dlpi)
+ #
+ # Needed for common functions used by pcap-[dlpi,libdlpi].c
+ #
+ SSRC="dlpisubs.c"
+
+ #
+ # Checks for some header files.
+ #
+ AC_CHECK_HEADERS(sys/bufmod.h sys/dlpi_ext.h)
+
+ #
+ # Checks to see if Solaris has the public libdlpi(3LIB) library.
+ # Note: The existence of /usr/include/libdlpi.h does not mean it is the
+ # public libdlpi(3LIB) version. Before libdlpi was made public, a
+ # private version also existed, which did not have the same APIs.
+ # Due to a gcc bug, the default search path for 32-bit libraries does
+ # not include /lib, we add it explicitly here.
+ # [http://bugs.opensolaris.org/view_bug.do?bug_id=6619485].
+ # Also, due to the bug above applications that link to libpcap with
+ # libdlpi will have to add "-L/lib" option to "configure".
+ #
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="$LIBS -L/lib"
+ AC_CHECK_LIB(dlpi, dlpi_walk,
+ [
+ LIBS="-ldlpi $LIBS"
+ V_PCAP=libdlpi
+ AC_DEFINE(HAVE_LIBDLPI,1,[if libdlpi exists])
+ ],
+ V_PCAP=dlpi)
+ LDFLAGS=$saved_ldflags
+
+ #
+ # Checks whether <sys/dlpi.h> is usable, to catch weird SCO
+ # versions of DLPI.
+ #
+ AC_MSG_CHECKING(whether <sys/dlpi.h> is usable)
+ AC_CACHE_VAL(ac_cv_sys_dlpi_usable,
+ AC_TRY_COMPILE(
+ [
+ #include <sys/types.h>
+ #include <sys/time.h>
+ #include <sys/dlpi.h>
+ ],
+ [int i = DL_PROMISC_PHYS;],
+ ac_cv_sys_dlpi_usable=yes,
+ ac_cv_sys_dlpi_usable=no))
+ AC_MSG_RESULT($ac_cv_sys_dlpi_usable)
+ if test $ac_cv_sys_dlpi_usable = no ; then
+ AC_MSG_ERROR(<sys/dlpi.h> is not usable on this system; it probably has a non-standard DLPI)
+ fi
+
+ #
+ # Check to see if Solaris has the dl_passive_req_t struct defined
+ # in <sys/dlpi.h>.
+ # This check is for DLPI support for passive modes.
+ # See dlpi(7P) for more details.
+ #
+ AC_CHECK_TYPES(dl_passive_req_t,,,
+ [
+ #include <sys/types.h>
+ #include <sys/dlpi.h>
+ ])
+ ;;
+
+linux)
+ #
+ # Do we have the wireless extensions?
+ #
+ AC_CHECK_HEADERS(linux/wireless.h, [], [],
+ [
+#include <sys/socket.h>
+#include <linux/if.h>
+#include <linux/types.h>
+ ])
+
+ #
+ # Do we have libnl?
+ #
+ AC_ARG_WITH(libnl,
+ AC_HELP_STRING([--without-libnl],[disable libnl support @<:@default=yes, on Linux, if present@:>@]),
+ with_libnl=$withval,with_libnl=if_available)
+
+ if test x$with_libnl != xno ; then
+ have_any_nl="no"
+
+ incdir=-I/usr/include/libnl3
+ libnldir=
+ case "$with_libnl" in
+
+ yes|if_available)
+ ;;
+
+ *)
+ if test -d $withval; then
+ libnldir=-L${withval}/lib/.libs
+ incdir=-I${withval}/include
+ fi
+ ;;
+ esac
+
+ #
+ # Try libnl 3.x first.
+ #
+ AC_CHECK_LIB(nl-3, nl_socket_alloc,
+ [
+ #
+ # Yes, we have libnl 3.x.
+ #
+ LIBS="${libnldir} -lnl-genl-3 -lnl-3 $LIBS"
+ AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+ AC_DEFINE(HAVE_LIBNL_3_x,1,[if libnl exists and is version 3.x])
+ AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
+ AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
+ V_INCLS="$V_INCLS ${incdir}"
+ have_any_nl="yes"
+ ],[], ${incdir} ${libnldir} -lnl-genl-3 -lnl-3 )
+
+ if test x$have_any_nl = xno ; then
+ #
+ # Try libnl 2.x
+ #
+ AC_CHECK_LIB(nl, nl_socket_alloc,
+ [
+ #
+ # Yes, we have libnl 2.x.
+ #
+ LIBS="${libnldir} -lnl-genl -lnl $LIBS"
+ AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+ AC_DEFINE(HAVE_LIBNL_2_x,1,[if libnl exists and is version 2.x])
+ AC_DEFINE(HAVE_LIBNL_NLE,1,[libnl has NLE_FAILURE])
+ AC_DEFINE(HAVE_LIBNL_SOCKETS,1,[libnl has new-style socket api])
+ have_any_nl="yes"
+ ])
+ fi
+
+ if test x$have_any_nl = xno ; then
+ #
+ # No, we don't; do we have libnl 1.x?
+ #
+ AC_CHECK_LIB(nl, nl_handle_alloc,
+ [
+ #
+ # Yes.
+ #
+ LIBS="${libnldir} -lnl $LIBS"
+ AC_DEFINE(HAVE_LIBNL,1,[if libnl exists])
+ have_any_nl="yes"
+ ])
+ fi
+
+ if test x$have_any_nl = xno ; then
+ #
+ # No, we don't have libnl at all.
+ #
+ if test x$with_libnl = xyes ; then
+ AC_MSG_ERROR([libnl support requested but libnl not found])
+ fi
+ fi
+ fi
+
+ AC_CHECK_HEADERS(linux/ethtool.h,,,
+ [
+AC_INCLUDES_DEFAULT
+#include <linux/types.h>
+ ])
+
+ #
+ # Check to see if struct tpacket_stats is defined in
+ # <linux/if_packet.h>. If so, then pcap-linux.c can use this
+ # to report proper statistics.
+ #
+ # -Scott Barron
+ #
+ AC_CHECK_TYPES(struct tpacket_stats,,,
+ [
+ #include <linux/if_packet.h>
+ ])
+
+ #
+ # Check to see if the tpacket_auxdata struct has a tp_vlan_tci member.
+ #
+ # NOTE: any failure means we conclude that it doesn't have that
+ # member, so if we don't have tpacket_auxdata, we conclude it
+ # doesn't have that member (which is OK, as either we won't be
+ # using code that would use that member, or we wouldn't compile
+ # in any case).
+ AC_CHECK_MEMBERS([struct tpacket_auxdata.tp_vlan_tci],,,
+ [
+ #include <sys/types.h>
+ #include <linux/if_packet.h>
+ ])
+ ;;
+
+bpf)
+ #
+ # Check whether we have the *BSD-style ioctls.
+ #
+ AC_CHECK_HEADERS(net/if_media.h)
+
+ #
+ # Check whether we have struct BPF_TIMEVAL.
+ #
+ AC_CHECK_TYPES(struct BPF_TIMEVAL,,,
+ [
+ #include <sys/types.h>
+ #include <sys/ioctl.h>
+ #ifdef HAVE_SYS_IOCCOM_H
+ #include <sys/ioccom.h>
+ #endif
+ #include <net/bpf.h>
+ ])
+ ;;
+
+dag)
+ #
+ # --with-pcap=dag is the only way to get here, and it means
+ # "DAG support but nothing else"
+ #
+ V_DEFS="$V_DEFS -DDAG_ONLY"
+ xxx_only=yes
+ ;;
+
+septel)
+ #
+ # --with-pcap=septel is the only way to get here, and it means
+ # "Septel support but nothing else"
+ #
+ V_DEFS="$V_DEFS -DSEPTEL_ONLY"
+ xxx_only=yes
+ ;;
+
+snf)
+ #
+ # --with-pcap=snf is the only way to get here, and it means
+ # "SNF support but nothing else"
+ #
+ V_DEFS="$V_DEFS -DSNF_ONLY"
+ xxx_only=yes
+ ;;
+
+null)
+ ;;
+
+*)
+ AC_MSG_ERROR($V_PCAP is not a valid pcap type)
+ ;;
+esac
+
+dnl
+dnl Now figure out how we get a list of interfaces and addresses,
+dnl if we support capturing. Don't bother if we don't support
+dnl capturing.
+dnl
+if test "$V_PCAP" != null
+then
+ AC_CHECK_FUNC(getifaddrs,[
+ #
+ # We have "getifaddrs()"; make sure we have <ifaddrs.h>
+ # as well, just in case some platform is really weird.
+ #
+ AC_CHECK_HEADER(ifaddrs.h,[
+ #
+ # We have the header, so we use "getifaddrs()" to
+ # get the list of interfaces.
+ #
+ V_FINDALLDEVS=fad-getad.c
+ ],[
+ #
+ # We don't have the header - give up.
+ # XXX - we could also fall back on some other
+ # mechanism, but, for now, this'll catch this
+ # problem so that we can at least try to figure
+ # out something to do on systems with "getifaddrs()"
+ # but without "ifaddrs.h", if there is something
+ # we can do on those systems.
+ #
+ AC_MSG_ERROR([Your system has getifaddrs() but doesn't have a usable <ifaddrs.h>.])
+ ])
+ ],[
+ #
+ # Well, we don't have "getifaddrs()", at least not with the
+ # libraries with which we've decided we need to link
+ # libpcap with, so we have to use some other mechanism.
+ #
+ # Note that this may happen on Solaris, which has
+ # getifaddrs(), but in -lsocket, not in -lxnet, so we
+ # won't find it if we link with -lxnet, which we want
+ # to do for other reasons.
+ #
+ # For now, we use either the SIOCGIFCONF ioctl or the
+ # SIOCGLIFCONF ioctl, preferring the latter if we have
+ # it; the latter is a Solarisism that first appeared
+ # in Solaris 8. (Solaris's getifaddrs() appears to
+ # be built atop SIOCGLIFCONF; using it directly
+ # avoids a not-all-that-useful middleman.)
+ #
+ AC_MSG_CHECKING(whether we have SIOCGLIFCONF)
+ AC_CACHE_VAL(ac_cv_lbl_have_siocglifconf,
+ AC_TRY_COMPILE(
+ [#include <sys/param.h>
+ #include <sys/file.h>
+ #include <sys/ioctl.h>
+ #include <sys/socket.h>
+ #include <sys/sockio.h>],
+ [ioctl(0, SIOCGLIFCONF, (char *)0);],
+ ac_cv_lbl_have_siocglifconf=yes,
+ ac_cv_lbl_have_siocglifconf=no))
+ AC_MSG_RESULT($ac_cv_lbl_have_siocglifconf)
+ if test $ac_cv_lbl_have_siocglifconf = yes ; then
+ V_FINDALLDEVS=fad-glifc.c
+ else
+ V_FINDALLDEVS=fad-gifc.c
+ fi
+ ])
+fi
+])
+
+dnl check for hardware timestamp support
+case "$host_os" in
+linux*)
+ AC_CHECK_HEADERS([linux/net_tstamp.h])
+ ;;
+*)
+ AC_MSG_NOTICE(no hardware timestamp support implemented for $host_os)
+ ;;
+esac
+
+AC_ARG_ENABLE([packet-ring],
+[AC_HELP_STRING([--enable-packet-ring],[enable packet ring support on Linux @<:@default=yes@:>@])],
+,enable_packet_ring=yes)
+
+if test "x$enable_packet_ring" != "xno" ; then
+ AC_DEFINE(PCAP_SUPPORT_PACKET_RING, 1, [use packet ring capture support on Linux if available])
+ AC_SUBST(PCAP_SUPPORT_PACKET_RING)
+fi
+
+#
+# Check for socklen_t.
+#
+AC_CHECK_TYPES(socklen_t,,,
+ [
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ])
+
+AC_ARG_ENABLE(ipv6,
+AC_HELP_STRING([--enable-ipv6],[build IPv6-capable version @<:@default=yes@:>@]),
+ [],
+ [enable_ipv6=yes])
+if test "$enable_ipv6" != "no"; then
+ #
+ # We've already made sure we have getaddrinfo above in
+ # AC_LBL_LIBRARY_NET.
+ #
+ AC_DEFINE(INET6,1,[IPv6])
+fi
+
+# Check for Endace DAG card support.
+AC_ARG_WITH([dag],
+AC_HELP_STRING([--with-dag@<:@=DIR@:>@],[include Endace DAG support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
+[
+ if test "$withval" = no
+ then
+ # User doesn't want DAG support.
+ want_dag=no
+ elif test "$withval" = yes
+ then
+ # User wants DAG support but hasn't specified a directory.
+ want_dag=yes
+ else
+ # User wants DAG support and has specified a directory, so use the provided value.
+ want_dag=yes
+ dag_root=$withval
+ fi
+],[
+ if test "$V_PCAP" = dag; then
+ # User requested DAG-only libpcap, so we'd better have
+ # the DAG API.
+ want_dag=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want DAG support.
+ want_dag=no
+ else
+ #
+ # Use DAG API if present, otherwise don't
+ #
+ want_dag=ifpresent
+ fi
+])
+
+AC_ARG_WITH([dag-includes],
+AC_HELP_STRING([--with-dag-includes=IDIR],[Endace DAG include directory, if not DIR/include]),
+[
+ # User wants DAG support and has specified a header directory, so use the provided value.
+ want_dag=yes
+ dag_include_dir=$withval
+],[])
+
+AC_ARG_WITH([dag-libraries],
+AC_HELP_STRING([--with-dag-libraries=LDIR],[Endace DAG library directory, if not DIR/lib]),
+[
+ # User wants DAG support and has specified a library directory, so use the provided value.
+ want_dag=yes
+ dag_lib_dir=$withval
+],[])
+
+if test "$want_dag" != no; then
+
+ # If necessary, set default paths for DAG API headers and libraries.
+ if test -z "$dag_root"; then
+ dag_root=/usr/local
+ fi
+
+ if test -z "$dag_include_dir"; then
+ dag_include_dir="$dag_root/include"
+ fi
+
+ if test -z "$dag_lib_dir"; then
+ dag_lib_dir="$dag_root/lib"
+ fi
+
+ V_INCLS="$V_INCLS -I$dag_include_dir"
+
+ AC_CHECK_HEADERS([dagapi.h])
+
+ if test "$ac_cv_header_dagapi_h" = yes; then
+
+ if test $V_PCAP != dag ; then
+ SSRC="$SSRC pcap-dag.c"
+ fi
+
+ # Check for various DAG API functions.
+ # Don't need to save and restore LIBS to prevent -ldag being
+ # included if there's a found-action (arg 3).
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="-L$dag_lib_dir"
+ AC_CHECK_LIB([dag], [dag_attach_stream],
+ [],
+ [AC_MSG_ERROR(DAG library lacks streams support)])
+ AC_CHECK_LIB([dag], [dag_attach_stream64], [dag_large_streams="1"], [dag_large_streams="0"])
+ AC_CHECK_LIB([dag],[dag_get_erf_types], [
+ AC_DEFINE(HAVE_DAG_GET_ERF_TYPES, 1, [define if you have dag_get_erf_types()])])
+ AC_CHECK_LIB([dag],[dag_get_stream_erf_types], [
+ AC_DEFINE(HAVE_DAG_GET_STREAM_ERF_TYPES, 1, [define if you have dag_get_stream_erf_types()])])
+
+ LDFLAGS=$saved_ldflags
+
+ #
+ # We assume that if we have libdag we have libdagconf,
+ # as they're installed at the same time from the same
+ # package.
+ #
+ LIBS="$LIBS -ldag -ldagconf"
+ LDFLAGS="$LDFLAGS -L$dag_lib_dir"
+
+ if test "$dag_large_streams" = 1; then
+ AC_DEFINE(HAVE_DAG_LARGE_STREAMS_API, 1, [define if you have large streams capable DAG API])
+ AC_CHECK_LIB([vdag],[vdag_set_device_info], [ac_dag_have_vdag="1"], [ac_dag_have_vdag="0"])
+ if test "$ac_dag_have_vdag" = 1; then
+ AC_DEFINE(HAVE_DAG_VDAG, 1, [define if you have vdag_set_device_info()])
+ if test "$ac_lbl_have_pthreads" != "found"; then
+ AC_MSG_ERROR([DAG requires pthreads, but we didn't find them])
+ fi
+ LIBS="$LIBS $PTHREAD_LIBS"
+ fi
+ fi
+
+ AC_DEFINE(HAVE_DAG_API, 1, [define if you have the DAG API])
+ else
+
+ if test "$V_PCAP" = dag; then
+ # User requested "dag" capture type but we couldn't
+ # find the DAG API support.
+ AC_MSG_ERROR([DAG support requested with --with-pcap=dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support])
+ fi
+
+ if test "$want_dag" = yes; then
+ # User wanted DAG support but we couldn't find it.
+ AC_MSG_ERROR([DAG support requested with --with-dag, but the DAG headers weren't found at $dag_include_dir: make sure the DAG support is installed, specify a different path or paths if necessary, or don't request DAG support])
+ fi
+ fi
+fi
+
+AC_ARG_WITH(septel,
+AC_HELP_STRING([--with-septel@<:@=DIR@:>@],[include Septel support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
+[
+ if test "$withval" = no
+ then
+ want_septel=no
+ elif test "$withval" = yes
+ then
+ want_septel=yes
+ septel_root=
+ else
+ want_septel=yes
+ septel_root=$withval
+ fi
+],[
+ if test "$V_PCAP" = septel; then
+ # User requested Septel-only libpcap, so we'd better have
+ # the Septel API.
+ want_septel=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Septel support.
+ want_septel=no
+ else
+ #
+ # Use Septel API if present, otherwise don't
+ #
+ want_septel=ifpresent
+ fi
+])
+
+ac_cv_lbl_septel_api=no
+if test "$with_septel" != no; then
+
+ AC_MSG_CHECKING([whether we have Septel API headers])
+
+ # If necessary, set default paths for Septel API headers and libraries.
+ if test -z "$septel_root"; then
+ septel_root=$srcdir/../septel
+ fi
+
+ septel_tools_dir="$septel_root"
+ septel_include_dir="$septel_root/INC"
+
+ if test -r "$septel_include_dir/msg.h"; then
+ ac_cv_lbl_septel_api=yes
+ fi
+
+ if test "$ac_cv_lbl_septel_api" = yes; then
+ AC_MSG_RESULT([yes ($septel_include_dir)])
+
+ V_INCLS="$V_INCLS -I$septel_include_dir"
+ ADDLOBJS="$ADDLOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+ ADDLARCHIVEOBJS="$ADDLARCHIVEOBJS $septel_tools_dir/asciibin.o $septel_tools_dir/bit2byte.o $septel_tools_dir/confirm.o $septel_tools_dir/fmtmsg.o $septel_tools_dir/gct_unix.o $septel_tools_dir/hqueue.o $septel_tools_dir/ident.o $septel_tools_dir/mem.o $septel_tools_dir/pack.o $septel_tools_dir/parse.o $septel_tools_dir/pool.o $septel_tools_dir/sdlsig.o $septel_tools_dir/strtonum.o $septel_tools_dir/timer.o $septel_tools_dir/trace.o"
+
+ if test "$V_PCAP" != septel ; then
+ SSRC="$SSRC pcap-septel.c"
+ fi
+
+ AC_DEFINE(HAVE_SEPTEL_API, 1, [define if you have the Septel API])
+ else
+ AC_MSG_RESULT(no)
+
+ if test "$V_PCAP" = septel; then
+ # User requested "septel" capture type but
+ # we couldn't find the Septel API support.
+ AC_MSG_ERROR([Septel support requested with --with-pcap=septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support])
+ fi
+
+ if test "$want_septel" = yes; then
+ # User wanted Septel support but we couldn't find it.
+ AC_MSG_ERROR([Septel support requested with --with-septel, but the Septel headers weren't found at $septel_include_dir: make sure the Septel support is installed, specify a different path or paths if necessary, or don't request Septel support])
+ fi
+ fi
+fi
+
+# Check for Myricom SNF support.
+AC_ARG_WITH([snf],
+AC_HELP_STRING([--with-snf@<:@=DIR@:>@],[include Myricom SNF support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
+[
+ if test "$withval" = no
+ then
+ # User explicitly doesn't want SNF
+ want_snf=no
+ elif test "$withval" = yes
+ then
+ # User wants SNF support but hasn't specified a directory.
+ want_snf=yes
+ else
+ # User wants SNF support with a specified directory.
+ want_snf=yes
+ snf_root=$withval
+ fi
+],[
+ if test "$V_PCAP" = snf; then
+ # User requested Sniffer-only libpcap, so we'd better have
+ # the Sniffer API.
+ want_snf=yes
+ elif test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want SNF support.
+ want_snf=no
+ else
+ #
+ # Use Sniffer API if present, otherwise don't
+ #
+ want_snf=ifpresent
+ fi
+])
+
+AC_ARG_WITH([snf-includes],
+AC_HELP_STRING([--with-snf-includes=IDIR],[Myricom SNF include directory, if not DIR/include]),
+[
+ # User wants SNF with specific header directory
+ want_snf=yes
+ snf_include_dir=$withval
+],[])
+
+AC_ARG_WITH([snf-libraries],
+AC_HELP_STRING([--with-snf-libraries=LDIR],[Myricom SNF library directory, if not DIR/lib]),
+[
+ # User wants SNF with specific lib directory
+ want_snf=yes
+ snf_lib_dir=$withval
+],[])
+
+ac_cv_lbl_snf_api=no
+if test "$with_snf" != no; then
+
+ AC_MSG_CHECKING(whether we have Myricom Sniffer API)
+
+ # If necessary, set default paths for Sniffer headers and libraries.
+ if test -z "$snf_root"; then
+ snf_root=/opt/snf
+ fi
+
+ if test -z "$snf_include_dir"; then
+ snf_include_dir="$snf_root/include"
+ fi
+
+ if test -z "$snf_lib_dir"; then
+ snf_lib_dir="$snf_root/lib"
+ fi
+
+ if test -f "$snf_include_dir/snf.h"; then
+ # We found a header; make sure we can link with the library
+ saved_ldflags=$LDFLAGS
+ LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+ AC_CHECK_LIB([snf], [snf_init], [ac_cv_lbl_snf_api="yes"])
+ LDFLAGS="$saved_ldflags"
+ if test "$ac_cv_lbl_snf_api" = no; then
+ AC_MSG_ERROR(SNF API cannot correctly be linked; check config.log)
+ fi
+ fi
+
+ if test "$ac_cv_lbl_snf_api" = yes; then
+ AC_MSG_RESULT([yes ($snf_root)])
+
+ V_INCLS="$V_INCLS -I$snf_include_dir"
+ LIBS="$LIBS -lsnf"
+ LDFLAGS="$LDFLAGS -L$snf_lib_dir"
+
+ if test "$V_PCAP" != snf ; then
+ SSRC="$SSRC pcap-snf.c"
+ fi
+
+ AC_DEFINE(HAVE_SNF_API, 1, [define if you have the Myricom SNF API])
+ else
+ AC_MSG_RESULT(no)
+
+ if test "$want_snf" = yes; then
+ # User requested "snf" capture type but
+ # we couldn't find the Sniffer API support.
+ AC_MSG_ERROR([Myricom Sniffer support requested with --with-pcap=snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support])
+ fi
+
+ if test "$want_snf" = yes; then
+ AC_MSG_ERROR([Myricom Sniffer support requested with --with-snf, but the Sniffer headers weren't found at $snf_include_dir: make sure the Sniffer support is installed, specify a different path or paths if necessary, or don't request Sniffer support])
+ fi
+ fi
+fi
+
+# Check for Riverbed TurboCap support.
+AC_ARG_WITH([turbocap],
+AC_HELP_STRING([--with-turbocap@<:@=DIR@:>@],[include Riverbed TurboCap support (located in directory DIR, if supplied). @<:@default=yes, if present@:>@]),
+[
+ if test "$withval" = no
+ then
+ # User explicitly doesn't want TurboCap
+ want_turbocap=no
+ elif test "$withval" = yes
+ then
+ # User wants TurboCap support but hasn't specified a directory.
+ want_turbocap=yes
+ else
+ # User wants TurboCap support with a specified directory.
+ want_turbocap=yes
+ turbocap_root=$withval
+ fi
+],[
+ if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want TurboCap support.
+ want_turbocap=no
+ else
+ #
+ # Use TurboCap API if present, otherwise don't
+ #
+ want_turbocap=ifpresent
+ fi
+])
+
+ac_cv_lbl_turbocap_api=no
+if test "$want_turbocap" != no; then
+
+ AC_MSG_CHECKING(whether TurboCap is supported)
+
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ if test ! -z "$turbocap_root"; then
+ TURBOCAP_CFLAGS="-I$turbocap_root/include"
+ TURBOCAP_LIBS="-L$turbocap_root/lib"
+ CFLAGS="$CFLAGS $TURBOCAP_CFLAGS"
+ fi
+
+ AC_TRY_COMPILE(
+ [
+ #include <TcApi.h>
+ ],
+ [
+ TC_INSTANCE a; TC_PORT b; TC_BOARD c;
+ TC_INSTANCE i;
+ (void)TcInstanceCreateByName("foo", &i);
+ ],
+ ac_cv_lbl_turbocap_api=yes)
+
+ CFLAGS="$save_CFLAGS"
+ if test $ac_cv_lbl_turbocap_api = yes; then
+ AC_MSG_RESULT(yes)
+
+ SSRC="$SSRC pcap-tc.c"
+ V_INCLS="$V_INCLS $TURBOCAP_CFLAGS"
+ LIBS="$LIBS $TURBOCAP_LIBS -lTcApi -lpthread -lstdc++"
+
+ AC_DEFINE(HAVE_TC_API, 1, [define if you have the TurboCap API])
+ else
+ AC_MSG_RESULT(no)
+
+ if test "$want_turbocap" = yes; then
+ # User wanted Turbo support but we couldn't find it.
+ AC_MSG_ERROR([TurboCap support requested with --with-turbocap, but the TurboCap headers weren't found: make sure the TurboCap support is installed or don't request TurboCap support])
+ fi
+ fi
+fi
+
+dnl
+dnl Allow the user to enable remote capture.
+dnl It's off by default, as that increases the attack surface of
+dnl libpcap, exposing it to malicious servers.
+dnl
+AC_MSG_CHECKING([whether to enable remote packet capture])
+AC_ARG_ENABLE(remote,
+[ --enable-remote enable remote packet capture @<:@default=no@:>@
+ --disable-remote disable remote packet capture],,
+ enableval=no)
+case "$enableval" in
+yes) AC_MSG_RESULT(yes)
+ AC_WARN([Remote packet capture may expose libpcap-based applications])
+ AC_WARN([to attacks by malicious remote capture servers!])
+ #
+ # rpcapd requires pthreads on UN*X.
+ #
+ if test "$ac_lbl_have_pthreads" != "found"; then
+ AC_MSG_ERROR([rpcapd requires pthreads, but we didn't find them])
+ fi
+ #
+ # It also requires crypt().
+ # Do we have it in the system libraries?
+ #
+ AC_CHECK_FUNC(crypt,,
+ [
+ #
+ # No. Do we have it in -lcrypt?
+ #
+ AC_CHECK_LIB(crypt, crypt,
+ [
+ #
+ # Yes; add -lcrypt to the libraries for rpcapd.
+ #
+ RPCAPD_LIBS="$RPCAPD_LIBS -lcrypt"
+ ],
+ [
+ AC_MSG_ERROR([rpcapd requires crypt(), but we didn't find it])
+ ])
+ ])
+
+ #
+ # OK, we have crypt(). Do we have getspnam()?
+ #
+ AC_CHECK_FUNCS(getspnam)
+
+ #
+ # Check for various members of struct msghdr.
+ #
+ AC_CHECK_MEMBERS([struct msghdr.msg_control],,,
+ [
+ #include "ftmacros.h"
+ #include <sys/socket.h>
+ ])
+ AC_CHECK_MEMBERS([struct msghdr.msg_flags],,,
+ [
+ #include "ftmacros.h"
+ #include <sys/socket.h>
+ ])
+
+ AC_DEFINE(ENABLE_REMOTE,,
+ [Define to 1 if remote packet capture is to be supported])
+ SSRC="$SSRC pcap-new.c pcap-rpcap.c rpcap-protocol.c sockutils.c"
+ BUILD_RPCAPD=build-rpcapd
+ INSTALL_RPCAPD=install-rpcapd
+ ;;
+*) AC_MSG_RESULT(no)
+ ;;
+esac
+
+AC_MSG_CHECKING(whether to build optimizer debugging code)
+AC_ARG_ENABLE(optimizer-dbg,
+AC_HELP_STRING([--enable-optimizer-dbg],[build optimizer debugging code]))
+if test "$enable_optimizer_dbg" = "yes"; then
+ AC_DEFINE(BDEBUG,1,[Enable optimizer debugging])
+fi
+AC_MSG_RESULT(${enable_optimizer_dbg-no})
+
+AC_MSG_CHECKING(whether to build parser debugging code)
+AC_ARG_ENABLE(yydebug,
+AC_HELP_STRING([--enable-yydebug],[build parser debugging code]))
+if test "$enable_yydebug" = "yes"; then
+ AC_DEFINE(YYDEBUG,1,[Enable parser debugging])
+fi
+AC_MSG_RESULT(${enable_yydebug-no})
+
+#
+# Look for {f}lex.
+#
+AC_PROG_LEX
+if test "$LEX" = ":"; then
+ AC_MSG_ERROR([Neither flex nor lex was found.])
+fi
+
+#
+# Make sure {f}lex supports the -P, --header-file, and --nounput flags
+# and supports processing our scanner.l.
+#
+AC_CACHE_CHECK([for capable lex], tcpdump_cv_capable_lex,
+ if $LEX -P pcap_ --header-file=/dev/null --nounput -t $srcdir/scanner.l > /dev/null 2>&1; then
+ tcpdump_cv_capable_lex=yes
+ else
+ tcpdump_cv_capable_lex=insufficient
+ fi)
+if test $tcpdump_cv_capable_lex = insufficient ; then
+ AC_MSG_ERROR([$LEX is insufficient to compile libpcap.
+ libpcap requires Flex 2.5.31 or later, or a compatible version of lex.])
+fi
+
+#
+# Look for yacc/bison/byacc.
+#
+AC_PROG_YACC
+
+#
+# Make sure it supports the -p flag and supports processing our
+# grammar.y.
+#
+AC_CACHE_CHECK([for capable yacc/bison], tcpdump_cv_capable_yacc,
+ if $YACC -p pcap_ -o /dev/null $srcdir/grammar.y >/dev/null 2>&1; then
+ tcpdump_cv_capable_yacc=yes
+ else
+ tcpdump_cv_capable_yacc=insufficient
+ fi)
+if test $tcpdump_cv_capable_yacc = insufficient ; then
+ AC_MSG_ERROR([$YACC is insufficient to compile libpcap.
+ libpcap requires Bison, a newer version of Berkeley YACC with support
+ for reentrant parsers, or another YACC compatible with them.])
+fi
+
+#
+# Do various checks for various OSes and versions of those OSes.
+#
+# Assume, by default, no support for shared libraries and V7/BSD
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8). Individual cases can override this.
+#
+DYEXT="none"
+MAN_DEVICES=4
+MAN_FILE_FORMATS=5
+MAN_MISC_INFO=7
+MAN_ADMIN_COMMANDS=8
+case "$host_os" in
+
+aix*)
+ dnl Workaround to enable certain features
+ AC_DEFINE(_SUN,1,[define on AIX to get certain functions])
+
+ #
+ # AIX makes it fun to build shared and static libraries,
+ # because they're *both* ".a" archive libraries. We
+ # build the static library for the benefit of the traditional
+ # scheme of building libpcap and tcpdump in subdirectories of
+ # the same directory, with tcpdump statically linked with the
+ # libpcap in question, but we also build a shared library as
+ # "libpcap.shareda" and install *it*, rather than the static
+ # library, as "libpcap.a".
+ #
+ DYEXT="shareda"
+
+ case "$V_PCAP" in
+
+ dlpi)
+ #
+ # If we're using DLPI, applications will need to
+ # use /lib/pse.exp if present, as we use the
+ # STREAMS routines.
+ #
+ pseexe="/lib/pse.exp"
+ AC_MSG_CHECKING(for $pseexe)
+ if test -f $pseexe ; then
+ AC_MSG_RESULT(yes)
+ LIBS="-I:$pseexe"
+ fi
+ ;;
+
+ bpf)
+ #
+ # If we're using BPF, we need "-lodm" and "-lcfg", as
+ # we use them to load the BPF module.
+ #
+ LIBS="-lodm -lcfg"
+ ;;
+ esac
+ ;;
+
+darwin*)
+ DYEXT="dylib"
+ V_CCOPT="$V_CCOPT -fno-common"
+ AC_ARG_ENABLE(universal,
+ AC_HELP_STRING([--disable-universal],[don't build universal on macOS]))
+ if test "$enable_universal" != "no"; then
+ case "$host_os" in
+
+ darwin[[0-7]].*)
+ #
+ # Pre-Tiger. Build only for 32-bit PowerPC; no
+ # need for any special compiler or linker flags.
+ #
+ ;;
+
+ darwin8.[[0123]]|darwin8.[[0123]].*)
+ #
+ # Tiger, prior to Intel support. Build
+ # libraries and executables for 32-bit PowerPC
+ # and 64-bit PowerPC, with 32-bit PowerPC first.
+ # (I'm guessing that's what Apple does.)
+ #
+ # (The double brackets are needed because
+ # autotools/m4 use brackets as a quoting
+ # character; the double brackets turn into
+ # single brackets in the generated configure
+ # file.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64"
+ V_PROG_CCOPT_FAT="-arch ppc -arch ppc64"
+ V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64"
+ ;;
+
+ darwin8.[[456]]|darwin.[[456]].*)
+ #
+ # Tiger, subsequent to Intel support but prior
+ # to x86-64 support. Build libraries and
+ # executables for 32-bit PowerPC, 64-bit
+ # PowerPC, and 32-bit x86, with 32-bit PowerPC
+ # first. (I'm guessing that's what Apple does.)
+ #
+ # (The double brackets are needed because
+ # autotools/m4 use brackets as a quoting
+ # character; the double brackets turn into
+ # single brackets in the generated configure
+ # file.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+ V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386"
+ V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386"
+ ;;
+
+ darwin8.*)
+ #
+ # All other Tiger, so subsequent to x86-64
+ # support. Build libraries and executables for
+ # 32-bit PowerPC, 64-bit PowerPC, 32-bit x86,
+ # and x86-64, with 32-bit PowerPC first. (I'm
+ # guessing that's what Apple does.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_PROG_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_PROG_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ ;;
+
+ darwin9.*)
+ #
+ # Leopard. Build libraries for 32-bit PowerPC,
+ # 64-bit PowerPC, 32-bit x86, and x86-64, with
+ # 32-bit PowerPC first, and build executables
+ # for 32-bit x86 and 32-bit PowerPC, with 32-bit
+ # x86 first. (That's what Apple does.)
+ #
+ V_LIB_CCOPT_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_LIB_LDFLAGS_FAT="-arch ppc -arch ppc64 -arch i386 -arch x86_64"
+ V_PROG_CCOPT_FAT="-arch i386 -arch ppc"
+ V_PROG_LDFLAGS_FAT="-arch i386 -arch ppc"
+ ;;
+
+ darwin10.*)
+ #
+ # Snow Leopard. Build libraries for x86-64,
+ # 32-bit x86, and 32-bit PowerPC, with x86-64
+ # first, and build executables for x86-64 and
+ # 32-bit x86, with x86-64 first. (That's what
+ # Apple does, even though Snow Leopard doesn't
+ # run on PPC, so PPC libpcap runs under Rosetta,
+ # and Rosetta doesn't support BPF ioctls, so PPC
+ # programs can't do live captures.)
+ #
+ V_LIB_CCOPT_FAT="-arch x86_64 -arch i386 -arch ppc"
+ V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386 -arch ppc"
+ V_PROG_CCOPT_FAT="-arch x86_64 -arch i386"
+ V_PROG_LDFLAGS_FAT="-arch x86_64 -arch i386"
+ ;;
+
+ darwin*)
+ #
+ # Post-Snow Leopard. Build libraries for x86-64
+ # and 32-bit x86, with x86-64 first, and build
+ # executables only for x86-64. (That's what
+ # Apple does.) This requires no special flags
+ # for programs.
+ # XXX - update if and when Apple drops support
+ # for 32-bit x86 code and if and when Apple adds
+ # ARM-based Macs. (You're on your own for iOS
+ # etc.)
+ #
+ # XXX - check whether we *can* build for
+ # i386 and, if not, suggest that the user
+ # install the /usr/include headers if they
+ # want to build fat.
+ #
+ AC_MSG_CHECKING(whether building for 32-bit x86 is supported)
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -arch i386"
+ AC_TRY_COMPILE(
+ [],
+ [return 0;],
+ [
+ AC_MSG_RESULT(yes)
+ V_LIB_CCOPT_FAT="-arch x86_64 -arch i386"
+ V_LIB_LDFLAGS_FAT="-arch x86_64 -arch i386"
+ ],
+ [
+ AC_MSG_RESULT(no)
+ V_LIB_CCOPT_FAT="-arch x86_64"
+ V_LIB_LDFLAGS_FAT="-arch x86_64"
+ case "$host_os" in
+
+ darwin18.*)
+ #
+ # Mojave; you need to install the
+ # /usr/include headers to get
+ # 32-bit x86 builds to work.
+ #
+ AC_MSG_WARN([Compiling for 32-bit x86 gives an error; try installing the command-line tools and, after that, installing the /usr/include headers from the /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg package])
+ ;;
+
+ *)
+ #
+ # Pre-Mojave; the command-line
+ # tools should be sufficient to
+ # enable 32-bit x86 builds.
+ #
+ AC_MSG_WARN([Compiling for 32-bit x86 gives an error; try installing the command-line tools])
+ ;;
+ esac
+ ])
+ CFLAGS="$save_CFLAGS"
+ ;;
+ esac
+ fi
+ ;;
+
+hpux9*)
+ AC_DEFINE(HAVE_HPUX9,1,[on HP-UX 9.x])
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+hpux10.0*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+hpux10.1*)
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+hpux*)
+ dnl HPUX 10.20 and above is similar to HPUX 9, but
+ dnl not the same....
+ dnl
+ dnl XXX - DYEXT should be set to "sl" if this is building
+ dnl for 32-bit PA-RISC, but should be left as "so" for
+ dnl 64-bit PA-RISC or, I suspect, IA-64.
+ AC_DEFINE(HAVE_HPUX10_20_OR_LATER,1,[on HP-UX 10.20 or later])
+ if test "`uname -m`" = "ia64"; then
+ DYEXT="so"
+ else
+ DYEXT="sl"
+ fi
+
+ #
+ # "-b" builds a shared library; "+h" sets the soname.
+ #
+ SHLIB_OPT="-b"
+ SONAME_OPT="+h"
+
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+irix*)
+ #
+ # Use IRIX conventions for man pages; they're the same as the
+ # System V conventions, except that they use section 8 for
+ # administrative commands and daemons.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ ;;
+
+linux*|freebsd*|netbsd*|openbsd*|dragonfly*|kfreebsd*|gnu*|midipix*)
+ DYEXT="so"
+
+ #
+ # Compiler assumed to be GCC; run-time linker may require a -R
+ # flag.
+ #
+ if test "$libdir" != "/usr/lib"; then
+ V_RFLAGS=-Wl,-R$libdir
+ fi
+ ;;
+
+osf*)
+ DYEXT="so"
+
+ #
+ # DEC OSF/1, a/k/a Digial UNIX, a/k/a Tru64 UNIX.
+ # Use Tru64 UNIX conventions for man pages; they're the same as
+ # the System V conventions except that they use section 8 for
+ # administrative commands and daemons.
+ #
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ MAN_DEVICES=7
+ ;;
+
+sinix*)
+ AC_MSG_CHECKING(if SINIX compiler defines sinix)
+ AC_CACHE_VAL(ac_cv_cc_sinix_defined,
+ AC_TRY_COMPILE(
+ [],
+ [int i = sinix;],
+ ac_cv_cc_sinix_defined=yes,
+ ac_cv_cc_sinix_defined=no))
+ AC_MSG_RESULT($ac_cv_cc_sinix_defined)
+ if test $ac_cv_cc_sinix_defined = no ; then
+ AC_DEFINE(sinix,1,[on sinix])
+ fi
+ ;;
+
+solaris*)
+ AC_DEFINE(HAVE_SOLARIS,1,[On solaris])
+
+ DYEXT="so"
+
+ #
+ # Make sure errno is thread-safe, in case we're called in
+ # a multithreaded program. We don't guarantee that two
+ # threads can use the *same* pcap_t safely, but the
+ # current version does guarantee that you can use different
+ # pcap_t's in different threads, and even that pcap_compile()
+ # is thread-safe (it wasn't thread-safe in some older versions).
+ #
+ V_CCOPT="$V_CCOPT -D_TS_ERRNO"
+
+ case "`uname -r`" in
+
+ 5.12)
+ ;;
+
+ *)
+ #
+ # Use System V conventions for man pages.
+ #
+ MAN_ADMIN_COMMANDS=1m
+ MAN_FILE_FORMATS=4
+ MAN_MISC_INFO=5
+ MAN_DEVICES=7D
+ esac
+ ;;
+esac
+
+AC_ARG_ENABLE(shared,
+AC_HELP_STRING([--enable-shared],[build shared libraries @<:@default=yes, if support available@:>@]))
+test "x$enable_shared" = "xno" && DYEXT="none"
+
+AC_PROG_RANLIB
+AC_CHECK_TOOL([AR], [ar])
+
+AC_PROG_LN_S
+AC_SUBST(LN_S)
+
+AC_LBL_DEVEL(V_CCOPT)
+
+#
+# Check to see if the sockaddr struct has the 4.4 BSD sa_len member.
+#
+AC_CHECK_MEMBERS([struct sockaddr.sa_len],,,
+ [
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ])
+
+#
+# Check to see if there's a sockaddr_storage structure.
+#
+AC_CHECK_TYPES(struct sockaddr_storage,,,
+ [
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ ])
+
+#
+# Check to see if the dl_hp_ppa_info_t struct has the HP-UX 11.00
+# dl_module_id_1 member.
+#
+# NOTE: any failure means we conclude that it doesn't have that member,
+# so if we don't have DLPI, don't have a <sys/dlpi_ext.h> header, or
+# have one that doesn't declare a dl_hp_ppa_info_t type, we conclude
+# it doesn't have that member (which is OK, as either we won't be
+# using code that would use that member, or we wouldn't compile in
+# any case).
+#
+AC_CHECK_MEMBERS([dl_hp_ppa_info_t.dl_module_id_1],,,
+ [
+ #include <sys/types.h>
+ #include <sys/dlpi.h>
+ #include <sys/dlpi_ext.h>
+ ])
+
+AC_LBL_UNALIGNED_ACCESS
+
+AC_SUBST(V_CCOPT)
+AC_SUBST(V_LIB_CCOPT_FAT)
+AC_SUBST(V_LIB_LDFLAGS_FAT)
+AC_SUBST(V_PROG_CCOPT_FAT)
+AC_SUBST(V_PROG_LDFLAGS_FAT)
+AC_SUBST(V_DEFS)
+AC_SUBST(V_FINDALLDEVS)
+AC_SUBST(V_INCLS)
+AC_SUBST(V_LEX)
+AC_SUBST(V_PCAP)
+AC_SUBST(V_SHLIB_CCOPT)
+AC_SUBST(V_SHLIB_CMD)
+AC_SUBST(V_SHLIB_OPT)
+AC_SUBST(V_SONAME_OPT)
+AC_SUBST(V_RPATH_OPT)
+AC_SUBST(V_YACC)
+AC_SUBST(ADDLOBJS)
+AC_SUBST(ADDLARCHIVEOBJS)
+AC_SUBST(SSRC)
+AC_SUBST(DYEXT)
+AC_SUBST(MAN_DEVICES)
+AC_SUBST(MAN_FILE_FORMATS)
+AC_SUBST(MAN_MISC_INFO)
+AC_SUBST(MAN_ADMIN_COMMANDS)
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(BUILD_RPCAPD)
+AC_SUBST(INSTALL_RPCAPD)
+AC_SUBST(RPCAPD_LIBS)
+AC_SUBST(EXTRA_NETWORK_LIBS)
+
+AC_ARG_ENABLE([usb],
+[AC_HELP_STRING([--enable-usb],[enable USB capture support @<:@default=yes, if support available@:>@])],
+ [],
+ [enable_usb=yes])
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want USB support.
+ enable_usb=no
+fi
+
+if test "x$enable_usb" != "xno" ; then
+ dnl check for USB sniffing support
+ AC_MSG_CHECKING(for USB sniffing support)
+ case "$host_os" in
+ linux*)
+ AC_DEFINE(PCAP_SUPPORT_USB, 1, [target host supports USB sniffing])
+ USB_SRC=pcap-usb-linux.c
+ AC_MSG_RESULT(yes)
+ ac_usb_dev_name=`udevinfo -q name -p /sys/class/usb_device/usbmon 2>/dev/null`
+ if test $? -ne 0 ; then
+ ac_usb_dev_name="usbmon"
+ fi
+ AC_DEFINE_UNQUOTED(LINUX_USB_MON_DEV, "/dev/$ac_usb_dev_name", [path for device for USB sniffing])
+ AC_MSG_NOTICE(Device for USB sniffing is /dev/$ac_usb_dev_name)
+ #
+ # Do we have a version of <linux/compiler.h> available?
+ # If so, we might need it for <linux/usbdevice_fs.h>.
+ #
+ AC_CHECK_HEADERS(linux/compiler.h)
+ if test "$ac_cv_header_linux_compiler_h" = yes; then
+ #
+ # Yes - include it when testing for <linux/usbdevice_fs.h>.
+ #
+ AC_CHECK_HEADERS(linux/usbdevice_fs.h,,,[#include <linux/compiler.h>])
+ else
+ AC_CHECK_HEADERS(linux/usbdevice_fs.h)
+ fi
+ if test "$ac_cv_header_linux_usbdevice_fs_h" = yes; then
+ #
+ # OK, does it define bRequestType? Older versions of the kernel
+ # define fields with names like "requesttype, "request", and
+ # "value", rather than "bRequestType", "bRequest", and
+ # "wValue".
+ #
+ AC_CHECK_MEMBERS([struct usbdevfs_ctrltransfer.bRequestType],,,
+ [
+ AC_INCLUDES_DEFAULT
+ #ifdef HAVE_LINUX_COMPILER_H
+ #include <linux/compiler.h>
+ #endif
+ #include <linux/usbdevice_fs.h>
+ ])
+ fi
+ ;;
+ freebsd*)
+ #
+ # This just uses BPF in FreeBSD 8.4 and later; we don't need
+ # to check for anything special for capturing.
+ #
+ AC_MSG_RESULT([yes, in FreeBSD 8.4 and later])
+ ;;
+
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+esac
+fi
+AC_SUBST(PCAP_SUPPORT_USB)
+AC_SUBST(USB_SRC)
+
+dnl check for netfilter sniffing support
+if test "xxx_only" != yes; then
+ AC_MSG_CHECKING(whether the platform could support netfilter sniffing)
+ case "$host_os" in
+ linux*)
+ AC_MSG_RESULT(yes)
+ #
+ # Life's too short to deal with trying to get this to compile
+ # if you don't get the right types defined with
+ # __KERNEL_STRICT_NAMES getting defined by some other include.
+ #
+ # Check whether the includes Just Work. If not, don't turn on
+ # netfilter support.
+ #
+ AC_MSG_CHECKING(whether we can compile the netfilter support)
+ AC_CACHE_VAL(ac_cv_netfilter_can_compile,
+ AC_TRY_COMPILE([
+AC_INCLUDES_DEFAULT
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netfilter/nfnetlink_queue.h>],
+ [],
+ ac_cv_netfilter_can_compile=yes,
+ ac_cv_netfilter_can_compile=no))
+ AC_MSG_RESULT($ac_cv_netfilter_can_compile)
+ if test $ac_cv_netfilter_can_compile = yes ; then
+ AC_DEFINE(PCAP_SUPPORT_NETFILTER, 1,
+ [target host supports netfilter sniffing])
+ NETFILTER_SRC=pcap-netfilter-linux.c
+ fi
+ ;;
+ *)
+ AC_MSG_RESULT(no)
+ ;;
+ esac
+fi
+AC_SUBST(PCAP_SUPPORT_NETFILTER)
+AC_SUBST(NETFILTER_SRC)
+
+AC_ARG_ENABLE([netmap],
+[AC_HELP_STRING([--enable-netmap],[enable netmap support @<:@default=yes, if support available@:>@])],
+ [],
+ [enable_netmap=yes])
+
+if test "x$enable_netmap" != "xno" ; then
+ #
+ # Check whether net/netmap_user.h is usable if NETMAP_WITH_LIBS is
+ # defined; it's not usable on DragonFly BSD 4.6 if NETMAP_WITH_LIBS
+ # is defined, for example, as it includes a non-existent malloc.h
+ # header.
+ #
+ AC_MSG_CHECKING(whether we can compile the netmap support)
+ AC_CACHE_VAL(ac_cv_net_netmap_user_can_compile,
+ AC_TRY_COMPILE([
+AC_INCLUDES_DEFAULT
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>],
+ [],
+ ac_cv_net_netmap_user_can_compile=yes,
+ ac_cv_net_netmap_user_can_compile=no))
+ AC_MSG_RESULT($ac_cv_net_netmap_user_can_compile)
+ if test $ac_cv_net_netmap_user_can_compile = yes ; then
+ AC_DEFINE(PCAP_SUPPORT_NETMAP, 1,
+ [target host supports netmap])
+ NETMAP_SRC=pcap-netmap.c
+ fi
+ AC_SUBST(PCAP_SUPPORT_NETMAP)
+ AC_SUBST(NETMAP_SRC)
+fi
+
+
+AC_ARG_ENABLE([bluetooth],
+[AC_HELP_STRING([--enable-bluetooth],[enable Bluetooth support @<:@default=yes, if support available@:>@])],
+ [],
+ [enable_bluetooth=ifsupportavailable])
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want Bluetooth support.
+ enable_bluetooth=no
+fi
+
+if test "x$enable_bluetooth" != "xno" ; then
+ dnl check for Bluetooth sniffing support
+ case "$host_os" in
+ linux*)
+ AC_CHECK_HEADER(bluetooth/bluetooth.h,
+ [
+ #
+ # We have bluetooth.h, so we support Bluetooth
+ # sniffing.
+ #
+ AC_DEFINE(PCAP_SUPPORT_BT, 1, [target host supports Bluetooth sniffing])
+ BT_SRC=pcap-bt-linux.c
+ AC_MSG_NOTICE(Bluetooth sniffing is supported)
+ ac_lbl_bluetooth_available=yes
+
+ #
+ # OK, does struct sockaddr_hci have an hci_channel
+ # member?
+ #
+ AC_CHECK_MEMBERS([struct sockaddr_hci.hci_channel],
+ [
+ #
+ # Yes; is HCI_CHANNEL_MONITOR defined?
+ #
+ AC_MSG_CHECKING(if HCI_CHANNEL_MONITOR is defined)
+ AC_CACHE_VAL(ac_cv_lbl_hci_channel_monitor_is_defined,
+ AC_TRY_COMPILE(
+ [
+ #include <bluetooth/bluetooth.h>
+ #include <bluetooth/hci.h>
+ ],
+ [
+ u_int i = HCI_CHANNEL_MONITOR;
+ ],
+ [
+ AC_MSG_RESULT(yes)
+ AC_DEFINE(PCAP_SUPPORT_BT_MONITOR,,
+ [target host supports Bluetooth Monitor])
+ BT_MONITOR_SRC=pcap-bt-monitor-linux.c
+ ],
+ [
+ AC_MSG_RESULT(no)
+ ]))
+ ],,
+ [
+ #include <bluetooth/bluetooth.h>
+ #include <bluetooth/hci.h>
+ ])
+ ],
+ [
+ #
+ # We don't have bluetooth.h, so we don't support
+ # Bluetooth sniffing.
+ #
+ if test "x$enable_bluetooth" = "xyes" ; then
+ AC_MSG_ERROR(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
+ else
+ AC_MSG_NOTICE(Bluetooth sniffing is not supported; install bluez-lib devel to enable it)
+ fi
+ ])
+ ;;
+ *)
+ if test "x$enable_bluetooth" = "xyes" ; then
+ AC_MSG_ERROR(no Bluetooth sniffing support implemented for $host_os)
+ else
+ AC_MSG_NOTICE(no Bluetooth sniffing support implemented for $host_os)
+ fi
+ ;;
+ esac
+ AC_SUBST(PCAP_SUPPORT_BT)
+ AC_SUBST(BT_SRC)
+ AC_SUBST(BT_MONITOR_SRC)
+fi
+
+AC_ARG_ENABLE([dbus],
+[AC_HELP_STRING([--enable-dbus],[enable D-Bus capture support @<:@default=yes, if support available@:>@])],
+ [],
+ [enable_dbus=ifavailable])
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want D-Bus support.
+ enable_dbus=no
+fi
+
+if test "x$enable_dbus" != "xno"; then
+ if test "x$enable_dbus" = "xyes"; then
+ case "$host_os" in
+
+ darwin*)
+ #
+ # We don't support D-Bus sniffing on macOS; see
+ #
+ # https://bugs.freedesktop.org/show_bug.cgi?id=74029
+ #
+ # The user requested it, so fail.
+ #
+ AC_MSG_ERROR([Due to freedesktop.org bug 74029, D-Bus capture support is not available on macOS])
+ esac
+ else
+ case "$host_os" in
+
+ darwin*)
+ #
+ # We don't support D-Bus sniffing on macOS; see
+ #
+ # https://bugs.freedesktop.org/show_bug.cgi?id=74029
+ #
+ # The user dind't explicitly request it, so just
+ # silently refuse to enable it.
+ #
+ enable_dbus="no"
+ ;;
+ esac
+ fi
+fi
+
+if test "x$enable_dbus" != "xno"; then
+ AC_CHECK_PROG([PKGCONFIG], [pkg-config], [pkg-config], [no])
+ if test "x$PKGCONFIG" != "xno"; then
+ AC_MSG_CHECKING([for D-Bus])
+ if "$PKGCONFIG" dbus-1; then
+ AC_MSG_RESULT([yes])
+ DBUS_CFLAGS=`"$PKGCONFIG" --cflags dbus-1`
+ DBUS_LIBS=`"$PKGCONFIG" --libs dbus-1`
+ save_CFLAGS="$CFLAGS"
+ save_LIBS="$LIBS"
+ CFLAGS="$CFLAGS $DBUS_CFLAGS"
+ LIBS="$LIBS $DBUS_LIBS"
+ AC_MSG_CHECKING(whether the D-Bus library defines dbus_connection_read_write)
+ AC_TRY_LINK(
+ [#include <string.h>
+
+ #include <time.h>
+ #include <sys/time.h>
+
+ #include <dbus/dbus.h>],
+ [return dbus_connection_read_write(NULL, 0);],
+ [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(PCAP_SUPPORT_DBUS, 1, [support D-Bus sniffing])
+ DBUS_SRC=pcap-dbus.c
+ V_INCLS="$V_INCLS $DBUS_CFLAGS"
+ ],
+ [
+ AC_MSG_RESULT([no])
+ if test "x$enable_dbus" = "xyes"; then
+ AC_MSG_ERROR([--enable-dbus was given, but the D-Bus library doesn't define dbus_connection_read_write()])
+ fi
+ LIBS="$save_LIBS"
+ ])
+ CFLAGS="$save_CFLAGS"
+ else
+ AC_MSG_RESULT([no])
+ if test "x$enable_dbus" = "xyes"; then
+ AC_MSG_ERROR([--enable-dbus was given, but the dbus-1 package is not installed])
+ fi
+ fi
+ fi
+ AC_SUBST(PCAP_SUPPORT_DBUS)
+ AC_SUBST(DBUS_SRC)
+fi
+
+AC_ARG_ENABLE([rdma],
+[AC_HELP_STRING([--enable-rdma],[enable RDMA capture support @<:@default=yes, if support available@:>@])],
+ [],
+ [enable_rdma=ifavailable])
+
+if test "xxx_only" = yes; then
+ # User requested something-else-only pcap, so they don't
+ # want RDMA support.
+ enable_rdma=no
+fi
+
+if test "x$enable_rdma" != "xno"; then
+ AC_CHECK_LIB(ibverbs, ibv_get_device_list, [
+ AC_CHECK_HEADER(infiniband/verbs.h, [
+ #
+ # ibv_create_flow may be defined as a static inline
+ # function in infiniband/verbs.h, so we can't
+ # use AC_CHECK_LIB.
+ #
+ # Too bad autoconf has no AC_SYMBOL_EXISTS()
+ # macro that works like CMake's check_symbol_exists()
+ # function, to check do a compile check like
+ # this (they do a clever trick to avoid having
+ # to know the function's signature).
+ #
+ AC_MSG_CHECKING(whether libibverbs defines ibv_create_flow)
+ AC_TRY_LINK(
+ [
+ #include <infiniband/verbs.h>
+ ],
+ [
+ (void) ibv_create_flow((struct ibv_qp *) NULL,
+ (struct ibv_flow_attr *) NULL);
+ ],
+ [
+ AC_MSG_RESULT([yes])
+ AC_DEFINE(PCAP_SUPPORT_RDMASNIFF, , [target host supports RDMA sniffing])
+ RDMA_SRC=pcap-rdmasniff.c
+ LIBS="-libverbs $LIBS"
+ ],
+ [
+ AC_MSG_RESULT([no])
+ ]
+ )
+ ])
+ ])
+ AC_SUBST(PCAP_SUPPORT_RDMASNIFF)
+ AC_SUBST(RDMA_SRC)
+fi
+
+AC_PROG_INSTALL
+
+AC_CONFIG_HEADER(config.h)
+
+AC_OUTPUT_COMMANDS([if test -f .devel; then
+ echo timestamp > stamp-h
+ cat $srcdir/Makefile-devel-adds >> Makefile
+ make depend
+fi])
+AC_OUTPUT(Makefile pcap-filter.manmisc pcap-linktype.manmisc
+ pcap-tstamp.manmisc pcap-savefile.manfile pcap.3pcap
+ pcap_compile.3pcap pcap_datalink.3pcap pcap_dump_open.3pcap
+ pcap_get_tstamp_precision.3pcap pcap_list_datalinks.3pcap
+ pcap_list_tstamp_types.3pcap pcap_open_dead.3pcap
+ pcap_open_offline.3pcap pcap_set_immediate_mode.3pcap
+ pcap_set_tstamp_precision.3pcap pcap_set_tstamp_type.3pcap
+ rpcapd/Makefile rpcapd/rpcapd.manadmin rpcapd/rpcapd-config.manfile
+ testprogs/Makefile)
+exit 0
diff --git a/lib/libpcap/libpcap/diag-control.h b/lib/libpcap/libpcap/diag-control.h
new file mode 100644
index 0000000..cfc581b
--- /dev/null
+++ b/lib/libpcap/libpcap/diag-control.h
@@ -0,0 +1,219 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#ifndef _diag_control_h
+#define _diag_control_h
+
+#include "pcap/compiler-tests.h"
+
+#ifndef _MSC_VER
+ /*
+ * Clang and GCC both support this way of putting pragmas into #defines.
+ * We don't use it unless we have a compiler that supports it; the
+ * warning-suppressing pragmas differ between Clang and GCC, so we test
+ * for both of those separately.
+ */
+ #define PCAP_DO_PRAGMA(x) _Pragma (#x)
+#endif
+
+/*
+ * Suppress Flex warnings.
+ */
+#if defined(_MSC_VER)
+ /*
+ * This is Microsoft Visual Studio; we can use __pragma(warning(disable:XXXX))
+ * and __pragma(warning(push/pop)).
+ *
+ * Suppress signed-vs-unsigned comparison, narrowing, and unreachable
+ * code warnings.
+ */
+ #define DIAG_OFF_FLEX \
+ __pragma(warning(push)) \
+ __pragma(warning(disable:4127)) \
+ __pragma(warning(disable:4242)) \
+ __pragma(warning(disable:4244)) \
+ __pragma(warning(disable:4702))
+ #define DIAG_ON_FLEX __pragma(warning(pop))
+#elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+ /*
+ * This is Clang 2.8 or later; we can use "clang diagnostic
+ * ignored -Wxxx" and "clang diagnostic push/pop".
+ *
+ * Suppress -Wdocumentation warnings; GCC doesn't support -Wdocumentation,
+ * at least according to the GCC 7.3 documentation. Apparently, Flex
+ * generates code that upsets at least some versions of Clang's
+ * -Wdocumentation.
+ */
+ #define DIAG_OFF_FLEX \
+ PCAP_DO_PRAGMA(clang diagnostic push) \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wsign-compare") \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wdocumentation") \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wmissing-noreturn") \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunused-parameter") \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+ #define DIAG_ON_FLEX \
+ PCAP_DO_PRAGMA(clang diagnostic pop)
+#elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
+ /*
+ * This is GCC 4.6 or later, or a compiler claiming to be that.
+ * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
+ * and "GCC diagnostic push/pop" (introduced in 4.6).
+ */
+ #define DIAG_OFF_FLEX \
+ PCAP_DO_PRAGMA(GCC diagnostic push) \
+ PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wsign-compare") \
+ PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunused-parameter") \
+ PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
+ #define DIAG_ON_FLEX \
+ PCAP_DO_PRAGMA(GCC diagnostic pop)
+#else
+ /*
+ * Neither Visual Studio, nor Clang 2.8 or later, nor GCC 4.6 or later
+ * or a compiler claiming to be that; there's nothing we know of that
+ * we can do.
+ */
+ #define DIAG_OFF_FLEX
+ #define DIAG_ON_FLEX
+#endif
+
+#ifdef YYBYACC
+ /*
+ * Berkeley YACC.
+ *
+ * It generates a global declaration of yylval, or the appropriately
+ * prefixed version of yylval, in grammar.h, *even though it's been
+ * told to generate a pure parser, meaning it doesn't have any global
+ * variables*. Bison doesn't do this.
+ *
+ * That causes a warning due to the local declaration in the parser
+ * shadowing the global declaration.
+ *
+ * So, if the compiler warns about that, we turn off -Wshadow warnings.
+ *
+ * In addition, the generated code may have functions with unreachable
+ * code, so suppress warnings about those.
+ */
+ #if defined(_MSC_VER)
+ /*
+ * This is Microsoft Visual Studio; we can use
+ * __pragma(warning(disable:XXXX)) and __pragma(warning(push/pop)).
+ */
+ #define DIAG_OFF_BISON_BYACC \
+ __pragma(warning(push)) \
+ __pragma(warning(disable:4702))
+ #define DIAG_ON_BISON_BYACC __pragma(warning(pop))
+ #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+ /*
+ * This is Clang 2.8 or later; we can use "clang diagnostic
+ * ignored -Wxxx" and "clang diagnostic push/pop".
+ */
+ #define DIAG_OFF_BISON_BYACC \
+ PCAP_DO_PRAGMA(clang diagnostic push) \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wshadow") \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+ #define DIAG_ON_BISON_BYACC \
+ PCAP_DO_PRAGMA(clang diagnostic pop)
+ #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
+ /*
+ * This is GCC 4.6 or later, or a compiler claiming to be that.
+ * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
+ * and "GCC diagnostic push/pop" (introduced in 4.6).
+ */
+ #define DIAG_OFF_BISON_BYACC \
+ PCAP_DO_PRAGMA(GCC diagnostic push) \
+ PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wshadow") \
+ PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
+ #define DIAG_ON_BISON_BYACC \
+ PCAP_DO_PRAGMA(GCC diagnostic pop)
+ #else
+ /*
+ * Neither Clang 2.8 or later nor GCC 4.6 or later or a compiler
+ * claiming to be that; there's nothing we know of that we can do.
+ */
+ #define DIAG_OFF_BISON_BYACC
+ #define DIAG_ON_BISON_BYACC
+ #endif
+#else
+ /*
+ * Bison.
+ *
+ * The generated code may have functions with unreachable code, so
+ * suppress warnings about those.
+ */
+ #if defined(_MSC_VER)
+ /*
+ * This is Microsoft Visual Studio; we can use
+ * __pragma(warning(disable:XXXX)) and __pragma(warning(push/pop)).
+ *
+ * Suppress some /Wall warnings.
+ */
+ #define DIAG_OFF_BISON_BYACC \
+ __pragma(warning(push)) \
+ __pragma(warning(disable:4127)) \
+ __pragma(warning(disable:4242)) \
+ __pragma(warning(disable:4244)) \
+ __pragma(warning(disable:4702))
+ #define DIAG_ON_BISON_BYACC __pragma(warning(pop))
+ #elif PCAP_IS_AT_LEAST_CLANG_VERSION(2,8)
+ /*
+ * This is Clang 2.8 or later; we can use "clang diagnostic
+ * ignored -Wxxx" and "clang diagnostic push/pop".
+ */
+ #define DIAG_OFF_BISON_BYACC \
+ PCAP_DO_PRAGMA(clang diagnostic push) \
+ PCAP_DO_PRAGMA(clang diagnostic ignored "-Wunreachable-code")
+ #define DIAG_ON_BISON_BYACC \
+ PCAP_DO_PRAGMA(clang diagnostic pop)
+ #elif PCAP_IS_AT_LEAST_GNUC_VERSION(4,6)
+ /*
+ * This is GCC 4.6 or later, or a compiler claiming to be that.
+ * We can use "GCC diagnostic ignored -Wxxx" (introduced in 4.2)
+ * and "GCC diagnostic push/pop" (introduced in 4.6).
+ */
+ #define DIAG_OFF_BISON_BYACC \
+ PCAP_DO_PRAGMA(GCC diagnostic push) \
+ PCAP_DO_PRAGMA(GCC diagnostic ignored "-Wunreachable-code")
+ #define DIAG_ON_BISON_BYACC \
+ PCAP_DO_PRAGMA(GCC diagnostic pop)
+ #else
+ /*
+ * Neither Clang 2.8 or later nor GCC 4.6 or later or a compiler
+ * claiming to be that; there's nothing we know of that we can do.
+ */
+ #define DIAG_OFF_BISON_BYACC
+ #define DIAG_ON_BISON_BYACC
+ #endif
+#endif
+
+#endif /* _diag_control_h */
diff --git a/lib/libpcap/libpcap/dlpisubs.c b/lib/libpcap/libpcap/dlpisubs.c
new file mode 100644
index 0000000..5f6e41a
--- /dev/null
+++ b/lib/libpcap/libpcap/dlpisubs.c
@@ -0,0 +1,398 @@
+/*
+ * This code is derived from code formerly in pcap-dlpi.c, originally
+ * contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk), University College
+ * London, and subsequently modified by Guy Harris (guy@alum.mit.edu),
+ * Mark Pizzolato <List-tcpdump-workers@subscriptions.pizzolato.net>,
+ * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
+ */
+
+/*
+ * This file contains dlpi/libdlpi related common functions used
+ * by pcap-[dlpi,libdlpi].c.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef DL_IPATM
+#define DL_IPATM 0x12 /* ATM Classical IP interface */
+#endif
+
+#ifdef HAVE_SYS_BUFMOD_H
+ /*
+ * Size of a bufmod chunk to pass upstream; that appears to be the
+ * biggest value to which you can set it, and setting it to that value
+ * (which is bigger than what appears to be the Solaris default of 8192)
+ * reduces the number of packet drops.
+ */
+#define CHUNKSIZE 65536
+
+ /*
+ * Size of the buffer to allocate for packet data we read; it must be
+ * large enough to hold a chunk.
+ */
+#define PKTBUFSIZE CHUNKSIZE
+
+#else /* HAVE_SYS_BUFMOD_H */
+
+ /*
+ * Size of the buffer to allocate for packet data we read; this is
+ * what the value used to be - there's no particular reason why it
+ * should be tied to MAXDLBUF, but we'll leave it as this for now.
+ */
+#define MAXDLBUF 8192
+#define PKTBUFSIZE (MAXDLBUF * sizeof(bpf_u_int32))
+
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_BUFMOD_H
+#include <sys/bufmod.h>
+#endif
+#include <sys/dlpi.h>
+#include <sys/stream.h>
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIBDLPI
+#include <libdlpi.h>
+#endif
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+#ifdef HAVE_SYS_BUFMOD_H
+static void pcap_stream_err(const char *, int, char *);
+#endif
+
+/*
+ * Get the packet statistics.
+ */
+int
+pcap_stats_dlpi(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_dlpi *pd = p->priv;
+
+ /*
+ * "ps_recv" counts packets handed to the filter, not packets
+ * that passed the filter. As filtering is done in userland,
+ * this would not include packets dropped because we ran out
+ * of buffer space; in order to make this more like other
+ * platforms (Linux 2.4 and later, BSDs with BPF), where the
+ * "packets received" count includes packets received but dropped
+ * due to running out of buffer space, and to keep from confusing
+ * applications that, for example, compute packet drop percentages,
+ * we also make it count packets dropped by "bufmod" (otherwise we
+ * might run the risk of the packet drop count being bigger than
+ * the received-packet count).
+ *
+ * "ps_drop" counts packets dropped by "bufmod" because of
+ * flow control requirements or resource exhaustion; it doesn't
+ * count packets dropped by the interface driver, or packets
+ * dropped upstream. As filtering is done in userland, it counts
+ * packets regardless of whether they would've passed the filter.
+ *
+ * These statistics don't include packets not yet read from
+ * the kernel by libpcap, but they may include packets not
+ * yet read from libpcap by the application.
+ */
+ *ps = pd->stat;
+
+ /*
+ * Add in the drop count, as per the above comment.
+ */
+ ps->ps_recv += ps->ps_drop;
+ return (0);
+}
+
+/*
+ * Loop through the packets and call the callback for each packet.
+ * Return the number of packets read.
+ */
+int
+pcap_process_pkts(pcap_t *p, pcap_handler callback, u_char *user,
+ int count, u_char *bufp, int len)
+{
+ struct pcap_dlpi *pd = p->priv;
+ int n, caplen, origlen;
+ u_char *ep, *pk;
+ struct pcap_pkthdr pkthdr;
+#ifdef HAVE_SYS_BUFMOD_H
+ struct sb_hdr *sbp;
+#ifdef LBL_ALIGN
+ struct sb_hdr sbhdr;
+#endif
+#endif
+
+ /* Loop through packets */
+ ep = bufp + len;
+ n = 0;
+
+#ifdef HAVE_SYS_BUFMOD_H
+ while (bufp < ep) {
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else {
+ p->bp = bufp;
+ p->cc = ep - bufp;
+ return (n);
+ }
+ }
+#ifdef LBL_ALIGN
+ if ((long)bufp & 3) {
+ sbp = &sbhdr;
+ memcpy(sbp, bufp, sizeof(*sbp));
+ } else
+#endif
+ sbp = (struct sb_hdr *)bufp;
+ pd->stat.ps_drop = sbp->sbh_drops;
+ pk = bufp + sizeof(*sbp);
+ bufp += sbp->sbh_totlen;
+ origlen = sbp->sbh_origlen;
+ caplen = sbp->sbh_msglen;
+#else
+ origlen = len;
+ caplen = min(p->snapshot, len);
+ pk = bufp;
+ bufp += caplen;
+#endif
+ ++pd->stat.ps_recv;
+ if (bpf_filter(p->fcode.bf_insns, pk, origlen, caplen)) {
+#ifdef HAVE_SYS_BUFMOD_H
+ pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec;
+ pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec;
+#else
+ (void) gettimeofday(&pkthdr.ts, NULL);
+#endif
+ pkthdr.len = origlen;
+ pkthdr.caplen = caplen;
+ /* Insure caplen does not exceed snapshot */
+ if (pkthdr.caplen > (bpf_u_int32)p->snapshot)
+ pkthdr.caplen = (bpf_u_int32)p->snapshot;
+ (*callback)(user, &pkthdr, pk);
+ if (++n >= count && !PACKET_COUNT_IS_UNLIMITED(count)) {
+ p->cc = ep - bufp;
+ p->bp = bufp;
+ return (n);
+ }
+ }
+#ifdef HAVE_SYS_BUFMOD_H
+ }
+#endif
+ p->cc = 0;
+ return (n);
+}
+
+/*
+ * Process the mac type. Returns -1 if no matching mac type found, otherwise 0.
+ */
+int
+pcap_process_mactype(pcap_t *p, u_int mactype)
+{
+ int retv = 0;
+
+ switch (mactype) {
+
+ case DL_CSMACD:
+ case DL_ETHER:
+ p->linktype = DLT_EN10MB;
+ p->offset = 2;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *)malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+ break;
+
+ case DL_FDDI:
+ p->linktype = DLT_FDDI;
+ p->offset = 3;
+ break;
+
+ case DL_TPR:
+ /* XXX - what about DL_TPB? Is that Token Bus? */
+ p->linktype = DLT_IEEE802;
+ p->offset = 2;
+ break;
+
+#ifdef HAVE_SOLARIS
+ case DL_IPATM:
+ p->linktype = DLT_SUNATM;
+ p->offset = 0; /* works for LANE and LLC encapsulation */
+ break;
+#endif
+
+#ifdef DL_IPV4
+ case DL_IPV4:
+ p->linktype = DLT_IPV4;
+ p->offset = 0;
+ break;
+#endif
+
+#ifdef DL_IPV6
+ case DL_IPV6:
+ p->linktype = DLT_IPV6;
+ p->offset = 0;
+ break;
+#endif
+
+#ifdef DL_IPNET
+ case DL_IPNET:
+ /*
+ * XXX - DL_IPNET devices default to "raw IP" rather than
+ * "IPNET header"; see
+ *
+ * http://seclists.org/tcpdump/2009/q1/202
+ *
+ * We'd have to do DL_IOC_IPNET_INFO to enable getting
+ * the IPNET header.
+ */
+ p->linktype = DLT_RAW;
+ p->offset = 0;
+ break;
+#endif
+
+ default:
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown mactype 0x%x",
+ mactype);
+ retv = -1;
+ }
+
+ return (retv);
+}
+
+#ifdef HAVE_SYS_BUFMOD_H
+/*
+ * Push and configure the buffer module. Returns -1 for error, otherwise 0.
+ */
+int
+pcap_conf_bufmod(pcap_t *p, int snaplen)
+{
+ struct timeval to;
+ bpf_u_int32 ss, chunksize;
+
+ /* Non-standard call to get the data nicely buffered. */
+ if (ioctl(p->fd, I_PUSH, "bufmod") != 0) {
+ pcap_stream_err("I_PUSH bufmod", errno, p->errbuf);
+ return (-1);
+ }
+
+ ss = snaplen;
+ if (ss > 0 &&
+ strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) {
+ pcap_stream_err("SBIOCSSNAP", errno, p->errbuf);
+ return (-1);
+ }
+
+ if (p->opt.immediate) {
+ /* Set the timeout to zero, for immediate delivery. */
+ to.tv_sec = 0;
+ to.tv_usec = 0;
+ if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
+ pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
+ return (-1);
+ }
+ } else {
+ /* Set up the bufmod timeout. */
+ if (p->opt.timeout != 0) {
+ to.tv_sec = p->opt.timeout / 1000;
+ to.tv_usec = (p->opt.timeout * 1000) % 1000000;
+ if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) {
+ pcap_stream_err("SBIOCSTIME", errno, p->errbuf);
+ return (-1);
+ }
+ }
+
+ /* Set the chunk length. */
+ chunksize = CHUNKSIZE;
+ if (strioctl(p->fd, SBIOCSCHUNK, sizeof(chunksize), (char *)&chunksize)
+ != 0) {
+ pcap_stream_err("SBIOCSCHUNKP", errno, p->errbuf);
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+#endif /* HAVE_SYS_BUFMOD_H */
+
+/*
+ * Allocate data buffer. Returns -1 if memory allocation fails, else 0.
+ */
+int
+pcap_alloc_databuf(pcap_t *p)
+{
+ p->bufsize = PKTBUFSIZE;
+ p->buffer = malloc(p->bufsize + p->offset);
+ if (p->buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Issue a STREAMS I_STR ioctl. Returns -1 on error, otherwise
+ * length of returned data on success.
+ */
+int
+strioctl(int fd, int cmd, int len, char *dp)
+{
+ struct strioctl str;
+ int retv;
+
+ str.ic_cmd = cmd;
+ str.ic_timout = -1;
+ str.ic_len = len;
+ str.ic_dp = dp;
+ if ((retv = ioctl(fd, I_STR, &str)) < 0)
+ return (retv);
+
+ return (str.ic_len);
+}
+
+#ifdef HAVE_SYS_BUFMOD_H
+/*
+ * Write stream error message to errbuf.
+ */
+static void
+pcap_stream_err(const char *func, int err, char *errbuf)
+{
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, err, "%s", func);
+}
+#endif
diff --git a/lib/libpcap/libpcap/dlpisubs.h b/lib/libpcap/libpcap/dlpisubs.h
new file mode 100644
index 0000000..cdc531c
--- /dev/null
+++ b/lib/libpcap/libpcap/dlpisubs.h
@@ -0,0 +1,38 @@
+#ifndef dlpisubs_h
+#define dlpisubs_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Private data for capturing on DLPI devices.
+ */
+struct pcap_dlpi {
+#ifdef HAVE_LIBDLPI
+ dlpi_handle_t dlpi_hd;
+#endif /* HAVE_LIBDLPI */
+#ifdef DL_HP_RAWDLS
+ int send_fd;
+#endif /* DL_HP_RAWDLS */
+
+ struct pcap_stat stat;
+};
+
+/*
+ * Functions defined by dlpisubs.c.
+ */
+int pcap_stats_dlpi(pcap_t *, struct pcap_stat *);
+int pcap_process_pkts(pcap_t *, pcap_handler, u_char *, int, u_char *, int);
+int pcap_process_mactype(pcap_t *, u_int);
+#ifdef HAVE_SYS_BUFMOD_H
+int pcap_conf_bufmod(pcap_t *, int);
+#endif
+int pcap_alloc_databuf(pcap_t *);
+int strioctl(int, int, int, char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libpcap/libpcap/doc/DLT_ALLOCATE_HOWTO.md b/lib/libpcap/libpcap/doc/DLT_ALLOCATE_HOWTO.md
new file mode 100644
index 0000000..ff77128
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/DLT_ALLOCATE_HOWTO.md
@@ -0,0 +1,29 @@
+DLT and LINKTYPE allocation
+===========================
+
+DLT_ types live in pcap/dlt.h. They can be requested by the community on a
+First-Come First-Served basis [i.e. https://tools.ietf.org/html/rfc8126#section-4.4 ]
+(Although libpcap is not at this time an IETF specification, there have been
+some as yet-incomplete efforts to do this).
+
+The Tcpdump Group prefers to link to an open specification on the new DLT_
+type, but they are available for closed, proprietary projects as well.
+In that case, a stable email address suffices so that someone who finds
+an unknown DLT_ type can investigate.
+We prefer to give out unambiguous numbers, and we try to do it as quickly
+as possible, but DLT_USERx is available while you wait.
+
+Note that DLT_ types are, in theory, private to the capture mechanism and can
+in some cases be operating system specific, and so a second set of values,
+LINKTYPE_ is allocated for actually writing to pcap files. As much as
+possible going forward, the DLT_ and LINKTYPE_ value are identical, however,
+this was not always the case. See pcap-common.c.
+
+The LINKTYPE_ values are not exported, but are in pcap-common.c only.
+
+DEVELOPER NOTES
+---------------
+
+When allocating a new DLT_ value, a corresponding value needs to be
+added to pcap-common.c.
+It is not necessary to copy the comments from dlt.h to pcap-common.c.
diff --git a/lib/libpcap/libpcap/doc/README.Win32.md b/lib/libpcap/libpcap/doc/README.Win32.md
new file mode 100644
index 0000000..8de25c8
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.Win32.md
@@ -0,0 +1,3 @@
+Win32 used to build with Visual Studio 6, but we now use cmake.
+
+This file needs to be adopted by a windows expert developer.
diff --git a/lib/libpcap/libpcap/doc/README.aix b/lib/libpcap/libpcap/doc/README.aix
new file mode 100644
index 0000000..92e513f
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.aix
@@ -0,0 +1,88 @@
+Using BPF:
+
+(1) AIX 4.x's version of BPF is undocumented and somewhat unstandard; the
+ current BPF support code includes changes that should work around
+ that; it appears to compile and work on at least one AIX 4.3.3
+ machine.
+
+ Note that the BPF driver and the "/dev/bpf" devices might not exist
+ on your machine; AIX's tcpdump loads the driver and creates the
+ devices if they don't already exist. Our libpcap should do the
+ same, and the configure script should detect that it's on an AIX
+ system and choose BPF even if the devices aren't there.
+
+ Also note that tcpdump _binary_ compiled on AIX 4 may have a problem
+ doing the initial loading of the BPF driver if copied to AIX 5 and
+ run there (GH #52). tcpdump binary natively compiled on AIX 5 should
+ not have this issue.
+
+(2) If libpcap doesn't compile on your machine when configured to use
+ BPF, or if the workarounds fail to make it work correctly, you
+ should send to tcpdump-workers@lists.tcpdump.org a detailed bug
+ report (if the compile fails, send us the compile error messages;
+ if it compiles but fails to work correctly, send us as detailed as
+ possible a description of the symptoms, including indications of the
+ network link-layer type being wrong or time stamps being wrong).
+
+ If you fix the problems yourself, please submit a patch by forking
+ the branch at
+
+ https://github.com/the-tcpdump-group/libpcap/issues
+
+ and issuing a pull request, so we can incorporate the fixes into the
+ next release.
+
+ If you don't fix the problems yourself, you can, as a workaround,
+ make libpcap use DLPI instead of BPF.
+
+ This can be done by specifying the flag:
+
+ --with-pcap=dlpi
+
+ to the "configure" script for libpcap.
+
+If you use DLPI:
+
+(1) It is a good idea to have the latest version of the DLPI driver on
+ your system, since certain versions may be buggy and cause your AIX
+ system to crash. DLPI is included in the fileset bos.rte.tty. I
+ found that the DLPI driver that came with AIX 4.3.2 was buggy, and
+ had to upgrade to bos.rte.tty 4.3.2.4:
+
+ lslpp -l bos.rte.tty
+
+ bos.rte.tty 4.3.2.4 COMMITTED Base TTY Support and Commands
+
+ Updates for AIX filesets can be obtained from:
+ ftp://service.software.ibm.com/aix/fixes/
+
+ These updates can be installed with the smit program.
+
+(2) After compiling libpcap, you need to make sure that the DLPI driver
+ is loaded. Type:
+
+ strload -q -d dlpi
+
+ If the result is:
+
+ dlpi: yes
+
+ then the DLPI driver is loaded correctly.
+
+ If it is:
+
+ dlpi: no
+
+ Then you need to type:
+
+ strload -f /etc/dlpi.conf
+
+ Check again with strload -q -d dlpi that the dlpi driver is loaded.
+
+ Alternatively, you can uncomment the lines for DLPI in
+ /etc/pse.conf and reboot the machine; this way DLPI will always
+ be loaded when you boot your system.
+
+(3) There appears to be a problem in the DLPI code in some versions of
+ AIX, causing a warning about DL_PROMISC_MULTI failing; this might
+ be responsible for DLPI not being able to capture outgoing packets.
diff --git a/lib/libpcap/libpcap/doc/README.dag b/lib/libpcap/libpcap/doc/README.dag
new file mode 100644
index 0000000..7ea2504
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.dag
@@ -0,0 +1,122 @@
+
+The following instructions apply if you have a Linux or FreeBSD platform and
+want libpcap to support the DAG range of passive network monitoring cards from
+Endace (http://www.endace.com, see below for further contact details).
+
+1) Install and build the DAG software distribution by following the
+instructions supplied with that package. Current Endace customers can download
+the DAG software distribution from https://www.endace.com
+
+2) Configure libcap. To allow the 'configure' script to locate the DAG
+software distribution use the '--with-dag' option:
+
+ ./configure --with-dag=DIR
+
+Where DIR is the root of the DAG software distribution, for example
+/var/src/dag. If the DAG software is correctly detected 'configure' will
+report:
+
+ checking whether we have DAG API... yes
+
+If 'configure' reports that there is no DAG API, the directory may have been
+incorrectly specified or the DAG software was not built before configuring
+libpcap.
+
+See also the libpcap INSTALL.txt file for further libpcap configuration
+options.
+
+Building libpcap at this stage will include support for both the native packet
+capture stream (linux or bpf) and for capturing from DAG cards. To build
+libpcap with only DAG support specify the capture type as 'dag' when
+configuring libpcap:
+
+ ./configure --with-dag=DIR --with-pcap=dag
+
+Applications built with libpcap configured in this way will only detect DAG
+cards and will not capture from the native OS packet stream.
+
+----------------------------------------------------------------------
+
+Libpcap when built for DAG cards against dag-2.5.1 or later releases:
+
+Timeouts are supported. pcap_dispatch() will return after to_ms milliseconds
+regardless of how many packets are received. If to_ms is zero pcap_dispatch()
+will block waiting for data indefinitely.
+
+pcap_dispatch() will block on and process a minimum of 64kB of data (before
+filtering) for efficiency. This can introduce high latencies on quiet
+interfaces unless a timeout value is set. The timeout expiring will override
+the 64kB minimum causing pcap_dispatch() to process any available data and
+return.
+
+pcap_setnonblock is supported. When nonblock is set, pcap_dispatch() will
+check once for available data, process any data available up to count, then
+return immediately.
+
+pcap_findalldevs() is supported, e.g. dag0, dag1...
+
+Some DAG cards can provide more than one 'stream' of received data.
+This can be data from different physical ports, or separated by filtering
+or load balancing mechanisms. Receive streams have even numbers, e.g.
+dag0:0, dag0:2 etc. Specifying transmit streams for capture is not supported.
+
+pcap_setfilter() is supported, BPF programs run in userspace.
+
+pcap_setdirection() is not supported. Only received traffic is captured.
+DAG cards normally do not have IP or link layer addresses assigned as
+they are used to passively monitor links.
+
+pcap_breakloop() is supported.
+
+pcap_datalink() and pcap_list_datalinks() are supported. The DAG card does
+not attempt to set the correct datalink type automatically where more than
+one type is possible.
+
+pcap_stats() is supported. ps_drop is the number of packets dropped due to
+RX stream buffer overflow, this count is before filters are applied (it will
+include packets that would have been dropped by the filter). The RX stream
+buffer size is user configurable outside libpcap, typically 16-512MB.
+
+pcap_get_selectable_fd() is not supported, as DAG cards do not support
+poll/select methods.
+
+pcap_inject() and pcap_sendpacket() are not supported.
+
+Some DAG cards now support capturing to multiple virtual interfaces, called
+streams. Capture streams have even numbers. These are available via libpcap
+as separate interfaces, e.g. dag0:0, dag0:2, dag0:4 etc. dag0:0 is the same
+as dag0. These are visible via pcap_findalldevs().
+
+libpcap now does NOT set the card's hardware snaplen (slen). This must now be
+set using the appropriate DAG configuration program, e.g. dagthree, dagfour,
+dagsix, dagconfig. This is because the snaplen is currently shared between
+all of the streams. In future this may change if per-stream slen is
+implemented.
+
+DAG cards by default capture entire packets including the L2
+CRC/FCS. If the card is not configured to discard the CRC/FCS, this
+can confuse applications that use libpcap if they're not prepared for
+packets to have an FCS.
+
+Libpcap now reads the environment variable ERF_FCS_BITS to determine
+how many bits of CRC/FCS to strip from the end of the captured
+frame. This defaults to 32 for use with Ethernet. If the card is
+configured to strip the CRC/FCS, then set ERF_FCS_BITS=0. If used with
+a HDLC/PoS/PPP/Frame Relay link with 16 bit CRC/FCS, then set
+ERF_FCS_BITS=16.
+
+If you wish to create a pcap file that DOES contain the Ethernet FCS,
+specify the environment variable ERF_DONT_STRIP_FCS. This will cause
+the existing FCS to be captured into the pcap file. Note some
+applications may incorrectly report capture errors or oversize packets
+when reading these files.
+
+----------------------------------------------------------------------
+
+Please submit bug reports via <support@endace.com>.
+
+Please also visit our Web site at:
+
+ http://www.endace.com/
+
+For more information about Endace DAG cards contact <sales@endace.com>.
diff --git a/lib/libpcap/libpcap/doc/README.hpux b/lib/libpcap/libpcap/doc/README.hpux
new file mode 100644
index 0000000..65ecff9
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.hpux
@@ -0,0 +1,254 @@
+For HP-UX 11i (11.11) and later, there are no known issues with
+promiscuous mode under HP-UX. If you are using a earlier version of
+HP-UX and cannot upgrade, please continue reading.
+
+HP-UX patches to fix packet capture problems
+
+Note that packet-capture programs such as tcpdump may, on HP-UX, not be
+able to see packets sent from the machine on which they're running.
+Some articles on groups.google.com discussing this are:
+
+ http://groups.google.com/groups?selm=82ld3v%2480i%241%40mamenchi.zrz.TU-Berlin.DE
+
+which says:
+
+ Newsgroups: comp.sys.hp.hpux
+ Subject: Re: Did someone made tcpdump working on 10.20 ?
+ Date: 12/08/1999
+ From: Lutz Jaenicke <jaenicke@emserv1.ee.TU-Berlin.DE>
+
+ In article <82ks5i$5vc$1@news1.dti.ne.jp>, mtsat <mtsat@iris.dti.ne.jp>
+ wrote:
+ >Hello,
+ >
+ >I downloaded and compiled tcpdump3.4 a couple of week ago. I tried to use
+ >it, but I can only see incoming data, never outgoing.
+ >Someone (raj) explained me that a patch was missing, and that this patch
+ >must me "patched" (poked) in order to see outbound data in promiscuous mode.
+ >Many things to do .... So the question is : did someone has already this
+ >"ready to use" PHNE_**** patch ?
+
+ Two things:
+ 1. You do need a late "LAN products cumulative patch" (e.g. PHNE_18173
+ for s700/10.20).
+ 2. You must use
+echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
+ You can insert this e.g. into /sbin/init.d/lan
+
+ Best regards,
+ Lutz
+
+and
+
+ http://groups.google.com/groups?selm=88cf4t%24p03%241%40web1.cup.hp.com
+
+which says:
+
+ Newsgroups: comp.sys.hp.hpux
+ Subject: Re: tcpdump only shows incoming packets
+ Date: 02/15/2000
+ From: Rick Jones <foo@bar.baz.invalid>
+
+ Harald Skotnes <harald@cc.uit.no> wrote:
+ > I am running HPUX 11.0 on a C200 hanging on a 100Mb switch. I have
+ > compiled libpcap-0.4 an tcpdump-3.4 and it seems to work. But at a
+ > closer look I only get to see the incoming packets not the
+ > outgoing. I have tried tcpflow-0.12 which also uses libpcap and the
+ > same thing happens. Could someone please give me a hint on how to
+ > get this right?
+
+ Search/Read the archives ?-)
+
+ What you are seeing is expected, un-patched, behaviour for an HP-UX
+ system. On 11.00, you need to install the latest lancommon/DLPI
+ patches, and then the latest driver patch for the interface(s) in use.
+ At that point, a miracle happens and you should start seeing outbound
+ traffic.
+
+[That article also mentions the patch that appears below.]
+
+and
+
+ http://groups.google.com/groups?selm=38AA973E.96BE7DF7%40cc.uit.no
+
+which says:
+
+ Newsgroups: comp.sys.hp.hpux
+ Subject: Re: tcpdump only shows incoming packets
+ Date: 02/16/2000
+ From: Harald Skotnes <harald@cc.uit.no>
+
+ Rick Jones wrote:
+
+ ...
+
+ > What you are seeing is expected, un-patched, behaviour for an HP-UX
+ > system. On 11.00, you need to install the latest lancommon/DLPI
+ > patches, and then the latest driver patch for the interface(s) in
+ > use. At that point, a miracle happens and you should start seeing
+ > outbound traffic.
+
+ Thanks a lot. I have this problem on several machines running HPUX
+ 10.20 and 11.00. The machines where patched up before y2k so did not
+ know what to think. Anyway I have now installed PHNE_19766,
+ PHNE_19826, PHNE_20008, PHNE_20735 on the C200 and now I can see the
+ outbound traffic too. Thanks again.
+
+(although those patches may not be the ones to install - there may be
+later patches).
+
+And another message to tcpdump-workers@tcpdump.org, from Rick Jones:
+
+ Date: Mon, 29 Apr 2002 15:59:55 -0700
+ From: Rick Jones
+ To: tcpdump-workers@tcpdump.org
+ Subject: Re: [tcpdump-workers] I Can't Capture the Outbound Traffic
+
+ ...
+
+ http://itrc.hp.com/ would be one place to start in a search for the most
+ up-to-date patches for DLPI and the lan driver(s) used on your system (I
+ cannot guess because 9000/800 is too generic - one hs to use the "model"
+ command these days and/or an ioscan command (see manpage) to guess what
+ the drivers (btlan[3456], gelan, etc) might be involved in addition to
+ DLPI.
+
+ Another option is to upgrade to 11i as outbound promiscuous mode support
+ is there in the base OS, no patches required.
+
+Another posting:
+
+ http://groups.google.com/groups?selm=7d6gvn%24b3%241%40ocean.cup.hp.com
+
+indicates that you need to install the optional STREAMS product to do
+captures on HP-UX 9.x:
+
+ Newsgroups: comp.sys.hp.hpux
+ Subject: Re: tcpdump HP/UX 9.x
+ Date: 03/22/1999
+ From: Rick Jones <foo@bar.baz>
+
+ Dave Barr (barr@cis.ohio-state.edu) wrote:
+ : Has anyone ported tcpdump (or something similar) to HP/UX 9.x?
+
+ I'm reasonably confident that any port of tcpdump to 9.X would require
+ the (then optional) STREAMS product. This would bring DLPI, which is
+ what one uses to access interfaces in promiscuous mode.
+
+ I'm not sure that HP even sells the 9.X STREAMS product any longer,
+ since HP-UX 9.X is off the pricelist (well, maybe 9.10 for the old 68K
+ devices).
+
+ Your best bet is to be up on 10.20 or better if that is at all
+ possible. If your hardware is supported by it, I'd go with HP-UX 11.
+ If you want to see the system's own outbound traffic, you'll never get
+ that functionality on 9.X, but it might happen at some point for 10.20
+ and 11.X.
+
+ rick jones
+
+(as per other messages cited here, the ability to see the system's own
+outbound traffic did happen).
+
+Rick Jones reports that HP-UX 11i needs no patches for outbound
+promiscuous mode support.
+
+An additional note, from Jost Martin, for HP-UX 10.20:
+
+ Q: How do I get ethereral on HPUX to capture the _outgoing_ packets
+ of an interface
+ A: You need to get PHNE_20892,PHNE_20725 and PHCO_10947 (or
+ newer, this is as of 4.4.00) and its dependencies. Then you can
+ enable the feature as descibed below:
+
+ Patch Name: PHNE_20892
+ Patch Description: s700 10.20 PCI 100Base-T cumulative patch
+ To trace the outbound packets, please do the following
+ to turn on a global promiscuous switch before running
+ the promiscuous applications like snoop or tcpdump:
+
+ adb -w /stand/vmunix /dev/mem
+ lanc_outbound_promisc_flag/W 1
+ (adb will echo the result showing that the flag has
+ been changed)
+ $quit
+ (Thanks for this part to HP-support, Ratingen)
+
+ The attached hack does this and some security-related stuff
+ (thanks to hildeb@www.stahl.bau.tu-bs.de (Ralf Hildebrandt) who
+ posted the security-part some time ago)
+
+ <<hack_ip_stack>>
+
+ (Don't switch IP-forwarding off, if you need it !)
+ Install the hack as /sbin/init.d/hacl_ip_stack (adjust
+ permissions !) and make a sequencing-symlink
+ /sbin/rc2.d/S350hack_ip_stack pointing to this script.
+ Now all this is done on every reboot.
+
+According to Rick Jones, the global promiscuous switch also has to be
+turned on for HP-UX 11.00, but not for 11i - and, in fact, the switch
+doesn't even exist on 11i.
+
+Here's the "hack_ip_stack" script:
+
+-----------------------------------Cut Here-------------------------------------
+#!/sbin/sh
+#
+# nettune: hack kernel parms for safety
+
+OKAY=0
+ERROR=-1
+
+# /usr/contrib/bin fuer nettune auf Pfad
+PATH=/sbin:/usr/sbin:/usr/bin:/usr/contrib/bin
+export PATH
+
+
+##########
+# main #
+##########
+
+case $1 in
+ start_msg)
+ print "Tune IP-Stack for security"
+ exit $OKAY
+ ;;
+
+ stop_msg)
+ print "This action is not applicable"
+ exit $OKAY
+ ;;
+
+ stop)
+ exit $OKAY
+ ;;
+
+ start)
+ ;; # fall through
+
+ *)
+ print "USAGE: $0 {start_msg | stop_msg | start | stop}" >&2
+ exit $ERROR
+ ;;
+ esac
+
+###########
+# start #
+###########
+
+#
+# tcp-Sequence-Numbers nicht mehr inkrementieren sondern random
+# Syn-Flood-Protection an
+# ip_forwarding aus
+# Source-Routing aus
+# Ausgehende Packets an ethereal/tcpdump etc.
+
+/usr/contrib/bin/nettune -s tcp_random_seq 2 || exit $ERROR
+/usr/contrib/bin/nettune -s hp_syn_protect 1 || exit $ERROR
+/usr/contrib/bin/nettune -s ip_forwarding 0 || exit $ERROR
+echo 'ip_block_source_routed/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem || exit $ERROR
+echo 'lanc_outbound_promisc_flag/W 1' | adb -w /stand/vmunix /dev/mem || exit $ERROR
+
+exit $OKAY
+-----------------------------------Cut Here-------------------------------------
diff --git a/lib/libpcap/libpcap/doc/README.linux.md b/lib/libpcap/libpcap/doc/README.linux.md
new file mode 100644
index 0000000..ddca4fe
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.linux.md
@@ -0,0 +1,108 @@
+In order for libpcap to be able to capture packets on a Linux system,
+the "packet" protocol must be supported by your kernel. If it is not,
+you may get error messages such as
+
+ modprobe: can't locate module net-pf-17
+
+in "/var/adm/messages", or may get messages such as
+
+ socket: Address family not supported by protocol
+
+from applications using libpcap.
+
+You must configure the kernel with the CONFIG_PACKET option for this
+protocol; the following note is from the Linux "Configure.help" file for
+the 2.0[.x] kernel:
+
+ Packet socket
+ CONFIG_PACKET
+ The Packet protocol is used by applications which communicate
+ directly with network devices without an intermediate network
+ protocol implemented in the kernel, e.g. tcpdump. If you want them
+ to work, choose Y.
+
+ This driver is also available as a module called af_packet.o ( =
+ code which can be inserted in and removed from the running kernel
+ whenever you want). If you want to compile it as a module, say M
+ here and read Documentation/modules.txt; if you use modprobe or
+ kmod, you may also want to add "alias net-pf-17 af_packet" to
+ /etc/modules.conf.
+
+and the note for the 2.2[.x] kernel says:
+
+ Packet socket
+ CONFIG_PACKET
+ The Packet protocol is used by applications which communicate
+ directly with network devices without an intermediate network
+ protocol implemented in the kernel, e.g. tcpdump. If you want them
+ to work, choose Y. This driver is also available as a module called
+ af_packet.o ( = code which can be inserted in and removed from the
+ running kernel whenever you want). If you want to compile it as a
+ module, say M here and read Documentation/modules.txt. You will
+ need to add 'alias net-pf-17 af_packet' to your /etc/conf.modules
+ file for the module version to function automatically. If unsure,
+ say Y.
+
+In addition, there is an option that, in 2.2 and later kernels, will
+allow packet capture filters specified to programs such as tcpdump to be
+executed in the kernel, so that packets that don't pass the filter won't
+be copied from the kernel to the program, rather than having all packets
+copied to the program and libpcap doing the filtering in user mode.
+
+Copying packets from the kernel to the program consumes a significant
+amount of CPU, so filtering in the kernel can reduce the overhead of
+capturing packets if a filter has been specified that discards a
+significant number of packets. (If no filter is specified, it makes no
+difference whether the filtering isn't performed in the kernel or isn't
+performed in user mode. :-))
+
+The option for this is the CONFIG_FILTER option; the "Configure.help"
+file says:
+
+ Socket filtering
+ CONFIG_FILTER
+ The Linux Socket Filter is derived from the Berkeley Packet Filter.
+ If you say Y here, user-space programs can attach a filter to any
+ socket and thereby tell the kernel that it should allow or disallow
+ certain types of data to get through the socket. Linux Socket
+ Filtering works on all socket types except TCP for now. See the text
+ file linux/Documentation/networking/filter.txt for more information.
+ If unsure, say N.
+
+Note that, by default, libpcap will, if libnl is present, build with it;
+it uses libnl to support monitor mode on mac80211 devices. There is a
+configuration option to disable building with libnl, but, if that option
+is chosen, the monitor-mode APIs (as used by tcpdump's "-I" flag, and as
+will probably be used by other applications in the future) won't work
+properly on mac80211 devices.
+
+Linux's run-time linker allows shared libraries to be linked with other
+shared libraries, which means that if an older version of a shared
+library doesn't require routines from some other shared library, and a
+later version of the shared library does require those routines, the
+later version of the shared library can be linked with that other shared
+library and, if it's otherwise binary-compatible with the older version,
+can replace that older version without breaking applications built with
+the older version, and without breaking configure scripts or the build
+procedure for applications whose configure script doesn't use the
+pcap-config script if they build with the shared library. (The build
+procedure for applications whose configure scripts use the pcap-config
+script if present will not break even if they build with the static
+library.)
+
+Statistics:
+Statistics reported by pcap are platform specific. The statistics
+reported by pcap_stats on Linux are as follows:
+
+2.2.x
+=====
+ps_recv Number of packets that were accepted by the pcap filter
+ps_drop Always 0, this statistic is not gathered on this platform
+
+2.4.x and later
+=====
+ps_recv Number of packets that were accepted by the pcap filter
+ps_drop Number of packets that had passed filtering but were not
+ passed on to pcap due to things like buffer shortage, etc.
+ This is useful because these are packets you are interested in
+ but won't be reported by, for example, tcpdump output.
diff --git a/lib/libpcap/libpcap/doc/README.macos b/lib/libpcap/libpcap/doc/README.macos
new file mode 100644
index 0000000..3cceb23
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.macos
@@ -0,0 +1,74 @@
+As with other systems using BPF, macOS allows users with read access to
+the BPF devices to capture packets with libpcap and allows users with
+write access to the BPF devices to send packets with libpcap.
+
+On some systems that use BPF, the BPF devices live on the root file
+system, and the permissions and/or ownership on those devices can be
+changed to give users other than root permission to read or write those
+devices.
+
+On newer versions of FreeBSD, the BPF devices live on devfs, and devfs
+can be configured to set the permissions and/or ownership of those
+devices to give users other than root permission to read or write those
+devices.
+
+On macOS, the BPF devices live on devfs, but the macOS version of devfs
+is based on an older (non-default) FreeBSD devfs, and that version of
+devfs cannot be configured to set the permissions and/or ownership of
+those devices.
+
+Therefore, we supply:
+
+ a "startup item" for older versions of macOS;
+
+ a launchd daemon for Tiger and later versions of macOS;
+
+Both of them will change the ownership of the BPF devices so that the
+"admin" group owns them, and will change the permission of the BPF
+devices to rw-rw----, so that all users in the "admin" group - i.e., all
+users with "Allow user to administer this computer" turned on - have
+both read and write access to them.
+
+The startup item is in the ChmodBPF directory in the source tree. A
+/Library/StartupItems directory should be created if it doesn't already
+exist, and the ChmodBPF directory should be copied to the
+/Library/StartupItems directory (copy the entire directory, so that
+there's a /Library/StartupItems/ChmodBPF directory, containing all the
+files in the source tree's ChmodBPF directory; don't copy the individual
+items in that directory to /Library/StartupItems). The ChmodBPF
+directory, and all files under it, must be owned by root. Installing
+the files won't immediately cause the startup item to be executed; it
+will be executed on the next reboot. To change the permissions before
+the reboot, run
+
+ sudo SystemStarter start ChmodBPF
+
+The launchd daemon is the chmod_bpf script, plus the
+org.tcpdump.chmod_bpf.plist launchd plist file. chmod_bpf should be
+installed in /usr/local/bin/chmod_bpf, and org.tcpdump.chmod_bpf.plist
+should be installed in /Library/LaunchDaemons. chmod_bpf, and
+org.tcpdump.chmod_bpf.plist, must be owned by root. Installing the
+script and plist file won't immediately cause the script to be executed;
+it will be executed on the next reboot. To change the permissions
+before the reboot, run
+
+ sudo /usr/local/bin/chmod_bpf
+
+or
+
+ sudo launchctl load /Library/LaunchDaemons/org.tcpdump.chmod_bpf.plist
+
+If you want to give a particular user permission to access the BPF
+devices, rather than giving all administrative users permission to
+access them, you can have the ChmodBPF/ChmodBPF script change the
+ownership of /dev/bpf* without changing the permissions. If you want to
+give a particular user permission to read and write the BPF devices and
+give the administrative users permission to read but not write the BPF
+devices, you can have the script change the owner to that user, the
+group to "admin", and the permissions to rw-r-----. Other possibilities
+are left as an exercise for the reader.
+
+(NOTE: due to a bug in Snow Leopard, if you change the permissions not
+to grant write permission to everybody who should be allowed to capture
+traffic, non-root users who cannot open the BPF devices for writing will
+not be able to capture outgoing packets.)
diff --git a/lib/libpcap/libpcap/doc/README.septel b/lib/libpcap/libpcap/doc/README.septel
new file mode 100644
index 0000000..fa2c0c9
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.septel
@@ -0,0 +1,50 @@
+The following instructions apply if you have a Linux platform and want
+libpcap to support the Septel range of passive network monitoring cards
+from Intel (http://www.intel.com)
+
+1) Install and build the Septel software distribution by following the
+instructions supplied with that package.
+
+2) Configure libcap. To allow the 'configure' script to locate the Septel
+software distribution use the '--with-septel' option:
+
+ ./configure --with-septel=DIR
+
+where DIR is the root of the Septel software distribution, for example
+/var/src/septel.
+
+By default (if you write only ./configure --with-septel) it takes
+./../septel as argument for DIR.
+
+If the Septel software is correctly detected 'configure' will
+report:
+
+ checking whether we have Septel API... yes
+
+If 'configure' reports that there is no Septel API, the directory may have been
+incorrectly specified or the Septel software was not built before configuring
+libpcap.
+
+See also the libpcap INSTALL.txt file for further libpcap configuration
+options.
+
+Building libpcap at this stage will include support for both the native
+packet capture stream and for capturing from Septel cards. To build
+libpcap with only Septel support specify the capture type as 'septel'
+when configuring libpcap:
+
+ ./configure --with-septel=DIR --with-pcap=septel
+
+Applications built with libpcap configured in this way will only detect Septel
+cards and will not capture from the native OS packet stream.
+
+Note: As mentioned in pcap-septel.c we should first edit the system.txt
+file to change the user part example (UPE) module id to 0xdd instead of
+0x2d for technical reason. So this change in system.txt is crucial and
+things will go wrong if it's not done. System.txt along with config.txt
+are configuration files that are edited by the user before running the
+gctload program that uses these files for initialising modules and
+configuring parameters.
+
+----------------------------------------------------------------------
+for more information please contact me : gil_hoyek@hotmail.com
diff --git a/lib/libpcap/libpcap/doc/README.sita b/lib/libpcap/libpcap/doc/README.sita
new file mode 100644
index 0000000..5a65822
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.sita
@@ -0,0 +1,64 @@
+The following instructions apply if you have a Linux platform and want
+libpcap to support the 'ACN' WAN/LAN router product from SITA
+(http://www.sita.aero)
+
+This might also work on non-Linux Unix-compatible platforms, but that
+has not been tested.
+
+See also the libpcap INSTALL.txt file for further libpcap configuration
+options.
+
+These additions/extensions have been made to PCAP to allow it to
+capture packets from a SITA ACN device (and potentially others).
+
+To enable its support you need to ensure that the distribution has
+a correct configure.ac file; that can be created if neccessay by
+using the normal autoconf procedure of:
+
+aclocal
+autoconf
+autoheader
+automake
+
+Then run configure with the 'sita' option:
+
+./configure --with-sita
+
+Applications built with libpcap configured in this way will only detect SITA
+ACN interfaces and will not capture from the native OS packet stream.
+
+The SITA extension provides a remote datascope operation for capturing
+both WAN and LAN protocols. It effectively splits the operation of
+PCAP into two halves. The top layer performs the majority of the
+work, but interfaces via a TCP session to remote agents that
+provide the lower layer functionality of actual sniffing and
+filtering. More detailed information regarding the functions and
+inter-device protocol and naming conventions are described in detail
+in 'pcap-sita.html'.
+
+pcap_findalldevs() reads the local system's /etc/hosts file looking
+for host names that match the format of IOP type devices. ie. aaa_I_x_y
+and then queries each associated IP address for a list of its WAN and
+LAN devices. The local system the aggregates the lists obtained from
+each IOP, sorts it, and provides it (to Wireshark et.al) as the
+list of monitorable interfaces.
+
+Once a valid interface has been selected, pcap_open() is called
+which opens a TCP session (to a well known port) on the target IOP
+and tells it to start monitoring.
+
+All captured packets are then forwarded across that TCP session
+back to the local 'top layer' for forwarding to the actual
+sniffing program (wireshark...)
+
+Note that the DLT_SITA link-layer type includes a proprietary header
+that is documented as part of the SITA dissector of Wireshark and is
+also described in 'pcap-sita.html' for posterity sake.
+
+That header provides:
+- Packet direction (in/out) (1 octet)
+- Link layer hardware signal status (1 octet)
+- Transmit/Receive error status (2 octets)
+- Encapsulated WAN protocol ID (1 octet)
+
+
diff --git a/lib/libpcap/libpcap/doc/README.tru64 b/lib/libpcap/libpcap/doc/README.tru64
new file mode 100644
index 0000000..2420d9e
--- /dev/null
+++ b/lib/libpcap/libpcap/doc/README.tru64
@@ -0,0 +1,49 @@
+The following instructions are applicable to Tru64 UNIX
+(formerly Digital UNIX (formerly DEC OSF/1)) version 4.0, and
+probably to later versions as well; at least some options apply to
+Digital UNIX 3.2 - perhaps all do.
+
+In order to use kernel packet filtering on this system, you have
+to configure it in such a way:
+
+Kernel configuration
+--------------------
+
+The packet filtering kernel option must be enabled at kernel
+installation. If it was not the case, you can rebuild the kernel with
+"doconfig -c" after adding the following line in the kernel
+configuration file (/sys/conf/<HOSTNAME>):
+
+ option PACKETFILTER
+
+or use "doconfig" without any arguments to add the packet filter driver
+option via the kernel option menu (see the system administration
+documentation for information on how to do this).
+
+Device configuration
+--------------------
+
+Devices used for packet filtering must be created thanks to
+the following command (executed in the /dev directory):
+
+ ./MAKEDEV pfilt
+
+Interface configuration
+-----------------------
+
+In order to capture all packets on a network, you may want to allow
+applications to put the interface on that network into "local copy"
+mode, so that tcpdump can see packets sent by the host on which it's
+running as well as packets received by that host, and to put the
+interface into "promiscuous" mode, so that tcpdump can see packets on
+the network segment not sent to the host on which it's running, by using
+the pfconfig(1) command:
+
+ pfconfig +c +p <network_device>
+
+or allow application to put any interface into "local copy" or
+"promiscuous" mode by using the command:
+
+ pfconfig +c +p -a
+
+Note: all instructions given require root privileges.
diff --git a/lib/libpcap/libpcap/etherent.c b/lib/libpcap/libpcap/etherent.c
new file mode 100644
index 0000000..5f49961
--- /dev/null
+++ b/lib/libpcap/libpcap/etherent.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+
+#include <ctype.h>
+#include <memory.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include <pcap/namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+static inline int skip_space(FILE *);
+static inline int skip_line(FILE *);
+
+/* Hex digit to integer. */
+static inline u_char
+xdtoi(u_char c)
+{
+ if (isdigit(c))
+ return (u_char)(c - '0');
+ else if (islower(c))
+ return (u_char)(c - 'a' + 10);
+ else
+ return (u_char)(c - 'A' + 10);
+}
+
+static inline int
+skip_space(FILE *f)
+{
+ int c;
+
+ do {
+ c = getc(f);
+ } while (isspace(c) && c != '\n');
+
+ return c;
+}
+
+static inline int
+skip_line(FILE *f)
+{
+ int c;
+
+ do
+ c = getc(f);
+ while (c != '\n' && c != EOF);
+
+ return c;
+}
+
+struct pcap_etherent *
+pcap_next_etherent(FILE *fp)
+{
+ register int c, i;
+ u_char d;
+ char *bp;
+ size_t namesize;
+ static struct pcap_etherent e;
+
+ memset((char *)&e, 0, sizeof(e));
+ for (;;) {
+ /* Find addr */
+ c = skip_space(fp);
+ if (c == EOF)
+ return (NULL);
+ if (c == '\n')
+ continue;
+
+ /* If this is a comment, or first thing on line
+ cannot be Ethernet address, skip the line. */
+ if (!isxdigit(c)) {
+ c = skip_line(fp);
+ if (c == EOF)
+ return (NULL);
+ continue;
+ }
+
+ /* must be the start of an address */
+ for (i = 0; i < 6; i += 1) {
+ d = xdtoi((u_char)c);
+ c = getc(fp);
+ if (c == EOF)
+ return (NULL);
+ if (isxdigit(c)) {
+ d <<= 4;
+ d |= xdtoi((u_char)c);
+ c = getc(fp);
+ if (c == EOF)
+ return (NULL);
+ }
+ e.addr[i] = d;
+ if (c != ':')
+ break;
+ c = getc(fp);
+ if (c == EOF)
+ return (NULL);
+ }
+
+ /* Must be whitespace */
+ if (!isspace(c)) {
+ c = skip_line(fp);
+ if (c == EOF)
+ return (NULL);
+ continue;
+ }
+ c = skip_space(fp);
+ if (c == EOF)
+ return (NULL);
+
+ /* hit end of line... */
+ if (c == '\n')
+ continue;
+
+ if (c == '#') {
+ c = skip_line(fp);
+ if (c == EOF)
+ return (NULL);
+ continue;
+ }
+
+ /* pick up name */
+ bp = e.name;
+ /* Use 'namesize' to prevent buffer overflow. */
+ namesize = sizeof(e.name) - 1;
+ do {
+ *bp++ = (u_char)c;
+ c = getc(fp);
+ if (c == EOF)
+ return (NULL);
+ } while (!isspace(c) && --namesize != 0);
+ *bp = '\0';
+
+ /* Eat trailing junk */
+ if (c != '\n')
+ (void)skip_line(fp);
+
+ return &e;
+ }
+}
diff --git a/lib/libpcap/libpcap/ethertype.h b/lib/libpcap/libpcap/ethertype.h
new file mode 100644
index 0000000..51f6308
--- /dev/null
+++ b/lib/libpcap/libpcap/ethertype.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1993, 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Ethernet types.
+ *
+ * We wrap the declarations with #ifdef, so that if a file includes
+ * <netinet/if_ether.h>, which may declare some of these, we don't
+ * get a bunch of complaints from the C compiler about redefinitions
+ * of these values.
+ *
+ * We declare all of them here so that no file has to include
+ * <netinet/if_ether.h> if all it needs are ETHERTYPE_ values.
+ */
+
+#ifndef ETHERTYPE_PUP
+#define ETHERTYPE_PUP 0x0200 /* PUP protocol */
+#endif
+#ifndef ETHERTYPE_IP
+#define ETHERTYPE_IP 0x0800 /* IP protocol */
+#endif
+#ifndef ETHERTYPE_ARP
+#define ETHERTYPE_ARP 0x0806 /* Addr. resolution protocol */
+#endif
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP 0x8035 /* reverse Addr. resolution protocol */
+#endif
+#ifndef ETHERTYPE_NS
+#define ETHERTYPE_NS 0x0600
+#endif
+#ifndef ETHERTYPE_SPRITE
+#define ETHERTYPE_SPRITE 0x0500
+#endif
+#ifndef ETHERTYPE_TRAIL
+#define ETHERTYPE_TRAIL 0x1000
+#endif
+#ifndef ETHERTYPE_MOPDL
+#define ETHERTYPE_MOPDL 0x6001
+#endif
+#ifndef ETHERTYPE_MOPRC
+#define ETHERTYPE_MOPRC 0x6002
+#endif
+#ifndef ETHERTYPE_DN
+#define ETHERTYPE_DN 0x6003
+#endif
+#ifndef ETHERTYPE_LAT
+#define ETHERTYPE_LAT 0x6004
+#endif
+#ifndef ETHERTYPE_SCA
+#define ETHERTYPE_SCA 0x6007
+#endif
+#ifndef ETHERTYPE_REVARP
+#define ETHERTYPE_REVARP 0x8035
+#endif
+#ifndef ETHERTYPE_LANBRIDGE
+#define ETHERTYPE_LANBRIDGE 0x8038
+#endif
+#ifndef ETHERTYPE_DECDNS
+#define ETHERTYPE_DECDNS 0x803c
+#endif
+#ifndef ETHERTYPE_DECDTS
+#define ETHERTYPE_DECDTS 0x803e
+#endif
+#ifndef ETHERTYPE_VEXP
+#define ETHERTYPE_VEXP 0x805b
+#endif
+#ifndef ETHERTYPE_VPROD
+#define ETHERTYPE_VPROD 0x805c
+#endif
+#ifndef ETHERTYPE_ATALK
+#define ETHERTYPE_ATALK 0x809b
+#endif
+#ifndef ETHERTYPE_AARP
+#define ETHERTYPE_AARP 0x80f3
+#endif
+#ifndef ETHERTYPE_8021Q
+#define ETHERTYPE_8021Q 0x8100
+#endif
+#ifndef ETHERTYPE_IPX
+#define ETHERTYPE_IPX 0x8137
+#endif
+#ifndef ETHERTYPE_IPV6
+#define ETHERTYPE_IPV6 0x86dd
+#endif
+#ifndef ETHERTYPE_MPLS
+#define ETHERTYPE_MPLS 0x8847
+#endif
+#ifndef ETHERTYPE_MPLS_MULTI
+#define ETHERTYPE_MPLS_MULTI 0x8848
+#endif
+#ifndef ETHERTYPE_PPPOED
+#define ETHERTYPE_PPPOED 0x8863
+#endif
+#ifndef ETHERTYPE_PPPOES
+#define ETHERTYPE_PPPOES 0x8864
+#endif
+#ifndef ETHERTYPE_8021AD
+#define ETHERTYPE_8021AD 0x88a8
+#endif
+#ifndef ETHERTYPE_LOOPBACK
+#define ETHERTYPE_LOOPBACK 0x9000
+#endif
+#ifndef ETHERTYPE_8021QINQ
+#define ETHERTYPE_8021QINQ 0x9100
+#endif
diff --git a/lib/libpcap/libpcap/extract.h b/lib/libpcap/libpcap/extract.h
new file mode 100644
index 0000000..aa3ff99
--- /dev/null
+++ b/lib/libpcap/libpcap/extract.h
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef _WIN32
+#include <arpa/inet.h>
+#endif
+
+#include <pcap/pcap-inttypes.h>
+#include <pcap/compiler-tests.h>
+
+/*
+ * Macros to extract possibly-unaligned big-endian integral values.
+ */
+#ifdef LBL_ALIGN
+/*
+ * The processor doesn't natively handle unaligned loads.
+ */
+#if PCAP_IS_AT_LEAST_GNUC_VERSION(2,0) && \
+ (defined(__alpha) || defined(__alpha__) || \
+ defined(__mips) || defined(__mips__))
+/*
+ * This is MIPS or Alpha, which don't natively handle unaligned loads,
+ * but which have instructions that can help when doing unaligned
+ * loads, and this is GCC 2.0 or later or a compiler that claims to
+ * be GCC 2.0 or later, which we assume that mean we have
+ * __attribute__((packed)), which we can use to convince the compiler
+ * to generate those instructions.
+ *
+ * Declare packed structures containing a uint16_t and a uint32_t,
+ * cast the pointer to point to one of those, and fetch through it;
+ * the GCC manual doesn't appear to explicitly say that
+ * __attribute__((packed)) causes the compiler to generate unaligned-safe
+ * code, but it apppears to do so.
+ *
+ * We do this in case the compiler can generate code using those
+ * instructions to do an unaligned load and pass stuff to "ntohs()" or
+ * "ntohl()", which might be better than than the code to fetch the
+ * bytes one at a time and assemble them. (That might not be the
+ * case on a little-endian platform, such as DEC's MIPS machines and
+ * Alpha machines, where "ntohs()" and "ntohl()" might not be done
+ * inline.)
+ *
+ * We do this only for specific architectures because, for example,
+ * at least some versions of GCC, when compiling for 64-bit SPARC,
+ * generate code that assumes alignment if we do this.
+ *
+ * XXX - add other architectures and compilers as possible and
+ * appropriate.
+ *
+ * HP's C compiler, indicated by __HP_cc being defined, supports
+ * "#pragma unaligned N" in version A.05.50 and later, where "N"
+ * specifies a number of bytes at which the typedef on the next
+ * line is aligned, e.g.
+ *
+ * #pragma unalign 1
+ * typedef uint16_t unaligned_uint16_t;
+ *
+ * to define unaligned_uint16_t as a 16-bit unaligned data type.
+ * This could be presumably used, in sufficiently recent versions of
+ * the compiler, with macros similar to those below. This would be
+ * useful only if that compiler could generate better code for PA-RISC
+ * or Itanium than would be generated by a bunch of shifts-and-ORs.
+ *
+ * DEC C, indicated by __DECC being defined, has, at least on Alpha,
+ * an __unaligned qualifier that can be applied to pointers to get the
+ * compiler to generate code that does unaligned loads and stores when
+ * dereferencing the pointer in question.
+ *
+ * XXX - what if the native C compiler doesn't support
+ * __attribute__((packed))? How can we get it to generate unaligned
+ * accesses for *specific* items?
+ */
+typedef struct {
+ uint16_t val;
+} __attribute__((packed)) unaligned_uint16_t;
+
+typedef struct {
+ uint32_t val;
+} __attribute__((packed)) unaligned_uint32_t;
+
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+ return ((uint16_t)ntohs(((const unaligned_uint16_t *)(p))->val));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+ return ((uint32_t)ntohl(((const unaligned_uint32_t *)(p))->val));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+ return ((uint64_t)(((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 0)->val)) << 32 | \
+ ((uint64_t)ntohl(((const unaligned_uint32_t *)(p) + 1)->val)) << 0));
+}
+
+#else /* have to do it a byte at a time */
+/*
+ * This isn't a GCC-compatible compiler, we don't have __attribute__,
+ * or we do but we don't know of any better way with this instruction
+ * set to do unaligned loads, so do unaligned loads of big-endian
+ * quantities the hard way - fetch the bytes one at a time and
+ * assemble them.
+ */
+#define EXTRACT_16BITS(p) \
+ ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 0)) << 8) | \
+ ((uint16_t)(*((const uint8_t *)(p) + 1)) << 0)))
+#define EXTRACT_32BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 24) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 2)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 3)) << 0)))
+#define EXTRACT_64BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 56) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 48) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 6)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 7)) << 0)))
+#endif /* must special-case unaligned accesses */
+#else /* LBL_ALIGN */
+/*
+ * The processor natively handles unaligned loads, so we can just
+ * cast the pointer and fetch through it.
+ */
+static inline uint16_t
+EXTRACT_16BITS(const void *p)
+{
+ return ((uint16_t)ntohs(*(const uint16_t *)(p)));
+}
+
+static inline uint32_t
+EXTRACT_32BITS(const void *p)
+{
+ return ((uint32_t)ntohl(*(const uint32_t *)(p)));
+}
+
+static inline uint64_t
+EXTRACT_64BITS(const void *p)
+{
+ return ((uint64_t)(((uint64_t)ntohl(*((const uint32_t *)(p) + 0))) << 32 | \
+ ((uint64_t)ntohl(*((const uint32_t *)(p) + 1))) << 0));
+
+}
+
+#endif /* LBL_ALIGN */
+
+#define EXTRACT_24BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 0)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 2)) << 0)))
+
+#define EXTRACT_40BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 0)))
+
+#define EXTRACT_48BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 0)))
+
+#define EXTRACT_56BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 0)) << 48) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 6)) << 0)))
+
+/*
+ * Macros to extract possibly-unaligned little-endian integral values.
+ * XXX - do loads on little-endian machines that support unaligned loads?
+ */
+#define EXTRACT_LE_8BITS(p) (*(p))
+#define EXTRACT_LE_16BITS(p) \
+ ((uint16_t)(((uint16_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint16_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_32BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_24BITS(p) \
+ ((uint32_t)(((uint32_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint32_t)(*((const uint8_t *)(p) + 0)) << 0)))
+#define EXTRACT_LE_64BITS(p) \
+ ((uint64_t)(((uint64_t)(*((const uint8_t *)(p) + 7)) << 56) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 6)) << 48) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 5)) << 40) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 4)) << 32) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 3)) << 24) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 2)) << 16) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 1)) << 8) | \
+ ((uint64_t)(*((const uint8_t *)(p) + 0)) << 0)))
diff --git a/lib/libpcap/libpcap/fad-getad.c b/lib/libpcap/libpcap/fad-getad.c
new file mode 100644
index 0000000..5236fbb
--- /dev/null
+++ b/lib/libpcap/libpcap/fad-getad.c
@@ -0,0 +1,280 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include <net/if.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ifaddrs.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * We don't do this on Solaris 11 and later, as it appears there aren't
+ * any AF_PACKET addresses on interfaces, so we don't need this, and
+ * we end up including both the OS's <net/bpf.h> and our <pcap/bpf.h>,
+ * and their definitions of some data structures collide.
+ */
+#if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
+# ifdef HAVE_NETPACKET_PACKET_H
+/* Linux distributions with newer glibc */
+# include <netpacket/packet.h>
+# else /* HAVE_NETPACKET_PACKET_H */
+/* LynxOS, Linux distributions with older glibc */
+# ifdef __Lynx__
+/* LynxOS */
+# include <netpacket/if_packet.h>
+# else /* __Lynx__ */
+/* Linux */
+# include <linux/types.h>
+# include <linux/if_packet.h>
+# endif /* __Lynx__ */
+# endif /* HAVE_NETPACKET_PACKET_H */
+#endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */
+
+/*
+ * This is fun.
+ *
+ * In older BSD systems, socket addresses were fixed-length, and
+ * "sizeof (struct sockaddr)" gave the size of the structure.
+ * All addresses fit within a "struct sockaddr".
+ *
+ * In newer BSD systems, the socket address is variable-length, and
+ * there's an "sa_len" field giving the length of the structure;
+ * this allows socket addresses to be longer than 2 bytes of family
+ * and 14 bytes of data.
+ *
+ * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
+ * variant of the old BSD scheme (with "struct sockaddr_storage" rather
+ * than "struct sockaddr"), and some use the new BSD scheme.
+ *
+ * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
+ * macro that determines the size based on the address family. Other
+ * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
+ * but not in the final version). On the latter systems, we explicitly
+ * check the AF_ type to determine the length; we assume that on
+ * all those systems we have "struct sockaddr_storage".
+ */
+#ifndef SA_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+#define SA_LEN(addr) ((addr)->sa_len)
+#else /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+#ifdef HAVE_STRUCT_SOCKADDR_STORAGE
+static size_t
+get_sa_len(struct sockaddr *addr)
+{
+ switch (addr->sa_family) {
+
+#ifdef AF_INET
+ case AF_INET:
+ return (sizeof (struct sockaddr_in));
+#endif
+
+#ifdef AF_INET6
+ case AF_INET6:
+ return (sizeof (struct sockaddr_in6));
+#endif
+
+#if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
+ case AF_PACKET:
+ return (sizeof (struct sockaddr_ll));
+#endif
+
+ default:
+ return (sizeof (struct sockaddr));
+ }
+}
+#define SA_LEN(addr) (get_sa_len(addr))
+#else /* HAVE_STRUCT_SOCKADDR_STORAGE */
+#define SA_LEN(addr) (sizeof (struct sockaddr))
+#endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+#endif /* SA_LEN */
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * could be opened.
+ */
+int
+pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
+ int (*check_usable)(const char *), get_if_flags_func get_flags_func)
+{
+ struct ifaddrs *ifap, *ifa;
+ struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
+ size_t addr_size, broadaddr_size, dstaddr_size;
+ int ret = 0;
+ char *p, *q;
+
+ /*
+ * Get the list of interface addresses.
+ *
+ * Note: this won't return information about interfaces
+ * with no addresses, so, if a platform has interfaces
+ * with no interfaces on which traffic can be captured,
+ * we must check for those interfaces as well (see, for
+ * example, what's done on Linux).
+ *
+ * LAN interfaces will probably have link-layer
+ * addresses; I don't know whether all implementations
+ * of "getifaddrs()" now, or in the future, will return
+ * those.
+ */
+ if (getifaddrs(&ifap) != 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "getifaddrs");
+ return (-1);
+ }
+ for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
+ /*
+ * If this entry has a colon followed by a number at
+ * the end, we assume it's a logical interface. Those
+ * are just the way you assign multiple IP addresses to
+ * a real interface on Linux, so an entry for a logical
+ * interface should be treated like the entry for the
+ * real interface; we do that by stripping off the ":"
+ * and the number.
+ *
+ * XXX - should we do this only on Linux?
+ */
+ p = strchr(ifa->ifa_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ q = p + 1;
+ while (isdigit((unsigned char)*q))
+ q++;
+ if (*q == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ * Strip off the ":" and everything after
+ * it.
+ */
+ *p = '\0';
+ }
+ }
+
+ /*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifa->ifa_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
+ /*
+ * "ifa_addr" was apparently null on at least one
+ * interface on some system. Therefore, we supply
+ * the address and netmask only if "ifa_addr" is
+ * non-null (if there's no address, there's obviously
+ * no netmask).
+ */
+ if (ifa->ifa_addr != NULL) {
+ addr = ifa->ifa_addr;
+ addr_size = SA_LEN(addr);
+ netmask = ifa->ifa_netmask;
+ } else {
+ addr = NULL;
+ addr_size = 0;
+ netmask = NULL;
+ }
+
+ /*
+ * Note that, on some platforms, ifa_broadaddr and
+ * ifa_dstaddr could be the same field (true on at
+ * least some versions of *BSD and macOS), so we
+ * can't just check whether the broadcast address
+ * is null and add it if so and check whether the
+ * destination address is null and add it if so.
+ *
+ * Therefore, we must also check the IFF_BROADCAST
+ * flag, and only add a broadcast address if it's
+ * set, and check the IFF_POINTTOPOINT flag, and
+ * only add a destination address if it's set (as
+ * per man page recommendations on some of those
+ * platforms).
+ */
+ if (ifa->ifa_flags & IFF_BROADCAST &&
+ ifa->ifa_broadaddr != NULL) {
+ broadaddr = ifa->ifa_broadaddr;
+ broadaddr_size = SA_LEN(broadaddr);
+ } else {
+ broadaddr = NULL;
+ broadaddr_size = 0;
+ }
+ if (ifa->ifa_flags & IFF_POINTOPOINT &&
+ ifa->ifa_dstaddr != NULL) {
+ dstaddr = ifa->ifa_dstaddr;
+ dstaddr_size = SA_LEN(ifa->ifa_dstaddr);
+ } else {
+ dstaddr = NULL;
+ dstaddr_size = 0;
+ }
+
+ /*
+ * Add information for this address to the list.
+ */
+ if (add_addr_to_if(devlistp, ifa->ifa_name, ifa->ifa_flags,
+ get_flags_func,
+ addr, addr_size, netmask, addr_size,
+ broadaddr, broadaddr_size, dstaddr, dstaddr_size,
+ errbuf) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+
+ freeifaddrs(ifap);
+
+ return (ret);
+}
diff --git a/lib/libpcap/libpcap/fad-gifc.c b/lib/libpcap/libpcap/fad-gifc.c
new file mode 100644
index 0000000..6b16127
--- /dev/null
+++ b/lib/libpcap/libpcap/fad-gifc.c
@@ -0,0 +1,431 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <sys/time.h> /* concession to AIX */
+
+struct mbuf; /* Squelch compiler warnings on some platforms for */
+struct rtentry; /* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * This is fun.
+ *
+ * In older BSD systems, socket addresses were fixed-length, and
+ * "sizeof (struct sockaddr)" gave the size of the structure.
+ * All addresses fit within a "struct sockaddr".
+ *
+ * In newer BSD systems, the socket address is variable-length, and
+ * there's an "sa_len" field giving the length of the structure;
+ * this allows socket addresses to be longer than 2 bytes of family
+ * and 14 bytes of data.
+ *
+ * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
+ * variant of the old BSD scheme (with "struct sockaddr_storage" rather
+ * than "struct sockaddr"), and some use the new BSD scheme.
+ *
+ * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
+ * macro that determines the size based on the address family. Other
+ * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
+ * but not in the final version).
+ *
+ * We assume that a UNIX that doesn't have "getifaddrs()" and doesn't have
+ * SIOCGLIFCONF, but has SIOCGIFCONF, uses "struct sockaddr" for the
+ * address in an entry returned by SIOCGIFCONF.
+ */
+#ifndef SA_LEN
+#ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
+#define SA_LEN(addr) ((addr)->sa_len)
+#else /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+#define SA_LEN(addr) (sizeof (struct sockaddr))
+#endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
+#endif /* SA_LEN */
+
+/*
+ * This is also fun.
+ *
+ * There is no ioctl that returns the amount of space required for all
+ * the data that SIOCGIFCONF could return, and if a buffer is supplied
+ * that's not large enough for all the data SIOCGIFCONF could return,
+ * on at least some platforms it just returns the data that'd fit with
+ * no indication that there wasn't enough room for all the data, much
+ * less an indication of how much more room is required.
+ *
+ * The only way to ensure that we got all the data is to pass a buffer
+ * large enough that the amount of space in the buffer *not* filled in
+ * is greater than the largest possible entry.
+ *
+ * We assume that's "sizeof(ifreq.ifr_name)" plus 255, under the assumption
+ * that no address is more than 255 bytes (on systems where the "sa_len"
+ * field in a "struct sockaddr" is 1 byte, e.g. newer BSDs, that's the
+ * case, and addresses are unlikely to be bigger than that in any case).
+ */
+#define MAX_SA_LEN 255
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * This is the implementation used on platforms that have SIOCGIFCONF but
+ * don't have any other mechanism for getting a list of interfaces.
+ *
+ * XXX - or platforms that have other, better mechanisms but for which
+ * we don't yet have code to use that mechanism; I think there's a better
+ * way on Linux, for example, but if that better way is "getifaddrs()",
+ * we already have that.
+ */
+int
+pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
+ int (*check_usable)(const char *), get_if_flags_func get_flags_func)
+{
+ register int fd;
+ register struct ifreq *ifrp, *ifend, *ifnext;
+ size_t n;
+ struct ifconf ifc;
+ char *buf = NULL;
+ unsigned buf_size;
+#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
+ char *p, *q;
+#endif
+ struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
+ struct sockaddr *netmask, *broadaddr, *dstaddr;
+ size_t netmask_size, broadaddr_size, dstaddr_size;
+ int ret = 0;
+
+ /*
+ * Create a socket from which to fetch the list of interfaces.
+ */
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ return (-1);
+ }
+
+ /*
+ * Start with an 8K buffer, and keep growing the buffer until
+ * we have more than "sizeof(ifrp->ifr_name) + MAX_SA_LEN"
+ * bytes left over in the buffer or we fail to get the
+ * interface list for some reason other than EINVAL (which is
+ * presumed here to mean "buffer is too small").
+ */
+ buf_size = 8192;
+ for (;;) {
+ /*
+ * Don't let the buffer size get bigger than INT_MAX.
+ */
+ if (buf_size > INT_MAX) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "interface information requires more than %u bytes",
+ INT_MAX);
+ (void)close(fd);
+ return (-1);
+ }
+ buf = malloc(buf_size);
+ if (buf == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ (void)close(fd);
+ return (-1);
+ }
+
+ ifc.ifc_len = buf_size;
+ ifc.ifc_buf = buf;
+ memset(buf, 0, buf_size);
+ if (ioctl(fd, SIOCGIFCONF, (char *)&ifc) < 0
+ && errno != EINVAL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFCONF");
+ (void)close(fd);
+ free(buf);
+ return (-1);
+ }
+ if (ifc.ifc_len < (int)buf_size &&
+ (buf_size - ifc.ifc_len) > sizeof(ifrp->ifr_name) + MAX_SA_LEN)
+ break;
+ free(buf);
+ buf_size *= 2;
+ }
+
+ ifrp = (struct ifreq *)buf;
+ ifend = (struct ifreq *)(buf + ifc.ifc_len);
+
+ for (; ifrp < ifend; ifrp = ifnext) {
+ /*
+ * XXX - what if this isn't an IPv4 address? Can
+ * we still get the netmask, etc. with ioctls on
+ * an IPv4 socket?
+ *
+ * The answer is probably platform-dependent, and
+ * if the answer is "no" on more than one platform,
+ * the way you work around it is probably platform-
+ * dependent as well.
+ */
+ n = SA_LEN(&ifrp->ifr_addr) + sizeof(ifrp->ifr_name);
+ if (n < sizeof(*ifrp))
+ ifnext = ifrp + 1;
+ else
+ ifnext = (struct ifreq *)((char *)ifrp + n);
+
+ /*
+ * XXX - The 32-bit compatibility layer for Linux on IA-64
+ * is slightly broken. It correctly converts the structures
+ * to and from kernel land from 64 bit to 32 bit but
+ * doesn't update ifc.ifc_len, leaving it larger than the
+ * amount really used. This means we read off the end
+ * of the buffer and encounter an interface with an
+ * "empty" name. Since this is highly unlikely to ever
+ * occur in a valid case we can just finish looking for
+ * interfaces if we see an empty name.
+ */
+ if (!(*ifrp->ifr_name))
+ break;
+
+ /*
+ * Skip entries that begin with "dummy".
+ * XXX - what are these? Is this Linux-specific?
+ * Are there platforms on which we shouldn't do this?
+ */
+ if (strncmp(ifrp->ifr_name, "dummy", 5) == 0)
+ continue;
+
+ /*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifrp->ifr_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
+ /*
+ * Get the flags for this interface.
+ */
+ strncpy(ifrflags.ifr_name, ifrp->ifr_name,
+ sizeof(ifrflags.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
+ if (errno == ENXIO)
+ continue;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFFLAGS: %.*s",
+ (int)sizeof(ifrflags.ifr_name),
+ ifrflags.ifr_name);
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Get the netmask for this address on this interface.
+ */
+ strncpy(ifrnetmask.ifr_name, ifrp->ifr_name,
+ sizeof(ifrnetmask.ifr_name));
+ memcpy(&ifrnetmask.ifr_addr, &ifrp->ifr_addr,
+ sizeof(ifrnetmask.ifr_addr));
+ if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifrnetmask) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+ /*
+ * Not available.
+ */
+ netmask = NULL;
+ netmask_size = 0;
+ } else {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFNETMASK: %.*s",
+ (int)sizeof(ifrnetmask.ifr_name),
+ ifrnetmask.ifr_name);
+ ret = -1;
+ break;
+ }
+ } else {
+ netmask = &ifrnetmask.ifr_addr;
+ netmask_size = SA_LEN(netmask);
+ }
+
+ /*
+ * Get the broadcast address for this address on this
+ * interface (if any).
+ */
+ if (ifrflags.ifr_flags & IFF_BROADCAST) {
+ strncpy(ifrbroadaddr.ifr_name, ifrp->ifr_name,
+ sizeof(ifrbroadaddr.ifr_name));
+ memcpy(&ifrbroadaddr.ifr_addr, &ifrp->ifr_addr,
+ sizeof(ifrbroadaddr.ifr_addr));
+ if (ioctl(fd, SIOCGIFBRDADDR,
+ (char *)&ifrbroadaddr) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+ /*
+ * Not available.
+ */
+ broadaddr = NULL;
+ broadaddr_size = 0;
+ } else {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFBRDADDR: %.*s",
+ (int)sizeof(ifrbroadaddr.ifr_name),
+ ifrbroadaddr.ifr_name);
+ ret = -1;
+ break;
+ }
+ } else {
+ broadaddr = &ifrbroadaddr.ifr_broadaddr;
+ broadaddr_size = SA_LEN(broadaddr);
+ }
+ } else {
+ /*
+ * Not a broadcast interface, so no broadcast
+ * address.
+ */
+ broadaddr = NULL;
+ broadaddr_size = 0;
+ }
+
+ /*
+ * Get the destination address for this address on this
+ * interface (if any).
+ */
+ if (ifrflags.ifr_flags & IFF_POINTOPOINT) {
+ strncpy(ifrdstaddr.ifr_name, ifrp->ifr_name,
+ sizeof(ifrdstaddr.ifr_name));
+ memcpy(&ifrdstaddr.ifr_addr, &ifrp->ifr_addr,
+ sizeof(ifrdstaddr.ifr_addr));
+ if (ioctl(fd, SIOCGIFDSTADDR,
+ (char *)&ifrdstaddr) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+ /*
+ * Not available.
+ */
+ dstaddr = NULL;
+ dstaddr_size = 0;
+ } else {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFDSTADDR: %.*s",
+ (int)sizeof(ifrdstaddr.ifr_name),
+ ifrdstaddr.ifr_name);
+ ret = -1;
+ break;
+ }
+ } else {
+ dstaddr = &ifrdstaddr.ifr_dstaddr;
+ dstaddr_size = SA_LEN(dstaddr);
+ }
+ } else {
+ /*
+ * Not a point-to-point interface, so no destination
+ * address.
+ */
+ dstaddr = NULL;
+ dstaddr_size = 0;
+ }
+
+#if defined (HAVE_SOLARIS) || defined (HAVE_HPUX10_20_OR_LATER)
+ /*
+ * If this entry has a colon followed by a number at
+ * the end, it's a logical interface. Those are just
+ * the way you assign multiple IP addresses to a real
+ * interface, so an entry for a logical interface should
+ * be treated like the entry for the real interface;
+ * we do that by stripping off the ":" and the number.
+ */
+ p = strchr(ifrp->ifr_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ q = p + 1;
+ while (isdigit((unsigned char)*q))
+ q++;
+ if (*q == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ * Strip off the ":" and everything after
+ * it.
+ */
+ *p = '\0';
+ }
+ }
+#endif
+
+ /*
+ * Add information for this address to the list.
+ */
+ if (add_addr_to_if(devlistp, ifrp->ifr_name,
+ ifrflags.ifr_flags, get_flags_func,
+ &ifrp->ifr_addr, SA_LEN(&ifrp->ifr_addr),
+ netmask, netmask_size, broadaddr, broadaddr_size,
+ dstaddr, dstaddr_size, errbuf) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+ free(buf);
+ (void)close(fd);
+
+ return (ret);
+}
diff --git a/lib/libpcap/libpcap/fad-glifc.c b/lib/libpcap/libpcap/fad-glifc.c
new file mode 100644
index 0000000..f22f56d
--- /dev/null
+++ b/lib/libpcap/libpcap/fad-glifc.c
@@ -0,0 +1,346 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#include <sys/time.h> /* concession to AIX */
+
+struct mbuf; /* Squelch compiler warnings on some platforms for */
+struct rtentry; /* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * Get a list of all interfaces that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ *
+ * This is the implementation used on platforms that have SIOCGLIFCONF
+ * but don't have "getifaddrs()". (Solaris 8 and later; we use
+ * SIOCGLIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.)
+ */
+int
+pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
+ int (*check_usable)(const char *), get_if_flags_func get_flags_func)
+{
+ register int fd4, fd6, fd;
+ register struct lifreq *ifrp, *ifend;
+ struct lifnum ifn;
+ struct lifconf ifc;
+ char *buf = NULL;
+ unsigned buf_size;
+#ifdef HAVE_SOLARIS
+ char *p, *q;
+#endif
+ struct lifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr;
+ struct sockaddr *netmask, *broadaddr, *dstaddr;
+ int ret = 0;
+
+ /*
+ * Create a socket from which to fetch the list of interfaces,
+ * and from which to fetch IPv4 information.
+ */
+ fd4 = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd4 < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket: AF_INET");
+ return (-1);
+ }
+
+ /*
+ * Create a socket from which to fetch IPv6 information.
+ */
+ fd6 = socket(AF_INET6, SOCK_DGRAM, 0);
+ if (fd6 < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket: AF_INET6");
+ (void)close(fd4);
+ return (-1);
+ }
+
+ /*
+ * How many entries will SIOCGLIFCONF return?
+ */
+ ifn.lifn_family = AF_UNSPEC;
+ ifn.lifn_flags = 0;
+ ifn.lifn_count = 0;
+ if (ioctl(fd4, SIOCGLIFNUM, (char *)&ifn) < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGLIFNUM");
+ (void)close(fd6);
+ (void)close(fd4);
+ return (-1);
+ }
+
+ /*
+ * Allocate a buffer for those entries.
+ */
+ buf_size = ifn.lifn_count * sizeof (struct lifreq);
+ buf = malloc(buf_size);
+ if (buf == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ (void)close(fd6);
+ (void)close(fd4);
+ return (-1);
+ }
+
+ /*
+ * Get the entries.
+ */
+ ifc.lifc_len = buf_size;
+ ifc.lifc_buf = buf;
+ ifc.lifc_family = AF_UNSPEC;
+ ifc.lifc_flags = 0;
+ memset(buf, 0, buf_size);
+ if (ioctl(fd4, SIOCGLIFCONF, (char *)&ifc) < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGLIFCONF");
+ (void)close(fd6);
+ (void)close(fd4);
+ free(buf);
+ return (-1);
+ }
+
+ /*
+ * Loop over the entries.
+ */
+ ifrp = (struct lifreq *)buf;
+ ifend = (struct lifreq *)(buf + ifc.lifc_len);
+
+ for (; ifrp < ifend; ifrp++) {
+ /*
+ * Skip entries that begin with "dummy".
+ * XXX - what are these? Is this Linux-specific?
+ * Are there platforms on which we shouldn't do this?
+ */
+ if (strncmp(ifrp->lifr_name, "dummy", 5) == 0)
+ continue;
+
+ /*
+ * Can we capture on this device?
+ */
+ if (!(*check_usable)(ifrp->lifr_name)) {
+ /*
+ * No.
+ */
+ continue;
+ }
+
+ /*
+ * IPv6 or not?
+ */
+ if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6)
+ fd = fd6;
+ else
+ fd = fd4;
+
+ /*
+ * Get the flags for this interface.
+ */
+ strncpy(ifrflags.lifr_name, ifrp->lifr_name,
+ sizeof(ifrflags.lifr_name));
+ if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) {
+ if (errno == ENXIO)
+ continue;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGLIFFLAGS: %.*s",
+ (int)sizeof(ifrflags.lifr_name),
+ ifrflags.lifr_name);
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Get the netmask for this address on this interface.
+ */
+ strncpy(ifrnetmask.lifr_name, ifrp->lifr_name,
+ sizeof(ifrnetmask.lifr_name));
+ memcpy(&ifrnetmask.lifr_addr, &ifrp->lifr_addr,
+ sizeof(ifrnetmask.lifr_addr));
+ if (ioctl(fd, SIOCGLIFNETMASK, (char *)&ifrnetmask) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+ /*
+ * Not available.
+ */
+ netmask = NULL;
+ } else {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGLIFNETMASK: %.*s",
+ (int)sizeof(ifrnetmask.lifr_name),
+ ifrnetmask.lifr_name);
+ ret = -1;
+ break;
+ }
+ } else
+ netmask = (struct sockaddr *)&ifrnetmask.lifr_addr;
+
+ /*
+ * Get the broadcast address for this address on this
+ * interface (if any).
+ */
+ if (ifrflags.lifr_flags & IFF_BROADCAST) {
+ strncpy(ifrbroadaddr.lifr_name, ifrp->lifr_name,
+ sizeof(ifrbroadaddr.lifr_name));
+ memcpy(&ifrbroadaddr.lifr_addr, &ifrp->lifr_addr,
+ sizeof(ifrbroadaddr.lifr_addr));
+ if (ioctl(fd, SIOCGLIFBRDADDR,
+ (char *)&ifrbroadaddr) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+ /*
+ * Not available.
+ */
+ broadaddr = NULL;
+ } else {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGLIFBRDADDR: %.*s",
+ (int)sizeof(ifrbroadaddr.lifr_name),
+ ifrbroadaddr.lifr_name);
+ ret = -1;
+ break;
+ }
+ } else
+ broadaddr = (struct sockaddr *)&ifrbroadaddr.lifr_broadaddr;
+ } else {
+ /*
+ * Not a broadcast interface, so no broadcast
+ * address.
+ */
+ broadaddr = NULL;
+ }
+
+ /*
+ * Get the destination address for this address on this
+ * interface (if any).
+ */
+ if (ifrflags.lifr_flags & IFF_POINTOPOINT) {
+ strncpy(ifrdstaddr.lifr_name, ifrp->lifr_name,
+ sizeof(ifrdstaddr.lifr_name));
+ memcpy(&ifrdstaddr.lifr_addr, &ifrp->lifr_addr,
+ sizeof(ifrdstaddr.lifr_addr));
+ if (ioctl(fd, SIOCGLIFDSTADDR,
+ (char *)&ifrdstaddr) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+ /*
+ * Not available.
+ */
+ dstaddr = NULL;
+ } else {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGLIFDSTADDR: %.*s",
+ (int)sizeof(ifrdstaddr.lifr_name),
+ ifrdstaddr.lifr_name);
+ ret = -1;
+ break;
+ }
+ } else
+ dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr;
+ } else
+ dstaddr = NULL;
+
+#ifdef HAVE_SOLARIS
+ /*
+ * If this entry has a colon followed by a number at
+ * the end, it's a logical interface. Those are just
+ * the way you assign multiple IP addresses to a real
+ * interface, so an entry for a logical interface should
+ * be treated like the entry for the real interface;
+ * we do that by stripping off the ":" and the number.
+ */
+ p = strchr(ifrp->lifr_name, ':');
+ if (p != NULL) {
+ /*
+ * We have a ":"; is it followed by a number?
+ */
+ q = p + 1;
+ while (isdigit((unsigned char)*q))
+ q++;
+ if (*q == '\0') {
+ /*
+ * All digits after the ":" until the end.
+ * Strip off the ":" and everything after
+ * it.
+ */
+ *p = '\0';
+ }
+ }
+#endif
+
+ /*
+ * Add information for this address to the list.
+ */
+ if (add_addr_to_if(devlistp, ifrp->lifr_name,
+ ifrflags.lifr_flags, get_flags_func,
+ (struct sockaddr *)&ifrp->lifr_addr,
+ sizeof (struct sockaddr_storage),
+ netmask, sizeof (struct sockaddr_storage),
+ broadaddr, sizeof (struct sockaddr_storage),
+ dstaddr, sizeof (struct sockaddr_storage), errbuf) < 0) {
+ ret = -1;
+ break;
+ }
+ }
+ free(buf);
+ (void)close(fd6);
+ (void)close(fd4);
+
+ return (ret);
+}
diff --git a/lib/libpcap/libpcap/fmtutils.c b/lib/libpcap/libpcap/fmtutils.c
new file mode 100644
index 0000000..091e0d3
--- /dev/null
+++ b/lib/libpcap/libpcap/fmtutils.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Utilities for message formatting used both by libpcap and rpcapd.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <pcap/pcap.h>
+
+#include "portability.h"
+
+#include "fmtutils.h"
+
+/*
+ * Generate an error message based on a format, arguments, and an
+ * errno, with a message for the errno after the formatted output.
+ */
+void
+pcap_fmt_errmsg_for_errno(char *errbuf, size_t errbuflen, int errnum,
+ const char *fmt, ...)
+{
+ va_list ap;
+ size_t msglen;
+ char *p;
+ size_t errbuflen_remaining;
+
+ va_start(ap, fmt);
+ pcap_vsnprintf(errbuf, errbuflen, fmt, ap);
+ va_end(ap);
+ msglen = strlen(errbuf);
+
+ /*
+ * Do we have enough space to append ": "?
+ * Including the terminating '\0', that's 3 bytes.
+ */
+ if (msglen + 3 > errbuflen) {
+ /* No - just give them what we've produced. */
+ return;
+ }
+ p = errbuf + msglen;
+ errbuflen_remaining = errbuflen - msglen;
+ *p++ = ':';
+ *p++ = ' ';
+ *p = '\0';
+ msglen += 2;
+ errbuflen_remaining -= 2;
+
+ /*
+ * Now append the string for the error code.
+ */
+#if defined(HAVE_STRERROR_S)
+ /*
+ * We have a Windows-style strerror_s().
+ */
+ errno_t err = strerror_s(p, errbuflen_remaining, errnum);
+ if (err != 0) {
+ /*
+ * It doesn't appear to be documented anywhere obvious
+ * what the error returns from strerror_s().
+ */
+ pcap_snprintf(p, errbuflen_remaining, "Error %d", errnum);
+ }
+#elif defined(HAVE_GNU_STRERROR_R)
+ /*
+ * We have a GNU-style strerror_r(), which is *not* guaranteed to
+ * do anything to the buffer handed to it, and which returns a
+ * pointer to the error string, which may or may not be in
+ * the buffer.
+ *
+ * It is, however, guaranteed to succeed.
+ */
+ char strerror_buf[PCAP_ERRBUF_SIZE];
+ char *errstring = strerror_r(errnum, strerror_buf, PCAP_ERRBUF_SIZE);
+ pcap_snprintf(p, errbuflen_remaining, "%s", errstring);
+#elif defined(HAVE_POSIX_STRERROR_R)
+ /*
+ * We have a POSIX-style strerror_r(), which is guaranteed to fill
+ * in the buffer, but is not guaranteed to succeed.
+ */
+ int err = strerror_r(errnum, p, errbuflen_remaining);
+ if (err == EINVAL) {
+ /*
+ * UNIX 03 says this isn't guaranteed to produce a
+ * fallback error message.
+ */
+ pcap_snprintf(p, errbuflen_remaining, "Unknown error: %d",
+ errnum);
+ } else if (err == ERANGE) {
+ /*
+ * UNIX 03 says this isn't guaranteed to produce a
+ * fallback error message.
+ */
+ pcap_snprintf(p, errbuflen_remaining,
+ "Message for error %d is too long", errnum);
+ }
+#else
+ /*
+ * We have neither strerror_s() nor strerror_r(), so we're
+ * stuck with using pcap_strerror().
+ */
+ pcap_snprintf(p, errbuflen_remaining, "%s", pcap_strerror(errnum));
+#endif
+}
+
+#ifdef _WIN32
+/*
+ * Generate an error message based on a format, arguments, and a
+ * Win32 error, with a message for the Win32 error after the formatted output.
+ */
+void
+pcap_fmt_errmsg_for_win32_err(char *errbuf, size_t errbuflen, DWORD errnum,
+ const char *fmt, ...)
+{
+ va_list ap;
+ size_t msglen;
+ char *p;
+ size_t errbuflen_remaining;
+ DWORD retval;
+ char win32_errbuf[PCAP_ERRBUF_SIZE+1];
+
+ va_start(ap, fmt);
+ pcap_vsnprintf(errbuf, errbuflen, fmt, ap);
+ va_end(ap);
+ msglen = strlen(errbuf);
+
+ /*
+ * Do we have enough space to append ": "?
+ * Including the terminating '\0', that's 3 bytes.
+ */
+ if (msglen + 3 > errbuflen) {
+ /* No - just give them what we've produced. */
+ return;
+ }
+ p = errbuf + msglen;
+ errbuflen_remaining = errbuflen - msglen;
+ *p++ = ':';
+ *p++ = ' ';
+ *p = '\0';
+ msglen += 2;
+ errbuflen_remaining -= 2;
+
+ /*
+ * Now append the string for the error code.
+ *
+ * XXX - what language ID to use?
+ *
+ * For UN*Xes, pcap_strerror() may or may not return localized
+ * strings.
+ *
+ * We currently don't have localized messages for libpcap, but
+ * we might want to do so. On the other hand, if most of these
+ * messages are going to be read by libpcap developers and
+ * perhaps by developers of libpcap-based applications, English
+ * might be a better choice, so the developer doesn't have to
+ * get the message translated if it's in a language they don't
+ * happen to understand.
+ */
+ retval = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, errnum, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ win32_errbuf, PCAP_ERRBUF_SIZE, NULL);
+ if (retval == 0) {
+ /*
+ * Failed.
+ */
+ pcap_snprintf(p, errbuflen_remaining,
+ "Couldn't get error message for error (%lu)", errnum);
+ return;
+ }
+
+ pcap_snprintf(p, errbuflen_remaining, "%s (%lu)", win32_errbuf, errnum);
+}
+#endif
diff --git a/lib/libpcap/libpcap/fmtutils.h b/lib/libpcap/libpcap/fmtutils.h
new file mode 100644
index 0000000..838948b
--- /dev/null
+++ b/lib/libpcap/libpcap/fmtutils.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef fmtutils_h
+#define fmtutils_h
+
+#include "pcap/funcattrs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void pcap_fmt_errmsg_for_errno(char *, size_t, int,
+ PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+
+#ifdef _WIN32
+void pcap_fmt_errmsg_for_win32_err(char *, size_t, DWORD,
+ PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(4, 5);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libpcap/libpcap/ftmacros.h b/lib/libpcap/libpcap/ftmacros.h
new file mode 100644
index 0000000..cd3daeb
--- /dev/null
+++ b/lib/libpcap/libpcap/ftmacros.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef ftmacros_h
+#define ftmacros_h
+
+/*
+ * Define some feature test macros to make sure that everything we want
+ * to be declared gets declared.
+ *
+ * On some UN*Xes we need to force strtok_r() to be declared.
+ * We do *NOT* want to define _POSIX_C_SOURCE, as that tends
+ * to make non-POSIX APIs that we use unavailable.
+ * XXX - is there no portable way to say "please pollute the
+ * namespace to the maximum extent possible"?
+ */
+#if defined(sun) || defined(__sun)
+ #define __EXTENSIONS__
+
+ /*
+ * We also need to define _XPG4_2 in order to get
+ * the Single UNIX Specification version of
+ * recvmsg().
+ */
+ #define _XPG4_2
+#elif defined(_hpux) || defined(hpux) || defined(__hpux)
+ #define _REENTRANT
+
+ /*
+ * We need this to get the versions of socket functions that
+ * use socklen_t. Define it only if it's not already defined,
+ * so we don't get redefiniton warnings.
+ */
+ #ifndef _XOPEN_SOURCE_EXTENDED
+ #define _XOPEN_SOURCE_EXTENDED
+ #endif
+
+ /*
+ * XXX - the list of PA-RISC options for GCC makes it sound as if
+ * building code that uses a particular vintage of UNIX API/ABI
+ * is complicated:
+ *
+ * https://gcc.gnu.org/onlinedocs/gcc/HPPA-Options.html
+ *
+ * See the description of the -munix flag.
+ *
+ * We probably want libpcap to work with programs built for any
+ * UN*X standard. I'm not sure whether that's possible and, if
+ * it is, what sort of stuff it'd have to do.
+ *
+ * It might also be a requirement that we build with a special
+ * flag to allow the library to be used with threaded code, at
+ * least with HP's C compiler; hopefully doing so won't make it
+ * *not* work with *un*-threaded code.
+ */
+#elif defined(__linux__) || defined(linux) || defined(__linux)
+ /*
+ * Turn on _GNU_SOURCE to get everything GNU libc has to offer,
+ * including asprintf().
+ *
+ * Unfortunately, one thing it has to offer is a strerror_r()
+ * that's not POSIX-compliant, but we deal with that in
+ * pcap_fmt_errmsg_for_errno().
+ */
+ #define _GNU_SOURCE
+
+ /*
+ * We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get
+ * the BSD u_XXX types, such as u_int and u_short, defined. We
+ * define _DEFAULT_SOURCE first, so that newer versions of GNU libc
+ * don't whine about _BSD_SOURCE being deprecated; we still have
+ * to define _BSD_SOURCE to handle older versions of GNU libc that
+ * don't support _DEFAULT_SOURCE.
+ */
+ #define _DEFAULT_SOURCE
+ #define _BSD_SOURCE
+#endif
+
+#endif
diff --git a/lib/libpcap/libpcap/gencode.c b/lib/libpcap/libpcap/gencode.c
new file mode 100644
index 0000000..e3425cd
--- /dev/null
+++ b/lib/libpcap/libpcap/gencode.c
@@ -0,0 +1,9991 @@
+/*#define CHASE_CHAIN*/
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+#ifdef _WIN32
+ #include <ws2tcpip.h>
+#else
+ #include <sys/socket.h>
+
+ #ifdef __NetBSD__
+ #include <sys/param.h>
+ #endif
+
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+#endif /* _WIN32 */
+
+#include <stdlib.h>
+#include <string.h>
+#include <memory.h>
+#include <setjmp.h>
+#include <stdarg.h>
+
+#ifdef MSDOS
+#include "pcap-dos.h"
+#endif
+
+#include "pcap-int.h"
+
+#include "extract.h"
+
+#include "ethertype.h"
+#include "nlpid.h"
+#include "llc.h"
+#include "gencode.h"
+#include "ieee80211.h"
+#include "atmuni31.h"
+#include "sunatmpos.h"
+#include "ppp.h"
+#include "pcap/sll.h"
+#include "pcap/ipnet.h"
+#include "arcnet.h"
+
+#include "grammar.h"
+#include "scanner.h"
+
+#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+#include <linux/types.h>
+#include <linux/if_packet.h>
+#include <linux/filter.h>
+#endif
+
+#ifdef HAVE_NET_PFVAR_H
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/pfvar.h>
+#include <net/if_pflog.h>
+#endif
+
+#ifndef offsetof
+#define offsetof(s, e) ((size_t)&((s *)0)->e)
+#endif
+
+#ifdef _WIN32
+ #ifdef INET6
+ #if defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF)
+/* IPv6 address */
+struct in6_addr
+ {
+ union
+ {
+ uint8_t u6_addr8[16];
+ uint16_t u6_addr16[8];
+ uint32_t u6_addr32[4];
+ } in6_u;
+#define s6_addr in6_u.u6_addr8
+#define s6_addr16 in6_u.u6_addr16
+#define s6_addr32 in6_u.u6_addr32
+#define s6_addr64 in6_u.u6_addr64
+ };
+
+typedef unsigned short sa_family_t;
+
+#define __SOCKADDR_COMMON(sa_prefix) \
+ sa_family_t sa_prefix##family
+
+/* Ditto, for IPv6. */
+struct sockaddr_in6
+ {
+ __SOCKADDR_COMMON (sin6_);
+ uint16_t sin6_port; /* Transport layer port # */
+ uint32_t sin6_flowinfo; /* IPv6 flow information */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ };
+
+ #ifndef EAI_ADDRFAMILY
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE, AI_CANONNAME */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
+ size_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 */
+};
+ #endif /* EAI_ADDRFAMILY */
+ #endif /* defined(__MINGW32__) && defined(DEFINE_ADDITIONAL_IPV6_STUFF) */
+ #endif /* INET6 */
+#else /* _WIN32 */
+ #include <netdb.h> /* for "struct addrinfo" */
+#endif /* _WIN32 */
+#include <pcap/namedb.h>
+
+#include "nametoaddr.h"
+
+#define ETHERMTU 1500
+
+#ifndef ETHERTYPE_TEB
+#define ETHERTYPE_TEB 0x6558
+#endif
+
+#ifndef IPPROTO_HOPOPTS
+#define IPPROTO_HOPOPTS 0
+#endif
+#ifndef IPPROTO_ROUTING
+#define IPPROTO_ROUTING 43
+#endif
+#ifndef IPPROTO_FRAGMENT
+#define IPPROTO_FRAGMENT 44
+#endif
+#ifndef IPPROTO_DSTOPTS
+#define IPPROTO_DSTOPTS 60
+#endif
+#ifndef IPPROTO_SCTP
+#define IPPROTO_SCTP 132
+#endif
+
+#define GENEVE_PORT 6081
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#define JMP(c) ((c)|BPF_JMP|BPF_K)
+
+/*
+ * "Push" the current value of the link-layer header type and link-layer
+ * header offset onto a "stack", and set a new value. (It's not a
+ * full-blown stack; we keep only the top two items.)
+ */
+#define PUSH_LINKHDR(cs, new_linktype, new_is_variable, new_constant_part, new_reg) \
+{ \
+ (cs)->prevlinktype = (cs)->linktype; \
+ (cs)->off_prevlinkhdr = (cs)->off_linkhdr; \
+ (cs)->linktype = (new_linktype); \
+ (cs)->off_linkhdr.is_variable = (new_is_variable); \
+ (cs)->off_linkhdr.constant_part = (new_constant_part); \
+ (cs)->off_linkhdr.reg = (new_reg); \
+ (cs)->is_geneve = 0; \
+}
+
+/*
+ * Offset "not set" value.
+ */
+#define OFFSET_NOT_SET 0xffffffffU
+
+/*
+ * Absolute offsets, which are offsets from the beginning of the raw
+ * packet data, are, in the general case, the sum of a variable value
+ * and a constant value; the variable value may be absent, in which
+ * case the offset is only the constant value, and the constant value
+ * may be zero, in which case the offset is only the variable value.
+ *
+ * bpf_abs_offset is a structure containing all that information:
+ *
+ * is_variable is 1 if there's a variable part.
+ *
+ * constant_part is the constant part of the value, possibly zero;
+ *
+ * if is_variable is 1, reg is the register number for a register
+ * containing the variable value if the register has been assigned,
+ * and -1 otherwise.
+ */
+typedef struct {
+ int is_variable;
+ u_int constant_part;
+ int reg;
+} bpf_abs_offset;
+
+/*
+ * Value passed to gen_load_a() to indicate what the offset argument
+ * is relative to the beginning of.
+ */
+enum e_offrel {
+ OR_PACKET, /* full packet data */
+ OR_LINKHDR, /* link-layer header */
+ OR_PREVLINKHDR, /* previous link-layer header */
+ OR_LLC, /* 802.2 LLC header */
+ OR_PREVMPLSHDR, /* previous MPLS header */
+ OR_LINKTYPE, /* link-layer type */
+ OR_LINKPL, /* link-layer payload */
+ OR_LINKPL_NOSNAP, /* link-layer payload, with no SNAP header at the link layer */
+ OR_TRAN_IPV4, /* transport-layer header, with IPv4 network layer */
+ OR_TRAN_IPV6 /* transport-layer header, with IPv6 network layer */
+};
+
+/*
+ * We divy out chunks of memory rather than call malloc each time so
+ * we don't have to worry about leaking memory. It's probably
+ * not a big deal if all this memory was wasted but if this ever
+ * goes into a library that would probably not be a good idea.
+ *
+ * XXX - this *is* in a library....
+ */
+#define NCHUNKS 16
+#define CHUNK0SIZE 1024
+struct chunk {
+ size_t n_left;
+ void *m;
+};
+
+/* Code generator state */
+
+struct _compiler_state {
+ jmp_buf top_ctx;
+ pcap_t *bpf_pcap;
+
+ struct icode ic;
+
+ int snaplen;
+
+ int linktype;
+ int prevlinktype;
+ int outermostlinktype;
+
+ bpf_u_int32 netmask;
+ int no_optimize;
+
+ /* Hack for handling VLAN and MPLS stacks. */
+ u_int label_stack_depth;
+ u_int vlan_stack_depth;
+
+ /* XXX */
+ u_int pcap_fddipad;
+
+ /*
+ * As errors are handled by a longjmp, anything allocated must
+ * be freed in the longjmp handler, so it must be reachable
+ * from that handler.
+ *
+ * One thing that's allocated is the result of pcap_nametoaddrinfo();
+ * it must be freed with freeaddrinfo(). This variable points to
+ * any addrinfo structure that would need to be freed.
+ */
+ struct addrinfo *ai;
+
+ /*
+ * Another thing that's allocated is the result of pcap_ether_aton();
+ * it must be freed with free(). This variable points to any
+ * address that would need to be freed.
+ */
+ u_char *e;
+
+ /*
+ * Various code constructs need to know the layout of the packet.
+ * These values give the necessary offsets from the beginning
+ * of the packet data.
+ */
+
+ /*
+ * Absolute offset of the beginning of the link-layer header.
+ */
+ bpf_abs_offset off_linkhdr;
+
+ /*
+ * If we're checking a link-layer header for a packet encapsulated
+ * in another protocol layer, this is the equivalent information
+ * for the previous layers' link-layer header from the beginning
+ * of the raw packet data.
+ */
+ bpf_abs_offset off_prevlinkhdr;
+
+ /*
+ * This is the equivalent information for the outermost layers'
+ * link-layer header.
+ */
+ bpf_abs_offset off_outermostlinkhdr;
+
+ /*
+ * Absolute offset of the beginning of the link-layer payload.
+ */
+ bpf_abs_offset off_linkpl;
+
+ /*
+ * "off_linktype" is the offset to information in the link-layer
+ * header giving the packet type. This is an absolute offset
+ * from the beginning of the packet.
+ *
+ * For Ethernet, it's the offset of the Ethernet type field; this
+ * means that it must have a value that skips VLAN tags.
+ *
+ * For link-layer types that always use 802.2 headers, it's the
+ * offset of the LLC header; this means that it must have a value
+ * that skips VLAN tags.
+ *
+ * For PPP, it's the offset of the PPP type field.
+ *
+ * For Cisco HDLC, it's the offset of the CHDLC type field.
+ *
+ * For BSD loopback, it's the offset of the AF_ value.
+ *
+ * For Linux cooked sockets, it's the offset of the type field.
+ *
+ * off_linktype.constant_part is set to OFFSET_NOT_SET for no
+ * encapsulation, in which case, IP is assumed.
+ */
+ bpf_abs_offset off_linktype;
+
+ /*
+ * TRUE if the link layer includes an ATM pseudo-header.
+ */
+ int is_atm;
+
+ /*
+ * TRUE if "geneve" appeared in the filter; it causes us to
+ * generate code that checks for a Geneve header and assume
+ * that later filters apply to the encapsulated payload.
+ */
+ int is_geneve;
+
+ /*
+ * TRUE if we need variable length part of VLAN offset
+ */
+ int is_vlan_vloffset;
+
+ /*
+ * These are offsets for the ATM pseudo-header.
+ */
+ u_int off_vpi;
+ u_int off_vci;
+ u_int off_proto;
+
+ /*
+ * These are offsets for the MTP2 fields.
+ */
+ u_int off_li;
+ u_int off_li_hsl;
+
+ /*
+ * These are offsets for the MTP3 fields.
+ */
+ u_int off_sio;
+ u_int off_opc;
+ u_int off_dpc;
+ u_int off_sls;
+
+ /*
+ * This is the offset of the first byte after the ATM pseudo_header,
+ * or -1 if there is no ATM pseudo-header.
+ */
+ u_int off_payload;
+
+ /*
+ * These are offsets to the beginning of the network-layer header.
+ * They are relative to the beginning of the link-layer payload
+ * (i.e., they don't include off_linkhdr.constant_part or
+ * off_linkpl.constant_part).
+ *
+ * If the link layer never uses 802.2 LLC:
+ *
+ * "off_nl" and "off_nl_nosnap" are the same.
+ *
+ * If the link layer always uses 802.2 LLC:
+ *
+ * "off_nl" is the offset if there's a SNAP header following
+ * the 802.2 header;
+ *
+ * "off_nl_nosnap" is the offset if there's no SNAP header.
+ *
+ * If the link layer is Ethernet:
+ *
+ * "off_nl" is the offset if the packet is an Ethernet II packet
+ * (we assume no 802.3+802.2+SNAP);
+ *
+ * "off_nl_nosnap" is the offset if the packet is an 802.3 packet
+ * with an 802.2 header following it.
+ */
+ u_int off_nl;
+ u_int off_nl_nosnap;
+
+ /*
+ * Here we handle simple allocation of the scratch registers.
+ * If too many registers are alloc'd, the allocator punts.
+ */
+ int regused[BPF_MEMWORDS];
+ int curreg;
+
+ /*
+ * Memory chunks.
+ */
+ struct chunk chunks[NCHUNKS];
+ int cur_chunk;
+};
+
+/*
+ * For use by routines outside this file.
+ */
+/* VARARGS */
+void
+bpf_set_error(compiler_state_t *cstate, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void)pcap_vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
+ fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * For use *ONLY* in routines in this file.
+ */
+static void PCAP_NORETURN bpf_error(compiler_state_t *, const char *, ...)
+ PCAP_PRINTFLIKE(2, 3);
+
+/* VARARGS */
+static void PCAP_NORETURN
+bpf_error(compiler_state_t *cstate, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void)pcap_vsnprintf(cstate->bpf_pcap->errbuf, PCAP_ERRBUF_SIZE,
+ fmt, ap);
+ va_end(ap);
+ longjmp(cstate->top_ctx, 1);
+ /*NOTREACHED*/
+}
+
+static int init_linktype(compiler_state_t *, pcap_t *);
+
+static void init_regs(compiler_state_t *);
+static int alloc_reg(compiler_state_t *);
+static void free_reg(compiler_state_t *, int);
+
+static void initchunks(compiler_state_t *cstate);
+static void *newchunk_nolongjmp(compiler_state_t *cstate, size_t);
+static void *newchunk(compiler_state_t *cstate, size_t);
+static void freechunks(compiler_state_t *cstate);
+static inline struct block *new_block(compiler_state_t *cstate, int);
+static inline struct slist *new_stmt(compiler_state_t *cstate, int);
+static struct block *gen_retblk(compiler_state_t *cstate, int);
+static inline void syntax(compiler_state_t *cstate);
+
+static void backpatch(struct block *, struct block *);
+static void merge(struct block *, struct block *);
+static struct block *gen_cmp(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_gt(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_ge(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_lt(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_cmp_le(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32);
+static struct block *gen_mcmp(compiler_state_t *, enum e_offrel, u_int,
+ u_int, bpf_int32, bpf_u_int32);
+static struct block *gen_bcmp(compiler_state_t *, enum e_offrel, u_int,
+ u_int, const u_char *);
+static struct block *gen_ncmp(compiler_state_t *, enum e_offrel, bpf_u_int32,
+ bpf_u_int32, bpf_u_int32, bpf_u_int32, int, bpf_int32);
+static struct slist *gen_load_absoffsetrel(compiler_state_t *, bpf_abs_offset *,
+ u_int, u_int);
+static struct slist *gen_load_a(compiler_state_t *, enum e_offrel, u_int,
+ u_int);
+static struct slist *gen_loadx_iphdrlen(compiler_state_t *);
+static struct block *gen_uncond(compiler_state_t *, int);
+static inline struct block *gen_true(compiler_state_t *);
+static inline struct block *gen_false(compiler_state_t *);
+static struct block *gen_ether_linktype(compiler_state_t *, int);
+static struct block *gen_ipnet_linktype(compiler_state_t *, int);
+static struct block *gen_linux_sll_linktype(compiler_state_t *, int);
+static struct slist *gen_load_prism_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_avs_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_radiotap_llprefixlen(compiler_state_t *);
+static struct slist *gen_load_ppi_llprefixlen(compiler_state_t *);
+static void insert_compute_vloffsets(compiler_state_t *, struct block *);
+static struct slist *gen_abs_offset_varpart(compiler_state_t *,
+ bpf_abs_offset *);
+static int ethertype_to_ppptype(int);
+static struct block *gen_linktype(compiler_state_t *, int);
+static struct block *gen_snap(compiler_state_t *, bpf_u_int32, bpf_u_int32);
+static struct block *gen_llc_linktype(compiler_state_t *, int);
+static struct block *gen_hostop(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+ int, int, u_int, u_int);
+#ifdef INET6
+static struct block *gen_hostop6(compiler_state_t *, struct in6_addr *,
+ struct in6_addr *, int, int, u_int, u_int);
+#endif
+static struct block *gen_ahostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ehostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_fhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_thostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_wlanhostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_ipfchostop(compiler_state_t *, const u_char *, int);
+static struct block *gen_dnhostop(compiler_state_t *, bpf_u_int32, int);
+static struct block *gen_mpls_linktype(compiler_state_t *, int);
+static struct block *gen_host(compiler_state_t *, bpf_u_int32, bpf_u_int32,
+ int, int, int);
+#ifdef INET6
+static struct block *gen_host6(compiler_state_t *, struct in6_addr *,
+ struct in6_addr *, int, int, int);
+#endif
+#ifndef INET6
+static struct block *gen_gateway(compiler_state_t *, const u_char *,
+ struct addrinfo *, int, int);
+#endif
+static struct block *gen_ipfrag(compiler_state_t *);
+static struct block *gen_portatom(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom(compiler_state_t *, int, bpf_int32,
+ bpf_int32);
+static struct block *gen_portatom6(compiler_state_t *, int, bpf_int32);
+static struct block *gen_portrangeatom6(compiler_state_t *, int, bpf_int32,
+ bpf_int32);
+struct block *gen_portop(compiler_state_t *, int, int, int);
+static struct block *gen_port(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange(compiler_state_t *, int, int, int, int);
+struct block *gen_portop6(compiler_state_t *, int, int, int);
+static struct block *gen_port6(compiler_state_t *, int, int, int);
+struct block *gen_portrangeop6(compiler_state_t *, int, int, int, int);
+static struct block *gen_portrange6(compiler_state_t *, int, int, int, int);
+static int lookup_proto(compiler_state_t *, const char *, int);
+static struct block *gen_protochain(compiler_state_t *, int, int, int);
+static struct block *gen_proto(compiler_state_t *, int, int, int);
+static struct slist *xfer_to_x(compiler_state_t *, struct arth *);
+static struct slist *xfer_to_a(compiler_state_t *, struct arth *);
+static struct block *gen_mac_multicast(compiler_state_t *, int);
+static struct block *gen_len(compiler_state_t *, int, int);
+static struct block *gen_check_802_11_data_frame(compiler_state_t *);
+static struct block *gen_geneve_ll_check(compiler_state_t *cstate);
+
+static struct block *gen_ppi_dlt_check(compiler_state_t *);
+static struct block *gen_atmfield_code_internal(compiler_state_t *, int,
+ bpf_int32, bpf_u_int32, int);
+static struct block *gen_atmtype_llc(compiler_state_t *);
+static struct block *gen_msg_abbrev(compiler_state_t *, int type);
+
+static void
+initchunks(compiler_state_t *cstate)
+{
+ int i;
+
+ for (i = 0; i < NCHUNKS; i++) {
+ cstate->chunks[i].n_left = 0;
+ cstate->chunks[i].m = NULL;
+ }
+ cstate->cur_chunk = 0;
+}
+
+static void *
+newchunk_nolongjmp(compiler_state_t *cstate, size_t n)
+{
+ struct chunk *cp;
+ int k;
+ size_t size;
+
+#ifndef __NetBSD__
+ /* XXX Round up to nearest long. */
+ n = (n + sizeof(long) - 1) & ~(sizeof(long) - 1);
+#else
+ /* XXX Round up to structure boundary. */
+ n = ALIGN(n);
+#endif
+
+ cp = &cstate->chunks[cstate->cur_chunk];
+ if (n > cp->n_left) {
+ ++cp;
+ k = ++cstate->cur_chunk;
+ if (k >= NCHUNKS) {
+ bpf_set_error(cstate, "out of memory");
+ return (NULL);
+ }
+ size = CHUNK0SIZE << k;
+ cp->m = (void *)malloc(size);
+ if (cp->m == NULL) {
+ bpf_set_error(cstate, "out of memory");
+ return (NULL);
+ }
+ memset((char *)cp->m, 0, size);
+ cp->n_left = size;
+ if (n > size) {
+ bpf_set_error(cstate, "out of memory");
+ return (NULL);
+ }
+ }
+ cp->n_left -= n;
+ return (void *)((char *)cp->m + cp->n_left);
+}
+
+static void *
+newchunk(compiler_state_t *cstate, size_t n)
+{
+ void *p;
+
+ p = newchunk_nolongjmp(cstate, n);
+ if (p == NULL) {
+ longjmp(cstate->top_ctx, 1);
+ /*NOTREACHED*/
+ }
+ return (p);
+}
+
+static void
+freechunks(compiler_state_t *cstate)
+{
+ int i;
+
+ for (i = 0; i < NCHUNKS; ++i)
+ if (cstate->chunks[i].m != NULL)
+ free(cstate->chunks[i].m);
+}
+
+/*
+ * A strdup whose allocations are freed after code generation is over.
+ * This is used by the lexical analyzer, so it can't longjmp; it just
+ * returns NULL on an allocation error, and the callers must check
+ * for it.
+ */
+char *
+sdup(compiler_state_t *cstate, const char *s)
+{
+ size_t n = strlen(s) + 1;
+ char *cp = newchunk_nolongjmp(cstate, n);
+
+ if (cp == NULL)
+ return (NULL);
+ pcap_strlcpy(cp, s, n);
+ return (cp);
+}
+
+static inline struct block *
+new_block(compiler_state_t *cstate, int code)
+{
+ struct block *p;
+
+ p = (struct block *)newchunk(cstate, sizeof(*p));
+ p->s.code = code;
+ p->head = p;
+
+ return p;
+}
+
+static inline struct slist *
+new_stmt(compiler_state_t *cstate, int code)
+{
+ struct slist *p;
+
+ p = (struct slist *)newchunk(cstate, sizeof(*p));
+ p->s.code = code;
+
+ return p;
+}
+
+static struct block *
+gen_retblk(compiler_state_t *cstate, int v)
+{
+ struct block *b = new_block(cstate, BPF_RET|BPF_K);
+
+ b->s.k = v;
+ return b;
+}
+
+static inline PCAP_NORETURN_DEF void
+syntax(compiler_state_t *cstate)
+{
+ bpf_error(cstate, "syntax error in filter expression");
+}
+
+int
+pcap_compile(pcap_t *p, struct bpf_program *program,
+ const char *buf, int optimize, bpf_u_int32 mask)
+{
+#ifdef _WIN32
+ static int done = 0;
+#endif
+ compiler_state_t cstate;
+ const char * volatile xbuf = buf;
+ yyscan_t scanner = NULL;
+ volatile YY_BUFFER_STATE in_buffer = NULL;
+ u_int len;
+ int rc;
+
+ /*
+ * If this pcap_t hasn't been activated, it doesn't have a
+ * link-layer type, so we can't use it.
+ */
+ if (!p->activated) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "not-yet-activated pcap_t passed to pcap_compile");
+ return (-1);
+ }
+
+#ifdef _WIN32
+ if (!done)
+ pcap_wsockinit();
+ done = 1;
+#endif
+
+#ifdef ENABLE_REMOTE
+ /*
+ * If the device on which we're capturing need to be notified
+ * that a new filter is being compiled, do so.
+ *
+ * This allows them to save a copy of it, in case, for example,
+ * they're implementing a form of remote packet capture, and
+ * want the remote machine to filter out the packets in which
+ * it's sending the packets it's captured.
+ *
+ * XXX - the fact that we happen to be compiling a filter
+ * doesn't necessarily mean we'll be installing it as the
+ * filter for this pcap_t; we might be running it from userland
+ * on captured packets to do packet classification. We really
+ * need a better way of handling this, but this is all that
+ * the WinPcap remote capture code did.
+ */
+ if (p->save_current_filter_op != NULL)
+ (p->save_current_filter_op)(p, buf);
+#endif
+
+ initchunks(&cstate);
+ cstate.no_optimize = 0;
+#ifdef INET6
+ cstate.ai = NULL;
+#endif
+ cstate.e = NULL;
+ cstate.ic.root = NULL;
+ cstate.ic.cur_mark = 0;
+ cstate.bpf_pcap = p;
+ init_regs(&cstate);
+
+ cstate.netmask = mask;
+
+ cstate.snaplen = pcap_snapshot(p);
+ if (cstate.snaplen == 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "snaplen of 0 rejects all packets");
+ rc = -1;
+ goto quit;
+ }
+
+ if (pcap_lex_init(&scanner) != 0)
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't initialize scanner");
+ in_buffer = pcap__scan_string(xbuf ? xbuf : "", scanner);
+
+ /*
+ * Associate the compiler state with the lexical analyzer
+ * state.
+ */
+ pcap_set_extra(&cstate, scanner);
+
+ if (init_linktype(&cstate, p) == -1) {
+ rc = -1;
+ goto quit;
+ }
+ if (pcap_parse(scanner, &cstate) != 0) {
+#ifdef INET6
+ if (cstate.ai != NULL)
+ freeaddrinfo(cstate.ai);
+#endif
+ if (cstate.e != NULL)
+ free(cstate.e);
+ rc = -1;
+ goto quit;
+ }
+
+ if (cstate.ic.root == NULL) {
+ /*
+ * Catch errors reported by gen_retblk().
+ */
+ if (setjmp(cstate.top_ctx)) {
+ rc = -1;
+ goto quit;
+ }
+ cstate.ic.root = gen_retblk(&cstate, cstate.snaplen);
+ }
+
+ if (optimize && !cstate.no_optimize) {
+ if (bpf_optimize(&cstate.ic, p->errbuf) == -1) {
+ /* Failure */
+ rc = -1;
+ goto quit;
+ }
+ if (cstate.ic.root == NULL ||
+ (cstate.ic.root->s.code == (BPF_RET|BPF_K) && cstate.ic.root->s.k == 0)) {
+ (void)pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "expression rejects all packets");
+ rc = -1;
+ goto quit;
+ }
+ }
+ program->bf_insns = icode_to_fcode(&cstate.ic,
+ cstate.ic.root, &len, p->errbuf);
+ if (program->bf_insns == NULL) {
+ /* Failure */
+ rc = -1;
+ goto quit;
+ }
+ program->bf_len = len;
+
+ rc = 0; /* We're all okay */
+
+quit:
+ /*
+ * Clean up everything for the lexical analyzer.
+ */
+ if (in_buffer != NULL)
+ pcap__delete_buffer(in_buffer, scanner);
+ if (scanner != NULL)
+ pcap_lex_destroy(scanner);
+
+ /*
+ * Clean up our own allocated memory.
+ */
+ freechunks(&cstate);
+
+ return (rc);
+}
+
+/*
+ * entry point for using the compiler with no pcap open
+ * pass in all the stuff that is needed explicitly instead.
+ */
+int
+pcap_compile_nopcap(int snaplen_arg, int linktype_arg,
+ struct bpf_program *program,
+ const char *buf, int optimize, bpf_u_int32 mask)
+{
+ pcap_t *p;
+ int ret;
+
+ p = pcap_open_dead(linktype_arg, snaplen_arg);
+ if (p == NULL)
+ return (-1);
+ ret = pcap_compile(p, program, buf, optimize, mask);
+ pcap_close(p);
+ return (ret);
+}
+
+/*
+ * Clean up a "struct bpf_program" by freeing all the memory allocated
+ * in it.
+ */
+void
+pcap_freecode(struct bpf_program *program)
+{
+ program->bf_len = 0;
+ if (program->bf_insns != NULL) {
+ free((char *)program->bf_insns);
+ program->bf_insns = NULL;
+ }
+}
+
+/*
+ * Backpatch the blocks in 'list' to 'target'. The 'sense' field indicates
+ * which of the jt and jf fields has been resolved and which is a pointer
+ * back to another unresolved block (or nil). At least one of the fields
+ * in each block is already resolved.
+ */
+static void
+backpatch(struct block *list, struct block *target)
+{
+ struct block *next;
+
+ while (list) {
+ if (!list->sense) {
+ next = JT(list);
+ JT(list) = target;
+ } else {
+ next = JF(list);
+ JF(list) = target;
+ }
+ list = next;
+ }
+}
+
+/*
+ * Merge the lists in b0 and b1, using the 'sense' field to indicate
+ * which of jt and jf is the link.
+ */
+static void
+merge(struct block *b0, struct block *b1)
+{
+ register struct block **p = &b0;
+
+ /* Find end of list. */
+ while (*p)
+ p = !((*p)->sense) ? &JT(*p) : &JF(*p);
+
+ /* Concatenate the lists. */
+ *p = b1;
+}
+
+int
+finish_parse(compiler_state_t *cstate, struct block *p)
+{
+ struct block *ppi_dlt_check;
+
+ /*
+ * Catch errors reported by us and routines below us, and return -1
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (-1);
+
+ /*
+ * Insert before the statements of the first (root) block any
+ * statements needed to load the lengths of any variable-length
+ * headers into registers.
+ *
+ * XXX - a fancier strategy would be to insert those before the
+ * statements of all blocks that use those lengths and that
+ * have no predecessors that use them, so that we only compute
+ * the lengths if we need them. There might be even better
+ * approaches than that.
+ *
+ * However, those strategies would be more complicated, and
+ * as we don't generate code to compute a length if the
+ * program has no tests that use the length, and as most
+ * tests will probably use those lengths, we would just
+ * postpone computing the lengths so that it's not done
+ * for tests that fail early, and it's not clear that's
+ * worth the effort.
+ */
+ insert_compute_vloffsets(cstate, p->head);
+
+ /*
+ * For DLT_PPI captures, generate a check of the per-packet
+ * DLT value to make sure it's DLT_IEEE802_11.
+ *
+ * XXX - TurboCap cards use DLT_PPI for Ethernet.
+ * Can we just define some DLT_ETHERNET_WITH_PHDR pseudo-header
+ * with appropriate Ethernet information and use that rather
+ * than using something such as DLT_PPI where you don't know
+ * the link-layer header type until runtime, which, in the
+ * general case, would force us to generate both Ethernet *and*
+ * 802.11 code (*and* anything else for which PPI is used)
+ * and choose between them early in the BPF program?
+ */
+ ppi_dlt_check = gen_ppi_dlt_check(cstate);
+ if (ppi_dlt_check != NULL)
+ gen_and(ppi_dlt_check, p);
+
+ backpatch(p, gen_retblk(cstate, cstate->snaplen));
+ p->sense = !p->sense;
+ backpatch(p, gen_retblk(cstate, 0));
+ cstate->ic.root = p->head;
+ return (0);
+}
+
+void
+gen_and(struct block *b0, struct block *b1)
+{
+ backpatch(b0, b1->head);
+ b0->sense = !b0->sense;
+ b1->sense = !b1->sense;
+ merge(b1, b0);
+ b1->sense = !b1->sense;
+ b1->head = b0->head;
+}
+
+void
+gen_or(struct block *b0, struct block *b1)
+{
+ b0->sense = !b0->sense;
+ backpatch(b0, b1->head);
+ b0->sense = !b0->sense;
+ merge(b1, b0);
+ b1->head = b0->head;
+}
+
+void
+gen_not(struct block *b)
+{
+ b->sense = !b->sense;
+}
+
+static struct block *
+gen_cmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
+{
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JEQ, 0, v);
+}
+
+static struct block *
+gen_cmp_gt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
+{
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 0, v);
+}
+
+static struct block *
+gen_cmp_ge(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
+{
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 0, v);
+}
+
+static struct block *
+gen_cmp_lt(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
+{
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGE, 1, v);
+}
+
+static struct block *
+gen_cmp_le(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v)
+{
+ return gen_ncmp(cstate, offrel, offset, size, 0xffffffff, BPF_JGT, 1, v);
+}
+
+static struct block *
+gen_mcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, bpf_int32 v, bpf_u_int32 mask)
+{
+ return gen_ncmp(cstate, offrel, offset, size, mask, BPF_JEQ, 0, v);
+}
+
+static struct block *
+gen_bcmp(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size, const u_char *v)
+{
+ register struct block *b, *tmp;
+
+ /*
+ * XXX - the actual *instructions* do unsigned comparisons on
+ * most platforms, and the load instructions don't do sign
+ * extension, so gen_cmp() should really take an unsigned
+ * value argument.
+ *
+ * As the load instructons also don't do sign-extension, we
+ * fetch the values from the byte array as unsigned. We don't
+ * want to use the signed versions of the extract calls.
+ */
+ b = NULL;
+ while (size >= 4) {
+ register const u_char *p = &v[size - 4];
+
+ tmp = gen_cmp(cstate, offrel, offset + size - 4, BPF_W,
+ (bpf_int32)EXTRACT_32BITS(p));
+ if (b != NULL)
+ gen_and(b, tmp);
+ b = tmp;
+ size -= 4;
+ }
+ while (size >= 2) {
+ register const u_char *p = &v[size - 2];
+
+ tmp = gen_cmp(cstate, offrel, offset + size - 2, BPF_H,
+ (bpf_int32)EXTRACT_16BITS(p));
+ if (b != NULL)
+ gen_and(b, tmp);
+ b = tmp;
+ size -= 2;
+ }
+ if (size > 0) {
+ tmp = gen_cmp(cstate, offrel, offset, BPF_B, (bpf_int32)v[0]);
+ if (b != NULL)
+ gen_and(b, tmp);
+ b = tmp;
+ }
+ return b;
+}
+
+/*
+ * AND the field of size "size" at offset "offset" relative to the header
+ * specified by "offrel" with "mask", and compare it with the value "v"
+ * with the test specified by "jtype"; if "reverse" is true, the test
+ * should test the opposite of "jtype".
+ */
+static struct block *
+gen_ncmp(compiler_state_t *cstate, enum e_offrel offrel, bpf_u_int32 offset,
+ bpf_u_int32 size, bpf_u_int32 mask, bpf_u_int32 jtype, int reverse,
+ bpf_int32 v)
+{
+ struct slist *s, *s2;
+ struct block *b;
+
+ s = gen_load_a(cstate, offrel, offset, size);
+
+ if (mask != 0xffffffff) {
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+ s2->s.k = mask;
+ sappend(s, s2);
+ }
+
+ b = new_block(cstate, JMP(jtype));
+ b->stmts = s;
+ b->s.k = v;
+ if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE))
+ gen_not(b);
+ return b;
+}
+
+static int
+init_linktype(compiler_state_t *cstate, pcap_t *p)
+{
+ cstate->pcap_fddipad = p->fddipad;
+
+ /*
+ * We start out with only one link-layer header.
+ */
+ cstate->outermostlinktype = pcap_datalink(p);
+ cstate->off_outermostlinkhdr.constant_part = 0;
+ cstate->off_outermostlinkhdr.is_variable = 0;
+ cstate->off_outermostlinkhdr.reg = -1;
+
+ cstate->prevlinktype = cstate->outermostlinktype;
+ cstate->off_prevlinkhdr.constant_part = 0;
+ cstate->off_prevlinkhdr.is_variable = 0;
+ cstate->off_prevlinkhdr.reg = -1;
+
+ cstate->linktype = cstate->outermostlinktype;
+ cstate->off_linkhdr.constant_part = 0;
+ cstate->off_linkhdr.is_variable = 0;
+ cstate->off_linkhdr.reg = -1;
+
+ /*
+ * XXX
+ */
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_linkpl.is_variable = 0;
+ cstate->off_linkpl.reg = -1;
+
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linktype.is_variable = 0;
+ cstate->off_linktype.reg = -1;
+
+ /*
+ * Assume it's not raw ATM with a pseudo-header, for now.
+ */
+ cstate->is_atm = 0;
+ cstate->off_vpi = OFFSET_NOT_SET;
+ cstate->off_vci = OFFSET_NOT_SET;
+ cstate->off_proto = OFFSET_NOT_SET;
+ cstate->off_payload = OFFSET_NOT_SET;
+
+ /*
+ * And not Geneve.
+ */
+ cstate->is_geneve = 0;
+
+ /*
+ * No variable length VLAN offset by default
+ */
+ cstate->is_vlan_vloffset = 0;
+
+ /*
+ * And assume we're not doing SS7.
+ */
+ cstate->off_li = OFFSET_NOT_SET;
+ cstate->off_li_hsl = OFFSET_NOT_SET;
+ cstate->off_sio = OFFSET_NOT_SET;
+ cstate->off_opc = OFFSET_NOT_SET;
+ cstate->off_dpc = OFFSET_NOT_SET;
+ cstate->off_sls = OFFSET_NOT_SET;
+
+ cstate->label_stack_depth = 0;
+ cstate->vlan_stack_depth = 0;
+
+ switch (cstate->linktype) {
+
+ case DLT_ARCNET:
+ cstate->off_linktype.constant_part = 2;
+ cstate->off_linkpl.constant_part = 6;
+ cstate->off_nl = 0; /* XXX in reality, variable! */
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_ARCNET_LINUX:
+ cstate->off_linktype.constant_part = 4;
+ cstate->off_linkpl.constant_part = 8;
+ cstate->off_nl = 0; /* XXX in reality, variable! */
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_EN10MB:
+ cstate->off_linktype.constant_part = 12;
+ cstate->off_linkpl.constant_part = 14; /* Ethernet header length */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
+ break;
+
+ case DLT_SLIP:
+ /*
+ * SLIP doesn't have a link level type. The 16 byte
+ * header is hacked into our SLIP driver.
+ */
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 16;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_SLIP_BSDOS:
+ /* XXX this may be the same as the DLT_PPP_BSDOS case */
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ /* XXX end */
+ cstate->off_linkpl.constant_part = 24;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_NULL:
+ case DLT_LOOP:
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 4;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_ENC:
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 12;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_PPP:
+ case DLT_PPP_PPPD:
+ case DLT_C_HDLC: /* BSD/OS Cisco HDLC */
+ case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */
+ cstate->off_linktype.constant_part = 2; /* skip HDLC-like framing */
+ cstate->off_linkpl.constant_part = 4; /* skip HDLC-like framing and protocol field */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_PPP_ETHER:
+ /*
+ * This does no include the Ethernet header, and
+ * only covers session state.
+ */
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = 8;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_PPP_BSDOS:
+ cstate->off_linktype.constant_part = 5;
+ cstate->off_linkpl.constant_part = 24;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_FDDI:
+ /*
+ * FDDI doesn't really have a link-level type field.
+ * We set "off_linktype" to the offset of the LLC header.
+ *
+ * To check for Ethernet types, we assume that SSAP = SNAP
+ * is being used and pick out the encapsulated Ethernet type.
+ * XXX - should we generate code to check for SNAP?
+ */
+ cstate->off_linktype.constant_part = 13;
+ cstate->off_linktype.constant_part += cstate->pcap_fddipad;
+ cstate->off_linkpl.constant_part = 13; /* FDDI MAC header length */
+ cstate->off_linkpl.constant_part += cstate->pcap_fddipad;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
+
+ case DLT_IEEE802:
+ /*
+ * Token Ring doesn't really have a link-level type field.
+ * We set "off_linktype" to the offset of the LLC header.
+ *
+ * To check for Ethernet types, we assume that SSAP = SNAP
+ * is being used and pick out the encapsulated Ethernet type.
+ * XXX - should we generate code to check for SNAP?
+ *
+ * XXX - the header is actually variable-length.
+ * Some various Linux patched versions gave 38
+ * as "off_linktype" and 40 as "off_nl"; however,
+ * if a token ring packet has *no* routing
+ * information, i.e. is not source-routed, the correct
+ * values are 20 and 22, as they are in the vanilla code.
+ *
+ * A packet is source-routed iff the uppermost bit
+ * of the first byte of the source address, at an
+ * offset of 8, has the uppermost bit set. If the
+ * packet is source-routed, the total number of bytes
+ * of routing information is 2 plus bits 0x1F00 of
+ * the 16-bit value at an offset of 14 (shifted right
+ * 8 - figure out which byte that is).
+ */
+ cstate->off_linktype.constant_part = 14;
+ cstate->off_linkpl.constant_part = 14; /* Token Ring MAC header length */
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
+
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ cstate->off_linkhdr.is_variable = 1;
+ /* Fall through, 802.11 doesn't have a variable link
+ * prefix but is otherwise the same. */
+ /* FALLTHROUGH */
+
+ case DLT_IEEE802_11:
+ /*
+ * 802.11 doesn't really have a link-level type field.
+ * We set "off_linktype.constant_part" to the offset of
+ * the LLC header.
+ *
+ * To check for Ethernet types, we assume that SSAP = SNAP
+ * is being used and pick out the encapsulated Ethernet type.
+ * XXX - should we generate code to check for SNAP?
+ *
+ * We also handle variable-length radio headers here.
+ * The Prism header is in theory variable-length, but in
+ * practice it's always 144 bytes long. However, some
+ * drivers on Linux use ARPHRD_IEEE80211_PRISM, but
+ * sometimes or always supply an AVS header, so we
+ * have to check whether the radio header is a Prism
+ * header or an AVS header, so, in practice, it's
+ * variable-length.
+ */
+ cstate->off_linktype.constant_part = 24;
+ cstate->off_linkpl.constant_part = 0; /* link-layer header is variable-length */
+ cstate->off_linkpl.is_variable = 1;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
+
+ case DLT_PPI:
+ /*
+ * At the moment we treat PPI the same way that we treat
+ * normal Radiotap encoded packets. The difference is in
+ * the function that generates the code at the beginning
+ * to compute the header length. Since this code generator
+ * of PPI supports bare 802.11 encapsulation only (i.e.
+ * the encapsulated DLT should be DLT_IEEE802_11) we
+ * generate code to check for this too.
+ */
+ cstate->off_linktype.constant_part = 24;
+ cstate->off_linkpl.constant_part = 0; /* link-layer header is variable-length */
+ cstate->off_linkpl.is_variable = 1;
+ cstate->off_linkhdr.is_variable = 1;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
+
+ case DLT_ATM_RFC1483:
+ case DLT_ATM_CLIP: /* Linux ATM defines this */
+ /*
+ * assume routed, non-ISO PDUs
+ * (i.e., LLC = 0xAA-AA-03, OUT = 0x00-00-00)
+ *
+ * XXX - what about ISO PDUs, e.g. CLNP, ISIS, ESIS,
+ * or PPP with the PPP NLPID (e.g., PPPoA)? The
+ * latter would presumably be treated the way PPPoE
+ * should be, so you can do "pppoe and udp port 2049"
+ * or "pppoa and tcp port 80" and have it check for
+ * PPPo{A,E} and a PPP protocol of IP and....
+ */
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 0; /* packet begins with LLC header */
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
+
+ case DLT_SUNATM:
+ /*
+ * Full Frontal ATM; you get AALn PDUs with an ATM
+ * pseudo-header.
+ */
+ cstate->is_atm = 1;
+ cstate->off_vpi = SUNATM_VPI_POS;
+ cstate->off_vci = SUNATM_VCI_POS;
+ cstate->off_proto = PROTO_POS;
+ cstate->off_payload = SUNATM_PKT_BEGIN_POS;
+ cstate->off_linktype.constant_part = cstate->off_payload;
+ cstate->off_linkpl.constant_part = cstate->off_payload; /* if LLC-encapsulated */
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
+
+ case DLT_RAW:
+ case DLT_IPV4:
+ case DLT_IPV6:
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_LINUX_SLL: /* fake header for Linux cooked socket v1 */
+ cstate->off_linktype.constant_part = 14;
+ cstate->off_linkpl.constant_part = 16;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_LINUX_SLL2: /* fake header for Linux cooked socket v2 */
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = 20;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_LTALK:
+ /*
+ * LocalTalk does have a 1-byte type field in the LLAP header,
+ * but really it just indicates whether there is a "short" or
+ * "long" DDP packet following.
+ */
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_IP_OVER_FC:
+ /*
+ * RFC 2625 IP-over-Fibre-Channel doesn't really have a
+ * link-level type field. We set "off_linktype" to the
+ * offset of the LLC header.
+ *
+ * To check for Ethernet types, we assume that SSAP = SNAP
+ * is being used and pick out the encapsulated Ethernet type.
+ * XXX - should we generate code to check for SNAP? RFC
+ * 2625 says SNAP should be used.
+ */
+ cstate->off_linktype.constant_part = 16;
+ cstate->off_linkpl.constant_part = 16;
+ cstate->off_nl = 8; /* 802.2+SNAP */
+ cstate->off_nl_nosnap = 3; /* 802.2 */
+ break;
+
+ case DLT_FRELAY:
+ /*
+ * XXX - we should set this to handle SNAP-encapsulated
+ * frames (NLPID of 0x80).
+ */
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ /*
+ * the only BPF-interesting FRF.16 frames are non-control frames;
+ * Frame Relay has a variable length link-layer
+ * so lets start with offset 4 for now and increments later on (FIXME);
+ */
+ case DLT_MFR:
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 0;
+ cstate->off_nl = 4;
+ cstate->off_nl_nosnap = 0; /* XXX - for now -> no 802.2 LLC */
+ break;
+
+ case DLT_APPLE_IP_OVER_IEEE1394:
+ cstate->off_linktype.constant_part = 16;
+ cstate->off_linkpl.constant_part = 18;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+
+ case DLT_SYMANTEC_FIREWALL:
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = 44;
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 0; /* XXX - what does it do with 802.3 packets? */
+ break;
+
+#ifdef HAVE_NET_PFVAR_H
+ case DLT_PFLOG:
+ cstate->off_linktype.constant_part = 0;
+ cstate->off_linkpl.constant_part = PFLOG_HDRLEN;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+ break;
+#endif
+
+ case DLT_JUNIPER_MFR:
+ case DLT_JUNIPER_MLFR:
+ case DLT_JUNIPER_MLPPP:
+ case DLT_JUNIPER_PPP:
+ case DLT_JUNIPER_CHDLC:
+ case DLT_JUNIPER_FRELAY:
+ cstate->off_linktype.constant_part = 4;
+ cstate->off_linkpl.constant_part = 4;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
+ break;
+
+ case DLT_JUNIPER_ATM1:
+ cstate->off_linktype.constant_part = 4; /* in reality variable between 4-8 */
+ cstate->off_linkpl.constant_part = 4; /* in reality variable between 4-8 */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 10;
+ break;
+
+ case DLT_JUNIPER_ATM2:
+ cstate->off_linktype.constant_part = 8; /* in reality variable between 8-12 */
+ cstate->off_linkpl.constant_part = 8; /* in reality variable between 8-12 */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 10;
+ break;
+
+ /* frames captured on a Juniper PPPoE service PIC
+ * contain raw ethernet frames */
+ case DLT_JUNIPER_PPPOE:
+ case DLT_JUNIPER_ETHER:
+ cstate->off_linkpl.constant_part = 14;
+ cstate->off_linktype.constant_part = 16;
+ cstate->off_nl = 18; /* Ethernet II */
+ cstate->off_nl_nosnap = 21; /* 802.3+802.2 */
+ break;
+
+ case DLT_JUNIPER_PPPOE_ATM:
+ cstate->off_linktype.constant_part = 4;
+ cstate->off_linkpl.constant_part = 6;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
+ break;
+
+ case DLT_JUNIPER_GGSN:
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = 12;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
+ break;
+
+ case DLT_JUNIPER_ES:
+ cstate->off_linktype.constant_part = 6;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* not really a network layer but raw IP addresses */
+ cstate->off_nl = OFFSET_NOT_SET; /* not really a network layer but raw IP addresses */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
+ break;
+
+ case DLT_JUNIPER_MONITOR:
+ cstate->off_linktype.constant_part = 12;
+ cstate->off_linkpl.constant_part = 12;
+ cstate->off_nl = 0; /* raw IP/IP6 header */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
+ break;
+
+ case DLT_BACNET_MS_TP:
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_JUNIPER_SERVICES:
+ cstate->off_linktype.constant_part = 12;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET; /* L3 proto location dep. on cookie type */
+ cstate->off_nl = OFFSET_NOT_SET; /* L3 proto location dep. on cookie type */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
+ break;
+
+ case DLT_JUNIPER_VP:
+ cstate->off_linktype.constant_part = 18;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_JUNIPER_ST:
+ cstate->off_linktype.constant_part = 18;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_JUNIPER_ISM:
+ cstate->off_linktype.constant_part = 8;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_JUNIPER_VS:
+ case DLT_JUNIPER_SRX_E2E:
+ case DLT_JUNIPER_FIBRECHANNEL:
+ case DLT_JUNIPER_ATM_CEMIC:
+ cstate->off_linktype.constant_part = 8;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_MTP2:
+ cstate->off_li = 2;
+ cstate->off_li_hsl = 4;
+ cstate->off_sio = 3;
+ cstate->off_opc = 4;
+ cstate->off_dpc = 4;
+ cstate->off_sls = 7;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_MTP2_WITH_PHDR:
+ cstate->off_li = 6;
+ cstate->off_li_hsl = 8;
+ cstate->off_sio = 7;
+ cstate->off_opc = 8;
+ cstate->off_dpc = 8;
+ cstate->off_sls = 11;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_ERF:
+ cstate->off_li = 22;
+ cstate->off_li_hsl = 24;
+ cstate->off_sio = 23;
+ cstate->off_opc = 24;
+ cstate->off_dpc = 24;
+ cstate->off_sls = 27;
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_PFSYNC:
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = 4;
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0;
+ break;
+
+ case DLT_AX25_KISS:
+ /*
+ * Currently, only raw "link[N:M]" filtering is supported.
+ */
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET; /* variable, min 15, max 71 steps of 7 */
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET; /* variable, min 16, max 71 steps of 7 */
+ cstate->off_nl_nosnap = OFFSET_NOT_SET; /* no 802.2 LLC */
+ break;
+
+ case DLT_IPNET:
+ cstate->off_linktype.constant_part = 1;
+ cstate->off_linkpl.constant_part = 24; /* ipnet header length */
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ break;
+
+ case DLT_NETANALYZER:
+ cstate->off_linkhdr.constant_part = 4; /* Ethernet header is past 4-byte pseudo-header */
+ cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* pseudo-header+Ethernet header length */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
+ break;
+
+ case DLT_NETANALYZER_TRANSPARENT:
+ cstate->off_linkhdr.constant_part = 12; /* MAC header is past 4-byte pseudo-header, preamble, and SFD */
+ cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* pseudo-header+preamble+SFD+Ethernet header length */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
+ break;
+
+ default:
+ /*
+ * For values in the range in which we've assigned new
+ * DLT_ values, only raw "link[N:M]" filtering is supported.
+ */
+ if (cstate->linktype >= DLT_MATCHING_MIN &&
+ cstate->linktype <= DLT_MATCHING_MAX) {
+ cstate->off_linktype.constant_part = OFFSET_NOT_SET;
+ cstate->off_linkpl.constant_part = OFFSET_NOT_SET;
+ cstate->off_nl = OFFSET_NOT_SET;
+ cstate->off_nl_nosnap = OFFSET_NOT_SET;
+ } else {
+ bpf_set_error(cstate, "unknown data link type %d", cstate->linktype);
+ return (-1);
+ }
+ break;
+ }
+
+ cstate->off_outermostlinkhdr = cstate->off_prevlinkhdr = cstate->off_linkhdr;
+ return (0);
+}
+
+/*
+ * Load a value relative to the specified absolute offset.
+ */
+static struct slist *
+gen_load_absoffsetrel(compiler_state_t *cstate, bpf_abs_offset *abs_offset,
+ u_int offset, u_int size)
+{
+ struct slist *s, *s2;
+
+ s = gen_abs_offset_varpart(cstate, abs_offset);
+
+ /*
+ * If "s" is non-null, it has code to arrange that the X register
+ * contains the variable part of the absolute offset, so we
+ * generate a load relative to that, with an offset of
+ * abs_offset->constant_part + offset.
+ *
+ * Otherwise, we can do an absolute load with an offset of
+ * abs_offset->constant_part + offset.
+ */
+ if (s != NULL) {
+ /*
+ * "s" points to a list of statements that puts the
+ * variable part of the absolute offset into the X register.
+ * Do an indirect load, to use the X register as an offset.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ s2->s.k = abs_offset->constant_part + offset;
+ sappend(s, s2);
+ } else {
+ /*
+ * There is no variable part of the absolute offset, so
+ * just do an absolute load.
+ */
+ s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
+ s->s.k = abs_offset->constant_part + offset;
+ }
+ return s;
+}
+
+/*
+ * Load a value relative to the beginning of the specified header.
+ */
+static struct slist *
+gen_load_a(compiler_state_t *cstate, enum e_offrel offrel, u_int offset,
+ u_int size)
+{
+ struct slist *s, *s2;
+
+ /*
+ * Squelch warnings from compilers that *don't* assume that
+ * offrel always has a valid enum value and therefore don't
+ * assume that we'll always go through one of the case arms.
+ *
+ * If we have a default case, compilers that *do* assume that
+ * will then complain about the default case code being
+ * unreachable.
+ *
+ * Damned if you do, damned if you don't.
+ */
+ s = NULL;
+
+ switch (offrel) {
+
+ case OR_PACKET:
+ s = new_stmt(cstate, BPF_LD|BPF_ABS|size);
+ s->s.k = offset;
+ break;
+
+ case OR_LINKHDR:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkhdr, offset, size);
+ break;
+
+ case OR_PREVLINKHDR:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_prevlinkhdr, offset, size);
+ break;
+
+ case OR_LLC:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, offset, size);
+ break;
+
+ case OR_PREVMPLSHDR:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl - 4 + offset, size);
+ break;
+
+ case OR_LINKPL:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + offset, size);
+ break;
+
+ case OR_LINKPL_NOSNAP:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl_nosnap + offset, size);
+ break;
+
+ case OR_LINKTYPE:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linktype, offset, size);
+ break;
+
+ case OR_TRAN_IPV4:
+ /*
+ * Load the X register with the length of the IPv4 header
+ * (plus the offset of the link-layer header, if it's
+ * preceded by a variable-length header such as a radio
+ * header), in bytes.
+ */
+ s = gen_loadx_iphdrlen(cstate);
+
+ /*
+ * Load the item at {offset of the link-layer payload} +
+ * {offset, relative to the start of the link-layer
+ * paylod, of the IPv4 header} + {length of the IPv4 header} +
+ * {specified offset}.
+ *
+ * If the offset of the link-layer payload is variable,
+ * the variable part of that offset is included in the
+ * value in the X register, and we include the constant
+ * part in the offset of the load.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + offset;
+ sappend(s, s2);
+ break;
+
+ case OR_TRAN_IPV6:
+ s = gen_load_absoffsetrel(cstate, &cstate->off_linkpl, cstate->off_nl + 40 + offset, size);
+ break;
+ }
+ return s;
+}
+
+/*
+ * Generate code to load into the X register the sum of the length of
+ * the IPv4 header and the variable part of the offset of the link-layer
+ * payload.
+ */
+static struct slist *
+gen_loadx_iphdrlen(compiler_state_t *cstate)
+{
+ struct slist *s, *s2;
+
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
+ if (s != NULL) {
+ /*
+ * The offset of the link-layer payload has a variable
+ * part. "s" points to a list of statements that put
+ * the variable part of that offset into the X register.
+ *
+ * The 4*([k]&0xf) addressing mode can't be used, as we
+ * don't have a constant offset, so we have to load the
+ * value in question into the A register and add to it
+ * the value from the X register.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s2->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+ s2->s.k = 0xf;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
+ s2->s.k = 2;
+ sappend(s, s2);
+
+ /*
+ * The A register now contains the length of the IP header.
+ * We need to add to it the variable part of the offset of
+ * the link-layer payload, which is still in the X
+ * register, and move the result into the X register.
+ */
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
+ } else {
+ /*
+ * The offset of the link-layer payload is a constant,
+ * so no code was generated to load the (non-existent)
+ * variable part of that offset.
+ *
+ * This means we can use the 4*([k]&0xf) addressing
+ * mode. Load the length of the IPv4 header, which
+ * is at an offset of cstate->off_nl from the beginning of
+ * the link-layer payload, and thus at an offset of
+ * cstate->off_linkpl.constant_part + cstate->off_nl from the beginning
+ * of the raw packet data, using that addressing mode.
+ */
+ s = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
+ s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ }
+ return s;
+}
+
+
+static struct block *
+gen_uncond(compiler_state_t *cstate, int rsense)
+{
+ struct block *b;
+ struct slist *s;
+
+ s = new_stmt(cstate, BPF_LD|BPF_IMM);
+ s->s.k = !rsense;
+ b = new_block(cstate, JMP(BPF_JEQ));
+ b->stmts = s;
+
+ return b;
+}
+
+static inline struct block *
+gen_true(compiler_state_t *cstate)
+{
+ return gen_uncond(cstate, 1);
+}
+
+static inline struct block *
+gen_false(compiler_state_t *cstate)
+{
+ return gen_uncond(cstate, 0);
+}
+
+/*
+ * Byte-swap a 32-bit number.
+ * ("htonl()" or "ntohl()" won't work - we want to byte-swap even on
+ * big-endian platforms.)
+ */
+#define SWAPLONG(y) \
+((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+
+/*
+ * Generate code to match a particular packet type.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU. We use that to determine whether to
+ * match the type/length field or to check the type/length field for
+ * a value <= ETHERMTU to see whether it's a type field and then do
+ * the appropriate test.
+ */
+static struct block *
+gen_ether_linktype(compiler_state_t *cstate, int proto)
+{
+ struct block *b0, *b1;
+
+ switch (proto) {
+
+ case LLCSAP_ISONS:
+ case LLCSAP_IP:
+ case LLCSAP_NETBEUI:
+ /*
+ * OSI protocols and NetBEUI always use 802.2 encapsulation,
+ * so we check the DSAP and SSAP.
+ *
+ * LLCSAP_IP checks for IP-over-802.2, rather
+ * than IP-over-Ethernet or IP-over-SNAP.
+ *
+ * XXX - should we check both the DSAP and the
+ * SSAP, like this, or should we check just the
+ * DSAP, as we do for other types <= ETHERMTU
+ * (i.e., other SAP values)?
+ */
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+ gen_not(b0);
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
+ ((proto << 8) | proto));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_IPX:
+ /*
+ * Check for;
+ *
+ * Ethernet_II frames, which are Ethernet
+ * frames with a frame type of ETHERTYPE_IPX;
+ *
+ * Ethernet_802.3 frames, which are 802.3
+ * frames (i.e., the type/length field is
+ * a length field, <= ETHERMTU, rather than
+ * a type field) with the first two bytes
+ * after the Ethernet/802.3 header being
+ * 0xFFFF;
+ *
+ * Ethernet_802.2 frames, which are 802.3
+ * frames with an 802.2 LLC header and
+ * with the IPX LSAP as the DSAP in the LLC
+ * header;
+ *
+ * Ethernet_SNAP frames, which are 802.3
+ * frames with an LLC header and a SNAP
+ * header and with an OUI of 0x000000
+ * (encapsulated Ethernet) and a protocol
+ * ID of ETHERTYPE_IPX in the SNAP header.
+ *
+ * XXX - should we generate the same code both
+ * for tests for LLCSAP_IPX and for ETHERTYPE_IPX?
+ */
+
+ /*
+ * This generates code to check both for the
+ * IPX LSAP (Ethernet_802.2) and for Ethernet_802.3.
+ */
+ b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
+ gen_or(b0, b1);
+
+ /*
+ * Now we add code to check for SNAP frames with
+ * ETHERTYPE_IPX, i.e. Ethernet_SNAP.
+ */
+ b0 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
+ gen_or(b0, b1);
+
+ /*
+ * Now we generate code to check for 802.3
+ * frames in general.
+ */
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+ gen_not(b0);
+
+ /*
+ * Now add the check for 802.3 frames before the
+ * check for Ethernet_802.2 and Ethernet_802.3,
+ * as those checks should only be done on 802.3
+ * frames, not on Ethernet frames.
+ */
+ gen_and(b0, b1);
+
+ /*
+ * Now add the check for Ethernet_II frames, and
+ * do that before checking for the other frame
+ * types.
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
+ gen_or(b0, b1);
+ return b1;
+
+ case ETHERTYPE_ATALK:
+ case ETHERTYPE_AARP:
+ /*
+ * EtherTalk (AppleTalk protocols on Ethernet link
+ * layer) may use 802.2 encapsulation.
+ */
+
+ /*
+ * Check for 802.2 encapsulation (EtherTalk phase 2?);
+ * we check for an Ethernet type field less than
+ * 1500, which means it's an 802.3 length field.
+ */
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+ gen_not(b0);
+
+ /*
+ * 802.2-encapsulated ETHERTYPE_ATALK packets are
+ * SNAP packets with an organization code of
+ * 0x080007 (Apple, for Appletalk) and a protocol
+ * type of ETHERTYPE_ATALK (Appletalk).
+ *
+ * 802.2-encapsulated ETHERTYPE_AARP packets are
+ * SNAP packets with an organization code of
+ * 0x000000 (encapsulated Ethernet) and a protocol
+ * type of ETHERTYPE_AARP (Appletalk ARP).
+ */
+ if (proto == ETHERTYPE_ATALK)
+ b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
+ else /* proto == ETHERTYPE_AARP */
+ b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
+ gen_and(b0, b1);
+
+ /*
+ * Check for Ethernet encapsulation (Ethertalk
+ * phase 1?); we just check for the Ethernet
+ * protocol type.
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+
+ gen_or(b0, b1);
+ return b1;
+
+ default:
+ if (proto <= ETHERMTU) {
+ /*
+ * This is an LLC SAP value, so the frames
+ * that match would be 802.2 frames.
+ * Check that the frame is an 802.2 frame
+ * (i.e., that the length/type field is
+ * a length field, <= ETHERMTU) and
+ * then check the DSAP.
+ */
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+ gen_not(b0);
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 2, BPF_B, (bpf_int32)proto);
+ gen_and(b0, b1);
+ return b1;
+ } else {
+ /*
+ * This is an Ethernet type, so compare
+ * the length/type field with it (if
+ * the frame is an 802.2 frame, the length
+ * field will be <= ETHERMTU, and, as
+ * "proto" is > ETHERMTU, this test
+ * will fail and the frame won't match,
+ * which is what we want).
+ */
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
+ (bpf_int32)proto);
+ }
+ }
+}
+
+static struct block *
+gen_loopback_linktype(compiler_state_t *cstate, int proto)
+{
+ /*
+ * For DLT_NULL, the link-layer header is a 32-bit word
+ * containing an AF_ value in *host* byte order, and for
+ * DLT_ENC, the link-layer header begins with a 32-bit
+ * word containing an AF_ value in host byte order.
+ *
+ * In addition, if we're reading a saved capture file,
+ * the host byte order in the capture may not be the
+ * same as the host byte order on this machine.
+ *
+ * For DLT_LOOP, the link-layer header is a 32-bit
+ * word containing an AF_ value in *network* byte order.
+ */
+ if (cstate->linktype == DLT_NULL || cstate->linktype == DLT_ENC) {
+ /*
+ * The AF_ value is in host byte order, but the BPF
+ * interpreter will convert it to network byte order.
+ *
+ * If this is a save file, and it's from a machine
+ * with the opposite byte order to ours, we byte-swap
+ * the AF_ value.
+ *
+ * Then we run it through "htonl()", and generate
+ * code to compare against the result.
+ */
+ if (cstate->bpf_pcap->rfile != NULL && cstate->bpf_pcap->swapped)
+ proto = SWAPLONG(proto);
+ proto = htonl(proto);
+ }
+ return (gen_cmp(cstate, OR_LINKHDR, 0, BPF_W, (bpf_int32)proto));
+}
+
+/*
+ * "proto" is an Ethernet type value and for IPNET, if it is not IPv4
+ * or IPv6 then we have an error.
+ */
+static struct block *
+gen_ipnet_linktype(compiler_state_t *cstate, int proto)
+{
+ switch (proto) {
+
+ case ETHERTYPE_IP:
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B, (bpf_int32)IPH_AF_INET);
+ /*NOTREACHED*/
+
+ case ETHERTYPE_IPV6:
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)IPH_AF_INET6);
+ /*NOTREACHED*/
+
+ default:
+ break;
+ }
+
+ return gen_false(cstate);
+}
+
+/*
+ * Generate code to match a particular packet type.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU. We use that to determine whether to
+ * match the type field or to check the type field for the special
+ * LINUX_SLL_P_802_2 value and then do the appropriate test.
+ */
+static struct block *
+gen_linux_sll_linktype(compiler_state_t *cstate, int proto)
+{
+ struct block *b0, *b1;
+
+ switch (proto) {
+
+ case LLCSAP_ISONS:
+ case LLCSAP_IP:
+ case LLCSAP_NETBEUI:
+ /*
+ * OSI protocols and NetBEUI always use 802.2 encapsulation,
+ * so we check the DSAP and SSAP.
+ *
+ * LLCSAP_IP checks for IP-over-802.2, rather
+ * than IP-over-Ethernet or IP-over-SNAP.
+ *
+ * XXX - should we check both the DSAP and the
+ * SSAP, like this, or should we check just the
+ * DSAP, as we do for other types <= ETHERMTU
+ * (i.e., other SAP values)?
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)
+ ((proto << 8) | proto));
+ gen_and(b0, b1);
+ return b1;
+
+ case LLCSAP_IPX:
+ /*
+ * Ethernet_II frames, which are Ethernet
+ * frames with a frame type of ETHERTYPE_IPX;
+ *
+ * Ethernet_802.3 frames, which have a frame
+ * type of LINUX_SLL_P_802_3;
+ *
+ * Ethernet_802.2 frames, which are 802.3
+ * frames with an 802.2 LLC header (i.e, have
+ * a frame type of LINUX_SLL_P_802_2) and
+ * with the IPX LSAP as the DSAP in the LLC
+ * header;
+ *
+ * Ethernet_SNAP frames, which are 802.3
+ * frames with an LLC header and a SNAP
+ * header and with an OUI of 0x000000
+ * (encapsulated Ethernet) and a protocol
+ * ID of ETHERTYPE_IPX in the SNAP header.
+ *
+ * First, do the checks on LINUX_SLL_P_802_2
+ * frames; generate the check for either
+ * Ethernet_802.2 or Ethernet_SNAP frames, and
+ * then put a check for LINUX_SLL_P_802_2 frames
+ * before it.
+ */
+ b0 = gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)LLCSAP_IPX);
+ b1 = gen_snap(cstate, 0x000000, ETHERTYPE_IPX);
+ gen_or(b0, b1);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+ gen_and(b0, b1);
+
+ /*
+ * Now check for 802.3 frames and OR that with
+ * the previous test.
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_3);
+ gen_or(b0, b1);
+
+ /*
+ * Now add the check for Ethernet_II frames, and
+ * do that before checking for the other frame
+ * types.
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)ETHERTYPE_IPX);
+ gen_or(b0, b1);
+ return b1;
+
+ case ETHERTYPE_ATALK:
+ case ETHERTYPE_AARP:
+ /*
+ * EtherTalk (AppleTalk protocols on Ethernet link
+ * layer) may use 802.2 encapsulation.
+ */
+
+ /*
+ * Check for 802.2 encapsulation (EtherTalk phase 2?);
+ * we check for the 802.2 protocol type in the
+ * "Ethernet type" field.
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+
+ /*
+ * 802.2-encapsulated ETHERTYPE_ATALK packets are
+ * SNAP packets with an organization code of
+ * 0x080007 (Apple, for Appletalk) and a protocol
+ * type of ETHERTYPE_ATALK (Appletalk).
+ *
+ * 802.2-encapsulated ETHERTYPE_AARP packets are
+ * SNAP packets with an organization code of
+ * 0x000000 (encapsulated Ethernet) and a protocol
+ * type of ETHERTYPE_AARP (Appletalk ARP).
+ */
+ if (proto == ETHERTYPE_ATALK)
+ b1 = gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
+ else /* proto == ETHERTYPE_AARP */
+ b1 = gen_snap(cstate, 0x000000, ETHERTYPE_AARP);
+ gen_and(b0, b1);
+
+ /*
+ * Check for Ethernet encapsulation (Ethertalk
+ * phase 1?); we just check for the Ethernet
+ * protocol type.
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+
+ gen_or(b0, b1);
+ return b1;
+
+ default:
+ if (proto <= ETHERMTU) {
+ /*
+ * This is an LLC SAP value, so the frames
+ * that match would be 802.2 frames.
+ * Check for the 802.2 protocol type
+ * in the "Ethernet type" field, and
+ * then check the DSAP.
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, LINUX_SLL_P_802_2);
+ b1 = gen_cmp(cstate, OR_LINKHDR, cstate->off_linkpl.constant_part, BPF_B,
+ (bpf_int32)proto);
+ gen_and(b0, b1);
+ return b1;
+ } else {
+ /*
+ * This is an Ethernet type, so compare
+ * the length/type field with it (if
+ * the frame is an 802.2 frame, the length
+ * field will be <= ETHERMTU, and, as
+ * "proto" is > ETHERMTU, this test
+ * will fail and the frame won't match,
+ * which is what we want).
+ */
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+ }
+ }
+}
+
+static struct slist *
+gen_load_prism_llprefixlen(compiler_state_t *cstate)
+{
+ struct slist *s1, *s2;
+ struct slist *sjeq_avs_cookie;
+ struct slist *sjcommon;
+
+ /*
+ * This code is not compatible with the optimizer, as
+ * we are generating jmp instructions within a normal
+ * slist of instructions
+ */
+ cstate->no_optimize = 1;
+
+ /*
+ * Generate code to load the length of the radio header into
+ * the register assigned to hold that length, if one has been
+ * assigned. (If one hasn't been assigned, no code we've
+ * generated uses that prefix, so we don't need to generate any
+ * code to load it.)
+ *
+ * Some Linux drivers use ARPHRD_IEEE80211_PRISM but sometimes
+ * or always use the AVS header rather than the Prism header.
+ * We load a 4-byte big-endian value at the beginning of the
+ * raw packet data, and see whether, when masked with 0xFFFFF000,
+ * it's equal to 0x80211000. If so, that indicates that it's
+ * an AVS header (the masked-out bits are the version number).
+ * Otherwise, it's a Prism header.
+ *
+ * XXX - the Prism header is also, in theory, variable-length,
+ * but no known software generates headers that aren't 144
+ * bytes long.
+ */
+ if (cstate->off_linkhdr.reg != -1) {
+ /*
+ * Load the cookie.
+ */
+ s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
+ s1->s.k = 0;
+
+ /*
+ * AND it with 0xFFFFF000.
+ */
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+ s2->s.k = 0xFFFFF000;
+ sappend(s1, s2);
+
+ /*
+ * Compare with 0x80211000.
+ */
+ sjeq_avs_cookie = new_stmt(cstate, JMP(BPF_JEQ));
+ sjeq_avs_cookie->s.k = 0x80211000;
+ sappend(s1, sjeq_avs_cookie);
+
+ /*
+ * If it's AVS:
+ *
+ * The 4 bytes at an offset of 4 from the beginning of
+ * the AVS header are the length of the AVS header.
+ * That field is big-endian.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
+ s2->s.k = 4;
+ sappend(s1, s2);
+ sjeq_avs_cookie->s.jt = s2;
+
+ /*
+ * Now jump to the code to allocate a register
+ * into which to save the header length and
+ * store the length there. (The "jump always"
+ * instruction needs to have the k field set;
+ * it's added to the PC, so, as we're jumping
+ * over a single instruction, it should be 1.)
+ */
+ sjcommon = new_stmt(cstate, JMP(BPF_JA));
+ sjcommon->s.k = 1;
+ sappend(s1, sjcommon);
+
+ /*
+ * Now for the code that handles the Prism header.
+ * Just load the length of the Prism header (144)
+ * into the A register. Have the test for an AVS
+ * header branch here if we don't have an AVS header.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_W|BPF_IMM);
+ s2->s.k = 144;
+ sappend(s1, s2);
+ sjeq_avs_cookie->s.jf = s2;
+
+ /*
+ * Now allocate a register to hold that value and store
+ * it. The code for the AVS header will jump here after
+ * loading the length of the AVS header.
+ */
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
+ sappend(s1, s2);
+ sjcommon->s.jf = s2;
+
+ /*
+ * Now move it into the X register.
+ */
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ return (s1);
+ } else
+ return (NULL);
+}
+
+static struct slist *
+gen_load_avs_llprefixlen(compiler_state_t *cstate)
+{
+ struct slist *s1, *s2;
+
+ /*
+ * Generate code to load the length of the AVS header into
+ * the register assigned to hold that length, if one has been
+ * assigned. (If one hasn't been assigned, no code we've
+ * generated uses that prefix, so we don't need to generate any
+ * code to load it.)
+ */
+ if (cstate->off_linkhdr.reg != -1) {
+ /*
+ * The 4 bytes at an offset of 4 from the beginning of
+ * the AVS header are the length of the AVS header.
+ * That field is big-endian.
+ */
+ s1 = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
+ s1->s.k = 4;
+
+ /*
+ * Now allocate a register to hold that value and store
+ * it.
+ */
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
+ sappend(s1, s2);
+
+ /*
+ * Now move it into the X register.
+ */
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ return (s1);
+ } else
+ return (NULL);
+}
+
+static struct slist *
+gen_load_radiotap_llprefixlen(compiler_state_t *cstate)
+{
+ struct slist *s1, *s2;
+
+ /*
+ * Generate code to load the length of the radiotap header into
+ * the register assigned to hold that length, if one has been
+ * assigned. (If one hasn't been assigned, no code we've
+ * generated uses that prefix, so we don't need to generate any
+ * code to load it.)
+ */
+ if (cstate->off_linkhdr.reg != -1) {
+ /*
+ * The 2 bytes at offsets of 2 and 3 from the beginning
+ * of the radiotap header are the length of the radiotap
+ * header; unfortunately, it's little-endian, so we have
+ * to load it a byte at a time and construct the value.
+ */
+
+ /*
+ * Load the high-order byte, at an offset of 3, shift it
+ * left a byte, and put the result in the X register.
+ */
+ s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ s1->s.k = 3;
+ s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
+ sappend(s1, s2);
+ s2->s.k = 8;
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ /*
+ * Load the next byte, at an offset of 2, and OR the
+ * value from the X register into it.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ sappend(s1, s2);
+ s2->s.k = 2;
+ s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
+ sappend(s1, s2);
+
+ /*
+ * Now allocate a register to hold that value and store
+ * it.
+ */
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
+ sappend(s1, s2);
+
+ /*
+ * Now move it into the X register.
+ */
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ return (s1);
+ } else
+ return (NULL);
+}
+
+/*
+ * At the moment we treat PPI as normal Radiotap encoded
+ * packets. The difference is in the function that generates
+ * the code at the beginning to compute the header length.
+ * Since this code generator of PPI supports bare 802.11
+ * encapsulation only (i.e. the encapsulated DLT should be
+ * DLT_IEEE802_11) we generate code to check for this too;
+ * that's done in finish_parse().
+ */
+static struct slist *
+gen_load_ppi_llprefixlen(compiler_state_t *cstate)
+{
+ struct slist *s1, *s2;
+
+ /*
+ * Generate code to load the length of the radiotap header
+ * into the register assigned to hold that length, if one has
+ * been assigned.
+ */
+ if (cstate->off_linkhdr.reg != -1) {
+ /*
+ * The 2 bytes at offsets of 2 and 3 from the beginning
+ * of the radiotap header are the length of the radiotap
+ * header; unfortunately, it's little-endian, so we have
+ * to load it a byte at a time and construct the value.
+ */
+
+ /*
+ * Load the high-order byte, at an offset of 3, shift it
+ * left a byte, and put the result in the X register.
+ */
+ s1 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ s1->s.k = 3;
+ s2 = new_stmt(cstate, BPF_ALU|BPF_LSH|BPF_K);
+ sappend(s1, s2);
+ s2->s.k = 8;
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ /*
+ * Load the next byte, at an offset of 2, and OR the
+ * value from the X register into it.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ sappend(s1, s2);
+ s2->s.k = 2;
+ s2 = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_X);
+ sappend(s1, s2);
+
+ /*
+ * Now allocate a register to hold that value and store
+ * it.
+ */
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkhdr.reg;
+ sappend(s1, s2);
+
+ /*
+ * Now move it into the X register.
+ */
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s1, s2);
+
+ return (s1);
+ } else
+ return (NULL);
+}
+
+/*
+ * Load a value relative to the beginning of the link-layer header after the 802.11
+ * header, i.e. LLC_SNAP.
+ * The link-layer header doesn't necessarily begin at the beginning
+ * of the packet data; there might be a variable-length prefix containing
+ * radio information.
+ */
+static struct slist *
+gen_load_802_11_header_len(compiler_state_t *cstate, struct slist *s, struct slist *snext)
+{
+ struct slist *s2;
+ struct slist *sjset_data_frame_1;
+ struct slist *sjset_data_frame_2;
+ struct slist *sjset_qos;
+ struct slist *sjset_radiotap_flags_present;
+ struct slist *sjset_radiotap_ext_present;
+ struct slist *sjset_radiotap_tsft_present;
+ struct slist *sjset_tsft_datapad, *sjset_notsft_datapad;
+ struct slist *s_roundup;
+
+ if (cstate->off_linkpl.reg == -1) {
+ /*
+ * No register has been assigned to the offset of
+ * the link-layer payload, which means nobody needs
+ * it; don't bother computing it - just return
+ * what we already have.
+ */
+ return (s);
+ }
+
+ /*
+ * This code is not compatible with the optimizer, as
+ * we are generating jmp instructions within a normal
+ * slist of instructions
+ */
+ cstate->no_optimize = 1;
+
+ /*
+ * If "s" is non-null, it has code to arrange that the X register
+ * contains the length of the prefix preceding the link-layer
+ * header.
+ *
+ * Otherwise, the length of the prefix preceding the link-layer
+ * header is "off_outermostlinkhdr.constant_part".
+ */
+ if (s == NULL) {
+ /*
+ * There is no variable-length header preceding the
+ * link-layer header.
+ *
+ * Load the length of the fixed-length prefix preceding
+ * the link-layer header (if any) into the X register,
+ * and store it in the cstate->off_linkpl.reg register.
+ * That length is off_outermostlinkhdr.constant_part.
+ */
+ s = new_stmt(cstate, BPF_LDX|BPF_IMM);
+ s->s.k = cstate->off_outermostlinkhdr.constant_part;
+ }
+
+ /*
+ * The X register contains the offset of the beginning of the
+ * link-layer header; add 24, which is the minimum length
+ * of the MAC header for a data frame, to that, and store it
+ * in cstate->off_linkpl.reg, and then load the Frame Control field,
+ * which is at the offset in the X register, with an indexed load.
+ */
+ s2 = new_stmt(cstate, BPF_MISC|BPF_TXA);
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s2->s.k = 24;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkpl.reg;
+ sappend(s, s2);
+
+ s2 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s2->s.k = 0;
+ sappend(s, s2);
+
+ /*
+ * Check the Frame Control field to see if this is a data frame;
+ * a data frame has the 0x08 bit (b3) in that field set and the
+ * 0x04 bit (b2) clear.
+ */
+ sjset_data_frame_1 = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_data_frame_1->s.k = 0x08;
+ sappend(s, sjset_data_frame_1);
+
+ /*
+ * If b3 is set, test b2, otherwise go to the first statement of
+ * the rest of the program.
+ */
+ sjset_data_frame_1->s.jt = sjset_data_frame_2 = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_data_frame_2->s.k = 0x04;
+ sappend(s, sjset_data_frame_2);
+ sjset_data_frame_1->s.jf = snext;
+
+ /*
+ * If b2 is not set, this is a data frame; test the QoS bit.
+ * Otherwise, go to the first statement of the rest of the
+ * program.
+ */
+ sjset_data_frame_2->s.jt = snext;
+ sjset_data_frame_2->s.jf = sjset_qos = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_qos->s.k = 0x80; /* QoS bit */
+ sappend(s, sjset_qos);
+
+ /*
+ * If it's set, add 2 to cstate->off_linkpl.reg, to skip the QoS
+ * field.
+ * Otherwise, go to the first statement of the rest of the
+ * program.
+ */
+ sjset_qos->s.jt = s2 = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s2->s.k = cstate->off_linkpl.reg;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
+ s2->s.k = 2;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkpl.reg;
+ sappend(s, s2);
+
+ /*
+ * If we have a radiotap header, look at it to see whether
+ * there's Atheros padding between the MAC-layer header
+ * and the payload.
+ *
+ * Note: all of the fields in the radiotap header are
+ * little-endian, so we byte-swap all of the values
+ * we test against, as they will be loaded as big-endian
+ * values.
+ *
+ * XXX - in the general case, we would have to scan through
+ * *all* the presence bits, if there's more than one word of
+ * presence bits. That would require a loop, meaning that
+ * we wouldn't be able to run the filter in the kernel.
+ *
+ * We assume here that the Atheros adapters that insert the
+ * annoying padding don't have multiple antennae and therefore
+ * do not generate radiotap headers with multiple presence words.
+ */
+ if (cstate->linktype == DLT_IEEE802_11_RADIO) {
+ /*
+ * Is the IEEE80211_RADIOTAP_FLAGS bit (0x0000002) set
+ * in the first presence flag word?
+ */
+ sjset_qos->s.jf = s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_W);
+ s2->s.k = 4;
+ sappend(s, s2);
+
+ sjset_radiotap_flags_present = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_radiotap_flags_present->s.k = SWAPLONG(0x00000002);
+ sappend(s, sjset_radiotap_flags_present);
+
+ /*
+ * If not, skip all of this.
+ */
+ sjset_radiotap_flags_present->s.jf = snext;
+
+ /*
+ * Otherwise, is the "extension" bit set in that word?
+ */
+ sjset_radiotap_ext_present = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_radiotap_ext_present->s.k = SWAPLONG(0x80000000);
+ sappend(s, sjset_radiotap_ext_present);
+ sjset_radiotap_flags_present->s.jt = sjset_radiotap_ext_present;
+
+ /*
+ * If so, skip all of this.
+ */
+ sjset_radiotap_ext_present->s.jt = snext;
+
+ /*
+ * Otherwise, is the IEEE80211_RADIOTAP_TSFT bit set?
+ */
+ sjset_radiotap_tsft_present = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_radiotap_tsft_present->s.k = SWAPLONG(0x00000001);
+ sappend(s, sjset_radiotap_tsft_present);
+ sjset_radiotap_ext_present->s.jf = sjset_radiotap_tsft_present;
+
+ /*
+ * If IEEE80211_RADIOTAP_TSFT is set, the flags field is
+ * at an offset of 16 from the beginning of the raw packet
+ * data (8 bytes for the radiotap header and 8 bytes for
+ * the TSFT field).
+ *
+ * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
+ * is set.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+ s2->s.k = 16;
+ sappend(s, s2);
+ sjset_radiotap_tsft_present->s.jt = s2;
+
+ sjset_tsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_tsft_datapad->s.k = 0x20;
+ sappend(s, sjset_tsft_datapad);
+
+ /*
+ * If IEEE80211_RADIOTAP_TSFT is not set, the flags field is
+ * at an offset of 8 from the beginning of the raw packet
+ * data (8 bytes for the radiotap header).
+ *
+ * Test whether the IEEE80211_RADIOTAP_F_DATAPAD bit (0x20)
+ * is set.
+ */
+ s2 = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+ s2->s.k = 8;
+ sappend(s, s2);
+ sjset_radiotap_tsft_present->s.jf = s2;
+
+ sjset_notsft_datapad = new_stmt(cstate, JMP(BPF_JSET));
+ sjset_notsft_datapad->s.k = 0x20;
+ sappend(s, sjset_notsft_datapad);
+
+ /*
+ * In either case, if IEEE80211_RADIOTAP_F_DATAPAD is
+ * set, round the length of the 802.11 header to
+ * a multiple of 4. Do that by adding 3 and then
+ * dividing by and multiplying by 4, which we do by
+ * ANDing with ~3.
+ */
+ s_roundup = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s_roundup->s.k = cstate->off_linkpl.reg;
+ sappend(s, s_roundup);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
+ s2->s.k = 3;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_IMM);
+ s2->s.k = ~3;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkpl.reg;
+ sappend(s, s2);
+
+ sjset_tsft_datapad->s.jt = s_roundup;
+ sjset_tsft_datapad->s.jf = snext;
+ sjset_notsft_datapad->s.jt = s_roundup;
+ sjset_notsft_datapad->s.jf = snext;
+ } else
+ sjset_qos->s.jf = snext;
+
+ return s;
+}
+
+static void
+insert_compute_vloffsets(compiler_state_t *cstate, struct block *b)
+{
+ struct slist *s;
+
+ /* There is an implicit dependency between the link
+ * payload and link header since the payload computation
+ * includes the variable part of the header. Therefore,
+ * if nobody else has allocated a register for the link
+ * header and we need it, do it now. */
+ if (cstate->off_linkpl.reg != -1 && cstate->off_linkhdr.is_variable &&
+ cstate->off_linkhdr.reg == -1)
+ cstate->off_linkhdr.reg = alloc_reg(cstate);
+
+ /*
+ * For link-layer types that have a variable-length header
+ * preceding the link-layer header, generate code to load
+ * the offset of the link-layer header into the register
+ * assigned to that offset, if any.
+ *
+ * XXX - this, and the next switch statement, won't handle
+ * encapsulation of 802.11 or 802.11+radio information in
+ * some other protocol stack. That's significantly more
+ * complicated.
+ */
+ switch (cstate->outermostlinktype) {
+
+ case DLT_PRISM_HEADER:
+ s = gen_load_prism_llprefixlen(cstate);
+ break;
+
+ case DLT_IEEE802_11_RADIO_AVS:
+ s = gen_load_avs_llprefixlen(cstate);
+ break;
+
+ case DLT_IEEE802_11_RADIO:
+ s = gen_load_radiotap_llprefixlen(cstate);
+ break;
+
+ case DLT_PPI:
+ s = gen_load_ppi_llprefixlen(cstate);
+ break;
+
+ default:
+ s = NULL;
+ break;
+ }
+
+ /*
+ * For link-layer types that have a variable-length link-layer
+ * header, generate code to load the offset of the link-layer
+ * payload into the register assigned to that offset, if any.
+ */
+ switch (cstate->outermostlinktype) {
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ s = gen_load_802_11_header_len(cstate, s, b->stmts);
+ break;
+ }
+
+ /*
+ * If there there is no initialization yet and we need variable
+ * length offsets for VLAN, initialize them to zero
+ */
+ if (s == NULL && cstate->is_vlan_vloffset) {
+ struct slist *s2;
+
+ if (cstate->off_linkpl.reg == -1)
+ cstate->off_linkpl.reg = alloc_reg(cstate);
+ if (cstate->off_linktype.reg == -1)
+ cstate->off_linktype.reg = alloc_reg(cstate);
+
+ s = new_stmt(cstate, BPF_LD|BPF_W|BPF_IMM);
+ s->s.k = 0;
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linkpl.reg;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = cstate->off_linktype.reg;
+ sappend(s, s2);
+ }
+
+ /*
+ * If we have any offset-loading code, append all the
+ * existing statements in the block to those statements,
+ * and make the resulting list the list of statements
+ * for the block.
+ */
+ if (s != NULL) {
+ sappend(s, b->stmts);
+ b->stmts = s;
+ }
+}
+
+static struct block *
+gen_ppi_dlt_check(compiler_state_t *cstate)
+{
+ struct slist *s_load_dlt;
+ struct block *b;
+
+ if (cstate->linktype == DLT_PPI)
+ {
+ /* Create the statements that check for the DLT
+ */
+ s_load_dlt = new_stmt(cstate, BPF_LD|BPF_W|BPF_ABS);
+ s_load_dlt->s.k = 4;
+
+ b = new_block(cstate, JMP(BPF_JEQ));
+
+ b->stmts = s_load_dlt;
+ b->s.k = SWAPLONG(DLT_IEEE802_11);
+ }
+ else
+ {
+ b = NULL;
+ }
+
+ return b;
+}
+
+/*
+ * Take an absolute offset, and:
+ *
+ * if it has no variable part, return NULL;
+ *
+ * if it has a variable part, generate code to load the register
+ * containing that variable part into the X register, returning
+ * a pointer to that code - if no register for that offset has
+ * been allocated, allocate it first.
+ *
+ * (The code to set that register will be generated later, but will
+ * be placed earlier in the code sequence.)
+ */
+static struct slist *
+gen_abs_offset_varpart(compiler_state_t *cstate, bpf_abs_offset *off)
+{
+ struct slist *s;
+
+ if (off->is_variable) {
+ if (off->reg == -1) {
+ /*
+ * We haven't yet assigned a register for the
+ * variable part of the offset of the link-layer
+ * header; allocate one.
+ */
+ off->reg = alloc_reg(cstate);
+ }
+
+ /*
+ * Load the register containing the variable part of the
+ * offset of the link-layer header into the X register.
+ */
+ s = new_stmt(cstate, BPF_LDX|BPF_MEM);
+ s->s.k = off->reg;
+ return s;
+ } else {
+ /*
+ * That offset isn't variable, there's no variable part,
+ * so we don't need to generate any code.
+ */
+ return NULL;
+ }
+}
+
+/*
+ * Map an Ethernet type to the equivalent PPP type.
+ */
+static int
+ethertype_to_ppptype(int proto)
+{
+ switch (proto) {
+
+ case ETHERTYPE_IP:
+ proto = PPP_IP;
+ break;
+
+ case ETHERTYPE_IPV6:
+ proto = PPP_IPV6;
+ break;
+
+ case ETHERTYPE_DN:
+ proto = PPP_DECNET;
+ break;
+
+ case ETHERTYPE_ATALK:
+ proto = PPP_APPLE;
+ break;
+
+ case ETHERTYPE_NS:
+ proto = PPP_NS;
+ break;
+
+ case LLCSAP_ISONS:
+ proto = PPP_OSI;
+ break;
+
+ case LLCSAP_8021D:
+ /*
+ * I'm assuming the "Bridging PDU"s that go
+ * over PPP are Spanning Tree Protocol
+ * Bridging PDUs.
+ */
+ proto = PPP_BRPDU;
+ break;
+
+ case LLCSAP_IPX:
+ proto = PPP_IPX;
+ break;
+ }
+ return (proto);
+}
+
+/*
+ * Generate any tests that, for encapsulation of a link-layer packet
+ * inside another protocol stack, need to be done to check for those
+ * link-layer packets (and that haven't already been done by a check
+ * for that encapsulation).
+ */
+static struct block *
+gen_prevlinkhdr_check(compiler_state_t *cstate)
+{
+ struct block *b0;
+
+ if (cstate->is_geneve)
+ return gen_geneve_ll_check(cstate);
+
+ switch (cstate->prevlinktype) {
+
+ case DLT_SUNATM:
+ /*
+ * This is LANE-encapsulated Ethernet; check that the LANE
+ * packet doesn't begin with an LE Control marker, i.e.
+ * that it's data, not a control message.
+ *
+ * (We've already generated a test for LANE.)
+ */
+ b0 = gen_cmp(cstate, OR_PREVLINKHDR, SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00);
+ gen_not(b0);
+ return b0;
+
+ default:
+ /*
+ * No such tests are necessary.
+ */
+ return NULL;
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * The three different values we should check for when checking for an
+ * IPv6 packet with DLT_NULL.
+ */
+#define BSD_AFNUM_INET6_BSD 24 /* NetBSD, OpenBSD, BSD/OS, Npcap */
+#define BSD_AFNUM_INET6_FREEBSD 28 /* FreeBSD */
+#define BSD_AFNUM_INET6_DARWIN 30 /* macOS, iOS, other Darwin-based OSes */
+
+/*
+ * Generate code to match a particular packet type by matching the
+ * link-layer type field or fields in the 802.2 LLC header.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU.
+ */
+static struct block *
+gen_linktype(compiler_state_t *cstate, int proto)
+{
+ struct block *b0, *b1, *b2;
+ const char *description;
+
+ /* are we checking MPLS-encapsulated packets? */
+ if (cstate->label_stack_depth > 0) {
+ switch (proto) {
+ case ETHERTYPE_IP:
+ case PPP_IP:
+ /* FIXME add other L3 proto IDs */
+ return gen_mpls_linktype(cstate, Q_IP);
+
+ case ETHERTYPE_IPV6:
+ case PPP_IPV6:
+ /* FIXME add other L3 proto IDs */
+ return gen_mpls_linktype(cstate, Q_IPV6);
+
+ default:
+ bpf_error(cstate, "unsupported protocol over mpls");
+ /*NOTREACHED*/
+ }
+ }
+
+ switch (cstate->linktype) {
+
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ /* Geneve has an EtherType regardless of whether there is an
+ * L2 header. */
+ if (!cstate->is_geneve)
+ b0 = gen_prevlinkhdr_check(cstate);
+ else
+ b0 = NULL;
+
+ b1 = gen_ether_linktype(cstate, proto);
+ if (b0 != NULL)
+ gen_and(b0, b1);
+ return b1;
+ /*NOTREACHED*/
+
+ case DLT_C_HDLC:
+ switch (proto) {
+
+ case LLCSAP_ISONS:
+ proto = (proto << 8 | LLCSAP_ISONS);
+ /* fall through */
+
+ default:
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+ /*NOTREACHED*/
+ }
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ /*
+ * Check that we have a data frame.
+ */
+ b0 = gen_check_802_11_data_frame(cstate);
+
+ /*
+ * Now check for the specified link-layer type.
+ */
+ b1 = gen_llc_linktype(cstate, proto);
+ gen_and(b0, b1);
+ return b1;
+ /*NOTREACHED*/
+
+ case DLT_FDDI:
+ /*
+ * XXX - check for LLC frames.
+ */
+ return gen_llc_linktype(cstate, proto);
+ /*NOTREACHED*/
+
+ case DLT_IEEE802:
+ /*
+ * XXX - check for LLC PDUs, as per IEEE 802.5.
+ */
+ return gen_llc_linktype(cstate, proto);
+ /*NOTREACHED*/
+
+ case DLT_ATM_RFC1483:
+ case DLT_ATM_CLIP:
+ case DLT_IP_OVER_FC:
+ return gen_llc_linktype(cstate, proto);
+ /*NOTREACHED*/
+
+ case DLT_SUNATM:
+ /*
+ * Check for an LLC-encapsulated version of this protocol;
+ * if we were checking for LANE, linktype would no longer
+ * be DLT_SUNATM.
+ *
+ * Check for LLC encapsulation and then check the protocol.
+ */
+ b0 = gen_atmfield_code_internal(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+ b1 = gen_llc_linktype(cstate, proto);
+ gen_and(b0, b1);
+ return b1;
+ /*NOTREACHED*/
+
+ case DLT_LINUX_SLL:
+ return gen_linux_sll_linktype(cstate, proto);
+ /*NOTREACHED*/
+
+ case DLT_SLIP:
+ case DLT_SLIP_BSDOS:
+ case DLT_RAW:
+ /*
+ * These types don't provide any type field; packets
+ * are always IPv4 or IPv6.
+ *
+ * XXX - for IPv4, check for a version number of 4, and,
+ * for IPv6, check for a version number of 6?
+ */
+ switch (proto) {
+
+ case ETHERTYPE_IP:
+ /* Check for a version number of 4. */
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x40, 0xF0);
+
+ case ETHERTYPE_IPV6:
+ /* Check for a version number of 6. */
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, 0x60, 0xF0);
+
+ default:
+ return gen_false(cstate); /* always false */
+ }
+ /*NOTREACHED*/
+
+ case DLT_IPV4:
+ /*
+ * Raw IPv4, so no type field.
+ */
+ if (proto == ETHERTYPE_IP)
+ return gen_true(cstate); /* always true */
+
+ /* Checking for something other than IPv4; always false */
+ return gen_false(cstate);
+ /*NOTREACHED*/
+
+ case DLT_IPV6:
+ /*
+ * Raw IPv6, so no type field.
+ */
+ if (proto == ETHERTYPE_IPV6)
+ return gen_true(cstate); /* always true */
+
+ /* Checking for something other than IPv6; always false */
+ return gen_false(cstate);
+ /*NOTREACHED*/
+
+ case DLT_PPP:
+ case DLT_PPP_PPPD:
+ case DLT_PPP_SERIAL:
+ case DLT_PPP_ETHER:
+ /*
+ * We use Ethernet protocol types inside libpcap;
+ * map them to the corresponding PPP protocol types.
+ */
+ proto = ethertype_to_ppptype(proto);
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+ /*NOTREACHED*/
+
+ case DLT_PPP_BSDOS:
+ /*
+ * We use Ethernet protocol types inside libpcap;
+ * map them to the corresponding PPP protocol types.
+ */
+ switch (proto) {
+
+ case ETHERTYPE_IP:
+ /*
+ * Also check for Van Jacobson-compressed IP.
+ * XXX - do this for other forms of PPP?
+ */
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_IP);
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJC);
+ gen_or(b0, b1);
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, PPP_VJNC);
+ gen_or(b1, b0);
+ return b0;
+
+ default:
+ proto = ethertype_to_ppptype(proto);
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H,
+ (bpf_int32)proto);
+ }
+ /*NOTREACHED*/
+
+ case DLT_NULL:
+ case DLT_LOOP:
+ case DLT_ENC:
+ switch (proto) {
+
+ case ETHERTYPE_IP:
+ return (gen_loopback_linktype(cstate, AF_INET));
+
+ case ETHERTYPE_IPV6:
+ /*
+ * AF_ values may, unfortunately, be platform-
+ * dependent; AF_INET isn't, because everybody
+ * used 4.2BSD's value, but AF_INET6 is, because
+ * 4.2BSD didn't have a value for it (given that
+ * IPv6 didn't exist back in the early 1980's),
+ * and they all picked their own values.
+ *
+ * This means that, if we're reading from a
+ * savefile, we need to check for all the
+ * possible values.
+ *
+ * If we're doing a live capture, we only need
+ * to check for this platform's value; however,
+ * Npcap uses 24, which isn't Windows's AF_INET6
+ * value. (Given the multiple different values,
+ * programs that read pcap files shouldn't be
+ * checking for their platform's AF_INET6 value
+ * anyway, they should check for all of the
+ * possible values. and they might as well do
+ * that even for live captures.)
+ */
+ if (cstate->bpf_pcap->rfile != NULL) {
+ /*
+ * Savefile - check for all three
+ * possible IPv6 values.
+ */
+ b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_BSD);
+ b1 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_FREEBSD);
+ gen_or(b0, b1);
+ b0 = gen_loopback_linktype(cstate, BSD_AFNUM_INET6_DARWIN);
+ gen_or(b0, b1);
+ return (b1);
+ } else {
+ /*
+ * Live capture, so we only need to
+ * check for the value used on this
+ * platform.
+ */
+#ifdef _WIN32
+ /*
+ * Npcap doesn't use Windows's AF_INET6,
+ * as that collides with AF_IPX on
+ * some BSDs (both have the value 23).
+ * Instead, it uses 24.
+ */
+ return (gen_loopback_linktype(cstate, 24));
+#else /* _WIN32 */
+#ifdef AF_INET6
+ return (gen_loopback_linktype(cstate, AF_INET6));
+#else /* AF_INET6 */
+ /*
+ * I guess this platform doesn't support
+ * IPv6, so we just reject all packets.
+ */
+ return gen_false(cstate);
+#endif /* AF_INET6 */
+#endif /* _WIN32 */
+ }
+
+ default:
+ /*
+ * Not a type on which we support filtering.
+ * XXX - support those that have AF_ values
+ * #defined on this platform, at least?
+ */
+ return gen_false(cstate);
+ }
+
+#ifdef HAVE_NET_PFVAR_H
+ case DLT_PFLOG:
+ /*
+ * af field is host byte order in contrast to the rest of
+ * the packet.
+ */
+ if (proto == ETHERTYPE_IP)
+ return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
+ BPF_B, (bpf_int32)AF_INET));
+ else if (proto == ETHERTYPE_IPV6)
+ return (gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, af),
+ BPF_B, (bpf_int32)AF_INET6));
+ else
+ return gen_false(cstate);
+ /*NOTREACHED*/
+#endif /* HAVE_NET_PFVAR_H */
+
+ case DLT_ARCNET:
+ case DLT_ARCNET_LINUX:
+ /*
+ * XXX should we check for first fragment if the protocol
+ * uses PHDS?
+ */
+ switch (proto) {
+
+ default:
+ return gen_false(cstate);
+
+ case ETHERTYPE_IPV6:
+ return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)ARCTYPE_INET6));
+
+ case ETHERTYPE_IP:
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)ARCTYPE_IP);
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)ARCTYPE_IP_OLD);
+ gen_or(b0, b1);
+ return (b1);
+
+ case ETHERTYPE_ARP:
+ b0 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)ARCTYPE_ARP);
+ b1 = gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)ARCTYPE_ARP_OLD);
+ gen_or(b0, b1);
+ return (b1);
+
+ case ETHERTYPE_REVARP:
+ return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)ARCTYPE_REVARP));
+
+ case ETHERTYPE_ATALK:
+ return (gen_cmp(cstate, OR_LINKTYPE, 0, BPF_B,
+ (bpf_int32)ARCTYPE_ATALK));
+ }
+ /*NOTREACHED*/
+
+ case DLT_LTALK:
+ switch (proto) {
+ case ETHERTYPE_ATALK:
+ return gen_true(cstate);
+ default:
+ return gen_false(cstate);
+ }
+ /*NOTREACHED*/
+
+ case DLT_FRELAY:
+ /*
+ * XXX - assumes a 2-byte Frame Relay header with
+ * DLCI and flags. What if the address is longer?
+ */
+ switch (proto) {
+
+ case ETHERTYPE_IP:
+ /*
+ * Check for the special NLPID for IP.
+ */
+ return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0xcc);
+
+ case ETHERTYPE_IPV6:
+ /*
+ * Check for the special NLPID for IPv6.
+ */
+ return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | 0x8e);
+
+ case LLCSAP_ISONS:
+ /*
+ * Check for several OSI protocols.
+ *
+ * Frame Relay packets typically have an OSI
+ * NLPID at the beginning; we check for each
+ * of them.
+ *
+ * What we check for is the NLPID and a frame
+ * control field of UI, i.e. 0x03 followed
+ * by the NLPID.
+ */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO8473_CLNP);
+ b1 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO9542_ESIS);
+ b2 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | ISO10589_ISIS);
+ gen_or(b1, b2);
+ gen_or(b0, b2);
+ return b2;
+
+ default:
+ return gen_false(cstate);
+ }
+ /*NOTREACHED*/
+
+ case DLT_MFR:
+ bpf_error(cstate, "Multi-link Frame Relay link-layer type filtering not implemented");
+
+ case DLT_JUNIPER_MFR:
+ case DLT_JUNIPER_MLFR:
+ case DLT_JUNIPER_MLPPP:
+ case DLT_JUNIPER_ATM1:
+ case DLT_JUNIPER_ATM2:
+ case DLT_JUNIPER_PPPOE:
+ case DLT_JUNIPER_PPPOE_ATM:
+ case DLT_JUNIPER_GGSN:
+ case DLT_JUNIPER_ES:
+ case DLT_JUNIPER_MONITOR:
+ case DLT_JUNIPER_SERVICES:
+ case DLT_JUNIPER_ETHER:
+ case DLT_JUNIPER_PPP:
+ case DLT_JUNIPER_FRELAY:
+ case DLT_JUNIPER_CHDLC:
+ case DLT_JUNIPER_VP:
+ case DLT_JUNIPER_ST:
+ case DLT_JUNIPER_ISM:
+ case DLT_JUNIPER_VS:
+ case DLT_JUNIPER_SRX_E2E:
+ case DLT_JUNIPER_FIBRECHANNEL:
+ case DLT_JUNIPER_ATM_CEMIC:
+
+ /* just lets verify the magic number for now -
+ * on ATM we may have up to 6 different encapsulations on the wire
+ * and need a lot of heuristics to figure out that the payload
+ * might be;
+ *
+ * FIXME encapsulation specific BPF_ filters
+ */
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x4d474300, 0xffffff00); /* compare the magic number */
+
+ case DLT_BACNET_MS_TP:
+ return gen_mcmp(cstate, OR_LINKHDR, 0, BPF_W, 0x55FF0000, 0xffff0000);
+
+ case DLT_IPNET:
+ return gen_ipnet_linktype(cstate, proto);
+
+ case DLT_LINUX_IRDA:
+ bpf_error(cstate, "IrDA link-layer type filtering not implemented");
+
+ case DLT_DOCSIS:
+ bpf_error(cstate, "DOCSIS link-layer type filtering not implemented");
+
+ case DLT_MTP2:
+ case DLT_MTP2_WITH_PHDR:
+ bpf_error(cstate, "MTP2 link-layer type filtering not implemented");
+
+ case DLT_ERF:
+ bpf_error(cstate, "ERF link-layer type filtering not implemented");
+
+ case DLT_PFSYNC:
+ bpf_error(cstate, "PFSYNC link-layer type filtering not implemented");
+
+ case DLT_LINUX_LAPD:
+ bpf_error(cstate, "LAPD link-layer type filtering not implemented");
+
+ case DLT_USB_FREEBSD:
+ case DLT_USB_LINUX:
+ case DLT_USB_LINUX_MMAPPED:
+ case DLT_USBPCAP:
+ bpf_error(cstate, "USB link-layer type filtering not implemented");
+
+ case DLT_BLUETOOTH_HCI_H4:
+ case DLT_BLUETOOTH_HCI_H4_WITH_PHDR:
+ bpf_error(cstate, "Bluetooth link-layer type filtering not implemented");
+
+ case DLT_CAN20B:
+ case DLT_CAN_SOCKETCAN:
+ bpf_error(cstate, "CAN link-layer type filtering not implemented");
+
+ case DLT_IEEE802_15_4:
+ case DLT_IEEE802_15_4_LINUX:
+ case DLT_IEEE802_15_4_NONASK_PHY:
+ case DLT_IEEE802_15_4_NOFCS:
+ bpf_error(cstate, "IEEE 802.15.4 link-layer type filtering not implemented");
+
+ case DLT_IEEE802_16_MAC_CPS_RADIO:
+ bpf_error(cstate, "IEEE 802.16 link-layer type filtering not implemented");
+
+ case DLT_SITA:
+ bpf_error(cstate, "SITA link-layer type filtering not implemented");
+
+ case DLT_RAIF1:
+ bpf_error(cstate, "RAIF1 link-layer type filtering not implemented");
+
+ case DLT_IPMB_KONTRON:
+ case DLT_IPMB_LINUX:
+ bpf_error(cstate, "IPMB link-layer type filtering not implemented");
+
+ case DLT_AX25_KISS:
+ bpf_error(cstate, "AX.25 link-layer type filtering not implemented");
+
+ case DLT_NFLOG:
+ /* Using the fixed-size NFLOG header it is possible to tell only
+ * the address family of the packet, other meaningful data is
+ * either missing or behind TLVs.
+ */
+ bpf_error(cstate, "NFLOG link-layer type filtering not implemented");
+
+ default:
+ /*
+ * Does this link-layer header type have a field
+ * indicating the type of the next protocol? If
+ * so, off_linktype.constant_part will be the offset of that
+ * field in the packet; if not, it will be OFFSET_NOT_SET.
+ */
+ if (cstate->off_linktype.constant_part != OFFSET_NOT_SET) {
+ /*
+ * Yes; assume it's an Ethernet type. (If
+ * it's not, it needs to be handled specially
+ * above.)
+ */
+ return gen_cmp(cstate, OR_LINKTYPE, 0, BPF_H, (bpf_int32)proto);
+ /*NOTREACHED */
+ } else {
+ /*
+ * No; report an error.
+ */
+ description = pcap_datalink_val_to_description_or_dlt(cstate->linktype);
+ bpf_error(cstate, "%s link-layer type filtering not implemented",
+ description);
+ /*NOTREACHED */
+ }
+ }
+}
+
+/*
+ * Check for an LLC SNAP packet with a given organization code and
+ * protocol type; we check the entire contents of the 802.2 LLC and
+ * snap headers, checking for DSAP and SSAP of SNAP and a control
+ * field of 0x03 in the LLC header, and for the specified organization
+ * code and protocol type in the SNAP header.
+ */
+static struct block *
+gen_snap(compiler_state_t *cstate, bpf_u_int32 orgcode, bpf_u_int32 ptype)
+{
+ u_char snapblock[8];
+
+ snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */
+ snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */
+ snapblock[2] = 0x03; /* control = UI */
+ snapblock[3] = (u_char)(orgcode >> 16); /* upper 8 bits of organization code */
+ snapblock[4] = (u_char)(orgcode >> 8); /* middle 8 bits of organization code */
+ snapblock[5] = (u_char)(orgcode >> 0); /* lower 8 bits of organization code */
+ snapblock[6] = (u_char)(ptype >> 8); /* upper 8 bits of protocol type */
+ snapblock[7] = (u_char)(ptype >> 0); /* lower 8 bits of protocol type */
+ return gen_bcmp(cstate, OR_LLC, 0, 8, snapblock);
+}
+
+/*
+ * Generate code to match frames with an LLC header.
+ */
+static struct block *
+gen_llc_internal(compiler_state_t *cstate)
+{
+ struct block *b0, *b1;
+
+ switch (cstate->linktype) {
+
+ case DLT_EN10MB:
+ /*
+ * We check for an Ethernet type field less than
+ * 1500, which means it's an 802.3 length field.
+ */
+ b0 = gen_cmp_gt(cstate, OR_LINKTYPE, 0, BPF_H, ETHERMTU);
+ gen_not(b0);
+
+ /*
+ * Now check for the purported DSAP and SSAP not being
+ * 0xFF, to rule out NetWare-over-802.3.
+ */
+ b1 = gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_int32)0xFFFF);
+ gen_not(b1);
+ gen_and(b0, b1);
+ return b1;
+
+ case DLT_SUNATM:
+ /*
+ * We check for LLC traffic.
+ */
+ b0 = gen_atmtype_llc(cstate);
+ return b0;
+
+ case DLT_IEEE802: /* Token Ring */
+ /*
+ * XXX - check for LLC frames.
+ */
+ return gen_true(cstate);
+
+ case DLT_FDDI:
+ /*
+ * XXX - check for LLC frames.
+ */
+ return gen_true(cstate);
+
+ case DLT_ATM_RFC1483:
+ /*
+ * For LLC encapsulation, these are defined to have an
+ * 802.2 LLC header.
+ *
+ * For VC encapsulation, they don't, but there's no
+ * way to check for that; the protocol used on the VC
+ * is negotiated out of band.
+ */
+ return gen_true(cstate);
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_PPI:
+ /*
+ * Check that we have a data frame.
+ */
+ b0 = gen_check_802_11_data_frame(cstate);
+ return b0;
+
+ default:
+ bpf_error(cstate, "'llc' not supported for %s",
+ pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+ /*NOTREACHED*/
+ }
+}
+
+struct block *
+gen_llc(compiler_state_t *cstate)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ return gen_llc_internal(cstate);
+}
+
+struct block *
+gen_llc_i(compiler_state_t *cstate)
+{
+ struct block *b0, *b1;
+ struct slist *s;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc_internal(cstate);
+
+ /*
+ * Load the control byte and test the low-order bit; it must
+ * be clear for I frames.
+ */
+ s = gen_load_a(cstate, OR_LLC, 2, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x01;
+ b1->stmts = s;
+ gen_not(b1);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_s(compiler_state_t *cstate)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc_internal(cstate);
+
+ /*
+ * Now compare the low-order 2 bit of the control byte against
+ * the appropriate value for S frames.
+ */
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_S_FMT, 0x03);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_u(compiler_state_t *cstate)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc_internal(cstate);
+
+ /*
+ * Now compare the low-order 2 bit of the control byte against
+ * the appropriate value for U frames.
+ */
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, LLC_U_FMT, 0x03);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_s_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc_internal(cstate);
+
+ /*
+ * Now check for an S frame with the appropriate type.
+ */
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_S_CMD_MASK);
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_llc_u_subtype(compiler_state_t *cstate, bpf_u_int32 subtype)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Check whether this is an LLC frame.
+ */
+ b0 = gen_llc_internal(cstate);
+
+ /*
+ * Now check for a U frame with the appropriate type.
+ */
+ b1 = gen_mcmp(cstate, OR_LLC, 2, BPF_B, subtype, LLC_U_CMD_MASK);
+ gen_and(b0, b1);
+ return b1;
+}
+
+/*
+ * Generate code to match a particular packet type, for link-layer types
+ * using 802.2 LLC headers.
+ *
+ * This is *NOT* used for Ethernet; "gen_ether_linktype()" is used
+ * for that - it handles the D/I/X Ethernet vs. 802.3+802.2 issues.
+ *
+ * "proto" is an Ethernet type value, if > ETHERMTU, or an LLC SAP
+ * value, if <= ETHERMTU. We use that to determine whether to
+ * match the DSAP or both DSAP and LSAP or to check the OUI and
+ * protocol ID in a SNAP header.
+ */
+static struct block *
+gen_llc_linktype(compiler_state_t *cstate, int proto)
+{
+ /*
+ * XXX - handle token-ring variable-length header.
+ */
+ switch (proto) {
+
+ case LLCSAP_IP:
+ case LLCSAP_ISONS:
+ case LLCSAP_NETBEUI:
+ /*
+ * XXX - should we check both the DSAP and the
+ * SSAP, like this, or should we check just the
+ * DSAP, as we do for other SAP values?
+ */
+ return gen_cmp(cstate, OR_LLC, 0, BPF_H, (bpf_u_int32)
+ ((proto << 8) | proto));
+
+ case LLCSAP_IPX:
+ /*
+ * XXX - are there ever SNAP frames for IPX on
+ * non-Ethernet 802.x networks?
+ */
+ return gen_cmp(cstate, OR_LLC, 0, BPF_B,
+ (bpf_int32)LLCSAP_IPX);
+
+ case ETHERTYPE_ATALK:
+ /*
+ * 802.2-encapsulated ETHERTYPE_ATALK packets are
+ * SNAP packets with an organization code of
+ * 0x080007 (Apple, for Appletalk) and a protocol
+ * type of ETHERTYPE_ATALK (Appletalk).
+ *
+ * XXX - check for an organization code of
+ * encapsulated Ethernet as well?
+ */
+ return gen_snap(cstate, 0x080007, ETHERTYPE_ATALK);
+
+ default:
+ /*
+ * XXX - we don't have to check for IPX 802.3
+ * here, but should we check for the IPX Ethertype?
+ */
+ if (proto <= ETHERMTU) {
+ /*
+ * This is an LLC SAP value, so check
+ * the DSAP.
+ */
+ return gen_cmp(cstate, OR_LLC, 0, BPF_B, (bpf_int32)proto);
+ } else {
+ /*
+ * This is an Ethernet type; we assume that it's
+ * unlikely that it'll appear in the right place
+ * at random, and therefore check only the
+ * location that would hold the Ethernet type
+ * in a SNAP frame with an organization code of
+ * 0x000000 (encapsulated Ethernet).
+ *
+ * XXX - if we were to check for the SNAP DSAP and
+ * LSAP, as per XXX, and were also to check for an
+ * organization code of 0x000000 (encapsulated
+ * Ethernet), we'd do
+ *
+ * return gen_snap(cstate, 0x000000, proto);
+ *
+ * here; for now, we don't, as per the above.
+ * I don't know whether it's worth the extra CPU
+ * time to do the right check or not.
+ */
+ return gen_cmp(cstate, OR_LLC, 6, BPF_H, (bpf_int32)proto);
+ }
+ }
+}
+
+static struct block *
+gen_hostop(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
+ int dir, int proto, u_int src_off, u_int dst_off)
+{
+ struct block *b0, *b1;
+ u_int offset;
+
+ switch (dir) {
+
+ case Q_SRC:
+ offset = src_off;
+ break;
+
+ case Q_DST:
+ offset = dst_off;
+ break;
+
+ case Q_AND:
+ b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_hostop(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+ b0 = gen_linktype(cstate, proto);
+ b1 = gen_mcmp(cstate, OR_LINKPL, offset, BPF_W, (bpf_int32)addr, mask);
+ gen_and(b0, b1);
+ return b1;
+}
+
+#ifdef INET6
+static struct block *
+gen_hostop6(compiler_state_t *cstate, struct in6_addr *addr,
+ struct in6_addr *mask, int dir, int proto, u_int src_off, u_int dst_off)
+{
+ struct block *b0, *b1;
+ u_int offset;
+ uint32_t *a, *m;
+
+ switch (dir) {
+
+ case Q_SRC:
+ offset = src_off;
+ break;
+
+ case Q_DST:
+ offset = dst_off;
+ break;
+
+ case Q_AND:
+ b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_hostop6(cstate, addr, mask, Q_SRC, proto, src_off, dst_off);
+ b1 = gen_hostop6(cstate, addr, mask, Q_DST, proto, src_off, dst_off);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+ /* this order is important */
+ a = (uint32_t *)addr;
+ m = (uint32_t *)mask;
+ b1 = gen_mcmp(cstate, OR_LINKPL, offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3]));
+ b0 = gen_mcmp(cstate, OR_LINKPL, offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2]));
+ gen_and(b0, b1);
+ b0 = gen_mcmp(cstate, OR_LINKPL, offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1]));
+ gen_and(b0, b1);
+ b0 = gen_mcmp(cstate, OR_LINKPL, offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0]));
+ gen_and(b0, b1);
+ b0 = gen_linktype(cstate, proto);
+ gen_and(b0, b1);
+ return b1;
+}
+#endif
+
+static struct block *
+gen_ehostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
+{
+ register struct block *b0, *b1;
+
+ switch (dir) {
+ case Q_SRC:
+ return gen_bcmp(cstate, OR_LINKHDR, 6, 6, eaddr);
+
+ case Q_DST:
+ return gen_bcmp(cstate, OR_LINKHDR, 0, 6, eaddr);
+
+ case Q_AND:
+ b0 = gen_ehostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ehostop(cstate, eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_ehostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ehostop(cstate, eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11 with 802.11 headers");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11 with 802.11 headers");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11 with 802.11 headers");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11 with 802.11 headers");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is only supported on 802.11 with 802.11 headers");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is only supported on 802.11 with 802.11 headers");
+ /*NOTREACHED*/
+ }
+ abort();
+ /*NOTREACHED*/
+}
+
+/*
+ * Like gen_ehostop, but for DLT_FDDI
+ */
+static struct block *
+gen_fhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
+{
+ struct block *b0, *b1;
+
+ switch (dir) {
+ case Q_SRC:
+ return gen_bcmp(cstate, OR_LINKHDR, 6 + 1 + cstate->pcap_fddipad, 6, eaddr);
+
+ case Q_DST:
+ return gen_bcmp(cstate, OR_LINKHDR, 0 + 1 + cstate->pcap_fddipad, 6, eaddr);
+
+ case Q_AND:
+ b0 = gen_fhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_fhostop(cstate, eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_fhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_fhostop(cstate, eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is only supported on 802.11");
+ /*NOTREACHED*/
+ }
+ abort();
+ /*NOTREACHED*/
+}
+
+/*
+ * Like gen_ehostop, but for DLT_IEEE802 (Token Ring)
+ */
+static struct block *
+gen_thostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
+{
+ register struct block *b0, *b1;
+
+ switch (dir) {
+ case Q_SRC:
+ return gen_bcmp(cstate, OR_LINKHDR, 8, 6, eaddr);
+
+ case Q_DST:
+ return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
+
+ case Q_AND:
+ b0 = gen_thostop(cstate, eaddr, Q_SRC);
+ b1 = gen_thostop(cstate, eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_thostop(cstate, eaddr, Q_SRC);
+ b1 = gen_thostop(cstate, eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is only supported on 802.11");
+ /*NOTREACHED*/
+ }
+ abort();
+ /*NOTREACHED*/
+}
+
+/*
+ * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) and
+ * various 802.11 + radio headers.
+ */
+static struct block *
+gen_wlanhostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
+{
+ register struct block *b0, *b1, *b2;
+ register struct slist *s;
+
+#ifdef ENABLE_WLAN_FILTERING_PATCH
+ /*
+ * TODO GV 20070613
+ * We need to disable the optimizer because the optimizer is buggy
+ * and wipes out some LD instructions generated by the below
+ * code to validate the Frame Control bits
+ */
+ cstate->no_optimize = 1;
+#endif /* ENABLE_WLAN_FILTERING_PATCH */
+
+ switch (dir) {
+ case Q_SRC:
+ /*
+ * Oh, yuk.
+ *
+ * For control frames, there is no SA.
+ *
+ * For management frames, SA is at an
+ * offset of 10 from the beginning of
+ * the packet.
+ *
+ * For data frames, SA is at an offset
+ * of 10 from the beginning of the packet
+ * if From DS is clear, at an offset of
+ * 16 from the beginning of the packet
+ * if From DS is set and To DS is clear,
+ * and an offset of 24 from the beginning
+ * of the packet if From DS is set and To DS
+ * is set.
+ */
+
+ /*
+ * Generate the tests to be done for data frames
+ * with From DS set.
+ *
+ * First, check for To DS set, i.e. check "link[1] & 0x01".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x01; /* To DS */
+ b1->stmts = s;
+
+ /*
+ * If To DS is set, the SA is at 24.
+ */
+ b0 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
+ gen_and(b1, b0);
+
+ /*
+ * Now, check for To DS not set, i.e. check
+ * "!(link[1] & 0x01)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
+ b2->s.k = 0x01; /* To DS */
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * If To DS is not set, the SA is at 16.
+ */
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
+ gen_and(b2, b1);
+
+ /*
+ * Now OR together the last two checks. That gives
+ * the complete set of checks for data frames with
+ * From DS set.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * Now check for From DS being set, and AND that with
+ * the ORed-together checks.
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x02; /* From DS */
+ b1->stmts = s;
+ gen_and(b1, b0);
+
+ /*
+ * Now check for data frames with From DS not set.
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
+ b2->s.k = 0x02; /* From DS */
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * If From DS isn't set, the SA is at 10.
+ */
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+ gen_and(b2, b1);
+
+ /*
+ * Now OR together the checks for data frames with
+ * From DS not set and for data frames with From DS
+ * set; that gives the checks done for data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * Now check for a data frame.
+ * I.e, check "link[0] & 0x08".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x08;
+ b1->stmts = s;
+
+ /*
+ * AND that with the checks done for data frames.
+ */
+ gen_and(b1, b0);
+
+ /*
+ * If the high-order bit of the type value is 0, this
+ * is a management frame.
+ * I.e, check "!(link[0] & 0x08)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
+ b2->s.k = 0x08;
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * For management frames, the SA is at 10.
+ */
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+ gen_and(b2, b1);
+
+ /*
+ * OR that with the checks done for data frames.
+ * That gives the checks done for management and
+ * data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * If the low-order bit of the type value is 1,
+ * this is either a control frame or a frame
+ * with a reserved type, and thus not a
+ * frame with an SA.
+ *
+ * I.e., check "!(link[0] & 0x04)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x04;
+ b1->stmts = s;
+ gen_not(b1);
+
+ /*
+ * AND that with the checks for data and management
+ * frames.
+ */
+ gen_and(b1, b0);
+ return b0;
+
+ case Q_DST:
+ /*
+ * Oh, yuk.
+ *
+ * For control frames, there is no DA.
+ *
+ * For management frames, DA is at an
+ * offset of 4 from the beginning of
+ * the packet.
+ *
+ * For data frames, DA is at an offset
+ * of 4 from the beginning of the packet
+ * if To DS is clear and at an offset of
+ * 16 from the beginning of the packet
+ * if To DS is set.
+ */
+
+ /*
+ * Generate the tests to be done for data frames.
+ *
+ * First, check for To DS set, i.e. "link[1] & 0x01".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x01; /* To DS */
+ b1->stmts = s;
+
+ /*
+ * If To DS is set, the DA is at 16.
+ */
+ b0 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
+ gen_and(b1, b0);
+
+ /*
+ * Now, check for To DS not set, i.e. check
+ * "!(link[1] & 0x01)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
+ b2->s.k = 0x01; /* To DS */
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * If To DS is not set, the DA is at 4.
+ */
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
+ gen_and(b2, b1);
+
+ /*
+ * Now OR together the last two checks. That gives
+ * the complete set of checks for data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * Now check for a data frame.
+ * I.e, check "link[0] & 0x08".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x08;
+ b1->stmts = s;
+
+ /*
+ * AND that with the checks done for data frames.
+ */
+ gen_and(b1, b0);
+
+ /*
+ * If the high-order bit of the type value is 0, this
+ * is a management frame.
+ * I.e, check "!(link[0] & 0x08)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
+ b2->s.k = 0x08;
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * For management frames, the DA is at 4.
+ */
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
+ gen_and(b2, b1);
+
+ /*
+ * OR that with the checks done for data frames.
+ * That gives the checks done for management and
+ * data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * If the low-order bit of the type value is 1,
+ * this is either a control frame or a frame
+ * with a reserved type, and thus not a
+ * frame with an SA.
+ *
+ * I.e., check "!(link[0] & 0x04)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x04;
+ b1->stmts = s;
+ gen_not(b1);
+
+ /*
+ * AND that with the checks for data and management
+ * frames.
+ */
+ gen_and(b1, b0);
+ return b0;
+
+ case Q_AND:
+ b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_wlanhostop(cstate, eaddr, Q_SRC);
+ b1 = gen_wlanhostop(cstate, eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ /*
+ * XXX - add BSSID keyword?
+ */
+ case Q_ADDR1:
+ return (gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr));
+
+ case Q_ADDR2:
+ /*
+ * Not present in CTS or ACK control frames.
+ */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ IEEE80211_FC0_TYPE_MASK);
+ gen_not(b0);
+ b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b1);
+ b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b2);
+ gen_and(b1, b2);
+ gen_or(b0, b2);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+ gen_and(b2, b1);
+ return b1;
+
+ case Q_ADDR3:
+ /*
+ * Not present in control frames.
+ */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ IEEE80211_FC0_TYPE_MASK);
+ gen_not(b0);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 16, 6, eaddr);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_ADDR4:
+ /*
+ * Present only if the direction mask has both "From DS"
+ * and "To DS" set. Neither control frames nor management
+ * frames should have both of those set, so we don't
+ * check the frame type.
+ */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B,
+ IEEE80211_FC1_DIR_DSTODS, IEEE80211_FC1_DIR_MASK);
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 24, 6, eaddr);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_RA:
+ /*
+ * Not present in management frames; addr1 in other
+ * frames.
+ */
+
+ /*
+ * If the high-order bit of the type value is 0, this
+ * is a management frame.
+ * I.e, check "(link[0] & 0x08)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x08;
+ b1->stmts = s;
+
+ /*
+ * Check addr1.
+ */
+ b0 = gen_bcmp(cstate, OR_LINKHDR, 4, 6, eaddr);
+
+ /*
+ * AND that with the check of addr1.
+ */
+ gen_and(b1, b0);
+ return (b0);
+
+ case Q_TA:
+ /*
+ * Not present in management frames; addr2, if present,
+ * in other frames.
+ */
+
+ /*
+ * Not present in CTS or ACK control frames.
+ */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_TYPE_CTL,
+ IEEE80211_FC0_TYPE_MASK);
+ gen_not(b0);
+ b1 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_CTS,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b1);
+ b2 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, IEEE80211_FC0_SUBTYPE_ACK,
+ IEEE80211_FC0_SUBTYPE_MASK);
+ gen_not(b2);
+ gen_and(b1, b2);
+ gen_or(b0, b2);
+
+ /*
+ * If the high-order bit of the type value is 0, this
+ * is a management frame.
+ * I.e, check "(link[0] & 0x08)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x08;
+ b1->stmts = s;
+
+ /*
+ * AND that with the check for frames other than
+ * CTS and ACK frames.
+ */
+ gen_and(b1, b2);
+
+ /*
+ * Check addr2.
+ */
+ b1 = gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+ gen_and(b2, b1);
+ return b1;
+ }
+ abort();
+ /*NOTREACHED*/
+}
+
+/*
+ * Like gen_ehostop, but for RFC 2625 IP-over-Fibre-Channel.
+ * (We assume that the addresses are IEEE 48-bit MAC addresses,
+ * as the RFC states.)
+ */
+static struct block *
+gen_ipfchostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
+{
+ register struct block *b0, *b1;
+
+ switch (dir) {
+ case Q_SRC:
+ return gen_bcmp(cstate, OR_LINKHDR, 10, 6, eaddr);
+
+ case Q_DST:
+ return gen_bcmp(cstate, OR_LINKHDR, 2, 6, eaddr);
+
+ case Q_AND:
+ b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_ipfchostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ipfchostop(cstate, eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is only supported on 802.11");
+ /*NOTREACHED*/
+ }
+ abort();
+ /*NOTREACHED*/
+}
+
+/*
+ * This is quite tricky because there may be pad bytes in front of the
+ * DECNET header, and then there are two possible data packet formats that
+ * carry both src and dst addresses, plus 5 packet types in a format that
+ * carries only the src node, plus 2 types that use a different format and
+ * also carry just the src node.
+ *
+ * Yuck.
+ *
+ * Instead of doing those all right, we just look for data packets with
+ * 0 or 1 bytes of padding. If you want to look at other packets, that
+ * will require a lot more hacking.
+ *
+ * To add support for filtering on DECNET "areas" (network numbers)
+ * one would want to add a "mask" argument to this routine. That would
+ * make the filter even more inefficient, although one could be clever
+ * and not generate masking instructions if the mask is 0xFFFF.
+ */
+static struct block *
+gen_dnhostop(compiler_state_t *cstate, bpf_u_int32 addr, int dir)
+{
+ struct block *b0, *b1, *b2, *tmp;
+ u_int offset_lh; /* offset if long header is received */
+ u_int offset_sh; /* offset if short header is received */
+
+ switch (dir) {
+
+ case Q_DST:
+ offset_sh = 1; /* follows flags */
+ offset_lh = 7; /* flgs,darea,dsubarea,HIORD */
+ break;
+
+ case Q_SRC:
+ offset_sh = 3; /* follows flags, dstnode */
+ offset_lh = 15; /* flgs,darea,dsubarea,did,sarea,ssub,HIORD */
+ break;
+
+ case Q_AND:
+ /* Inefficient because we do our Calvinball dance twice */
+ b0 = gen_dnhostop(cstate, addr, Q_SRC);
+ b1 = gen_dnhostop(cstate, addr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ /* Inefficient because we do our Calvinball dance twice */
+ b0 = gen_dnhostop(cstate, addr, Q_SRC);
+ b1 = gen_dnhostop(cstate, addr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for addresses other than 802.11 MAC addresses");
+ /*NOTREACHED*/
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+ b0 = gen_linktype(cstate, ETHERTYPE_DN);
+ /* Check for pad = 1, long header case */
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
+ (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF));
+ b1 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_lh,
+ BPF_H, (bpf_int32)ntohs((u_short)addr));
+ gen_and(tmp, b1);
+ /* Check for pad = 0, long header case */
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7);
+ b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_lh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+ gen_and(tmp, b2);
+ gen_or(b2, b1);
+ /* Check for pad = 1, short header case */
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_H,
+ (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF));
+ b2 = gen_cmp(cstate, OR_LINKPL, 2 + 1 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+ gen_and(tmp, b2);
+ gen_or(b2, b1);
+ /* Check for pad = 0, short header case */
+ tmp = gen_mcmp(cstate, OR_LINKPL, 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7);
+ b2 = gen_cmp(cstate, OR_LINKPL, 2 + offset_sh, BPF_H, (bpf_int32)ntohs((u_short)addr));
+ gen_and(tmp, b2);
+ gen_or(b2, b1);
+
+ /* Combine with test for cstate->linktype */
+ gen_and(b0, b1);
+ return b1;
+}
+
+/*
+ * Generate a check for IPv4 or IPv6 for MPLS-encapsulated packets;
+ * test the bottom-of-stack bit, and then check the version number
+ * field in the IP header.
+ */
+static struct block *
+gen_mpls_linktype(compiler_state_t *cstate, int proto)
+{
+ struct block *b0, *b1;
+
+ switch (proto) {
+
+ case Q_IP:
+ /* match the bottom-of-stack bit */
+ b0 = gen_mcmp(cstate, OR_LINKPL, (u_int)-2, BPF_B, 0x01, 0x01);
+ /* match the IPv4 version number */
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x40, 0xf0);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_IPV6:
+ /* match the bottom-of-stack bit */
+ b0 = gen_mcmp(cstate, OR_LINKPL, (u_int)-2, BPF_B, 0x01, 0x01);
+ /* match the IPv4 version number */
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_B, 0x60, 0xf0);
+ gen_and(b0, b1);
+ return b1;
+
+ default:
+ abort();
+ }
+}
+
+static struct block *
+gen_host(compiler_state_t *cstate, bpf_u_int32 addr, bpf_u_int32 mask,
+ int proto, int dir, int type)
+{
+ struct block *b0, *b1;
+ const char *typestr;
+
+ if (type == Q_NET)
+ typestr = "net";
+ else
+ typestr = "host";
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ b0 = gen_host(cstate, addr, mask, Q_IP, dir, type);
+ /*
+ * Only check for non-IPv4 addresses if we're not
+ * checking MPLS-encapsulated packets.
+ */
+ if (cstate->label_stack_depth == 0) {
+ b1 = gen_host(cstate, addr, mask, Q_ARP, dir, type);
+ gen_or(b0, b1);
+ b0 = gen_host(cstate, addr, mask, Q_RARP, dir, type);
+ gen_or(b1, b0);
+ }
+ return b0;
+
+ case Q_LINK:
+ bpf_error(cstate, "link-layer modifier applied to %s", typestr);
+
+ case Q_IP:
+ return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_IP, 12, 16);
+
+ case Q_RARP:
+ return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_REVARP, 14, 24);
+
+ case Q_ARP:
+ return gen_hostop(cstate, addr, mask, dir, ETHERTYPE_ARP, 14, 24);
+
+ case Q_SCTP:
+ bpf_error(cstate, "'sctp' modifier applied to %s", typestr);
+
+ case Q_TCP:
+ bpf_error(cstate, "'tcp' modifier applied to %s", typestr);
+
+ case Q_UDP:
+ bpf_error(cstate, "'udp' modifier applied to %s", typestr);
+
+ case Q_ICMP:
+ bpf_error(cstate, "'icmp' modifier applied to %s", typestr);
+
+ case Q_IGMP:
+ bpf_error(cstate, "'igmp' modifier applied to %s", typestr);
+
+ case Q_IGRP:
+ bpf_error(cstate, "'igrp' modifier applied to %s", typestr);
+
+ case Q_ATALK:
+ bpf_error(cstate, "AppleTalk host filtering not implemented");
+
+ case Q_DECNET:
+ return gen_dnhostop(cstate, addr, dir);
+
+ case Q_LAT:
+ bpf_error(cstate, "LAT host filtering not implemented");
+
+ case Q_SCA:
+ bpf_error(cstate, "SCA host filtering not implemented");
+
+ case Q_MOPRC:
+ bpf_error(cstate, "MOPRC host filtering not implemented");
+
+ case Q_MOPDL:
+ bpf_error(cstate, "MOPDL host filtering not implemented");
+
+ case Q_IPV6:
+ bpf_error(cstate, "'ip6' modifier applied to ip host");
+
+ case Q_ICMPV6:
+ bpf_error(cstate, "'icmp6' modifier applied to %s", typestr);
+
+ case Q_AH:
+ bpf_error(cstate, "'ah' modifier applied to %s", typestr);
+
+ case Q_ESP:
+ bpf_error(cstate, "'esp' modifier applied to %s", typestr);
+
+ case Q_PIM:
+ bpf_error(cstate, "'pim' modifier applied to %s", typestr);
+
+ case Q_VRRP:
+ bpf_error(cstate, "'vrrp' modifier applied to %s", typestr);
+
+ case Q_AARP:
+ bpf_error(cstate, "AARP host filtering not implemented");
+
+ case Q_ISO:
+ bpf_error(cstate, "ISO host filtering not implemented");
+
+ case Q_ESIS:
+ bpf_error(cstate, "'esis' modifier applied to %s", typestr);
+
+ case Q_ISIS:
+ bpf_error(cstate, "'isis' modifier applied to %s", typestr);
+
+ case Q_CLNP:
+ bpf_error(cstate, "'clnp' modifier applied to %s", typestr);
+
+ case Q_STP:
+ bpf_error(cstate, "'stp' modifier applied to %s", typestr);
+
+ case Q_IPX:
+ bpf_error(cstate, "IPX host filtering not implemented");
+
+ case Q_NETBEUI:
+ bpf_error(cstate, "'netbeui' modifier applied to %s", typestr);
+
+ case Q_ISIS_L1:
+ bpf_error(cstate, "'l1' modifier applied to %s", typestr);
+
+ case Q_ISIS_L2:
+ bpf_error(cstate, "'l2' modifier applied to %s", typestr);
+
+ case Q_ISIS_IIH:
+ bpf_error(cstate, "'iih' modifier applied to %s", typestr);
+
+ case Q_ISIS_SNP:
+ bpf_error(cstate, "'snp' modifier applied to %s", typestr);
+
+ case Q_ISIS_CSNP:
+ bpf_error(cstate, "'csnp' modifier applied to %s", typestr);
+
+ case Q_ISIS_PSNP:
+ bpf_error(cstate, "'psnp' modifier applied to %s", typestr);
+
+ case Q_ISIS_LSP:
+ bpf_error(cstate, "'lsp' modifier applied to %s", typestr);
+
+ case Q_RADIO:
+ bpf_error(cstate, "'radio' modifier applied to %s", typestr);
+
+ case Q_CARP:
+ bpf_error(cstate, "'carp' modifier applied to %s", typestr);
+
+ default:
+ abort();
+ }
+ /*NOTREACHED*/
+}
+
+#ifdef INET6
+static struct block *
+gen_host6(compiler_state_t *cstate, struct in6_addr *addr,
+ struct in6_addr *mask, int proto, int dir, int type)
+{
+ const char *typestr;
+
+ if (type == Q_NET)
+ typestr = "net";
+ else
+ typestr = "host";
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ return gen_host6(cstate, addr, mask, Q_IPV6, dir, type);
+
+ case Q_LINK:
+ bpf_error(cstate, "link-layer modifier applied to ip6 %s", typestr);
+
+ case Q_IP:
+ bpf_error(cstate, "'ip' modifier applied to ip6 %s", typestr);
+
+ case Q_RARP:
+ bpf_error(cstate, "'rarp' modifier applied to ip6 %s", typestr);
+
+ case Q_ARP:
+ bpf_error(cstate, "'arp' modifier applied to ip6 %s", typestr);
+
+ case Q_SCTP:
+ bpf_error(cstate, "'sctp' modifier applied to ip6 %s", typestr);
+
+ case Q_TCP:
+ bpf_error(cstate, "'tcp' modifier applied to ip6 %s", typestr);
+
+ case Q_UDP:
+ bpf_error(cstate, "'udp' modifier applied to ip6 %s", typestr);
+
+ case Q_ICMP:
+ bpf_error(cstate, "'icmp' modifier applied to ip6 %s", typestr);
+
+ case Q_IGMP:
+ bpf_error(cstate, "'igmp' modifier applied to ip6 %s", typestr);
+
+ case Q_IGRP:
+ bpf_error(cstate, "'igrp' modifier applied to ip6 %s", typestr);
+
+ case Q_ATALK:
+ bpf_error(cstate, "AppleTalk modifier applied to ip6 %s", typestr);
+
+ case Q_DECNET:
+ bpf_error(cstate, "'decnet' modifier applied to ip6 %s", typestr);
+
+ case Q_LAT:
+ bpf_error(cstate, "'lat' modifier applied to ip6 %s", typestr);
+
+ case Q_SCA:
+ bpf_error(cstate, "'sca' modifier applied to ip6 %s", typestr);
+
+ case Q_MOPRC:
+ bpf_error(cstate, "'moprc' modifier applied to ip6 %s", typestr);
+
+ case Q_MOPDL:
+ bpf_error(cstate, "'mopdl' modifier applied to ip6 %s", typestr);
+
+ case Q_IPV6:
+ return gen_hostop6(cstate, addr, mask, dir, ETHERTYPE_IPV6, 8, 24);
+
+ case Q_ICMPV6:
+ bpf_error(cstate, "'icmp6' modifier applied to ip6 %s", typestr);
+
+ case Q_AH:
+ bpf_error(cstate, "'ah' modifier applied to ip6 %s", typestr);
+
+ case Q_ESP:
+ bpf_error(cstate, "'esp' modifier applied to ip6 %s", typestr);
+
+ case Q_PIM:
+ bpf_error(cstate, "'pim' modifier applied to ip6 %s", typestr);
+
+ case Q_VRRP:
+ bpf_error(cstate, "'vrrp' modifier applied to ip6 %s", typestr);
+
+ case Q_AARP:
+ bpf_error(cstate, "'aarp' modifier applied to ip6 %s", typestr);
+
+ case Q_ISO:
+ bpf_error(cstate, "'iso' modifier applied to ip6 %s", typestr);
+
+ case Q_ESIS:
+ bpf_error(cstate, "'esis' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS:
+ bpf_error(cstate, "'isis' modifier applied to ip6 %s", typestr);
+
+ case Q_CLNP:
+ bpf_error(cstate, "'clnp' modifier applied to ip6 %s", typestr);
+
+ case Q_STP:
+ bpf_error(cstate, "'stp' modifier applied to ip6 %s", typestr);
+
+ case Q_IPX:
+ bpf_error(cstate, "'ipx' modifier applied to ip6 %s", typestr);
+
+ case Q_NETBEUI:
+ bpf_error(cstate, "'netbeui' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_L1:
+ bpf_error(cstate, "'l1' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_L2:
+ bpf_error(cstate, "'l2' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_IIH:
+ bpf_error(cstate, "'iih' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_SNP:
+ bpf_error(cstate, "'snp' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_CSNP:
+ bpf_error(cstate, "'csnp' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_PSNP:
+ bpf_error(cstate, "'psnp' modifier applied to ip6 %s", typestr);
+
+ case Q_ISIS_LSP:
+ bpf_error(cstate, "'lsp' modifier applied to ip6 %s", typestr);
+
+ case Q_RADIO:
+ bpf_error(cstate, "'radio' modifier applied to ip6 %s", typestr);
+
+ case Q_CARP:
+ bpf_error(cstate, "'carp' modifier applied to ip6 %s", typestr);
+
+ default:
+ abort();
+ }
+ /*NOTREACHED*/
+}
+#endif
+
+#ifndef INET6
+static struct block *
+gen_gateway(compiler_state_t *cstate, const u_char *eaddr,
+ struct addrinfo *alist, int proto, int dir)
+{
+ struct block *b0, *b1, *tmp;
+ struct addrinfo *ai;
+ struct sockaddr_in *sin;
+
+ if (dir != 0)
+ bpf_error(cstate, "direction applied to 'gateway'");
+
+ switch (proto) {
+ case Q_DEFAULT:
+ case Q_IP:
+ case Q_ARP:
+ case Q_RARP:
+ switch (cstate->linktype) {
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ b1 = gen_prevlinkhdr_check(cstate);
+ b0 = gen_ehostop(cstate, eaddr, Q_OR);
+ if (b1 != NULL)
+ gen_and(b1, b0);
+ break;
+ case DLT_FDDI:
+ b0 = gen_fhostop(cstate, eaddr, Q_OR);
+ break;
+ case DLT_IEEE802:
+ b0 = gen_thostop(cstate, eaddr, Q_OR);
+ break;
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ b0 = gen_wlanhostop(cstate, eaddr, Q_OR);
+ break;
+ case DLT_SUNATM:
+ /*
+ * This is LLC-multiplexed traffic; if it were
+ * LANE, cstate->linktype would have been set to
+ * DLT_EN10MB.
+ */
+ bpf_error(cstate,
+ "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+ break;
+ case DLT_IP_OVER_FC:
+ b0 = gen_ipfchostop(cstate, eaddr, Q_OR);
+ break;
+ default:
+ bpf_error(cstate,
+ "'gateway' supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+ }
+ b1 = NULL;
+ for (ai = alist; ai != NULL; ai = ai->ai_next) {
+ /*
+ * Does it have an address?
+ */
+ if (ai->ai_addr != NULL) {
+ /*
+ * Yes. Is it an IPv4 address?
+ */
+ if (ai->ai_addr->sa_family == AF_INET) {
+ /*
+ * Generate an entry for it.
+ */
+ sin = (struct sockaddr_in *)ai->ai_addr;
+ tmp = gen_host(cstate,
+ ntohl(sin->sin_addr.s_addr),
+ 0xffffffff, proto, Q_OR, Q_HOST);
+ /*
+ * Is it the *first* IPv4 address?
+ */
+ if (b1 == NULL) {
+ /*
+ * Yes, so start with it.
+ */
+ b1 = tmp;
+ } else {
+ /*
+ * No, so OR it into the
+ * existing set of
+ * addresses.
+ */
+ gen_or(b1, tmp);
+ b1 = tmp;
+ }
+ }
+ }
+ }
+ if (b1 == NULL) {
+ /*
+ * No IPv4 addresses found.
+ */
+ return (NULL);
+ }
+ gen_not(b1);
+ gen_and(b0, b1);
+ return b1;
+ }
+ bpf_error(cstate, "illegal modifier of 'gateway'");
+ /*NOTREACHED*/
+}
+#endif
+
+static struct block *
+gen_proto_abbrev_internal(compiler_state_t *cstate, int proto)
+{
+ struct block *b0;
+ struct block *b1;
+
+ switch (proto) {
+
+ case Q_SCTP:
+ b1 = gen_proto(cstate, IPPROTO_SCTP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_SCTP, Q_IPV6, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_TCP:
+ b1 = gen_proto(cstate, IPPROTO_TCP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_TCP, Q_IPV6, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_UDP:
+ b1 = gen_proto(cstate, IPPROTO_UDP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_UDP, Q_IPV6, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ICMP:
+ b1 = gen_proto(cstate, IPPROTO_ICMP, Q_IP, Q_DEFAULT);
+ break;
+
+#ifndef IPPROTO_IGMP
+#define IPPROTO_IGMP 2
+#endif
+
+ case Q_IGMP:
+ b1 = gen_proto(cstate, IPPROTO_IGMP, Q_IP, Q_DEFAULT);
+ break;
+
+#ifndef IPPROTO_IGRP
+#define IPPROTO_IGRP 9
+#endif
+ case Q_IGRP:
+ b1 = gen_proto(cstate, IPPROTO_IGRP, Q_IP, Q_DEFAULT);
+ break;
+
+#ifndef IPPROTO_PIM
+#define IPPROTO_PIM 103
+#endif
+
+ case Q_PIM:
+ b1 = gen_proto(cstate, IPPROTO_PIM, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_PIM, Q_IPV6, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+#ifndef IPPROTO_VRRP
+#define IPPROTO_VRRP 112
+#endif
+
+ case Q_VRRP:
+ b1 = gen_proto(cstate, IPPROTO_VRRP, Q_IP, Q_DEFAULT);
+ break;
+
+#ifndef IPPROTO_CARP
+#define IPPROTO_CARP 112
+#endif
+
+ case Q_CARP:
+ b1 = gen_proto(cstate, IPPROTO_CARP, Q_IP, Q_DEFAULT);
+ break;
+
+ case Q_IP:
+ b1 = gen_linktype(cstate, ETHERTYPE_IP);
+ break;
+
+ case Q_ARP:
+ b1 = gen_linktype(cstate, ETHERTYPE_ARP);
+ break;
+
+ case Q_RARP:
+ b1 = gen_linktype(cstate, ETHERTYPE_REVARP);
+ break;
+
+ case Q_LINK:
+ bpf_error(cstate, "link layer applied in wrong context");
+
+ case Q_ATALK:
+ b1 = gen_linktype(cstate, ETHERTYPE_ATALK);
+ break;
+
+ case Q_AARP:
+ b1 = gen_linktype(cstate, ETHERTYPE_AARP);
+ break;
+
+ case Q_DECNET:
+ b1 = gen_linktype(cstate, ETHERTYPE_DN);
+ break;
+
+ case Q_SCA:
+ b1 = gen_linktype(cstate, ETHERTYPE_SCA);
+ break;
+
+ case Q_LAT:
+ b1 = gen_linktype(cstate, ETHERTYPE_LAT);
+ break;
+
+ case Q_MOPDL:
+ b1 = gen_linktype(cstate, ETHERTYPE_MOPDL);
+ break;
+
+ case Q_MOPRC:
+ b1 = gen_linktype(cstate, ETHERTYPE_MOPRC);
+ break;
+
+ case Q_IPV6:
+ b1 = gen_linktype(cstate, ETHERTYPE_IPV6);
+ break;
+
+#ifndef IPPROTO_ICMPV6
+#define IPPROTO_ICMPV6 58
+#endif
+ case Q_ICMPV6:
+ b1 = gen_proto(cstate, IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT);
+ break;
+
+#ifndef IPPROTO_AH
+#define IPPROTO_AH 51
+#endif
+ case Q_AH:
+ b1 = gen_proto(cstate, IPPROTO_AH, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_AH, Q_IPV6, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+#ifndef IPPROTO_ESP
+#define IPPROTO_ESP 50
+#endif
+ case Q_ESP:
+ b1 = gen_proto(cstate, IPPROTO_ESP, Q_IP, Q_DEFAULT);
+ b0 = gen_proto(cstate, IPPROTO_ESP, Q_IPV6, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ISO:
+ b1 = gen_linktype(cstate, LLCSAP_ISONS);
+ break;
+
+ case Q_ESIS:
+ b1 = gen_proto(cstate, ISO9542_ESIS, Q_ISO, Q_DEFAULT);
+ break;
+
+ case Q_ISIS:
+ b1 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+ break;
+
+ case Q_ISIS_L1: /* all IS-IS Level1 PDU-Types */
+ b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ISIS_L2: /* all IS-IS Level2 PDU-Types */
+ b0 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT); /* FIXME extract the circuit-type bits */
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ISIS_IIH: /* all IS-IS Hello PDU-Types */
+ b0 = gen_proto(cstate, ISIS_L1_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_LAN_IIH, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_PTP_IIH, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ISIS_LSP:
+ b0 = gen_proto(cstate, ISIS_L1_LSP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_LSP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ISIS_SNP:
+ b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ b0 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ISIS_CSNP:
+ b0 = gen_proto(cstate, ISIS_L1_CSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_CSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_ISIS_PSNP:
+ b0 = gen_proto(cstate, ISIS_L1_PSNP, Q_ISIS, Q_DEFAULT);
+ b1 = gen_proto(cstate, ISIS_L2_PSNP, Q_ISIS, Q_DEFAULT);
+ gen_or(b0, b1);
+ break;
+
+ case Q_CLNP:
+ b1 = gen_proto(cstate, ISO8473_CLNP, Q_ISO, Q_DEFAULT);
+ break;
+
+ case Q_STP:
+ b1 = gen_linktype(cstate, LLCSAP_8021D);
+ break;
+
+ case Q_IPX:
+ b1 = gen_linktype(cstate, LLCSAP_IPX);
+ break;
+
+ case Q_NETBEUI:
+ b1 = gen_linktype(cstate, LLCSAP_NETBEUI);
+ break;
+
+ case Q_RADIO:
+ bpf_error(cstate, "'radio' is not a valid protocol type");
+
+ default:
+ abort();
+ }
+ return b1;
+}
+
+struct block *
+gen_proto_abbrev(compiler_state_t *cstate, int proto)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ return gen_proto_abbrev_internal(cstate, proto);
+}
+
+static struct block *
+gen_ipfrag(compiler_state_t *cstate)
+{
+ struct slist *s;
+ struct block *b;
+
+ /* not IPv4 frag other than the first frag */
+ s = gen_load_a(cstate, OR_LINKPL, 6, BPF_H);
+ b = new_block(cstate, JMP(BPF_JSET));
+ b->s.k = 0x1fff;
+ b->stmts = s;
+ gen_not(b);
+
+ return b;
+}
+
+/*
+ * Generate a comparison to a port value in the transport-layer header
+ * at the specified offset from the beginning of that header.
+ *
+ * XXX - this handles a variable-length prefix preceding the link-layer
+ * header, such as the radiotap or AVS radio prefix, but doesn't handle
+ * variable-length link-layer headers (such as Token Ring or 802.11
+ * headers).
+ */
+static struct block *
+gen_portatom(compiler_state_t *cstate, int off, bpf_int32 v)
+{
+ return gen_cmp(cstate, OR_TRAN_IPV4, off, BPF_H, v);
+}
+
+static struct block *
+gen_portatom6(compiler_state_t *cstate, int off, bpf_int32 v)
+{
+ return gen_cmp(cstate, OR_TRAN_IPV6, off, BPF_H, v);
+}
+
+struct block *
+gen_portop(compiler_state_t *cstate, int port, int proto, int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ip proto 'proto' and not a fragment other than the first fragment */
+ tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+ b0 = gen_ipfrag(cstate);
+ gen_and(tmp, b0);
+
+ switch (dir) {
+ case Q_SRC:
+ b1 = gen_portatom(cstate, 0, (bpf_int32)port);
+ break;
+
+ case Q_DST:
+ b1 = gen_portatom(cstate, 2, (bpf_int32)port);
+ break;
+
+ case Q_AND:
+ tmp = gen_portatom(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom(cstate, 2, (bpf_int32)port);
+ gen_and(tmp, b1);
+ break;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ tmp = gen_portatom(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom(cstate, 2, (bpf_int32)port);
+ gen_or(tmp, b1);
+ break;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for ports");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for ports");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for ports");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for ports");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for ports");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for ports");
+ /*NOTREACHED*/
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_port(compiler_state_t *cstate, int port, int ip_proto, int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /*
+ * ether proto ip
+ *
+ * For FDDI, RFC 1188 says that SNAP encapsulation is used,
+ * not LLC encapsulation with LLCSAP_IP.
+ *
+ * For IEEE 802 networks - which includes 802.5 token ring
+ * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
+ * says that SNAP encapsulation is used, not LLC encapsulation
+ * with LLCSAP_IP.
+ *
+ * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
+ * RFC 2225 say that SNAP encapsulation is used, not LLC
+ * encapsulation with LLCSAP_IP.
+ *
+ * So we always check for ETHERTYPE_IP.
+ */
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ b1 = gen_portop(cstate, port, ip_proto, dir);
+ break;
+
+ case PROTO_UNDEF:
+ tmp = gen_portop(cstate, port, IPPROTO_TCP, dir);
+ b1 = gen_portop(cstate, port, IPPROTO_UDP, dir);
+ gen_or(tmp, b1);
+ tmp = gen_portop(cstate, port, IPPROTO_SCTP, dir);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+ return b1;
+}
+
+struct block *
+gen_portop6(compiler_state_t *cstate, int port, int proto, int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ip6 proto 'proto' */
+ /* XXX - catch the first fragment of a fragmented packet? */
+ b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
+
+ switch (dir) {
+ case Q_SRC:
+ b1 = gen_portatom6(cstate, 0, (bpf_int32)port);
+ break;
+
+ case Q_DST:
+ b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
+ break;
+
+ case Q_AND:
+ tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
+ gen_and(tmp, b1);
+ break;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ tmp = gen_portatom6(cstate, 0, (bpf_int32)port);
+ b1 = gen_portatom6(cstate, 2, (bpf_int32)port);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_port6(compiler_state_t *cstate, int port, int ip_proto, int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /* link proto ip6 */
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ b1 = gen_portop6(cstate, port, ip_proto, dir);
+ break;
+
+ case PROTO_UNDEF:
+ tmp = gen_portop6(cstate, port, IPPROTO_TCP, dir);
+ b1 = gen_portop6(cstate, port, IPPROTO_UDP, dir);
+ gen_or(tmp, b1);
+ tmp = gen_portop6(cstate, port, IPPROTO_SCTP, dir);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+ return b1;
+}
+
+/* gen_portrange code */
+static struct block *
+gen_portrangeatom(compiler_state_t *cstate, int off, bpf_int32 v1,
+ bpf_int32 v2)
+{
+ struct block *b1, *b2;
+
+ if (v1 > v2) {
+ /*
+ * Reverse the order of the ports, so v1 is the lower one.
+ */
+ bpf_int32 vtemp;
+
+ vtemp = v1;
+ v1 = v2;
+ v2 = vtemp;
+ }
+
+ b1 = gen_cmp_ge(cstate, OR_TRAN_IPV4, off, BPF_H, v1);
+ b2 = gen_cmp_le(cstate, OR_TRAN_IPV4, off, BPF_H, v2);
+
+ gen_and(b1, b2);
+
+ return b2;
+}
+
+struct block *
+gen_portrangeop(compiler_state_t *cstate, int port1, int port2, int proto,
+ int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ip proto 'proto' and not a fragment other than the first fragment */
+ tmp = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)proto);
+ b0 = gen_ipfrag(cstate);
+ gen_and(tmp, b0);
+
+ switch (dir) {
+ case Q_SRC:
+ b1 = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_DST:
+ b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_AND:
+ tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_and(tmp, b1);
+ break;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ tmp = gen_portrangeatom(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_or(tmp, b1);
+ break;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are not valid qualifiers for port ranges");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are not valid qualifiers for port ranges");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are not valid qualifiers for port ranges");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are not valid qualifiers for port ranges");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is not a valid qualifier for port ranges");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is not a valid qualifier for port ranges");
+ /*NOTREACHED*/
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_portrange(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+ int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /* link proto ip */
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ b1 = gen_portrangeop(cstate, port1, port2, ip_proto, dir);
+ break;
+
+ case PROTO_UNDEF:
+ tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_TCP, dir);
+ b1 = gen_portrangeop(cstate, port1, port2, IPPROTO_UDP, dir);
+ gen_or(tmp, b1);
+ tmp = gen_portrangeop(cstate, port1, port2, IPPROTO_SCTP, dir);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+ return b1;
+}
+
+static struct block *
+gen_portrangeatom6(compiler_state_t *cstate, int off, bpf_int32 v1,
+ bpf_int32 v2)
+{
+ struct block *b1, *b2;
+
+ if (v1 > v2) {
+ /*
+ * Reverse the order of the ports, so v1 is the lower one.
+ */
+ bpf_int32 vtemp;
+
+ vtemp = v1;
+ v1 = v2;
+ v2 = vtemp;
+ }
+
+ b1 = gen_cmp_ge(cstate, OR_TRAN_IPV6, off, BPF_H, v1);
+ b2 = gen_cmp_le(cstate, OR_TRAN_IPV6, off, BPF_H, v2);
+
+ gen_and(b1, b2);
+
+ return b2;
+}
+
+struct block *
+gen_portrangeop6(compiler_state_t *cstate, int port1, int port2, int proto,
+ int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /* ip6 proto 'proto' */
+ /* XXX - catch the first fragment of a fragmented packet? */
+ b0 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)proto);
+
+ switch (dir) {
+ case Q_SRC:
+ b1 = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_DST:
+ b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+ break;
+
+ case Q_AND:
+ tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_and(tmp, b1);
+ break;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ tmp = gen_portrangeatom6(cstate, 0, (bpf_int32)port1, (bpf_int32)port2);
+ b1 = gen_portrangeatom6(cstate, 2, (bpf_int32)port1, (bpf_int32)port2);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_portrange6(compiler_state_t *cstate, int port1, int port2, int ip_proto,
+ int dir)
+{
+ struct block *b0, *b1, *tmp;
+
+ /* link proto ip6 */
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+
+ switch (ip_proto) {
+ case IPPROTO_UDP:
+ case IPPROTO_TCP:
+ case IPPROTO_SCTP:
+ b1 = gen_portrangeop6(cstate, port1, port2, ip_proto, dir);
+ break;
+
+ case PROTO_UNDEF:
+ tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_TCP, dir);
+ b1 = gen_portrangeop6(cstate, port1, port2, IPPROTO_UDP, dir);
+ gen_or(tmp, b1);
+ tmp = gen_portrangeop6(cstate, port1, port2, IPPROTO_SCTP, dir);
+ gen_or(tmp, b1);
+ break;
+
+ default:
+ abort();
+ }
+ gen_and(b0, b1);
+ return b1;
+}
+
+static int
+lookup_proto(compiler_state_t *cstate, const char *name, int proto)
+{
+ register int v;
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ case Q_IP:
+ case Q_IPV6:
+ v = pcap_nametoproto(name);
+ if (v == PROTO_UNDEF)
+ bpf_error(cstate, "unknown ip proto '%s'", name);
+ break;
+
+ case Q_LINK:
+ /* XXX should look up h/w protocol type based on cstate->linktype */
+ v = pcap_nametoeproto(name);
+ if (v == PROTO_UNDEF) {
+ v = pcap_nametollc(name);
+ if (v == PROTO_UNDEF)
+ bpf_error(cstate, "unknown ether proto '%s'", name);
+ }
+ break;
+
+ case Q_ISO:
+ if (strcmp(name, "esis") == 0)
+ v = ISO9542_ESIS;
+ else if (strcmp(name, "isis") == 0)
+ v = ISO10589_ISIS;
+ else if (strcmp(name, "clnp") == 0)
+ v = ISO8473_CLNP;
+ else
+ bpf_error(cstate, "unknown osi proto '%s'", name);
+ break;
+
+ default:
+ v = PROTO_UNDEF;
+ break;
+ }
+ return v;
+}
+
+#if 0
+struct stmt *
+gen_joinsp(struct stmt **s, int n)
+{
+ return NULL;
+}
+#endif
+
+static struct block *
+gen_protochain(compiler_state_t *cstate, int v, int proto, int dir)
+{
+#ifdef NO_PROTOCHAIN
+ return gen_proto(cstate, v, proto, dir);
+#else
+ struct block *b0, *b;
+ struct slist *s[100];
+ int fix2, fix3, fix4, fix5;
+ int ahcheck, again, end;
+ int i, max;
+ int reg2 = alloc_reg(cstate);
+
+ memset(s, 0, sizeof(s));
+ fix3 = fix4 = fix5 = 0;
+
+ switch (proto) {
+ case Q_IP:
+ case Q_IPV6:
+ break;
+ case Q_DEFAULT:
+ b0 = gen_protochain(cstate, v, Q_IP, dir);
+ b = gen_protochain(cstate, v, Q_IPV6, dir);
+ gen_or(b0, b);
+ return b;
+ default:
+ bpf_error(cstate, "bad protocol applied for 'protochain'");
+ /*NOTREACHED*/
+ }
+
+ /*
+ * We don't handle variable-length prefixes before the link-layer
+ * header, or variable-length link-layer headers, here yet.
+ * We might want to add BPF instructions to do the protochain
+ * work, to simplify that and, on platforms that have a BPF
+ * interpreter with the new instructions, let the filtering
+ * be done in the kernel. (We already require a modified BPF
+ * engine to do the protochain stuff, to support backward
+ * branches, and backward branch support is unlikely to appear
+ * in kernel BPF engines.)
+ */
+ if (cstate->off_linkpl.is_variable)
+ bpf_error(cstate, "'protochain' not supported with variable length headers");
+
+ cstate->no_optimize = 1; /* this code is not compatible with optimizer yet */
+
+ /*
+ * s[0] is a dummy entry to protect other BPF insn from damage
+ * by s[fix] = foo with uninitialized variable "fix". It is somewhat
+ * hard to find interdependency made by jump table fixup.
+ */
+ i = 0;
+ s[i] = new_stmt(cstate, 0); /*dummy*/
+ i++;
+
+ switch (proto) {
+ case Q_IP:
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+
+ /* A = ip->ip_p */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 9;
+ i++;
+ /* X = ip->ip_hl << 2 */
+ s[i] = new_stmt(cstate, BPF_LDX|BPF_MSH|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ i++;
+ break;
+
+ case Q_IPV6:
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+
+ /* A = ip6->ip_nxt */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_ABS|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 6;
+ i++;
+ /* X = sizeof(struct ip6_hdr) */
+ s[i] = new_stmt(cstate, BPF_LDX|BPF_IMM);
+ s[i]->s.k = 40;
+ i++;
+ break;
+
+ default:
+ bpf_error(cstate, "unsupported proto to gen_protochain");
+ /*NOTREACHED*/
+ }
+
+ /* again: if (A == v) goto end; else fall through; */
+ again = i;
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
+ s[i]->s.k = v;
+ s[i]->s.jt = NULL; /*later*/
+ s[i]->s.jf = NULL; /*update in next stmt*/
+ fix5 = i;
+ i++;
+
+#ifndef IPPROTO_NONE
+#define IPPROTO_NONE 59
+#endif
+ /* if (A == IPPROTO_NONE) goto end */
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
+ s[i]->s.jt = NULL; /*later*/
+ s[i]->s.jf = NULL; /*update in next stmt*/
+ s[i]->s.k = IPPROTO_NONE;
+ s[fix5]->s.jf = s[i];
+ fix2 = i;
+ i++;
+
+ if (proto == Q_IPV6) {
+ int v6start, v6end, v6advance, j;
+
+ v6start = i;
+ /* if (A == IPPROTO_HOPOPTS) goto v6advance */
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
+ s[i]->s.jt = NULL; /*later*/
+ s[i]->s.jf = NULL; /*update in next stmt*/
+ s[i]->s.k = IPPROTO_HOPOPTS;
+ s[fix2]->s.jf = s[i];
+ i++;
+ /* if (A == IPPROTO_DSTOPTS) goto v6advance */
+ s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
+ s[i]->s.jt = NULL; /*later*/
+ s[i]->s.jf = NULL; /*update in next stmt*/
+ s[i]->s.k = IPPROTO_DSTOPTS;
+ i++;
+ /* if (A == IPPROTO_ROUTING) goto v6advance */
+ s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
+ s[i]->s.jt = NULL; /*later*/
+ s[i]->s.jf = NULL; /*update in next stmt*/
+ s[i]->s.k = IPPROTO_ROUTING;
+ i++;
+ /* if (A == IPPROTO_FRAGMENT) goto v6advance; else goto ahcheck; */
+ s[i - 1]->s.jf = s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
+ s[i]->s.jt = NULL; /*later*/
+ s[i]->s.jf = NULL; /*later*/
+ s[i]->s.k = IPPROTO_FRAGMENT;
+ fix3 = i;
+ v6end = i;
+ i++;
+
+ /* v6advance: */
+ v6advance = i;
+
+ /*
+ * in short,
+ * A = P[X + packet head];
+ * X = X + (P[X + packet head + 1] + 1) * 8;
+ */
+ /* A = P[X + packet head] */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ i++;
+ /* MEM[reg2] = A */
+ s[i] = new_stmt(cstate, BPF_ST);
+ s[i]->s.k = reg2;
+ i++;
+ /* A = P[X + packet head + 1]; */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 1;
+ i++;
+ /* A += 1 */
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s[i]->s.k = 1;
+ i++;
+ /* A *= 8 */
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
+ s[i]->s.k = 8;
+ i++;
+ /* A += X */
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
+ s[i]->s.k = 0;
+ i++;
+ /* X = A; */
+ s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ i++;
+ /* A = MEM[reg2] */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s[i]->s.k = reg2;
+ i++;
+
+ /* goto again; (must use BPF_JA for backward jump) */
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
+ s[i]->s.k = again - i - 1;
+ s[i - 1]->s.jf = s[i];
+ i++;
+
+ /* fixup */
+ for (j = v6start; j <= v6end; j++)
+ s[j]->s.jt = s[v6advance];
+ } else {
+ /* nop */
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s[i]->s.k = 0;
+ s[fix2]->s.jf = s[i];
+ i++;
+ }
+
+ /* ahcheck: */
+ ahcheck = i;
+ /* if (A == IPPROTO_AH) then fall through; else goto end; */
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JEQ|BPF_K);
+ s[i]->s.jt = NULL; /*later*/
+ s[i]->s.jf = NULL; /*later*/
+ s[i]->s.k = IPPROTO_AH;
+ if (fix3)
+ s[fix3]->s.jf = s[ahcheck];
+ fix4 = i;
+ i++;
+
+ /*
+ * in short,
+ * A = P[X];
+ * X = X + (P[X + 1] + 2) * 4;
+ */
+ /* A = X */
+ s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
+ i++;
+ /* A = P[X + packet head]; */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ i++;
+ /* MEM[reg2] = A */
+ s[i] = new_stmt(cstate, BPF_ST);
+ s[i]->s.k = reg2;
+ i++;
+ /* A = X */
+ s[i - 1]->s.jt = s[i] = new_stmt(cstate, BPF_MISC|BPF_TXA);
+ i++;
+ /* A += 1 */
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s[i]->s.k = 1;
+ i++;
+ /* X = A */
+ s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ i++;
+ /* A = P[X + packet head] */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s[i]->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ i++;
+ /* A += 2 */
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s[i]->s.k = 2;
+ i++;
+ /* A *= 4 */
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
+ s[i]->s.k = 4;
+ i++;
+ /* X = A; */
+ s[i] = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ i++;
+ /* A = MEM[reg2] */
+ s[i] = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s[i]->s.k = reg2;
+ i++;
+
+ /* goto again; (must use BPF_JA for backward jump) */
+ s[i] = new_stmt(cstate, BPF_JMP|BPF_JA);
+ s[i]->s.k = again - i - 1;
+ i++;
+
+ /* end: nop */
+ end = i;
+ s[i] = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s[i]->s.k = 0;
+ s[fix2]->s.jt = s[end];
+ s[fix4]->s.jf = s[end];
+ s[fix5]->s.jt = s[end];
+ i++;
+
+ /*
+ * make slist chain
+ */
+ max = i;
+ for (i = 0; i < max - 1; i++)
+ s[i]->next = s[i + 1];
+ s[max - 1]->next = NULL;
+
+ /*
+ * emit final check
+ */
+ b = new_block(cstate, JMP(BPF_JEQ));
+ b->stmts = s[1]; /*remember, s[0] is dummy*/
+ b->s.k = v;
+
+ free_reg(cstate, reg2);
+
+ gen_and(b0, b);
+ return b;
+#endif
+}
+
+static struct block *
+gen_check_802_11_data_frame(compiler_state_t *cstate)
+{
+ struct slist *s;
+ struct block *b0, *b1;
+
+ /*
+ * A data frame has the 0x08 bit (b3) in the frame control field set
+ * and the 0x04 bit (b2) clear.
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b0 = new_block(cstate, JMP(BPF_JSET));
+ b0->s.k = 0x08;
+ b0->stmts = s;
+
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x04;
+ b1->stmts = s;
+ gen_not(b1);
+
+ gen_and(b1, b0);
+
+ return b0;
+}
+
+/*
+ * Generate code that checks whether the packet is a packet for protocol
+ * <proto> and whether the type field in that protocol's header has
+ * the value <v>, e.g. if <proto> is Q_IP, it checks whether it's an
+ * IP packet and checks the protocol number in the IP header against <v>.
+ *
+ * If <proto> is Q_DEFAULT, i.e. just "proto" was specified, it checks
+ * against Q_IP and Q_IPV6.
+ */
+static struct block *
+gen_proto(compiler_state_t *cstate, int v, int proto, int dir)
+{
+ struct block *b0, *b1;
+#ifndef CHASE_CHAIN
+ struct block *b2;
+#endif
+
+ if (dir != Q_DEFAULT)
+ bpf_error(cstate, "direction applied to 'proto'");
+
+ switch (proto) {
+ case Q_DEFAULT:
+ b0 = gen_proto(cstate, v, Q_IP, dir);
+ b1 = gen_proto(cstate, v, Q_IPV6, dir);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_LINK:
+ return gen_linktype(cstate, v);
+
+ case Q_IP:
+ /*
+ * For FDDI, RFC 1188 says that SNAP encapsulation is used,
+ * not LLC encapsulation with LLCSAP_IP.
+ *
+ * For IEEE 802 networks - which includes 802.5 token ring
+ * (which is what DLT_IEEE802 means) and 802.11 - RFC 1042
+ * says that SNAP encapsulation is used, not LLC encapsulation
+ * with LLCSAP_IP.
+ *
+ * For LLC-encapsulated ATM/"Classical IP", RFC 1483 and
+ * RFC 2225 say that SNAP encapsulation is used, not LLC
+ * encapsulation with LLCSAP_IP.
+ *
+ * So we always check for ETHERTYPE_IP.
+ */
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+#ifndef CHASE_CHAIN
+ b1 = gen_cmp(cstate, OR_LINKPL, 9, BPF_B, (bpf_int32)v);
+#else
+ b1 = gen_protochain(cstate, v, Q_IP);
+#endif
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_ARP:
+ bpf_error(cstate, "arp does not encapsulate another protocol");
+ /*NOTREACHED*/
+
+ case Q_RARP:
+ bpf_error(cstate, "rarp does not encapsulate another protocol");
+ /*NOTREACHED*/
+
+ case Q_SCTP:
+ bpf_error(cstate, "'sctp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_TCP:
+ bpf_error(cstate, "'tcp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_UDP:
+ bpf_error(cstate, "'udp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ICMP:
+ bpf_error(cstate, "'icmp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_IGMP:
+ bpf_error(cstate, "'igmp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_IGRP:
+ bpf_error(cstate, "'igrp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ATALK:
+ bpf_error(cstate, "AppleTalk encapsulation is not specifiable");
+ /*NOTREACHED*/
+
+ case Q_DECNET:
+ bpf_error(cstate, "DECNET encapsulation is not specifiable");
+ /*NOTREACHED*/
+
+ case Q_LAT:
+ bpf_error(cstate, "LAT does not encapsulate another protocol");
+ /*NOTREACHED*/
+
+ case Q_SCA:
+ bpf_error(cstate, "SCA does not encapsulate another protocol");
+ /*NOTREACHED*/
+
+ case Q_MOPRC:
+ bpf_error(cstate, "MOPRC does not encapsulate another protocol");
+ /*NOTREACHED*/
+
+ case Q_MOPDL:
+ bpf_error(cstate, "MOPDL does not encapsulate another protocol");
+ /*NOTREACHED*/
+
+ case Q_IPV6:
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+#ifndef CHASE_CHAIN
+ /*
+ * Also check for a fragment header before the final
+ * header.
+ */
+ b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, IPPROTO_FRAGMENT);
+ b1 = gen_cmp(cstate, OR_LINKPL, 40, BPF_B, (bpf_int32)v);
+ gen_and(b2, b1);
+ b2 = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, (bpf_int32)v);
+ gen_or(b2, b1);
+#else
+ b1 = gen_protochain(cstate, v, Q_IPV6);
+#endif
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_ICMPV6:
+ bpf_error(cstate, "'icmp6 proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_AH:
+ bpf_error(cstate, "'ah proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ESP:
+ bpf_error(cstate, "'ah proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_PIM:
+ bpf_error(cstate, "'pim proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_VRRP:
+ bpf_error(cstate, "'vrrp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_AARP:
+ bpf_error(cstate, "'aarp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISO:
+ switch (cstate->linktype) {
+
+ case DLT_FRELAY:
+ /*
+ * Frame Relay packets typically have an OSI
+ * NLPID at the beginning; "gen_linktype(cstate, LLCSAP_ISONS)"
+ * generates code to check for all the OSI
+ * NLPIDs, so calling it and then adding a check
+ * for the particular NLPID for which we're
+ * looking is bogus, as we can just check for
+ * the NLPID.
+ *
+ * What we check for is the NLPID and a frame
+ * control field value of UI, i.e. 0x03 followed
+ * by the NLPID.
+ *
+ * XXX - assumes a 2-byte Frame Relay header with
+ * DLCI and flags. What if the address is longer?
+ *
+ * XXX - what about SNAP-encapsulated frames?
+ */
+ return gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, (0x03<<8) | v);
+ /*NOTREACHED*/
+
+ case DLT_C_HDLC:
+ /*
+ * Cisco uses an Ethertype lookalike - for OSI,
+ * it's 0xfefe.
+ */
+ b0 = gen_linktype(cstate, LLCSAP_ISONS<<8 | LLCSAP_ISONS);
+ /* OSI in C-HDLC is stuffed with a fudge byte */
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 1, BPF_B, (long)v);
+ gen_and(b0, b1);
+ return b1;
+
+ default:
+ b0 = gen_linktype(cstate, LLCSAP_ISONS);
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 0, BPF_B, (long)v);
+ gen_and(b0, b1);
+ return b1;
+ }
+
+ case Q_ESIS:
+ bpf_error(cstate, "'esis proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS:
+ b0 = gen_proto(cstate, ISO10589_ISIS, Q_ISO, Q_DEFAULT);
+ /*
+ * 4 is the offset of the PDU type relative to the IS-IS
+ * header.
+ */
+ b1 = gen_cmp(cstate, OR_LINKPL_NOSNAP, 4, BPF_B, (long)v);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_CLNP:
+ bpf_error(cstate, "'clnp proto' is not supported");
+ /*NOTREACHED*/
+
+ case Q_STP:
+ bpf_error(cstate, "'stp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_IPX:
+ bpf_error(cstate, "'ipx proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_NETBEUI:
+ bpf_error(cstate, "'netbeui proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS_L1:
+ bpf_error(cstate, "'l1 proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS_L2:
+ bpf_error(cstate, "'l2 proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS_IIH:
+ bpf_error(cstate, "'iih proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS_SNP:
+ bpf_error(cstate, "'snp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS_CSNP:
+ bpf_error(cstate, "'csnp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS_PSNP:
+ bpf_error(cstate, "'psnp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_ISIS_LSP:
+ bpf_error(cstate, "'lsp proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_RADIO:
+ bpf_error(cstate, "'radio proto' is bogus");
+ /*NOTREACHED*/
+
+ case Q_CARP:
+ bpf_error(cstate, "'carp proto' is bogus");
+ /*NOTREACHED*/
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_scode(compiler_state_t *cstate, const char *name, struct qual q)
+{
+ int proto = q.proto;
+ int dir = q.dir;
+ int tproto;
+ u_char *eaddr;
+ bpf_u_int32 mask, addr;
+ struct addrinfo *res, *res0;
+ struct sockaddr_in *sin4;
+#ifdef INET6
+ int tproto6;
+ struct sockaddr_in6 *sin6;
+ struct in6_addr mask128;
+#endif /*INET6*/
+ struct block *b, *tmp;
+ int port, real_proto;
+ int port1, port2;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (q.addr) {
+
+ case Q_NET:
+ addr = pcap_nametonetaddr(name);
+ if (addr == 0)
+ bpf_error(cstate, "unknown network '%s'", name);
+ /* Left justify network addr and calculate its network mask */
+ mask = 0xffffffff;
+ while (addr && (addr & 0xff000000) == 0) {
+ addr <<= 8;
+ mask <<= 8;
+ }
+ return gen_host(cstate, addr, mask, proto, dir, q.addr);
+
+ case Q_DEFAULT:
+ case Q_HOST:
+ if (proto == Q_LINK) {
+ switch (cstate->linktype) {
+
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ eaddr = pcap_ether_hostton(name);
+ if (eaddr == NULL)
+ bpf_error(cstate,
+ "unknown ether host '%s'", name);
+ tmp = gen_prevlinkhdr_check(cstate);
+ b = gen_ehostop(cstate, eaddr, dir);
+ if (tmp != NULL)
+ gen_and(tmp, b);
+ free(eaddr);
+ return b;
+
+ case DLT_FDDI:
+ eaddr = pcap_ether_hostton(name);
+ if (eaddr == NULL)
+ bpf_error(cstate,
+ "unknown FDDI host '%s'", name);
+ b = gen_fhostop(cstate, eaddr, dir);
+ free(eaddr);
+ return b;
+
+ case DLT_IEEE802:
+ eaddr = pcap_ether_hostton(name);
+ if (eaddr == NULL)
+ bpf_error(cstate,
+ "unknown token ring host '%s'", name);
+ b = gen_thostop(cstate, eaddr, dir);
+ free(eaddr);
+ return b;
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ eaddr = pcap_ether_hostton(name);
+ if (eaddr == NULL)
+ bpf_error(cstate,
+ "unknown 802.11 host '%s'", name);
+ b = gen_wlanhostop(cstate, eaddr, dir);
+ free(eaddr);
+ return b;
+
+ case DLT_IP_OVER_FC:
+ eaddr = pcap_ether_hostton(name);
+ if (eaddr == NULL)
+ bpf_error(cstate,
+ "unknown Fibre Channel host '%s'", name);
+ b = gen_ipfchostop(cstate, eaddr, dir);
+ free(eaddr);
+ return b;
+ }
+
+ bpf_error(cstate, "only ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel supports link-level host name");
+ } else if (proto == Q_DECNET) {
+ unsigned short dn_addr;
+
+ if (!__pcap_nametodnaddr(name, &dn_addr)) {
+#ifdef DECNETLIB
+ bpf_error(cstate, "unknown decnet host name '%s'\n", name);
+#else
+ bpf_error(cstate, "decnet name support not included, '%s' cannot be translated\n",
+ name);
+#endif
+ }
+ /*
+ * I don't think DECNET hosts can be multihomed, so
+ * there is no need to build up a list of addresses
+ */
+ return (gen_host(cstate, dn_addr, 0, proto, dir, q.addr));
+ } else {
+#ifdef INET6
+ memset(&mask128, 0xff, sizeof(mask128));
+#endif
+ res0 = res = pcap_nametoaddrinfo(name);
+ if (res == NULL)
+ bpf_error(cstate, "unknown host '%s'", name);
+ cstate->ai = res;
+ b = tmp = NULL;
+ tproto = proto;
+#ifdef INET6
+ tproto6 = proto;
+#endif
+ if (cstate->off_linktype.constant_part == OFFSET_NOT_SET &&
+ tproto == Q_DEFAULT) {
+ tproto = Q_IP;
+#ifdef INET6
+ tproto6 = Q_IPV6;
+#endif
+ }
+ for (res = res0; res; res = res->ai_next) {
+ switch (res->ai_family) {
+ case AF_INET:
+#ifdef INET6
+ if (tproto == Q_IPV6)
+ continue;
+#endif
+
+ sin4 = (struct sockaddr_in *)
+ res->ai_addr;
+ tmp = gen_host(cstate, ntohl(sin4->sin_addr.s_addr),
+ 0xffffffff, tproto, dir, q.addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (tproto6 == Q_IP)
+ continue;
+
+ sin6 = (struct sockaddr_in6 *)
+ res->ai_addr;
+ tmp = gen_host6(cstate, &sin6->sin6_addr,
+ &mask128, tproto6, dir, q.addr);
+ break;
+#endif
+ default:
+ continue;
+ }
+ if (b)
+ gen_or(b, tmp);
+ b = tmp;
+ }
+ cstate->ai = NULL;
+ freeaddrinfo(res0);
+ if (b == NULL) {
+ bpf_error(cstate, "unknown host '%s'%s", name,
+ (proto == Q_DEFAULT)
+ ? ""
+ : " for specified address family");
+ }
+ return b;
+ }
+
+ case Q_PORT:
+ if (proto != Q_DEFAULT &&
+ proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
+ bpf_error(cstate, "illegal qualifier of 'port'");
+ if (pcap_nametoport(name, &port, &real_proto) == 0)
+ bpf_error(cstate, "unknown port '%s'", name);
+ if (proto == Q_UDP) {
+ if (real_proto == IPPROTO_TCP)
+ bpf_error(cstate, "port '%s' is tcp", name);
+ else if (real_proto == IPPROTO_SCTP)
+ bpf_error(cstate, "port '%s' is sctp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_UDP;
+ }
+ if (proto == Q_TCP) {
+ if (real_proto == IPPROTO_UDP)
+ bpf_error(cstate, "port '%s' is udp", name);
+
+ else if (real_proto == IPPROTO_SCTP)
+ bpf_error(cstate, "port '%s' is sctp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_TCP;
+ }
+ if (proto == Q_SCTP) {
+ if (real_proto == IPPROTO_UDP)
+ bpf_error(cstate, "port '%s' is udp", name);
+
+ else if (real_proto == IPPROTO_TCP)
+ bpf_error(cstate, "port '%s' is tcp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_SCTP;
+ }
+ if (port < 0)
+ bpf_error(cstate, "illegal port number %d < 0", port);
+ if (port > 65535)
+ bpf_error(cstate, "illegal port number %d > 65535", port);
+ b = gen_port(cstate, port, real_proto, dir);
+ gen_or(gen_port6(cstate, port, real_proto, dir), b);
+ return b;
+
+ case Q_PORTRANGE:
+ if (proto != Q_DEFAULT &&
+ proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP)
+ bpf_error(cstate, "illegal qualifier of 'portrange'");
+ if (pcap_nametoportrange(name, &port1, &port2, &real_proto) == 0)
+ bpf_error(cstate, "unknown port in range '%s'", name);
+ if (proto == Q_UDP) {
+ if (real_proto == IPPROTO_TCP)
+ bpf_error(cstate, "port in range '%s' is tcp", name);
+ else if (real_proto == IPPROTO_SCTP)
+ bpf_error(cstate, "port in range '%s' is sctp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_UDP;
+ }
+ if (proto == Q_TCP) {
+ if (real_proto == IPPROTO_UDP)
+ bpf_error(cstate, "port in range '%s' is udp", name);
+ else if (real_proto == IPPROTO_SCTP)
+ bpf_error(cstate, "port in range '%s' is sctp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_TCP;
+ }
+ if (proto == Q_SCTP) {
+ if (real_proto == IPPROTO_UDP)
+ bpf_error(cstate, "port in range '%s' is udp", name);
+ else if (real_proto == IPPROTO_TCP)
+ bpf_error(cstate, "port in range '%s' is tcp", name);
+ else
+ /* override PROTO_UNDEF */
+ real_proto = IPPROTO_SCTP;
+ }
+ if (port1 < 0)
+ bpf_error(cstate, "illegal port number %d < 0", port1);
+ if (port1 > 65535)
+ bpf_error(cstate, "illegal port number %d > 65535", port1);
+ if (port2 < 0)
+ bpf_error(cstate, "illegal port number %d < 0", port2);
+ if (port2 > 65535)
+ bpf_error(cstate, "illegal port number %d > 65535", port2);
+
+ b = gen_portrange(cstate, port1, port2, real_proto, dir);
+ gen_or(gen_portrange6(cstate, port1, port2, real_proto, dir), b);
+ return b;
+
+ case Q_GATEWAY:
+#ifndef INET6
+ eaddr = pcap_ether_hostton(name);
+ if (eaddr == NULL)
+ bpf_error(cstate, "unknown ether host: %s", name);
+
+ res = pcap_nametoaddrinfo(name);
+ cstate->ai = res;
+ if (res == NULL)
+ bpf_error(cstate, "unknown host '%s'", name);
+ b = gen_gateway(cstate, eaddr, res, proto, dir);
+ cstate->ai = NULL;
+ freeaddrinfo(res);
+ if (b == NULL)
+ bpf_error(cstate, "unknown host '%s'", name);
+ return b;
+#else
+ bpf_error(cstate, "'gateway' not supported in this configuration");
+#endif /*INET6*/
+
+ case Q_PROTO:
+ real_proto = lookup_proto(cstate, name, proto);
+ if (real_proto >= 0)
+ return gen_proto(cstate, real_proto, proto, dir);
+ else
+ bpf_error(cstate, "unknown protocol: %s", name);
+
+ case Q_PROTOCHAIN:
+ real_proto = lookup_proto(cstate, name, proto);
+ if (real_proto >= 0)
+ return gen_protochain(cstate, real_proto, proto, dir);
+ else
+ bpf_error(cstate, "unknown protocol: %s", name);
+
+ case Q_UNDEF:
+ syntax(cstate);
+ /*NOTREACHED*/
+ }
+ abort();
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_mcode(compiler_state_t *cstate, const char *s1, const char *s2,
+ unsigned int masklen, struct qual q)
+{
+ register int nlen, mlen;
+ bpf_u_int32 n, m;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ nlen = __pcap_atoin(s1, &n);
+ /* Promote short ipaddr */
+ n <<= 32 - nlen;
+
+ if (s2 != NULL) {
+ mlen = __pcap_atoin(s2, &m);
+ /* Promote short ipaddr */
+ m <<= 32 - mlen;
+ if ((n & ~m) != 0)
+ bpf_error(cstate, "non-network bits set in \"%s mask %s\"",
+ s1, s2);
+ } else {
+ /* Convert mask len to mask */
+ if (masklen > 32)
+ bpf_error(cstate, "mask length must be <= 32");
+ if (masklen == 0) {
+ /*
+ * X << 32 is not guaranteed by C to be 0; it's
+ * undefined.
+ */
+ m = 0;
+ } else
+ m = 0xffffffff << (32 - masklen);
+ if ((n & ~m) != 0)
+ bpf_error(cstate, "non-network bits set in \"%s/%d\"",
+ s1, masklen);
+ }
+
+ switch (q.addr) {
+
+ case Q_NET:
+ return gen_host(cstate, n, m, q.proto, q.dir, q.addr);
+
+ default:
+ bpf_error(cstate, "Mask syntax for networks only");
+ /*NOTREACHED*/
+ }
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_ncode(compiler_state_t *cstate, const char *s, bpf_u_int32 v, struct qual q)
+{
+ bpf_u_int32 mask;
+ int proto;
+ int dir;
+ register int vlen;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ proto = q.proto;
+ dir = q.dir;
+ if (s == NULL)
+ vlen = 32;
+ else if (q.proto == Q_DECNET) {
+ vlen = __pcap_atodn(s, &v);
+ if (vlen == 0)
+ bpf_error(cstate, "malformed decnet address '%s'", s);
+ } else
+ vlen = __pcap_atoin(s, &v);
+
+ switch (q.addr) {
+
+ case Q_DEFAULT:
+ case Q_HOST:
+ case Q_NET:
+ if (proto == Q_DECNET)
+ return gen_host(cstate, v, 0, proto, dir, q.addr);
+ else if (proto == Q_LINK) {
+ bpf_error(cstate, "illegal link layer address");
+ } else {
+ mask = 0xffffffff;
+ if (s == NULL && q.addr == Q_NET) {
+ /* Promote short net number */
+ while (v && (v & 0xff000000) == 0) {
+ v <<= 8;
+ mask <<= 8;
+ }
+ } else {
+ /* Promote short ipaddr */
+ v <<= 32 - vlen;
+ mask <<= 32 - vlen ;
+ }
+ return gen_host(cstate, v, mask, proto, dir, q.addr);
+ }
+
+ case Q_PORT:
+ if (proto == Q_UDP)
+ proto = IPPROTO_UDP;
+ else if (proto == Q_TCP)
+ proto = IPPROTO_TCP;
+ else if (proto == Q_SCTP)
+ proto = IPPROTO_SCTP;
+ else if (proto == Q_DEFAULT)
+ proto = PROTO_UNDEF;
+ else
+ bpf_error(cstate, "illegal qualifier of 'port'");
+
+ if (v > 65535)
+ bpf_error(cstate, "illegal port number %u > 65535", v);
+
+ {
+ struct block *b;
+ b = gen_port(cstate, (int)v, proto, dir);
+ gen_or(gen_port6(cstate, (int)v, proto, dir), b);
+ return b;
+ }
+
+ case Q_PORTRANGE:
+ if (proto == Q_UDP)
+ proto = IPPROTO_UDP;
+ else if (proto == Q_TCP)
+ proto = IPPROTO_TCP;
+ else if (proto == Q_SCTP)
+ proto = IPPROTO_SCTP;
+ else if (proto == Q_DEFAULT)
+ proto = PROTO_UNDEF;
+ else
+ bpf_error(cstate, "illegal qualifier of 'portrange'");
+
+ if (v > 65535)
+ bpf_error(cstate, "illegal port number %u > 65535", v);
+
+ {
+ struct block *b;
+ b = gen_portrange(cstate, (int)v, (int)v, proto, dir);
+ gen_or(gen_portrange6(cstate, (int)v, (int)v, proto, dir), b);
+ return b;
+ }
+
+ case Q_GATEWAY:
+ bpf_error(cstate, "'gateway' requires a name");
+ /*NOTREACHED*/
+
+ case Q_PROTO:
+ return gen_proto(cstate, (int)v, proto, dir);
+
+ case Q_PROTOCHAIN:
+ return gen_protochain(cstate, (int)v, proto, dir);
+
+ case Q_UNDEF:
+ syntax(cstate);
+ /*NOTREACHED*/
+
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+ /*NOTREACHED*/
+}
+
+#ifdef INET6
+struct block *
+gen_mcode6(compiler_state_t *cstate, const char *s1, const char *s2,
+ unsigned int masklen, struct qual q)
+{
+ struct addrinfo *res;
+ struct in6_addr *addr;
+ struct in6_addr mask;
+ struct block *b;
+ uint32_t *a, *m;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (s2)
+ bpf_error(cstate, "no mask %s supported", s2);
+
+ res = pcap_nametoaddrinfo(s1);
+ if (!res)
+ bpf_error(cstate, "invalid ip6 address %s", s1);
+ cstate->ai = res;
+ if (res->ai_next)
+ bpf_error(cstate, "%s resolved to multiple address", s1);
+ addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+
+ if (sizeof(mask) * 8 < masklen)
+ bpf_error(cstate, "mask length must be <= %u", (unsigned int)(sizeof(mask) * 8));
+ memset(&mask, 0, sizeof(mask));
+ memset(&mask, 0xff, masklen / 8);
+ if (masklen % 8) {
+ mask.s6_addr[masklen / 8] =
+ (0xff << (8 - masklen % 8)) & 0xff;
+ }
+
+ a = (uint32_t *)addr;
+ m = (uint32_t *)&mask;
+ if ((a[0] & ~m[0]) || (a[1] & ~m[1])
+ || (a[2] & ~m[2]) || (a[3] & ~m[3])) {
+ bpf_error(cstate, "non-network bits set in \"%s/%d\"", s1, masklen);
+ }
+
+ switch (q.addr) {
+
+ case Q_DEFAULT:
+ case Q_HOST:
+ if (masklen != 128)
+ bpf_error(cstate, "Mask syntax for networks only");
+ /* FALLTHROUGH */
+
+ case Q_NET:
+ b = gen_host6(cstate, addr, &mask, q.proto, q.dir, q.addr);
+ cstate->ai = NULL;
+ freeaddrinfo(res);
+ return b;
+
+ default:
+ bpf_error(cstate, "invalid qualifier against IPv6 address");
+ /*NOTREACHED*/
+ }
+}
+#endif /*INET6*/
+
+struct block *
+gen_ecode(compiler_state_t *cstate, const char *s, struct qual q)
+{
+ struct block *b, *tmp;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) {
+ cstate->e = pcap_ether_aton(s);
+ if (cstate->e == NULL)
+ bpf_error(cstate, "malloc");
+ switch (cstate->linktype) {
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ tmp = gen_prevlinkhdr_check(cstate);
+ b = gen_ehostop(cstate, cstate->e, (int)q.dir);
+ if (tmp != NULL)
+ gen_and(tmp, b);
+ break;
+ case DLT_FDDI:
+ b = gen_fhostop(cstate, cstate->e, (int)q.dir);
+ break;
+ case DLT_IEEE802:
+ b = gen_thostop(cstate, cstate->e, (int)q.dir);
+ break;
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ b = gen_wlanhostop(cstate, cstate->e, (int)q.dir);
+ break;
+ case DLT_IP_OVER_FC:
+ b = gen_ipfchostop(cstate, cstate->e, (int)q.dir);
+ break;
+ default:
+ free(cstate->e);
+ cstate->e = NULL;
+ bpf_error(cstate, "ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel");
+ /*NOTREACHED*/
+ }
+ free(cstate->e);
+ cstate->e = NULL;
+ return (b);
+ }
+ bpf_error(cstate, "ethernet address used in non-ether expression");
+ /*NOTREACHED*/
+}
+
+void
+sappend(struct slist *s0, struct slist *s1)
+{
+ /*
+ * This is definitely not the best way to do this, but the
+ * lists will rarely get long.
+ */
+ while (s0->next)
+ s0 = s0->next;
+ s0->next = s1;
+}
+
+static struct slist *
+xfer_to_x(compiler_state_t *cstate, struct arth *a)
+{
+ struct slist *s;
+
+ s = new_stmt(cstate, BPF_LDX|BPF_MEM);
+ s->s.k = a->regno;
+ return s;
+}
+
+static struct slist *
+xfer_to_a(compiler_state_t *cstate, struct arth *a)
+{
+ struct slist *s;
+
+ s = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s->s.k = a->regno;
+ return s;
+}
+
+/*
+ * Modify "index" to use the value stored into its register as an
+ * offset relative to the beginning of the header for the protocol
+ * "proto", and allocate a register and put an item "size" bytes long
+ * (1, 2, or 4) at that offset into that register, making it the register
+ * for "index".
+ */
+static struct arth *
+gen_load_internal(compiler_state_t *cstate, int proto, struct arth *inst, int size)
+{
+ struct slist *s, *tmp;
+ struct block *b;
+ int regno = alloc_reg(cstate);
+
+ free_reg(cstate, inst->regno);
+ switch (size) {
+
+ default:
+ bpf_error(cstate, "data size must be 1, 2, or 4");
+
+ case 1:
+ size = BPF_B;
+ break;
+
+ case 2:
+ size = BPF_H;
+ break;
+
+ case 4:
+ size = BPF_W;
+ break;
+ }
+ switch (proto) {
+ default:
+ bpf_error(cstate, "unsupported index operation");
+
+ case Q_RADIO:
+ /*
+ * The offset is relative to the beginning of the packet
+ * data, if we have a radio header. (If we don't, this
+ * is an error.)
+ */
+ if (cstate->linktype != DLT_IEEE802_11_RADIO_AVS &&
+ cstate->linktype != DLT_IEEE802_11_RADIO &&
+ cstate->linktype != DLT_PRISM_HEADER)
+ bpf_error(cstate, "radio information not present in capture");
+
+ /*
+ * Load into the X register the offset computed into the
+ * register specified by "index".
+ */
+ s = xfer_to_x(cstate, inst);
+
+ /*
+ * Load the item at that offset.
+ */
+ tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ sappend(s, tmp);
+ sappend(inst->s, s);
+ break;
+
+ case Q_LINK:
+ /*
+ * The offset is relative to the beginning of
+ * the link-layer header.
+ *
+ * XXX - what about ATM LANE? Should the index be
+ * relative to the beginning of the AAL5 frame, so
+ * that 0 refers to the beginning of the LE Control
+ * field, or relative to the beginning of the LAN
+ * frame, so that 0 refers, for Ethernet LANE, to
+ * the beginning of the destination address?
+ */
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkhdr);
+
+ /*
+ * If "s" is non-null, it has code to arrange that the
+ * X register contains the length of the prefix preceding
+ * the link-layer header. Add to it the offset computed
+ * into the register specified by "index", and move that
+ * into the X register. Otherwise, just load into the X
+ * register the offset computed into the register specified
+ * by "index".
+ */
+ if (s != NULL) {
+ sappend(s, xfer_to_a(cstate, inst));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
+ } else
+ s = xfer_to_x(cstate, inst);
+
+ /*
+ * Load the item at the sum of the offset we've put in the
+ * X register and the offset of the start of the link
+ * layer header (which is 0 if the radio header is
+ * variable-length; that header length is what we put
+ * into the X register and then added to the index).
+ */
+ tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ tmp->s.k = cstate->off_linkhdr.constant_part;
+ sappend(s, tmp);
+ sappend(inst->s, s);
+ break;
+
+ case Q_IP:
+ case Q_ARP:
+ case Q_RARP:
+ case Q_ATALK:
+ case Q_DECNET:
+ case Q_SCA:
+ case Q_LAT:
+ case Q_MOPRC:
+ case Q_MOPDL:
+ case Q_IPV6:
+ /*
+ * The offset is relative to the beginning of
+ * the network-layer header.
+ * XXX - are there any cases where we want
+ * cstate->off_nl_nosnap?
+ */
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
+
+ /*
+ * If "s" is non-null, it has code to arrange that the
+ * X register contains the variable part of the offset
+ * of the link-layer payload. Add to it the offset
+ * computed into the register specified by "index",
+ * and move that into the X register. Otherwise, just
+ * load into the X register the offset computed into
+ * the register specified by "index".
+ */
+ if (s != NULL) {
+ sappend(s, xfer_to_a(cstate, inst));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
+ } else
+ s = xfer_to_x(cstate, inst);
+
+ /*
+ * Load the item at the sum of the offset we've put in the
+ * X register, the offset of the start of the network
+ * layer header from the beginning of the link-layer
+ * payload, and the constant part of the offset of the
+ * start of the link-layer payload.
+ */
+ tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ sappend(s, tmp);
+ sappend(inst->s, s);
+
+ /*
+ * Do the computation only if the packet contains
+ * the protocol in question.
+ */
+ b = gen_proto_abbrev_internal(cstate, proto);
+ if (inst->b)
+ gen_and(inst->b, b);
+ inst->b = b;
+ break;
+
+ case Q_SCTP:
+ case Q_TCP:
+ case Q_UDP:
+ case Q_ICMP:
+ case Q_IGMP:
+ case Q_IGRP:
+ case Q_PIM:
+ case Q_VRRP:
+ case Q_CARP:
+ /*
+ * The offset is relative to the beginning of
+ * the transport-layer header.
+ *
+ * Load the X register with the length of the IPv4 header
+ * (plus the offset of the link-layer header, if it's
+ * a variable-length header), in bytes.
+ *
+ * XXX - are there any cases where we want
+ * cstate->off_nl_nosnap?
+ * XXX - we should, if we're built with
+ * IPv6 support, generate code to load either
+ * IPv4, IPv6, or both, as appropriate.
+ */
+ s = gen_loadx_iphdrlen(cstate);
+
+ /*
+ * The X register now contains the sum of the variable
+ * part of the offset of the link-layer payload and the
+ * length of the network-layer header.
+ *
+ * Load into the A register the offset relative to
+ * the beginning of the transport layer header,
+ * add the X register to that, move that to the
+ * X register, and load with an offset from the
+ * X register equal to the sum of the constant part of
+ * the offset of the link-layer payload and the offset,
+ * relative to the beginning of the link-layer payload,
+ * of the network-layer header.
+ */
+ sappend(s, xfer_to_a(cstate, inst));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
+ sappend(s, tmp = new_stmt(cstate, BPF_LD|BPF_IND|size));
+ tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl;
+ sappend(inst->s, s);
+
+ /*
+ * Do the computation only if the packet contains
+ * the protocol in question - which is true only
+ * if this is an IP datagram and is the first or
+ * only fragment of that datagram.
+ */
+ gen_and(gen_proto_abbrev_internal(cstate, proto), b = gen_ipfrag(cstate));
+ if (inst->b)
+ gen_and(inst->b, b);
+ gen_and(gen_proto_abbrev_internal(cstate, Q_IP), b);
+ inst->b = b;
+ break;
+ case Q_ICMPV6:
+ /*
+ * Do the computation only if the packet contains
+ * the protocol in question.
+ */
+ b = gen_proto_abbrev_internal(cstate, Q_IPV6);
+ if (inst->b) {
+ gen_and(inst->b, b);
+ }
+ inst->b = b;
+
+ /*
+ * Check if we have an icmp6 next header
+ */
+ b = gen_cmp(cstate, OR_LINKPL, 6, BPF_B, 58);
+ if (inst->b) {
+ gen_and(inst->b, b);
+ }
+ inst->b = b;
+
+
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
+ /*
+ * If "s" is non-null, it has code to arrange that the
+ * X register contains the variable part of the offset
+ * of the link-layer payload. Add to it the offset
+ * computed into the register specified by "index",
+ * and move that into the X register. Otherwise, just
+ * load into the X register the offset computed into
+ * the register specified by "index".
+ */
+ if (s != NULL) {
+ sappend(s, xfer_to_a(cstate, inst));
+ sappend(s, new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X));
+ sappend(s, new_stmt(cstate, BPF_MISC|BPF_TAX));
+ } else {
+ s = xfer_to_x(cstate, inst);
+ }
+
+ /*
+ * Load the item at the sum of the offset we've put in the
+ * X register, the offset of the start of the network
+ * layer header from the beginning of the link-layer
+ * payload, and the constant part of the offset of the
+ * start of the link-layer payload.
+ */
+ tmp = new_stmt(cstate, BPF_LD|BPF_IND|size);
+ tmp->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 40;
+
+ sappend(s, tmp);
+ sappend(inst->s, s);
+
+ break;
+ }
+ inst->regno = regno;
+ s = new_stmt(cstate, BPF_ST);
+ s->s.k = regno;
+ sappend(inst->s, s);
+
+ return inst;
+}
+
+struct arth *
+gen_load(compiler_state_t *cstate, int proto, struct arth *inst, int size)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ return gen_load_internal(cstate, proto, inst, size);
+}
+
+static struct block *
+gen_relation_internal(compiler_state_t *cstate, int code, struct arth *a0,
+ struct arth *a1, int reversed)
+{
+ struct slist *s0, *s1, *s2;
+ struct block *b, *tmp;
+
+ s0 = xfer_to_x(cstate, a1);
+ s1 = xfer_to_a(cstate, a0);
+ if (code == BPF_JEQ) {
+ s2 = new_stmt(cstate, BPF_ALU|BPF_SUB|BPF_X);
+ b = new_block(cstate, JMP(code));
+ sappend(s1, s2);
+ }
+ else
+ b = new_block(cstate, BPF_JMP|code|BPF_X);
+ if (reversed)
+ gen_not(b);
+
+ sappend(s0, s1);
+ sappend(a1->s, s0);
+ sappend(a0->s, a1->s);
+
+ b->stmts = a0->s;
+
+ free_reg(cstate, a0->regno);
+ free_reg(cstate, a1->regno);
+
+ /* 'and' together protocol checks */
+ if (a0->b) {
+ if (a1->b) {
+ gen_and(a0->b, tmp = a1->b);
+ }
+ else
+ tmp = a0->b;
+ } else
+ tmp = a1->b;
+
+ if (tmp)
+ gen_and(tmp, b);
+
+ return b;
+}
+
+struct block *
+gen_relation(compiler_state_t *cstate, int code, struct arth *a0,
+ struct arth *a1, int reversed)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ return gen_relation_internal(cstate, code, a0, a1, reversed);
+}
+
+struct arth *
+gen_loadlen(compiler_state_t *cstate)
+{
+ int regno;
+ struct arth *a;
+ struct slist *s;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ regno = alloc_reg(cstate);
+ a = (struct arth *)newchunk(cstate, sizeof(*a));
+ s = new_stmt(cstate, BPF_LD|BPF_LEN);
+ s->next = new_stmt(cstate, BPF_ST);
+ s->next->s.k = regno;
+ a->s = s;
+ a->regno = regno;
+
+ return a;
+}
+
+static struct arth *
+gen_loadi_internal(compiler_state_t *cstate, int val)
+{
+ struct arth *a;
+ struct slist *s;
+ int reg;
+
+ a = (struct arth *)newchunk(cstate, sizeof(*a));
+
+ reg = alloc_reg(cstate);
+
+ s = new_stmt(cstate, BPF_LD|BPF_IMM);
+ s->s.k = val;
+ s->next = new_stmt(cstate, BPF_ST);
+ s->next->s.k = reg;
+ a->s = s;
+ a->regno = reg;
+
+ return a;
+}
+
+struct arth *
+gen_loadi(compiler_state_t *cstate, int val)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ return gen_loadi_internal(cstate, val);
+}
+
+/*
+ * The a_arg dance is to avoid annoying whining by compilers that
+ * a might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
+struct arth *
+gen_neg(compiler_state_t *cstate, struct arth *a_arg)
+{
+ struct arth *a = a_arg;
+ struct slist *s;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ s = xfer_to_a(cstate, a);
+ sappend(a->s, s);
+ s = new_stmt(cstate, BPF_ALU|BPF_NEG);
+ s->s.k = 0;
+ sappend(a->s, s);
+ s = new_stmt(cstate, BPF_ST);
+ s->s.k = a->regno;
+ sappend(a->s, s);
+
+ return a;
+}
+
+/*
+ * The a0_arg dance is to avoid annoying whining by compilers that
+ * a0 might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
+struct arth *
+gen_arth(compiler_state_t *cstate, int code, struct arth *a0_arg,
+ struct arth *a1)
+{
+ struct arth *a0 = a0_arg;
+ struct slist *s0, *s1, *s2;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Disallow division by, or modulus by, zero; we do this here
+ * so that it gets done even if the optimizer is disabled.
+ *
+ * Also disallow shifts by a value greater than 31; we do this
+ * here, for the same reason.
+ */
+ if (code == BPF_DIV) {
+ if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
+ bpf_error(cstate, "division by zero");
+ } else if (code == BPF_MOD) {
+ if (a1->s->s.code == (BPF_LD|BPF_IMM) && a1->s->s.k == 0)
+ bpf_error(cstate, "modulus by zero");
+ } else if (code == BPF_LSH || code == BPF_RSH) {
+ /*
+ * XXX - we need to make up our minds as to what integers
+ * are signed and what integers are unsigned in BPF programs
+ * and in our IR.
+ */
+ if (a1->s->s.code == (BPF_LD|BPF_IMM) &&
+ (a1->s->s.k < 0 || a1->s->s.k > 31))
+ bpf_error(cstate, "shift by more than 31 bits");
+ }
+ s0 = xfer_to_x(cstate, a1);
+ s1 = xfer_to_a(cstate, a0);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_X|code);
+
+ sappend(s1, s2);
+ sappend(s0, s1);
+ sappend(a1->s, s0);
+ sappend(a0->s, a1->s);
+
+ free_reg(cstate, a0->regno);
+ free_reg(cstate, a1->regno);
+
+ s0 = new_stmt(cstate, BPF_ST);
+ a0->regno = s0->s.k = alloc_reg(cstate);
+ sappend(a0->s, s0);
+
+ return a0;
+}
+
+/*
+ * Initialize the table of used registers and the current register.
+ */
+static void
+init_regs(compiler_state_t *cstate)
+{
+ cstate->curreg = 0;
+ memset(cstate->regused, 0, sizeof cstate->regused);
+}
+
+/*
+ * Return the next free register.
+ */
+static int
+alloc_reg(compiler_state_t *cstate)
+{
+ int n = BPF_MEMWORDS;
+
+ while (--n >= 0) {
+ if (cstate->regused[cstate->curreg])
+ cstate->curreg = (cstate->curreg + 1) % BPF_MEMWORDS;
+ else {
+ cstate->regused[cstate->curreg] = 1;
+ return cstate->curreg;
+ }
+ }
+ bpf_error(cstate, "too many registers needed to evaluate expression");
+ /*NOTREACHED*/
+}
+
+/*
+ * Return a register to the table so it can
+ * be used later.
+ */
+static void
+free_reg(compiler_state_t *cstate, int n)
+{
+ cstate->regused[n] = 0;
+}
+
+static struct block *
+gen_len(compiler_state_t *cstate, int jmp, int n)
+{
+ struct slist *s;
+ struct block *b;
+
+ s = new_stmt(cstate, BPF_LD|BPF_LEN);
+ b = new_block(cstate, JMP(jmp));
+ b->stmts = s;
+ b->s.k = n;
+
+ return b;
+}
+
+struct block *
+gen_greater(compiler_state_t *cstate, int n)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ return gen_len(cstate, BPF_JGE, n);
+}
+
+/*
+ * Actually, this is less than or equal.
+ */
+struct block *
+gen_less(compiler_state_t *cstate, int n)
+{
+ struct block *b;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ b = gen_len(cstate, BPF_JGT, n);
+ gen_not(b);
+
+ return b;
+}
+
+/*
+ * This is for "byte {idx} {op} {val}"; "idx" is treated as relative to
+ * the beginning of the link-layer header.
+ * XXX - that means you can't test values in the radiotap header, but
+ * as that header is difficult if not impossible to parse generally
+ * without a loop, that might not be a severe problem. A new keyword
+ * "radio" could be added for that, although what you'd really want
+ * would be a way of testing particular radio header values, which
+ * would generate code appropriate to the radio header in question.
+ */
+struct block *
+gen_byteop(compiler_state_t *cstate, int op, int idx, int val)
+{
+ struct block *b;
+ struct slist *s;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (op) {
+ default:
+ abort();
+
+ case '=':
+ return gen_cmp(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+
+ case '<':
+ b = gen_cmp_lt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+ return b;
+
+ case '>':
+ b = gen_cmp_gt(cstate, OR_LINKHDR, (u_int)idx, BPF_B, (bpf_int32)val);
+ return b;
+
+ case '|':
+ s = new_stmt(cstate, BPF_ALU|BPF_OR|BPF_K);
+ break;
+
+ case '&':
+ s = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+ break;
+ }
+ s->s.k = val;
+ b = new_block(cstate, JMP(BPF_JEQ));
+ b->stmts = s;
+ gen_not(b);
+
+ return b;
+}
+
+static const u_char abroadcast[] = { 0x0 };
+
+struct block *
+gen_broadcast(compiler_state_t *cstate, int proto)
+{
+ bpf_u_int32 hostmask;
+ struct block *b0, *b1, *b2;
+ static const u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ case Q_LINK:
+ switch (cstate->linktype) {
+ case DLT_ARCNET:
+ case DLT_ARCNET_LINUX:
+ return gen_ahostop(cstate, abroadcast, Q_DST);
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ b1 = gen_prevlinkhdr_check(cstate);
+ b0 = gen_ehostop(cstate, ebroadcast, Q_DST);
+ if (b1 != NULL)
+ gen_and(b1, b0);
+ return b0;
+ case DLT_FDDI:
+ return gen_fhostop(cstate, ebroadcast, Q_DST);
+ case DLT_IEEE802:
+ return gen_thostop(cstate, ebroadcast, Q_DST);
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ return gen_wlanhostop(cstate, ebroadcast, Q_DST);
+ case DLT_IP_OVER_FC:
+ return gen_ipfchostop(cstate, ebroadcast, Q_DST);
+ default:
+ bpf_error(cstate, "not a broadcast link");
+ }
+ /*NOTREACHED*/
+
+ case Q_IP:
+ /*
+ * We treat a netmask of PCAP_NETMASK_UNKNOWN (0xffffffff)
+ * as an indication that we don't know the netmask, and fail
+ * in that case.
+ */
+ if (cstate->netmask == PCAP_NETMASK_UNKNOWN)
+ bpf_error(cstate, "netmask not known, so 'ip broadcast' not supported");
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+ hostmask = ~cstate->netmask;
+ b1 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W, (bpf_int32)0, hostmask);
+ b2 = gen_mcmp(cstate, OR_LINKPL, 16, BPF_W,
+ (bpf_int32)(~0 & hostmask), hostmask);
+ gen_or(b1, b2);
+ gen_and(b0, b2);
+ return b2;
+ }
+ bpf_error(cstate, "only link-layer/IP broadcast filters supported");
+ /*NOTREACHED*/
+}
+
+/*
+ * Generate code to test the low-order bit of a MAC address (that's
+ * the bottom bit of the *first* byte).
+ */
+static struct block *
+gen_mac_multicast(compiler_state_t *cstate, int offset)
+{
+ register struct block *b0;
+ register struct slist *s;
+
+ /* link[offset] & 1 != 0 */
+ s = gen_load_a(cstate, OR_LINKHDR, offset, BPF_B);
+ b0 = new_block(cstate, JMP(BPF_JSET));
+ b0->s.k = 1;
+ b0->stmts = s;
+ return b0;
+}
+
+struct block *
+gen_multicast(compiler_state_t *cstate, int proto)
+{
+ register struct block *b0, *b1, *b2;
+ register struct slist *s;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (proto) {
+
+ case Q_DEFAULT:
+ case Q_LINK:
+ switch (cstate->linktype) {
+ case DLT_ARCNET:
+ case DLT_ARCNET_LINUX:
+ /* all ARCnet multicasts use the same address */
+ return gen_ahostop(cstate, abroadcast, Q_DST);
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ b1 = gen_prevlinkhdr_check(cstate);
+ /* ether[0] & 1 != 0 */
+ b0 = gen_mac_multicast(cstate, 0);
+ if (b1 != NULL)
+ gen_and(b1, b0);
+ return b0;
+ case DLT_FDDI:
+ /*
+ * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX
+ *
+ * XXX - was that referring to bit-order issues?
+ */
+ /* fddi[1] & 1 != 0 */
+ return gen_mac_multicast(cstate, 1);
+ case DLT_IEEE802:
+ /* tr[2] & 1 != 0 */
+ return gen_mac_multicast(cstate, 2);
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ case DLT_PPI:
+ /*
+ * Oh, yuk.
+ *
+ * For control frames, there is no DA.
+ *
+ * For management frames, DA is at an
+ * offset of 4 from the beginning of
+ * the packet.
+ *
+ * For data frames, DA is at an offset
+ * of 4 from the beginning of the packet
+ * if To DS is clear and at an offset of
+ * 16 from the beginning of the packet
+ * if To DS is set.
+ */
+
+ /*
+ * Generate the tests to be done for data frames.
+ *
+ * First, check for To DS set, i.e. "link[1] & 0x01".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x01; /* To DS */
+ b1->stmts = s;
+
+ /*
+ * If To DS is set, the DA is at 16.
+ */
+ b0 = gen_mac_multicast(cstate, 16);
+ gen_and(b1, b0);
+
+ /*
+ * Now, check for To DS not set, i.e. check
+ * "!(link[1] & 0x01)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 1, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
+ b2->s.k = 0x01; /* To DS */
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * If To DS is not set, the DA is at 4.
+ */
+ b1 = gen_mac_multicast(cstate, 4);
+ gen_and(b2, b1);
+
+ /*
+ * Now OR together the last two checks. That gives
+ * the complete set of checks for data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * Now check for a data frame.
+ * I.e, check "link[0] & 0x08".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x08;
+ b1->stmts = s;
+
+ /*
+ * AND that with the checks done for data frames.
+ */
+ gen_and(b1, b0);
+
+ /*
+ * If the high-order bit of the type value is 0, this
+ * is a management frame.
+ * I.e, check "!(link[0] & 0x08)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b2 = new_block(cstate, JMP(BPF_JSET));
+ b2->s.k = 0x08;
+ b2->stmts = s;
+ gen_not(b2);
+
+ /*
+ * For management frames, the DA is at 4.
+ */
+ b1 = gen_mac_multicast(cstate, 4);
+ gen_and(b2, b1);
+
+ /*
+ * OR that with the checks done for data frames.
+ * That gives the checks done for management and
+ * data frames.
+ */
+ gen_or(b1, b0);
+
+ /*
+ * If the low-order bit of the type value is 1,
+ * this is either a control frame or a frame
+ * with a reserved type, and thus not a
+ * frame with an SA.
+ *
+ * I.e., check "!(link[0] & 0x04)".
+ */
+ s = gen_load_a(cstate, OR_LINKHDR, 0, BPF_B);
+ b1 = new_block(cstate, JMP(BPF_JSET));
+ b1->s.k = 0x04;
+ b1->stmts = s;
+ gen_not(b1);
+
+ /*
+ * AND that with the checks for data and management
+ * frames.
+ */
+ gen_and(b1, b0);
+ return b0;
+ case DLT_IP_OVER_FC:
+ b0 = gen_mac_multicast(cstate, 2);
+ return b0;
+ default:
+ break;
+ }
+ /* Link not known to support multicasts */
+ break;
+
+ case Q_IP:
+ b0 = gen_linktype(cstate, ETHERTYPE_IP);
+ b1 = gen_cmp_ge(cstate, OR_LINKPL, 16, BPF_B, (bpf_int32)224);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_IPV6:
+ b0 = gen_linktype(cstate, ETHERTYPE_IPV6);
+ b1 = gen_cmp(cstate, OR_LINKPL, 24, BPF_B, (bpf_int32)255);
+ gen_and(b0, b1);
+ return b1;
+ }
+ bpf_error(cstate, "link-layer multicast filters supported only on ethernet/FDDI/token ring/ARCNET/802.11/ATM LANE/Fibre Channel");
+ /*NOTREACHED*/
+}
+
+/*
+ * Filter on inbound (dir == 0) or outbound (dir == 1) traffic.
+ * Outbound traffic is sent by this machine, while inbound traffic is
+ * sent by a remote machine (and may include packets destined for a
+ * unicast or multicast link-layer address we are not subscribing to).
+ * These are the same definitions implemented by pcap_setdirection().
+ * Capturing only unicast traffic destined for this host is probably
+ * better accomplished using a higher-layer filter.
+ */
+struct block *
+gen_inbound(compiler_state_t *cstate, int dir)
+{
+ register struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Only some data link types support inbound/outbound qualifiers.
+ */
+ switch (cstate->linktype) {
+ case DLT_SLIP:
+ b0 = gen_relation_internal(cstate, BPF_JEQ,
+ gen_load_internal(cstate, Q_LINK, gen_loadi_internal(cstate, 0), 1),
+ gen_loadi_internal(cstate, 0),
+ dir);
+ break;
+
+ case DLT_IPNET:
+ if (dir) {
+ /* match outgoing packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_OUTBOUND);
+ } else {
+ /* match incoming packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 2, BPF_H, IPNET_INBOUND);
+ }
+ break;
+
+ case DLT_LINUX_SLL:
+ /* match outgoing packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_H, LINUX_SLL_OUTGOING);
+ if (!dir) {
+ /* to filter on inbound traffic, invert the match */
+ gen_not(b0);
+ }
+ break;
+
+ case DLT_LINUX_SLL2:
+ /* match outgoing packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 10, BPF_B, LINUX_SLL_OUTGOING);
+ if (!dir) {
+ /* to filter on inbound traffic, invert the match */
+ gen_not(b0);
+ }
+ break;
+
+#ifdef HAVE_NET_PFVAR_H
+ case DLT_PFLOG:
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, dir), BPF_B,
+ (bpf_int32)((dir == 0) ? PF_IN : PF_OUT));
+ break;
+#endif
+
+ case DLT_PPP_PPPD:
+ if (dir) {
+ /* match outgoing packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_OUT);
+ } else {
+ /* match incoming packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, 0, BPF_B, PPP_PPPD_IN);
+ }
+ break;
+
+ case DLT_JUNIPER_MFR:
+ case DLT_JUNIPER_MLFR:
+ case DLT_JUNIPER_MLPPP:
+ case DLT_JUNIPER_ATM1:
+ case DLT_JUNIPER_ATM2:
+ case DLT_JUNIPER_PPPOE:
+ case DLT_JUNIPER_PPPOE_ATM:
+ case DLT_JUNIPER_GGSN:
+ case DLT_JUNIPER_ES:
+ case DLT_JUNIPER_MONITOR:
+ case DLT_JUNIPER_SERVICES:
+ case DLT_JUNIPER_ETHER:
+ case DLT_JUNIPER_PPP:
+ case DLT_JUNIPER_FRELAY:
+ case DLT_JUNIPER_CHDLC:
+ case DLT_JUNIPER_VP:
+ case DLT_JUNIPER_ST:
+ case DLT_JUNIPER_ISM:
+ case DLT_JUNIPER_VS:
+ case DLT_JUNIPER_SRX_E2E:
+ case DLT_JUNIPER_FIBRECHANNEL:
+ case DLT_JUNIPER_ATM_CEMIC:
+
+ /* juniper flags (including direction) are stored
+ * the byte after the 3-byte magic number */
+ if (dir) {
+ /* match outgoing packets */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 0, 0x01);
+ } else {
+ /* match incoming packets */
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 3, BPF_B, 1, 0x01);
+ }
+ break;
+
+ default:
+ /*
+ * If we have packet meta-data indicating a direction,
+ * and that metadata can be checked by BPF code, check
+ * it. Otherwise, give up, as this link-layer type has
+ * nothing in the packet data.
+ *
+ * Currently, the only platform where a BPF filter can
+ * check that metadata is Linux with the in-kernel
+ * BPF interpreter. If other packet capture mechanisms
+ * and BPF filters also supported this, it would be
+ * nice. It would be even better if they made that
+ * metadata available so that we could provide it
+ * with newer capture APIs, allowing it to be saved
+ * in pcapng files.
+ */
+#if defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER)
+ /*
+ * This is Linux with PF_PACKET support.
+ * If this is a *live* capture, we can look at
+ * special meta-data in the filter expression;
+ * if it's a savefile, we can't.
+ */
+ if (cstate->bpf_pcap->rfile != NULL) {
+ /* We have a FILE *, so this is a savefile */
+ bpf_error(cstate, "inbound/outbound not supported on %s when reading savefiles",
+ pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+ b0 = NULL;
+ /*NOTREACHED*/
+ }
+ /* match outgoing packets */
+ b0 = gen_cmp(cstate, OR_LINKHDR, SKF_AD_OFF + SKF_AD_PKTTYPE, BPF_H,
+ PACKET_OUTGOING);
+ if (!dir) {
+ /* to filter on inbound traffic, invert the match */
+ gen_not(b0);
+ }
+#else /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
+ bpf_error(cstate, "inbound/outbound not supported on %s",
+ pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+ /*NOTREACHED*/
+#endif /* defined(linux) && defined(PF_PACKET) && defined(SO_ATTACH_FILTER) */
+ }
+ return (b0);
+}
+
+#ifdef HAVE_NET_PFVAR_H
+/* PF firewall log matched interface */
+struct block *
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname)
+{
+ struct block *b0;
+ u_int len, off;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "ifname supported only on PF linktype");
+ /*NOTREACHED*/
+ }
+ len = sizeof(((struct pfloghdr *)0)->ifname);
+ off = offsetof(struct pfloghdr, ifname);
+ if (strlen(ifname) >= len) {
+ bpf_error(cstate, "ifname interface names can only be %d characters",
+ len-1);
+ /*NOTREACHED*/
+ }
+ b0 = gen_bcmp(cstate, OR_LINKHDR, off, (u_int)strlen(ifname),
+ (const u_char *)ifname);
+ return (b0);
+}
+
+/* PF firewall log ruleset name */
+struct block *
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "ruleset supported only on PF linktype");
+ /*NOTREACHED*/
+ }
+
+ if (strlen(ruleset) >= sizeof(((struct pfloghdr *)0)->ruleset)) {
+ bpf_error(cstate, "ruleset names can only be %ld characters",
+ (long)(sizeof(((struct pfloghdr *)0)->ruleset) - 1));
+ /*NOTREACHED*/
+ }
+
+ b0 = gen_bcmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, ruleset),
+ (u_int)strlen(ruleset), (const u_char *)ruleset);
+ return (b0);
+}
+
+/* PF firewall log rule number */
+struct block *
+gen_pf_rnr(compiler_state_t *cstate, int rnr)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "rnr supported only on PF linktype");
+ /*NOTREACHED*/
+ }
+
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, rulenr), BPF_W,
+ (bpf_int32)rnr);
+ return (b0);
+}
+
+/* PF firewall log sub-rule number */
+struct block *
+gen_pf_srnr(compiler_state_t *cstate, int srnr)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "srnr supported only on PF linktype");
+ /*NOTREACHED*/
+ }
+
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, subrulenr), BPF_W,
+ (bpf_int32)srnr);
+ return (b0);
+}
+
+/* PF firewall log reason code */
+struct block *
+gen_pf_reason(compiler_state_t *cstate, int reason)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "reason supported only on PF linktype");
+ /*NOTREACHED*/
+ }
+
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, reason), BPF_B,
+ (bpf_int32)reason);
+ return (b0);
+}
+
+/* PF firewall log action */
+struct block *
+gen_pf_action(compiler_state_t *cstate, int action)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (cstate->linktype != DLT_PFLOG) {
+ bpf_error(cstate, "action supported only on PF linktype");
+ /*NOTREACHED*/
+ }
+
+ b0 = gen_cmp(cstate, OR_LINKHDR, offsetof(struct pfloghdr, action), BPF_B,
+ (bpf_int32)action);
+ return (b0);
+}
+#else /* !HAVE_NET_PFVAR_H */
+struct block *
+gen_pf_ifname(compiler_state_t *cstate, const char *ifname _U_)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ bpf_error(cstate, "libpcap was compiled without pf support");
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_pf_ruleset(compiler_state_t *cstate, char *ruleset _U_)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_pf_rnr(compiler_state_t *cstate, int rnr _U_)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_pf_srnr(compiler_state_t *cstate, int srnr _U_)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_pf_reason(compiler_state_t *cstate, int reason _U_)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+ /*NOTREACHED*/
+}
+
+struct block *
+gen_pf_action(compiler_state_t *cstate, int action _U_)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ bpf_error(cstate, "libpcap was compiled on a machine without pf support");
+ /*NOTREACHED*/
+}
+#endif /* HAVE_NET_PFVAR_H */
+
+/* IEEE 802.11 wireless header */
+struct block *
+gen_p80211_type(compiler_state_t *cstate, int type, int mask)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (cstate->linktype) {
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 0, BPF_B, (bpf_int32)type,
+ (bpf_int32)mask);
+ break;
+
+ default:
+ bpf_error(cstate, "802.11 link-layer types supported only on 802.11");
+ /*NOTREACHED*/
+ }
+
+ return (b0);
+}
+
+struct block *
+gen_p80211_fcdir(compiler_state_t *cstate, int fcdir)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (cstate->linktype) {
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ break;
+
+ default:
+ bpf_error(cstate, "frame direction supported only with 802.11 headers");
+ /*NOTREACHED*/
+ }
+
+ b0 = gen_mcmp(cstate, OR_LINKHDR, 1, BPF_B, (bpf_int32)fcdir,
+ (bpf_u_int32)IEEE80211_FC1_DIR_MASK);
+
+ return (b0);
+}
+
+struct block *
+gen_acode(compiler_state_t *cstate, const char *s, struct qual q)
+{
+ struct block *b;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (cstate->linktype) {
+
+ case DLT_ARCNET:
+ case DLT_ARCNET_LINUX:
+ if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) &&
+ q.proto == Q_LINK) {
+ cstate->e = pcap_ether_aton(s);
+ if (cstate->e == NULL)
+ bpf_error(cstate, "malloc");
+ b = gen_ahostop(cstate, cstate->e, (int)q.dir);
+ free(cstate->e);
+ cstate->e = NULL;
+ return (b);
+ } else
+ bpf_error(cstate, "ARCnet address used in non-arc expression");
+ /*NOTREACHED*/
+
+ default:
+ bpf_error(cstate, "aid supported only on ARCnet");
+ /*NOTREACHED*/
+ }
+}
+
+static struct block *
+gen_ahostop(compiler_state_t *cstate, const u_char *eaddr, int dir)
+{
+ register struct block *b0, *b1;
+
+ switch (dir) {
+ /* src comes first, different from Ethernet */
+ case Q_SRC:
+ return gen_bcmp(cstate, OR_LINKHDR, 0, 1, eaddr);
+
+ case Q_DST:
+ return gen_bcmp(cstate, OR_LINKHDR, 1, 1, eaddr);
+
+ case Q_AND:
+ b0 = gen_ahostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ahostop(cstate, eaddr, Q_DST);
+ gen_and(b0, b1);
+ return b1;
+
+ case Q_DEFAULT:
+ case Q_OR:
+ b0 = gen_ahostop(cstate, eaddr, Q_SRC);
+ b1 = gen_ahostop(cstate, eaddr, Q_DST);
+ gen_or(b0, b1);
+ return b1;
+
+ case Q_ADDR1:
+ bpf_error(cstate, "'addr1' and 'address1' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR2:
+ bpf_error(cstate, "'addr2' and 'address2' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR3:
+ bpf_error(cstate, "'addr3' and 'address3' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_ADDR4:
+ bpf_error(cstate, "'addr4' and 'address4' are only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_RA:
+ bpf_error(cstate, "'ra' is only supported on 802.11");
+ /*NOTREACHED*/
+
+ case Q_TA:
+ bpf_error(cstate, "'ta' is only supported on 802.11");
+ /*NOTREACHED*/
+ }
+ abort();
+ /*NOTREACHED*/
+}
+
+static struct block *
+gen_vlan_tpid_test(compiler_state_t *cstate)
+{
+ struct block *b0, *b1;
+
+ /* check for VLAN, including QinQ */
+ b0 = gen_linktype(cstate, ETHERTYPE_8021Q);
+ b1 = gen_linktype(cstate, ETHERTYPE_8021AD);
+ gen_or(b0,b1);
+ b0 = b1;
+ b1 = gen_linktype(cstate, ETHERTYPE_8021QINQ);
+ gen_or(b0,b1);
+
+ return b1;
+}
+
+static struct block *
+gen_vlan_vid_test(compiler_state_t *cstate, bpf_u_int32 vlan_num)
+{
+ if (vlan_num > 0x0fff) {
+ bpf_error(cstate, "VLAN tag %u greater than maximum %u",
+ vlan_num, 0x0fff);
+ }
+ return gen_mcmp(cstate, OR_LINKPL, 0, BPF_H, (bpf_int32)vlan_num, 0x0fff);
+}
+
+static struct block *
+gen_vlan_no_bpf_extensions(compiler_state_t *cstate, bpf_u_int32 vlan_num,
+ int has_vlan_tag)
+{
+ struct block *b0, *b1;
+
+ b0 = gen_vlan_tpid_test(cstate);
+
+ if (has_vlan_tag) {
+ b1 = gen_vlan_vid_test(cstate, vlan_num);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ /*
+ * Both payload and link header type follow the VLAN tags so that
+ * both need to be updated.
+ */
+ cstate->off_linkpl.constant_part += 4;
+ cstate->off_linktype.constant_part += 4;
+
+ return b0;
+}
+
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
+/* add v to variable part of off */
+static void
+gen_vlan_vloffset_add(compiler_state_t *cstate, bpf_abs_offset *off, int v, struct slist *s)
+{
+ struct slist *s2;
+
+ if (!off->is_variable)
+ off->is_variable = 1;
+ if (off->reg == -1)
+ off->reg = alloc_reg(cstate);
+
+ s2 = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s2->s.k = off->reg;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_IMM);
+ s2->s.k = v;
+ sappend(s, s2);
+ s2 = new_stmt(cstate, BPF_ST);
+ s2->s.k = off->reg;
+ sappend(s, s2);
+}
+
+/*
+ * patch block b_tpid (VLAN TPID test) to update variable parts of link payload
+ * and link type offsets first
+ */
+static void
+gen_vlan_patch_tpid_test(compiler_state_t *cstate, struct block *b_tpid)
+{
+ struct slist s;
+
+ /* offset determined at run time, shift variable part */
+ s.next = NULL;
+ cstate->is_vlan_vloffset = 1;
+ gen_vlan_vloffset_add(cstate, &cstate->off_linkpl, 4, &s);
+ gen_vlan_vloffset_add(cstate, &cstate->off_linktype, 4, &s);
+
+ /* we get a pointer to a chain of or-ed blocks, patch first of them */
+ sappend(s.next, b_tpid->head->stmts);
+ b_tpid->head->stmts = s.next;
+}
+
+/*
+ * patch block b_vid (VLAN id test) to load VID value either from packet
+ * metadata (using BPF extensions) if SKF_AD_VLAN_TAG_PRESENT is true
+ */
+static void
+gen_vlan_patch_vid_test(compiler_state_t *cstate, struct block *b_vid)
+{
+ struct slist *s, *s2, *sjeq;
+ unsigned cnt;
+
+ s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
+
+ /* true -> next instructions, false -> beginning of b_vid */
+ sjeq = new_stmt(cstate, JMP(BPF_JEQ));
+ sjeq->s.k = 1;
+ sjeq->s.jf = b_vid->stmts;
+ sappend(s, sjeq);
+
+ s2 = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ s2->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG;
+ sappend(s, s2);
+ sjeq->s.jt = s2;
+
+ /* Jump to the test in b_vid. We need to jump one instruction before
+ * the end of the b_vid block so that we only skip loading the TCI
+ * from packet data and not the 'and' instruction extractging VID.
+ */
+ cnt = 0;
+ for (s2 = b_vid->stmts; s2; s2 = s2->next)
+ cnt++;
+ s2 = new_stmt(cstate, JMP(BPF_JA));
+ s2->s.k = cnt - 1;
+ sappend(s, s2);
+
+ /* insert our statements at the beginning of b_vid */
+ sappend(s, b_vid->stmts);
+ b_vid->stmts = s;
+}
+
+/*
+ * Generate check for "vlan" or "vlan <id>" on systems with support for BPF
+ * extensions. Even if kernel supports VLAN BPF extensions, (outermost) VLAN
+ * tag can be either in metadata or in packet data; therefore if the
+ * SKF_AD_VLAN_TAG_PRESENT test is negative, we need to check link
+ * header for VLAN tag. As the decision is done at run time, we need
+ * update variable part of the offsets
+ */
+static struct block *
+gen_vlan_bpf_extensions(compiler_state_t *cstate, bpf_u_int32 vlan_num,
+ int has_vlan_tag)
+{
+ struct block *b0, *b_tpid, *b_vid = NULL;
+ struct slist *s;
+
+ /* generate new filter code based on extracting packet
+ * metadata */
+ s = new_stmt(cstate, BPF_LD|BPF_B|BPF_ABS);
+ s->s.k = SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT;
+
+ b0 = new_block(cstate, JMP(BPF_JEQ));
+ b0->stmts = s;
+ b0->s.k = 1;
+
+ /*
+ * This is tricky. We need to insert the statements updating variable
+ * parts of offsets before the the traditional TPID and VID tests so
+ * that they are called whenever SKF_AD_VLAN_TAG_PRESENT fails but
+ * we do not want this update to affect those checks. That's why we
+ * generate both test blocks first and insert the statements updating
+ * variable parts of both offsets after that. This wouldn't work if
+ * there already were variable length link header when entering this
+ * function but gen_vlan_bpf_extensions() isn't called in that case.
+ */
+ b_tpid = gen_vlan_tpid_test(cstate);
+ if (has_vlan_tag)
+ b_vid = gen_vlan_vid_test(cstate, vlan_num);
+
+ gen_vlan_patch_tpid_test(cstate, b_tpid);
+ gen_or(b0, b_tpid);
+ b0 = b_tpid;
+
+ if (has_vlan_tag) {
+ gen_vlan_patch_vid_test(cstate, b_vid);
+ gen_and(b0, b_vid);
+ b0 = b_vid;
+ }
+
+ return b0;
+}
+#endif
+
+/*
+ * support IEEE 802.1Q VLAN trunk over ethernet
+ */
+struct block *
+gen_vlan(compiler_state_t *cstate, bpf_u_int32 vlan_num, int has_vlan_tag)
+{
+ struct block *b0;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /* can't check for VLAN-encapsulated packets inside MPLS */
+ if (cstate->label_stack_depth > 0)
+ bpf_error(cstate, "no VLAN match after MPLS");
+
+ /*
+ * Check for a VLAN packet, and then change the offsets to point
+ * to the type and data fields within the VLAN packet. Just
+ * increment the offsets, so that we can support a hierarchy, e.g.
+ * "vlan 300 && vlan 200" to capture VLAN 200 encapsulated within
+ * VLAN 100.
+ *
+ * XXX - this is a bit of a kludge. If we were to split the
+ * compiler into a parser that parses an expression and
+ * generates an expression tree, and a code generator that
+ * takes an expression tree (which could come from our
+ * parser or from some other parser) and generates BPF code,
+ * we could perhaps make the offsets parameters of routines
+ * and, in the handler for an "AND" node, pass to subnodes
+ * other than the VLAN node the adjusted offsets.
+ *
+ * This would mean that "vlan" would, instead of changing the
+ * behavior of *all* tests after it, change only the behavior
+ * of tests ANDed with it. That would change the documented
+ * semantics of "vlan", which might break some expressions.
+ * However, it would mean that "(vlan and ip) or ip" would check
+ * both for VLAN-encapsulated IP and IP-over-Ethernet, rather than
+ * checking only for VLAN-encapsulated IP, so that could still
+ * be considered worth doing; it wouldn't break expressions
+ * that are of the form "vlan and ..." or "vlan N and ...",
+ * which I suspect are the most common expressions involving
+ * "vlan". "vlan or ..." doesn't necessarily do what the user
+ * would really want, now, as all the "or ..." tests would
+ * be done assuming a VLAN, even though the "or" could be viewed
+ * as meaning "or, if this isn't a VLAN packet...".
+ */
+ switch (cstate->linktype) {
+
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+#if defined(SKF_AD_VLAN_TAG_PRESENT)
+ /* Verify that this is the outer part of the packet and
+ * not encapsulated somehow. */
+ if (cstate->vlan_stack_depth == 0 && !cstate->off_linkhdr.is_variable &&
+ cstate->off_linkhdr.constant_part ==
+ cstate->off_outermostlinkhdr.constant_part) {
+ /*
+ * Do we need special VLAN handling?
+ */
+ if (cstate->bpf_pcap->bpf_codegen_flags & BPF_SPECIAL_VLAN_HANDLING)
+ b0 = gen_vlan_bpf_extensions(cstate, vlan_num,
+ has_vlan_tag);
+ else
+ b0 = gen_vlan_no_bpf_extensions(cstate,
+ vlan_num, has_vlan_tag);
+ } else
+#endif
+ b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num,
+ has_vlan_tag);
+ break;
+
+ case DLT_IEEE802_11:
+ case DLT_PRISM_HEADER:
+ case DLT_IEEE802_11_RADIO_AVS:
+ case DLT_IEEE802_11_RADIO:
+ b0 = gen_vlan_no_bpf_extensions(cstate, vlan_num, has_vlan_tag);
+ break;
+
+ default:
+ bpf_error(cstate, "no VLAN support for %s",
+ pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+ /*NOTREACHED*/
+ }
+
+ cstate->vlan_stack_depth++;
+
+ return (b0);
+}
+
+/*
+ * support for MPLS
+ *
+ * The label_num_arg dance is to avoid annoying whining by compilers that
+ * label_num might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
+struct block *
+gen_mpls(compiler_state_t *cstate, bpf_u_int32 label_num_arg,
+ int has_label_num)
+{
+ volatile bpf_u_int32 label_num = label_num_arg;
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ if (cstate->label_stack_depth > 0) {
+ /* just match the bottom-of-stack bit clear */
+ b0 = gen_mcmp(cstate, OR_PREVMPLSHDR, 2, BPF_B, 0, 0x01);
+ } else {
+ /*
+ * We're not in an MPLS stack yet, so check the link-layer
+ * type against MPLS.
+ */
+ switch (cstate->linktype) {
+
+ case DLT_C_HDLC: /* fall through */
+ case DLT_EN10MB:
+ case DLT_NETANALYZER:
+ case DLT_NETANALYZER_TRANSPARENT:
+ b0 = gen_linktype(cstate, ETHERTYPE_MPLS);
+ break;
+
+ case DLT_PPP:
+ b0 = gen_linktype(cstate, PPP_MPLS_UCAST);
+ break;
+
+ /* FIXME add other DLT_s ...
+ * for Frame-Relay/and ATM this may get messy due to SNAP headers
+ * leave it for now */
+
+ default:
+ bpf_error(cstate, "no MPLS support for %s",
+ pcap_datalink_val_to_description_or_dlt(cstate->linktype));
+ /*NOTREACHED*/
+ }
+ }
+
+ /* If a specific MPLS label is requested, check it */
+ if (has_label_num) {
+ if (label_num > 0xFFFFF) {
+ bpf_error(cstate, "MPLS label %u greater than maximum %u",
+ label_num, 0xFFFFF);
+ }
+ label_num = label_num << 12; /* label is shifted 12 bits on the wire */
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W, (bpf_int32)label_num,
+ 0xfffff000); /* only compare the first 20 bits */
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ /*
+ * Change the offsets to point to the type and data fields within
+ * the MPLS packet. Just increment the offsets, so that we
+ * can support a hierarchy, e.g. "mpls 100000 && mpls 1024" to
+ * capture packets with an outer label of 100000 and an inner
+ * label of 1024.
+ *
+ * Increment the MPLS stack depth as well; this indicates that
+ * we're checking MPLS-encapsulated headers, to make sure higher
+ * level code generators don't try to match against IP-related
+ * protocols such as Q_ARP, Q_RARP etc.
+ *
+ * XXX - this is a bit of a kludge. See comments in gen_vlan().
+ */
+ cstate->off_nl_nosnap += 4;
+ cstate->off_nl += 4;
+ cstate->label_stack_depth++;
+ return (b0);
+}
+
+/*
+ * Support PPPOE discovery and session.
+ */
+struct block *
+gen_pppoed(compiler_state_t *cstate)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /* check for PPPoE discovery */
+ return gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOED);
+}
+
+struct block *
+gen_pppoes(compiler_state_t *cstate, bpf_u_int32 sess_num, int has_sess_num)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ /*
+ * Test against the PPPoE session link-layer type.
+ */
+ b0 = gen_linktype(cstate, (bpf_int32)ETHERTYPE_PPPOES);
+
+ /* If a specific session is requested, check PPPoE session id */
+ if (has_sess_num) {
+ if (sess_num > 0x0000ffff) {
+ bpf_error(cstate, "PPPoE session number %u greater than maximum %u",
+ sess_num, 0x0000ffff);
+ }
+ b1 = gen_mcmp(cstate, OR_LINKPL, 0, BPF_W,
+ (bpf_int32)sess_num, 0x0000ffff);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ /*
+ * Change the offsets to point to the type and data fields within
+ * the PPP packet, and note that this is PPPoE rather than
+ * raw PPP.
+ *
+ * XXX - this is a bit of a kludge. See the comments in
+ * gen_vlan().
+ *
+ * The "network-layer" protocol is PPPoE, which has a 6-byte
+ * PPPoE header, followed by a PPP packet.
+ *
+ * There is no HDLC encapsulation for the PPP packet (it's
+ * encapsulated in PPPoES instead), so the link-layer type
+ * starts at the first byte of the PPP packet. For PPPoE,
+ * that offset is relative to the beginning of the total
+ * link-layer payload, including any 802.2 LLC header, so
+ * it's 6 bytes past cstate->off_nl.
+ */
+ PUSH_LINKHDR(cstate, DLT_PPP, cstate->off_linkpl.is_variable,
+ cstate->off_linkpl.constant_part + cstate->off_nl + 6, /* 6 bytes past the PPPoE header */
+ cstate->off_linkpl.reg);
+
+ cstate->off_linktype = cstate->off_linkhdr;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 2;
+
+ cstate->off_nl = 0;
+ cstate->off_nl_nosnap = 0; /* no 802.2 LLC */
+
+ return b0;
+}
+
+/* Check that this is Geneve and the VNI is correct if
+ * specified. Parameterized to handle both IPv4 and IPv6. */
+static struct block *
+gen_geneve_check(compiler_state_t *cstate,
+ struct block *(*gen_portfn)(compiler_state_t *, int, int, int),
+ enum e_offrel offrel, bpf_u_int32 vni, int has_vni)
+{
+ struct block *b0, *b1;
+
+ b0 = gen_portfn(cstate, GENEVE_PORT, IPPROTO_UDP, Q_DST);
+
+ /* Check that we are operating on version 0. Otherwise, we
+ * can't decode the rest of the fields. The version is 2 bits
+ * in the first byte of the Geneve header. */
+ b1 = gen_mcmp(cstate, offrel, 8, BPF_B, (bpf_int32)0, 0xc0);
+ gen_and(b0, b1);
+ b0 = b1;
+
+ if (has_vni) {
+ if (vni > 0xffffff) {
+ bpf_error(cstate, "Geneve VNI %u greater than maximum %u",
+ vni, 0xffffff);
+ }
+ vni <<= 8; /* VNI is in the upper 3 bytes */
+ b1 = gen_mcmp(cstate, offrel, 12, BPF_W, (bpf_int32)vni,
+ 0xffffff00);
+ gen_and(b0, b1);
+ b0 = b1;
+ }
+
+ return b0;
+}
+
+/* The IPv4 and IPv6 Geneve checks need to do two things:
+ * - Verify that this actually is Geneve with the right VNI.
+ * - Place the IP header length (plus variable link prefix if
+ * needed) into register A to be used later to compute
+ * the inner packet offsets. */
+static struct block *
+gen_geneve4(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
+{
+ struct block *b0, *b1;
+ struct slist *s, *s1;
+
+ b0 = gen_geneve_check(cstate, gen_port, OR_TRAN_IPV4, vni, has_vni);
+
+ /* Load the IP header length into A. */
+ s = gen_loadx_iphdrlen(cstate);
+
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
+ sappend(s, s1);
+
+ /* Forcibly append these statements to the true condition
+ * of the protocol check by creating a new block that is
+ * always true and ANDing them. */
+ b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
+ b1->stmts = s;
+ b1->s.k = 0;
+
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+static struct block *
+gen_geneve6(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
+{
+ struct block *b0, *b1;
+ struct slist *s, *s1;
+
+ b0 = gen_geneve_check(cstate, gen_port6, OR_TRAN_IPV6, vni, has_vni);
+
+ /* Load the IP header length. We need to account for a
+ * variable length link prefix if there is one. */
+ s = gen_abs_offset_varpart(cstate, &cstate->off_linkpl);
+ if (s) {
+ s1 = new_stmt(cstate, BPF_LD|BPF_IMM);
+ s1->s.k = 40;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
+ s1->s.k = 0;
+ sappend(s, s1);
+ } else {
+ s = new_stmt(cstate, BPF_LD|BPF_IMM);
+ s->s.k = 40;
+ }
+
+ /* Forcibly append these statements to the true condition
+ * of the protocol check by creating a new block that is
+ * always true and ANDing them. */
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s, s1);
+
+ b1 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
+ b1->stmts = s;
+ b1->s.k = 0;
+
+ gen_and(b0, b1);
+
+ return b1;
+}
+
+/* We need to store three values based on the Geneve header::
+ * - The offset of the linktype.
+ * - The offset of the end of the Geneve header.
+ * - The offset of the end of the encapsulated MAC header. */
+static struct slist *
+gen_geneve_offsets(compiler_state_t *cstate)
+{
+ struct slist *s, *s1, *s_proto;
+
+ /* First we need to calculate the offset of the Geneve header
+ * itself. This is composed of the IP header previously calculated
+ * (include any variable link prefix) and stored in A plus the
+ * fixed sized headers (fixed link prefix, MAC length, and UDP
+ * header). */
+ s = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s->s.k = cstate->off_linkpl.constant_part + cstate->off_nl + 8;
+
+ /* Stash this in X since we'll need it later. */
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s, s1);
+
+ /* The EtherType in Geneve is 2 bytes in. Calculate this and
+ * store it. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 2;
+ sappend(s, s1);
+
+ cstate->off_linktype.reg = alloc_reg(cstate);
+ cstate->off_linktype.is_variable = 1;
+ cstate->off_linktype.constant_part = 0;
+
+ s1 = new_stmt(cstate, BPF_ST);
+ s1->s.k = cstate->off_linktype.reg;
+ sappend(s, s1);
+
+ /* Load the Geneve option length and mask and shift to get the
+ * number of bytes. It is stored in the first byte of the Geneve
+ * header. */
+ s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_B);
+ s1->s.k = 0;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ALU|BPF_AND|BPF_K);
+ s1->s.k = 0x3f;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ALU|BPF_MUL|BPF_K);
+ s1->s.k = 4;
+ sappend(s, s1);
+
+ /* Add in the rest of the Geneve base header. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 8;
+ sappend(s, s1);
+
+ /* Add the Geneve header length to its offset and store. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_X);
+ s1->s.k = 0;
+ sappend(s, s1);
+
+ /* Set the encapsulated type as Ethernet. Even though we may
+ * not actually have Ethernet inside there are two reasons this
+ * is useful:
+ * - The linktype field is always in EtherType format regardless
+ * of whether it is in Geneve or an inner Ethernet frame.
+ * - The only link layer that we have specific support for is
+ * Ethernet. We will confirm that the packet actually is
+ * Ethernet at runtime before executing these checks. */
+ PUSH_LINKHDR(cstate, DLT_EN10MB, 1, 0, alloc_reg(cstate));
+
+ s1 = new_stmt(cstate, BPF_ST);
+ s1->s.k = cstate->off_linkhdr.reg;
+ sappend(s, s1);
+
+ /* Calculate whether we have an Ethernet header or just raw IP/
+ * MPLS/etc. If we have Ethernet, advance the end of the MAC offset
+ * and linktype by 14 bytes so that the network header can be found
+ * seamlessly. Otherwise, keep what we've calculated already. */
+
+ /* We have a bare jmp so we can't use the optimizer. */
+ cstate->no_optimize = 1;
+
+ /* Load the EtherType in the Geneve header, 2 bytes in. */
+ s1 = new_stmt(cstate, BPF_LD|BPF_IND|BPF_H);
+ s1->s.k = 2;
+ sappend(s, s1);
+
+ /* Load X with the end of the Geneve header. */
+ s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
+ s1->s.k = cstate->off_linkhdr.reg;
+ sappend(s, s1);
+
+ /* Check if the EtherType is Transparent Ethernet Bridging. At the
+ * end of this check, we should have the total length in X. In
+ * the non-Ethernet case, it's already there. */
+ s_proto = new_stmt(cstate, JMP(BPF_JEQ));
+ s_proto->s.k = ETHERTYPE_TEB;
+ sappend(s, s_proto);
+
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TXA);
+ sappend(s, s1);
+ s_proto->s.jt = s1;
+
+ /* Since this is Ethernet, use the EtherType of the payload
+ * directly as the linktype. Overwrite what we already have. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 12;
+ sappend(s, s1);
+
+ s1 = new_stmt(cstate, BPF_ST);
+ s1->s.k = cstate->off_linktype.reg;
+ sappend(s, s1);
+
+ /* Advance two bytes further to get the end of the Ethernet
+ * header. */
+ s1 = new_stmt(cstate, BPF_ALU|BPF_ADD|BPF_K);
+ s1->s.k = 2;
+ sappend(s, s1);
+
+ /* Move the result to X. */
+ s1 = new_stmt(cstate, BPF_MISC|BPF_TAX);
+ sappend(s, s1);
+
+ /* Store the final result of our linkpl calculation. */
+ cstate->off_linkpl.reg = alloc_reg(cstate);
+ cstate->off_linkpl.is_variable = 1;
+ cstate->off_linkpl.constant_part = 0;
+
+ s1 = new_stmt(cstate, BPF_STX);
+ s1->s.k = cstate->off_linkpl.reg;
+ sappend(s, s1);
+ s_proto->s.jf = s1;
+
+ cstate->off_nl = 0;
+
+ return s;
+}
+
+/* Check to see if this is a Geneve packet. */
+struct block *
+gen_geneve(compiler_state_t *cstate, bpf_u_int32 vni, int has_vni)
+{
+ struct block *b0, *b1;
+ struct slist *s;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ b0 = gen_geneve4(cstate, vni, has_vni);
+ b1 = gen_geneve6(cstate, vni, has_vni);
+
+ gen_or(b0, b1);
+ b0 = b1;
+
+ /* Later filters should act on the payload of the Geneve frame,
+ * update all of the header pointers. Attach this code so that
+ * it gets executed in the event that the Geneve filter matches. */
+ s = gen_geneve_offsets(cstate);
+
+ b1 = gen_true(cstate);
+ sappend(s, b1->stmts);
+ b1->stmts = s;
+
+ gen_and(b0, b1);
+
+ cstate->is_geneve = 1;
+
+ return b1;
+}
+
+/* Check that the encapsulated frame has a link layer header
+ * for Ethernet filters. */
+static struct block *
+gen_geneve_ll_check(compiler_state_t *cstate)
+{
+ struct block *b0;
+ struct slist *s, *s1;
+
+ /* The easiest way to see if there is a link layer present
+ * is to check if the link layer header and payload are not
+ * the same. */
+
+ /* Geneve always generates pure variable offsets so we can
+ * compare only the registers. */
+ s = new_stmt(cstate, BPF_LD|BPF_MEM);
+ s->s.k = cstate->off_linkhdr.reg;
+
+ s1 = new_stmt(cstate, BPF_LDX|BPF_MEM);
+ s1->s.k = cstate->off_linkpl.reg;
+ sappend(s, s1);
+
+ b0 = new_block(cstate, BPF_JMP|BPF_JEQ|BPF_X);
+ b0->stmts = s;
+ b0->s.k = 0;
+ gen_not(b0);
+
+ return b0;
+}
+
+static struct block *
+gen_atmfield_code_internal(compiler_state_t *cstate, int atmfield,
+ bpf_int32 jvalue, bpf_u_int32 jtype, int reverse)
+{
+ struct block *b0;
+
+ switch (atmfield) {
+
+ case A_VPI:
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'vpi' supported only on raw ATM");
+ if (cstate->off_vpi == OFFSET_NOT_SET)
+ abort();
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vpi, BPF_B, 0xffffffff, jtype,
+ reverse, jvalue);
+ break;
+
+ case A_VCI:
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'vci' supported only on raw ATM");
+ if (cstate->off_vci == OFFSET_NOT_SET)
+ abort();
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_vci, BPF_H, 0xffffffff, jtype,
+ reverse, jvalue);
+ break;
+
+ case A_PROTOTYPE:
+ if (cstate->off_proto == OFFSET_NOT_SET)
+ abort(); /* XXX - this isn't on FreeBSD */
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0x0f, jtype,
+ reverse, jvalue);
+ break;
+
+ case A_MSGTYPE:
+ if (cstate->off_payload == OFFSET_NOT_SET)
+ abort();
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_payload + MSG_TYPE_POS, BPF_B,
+ 0xffffffff, jtype, reverse, jvalue);
+ break;
+
+ case A_CALLREFTYPE:
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'callref' supported only on raw ATM");
+ if (cstate->off_proto == OFFSET_NOT_SET)
+ abort();
+ b0 = gen_ncmp(cstate, OR_LINKHDR, cstate->off_proto, BPF_B, 0xffffffff,
+ jtype, reverse, jvalue);
+ break;
+
+ default:
+ abort();
+ }
+ return b0;
+}
+
+static struct block *
+gen_atmtype_metac(compiler_state_t *cstate)
+{
+ struct block *b0, *b1;
+
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 1, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ return b1;
+}
+
+static struct block *
+gen_atmtype_sc(compiler_state_t *cstate)
+{
+ struct block *b0, *b1;
+
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 5, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ return b1;
+}
+
+static struct block *
+gen_atmtype_llc(compiler_state_t *cstate)
+{
+ struct block *b0;
+
+ b0 = gen_atmfield_code_internal(cstate, A_PROTOTYPE, PT_LLC, BPF_JEQ, 0);
+ cstate->linktype = cstate->prevlinktype;
+ return b0;
+}
+
+struct block *
+gen_atmfield_code(compiler_state_t *cstate, int atmfield,
+ bpf_int32 jvalue, bpf_u_int32 jtype, int reverse)
+{
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ return gen_atmfield_code_internal(cstate, atmfield, jvalue, jtype,
+ reverse);
+}
+
+struct block *
+gen_atmtype_abbrev(compiler_state_t *cstate, int type)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (type) {
+
+ case A_METAC:
+ /* Get all packets in Meta signalling Circuit */
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'metac' supported only on raw ATM");
+ b1 = gen_atmtype_metac(cstate);
+ break;
+
+ case A_BCC:
+ /* Get all packets in Broadcast Circuit*/
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'bcc' supported only on raw ATM");
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 2, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ break;
+
+ case A_OAMF4SC:
+ /* Get all cells in Segment OAM F4 circuit*/
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oam4sc' supported only on raw ATM");
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ break;
+
+ case A_OAMF4EC:
+ /* Get all cells in End-to-End OAM F4 Circuit*/
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oam4ec' supported only on raw ATM");
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 4, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ break;
+
+ case A_SC:
+ /* Get all packets in connection Signalling Circuit */
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'sc' supported only on raw ATM");
+ b1 = gen_atmtype_sc(cstate);
+ break;
+
+ case A_ILMIC:
+ /* Get all packets in ILMI Circuit */
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'ilmic' supported only on raw ATM");
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 16, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ break;
+
+ case A_LANE:
+ /* Get all LANE packets */
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'lane' supported only on raw ATM");
+ b1 = gen_atmfield_code_internal(cstate, A_PROTOTYPE, PT_LANE, BPF_JEQ, 0);
+
+ /*
+ * Arrange that all subsequent tests assume LANE
+ * rather than LLC-encapsulated packets, and set
+ * the offsets appropriately for LANE-encapsulated
+ * Ethernet.
+ *
+ * We assume LANE means Ethernet, not Token Ring.
+ */
+ PUSH_LINKHDR(cstate, DLT_EN10MB, 0,
+ cstate->off_payload + 2, /* Ethernet header */
+ -1);
+ cstate->off_linktype.constant_part = cstate->off_linkhdr.constant_part + 12;
+ cstate->off_linkpl.constant_part = cstate->off_linkhdr.constant_part + 14; /* Ethernet */
+ cstate->off_nl = 0; /* Ethernet II */
+ cstate->off_nl_nosnap = 3; /* 802.3+802.2 */
+ break;
+
+ case A_LLC:
+ /* Get all LLC-encapsulated packets */
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'llc' supported only on raw ATM");
+ b1 = gen_atmtype_llc(cstate);
+ break;
+
+ default:
+ abort();
+ }
+ return b1;
+}
+
+/*
+ * Filtering for MTP2 messages based on li value
+ * FISU, length is null
+ * LSSU, length is 1 or 2
+ * MSU, length is 3 or more
+ * For MTP2_HSL, sequences are on 2 bytes, and length on 9 bits
+ */
+struct block *
+gen_mtp2type_abbrev(compiler_state_t *cstate, int type)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (type) {
+
+ case M_FISU:
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'fisu' supported only on MTP2");
+ /* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JEQ, 0, 0);
+ break;
+
+ case M_LSSU:
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'lssu' supported only on MTP2");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 1, 2);
+ b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 0);
+ gen_and(b1, b0);
+ break;
+
+ case M_MSU:
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'msu' supported only on MTP2");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li, BPF_B, 0x3f, BPF_JGT, 0, 2);
+ break;
+
+ case MH_FISU:
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'hfisu' supported only on MTP2_HSL");
+ /* gen_ncmp(cstate, offrel, offset, size, mask, jtype, reverse, value) */
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JEQ, 0, 0);
+ break;
+
+ case MH_LSSU:
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'hlssu' supported only on MTP2_HSL");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 1, 0x0100);
+ b1 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0);
+ gen_and(b1, b0);
+ break;
+
+ case MH_MSU:
+ if ( (cstate->linktype != DLT_MTP2) &&
+ (cstate->linktype != DLT_ERF) &&
+ (cstate->linktype != DLT_MTP2_WITH_PHDR) )
+ bpf_error(cstate, "'hmsu' supported only on MTP2_HSL");
+ b0 = gen_ncmp(cstate, OR_PACKET, cstate->off_li_hsl, BPF_H, 0xff80, BPF_JGT, 0, 0x0100);
+ break;
+
+ default:
+ abort();
+ }
+ return b0;
+}
+
+/*
+ * The jvalue_arg dance is to avoid annoying whining by compilers that
+ * jvalue might be clobbered by longjmp - yeah, it might, but *WHO CARES*?
+ * It's not *used* after setjmp returns.
+ */
+struct block *
+gen_mtp3field_code(compiler_state_t *cstate, int mtp3field,
+ bpf_u_int32 jvalue_arg, bpf_u_int32 jtype, int reverse)
+{
+ volatile bpf_u_int32 jvalue = jvalue_arg;
+ struct block *b0;
+ bpf_u_int32 val1 , val2 , val3;
+ u_int newoff_sio;
+ u_int newoff_opc;
+ u_int newoff_dpc;
+ u_int newoff_sls;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ newoff_sio = cstate->off_sio;
+ newoff_opc = cstate->off_opc;
+ newoff_dpc = cstate->off_dpc;
+ newoff_sls = cstate->off_sls;
+ switch (mtp3field) {
+
+ case MH_SIO:
+ newoff_sio += 3; /* offset for MTP2_HSL */
+ /* FALLTHROUGH */
+
+ case M_SIO:
+ if (cstate->off_sio == OFFSET_NOT_SET)
+ bpf_error(cstate, "'sio' supported only on SS7");
+ /* sio coded on 1 byte so max value 255 */
+ if(jvalue > 255)
+ bpf_error(cstate, "sio value %u too big; max value = 255",
+ jvalue);
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_sio, BPF_B, 0xffffffff,
+ (u_int)jtype, reverse, (u_int)jvalue);
+ break;
+
+ case MH_OPC:
+ newoff_opc += 3;
+
+ /* FALLTHROUGH */
+ case M_OPC:
+ if (cstate->off_opc == OFFSET_NOT_SET)
+ bpf_error(cstate, "'opc' supported only on SS7");
+ /* opc coded on 14 bits so max value 16383 */
+ if (jvalue > 16383)
+ bpf_error(cstate, "opc value %u too big; max value = 16383",
+ jvalue);
+ /* the following instructions are made to convert jvalue
+ * to the form used to write opc in an ss7 message*/
+ val1 = jvalue & 0x00003c00;
+ val1 = val1 >>10;
+ val2 = jvalue & 0x000003fc;
+ val2 = val2 <<6;
+ val3 = jvalue & 0x00000003;
+ val3 = val3 <<22;
+ jvalue = val1 + val2 + val3;
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_opc, BPF_W, 0x00c0ff0f,
+ (u_int)jtype, reverse, (u_int)jvalue);
+ break;
+
+ case MH_DPC:
+ newoff_dpc += 3;
+ /* FALLTHROUGH */
+
+ case M_DPC:
+ if (cstate->off_dpc == OFFSET_NOT_SET)
+ bpf_error(cstate, "'dpc' supported only on SS7");
+ /* dpc coded on 14 bits so max value 16383 */
+ if (jvalue > 16383)
+ bpf_error(cstate, "dpc value %u too big; max value = 16383",
+ jvalue);
+ /* the following instructions are made to convert jvalue
+ * to the forme used to write dpc in an ss7 message*/
+ val1 = jvalue & 0x000000ff;
+ val1 = val1 << 24;
+ val2 = jvalue & 0x00003f00;
+ val2 = val2 << 8;
+ jvalue = val1 + val2;
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_dpc, BPF_W, 0xff3f0000,
+ (u_int)jtype, reverse, (u_int)jvalue);
+ break;
+
+ case MH_SLS:
+ newoff_sls += 3;
+ /* FALLTHROUGH */
+
+ case M_SLS:
+ if (cstate->off_sls == OFFSET_NOT_SET)
+ bpf_error(cstate, "'sls' supported only on SS7");
+ /* sls coded on 4 bits so max value 15 */
+ if (jvalue > 15)
+ bpf_error(cstate, "sls value %u too big; max value = 15",
+ jvalue);
+ /* the following instruction is made to convert jvalue
+ * to the forme used to write sls in an ss7 message*/
+ jvalue = jvalue << 4;
+ b0 = gen_ncmp(cstate, OR_PACKET, newoff_sls, BPF_B, 0xf0,
+ (u_int)jtype,reverse, (u_int)jvalue);
+ break;
+
+ default:
+ abort();
+ }
+ return b0;
+}
+
+static struct block *
+gen_msg_abbrev(compiler_state_t *cstate, int type)
+{
+ struct block *b1;
+
+ /*
+ * Q.2931 signalling protocol messages for handling virtual circuits
+ * establishment and teardown
+ */
+ switch (type) {
+
+ case A_SETUP:
+ b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, SETUP, BPF_JEQ, 0);
+ break;
+
+ case A_CALLPROCEED:
+ b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0);
+ break;
+
+ case A_CONNECT:
+ b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, CONNECT, BPF_JEQ, 0);
+ break;
+
+ case A_CONNECTACK:
+ b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0);
+ break;
+
+ case A_RELEASE:
+ b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, RELEASE, BPF_JEQ, 0);
+ break;
+
+ case A_RELEASE_DONE:
+ b1 = gen_atmfield_code_internal(cstate, A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0);
+ break;
+
+ default:
+ abort();
+ }
+ return b1;
+}
+
+struct block *
+gen_atmmulti_abbrev(compiler_state_t *cstate, int type)
+{
+ struct block *b0, *b1;
+
+ /*
+ * Catch errors reported by us and routines below us, and return NULL
+ * on an error.
+ */
+ if (setjmp(cstate->top_ctx))
+ return (NULL);
+
+ switch (type) {
+
+ case A_OAM:
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oam' supported only on raw ATM");
+ /* OAM F4 type */
+ b0 = gen_atmfield_code_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 4, BPF_JEQ, 0);
+ gen_or(b0, b1);
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ break;
+
+ case A_OAMF4:
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'oamf4' supported only on raw ATM");
+ /* OAM F4 type */
+ b0 = gen_atmfield_code_internal(cstate, A_VCI, 3, BPF_JEQ, 0);
+ b1 = gen_atmfield_code_internal(cstate, A_VCI, 4, BPF_JEQ, 0);
+ gen_or(b0, b1);
+ b0 = gen_atmfield_code_internal(cstate, A_VPI, 0, BPF_JEQ, 0);
+ gen_and(b0, b1);
+ break;
+
+ case A_CONNECTMSG:
+ /*
+ * Get Q.2931 signalling messages for switched
+ * virtual connection
+ */
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'connectmsg' supported only on raw ATM");
+ b0 = gen_msg_abbrev(cstate, A_SETUP);
+ b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
+ gen_or(b0, b1);
+ b0 = gen_msg_abbrev(cstate, A_CONNECT);
+ gen_or(b0, b1);
+ b0 = gen_msg_abbrev(cstate, A_CONNECTACK);
+ gen_or(b0, b1);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE);
+ gen_or(b0, b1);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
+ gen_or(b0, b1);
+ b0 = gen_atmtype_sc(cstate);
+ gen_and(b0, b1);
+ break;
+
+ case A_METACONNECT:
+ if (!cstate->is_atm)
+ bpf_error(cstate, "'metaconnect' supported only on raw ATM");
+ b0 = gen_msg_abbrev(cstate, A_SETUP);
+ b1 = gen_msg_abbrev(cstate, A_CALLPROCEED);
+ gen_or(b0, b1);
+ b0 = gen_msg_abbrev(cstate, A_CONNECT);
+ gen_or(b0, b1);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE);
+ gen_or(b0, b1);
+ b0 = gen_msg_abbrev(cstate, A_RELEASE_DONE);
+ gen_or(b0, b1);
+ b0 = gen_atmtype_metac(cstate);
+ gen_and(b0, b1);
+ break;
+
+ default:
+ abort();
+ }
+ return b1;
+}
diff --git a/lib/libpcap/libpcap/gencode.h b/lib/libpcap/libpcap/gencode.h
new file mode 100644
index 0000000..cc21e04
--- /dev/null
+++ b/lib/libpcap/libpcap/gencode.h
@@ -0,0 +1,388 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "pcap/funcattrs.h"
+
+/*
+ * ATM support:
+ *
+ * Copyright (c) 1997 Yen Yen Lim and North Dakota State University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Yen Yen Lim and
+ * North Dakota State University
+ * 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.
+ */
+
+/* Address qualifiers. */
+
+#define Q_HOST 1
+#define Q_NET 2
+#define Q_PORT 3
+#define Q_GATEWAY 4
+#define Q_PROTO 5
+#define Q_PROTOCHAIN 6
+#define Q_PORTRANGE 7
+
+/* Protocol qualifiers. */
+
+#define Q_LINK 1
+#define Q_IP 2
+#define Q_ARP 3
+#define Q_RARP 4
+#define Q_SCTP 5
+#define Q_TCP 6
+#define Q_UDP 7
+#define Q_ICMP 8
+#define Q_IGMP 9
+#define Q_IGRP 10
+
+
+#define Q_ATALK 11
+#define Q_DECNET 12
+#define Q_LAT 13
+#define Q_SCA 14
+#define Q_MOPRC 15
+#define Q_MOPDL 16
+
+
+#define Q_IPV6 17
+#define Q_ICMPV6 18
+#define Q_AH 19
+#define Q_ESP 20
+
+#define Q_PIM 21
+#define Q_VRRP 22
+
+#define Q_AARP 23
+
+#define Q_ISO 24
+#define Q_ESIS 25
+#define Q_ISIS 26
+#define Q_CLNP 27
+
+#define Q_STP 28
+
+#define Q_IPX 29
+
+#define Q_NETBEUI 30
+
+/* IS-IS Levels */
+#define Q_ISIS_L1 31
+#define Q_ISIS_L2 32
+/* PDU types */
+#define Q_ISIS_IIH 33
+#define Q_ISIS_SNP 34
+#define Q_ISIS_CSNP 35
+#define Q_ISIS_PSNP 36
+#define Q_ISIS_LSP 37
+
+#define Q_RADIO 38
+
+#define Q_CARP 39
+
+/* Directional qualifiers. */
+
+#define Q_SRC 1
+#define Q_DST 2
+#define Q_OR 3
+#define Q_AND 4
+#define Q_ADDR1 5
+#define Q_ADDR2 6
+#define Q_ADDR3 7
+#define Q_ADDR4 8
+#define Q_RA 9
+#define Q_TA 10
+
+#define Q_DEFAULT 0
+#define Q_UNDEF 255
+
+/* ATM types */
+#define A_METAC 22 /* Meta signalling Circuit */
+#define A_BCC 23 /* Broadcast Circuit */
+#define A_OAMF4SC 24 /* Segment OAM F4 Circuit */
+#define A_OAMF4EC 25 /* End-to-End OAM F4 Circuit */
+#define A_SC 26 /* Signalling Circuit*/
+#define A_ILMIC 27 /* ILMI Circuit */
+#define A_OAM 28 /* OAM cells : F4 only */
+#define A_OAMF4 29 /* OAM F4 cells: Segment + End-to-end */
+#define A_LANE 30 /* LANE traffic */
+#define A_LLC 31 /* LLC-encapsulated traffic */
+
+/* Based on Q.2931 signalling protocol */
+#define A_SETUP 41 /* Setup message */
+#define A_CALLPROCEED 42 /* Call proceeding message */
+#define A_CONNECT 43 /* Connect message */
+#define A_CONNECTACK 44 /* Connect Ack message */
+#define A_RELEASE 45 /* Release message */
+#define A_RELEASE_DONE 46 /* Release message */
+
+/* ATM field types */
+#define A_VPI 51
+#define A_VCI 52
+#define A_PROTOTYPE 53
+#define A_MSGTYPE 54
+#define A_CALLREFTYPE 55
+
+#define A_CONNECTMSG 70 /* returns Q.2931 signalling messages for
+ establishing and destroying switched
+ virtual connection */
+#define A_METACONNECT 71 /* returns Q.2931 signalling messages for
+ establishing and destroying predefined
+ virtual circuits, such as broadcast
+ circuit, oamf4 segment circuit, oamf4
+ end-to-end circuits, ILMI circuits or
+ connection signalling circuit. */
+
+/* MTP2 types */
+#define M_FISU 22 /* FISU */
+#define M_LSSU 23 /* LSSU */
+#define M_MSU 24 /* MSU */
+
+/* MTP2 HSL types */
+#define MH_FISU 25 /* FISU for HSL */
+#define MH_LSSU 26 /* LSSU */
+#define MH_MSU 27 /* MSU */
+
+/* MTP3 field types */
+#define M_SIO 1
+#define M_OPC 2
+#define M_DPC 3
+#define M_SLS 4
+
+/* MTP3 field types in case of MTP2 HSL */
+#define MH_SIO 5
+#define MH_OPC 6
+#define MH_DPC 7
+#define MH_SLS 8
+
+
+struct slist;
+
+struct stmt {
+ int code;
+ struct slist *jt; /*only for relative jump in block*/
+ struct slist *jf; /*only for relative jump in block*/
+ bpf_int32 k;
+};
+
+struct slist {
+ struct stmt s;
+ struct slist *next;
+};
+
+/*
+ * A bit vector to represent definition sets. We assume TOT_REGISTERS
+ * is smaller than 8*sizeof(atomset).
+ */
+typedef bpf_u_int32 atomset;
+#define ATOMMASK(n) (1 << (n))
+#define ATOMELEM(d, n) (d & ATOMMASK(n))
+
+/*
+ * An unbounded set.
+ */
+typedef bpf_u_int32 *uset;
+
+/*
+ * Total number of atomic entities, including accumulator (A) and index (X).
+ * We treat all these guys similarly during flow analysis.
+ */
+#define N_ATOMS (BPF_MEMWORDS+2)
+
+struct edge {
+ int id;
+ int code;
+ uset edom;
+ struct block *succ;
+ struct block *pred;
+ struct edge *next; /* link list of incoming edges for a node */
+};
+
+struct block {
+ int id;
+ struct slist *stmts; /* side effect stmts */
+ struct stmt s; /* branch stmt */
+ int mark;
+ u_int longjt; /* jt branch requires long jump */
+ u_int longjf; /* jf branch requires long jump */
+ int level;
+ int offset;
+ int sense;
+ struct edge et;
+ struct edge ef;
+ struct block *head;
+ struct block *link; /* link field used by optimizer */
+ uset dom;
+ uset closure;
+ struct edge *in_edges;
+ atomset def, kill;
+ atomset in_use;
+ atomset out_use;
+ int oval;
+ int val[N_ATOMS];
+};
+
+/*
+ * A value of 0 for val[i] means the value is unknown.
+ */
+#define VAL_UNKNOWN 0
+
+struct arth {
+ struct block *b; /* protocol checks */
+ struct slist *s; /* stmt list */
+ int regno; /* virtual register number of result */
+};
+
+struct qual {
+ unsigned char addr;
+ unsigned char proto;
+ unsigned char dir;
+ unsigned char pad;
+};
+
+struct _compiler_state;
+
+typedef struct _compiler_state compiler_state_t;
+
+struct arth *gen_loadi(compiler_state_t *, int);
+struct arth *gen_load(compiler_state_t *, int, struct arth *, int);
+struct arth *gen_loadlen(compiler_state_t *);
+struct arth *gen_neg(compiler_state_t *, struct arth *);
+struct arth *gen_arth(compiler_state_t *, int, struct arth *, struct arth *);
+
+void gen_and(struct block *, struct block *);
+void gen_or(struct block *, struct block *);
+void gen_not(struct block *);
+
+struct block *gen_scode(compiler_state_t *, const char *, struct qual);
+struct block *gen_ecode(compiler_state_t *, const char *, struct qual);
+struct block *gen_acode(compiler_state_t *, const char *, struct qual);
+struct block *gen_mcode(compiler_state_t *, const char *, const char *,
+ unsigned int, struct qual);
+#ifdef INET6
+struct block *gen_mcode6(compiler_state_t *, const char *, const char *,
+ unsigned int, struct qual);
+#endif
+struct block *gen_ncode(compiler_state_t *, const char *, bpf_u_int32,
+ struct qual);
+struct block *gen_proto_abbrev(compiler_state_t *, int);
+struct block *gen_relation(compiler_state_t *, int, struct arth *,
+ struct arth *, int);
+struct block *gen_less(compiler_state_t *, int);
+struct block *gen_greater(compiler_state_t *, int);
+struct block *gen_byteop(compiler_state_t *, int, int, int);
+struct block *gen_broadcast(compiler_state_t *, int);
+struct block *gen_multicast(compiler_state_t *, int);
+struct block *gen_inbound(compiler_state_t *, int);
+
+struct block *gen_llc(compiler_state_t *);
+struct block *gen_llc_i(compiler_state_t *);
+struct block *gen_llc_s(compiler_state_t *);
+struct block *gen_llc_u(compiler_state_t *);
+struct block *gen_llc_s_subtype(compiler_state_t *, bpf_u_int32);
+struct block *gen_llc_u_subtype(compiler_state_t *, bpf_u_int32);
+
+struct block *gen_vlan(compiler_state_t *, bpf_u_int32, int);
+struct block *gen_mpls(compiler_state_t *, bpf_u_int32, int);
+
+struct block *gen_pppoed(compiler_state_t *);
+struct block *gen_pppoes(compiler_state_t *, bpf_u_int32, int);
+
+struct block *gen_geneve(compiler_state_t *, bpf_u_int32, int);
+
+struct block *gen_atmfield_code(compiler_state_t *, int, bpf_int32,
+ bpf_u_int32, int);
+struct block *gen_atmtype_abbrev(compiler_state_t *, int type);
+struct block *gen_atmmulti_abbrev(compiler_state_t *, int type);
+
+struct block *gen_mtp2type_abbrev(compiler_state_t *, int type);
+struct block *gen_mtp3field_code(compiler_state_t *, int, bpf_u_int32,
+ bpf_u_int32, int);
+
+struct block *gen_pf_ifname(compiler_state_t *, const char *);
+struct block *gen_pf_rnr(compiler_state_t *, int);
+struct block *gen_pf_srnr(compiler_state_t *, int);
+struct block *gen_pf_ruleset(compiler_state_t *, char *);
+struct block *gen_pf_reason(compiler_state_t *, int);
+struct block *gen_pf_action(compiler_state_t *, int);
+
+struct block *gen_p80211_type(compiler_state_t *, int, int);
+struct block *gen_p80211_fcdir(compiler_state_t *, int);
+
+/*
+ * Representation of a program as a tree of blocks, plus current mark.
+ * A block is marked if only if its mark equals the current mark.
+ * Rather than traverse the code array, marking each item, 'cur_mark'
+ * is incremented. This automatically makes each element unmarked.
+ */
+#define isMarked(icp, p) ((p)->mark == (icp)->cur_mark)
+#define unMarkAll(icp) (icp)->cur_mark += 1
+#define Mark(icp, p) ((p)->mark = (icp)->cur_mark)
+
+struct icode {
+ struct block *root;
+ int cur_mark;
+};
+
+int bpf_optimize(struct icode *, char *);
+void bpf_set_error(compiler_state_t *, const char *, ...)
+ PCAP_PRINTFLIKE(2, 3);
+
+int finish_parse(compiler_state_t *, struct block *);
+char *sdup(compiler_state_t *, const char *);
+
+struct bpf_insn *icode_to_fcode(struct icode *, struct block *, u_int *,
+ char *);
+void sappend(struct slist *, struct slist *);
+
+/*
+ * Older versions of Bison don't put this declaration in
+ * grammar.h.
+ */
+int pcap_parse(void *, compiler_state_t *);
+
+/* XXX */
+#define JT(b) ((b)->et.succ)
+#define JF(b) ((b)->ef.succ)
diff --git a/lib/libpcap/libpcap/grammar.y b/lib/libpcap/libpcap/grammar.y
new file mode 100644
index 0000000..32cb19c
--- /dev/null
+++ b/lib/libpcap/libpcap/grammar.y
@@ -0,0 +1,799 @@
+/*
+ * We want a reentrant parser.
+ */
+%pure-parser
+
+/*
+ * We also want a reentrant scanner, so we have to pass the
+ * handle for the reentrant scanner to the parser, and the
+ * parser has to pass it to the lexical analyzer.
+ *
+ * We use void * rather than yyscan_t because, at least with some
+ * versions of Flex and Bison, if you use yyscan_t in %parse-param and
+ * %lex-param, you have to include scanner.h before grammar.h to get
+ * yyscan_t declared, and you have to include grammar.h before scanner.h
+ * to get YYSTYPE declared. Using void * breaks the cycle; the Flex
+ * documentation says yyscan_t is just a void *.
+ */
+%parse-param {void *yyscanner}
+%lex-param {void *yyscanner}
+
+/*
+ * And we need to pass the compiler state to the scanner.
+ */
+%parse-param { compiler_state_t *cstate }
+
+%{
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#ifndef _WIN32
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#if __STDC__
+struct mbuf;
+struct rtentry;
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#endif /* _WIN32 */
+
+#include <stdio.h>
+
+#include "diag-control.h"
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#include "grammar.h"
+#include "scanner.h"
+
+#ifdef HAVE_NET_PFVAR_H
+#include <net/if.h>
+#include <net/pfvar.h>
+#include <net/if_pflog.h>
+#endif
+#include "llc.h"
+#include "ieee80211.h"
+#include <pcap/namedb.h>
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef YYBYACC
+/*
+ * Both Berkeley YACC and Bison define yydebug (under whatever name
+ * it has) as a global, but Bison does so only if YYDEBUG is defined.
+ * Berkeley YACC define it even if YYDEBUG isn't defined; declare it
+ * here to suppress a warning.
+ */
+#if !defined(YYDEBUG)
+extern int yydebug;
+#endif
+
+/*
+ * In Berkeley YACC, yynerrs (under whatever name it has) is global,
+ * even if it's building a reentrant parser. In Bison, it's local
+ * in reentrant parsers.
+ *
+ * Declare it to squelch a warning.
+ */
+extern int yynerrs;
+#endif
+
+#define QSET(q, p, d, a) (q).proto = (unsigned char)(p),\
+ (q).dir = (unsigned char)(d),\
+ (q).addr = (unsigned char)(a)
+
+struct tok {
+ int v; /* value */
+ const char *s; /* string */
+};
+
+static const struct tok ieee80211_types[] = {
+ { IEEE80211_FC0_TYPE_DATA, "data" },
+ { IEEE80211_FC0_TYPE_MGT, "mgt" },
+ { IEEE80211_FC0_TYPE_MGT, "management" },
+ { IEEE80211_FC0_TYPE_CTL, "ctl" },
+ { IEEE80211_FC0_TYPE_CTL, "control" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_mgt_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assocreq" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_REQ, "assoc-req" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assocresp" },
+ { IEEE80211_FC0_SUBTYPE_ASSOC_RESP, "assoc-resp" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassocreq" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_REQ, "reassoc-req" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassocresp" },
+ { IEEE80211_FC0_SUBTYPE_REASSOC_RESP, "reassoc-resp" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probereq" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_REQ, "probe-req" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "proberesp" },
+ { IEEE80211_FC0_SUBTYPE_PROBE_RESP, "probe-resp" },
+ { IEEE80211_FC0_SUBTYPE_BEACON, "beacon" },
+ { IEEE80211_FC0_SUBTYPE_ATIM, "atim" },
+ { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassoc" },
+ { IEEE80211_FC0_SUBTYPE_DISASSOC, "disassociation" },
+ { IEEE80211_FC0_SUBTYPE_AUTH, "auth" },
+ { IEEE80211_FC0_SUBTYPE_AUTH, "authentication" },
+ { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauth" },
+ { IEEE80211_FC0_SUBTYPE_DEAUTH, "deauthentication" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_ctl_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_PS_POLL, "ps-poll" },
+ { IEEE80211_FC0_SUBTYPE_RTS, "rts" },
+ { IEEE80211_FC0_SUBTYPE_CTS, "cts" },
+ { IEEE80211_FC0_SUBTYPE_ACK, "ack" },
+ { IEEE80211_FC0_SUBTYPE_CF_END, "cf-end" },
+ { IEEE80211_FC0_SUBTYPE_CF_END_ACK, "cf-end-ack" },
+ { 0, NULL }
+};
+static const struct tok ieee80211_data_subtypes[] = {
+ { IEEE80211_FC0_SUBTYPE_DATA, "data" },
+ { IEEE80211_FC0_SUBTYPE_CF_ACK, "data-cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_CF_POLL, "data-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_CF_ACPL, "data-cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_NODATA, "null" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK, "cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_DATA, "qos-data" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACK, "qos-data-cf-ack" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_POLL, "qos-data-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_CF_ACPL, "qos-data-cf-ack-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA, "qos" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL, "qos-cf-poll" },
+ { IEEE80211_FC0_SUBTYPE_QOS|IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL, "qos-cf-ack-poll" },
+ { 0, NULL }
+};
+static const struct tok llc_s_subtypes[] = {
+ { LLC_RR, "rr" },
+ { LLC_RNR, "rnr" },
+ { LLC_REJ, "rej" },
+ { 0, NULL }
+};
+static const struct tok llc_u_subtypes[] = {
+ { LLC_UI, "ui" },
+ { LLC_UA, "ua" },
+ { LLC_DISC, "disc" },
+ { LLC_DM, "dm" },
+ { LLC_SABME, "sabme" },
+ { LLC_TEST, "test" },
+ { LLC_XID, "xid" },
+ { LLC_FRMR, "frmr" },
+ { 0, NULL }
+};
+struct type2tok {
+ int type;
+ const struct tok *tok;
+};
+static const struct type2tok ieee80211_type_subtypes[] = {
+ { IEEE80211_FC0_TYPE_MGT, ieee80211_mgt_subtypes },
+ { IEEE80211_FC0_TYPE_CTL, ieee80211_ctl_subtypes },
+ { IEEE80211_FC0_TYPE_DATA, ieee80211_data_subtypes },
+ { 0, NULL }
+};
+
+static int
+str2tok(const char *str, const struct tok *toks)
+{
+ int i;
+
+ for (i = 0; toks[i].s != NULL; i++) {
+ if (pcap_strcasecmp(toks[i].s, str) == 0)
+ return (toks[i].v);
+ }
+ return (-1);
+}
+
+static const struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF };
+
+static void
+yyerror(void *yyscanner _U_, compiler_state_t *cstate, const char *msg)
+{
+ bpf_set_error(cstate, "can't parse filter expression: %s", msg);
+}
+
+#ifdef HAVE_NET_PFVAR_H
+static int
+pfreason_to_num(compiler_state_t *cstate, const char *reason)
+{
+ const char *reasons[] = PFRES_NAMES;
+ int i;
+
+ for (i = 0; reasons[i]; i++) {
+ if (pcap_strcasecmp(reason, reasons[i]) == 0)
+ return (i);
+ }
+ bpf_set_error(cstate, "unknown PF reason");
+ return (-1);
+}
+
+static int
+pfaction_to_num(compiler_state_t *cstate, const char *action)
+{
+ if (pcap_strcasecmp(action, "pass") == 0 ||
+ pcap_strcasecmp(action, "accept") == 0)
+ return (PF_PASS);
+ else if (pcap_strcasecmp(action, "drop") == 0 ||
+ pcap_strcasecmp(action, "block") == 0)
+ return (PF_DROP);
+#if HAVE_PF_NAT_THROUGH_PF_NORDR
+ else if (pcap_strcasecmp(action, "rdr") == 0)
+ return (PF_RDR);
+ else if (pcap_strcasecmp(action, "nat") == 0)
+ return (PF_NAT);
+ else if (pcap_strcasecmp(action, "binat") == 0)
+ return (PF_BINAT);
+ else if (pcap_strcasecmp(action, "nordr") == 0)
+ return (PF_NORDR);
+#endif
+ else {
+ bpf_set_error(cstate, "unknown PF action");
+ return (-1);
+ }
+}
+#else /* !HAVE_NET_PFVAR_H */
+static int
+pfreason_to_num(compiler_state_t *cstate, const char *reason _U_)
+{
+ bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+ return (-1);
+}
+
+static int
+pfaction_to_num(compiler_state_t *cstate, const char *action _U_)
+{
+ bpf_set_error(cstate, "libpcap was compiled on a machine without pf support");
+ return (-1);
+}
+#endif /* HAVE_NET_PFVAR_H */
+
+/*
+ * For calls that might return an "an error occurred" value.
+ */
+#define CHECK_INT_VAL(val) if (val == -1) YYABORT
+#define CHECK_PTR_VAL(val) if (val == NULL) YYABORT
+
+DIAG_OFF_BISON_BYACC
+%}
+
+%union {
+ int i;
+ bpf_u_int32 h;
+ char *s;
+ struct stmt *stmt;
+ struct arth *a;
+ struct {
+ struct qual q;
+ int atmfieldtype;
+ int mtp3fieldtype;
+ struct block *b;
+ } blk;
+ struct block *rblk;
+}
+
+%type <blk> expr id nid pid term rterm qid
+%type <blk> head
+%type <i> pqual dqual aqual ndaqual
+%type <a> arth narth
+%type <i> byteop pname pnum relop irelop
+%type <blk> and or paren not null prog
+%type <rblk> other pfvar p80211 pllc
+%type <i> atmtype atmmultitype
+%type <blk> atmfield
+%type <blk> atmfieldvalue atmvalue atmlistvalue
+%type <i> mtp2type
+%type <blk> mtp3field
+%type <blk> mtp3fieldvalue mtp3value mtp3listvalue
+
+
+%token DST SRC HOST GATEWAY
+%token NET NETMASK PORT PORTRANGE LESS GREATER PROTO PROTOCHAIN CBYTE
+%token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP CARP
+%token ATALK AARP DECNET LAT SCA MOPRC MOPDL
+%token TK_BROADCAST TK_MULTICAST
+%token NUM INBOUND OUTBOUND
+%token PF_IFNAME PF_RSET PF_RNR PF_SRNR PF_REASON PF_ACTION
+%token TYPE SUBTYPE DIR ADDR1 ADDR2 ADDR3 ADDR4 RA TA
+%token LINK
+%token GEQ LEQ NEQ
+%token ID EID HID HID6 AID
+%token LSH RSH
+%token LEN
+%token IPV6 ICMPV6 AH ESP
+%token VLAN MPLS
+%token PPPOED PPPOES GENEVE
+%token ISO ESIS CLNP ISIS L1 L2 IIH LSP SNP CSNP PSNP
+%token STP
+%token IPX
+%token NETBEUI
+%token LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC
+%token OAM OAMF4 CONNECTMSG METACONNECT
+%token VPI VCI
+%token RADIO
+%token FISU LSSU MSU HFISU HLSSU HMSU
+%token SIO OPC DPC SLS HSIO HOPC HDPC HSLS
+%token LEX_ERROR
+
+%type <s> ID EID AID
+%type <s> HID HID6
+%type <i> NUM action reason type subtype type_subtype dir
+
+%left OR AND
+%nonassoc '!'
+%left '|'
+%left '&'
+%left LSH RSH
+%left '+' '-'
+%left '*' '/'
+%nonassoc UMINUS
+%%
+prog: null expr
+{
+ CHECK_INT_VAL(finish_parse(cstate, $2.b));
+}
+ | null
+ ;
+null: /* null */ { $$.q = qerr; }
+ ;
+expr: term
+ | expr and term { gen_and($1.b, $3.b); $$ = $3; }
+ | expr and id { gen_and($1.b, $3.b); $$ = $3; }
+ | expr or term { gen_or($1.b, $3.b); $$ = $3; }
+ | expr or id { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+and: AND { $$ = $<blk>0; }
+ ;
+or: OR { $$ = $<blk>0; }
+ ;
+id: nid
+ | pnum { CHECK_PTR_VAL(($$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
+ $$.q = $<blk>0.q))); }
+ | paren pid ')' { $$ = $2; }
+ ;
+nid: ID { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_scode(cstate, $1, $$.q = $<blk>0.q))); }
+ | HID '/' NUM { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, NULL, $3,
+ $$.q = $<blk>0.q))); }
+ | HID NETMASK HID { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_mcode(cstate, $1, $3, 0,
+ $$.q = $<blk>0.q))); }
+ | HID {
+ CHECK_PTR_VAL($1);
+ /* Decide how to parse HID based on proto */
+ $$.q = $<blk>0.q;
+ if ($$.q.addr == Q_PORT) {
+ bpf_set_error(cstate, "'port' modifier applied to ip host");
+ YYABORT;
+ } else if ($$.q.addr == Q_PORTRANGE) {
+ bpf_set_error(cstate, "'portrange' modifier applied to ip host");
+ YYABORT;
+ } else if ($$.q.addr == Q_PROTO) {
+ bpf_set_error(cstate, "'proto' modifier applied to ip host");
+ YYABORT;
+ } else if ($$.q.addr == Q_PROTOCHAIN) {
+ bpf_set_error(cstate, "'protochain' modifier applied to ip host");
+ YYABORT;
+ }
+ CHECK_PTR_VAL(($$.b = gen_ncode(cstate, $1, 0, $$.q)));
+ }
+ | HID6 '/' NUM {
+ CHECK_PTR_VAL($1);
+#ifdef INET6
+ CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, NULL, $3,
+ $$.q = $<blk>0.q)));
+#else
+ bpf_set_error(cstate, "'ip6addr/prefixlen' not supported "
+ "in this configuration");
+ YYABORT;
+#endif /*INET6*/
+ }
+ | HID6 {
+ CHECK_PTR_VAL($1);
+#ifdef INET6
+ CHECK_PTR_VAL(($$.b = gen_mcode6(cstate, $1, 0, 128,
+ $$.q = $<blk>0.q)));
+#else
+ bpf_set_error(cstate, "'ip6addr' not supported "
+ "in this configuration");
+ YYABORT;
+#endif /*INET6*/
+ }
+ | EID { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_ecode(cstate, $1, $$.q = $<blk>0.q))); }
+ | AID { CHECK_PTR_VAL($1); CHECK_PTR_VAL(($$.b = gen_acode(cstate, $1, $$.q = $<blk>0.q))); }
+ | not id { gen_not($2.b); $$ = $2; }
+ ;
+not: '!' { $$ = $<blk>0; }
+ ;
+paren: '(' { $$ = $<blk>0; }
+ ;
+pid: nid
+ | qid and id { gen_and($1.b, $3.b); $$ = $3; }
+ | qid or id { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+qid: pnum { CHECK_PTR_VAL(($$.b = gen_ncode(cstate, NULL, (bpf_u_int32)$1,
+ $$.q = $<blk>0.q))); }
+ | pid
+ ;
+term: rterm
+ | not term { gen_not($2.b); $$ = $2; }
+ ;
+head: pqual dqual aqual { QSET($$.q, $1, $2, $3); }
+ | pqual dqual { QSET($$.q, $1, $2, Q_DEFAULT); }
+ | pqual aqual { QSET($$.q, $1, Q_DEFAULT, $2); }
+ | pqual PROTO { QSET($$.q, $1, Q_DEFAULT, Q_PROTO); }
+ | pqual PROTOCHAIN {
+#ifdef NO_PROTOCHAIN
+ bpf_set_error(cstate, "protochain not supported");
+ YYABORT;
+#else
+ QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN);
+#endif
+ }
+ | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); }
+ ;
+rterm: head id { $$ = $2; }
+ | paren expr ')' { $$.b = $2.b; $$.q = $1.q; }
+ | pname { CHECK_PTR_VAL(($$.b = gen_proto_abbrev(cstate, $1))); $$.q = qerr; }
+ | arth relop arth { CHECK_PTR_VAL(($$.b = gen_relation(cstate, $2, $1, $3, 0)));
+ $$.q = qerr; }
+ | arth irelop arth { CHECK_PTR_VAL(($$.b = gen_relation(cstate, $2, $1, $3, 1)));
+ $$.q = qerr; }
+ | other { $$.b = $1; $$.q = qerr; }
+ | atmtype { CHECK_PTR_VAL(($$.b = gen_atmtype_abbrev(cstate, $1))); $$.q = qerr; }
+ | atmmultitype { CHECK_PTR_VAL(($$.b = gen_atmmulti_abbrev(cstate, $1))); $$.q = qerr; }
+ | atmfield atmvalue { $$.b = $2.b; $$.q = qerr; }
+ | mtp2type { CHECK_PTR_VAL(($$.b = gen_mtp2type_abbrev(cstate, $1))); $$.q = qerr; }
+ | mtp3field mtp3value { $$.b = $2.b; $$.q = qerr; }
+ ;
+/* protocol level qualifiers */
+pqual: pname
+ | { $$ = Q_DEFAULT; }
+ ;
+/* 'direction' qualifiers */
+dqual: SRC { $$ = Q_SRC; }
+ | DST { $$ = Q_DST; }
+ | SRC OR DST { $$ = Q_OR; }
+ | DST OR SRC { $$ = Q_OR; }
+ | SRC AND DST { $$ = Q_AND; }
+ | DST AND SRC { $$ = Q_AND; }
+ | ADDR1 { $$ = Q_ADDR1; }
+ | ADDR2 { $$ = Q_ADDR2; }
+ | ADDR3 { $$ = Q_ADDR3; }
+ | ADDR4 { $$ = Q_ADDR4; }
+ | RA { $$ = Q_RA; }
+ | TA { $$ = Q_TA; }
+ ;
+/* address type qualifiers */
+aqual: HOST { $$ = Q_HOST; }
+ | NET { $$ = Q_NET; }
+ | PORT { $$ = Q_PORT; }
+ | PORTRANGE { $$ = Q_PORTRANGE; }
+ ;
+/* non-directional address type qualifiers */
+ndaqual: GATEWAY { $$ = Q_GATEWAY; }
+ ;
+pname: LINK { $$ = Q_LINK; }
+ | IP { $$ = Q_IP; }
+ | ARP { $$ = Q_ARP; }
+ | RARP { $$ = Q_RARP; }
+ | SCTP { $$ = Q_SCTP; }
+ | TCP { $$ = Q_TCP; }
+ | UDP { $$ = Q_UDP; }
+ | ICMP { $$ = Q_ICMP; }
+ | IGMP { $$ = Q_IGMP; }
+ | IGRP { $$ = Q_IGRP; }
+ | PIM { $$ = Q_PIM; }
+ | VRRP { $$ = Q_VRRP; }
+ | CARP { $$ = Q_CARP; }
+ | ATALK { $$ = Q_ATALK; }
+ | AARP { $$ = Q_AARP; }
+ | DECNET { $$ = Q_DECNET; }
+ | LAT { $$ = Q_LAT; }
+ | SCA { $$ = Q_SCA; }
+ | MOPDL { $$ = Q_MOPDL; }
+ | MOPRC { $$ = Q_MOPRC; }
+ | IPV6 { $$ = Q_IPV6; }
+ | ICMPV6 { $$ = Q_ICMPV6; }
+ | AH { $$ = Q_AH; }
+ | ESP { $$ = Q_ESP; }
+ | ISO { $$ = Q_ISO; }
+ | ESIS { $$ = Q_ESIS; }
+ | ISIS { $$ = Q_ISIS; }
+ | L1 { $$ = Q_ISIS_L1; }
+ | L2 { $$ = Q_ISIS_L2; }
+ | IIH { $$ = Q_ISIS_IIH; }
+ | LSP { $$ = Q_ISIS_LSP; }
+ | SNP { $$ = Q_ISIS_SNP; }
+ | PSNP { $$ = Q_ISIS_PSNP; }
+ | CSNP { $$ = Q_ISIS_CSNP; }
+ | CLNP { $$ = Q_CLNP; }
+ | STP { $$ = Q_STP; }
+ | IPX { $$ = Q_IPX; }
+ | NETBEUI { $$ = Q_NETBEUI; }
+ | RADIO { $$ = Q_RADIO; }
+ ;
+other: pqual TK_BROADCAST { CHECK_PTR_VAL(($$ = gen_broadcast(cstate, $1))); }
+ | pqual TK_MULTICAST { CHECK_PTR_VAL(($$ = gen_multicast(cstate, $1))); }
+ | LESS NUM { CHECK_PTR_VAL(($$ = gen_less(cstate, $2))); }
+ | GREATER NUM { CHECK_PTR_VAL(($$ = gen_greater(cstate, $2))); }
+ | CBYTE NUM byteop NUM { CHECK_PTR_VAL(($$ = gen_byteop(cstate, $3, $2, $4))); }
+ | INBOUND { CHECK_PTR_VAL(($$ = gen_inbound(cstate, 0))); }
+ | OUTBOUND { CHECK_PTR_VAL(($$ = gen_inbound(cstate, 1))); }
+ | VLAN pnum { CHECK_PTR_VAL(($$ = gen_vlan(cstate, (bpf_u_int32)$2, 1))); }
+ | VLAN { CHECK_PTR_VAL(($$ = gen_vlan(cstate, 0, 0))); }
+ | MPLS pnum { CHECK_PTR_VAL(($$ = gen_mpls(cstate, (bpf_u_int32)$2, 1))); }
+ | MPLS { CHECK_PTR_VAL(($$ = gen_mpls(cstate, 0, 0))); }
+ | PPPOED { CHECK_PTR_VAL(($$ = gen_pppoed(cstate))); }
+ | PPPOES pnum { CHECK_PTR_VAL(($$ = gen_pppoes(cstate, (bpf_u_int32)$2, 1))); }
+ | PPPOES { CHECK_PTR_VAL(($$ = gen_pppoes(cstate, 0, 0))); }
+ | GENEVE pnum { CHECK_PTR_VAL(($$ = gen_geneve(cstate, (bpf_u_int32)$2, 1))); }
+ | GENEVE { CHECK_PTR_VAL(($$ = gen_geneve(cstate, 0, 0))); }
+ | pfvar { $$ = $1; }
+ | pqual p80211 { $$ = $2; }
+ | pllc { $$ = $1; }
+ ;
+
+pfvar: PF_IFNAME ID { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ifname(cstate, $2))); }
+ | PF_RSET ID { CHECK_PTR_VAL($2); CHECK_PTR_VAL(($$ = gen_pf_ruleset(cstate, $2))); }
+ | PF_RNR NUM { CHECK_PTR_VAL(($$ = gen_pf_rnr(cstate, $2))); }
+ | PF_SRNR NUM { CHECK_PTR_VAL(($$ = gen_pf_srnr(cstate, $2))); }
+ | PF_REASON reason { CHECK_PTR_VAL(($$ = gen_pf_reason(cstate, $2))); }
+ | PF_ACTION action { CHECK_PTR_VAL(($$ = gen_pf_action(cstate, $2))); }
+ ;
+
+p80211: TYPE type SUBTYPE subtype
+ { CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2 | $4,
+ IEEE80211_FC0_TYPE_MASK |
+ IEEE80211_FC0_SUBTYPE_MASK)));
+ }
+ | TYPE type { CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
+ IEEE80211_FC0_TYPE_MASK)));
+ }
+ | SUBTYPE type_subtype { CHECK_PTR_VAL(($$ = gen_p80211_type(cstate, $2,
+ IEEE80211_FC0_TYPE_MASK |
+ IEEE80211_FC0_SUBTYPE_MASK)));
+ }
+ | DIR dir { CHECK_PTR_VAL(($$ = gen_p80211_fcdir(cstate, $2))); }
+ ;
+
+type: NUM
+ | ID { CHECK_PTR_VAL($1);
+ $$ = str2tok($1, ieee80211_types);
+ if ($$ == -1) {
+ bpf_set_error(cstate, "unknown 802.11 type name");
+ YYABORT;
+ }
+ }
+ ;
+
+subtype: NUM
+ | ID { const struct tok *types = NULL;
+ int i;
+ CHECK_PTR_VAL($1);
+ for (i = 0;; i++) {
+ if (ieee80211_type_subtypes[i].tok == NULL) {
+ /* Ran out of types */
+ bpf_set_error(cstate, "unknown 802.11 type");
+ YYABORT;
+ }
+ if ($<i>-1 == ieee80211_type_subtypes[i].type) {
+ types = ieee80211_type_subtypes[i].tok;
+ break;
+ }
+ }
+
+ $$ = str2tok($1, types);
+ if ($$ == -1) {
+ bpf_set_error(cstate, "unknown 802.11 subtype name");
+ YYABORT;
+ }
+ }
+ ;
+
+type_subtype: ID { int i;
+ CHECK_PTR_VAL($1);
+ for (i = 0;; i++) {
+ if (ieee80211_type_subtypes[i].tok == NULL) {
+ /* Ran out of types */
+ bpf_set_error(cstate, "unknown 802.11 type name");
+ YYABORT;
+ }
+ $$ = str2tok($1, ieee80211_type_subtypes[i].tok);
+ if ($$ != -1) {
+ $$ |= ieee80211_type_subtypes[i].type;
+ break;
+ }
+ }
+ }
+ ;
+
+pllc: LLC { CHECK_PTR_VAL(($$ = gen_llc(cstate))); }
+ | LLC ID { CHECK_PTR_VAL($2);
+ if (pcap_strcasecmp($2, "i") == 0) {
+ CHECK_PTR_VAL(($$ = gen_llc_i(cstate)));
+ } else if (pcap_strcasecmp($2, "s") == 0) {
+ CHECK_PTR_VAL(($$ = gen_llc_s(cstate)));
+ } else if (pcap_strcasecmp($2, "u") == 0) {
+ CHECK_PTR_VAL(($$ = gen_llc_u(cstate)));
+ } else {
+ int subtype;
+
+ subtype = str2tok($2, llc_s_subtypes);
+ if (subtype != -1) {
+ CHECK_PTR_VAL(($$ = gen_llc_s_subtype(cstate, subtype)));
+ } else {
+ subtype = str2tok($2, llc_u_subtypes);
+ if (subtype == -1) {
+ bpf_set_error(cstate, "unknown LLC type name \"%s\"", $2);
+ YYABORT;
+ }
+ CHECK_PTR_VAL(($$ = gen_llc_u_subtype(cstate, subtype)));
+ }
+ }
+ }
+ /* sigh, "rnr" is already a keyword for PF */
+ | LLC PF_RNR { CHECK_PTR_VAL(($$ = gen_llc_s_subtype(cstate, LLC_RNR))); }
+ ;
+
+dir: NUM
+ | ID { CHECK_PTR_VAL($1);
+ if (pcap_strcasecmp($1, "nods") == 0)
+ $$ = IEEE80211_FC1_DIR_NODS;
+ else if (pcap_strcasecmp($1, "tods") == 0)
+ $$ = IEEE80211_FC1_DIR_TODS;
+ else if (pcap_strcasecmp($1, "fromds") == 0)
+ $$ = IEEE80211_FC1_DIR_FROMDS;
+ else if (pcap_strcasecmp($1, "dstods") == 0)
+ $$ = IEEE80211_FC1_DIR_DSTODS;
+ else {
+ bpf_set_error(cstate, "unknown 802.11 direction");
+ YYABORT;
+ }
+ }
+ ;
+
+reason: NUM { $$ = $1; }
+ | ID { CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfreason_to_num(cstate, $1))); }
+ ;
+
+action: ID { CHECK_PTR_VAL($1); CHECK_INT_VAL(($$ = pfaction_to_num(cstate, $1))); }
+ ;
+
+relop: '>' { $$ = BPF_JGT; }
+ | GEQ { $$ = BPF_JGE; }
+ | '=' { $$ = BPF_JEQ; }
+ ;
+irelop: LEQ { $$ = BPF_JGT; }
+ | '<' { $$ = BPF_JGE; }
+ | NEQ { $$ = BPF_JEQ; }
+ ;
+arth: pnum { CHECK_PTR_VAL(($$ = gen_loadi(cstate, $1))); }
+ | narth
+ ;
+narth: pname '[' arth ']' { CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, 1))); }
+ | pname '[' arth ':' NUM ']' { CHECK_PTR_VAL(($$ = gen_load(cstate, $1, $3, $5))); }
+ | arth '+' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_ADD, $1, $3))); }
+ | arth '-' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_SUB, $1, $3))); }
+ | arth '*' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MUL, $1, $3))); }
+ | arth '/' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_DIV, $1, $3))); }
+ | arth '%' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_MOD, $1, $3))); }
+ | arth '&' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_AND, $1, $3))); }
+ | arth '|' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_OR, $1, $3))); }
+ | arth '^' arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_XOR, $1, $3))); }
+ | arth LSH arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_LSH, $1, $3))); }
+ | arth RSH arth { CHECK_PTR_VAL(($$ = gen_arth(cstate, BPF_RSH, $1, $3))); }
+ | '-' arth %prec UMINUS { CHECK_PTR_VAL(($$ = gen_neg(cstate, $2))); }
+ | paren narth ')' { $$ = $2; }
+ | LEN { CHECK_PTR_VAL(($$ = gen_loadlen(cstate))); }
+ ;
+byteop: '&' { $$ = '&'; }
+ | '|' { $$ = '|'; }
+ | '<' { $$ = '<'; }
+ | '>' { $$ = '>'; }
+ | '=' { $$ = '='; }
+ ;
+pnum: NUM
+ | paren pnum ')' { $$ = $2; }
+ ;
+atmtype: LANE { $$ = A_LANE; }
+ | METAC { $$ = A_METAC; }
+ | BCC { $$ = A_BCC; }
+ | OAMF4EC { $$ = A_OAMF4EC; }
+ | OAMF4SC { $$ = A_OAMF4SC; }
+ | SC { $$ = A_SC; }
+ | ILMIC { $$ = A_ILMIC; }
+ ;
+atmmultitype: OAM { $$ = A_OAM; }
+ | OAMF4 { $$ = A_OAMF4; }
+ | CONNECTMSG { $$ = A_CONNECTMSG; }
+ | METACONNECT { $$ = A_METACONNECT; }
+ ;
+ /* ATM field types quantifier */
+atmfield: VPI { $$.atmfieldtype = A_VPI; }
+ | VCI { $$.atmfieldtype = A_VCI; }
+ ;
+atmvalue: atmfieldvalue
+ | relop NUM { CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 0))); }
+ | irelop NUM { CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $<blk>0.atmfieldtype, (bpf_int32)$2, (bpf_u_int32)$1, 1))); }
+ | paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; }
+ ;
+atmfieldvalue: NUM {
+ $$.atmfieldtype = $<blk>0.atmfieldtype;
+ if ($$.atmfieldtype == A_VPI ||
+ $$.atmfieldtype == A_VCI)
+ CHECK_PTR_VAL(($$.b = gen_atmfield_code(cstate, $$.atmfieldtype, (bpf_int32) $1, BPF_JEQ, 0)));
+ }
+ ;
+atmlistvalue: atmfieldvalue
+ | atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+ /* MTP2 types quantifier */
+mtp2type: FISU { $$ = M_FISU; }
+ | LSSU { $$ = M_LSSU; }
+ | MSU { $$ = M_MSU; }
+ | HFISU { $$ = MH_FISU; }
+ | HLSSU { $$ = MH_LSSU; }
+ | HMSU { $$ = MH_MSU; }
+ ;
+ /* MTP3 field types quantifier */
+mtp3field: SIO { $$.mtp3fieldtype = M_SIO; }
+ | OPC { $$.mtp3fieldtype = M_OPC; }
+ | DPC { $$.mtp3fieldtype = M_DPC; }
+ | SLS { $$.mtp3fieldtype = M_SLS; }
+ | HSIO { $$.mtp3fieldtype = MH_SIO; }
+ | HOPC { $$.mtp3fieldtype = MH_OPC; }
+ | HDPC { $$.mtp3fieldtype = MH_DPC; }
+ | HSLS { $$.mtp3fieldtype = MH_SLS; }
+ ;
+mtp3value: mtp3fieldvalue
+ | relop NUM { CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 0))); }
+ | irelop NUM { CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $<blk>0.mtp3fieldtype, (u_int)$2, (u_int)$1, 1))); }
+ | paren mtp3listvalue ')' { $$.b = $2.b; $$.q = qerr; }
+ ;
+mtp3fieldvalue: NUM {
+ $$.mtp3fieldtype = $<blk>0.mtp3fieldtype;
+ if ($$.mtp3fieldtype == M_SIO ||
+ $$.mtp3fieldtype == M_OPC ||
+ $$.mtp3fieldtype == M_DPC ||
+ $$.mtp3fieldtype == M_SLS ||
+ $$.mtp3fieldtype == MH_SIO ||
+ $$.mtp3fieldtype == MH_OPC ||
+ $$.mtp3fieldtype == MH_DPC ||
+ $$.mtp3fieldtype == MH_SLS)
+ CHECK_PTR_VAL(($$.b = gen_mtp3field_code(cstate, $$.mtp3fieldtype, (u_int) $1, BPF_JEQ, 0)));
+ }
+ ;
+mtp3listvalue: mtp3fieldvalue
+ | mtp3listvalue or mtp3fieldvalue { gen_or($1.b, $3.b); $$ = $3; }
+ ;
+%%
diff --git a/lib/libpcap/libpcap/ieee80211.h b/lib/libpcap/libpcap/ieee80211.h
new file mode 100644
index 0000000..473803d
--- /dev/null
+++ b/lib/libpcap/libpcap/ieee80211.h
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 2001 Atsushi Onoe
+ * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD: src/sys/net80211/ieee80211.h,v 1.10 2005/07/22 16:55:27 sam Exp $
+ */
+#ifndef _NET80211_IEEE80211_H_
+#define _NET80211_IEEE80211_H_
+
+/*
+ * 802.11 protocol definitions.
+ */
+
+#define IEEE80211_FC0_VERSION_MASK 0x03
+#define IEEE80211_FC0_VERSION_SHIFT 0
+#define IEEE80211_FC0_VERSION_0 0x00
+#define IEEE80211_FC0_TYPE_MASK 0x0c
+#define IEEE80211_FC0_TYPE_SHIFT 2
+#define IEEE80211_FC0_TYPE_MGT 0x00
+#define IEEE80211_FC0_TYPE_CTL 0x04
+#define IEEE80211_FC0_TYPE_DATA 0x08
+
+#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
+#define IEEE80211_FC0_SUBTYPE_SHIFT 4
+/* for TYPE_MGT */
+#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
+#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
+#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
+#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
+#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
+#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
+#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
+#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
+#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
+#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
+#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
+/* for TYPE_CTL */
+#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0
+#define IEEE80211_FC0_SUBTYPE_RTS 0xb0
+#define IEEE80211_FC0_SUBTYPE_CTS 0xc0
+#define IEEE80211_FC0_SUBTYPE_ACK 0xd0
+#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0
+#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0
+/* for TYPE_DATA (bit combination) */
+#define IEEE80211_FC0_SUBTYPE_DATA 0x00
+#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10
+#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20
+#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30
+#define IEEE80211_FC0_SUBTYPE_NODATA 0x40
+#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACK 0x50
+#define IEEE80211_FC0_SUBTYPE_NODATA_CF_POLL 0x60
+#define IEEE80211_FC0_SUBTYPE_NODATA_CF_ACPL 0x70
+#define IEEE80211_FC0_SUBTYPE_QOS 0x80
+#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0
+
+#define IEEE80211_FC1_DIR_MASK 0x03
+#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
+#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
+#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
+#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
+
+#define IEEE80211_FC1_MORE_FRAG 0x04
+#define IEEE80211_FC1_RETRY 0x08
+#define IEEE80211_FC1_PWR_MGT 0x10
+#define IEEE80211_FC1_MORE_DATA 0x20
+#define IEEE80211_FC1_WEP 0x40
+#define IEEE80211_FC1_ORDER 0x80
+
+#define IEEE80211_SEQ_FRAG_MASK 0x000f
+#define IEEE80211_SEQ_FRAG_SHIFT 0
+#define IEEE80211_SEQ_SEQ_MASK 0xfff0
+#define IEEE80211_SEQ_SEQ_SHIFT 4
+
+#define IEEE80211_NWID_LEN 32
+
+#define IEEE80211_QOS_TXOP 0x00ff
+/* bit 8 is reserved */
+#define IEEE80211_QOS_ACKPOLICY 0x60
+#define IEEE80211_QOS_ACKPOLICY_S 5
+#define IEEE80211_QOS_ESOP 0x10
+#define IEEE80211_QOS_ESOP_S 4
+#define IEEE80211_QOS_TID 0x0f
+
+#define IEEE80211_MGT_SUBTYPE_NAMES { \
+ "assoc-req", "assoc-resp", \
+ "reassoc-req", "reassoc-resp", \
+ "probe-req", "probe-resp", \
+ "reserved#6", "reserved#7", \
+ "beacon", "atim", \
+ "disassoc", "auth", \
+ "deauth", "reserved#13", \
+ "reserved#14", "reserved#15" \
+}
+
+#define IEEE80211_CTL_SUBTYPE_NAMES { \
+ "reserved#0", "reserved#1", \
+ "reserved#2", "reserved#3", \
+ "reserved#3", "reserved#5", \
+ "reserved#6", "reserved#7", \
+ "reserved#8", "reserved#9", \
+ "ps-poll", "rts", \
+ "cts", "ack", \
+ "cf-end", "cf-end-ack" \
+}
+
+#define IEEE80211_DATA_SUBTYPE_NAMES { \
+ "data", "data-cf-ack", \
+ "data-cf-poll", "data-cf-ack-poll", \
+ "null", "cf-ack", \
+ "cf-poll", "cf-ack-poll", \
+ "qos-data", "qos-data-cf-ack", \
+ "qos-data-cf-poll", "qos-data-cf-ack-poll", \
+ "qos", "reserved#13", \
+ "qos-cf-poll", "qos-cf-ack-poll" \
+}
+
+#define IEEE80211_TYPE_NAMES { "mgt", "ctl", "data", "reserved#4" }
+
+#endif /* _NET80211_IEEE80211_H_ */
diff --git a/lib/libpcap/libpcap/install-sh b/lib/libpcap/libpcap/install-sh
new file mode 100755
index 0000000..b44de09
--- /dev/null
+++ b/lib/libpcap/libpcap/install-sh
@@ -0,0 +1,250 @@
+#! /bin/sh
+#
+# install - install a program, script, or datafile
+# This comes from X11R5 (mit/util/scripts/install.sh).
+#
+# Copyright 1991 by the Massachusetts Institute of Technology
+#
+# Permission to use, copy, modify, distribute, and sell this software and its
+# documentation for any purpose is hereby granted without fee, provided that
+# the above copyright notice appear in all copies and that both that
+# copyright notice and this permission notice appear in supporting
+# documentation, and that the name of M.I.T. not be used in advertising or
+# publicity pertaining to distribution of the software without specific,
+# written prior permission. M.I.T. makes no representations about the
+# suitability of this software for any purpose. It is provided "as is"
+# without express or implied warranty.
+#
+# Calling this script install-sh is preferred over install.sh, to prevent
+# `make' implicit rules from creating a file called install from it
+# when there is no Makefile.
+#
+# This script is compatible with the BSD install script, but was written
+# from scratch. It can only install one file at a time, a restriction
+# shared with many OS's install programs.
+
+
+# set DOITPROG to echo to test this script
+
+# Don't use :- since 4.3BSD and earlier shells don't like it.
+doit="${DOITPROG-}"
+
+
+# put in absolute paths if you don't have them in your path; or use env. vars.
+
+mvprog="${MVPROG-mv}"
+cpprog="${CPPROG-cp}"
+chmodprog="${CHMODPROG-chmod}"
+chownprog="${CHOWNPROG-chown}"
+chgrpprog="${CHGRPPROG-chgrp}"
+stripprog="${STRIPPROG-strip}"
+rmprog="${RMPROG-rm}"
+mkdirprog="${MKDIRPROG-mkdir}"
+
+transformbasename=""
+transform_arg=""
+instcmd="$mvprog"
+chmodcmd="$chmodprog 0755"
+chowncmd=""
+chgrpcmd=""
+stripcmd=""
+rmcmd="$rmprog -f"
+mvcmd="$mvprog"
+src=""
+dst=""
+dir_arg=""
+
+while [ x"$1" != x ]; do
+ case $1 in
+ -c) instcmd="$cpprog"
+ shift
+ continue;;
+
+ -d) dir_arg=true
+ shift
+ continue;;
+
+ -m) chmodcmd="$chmodprog $2"
+ shift
+ shift
+ continue;;
+
+ -o) chowncmd="$chownprog $2"
+ shift
+ shift
+ continue;;
+
+ -g) chgrpcmd="$chgrpprog $2"
+ shift
+ shift
+ continue;;
+
+ -s) stripcmd="$stripprog"
+ shift
+ continue;;
+
+ -t=*) transformarg=`echo $1 | sed 's/-t=//'`
+ shift
+ continue;;
+
+ -b=*) transformbasename=`echo $1 | sed 's/-b=//'`
+ shift
+ continue;;
+
+ *) if [ x"$src" = x ]
+ then
+ src=$1
+ else
+ # this colon is to work around a 386BSD /bin/sh bug
+ :
+ dst=$1
+ fi
+ shift
+ continue;;
+ esac
+done
+
+if [ x"$src" = x ]
+then
+ echo "install: no input file specified"
+ exit 1
+else
+ true
+fi
+
+if [ x"$dir_arg" != x ]; then
+ dst=$src
+ src=""
+
+ if [ -d $dst ]; then
+ instcmd=:
+ else
+ instcmd=mkdir
+ fi
+else
+
+# Waiting for this to be detected by the "$instcmd $src $dsttmp" command
+# might cause directories to be created, which would be especially bad
+# if $src (and thus $dsttmp) contains '*'.
+
+ if [ -f $src -o -d $src ]
+ then
+ true
+ else
+ echo "install: $src does not exist"
+ exit 1
+ fi
+
+ if [ x"$dst" = x ]
+ then
+ echo "install: no destination specified"
+ exit 1
+ else
+ true
+ fi
+
+# If destination is a directory, append the input filename; if your system
+# does not like double slashes in filenames, you may need to add some logic
+
+ if [ -d $dst ]
+ then
+ dst="$dst"/`basename $src`
+ else
+ true
+ fi
+fi
+
+## this sed command emulates the dirname command
+dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'`
+
+# Make sure that the destination directory exists.
+# this part is taken from Noah Friedman's mkinstalldirs script
+
+# Skip lots of stat calls in the usual case.
+if [ ! -d "$dstdir" ]; then
+defaultIFS='
+'
+IFS="${IFS-${defaultIFS}}"
+
+oIFS="${IFS}"
+# Some sh's can't handle IFS=/ for some reason.
+IFS='%'
+set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'`
+IFS="${oIFS}"
+
+pathcomp=''
+
+while [ $# -ne 0 ] ; do
+ pathcomp="${pathcomp}${1}"
+ shift
+
+ if [ ! -d "${pathcomp}" ] ;
+ then
+ $mkdirprog "${pathcomp}"
+ else
+ true
+ fi
+
+ pathcomp="${pathcomp}/"
+done
+fi
+
+if [ x"$dir_arg" != x ]
+then
+ $doit $instcmd $dst &&
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi
+else
+
+# If we're going to rename the final executable, determine the name now.
+
+ if [ x"$transformarg" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ dstfile=`basename $dst $transformbasename |
+ sed $transformarg`$transformbasename
+ fi
+
+# don't allow the sed command to completely eliminate the filename
+
+ if [ x"$dstfile" = x ]
+ then
+ dstfile=`basename $dst`
+ else
+ true
+ fi
+
+# Make a temp file name in the proper directory.
+
+ dsttmp=$dstdir/#inst.$$#
+
+# Move or copy the file name to the temp name
+
+ $doit $instcmd $src $dsttmp &&
+
+ trap "rm -f ${dsttmp}" 0 &&
+
+# and set any options; do chmod last to preserve setuid bits
+
+# If any of these fail, we abort the whole thing. If we want to
+# ignore errors from any of these, just make sure not to ignore
+# errors from the above "$doit $instcmd $src $dsttmp" command.
+
+ if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi &&
+ if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi &&
+ if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi &&
+ if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi &&
+
+# Now rename the file to the real destination.
+
+ $doit $rmcmd -f $dstdir/$dstfile &&
+ $doit $mvcmd $dsttmp $dstdir/$dstfile
+
+fi &&
+
+
+exit 0
diff --git a/lib/libpcap/libpcap/lbl/os-aix4.h b/lib/libpcap/libpcap/lbl/os-aix4.h
new file mode 100644
index 0000000..5cf4586
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-aix4.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in AIX 4.x */
+int ffs(int i);
diff --git a/lib/libpcap/libpcap/lbl/os-aix7.h b/lib/libpcap/libpcap/lbl/os-aix7.h
new file mode 100644
index 0000000..93b12f2
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-aix7.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in AIX 7.x */
+int ffs(int i);
diff --git a/lib/libpcap/libpcap/lbl/os-hpux11.h b/lib/libpcap/libpcap/lbl/os-hpux11.h
new file mode 100644
index 0000000..42c6b60
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-hpux11.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in HP-UX 11.x */
+int ffs(int i);
diff --git a/lib/libpcap/libpcap/lbl/os-osf4.h b/lib/libpcap/libpcap/lbl/os-osf4.h
new file mode 100644
index 0000000..055eb80
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-osf4.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in Digital UNIX 4.x */
+int pcap_snprintf(char *, size_t, const char *, ...);
+int pcap_vsnprintf(char *, size_t, const char *, va_list);
+int pfopen(char *, int);
+
diff --git a/lib/libpcap/libpcap/lbl/os-osf5.h b/lib/libpcap/libpcap/lbl/os-osf5.h
new file mode 100644
index 0000000..5422f18
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-osf5.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Prototypes missing in Tru64 UNIX 5.x
+ * XXX - "pcap_snprintf()" and "pcap_vsnprintf()" aren't missing, but you have to
+ * #define the right value to get them defined by <stdio.h>.
+ */
+int pcap_snprintf(char *, size_t, const char *, ...);
+int pcap_vsnprintf(char *, size_t, const char *, va_list);
+int pfopen(char *, int);
+
diff --git a/lib/libpcap/libpcap/lbl/os-solaris2.h b/lib/libpcap/libpcap/lbl/os-solaris2.h
new file mode 100644
index 0000000..a555f5e
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-solaris2.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in SunOS 5 */
+char *strerror(int);
+int pcap_snprintf(char *, size_t, const char *, ...);
diff --git a/lib/libpcap/libpcap/lbl/os-sunos4.h b/lib/libpcap/libpcap/lbl/os-sunos4.h
new file mode 100644
index 0000000..6353fb0
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-sunos4.h
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 1989, 1990, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in SunOS 4 */
+#ifdef FILE
+int _filbuf(FILE *);
+int _flsbuf(u_char, FILE *);
+int fclose(FILE *);
+int fflush(FILE *);
+int fgetc(FILE *);
+int fprintf(FILE *, const char *, ...);
+int fputc(int, FILE *);
+int fputs(const char *, FILE *);
+u_int fread(void *, u_int, u_int, FILE *);
+int fseek(FILE *, long, int);
+u_int fwrite(const void *, u_int, u_int, FILE *);
+int pclose(FILE *);
+void rewind(FILE *);
+void setbuf(FILE *, char *);
+int setlinebuf(FILE *);
+int ungetc(int, FILE *);
+int vfprintf(FILE *, const char *, ...);
+int vprintf(const char *, ...);
+#endif
+
+#if __GNUC__ <= 1
+int read(int, char *, u_int);
+int write(int, char *, u_int);
+#endif
+
+long a64l(const char *);
+#ifdef __STDC__
+struct sockaddr;
+#endif
+int accept(int, struct sockaddr *, int *);
+int bind(int, struct sockaddr *, int);
+int bcmp(const void *, const void *, u_int);
+void bcopy(const void *, void *, u_int);
+void bzero(void *, int);
+int chroot(const char *);
+int close(int);
+void closelog(void);
+int connect(int, struct sockaddr *, int);
+char *crypt(const char *, const char *);
+int daemon(int, int);
+int fchmod(int, int);
+int fchown(int, int, int);
+void endgrent(void);
+void endpwent(void);
+#ifdef __STDC__
+struct ether_addr;
+#endif
+struct ether_addr *ether_aton(const char *);
+int flock(int, int);
+#ifdef __STDC__
+struct stat;
+#endif
+int fstat(int, struct stat *);
+#ifdef __STDC__
+struct statfs;
+#endif
+int fstatfs(int, struct statfs *);
+int fsync(int);
+#ifdef __STDC__
+struct timeb;
+#endif
+int ftime(struct timeb *);
+int ftruncate(int, off_t);
+int getdtablesize(void);
+long gethostid(void);
+int gethostname(char *, int);
+int getopt(int, char * const *, const char *);
+int getpagesize(void);
+char *getpass(char *);
+int getpeername(int, struct sockaddr *, int *);
+int getpriority(int, int);
+#ifdef __STDC__
+struct rlimit;
+#endif
+int getrlimit(int, struct rlimit *);
+int getsockname(int, struct sockaddr *, int *);
+int getsockopt(int, int, int, char *, int *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int gettimeofday(struct timeval *, struct timezone *);
+char *getusershell(void);
+char *getwd(char *);
+int initgroups(const char *, int);
+int ioctl(int, int, caddr_t);
+int iruserok(u_long, int, char *, char *);
+int isatty(int);
+int killpg(int, int);
+int listen(int, int);
+#ifdef __STDC__
+struct utmp;
+#endif
+void login(struct utmp *);
+int logout(const char *);
+off_t lseek(int, off_t, int);
+int lstat(const char *, struct stat *);
+int mkstemp(char *);
+char *mktemp(char *);
+int munmap(caddr_t, int);
+void openlog(const char *, int, int);
+void perror(const char *);
+int printf(const char *, ...);
+int puts(const char *);
+long random(void);
+int readlink(const char *, char *, int);
+#ifdef __STDC__
+struct iovec;
+#endif
+int readv(int, struct iovec *, int);
+int recv(int, char *, u_int, int);
+int recvfrom(int, char *, u_int, int, struct sockaddr *, int *);
+int rename(const char *, const char *);
+int rcmd(char **, u_short, char *, char *, char *, int *);
+int rresvport(int *);
+int send(int, char *, u_int, int);
+int sendto(int, char *, u_int, int, struct sockaddr *, int);
+int setenv(const char *, const char *, int);
+int seteuid(int);
+int setpriority(int, int, int);
+int select(int, fd_set *, fd_set *, fd_set *, struct timeval *);
+int setpgrp(int, int);
+void setpwent(void);
+int setrlimit(int, struct rlimit *);
+int setsockopt(int, int, int, char *, int);
+int shutdown(int, int);
+int sigblock(int);
+void (*signal (int, void (*) (int))) (int);
+int sigpause(int);
+int sigsetmask(int);
+#ifdef __STDC__
+struct sigvec;
+#endif
+int sigvec(int, struct sigvec *, struct sigvec*);
+int pcap_snprintf(char *, size_t, const char *, ...);
+int socket(int, int, int);
+int socketpair(int, int, int, int *);
+int symlink(const char *, const char *);
+void srandom(int);
+int sscanf(char *, const char *, ...);
+int stat(const char *, struct stat *);
+int statfs(char *, struct statfs *);
+char *strerror(int);
+int strcasecmp(const char *, const char *);
+#ifdef __STDC__
+struct tm;
+#endif
+int strftime(char *, int, char *, struct tm *);
+int strncasecmp(const char *, const char *, int);
+long strtol(const char *, char **, int);
+void sync(void);
+void syslog(int, const char *, ...);
+int system(const char *);
+long tell(int);
+time_t time(time_t *);
+char *timezone(int, int);
+int tolower(int);
+int toupper(int);
+int truncate(char *, off_t);
+void unsetenv(const char *);
+int vfork(void);
+int vsprintf(char *, const char *, ...);
+int writev(int, struct iovec *, int);
+#ifdef __STDC__
+struct rusage;
+#endif
+int utimes(const char *, struct timeval *);
+#if __GNUC__ <= 1
+int wait(int *);
+pid_t wait3(int *, int, struct rusage *);
+#endif
+
+/* Ugly signal hacking */
+#ifdef SIG_ERR
+#undef SIG_ERR
+#define SIG_ERR (void (*)(int))-1
+#undef SIG_DFL
+#define SIG_DFL (void (*)(int))0
+#undef SIG_IGN
+#define SIG_IGN (void (*)(int))1
+
+#ifdef KERNEL
+#undef SIG_CATCH
+#define SIG_CATCH (void (*)(int))2
+#endif
+#undef SIG_HOLD
+#define SIG_HOLD (void (*)(int))3
+#endif
diff --git a/lib/libpcap/libpcap/lbl/os-ultrix4.h b/lib/libpcap/libpcap/lbl/os-ultrix4.h
new file mode 100644
index 0000000..21e5702
--- /dev/null
+++ b/lib/libpcap/libpcap/lbl/os-ultrix4.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1990, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Prototypes missing in Ultrix 4 */
+int bcmp(const char *, const char *, u_int);
+void bcopy(const void *, void *, u_int);
+void bzero(void *, u_int);
+int getopt(int, char * const *, const char *);
+#ifdef __STDC__
+struct timeval;
+struct timezone;
+#endif
+int gettimeofday(struct timeval *, struct timezone *);
+int ioctl(int, int, caddr_t);
+int pfopen(char *, int);
+int setlinebuf(FILE *);
+int socket(int, int, int);
+int strcasecmp(const char *, const char *);
diff --git a/lib/libpcap/libpcap/libpcap.pc.in b/lib/libpcap/libpcap/libpcap.pc.in
new file mode 100644
index 0000000..d74cbc5
--- /dev/null
+++ b/lib/libpcap/libpcap/libpcap.pc.in
@@ -0,0 +1,18 @@
+#
+# pkg-config file for libpcap.
+#
+# These variables come from the configure script, so includedir and
+# libdir may be defined in terms of prefix and exec_prefix, so the
+# latter must be defined as well.
+#
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+includedir="@includedir@"
+libdir="@libdir@"
+
+Name: libpcap
+Description: Platform-independent network traffic capture library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -l@PACKAGE_NAME@
+Libs.private: @LIBS@
+Cflags: -I${includedir}
diff --git a/lib/libpcap/libpcap/llc.h b/lib/libpcap/libpcap/llc.h
new file mode 100644
index 0000000..b0cf881
--- /dev/null
+++ b/lib/libpcap/libpcap/llc.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 1993, 1994, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Definitions for information in the LLC header.
+ */
+
+#define LLC_U_FMT 3
+#define LLC_GSAP 1
+#define LLC_IG 1 /* Individual / Group */
+#define LLC_S_FMT 1
+
+#define LLC_U_POLL 0x10
+#define LLC_IS_POLL 0x0100
+#define LLC_XID_FI 0x81
+
+#define LLC_U_CMD_MASK 0xef
+#define LLC_UI 0x03
+#define LLC_UA 0x63
+#define LLC_DISC 0x43
+#define LLC_DM 0x0f
+#define LLC_SABME 0x6f
+#define LLC_TEST 0xe3
+#define LLC_XID 0xaf
+#define LLC_FRMR 0x87
+
+#define LLC_S_CMD_MASK 0x0f
+#define LLC_RR 0x0001
+#define LLC_RNR 0x0005
+#define LLC_REJ 0x0009
+
+#define LLC_IS_NR(is) (((is) >> 9) & 0x7f)
+#define LLC_I_NS(is) (((is) >> 1) & 0x7f)
+
+/*
+ * 802.2 LLC SAP values.
+ */
+
+#ifndef LLCSAP_NULL
+#define LLCSAP_NULL 0x00
+#endif
+#ifndef LLCSAP_GLOBAL
+#define LLCSAP_GLOBAL 0xff
+#endif
+#ifndef LLCSAP_8021B_I
+#define LLCSAP_8021B_I 0x02
+#endif
+#ifndef LLCSAP_8021B_G
+#define LLCSAP_8021B_G 0x03
+#endif
+#ifndef LLCSAP_IP
+#define LLCSAP_IP 0x06
+#endif
+#ifndef LLCSAP_PROWAYNM
+#define LLCSAP_PROWAYNM 0x0e
+#endif
+#ifndef LLCSAP_8021D
+#define LLCSAP_8021D 0x42
+#endif
+#ifndef LLCSAP_RS511
+#define LLCSAP_RS511 0x4e
+#endif
+#ifndef LLCSAP_ISO8208
+#define LLCSAP_ISO8208 0x7e
+#endif
+#ifndef LLCSAP_PROWAY
+#define LLCSAP_PROWAY 0x8e
+#endif
+#ifndef LLCSAP_SNAP
+#define LLCSAP_SNAP 0xaa
+#endif
+#ifndef LLCSAP_IPX
+#define LLCSAP_IPX 0xe0
+#endif
+#ifndef LLCSAP_NETBEUI
+#define LLCSAP_NETBEUI 0xf0
+#endif
+#ifndef LLCSAP_ISONS
+#define LLCSAP_ISONS 0xfe
+#endif
diff --git a/lib/libpcap/libpcap/missing/asprintf.c b/lib/libpcap/libpcap/missing/asprintf.c
new file mode 100644
index 0000000..3aa55ed
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/asprintf.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+/*
+ * vasprintf() and asprintf() for platforms with a C99-compliant
+ * snprintf() - so that, if you format into a 1-byte buffer, it
+ * will return how many characters it would have produced had
+ * it been given an infinite-sized buffer.
+ */
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+ char buf;
+ int len;
+ size_t str_size;
+ char *str;
+ int ret;
+
+ /*
+ * XXX - the C99 standard says, in section 7.19.6.5 "Thes
+ * nprintf function":
+ *
+ * The snprintf function is equivalent to fprintf, except that
+ * the output is written into an array (specified by argument s)
+ * rather than to a stream. If n is zero, nothing is written,
+ * and s may be a null pointer. Otherwise, output characters
+ * beyond the n-1st are discarded rather than being written
+ * to the array, and a null character is written at the end
+ * of the characters actually written into the array.
+ *
+ * ...
+ *
+ * The snprintf function returns the number of characters that
+ * would have been written had n been sufficiently large, not
+ * counting the terminating null character, or a negative value
+ * if an encoding error occurred. Thus, the null-terminated
+ * output has been completely written if and only if the returned
+ * value is nonnegative and less than n.
+ *
+ * That doesn't make it entirely clear whether, if a null buffer
+ * pointer and a zero count are passed, it will return the number
+ * of characters that would have been written had a buffer been
+ * passed.
+ *
+ * And, even if C99 *does*, in fact, say it has to work, it
+ * doesn't work in Solaris 8, for example - it returns -1 for
+ * NULL/0, but returns the correct character count for a 1-byte
+ * buffer.
+ *
+ * So we pass a one-character pointer in order to find out how
+ * many characters this format and those arguments will need
+ * without actually generating any more of those characters
+ * than we need.
+ *
+ * (The fact that it might happen to work with GNU libc or with
+ * various BSD libcs is completely uninteresting, as those tend
+ * to have asprintf() already and thus don't even *need* this
+ * code; this is for use in those UN*Xes that *don't* have
+ * asprintf().)
+ */
+ len = vsnprintf(&buf, sizeof buf, format, args);
+ if (len == -1) {
+ *strp = NULL;
+ return (-1);
+ }
+ str_size = len + 1;
+ str = malloc(str_size);
+ if (str == NULL) {
+ *strp = NULL;
+ return (-1);
+ }
+ ret = vsnprintf(str, str_size, format, args);
+ if (ret == -1) {
+ free(str);
+ *strp = NULL;
+ return (-1);
+ }
+ *strp = str;
+ /*
+ * vsnprintf() shouldn't truncate the string, as we have
+ * allocated a buffer large enough to hold the string, so its
+ * return value should be the number of characters written.
+ */
+ return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = pcap_vasprintf(strp, format, args);
+ va_end(args);
+ return (ret);
+}
+
diff --git a/lib/libpcap/libpcap/missing/getopt.c b/lib/libpcap/libpcap/missing/getopt.c
new file mode 100644
index 0000000..7c897c6
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/getopt.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1987, 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.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "getopt.h"
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt(int nargc, char * const *nargv, const char *ostr)
+{
+ char *cp;
+ static char *__progname;
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ if (__progname == NULL) {
+ if ((cp = strrchr(nargv[0], '/')) != NULL)
+ __progname = cp + 1;
+ else
+ __progname = nargv[0];
+ }
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc || *(place = nargv[optind]) != '-') {
+ place = EMSG;
+ return (-1);
+ }
+ if (place[1] && *++place == '-') { /* found "--" */
+ ++optind;
+ place = EMSG;
+ return (-1);
+ }
+ } /* option letter okay? */
+ if ((optopt = (int)*place++) == (int)':' ||
+ !(oli = strchr(ostr, optopt))) {
+ /*
+ * if the user didn't specify '-' as an option,
+ * assume it means -1.
+ */
+ if (optopt == (int)'-')
+ return (-1);
+ if (!*place)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", __progname, optopt);
+ return (BADCH);
+ }
+ if (*++oli != ':') { /* don't need argument */
+ optarg = NULL;
+ if (!*place)
+ ++optind;
+ }
+ else { /* need an argument */
+ if (*place) /* no white space */
+ optarg = place;
+ else if (nargc <= ++optind) { /* no arg */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ __progname, optopt);
+ return (BADCH);
+ }
+ else /* white space */
+ optarg = nargv[optind];
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* dump back option letter */
+}
diff --git a/lib/libpcap/libpcap/missing/getopt.h b/lib/libpcap/libpcap/missing/getopt.h
new file mode 100644
index 0000000..fc83c94
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/getopt.h
@@ -0,0 +1,7 @@
+/*
+ * Header for the getopt() we supply if the platform doesn't supply it.
+ */
+extern char *optarg; /* getopt(3) external variables */
+extern int optind, opterr, optreset, optopt;
+
+extern int getopt(int nargc, char * const *nargv, const char *ostr);
diff --git a/lib/libpcap/libpcap/missing/snprintf.c b/lib/libpcap/libpcap/missing/snprintf.c
new file mode 100644
index 0000000..9cce728
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/snprintf.c
@@ -0,0 +1,631 @@
+/*
+ * Copyright (c) 1995-1999 Kungliga Tekniska Hšgskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * We use this for platforms that don't have snprintf() at all.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/types.h>
+
+#include "portability.h"
+
+enum format_flags {
+ minus_flag = 1,
+ plus_flag = 2,
+ space_flag = 4,
+ alternate_flag = 8,
+ zero_flag = 16
+};
+
+/*
+ * Common state
+ */
+
+struct state {
+ unsigned char *str;
+ unsigned char *s;
+ unsigned char *theend;
+ size_t sz;
+ size_t max_sz;
+ int (*append_char)(struct state *, unsigned char);
+ int (*reserve)(struct state *, size_t);
+ /* XXX - methods */
+};
+
+#ifndef HAVE_VSNPRINTF
+static int
+sn_reserve (struct state *state, size_t n)
+{
+ return state->s + n > state->theend;
+}
+
+static int
+sn_append_char (struct state *state, unsigned char c)
+{
+ if (sn_reserve (state, 1)) {
+ return 1;
+ } else {
+ *state->s++ = c;
+ return 0;
+ }
+}
+#endif
+
+#if 0
+static int
+as_reserve (struct state *state, size_t n)
+{
+ if (state->s + n > state->theend) {
+ int off = state->s - state->str;
+ unsigned char *tmp;
+
+ if (state->max_sz && state->sz >= state->max_sz)
+ return 1;
+
+ state->sz = max(state->sz * 2, state->sz + n);
+ if (state->max_sz)
+ state->sz = min(state->sz, state->max_sz);
+ tmp = realloc (state->str, state->sz);
+ if (tmp == NULL)
+ return 1;
+ state->str = tmp;
+ state->s = state->str + off;
+ state->theend = state->str + state->sz - 1;
+ }
+ return 0;
+}
+
+static int
+as_append_char (struct state *state, unsigned char c)
+{
+ if(as_reserve (state, 1))
+ return 1;
+ else {
+ *state->s++ = c;
+ return 0;
+ }
+}
+#endif
+
+static int
+append_number(struct state *state,
+ unsigned long num, unsigned base, char *rep,
+ int width, int prec, int flags, int minusp)
+{
+ int len = 0;
+ int i;
+
+ /* given precision, ignore zero flag */
+ if(prec != -1)
+ flags &= ~zero_flag;
+ else
+ prec = 1;
+ /* zero value with zero precision -> "" */
+ if(prec == 0 && num == 0)
+ return 0;
+ do{
+ if((*state->append_char)(state, rep[num % base]))
+ return 1;
+ len++;
+ num /= base;
+ }while(num);
+ prec -= len;
+ /* pad with prec zeros */
+ while(prec-- > 0){
+ if((*state->append_char)(state, '0'))
+ return 1;
+ len++;
+ }
+ /* add length of alternate prefix (added later) to len */
+ if(flags & alternate_flag && (base == 16 || base == 8))
+ len += base / 8;
+ /* pad with zeros */
+ if(flags & zero_flag){
+ width -= len;
+ if(minusp || (flags & space_flag) || (flags & plus_flag))
+ width--;
+ while(width-- > 0){
+ if((*state->append_char)(state, '0'))
+ return 1;
+ len++;
+ }
+ }
+ /* add alternate prefix */
+ if(flags & alternate_flag && (base == 16 || base == 8)){
+ if(base == 16)
+ if((*state->append_char)(state, rep[10] + 23)) /* XXX */
+ return 1;
+ if((*state->append_char)(state, '0'))
+ return 1;
+ }
+ /* add sign */
+ if(minusp){
+ if((*state->append_char)(state, '-'))
+ return 1;
+ len++;
+ } else if(flags & plus_flag) {
+ if((*state->append_char)(state, '+'))
+ return 1;
+ len++;
+ } else if(flags & space_flag) {
+ if((*state->append_char)(state, ' '))
+ return 1;
+ len++;
+ }
+ if(flags & minus_flag)
+ /* swap before padding with spaces */
+ for(i = 0; i < len / 2; i++){
+ char c = state->s[-i-1];
+ state->s[-i-1] = state->s[-len+i];
+ state->s[-len+i] = c;
+ }
+ width -= len;
+ while(width-- > 0){
+ if((*state->append_char)(state, ' '))
+ return 1;
+ len++;
+ }
+ if(!(flags & minus_flag))
+ /* swap after padding with spaces */
+ for(i = 0; i < len / 2; i++){
+ char c = state->s[-i-1];
+ state->s[-i-1] = state->s[-len+i];
+ state->s[-len+i] = c;
+ }
+
+ return 0;
+}
+
+static int
+append_string (struct state *state,
+ unsigned char *arg,
+ int width,
+ int prec,
+ int flags)
+{
+ if(prec != -1)
+ width -= prec;
+ else
+ width -= strlen((char *)arg);
+ if(!(flags & minus_flag))
+ while(width-- > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+ if (prec != -1) {
+ while (*arg && prec--)
+ if ((*state->append_char) (state, *arg++))
+ return 1;
+ } else {
+ while (*arg)
+ if ((*state->append_char) (state, *arg++))
+ return 1;
+ }
+ if(flags & minus_flag)
+ while(width-- > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+ return 0;
+}
+
+static int
+append_char(struct state *state,
+ unsigned char arg,
+ int width,
+ int flags)
+{
+ while(!(flags & minus_flag) && --width > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+
+ if((*state->append_char) (state, arg))
+ return 1;
+ while((flags & minus_flag) && --width > 0)
+ if((*state->append_char) (state, ' '))
+ return 1;
+
+ return 0;
+}
+
+/*
+ * This can't be made into a function...
+ */
+
+#define PARSE_INT_FORMAT(res, arg, unsig) \
+if (long_flag) \
+ res = (unsig long)va_arg(arg, unsig long); \
+else if (short_flag) \
+ res = (unsig short)va_arg(arg, unsig int); \
+else \
+ res = (unsig int)va_arg(arg, unsig int)
+
+/*
+ * zyxprintf - return 0 or -1
+ */
+
+static int
+xyzprintf (struct state *state, const char *char_format, va_list ap)
+{
+ const unsigned char *format = (const unsigned char *)char_format;
+ unsigned char c;
+
+ while((c = *format++)) {
+ if (c == '%') {
+ int flags = 0;
+ int width = 0;
+ int prec = -1;
+ int long_flag = 0;
+ int short_flag = 0;
+
+ /* flags */
+ while((c = *format++)){
+ if(c == '-')
+ flags |= minus_flag;
+ else if(c == '+')
+ flags |= plus_flag;
+ else if(c == ' ')
+ flags |= space_flag;
+ else if(c == '#')
+ flags |= alternate_flag;
+ else if(c == '0')
+ flags |= zero_flag;
+ else
+ break;
+ }
+
+ if((flags & space_flag) && (flags & plus_flag))
+ flags ^= space_flag;
+
+ if((flags & minus_flag) && (flags & zero_flag))
+ flags ^= zero_flag;
+
+ /* width */
+ if (isdigit(c))
+ do {
+ width = width * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if(c == '*') {
+ width = va_arg(ap, int);
+ c = *format++;
+ }
+
+ /* precision */
+ if (c == '.') {
+ prec = 0;
+ c = *format++;
+ if (isdigit(c))
+ do {
+ prec = prec * 10 + c - '0';
+ c = *format++;
+ } while(isdigit(c));
+ else if (c == '*') {
+ prec = va_arg(ap, int);
+ c = *format++;
+ }
+ }
+
+ /* size */
+
+ if (c == 'h') {
+ short_flag = 1;
+ c = *format++;
+ } else if (c == 'l') {
+ long_flag = 1;
+ c = *format++;
+ }
+
+ switch (c) {
+ case 'c' :
+ if(append_char(state, va_arg(ap, int), width, flags))
+ return -1;
+ break;
+ case 's' :
+ if (append_string(state,
+ va_arg(ap, unsigned char*),
+ width,
+ prec,
+ flags))
+ return -1;
+ break;
+ case 'd' :
+ case 'i' : {
+ long arg;
+ unsigned long num;
+ int minusp = 0;
+
+ PARSE_INT_FORMAT(arg, ap, signed);
+
+ if (arg < 0) {
+ minusp = 1;
+ num = -arg;
+ } else
+ num = arg;
+
+ if (append_number (state, num, 10, "0123456789",
+ width, prec, flags, minusp))
+ return -1;
+ break;
+ }
+ case 'u' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 10, "0123456789",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'o' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 010, "01234567",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'x' : {
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 0x10, "0123456789abcdef",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'X' :{
+ unsigned long arg;
+
+ PARSE_INT_FORMAT(arg, ap, unsigned);
+
+ if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'p' : {
+ unsigned long arg = (unsigned long)va_arg(ap, void*);
+
+ if (append_number (state, arg, 0x10, "0123456789ABCDEF",
+ width, prec, flags, 0))
+ return -1;
+ break;
+ }
+ case 'n' : {
+ int *arg = va_arg(ap, int*);
+ *arg = state->s - state->str;
+ break;
+ }
+ case '\0' :
+ --format;
+ /* FALLTHROUGH */
+ case '%' :
+ if ((*state->append_char)(state, c))
+ return -1;
+ break;
+ default :
+ if ( (*state->append_char)(state, '%')
+ || (*state->append_char)(state, c))
+ return -1;
+ break;
+ }
+ } else
+ if ((*state->append_char) (state, c))
+ return -1;
+ }
+ return 0;
+}
+
+#ifndef HAVE_SNPRINTF
+int
+pcap_snprintf (char *str, size_t sz, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = pcap_vsnprintf (str, sz, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+
+ tmp = malloc (sz);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = pcap_vsprintf (tmp, format, args);
+ if (ret != ret2 || strcmp(str, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return ret;
+}
+#endif
+
+#if 0
+#ifndef HAVE_ASPRINTF
+int
+asprintf (char **ret, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = vasprintf (ret, format, args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ ret2 = vsprintf (tmp, format, args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ va_end(args);
+ return val;
+}
+#endif
+
+#ifndef HAVE_ASNPRINTF
+int
+pcap_asnprintf (char **ret, size_t max_sz, const char *format, ...)
+{
+ va_list args;
+ int val;
+
+ va_start(args, format);
+ val = pcap_vasnprintf (ret, max_sz, format, args);
+ va_end(args);
+
+#ifdef PARANOIA
+ {
+ int ret2;
+ char *tmp;
+ tmp = malloc (val + 1);
+ if (tmp == NULL)
+ abort ();
+
+ va_start(args, format);
+ ret2 = pcap_vsprintf (tmp, format, args);
+ va_end(args);
+ if (val != ret2 || strcmp(*ret, tmp))
+ abort ();
+ free (tmp);
+ }
+#endif
+
+ return val;
+}
+#endif
+
+#ifndef HAVE_VASPRINTF
+int
+pcap_vasprintf (char **ret, const char *format, va_list args)
+{
+ return pcap_vasnprintf (ret, 0, format, args);
+}
+#endif
+
+
+#ifndef HAVE_VASNPRINTF
+int
+pcap_vasnprintf (char **ret, size_t max_sz, const char *format, va_list args)
+{
+ int st;
+ size_t len;
+ struct state state;
+
+ state.max_sz = max_sz;
+ state.sz = 1;
+ state.str = malloc(state.sz);
+ if (state.str == NULL) {
+ *ret = NULL;
+ return -1;
+ }
+ state.s = state.str;
+ state.theend = state.s + state.sz - 1;
+ state.append_char = as_append_char;
+ state.reserve = as_reserve;
+
+ st = xyzprintf (&state, format, args);
+ if (st) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ } else {
+ char *tmp;
+
+ *state.s = '\0';
+ len = state.s - state.str;
+ tmp = realloc (state.str, len+1);
+ if (tmp == NULL) {
+ free (state.str);
+ *ret = NULL;
+ return -1;
+ }
+ *ret = tmp;
+ return len;
+ }
+}
+#endif
+#endif
+
+#ifndef HAVE_VSNPRINTF
+int
+pcap_vsnprintf (char *str, size_t sz, const char *format, va_list args)
+{
+ struct state state;
+ int ret;
+ unsigned char *ustr = (unsigned char *)str;
+
+ state.max_sz = 0;
+ state.sz = sz;
+ state.str = ustr;
+ state.s = ustr;
+ state.theend = ustr + sz - 1;
+ state.append_char = sn_append_char;
+ state.reserve = sn_reserve;
+
+ ret = xyzprintf (&state, format, args);
+ *state.s = '\0';
+ if (ret)
+ return sz;
+ else
+ return state.s - state.str;
+}
+#endif
+
diff --git a/lib/libpcap/libpcap/missing/strlcat.c b/lib/libpcap/libpcap/missing/strlcat.c
new file mode 100644
index 0000000..bb78a3d
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/strlcat.c
@@ -0,0 +1,61 @@
+/* $OpenBSD: pcap_strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+#include "portability.h"
+
+/*
+ * Appends src to string dst of size dsize (unlike strncat, dsize is the
+ * full size of dst, not space left). At most dsize-1 characters
+ * will be copied. Always NUL terminates (unless dsize <= strlen(dst)).
+ * Returns strlen(src) + MIN(dsize, strlen(initial dst)).
+ * If retval >= dsize, truncation occurred.
+ */
+size_t
+pcap_strlcat(char * restrict dst, const char * restrict src, size_t dsize)
+{
+ const char *odst = dst;
+ const char *osrc = src;
+ size_t n = dsize;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end. */
+ while (n-- != 0 && *dst != '\0')
+ dst++;
+ dlen = dst - odst;
+ n = dsize - dlen;
+
+ if (n-- == 0)
+ return(dlen + strlen(src));
+ while (*src != '\0') {
+ if (n != 0) {
+ *dst++ = *src;
+ n--;
+ }
+ src++;
+ }
+ *dst = '\0';
+
+ return(dlen + (src - osrc)); /* count does not include NUL */
+}
diff --git a/lib/libpcap/libpcap/missing/strlcpy.c b/lib/libpcap/libpcap/missing/strlcpy.c
new file mode 100644
index 0000000..c552e0d
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/strlcpy.c
@@ -0,0 +1,56 @@
+/* $OpenBSD: pcap_strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */
+
+/*
+ * Copyright (c) 1998, 2015 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * 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 HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
+
+#include "portability.h"
+
+/*
+ * Copy string src to buffer dst of size dsize. At most dsize-1
+ * chars will be copied. Always NUL terminates (unless dsize == 0).
+ * Returns strlen(src); if retval >= dsize, truncation occurred.
+ */
+size_t
+pcap_strlcpy(char * restrict dst, const char * restrict src, size_t dsize)
+{
+ const char *osrc = src;
+ size_t nleft = dsize;
+
+ /* Copy as many bytes as will fit. */
+ if (nleft != 0) {
+ while (--nleft != 0) {
+ if ((*dst++ = *src++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src. */
+ if (nleft == 0) {
+ if (dsize != 0)
+ *dst = '\0'; /* NUL-terminate dst */
+ while (*src++)
+ ;
+ }
+
+ return(src - osrc - 1); /* count does not include NUL */
+}
diff --git a/lib/libpcap/libpcap/missing/strtok_r.c b/lib/libpcap/libpcap/missing/strtok_r.c
new file mode 100644
index 0000000..5fca2f3
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/strtok_r.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC. All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * 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
+ * notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notices, 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 SOFTWEYR LLC, 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 SOFTWEYR LLC, 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: @(#)strtok.c 8.1 (Berkeley) 6/4/93
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "portability.h"
+
+char *
+pcap_strtok_r(char *s, const char *delim, char **last)
+{
+ char *spanp, *tok;
+ int c, sc;
+
+ if (s == NULL && (s = *last) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0) { /* no non-delimiter characters */
+ *last = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = '\0';
+ *last = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libpcap/libpcap/missing/win_asprintf.c b/lib/libpcap/libpcap/missing/win_asprintf.c
new file mode 100644
index 0000000..cce6296
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/win_asprintf.c
@@ -0,0 +1,51 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+int
+pcap_vasprintf(char **strp, const char *format, va_list args)
+{
+ int len;
+ size_t str_size;
+ char *str;
+ int ret;
+
+ len = _vscprintf(format, args);
+ if (len == -1) {
+ *strp = NULL;
+ return (-1);
+ }
+ str_size = len + 1;
+ str = malloc(str_size);
+ if (str == NULL) {
+ *strp = NULL;
+ return (-1);
+ }
+ ret = pcap_vsnprintf(str, str_size, format, args);
+ if (ret == -1) {
+ free(str);
+ *strp = NULL;
+ return (-1);
+ }
+ *strp = str;
+ /*
+ * pcap_vsnprintf() shouldn't truncate the string, as we have
+ * allocated a buffer large enough to hold the string, so its
+ * return value should be the number of characters printed.
+ */
+ return (ret);
+}
+
+int
+pcap_asprintf(char **strp, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = pcap_vasprintf(strp, format, args);
+ va_end(args);
+ return (ret);
+}
diff --git a/lib/libpcap/libpcap/missing/win_snprintf.c b/lib/libpcap/libpcap/missing/win_snprintf.c
new file mode 100644
index 0000000..f422403
--- /dev/null
+++ b/lib/libpcap/libpcap/missing/win_snprintf.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "portability.h"
+
+int
+pcap_vsnprintf(char *str, size_t str_size, const char *format, va_list args)
+{
+ int ret;
+
+ ret = _vsnprintf_s(str, str_size, _TRUNCATE, format, args);
+
+ /*
+ * XXX - _vsnprintf() and _snprintf() do *not* guarantee
+ * that str is null-terminated, but C99's vsnprintf()
+ * and snprintf() do, and we want to offer C99 behavior,
+ * so forcibly null-terminate the string.
+ *
+ * We don't, however, offer C99 behavior for the return
+ * value; _vsnprintf_s() returns -1, not the number of
+ * characters that would have been put into the buffer
+ * had it been large enough, if the string is truncated.
+ * The only way to get that value is to use _vscprintf();
+ * getting that count isn't worth the re-formatting.
+ *
+ * XXX - does _vsnprintf_s() return -1 on a formatting
+ * error?
+ */
+ str[str_size - 1] = '\0';
+ return (ret);
+}
+
+int
+pcap_snprintf(char *str, size_t str_size, const char *format, ...)
+{
+ va_list args;
+ int ret;
+
+ va_start(args, format);
+ ret = pcap_vsnprintf(str, str_size, format, args);
+ va_end(args);
+ return (ret);
+}
diff --git a/lib/libpcap/libpcap/mkdep b/lib/libpcap/libpcap/mkdep
new file mode 100755
index 0000000..1486b18
--- /dev/null
+++ b/lib/libpcap/libpcap/mkdep
@@ -0,0 +1,112 @@
+#!/bin/sh -
+#
+# Copyright (c) 1994, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms are permitted
+# provided that this notice is preserved and that due credit is given
+# to the University of California at Berkeley. The name of the University
+# may not be used to endorse or promote products derived from this
+# software without specific prior written permission. This software
+# is provided ``as is'' without express or implied warranty.
+#
+# @(#)mkdep.sh 5.11 (Berkeley) 5/5/88
+#
+
+MAKE=Makefile # default makefile name is "Makefile"
+CC=cc # default C compiler is "cc"
+DEPENDENCY_CFLAG=-M # default dependency-generation flag is -M
+
+while :
+ do case "$1" in
+ # -c allows you to specify the C compiler
+ -c)
+ CC=$2
+ shift; shift ;;
+
+ # -f allows you to select a makefile name
+ -f)
+ MAKE=$2
+ shift; shift ;;
+
+ # -m allows you to specify the dependency-generation flag
+ -m)
+ DEPENDENCY_CFLAG=$2
+ shift; shift ;;
+
+ # the -p flag produces "program: program.c" style dependencies
+ # so .o's don't get produced
+ -p)
+ SED='s;\.o;;'
+ shift ;;
+ *)
+ break ;;
+ esac
+done
+
+if [ $# = 0 ] ; then
+ echo 'usage: mkdep [-p] [-c cc] [-f makefile] [-m dependency-cflag] [flags] file ...'
+ exit 1
+fi
+
+if [ ! -w $MAKE ]; then
+ echo "mkdep: no writeable file \"$MAKE\""
+ exit 1
+fi
+
+TMP=/tmp/mkdep$$
+
+trap 'rm -f $TMP ; exit 1' 1 2 3 13 15
+
+cp $MAKE ${MAKE}.bak
+
+sed -e '/DO NOT DELETE THIS LINE/,$d' < $MAKE > $TMP
+
+cat << _EOF_ >> $TMP
+# DO NOT DELETE THIS LINE -- mkdep uses it.
+# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
+
+_EOF_
+
+# If your compiler doesn't have -M, add it. If you can't, the next two
+# lines will try and replace the "cc -M". The real problem is that this
+# hack can't deal with anything that requires a search path, and doesn't
+# even try for anything using bracket (<>) syntax.
+#
+# egrep '^#include[ ]*".*"' /dev/null $* |
+# sed -e 's/:[^"]*"\([^"]*\)".*/: \1/' -e 's/\.c/.o/' |
+
+# XXX this doesn't work with things like "-DDECLWAITSTATUS=union\ wait"
+$CC $DEPENDENCY_CFLAG $* |
+sed "
+ s; \./; ;g
+ $SED" |
+awk '{
+ if ($1 != prev) {
+ if (rec != "")
+ print rec;
+ rec = $0;
+ prev = $1;
+ }
+ else {
+ if (length(rec $2) > 78) {
+ print rec;
+ rec = $0;
+ }
+ else
+ rec = rec " " $2
+ }
+}
+END {
+ print rec
+}' >> $TMP
+
+cat << _EOF_ >> $TMP
+
+# IF YOU PUT ANYTHING HERE IT WILL GO AWAY
+_EOF_
+
+# copy to preserve permissions
+cp $TMP $MAKE
+rm -f ${MAKE}.bak $TMP
+exit 0
diff --git a/lib/libpcap/libpcap/msdos/bin2c.c b/lib/libpcap/libpcap/msdos/bin2c.c
new file mode 100644
index 0000000..26d9008
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/bin2c.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <time.h>
+
+static void Abort (const char *fmt,...)
+{
+ va_list args;
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ va_end (args);
+ exit (1);
+}
+
+int main (int argc, char **argv)
+{
+ FILE *inFile;
+ FILE *outFile = stdout;
+ time_t now = time (NULL);
+ int ch, i;
+
+ if (argc != 2)
+ Abort ("Usage: %s bin-file [> result]", argv[0]);
+
+ if ((inFile = fopen(argv[1],"rb")) == NULL)
+ Abort ("Cannot open %s\n", argv[1]);
+
+ fprintf (outFile,
+ "/* data statements for file %s at %.24s */\n"
+ "/* Generated by BIN2C, G. Vanem 1995 */\n",
+ argv[1], ctime(&now));
+
+ i = 0;
+ while ((ch = fgetc(inFile)) != EOF)
+ {
+ if (i++ % 12 == 0)
+ fputs ("\n ", outFile);
+ fprintf (outFile, "0x%02X,", ch);
+ }
+ fputc ('\n', outFile);
+ fclose (inFile);
+ return (0);
+}
diff --git a/lib/libpcap/libpcap/msdos/common.dj b/lib/libpcap/libpcap/msdos/common.dj
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/common.dj
diff --git a/lib/libpcap/libpcap/msdos/makefile b/lib/libpcap/libpcap/msdos/makefile
new file mode 100644
index 0000000..599a619
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/makefile
@@ -0,0 +1,180 @@
+#
+# Makefile for dos-libpcap. NB. This makefile requires a Borland
+# compatible make tool.
+#
+# Targets:
+# Borland C 4.0+ (DOS large model)
+# Metaware HighC 3.3+ (PharLap 386|DosX)
+#
+
+.AUTODEPEND
+.SWAP
+
+!if "$(WATT_ROOT)" == ""
+!error Environment variable "WATT_ROOT" not set.
+!endif
+
+WATT_INC = $(WATT_ROOT)\inc
+
+DEFS = -DMSDOS -DDEBUG -DNDIS_DEBUG -D_U_= -Dinline= \
+ -DHAVE_STRERROR -DHAVE_LIMITS_H
+
+ASM = tasm.exe -t -l -mx -m2 -DDEBUG
+
+SOURCE = grammar.c scanner.c bpf_filt.c bpf_imag.c bpf_dump.c \
+ etherent.c gencode.c nametoad.c pcap-dos.c optimize.c \
+ savefile.c pcap.c msdos\ndis2.c msdos\pktdrvr.c \
+ missing\snprintf.c
+
+BORLAND_OBJ = $(SOURCE:.c=.obj) msdos\pkt_rx0.obj msdos\ndis_0.obj
+
+HIGHC_OBJ = $(SOURCE:.c=.o32) msdos\pkt_rx0.o32
+
+all:
+ @echo Usage: make pcap_bc.lib or pcap_hc.lib
+
+
+pcap_bc.lib: bcc.arg $(BORLAND_OBJ) pcap_bc
+
+
+pcap_hc.lib: hc386.arg $(HIGHC_OBJ)
+ 386lib $< @&&|
+ -nowarn -nobackup -twocase -replace $(HIGHC_OBJ)
+|
+
+pcap_bc: $(BORLAND_OBJ)
+ @tlib pcap_bc.lib /C @&&|
+ -+$(**:.obj=-+)
+|
+
+.c.obj:
+ bcc.exe @bcc.arg -o$*.obj $*.c
+
+.c.o32:
+ hc386.exe @hc386.arg -o $*.o32 $*.c
+
+.asm.obj:
+ $(ASM) $*.asm, $*.obj
+
+.asm.o32:
+ $(ASM) -DDOSX=1 $*.asm, $*.o32
+
+scanner.c: scanner.l
+ flex -Ppcap_ -7 -oscanner.c scanner.l
+
+grammar.c tokdefs.h: grammar.y
+ bison --name-prefix=pcap_ --yacc --defines grammar.y
+ - @del grammar.c
+ - @del tokdefs.h
+ ren y_tab.c grammar.c
+ ren y_tab.h tokdefs.h
+
+bcc.arg: msdos\Makefile
+ @copy &&|
+ $(DEFS) -ml -c -v -3 -O2 -po -RT- -w-
+ -I$(WATT_INC) -I. -I.\msdos\pm_drvr -H=$(TEMP)\bcc.sym
+| $<
+
+hc386.arg: msdos\Makefile
+ @copy &&|
+ # -DUSE_32BIT_DRIVERS
+ $(DEFS) -DDOSX=1 -w3 -c -g -O5
+ -I$(WATT_INC) -I. -I.\msdos\pm_drvr
+ -Hsuffix=.o32
+ -Hnocopyr
+ -Hpragma=Offwarn(491,553,572)
+ -Hon=Recognize_library # make memcpy/strlen etc. inline
+ -Hoff=Behaved # turn off some optimiser warnings
+| $<
+
+clean:
+ @del *.obj
+ @del *.o32
+ @del *.lst
+ @del *.map
+ @del bcc.arg
+ @del hc386.arg
+ @del grammar.c
+ @del tokdefs.h
+ @del scanner.c
+ @echo Cleaned
+
+#
+# dependencies
+#
+pkt_rx0.obj: msdos\pkt_rx0.asm
+
+bpf_filt.obj: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+
+bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h
+
+etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+ pf.h pcap-namedb.h
+
+scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+ pcap-namedb.h tokdefs.h
+
+gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+ ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \
+ arcnet.h pf.h pcap-namedb.h
+
+nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+ pcap-namedb.h ethertype.h
+
+pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \
+ msdos\pktdrvr.h
+
+pktdrvr.obj: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \
+ pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+ msdos\ndis2.h
+
+pkt_rx0.o32: msdos\pkt_rx0.asm
+
+bpf_filt.o32: bpf_filt.c pcap-int.h pcap.h pcap-bpf.h gnuc.h
+
+bpf_imag.o32: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+bpf_dump.o32: bpf_dump.c pcap.h pcap-bpf.h
+
+etherent.o32: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+optimize.o32: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+savefile.o32: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+pcap.o32: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+grammar.o32: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+ pf.h pcap-namedb.h
+
+scanner.o32: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+ pcap-namedb.h tokdefs.h
+
+gencode.o32: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+ ethertype.h nlpid.h llc.h gencode.h atmuni31.h sunatmpos.h ppp.h sll.h \
+ arcnet.h pf.h pcap-namedb.h
+
+nametoad.o32: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h \
+ pcap-namedb.h ethertype.h
+
+pcap-dos.o32: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h \
+ msdos\pktdrvr.h
+
+pktdrvr.o32: msdos\pktdrvr.c gnuc.h pcap-dos.h pcap-int.h \
+ pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+ndis2.o32: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h \
+ msdos\ndis2.h
+
diff --git a/lib/libpcap/libpcap/msdos/makefile.dj b/lib/libpcap/libpcap/msdos/makefile.dj
new file mode 100644
index 0000000..190db00
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/makefile.dj
@@ -0,0 +1,127 @@
+#
+# GNU Makefile for DOS-libpcap. djgpp version.
+#
+# Use this makefile from the libpcap root directory.
+# E.g. like this:
+#
+# c:\net\pcap> make -f msdos/makefile.dj
+#
+# Note: you should do a "set LFN=y" before running this makefile.
+#
+
+VPATH = missing msdos bpf/net
+
+PREREQUISITES = scanner.c grammar.c tokdefs.h version.h msdos/pkt_stub.inc
+
+include ./msdos/common.dj
+
+DRIVER_DIR = ./msdos/pm_drvr
+
+CFLAGS += -DDEBUG -DNDIS_DEBUG -DHAVE_LIMITS_H -DHAVE_STRERROR -DHAVE_SNPRINTF -DHAVE_VSNPRINTF\
+ -D_U_='__attribute__((unused))'
+
+CFLAGS += -Dyylval=pcap_lval # -DBDEBUG -DNDEBUG
+
+SOURCES = grammar.c scanner.c bpf/net/bpf_filter.c bpf_image.c bpf_dump.c \
+ etherent.c gencode.c nametoaddr.c pcap-common.c pcap-dos.c optimize.c \
+ savefile.c pcap.c sf-pcap.c sf-pcapng.c \
+ msdos/pktdrvr.c msdos/ndis2.c # missing/snprintf.c
+
+OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:.c=.o)))
+TEMPBIN = tmp.bin
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+ PM_OBJECTS = $(addprefix $(OBJ_DIR)/, \
+ printk.o pci.o pci-scan.o bios32.o dma.o irq.o intwrap.o \
+ lock.o kmalloc.o quirks.o timer.o net_init.o)
+ #
+ # Static link of drivers
+ #
+ ifeq ($(USE_32BIT_MODULES),0)
+ PM_OBJECTS += $(addprefix $(OBJ_DIR)/, \
+ accton.o 8390.o 3c503.o 3c509.o 3c59x.o 3c515.o \
+ 3c575_cb.o 3c90x.o ne.o wd.o cs89x0.o rtl8139.o)
+ endif
+endif
+
+TARGETS = msdos/bin2c.exe libpcap.a filtertest.exe findalldevstest.exe \
+ nonblocktest.exe opentest.exe
+
+all: $(TARGETS)
+ @echo 'Welcome to libpcap/djgpp with samples.'
+
+ifeq ($(USE_32BIT_DRIVERS),1)
+$(PM_OBJECTS):
+ $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) $(notdir $@)
+endif
+
+libpcap.a: version.h $(OBJECTS) $(PM_OBJECTS)
+ rm -f $@
+ ar rs $@ $^
+
+filtertest.exe: tests/filtertest.c libpcap.a
+ $(CC) $(CFLAGS) -Din_addr_t=u_long -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+ @echo
+
+findalldevstest.exe: tests/findalldevstest.c libpcap.a
+ $(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+ @echo
+
+nonblocktest.exe: tests/nonblocktest.c libpcap.a
+ $(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+ @echo
+
+opentest.exe: tests/opentest.c libpcap.a
+ $(CC) $(CFLAGS) -o $@ $^ $(WATT32_ROOT)/lib/libwatt.a
+ @echo
+
+msdos/pkt_stub.inc: msdos/bin2c.exe msdos/pkt_rx1.S
+ $(ASM) -o $(TEMPBIN) -lmsdos/pkt_rx1.lst msdos/pkt_rx1.S
+ ./msdos/bin2c $(TEMPBIN) > $@
+ rm -f $(TEMPBIN)
+
+grammar.c tokdefs.h: grammar.y
+ rm -f grammar.c tokdefs.h
+ $(YACC) --name-prefix=pcap_ --yacc --defines grammar.y
+ mv -f y.tab.c grammar.c
+ mv -f y.tab.h tokdefs.h
+
+version.h: ./VERSION
+ @echo '/* Generated from VERSION. Do not edit */' > $@
+ sed -e 's/.*/static char pcap_version_string[] = "libpcap (&)";/' ./VERSION >> $@
+
+scanner.c: scanner.l
+ $(LEX) -Ppcap_ -7 -t $^ > $@
+ @echo
+
+msdos/bin2c.exe: msdos/bin2c.c
+ $(CC) $*.c -o $*.exe
+
+clean:
+ rm -f $(OBJECTS) msdos/pkt_rx1.lst Makefile.bak .depend.dj $(PREREQUISITES)
+# $(MAKE) -f Makefile.dj -C $(DRIVER_DIR) clean
+
+vclean: clean
+ rm -f $(TARGETS)
+ -rmdir $(OBJ_DIR)
+
+#
+# Manually generated dependencies
+#
+msdos/pktdrvr.c: msdos/pkt_stub.inc
+scanner.c: scanner.l
+grammar.c tokdefs.h: grammar.y
+grammar.h: grammar.y
+scanner.l: pcap-int.h pcap-namedb.h gencode.h grammar.h
+grammar.y: pcap-int.h gencode.h pcap-namedb.h
+
+#
+# Generate dependencies.
+#
+REPLACE = sed -e 's/\(.*\)\.o: /\n$$(OBJ_DIR)\/\1.o: /'
+
+depend: $(PREREQUISITES)
+ $(CC) -MM $(CFLAGS) $(SOURCES) | $(REPLACE) > .depend.dj
+
+-include .depend.dj
+
diff --git a/lib/libpcap/libpcap/msdos/makefile.wc b/lib/libpcap/libpcap/msdos/makefile.wc
new file mode 100644
index 0000000..0246012
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/makefile.wc
@@ -0,0 +1,132 @@
+#
+# Watcom Makefile for dos-libpcap.
+#
+# Specify MODEL = `3r' or `3s'
+# Specify TARGET = `pharlap' or `dos4g'
+#
+# Use this makefile from the libpcap root directory.
+# E.g. like this:
+#
+# c:\net\pcap> wmake -f msdos\makefile.wc
+#
+
+MODEL = 3s
+TARGET = dos4g
+
+OBJDIR = msdos\$(TARGET).w$(MODEL)
+LIB = $(OBJDIR)\pcap.lib
+
+.EXTENSIONS: .l .y
+
+DEFS = -dDEBUG -dNDIS_DEBUG -d_U_= -dHAVE_LIMITS_H -dHAVE_STRERROR &
+ -dHAVE_SNPRINTF -dHAVE_VSNPRINTF
+
+CC = wcc386.exe
+ASM = wasm.exe -$(MODEL) $(DEFS) -dDOSX -dDOS4GW -zq -bt=dos -fr=nul -d3 -s
+
+OBJS = $(OBJDIR)\grammar.obj $(OBJDIR)\scanner.obj $(OBJDIR)\pcap.obj &
+ $(OBJDIR)\bpf_filter.obj $(OBJDIR)\bpf_imag.obj $(OBJDIR)\bpf_dump.obj &
+ $(OBJDIR)\etherent.obj $(OBJDIR)\gencode.obj $(OBJDIR)\nametoad.obj &
+ $(OBJDIR)\pcap-dos.obj $(OBJDIR)\pktdrvr.obj $(OBJDIR)\optimize.obj &
+ $(OBJDIR)\savefile.obj $(OBJDIR)\ndis2.obj
+
+CFLAGS = $(DEFS) $(YYDEFS) -I. -I$(%watt_root)\inc -I.\msdos\pm_drvr &
+ -$(MODEL) -mf -zff -zgf -zq -bt=dos -fr=nul -w6 -fpi &
+ -oilrtf -zm
+
+TEMPBIN = tmp.bin
+
+all: $(OBJDIR) $(OBJDIR)\pcap.lib
+
+$(OBJDIR):
+ - mkdir $(OBJDIR)
+
+$(OBJDIR)\pcap.lib: $(OBJS) wlib.arg
+ wlib -q -b -c $(OBJDIR)\pcap.lib @wlib.arg
+
+wlib.arg: msdos\makefile.wc
+ %create $^@
+ for %f in ($(OBJS)) do %append $^@ +- %f
+
+$(OBJDIR)\pktdrvr.obj: msdos\pkt_stub.inc msdos\pktdrvr.c &
+ pcap-dos.h pcap-int.h pcap.h msdos\pktdrvr.h
+ *$(CC) $(CFLAGS) msdos\pktdrvr.c -fo=$@
+
+$(OBJDIR)\bpf_filter.obj: bpf\net\bpf_filter.c
+ *$(CC) $(CFLAGS) bpf\net\bpf_filter.c -fo=$@
+
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c
+ *$(CC) $(CFLAGS) msdos\ndis2.c -fo=$@
+
+.ERASE
+.c{$(OBJDIR)}.obj:
+ *$(CC) $(CFLAGS) $[@ -fo=$@
+
+grammar.c tokdefs.h: grammar.y
+ bison --name-prefix=pcap_ --yacc --defines $[@
+ - @del grammar.c
+ - @del tokdefs.h
+ ren y_tab.c grammar.c
+ ren y_tab.h tokdefs.h
+
+scanner.c: scanner.l
+ flex -Ppcap_ -7 -o$@ $[@
+
+msdos\pkt_stub.inc: bin2c.exe msdos\pkt_rx1.S
+ nasm -fbin -dDEBUG -o $(TEMPBIN) -lmsdos\pkt_rx1.lst msdos\pkt_rx1.S
+ bin2c.exe $(TEMPBIN) > $@
+ @del $(TEMPBIN)
+
+bin2c.exe: msdos\bin2c.c
+ wcl $[@
+
+clean realclean vclean: .SYMBOLIC
+ for %f in (dos4g.w3r dos4g.w3s pharlap.w3r pharlap.w3s) do &
+ @del %f\*.obj
+ @del grammar.c
+ @del tokdefs.h
+ @del scanner.c
+ @del bin2c.exe
+ @del bin2c.obj
+ @del msdos\pkt_stub.inc
+ @echo Cleaned
+
+#
+# dependencies
+#
+$(OBJDIR)\bpf_filter.obj: bpf\net\bpf_filter.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\bpf_imag.obj: bpf_imag.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\bpf_dump.obj: bpf_dump.c pcap.h pcap-bpf.h
+
+$(OBJDIR)\etherent.obj: etherent.c pcap-int.h pcap.h pcap-bpf.h pcap-namedb.h
+
+$(OBJDIR)\optimize.obj: optimize.c pcap-int.h pcap.h pcap-bpf.h gencode.h
+
+$(OBJDIR)\savefile.obj: savefile.c pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\pcap.obj: pcap.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h
+
+$(OBJDIR)\grammar.obj: grammar.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+ pcap-namedb.h
+
+$(OBJDIR)\scanner.obj: scanner.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+ pcap-namedb.h tokdefs.h
+
+$(OBJDIR)\gencode.obj: gencode.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &
+ ethertyp.h nlpid.h llc.h gencode.h atmuni31.h sunatmpo.h ppp.h sll.h &
+ arcnet.h pcap-namedb.h
+
+$(OBJDIR)\nametoad.obj: nametoad.c pcap-int.h pcap.h pcap-bpf.h gencode.h &
+ pcap-namedb.h ethertyp.h
+
+$(OBJDIR)\pcap-dos.obj: pcap-dos.c pcap.h pcap-bpf.h pcap-dos.h pcap-int.h &
+ msdos\pktdrvr.h
+
+$(OBJDIR)\pktdrvr.obj: msdos\pktdrvr.c pcap-dos.h pcap-int.h &
+ pcap.h pcap-bpf.h msdos\pktdrvr.h msdos\pkt_stub.inc
+
+$(OBJDIR)\ndis2.obj: msdos\ndis2.c pcap-dos.h pcap-int.h pcap.h pcap-bpf.h &
+ msdos\ndis2.h
+
diff --git a/lib/libpcap/libpcap/msdos/ndis2.c b/lib/libpcap/libpcap/msdos/ndis2.c
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/ndis2.c
diff --git a/lib/libpcap/libpcap/msdos/ndis2.h b/lib/libpcap/libpcap/msdos/ndis2.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/ndis2.h
diff --git a/lib/libpcap/libpcap/msdos/ndis_0.asm b/lib/libpcap/libpcap/msdos/ndis_0.asm
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/ndis_0.asm
diff --git a/lib/libpcap/libpcap/msdos/pkt_rx0.asm b/lib/libpcap/libpcap/msdos/pkt_rx0.asm
new file mode 100644
index 0000000..d604fa1
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/pkt_rx0.asm
@@ -0,0 +1,197 @@
+PAGE 60,132
+NAME PKT_RX
+
+ifdef ??version ; using TASM
+ masm
+ jumps
+endif
+
+PUBLIC _pktDrop, _pktRxBuf, _pktTxBuf, _pktTemp
+PUBLIC _rxOutOfs, _rxInOfs, _PktReceiver, _pktRxEnd
+
+;
+; these sizes MUST be equal to the sizes in PKTDRVR.H
+;
+
+RX_BUF_SIZE = 1500 ; max message size on Ethernet
+TX_BUF_SIZE = 1500
+
+ifdef DOSX
+ .386
+ NUM_RX_BUF = 32 ; # of RX element buffers
+ _TEXT SEGMENT PUBLIC DWORD USE16 'CODE'
+ _TEXT ENDS
+ _DATA SEGMENT PUBLIC DWORD USE16 'CODE'
+ _DATA ENDS
+ D_SEG EQU <_TEXT SEGMENT>
+ D_END EQU <_TEXT ENDS>
+ ASSUME CS:_TEXT,DS:_TEXT
+else
+ .286
+ NUM_RX_BUF = 10
+ _TEXT SEGMENT PUBLIC DWORD 'CODE'
+ _TEXT ENDS
+ _DATA SEGMENT PUBLIC DWORD 'DATA'
+ _DATA ENDS
+ D_SEG EQU <_DATA SEGMENT>
+ D_END EQU <_DATA ENDS>
+ ASSUME CS:_TEXT,DS:_DATA
+endif
+
+;-------------------------------------------
+
+D_SEG
+
+RX_ELEMENT STRUC
+ firstCount dw 0 ; # of bytes on 1st call
+ secondCount dw 0 ; # of bytes on 2nd call
+ handle dw 0 ; handle for upcall
+ destinAdr db 6 dup (0) ; packet destination address
+ sourceAdr db 6 dup (0) ; packet source address
+ protocol dw 0 ; packet protocol number
+ rxBuffer db RX_BUF_SIZE dup (0) ; RX buffer
+ENDS
+ align 4
+_rxOutOfs dw offset _pktRxBuf ; ring buffer offsets
+_rxInOfs dw offset _pktRxBuf ; into _pktRxBuf
+_pktDrop dw 0,0 ; packet drop counter
+_pktTemp db 20 dup (0) ; temp work area
+_pktTxBuf db (TX_BUF_SIZE+14) dup (0) ; TX buffer
+_pktRxBuf RX_ELEMENT NUM_RX_BUF dup (<>) ; RX structures
+ LAST_OFS = offset $
+
+ screenSeg dw 0B800h
+ newInOffset dw 0
+
+ fanChars db '-\|/'
+ fanIndex dw 0
+
+D_END
+
+_TEXT SEGMENT
+
+
+SHOW_RX MACRO
+ push es
+ push bx
+ mov bx, screenSeg
+ mov es, bx ;; r-mode segment of colour screen
+ mov di, 158 ;; upper right corner - 1
+ mov bx, fanIndex
+ mov al, fanChars[bx] ;; get write char
+ mov ah, 15 ;; and white colour
+ stosw ;; write to screen at ES:EDI
+ inc fanIndex ;; update next index
+ and fanIndex, 3
+ pop bx
+ pop es
+ENDM
+
+;------------------------------------------------------------------------
+;
+; This macro return ES:DI to tail of Rx queue
+
+ENQUEUE MACRO
+ LOCAL @noWrap
+ mov ax, _rxInOfs ;; DI = current in-offset
+ add ax, SIZE RX_ELEMENT ;; point to next _pktRxBuf buffer
+ cmp ax, LAST_OFS ;; pointing past last ?
+ jb @noWrap ;; no - jump
+ lea ax, _pktRxBuf ;; yes, point to 1st buffer
+ align 4
+@noWrap: cmp ax, _rxOutOfs ;; in-ofs = out-ofs ?
+ je @dump ;; yes, queue is full
+ mov di, _rxInOfs ;; ES:DI -> buffer at queue input
+ mov newInOffset, ax ;; remember new input offset
+
+ ;; NOTE. rxInOfs is updated after the packet has been copied
+ ;; to ES:DI (= DS:SI on 2nd call) by the packet driver
+
+ENDM
+
+;------------------------------------------------------------------------
+;
+; This routine gets called by the packet driver twice:
+; 1st time (AX=0) it requests an address where to put the packet
+;
+; 2nd time (AX=1) the packet has been copied to this location (DS:SI)
+; BX has client handle (stored in RX_ELEMENT.handle).
+; CX has # of bytes in packet on both call. They should be equal.
+;
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount
+; and _pktRxBuf[n].secondCount, and CL on first call in
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"
+; (PKTDRVR.C)
+;
+;---------------------------------------------------------------------
+
+_PktReceiver:
+ pushf
+ cli ; no distraction wanted !
+ push ds
+ push bx
+ifdef DOSX
+ mov bx, cs
+else
+ mov bx, SEG _DATA
+endif
+ mov ds, bx
+ mov es, bx ; ES = DS = CS or seg _DATA
+ pop bx ; restore handle
+
+ cmp ax, 0 ; first call? (AX=0)
+ jne @post ; AX=1: second call, do post process
+
+ifdef DEBUG
+ SHOW_RX ; show that a packet is received
+endif
+ cmp cx, RX_BUF_SIZE+14 ; size OK ?
+ ja @skip ; no, packet to large for us
+
+ ENQUEUE ; ES:DI -> _pktRxBuf[n]
+
+ mov [di].firstCount, cx ; remember the first count.
+ mov [di].handle, bx ; remember the handle.
+ add di, 6 ; ES:DI -> _pktRxBuf[n].destinAdr
+ pop ds
+ popf
+ retf ; far return to driver with ES:DI
+
+ align 4
+@dump: inc _pktDrop[0] ; discard the packet on 1st call
+ adc _pktDrop[2], 0 ; increment packets lost
+
+@skip: xor di, di ; return ES:DI = NIL pointer
+ xor ax, ax
+ mov es, ax
+ pop ds
+ popf
+ retf
+
+ align 4
+@post: or si, si ; DS:SI->_pktRxBuf[n][n].destinAdr
+ jz @discard ; make sure we don't use NULL-pointer
+
+ sub si, 6 ; DS:SI -> _pktRxBuf[n].destinAdr
+ ;
+ ; push si
+ ; push [si].firstCount
+ ; call bpf_filter_match ; run the filter here some day?
+ ; add sp, 4
+ ; cmp ax, 0
+ ; je @discard
+
+ mov [si].secondCount, cx
+ mov ax, newInOffset
+ mov _rxInOfs, ax ; update _pktRxBuf input offset
+
+ align 4
+@discard:pop ds
+ popf
+ retf
+
+_pktRxEnd db 0 ; marker for end of r-mode code/data
+
+_TEXT ENDS
+
+END
diff --git a/lib/libpcap/libpcap/msdos/pkt_rx1.s b/lib/libpcap/libpcap/msdos/pkt_rx1.s
new file mode 100644
index 0000000..654e657
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/pkt_rx1.s
@@ -0,0 +1,155 @@
+;
+; This file requires NASM 0.97+ to assemble
+;
+; Currently used only for djgpp + DOS4GW targets
+;
+; these sizes MUST be equal to the sizes in PKTDRVR.H
+;
+%define ETH_MTU 1500 ; max data size on Ethernet
+%define ETH_MIN 60 ; min/max total frame size
+%define ETH_MAX (ETH_MTU+2*6+2) ; =1514
+%define NUM_RX_BUF 32 ; # of RX element buffers
+%define RX_SIZE (ETH_MAX+6) ; sizeof(RX_ELEMENT) = 1514+6
+%idefine offset
+
+struc RX_ELEMENT
+ .firstCount resw 1 ; # of bytes on 1st call
+ .secondCount resw 1 ; # of bytes on 2nd call
+ .handle resw 1 ; handle for upcall
+ ; .timeStamp resw 4 ; 64-bit RDTSC value
+ .destinAdr resb 6 ; packet destination address
+ .sourceAdr resb 6 ; packet source address
+ .protocol resw 1 ; packet protocol number
+ .rxBuffer resb ETH_MTU ; RX buffer
+endstruc
+
+;-------------------------------------------
+
+[org 0] ; assemble to .bin file
+
+_rxOutOfs dw offset _pktRxBuf ; ring buffer offsets
+_rxInOfs dw offset _pktRxBuf ; into _pktRxBuf
+_pktDrop dw 0,0 ; packet drop counter
+_pktTemp resb 20 ; temp work area
+_pktTxBuf resb (ETH_MAX) ; TX buffer
+_pktRxBuf resb (RX_SIZE*NUM_RX_BUF) ; RX structures
+ LAST_OFS equ $
+
+screenSeg dw 0B800h
+newInOffset dw 0
+
+fanChars db '-\|/'
+fanIndex dw 0
+
+%macro SHOW_RX 0
+ push es
+ push bx
+ mov bx, [screenSeg]
+ mov es, bx ;; r-mode segment of colour screen
+ mov di, 158 ;; upper right corner - 1
+ mov bx, [fanIndex]
+ mov al, [fanChars+bx] ;; get write char
+ mov ah, 15 ;; and white colour
+ cld ;; Needed?
+ stosw ;; write to screen at ES:EDI
+ inc word [fanIndex] ;; update next index
+ and word [fanIndex], 3
+ pop bx
+ pop es
+%endmacro
+
+;PutTimeStamp
+; rdtsc
+; mov [si].timeStamp, eax
+; mov [si+4].timeStamp, edx
+; ret
+
+
+;------------------------------------------------------------------------
+;
+; This routine gets called by the packet driver twice:
+; 1st time (AX=0) it requests an address where to put the packet
+;
+; 2nd time (AX=1) the packet has been copied to this location (DS:SI)
+; BX has client handle (stored in RX_ELEMENT.handle).
+; CX has # of bytes in packet on both call. They should be equal.
+; A test for equality is done by putting CX in _pktRxBuf [n].firstCount
+; and _pktRxBuf[n].secondCount, and CL on first call in
+; _pktRxBuf[n].rxBuffer[CX]. These values are checked in "PktReceive"
+; (PKTDRVR.C)
+;
+;---------------------------------------------------------------------
+
+_PktReceiver:
+ pushf
+ cli ; no distraction wanted !
+ push ds
+ push bx
+ mov bx, cs
+ mov ds, bx
+ mov es, bx ; ES = DS = CS or seg _DATA
+ pop bx ; restore handle
+
+ cmp ax, 0 ; first call? (AX=0)
+ jne @post ; AX=1: second call, do post process
+
+%ifdef DEBUG
+ SHOW_RX ; show that a packet is received
+%endif
+
+ cmp cx, ETH_MAX ; size OK ?
+ ja @skip ; no, too big
+
+ mov ax, [_rxInOfs]
+ add ax, RX_SIZE
+ cmp ax, LAST_OFS
+ jb @noWrap
+ mov ax, offset _pktRxBuf
+@noWrap:
+ cmp ax, [_rxOutOfs]
+ je @dump
+ mov di, [_rxInOfs] ; ES:DI -> _pktRxBuf[n]
+ mov [newInOffset], ax
+
+ mov [di], cx ; remember firstCount.
+ mov [di+4], bx ; remember handle.
+ add di, 6 ; ES:DI -> _pktRxBuf[n].destinAdr
+ pop ds
+ popf
+ retf ; far return to driver with ES:DI
+
+@dump: add word [_pktDrop+0], 1 ; discard the packet on 1st call
+ adc word [_pktDrop+2], 0 ; increment packets lost
+
+@skip: xor di, di ; return ES:DI = NIL pointer
+ xor ax, ax
+ mov es, ax
+ pop ds
+ popf
+ retf
+
+@post: or si, si ; DS:SI->_pktRxBuf[n][n].destinAdr
+ jz @discard ; make sure we don't use NULL-pointer
+
+ ;
+ ; push si
+ ; call bpf_filter_match ; run the filter here some day
+ ; pop si
+ ; cmp ax, 0
+ ; je @discard
+
+ mov [si-6+2], cx ; store _pktRxBuf[n].secondCount
+ mov ax, [newInOffset]
+ mov [_rxInOfs], ax ; update _pktRxBuf input offset
+
+ ; call PutTimeStamp
+
+@discard:
+ pop ds
+ popf
+ retf
+
+_pktRxEnd db 0 ; marker for end of r-mode code/data
+
+END
+
diff --git a/lib/libpcap/libpcap/msdos/pktdrvr.c b/lib/libpcap/libpcap/msdos/pktdrvr.c
new file mode 100644
index 0000000..37fc8a4
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/pktdrvr.c
@@ -0,0 +1,1436 @@
+/*
+ * File.........: pktdrvr.c
+ *
+ * Responsible..: Gisle Vanem, giva@bgnett.no
+ *
+ * Created......: 26.Sept 1995
+ *
+ * Description..: Packet-driver interface for 16/32-bit C :
+ * Borland C/C++ 3.0+ small/large model
+ * Watcom C/C++ 11+, DOS4GW flat model
+ * Metaware HighC 3.1+ and PharLap 386|DosX
+ * GNU C/C++ 2.7+ and djgpp 2.x extender
+ *
+ * References...: PC/TCP Packet driver Specification. rev 1.09
+ * FTP Software Inc.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dos.h>
+
+#include "pcap-dos.h"
+#include "pcap-int.h"
+#include "msdos/pktdrvr.h"
+
+#if (DOSX)
+#define NUM_RX_BUF 32 /* # of buffers in Rx FIFO queue */
+#else
+#define NUM_RX_BUF 10
+#endif
+
+#define DIM(x) (sizeof((x)) / sizeof(x[0]))
+#define PUTS(s) do { \
+ if (!pktInfo.quiet) \
+ pktInfo.error ? \
+ printf ("%s: %s\n", s, pktInfo.error) : \
+ printf ("%s\n", pktInfo.error = s); \
+ } while (0)
+
+#if defined(__HIGHC__)
+ extern UINT _mwenv;
+
+#elif defined(__DJGPP__)
+ #include <stddef.h>
+ #include <dpmi.h>
+ #include <go32.h>
+ #include <pc.h>
+ #include <sys/farptr.h>
+
+#elif defined(__WATCOMC__)
+ #include <i86.h>
+ #include <stddef.h>
+ extern char _Extender;
+
+#else
+ extern void far PktReceiver (void);
+#endif
+
+
+#if (DOSX & (DJGPP|DOS4GW))
+ #include <sys/pack_on.h>
+
+ struct DPMI_regs {
+ DWORD r_di;
+ DWORD r_si;
+ DWORD r_bp;
+ DWORD reserved;
+ DWORD r_bx;
+ DWORD r_dx;
+ DWORD r_cx;
+ DWORD r_ax;
+ WORD r_flags;
+ WORD r_es, r_ds, r_fs, r_gs;
+ WORD r_ip, r_cs, r_sp, r_ss;
+ };
+
+ /* Data located in a real-mode segment. This becomes far at runtime
+ */
+ typedef struct { /* must match data/code in pkt_rx1.s */
+ WORD _rxOutOfs;
+ WORD _rxInOfs;
+ DWORD _pktDrop;
+ BYTE _pktTemp [20];
+ TX_ELEMENT _pktTxBuf[1];
+ RX_ELEMENT _pktRxBuf[NUM_RX_BUF];
+ WORD _dummy[2]; /* screenSeg,newInOffset */
+ BYTE _fanChars[4];
+ WORD _fanIndex;
+ BYTE _PktReceiver[15]; /* starts on a paragraph (16byte) */
+ } PktRealStub;
+ #include <sys/pack_off.h>
+
+ static BYTE real_stub_array [] = {
+ #include "pkt_stub.inc" /* generated opcode array */
+ };
+
+ #define rxOutOfs offsetof (PktRealStub,_rxOutOfs)
+ #define rxInOfs offsetof (PktRealStub,_rxInOfs)
+ #define PktReceiver offsetof (PktRealStub,_PktReceiver [para_skip])
+ #define pktDrop offsetof (PktRealStub,_pktDrop)
+ #define pktTemp offsetof (PktRealStub,_pktTemp)
+ #define pktTxBuf offsetof (PktRealStub,_pktTxBuf)
+ #define FIRST_RX_BUF offsetof (PktRealStub,_pktRxBuf [0])
+ #define LAST_RX_BUF offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])
+
+#else
+ extern WORD rxOutOfs; /* offsets into pktRxBuf FIFO queue */
+ extern WORD rxInOfs;
+ extern DWORD pktDrop; /* # packets dropped in PktReceiver() */
+ extern BYTE pktRxEnd; /* marks the end of r-mode code/data */
+
+ extern RX_ELEMENT pktRxBuf [NUM_RX_BUF]; /* PktDrvr Rx buffers */
+ extern TX_ELEMENT pktTxBuf; /* PktDrvr Tx buffer */
+ extern char pktTemp[20]; /* PktDrvr temp area */
+
+ #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
+ #define LAST_RX_BUF (WORD) &pktRxBuf [NUM_RX_BUF-1]
+#endif
+
+
+#ifdef __BORLANDC__ /* Use Borland's inline functions */
+ #define memcpy __memcpy__
+ #define memcmp __memcmp__
+ #define memset __memset__
+#endif
+
+
+#if (DOSX & PHARLAP)
+ extern void PktReceiver (void); /* in pkt_rx0.asm */
+ static int RealCopy (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);
+
+ #undef FP_SEG
+ #undef FP_OFF
+ #define FP_OFF(x) ((WORD)(x))
+ #define FP_SEG(x) ((WORD)(realBase >> 16))
+ #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))
+ #define r_ax eax
+ #define r_bx ebx
+ #define r_dx edx
+ #define r_cx ecx
+ #define r_si esi
+ #define r_di edi
+ #define r_ds ds
+ #define r_es es
+ LOCAL FARPTR protBase;
+ LOCAL REALPTR realBase;
+ LOCAL WORD realSeg; /* DOS para-address of allocated area */
+ LOCAL SWI_REGS reg;
+
+ static WORD _far *rxOutOfsFp, *rxInOfsFp;
+
+#elif (DOSX & DJGPP)
+ static _go32_dpmi_seginfo rm_mem;
+ static __dpmi_regs reg;
+ static DWORD realBase;
+ static int para_skip = 0;
+
+ #define DOS_ADDR(s,o) (((WORD)(s) << 4) + (o))
+ #define r_ax x.ax
+ #define r_bx x.bx
+ #define r_dx x.dx
+ #define r_cx x.cx
+ #define r_si x.si
+ #define r_di x.di
+ #define r_ds x.ds
+ #define r_es x.es
+
+#elif (DOSX & DOS4GW)
+ LOCAL struct DPMI_regs reg;
+ LOCAL WORD rm_base_seg, rm_base_sel;
+ LOCAL DWORD realBase;
+ LOCAL int para_skip = 0;
+
+ LOCAL DWORD dpmi_get_real_vector (int intr);
+ LOCAL WORD dpmi_real_malloc (int size, WORD *selector);
+ LOCAL void dpmi_real_free (WORD selector);
+ #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))
+
+#else /* real-mode Borland etc. */
+ static struct {
+ WORD r_ax, r_bx, r_cx, r_dx, r_bp;
+ WORD r_si, r_di, r_ds, r_es, r_flags;
+ } reg;
+#endif
+
+#ifdef __HIGHC__
+ #pragma Alias (pktDrop, "_pktDrop")
+ #pragma Alias (pktRxBuf, "_pktRxBuf")
+ #pragma Alias (pktTxBuf, "_pktTxBuf")
+ #pragma Alias (pktTemp, "_pktTemp")
+ #pragma Alias (rxOutOfs, "_rxOutOfs")
+ #pragma Alias (rxInOfs, "_rxInOfs")
+ #pragma Alias (pktRxEnd, "_pktRxEnd")
+ #pragma Alias (PktReceiver,"_PktReceiver")
+#endif
+
+
+PUBLIC PKT_STAT pktStat; /* statistics for packets */
+PUBLIC PKT_INFO pktInfo; /* packet-driver information */
+
+PUBLIC PKT_RX_MODE receiveMode = PDRX_DIRECT;
+PUBLIC ETHER myAddress = { 0, 0, 0, 0, 0, 0 };
+PUBLIC ETHER ethBroadcast = { 255,255,255,255,255,255 };
+
+LOCAL struct { /* internal statistics */
+ DWORD tooSmall; /* size < ETH_MIN */
+ DWORD tooLarge; /* size > ETH_MAX */
+ DWORD badSync; /* count_1 != count_2 */
+ DWORD wrongHandle; /* upcall to wrong handle */
+ } intStat;
+
+/***************************************************************************/
+
+PUBLIC const char *PktGetErrorStr (int errNum)
+{
+ static const char *errStr[] = {
+ "",
+ "Invalid handle number",
+ "No interfaces of specified class found",
+ "No interfaces of specified type found",
+ "No interfaces of specified number found",
+ "Bad packet type specified",
+ "Interface does not support multicast",
+ "Packet driver cannot terminate",
+ "Invalid receiver mode specified",
+ "Insufficient memory space",
+ "Type previously accessed, and not released",
+ "Command out of range, or not implemented",
+ "Cannot send packet (usually hardware error)",
+ "Cannot change hardware address ( > 1 handle open)",
+ "Hardware address has bad length or format",
+ "Cannot reset interface (more than 1 handle open)",
+ "Bad Check-sum",
+ "Bad size",
+ "Bad sync" ,
+ "Source hit"
+ };
+
+ if (errNum < 0 || errNum >= DIM(errStr))
+ return ("Unknown driver error.");
+ return (errStr [errNum]);
+}
+
+/**************************************************************************/
+
+PUBLIC const char *PktGetClassName (WORD class)
+{
+ switch (class)
+ {
+ case PD_ETHER:
+ return ("DIX-Ether");
+ case PD_PRONET10:
+ return ("ProNET-10");
+ case PD_IEEE8025:
+ return ("IEEE 802.5");
+ case PD_OMNINET:
+ return ("OmniNet");
+ case PD_APPLETALK:
+ return ("AppleTalk");
+ case PD_SLIP:
+ return ("SLIP");
+ case PD_STARTLAN:
+ return ("StartLAN");
+ case PD_ARCNET:
+ return ("ArcNet");
+ case PD_AX25:
+ return ("AX.25");
+ case PD_KISS:
+ return ("KISS");
+ case PD_IEEE8023_2:
+ return ("IEEE 802.3 w/802.2 hdr");
+ case PD_FDDI8022:
+ return ("FDDI w/802.2 hdr");
+ case PD_X25:
+ return ("X.25");
+ case PD_LANstar:
+ return ("LANstar");
+ case PD_PPP:
+ return ("PPP");
+ default:
+ return ("unknown");
+ }
+}
+
+/**************************************************************************/
+
+PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)
+{
+ static const char *modeStr [] = {
+ "Receiver turned off",
+ "Receive only directly addressed packets",
+ "Receive direct & broadcast packets",
+ "Receive direct,broadcast and limited multicast packets",
+ "Receive direct,broadcast and all multicast packets",
+ "Receive all packets (promiscuouos mode)"
+ };
+
+ if (mode > DIM(modeStr))
+ return ("??");
+ return (modeStr [mode-1]);
+}
+
+/**************************************************************************/
+
+LOCAL __inline BOOL PktInterrupt (void)
+{
+ BOOL okay;
+
+#if (DOSX & PHARLAP)
+ _dx_real_int ((UINT)pktInfo.intr, &reg);
+ okay = ((reg.flags & 1) == 0); /* OK if carry clear */
+
+#elif (DOSX & DJGPP)
+ __dpmi_int ((int)pktInfo.intr, &reg);
+ okay = ((reg.x.flags & 1) == 0);
+
+#elif (DOSX & DOS4GW)
+ union REGS r;
+ struct SREGS s;
+
+ memset (&r, 0, sizeof(r));
+ segread (&s);
+ r.w.ax = 0x300;
+ r.x.ebx = pktInfo.intr;
+ r.w.cx = 0;
+ s.es = FP_SEG (&reg);
+ r.x.edi = FP_OFF (&reg);
+ reg.r_flags = 0;
+ reg.r_ss = reg.r_sp = 0; /* DPMI host provides stack */
+
+ int386x (0x31, &r, &r, &s);
+ okay = (!r.w.cflag);
+
+#else
+ reg.r_flags = 0;
+ intr (pktInfo.intr, (struct REGPACK*)&reg);
+ okay = ((reg.r_flags & 1) == 0);
+#endif
+
+ if (okay)
+ pktInfo.error = NULL;
+ else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);
+ return (okay);
+}
+
+/**************************************************************************/
+
+/*
+ * Search for packet driver at interrupt 60h through 80h. If ASCIIZ
+ * string "PKT DRVR" found at offset 3 in the interrupt handler, return
+ * interrupt number, else return zero in pktInfo.intr
+ */
+PUBLIC BOOL PktSearchDriver (void)
+{
+ BYTE intr = 0x20;
+ BOOL found = FALSE;
+
+ while (!found && intr < 0xFF)
+ {
+ static char str[12]; /* 3 + strlen("PKT DRVR") */
+ static char pktStr[9] = "PKT DRVR"; /* ASCIIZ string at ofs 3 */
+ DWORD rp; /* in interrupt routine */
+
+#if (DOSX & PHARLAP)
+ _dx_rmiv_get (intr, &rp);
+ ReadRealMem (&str, (REALPTR)rp, sizeof(str));
+
+#elif (DOSX & DJGPP)
+ __dpmi_raddr realAdr;
+ __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);
+ rp = (realAdr.segment << 4) + realAdr.offset16;
+ dosmemget (rp, sizeof(str), &str);
+
+#elif (DOSX & DOS4GW)
+ rp = dpmi_get_real_vector (intr);
+ memcpy (&str, (void*)rp, sizeof(str));
+
+#else
+ _fmemcpy (&str, getvect(intr), sizeof(str));
+#endif
+
+ found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;
+ intr++;
+ }
+ pktInfo.intr = (found ? intr-1 : 0);
+ return (found);
+}
+
+
+/**************************************************************************/
+
+static BOOL PktSetAccess (void)
+{
+ reg.r_ax = 0x0200 + pktInfo.class;
+ reg.r_bx = 0xFFFF;
+ reg.r_dx = 0;
+ reg.r_cx = 0;
+
+#if (DOSX & PHARLAP)
+ reg.ds = 0;
+ reg.esi = 0;
+ reg.es = RP_SEG (realBase);
+ reg.edi = (WORD) &PktReceiver;
+
+#elif (DOSX & DJGPP)
+ reg.x.ds = 0;
+ reg.x.si = 0;
+ reg.x.es = rm_mem.rm_segment;
+ reg.x.di = PktReceiver;
+
+#elif (DOSX & DOS4GW)
+ reg.r_ds = 0;
+ reg.r_si = 0;
+ reg.r_es = rm_base_seg;
+ reg.r_di = PktReceiver;
+
+#else
+ reg.r_ds = 0;
+ reg.r_si = 0;
+ reg.r_es = FP_SEG (&PktReceiver);
+ reg.r_di = FP_OFF (&PktReceiver);
+#endif
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ pktInfo.handle = reg.r_ax;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktReleaseHandle (WORD handle)
+{
+ reg.r_ax = 0x0300;
+ reg.r_bx = handle;
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTransmit (const void *eth, int len)
+{
+ if (len > ETH_MTU)
+ return (FALSE);
+
+ reg.r_ax = 0x0400; /* Function 4, send pkt */
+ reg.r_cx = len; /* total size of frame */
+
+#if (DOSX & DJGPP)
+ dosmemput (eth, len, realBase+pktTxBuf);
+ reg.x.ds = rm_mem.rm_segment; /* DOS data segment and */
+ reg.x.si = pktTxBuf; /* DOS offset to buffer */
+
+#elif (DOSX & DOS4GW)
+ memcpy ((void*)(realBase+pktTxBuf), eth, len);
+ reg.r_ds = rm_base_seg;
+ reg.r_si = pktTxBuf;
+
+#elif (DOSX & PHARLAP)
+ memcpy (&pktTxBuf, eth, len);
+ reg.r_ds = FP_SEG (&pktTxBuf);
+ reg.r_si = FP_OFF (&pktTxBuf);
+
+#else
+ reg.r_ds = FP_SEG (eth);
+ reg.r_si = FP_OFF (eth);
+#endif
+
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+#if (DOSX & (DJGPP|DOS4GW))
+LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)
+#else
+LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)
+#endif
+{
+ WORD count_1, count_2;
+
+ /*
+ * We got an upcall to the same RMCB with wrong handle.
+ * This can happen if we failed to release handle at program exit
+ */
+ if (rx->handle != pktInfo.handle)
+ {
+ pktInfo.error = "Wrong handle";
+ intStat.wrongHandle++;
+ PktReleaseHandle (rx->handle);
+ return (FALSE);
+ }
+ count_1 = rx->firstCount;
+ count_2 = rx->secondCount;
+
+ if (count_1 != count_2)
+ {
+ pktInfo.error = "Bad sync";
+ intStat.badSync++;
+ return (FALSE);
+ }
+ if (count_1 > ETH_MAX)
+ {
+ pktInfo.error = "Large esize";
+ intStat.tooLarge++;
+ return (FALSE);
+ }
+#if 0
+ if (count_1 < ETH_MIN)
+ {
+ pktInfo.error = "Small esize";
+ intStat.tooSmall++;
+ return (FALSE);
+ }
+#endif
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTerminHandle (WORD handle)
+{
+ reg.r_ax = 0x0500;
+ reg.r_bx = handle;
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetInterface (WORD handle)
+{
+ reg.r_ax = 0x0700;
+ reg.r_bx = handle;
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)
+{
+ if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)
+ return (TRUE);
+
+ reg.r_ax = 0x1400;
+ reg.r_bx = pktInfo.handle;
+ reg.r_cx = (WORD)mode;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ receiveMode = mode;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)
+{
+ reg.r_ax = 0x1500;
+ reg.r_bx = pktInfo.handle;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ *mode = reg.r_ax;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+static PKT_STAT initialStat; /* statistics at startup */
+static BOOL resetStat = FALSE; /* statistics reset ? */
+
+PUBLIC BOOL PktGetStatistics (WORD handle)
+{
+ reg.r_ax = 0x1800;
+ reg.r_bx = handle;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));
+
+#elif (DOSX & DJGPP)
+ dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);
+
+#elif (DOSX & DOS4GW)
+ memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));
+
+#else
+ _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));
+#endif
+
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSessStatistics (WORD handle)
+{
+ if (!PktGetStatistics(pktInfo.handle))
+ return (FALSE);
+
+ if (resetStat)
+ {
+ pktStat.inPackets -= initialStat.inPackets;
+ pktStat.outPackets -= initialStat.outPackets;
+ pktStat.inBytes -= initialStat.inBytes;
+ pktStat.outBytes -= initialStat.outBytes;
+ pktStat.inErrors -= initialStat.inErrors;
+ pktStat.outErrors -= initialStat.outErrors;
+ pktStat.outErrors -= initialStat.outErrors;
+ pktStat.lost -= initialStat.lost;
+ }
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetStatistics (WORD handle)
+{
+ if (!PktGetStatistics(pktInfo.handle))
+ return (FALSE);
+
+ memcpy (&initialStat, &pktStat, sizeof(initialStat));
+ resetStat = TRUE;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetAddress (ETHER *addr)
+{
+ reg.r_ax = 0x0600;
+ reg.r_bx = pktInfo.handle;
+ reg.r_cx = sizeof (*addr);
+
+#if (DOSX & DJGPP)
+ reg.x.es = rm_mem.rm_segment;
+ reg.x.di = pktTemp;
+#elif (DOSX & DOS4GW)
+ reg.r_es = rm_base_seg;
+ reg.r_di = pktTemp;
+#else
+ reg.r_es = FP_SEG (&pktTemp);
+ reg.r_di = FP_OFF (&pktTemp); /* ES:DI = address for result */
+#endif
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+ dosmemget (realBase+pktTemp, sizeof(*addr), addr);
+
+#elif (DOSX & DOS4GW)
+ memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));
+
+#else
+ memcpy ((void*)addr, &pktTemp, sizeof(*addr));
+#endif
+
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetAddress (const ETHER *addr)
+{
+ /* copy addr to real-mode scrath area */
+
+#if (DOSX & PHARLAP)
+ WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+ dosmemput (addr, sizeof(*addr), realBase+pktTemp);
+
+#elif (DOSX & DOS4GW)
+ memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));
+
+#else
+ memcpy (&pktTemp, (void*)addr, sizeof(*addr));
+#endif
+
+ reg.r_ax = 0x1900;
+ reg.r_cx = sizeof (*addr); /* address length */
+
+#if (DOSX & DJGPP)
+ reg.x.es = rm_mem.rm_segment; /* DOS offset to param */
+ reg.x.di = pktTemp; /* DOS segment to param */
+#elif (DOSX & DOS4GW)
+ reg.r_es = rm_base_seg;
+ reg.r_di = pktTemp;
+#else
+ reg.r_es = FP_SEG (&pktTemp);
+ reg.r_di = FP_OFF (&pktTemp);
+#endif
+
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverInfo (void)
+{
+ pktInfo.majVer = 0;
+ pktInfo.minVer = 0;
+ memset (&pktInfo.name, 0, sizeof(pktInfo.name));
+ reg.r_ax = 0x01FF;
+ reg.r_bx = 0;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ pktInfo.number = reg.r_cx & 0xFF;
+ pktInfo.class = reg.r_cx >> 8;
+#if 0
+ pktInfo.minVer = reg.r_bx % 10;
+ pktInfo.majVer = reg.r_bx / 10;
+#else
+ pktInfo.majVer = reg.r_bx; // !!
+#endif
+ pktInfo.funcs = reg.r_ax & 0xFF;
+ pktInfo.type = reg.r_dx & 0xFF;
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));
+
+#elif (DOSX & DJGPP)
+ dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);
+
+#elif (DOSX & DOS4GW)
+ memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+
+#else
+ _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+#endif
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverParam (void)
+{
+ reg.r_ax = 0x0A00;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);
+
+#elif (DOSX & DJGPP)
+ dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);
+
+#elif (DOSX & DOS4GW)
+ memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+
+#else
+ _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+#endif
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+#if (DOSX & PHARLAP)
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ WORD inOfs = *rxInOfsFp;
+ WORD outOfs = *rxOutOfsFp;
+
+ if (outOfs != inOfs)
+ {
+ RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);
+ int size, len = max;
+
+ if (CheckElement(head))
+ {
+ size = min (head->firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ _fmemcpy (buf, &head->destin, len);
+ }
+ else
+ size = -1;
+
+ outOfs += sizeof (RX_ELEMENT);
+ if (outOfs > LAST_RX_BUF)
+ outOfs = FIRST_RX_BUF;
+ *rxOutOfsFp = outOfs;
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;
+ if (*rxOutOfsFp > LAST_RX_BUF)
+ *rxOutOfsFp = FIRST_RX_BUF;
+ *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs = *rxInOfsFp;
+ WORD outOfs = *rxOutOfsFp;
+
+ if (inOfs >= outOfs)
+ return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return (*(DWORD _far*)(protBase + (WORD)&pktDrop));
+ }
+
+#elif (DOSX & DJGPP)
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+
+ if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))
+ {
+ RX_ELEMENT head;
+ int size, len = max;
+
+ head.firstCount = _farpeekw (_dos_ds, realBase+ofs);
+ head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);
+ head.handle = _farpeekw (_dos_ds, realBase+ofs+4);
+
+ if (CheckElement(&head))
+ {
+ size = min (head.firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ dosmemget (realBase+ofs+6, len, buf);
+ }
+ else
+ size = -1;
+
+ ofs += sizeof (RX_ELEMENT);
+ if (ofs > LAST_RX_BUF)
+ _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+ else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ WORD ofs;
+
+ disable();
+ ofs = _farpeekw (_dos_ds, realBase+rxInOfs);
+ if (busy)
+ ofs += sizeof (RX_ELEMENT);
+
+ if (ofs > LAST_RX_BUF)
+ _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+ else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+ _farpokel (_dos_ds, realBase+pktDrop, 0UL);
+ enable();
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs, outOfs;
+
+ disable();
+ inOfs = _farpeekw (_dos_ds, realBase+rxInOfs);
+ outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+ enable();
+ if (inOfs >= outOfs)
+ return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return _farpeekl (_dos_ds, realBase+pktDrop);
+ }
+
+#elif (DOSX & DOS4GW)
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ WORD ofs = *(WORD*) (realBase+rxOutOfs);
+
+ if (ofs != *(WORD*) (realBase+rxInOfs))
+ {
+ RX_ELEMENT head;
+ int size, len = max;
+
+ head.firstCount = *(WORD*) (realBase+ofs);
+ head.secondCount = *(WORD*) (realBase+ofs+2);
+ head.handle = *(WORD*) (realBase+ofs+4);
+
+ if (CheckElement(&head))
+ {
+ size = min (head.firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ memcpy (buf, (const void*)(realBase+ofs+6), len);
+ }
+ else
+ size = -1;
+
+ ofs += sizeof (RX_ELEMENT);
+ if (ofs > LAST_RX_BUF)
+ *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+ else *(WORD*) (realBase+rxOutOfs) = ofs;
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ WORD ofs;
+
+ _disable();
+ ofs = *(WORD*) (realBase+rxInOfs);
+ if (busy)
+ ofs += sizeof (RX_ELEMENT);
+
+ if (ofs > LAST_RX_BUF)
+ *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+ else *(WORD*) (realBase+rxOutOfs) = ofs;
+ *(DWORD*) (realBase+pktDrop) = 0UL;
+ _enable();
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs, outOfs;
+
+ _disable();
+ inOfs = *(WORD*) (realBase+rxInOfs);
+ outOfs = *(WORD*) (realBase+rxOutOfs);
+ _enable();
+ if (inOfs >= outOfs)
+ return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return *(DWORD*) (realBase+pktDrop);
+ }
+
+#else /* real-mode small/large model */
+
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ if (rxOutOfs != rxInOfs)
+ {
+ RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
+ int size, len = max;
+
+ if (CheckElement(head))
+ {
+ size = min (head->firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ _fmemcpy (buf, &head->destin, len);
+ }
+ else
+ size = -1;
+
+ rxOutOfs += sizeof (RX_ELEMENT);
+ if (rxOutOfs > LAST_RX_BUF)
+ rxOutOfs = FIRST_RX_BUF;
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
+ if (rxOutOfs > LAST_RX_BUF)
+ rxOutOfs = FIRST_RX_BUF;
+ pktDrop = 0L;
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs = rxInOfs;
+ WORD outOfs = rxOutOfs;
+
+ if (inOfs >= outOfs)
+ return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return (pktDrop);
+ }
+#endif
+
+/**************************************************************************/
+
+LOCAL __inline void PktFreeMem (void)
+{
+#if (DOSX & PHARLAP)
+ if (realSeg)
+ {
+ _dx_real_free (realSeg);
+ realSeg = 0;
+ }
+#elif (DOSX & DJGPP)
+ if (rm_mem.rm_segment)
+ {
+ unsigned ofs; /* clear the DOS-mem to prevent further upcalls */
+
+ for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)
+ _farpokel (_dos_ds, realBase + ofs, 0);
+ _go32_dpmi_free_dos_memory (&rm_mem);
+ rm_mem.rm_segment = 0;
+ }
+#elif (DOSX & DOS4GW)
+ if (rm_base_sel)
+ {
+ dpmi_real_free (rm_base_sel);
+ rm_base_sel = 0;
+ }
+#endif
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktExitDriver (void)
+{
+ if (pktInfo.handle)
+ {
+ if (!PktSetReceiverMode(PDRX_BROADCAST))
+ PUTS ("Error restoring receiver mode.");
+
+ if (!PktReleaseHandle(pktInfo.handle))
+ PUTS ("Error releasing PKT-DRVR handle.");
+
+ PktFreeMem();
+ pktInfo.handle = 0;
+ }
+
+ if (pcap_pkt_debug >= 1)
+ printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
+ "wrong-handle %lu\n",
+ intStat.tooSmall, intStat.tooLarge,
+ intStat.badSync, intStat.wrongHandle);
+ return (TRUE);
+}
+
+#if (DOSX & (DJGPP|DOS4GW))
+static void dump_pkt_stub (void)
+{
+ int i;
+
+ fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
+ PktReceiver);
+ for (i = 0; i < 15; i++)
+ fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);
+ fputs ("\n", stderr);
+}
+#endif
+
+/*
+ * Front end initialization routine
+ */
+PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
+{
+ PKT_RX_MODE rxMode;
+ BOOL writeInfo = (pcap_pkt_debug >= 3);
+
+ pktInfo.quiet = (pcap_pkt_debug < 3);
+
+#if (DOSX & PHARLAP) && defined(__HIGHC__)
+ if (_mwenv != 2)
+ {
+ fprintf (stderr, "Only Pharlap DOS extender supported.\n");
+ return (FALSE);
+ }
+#endif
+
+#if (DOSX & PHARLAP) && defined(__WATCOMC__)
+ if (_Extender != 1)
+ {
+ fprintf (stderr, "Only DOS4GW style extenders supported.\n");
+ return (FALSE);
+ }
+#endif
+
+ if (!PktSearchDriver())
+ {
+ PUTS ("Packet driver not found.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktGetDriverInfo())
+ {
+ PUTS ("Error getting pkt-drvr information.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+#if (DOSX & PHARLAP)
+ if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
+ &realBase, &protBase, (USHORT*)&realSeg))
+ {
+ rxOutOfsFp = (WORD _far *) (protBase + (WORD) &rxOutOfs);
+ rxInOfsFp = (WORD _far *) (protBase + (WORD) &rxInOfs);
+ *rxOutOfsFp = FIRST_RX_BUF;
+ *rxInOfsFp = FIRST_RX_BUF;
+ }
+ else
+ {
+ PUTS ("Cannot allocate real-mode stub.");
+ return (FALSE);
+ }
+
+#elif (DOSX & (DJGPP|DOS4GW))
+ if (sizeof(real_stub_array) > 0xFFFF)
+ {
+ fprintf (stderr, "`real_stub_array[]' too big.\n");
+ return (FALSE);
+ }
+#if (DOSX & DJGPP)
+ rm_mem.size = (sizeof(real_stub_array) + 15) / 16;
+
+ if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
+ {
+ PUTS ("real-mode init failed.");
+ return (FALSE);
+ }
+ realBase = (rm_mem.rm_segment << 4);
+ dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);
+ _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+ _farpokel (_dos_ds, realBase+rxInOfs, FIRST_RX_BUF);
+
+#elif (DOSX & DOS4GW)
+ rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
+ if (!rm_base_seg)
+ {
+ PUTS ("real-mode init failed.");
+ return (FALSE);
+ }
+ realBase = (rm_base_seg << 4);
+ memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));
+ *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+ *(WORD*) (realBase+rxInOfs) = FIRST_RX_BUF;
+
+#endif
+ {
+ int pushf = PktReceiver;
+
+ while (real_stub_array[pushf++] != 0x9C && /* pushf */
+ real_stub_array[pushf] != 0xFA) /* cli */
+ {
+ if (++para_skip > 16)
+ {
+ fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
+ para_skip = 0;
+ dump_pkt_stub();
+ return (FALSE);
+ }
+ }
+ if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
+ {
+ fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
+ return (FALSE);
+ }
+ }
+
+ if (pcap_pkt_debug > 2)
+ dump_pkt_stub();
+
+#else
+ rxOutOfs = FIRST_RX_BUF;
+ rxInOfs = FIRST_RX_BUF;
+#endif
+
+ if (!PktSetAccess())
+ {
+ PUTS ("Error setting pkt-drvr access.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktGetAddress(&myAddress))
+ {
+ PUTS ("Error fetching adapter address.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktSetReceiverMode(mode))
+ {
+ PUTS ("Error setting receiver mode.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktGetReceiverMode(&rxMode))
+ {
+ PUTS ("Error getting receiver mode.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (writeInfo)
+ printf ("Pkt-driver information:\n"
+ " Version : %d.%d\n"
+ " Name : %.15s\n"
+ " Class : %u (%s)\n"
+ " Type : %u\n"
+ " Number : %u\n"
+ " Funcs : %u\n"
+ " Intr : %Xh\n"
+ " Handle : %u\n"
+ " Extended : %s\n"
+ " Hi-perf : %s\n"
+ " RX mode : %s\n"
+ " Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
+
+ pktInfo.majVer, pktInfo.minVer, pktInfo.name,
+ pktInfo.class, PktGetClassName(pktInfo.class),
+ pktInfo.type, pktInfo.number,
+ pktInfo.funcs, pktInfo.intr, pktInfo.handle,
+ pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",
+ pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",
+ PktRXmodeStr(rxMode),
+ myAddress[0], myAddress[1], myAddress[2],
+ myAddress[3], myAddress[4], myAddress[5]);
+
+#if defined(DEBUG) && (DOSX & PHARLAP)
+ if (writeInfo)
+ {
+ DWORD rAdr = realBase + (WORD)&PktReceiver;
+ unsigned sel, ofs;
+
+ printf ("\nReceiver at %04X:%04X\n", RP_SEG(rAdr), RP_OFF(rAdr));
+ printf ("Realbase = %04X:%04X\n", RP_SEG(realBase),RP_OFF(realBase));
+
+ sel = _FP_SEG (protBase);
+ ofs = _FP_OFF (protBase);
+ printf ("Protbase = %04X:%08X\n", sel,ofs);
+ printf ("RealSeg = %04X\n", realSeg);
+
+ sel = _FP_SEG (rxOutOfsFp);
+ ofs = _FP_OFF (rxOutOfsFp);
+ printf ("rxOutOfsFp = %04X:%08X\n", sel,ofs);
+
+ sel = _FP_SEG (rxInOfsFp);
+ ofs = _FP_OFF (rxInOfsFp);
+ printf ("rxInOfsFp = %04X:%08X\n", sel,ofs);
+
+ printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+ *rxOutOfsFp, *rxInOfsFp);
+
+ PktQueueBusy (TRUE);
+ printf ("Busy: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+ *rxOutOfsFp, *rxInOfsFp);
+ }
+#endif
+
+ memset (&pktStat, 0, sizeof(pktStat)); /* clear statistics */
+ PktQueueBusy (TRUE);
+ return (TRUE);
+}
+
+
+/*
+ * DPMI functions only for Watcom + DOS4GW extenders
+ */
+#if (DOSX & DOS4GW)
+LOCAL DWORD dpmi_get_real_vector (int intr)
+{
+ union REGS r;
+
+ r.x.eax = 0x200;
+ r.x.ebx = (DWORD) intr;
+ int386 (0x31, &r, &r);
+ return ((r.w.cx << 4) + r.w.dx);
+}
+
+LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
+{
+ union REGS r;
+
+ r.x.eax = 0x0100; /* DPMI allocate DOS memory */
+ r.x.ebx = (size + 15) / 16; /* Number of paragraphs requested */
+ int386 (0x31, &r, &r);
+ if (r.w.cflag & 1)
+ return (0);
+
+ *selector = r.w.dx;
+ return (r.w.ax); /* Return segment address */
+}
+
+LOCAL void dpmi_real_free (WORD selector)
+{
+ union REGS r;
+
+ r.x.eax = 0x101; /* DPMI free DOS memory */
+ r.x.ebx = selector; /* Selector to free */
+ int386 (0x31, &r, &r);
+}
+#endif
+
+
+#if defined(DOSX) && (DOSX & PHARLAP)
+/*
+ * Description:
+ * This routine allocates conventional memory for the specified block
+ * of code (which must be within the first 64K of the protected mode
+ * program segment) and copies the code to it.
+ *
+ * The caller should free up the conventional memory block when it
+ * is done with the conventional memory.
+ *
+ * NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
+ *
+ * Calling arguments:
+ * start_offs start of real mode code in program segment
+ * end_offs 1 byte past end of real mode code in program segment
+ * real_basep returned; real mode ptr to use as a base for the
+ * real mode code (eg, to get the real mode FAR
+ * addr of a function foo(), take
+ * real_basep + (ULONG) foo).
+ * This pointer is constructed such that
+ * offsets within the real mode segment are
+ * the same as the link-time offsets in the
+ * protected mode program segment
+ * prot_basep returned; prot mode ptr to use as a base for getting
+ * to the conventional memory, also constructed
+ * so that adding the prot mode offset of a
+ * function or variable to the base gets you a
+ * ptr to the function or variable in the
+ * conventional memory block.
+ * rmem_adrp returned; real mode para addr of allocated
+ * conventional memory block, to be used to free
+ * up the conventional memory when done. DO NOT
+ * USE THIS TO CONSTRUCT A REAL MODE PTR, USE
+ * REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
+ * CORRECTLY.
+ *
+ * Returned values:
+ * 0 if error
+ * 1 if success
+ */
+int RealCopy (ULONG start_offs,
+ ULONG end_offs,
+ REALPTR *real_basep,
+ FARPTR *prot_basep,
+ USHORT *rmem_adrp)
+{
+ ULONG rm_base; /* base real mode para addr for accessing */
+ /* allocated conventional memory */
+ UCHAR *source; /* source pointer for copy */
+ FARPTR destin; /* destination pointer for copy */
+ ULONG len; /* number of bytes to copy */
+ ULONG temp;
+ USHORT stemp;
+
+ /* First check for valid inputs
+ */
+ if (start_offs >= end_offs || end_offs > 0x10000)
+ return (FALSE);
+
+ /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
+ * the real mode pointer easily. Round up end_offs to make sure we allocate
+ * enough paragraphs
+ */
+ start_offs &= ~15;
+ end_offs = (15 + (end_offs << 4)) >> 4;
+
+ /* Allocate the conventional memory for our real mode code. Remember to
+ * round byte count UP to 16-byte paragraph size. We alloc it
+ * above the DOS data buffer so both the DOS data buffer and the appl
+ * conventional mem block can still be resized.
+ *
+ * First just try to alloc it; if we can't get it, shrink the appl mem
+ * block down to the minimum, try to alloc the memory again, then grow the
+ * appl mem block back to the maximum. (Don't try to shrink the DOS data
+ * buffer to free conventional memory; it wouldn't be good for this routine
+ * to have the possible side effect of making file I/O run slower.)
+ */
+ len = ((end_offs - start_offs) + 15) >> 4;
+ if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+ {
+ if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
+ return (FALSE);
+
+ if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+ *rmem_adrp = 0;
+
+ if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
+ {
+ if (*rmem_adrp != 0)
+ _dx_real_free (*rmem_adrp);
+ return (FALSE);
+ }
+
+ if (*rmem_adrp == 0)
+ return (FALSE);
+ }
+
+ /* Construct real mode & protected mode pointers to access the allocated
+ * memory. Note we know start_offs is aligned on a paragraph (16-byte)
+ * boundary, because we rounded it down.
+ *
+ * We make the offsets come out rights by backing off the real mode selector
+ * by start_offs.
+ */
+ rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
+ RP_SET (*real_basep, 0, rm_base);
+ FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);
+
+ /* Copy the real mode code/data to the allocated memory
+ */
+ source = (UCHAR *) start_offs;
+ destin = *prot_basep;
+ FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
+ len = end_offs - start_offs;
+ WriteFarMem (destin, source, len);
+
+ return (TRUE);
+}
+#endif /* DOSX && (DOSX & PHARLAP) */
diff --git a/lib/libpcap/libpcap/msdos/pktdrvr.h b/lib/libpcap/libpcap/msdos/pktdrvr.h
new file mode 100644
index 0000000..3e0cfe0
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/pktdrvr.h
@@ -0,0 +1,153 @@
+#ifndef __PKTDRVR_H
+#define __PKTDRVR_H
+
+#define PUBLIC
+#define LOCAL static
+
+#define RX_BUF_SIZE ETH_MTU /* buffer size variables. NB !! */
+#define TX_BUF_SIZE ETH_MTU /* must be same as in pkt_rx*.* */
+
+#ifdef __HIGHC__
+#pragma Off(Align_members)
+#else
+#pragma pack(1)
+#endif
+
+typedef enum { /* Packet-driver classes */
+ PD_ETHER = 1,
+ PD_PRONET10 = 2,
+ PD_IEEE8025 = 3,
+ PD_OMNINET = 4,
+ PD_APPLETALK = 5,
+ PD_SLIP = 6,
+ PD_STARTLAN = 7,
+ PD_ARCNET = 8,
+ PD_AX25 = 9,
+ PD_KISS = 10,
+ PD_IEEE8023_2 = 11,
+ PD_FDDI8022 = 12,
+ PD_X25 = 13,
+ PD_LANstar = 14,
+ PD_PPP = 18
+ } PKT_CLASS;
+
+typedef enum { /* Packet-driver receive modes */
+ PDRX_OFF = 1, /* turn off receiver */
+ PDRX_DIRECT, /* receive only to this interface */
+ PDRX_BROADCAST, /* DIRECT + broadcast packets */
+ PDRX_MULTICAST1, /* BROADCAST + limited multicast */
+ PDRX_MULTICAST2, /* BROADCAST + all multicast */
+ PDRX_ALL_PACKETS, /* receive all packets on network */
+ } PKT_RX_MODE;
+
+typedef struct {
+ char type[8];
+ char len;
+ } PKT_FRAME;
+
+
+typedef struct {
+ BYTE class; /* = 1 for DEC/Interl/Xerox Ethernet */
+ BYTE number; /* = 0 for single LAN adapter */
+ WORD type; /* = 13 for 3C523 */
+ BYTE funcs; /* Basic/Extended/HiPerf functions */
+ WORD intr; /* user interrupt vector number */
+ WORD handle; /* Handle associated with session */
+ BYTE name [15]; /* Name of adapter interface,ie.3C523*/
+ BOOL quiet; /* (don't) print errors to stdout */
+ const char *error; /* address of error string */
+ BYTE majVer; /* Major driver implementation ver. */
+ BYTE minVer; /* Minor driver implementation ver. */
+ BYTE dummyLen; /* length of following data */
+ WORD MAClength; /* HiPerformance data, N/A */
+ WORD MTU; /* HiPerformance data, N/A */
+ WORD multicast; /* HiPerformance data, N/A */
+ WORD rcvrBuffers; /* valid for */
+ WORD UMTbufs; /* High Performance drivers only */
+ WORD postEOIintr; /* Usage ?? */
+ } PKT_INFO;
+
+#define PKT_PARAM_SIZE 14 /* members majVer - postEOIintr */
+
+
+typedef struct {
+ DWORD inPackets; /* # of packets received */
+ DWORD outPackets; /* # of packets transmitted */
+ DWORD inBytes; /* # of bytes received */
+ DWORD outBytes; /* # of bytes transmitted */
+ DWORD inErrors; /* # of reception errors */
+ DWORD outErrors; /* # of transmission errors */
+ DWORD lost; /* # of packets lost (RX) */
+ } PKT_STAT;
+
+
+typedef struct {
+ ETHER destin;
+ ETHER source;
+ WORD proto;
+ BYTE data [TX_BUF_SIZE];
+ } TX_ELEMENT;
+
+typedef struct {
+ WORD firstCount; /* # of bytes on 1st */
+ WORD secondCount; /* and 2nd upcall */
+ WORD handle; /* instance that upcalled */
+ ETHER destin; /* E-net destination address */
+ ETHER source; /* E-net source address */
+ WORD proto; /* protocol number */
+ BYTE data [RX_BUF_SIZE];
+ } RX_ELEMENT;
+
+
+#ifdef __HIGHC__
+#pragma pop(Align_members)
+#else
+#pragma pack()
+#endif
+
+
+/*
+ * Prototypes for publics
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern PKT_STAT pktStat; /* statistics for packets */
+extern PKT_INFO pktInfo; /* packet-driver information */
+
+extern PKT_RX_MODE receiveMode;
+extern ETHER myAddress, ethBroadcast;
+
+extern BOOL PktInitDriver (PKT_RX_MODE mode);
+extern BOOL PktExitDriver (void);
+
+extern const char *PktGetErrorStr (int errNum);
+extern const char *PktGetClassName (WORD class);
+extern const char *PktRXmodeStr (PKT_RX_MODE mode);
+extern BOOL PktSearchDriver (void);
+extern int PktReceive (BYTE *buf, int max);
+extern BOOL PktTransmit (const void *eth, int len);
+extern DWORD PktRxDropped (void);
+extern BOOL PktReleaseHandle (WORD handle);
+extern BOOL PktTerminHandle (WORD handle);
+extern BOOL PktResetInterface (WORD handle);
+extern BOOL PktSetReceiverMode(PKT_RX_MODE mode);
+extern BOOL PktGetReceiverMode(PKT_RX_MODE *mode);
+extern BOOL PktGetStatistics (WORD handle);
+extern BOOL PktSessStatistics (WORD handle);
+extern BOOL PktResetStatistics(WORD handle);
+extern BOOL PktGetAddress (ETHER *addr);
+extern BOOL PktSetAddress (const ETHER *addr);
+extern BOOL PktGetDriverInfo (void);
+extern BOOL PktGetDriverParam (void);
+extern void PktQueueBusy (BOOL busy);
+extern WORD PktBuffersUsed (void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __PKTDRVR_H */
+
diff --git a/lib/libpcap/libpcap/msdos/readme.dos b/lib/libpcap/libpcap/msdos/readme.dos
new file mode 100644
index 0000000..b95483f
--- /dev/null
+++ b/lib/libpcap/libpcap/msdos/readme.dos
@@ -0,0 +1,166 @@
+libpcap for DOS
+---------------
+
+This file contains some notes on building and using libpcap for MS-DOS.
+Look in `README' and `pcap.man' for usage and details. These targets are
+supported:
+
+ - Borland C 4.0+ small or large model.
+ - Metaware HighC 3.1+ with PharLap DOS-extender
+ - GNU C 2.7+ with djgpp 2.01+ DOS extender
+ - Watcom C 11.x with DOS4GW extender
+
+Note: the files in the libpcap.zip contains short truncated filenames.
+ So for djgpp to work with these, disable the use of long file names by
+ setting "LFN=n" in the environment. On the other hand, if you get libpcap
+ from Github or the official libpcap.tar.gz, some filenames are beyond 8+3.
+ In this case set "LFN=y".
+
+Files specific to DOS are pcap-dos.[ch] and the assembly and C files in
+the MSDOS sub-directory. Remember to built the libpcap library from the top
+install directory. And not from the MSDOS sub-directory.
+
+Note for djgpp users:
+ If you got the libpcap from the official site www.tcpdump, then that
+ distribution does NOT contain any sources for building 32-bit drivers.
+ Instead get the full version at
+ http://www.watt-32.net/pcap/libpcap.zip
+
+ and set "USE_32BIT_DRIVERS = 1" in msdos\common.dj.
+
+
+
+Requirements
+------------
+
+DOS-libpcap currently only works reliably with a real-mode Ethernet packet-
+driver. This driver must be installed prior to using any program (e.g.
+tcpdump) compiled with libpcap. Work is underway to implement protected-
+mode drivers for 32-bit targets (djgpp only). The 3Com 3c509 driver is
+working almost perfectly. Due to lack of LAN-cards, I've not had the
+opportunity to test other drivers. These 32-bit drivers are modified
+Linux drivers.
+
+
+Required packages
+-----------------
+
+The following packages and tools must be present for all targets.
+
+1. Watt-32 tcp/ip library. This library is *not* used to send or
+ receive network data. It's mostly used to access the 'hosts'
+ file and other <netdb.h> features. Get 'watt32s*.zip' at:
+
+ http://www.watt-32.net
+
+2. Exception handler and disassember library (libexc.a) is needed if
+ "USE_EXCEPT = 1" in common.dj. Available at:
+
+ http://www.watt-32.net/misc/exc_dx07.zip
+
+3. Flex & Bison is used to generate parser for the filter handler
+ pcap_compile:
+ ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/flx254b.zip
+ ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/bsn241b.zip
+
+4. NASM assembler v 0.98 or later is required when building djgpp and
+ Watcom targets:
+ http://www.nasm.us/
+
+5. sed (Stream Editor) is required for doing `make depend'.
+ It's available at:
+ ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/sed422b.zip
+
+ A touch tool to update the time-stamp of a file. E.g.:
+ ftp://ftp.delorie.com/pub/djgpp/current/v2gnu/grep29b.zip
+
+6. For djgpp rm.exe and cp.exe are required. These should already be
+ part of your djgpp installation. Also required (experimental at the
+ time) for djgpp is DLX 2.91 or later. This tool is for the generation
+ of dynamically loadable modules.
+
+
+Compiling libpcap
+-----------------
+
+Follow these steps in building libpcap:
+
+1. Make sure you've installed Watt-32 properly (see it's `INSTALL' file).
+ During that installation a environment variable `WATT_ROOT' is set.
+ This variable is used for building libpcap also (`WATT_INC' is
+ deducted from `WATT_ROOT'). djgpp users should also define environment
+ variables `C_INCLUDE_PATH' and `LIBRARY_PATH' to point to the include
+ directory and library directory respectively. E.g. put this in your
+ AUTOEXEC.BAT:
+ set C_INCLUDE_PATH=c:/net/watt/inc
+ set LIBRARY_PATH=c:/net/watt/lib
+
+2. Revise the msdos/common.dj file for your djgpp/gcc installation;
+ - change the value of `GCCLIB' to match location of libgcc.a.
+ - set `USE_32BIT_DRIVERS = 1' to build 32-bit driver objects.
+
+
+3. Build pcap by using appropriate makefile. For djgpp, use:
+ `make -f msdos/makefile.dj' (i.e. GNU `make')
+
+ For a Watcom target say:
+ `wmake -f msdos\makefile.wc'
+
+ For a Borland target say:
+ `maker -f msdos\Makefile pcap_bc.lib' (Borland's `maker.exe')
+
+ And for a HighC/Pharlap target say:
+ `maker -f msdos\Makefile pcap_hc.lib' (Borland's `maker.exe')
+
+ You might like to change some `CFLAGS' -- only `DEBUG' define currently
+ have any effect. It shows a rotating "fan" in upper right corner of
+ screen. Remove `DEBUG' if you don't like it. You could add
+ `-fomit-frame-pointer' to `CFLAGS' to speed up the generated code.
+ But note, this makes debugging and crash-traceback difficult. Only
+ add it if you're fully confident your application is 100% stable.
+
+ Note: Code in `USE_NDIS2' does not work at the moment.
+
+4. The resulting library is put in current directory. There's some
+ test-program for `libpcap': `filtertest.exe', `findalldevstest.exe',
+ `nonblocktest.exe' and `opentest.exe'.
+
+ But linking the library with `tcpdump' is the ultimate test. DOS/djgpp
+ should now hopefully be a supported target. Get the sources at:
+ https://www.tcpdump.org/
+ or
+ https://github.com/the-tcpdump-group/tcpdump/
+
+ (click on the 'Download ZIP' on the right side of that page.)
+
+
+Extensions to libpcap
+---------------------
+
+I've included some extra functions to DOS-libpcap:
+
+ `pcap_config_hook (const char *keyword, const char *value)' :
+
+ Allows an application to set values of internal libpcap variables.
+ `keyword' and an associated `value' should be present in the `debug_tab[]'
+ array in pcap-dos.c (currently only used to set debug-levels and parameters
+ for the 32-bit network drivers.) Thus an application using DOS-libpcap can
+ override the default value during it's configure process (see tcpdump's
+ msdos/config.c file for an extended example).
+
+ `pcap_set_wait (pcap_t *, void (*)(void), int)' :
+
+ Only effective when reading offline traffic from dump-files.
+ Function `pcap_offline_read()' will wait (and optionally yield)
+ before printing next packet. This will simulate the pace the packets
+ where actually recorded.
+
+
+
+Happy sniffing !
+
+
+Gisle Vanem <gvanem@yahoo.no>
+
+October 1999, 2004, 2006, 2013
+
diff --git a/lib/libpcap/libpcap/nametoaddr.c b/lib/libpcap/libpcap/nametoaddr.c
new file mode 100644
index 0000000..1c58498
--- /dev/null
+++ b/lib/libpcap/libpcap/nametoaddr.c
@@ -0,0 +1,800 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Name to id translation routines used by the scanner.
+ * These functions are not time critical.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef DECNETLIB
+#include <sys/types.h>
+#include <netdnet/dnetdb.h>
+#endif
+
+#ifdef _WIN32
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+
+#ifdef INET6
+/*
+ * To quote the MSDN page for getaddrinfo() at
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
+ *
+ * "Support for getaddrinfo on Windows 2000 and older versions
+ * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
+ * later. To execute an application that uses this function on earlier
+ * versions of Windows, then you need to include the Ws2tcpip.h and
+ * Wspiapi.h files. When the Wspiapi.h include file is added, the
+ * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
+ * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
+ * function is implemented in such a way that if the Ws2_32.dll or the
+ * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
+ * Preview for Windows 2000) does not include getaddrinfo, then a
+ * version of getaddrinfo is implemented inline based on code in the
+ * Wspiapi.h header file. This inline code will be used on older Windows
+ * platforms that do not natively support the getaddrinfo function."
+ *
+ * We use getaddrinfo(), so we include Wspiapi.h here.
+ */
+ #include <wspiapi.h>
+ #endif /* INET6 */
+#else /* _WIN32 */
+#include <sys/param.h>
+ #include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+
+#ifdef HAVE_ETHER_HOSTTON
+ #if defined(NET_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+ /*
+ * OK, just include <net/ethernet.h>.
+ */
+ #include <net/ethernet.h>
+ #elif defined(NETINET_ETHER_H_DECLARES_ETHER_HOSTTON)
+ /*
+ * OK, just include <netinet/ether.h>
+ */
+ #include <netinet/ether.h>
+ #elif defined(SYS_ETHERNET_H_DECLARES_ETHER_HOSTTON)
+ /*
+ * OK, just include <sys/ethernet.h>
+ */
+ #include <sys/ethernet.h>
+ #elif defined(ARPA_INET_H_DECLARES_ETHER_HOSTTON)
+ /*
+ * OK, just include <arpa/inet.h>
+ */
+ #include <arpa/inet.h>
+ #elif defined(NETINET_IF_ETHER_H_DECLARES_ETHER_HOSTTON)
+ /*
+ * OK, include <netinet/if_ether.h>, after all the other stuff we
+ * need to include or define for its benefit.
+ */
+ #define NEED_NETINET_IF_ETHER_H
+ #else
+ /*
+ * We'll have to declare it ourselves.
+ * If <netinet/if_ether.h> defines struct ether_addr, include
+ * it. Otherwise, define it ourselves.
+ */
+ #ifdef HAVE_STRUCT_ETHER_ADDR
+ #define NEED_NETINET_IF_ETHER_H
+ #else /* HAVE_STRUCT_ETHER_ADDR */
+ struct ether_addr {
+ unsigned char ether_addr_octet[6];
+ };
+ #endif /* HAVE_STRUCT_ETHER_ADDR */
+ #endif /* what declares ether_hostton() */
+
+ #ifdef NEED_NETINET_IF_ETHER_H
+ #include <net/if.h> /* Needed on some platforms */
+ #include <netinet/in.h> /* Needed on some platforms */
+#include <netinet/if_ether.h>
+ #endif /* NEED_NETINET_IF_ETHER_H */
+
+ #ifndef HAVE_DECL_ETHER_HOSTTON
+ /*
+ * No header declares it, so declare it ourselves.
+ */
+ extern int ether_hostton(const char *, struct ether_addr *);
+ #endif /* !defined(HAVE_DECL_ETHER_HOSTTON) */
+#endif /* HAVE_ETHER_HOSTTON */
+
+#include <arpa/inet.h>
+#include <netdb.h>
+#endif /* _WIN32 */
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#include <pcap/namedb.h>
+#include "nametoaddr.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifndef NTOHL
+#define NTOHL(x) (x) = ntohl(x)
+#define NTOHS(x) (x) = ntohs(x)
+#endif
+
+/*
+ * Convert host name to internet address.
+ * Return 0 upon failure.
+ * XXX - not thread-safe; don't use it inside libpcap.
+ */
+bpf_u_int32 **
+pcap_nametoaddr(const char *name)
+{
+#ifndef h_addr
+ static bpf_u_int32 *hlist[2];
+#endif
+ bpf_u_int32 **p;
+ struct hostent *hp;
+
+ if ((hp = gethostbyname(name)) != NULL) {
+#ifndef h_addr
+ hlist[0] = (bpf_u_int32 *)hp->h_addr;
+ NTOHL(hp->h_addr);
+ return hlist;
+#else
+ for (p = (bpf_u_int32 **)hp->h_addr_list; *p; ++p)
+ NTOHL(**p);
+ return (bpf_u_int32 **)hp->h_addr_list;
+#endif
+ }
+ else
+ return 0;
+}
+
+struct addrinfo *
+pcap_nametoaddrinfo(const char *name)
+{
+ struct addrinfo hints, *res;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM; /*not really*/
+ hints.ai_protocol = IPPROTO_TCP; /*not really*/
+ error = getaddrinfo(name, NULL, &hints, &res);
+ if (error)
+ return NULL;
+ else
+ return res;
+}
+
+/*
+ * Convert net name to internet address.
+ * Return 0 upon failure.
+ * XXX - not guaranteed to be thread-safe! See below for platforms
+ * on which it is thread-safe and on which it isn't.
+ */
+bpf_u_int32
+pcap_nametonetaddr(const char *name)
+{
+#ifdef _WIN32
+ /*
+ * There's no "getnetbyname()" on Windows.
+ *
+ * XXX - I guess we could use the BSD code to read
+ * C:\Windows\System32\drivers\etc/networks, assuming
+ * that's its home on all the versions of Windows
+ * we use, but that file probably just has the loopback
+ * network on 127/24 on 99 44/100% of Windows machines.
+ *
+ * (Heck, these days it probably just has that on 99 44/100%
+ * of *UN*X* machines.)
+ */
+ return 0;
+#else
+ /*
+ * UN*X.
+ */
+ struct netent *np;
+ #if defined(HAVE_LINUX_GETNETBYNAME_R)
+ /*
+ * We have Linux's reentrant getnetbyname_r().
+ */
+ struct netent result_buf;
+ char buf[1024]; /* arbitrary size */
+ int h_errnoval;
+ int err;
+
+ /*
+ * Apparently, the man page at
+ *
+ * http://man7.org/linux/man-pages/man3/getnetbyname_r.3.html
+ *
+ * lies when it says
+ *
+ * If the function call successfully obtains a network record,
+ * then *result is set pointing to result_buf; otherwise, *result
+ * is set to NULL.
+ *
+ * and, in fact, at least in some versions of GNU libc, it does
+ * *not* always get set if getnetbyname_r() succeeds.
+ */
+ np = NULL;
+ err = getnetbyname_r(name, &result_buf, buf, sizeof buf, &np,
+ &h_errnoval);
+ if (err != 0) {
+ /*
+ * XXX - dynamically allocate the buffer, and make it
+ * bigger if we get ERANGE back?
+ */
+ return 0;
+ }
+ #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+ /*
+ * We have Solaris's and IRIX's reentrant getnetbyname_r().
+ */
+ struct netent result_buf;
+ char buf[1024]; /* arbitrary size */
+
+ np = getnetbyname_r(name, &result_buf, buf, (int)sizeof buf);
+ #elif defined(HAVE_AIX_GETNETBYNAME_R)
+ /*
+ * We have AIX's reentrant getnetbyname_r().
+ */
+ struct netent result_buf;
+ struct netent_data net_data;
+
+ if (getnetbyname_r(name, &result_buf, &net_data) == -1)
+ np = NULL;
+ else
+ np = &result_buf;
+ #else
+ /*
+ * We don't have any getnetbyname_r(); either we have a
+ * getnetbyname() that uses thread-specific data, in which
+ * case we're thread-safe (sufficiently recent FreeBSD,
+ * sufficiently recent Darwin-based OS, sufficiently recent
+ * HP-UX, sufficiently recent Tru64 UNIX), or we have the
+ * traditional getnetbyname() (everything else, including
+ * current NetBSD and OpenBSD), in which case we're not
+ * thread-safe.
+ */
+ np = getnetbyname(name);
+#endif
+ if (np != NULL)
+ return np->n_net;
+ else
+ return 0;
+#endif /* _WIN32 */
+}
+
+/*
+ * Convert a port name to its port and protocol numbers.
+ * We assume only TCP or UDP.
+ * Return 0 upon failure.
+ */
+int
+pcap_nametoport(const char *name, int *port, int *proto)
+{
+ struct addrinfo hints, *res, *ai;
+ int error;
+ struct sockaddr_in *in4;
+#ifdef INET6
+ struct sockaddr_in6 *in6;
+#endif
+ int tcp_port = -1;
+ int udp_port = -1;
+
+ /*
+ * We check for both TCP and UDP in case there are
+ * ambiguous entries.
+ */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = IPPROTO_TCP;
+ error = getaddrinfo(NULL, name, &hints, &res);
+ if (error != 0) {
+ if (error != EAI_NONAME &&
+ error != EAI_SERVICE) {
+ /*
+ * This is a real error, not just "there's
+ * no such service name".
+ * XXX - this doesn't return an error string.
+ */
+ return 0;
+ }
+ } else {
+ /*
+ * OK, we found it. Did it find anything?
+ */
+ for (ai = res; ai != NULL; ai = ai->ai_next) {
+ /*
+ * Does it have an address?
+ */
+ if (ai->ai_addr != NULL) {
+ /*
+ * Yes. Get a port number; we're done.
+ */
+ if (ai->ai_addr->sa_family == AF_INET) {
+ in4 = (struct sockaddr_in *)ai->ai_addr;
+ tcp_port = ntohs(in4->sin_port);
+ break;
+ }
+#ifdef INET6
+ if (ai->ai_addr->sa_family == AF_INET6) {
+ in6 = (struct sockaddr_in6 *)ai->ai_addr;
+ tcp_port = ntohs(in6->sin6_port);
+ break;
+ }
+#endif
+ }
+ }
+ freeaddrinfo(res);
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = IPPROTO_UDP;
+ error = getaddrinfo(NULL, name, &hints, &res);
+ if (error != 0) {
+ if (error != EAI_NONAME &&
+ error != EAI_SERVICE) {
+ /*
+ * This is a real error, not just "there's
+ * no such service name".
+ * XXX - this doesn't return an error string.
+ */
+ return 0;
+ }
+ } else {
+ /*
+ * OK, we found it. Did it find anything?
+ */
+ for (ai = res; ai != NULL; ai = ai->ai_next) {
+ /*
+ * Does it have an address?
+ */
+ if (ai->ai_addr != NULL) {
+ /*
+ * Yes. Get a port number; we're done.
+ */
+ if (ai->ai_addr->sa_family == AF_INET) {
+ in4 = (struct sockaddr_in *)ai->ai_addr;
+ udp_port = ntohs(in4->sin_port);
+ break;
+ }
+#ifdef INET6
+ if (ai->ai_addr->sa_family == AF_INET6) {
+ in6 = (struct sockaddr_in6 *)ai->ai_addr;
+ udp_port = ntohs(in6->sin6_port);
+ break;
+ }
+#endif
+ }
+ }
+ freeaddrinfo(res);
+ }
+
+ /*
+ * We need to check /etc/services for ambiguous entries.
+ * If we find an ambiguous entry, and it has the
+ * same port number, change the proto to PROTO_UNDEF
+ * so both TCP and UDP will be checked.
+ */
+ if (tcp_port >= 0) {
+ *port = tcp_port;
+ *proto = IPPROTO_TCP;
+ if (udp_port >= 0) {
+ if (udp_port == tcp_port)
+ *proto = PROTO_UNDEF;
+#ifdef notdef
+ else
+ /* Can't handle ambiguous names that refer
+ to different port numbers. */
+ warning("ambiguous port %s in /etc/services",
+ name);
+#endif
+ }
+ return 1;
+ }
+ if (udp_port >= 0) {
+ *port = udp_port;
+ *proto = IPPROTO_UDP;
+ return 1;
+ }
+#if defined(ultrix) || defined(__osf__)
+ /* Special hack in case NFS isn't in /etc/services */
+ if (strcmp(name, "nfs") == 0) {
+ *port = 2049;
+ *proto = PROTO_UNDEF;
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Convert a string in the form PPP-PPP, where correspond to ports, to
+ * a starting and ending port in a port range.
+ * Return 0 on failure.
+ */
+int
+pcap_nametoportrange(const char *name, int *port1, int *port2, int *proto)
+{
+ u_int p1, p2;
+ char *off, *cpy;
+ int save_proto;
+
+ if (sscanf(name, "%d-%d", &p1, &p2) != 2) {
+ if ((cpy = strdup(name)) == NULL)
+ return 0;
+
+ if ((off = strchr(cpy, '-')) == NULL) {
+ free(cpy);
+ return 0;
+ }
+
+ *off = '\0';
+
+ if (pcap_nametoport(cpy, port1, proto) == 0) {
+ free(cpy);
+ return 0;
+ }
+ save_proto = *proto;
+
+ if (pcap_nametoport(off + 1, port2, proto) == 0) {
+ free(cpy);
+ return 0;
+ }
+ free(cpy);
+
+ if (*proto != save_proto)
+ *proto = PROTO_UNDEF;
+ } else {
+ *port1 = p1;
+ *port2 = p2;
+ *proto = PROTO_UNDEF;
+ }
+
+ return 1;
+}
+
+/*
+ * XXX - not guaranteed to be thread-safe! See below for platforms
+ * on which it is thread-safe and on which it isn't.
+ */
+int
+pcap_nametoproto(const char *str)
+{
+ struct protoent *p;
+ #if defined(HAVE_LINUX_GETNETBYNAME_R)
+ /*
+ * We have Linux's reentrant getprotobyname_r().
+ */
+ struct protoent result_buf;
+ char buf[1024]; /* arbitrary size */
+ int err;
+
+ err = getprotobyname_r(str, &result_buf, buf, sizeof buf, &p);
+ if (err != 0) {
+ /*
+ * XXX - dynamically allocate the buffer, and make it
+ * bigger if we get ERANGE back?
+ */
+ return 0;
+ }
+ #elif defined(HAVE_SOLARIS_IRIX_GETNETBYNAME_R)
+ /*
+ * We have Solaris's and IRIX's reentrant getprotobyname_r().
+ */
+ struct protoent result_buf;
+ char buf[1024]; /* arbitrary size */
+
+ p = getprotobyname_r(str, &result_buf, buf, (int)sizeof buf);
+ #elif defined(HAVE_AIX_GETNETBYNAME_R)
+ /*
+ * We have AIX's reentrant getprotobyname_r().
+ */
+ struct protoent result_buf;
+ struct protoent_data proto_data;
+
+ if (getprotobyname_r(str, &result_buf, &proto_data) == -1)
+ p = NULL;
+ else
+ p = &result_buf;
+ #else
+ /*
+ * We don't have any getprotobyname_r(); either we have a
+ * getprotobyname() that uses thread-specific data, in which
+ * case we're thread-safe (sufficiently recent FreeBSD,
+ * sufficiently recent Darwin-based OS, sufficiently recent
+ * HP-UX, sufficiently recent Tru64 UNIX, Windows), or we have
+ * the traditional getprotobyname() (everything else, including
+ * current NetBSD and OpenBSD), in which case we're not
+ * thread-safe.
+ */
+ p = getprotobyname(str);
+ #endif
+ if (p != 0)
+ return p->p_proto;
+ else
+ return PROTO_UNDEF;
+}
+
+#include "ethertype.h"
+
+struct eproto {
+ const char *s;
+ u_short p;
+};
+
+/*
+ * Static data base of ether protocol types.
+ * tcpdump used to import this, and it's declared as an export on
+ * Debian, at least, so make it a public symbol, even though we
+ * don't officially export it by declaring it in a header file.
+ * (Programs *should* do this themselves, as tcpdump now does.)
+ *
+ * We declare it here, right before defining it, to squelch any
+ * warnings we might get from compilers about the lack of a
+ * declaration.
+ */
+PCAP_API struct eproto eproto_db[];
+PCAP_API_DEF struct eproto eproto_db[] = {
+ { "pup", ETHERTYPE_PUP },
+ { "xns", ETHERTYPE_NS },
+ { "ip", ETHERTYPE_IP },
+#ifdef INET6
+ { "ip6", ETHERTYPE_IPV6 },
+#endif
+ { "arp", ETHERTYPE_ARP },
+ { "rarp", ETHERTYPE_REVARP },
+ { "sprite", ETHERTYPE_SPRITE },
+ { "mopdl", ETHERTYPE_MOPDL },
+ { "moprc", ETHERTYPE_MOPRC },
+ { "decnet", ETHERTYPE_DN },
+ { "lat", ETHERTYPE_LAT },
+ { "sca", ETHERTYPE_SCA },
+ { "lanbridge", ETHERTYPE_LANBRIDGE },
+ { "vexp", ETHERTYPE_VEXP },
+ { "vprod", ETHERTYPE_VPROD },
+ { "atalk", ETHERTYPE_ATALK },
+ { "atalkarp", ETHERTYPE_AARP },
+ { "loopback", ETHERTYPE_LOOPBACK },
+ { "decdts", ETHERTYPE_DECDTS },
+ { "decdns", ETHERTYPE_DECDNS },
+ { (char *)0, 0 }
+};
+
+int
+pcap_nametoeproto(const char *s)
+{
+ struct eproto *p = eproto_db;
+
+ while (p->s != 0) {
+ if (strcmp(p->s, s) == 0)
+ return p->p;
+ p += 1;
+ }
+ return PROTO_UNDEF;
+}
+
+#include "llc.h"
+
+/* Static data base of LLC values. */
+static struct eproto llc_db[] = {
+ { "iso", LLCSAP_ISONS },
+ { "stp", LLCSAP_8021D },
+ { "ipx", LLCSAP_IPX },
+ { "netbeui", LLCSAP_NETBEUI },
+ { (char *)0, 0 }
+};
+
+int
+pcap_nametollc(const char *s)
+{
+ struct eproto *p = llc_db;
+
+ while (p->s != 0) {
+ if (strcmp(p->s, s) == 0)
+ return p->p;
+ p += 1;
+ }
+ return PROTO_UNDEF;
+}
+
+/* Hex digit to 8-bit unsigned integer. */
+static inline u_char
+xdtoi(u_char c)
+{
+ if (isdigit(c))
+ return (u_char)(c - '0');
+ else if (islower(c))
+ return (u_char)(c - 'a' + 10);
+ else
+ return (u_char)(c - 'A' + 10);
+}
+
+int
+__pcap_atoin(const char *s, bpf_u_int32 *addr)
+{
+ u_int n;
+ int len;
+
+ *addr = 0;
+ len = 0;
+ for (;;) {
+ n = 0;
+ while (*s && *s != '.')
+ n = n * 10 + *s++ - '0';
+ *addr <<= 8;
+ *addr |= n & 0xff;
+ len += 8;
+ if (*s == '\0')
+ return len;
+ ++s;
+ }
+ /* NOTREACHED */
+}
+
+int
+__pcap_atodn(const char *s, bpf_u_int32 *addr)
+{
+#define AREASHIFT 10
+#define AREAMASK 0176000
+#define NODEMASK 01777
+
+ u_int node, area;
+
+ if (sscanf(s, "%d.%d", &area, &node) != 2)
+ return(0);
+
+ *addr = (area << AREASHIFT) & AREAMASK;
+ *addr |= (node & NODEMASK);
+
+ return(32);
+}
+
+/*
+ * Convert 's', which can have the one of the forms:
+ *
+ * "xx:xx:xx:xx:xx:xx"
+ * "xx.xx.xx.xx.xx.xx"
+ * "xx-xx-xx-xx-xx-xx"
+ * "xxxx.xxxx.xxxx"
+ * "xxxxxxxxxxxx"
+ *
+ * (or various mixes of ':', '.', and '-') into a new
+ * ethernet address. Assumes 's' is well formed.
+ */
+u_char *
+pcap_ether_aton(const char *s)
+{
+ register u_char *ep, *e;
+ register u_char d;
+
+ e = ep = (u_char *)malloc(6);
+ if (e == NULL)
+ return (NULL);
+
+ while (*s) {
+ if (*s == ':' || *s == '.' || *s == '-')
+ s += 1;
+ d = xdtoi(*s++);
+ if (isxdigit((unsigned char)*s)) {
+ d <<= 4;
+ d |= xdtoi(*s++);
+ }
+ *ep++ = d;
+ }
+
+ return (e);
+}
+
+#ifndef HAVE_ETHER_HOSTTON
+/*
+ * Roll our own.
+ * XXX - not thread-safe, because pcap_next_etherent() isn't thread-
+ * safe! Needs a mutex or a thread-safe pcap_next_etherent().
+ */
+u_char *
+pcap_ether_hostton(const char *name)
+{
+ register struct pcap_etherent *ep;
+ register u_char *ap;
+ static FILE *fp = NULL;
+ static int init = 0;
+
+ if (!init) {
+ fp = fopen(PCAP_ETHERS_FILE, "r");
+ ++init;
+ if (fp == NULL)
+ return (NULL);
+ } else if (fp == NULL)
+ return (NULL);
+ else
+ rewind(fp);
+
+ while ((ep = pcap_next_etherent(fp)) != NULL) {
+ if (strcmp(ep->name, name) == 0) {
+ ap = (u_char *)malloc(6);
+ if (ap != NULL) {
+ memcpy(ap, ep->addr, 6);
+ return (ap);
+ }
+ break;
+ }
+ }
+ return (NULL);
+}
+#else
+/*
+ * Use the OS-supplied routine.
+ * This *should* be thread-safe; the API doesn't have a static buffer.
+ */
+u_char *
+pcap_ether_hostton(const char *name)
+{
+ register u_char *ap;
+ u_char a[6];
+
+ ap = NULL;
+ if (ether_hostton(name, (struct ether_addr *)a) == 0) {
+ ap = (u_char *)malloc(6);
+ if (ap != NULL)
+ memcpy((char *)ap, (char *)a, 6);
+ }
+ return (ap);
+}
+#endif
+
+/*
+ * XXX - not guaranteed to be thread-safe!
+ */
+int
+#ifdef DECNETLIB
+__pcap_nametodnaddr(const char *name, u_short *res)
+{
+ struct nodeent *getnodebyname();
+ struct nodeent *nep;
+
+ nep = getnodebyname(name);
+ if (nep == ((struct nodeent *)0))
+ return(0);
+
+ memcpy((char *)res, (char *)nep->n_addr, sizeof(unsigned short));
+ return(1);
+#else
+__pcap_nametodnaddr(const char *name _U_, u_short *res _U_)
+{
+ return(0);
+#endif
+}
diff --git a/lib/libpcap/libpcap/nametoaddr.h b/lib/libpcap/libpcap/nametoaddr.h
new file mode 100644
index 0000000..fd6b7e1
--- /dev/null
+++ b/lib/libpcap/libpcap/nametoaddr.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Routines used for name-or-address-string-to-address resolution
+ * that are *not* exported to code using libpcap.
+ */
+int __pcap_atodn(const char *, bpf_u_int32 *);
+int __pcap_atoin(const char *, bpf_u_int32 *);
+int __pcap_nametodnaddr(const char *, u_short *);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/libpcap/libpcap/nlpid.h b/lib/libpcap/libpcap/nlpid.h
new file mode 100644
index 0000000..9dfa752
--- /dev/null
+++ b/lib/libpcap/libpcap/nlpid.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1996
+ * Juniper Networks, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution. The name of Juniper Networks may not
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* Types missing from some systems */
+
+/*
+ * Network layer prototocol identifiers
+ */
+#ifndef ISO8473_CLNP
+#define ISO8473_CLNP 0x81
+#endif
+#ifndef ISO9542_ESIS
+#define ISO9542_ESIS 0x82
+#endif
+#ifndef ISO9542X25_ESIS
+#define ISO9542X25_ESIS 0x8a
+#endif
+#ifndef ISO10589_ISIS
+#define ISO10589_ISIS 0x83
+#endif
+/*
+ * this does not really belong in the nlpid.h file
+ * however we need it for generating nice
+ * IS-IS related BPF filters
+ */
+#define ISIS_L1_LAN_IIH 15
+#define ISIS_L2_LAN_IIH 16
+#define ISIS_PTP_IIH 17
+#define ISIS_L1_LSP 18
+#define ISIS_L2_LSP 20
+#define ISIS_L1_CSNP 24
+#define ISIS_L2_CSNP 25
+#define ISIS_L1_PSNP 26
+#define ISIS_L2_PSNP 27
+
+#ifndef ISO8878A_CONS
+#define ISO8878A_CONS 0x84
+#endif
+#ifndef ISO10747_IDRP
+#define ISO10747_IDRP 0x85
+#endif
diff --git a/lib/libpcap/libpcap/nomkdep b/lib/libpcap/libpcap/nomkdep
new file mode 100644
index 0000000..bed7366
--- /dev/null
+++ b/lib/libpcap/libpcap/nomkdep
@@ -0,0 +1,6 @@
+#!/bin/sh -
+#
+# Does nothing; used if we don't have a command-line flag to the compiler
+# to get it to generate dependencies.
+#
+exit 0
diff --git a/lib/libpcap/libpcap/optimize.c b/lib/libpcap/libpcap/optimize.c
new file mode 100644
index 0000000..448452d
--- /dev/null
+++ b/lib/libpcap/libpcap/optimize.c
@@ -0,0 +1,2664 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Optimization module for BPF code intermediate representation.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <setjmp.h>
+#include <string.h>
+
+#include <errno.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+#include "optimize.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef BDEBUG
+/*
+ * The internal "debug printout" flag for the filter expression optimizer.
+ * The code to print that stuff is present only if BDEBUG is defined, so
+ * the flag, and the routine to set it, are defined only if BDEBUG is
+ * defined.
+ */
+static int pcap_optimizer_debug;
+
+/*
+ * Routine to set that flag.
+ *
+ * This is intended for libpcap developers, not for general use.
+ * If you want to set these in a program, you'll have to declare this
+ * routine yourself, with the appropriate DLL import attribute on Windows;
+ * it's not declared in any header file, and won't be declared in any
+ * header file provided by libpcap.
+ */
+PCAP_API void pcap_set_optimizer_debug(int value);
+
+PCAP_API_DEF void
+pcap_set_optimizer_debug(int value)
+{
+ pcap_optimizer_debug = value;
+}
+
+/*
+ * The internal "print dot graph" flag for the filter expression optimizer.
+ * The code to print that stuff is present only if BDEBUG is defined, so
+ * the flag, and the routine to set it, are defined only if BDEBUG is
+ * defined.
+ */
+static int pcap_print_dot_graph;
+
+/*
+ * Routine to set that flag.
+ *
+ * This is intended for libpcap developers, not for general use.
+ * If you want to set these in a program, you'll have to declare this
+ * routine yourself, with the appropriate DLL import attribute on Windows;
+ * it's not declared in any header file, and won't be declared in any
+ * header file provided by libpcap.
+ */
+PCAP_API void pcap_set_print_dot_graph(int value);
+
+PCAP_API_DEF void
+pcap_set_print_dot_graph(int value)
+{
+ pcap_print_dot_graph = value;
+}
+
+#endif
+
+/*
+ * lowest_set_bit().
+ *
+ * Takes a 32-bit integer as an argument.
+ *
+ * If handed a non-zero value, returns the index of the lowest set bit,
+ * counting upwards fro zero.
+ *
+ * If handed zero, the results are platform- and compiler-dependent.
+ * Keep it out of the light, don't give it any water, don't feed it
+ * after midnight, and don't pass zero to it.
+ *
+ * This is the same as the count of trailing zeroes in the word.
+ */
+#if PCAP_IS_AT_LEAST_GNUC_VERSION(3,4)
+ /*
+ * GCC 3.4 and later; we have __builtin_ctz().
+ */
+ #define lowest_set_bit(mask) __builtin_ctz(mask)
+#elif defined(_MSC_VER)
+ /*
+ * Visual Studio; we support only 2005 and later, so use
+ * _BitScanForward().
+ */
+#include <intrin.h>
+
+#ifndef __clang__
+#pragma intrinsic(_BitScanForward)
+#endif
+
+static __forceinline int
+lowest_set_bit(int mask)
+{
+ unsigned long bit;
+
+ /*
+ * Don't sign-extend mask if long is longer than int.
+ * (It's currently not, in MSVC, even on 64-bit platforms, but....)
+ */
+ if (_BitScanForward(&bit, (unsigned int)mask) == 0)
+ return -1; /* mask is zero */
+ return (int)bit;
+}
+#elif defined(MSDOS) && defined(__DJGPP__)
+ /*
+ * MS-DOS with DJGPP, which declares ffs() in <string.h>, which
+ * we've already included.
+ */
+ #define lowest_set_bit(mask) (ffs((mask)) - 1)
+#elif (defined(MSDOS) && defined(__WATCOMC__)) || defined(STRINGS_H_DECLARES_FFS)
+ /*
+ * MS-DOS with Watcom C, which has <strings.h> and declares ffs() there,
+ * or some other platform (UN*X conforming to a sufficient recent version
+ * of the Single UNIX Specification).
+ */
+ #include <strings.h>
+ #define lowest_set_bit(mask) (ffs((mask)) - 1)
+#else
+/*
+ * None of the above.
+ * Use a perfect-hash-function-based function.
+ */
+static int
+lowest_set_bit(int mask)
+{
+ unsigned int v = (unsigned int)mask;
+
+ static const int MultiplyDeBruijnBitPosition[32] = {
+ 0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8,
+ 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9
+ };
+
+ /*
+ * We strip off all but the lowermost set bit (v & ~v),
+ * and perform a minimal perfect hash on it to look up the
+ * number of low-order zero bits in a table.
+ *
+ * See:
+ *
+ * http://7ooo.mooo.com/text/ComputingTrailingZerosHOWTO.pdf
+ *
+ * http://supertech.csail.mit.edu/papers/debruijn.pdf
+ */
+ return (MultiplyDeBruijnBitPosition[((v & -v) * 0x077CB531U) >> 27]);
+}
+#endif
+
+/*
+ * Represents a deleted instruction.
+ */
+#define NOP -1
+
+/*
+ * Register numbers for use-def values.
+ * 0 through BPF_MEMWORDS-1 represent the corresponding scratch memory
+ * location. A_ATOM is the accumulator and X_ATOM is the index
+ * register.
+ */
+#define A_ATOM BPF_MEMWORDS
+#define X_ATOM (BPF_MEMWORDS+1)
+
+/*
+ * This define is used to represent *both* the accumulator and
+ * x register in use-def computations.
+ * Currently, the use-def code assumes only one definition per instruction.
+ */
+#define AX_ATOM N_ATOMS
+
+/*
+ * These data structures are used in a Cocke and Shwarz style
+ * value numbering scheme. Since the flowgraph is acyclic,
+ * exit values can be propagated from a node's predecessors
+ * provided it is uniquely defined.
+ */
+struct valnode {
+ int code;
+ int v0, v1;
+ int val;
+ struct valnode *next;
+};
+
+/* Integer constants mapped with the load immediate opcode. */
+#define K(i) F(opt_state, BPF_LD|BPF_IMM|BPF_W, i, 0L)
+
+struct vmapinfo {
+ int is_const;
+ bpf_int32 const_val;
+};
+
+typedef struct {
+ /*
+ * Place to longjmp to on an error.
+ */
+ jmp_buf top_ctx;
+
+ /*
+ * The buffer into which to put error message.
+ */
+ char *errbuf;
+
+ /*
+ * A flag to indicate that further optimization is needed.
+ * Iterative passes are continued until a given pass yields no
+ * branch movement.
+ */
+ int done;
+
+ int n_blocks;
+ struct block **blocks;
+ int n_edges;
+ struct edge **edges;
+
+ /*
+ * A bit vector set representation of the dominators.
+ * We round up the set size to the next power of two.
+ */
+ int nodewords;
+ int edgewords;
+ struct block **levels;
+ bpf_u_int32 *space;
+
+#define BITS_PER_WORD (8*sizeof(bpf_u_int32))
+/*
+ * True if a is in uset {p}
+ */
+#define SET_MEMBER(p, a) \
+((p)[(unsigned)(a) / BITS_PER_WORD] & ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD)))
+
+/*
+ * Add 'a' to uset p.
+ */
+#define SET_INSERT(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] |= ((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * Delete 'a' from uset p.
+ */
+#define SET_DELETE(p, a) \
+(p)[(unsigned)(a) / BITS_PER_WORD] &= ~((bpf_u_int32)1 << ((unsigned)(a) % BITS_PER_WORD))
+
+/*
+ * a := a intersect b
+ */
+#define SET_INTERSECT(a, b, n)\
+{\
+ register bpf_u_int32 *_x = a, *_y = b;\
+ register int _n = n;\
+ while (--_n >= 0) *_x++ &= *_y++;\
+}
+
+/*
+ * a := a - b
+ */
+#define SET_SUBTRACT(a, b, n)\
+{\
+ register bpf_u_int32 *_x = a, *_y = b;\
+ register int _n = n;\
+ while (--_n >= 0) *_x++ &=~ *_y++;\
+}
+
+/*
+ * a := a union b
+ */
+#define SET_UNION(a, b, n)\
+{\
+ register bpf_u_int32 *_x = a, *_y = b;\
+ register int _n = n;\
+ while (--_n >= 0) *_x++ |= *_y++;\
+}
+
+ uset all_dom_sets;
+ uset all_closure_sets;
+ uset all_edge_sets;
+
+#define MODULUS 213
+ struct valnode *hashtbl[MODULUS];
+ int curval;
+ int maxval;
+
+ struct vmapinfo *vmap;
+ struct valnode *vnode_base;
+ struct valnode *next_vnode;
+} opt_state_t;
+
+typedef struct {
+ /*
+ * Place to longjmp to on an error.
+ */
+ jmp_buf top_ctx;
+
+ /*
+ * The buffer into which to put error message.
+ */
+ char *errbuf;
+
+ /*
+ * Some pointers used to convert the basic block form of the code,
+ * into the array form that BPF requires. 'fstart' will point to
+ * the malloc'd array while 'ftail' is used during the recursive
+ * traversal.
+ */
+ struct bpf_insn *fstart;
+ struct bpf_insn *ftail;
+} conv_state_t;
+
+static void opt_init(opt_state_t *, struct icode *);
+static void opt_cleanup(opt_state_t *);
+static void PCAP_NORETURN opt_error(opt_state_t *, const char *, ...)
+ PCAP_PRINTFLIKE(2, 3);
+
+static void intern_blocks(opt_state_t *, struct icode *);
+
+static void find_inedges(opt_state_t *, struct block *);
+#ifdef BDEBUG
+static void opt_dump(opt_state_t *, struct icode *);
+#endif
+
+#ifndef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+static void
+find_levels_r(opt_state_t *opt_state, struct icode *ic, struct block *b)
+{
+ int level;
+
+ if (isMarked(ic, b))
+ return;
+
+ Mark(ic, b);
+ b->link = 0;
+
+ if (JT(b)) {
+ find_levels_r(opt_state, ic, JT(b));
+ find_levels_r(opt_state, ic, JF(b));
+ level = MAX(JT(b)->level, JF(b)->level) + 1;
+ } else
+ level = 0;
+ b->level = level;
+ b->link = opt_state->levels[level];
+ opt_state->levels[level] = b;
+}
+
+/*
+ * Level graph. The levels go from 0 at the leaves to
+ * N_LEVELS at the root. The opt_state->levels[] array points to the
+ * first node of the level list, whose elements are linked
+ * with the 'link' field of the struct block.
+ */
+static void
+find_levels(opt_state_t *opt_state, struct icode *ic)
+{
+ memset((char *)opt_state->levels, 0, opt_state->n_blocks * sizeof(*opt_state->levels));
+ unMarkAll(ic);
+ find_levels_r(opt_state, ic, ic->root);
+}
+
+/*
+ * Find dominator relationships.
+ * Assumes graph has been leveled.
+ */
+static void
+find_dom(opt_state_t *opt_state, struct block *root)
+{
+ int i;
+ struct block *b;
+ bpf_u_int32 *x;
+
+ /*
+ * Initialize sets to contain all nodes.
+ */
+ x = opt_state->all_dom_sets;
+ i = opt_state->n_blocks * opt_state->nodewords;
+ while (--i >= 0)
+ *x++ = 0xFFFFFFFFU;
+ /* Root starts off empty. */
+ for (i = opt_state->nodewords; --i >= 0;)
+ root->dom[i] = 0;
+
+ /* root->level is the highest level no found. */
+ for (i = root->level; i >= 0; --i) {
+ for (b = opt_state->levels[i]; b; b = b->link) {
+ SET_INSERT(b->dom, b->id);
+ if (JT(b) == 0)
+ continue;
+ SET_INTERSECT(JT(b)->dom, b->dom, opt_state->nodewords);
+ SET_INTERSECT(JF(b)->dom, b->dom, opt_state->nodewords);
+ }
+ }
+}
+
+static void
+propedom(opt_state_t *opt_state, struct edge *ep)
+{
+ SET_INSERT(ep->edom, ep->id);
+ if (ep->succ) {
+ SET_INTERSECT(ep->succ->et.edom, ep->edom, opt_state->edgewords);
+ SET_INTERSECT(ep->succ->ef.edom, ep->edom, opt_state->edgewords);
+ }
+}
+
+/*
+ * Compute edge dominators.
+ * Assumes graph has been leveled and predecessors established.
+ */
+static void
+find_edom(opt_state_t *opt_state, struct block *root)
+{
+ int i;
+ uset x;
+ struct block *b;
+
+ x = opt_state->all_edge_sets;
+ for (i = opt_state->n_edges * opt_state->edgewords; --i >= 0; )
+ x[i] = 0xFFFFFFFFU;
+
+ /* root->level is the highest level no found. */
+ memset(root->et.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
+ memset(root->ef.edom, 0, opt_state->edgewords * sizeof(*(uset)0));
+ for (i = root->level; i >= 0; --i) {
+ for (b = opt_state->levels[i]; b != 0; b = b->link) {
+ propedom(opt_state, &b->et);
+ propedom(opt_state, &b->ef);
+ }
+ }
+}
+
+/*
+ * Find the backwards transitive closure of the flow graph. These sets
+ * are backwards in the sense that we find the set of nodes that reach
+ * a given node, not the set of nodes that can be reached by a node.
+ *
+ * Assumes graph has been leveled.
+ */
+static void
+find_closure(opt_state_t *opt_state, struct block *root)
+{
+ int i;
+ struct block *b;
+
+ /*
+ * Initialize sets to contain no nodes.
+ */
+ memset((char *)opt_state->all_closure_sets, 0,
+ opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->all_closure_sets));
+
+ /* root->level is the highest level no found. */
+ for (i = root->level; i >= 0; --i) {
+ for (b = opt_state->levels[i]; b; b = b->link) {
+ SET_INSERT(b->closure, b->id);
+ if (JT(b) == 0)
+ continue;
+ SET_UNION(JT(b)->closure, b->closure, opt_state->nodewords);
+ SET_UNION(JF(b)->closure, b->closure, opt_state->nodewords);
+ }
+ }
+}
+
+/*
+ * Return the register number that is used by s. If A and X are both
+ * used, return AX_ATOM. If no register is used, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomuse(struct stmt *s)
+{
+ register int c = s->code;
+
+ if (c == NOP)
+ return -1;
+
+ switch (BPF_CLASS(c)) {
+
+ case BPF_RET:
+ return (BPF_RVAL(c) == BPF_A) ? A_ATOM :
+ (BPF_RVAL(c) == BPF_X) ? X_ATOM : -1;
+
+ case BPF_LD:
+ case BPF_LDX:
+ return (BPF_MODE(c) == BPF_IND) ? X_ATOM :
+ (BPF_MODE(c) == BPF_MEM) ? s->k : -1;
+
+ case BPF_ST:
+ return A_ATOM;
+
+ case BPF_STX:
+ return X_ATOM;
+
+ case BPF_JMP:
+ case BPF_ALU:
+ if (BPF_SRC(c) == BPF_X)
+ return AX_ATOM;
+ return A_ATOM;
+
+ case BPF_MISC:
+ return BPF_MISCOP(c) == BPF_TXA ? X_ATOM : A_ATOM;
+ }
+ abort();
+ /* NOTREACHED */
+}
+
+/*
+ * Return the register number that is defined by 's'. We assume that
+ * a single stmt cannot define more than one register. If no register
+ * is defined, return -1.
+ *
+ * The implementation should probably change to an array access.
+ */
+static int
+atomdef(struct stmt *s)
+{
+ if (s->code == NOP)
+ return -1;
+
+ switch (BPF_CLASS(s->code)) {
+
+ case BPF_LD:
+ case BPF_ALU:
+ return A_ATOM;
+
+ case BPF_LDX:
+ return X_ATOM;
+
+ case BPF_ST:
+ case BPF_STX:
+ return s->k;
+
+ case BPF_MISC:
+ return BPF_MISCOP(s->code) == BPF_TAX ? X_ATOM : A_ATOM;
+ }
+ return -1;
+}
+
+/*
+ * Compute the sets of registers used, defined, and killed by 'b'.
+ *
+ * "Used" means that a statement in 'b' uses the register before any
+ * statement in 'b' defines it, i.e. it uses the value left in
+ * that register by a predecessor block of this block.
+ * "Defined" means that a statement in 'b' defines it.
+ * "Killed" means that a statement in 'b' defines it before any
+ * statement in 'b' uses it, i.e. it kills the value left in that
+ * register by a predecessor block of this block.
+ */
+static void
+compute_local_ud(struct block *b)
+{
+ struct slist *s;
+ atomset def = 0, use = 0, killed = 0;
+ int atom;
+
+ for (s = b->stmts; s; s = s->next) {
+ if (s->s.code == NOP)
+ continue;
+ atom = atomuse(&s->s);
+ if (atom >= 0) {
+ if (atom == AX_ATOM) {
+ if (!ATOMELEM(def, X_ATOM))
+ use |= ATOMMASK(X_ATOM);
+ if (!ATOMELEM(def, A_ATOM))
+ use |= ATOMMASK(A_ATOM);
+ }
+ else if (atom < N_ATOMS) {
+ if (!ATOMELEM(def, atom))
+ use |= ATOMMASK(atom);
+ }
+ else
+ abort();
+ }
+ atom = atomdef(&s->s);
+ if (atom >= 0) {
+ if (!ATOMELEM(use, atom))
+ killed |= ATOMMASK(atom);
+ def |= ATOMMASK(atom);
+ }
+ }
+ if (BPF_CLASS(b->s.code) == BPF_JMP) {
+ /*
+ * XXX - what about RET?
+ */
+ atom = atomuse(&b->s);
+ if (atom >= 0) {
+ if (atom == AX_ATOM) {
+ if (!ATOMELEM(def, X_ATOM))
+ use |= ATOMMASK(X_ATOM);
+ if (!ATOMELEM(def, A_ATOM))
+ use |= ATOMMASK(A_ATOM);
+ }
+ else if (atom < N_ATOMS) {
+ if (!ATOMELEM(def, atom))
+ use |= ATOMMASK(atom);
+ }
+ else
+ abort();
+ }
+ }
+
+ b->def = def;
+ b->kill = killed;
+ b->in_use = use;
+}
+
+/*
+ * Assume graph is already leveled.
+ */
+static void
+find_ud(opt_state_t *opt_state, struct block *root)
+{
+ int i, maxlevel;
+ struct block *p;
+
+ /*
+ * root->level is the highest level no found;
+ * count down from there.
+ */
+ maxlevel = root->level;
+ for (i = maxlevel; i >= 0; --i)
+ for (p = opt_state->levels[i]; p; p = p->link) {
+ compute_local_ud(p);
+ p->out_use = 0;
+ }
+
+ for (i = 1; i <= maxlevel; ++i) {
+ for (p = opt_state->levels[i]; p; p = p->link) {
+ p->out_use |= JT(p)->in_use | JF(p)->in_use;
+ p->in_use |= p->out_use &~ p->kill;
+ }
+ }
+}
+static void
+init_val(opt_state_t *opt_state)
+{
+ opt_state->curval = 0;
+ opt_state->next_vnode = opt_state->vnode_base;
+ memset((char *)opt_state->vmap, 0, opt_state->maxval * sizeof(*opt_state->vmap));
+ memset((char *)opt_state->hashtbl, 0, sizeof opt_state->hashtbl);
+}
+
+/* Because we really don't have an IR, this stuff is a little messy. */
+static int
+F(opt_state_t *opt_state, int code, int v0, int v1)
+{
+ u_int hash;
+ int val;
+ struct valnode *p;
+
+ hash = (u_int)code ^ ((u_int)v0 << 4) ^ ((u_int)v1 << 8);
+ hash %= MODULUS;
+
+ for (p = opt_state->hashtbl[hash]; p; p = p->next)
+ if (p->code == code && p->v0 == v0 && p->v1 == v1)
+ return p->val;
+
+ val = ++opt_state->curval;
+ if (BPF_MODE(code) == BPF_IMM &&
+ (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) {
+ opt_state->vmap[val].const_val = v0;
+ opt_state->vmap[val].is_const = 1;
+ }
+ p = opt_state->next_vnode++;
+ p->val = val;
+ p->code = code;
+ p->v0 = v0;
+ p->v1 = v1;
+ p->next = opt_state->hashtbl[hash];
+ opt_state->hashtbl[hash] = p;
+
+ return val;
+}
+
+static inline void
+vstore(struct stmt *s, int *valp, int newval, int alter)
+{
+ if (alter && newval != VAL_UNKNOWN && *valp == newval)
+ s->code = NOP;
+ else
+ *valp = newval;
+}
+
+/*
+ * Do constant-folding on binary operators.
+ * (Unary operators are handled elsewhere.)
+ */
+static void
+fold_op(opt_state_t *opt_state, struct stmt *s, int v0, int v1)
+{
+ bpf_u_int32 a, b;
+
+ a = opt_state->vmap[v0].const_val;
+ b = opt_state->vmap[v1].const_val;
+
+ switch (BPF_OP(s->code)) {
+ case BPF_ADD:
+ a += b;
+ break;
+
+ case BPF_SUB:
+ a -= b;
+ break;
+
+ case BPF_MUL:
+ a *= b;
+ break;
+
+ case BPF_DIV:
+ if (b == 0)
+ opt_error(opt_state, "division by zero");
+ a /= b;
+ break;
+
+ case BPF_MOD:
+ if (b == 0)
+ opt_error(opt_state, "modulus by zero");
+ a %= b;
+ break;
+
+ case BPF_AND:
+ a &= b;
+ break;
+
+ case BPF_OR:
+ a |= b;
+ break;
+
+ case BPF_XOR:
+ a ^= b;
+ break;
+
+ case BPF_LSH:
+ /*
+ * A left shift of more than the width of the type
+ * is undefined in C; we'll just treat it as shifting
+ * all the bits out.
+ *
+ * XXX - the BPF interpreter doesn't check for this,
+ * so its behavior is dependent on the behavior of
+ * the processor on which it's running. There are
+ * processors on which it shifts all the bits out
+ * and processors on which it does no shift.
+ */
+ if (b < 32)
+ a <<= b;
+ else
+ a = 0;
+ break;
+
+ case BPF_RSH:
+ /*
+ * A right shift of more than the width of the type
+ * is undefined in C; we'll just treat it as shifting
+ * all the bits out.
+ *
+ * XXX - the BPF interpreter doesn't check for this,
+ * so its behavior is dependent on the behavior of
+ * the processor on which it's running. There are
+ * processors on which it shifts all the bits out
+ * and processors on which it does no shift.
+ */
+ if (b < 32)
+ a >>= b;
+ else
+ a = 0;
+ break;
+
+ default:
+ abort();
+ }
+ s->k = a;
+ s->code = BPF_LD|BPF_IMM;
+ opt_state->done = 0;
+}
+
+static inline struct slist *
+this_op(struct slist *s)
+{
+ while (s != 0 && s->s.code == NOP)
+ s = s->next;
+ return s;
+}
+
+static void
+opt_not(struct block *b)
+{
+ struct block *tmp = JT(b);
+
+ JT(b) = JF(b);
+ JF(b) = tmp;
+}
+
+static void
+opt_peep(opt_state_t *opt_state, struct block *b)
+{
+ struct slist *s;
+ struct slist *next, *last;
+ int val;
+
+ s = b->stmts;
+ if (s == 0)
+ return;
+
+ last = s;
+ for (/*empty*/; /*empty*/; s = next) {
+ /*
+ * Skip over nops.
+ */
+ s = this_op(s);
+ if (s == 0)
+ break; /* nothing left in the block */
+
+ /*
+ * Find the next real instruction after that one
+ * (skipping nops).
+ */
+ next = this_op(s->next);
+ if (next == 0)
+ break; /* no next instruction */
+ last = next;
+
+ /*
+ * st M[k] --> st M[k]
+ * ldx M[k] tax
+ */
+ if (s->s.code == BPF_ST &&
+ next->s.code == (BPF_LDX|BPF_MEM) &&
+ s->s.k == next->s.k) {
+ opt_state->done = 0;
+ next->s.code = BPF_MISC|BPF_TAX;
+ }
+ /*
+ * ld #k --> ldx #k
+ * tax txa
+ */
+ if (s->s.code == (BPF_LD|BPF_IMM) &&
+ next->s.code == (BPF_MISC|BPF_TAX)) {
+ s->s.code = BPF_LDX|BPF_IMM;
+ next->s.code = BPF_MISC|BPF_TXA;
+ opt_state->done = 0;
+ }
+ /*
+ * This is an ugly special case, but it happens
+ * when you say tcp[k] or udp[k] where k is a constant.
+ */
+ if (s->s.code == (BPF_LD|BPF_IMM)) {
+ struct slist *add, *tax, *ild;
+
+ /*
+ * Check that X isn't used on exit from this
+ * block (which the optimizer might cause).
+ * We know the code generator won't generate
+ * any local dependencies.
+ */
+ if (ATOMELEM(b->out_use, X_ATOM))
+ continue;
+
+ /*
+ * Check that the instruction following the ldi
+ * is an addx, or it's an ldxms with an addx
+ * following it (with 0 or more nops between the
+ * ldxms and addx).
+ */
+ if (next->s.code != (BPF_LDX|BPF_MSH|BPF_B))
+ add = next;
+ else
+ add = this_op(next->next);
+ if (add == 0 || add->s.code != (BPF_ALU|BPF_ADD|BPF_X))
+ continue;
+
+ /*
+ * Check that a tax follows that (with 0 or more
+ * nops between them).
+ */
+ tax = this_op(add->next);
+ if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX))
+ continue;
+
+ /*
+ * Check that an ild follows that (with 0 or more
+ * nops between them).
+ */
+ ild = this_op(tax->next);
+ if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD ||
+ BPF_MODE(ild->s.code) != BPF_IND)
+ continue;
+ /*
+ * We want to turn this sequence:
+ *
+ * (004) ldi #0x2 {s}
+ * (005) ldxms [14] {next} -- optional
+ * (006) addx {add}
+ * (007) tax {tax}
+ * (008) ild [x+0] {ild}
+ *
+ * into this sequence:
+ *
+ * (004) nop
+ * (005) ldxms [14]
+ * (006) nop
+ * (007) nop
+ * (008) ild [x+2]
+ *
+ * XXX We need to check that X is not
+ * subsequently used, because we want to change
+ * what'll be in it after this sequence.
+ *
+ * We know we can eliminate the accumulator
+ * modifications earlier in the sequence since
+ * it is defined by the last stmt of this sequence
+ * (i.e., the last statement of the sequence loads
+ * a value into the accumulator, so we can eliminate
+ * earlier operations on the accumulator).
+ */
+ ild->s.k += s->s.k;
+ s->s.code = NOP;
+ add->s.code = NOP;
+ tax->s.code = NOP;
+ opt_state->done = 0;
+ }
+ }
+ /*
+ * If the comparison at the end of a block is an equality
+ * comparison against a constant, and nobody uses the value
+ * we leave in the A register at the end of a block, and
+ * the operation preceding the comparison is an arithmetic
+ * operation, we can sometime optimize it away.
+ */
+ if (b->s.code == (BPF_JMP|BPF_JEQ|BPF_K) &&
+ !ATOMELEM(b->out_use, A_ATOM)) {
+ /*
+ * We can optimize away certain subtractions of the
+ * X register.
+ */
+ if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X)) {
+ val = b->val[X_ATOM];
+ if (opt_state->vmap[val].is_const) {
+ /*
+ * If we have a subtract to do a comparison,
+ * and the X register is a known constant,
+ * we can merge this value into the
+ * comparison:
+ *
+ * sub x -> nop
+ * jeq #y jeq #(x+y)
+ */
+ b->s.k += opt_state->vmap[val].const_val;
+ last->s.code = NOP;
+ opt_state->done = 0;
+ } else if (b->s.k == 0) {
+ /*
+ * If the X register isn't a constant,
+ * and the comparison in the test is
+ * against 0, we can compare with the
+ * X register, instead:
+ *
+ * sub x -> nop
+ * jeq #0 jeq x
+ */
+ last->s.code = NOP;
+ b->s.code = BPF_JMP|BPF_JEQ|BPF_X;
+ opt_state->done = 0;
+ }
+ }
+ /*
+ * Likewise, a constant subtract can be simplified:
+ *
+ * sub #x -> nop
+ * jeq #y -> jeq #(x+y)
+ */
+ else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K)) {
+ last->s.code = NOP;
+ b->s.k += last->s.k;
+ opt_state->done = 0;
+ }
+ /*
+ * And, similarly, a constant AND can be simplified
+ * if we're testing against 0, i.e.:
+ *
+ * and #k nop
+ * jeq #0 -> jset #k
+ */
+ else if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) &&
+ b->s.k == 0) {
+ b->s.k = last->s.k;
+ b->s.code = BPF_JMP|BPF_K|BPF_JSET;
+ last->s.code = NOP;
+ opt_state->done = 0;
+ opt_not(b);
+ }
+ }
+ /*
+ * jset #0 -> never
+ * jset #ffffffff -> always
+ */
+ if (b->s.code == (BPF_JMP|BPF_K|BPF_JSET)) {
+ if (b->s.k == 0)
+ JT(b) = JF(b);
+ if ((u_int)b->s.k == 0xffffffffU)
+ JF(b) = JT(b);
+ }
+ /*
+ * If we're comparing against the index register, and the index
+ * register is a known constant, we can just compare against that
+ * constant.
+ */
+ val = b->val[X_ATOM];
+ if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_X) {
+ bpf_int32 v = opt_state->vmap[val].const_val;
+ b->s.code &= ~BPF_X;
+ b->s.k = v;
+ }
+ /*
+ * If the accumulator is a known constant, we can compute the
+ * comparison result.
+ */
+ val = b->val[A_ATOM];
+ if (opt_state->vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) {
+ bpf_int32 v = opt_state->vmap[val].const_val;
+ switch (BPF_OP(b->s.code)) {
+
+ case BPF_JEQ:
+ v = v == b->s.k;
+ break;
+
+ case BPF_JGT:
+ v = (unsigned)v > (unsigned)b->s.k;
+ break;
+
+ case BPF_JGE:
+ v = (unsigned)v >= (unsigned)b->s.k;
+ break;
+
+ case BPF_JSET:
+ v &= b->s.k;
+ break;
+
+ default:
+ abort();
+ }
+ if (JF(b) != JT(b))
+ opt_state->done = 0;
+ if (v)
+ JF(b) = JT(b);
+ else
+ JT(b) = JF(b);
+ }
+}
+
+/*
+ * Compute the symbolic value of expression of 's', and update
+ * anything it defines in the value table 'val'. If 'alter' is true,
+ * do various optimizations. This code would be cleaner if symbolic
+ * evaluation and code transformations weren't folded together.
+ */
+static void
+opt_stmt(opt_state_t *opt_state, struct stmt *s, int val[], int alter)
+{
+ int op;
+ int v;
+
+ switch (s->code) {
+
+ case BPF_LD|BPF_ABS|BPF_W:
+ case BPF_LD|BPF_ABS|BPF_H:
+ case BPF_LD|BPF_ABS|BPF_B:
+ v = F(opt_state, s->code, s->k, 0L);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LD|BPF_IND|BPF_W:
+ case BPF_LD|BPF_IND|BPF_H:
+ case BPF_LD|BPF_IND|BPF_B:
+ v = val[X_ATOM];
+ if (alter && opt_state->vmap[v].is_const) {
+ s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code);
+ s->k += opt_state->vmap[v].const_val;
+ v = F(opt_state, s->code, s->k, 0L);
+ opt_state->done = 0;
+ }
+ else
+ v = F(opt_state, s->code, s->k, v);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LD|BPF_LEN:
+ v = F(opt_state, s->code, 0L, 0L);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LD|BPF_IMM:
+ v = K(s->k);
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_LDX|BPF_IMM:
+ v = K(s->k);
+ vstore(s, &val[X_ATOM], v, alter);
+ break;
+
+ case BPF_LDX|BPF_MSH|BPF_B:
+ v = F(opt_state, s->code, s->k, 0L);
+ vstore(s, &val[X_ATOM], v, alter);
+ break;
+
+ case BPF_ALU|BPF_NEG:
+ if (alter && opt_state->vmap[val[A_ATOM]].is_const) {
+ s->code = BPF_LD|BPF_IMM;
+ /*
+ * Do this negation as unsigned arithmetic; that's
+ * what modern BPF engines do, and it guarantees
+ * that all possible values can be negated. (Yeah,
+ * negating 0x80000000, the minimum signed 32-bit
+ * two's-complement value, results in 0x80000000,
+ * so it's still negative, but we *should* be doing
+ * all unsigned arithmetic here, to match what
+ * modern BPF engines do.)
+ *
+ * Express it as 0U - (unsigned value) so that we
+ * don't get compiler warnings about negating an
+ * unsigned value and don't get UBSan warnings
+ * about the result of negating 0x80000000 being
+ * undefined.
+ */
+ s->k = 0U - (bpf_u_int32)(opt_state->vmap[val[A_ATOM]].const_val);
+ val[A_ATOM] = K(s->k);
+ }
+ else
+ val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], 0L);
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_K:
+ case BPF_ALU|BPF_SUB|BPF_K:
+ case BPF_ALU|BPF_MUL|BPF_K:
+ case BPF_ALU|BPF_DIV|BPF_K:
+ case BPF_ALU|BPF_MOD|BPF_K:
+ case BPF_ALU|BPF_AND|BPF_K:
+ case BPF_ALU|BPF_OR|BPF_K:
+ case BPF_ALU|BPF_XOR|BPF_K:
+ case BPF_ALU|BPF_LSH|BPF_K:
+ case BPF_ALU|BPF_RSH|BPF_K:
+ op = BPF_OP(s->code);
+ if (alter) {
+ if (s->k == 0) {
+ /*
+ * Optimize operations where the constant
+ * is zero.
+ *
+ * Don't optimize away "sub #0"
+ * as it may be needed later to
+ * fixup the generated math code.
+ *
+ * Fail if we're dividing by zero or taking
+ * a modulus by zero.
+ */
+ if (op == BPF_ADD ||
+ op == BPF_LSH || op == BPF_RSH ||
+ op == BPF_OR || op == BPF_XOR) {
+ s->code = NOP;
+ break;
+ }
+ if (op == BPF_MUL || op == BPF_AND) {
+ s->code = BPF_LD|BPF_IMM;
+ val[A_ATOM] = K(s->k);
+ break;
+ }
+ if (op == BPF_DIV)
+ opt_error(opt_state,
+ "division by zero");
+ if (op == BPF_MOD)
+ opt_error(opt_state,
+ "modulus by zero");
+ }
+ if (opt_state->vmap[val[A_ATOM]].is_const) {
+ fold_op(opt_state, s, val[A_ATOM], K(s->k));
+ val[A_ATOM] = K(s->k);
+ break;
+ }
+ }
+ val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], K(s->k));
+ break;
+
+ case BPF_ALU|BPF_ADD|BPF_X:
+ case BPF_ALU|BPF_SUB|BPF_X:
+ case BPF_ALU|BPF_MUL|BPF_X:
+ case BPF_ALU|BPF_DIV|BPF_X:
+ case BPF_ALU|BPF_MOD|BPF_X:
+ case BPF_ALU|BPF_AND|BPF_X:
+ case BPF_ALU|BPF_OR|BPF_X:
+ case BPF_ALU|BPF_XOR|BPF_X:
+ case BPF_ALU|BPF_LSH|BPF_X:
+ case BPF_ALU|BPF_RSH|BPF_X:
+ op = BPF_OP(s->code);
+ if (alter && opt_state->vmap[val[X_ATOM]].is_const) {
+ if (opt_state->vmap[val[A_ATOM]].is_const) {
+ fold_op(opt_state, s, val[A_ATOM], val[X_ATOM]);
+ val[A_ATOM] = K(s->k);
+ }
+ else {
+ s->code = BPF_ALU|BPF_K|op;
+ s->k = opt_state->vmap[val[X_ATOM]].const_val;
+ /*
+ * XXX - we need to make up our minds
+ * as to what integers are signed and
+ * what integers are unsigned in BPF
+ * programs and in our IR.
+ */
+ if ((op == BPF_LSH || op == BPF_RSH) &&
+ (s->k < 0 || s->k > 31))
+ opt_error(opt_state,
+ "shift by more than 31 bits");
+ opt_state->done = 0;
+ val[A_ATOM] =
+ F(opt_state, s->code, val[A_ATOM], K(s->k));
+ }
+ break;
+ }
+ /*
+ * Check if we're doing something to an accumulator
+ * that is 0, and simplify. This may not seem like
+ * much of a simplification but it could open up further
+ * optimizations.
+ * XXX We could also check for mul by 1, etc.
+ */
+ if (alter && opt_state->vmap[val[A_ATOM]].is_const
+ && opt_state->vmap[val[A_ATOM]].const_val == 0) {
+ if (op == BPF_ADD || op == BPF_OR || op == BPF_XOR) {
+ s->code = BPF_MISC|BPF_TXA;
+ vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+ break;
+ }
+ else if (op == BPF_MUL || op == BPF_DIV || op == BPF_MOD ||
+ op == BPF_AND || op == BPF_LSH || op == BPF_RSH) {
+ s->code = BPF_LD|BPF_IMM;
+ s->k = 0;
+ vstore(s, &val[A_ATOM], K(s->k), alter);
+ break;
+ }
+ else if (op == BPF_NEG) {
+ s->code = NOP;
+ break;
+ }
+ }
+ val[A_ATOM] = F(opt_state, s->code, val[A_ATOM], val[X_ATOM]);
+ break;
+
+ case BPF_MISC|BPF_TXA:
+ vstore(s, &val[A_ATOM], val[X_ATOM], alter);
+ break;
+
+ case BPF_LD|BPF_MEM:
+ v = val[s->k];
+ if (alter && opt_state->vmap[v].is_const) {
+ s->code = BPF_LD|BPF_IMM;
+ s->k = opt_state->vmap[v].const_val;
+ opt_state->done = 0;
+ }
+ vstore(s, &val[A_ATOM], v, alter);
+ break;
+
+ case BPF_MISC|BPF_TAX:
+ vstore(s, &val[X_ATOM], val[A_ATOM], alter);
+ break;
+
+ case BPF_LDX|BPF_MEM:
+ v = val[s->k];
+ if (alter && opt_state->vmap[v].is_const) {
+ s->code = BPF_LDX|BPF_IMM;
+ s->k = opt_state->vmap[v].const_val;
+ opt_state->done = 0;
+ }
+ vstore(s, &val[X_ATOM], v, alter);
+ break;
+
+ case BPF_ST:
+ vstore(s, &val[s->k], val[A_ATOM], alter);
+ break;
+
+ case BPF_STX:
+ vstore(s, &val[s->k], val[X_ATOM], alter);
+ break;
+ }
+}
+
+static void
+deadstmt(opt_state_t *opt_state, register struct stmt *s, register struct stmt *last[])
+{
+ register int atom;
+
+ atom = atomuse(s);
+ if (atom >= 0) {
+ if (atom == AX_ATOM) {
+ last[X_ATOM] = 0;
+ last[A_ATOM] = 0;
+ }
+ else
+ last[atom] = 0;
+ }
+ atom = atomdef(s);
+ if (atom >= 0) {
+ if (last[atom]) {
+ opt_state->done = 0;
+ last[atom]->code = NOP;
+ }
+ last[atom] = s;
+ }
+}
+
+static void
+opt_deadstores(opt_state_t *opt_state, register struct block *b)
+{
+ register struct slist *s;
+ register int atom;
+ struct stmt *last[N_ATOMS];
+
+ memset((char *)last, 0, sizeof last);
+
+ for (s = b->stmts; s != 0; s = s->next)
+ deadstmt(opt_state, &s->s, last);
+ deadstmt(opt_state, &b->s, last);
+
+ for (atom = 0; atom < N_ATOMS; ++atom)
+ if (last[atom] && !ATOMELEM(b->out_use, atom)) {
+ last[atom]->code = NOP;
+ opt_state->done = 0;
+ }
+}
+
+static void
+opt_blk(opt_state_t *opt_state, struct block *b, int do_stmts)
+{
+ struct slist *s;
+ struct edge *p;
+ int i;
+ bpf_int32 aval, xval;
+
+#if 0
+ for (s = b->stmts; s && s->next; s = s->next)
+ if (BPF_CLASS(s->s.code) == BPF_JMP) {
+ do_stmts = 0;
+ break;
+ }
+#endif
+
+ /*
+ * Initialize the atom values.
+ */
+ p = b->in_edges;
+ if (p == 0) {
+ /*
+ * We have no predecessors, so everything is undefined
+ * upon entry to this block.
+ */
+ memset((char *)b->val, 0, sizeof(b->val));
+ } else {
+ /*
+ * Inherit values from our predecessors.
+ *
+ * First, get the values from the predecessor along the
+ * first edge leading to this node.
+ */
+ memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val));
+ /*
+ * Now look at all the other nodes leading to this node.
+ * If, for the predecessor along that edge, a register
+ * has a different value from the one we have (i.e.,
+ * control paths are merging, and the merging paths
+ * assign different values to that register), give the
+ * register the undefined value of 0.
+ */
+ while ((p = p->next) != NULL) {
+ for (i = 0; i < N_ATOMS; ++i)
+ if (b->val[i] != p->pred->val[i])
+ b->val[i] = 0;
+ }
+ }
+ aval = b->val[A_ATOM];
+ xval = b->val[X_ATOM];
+ for (s = b->stmts; s; s = s->next)
+ opt_stmt(opt_state, &s->s, b->val, do_stmts);
+
+ /*
+ * This is a special case: if we don't use anything from this
+ * block, and we load the accumulator or index register with a
+ * value that is already there, or if this block is a return,
+ * eliminate all the statements.
+ *
+ * XXX - what if it does a store?
+ *
+ * XXX - why does it matter whether we use anything from this
+ * block? If the accumulator or index register doesn't change
+ * its value, isn't that OK even if we use that value?
+ *
+ * XXX - if we load the accumulator with a different value,
+ * and the block ends with a conditional branch, we obviously
+ * can't eliminate it, as the branch depends on that value.
+ * For the index register, the conditional branch only depends
+ * on the index register value if the test is against the index
+ * register value rather than a constant; if nothing uses the
+ * value we put into the index register, and we're not testing
+ * against the index register's value, and there aren't any
+ * other problems that would keep us from eliminating this
+ * block, can we eliminate it?
+ */
+ if (do_stmts &&
+ ((b->out_use == 0 &&
+ aval != VAL_UNKNOWN && b->val[A_ATOM] == aval &&
+ xval != VAL_UNKNOWN && b->val[X_ATOM] == xval) ||
+ BPF_CLASS(b->s.code) == BPF_RET)) {
+ if (b->stmts != 0) {
+ b->stmts = 0;
+ opt_state->done = 0;
+ }
+ } else {
+ opt_peep(opt_state, b);
+ opt_deadstores(opt_state, b);
+ }
+ /*
+ * Set up values for branch optimizer.
+ */
+ if (BPF_SRC(b->s.code) == BPF_K)
+ b->oval = K(b->s.k);
+ else
+ b->oval = b->val[X_ATOM];
+ b->et.code = b->s.code;
+ b->ef.code = -b->s.code;
+}
+
+/*
+ * Return true if any register that is used on exit from 'succ', has
+ * an exit value that is different from the corresponding exit value
+ * from 'b'.
+ */
+static int
+use_conflict(struct block *b, struct block *succ)
+{
+ int atom;
+ atomset use = succ->out_use;
+
+ if (use == 0)
+ return 0;
+
+ for (atom = 0; atom < N_ATOMS; ++atom)
+ if (ATOMELEM(use, atom))
+ if (b->val[atom] != succ->val[atom])
+ return 1;
+ return 0;
+}
+
+static struct block *
+fold_edge(struct block *child, struct edge *ep)
+{
+ int sense;
+ int aval0, aval1, oval0, oval1;
+ int code = ep->code;
+
+ if (code < 0) {
+ code = -code;
+ sense = 0;
+ } else
+ sense = 1;
+
+ if (child->s.code != code)
+ return 0;
+
+ aval0 = child->val[A_ATOM];
+ oval0 = child->oval;
+ aval1 = ep->pred->val[A_ATOM];
+ oval1 = ep->pred->oval;
+
+ if (aval0 != aval1)
+ return 0;
+
+ if (oval0 == oval1)
+ /*
+ * The operands of the branch instructions are
+ * identical, so the result is true if a true
+ * branch was taken to get here, otherwise false.
+ */
+ return sense ? JT(child) : JF(child);
+
+ if (sense && code == (BPF_JMP|BPF_JEQ|BPF_K))
+ /*
+ * At this point, we only know the comparison if we
+ * came down the true branch, and it was an equality
+ * comparison with a constant.
+ *
+ * I.e., if we came down the true branch, and the branch
+ * was an equality comparison with a constant, we know the
+ * accumulator contains that constant. If we came down
+ * the false branch, or the comparison wasn't with a
+ * constant, we don't know what was in the accumulator.
+ *
+ * We rely on the fact that distinct constants have distinct
+ * value numbers.
+ */
+ return JF(child);
+
+ return 0;
+}
+
+static void
+opt_j(opt_state_t *opt_state, struct edge *ep)
+{
+ register int i, k;
+ register struct block *target;
+
+ if (JT(ep->succ) == 0)
+ return;
+
+ if (JT(ep->succ) == JF(ep->succ)) {
+ /*
+ * Common branch targets can be eliminated, provided
+ * there is no data dependency.
+ */
+ if (!use_conflict(ep->pred, ep->succ->et.succ)) {
+ opt_state->done = 0;
+ ep->succ = JT(ep->succ);
+ }
+ }
+ /*
+ * For each edge dominator that matches the successor of this
+ * edge, promote the edge successor to the its grandchild.
+ *
+ * XXX We violate the set abstraction here in favor a reasonably
+ * efficient loop.
+ */
+ top:
+ for (i = 0; i < opt_state->edgewords; ++i) {
+ register bpf_u_int32 x = ep->edom[i];
+
+ while (x != 0) {
+ k = lowest_set_bit(x);
+ x &=~ ((bpf_u_int32)1 << k);
+ k += i * BITS_PER_WORD;
+
+ target = fold_edge(ep->succ, opt_state->edges[k]);
+ /*
+ * Check that there is no data dependency between
+ * nodes that will be violated if we move the edge.
+ */
+ if (target != 0 && !use_conflict(ep->pred, target)) {
+ opt_state->done = 0;
+ ep->succ = target;
+ if (JT(target) != 0)
+ /*
+ * Start over unless we hit a leaf.
+ */
+ goto top;
+ return;
+ }
+ }
+ }
+}
+
+
+static void
+or_pullup(opt_state_t *opt_state, struct block *b)
+{
+ int val, at_top;
+ struct block *pull;
+ struct block **diffp, **samep;
+ struct edge *ep;
+
+ ep = b->in_edges;
+ if (ep == 0)
+ return;
+
+ /*
+ * Make sure each predecessor loads the same value.
+ * XXX why?
+ */
+ val = ep->pred->val[A_ATOM];
+ for (ep = ep->next; ep != 0; ep = ep->next)
+ if (val != ep->pred->val[A_ATOM])
+ return;
+
+ if (JT(b->in_edges->pred) == b)
+ diffp = &JT(b->in_edges->pred);
+ else
+ diffp = &JF(b->in_edges->pred);
+
+ at_top = 1;
+ for (;;) {
+ if (*diffp == 0)
+ return;
+
+ if (JT(*diffp) != JT(b))
+ return;
+
+ if (!SET_MEMBER((*diffp)->dom, b->id))
+ return;
+
+ if ((*diffp)->val[A_ATOM] != val)
+ break;
+
+ diffp = &JF(*diffp);
+ at_top = 0;
+ }
+ samep = &JF(*diffp);
+ for (;;) {
+ if (*samep == 0)
+ return;
+
+ if (JT(*samep) != JT(b))
+ return;
+
+ if (!SET_MEMBER((*samep)->dom, b->id))
+ return;
+
+ if ((*samep)->val[A_ATOM] == val)
+ break;
+
+ /* XXX Need to check that there are no data dependencies
+ between dp0 and dp1. Currently, the code generator
+ will not produce such dependencies. */
+ samep = &JF(*samep);
+ }
+#ifdef notdef
+ /* XXX This doesn't cover everything. */
+ for (i = 0; i < N_ATOMS; ++i)
+ if ((*samep)->val[i] != pred->val[i])
+ return;
+#endif
+ /* Pull up the node. */
+ pull = *samep;
+ *samep = JF(pull);
+ JF(pull) = *diffp;
+
+ /*
+ * At the top of the chain, each predecessor needs to point at the
+ * pulled up node. Inside the chain, there is only one predecessor
+ * to worry about.
+ */
+ if (at_top) {
+ for (ep = b->in_edges; ep != 0; ep = ep->next) {
+ if (JT(ep->pred) == b)
+ JT(ep->pred) = pull;
+ else
+ JF(ep->pred) = pull;
+ }
+ }
+ else
+ *diffp = pull;
+
+ opt_state->done = 0;
+}
+
+static void
+and_pullup(opt_state_t *opt_state, struct block *b)
+{
+ int val, at_top;
+ struct block *pull;
+ struct block **diffp, **samep;
+ struct edge *ep;
+
+ ep = b->in_edges;
+ if (ep == 0)
+ return;
+
+ /*
+ * Make sure each predecessor loads the same value.
+ */
+ val = ep->pred->val[A_ATOM];
+ for (ep = ep->next; ep != 0; ep = ep->next)
+ if (val != ep->pred->val[A_ATOM])
+ return;
+
+ if (JT(b->in_edges->pred) == b)
+ diffp = &JT(b->in_edges->pred);
+ else
+ diffp = &JF(b->in_edges->pred);
+
+ at_top = 1;
+ for (;;) {
+ if (*diffp == 0)
+ return;
+
+ if (JF(*diffp) != JF(b))
+ return;
+
+ if (!SET_MEMBER((*diffp)->dom, b->id))
+ return;
+
+ if ((*diffp)->val[A_ATOM] != val)
+ break;
+
+ diffp = &JT(*diffp);
+ at_top = 0;
+ }
+ samep = &JT(*diffp);
+ for (;;) {
+ if (*samep == 0)
+ return;
+
+ if (JF(*samep) != JF(b))
+ return;
+
+ if (!SET_MEMBER((*samep)->dom, b->id))
+ return;
+
+ if ((*samep)->val[A_ATOM] == val)
+ break;
+
+ /* XXX Need to check that there are no data dependencies
+ between diffp and samep. Currently, the code generator
+ will not produce such dependencies. */
+ samep = &JT(*samep);
+ }
+#ifdef notdef
+ /* XXX This doesn't cover everything. */
+ for (i = 0; i < N_ATOMS; ++i)
+ if ((*samep)->val[i] != pred->val[i])
+ return;
+#endif
+ /* Pull up the node. */
+ pull = *samep;
+ *samep = JT(pull);
+ JT(pull) = *diffp;
+
+ /*
+ * At the top of the chain, each predecessor needs to point at the
+ * pulled up node. Inside the chain, there is only one predecessor
+ * to worry about.
+ */
+ if (at_top) {
+ for (ep = b->in_edges; ep != 0; ep = ep->next) {
+ if (JT(ep->pred) == b)
+ JT(ep->pred) = pull;
+ else
+ JF(ep->pred) = pull;
+ }
+ }
+ else
+ *diffp = pull;
+
+ opt_state->done = 0;
+}
+
+static void
+opt_blks(opt_state_t *opt_state, struct icode *ic, int do_stmts)
+{
+ int i, maxlevel;
+ struct block *p;
+
+ init_val(opt_state);
+ maxlevel = ic->root->level;
+
+ find_inedges(opt_state, ic->root);
+ for (i = maxlevel; i >= 0; --i)
+ for (p = opt_state->levels[i]; p; p = p->link)
+ opt_blk(opt_state, p, do_stmts);
+
+ if (do_stmts)
+ /*
+ * No point trying to move branches; it can't possibly
+ * make a difference at this point.
+ */
+ return;
+
+ for (i = 1; i <= maxlevel; ++i) {
+ for (p = opt_state->levels[i]; p; p = p->link) {
+ opt_j(opt_state, &p->et);
+ opt_j(opt_state, &p->ef);
+ }
+ }
+
+ find_inedges(opt_state, ic->root);
+ for (i = 1; i <= maxlevel; ++i) {
+ for (p = opt_state->levels[i]; p; p = p->link) {
+ or_pullup(opt_state, p);
+ and_pullup(opt_state, p);
+ }
+ }
+}
+
+static inline void
+link_inedge(struct edge *parent, struct block *child)
+{
+ parent->next = child->in_edges;
+ child->in_edges = parent;
+}
+
+static void
+find_inedges(opt_state_t *opt_state, struct block *root)
+{
+ int i;
+ struct block *b;
+
+ for (i = 0; i < opt_state->n_blocks; ++i)
+ opt_state->blocks[i]->in_edges = 0;
+
+ /*
+ * Traverse the graph, adding each edge to the predecessor
+ * list of its successors. Skip the leaves (i.e. level 0).
+ */
+ for (i = root->level; i > 0; --i) {
+ for (b = opt_state->levels[i]; b != 0; b = b->link) {
+ link_inedge(&b->et, JT(b));
+ link_inedge(&b->ef, JF(b));
+ }
+ }
+}
+
+static void
+opt_root(struct block **b)
+{
+ struct slist *tmp, *s;
+
+ s = (*b)->stmts;
+ (*b)->stmts = 0;
+ while (BPF_CLASS((*b)->s.code) == BPF_JMP && JT(*b) == JF(*b))
+ *b = JT(*b);
+
+ tmp = (*b)->stmts;
+ if (tmp != 0)
+ sappend(s, tmp);
+ (*b)->stmts = s;
+
+ /*
+ * If the root node is a return, then there is no
+ * point executing any statements (since the bpf machine
+ * has no side effects).
+ */
+ if (BPF_CLASS((*b)->s.code) == BPF_RET)
+ (*b)->stmts = 0;
+}
+
+static void
+opt_loop(opt_state_t *opt_state, struct icode *ic, int do_stmts)
+{
+
+#ifdef BDEBUG
+ if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
+ printf("opt_loop(root, %d) begin\n", do_stmts);
+ opt_dump(opt_state, ic);
+ }
+#endif
+ do {
+ opt_state->done = 1;
+ find_levels(opt_state, ic);
+ find_dom(opt_state, ic->root);
+ find_closure(opt_state, ic->root);
+ find_ud(opt_state, ic->root);
+ find_edom(opt_state, ic->root);
+ opt_blks(opt_state, ic, do_stmts);
+#ifdef BDEBUG
+ if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
+ printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, opt_state->done);
+ opt_dump(opt_state, ic);
+ }
+#endif
+ } while (!opt_state->done);
+}
+
+/*
+ * Optimize the filter code in its dag representation.
+ * Return 0 on success, -1 on error.
+ */
+int
+bpf_optimize(struct icode *ic, char *errbuf)
+{
+ opt_state_t opt_state;
+
+ memset(&opt_state, 0, sizeof(opt_state));
+ opt_state.errbuf = errbuf;
+ if (setjmp(opt_state.top_ctx)) {
+ opt_cleanup(&opt_state);
+ return -1;
+ }
+ opt_init(&opt_state, ic);
+ opt_loop(&opt_state, ic, 0);
+ opt_loop(&opt_state, ic, 1);
+ intern_blocks(&opt_state, ic);
+#ifdef BDEBUG
+ if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
+ printf("after intern_blocks()\n");
+ opt_dump(&opt_state, ic);
+ }
+#endif
+ opt_root(&ic->root);
+#ifdef BDEBUG
+ if (pcap_optimizer_debug > 1 || pcap_print_dot_graph) {
+ printf("after opt_root()\n");
+ opt_dump(&opt_state, ic);
+ }
+#endif
+ opt_cleanup(&opt_state);
+ return 0;
+}
+
+static void
+make_marks(struct icode *ic, struct block *p)
+{
+ if (!isMarked(ic, p)) {
+ Mark(ic, p);
+ if (BPF_CLASS(p->s.code) != BPF_RET) {
+ make_marks(ic, JT(p));
+ make_marks(ic, JF(p));
+ }
+ }
+}
+
+/*
+ * Mark code array such that isMarked(ic->cur_mark, i) is true
+ * only for nodes that are alive.
+ */
+static void
+mark_code(struct icode *ic)
+{
+ ic->cur_mark += 1;
+ make_marks(ic, ic->root);
+}
+
+/*
+ * True iff the two stmt lists load the same value from the packet into
+ * the accumulator.
+ */
+static int
+eq_slist(struct slist *x, struct slist *y)
+{
+ for (;;) {
+ while (x && x->s.code == NOP)
+ x = x->next;
+ while (y && y->s.code == NOP)
+ y = y->next;
+ if (x == 0)
+ return y == 0;
+ if (y == 0)
+ return x == 0;
+ if (x->s.code != y->s.code || x->s.k != y->s.k)
+ return 0;
+ x = x->next;
+ y = y->next;
+ }
+}
+
+static inline int
+eq_blk(struct block *b0, struct block *b1)
+{
+ if (b0->s.code == b1->s.code &&
+ b0->s.k == b1->s.k &&
+ b0->et.succ == b1->et.succ &&
+ b0->ef.succ == b1->ef.succ)
+ return eq_slist(b0->stmts, b1->stmts);
+ return 0;
+}
+
+static void
+intern_blocks(opt_state_t *opt_state, struct icode *ic)
+{
+ struct block *p;
+ int i, j;
+ int done1; /* don't shadow global */
+ top:
+ done1 = 1;
+ for (i = 0; i < opt_state->n_blocks; ++i)
+ opt_state->blocks[i]->link = 0;
+
+ mark_code(ic);
+
+ for (i = opt_state->n_blocks - 1; --i >= 0; ) {
+ if (!isMarked(ic, opt_state->blocks[i]))
+ continue;
+ for (j = i + 1; j < opt_state->n_blocks; ++j) {
+ if (!isMarked(ic, opt_state->blocks[j]))
+ continue;
+ if (eq_blk(opt_state->blocks[i], opt_state->blocks[j])) {
+ opt_state->blocks[i]->link = opt_state->blocks[j]->link ?
+ opt_state->blocks[j]->link : opt_state->blocks[j];
+ break;
+ }
+ }
+ }
+ for (i = 0; i < opt_state->n_blocks; ++i) {
+ p = opt_state->blocks[i];
+ if (JT(p) == 0)
+ continue;
+ if (JT(p)->link) {
+ done1 = 0;
+ JT(p) = JT(p)->link;
+ }
+ if (JF(p)->link) {
+ done1 = 0;
+ JF(p) = JF(p)->link;
+ }
+ }
+ if (!done1)
+ goto top;
+}
+
+static void
+opt_cleanup(opt_state_t *opt_state)
+{
+ free((void *)opt_state->vnode_base);
+ free((void *)opt_state->vmap);
+ free((void *)opt_state->edges);
+ free((void *)opt_state->space);
+ free((void *)opt_state->levels);
+ free((void *)opt_state->blocks);
+}
+
+/*
+ * For optimizer errors.
+ */
+static void PCAP_NORETURN
+opt_error(opt_state_t *opt_state, const char *fmt, ...)
+{
+ va_list ap;
+
+ if (opt_state->errbuf != NULL) {
+ va_start(ap, fmt);
+ (void)pcap_vsnprintf(opt_state->errbuf,
+ PCAP_ERRBUF_SIZE, fmt, ap);
+ va_end(ap);
+ }
+ longjmp(opt_state->top_ctx, 1);
+ /* NOTREACHED */
+}
+
+/*
+ * Return the number of stmts in 's'.
+ */
+static u_int
+slength(struct slist *s)
+{
+ u_int n = 0;
+
+ for (; s; s = s->next)
+ if (s->s.code != NOP)
+ ++n;
+ return n;
+}
+
+/*
+ * Return the number of nodes reachable by 'p'.
+ * All nodes should be initially unmarked.
+ */
+static int
+count_blocks(struct icode *ic, struct block *p)
+{
+ if (p == 0 || isMarked(ic, p))
+ return 0;
+ Mark(ic, p);
+ return count_blocks(ic, JT(p)) + count_blocks(ic, JF(p)) + 1;
+}
+
+/*
+ * Do a depth first search on the flow graph, numbering the
+ * the basic blocks, and entering them into the 'blocks' array.`
+ */
+static void
+number_blks_r(opt_state_t *opt_state, struct icode *ic, struct block *p)
+{
+ int n;
+
+ if (p == 0 || isMarked(ic, p))
+ return;
+
+ Mark(ic, p);
+ n = opt_state->n_blocks++;
+ p->id = n;
+ opt_state->blocks[n] = p;
+
+ number_blks_r(opt_state, ic, JT(p));
+ number_blks_r(opt_state, ic, JF(p));
+}
+
+/*
+ * Return the number of stmts in the flowgraph reachable by 'p'.
+ * The nodes should be unmarked before calling.
+ *
+ * Note that "stmts" means "instructions", and that this includes
+ *
+ * side-effect statements in 'p' (slength(p->stmts));
+ *
+ * statements in the true branch from 'p' (count_stmts(JT(p)));
+ *
+ * statements in the false branch from 'p' (count_stmts(JF(p)));
+ *
+ * the conditional jump itself (1);
+ *
+ * an extra long jump if the true branch requires it (p->longjt);
+ *
+ * an extra long jump if the false branch requires it (p->longjf).
+ */
+static u_int
+count_stmts(struct icode *ic, struct block *p)
+{
+ u_int n;
+
+ if (p == 0 || isMarked(ic, p))
+ return 0;
+ Mark(ic, p);
+ n = count_stmts(ic, JT(p)) + count_stmts(ic, JF(p));
+ return slength(p->stmts) + n + 1 + p->longjt + p->longjf;
+}
+
+/*
+ * Allocate memory. All allocation is done before optimization
+ * is begun. A linear bound on the size of all data structures is computed
+ * from the total number of blocks and/or statements.
+ */
+static void
+opt_init(opt_state_t *opt_state, struct icode *ic)
+{
+ bpf_u_int32 *p;
+ int i, n, max_stmts;
+
+ /*
+ * First, count the blocks, so we can malloc an array to map
+ * block number to block. Then, put the blocks into the array.
+ */
+ unMarkAll(ic);
+ n = count_blocks(ic, ic->root);
+ opt_state->blocks = (struct block **)calloc(n, sizeof(*opt_state->blocks));
+ if (opt_state->blocks == NULL)
+ opt_error(opt_state, "malloc");
+ unMarkAll(ic);
+ opt_state->n_blocks = 0;
+ number_blks_r(opt_state, ic, ic->root);
+
+ opt_state->n_edges = 2 * opt_state->n_blocks;
+ opt_state->edges = (struct edge **)calloc(opt_state->n_edges, sizeof(*opt_state->edges));
+ if (opt_state->edges == NULL) {
+ opt_error(opt_state, "malloc");
+ }
+
+ /*
+ * The number of levels is bounded by the number of nodes.
+ */
+ opt_state->levels = (struct block **)calloc(opt_state->n_blocks, sizeof(*opt_state->levels));
+ if (opt_state->levels == NULL) {
+ opt_error(opt_state, "malloc");
+ }
+
+ opt_state->edgewords = opt_state->n_edges / (8 * sizeof(bpf_u_int32)) + 1;
+ opt_state->nodewords = opt_state->n_blocks / (8 * sizeof(bpf_u_int32)) + 1;
+
+ /* XXX */
+ opt_state->space = (bpf_u_int32 *)malloc(2 * opt_state->n_blocks * opt_state->nodewords * sizeof(*opt_state->space)
+ + opt_state->n_edges * opt_state->edgewords * sizeof(*opt_state->space));
+ if (opt_state->space == NULL) {
+ opt_error(opt_state, "malloc");
+ }
+ p = opt_state->space;
+ opt_state->all_dom_sets = p;
+ for (i = 0; i < n; ++i) {
+ opt_state->blocks[i]->dom = p;
+ p += opt_state->nodewords;
+ }
+ opt_state->all_closure_sets = p;
+ for (i = 0; i < n; ++i) {
+ opt_state->blocks[i]->closure = p;
+ p += opt_state->nodewords;
+ }
+ opt_state->all_edge_sets = p;
+ for (i = 0; i < n; ++i) {
+ register struct block *b = opt_state->blocks[i];
+
+ b->et.edom = p;
+ p += opt_state->edgewords;
+ b->ef.edom = p;
+ p += opt_state->edgewords;
+ b->et.id = i;
+ opt_state->edges[i] = &b->et;
+ b->ef.id = opt_state->n_blocks + i;
+ opt_state->edges[opt_state->n_blocks + i] = &b->ef;
+ b->et.pred = b;
+ b->ef.pred = b;
+ }
+ max_stmts = 0;
+ for (i = 0; i < n; ++i)
+ max_stmts += slength(opt_state->blocks[i]->stmts) + 1;
+ /*
+ * We allocate at most 3 value numbers per statement,
+ * so this is an upper bound on the number of valnodes
+ * we'll need.
+ */
+ opt_state->maxval = 3 * max_stmts;
+ opt_state->vmap = (struct vmapinfo *)calloc(opt_state->maxval, sizeof(*opt_state->vmap));
+ if (opt_state->vmap == NULL) {
+ opt_error(opt_state, "malloc");
+ }
+ opt_state->vnode_base = (struct valnode *)calloc(opt_state->maxval, sizeof(*opt_state->vnode_base));
+ if (opt_state->vnode_base == NULL) {
+ opt_error(opt_state, "malloc");
+ }
+}
+
+/*
+ * This is only used when supporting optimizer debugging. It is
+ * global state, so do *not* do more than one compile in parallel
+ * and expect it to provide meaningful information.
+ */
+#ifdef BDEBUG
+int bids[NBIDS];
+#endif
+
+static void PCAP_NORETURN conv_error(conv_state_t *, const char *, ...)
+ PCAP_PRINTFLIKE(2, 3);
+
+/*
+ * Returns true if successful. Returns false if a branch has
+ * an offset that is too large. If so, we have marked that
+ * branch so that on a subsequent iteration, it will be treated
+ * properly.
+ */
+static int
+convert_code_r(conv_state_t *conv_state, struct icode *ic, struct block *p)
+{
+ struct bpf_insn *dst;
+ struct slist *src;
+ u_int slen;
+ u_int off;
+ u_int extrajmps; /* number of extra jumps inserted */
+ struct slist **offset = NULL;
+
+ if (p == 0 || isMarked(ic, p))
+ return (1);
+ Mark(ic, p);
+
+ if (convert_code_r(conv_state, ic, JF(p)) == 0)
+ return (0);
+ if (convert_code_r(conv_state, ic, JT(p)) == 0)
+ return (0);
+
+ slen = slength(p->stmts);
+ dst = conv_state->ftail -= (slen + 1 + p->longjt + p->longjf);
+ /* inflate length by any extra jumps */
+
+ p->offset = (int)(dst - conv_state->fstart);
+
+ /* generate offset[] for convenience */
+ if (slen) {
+ offset = (struct slist **)calloc(slen, sizeof(struct slist *));
+ if (!offset) {
+ conv_error(conv_state, "not enough core");
+ /*NOTREACHED*/
+ }
+ }
+ src = p->stmts;
+ for (off = 0; off < slen && src; off++) {
+#if 0
+ printf("off=%d src=%x\n", off, src);
+#endif
+ offset[off] = src;
+ src = src->next;
+ }
+
+ off = 0;
+ for (src = p->stmts; src; src = src->next) {
+ if (src->s.code == NOP)
+ continue;
+ dst->code = (u_short)src->s.code;
+ dst->k = src->s.k;
+
+ /* fill block-local relative jump */
+ if (BPF_CLASS(src->s.code) != BPF_JMP || src->s.code == (BPF_JMP|BPF_JA)) {
+#if 0
+ if (src->s.jt || src->s.jf) {
+ free(offset);
+ conv_error(conv_state, "illegal jmp destination");
+ /*NOTREACHED*/
+ }
+#endif
+ goto filled;
+ }
+ if (off == slen - 2) /*???*/
+ goto filled;
+
+ {
+ u_int i;
+ int jt, jf;
+ const char ljerr[] = "%s for block-local relative jump: off=%d";
+
+#if 0
+ printf("code=%x off=%d %x %x\n", src->s.code,
+ off, src->s.jt, src->s.jf);
+#endif
+
+ if (!src->s.jt || !src->s.jf) {
+ free(offset);
+ conv_error(conv_state, ljerr, "no jmp destination", off);
+ /*NOTREACHED*/
+ }
+
+ jt = jf = 0;
+ for (i = 0; i < slen; i++) {
+ if (offset[i] == src->s.jt) {
+ if (jt) {
+ free(offset);
+ conv_error(conv_state, ljerr, "multiple matches", off);
+ /*NOTREACHED*/
+ }
+
+ if (i - off - 1 >= 256) {
+ free(offset);
+ conv_error(conv_state, ljerr, "out-of-range jump", off);
+ /*NOTREACHED*/
+ }
+ dst->jt = (u_char)(i - off - 1);
+ jt++;
+ }
+ if (offset[i] == src->s.jf) {
+ if (jf) {
+ free(offset);
+ conv_error(conv_state, ljerr, "multiple matches", off);
+ /*NOTREACHED*/
+ }
+ if (i - off - 1 >= 256) {
+ free(offset);
+ conv_error(conv_state, ljerr, "out-of-range jump", off);
+ /*NOTREACHED*/
+ }
+ dst->jf = (u_char)(i - off - 1);
+ jf++;
+ }
+ }
+ if (!jt || !jf) {
+ free(offset);
+ conv_error(conv_state, ljerr, "no destination found", off);
+ /*NOTREACHED*/
+ }
+ }
+filled:
+ ++dst;
+ ++off;
+ }
+ if (offset)
+ free(offset);
+
+#ifdef BDEBUG
+ if (dst - conv_state->fstart < NBIDS)
+ bids[dst - conv_state->fstart] = p->id + 1;
+#endif
+ dst->code = (u_short)p->s.code;
+ dst->k = p->s.k;
+ if (JT(p)) {
+ extrajmps = 0;
+ off = JT(p)->offset - (p->offset + slen) - 1;
+ if (off >= 256) {
+ /* offset too large for branch, must add a jump */
+ if (p->longjt == 0) {
+ /* mark this instruction and retry */
+ p->longjt++;
+ return(0);
+ }
+ /* branch if T to following jump */
+ if (extrajmps >= 256) {
+ conv_error(conv_state, "too many extra jumps");
+ /*NOTREACHED*/
+ }
+ dst->jt = (u_char)extrajmps;
+ extrajmps++;
+ dst[extrajmps].code = BPF_JMP|BPF_JA;
+ dst[extrajmps].k = off - extrajmps;
+ }
+ else
+ dst->jt = (u_char)off;
+ off = JF(p)->offset - (p->offset + slen) - 1;
+ if (off >= 256) {
+ /* offset too large for branch, must add a jump */
+ if (p->longjf == 0) {
+ /* mark this instruction and retry */
+ p->longjf++;
+ return(0);
+ }
+ /* branch if F to following jump */
+ /* if two jumps are inserted, F goes to second one */
+ if (extrajmps >= 256) {
+ conv_error(conv_state, "too many extra jumps");
+ /*NOTREACHED*/
+ }
+ dst->jf = (u_char)extrajmps;
+ extrajmps++;
+ dst[extrajmps].code = BPF_JMP|BPF_JA;
+ dst[extrajmps].k = off - extrajmps;
+ }
+ else
+ dst->jf = (u_char)off;
+ }
+ return (1);
+}
+
+
+/*
+ * Convert flowgraph intermediate representation to the
+ * BPF array representation. Set *lenp to the number of instructions.
+ *
+ * This routine does *NOT* leak the memory pointed to by fp. It *must
+ * not* do free(fp) before returning fp; doing so would make no sense,
+ * as the BPF array pointed to by the return value of icode_to_fcode()
+ * must be valid - it's being returned for use in a bpf_program structure.
+ *
+ * If it appears that icode_to_fcode() is leaking, the problem is that
+ * the program using pcap_compile() is failing to free the memory in
+ * the BPF program when it's done - the leak is in the program, not in
+ * the routine that happens to be allocating the memory. (By analogy, if
+ * a program calls fopen() without ever calling fclose() on the FILE *,
+ * it will leak the FILE structure; the leak is not in fopen(), it's in
+ * the program.) Change the program to use pcap_freecode() when it's
+ * done with the filter program. See the pcap man page.
+ */
+struct bpf_insn *
+icode_to_fcode(struct icode *ic, struct block *root, u_int *lenp,
+ char *errbuf)
+{
+ u_int n;
+ struct bpf_insn *fp;
+ conv_state_t conv_state;
+
+ conv_state.fstart = NULL;
+ conv_state.errbuf = errbuf;
+ if (setjmp(conv_state.top_ctx) != 0) {
+ free(conv_state.fstart);
+ return NULL;
+ }
+
+ /*
+ * Loop doing convert_code_r() until no branches remain
+ * with too-large offsets.
+ */
+ for (;;) {
+ unMarkAll(ic);
+ n = *lenp = count_stmts(ic, root);
+
+ fp = (struct bpf_insn *)malloc(sizeof(*fp) * n);
+ if (fp == NULL) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "malloc");
+ free(fp);
+ return NULL;
+ }
+ memset((char *)fp, 0, sizeof(*fp) * n);
+ conv_state.fstart = fp;
+ conv_state.ftail = fp + n;
+
+ unMarkAll(ic);
+ if (convert_code_r(&conv_state, ic, root))
+ break;
+ free(fp);
+ }
+
+ return fp;
+}
+
+/*
+ * For iconv_to_fconv() errors.
+ */
+static void PCAP_NORETURN
+conv_error(conv_state_t *conv_state, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void)pcap_vsnprintf(conv_state->errbuf,
+ PCAP_ERRBUF_SIZE, fmt, ap);
+ va_end(ap);
+ longjmp(conv_state->top_ctx, 1);
+ /* NOTREACHED */
+}
+
+/*
+ * Make a copy of a BPF program and put it in the "fcode" member of
+ * a "pcap_t".
+ *
+ * If we fail to allocate memory for the copy, fill in the "errbuf"
+ * member of the "pcap_t" with an error message, and return -1;
+ * otherwise, return 0.
+ */
+int
+install_bpf_program(pcap_t *p, struct bpf_program *fp)
+{
+ size_t prog_size;
+
+ /*
+ * Validate the program.
+ */
+ if (!bpf_validate(fp->bf_insns, fp->bf_len)) {
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "BPF program is not valid");
+ return (-1);
+ }
+
+ /*
+ * Free up any already installed program.
+ */
+ pcap_freecode(&p->fcode);
+
+ prog_size = sizeof(*fp->bf_insns) * fp->bf_len;
+ p->fcode.bf_len = fp->bf_len;
+ p->fcode.bf_insns = (struct bpf_insn *)malloc(prog_size);
+ if (p->fcode.bf_insns == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "malloc");
+ return (-1);
+ }
+ memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size);
+ return (0);
+}
+
+#ifdef BDEBUG
+static void
+dot_dump_node(struct icode *ic, struct block *block, struct bpf_program *prog,
+ FILE *out)
+{
+ int icount, noffset;
+ int i;
+
+ if (block == NULL || isMarked(ic, block))
+ return;
+ Mark(ic, block);
+
+ icount = slength(block->stmts) + 1 + block->longjt + block->longjf;
+ noffset = min(block->offset + icount, (int)prog->bf_len);
+
+ fprintf(out, "\tblock%d [shape=ellipse, id=\"block-%d\" label=\"BLOCK%d\\n", block->id, block->id, block->id);
+ for (i = block->offset; i < noffset; i++) {
+ fprintf(out, "\\n%s", bpf_image(prog->bf_insns + i, i));
+ }
+ fprintf(out, "\" tooltip=\"");
+ for (i = 0; i < BPF_MEMWORDS; i++)
+ if (block->val[i] != VAL_UNKNOWN)
+ fprintf(out, "val[%d]=%d ", i, block->val[i]);
+ fprintf(out, "val[A]=%d ", block->val[A_ATOM]);
+ fprintf(out, "val[X]=%d", block->val[X_ATOM]);
+ fprintf(out, "\"");
+ if (JT(block) == NULL)
+ fprintf(out, ", peripheries=2");
+ fprintf(out, "];\n");
+
+ dot_dump_node(ic, JT(block), prog, out);
+ dot_dump_node(ic, JF(block), prog, out);
+}
+
+static void
+dot_dump_edge(struct icode *ic, struct block *block, FILE *out)
+{
+ if (block == NULL || isMarked(ic, block))
+ return;
+ Mark(ic, block);
+
+ if (JT(block)) {
+ fprintf(out, "\t\"block%d\":se -> \"block%d\":n [label=\"T\"]; \n",
+ block->id, JT(block)->id);
+ fprintf(out, "\t\"block%d\":sw -> \"block%d\":n [label=\"F\"]; \n",
+ block->id, JF(block)->id);
+ }
+ dot_dump_edge(ic, JT(block), out);
+ dot_dump_edge(ic, JF(block), out);
+}
+
+/* Output the block CFG using graphviz/DOT language
+ * In the CFG, block's code, value index for each registers at EXIT,
+ * and the jump relationship is show.
+ *
+ * example DOT for BPF `ip src host 1.1.1.1' is:
+ digraph BPF {
+ block0 [shape=ellipse, id="block-0" label="BLOCK0\n\n(000) ldh [12]\n(001) jeq #0x800 jt 2 jf 5" tooltip="val[A]=0 val[X]=0"];
+ block1 [shape=ellipse, id="block-1" label="BLOCK1\n\n(002) ld [26]\n(003) jeq #0x1010101 jt 4 jf 5" tooltip="val[A]=0 val[X]=0"];
+ block2 [shape=ellipse, id="block-2" label="BLOCK2\n\n(004) ret #68" tooltip="val[A]=0 val[X]=0", peripheries=2];
+ block3 [shape=ellipse, id="block-3" label="BLOCK3\n\n(005) ret #0" tooltip="val[A]=0 val[X]=0", peripheries=2];
+ "block0":se -> "block1":n [label="T"];
+ "block0":sw -> "block3":n [label="F"];
+ "block1":se -> "block2":n [label="T"];
+ "block1":sw -> "block3":n [label="F"];
+ }
+ *
+ * After install graphviz on http://www.graphviz.org/, save it as bpf.dot
+ * and run `dot -Tpng -O bpf.dot' to draw the graph.
+ */
+static int
+dot_dump(struct icode *ic, char *errbuf)
+{
+ struct bpf_program f;
+ FILE *out = stdout;
+
+ memset(bids, 0, sizeof bids);
+ f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
+ if (f.bf_insns == NULL)
+ return -1;
+
+ fprintf(out, "digraph BPF {\n");
+ unMarkAll(ic);
+ dot_dump_node(ic, ic->root, &f, out);
+ unMarkAll(ic);
+ dot_dump_edge(ic, ic->root, out);
+ fprintf(out, "}\n");
+
+ free((char *)f.bf_insns);
+ return 0;
+}
+
+static int
+plain_dump(struct icode *ic, char *errbuf)
+{
+ struct bpf_program f;
+
+ memset(bids, 0, sizeof bids);
+ f.bf_insns = icode_to_fcode(ic, ic->root, &f.bf_len, errbuf);
+ if (f.bf_insns == NULL)
+ return -1;
+ bpf_dump(&f, 1);
+ putchar('\n');
+ free((char *)f.bf_insns);
+ return 0;
+}
+
+static void
+opt_dump(opt_state_t *opt_state, struct icode *ic)
+{
+ int status;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ /*
+ * If the CFG, in DOT format, is requested, output it rather than
+ * the code that would be generated from that graph.
+ */
+ if (pcap_print_dot_graph)
+ status = dot_dump(ic, errbuf);
+ else
+ status = plain_dump(ic, errbuf);
+ if (status == -1)
+ opt_error(opt_state, "opt_dump: icode_to_fcode failed: %s", errbuf);
+}
+#endif
diff --git a/lib/libpcap/libpcap/optimize.h b/lib/libpcap/libpcap/optimize.h
new file mode 100644
index 0000000..56b31f4
--- /dev/null
+++ b/lib/libpcap/libpcap/optimize.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ * Some stuff for use when debugging the optimizer.
+ */
+#ifdef BDEBUG
+#define NBIDS 1000
+extern int bids[NBIDS];
+#endif
diff --git a/lib/libpcap/libpcap/org.tcpdump.chmod_bpf.plist b/lib/libpcap/libpcap/org.tcpdump.chmod_bpf.plist
new file mode 100644
index 0000000..8ad6852
--- /dev/null
+++ b/lib/libpcap/libpcap/org.tcpdump.chmod_bpf.plist
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Label</key>
+ <string>org.tcpdump.chmod_bpf</string>
+ <key>RunAtLoad</key>
+ <true/>
+ <key>Program</key>
+ <string>/usr/local/bin/chmod_bpf</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/local/bin/chmod_bpf</string>
+ </array>
+</dict>
+</plist>
diff --git a/lib/libpcap/libpcap/pcap-bpf.c b/lib/libpcap/libpcap/pcap-bpf.c
new file mode 100644
index 0000000..cdc9c5b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-bpf.c
@@ -0,0 +1,3435 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/param.h> /* optionally get BSD define */
+#include <sys/socket.h>
+#include <time.h>
+/*
+ * <net/bpf.h> defines ioctls, but doesn't include <sys/ioccom.h>.
+ *
+ * We include <sys/ioctl.h> as it might be necessary to declare ioctl();
+ * at least on *BSD and macOS, it also defines various SIOC ioctls -
+ * we could include <sys/sockio.h>, but if we're already including
+ * <sys/ioctl.h>, which includes <sys/sockio.h> on those platforms,
+ * there's not much point in doing so.
+ *
+ * If we have <sys/ioccom.h>, we include it as well, to handle systems
+ * such as Solaris which don't arrange to include <sys/ioccom.h> if you
+ * include <sys/ioctl.h>
+ */
+#include <sys/ioctl.h>
+#ifdef HAVE_SYS_IOCCOM_H
+#include <sys/ioccom.h>
+#endif
+#include <sys/utsname.h>
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+/*
+ * Add support for capturing on FreeBSD usbusN interfaces.
+ */
+static const char usbus_prefix[] = "usbus";
+#define USBUS_PREFIX_LEN (sizeof(usbus_prefix) - 1)
+#include <dirent.h>
+#endif
+
+#include <net/if.h>
+
+#ifdef _AIX
+
+/*
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
+ * native OS version, as we need "struct bpf_config" from it.
+ */
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+
+#include <sys/types.h>
+
+/*
+ * Prevent bpf.h from redefining the DLT_ values to their
+ * IFT_ values, as we're going to return the standard libpcap
+ * values, not IBM's non-standard IFT_ values.
+ */
+#undef _AIX
+#include <net/bpf.h>
+#define _AIX
+
+/*
+ * If both BIOCROTZBUF and BPF_BUFMODE_ZBUF are defined, we have
+ * zero-copy BPF.
+ */
+#if defined(BIOCROTZBUF) && defined(BPF_BUFMODE_ZBUF)
+ #define HAVE_ZEROCOPY_BPF
+ #include <sys/mman.h>
+ #include <machine/atomic.h>
+#endif
+
+#include <net/if_types.h> /* for IFT_ values */
+#include <sys/sysconfig.h>
+#include <sys/device.h>
+#include <sys/cfgodm.h>
+#include <cf.h>
+
+#ifdef __64BIT__
+#define domakedev makedev64
+#define getmajor major64
+#define bpf_hdr bpf_hdr32
+#else /* __64BIT__ */
+#define domakedev makedev
+#define getmajor major
+#endif /* __64BIT__ */
+
+#define BPF_NAME "bpf"
+#define BPF_MINORS 4
+#define DRIVER_PATH "/usr/lib/drivers"
+#define BPF_NODE "/dev/bpf"
+static int bpfloadedflag = 0;
+static int odmlockid = 0;
+
+static int bpf_load(char *errbuf);
+
+#else /* _AIX */
+
+#include <net/bpf.h>
+
+#endif /* _AIX */
+
+#include <ctype.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef SIOCGIFMEDIA
+# include <net/if_media.h>
+#endif
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef __APPLE__
+#include "pcap-util.h"
+#endif /* __APPLE__ */
+
+/*
+ * Later versions of NetBSD stick padding in front of FDDI frames
+ * to align the IP header on a 4-byte boundary.
+ */
+#if defined(__NetBSD__) && __NetBSD_Version__ > 106000000
+#define PCAP_FDDIPAD 3
+#endif
+
+/*
+ * Private data for capturing on BPF devices.
+ */
+struct pcap_bpf {
+#ifdef HAVE_ZEROCOPY_BPF
+ /*
+ * Zero-copy read buffer -- for zero-copy BPF. 'buffer' above will
+ * alternative between these two actual mmap'd buffers as required.
+ * As there is a header on the front size of the mmap'd buffer, only
+ * some of the buffer is exposed to libpcap as a whole via bufsize;
+ * zbufsize is the true size. zbuffer tracks the current zbuf
+ * assocated with buffer so that it can be used to decide which the
+ * next buffer to read will be.
+ */
+ u_char *zbuf1, *zbuf2, *zbuffer;
+ u_int zbufsize;
+ u_int zerocopy;
+ u_int interrupted;
+ struct timespec firstsel;
+ /*
+ * If there's currently a buffer being actively processed, then it is
+ * referenced here; 'buffer' is also pointed at it, but offset by the
+ * size of the header.
+ */
+ struct bpf_zbuf_header *bzh;
+ int nonblock; /* true if in nonblocking mode */
+#endif /* HAVE_ZEROCOPY_BPF */
+
+ char *device; /* device name */
+ int filtering_in_kernel; /* using kernel filter */
+ int must_do_on_close; /* stuff we must do when we close */
+};
+
+/*
+ * Stuff to do when we close.
+ */
+#define MUST_CLEAR_RFMON 0x00000001 /* clear rfmon (monitor) mode */
+#define MUST_DESTROY_USBUS 0x00000002 /* destroy usbusN interface */
+
+#ifdef BIOCGDLTLIST
+# if (defined(HAVE_NET_IF_MEDIA_H) && defined(IFM_IEEE80211)) && !defined(__APPLE__)
+#define HAVE_BSD_IEEE80211
+
+/*
+ * The ifm_ulist member of a struct ifmediareq is an int * on most systems,
+ * but it's a uint64_t on newer versions of OpenBSD.
+ *
+ * We check this by checking whether IFM_GMASK is defined and > 2^32-1.
+ */
+# if defined(IFM_GMASK) && IFM_GMASK > 0xFFFFFFFF
+# define IFM_ULIST_TYPE uint64_t
+# else
+# define IFM_ULIST_TYPE int
+# endif
+# endif
+
+# if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
+static int find_802_11(struct bpf_dltlist *);
+
+# ifdef HAVE_BSD_IEEE80211
+static int monitor_mode(pcap_t *, int);
+# endif
+
+# if defined(__APPLE__)
+static void remove_non_802_11(pcap_t *);
+static void remove_802_11(pcap_t *);
+# endif
+
+# endif /* defined(__APPLE__) || defined(HAVE_BSD_IEEE80211) */
+
+#endif /* BIOCGDLTLIST */
+
+#if defined(sun) && defined(LIFNAMSIZ) && defined(lifr_zoneid)
+#include <zone.h>
+#endif
+
+/*
+ * We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
+ */
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS 143
+#endif
+
+/*
+ * In some versions of macOS, we might not even get any of the
+ * 802.11-plus-radio-header DLT_'s defined, even though some
+ * of them are used by various Airport drivers in those versions.
+ */
+#ifndef DLT_PRISM_HEADER
+#define DLT_PRISM_HEADER 119
+#endif
+#ifndef DLT_AIRONET_HEADER
+#define DLT_AIRONET_HEADER 120
+#endif
+#ifndef DLT_IEEE802_11_RADIO
+#define DLT_IEEE802_11_RADIO 127
+#endif
+#ifndef DLT_IEEE802_11_RADIO_AVS
+#define DLT_IEEE802_11_RADIO_AVS 163
+#endif
+
+static int pcap_can_set_rfmon_bpf(pcap_t *p);
+static int pcap_activate_bpf(pcap_t *p);
+static int pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp);
+static int pcap_setdirection_bpf(pcap_t *, pcap_direction_t);
+static int pcap_set_datalink_bpf(pcap_t *p, int dlt);
+
+/*
+ * For zerocopy bpf, the setnonblock/getnonblock routines need to modify
+ * pb->nonblock so we don't call select(2) if the pcap handle is in non-
+ * blocking mode.
+ */
+static int
+pcap_getnonblock_bpf(pcap_t *p)
+{
+#ifdef HAVE_ZEROCOPY_BPF
+ struct pcap_bpf *pb = p->priv;
+
+ if (pb->zerocopy)
+ return (pb->nonblock);
+#endif
+ return (pcap_getnonblock_fd(p));
+}
+
+static int
+pcap_setnonblock_bpf(pcap_t *p, int nonblock)
+{
+#ifdef HAVE_ZEROCOPY_BPF
+ struct pcap_bpf *pb = p->priv;
+
+ if (pb->zerocopy) {
+ pb->nonblock = nonblock;
+ return (0);
+ }
+#endif
+ return (pcap_setnonblock_fd(p, nonblock));
+}
+
+#ifdef HAVE_ZEROCOPY_BPF
+/*
+ * Zero-copy BPF buffer routines to check for and acknowledge BPF data in
+ * shared memory buffers.
+ *
+ * pcap_next_zbuf_shm(): Check for a newly available shared memory buffer,
+ * and set up p->buffer and cc to reflect one if available. Notice that if
+ * there was no prior buffer, we select zbuf1 as this will be the first
+ * buffer filled for a fresh BPF session.
+ */
+static int
+pcap_next_zbuf_shm(pcap_t *p, int *cc)
+{
+ struct pcap_bpf *pb = p->priv;
+ struct bpf_zbuf_header *bzh;
+
+ if (pb->zbuffer == pb->zbuf2 || pb->zbuffer == NULL) {
+ bzh = (struct bpf_zbuf_header *)pb->zbuf1;
+ if (bzh->bzh_user_gen !=
+ atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
+ pb->bzh = bzh;
+ pb->zbuffer = (u_char *)pb->zbuf1;
+ p->buffer = pb->zbuffer + sizeof(*bzh);
+ *cc = bzh->bzh_kernel_len;
+ return (1);
+ }
+ } else if (pb->zbuffer == pb->zbuf1) {
+ bzh = (struct bpf_zbuf_header *)pb->zbuf2;
+ if (bzh->bzh_user_gen !=
+ atomic_load_acq_int(&bzh->bzh_kernel_gen)) {
+ pb->bzh = bzh;
+ pb->zbuffer = (u_char *)pb->zbuf2;
+ p->buffer = pb->zbuffer + sizeof(*bzh);
+ *cc = bzh->bzh_kernel_len;
+ return (1);
+ }
+ }
+ *cc = 0;
+ return (0);
+}
+
+/*
+ * pcap_next_zbuf() -- Similar to pcap_next_zbuf_shm(), except wait using
+ * select() for data or a timeout, and possibly force rotation of the buffer
+ * in the event we time out or are in immediate mode. Invoke the shared
+ * memory check before doing system calls in order to avoid doing avoidable
+ * work.
+ */
+static int
+pcap_next_zbuf(pcap_t *p, int *cc)
+{
+ struct pcap_bpf *pb = p->priv;
+ struct bpf_zbuf bz;
+ struct timeval tv;
+ struct timespec cur;
+ fd_set r_set;
+ int data, r;
+ int expire, tmout;
+
+#define TSTOMILLI(ts) (((ts)->tv_sec * 1000) + ((ts)->tv_nsec / 1000000))
+ /*
+ * Start out by seeing whether anything is waiting by checking the
+ * next shared memory buffer for data.
+ */
+ data = pcap_next_zbuf_shm(p, cc);
+ if (data)
+ return (data);
+ /*
+ * If a previous sleep was interrupted due to signal delivery, make
+ * sure that the timeout gets adjusted accordingly. This requires
+ * that we analyze when the timeout should be been expired, and
+ * subtract the current time from that. If after this operation,
+ * our timeout is less then or equal to zero, handle it like a
+ * regular timeout.
+ */
+ tmout = p->opt.timeout;
+ if (tmout)
+ (void) clock_gettime(CLOCK_MONOTONIC, &cur);
+ if (pb->interrupted && p->opt.timeout) {
+ expire = TSTOMILLI(&pb->firstsel) + p->opt.timeout;
+ tmout = expire - TSTOMILLI(&cur);
+#undef TSTOMILLI
+ if (tmout <= 0) {
+ pb->interrupted = 0;
+ data = pcap_next_zbuf_shm(p, cc);
+ if (data)
+ return (data);
+ if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "BIOCROTZBUF");
+ return (PCAP_ERROR);
+ }
+ return (pcap_next_zbuf_shm(p, cc));
+ }
+ }
+ /*
+ * No data in the buffer, so must use select() to wait for data or
+ * the next timeout. Note that we only call select if the handle
+ * is in blocking mode.
+ */
+ if (!pb->nonblock) {
+ FD_ZERO(&r_set);
+ FD_SET(p->fd, &r_set);
+ if (tmout != 0) {
+ tv.tv_sec = tmout / 1000;
+ tv.tv_usec = (tmout * 1000) % 1000000;
+ }
+ r = select(p->fd + 1, &r_set, NULL, NULL,
+ p->opt.timeout != 0 ? &tv : NULL);
+ if (r < 0 && errno == EINTR) {
+ if (!pb->interrupted && p->opt.timeout) {
+ pb->interrupted = 1;
+ pb->firstsel = cur;
+ }
+ return (0);
+ } else if (r < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "select");
+ return (PCAP_ERROR);
+ }
+ }
+ pb->interrupted = 0;
+ /*
+ * Check again for data, which may exist now that we've either been
+ * woken up as a result of data or timed out. Try the "there's data"
+ * case first since it doesn't require a system call.
+ */
+ data = pcap_next_zbuf_shm(p, cc);
+ if (data)
+ return (data);
+ /*
+ * Try forcing a buffer rotation to dislodge timed out or immediate
+ * data.
+ */
+ if (ioctl(p->fd, BIOCROTZBUF, &bz) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCROTZBUF");
+ return (PCAP_ERROR);
+ }
+ return (pcap_next_zbuf_shm(p, cc));
+}
+
+/*
+ * Notify kernel that we are done with the buffer. We don't reset zbuffer so
+ * that we know which buffer to use next time around.
+ */
+static int
+pcap_ack_zbuf(pcap_t *p)
+{
+ struct pcap_bpf *pb = p->priv;
+
+ atomic_store_rel_int(&pb->bzh->bzh_user_gen,
+ pb->bzh->bzh_kernel_gen);
+ pb->bzh = NULL;
+ p->buffer = NULL;
+ return (0);
+}
+#endif /* HAVE_ZEROCOPY_BPF */
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_bpf));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_bpf;
+ p->can_set_rfmon_op = pcap_can_set_rfmon_bpf;
+#ifdef BIOCSTSTAMP
+ /*
+ * We claim that we support microsecond and nanosecond time
+ * stamps.
+ */
+ p->tstamp_precision_count = 2;
+ p->tstamp_precision_list = malloc(2 * sizeof(u_int));
+ if (p->tstamp_precision_list == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+ "malloc");
+ free(p);
+ return (NULL);
+ }
+ p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+ p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+#endif /* BIOCSTSTAMP */
+ return (p);
+}
+
+/*
+ * On success, returns a file descriptor for a BPF device.
+ * On failure, returns a PCAP_ERROR_ value, and sets p->errbuf.
+ */
+static int
+bpf_open(char *errbuf)
+{
+ int fd = -1;
+ static const char cloning_device[] = "/dev/bpf";
+ int n = 0;
+ char device[sizeof "/dev/bpf0000000000"];
+ static int no_cloning_bpf = 0;
+
+#ifdef _AIX
+ /*
+ * Load the bpf driver, if it isn't already loaded,
+ * and create the BPF device entries, if they don't
+ * already exist.
+ */
+ if (bpf_load(errbuf) == PCAP_ERROR)
+ return (PCAP_ERROR);
+#endif
+
+ /*
+ * First, unless we've already tried opening /dev/bpf and
+ * gotten ENOENT, try opening /dev/bpf.
+ * If it fails with ENOENT, remember that, so we don't try
+ * again, and try /dev/bpfN.
+ */
+ if (!no_cloning_bpf &&
+ (fd = open(cloning_device, O_RDWR)) == -1 &&
+ ((errno != EACCES && errno != ENOENT) ||
+ (fd = open(cloning_device, O_RDONLY)) == -1)) {
+ if (errno != ENOENT) {
+ if (errno == EACCES)
+ fd = PCAP_ERROR_PERM_DENIED;
+ else
+ fd = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "(cannot open device) %s", cloning_device);
+ return (fd);
+ }
+ no_cloning_bpf = 1;
+ }
+
+ if (no_cloning_bpf) {
+ /*
+ * We don't have /dev/bpf.
+ * Go through all the /dev/bpfN minors and find one
+ * that isn't in use.
+ */
+ do {
+ (void)pcap_snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+ /*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ */
+ fd = open(device, O_RDWR);
+ if (fd == -1 && errno == EACCES)
+ fd = open(device, O_RDONLY);
+ } while (fd < 0 && errno == EBUSY);
+ }
+
+ /*
+ * XXX better message for all minors used
+ */
+ if (fd < 0) {
+ switch (errno) {
+
+ case ENOENT:
+ fd = PCAP_ERROR;
+ if (n == 1) {
+ /*
+ * /dev/bpf0 doesn't exist, which
+ * means we probably have no BPF
+ * devices.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "(there are no BPF devices)");
+ } else {
+ /*
+ * We got EBUSY on at least one
+ * BPF device, so we have BPF
+ * devices, but all the ones
+ * that exist are busy.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "(all BPF devices are busy)");
+ }
+ break;
+
+ case EACCES:
+ /*
+ * Got EACCES on the last device we tried,
+ * and EBUSY on all devices before that,
+ * if any.
+ */
+ fd = PCAP_ERROR_PERM_DENIED;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "(cannot open BPF device) %s", device);
+ break;
+
+ default:
+ /*
+ * Some other problem.
+ */
+ fd = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "(cannot open BPF device) %s", device);
+ break;
+ }
+ }
+
+ return (fd);
+}
+
+/*
+ * Open and bind to a device; used if we're not actually going to use
+ * the device, but are just testing whether it can be opened, or opening
+ * it to get information about it.
+ *
+ * Returns an error code on failure (always negative), and an FD for
+ * the now-bound BPF device on success (always non-negative).
+ */
+static int
+bpf_open_and_bind(const char *name, char *errbuf)
+{
+ int fd;
+ struct ifreq ifr;
+
+ /*
+ * First, open a BPF device.
+ */
+ fd = bpf_open(errbuf);
+ if (fd < 0)
+ return (fd); /* fd is the appropriate error code */
+
+ /*
+ * Now bind to the device.
+ */
+#ifdef __APPLE__
+ (void)strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+#else
+ (void)strncpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+#endif /* __APPLE__ */
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ switch (errno) {
+
+ case ENXIO:
+ /*
+ * There's no such device.
+ */
+ close(fd);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ case ENETDOWN:
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ close(fd);
+ return (PCAP_ERROR_IFACE_NOT_UP);
+
+ default:
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", name);
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ }
+
+ /*
+ * Success.
+ */
+ return (fd);
+}
+
+#ifdef BIOCGDLTLIST
+static int
+get_dlt_list(int fd, int v, struct bpf_dltlist *bdlp, char *ebuf)
+{
+ memset(bdlp, 0, sizeof(*bdlp));
+ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) == 0) {
+ u_int i;
+ int is_ethernet;
+
+ bdlp->bfl_list = (u_int *) malloc(sizeof(u_int) * (bdlp->bfl_len + 1));
+ if (bdlp->bfl_list == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (PCAP_ERROR);
+ }
+
+ if (ioctl(fd, BIOCGDLTLIST, (caddr_t)bdlp) < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGDLTLIST");
+ free(bdlp->bfl_list);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * OK, for real Ethernet devices, add DLT_DOCSIS to the
+ * list, so that an application can let you choose it,
+ * in case you're capturing DOCSIS traffic that a Cisco
+ * Cable Modem Termination System is putting out onto
+ * an Ethernet (it doesn't put an Ethernet header onto
+ * the wire, it puts raw DOCSIS frames out on the wire
+ * inside the low-level Ethernet framing).
+ *
+ * A "real Ethernet device" is defined here as a device
+ * that has a link-layer type of DLT_EN10MB and that has
+ * no alternate link-layer types; that's done to exclude
+ * 802.11 interfaces (which might or might not be the
+ * right thing to do, but I suspect it is - Ethernet <->
+ * 802.11 bridges would probably badly mishandle frames
+ * that don't have Ethernet headers).
+ *
+ * On Solaris with BPF, Ethernet devices also offer
+ * DLT_IPNET, so we, if DLT_IPNET is defined, we don't
+ * treat it as an indication that the device isn't an
+ * Ethernet.
+ */
+ if (v == DLT_EN10MB) {
+ is_ethernet = 1;
+ for (i = 0; i < bdlp->bfl_len; i++) {
+ if (bdlp->bfl_list[i] != DLT_EN10MB
+#ifdef DLT_IPNET
+ && bdlp->bfl_list[i] != DLT_IPNET
+#endif
+ ) {
+ is_ethernet = 0;
+ break;
+ }
+ }
+ if (is_ethernet) {
+ /*
+ * We reserved one more slot at the end of
+ * the list.
+ */
+ bdlp->bfl_list[bdlp->bfl_len] = DLT_DOCSIS;
+ bdlp->bfl_len++;
+ }
+ }
+ } else {
+ /*
+ * EINVAL just means "we don't support this ioctl on
+ * this device"; don't treat it as an error.
+ */
+ if (errno != EINVAL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGDLTLIST");
+ return (PCAP_ERROR);
+ }
+ }
+ return (0);
+}
+#endif
+
+#if defined(__APPLE__)
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p)
+{
+ struct utsname osinfo;
+ struct ifreq ifr;
+ int fd;
+#ifdef BIOCGDLTLIST
+ struct bpf_dltlist bdl;
+#endif
+
+ /*
+ * The joys of monitor mode on Mac OS X/OS X/macOS.
+ *
+ * Prior to 10.4, it's not supported at all.
+ *
+ * In 10.4, if adapter enN supports monitor mode, there's a
+ * wltN adapter corresponding to it; you open it, instead of
+ * enN, to get monitor mode. You get whatever link-layer
+ * headers it supplies.
+ *
+ * In 10.5, and, we assume, later releases, if adapter enN
+ * supports monitor mode, it offers, among its selectable
+ * DLT_ values, values that let you get the 802.11 header;
+ * selecting one of those values puts the adapter into monitor
+ * mode (i.e., you can't get 802.11 headers except in monitor
+ * mode, and you can't get Ethernet headers in monitor mode).
+ */
+ if (uname(&osinfo) == -1) {
+ /*
+ * Can't get the OS version; just say "no".
+ */
+ return (0);
+ }
+ /*
+ * We assume osinfo.sysname is "Darwin", because
+ * __APPLE__ is defined. We just check the version.
+ */
+ if (osinfo.release[0] < '8' && osinfo.release[1] == '.') {
+ /*
+ * 10.3 (Darwin 7.x) or earlier.
+ * Monitor mode not supported.
+ */
+ return (0);
+ }
+ if (osinfo.release[0] == '8' && osinfo.release[1] == '.') {
+ /*
+ * 10.4 (Darwin 8.x). s/en/wlt/, and check
+ * whether the device exists.
+ */
+ if (strncmp(p->opt.device, "en", 2) != 0) {
+ /*
+ * Not an enN device; no monitor mode.
+ */
+ return (0);
+ }
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ return (PCAP_ERROR);
+ }
+ pcap_strlcpy(ifr.ifr_name, "wlt", sizeof(ifr.ifr_name));
+ pcap_strlcat(ifr.ifr_name, p->opt.device + 2, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+ /*
+ * No such device?
+ */
+ close(fd);
+ return (0);
+ }
+ close(fd);
+ return (1);
+ }
+
+#ifdef BIOCGDLTLIST
+ /*
+ * Everything else is 10.5 or later; for those,
+ * we just open the enN device, and check whether
+ * we have any 802.11 devices.
+ *
+ * First, open a BPF device.
+ */
+ fd = bpf_open(p->errbuf);
+ if (fd < 0)
+ return (fd); /* fd is the appropriate error code */
+
+ /*
+ * Now bind to the device.
+ */
+#ifdef __APPLE__
+ (void)strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+#else
+ (void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+#endif /* __APPLE__ */
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ switch (errno) {
+
+ case ENXIO:
+ /*
+ * There's no such device.
+ */
+ close(fd);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ case ENETDOWN:
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ close(fd);
+ return (PCAP_ERROR_IFACE_NOT_UP);
+
+ default:
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", p->opt.device);
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ }
+
+ /*
+ * We know the default link type -- now determine all the DLTs
+ * this interface supports. If this fails with EINVAL, it's
+ * not fatal; we just don't get to use the feature later.
+ * (We don't care about DLT_DOCSIS, so we pass DLT_NULL
+ * as the default DLT for this adapter.)
+ */
+ if (get_dlt_list(fd, DLT_NULL, &bdl, p->errbuf) == PCAP_ERROR) {
+ close(fd);
+ return (PCAP_ERROR);
+ }
+ if (find_802_11(&bdl) != -1) {
+ /*
+ * We have an 802.11 DLT, so we can set monitor mode.
+ */
+ free(bdl.bfl_list);
+ close(fd);
+ return (1);
+ }
+ free(bdl.bfl_list);
+ close(fd);
+#endif /* BIOCGDLTLIST */
+ return (0);
+}
+#elif defined(HAVE_BSD_IEEE80211)
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p)
+{
+ int ret;
+
+ ret = monitor_mode(p, 0);
+ if (ret == PCAP_ERROR_RFMON_NOTSUP)
+ return (0); /* not an error, just a "can't do" */
+ if (ret == 0)
+ return (1); /* success */
+ return (ret);
+}
+#else
+static int
+pcap_can_set_rfmon_bpf(pcap_t *p _U_)
+{
+ return (0);
+}
+#endif
+
+static int
+pcap_stats_bpf(pcap_t *p, struct pcap_stat *ps)
+{
+ struct bpf_stat s;
+
+ /*
+ * "ps_recv" counts packets handed to the filter, not packets
+ * that passed the filter. This includes packets later dropped
+ * because we ran out of buffer space.
+ *
+ * "ps_drop" counts packets dropped inside the BPF device
+ * because we ran out of buffer space. It doesn't count
+ * packets dropped by the interface driver. It counts
+ * only packets that passed the filter.
+ *
+ * Both statistics include packets not yet read from the kernel
+ * by libpcap, and thus not yet seen by the application.
+ */
+ if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGSTATS");
+ return (PCAP_ERROR);
+ }
+
+ ps->ps_recv = s.bs_recv;
+ ps->ps_drop = s.bs_drop;
+ ps->ps_ifdrop = 0;
+ return (0);
+}
+
+static int
+pcap_read_bpf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_bpf *pb = p->priv;
+ int cc;
+ int n = 0;
+ register u_char *bp, *ep;
+ u_char *datap;
+#ifdef PCAP_FDDIPAD
+ register u_int pad;
+#endif
+#ifdef HAVE_ZEROCOPY_BPF
+ int i;
+#endif
+
+ again:
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return PCAP_ERROR_BREAK to indicate
+ * that we were told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return (PCAP_ERROR_BREAK);
+ }
+ cc = p->cc;
+ if (p->cc == 0) {
+ /*
+ * When reading without zero-copy from a file descriptor, we
+ * use a single buffer and return a length of data in the
+ * buffer. With zero-copy, we update the p->buffer pointer
+ * to point at whatever underlying buffer contains the next
+ * data and update cc to reflect the data found in the
+ * buffer.
+ */
+#ifdef HAVE_ZEROCOPY_BPF
+ if (pb->zerocopy) {
+ if (p->buffer != NULL)
+ pcap_ack_zbuf(p);
+ i = pcap_next_zbuf(p, &cc);
+ if (i == 0)
+ goto again;
+ if (i < 0)
+ return (PCAP_ERROR);
+ } else
+#endif
+ {
+ cc = read(p->fd, p->buffer, p->bufsize);
+ }
+ if (cc < 0) {
+ /* Don't choke when we get ptraced */
+ switch (errno) {
+
+ case EINTR:
+ goto again;
+
+#ifdef _AIX
+ case EFAULT:
+ /*
+ * Sigh. More AIX wonderfulness.
+ *
+ * For some unknown reason the uiomove()
+ * operation in the bpf kernel extension
+ * used to copy the buffer into user
+ * space sometimes returns EFAULT. I have
+ * no idea why this is the case given that
+ * a kernel debugger shows the user buffer
+ * is correct. This problem appears to
+ * be mostly mitigated by the memset of
+ * the buffer before it is first used.
+ * Very strange.... Shaun Clowes
+ *
+ * In any case this means that we shouldn't
+ * treat EFAULT as a fatal error; as we
+ * don't have an API for returning
+ * a "some packets were dropped since
+ * the last packet you saw" indication,
+ * we just ignore EFAULT and keep reading.
+ */
+ goto again;
+#endif
+
+ case EWOULDBLOCK:
+ return (0);
+
+ case ENXIO: /* FreeBSD, DragonFly BSD, and Darwin */
+ case EIO: /* OpenBSD */
+ /* NetBSD appears not to return an error in this case */
+ /*
+ * The device on which we're capturing
+ * went away.
+ *
+ * XXX - we should really return
+ * an appropriate error for that,
+ * but pcap_dispatch() etc. aren't
+ * documented as having error returns
+ * other than PCAP_ERROR or PCAP_ERROR_BREAK.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The interface disappeared");
+ return (PCAP_ERROR);
+
+#if defined(sun) && !defined(BSD) && !defined(__svr4__) && !defined(__SVR4)
+ /*
+ * Due to a SunOS bug, after 2^31 bytes, the kernel
+ * file offset overflows and read fails with EINVAL.
+ * The lseek() to 0 will fix things.
+ */
+ case EINVAL:
+ if (lseek(p->fd, 0L, SEEK_CUR) +
+ p->bufsize < 0) {
+ (void)lseek(p->fd, 0L, SEEK_SET);
+ goto again;
+ }
+ /* fall through */
+#endif
+ }
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "read");
+ return (PCAP_ERROR);
+ }
+ bp = (u_char *)p->buffer;
+ } else
+ bp = p->bp;
+
+ /*
+ * Loop through each packet.
+ */
+#ifdef BIOCSTSTAMP
+#define bhp ((struct bpf_xhdr *)bp)
+#else
+#define bhp ((struct bpf_hdr *)bp)
+#endif
+ ep = bp + cc;
+#ifdef PCAP_FDDIPAD
+ pad = p->fddipad;
+#endif
+ while (bp < ep) {
+ register u_int caplen, hdrlen;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return PCAP_ERROR_BREAK
+ * to indicate that we were told to break out of the loop,
+ * otherwise leave the flag set, so that the *next* call
+ * will break out of the loop without having read any
+ * packets, and return the number of packets we've
+ * processed so far.
+ */
+ if (p->break_loop) {
+ p->bp = bp;
+ p->cc = ep - bp;
+ /*
+ * ep is set based on the return value of read(),
+ * but read() from a BPF device doesn't necessarily
+ * return a value that's a multiple of the alignment
+ * value for BPF_WORDALIGN(). However, whenever we
+ * increment bp, we round up the increment value by
+ * a value rounded up by BPF_WORDALIGN(), so we
+ * could increment bp past ep after processing the
+ * last packet in the buffer.
+ *
+ * We treat ep < bp as an indication that this
+ * happened, and just set p->cc to 0.
+ */
+ if (p->cc < 0)
+ p->cc = 0;
+ if (n == 0) {
+ p->break_loop = 0;
+ return (PCAP_ERROR_BREAK);
+ } else
+ return (n);
+ }
+
+ caplen = bhp->bh_caplen;
+ hdrlen = bhp->bh_hdrlen;
+ datap = bp + hdrlen;
+ /*
+ * Short-circuit evaluation: if using BPF filter
+ * in kernel, no need to do it now - we already know
+ * the packet passed the filter.
+ *
+#ifdef PCAP_FDDIPAD
+ * Note: the filter code was generated assuming
+ * that p->fddipad was the amount of padding
+ * before the header, as that's what's required
+ * in the kernel, so we run the filter before
+ * skipping that padding.
+#endif
+ */
+ if (pb->filtering_in_kernel ||
+ bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
+ struct pcap_pkthdr pkthdr;
+#ifdef BIOCSTSTAMP
+ struct bintime bt;
+
+ bt.sec = bhp->bh_tstamp.bt_sec;
+ bt.frac = bhp->bh_tstamp.bt_frac;
+ if (p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
+ struct timespec ts;
+
+ bintime2timespec(&bt, &ts);
+ pkthdr.ts.tv_sec = ts.tv_sec;
+ pkthdr.ts.tv_usec = ts.tv_nsec;
+ } else {
+ struct timeval tv;
+
+ bintime2timeval(&bt, &tv);
+ pkthdr.ts.tv_sec = tv.tv_sec;
+ pkthdr.ts.tv_usec = tv.tv_usec;
+ }
+#else
+ pkthdr.ts.tv_sec = bhp->bh_tstamp.tv_sec;
+#ifdef _AIX
+ /*
+ * AIX's BPF returns seconds/nanoseconds time
+ * stamps, not seconds/microseconds time stamps.
+ */
+ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec/1000;
+#else
+ pkthdr.ts.tv_usec = bhp->bh_tstamp.tv_usec;
+#endif
+#endif /* BIOCSTSTAMP */
+#ifdef PCAP_FDDIPAD
+ if (caplen > pad)
+ pkthdr.caplen = caplen - pad;
+ else
+ pkthdr.caplen = 0;
+ if (bhp->bh_datalen > pad)
+ pkthdr.len = bhp->bh_datalen - pad;
+ else
+ pkthdr.len = 0;
+ datap += pad;
+#else
+ pkthdr.caplen = caplen;
+ pkthdr.len = bhp->bh_datalen;
+#endif
+
+#ifdef __APPLE__
+ pcap_read_bpf_header(p, bp, &pkthdr);
+#endif /* __APPLE__ */
+
+ (*callback)(user, &pkthdr, datap);
+ bp += BPF_WORDALIGN(caplen + hdrlen);
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
+ p->bp = bp;
+ p->cc = ep - bp;
+ /*
+ * See comment above about p->cc < 0.
+ */
+ if (p->cc < 0)
+ p->cc = 0;
+ return (n);
+ }
+ } else {
+ /*
+ * Skip this packet.
+ */
+ bp += BPF_WORDALIGN(caplen + hdrlen);
+ }
+ }
+#undef bhp
+ p->cc = 0;
+ return (n);
+}
+
+static int
+pcap_inject_bpf(pcap_t *p, const void *buf, size_t size)
+{
+ int ret;
+
+ ret = write(p->fd, buf, size);
+#ifdef __APPLE__
+ if (ret == -1 && errno == EAFNOSUPPORT) {
+ /*
+ * In some versions of macOS, there's a bug wherein setting
+ * the BIOCSHDRCMPLT flag causes writes to fail; see, for
+ * example:
+ *
+ * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/BIOCSHDRCMPLT-10.3.3.patch
+ *
+ * So, if, on macOS, we get EAFNOSUPPORT from the write, we
+ * assume it's due to that bug, and turn off that flag
+ * and try again. If we succeed, it either means that
+ * somebody applied the fix from that URL, or other patches
+ * for that bug from
+ *
+ * http://cerberus.sourcefire.com/~jeff/archives/patches/macosx/
+ *
+ * and are running a Darwin kernel with those fixes, or
+ * that Apple fixed the problem in some macOS release.
+ */
+ u_int spoof_eth_src = 0;
+
+ if (ioctl(p->fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send: can't turn off BIOCSHDRCMPLT");
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Now try the write again.
+ */
+ ret = write(p->fd, buf, size);
+ }
+#endif /* __APPLE__ */
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (PCAP_ERROR);
+ }
+ return (ret);
+}
+
+#ifdef _AIX
+static int
+bpf_odminit(char *errbuf)
+{
+ char *errstr;
+
+ if (odm_initialize() == -1) {
+ if (odm_err_msg(odmerrno, &errstr) == -1)
+ errstr = "Unknown error";
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "bpf_load: odm_initialize failed: %s",
+ errstr);
+ return (PCAP_ERROR);
+ }
+
+ if ((odmlockid = odm_lock("/etc/objrepos/config_lock", ODM_WAIT)) == -1) {
+ if (odm_err_msg(odmerrno, &errstr) == -1)
+ errstr = "Unknown error";
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "bpf_load: odm_lock of /etc/objrepos/config_lock failed: %s",
+ errstr);
+ (void)odm_terminate();
+ return (PCAP_ERROR);
+ }
+
+ return (0);
+}
+
+static int
+bpf_odmcleanup(char *errbuf)
+{
+ char *errstr;
+
+ if (odm_unlock(odmlockid) == -1) {
+ if (errbuf != NULL) {
+ if (odm_err_msg(odmerrno, &errstr) == -1)
+ errstr = "Unknown error";
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "bpf_load: odm_unlock failed: %s",
+ errstr);
+ }
+ return (PCAP_ERROR);
+ }
+
+ if (odm_terminate() == -1) {
+ if (errbuf != NULL) {
+ if (odm_err_msg(odmerrno, &errstr) == -1)
+ errstr = "Unknown error";
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "bpf_load: odm_terminate failed: %s",
+ errstr);
+ }
+ return (PCAP_ERROR);
+ }
+
+ return (0);
+}
+
+static int
+bpf_load(char *errbuf)
+{
+ long major;
+ int *minors;
+ int numminors, i, rc;
+ char buf[1024];
+ struct stat sbuf;
+ struct bpf_config cfg_bpf;
+ struct cfg_load cfg_ld;
+ struct cfg_kmod cfg_km;
+
+ /*
+ * This is very very close to what happens in the real implementation
+ * but I've fixed some (unlikely) bug situations.
+ */
+ if (bpfloadedflag)
+ return (0);
+
+ if (bpf_odminit(errbuf) == PCAP_ERROR)
+ return (PCAP_ERROR);
+
+ major = genmajor(BPF_NAME);
+ if (major == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: genmajor failed");
+ (void)bpf_odmcleanup(NULL);
+ return (PCAP_ERROR);
+ }
+
+ minors = getminor(major, &numminors, BPF_NAME);
+ if (!minors) {
+ minors = genminor("bpf", major, 0, BPF_MINORS, 1, 1);
+ if (!minors) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: genminor failed");
+ (void)bpf_odmcleanup(NULL);
+ return (PCAP_ERROR);
+ }
+ }
+
+ if (bpf_odmcleanup(errbuf) == PCAP_ERROR)
+ return (PCAP_ERROR);
+
+ rc = stat(BPF_NODE "0", &sbuf);
+ if (rc == -1 && errno != ENOENT) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: can't stat %s", BPF_NODE "0");
+ return (PCAP_ERROR);
+ }
+
+ if (rc == -1 || getmajor(sbuf.st_rdev) != major) {
+ for (i = 0; i < BPF_MINORS; i++) {
+ pcap_snprintf(buf, sizeof(buf), "%s%d", BPF_NODE, i);
+ unlink(buf);
+ if (mknod(buf, S_IRUSR | S_IFCHR, domakedev(major, i)) == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "bpf_load: can't mknod %s", buf);
+ return (PCAP_ERROR);
+ }
+ }
+ }
+
+ /* Check if the driver is loaded */
+ memset(&cfg_ld, 0x0, sizeof(cfg_ld));
+ pcap_snprintf(buf, sizeof(buf), "%s/%s", DRIVER_PATH, BPF_NAME);
+ cfg_ld.path = buf;
+ if ((sysconfig(SYS_QUERYLOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) ||
+ (cfg_ld.kmid == 0)) {
+ /* Driver isn't loaded, load it now */
+ if (sysconfig(SYS_SINGLELOAD, (void *)&cfg_ld, sizeof(cfg_ld)) == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: could not load driver");
+ return (PCAP_ERROR);
+ }
+ }
+
+ /* Configure the driver */
+ cfg_km.cmd = CFG_INIT;
+ cfg_km.kmid = cfg_ld.kmid;
+ cfg_km.mdilen = sizeof(cfg_bpf);
+ cfg_km.mdiptr = (void *)&cfg_bpf;
+ for (i = 0; i < BPF_MINORS; i++) {
+ cfg_bpf.devno = domakedev(major, i);
+ if (sysconfig(SYS_CFGKMOD, (void *)&cfg_km, sizeof(cfg_km)) == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bpf_load: could not configure driver");
+ return (PCAP_ERROR);
+ }
+ }
+
+ bpfloadedflag = 1;
+
+ return (0);
+}
+#endif
+
+/*
+ * Undo any operations done when opening the device when necessary.
+ */
+static void
+pcap_cleanup_bpf(pcap_t *p)
+{
+ struct pcap_bpf *pb = p->priv;
+#ifdef HAVE_BSD_IEEE80211
+ int sock;
+ struct ifmediareq req;
+ struct ifreq ifr;
+#endif
+
+ if (pb->must_do_on_close != 0) {
+ /*
+ * There's something we have to do when closing this
+ * pcap_t.
+ */
+#ifdef HAVE_BSD_IEEE80211
+ if (pb->must_do_on_close & MUST_CLEAR_RFMON) {
+ /*
+ * We put the interface into rfmon mode;
+ * take it out of rfmon mode.
+ *
+ * XXX - if somebody else wants it in rfmon
+ * mode, this code cannot know that, so it'll take
+ * it out of rfmon mode.
+ */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags (socket() failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ } else {
+ memset(&req, 0, sizeof(req));
+
+#ifdef __APPLE__
+ strlcpy(req.ifm_name, pb->device,
+ sizeof(req.ifm_name));
+#else
+ strncpy(req.ifm_name, pb->device,
+ sizeof(req.ifm_name));
+#endif /* __APPLE__ */
+
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ fprintf(stderr,
+ "Can't restore interface flags (SIOCGIFMEDIA failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ } else {
+ if (req.ifm_current & IFM_IEEE80211_MONITOR) {
+ /*
+ * Rfmon mode is currently on;
+ * turn it off.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+
+#ifdef __APPLE__
+ (void)strlcpy(ifr.ifr_name,
+ pb->device,
+ sizeof(ifr.ifr_name));
+#else
+ (void)strncpy(ifr.ifr_name,
+ pb->device,
+ sizeof(ifr.ifr_name));
+#endif /* __APPLE__ */
+
+ ifr.ifr_media =
+ req.ifm_current & ~IFM_IEEE80211_MONITOR;
+ if (ioctl(sock, SIOCSIFMEDIA,
+ &ifr) == -1) {
+ fprintf(stderr,
+ "Can't restore interface flags (SIOCSIFMEDIA failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ }
+ }
+ }
+ close(sock);
+ }
+ }
+#endif /* HAVE_BSD_IEEE80211 */
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ /*
+ * Attempt to destroy the usbusN interface that we created.
+ */
+ if (pb->must_do_on_close & MUST_DESTROY_USBUS) {
+ if (if_nametoindex(pb->device) > 0) {
+ int s;
+
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s >= 0) {
+ pcap_strlcpy(ifr.ifr_name, pb->device,
+ sizeof(ifr.ifr_name));
+ ioctl(s, SIOCIFDESTROY, &ifr);
+ close(s);
+ }
+ }
+ }
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
+ /*
+ * Take this pcap out of the list of pcaps for which we
+ * have to take the interface out of some mode.
+ */
+ pcap_remove_from_pcaps_to_close(p);
+ pb->must_do_on_close = 0;
+ }
+
+#ifdef HAVE_ZEROCOPY_BPF
+ if (pb->zerocopy) {
+ /*
+ * Delete the mappings. Note that p->buffer gets
+ * initialized to one of the mmapped regions in
+ * this case, so do not try and free it directly;
+ * null it out so that pcap_cleanup_live_common()
+ * doesn't try to free it.
+ */
+ if (pb->zbuf1 != MAP_FAILED && pb->zbuf1 != NULL)
+ (void) munmap(pb->zbuf1, pb->zbufsize);
+ if (pb->zbuf2 != MAP_FAILED && pb->zbuf2 != NULL)
+ (void) munmap(pb->zbuf2, pb->zbufsize);
+ p->buffer = NULL;
+ }
+#endif
+ if (pb->device != NULL) {
+ free(pb->device);
+ pb->device = NULL;
+ }
+ pcap_cleanup_live_common(p);
+}
+
+static int
+check_setif_failure(pcap_t *p, int error)
+{
+#ifdef __APPLE__
+ int fd;
+ struct ifreq ifr;
+ int err;
+#endif
+
+ if (error == ENXIO) {
+ /*
+ * No such device exists.
+ */
+#ifdef __APPLE__
+ if (p->opt.rfmon && strncmp(p->opt.device, "wlt", 3) == 0) {
+ /*
+ * Monitor mode was requested, and we're trying
+ * to open a "wltN" device. Assume that this
+ * is 10.4 and that we were asked to open an
+ * "enN" device; if that device exists, return
+ * "monitor mode not supported on the device".
+ */
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd != -1) {
+ pcap_strlcpy(ifr.ifr_name, "en",
+ sizeof(ifr.ifr_name));
+ pcap_strlcat(ifr.ifr_name, p->opt.device + 3,
+ sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifr) < 0) {
+ /*
+ * We assume this failed because
+ * the underlying device doesn't
+ * exist.
+ */
+ err = PCAP_ERROR_NO_SUCH_DEVICE;
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFFLAGS on %s failed",
+ ifr.ifr_name);
+ } else {
+ /*
+ * The underlying "enN" device
+ * exists, but there's no
+ * corresponding "wltN" device;
+ * that means that the "enN"
+ * device doesn't support
+ * monitor mode, probably because
+ * it's an Ethernet device rather
+ * than a wireless device.
+ */
+ err = PCAP_ERROR_RFMON_NOTSUP;
+ }
+ close(fd);
+ } else {
+ /*
+ * We can't find out whether there's
+ * an underlying "enN" device, so
+ * just report "no such device".
+ */
+ err = PCAP_ERROR_NO_SUCH_DEVICE;
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ errno, PCAP_ERRBUF_SIZE,
+ "socket() failed");
+ }
+ return (err);
+ }
+#endif
+ /*
+ * No such device.
+ */
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF failed");
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ } else if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return (PCAP_ERROR_IFACE_NOT_UP);
+ } else {
+ /*
+ * Some other error; fill in the error string, and
+ * return PCAP_ERROR.
+ */
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", p->opt.device);
+ return (PCAP_ERROR);
+ }
+}
+
+/*
+ * Default capture buffer size.
+ * 32K isn't very much for modern machines with fast networks; we
+ * pick .5M, as that's the maximum on at least some systems with BPF.
+ *
+ * However, on AIX 3.5, the larger buffer sized caused unrecoverable
+ * read failures under stress, so we leave it as 32K; yet another
+ * place where AIX's BPF is broken.
+ */
+#ifdef _AIX
+#define DEFAULT_BUFSIZE 32768
+#else
+#define DEFAULT_BUFSIZE 524288
+#endif
+
+static int
+pcap_activate_bpf(pcap_t *p)
+{
+ struct pcap_bpf *pb = p->priv;
+ int status = 0;
+#ifdef HAVE_BSD_IEEE80211
+ int retv;
+#endif
+ int fd;
+#ifdef LIFNAMSIZ
+ char *zonesep;
+ struct lifreq ifr;
+ char *ifrname = ifr.lifr_name;
+ const size_t ifnamsiz = sizeof(ifr.lifr_name);
+#else
+ struct ifreq ifr;
+ char *ifrname = ifr.ifr_name;
+ const size_t ifnamsiz = sizeof(ifr.ifr_name);
+#endif
+ struct bpf_version bv;
+#ifdef __APPLE__
+ int sockfd;
+ char *wltdev = NULL;
+#endif
+#ifdef BIOCGDLTLIST
+ struct bpf_dltlist bdl;
+#if defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)
+ int new_dlt;
+#endif
+#endif /* BIOCGDLTLIST */
+#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
+ u_int spoof_eth_src = 1;
+#endif
+ u_int v;
+ struct bpf_insn total_insn;
+ struct bpf_program total_prog;
+ struct utsname osinfo;
+ int have_osinfo = 0;
+#ifdef HAVE_ZEROCOPY_BPF
+ struct bpf_zbuf bz;
+ u_int bufmode, zbufmax;
+#endif
+
+ fd = bpf_open(p->errbuf);
+ if (fd < 0) {
+ status = fd;
+ goto bad;
+ }
+
+ p->fd = fd;
+
+ if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCVERSION");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ if (bv.bv_major != BPF_MAJOR_VERSION ||
+ bv.bv_minor < BPF_MINOR_VERSION) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "kernel bpf filter out of date");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+#ifdef __APPLE__
+#ifdef BIOCSWANTPKTAP
+ if (ioctl(p->fd, BIOCSWANTPKTAP, (caddr_t)&p->wantpktap) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSWANTPKTAP: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif
+
+#ifdef BIOCSTRUNCATE
+ v = p->truncation;
+ if (v != 0 && ioctl(p->fd, BIOCSTRUNCATE, &v)) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSTRUNCATE: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif /* BIOCSTRUNCATE */
+
+#ifdef BIOCSPKTHDRV2
+ v = p->pktaphdrv2;
+ if (v != 0 && ioctl(p->fd, BIOCSPKTHDRV2, &v)) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSPKTHDRV2: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif /* BIOCSPKTHDRV2 */
+#endif /* __APPLE__ */
+
+
+#if defined(LIFNAMSIZ) && defined(ZONENAME_MAX) && defined(lifr_zoneid)
+ /*
+ * Retrieve the zoneid of the zone we are currently executing in.
+ */
+ if ((ifr.lifr_zoneid = getzoneid()) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "getzoneid()");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ /*
+ * Check if the given source datalink name has a '/' separated
+ * zonename prefix string. The zonename prefixed source datalink can
+ * be used by pcap consumers in the Solaris global zone to capture
+ * traffic on datalinks in non-global zones. Non-global zones
+ * do not have access to datalinks outside of their own namespace.
+ */
+ if ((zonesep = strchr(p->opt.device, '/')) != NULL) {
+ char path_zname[ZONENAME_MAX];
+ int znamelen;
+ char *lnamep;
+
+ if (ifr.lifr_zoneid != GLOBAL_ZONEID) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "zonename/linkname only valid in global zone.");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ znamelen = zonesep - p->opt.device;
+ (void) pcap_strlcpy(path_zname, p->opt.device, znamelen + 1);
+ ifr.lifr_zoneid = getzoneidbyname(path_zname);
+ if (ifr.lifr_zoneid == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "getzoneidbyname(%s)", path_zname);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ lnamep = strdup(zonesep + 1);
+ if (lnamep == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "strdup");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ free(p->opt.device);
+ p->opt.device = lnamep;
+ }
+#endif
+
+ pb->device = strdup(p->opt.device);
+ if (pb->device == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "strdup");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Attempt to find out the version of the OS on which we're running.
+ */
+ if (uname(&osinfo) == 0)
+ have_osinfo = 1;
+
+#ifdef __APPLE__
+ /*
+ * See comment in pcap_can_set_rfmon_bpf() for an explanation
+ * of why we check the version number.
+ */
+ if (p->opt.rfmon) {
+ if (have_osinfo) {
+ /*
+ * We assume osinfo.sysname is "Darwin", because
+ * __APPLE__ is defined. We just check the version.
+ */
+ if (osinfo.release[0] < '8' &&
+ osinfo.release[1] == '.') {
+ /*
+ * 10.3 (Darwin 7.x) or earlier.
+ */
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+ if (osinfo.release[0] == '8' &&
+ osinfo.release[1] == '.') {
+ /*
+ * 10.4 (Darwin 8.x). s/en/wlt/
+ */
+ if (strncmp(p->opt.device, "en", 2) != 0) {
+ /*
+ * Not an enN device; check
+ * whether the device even exists.
+ */
+ sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd != -1) {
+ pcap_strlcpy(ifrname,
+ p->opt.device, ifnamsiz);
+ if (ioctl(sockfd, SIOCGIFFLAGS,
+ (char *)&ifr) < 0) {
+ /*
+ * We assume this
+ * failed because
+ * the underlying
+ * device doesn't
+ * exist.
+ */
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE,
+ errno,
+ "SIOCGIFFLAGS failed");
+ } else
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ close(sockfd);
+ } else {
+ /*
+ * We can't find out whether
+ * the device exists, so just
+ * report "no such device".
+ */
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "socket() failed");
+ }
+ goto bad;
+ }
+ wltdev = malloc(strlen(p->opt.device) + 2);
+ if (wltdev == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ strcpy(wltdev, "wlt");
+ strcat(wltdev, p->opt.device + 2);
+ free(p->opt.device);
+ p->opt.device = wltdev;
+ }
+ /*
+ * Everything else is 10.5 or later; for those,
+ * we just open the enN device, and set the DLT.
+ */
+ }
+ }
+#endif /* __APPLE__ */
+
+ /*
+ * If this is FreeBSD, and the device name begins with "usbus",
+ * try to create the interface if it's not available.
+ */
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ if (strncmp(p->opt.device, usbus_prefix, USBUS_PREFIX_LEN) == 0) {
+ /*
+ * Do we already have an interface with that name?
+ */
+ if (if_nametoindex(p->opt.device) == 0) {
+ /*
+ * No. We need to create it, and, if we
+ * succeed, remember that we should destroy
+ * it when the pcap_t is closed.
+ */
+ int s;
+
+ /*
+ * Open a socket to use for ioctls to
+ * create the interface.
+ */
+ s = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ if (s < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't open socket");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(p)) {
+ /*
+ * "atexit()" failed; don't create the
+ * interface, just give up.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "atexit failed");
+ close(s);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Create the interface.
+ */
+ pcap_strlcpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCIFCREATE2, &ifr) < 0) {
+ if (errno == EINVAL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Invalid USB bus interface %s",
+ p->opt.device);
+ } else {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't create interface for %s",
+ p->opt.device);
+ }
+ close(s);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Make sure we clean this up when we close.
+ */
+ pb->must_do_on_close |= MUST_DESTROY_USBUS;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(p);
+ }
+ }
+#endif /* defined(__FreeBSD__) && defined(SIOCIFCREATE2) */
+
+#ifdef HAVE_ZEROCOPY_BPF
+ /*
+ * If the BPF extension to set buffer mode is present, try setting
+ * the mode to zero-copy. If that fails, use regular buffering. If
+ * it succeeds but other setup fails, return an error to the user.
+ */
+ bufmode = BPF_BUFMODE_ZBUF;
+ if (ioctl(fd, BIOCSETBUFMODE, (caddr_t)&bufmode) == 0) {
+ /*
+ * We have zerocopy BPF; use it.
+ */
+ pb->zerocopy = 1;
+
+ /*
+ * How to pick a buffer size: first, query the maximum buffer
+ * size supported by zero-copy. This also lets us quickly
+ * determine whether the kernel generally supports zero-copy.
+ * Then, if a buffer size was specified, use that, otherwise
+ * query the default buffer size, which reflects kernel
+ * policy for a desired default. Round to the nearest page
+ * size.
+ */
+ if (ioctl(fd, BIOCGETZMAX, (caddr_t)&zbufmax) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGETZMAX");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ if (p->opt.buffer_size != 0) {
+ /*
+ * A buffer size was explicitly specified; use it.
+ */
+ v = p->opt.buffer_size;
+ } else {
+ if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) ||
+ v < DEFAULT_BUFSIZE)
+ v = DEFAULT_BUFSIZE;
+ }
+#ifndef roundup
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* to any y */
+#endif
+ pb->zbufsize = roundup(v, getpagesize());
+ if (pb->zbufsize > zbufmax)
+ pb->zbufsize = zbufmax;
+ pb->zbuf1 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
+ MAP_ANON, -1, 0);
+ pb->zbuf2 = mmap(NULL, pb->zbufsize, PROT_READ | PROT_WRITE,
+ MAP_ANON, -1, 0);
+ if (pb->zbuf1 == MAP_FAILED || pb->zbuf2 == MAP_FAILED) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "mmap");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ memset(&bz, 0, sizeof(bz)); /* bzero() deprecated, replaced with memset() */
+ bz.bz_bufa = pb->zbuf1;
+ bz.bz_bufb = pb->zbuf2;
+ bz.bz_buflen = pb->zbufsize;
+ if (ioctl(fd, BIOCSETZBUF, (caddr_t)&bz) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETZBUF");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#ifdef __APPLE__
+ (void)strlcpy(ifrname, p->opt.device, ifnamsiz);
+#else
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
+#endif /* __APPLE__ */
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETIF: %s", p->opt.device);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ v = pb->zbufsize - sizeof(struct bpf_zbuf_header);
+ } else
+#endif
+ {
+ /*
+ * We don't have zerocopy BPF.
+ * Set the buffer size.
+ */
+ if (p->opt.buffer_size != 0) {
+ /*
+ * A buffer size was explicitly specified; use it.
+ */
+ if (ioctl(fd, BIOCSBLEN,
+ (caddr_t)&p->opt.buffer_size) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "BIOCSBLEN: %s", p->opt.device);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Now bind to the device.
+ */
+#ifdef __APPLE__
+ (void)strlcpy(ifrname, p->opt.device, ifnamsiz);
+#else
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
+#endif /* __APPLE__ */
+
+#ifdef BIOCSETLIF
+ if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) < 0)
+#else
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0)
+#endif
+ {
+ status = check_setif_failure(p, errno);
+ goto bad;
+ }
+ } else {
+ /*
+ * No buffer size was explicitly specified.
+ *
+ * Try finding a good size for the buffer;
+ * DEFAULT_BUFSIZE may be too big, so keep
+ * cutting it in half until we find a size
+ * that works, or run out of sizes to try.
+ * If the default is larger, don't make it smaller.
+ */
+ if ((ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) ||
+ v < DEFAULT_BUFSIZE)
+ v = DEFAULT_BUFSIZE;
+ for ( ; v != 0; v >>= 1) {
+ /*
+ * Ignore the return value - this is because the
+ * call fails on BPF systems that don't have
+ * kernel malloc. And if the call fails, it's
+ * no big deal, we just continue to use the
+ * standard buffer size.
+ */
+ (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v);
+
+#ifdef __APPLE__
+ (void)strlcpy(ifrname, p->opt.device, ifnamsiz);
+#else
+ (void)strncpy(ifrname, p->opt.device, ifnamsiz);
+#endif /* __APPLE__ */
+
+#ifdef BIOCSETLIF
+ if (ioctl(fd, BIOCSETLIF, (caddr_t)&ifr) >= 0)
+#else
+ if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0)
+#endif
+ break; /* that size worked; we're done */
+
+ if (errno != ENOBUFS) {
+ status = check_setif_failure(p, errno);
+ goto bad;
+ }
+ }
+
+ if (v == 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "BIOCSBLEN: %s: No buffer size worked",
+ p->opt.device);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ }
+ }
+
+ /* Get the data link layer type. */
+ if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGDLT");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+#ifdef _AIX
+ /*
+ * AIX's BPF returns IFF_ types, not DLT_ types, in BIOCGDLT.
+ */
+ switch (v) {
+
+ case IFT_ETHER:
+ case IFT_ISO88023:
+ v = DLT_EN10MB;
+ break;
+
+ case IFT_FDDI:
+ v = DLT_FDDI;
+ break;
+
+ case IFT_ISO88025:
+ v = DLT_IEEE802;
+ break;
+
+ case IFT_LOOP:
+ v = DLT_NULL;
+ break;
+
+ default:
+ /*
+ * We don't know what to map this to yet.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "unknown interface type %u",
+ v);
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif
+#if _BSDI_VERSION - 0 >= 199510
+ /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */
+ switch (v) {
+
+ case DLT_SLIP:
+ v = DLT_SLIP_BSDOS;
+ break;
+
+ case DLT_PPP:
+ v = DLT_PPP_BSDOS;
+ break;
+
+ case 11: /*DLT_FR*/
+ v = DLT_FRELAY;
+ break;
+
+ case 12: /*DLT_C_HDLC*/
+ v = DLT_CHDLC;
+ break;
+ }
+#endif
+
+#ifdef BIOCGDLTLIST
+ /*
+ * We know the default link type -- now determine all the DLTs
+ * this interface supports. If this fails with EINVAL, it's
+ * not fatal; we just don't get to use the feature later.
+ */
+ if (get_dlt_list(fd, v, &bdl, p->errbuf) == -1) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ p->dlt_count = bdl.bfl_len;
+ p->dlt_list = bdl.bfl_list;
+
+#ifdef __APPLE__
+ /*
+ * Monitor mode fun, continued.
+ *
+ * For 10.5 and, we're assuming, later releases, as noted above,
+ * 802.1 adapters that support monitor mode offer both DLT_EN10MB,
+ * DLT_IEEE802_11, and possibly some 802.11-plus-radio-information
+ * DLT_ value. Choosing one of the 802.11 DLT_ values will turn
+ * monitor mode on.
+ *
+ * Therefore, if the user asked for monitor mode, we filter out
+ * the DLT_EN10MB value, as you can't get that in monitor mode,
+ * and, if the user didn't ask for monitor mode, we filter out
+ * the 802.11 DLT_ values, because selecting those will turn
+ * monitor mode on. Then, for monitor mode, if an 802.11-plus-
+ * radio DLT_ value is offered, we try to select that, otherwise
+ * we try to select DLT_IEEE802_11.
+ */
+ if (have_osinfo) {
+ if (isdigit((unsigned)osinfo.release[0]) &&
+ (osinfo.release[0] == '9' ||
+ isdigit((unsigned)osinfo.release[1]))) {
+ /*
+ * 10.5 (Darwin 9.x), or later.
+ */
+ new_dlt = find_802_11(&bdl);
+ if (new_dlt != -1) {
+ /*
+ * We have at least one 802.11 DLT_ value,
+ * so this is an 802.11 interface.
+ * new_dlt is the best of the 802.11
+ * DLT_ values in the list.
+ */
+ if (p->opt.rfmon) {
+ /*
+ * Our caller wants monitor mode.
+ * Purge DLT_EN10MB from the list
+ * of link-layer types, as selecting
+ * it will keep monitor mode off.
+ */
+ remove_non_802_11(p);
+
+ /*
+ * If the new mode we want isn't
+ * the default mode, attempt to
+ * select the new mode.
+ */
+ if ((u_int)new_dlt != v) {
+ if (ioctl(p->fd, BIOCSDLT,
+ &new_dlt) != -1) {
+ /*
+ * We succeeded;
+ * make this the
+ * new DLT_ value.
+ */
+ v = new_dlt;
+ }
+ }
+ } else {
+ /*
+ * Our caller doesn't want
+ * monitor mode. Unless this
+ * is being done by pcap_open_live(),
+ * purge the 802.11 link-layer types
+ * from the list, as selecting
+ * one of them will turn monitor
+ * mode on.
+ */
+ if (!p->oldstyle)
+ remove_802_11(p);
+ }
+ } else {
+ if (p->opt.rfmon) {
+ /*
+ * The caller requested monitor
+ * mode, but we have no 802.11
+ * link-layer types, so they
+ * can't have it.
+ */
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+ }
+ }
+ }
+#elif defined(HAVE_BSD_IEEE80211)
+ /*
+ * *BSD with the new 802.11 ioctls.
+ * Do we want monitor mode?
+ */
+ if (p->opt.rfmon) {
+ /*
+ * Try to put the interface into monitor mode.
+ */
+ retv = monitor_mode(p, 1);
+ if (retv != 0) {
+ /*
+ * We failed.
+ */
+ status = retv;
+ goto bad;
+ }
+
+ /*
+ * We're in monitor mode.
+ * Try to find the best 802.11 DLT_ value and, if we
+ * succeed, try to switch to that mode if we're not
+ * already in that mode.
+ */
+ new_dlt = find_802_11(&bdl);
+ if (new_dlt != -1) {
+ /*
+ * We have at least one 802.11 DLT_ value.
+ * new_dlt is the best of the 802.11
+ * DLT_ values in the list.
+ *
+ * If the new mode we want isn't the default mode,
+ * attempt to select the new mode.
+ */
+ if ((u_int)new_dlt != v) {
+ if (ioctl(p->fd, BIOCSDLT, &new_dlt) != -1) {
+ /*
+ * We succeeded; make this the
+ * new DLT_ value.
+ */
+ v = new_dlt;
+ }
+ }
+ }
+ }
+#endif /* various platforms */
+#endif /* BIOCGDLTLIST */
+
+ /*
+ * If this is an Ethernet device, and we don't have a DLT_ list,
+ * give it a list with DLT_EN10MB and DLT_DOCSIS. (That'd give
+ * 802.11 interfaces DLT_DOCSIS, which isn't the right thing to
+ * do, but there's not much we can do about that without finding
+ * some other way of determining whether it's an Ethernet or 802.11
+ * device.)
+ */
+ if (v == DLT_EN10MB && p->dlt_count == 0) {
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+ }
+#ifdef PCAP_FDDIPAD
+ if (v == DLT_FDDI)
+ p->fddipad = PCAP_FDDIPAD;
+ else
+#endif
+ p->fddipad = 0;
+ p->linktype = v;
+
+#if defined(BIOCGHDRCMPLT) && defined(BIOCSHDRCMPLT)
+ /*
+ * Do a BIOCSHDRCMPLT, if defined, to turn that flag on, so
+ * the link-layer source address isn't forcibly overwritten.
+ * (Should we ignore errors? Should we do this only if
+ * we're open for writing?)
+ *
+ * XXX - I seem to remember some packet-sending bug in some
+ * BSDs - check CVS log for "bpf.c"?
+ */
+ if (ioctl(fd, BIOCSHDRCMPLT, &spoof_eth_src) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSHDRCMPLT");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif
+ /* set timeout */
+#ifdef HAVE_ZEROCOPY_BPF
+ /*
+ * In zero-copy mode, we just use the timeout in select().
+ * XXX - what if we're in non-blocking mode and the *application*
+ * is using select() or poll() or kqueues or....?
+ */
+ if (p->opt.timeout && !pb->zerocopy) {
+#else
+ if (p->opt.timeout) {
+#endif
+ /*
+ * XXX - is this seconds/nanoseconds in AIX?
+ * (Treating it as such doesn't fix the timeout
+ * problem described below.)
+ *
+ * XXX - Mac OS X 10.6 mishandles BIOCSRTIMEOUT in
+ * 64-bit userland - it takes, as an argument, a
+ * "struct BPF_TIMEVAL", which has 32-bit tv_sec
+ * and tv_usec, rather than a "struct timeval".
+ *
+ * If this platform defines "struct BPF_TIMEVAL",
+ * we check whether the structure size in BIOCSRTIMEOUT
+ * is that of a "struct timeval" and, if not, we use
+ * a "struct BPF_TIMEVAL" rather than a "struct timeval".
+ * (That way, if the bug is fixed in a future release,
+ * we will still do the right thing.)
+ */
+ struct timeval to;
+#ifdef HAVE_STRUCT_BPF_TIMEVAL
+ struct BPF_TIMEVAL bpf_to;
+
+ if (IOCPARM_LEN(BIOCSRTIMEOUT) != sizeof(struct timeval)) {
+ bpf_to.tv_sec = p->opt.timeout / 1000;
+ bpf_to.tv_usec = (p->opt.timeout * 1000) % 1000000;
+ if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&bpf_to) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ } else {
+#endif
+ to.tv_sec = p->opt.timeout / 1000;
+ to.tv_usec = (p->opt.timeout * 1000) % 1000000;
+ if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ errno, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#ifdef HAVE_STRUCT_BPF_TIMEVAL
+ }
+#endif
+ }
+
+#ifdef BIOCIMMEDIATE
+ /*
+ * Darren Reed notes that
+ *
+ * On AIX (4.2 at least), if BIOCIMMEDIATE is not set, the
+ * timeout appears to be ignored and it waits until the buffer
+ * is filled before returning. The result of not having it
+ * set is almost worse than useless if your BPF filter
+ * is reducing things to only a few packets (i.e. one every
+ * second or so).
+ *
+ * so we always turn BIOCIMMEDIATE mode on if this is AIX.
+ *
+ * For other platforms, we don't turn immediate mode on by default,
+ * as that would mean we get woken up for every packet, which
+ * probably isn't what you want for a packet sniffer.
+ *
+ * We set immediate mode if the caller requested it by calling
+ * pcap_set_immediate() before calling pcap_activate().
+ */
+#ifndef _AIX
+ if (p->opt.immediate) {
+#endif /* _AIX */
+ v = 1;
+ if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCIMMEDIATE");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#ifndef _AIX
+ }
+#endif /* _AIX */
+#else /* BIOCIMMEDIATE */
+ if (p->opt.immediate) {
+ /*
+ * We don't support immediate mode. Fail.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Immediate mode not supported");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif /* BIOCIMMEDIATE */
+
+ if (p->opt.promisc) {
+ /* set promiscuous mode, just warn if it fails */
+ if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCPROMISC");
+ status = PCAP_WARNING_PROMISC_NOTSUP;
+ }
+ }
+
+#ifdef BIOCSTSTAMP
+ v = BPF_T_BINTIME;
+ if (ioctl(p->fd, BIOCSTSTAMP, &v) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSTSTAMP");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif /* BIOCSTSTAMP */
+
+ if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCGBLEN");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ p->bufsize = v;
+#ifdef HAVE_ZEROCOPY_BPF
+ if (!pb->zerocopy) {
+#endif
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#ifdef _AIX
+ /* For some strange reason this seems to prevent the EFAULT
+ * problems we have experienced from AIX BPF. */
+ memset(p->buffer, 0x0, p->bufsize);
+#endif
+#ifdef HAVE_ZEROCOPY_BPF
+ }
+#endif
+
+ /*
+ * If there's no filter program installed, there's
+ * no indication to the kernel of what the snapshot
+ * length should be, so no snapshotting is done.
+ *
+ * Therefore, when we open the device, we install
+ * an "accept everything" filter with the specified
+ * snapshot length.
+ */
+ total_insn.code = (u_short)(BPF_RET | BPF_K);
+ total_insn.jt = 0;
+ total_insn.jf = 0;
+ total_insn.k = p->snapshot;
+
+ total_prog.bf_len = 1;
+ total_prog.bf_insns = &total_insn;
+ if (ioctl(p->fd, BIOCSETF, (caddr_t)&total_prog) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETF");
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * On most BPF platforms, either you can do a "select()" or
+ * "poll()" on a BPF file descriptor and it works correctly,
+ * or you can do it and it will return "readable" if the
+ * hold buffer is full but not if the timeout expires *and*
+ * a non-blocking read will, if the hold buffer is empty
+ * but the store buffer isn't empty, rotate the buffers
+ * and return what packets are available.
+ *
+ * In the latter case, the fact that a non-blocking read
+ * will give you the available packets means you can work
+ * around the failure of "select()" and "poll()" to wake up
+ * and return "readable" when the timeout expires by using
+ * the timeout as the "select()" or "poll()" timeout, putting
+ * the BPF descriptor into non-blocking mode, and read from
+ * it regardless of whether "select()" reports it as readable
+ * or not.
+ *
+ * However, in FreeBSD 4.3 and 4.4, "select()" and "poll()"
+ * won't wake up and return "readable" if the timer expires
+ * and non-blocking reads return EWOULDBLOCK if the hold
+ * buffer is empty, even if the store buffer is non-empty.
+ *
+ * This means the workaround in question won't work.
+ *
+ * Therefore, on FreeBSD 4.3 and 4.4, we set "p->selectable_fd"
+ * to -1, which means "sorry, you can't use 'select()' or 'poll()'
+ * here". On all other BPF platforms, we set it to the FD for
+ * the BPF device; in NetBSD, OpenBSD, and Darwin, a non-blocking
+ * read will, if the hold buffer is empty and the store buffer
+ * isn't empty, rotate the buffers and return what packets are
+ * there (and in sufficiently recent versions of OpenBSD
+ * "select()" and "poll()" should work correctly).
+ *
+ * XXX - what about AIX?
+ */
+ p->selectable_fd = p->fd; /* assume select() works until we know otherwise */
+ if (have_osinfo) {
+ /*
+ * We can check what OS this is.
+ */
+ if (strcmp(osinfo.sysname, "FreeBSD") == 0) {
+ if (strncmp(osinfo.release, "4.3-", 4) == 0 ||
+ strncmp(osinfo.release, "4.4-", 4) == 0)
+ p->selectable_fd = -1;
+ }
+ }
+
+ p->read_op = pcap_read_bpf;
+ p->inject_op = pcap_inject_bpf;
+ p->setfilter_op = pcap_setfilter_bpf;
+ p->setdirection_op = pcap_setdirection_bpf;
+ p->set_datalink_op = pcap_set_datalink_bpf;
+ p->getnonblock_op = pcap_getnonblock_bpf;
+ p->setnonblock_op = pcap_setnonblock_bpf;
+ p->stats_op = pcap_stats_bpf;
+ p->cleanup_op = pcap_cleanup_bpf;
+
+ return (status);
+ bad:
+ pcap_cleanup_bpf(p);
+ return (status);
+}
+
+/*
+ * Not all interfaces can be bound to by BPF, so try to bind to
+ * the specified interface; return 0 if we fail with
+ * PCAP_ERROR_NO_SUCH_DEVICE (which means we got an ENXIO when we tried
+ * to bind, which means this interface isn't in the list of interfaces
+ * attached to BPF) and 1 otherwise.
+ */
+static int
+check_bpf_bindable(const char *name)
+{
+ int fd;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ /*
+ * On macOS, we don't do this check if the device name begins
+ * with "wlt"; at least some versions of macOS (actually, it
+ * was called "Mac OS X" then...) offer monitor mode capturing
+ * by having a separate "monitor mode" device for each wireless
+ * adapter, rather than by implementing the ioctls that
+ * {Free,Net,Open,DragonFly}BSD provide. Opening that device
+ * puts the adapter into monitor mode, which, at least for
+ * some adapters, causes them to deassociate from the network
+ * with which they're associated.
+ *
+ * Instead, we try to open the corresponding "en" device (so
+ * that we don't end up with, for users without sufficient
+ * privilege to open capture devices, a list of adapters that
+ * only includes the wlt devices).
+ */
+#ifdef __APPLE__
+ if (strncmp(name, "wlt", 3) == 0) {
+ char *en_name;
+ size_t en_name_len;
+
+ /*
+ * Try to allocate a buffer for the "en"
+ * device's name.
+ */
+ en_name_len = strlen(name) - 1;
+ en_name = malloc(en_name_len + 1);
+ if (en_name == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+ strcpy(en_name, "en");
+ strcat(en_name, name + 3);
+ fd = bpf_open_and_bind(en_name, errbuf);
+ free(en_name);
+ } else
+#endif /* __APPLE */
+ fd = bpf_open_and_bind(name, errbuf);
+ if (fd < 0) {
+ /*
+ * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+ */
+ if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Yes, so we can't bind to this because it's
+ * not something supported by BPF.
+ */
+ return (0);
+ }
+ /*
+ * No, so we don't know whether it's supported or not;
+ * say it is, so that the user can at least try to
+ * open it and report the error (which is probably
+ * "you don't have permission to open BPF devices";
+ * reporting those interfaces means users will ask
+ * "why am I getting a permissions error when I try
+ * to capture" rather than "why am I not seeing any
+ * interfaces", making the underlying problem clearer).
+ */
+ return (1);
+ }
+
+ /*
+ * Success.
+ */
+ close(fd);
+ return (1);
+}
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+static int
+get_usb_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * XXX - if there's a way to determine whether there's something
+ * plugged into a given USB bus, use that to determine whether
+ * this device is "connected" or not.
+ */
+ return (0);
+}
+
+static int
+finddevs_usb(pcap_if_list_t *devlistp, char *errbuf)
+{
+ DIR *usbdir;
+ struct dirent *usbitem;
+ size_t name_max;
+ char *name;
+
+ /*
+ * We might have USB sniffing support, so try looking for USB
+ * interfaces.
+ *
+ * We want to report a usbusN device for each USB bus, but
+ * usbusN interfaces might, or might not, exist for them -
+ * we create one if there isn't already one.
+ *
+ * So, instead, we look in /dev/usb for all buses and create
+ * a "usbusN" device for each one.
+ */
+ usbdir = opendir("/dev/usb");
+ if (usbdir == NULL) {
+ /*
+ * Just punt.
+ */
+ return (0);
+ }
+
+ /*
+ * Leave enough room for a 32-bit (10-digit) bus number.
+ * Yes, that's overkill, but we won't be using
+ * the buffer very long.
+ */
+ name_max = USBUS_PREFIX_LEN + 10 + 1;
+ name = malloc(name_max);
+ if (name == NULL) {
+ closedir(usbdir);
+ return (0);
+ }
+ while ((usbitem = readdir(usbdir)) != NULL) {
+ char *p;
+ size_t busnumlen;
+
+ if (strcmp(usbitem->d_name, ".") == 0 ||
+ strcmp(usbitem->d_name, "..") == 0) {
+ /*
+ * Ignore these.
+ */
+ continue;
+ }
+ p = strchr(usbitem->d_name, '.');
+ if (p == NULL)
+ continue;
+ busnumlen = p - usbitem->d_name;
+ memcpy(name, usbus_prefix, USBUS_PREFIX_LEN);
+ memcpy(name + USBUS_PREFIX_LEN, usbitem->d_name, busnumlen);
+ *(name + USBUS_PREFIX_LEN + busnumlen) = '\0';
+ /*
+ * There's an entry in this directory for every USB device,
+ * not for every bus; if there's more than one device on
+ * the bus, there'll be more than one entry for that bus,
+ * so we need to avoid adding multiple capture devices
+ * for each bus.
+ */
+ if (find_or_add_dev(devlistp, name, PCAP_IF_UP,
+ get_usb_if_flags, NULL, errbuf) == NULL) {
+ free(name);
+ closedir(usbdir);
+ return (PCAP_ERROR);
+ }
+ }
+ free(name);
+ closedir(usbdir);
+ return (0);
+}
+#endif
+
+/*
+ * Get additional flags for a device, using SIOCGIFMEDIA.
+ */
+#ifdef SIOCGIFMEDIA
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+ int sock;
+ struct ifmediareq req;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "Can't create socket to get media information for %s",
+ name);
+ return (-1);
+ }
+ memset(&req, 0, sizeof(req));
+#ifdef __APPLE__
+ strlcpy(req.ifm_name, name, sizeof(req.ifm_name));
+#else
+ strncpy(req.ifm_name, name, sizeof(req.ifm_name));
+#endif /* __APPLE__ */
+
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ if (errno == EOPNOTSUPP || errno == EINVAL || errno == ENOTTY ||
+#ifdef __APPLE__
+ errno == EPWROFF ||
+#endif /* __APPLE__ */
+ errno == ENODEV || errno == EPERM) {
+ /*
+ * Not supported, so we can't provide any
+ * additional information. Assume that
+ * this means that "connected" vs.
+ * "disconnected" doesn't apply.
+ *
+ * The ioctl routine for Apple's pktap devices,
+ * annoyingly, checks for "are you root?" before
+ * checking whether the ioctl is valid, so it
+ * returns EPERM, rather than ENOTSUP, for the
+ * invalid SIOCGIFMEDIA, unless you're root.
+ * So, just as we do for some ethtool ioctls
+ * on Linux, which makes the same mistake, we
+ * also treat EPERM as meaning "not supported".
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ close(sock);
+ return (0);
+ }
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "SIOCGIFMEDIA on %s failed", name);
+ close(sock);
+ return (-1);
+ }
+ close(sock);
+
+ /*
+ * OK, what type of network is this?
+ */
+ switch (IFM_TYPE(req.ifm_active)) {
+
+ case IFM_IEEE80211:
+ /*
+ * Wireless.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ break;
+ }
+
+ /*
+ * Do we know whether it's connected?
+ */
+ if (req.ifm_status & IFM_AVALID) {
+ /*
+ * Yes.
+ */
+ if (req.ifm_status & IFM_ACTIVE) {
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ } else {
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ }
+ }
+ return (0);
+}
+#else
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do other than mark loopback devices as "the
+ * connected/disconnected status doesn't apply".
+ *
+ * XXX - on Solaris, can we do what the dladm command does,
+ * i.e. get a connected/disconnected indication from a kstat?
+ * (Note that you can also get the link speed, and possibly
+ * other information, from a kstat as well.)
+ */
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback devices aren't wireless, and "connected"/
+ * "disconnected" doesn't apply to them.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return (0);
+ }
+ return (0);
+}
+#endif
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(devlistp, errbuf, check_bpf_bindable,
+ get_if_flags) == -1)
+ return (-1); /* failure */
+
+#if defined(__FreeBSD__) && defined(SIOCIFCREATE2)
+ if (finddevs_usb(devlistp, errbuf) == -1)
+ return (-1);
+#endif
+
+ return (0);
+}
+
+#ifdef HAVE_BSD_IEEE80211
+static int
+monitor_mode(pcap_t *p, int set)
+{
+ struct pcap_bpf *pb = p->priv;
+ int sock;
+ struct ifmediareq req;
+ IFM_ULIST_TYPE *media_list;
+ int i;
+ int can_do;
+ struct ifreq ifr;
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't open socket");
+ return (PCAP_ERROR);
+ }
+
+ memset(&req, 0, sizeof req);
+#ifdef __APPLE__
+ strlcpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
+#else
+ strncpy(req.ifm_name, p->opt.device, sizeof req.ifm_name);
+#endif /* __APPLE__ */
+
+ /*
+ * Find out how many media types we have.
+ */
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ /*
+ * Can't get the media types.
+ */
+ switch (errno) {
+
+ case ENXIO:
+ /*
+ * There's no such device.
+ */
+ close(sock);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ case EINVAL:
+ /*
+ * Interface doesn't support SIOC{G,S}IFMEDIA.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+
+ default:
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFMEDIA");
+ close(sock);
+ return (PCAP_ERROR);
+ }
+ }
+ if (req.ifm_count == 0) {
+ /*
+ * No media types.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ /*
+ * Allocate a buffer to hold all the media types, and
+ * get the media types.
+ */
+ media_list = malloc(req.ifm_count * sizeof(*media_list));
+ if (media_list == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ close(sock);
+ return (PCAP_ERROR);
+ }
+ req.ifm_ulist = media_list;
+ if (ioctl(sock, SIOCGIFMEDIA, &req) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFMEDIA");
+ free(media_list);
+ close(sock);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Look for an 802.11 "automatic" media type.
+ * We assume that all 802.11 adapters have that media type,
+ * and that it will carry the monitor mode supported flag.
+ */
+ can_do = 0;
+ for (i = 0; i < req.ifm_count; i++) {
+ if (IFM_TYPE(media_list[i]) == IFM_IEEE80211
+ && IFM_SUBTYPE(media_list[i]) == IFM_AUTO) {
+ /* OK, does it do monitor mode? */
+ if (media_list[i] & IFM_IEEE80211_MONITOR) {
+ can_do = 1;
+ break;
+ }
+ }
+ }
+ free(media_list);
+ if (!can_do) {
+ /*
+ * This adapter doesn't support monitor mode.
+ */
+ close(sock);
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ if (set) {
+ /*
+ * Don't just check whether we can enable monitor mode,
+ * do so, if it's not already enabled.
+ */
+ if ((req.ifm_current & IFM_IEEE80211_MONITOR) == 0) {
+ /*
+ * Monitor mode isn't currently on, so turn it on,
+ * and remember that we should turn it off when the
+ * pcap_t is closed.
+ */
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(p)) {
+ /*
+ * "atexit()" failed; don't put the interface
+ * in monitor mode, just give up.
+ */
+ close(sock);
+ return (PCAP_ERROR);
+ }
+ memset(&ifr, 0, sizeof(ifr));
+
+#ifdef __APPLE__
+ (void)strlcpy(ifr.ifr_name, p->opt.device,
+ sizeof(ifr.ifr_name));
+#else
+ (void)strncpy(ifr.ifr_name, p->opt.device,
+ sizeof(ifr.ifr_name));
+#endif /* __APPLE__ */
+
+ ifr.ifr_media = req.ifm_current | IFM_IEEE80211_MONITOR;
+ if (ioctl(sock, SIOCSIFMEDIA, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SIOCSIFMEDIA");
+ close(sock);
+ return (PCAP_ERROR);
+ }
+
+ pb->must_do_on_close |= MUST_CLEAR_RFMON;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(p);
+ }
+ }
+ return (0);
+}
+#endif /* HAVE_BSD_IEEE80211 */
+
+#if defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211))
+/*
+ * Check whether we have any 802.11 link-layer types; return the best
+ * of the 802.11 link-layer types if we find one, and return -1
+ * otherwise.
+ *
+ * DLT_IEEE802_11_RADIO, with the radiotap header, is considered the
+ * best 802.11 link-layer type; any of the other 802.11-plus-radio
+ * headers are second-best; 802.11 with no radio information is
+ * the least good.
+ */
+static int
+find_802_11(struct bpf_dltlist *bdlp)
+{
+ int new_dlt;
+ u_int i;
+
+ /*
+ * Scan the list of DLT_ values, looking for 802.11 values,
+ * and, if we find any, choose the best of them.
+ */
+ new_dlt = -1;
+ for (i = 0; i < bdlp->bfl_len; i++) {
+ switch (bdlp->bfl_list[i]) {
+
+ case DLT_IEEE802_11:
+ /*
+ * 802.11, but no radio.
+ *
+ * Offer this, and select it as the new mode
+ * unless we've already found an 802.11
+ * header with radio information.
+ */
+ if (new_dlt == -1)
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+#ifdef DLT_PRISM_HEADER
+ case DLT_PRISM_HEADER:
+#endif
+#ifdef DLT_AIRONET_HEADER
+ case DLT_AIRONET_HEADER:
+#endif
+ case DLT_IEEE802_11_RADIO_AVS:
+ /*
+ * 802.11 with radio, but not radiotap.
+ *
+ * Offer this, and select it as the new mode
+ * unless we've already found the radiotap DLT_.
+ */
+ if (new_dlt != DLT_IEEE802_11_RADIO)
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+ case DLT_IEEE802_11_RADIO:
+ /*
+ * 802.11 with radiotap.
+ *
+ * Offer this, and select it as the new mode.
+ */
+ new_dlt = bdlp->bfl_list[i];
+ break;
+
+ default:
+ /*
+ * Not 802.11.
+ */
+ break;
+ }
+ }
+
+ return (new_dlt);
+}
+#endif /* defined(BIOCGDLTLIST) && (defined(__APPLE__) || defined(HAVE_BSD_IEEE80211)) */
+
+#if defined(__APPLE__) && defined(BIOCGDLTLIST)
+/*
+ * Remove non-802.11 header types from the list of DLT_ values, as we're in
+ * monitor mode, and those header types aren't supported in monitor mode.
+ */
+static void
+remove_non_802_11(pcap_t *p)
+{
+ int i, j;
+
+ /*
+ * Scan the list of DLT_ values and discard non-802.11 ones.
+ */
+ j = 0;
+ for (i = 0; i < p->dlt_count; i++) {
+ switch (p->dlt_list[i]) {
+
+ case DLT_EN10MB:
+ case DLT_RAW:
+ /*
+ * Not 802.11. Don't offer this one.
+ */
+ continue;
+
+ default:
+ /*
+ * Just copy this mode over.
+ */
+ break;
+ }
+
+ /*
+ * Copy this DLT_ value to its new position.
+ */
+ p->dlt_list[j] = p->dlt_list[i];
+ j++;
+ }
+
+ /*
+ * Set the DLT_ count to the number of entries we copied.
+ */
+ p->dlt_count = j;
+}
+
+/*
+ * Remove 802.11 link-layer types from the list of DLT_ values, as
+ * we're not in monitor mode, and those DLT_ values will switch us
+ * to monitor mode.
+ */
+static void
+remove_802_11(pcap_t *p)
+{
+ int i, j;
+
+ /*
+ * Scan the list of DLT_ values and discard 802.11 values.
+ */
+ j = 0;
+ for (i = 0; i < p->dlt_count; i++) {
+ switch (p->dlt_list[i]) {
+
+ case DLT_IEEE802_11:
+#ifdef DLT_PRISM_HEADER
+ case DLT_PRISM_HEADER:
+#endif
+#ifdef DLT_AIRONET_HEADER
+ case DLT_AIRONET_HEADER:
+#endif
+ case DLT_IEEE802_11_RADIO:
+ case DLT_IEEE802_11_RADIO_AVS:
+#ifdef DLT_PPI
+ case DLT_PPI:
+#endif
+ /*
+ * 802.11. Don't offer this one.
+ */
+ continue;
+
+ default:
+ /*
+ * Just copy this mode over.
+ */
+ break;
+ }
+
+ /*
+ * Copy this DLT_ value to its new position.
+ */
+ p->dlt_list[j] = p->dlt_list[i];
+ j++;
+ }
+
+ /*
+ * Set the DLT_ count to the number of entries we copied.
+ */
+ p->dlt_count = j;
+}
+#endif /* defined(__APPLE__) && defined(BIOCGDLTLIST) */
+
+static int
+pcap_setfilter_bpf(pcap_t *p, struct bpf_program *fp)
+{
+ struct pcap_bpf *pb = p->priv;
+
+ /*
+ * Free any user-mode filter we might happen to have installed.
+ */
+ pcap_freecode(&p->fcode);
+
+ /*
+ * Try to install the kernel filter.
+ */
+ if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) == 0) {
+ /*
+ * It worked.
+ */
+ pb->filtering_in_kernel = 1; /* filtering in the kernel */
+
+ /*
+ * Discard any previously-received packets, as they might
+ * have passed whatever filter was formerly in effect, but
+ * might not pass this filter (BIOCSETF discards packets
+ * buffered in the kernel, so you can lose packets in any
+ * case).
+ */
+ p->cc = 0;
+ return (0);
+ }
+
+ /*
+ * We failed.
+ *
+ * If it failed with EINVAL, that's probably because the program
+ * is invalid or too big. Validate it ourselves; if we like it
+ * (we currently allow backward branches, to support protochain),
+ * run it in userland. (There's no notion of "too big" for
+ * userland.)
+ *
+ * Otherwise, just give up.
+ * XXX - if the copy of the program into the kernel failed,
+ * we will get EINVAL rather than, say, EFAULT on at least
+ * some kernels.
+ */
+ if (errno != EINVAL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "BIOCSETF");
+ return (-1);
+ }
+
+ /*
+ * install_bpf_program() validates the program.
+ *
+ * XXX - what if we already have a filter in the kernel?
+ */
+ if (install_bpf_program(p, fp) < 0)
+ return (-1);
+ pb->filtering_in_kernel = 0; /* filtering in userland */
+ return (0);
+}
+
+/*
+ * Set direction flag: Which packets do we accept on a forwarding
+ * single device? IN, OUT or both?
+ */
+#if defined(BIOCSDIRECTION)
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
+{
+ u_int direction;
+
+ direction = (d == PCAP_D_IN) ? BPF_D_IN :
+ ((d == PCAP_D_OUT) ? BPF_D_OUT : BPF_D_INOUT);
+ if (ioctl(p->fd, BIOCSDIRECTION, &direction) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "Cannot set direction to %s",
+ (d == PCAP_D_IN) ? "PCAP_D_IN" :
+ ((d == PCAP_D_OUT) ? "PCAP_D_OUT" : "PCAP_D_INOUT"));
+ return (-1);
+ }
+ return (0);
+}
+#elif defined(BIOCSSEESENT)
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d)
+{
+ u_int seesent;
+
+ /*
+ * We don't support PCAP_D_OUT.
+ */
+ if (d == PCAP_D_OUT) {
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "Setting direction to PCAP_D_OUT is not supported on BPF");
+ return -1;
+ }
+
+ seesent = (d == PCAP_D_INOUT);
+ if (ioctl(p->fd, BIOCSSEESENT, &seesent) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "Cannot set direction to %s",
+ (d == PCAP_D_INOUT) ? "PCAP_D_INOUT" : "PCAP_D_IN");
+ return (-1);
+ }
+ return (0);
+}
+#else
+static int
+pcap_setdirection_bpf(pcap_t *p, pcap_direction_t d _U_)
+{
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "This system doesn't support BIOCSSEESENT, so the direction can't be set");
+ return (-1);
+}
+#endif
+
+#ifdef BIOCSDLT
+static int
+pcap_set_datalink_bpf(pcap_t *p, int dlt)
+{
+ if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "Cannot set DLT %d", dlt);
+ return (-1);
+ }
+ return (0);
+}
+#else
+static int
+pcap_set_datalink_bpf(pcap_t *p _U_, int dlt _U_)
+{
+ return (0);
+}
+#endif
+
+/*
+ * Platform-specific information.
+ */
+const char *
+pcap_lib_version(void)
+{
+#ifdef HAVE_ZEROCOPY_BPF
+ return (PCAP_VERSION_STRING " (with zerocopy support)");
+#else
+ return (PCAP_VERSION_STRING);
+#endif
+}
diff --git a/lib/libpcap/libpcap/pcap-bpf.h b/lib/libpcap/libpcap/pcap-bpf.h
new file mode 100644
index 0000000..ebb64c3
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-bpf.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file! Some applications
+ * might expect to be able to include <pcap-bpf.h>.
+ */
+#include <pcap/bpf.h>
diff --git a/lib/libpcap/libpcap/pcap-bt-linux.c b/lib/libpcap/libpcap/pcap-bt-linux.c
new file mode 100644
index 0000000..9c8712e
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-bt-linux.c
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Bluetooth sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pcap-int.h"
+#include "pcap-bt-linux.h"
+#include "pcap/bluetooth.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#define BT_IFACE "bluetooth"
+#define BT_CTRL_SIZE 128
+
+/* forward declaration */
+static int bt_activate(pcap_t *);
+static int bt_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int bt_inject_linux(pcap_t *, const void *, size_t);
+static int bt_setdirection_linux(pcap_t *, pcap_direction_t);
+static int bt_stats_linux(pcap_t *, struct pcap_stat *);
+
+/*
+ * Private data for capturing on Linux Bluetooth devices.
+ */
+struct pcap_bt {
+ int dev_id; /* device ID of device we're bound to */
+};
+
+int
+bt_findalldevs(pcap_if_list_t *devlistp, char *err_str)
+{
+ struct hci_dev_list_req *dev_list;
+ struct hci_dev_req *dev_req;
+ int sock;
+ unsigned i;
+ int ret = 0;
+
+ sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (sock < 0)
+ {
+ /* if bluetooth is not supported this is not fatal*/
+ if (errno == EAFNOSUPPORT)
+ return 0;
+ pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
+ errno, "Can't open raw Bluetooth socket");
+ return -1;
+ }
+
+ dev_list = malloc(HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
+ if (!dev_list)
+ {
+ pcap_snprintf(err_str, PCAP_ERRBUF_SIZE, "Can't allocate %zu bytes for Bluetooth device list",
+ HCI_MAX_DEV * sizeof(*dev_req) + sizeof(*dev_list));
+ ret = -1;
+ goto done;
+ }
+
+ dev_list->dev_num = HCI_MAX_DEV;
+
+ if (ioctl(sock, HCIGETDEVLIST, (void *) dev_list) < 0)
+ {
+ pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
+ errno, "Can't get Bluetooth device list via ioctl");
+ ret = -1;
+ goto free;
+ }
+
+ dev_req = dev_list->dev_req;
+ for (i = 0; i < dev_list->dev_num; i++, dev_req++) {
+ char dev_name[20], dev_descr[40];
+
+ pcap_snprintf(dev_name, sizeof(dev_name), BT_IFACE"%u", dev_req->dev_id);
+ pcap_snprintf(dev_descr, sizeof(dev_descr), "Bluetooth adapter number %u", i);
+
+ /*
+ * Bluetooth is a wireless technology.
+ * XXX - if there's the notion of associating with a
+ * network, and we can determine whether the interface
+ * is associated with a network, check that and set
+ * the status to PCAP_IF_CONNECTION_STATUS_CONNECTED
+ * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED.
+ */
+ if (add_dev(devlistp, dev_name, PCAP_IF_WIRELESS, dev_descr, err_str) == NULL)
+ {
+ ret = -1;
+ break;
+ }
+ }
+
+free:
+ free(dev_list);
+
+done:
+ close(sock);
+ return ret;
+}
+
+pcap_t *
+bt_create(const char *device, char *ebuf, int *is_ours)
+{
+ const char *cp;
+ char *cpend;
+ long devnum;
+ pcap_t *p;
+
+ /* Does this look like a Bluetooth device? */
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+ /* Does it begin with BT_IFACE? */
+ if (strncmp(cp, BT_IFACE, sizeof BT_IFACE - 1) != 0) {
+ /* Nope, doesn't begin with BT_IFACE */
+ *is_ours = 0;
+ return NULL;
+ }
+ /* Yes - is BT_IFACE followed by a number? */
+ cp += sizeof BT_IFACE - 1;
+ devnum = strtol(cp, &cpend, 10);
+ if (cpend == cp || *cpend != '\0') {
+ /* Not followed by a number. */
+ *is_ours = 0;
+ return NULL;
+ }
+ if (devnum < 0) {
+ /* Followed by a non-valid number. */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_bt));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = bt_activate;
+ return (p);
+}
+
+static int
+bt_activate(pcap_t* handle)
+{
+ struct pcap_bt *handlep = handle->priv;
+ struct sockaddr_hci addr;
+ int opt;
+ int dev_id;
+ struct hci_filter flt;
+ int err = PCAP_ERROR;
+
+ /* get bt interface id */
+ if (sscanf(handle->opt.device, BT_IFACE"%d", &dev_id) != 1)
+ {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get Bluetooth device index from %s",
+ handle->opt.device);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+ handle->snapshot = MAXIMUM_SNAPLEN;
+
+ /* Initialize some components of the pcap structure. */
+ handle->bufsize = BT_CTRL_SIZE+sizeof(pcap_bluetooth_h4_header)+handle->snapshot;
+ handle->linktype = DLT_BLUETOOTH_HCI_H4_WITH_PHDR;
+
+ handle->read_op = bt_read_linux;
+ handle->inject_op = bt_inject_linux;
+ handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+ handle->setdirection_op = bt_setdirection_linux;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->stats_op = bt_stats_linux;
+ handlep->dev_id = dev_id;
+
+ /* Create HCI socket */
+ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (handle->fd < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't create raw socket");
+ return PCAP_ERROR;
+ }
+
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't allocate dump buffer");
+ goto close_fail;
+ }
+
+ opt = 1;
+ if (setsockopt(handle->fd, SOL_HCI, HCI_DATA_DIR, &opt, sizeof(opt)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't enable data direction info");
+ goto close_fail;
+ }
+
+ opt = 1;
+ if (setsockopt(handle->fd, SOL_HCI, HCI_TIME_STAMP, &opt, sizeof(opt)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't enable time stamp");
+ goto close_fail;
+ }
+
+ /* Setup filter, do not call hci function to avoid dependence on
+ * external libs */
+ memset(&flt, 0, sizeof(flt));
+ memset((void *) &flt.type_mask, 0xff, sizeof(flt.type_mask));
+ memset((void *) &flt.event_mask, 0xff, sizeof(flt.event_mask));
+ if (setsockopt(handle->fd, SOL_HCI, HCI_FILTER, &flt, sizeof(flt)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't set filter");
+ goto close_fail;
+ }
+
+
+ /* Bind socket to the HCI device */
+ addr.hci_family = AF_BLUETOOTH;
+ addr.hci_dev = handlep->dev_id;
+#ifdef HAVE_STRUCT_SOCKADDR_HCI_HCI_CHANNEL
+ addr.hci_channel = HCI_CHANNEL_RAW;
+#endif
+ if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't attach to device %d", handlep->dev_id);
+ goto close_fail;
+ }
+
+ if (handle->opt.rfmon) {
+ /*
+ * Monitor mode doesn't apply to Bluetooth devices.
+ */
+ err = PCAP_ERROR_RFMON_NOTSUP;
+ goto close_fail;
+ }
+
+ if (handle->opt.buffer_size != 0) {
+ /*
+ * Set the socket buffer size to the specified value.
+ */
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
+ &handle->opt.buffer_size,
+ sizeof(handle->opt.buffer_size)) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ errno, PCAP_ERRBUF_SIZE, "SO_RCVBUF");
+ goto close_fail;
+ }
+ }
+
+ handle->selectable_fd = handle->fd;
+ return 0;
+
+close_fail:
+ pcap_cleanup_live_common(handle);
+ return err;
+}
+
+static int
+bt_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
+{
+ struct cmsghdr *cmsg;
+ struct msghdr msg;
+ struct iovec iv;
+ ssize_t ret;
+ struct pcap_pkthdr pkth;
+ pcap_bluetooth_h4_header* bthdr;
+ u_char *pktd;
+ int in = 0;
+
+ pktd = (u_char *)handle->buffer + BT_CTRL_SIZE;
+ bthdr = (pcap_bluetooth_h4_header*)(void *)pktd;
+ iv.iov_base = pktd + sizeof(pcap_bluetooth_h4_header);
+ iv.iov_len = handle->snapshot;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &iv;
+ msg.msg_iovlen = 1;
+ msg.msg_control = handle->buffer;
+ msg.msg_controllen = BT_CTRL_SIZE;
+
+ /* ignore interrupt system call error */
+ do {
+ ret = recvmsg(handle->fd, &msg, 0);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+
+ if (ret < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't receive packet");
+ return -1;
+ }
+
+ pkth.caplen = ret;
+
+ /* get direction and timestamp*/
+ cmsg = CMSG_FIRSTHDR(&msg);
+ while (cmsg) {
+ switch (cmsg->cmsg_type) {
+ case HCI_CMSG_DIR:
+ memcpy(&in, CMSG_DATA(cmsg), sizeof in);
+ break;
+ case HCI_CMSG_TSTAMP:
+ memcpy(&pkth.ts, CMSG_DATA(cmsg),
+ sizeof pkth.ts);
+ break;
+ }
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+ if ((in && (handle->direction == PCAP_D_OUT)) ||
+ ((!in) && (handle->direction == PCAP_D_IN)))
+ return 0;
+
+ bthdr->direction = htonl(in != 0);
+ pkth.caplen+=sizeof(pcap_bluetooth_h4_header);
+ pkth.len = pkth.caplen;
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+ callback(user, &pkth, pktd);
+ return 1;
+ }
+ return 0; /* didn't pass filter */
+}
+
+static int
+bt_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
+{
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Packet injection is not supported on Bluetooth devices");
+ return (-1);
+}
+
+
+static int
+bt_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+ struct pcap_bt *handlep = handle->priv;
+ int ret;
+ struct hci_dev_info dev_info;
+ struct hci_dev_stats * s = &dev_info.stat;
+ dev_info.dev_id = handlep->dev_id;
+
+ /* ignore eintr */
+ do {
+ ret = ioctl(handle->fd, HCIGETDEVINFO, (void *)&dev_info);
+ } while ((ret == -1) && (errno == EINTR));
+
+ if (ret < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't get stats via ioctl");
+ return (-1);
+
+ }
+
+ /* we receive both rx and tx frames, so comulate all stats */
+ stats->ps_recv = s->evt_rx + s->acl_rx + s->sco_rx + s->cmd_tx +
+ s->acl_tx +s->sco_tx;
+ stats->ps_drop = s->err_rx + s->err_tx;
+ stats->ps_ifdrop = 0;
+ return 0;
+}
+
+static int
+bt_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+ p->direction = d;
+ return 0;
+}
diff --git a/lib/libpcap/libpcap/pcap-bt-linux.h b/lib/libpcap/libpcap/pcap-bt-linux.h
new file mode 100644
index 0000000..163bd34
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-bt-linux.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Bluetooth sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ */
+
+/*
+ * Prototypes for Bluetooth-related functions
+ */
+int bt_findalldevs(pcap_if_list_t *devlistp, char *err_str);
+pcap_t *bt_create(const char *device, char *ebuf, int *is_ours);
diff --git a/lib/libpcap/libpcap/pcap-bt-monitor-linux.c b/lib/libpcap/libpcap/pcap-bt-monitor-linux.c
new file mode 100644
index 0000000..a693949
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-bt-monitor-linux.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2014 Michal Labedzki for Tieto 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 author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+
+#include "pcap/bluetooth.h"
+#include "pcap-int.h"
+
+#include "pcap-bt-monitor-linux.h"
+
+#define BT_CONTROL_SIZE 32
+#define INTERFACE_NAME "bluetooth-monitor"
+
+/*
+ * Fields and alignment must match the declaration in the Linux kernel 3.4+.
+ * See struct hci_mon_hdr in include/net/bluetooth/hci_mon.h.
+ */
+struct hci_mon_hdr {
+ uint16_t opcode;
+ uint16_t index;
+ uint16_t len;
+} __attribute__((packed));
+
+int
+bt_monitor_findalldevs(pcap_if_list_t *devlistp, char *err_str)
+{
+ int ret = 0;
+
+ /*
+ * Bluetooth is a wireless technology.
+ *
+ * This is a device to monitor all Bluetooth interfaces, so
+ * there's no notion of "connected" or "disconnected", any
+ * more than there's a notion of "connected" or "disconnected"
+ * for the "any" device.
+ */
+ if (add_dev(devlistp, INTERFACE_NAME,
+ PCAP_IF_WIRELESS|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ "Bluetooth Linux Monitor", err_str) == NULL)
+ {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int
+bt_monitor_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
+{
+ struct cmsghdr *cmsg;
+ struct msghdr msg;
+ struct iovec iv[2];
+ ssize_t ret;
+ struct pcap_pkthdr pkth;
+ pcap_bluetooth_linux_monitor_header *bthdr;
+ u_char *pktd;
+ struct hci_mon_hdr hdr;
+
+ pktd = (u_char *)handle->buffer + BT_CONTROL_SIZE;
+ bthdr = (pcap_bluetooth_linux_monitor_header*)(void *)pktd;
+
+ iv[0].iov_base = &hdr;
+ iv[0].iov_len = sizeof(hdr);
+ iv[1].iov_base = pktd + sizeof(pcap_bluetooth_linux_monitor_header);
+ iv[1].iov_len = handle->snapshot;
+
+ memset(&pkth.ts, 0, sizeof(pkth.ts));
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = iv;
+ msg.msg_iovlen = 2;
+ msg.msg_control = handle->buffer;
+ msg.msg_controllen = BT_CONTROL_SIZE;
+
+ do {
+ ret = recvmsg(handle->fd, &msg, 0);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+
+ if (ret < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't receive packet");
+ return -1;
+ }
+
+ pkth.caplen = ret - sizeof(hdr) + sizeof(pcap_bluetooth_linux_monitor_header);
+ pkth.len = pkth.caplen;
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level != SOL_SOCKET) continue;
+
+ if (cmsg->cmsg_type == SCM_TIMESTAMP) {
+ memcpy(&pkth.ts, CMSG_DATA(cmsg), sizeof(pkth.ts));
+ }
+ }
+
+ bthdr->adapter_id = htons(hdr.index);
+ bthdr->opcode = htons(hdr.opcode);
+
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+ callback(user, &pkth, pktd);
+ return 1;
+ }
+ return 0; /* didn't pass filter */
+}
+
+static int
+bt_monitor_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
+{
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Packet injection is not supported yet on Bluetooth monitor devices");
+ return -1;
+}
+
+static int
+bt_monitor_setdirection(pcap_t *p, pcap_direction_t d)
+{
+ p->direction = d;
+ return 0;
+}
+
+static int
+bt_monitor_stats(pcap_t *handle _U_, struct pcap_stat *stats)
+{
+ stats->ps_recv = 0;
+ stats->ps_drop = 0;
+ stats->ps_ifdrop = 0;
+
+ return 0;
+}
+
+static int
+bt_monitor_activate(pcap_t* handle)
+{
+ struct sockaddr_hci addr;
+ int err = PCAP_ERROR;
+ int opt;
+
+ if (handle->opt.rfmon) {
+ /* monitor mode doesn't apply here */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+ handle->snapshot = MAXIMUM_SNAPLEN;
+
+ handle->bufsize = BT_CONTROL_SIZE + sizeof(pcap_bluetooth_linux_monitor_header) + handle->snapshot;
+ handle->linktype = DLT_BLUETOOTH_LINUX_MONITOR;
+
+ handle->read_op = bt_monitor_read;
+ handle->inject_op = bt_monitor_inject;
+ handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+ handle->setdirection_op = bt_monitor_setdirection;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->stats_op = bt_monitor_stats;
+
+ handle->fd = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (handle->fd < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't create raw socket");
+ return PCAP_ERROR;
+ }
+
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't allocate dump buffer");
+ goto close_fail;
+ }
+
+ /* Bind socket to the HCI device */
+ addr.hci_family = AF_BLUETOOTH;
+ addr.hci_dev = HCI_DEV_NONE;
+ addr.hci_channel = HCI_CHANNEL_MONITOR;
+
+ if (bind(handle->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't attach to interface");
+ goto close_fail;
+ }
+
+ opt = 1;
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_TIMESTAMP, &opt, sizeof(opt)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't enable time stamp");
+ goto close_fail;
+ }
+
+ handle->selectable_fd = handle->fd;
+
+ return 0;
+
+close_fail:
+ pcap_cleanup_live_common(handle);
+ return err;
+}
+
+pcap_t *
+bt_monitor_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *p;
+ const char *cp;
+
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+
+ if (strcmp(cp, INTERFACE_NAME) != 0) {
+ *is_ours = 0;
+ return NULL;
+ }
+
+ *is_ours = 1;
+ p = pcap_create_common(ebuf, 0);
+ if (p == NULL)
+ return NULL;
+
+ p->activate_op = bt_monitor_activate;
+
+ return p;
+}
diff --git a/lib/libpcap/libpcap/pcap-bt-monitor-linux.h b/lib/libpcap/libpcap/pcap-bt-monitor-linux.h
new file mode 100644
index 0000000..8133710
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-bt-monitor-linux.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2014 Michal Labedzki for Tieto 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 author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+int bt_monitor_findalldevs(pcap_if_list_t *devlistp, char *err_str);
+pcap_t *bt_monitor_create(const char *device, char *ebuf, int *is_ours);
diff --git a/lib/libpcap/libpcap/pcap-common.c b/lib/libpcap/libpcap/pcap-common.c
new file mode 100644
index 0000000..bec3248
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-common.c
@@ -0,0 +1,1592 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * pcap-common.c - common code for pcap and pcapng files
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+
+#include "pcap-int.h"
+#include "extract.h"
+#include "pcap/sll.h"
+#include "pcap/usb.h"
+#include "pcap/nflog.h"
+#include "pcap/can_socketcan.h"
+
+#include "pcap-common.h"
+
+/*
+ * We don't write DLT_* values to capture files, because they're not the
+ * same on all platforms.
+ *
+ * Unfortunately, the various flavors of BSD have not always used the same
+ * numerical values for the same data types, and various patches to
+ * libpcap for non-BSD OSes have added their own DLT_* codes for link
+ * layer encapsulation types seen on those OSes, and those codes have had,
+ * in some cases, values that were also used, on other platforms, for other
+ * link layer encapsulation types.
+ *
+ * This means that capture files of a type whose numerical DLT_* code
+ * means different things on different BSDs, or with different versions
+ * of libpcap, can't always be read on systems other than those like
+ * the one running on the machine on which the capture was made.
+ *
+ * Instead, we define here a set of LINKTYPE_* codes, and map DLT_* codes
+ * to LINKTYPE_* codes when writing a savefile header, and map LINKTYPE_*
+ * codes to DLT_* codes when reading a savefile header.
+ *
+ * For those DLT_* codes that have, as far as we know, the same values on
+ * all platforms (DLT_NULL through DLT_FDDI), we define LINKTYPE_xxx as
+ * DLT_xxx; that way, captures of those types can still be read by
+ * versions of libpcap that map LINKTYPE_* values to DLT_* values, and
+ * captures of those types written by versions of libpcap that map DLT_
+ * values to LINKTYPE_ values can still be read by older versions
+ * of libpcap.
+ *
+ * The other LINKTYPE_* codes are given values starting at 100, in the
+ * hopes that no DLT_* code will be given one of those values.
+ *
+ * In order to ensure that a given LINKTYPE_* code's value will refer to
+ * the same encapsulation type on all platforms, you should not allocate
+ * a new LINKTYPE_* value without consulting
+ * "tcpdump-workers@lists.tcpdump.org". The tcpdump developers will
+ * allocate a value for you, and will not subsequently allocate it to
+ * anybody else; that value will be added to the "pcap.h" in the
+ * tcpdump.org Git repository, so that a future libpcap release will
+ * include it.
+ *
+ * You should, if possible, also contribute patches to libpcap and tcpdump
+ * to handle the new encapsulation type, so that they can also be checked
+ * into the tcpdump.org Git repository and so that they will appear in
+ * future libpcap and tcpdump releases.
+ *
+ * Do *NOT* assume that any values after the largest value in this file
+ * are available; you might not have the most up-to-date version of this
+ * file, and new values after that one might have been assigned. Also,
+ * do *NOT* use any values below 100 - those might already have been
+ * taken by one (or more!) organizations.
+ *
+ * Any platform that defines additional DLT_* codes should:
+ *
+ * request a LINKTYPE_* code and value from tcpdump.org,
+ * as per the above;
+ *
+ * add, in their version of libpcap, an entry to map
+ * those DLT_* codes to the corresponding LINKTYPE_*
+ * code;
+ *
+ * redefine, in their "net/bpf.h", any DLT_* values
+ * that collide with the values used by their additional
+ * DLT_* codes, to remove those collisions (but without
+ * making them collide with any of the LINKTYPE_*
+ * values equal to 50 or above; they should also avoid
+ * defining DLT_* values that collide with those
+ * LINKTYPE_* values, either).
+ */
+#define LINKTYPE_NULL DLT_NULL
+#define LINKTYPE_ETHERNET DLT_EN10MB /* also for 100Mb and up */
+#define LINKTYPE_EXP_ETHERNET DLT_EN3MB /* 3Mb experimental Ethernet */
+#define LINKTYPE_AX25 DLT_AX25
+#define LINKTYPE_PRONET DLT_PRONET
+#define LINKTYPE_CHAOS DLT_CHAOS
+#define LINKTYPE_IEEE802_5 DLT_IEEE802 /* DLT_IEEE802 is used for 802.5 Token Ring */
+#define LINKTYPE_ARCNET_BSD DLT_ARCNET /* BSD-style headers */
+#define LINKTYPE_SLIP DLT_SLIP
+#define LINKTYPE_PPP DLT_PPP
+#define LINKTYPE_FDDI DLT_FDDI
+
+/*
+ * LINKTYPE_PPP is for use when there might, or might not, be an RFC 1662
+ * PPP in HDLC-like framing header (with 0xff 0x03 before the PPP protocol
+ * field) at the beginning of the packet.
+ *
+ * This is for use when there is always such a header; the address field
+ * might be 0xff, for regular PPP, or it might be an address field for Cisco
+ * point-to-point with HDLC framing as per section 4.3.1 of RFC 1547 ("Cisco
+ * HDLC"). This is, for example, what you get with NetBSD's DLT_PPP_SERIAL.
+ *
+ * We give it the same value as NetBSD's DLT_PPP_SERIAL, in the hopes that
+ * nobody else will choose a DLT_ value of 50, and so that DLT_PPP_SERIAL
+ * captures will be written out with a link type that NetBSD's tcpdump
+ * can read.
+ */
+#define LINKTYPE_PPP_HDLC 50 /* PPP in HDLC-like framing */
+
+#define LINKTYPE_PPP_ETHER 51 /* NetBSD PPP-over-Ethernet */
+
+#define LINKTYPE_SYMANTEC_FIREWALL 99 /* Symantec Enterprise Firewall */
+
+/*
+ * These correspond to DLT_s that have different values on different
+ * platforms; we map between these values in capture files and
+ * the DLT_ values as returned by pcap_datalink() and passed to
+ * pcap_open_dead().
+ */
+#define LINKTYPE_ATM_RFC1483 100 /* LLC/SNAP-encapsulated ATM */
+#define LINKTYPE_RAW 101 /* raw IP */
+#define LINKTYPE_SLIP_BSDOS 102 /* BSD/OS SLIP BPF header */
+#define LINKTYPE_PPP_BSDOS 103 /* BSD/OS PPP BPF header */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * LINKTYPE_MATCHING_MIN is the lowest such value; LINKTYPE_MATCHING_MAX
+ * is the highest such value.
+ */
+#define LINKTYPE_MATCHING_MIN 104 /* lowest value in the "matching" range */
+
+#define LINKTYPE_C_HDLC 104 /* Cisco HDLC */
+#define LINKTYPE_IEEE802_11 105 /* IEEE 802.11 (wireless) */
+#define LINKTYPE_ATM_CLIP 106 /* Linux Classical IP over ATM */
+#define LINKTYPE_FRELAY 107 /* Frame Relay */
+#define LINKTYPE_LOOP 108 /* OpenBSD loopback */
+#define LINKTYPE_ENC 109 /* OpenBSD IPSEC enc */
+
+/*
+ * These three types are reserved for future use.
+ */
+#define LINKTYPE_LANE8023 110 /* ATM LANE + 802.3 */
+#define LINKTYPE_HIPPI 111 /* NetBSD HIPPI */
+#define LINKTYPE_HDLC 112 /* NetBSD HDLC framing */
+
+#define LINKTYPE_LINUX_SLL 113 /* Linux cooked socket capture */
+#define LINKTYPE_LTALK 114 /* Apple LocalTalk hardware */
+#define LINKTYPE_ECONET 115 /* Acorn Econet */
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define LINKTYPE_IPFILTER 116
+
+#define LINKTYPE_PFLOG 117 /* OpenBSD DLT_PFLOG */
+#define LINKTYPE_CISCO_IOS 118 /* For Cisco-internal use */
+#define LINKTYPE_IEEE802_11_PRISM 119 /* 802.11 plus Prism II monitor mode radio metadata header */
+#define LINKTYPE_IEEE802_11_AIRONET 120 /* 802.11 plus FreeBSD Aironet driver radio metadata header */
+
+/*
+ * Reserved for Siemens HiPath HDLC.
+ */
+#define LINKTYPE_HHDLC 121
+
+#define LINKTYPE_IP_OVER_FC 122 /* RFC 2625 IP-over-Fibre Channel */
+#define LINKTYPE_SUNATM 123 /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define LINKTYPE_RIO 124 /* RapidIO */
+#define LINKTYPE_PCI_EXP 125 /* PCI Express */
+#define LINKTYPE_AURORA 126 /* Xilinx Aurora link layer */
+
+#define LINKTYPE_IEEE802_11_RADIOTAP 127 /* 802.11 plus radiotap radio metadata header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define LINKTYPE_TZSP 128 /* Tazmen Sniffer Protocol */
+
+#define LINKTYPE_ARCNET_LINUX 129 /* Linux-style headers */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The corresponding
+ * DLT_s are used for passing on chassis-internal
+ * metainformation such as QOS profiles, etc..
+ */
+#define LINKTYPE_JUNIPER_MLPPP 130
+#define LINKTYPE_JUNIPER_MLFR 131
+#define LINKTYPE_JUNIPER_ES 132
+#define LINKTYPE_JUNIPER_GGSN 133
+#define LINKTYPE_JUNIPER_MFR 134
+#define LINKTYPE_JUNIPER_ATM2 135
+#define LINKTYPE_JUNIPER_SERVICES 136
+#define LINKTYPE_JUNIPER_ATM1 137
+
+#define LINKTYPE_APPLE_IP_OVER_IEEE1394 138 /* Apple IP-over-IEEE 1394 cooked header */
+
+#define LINKTYPE_MTP2_WITH_PHDR 139
+#define LINKTYPE_MTP2 140
+#define LINKTYPE_MTP3 141
+#define LINKTYPE_SCCP 142
+
+#define LINKTYPE_DOCSIS 143 /* DOCSIS MAC frames */
+
+#define LINKTYPE_LINUX_IRDA 144 /* Linux-IrDA */
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define LINKTYPE_IBM_SP 145
+#define LINKTYPE_IBM_SN 146
+
+/*
+ * Reserved for private use. If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that LINKTYPE_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, in those cases, ask "tcpdump-workers@lists.tcpdump.org" for a
+ * new DLT_ and LINKTYPE_ value, as per the comment in pcap/bpf.h, and use
+ * the type you're given.
+ */
+#define LINKTYPE_USER0 147
+#define LINKTYPE_USER1 148
+#define LINKTYPE_USER2 149
+#define LINKTYPE_USER3 150
+#define LINKTYPE_USER4 151
+#define LINKTYPE_USER5 152
+#define LINKTYPE_USER6 153
+#define LINKTYPE_USER7 154
+#define LINKTYPE_USER8 155
+#define LINKTYPE_USER9 156
+#define LINKTYPE_USER10 157
+#define LINKTYPE_USER11 158
+#define LINKTYPE_USER12 159
+#define LINKTYPE_USER13 160
+#define LINKTYPE_USER14 161
+#define LINKTYPE_USER15 162
+
+#ifdef __APPLE__
+#define LINKTYPE_PKTAP LINKTYPE_USER2
+#endif
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ */
+#define LINKTYPE_IEEE802_11_AVS 163 /* 802.11 plus AVS radio metadata header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The corresponding
+ * DLT_s are used for passing on chassis-internal
+ * metainformation such as QOS profiles, etc..
+ */
+#define LINKTYPE_JUNIPER_MONITOR 164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define LINKTYPE_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define LINKTYPE_PPP_PPPD 166
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define LINKTYPE_JUNIPER_PPPOE 167
+#define LINKTYPE_JUNIPER_PPPOE_ATM 168
+
+#define LINKTYPE_GPRS_LLC 169 /* GPRS LLC */
+#define LINKTYPE_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define LINKTYPE_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define LINKTYPE_GCOM_T1E1 172
+#define LINKTYPE_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define LINKTYPE_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define LINKTYPE_ERF_ETH 175 /* Ethernet */
+#define LINKTYPE_ERF_POS 176 /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define LINKTYPE_LINUX_LAPD 177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The Link Types are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define LINKTYPE_JUNIPER_ETHER 178
+#define LINKTYPE_JUNIPER_PPP 179
+#define LINKTYPE_JUNIPER_FRELAY 180
+#define LINKTYPE_JUNIPER_CHDLC 181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define LINKTYPE_MFR 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define LINKTYPE_JUNIPER_VP 183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define LINKTYPE_A429 184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define LINKTYPE_A653_ICM 185
+
+/*
+ * This used to be "USB packets, beginning with a USB setup header;
+ * requested by Paolo Abeni <paolo.abeni@email.it>."
+ *
+ * However, that header didn't work all that well - it left out some
+ * useful information - and was abandoned in favor of the DLT_USB_LINUX
+ * header.
+ *
+ * This is now used by FreeBSD for its BPF taps for USB; that has its
+ * own headers. So it is written, so it is done.
+ */
+#define LINKTYPE_USB_FREEBSD 186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define LINKTYPE_BLUETOOTH_HCI_H4 187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define LINKTYPE_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define LINKTYPE_USB_LINUX 189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define LINKTYPE_CAN20B 190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define LINKTYPE_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * LINKTYPE_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define LINKTYPE_PPI 192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define LINKTYPE_IEEE802_16_MAC_CPS_RADIO 193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define LINKTYPE_JUNIPER_ISM 194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with the FCS at the end of the frame; requested by
+ * Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ *
+ * This should only be used if the FCS is present at the end of the
+ * frame; if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be
+ * used.
+ */
+#define LINKTYPE_IEEE802_15_4_WITHFCS 195
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define LINKTYPE_SITA 196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records. Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define LINKTYPE_ERF 197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board. Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define LINKTYPE_RAIF1 198
+
+/*
+ * IPMB packet for IPMI, beginning with a 2-byte header, followed by
+ * the I2C slave address, followed by the netFn and LUN, etc..
+ * Requested by Chanthy Toeung <chanthy.toeung@ca.kontron.com>.
+ *
+ * XXX - its DLT_ value used to be called DLT_IPMB, back when we got the
+ * impression from the email thread requesting it that the packet
+ * had no extra 2-byte header. We've renamed it; if anybody used
+ * DLT_IPMB and assumed no 2-byte header, this will cause the compile
+ * to fail, at which point we'll have to figure out what to do about
+ * the two header types using the same DLT_/LINKTYPE_ value. If that
+ * doesn't happen, we'll assume nobody used it and that the redefinition
+ * is safe.
+ */
+#define LINKTYPE_IPMB_KONTRON 199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define LINKTYPE_JUNIPER_ST 200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define LINKTYPE_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define LINKTYPE_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define LINKTYPE_LAPD 203
+
+
+/*
+ * PPP, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host", non-zero (any non-zero value) means "sent by
+ * this host" - as per Will Barker <w.barker@zen.co.uk>.
+ */
+#define LINKTYPE_PPP_WITH_DIR 204 /* Don't confuse with LINKTYPE_PPP_PPPD */
+
+/*
+ * Cisco HDLC, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host", non-zero (any non-zero value) means
+ * "sent by this host" - as per Will Barker <w.barker@zen.co.uk>.
+ */
+#define LINKTYPE_C_HDLC_WITH_DIR 205 /* Cisco HDLC */
+
+/*
+ * Frame Relay, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host" (DCE -> DTE), non-zero (any non-zero
+ * value) means "sent by this host" (DTE -> DCE) - as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define LINKTYPE_FRELAY_WITH_DIR 206 /* Frame Relay */
+
+/*
+ * LAPB, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host" (DCE -> DTE), non-zero (any non-zero value)
+ * means "sent by this host" (DTE -> DCE)- as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define LINKTYPE_LAPB_WITH_DIR 207 /* LAPB */
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define LINKTYPE_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define LINKTYPE_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define LINKTYPE_IEEE802_15_4_NONASK_PHY 215
+
+/*
+ * David Gibson <david@gibson.dropbear.id.au> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg.
+ */
+#define LINKTYPE_LINUX_EVDEV 216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <laforge@gnumonks.org>.
+ */
+#define LINKTYPE_GSMTAP_UM 217
+#define LINKTYPE_GSMTAP_ABIS 218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <michele@openbsd.org> on behalf
+ * of OpenBSD.
+ */
+#define LINKTYPE_MPLS 219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define LINKTYPE_USB_LINUX_MMAPPED 220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <tcpdump@mazzoo.de>.
+ */
+#define LINKTYPE_DECT 221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ * I have already written dissectors for but need an OK from
+ * legal before I can submit a patch.
+ *
+ */
+#define LINKTYPE_AOS 222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <vieuxtech@gmail.com>.
+ */
+#define LINKTYPE_WIHART 223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define LINKTYPE_FC_2 224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define LINKTYPE_FC_2_WITH_FRAME_DELIMS 225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ * uint8_t dli_version;
+ * uint8_t dli_family;
+ * uint16_t dli_htype;
+ * uint32_t dli_pktlen;
+ * uint32_t dli_ifindex;
+ * uint32_t dli_grifindex;
+ * uint32_t dli_zsrc;
+ * uint32_t dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define LINKTYPE_IPNET 226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN, and with multi-byte numerical fields in that header
+ * in big-endian byte order.
+ *
+ * See Documentation/networking/can.txt in the Linux source.
+ *
+ * Requested by Felix Obenhuber <felix@obenhuber.de>.
+ */
+#define LINKTYPE_CAN_SOCKETCAN 227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6. Requested by Darren Reed <Darren.Reed@Sun.COM>.
+ */
+#define LINKTYPE_IPV4 228
+#define LINKTYPE_IPV6 229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl@gmail.com>.
+ */
+#define LINKTYPE_IEEE802_15_4_NOFCS 230
+
+/*
+ * Raw D-Bus:
+ *
+ * http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin@vidner.net>.
+ */
+#define LINKTYPE_DBUS 231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define LINKTYPE_JUNIPER_VS 232
+#define LINKTYPE_JUNIPER_SRX_E2E 233
+#define LINKTYPE_JUNIPER_FIBRECHANNEL 234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver). See
+ *
+ * http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin@kaiser.cx>.
+ */
+#define LINKTYPE_DVB_CI 235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol. Requested
+ * by Hans-Christoph Schemmel <hans-christoph.schemmel@cinterion.com>.
+ */
+#define LINKTYPE_MUX27010 236
+
+/*
+ * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
+ * <barisdemiray@gmail.com>.
+ */
+#define LINKTYPE_STANAG_5066_D_PDU 237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define LINKTYPE_JUNIPER_ATM_CEMIC 238
+
+/*
+ * NetFilter LOG messages
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ */
+#define LINKTYPE_NFLOG 239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define LINKTYPE_NETANALYZER 240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define LINKTYPE_NETANALYZER_TRANSPARENT 241
+
+/*
+ * IP-over-InfiniBand, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
+ */
+#define LINKTYPE_IPOIB 242
+
+/*
+ * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
+ *
+ * Requested by Guy Martin <gmsoft@tuxicoman.be>.
+ */
+#define LINKTYPE_MPEG_2_TS 243
+
+/*
+ * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
+ * used by their ng40 protocol tester.
+ *
+ * Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
+ */
+#define LINKTYPE_NG40 244
+
+/*
+ * Pseudo-header giving adapter number and flags, followed by an NFC
+ * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
+ * as specified by NFC Forum Logical Link Control Protocol Technical
+ * Specification LLCP 1.1.
+ *
+ * Requested by Mike Wakerly <mikey@google.com>.
+ */
+#define LINKTYPE_NFC_LLCP 245
+
+/*
+ * pfsync output; DLT_PFSYNC is 18, which collides with DLT_CIP in
+ * SuSE 6.3, on OpenBSD, NetBSD, DragonFly BSD, and macOS, and
+ * is 121, which collides with DLT_HHDLC, in FreeBSD. We pick a
+ * shiny new link-layer header type value that doesn't collide with
+ * anything, in the hopes that future pfsync savefiles, if any,
+ * won't require special hacks to distinguish from other savefiles.
+ *
+ */
+#define LINKTYPE_PFSYNC 246
+
+/*
+ * Raw InfiniBand packets, starting with the Local Routing Header.
+ *
+ * Requested by Oren Kladnitsky <orenk@mellanox.com>.
+ */
+#define LINKTYPE_INFINIBAND 247
+
+/*
+ * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
+ *
+ * Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
+ */
+#define LINKTYPE_SCTP 248
+
+/*
+ * USB packets, beginning with a USBPcap header.
+ *
+ * Requested by Tomasz Mon <desowin@gmail.com>
+ */
+#define LINKTYPE_USBPCAP 249
+
+/*
+ * Schweitzer Engineering Laboratories "RTAC" product serial-line
+ * packets.
+ *
+ * Requested by Chris Bontje <chris_bontje@selinc.com>.
+ */
+#define DLT_RTAC_SERIAL 250
+
+/*
+ * Bluetooth Low Energy air interface link-layer packets.
+ *
+ * Requested by Mike Kershaw <dragorn@kismetwireless.net>.
+ */
+#define LINKTYPE_BLUETOOTH_LE_LL 251
+
+/*
+ * Link-layer header type for upper-protocol layer PDU saves from wireshark.
+ *
+ * the actual contents are determined by two TAGs stored with each
+ * packet:
+ * EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the
+ * original packet.
+ *
+ * EXP_PDU_TAG_PROTO_NAME the name of the wireshark dissector
+ * that can make sense of the data stored.
+ */
+#define LINKTYPE_WIRESHARK_UPPER_PDU 252
+
+/*
+ * Link-layer header type for the netlink protocol (nlmon devices).
+ */
+#define LINKTYPE_NETLINK 253
+
+/*
+ * Bluetooth Linux Monitor headers for the BlueZ stack.
+ */
+#define LINKTYPE_BLUETOOTH_LINUX_MONITOR 254
+
+/*
+ * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
+ * captured by Ubertooth.
+ */
+#define LINKTYPE_BLUETOOTH_BREDR_BB 255
+
+/*
+ * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
+ */
+#define LINKTYPE_BLUETOOTH_LE_LL_WITH_PHDR 256
+
+/*
+ * PROFIBUS data link layer.
+ */
+#define LINKTYPE_PROFIBUS_DL 257
+
+/*
+ * Apple's DLT_PKTAP headers.
+ *
+ * Sadly, the folks at Apple either had no clue that the DLT_USERn values
+ * are for internal use within an organization and partners only, and
+ * didn't know that the right way to get a link-layer header type is to
+ * ask tcpdump.org for one, or knew and didn't care, so they just
+ * used DLT_USER2, which causes problems for everything except for
+ * their version of tcpdump.
+ *
+ * So I'll just give them one; hopefully this will show up in a
+ * libpcap release in time for them to get this into 10.10 Big Sur
+ * or whatever Mavericks' successor is called. LINKTYPE_PKTAP
+ * will be 258 *even on macOS*; that is *intentional*, so that
+ * PKTAP files look the same on *all* OSes (different OSes can have
+ * different numerical values for a given DLT_, but *MUST NOT* have
+ * different values for what goes in a file, as files can be moved
+ * between OSes!).
+ */
+#ifdef __APPLE__
+#ifndef LINKTYPE_PKTAP
+#define LINKTYPE_PKTAP 258
+#endif /* LINKTYPE_PKTAP */
+#endif /* __APPLE__ */
+
+/*
+ * Ethernet packets preceded by a header giving the last 6 octets
+ * of the preamble specified by 802.3-2012 Clause 65, section
+ * 65.1.3.2 "Transmit".
+ */
+#define LINKTYPE_EPON 259
+
+/*
+ * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
+ * in the PICMG HPM.2 specification.
+ */
+#define LINKTYPE_IPMI_HPM_2 260
+
+/*
+ * per Joshua Wright <jwright@hasborg.com>, formats for Zwave captures.
+ */
+#define LINKTYPE_ZWAVE_R1_R2 261
+#define LINKTYPE_ZWAVE_R3 262
+
+/*
+ * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
+ * Digital Lighting Management room bus serial protocol captures.
+ */
+#define LINKTYPE_WATTSTOPPER_DLM 263
+
+/*
+ * ISO 14443 contactless smart card messages.
+ */
+#define LINKTYPE_ISO_14443 264
+
+/*
+ * Radio data system (RDS) groups. IEC 62106.
+ * Per Jonathan Brucker <jonathan.brucke@gmail.com>.
+ */
+#define LINKTYPE_RDS 265
+
+/*
+ * USB packets, beginning with a Darwin (macOS, etc.) header.
+ */
+#define LINKTYPE_USB_DARWIN 266
+
+/*
+ * OpenBSD DLT_OPENFLOW.
+ */
+#define LINKTYPE_OPENFLOW 267
+
+/*
+ * SDLC frames containing SNA PDUs.
+ */
+#define LINKTYPE_SDLC 268
+
+/*
+ * per "Selvig, Bjorn" <b.selvig@ti.com> used for
+ * TI protocol sniffer.
+ */
+#define LINKTYPE_TI_LLN_SNIFFER 269
+
+/*
+ * per: Erik de Jong <erikdejong at gmail.com> for
+ * https://github.com/eriknl/LoRaTap/releases/tag/v0.1
+ */
+#define LINKTYPE_LORATAP 270
+
+/*
+ * per: Stefanha at gmail.com for
+ * http://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
+ * and: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vsockmon.h
+ * for: http://qemu-project.org/Features/VirtioVsock
+ */
+#define LINKTYPE_VSOCK 271
+
+/*
+ * Nordic Semiconductor Bluetooth LE sniffer.
+ */
+#define LINKTYPE_NORDIC_BLE 272
+
+/*
+ * Excentis DOCSIS 3.1 RF sniffer (XRA-31)
+ * per: bruno.verstuyft at excentis.com
+ * http://www.xra31.com/xra-header
+ */
+#define LINKTYPE_DOCSIS31_XRA31 273
+
+/*
+ * mPackets, as specified by IEEE 802.3br Figure 99-4, starting
+ * with the preamble and always ending with a CRC field.
+ */
+#define LINKTYPE_ETHERNET_MPACKET 274
+
+/*
+ * DisplayPort AUX channel monitoring data as specified by VESA
+ * DisplayPort(DP) Standard preceeded by a pseudo-header.
+ * per dirk.eibach at gdsys.cc
+ */
+#define LINKTYPE_DISPLAYPORT_AUX 275
+
+/*
+ * Linux cooked sockets v2.
+ */
+#define LINKTYPE_LINUX_SLL2 276
+
+#define LINKTYPE_MATCHING_MAX 276 /* highest value in the "matching" range */
+
+/*
+ * The DLT_ and LINKTYPE_ values in the "matching" range should be the
+ * same, so DLT_MATCHING_MAX and LINKTYPE_MATCHING_MAX should be the
+ * same.
+ */
+#if LINKTYPE_MATCHING_MAX != DLT_MATCHING_MAX
+#error The LINKTYPE_ matching range does not match the DLT_ matching range
+#endif
+
+static struct linktype_map {
+ int dlt;
+ int linktype;
+} map[] = {
+ /*
+ * These DLT_* codes have LINKTYPE_* codes with values identical
+ * to the values of the corresponding DLT_* code.
+ */
+ { DLT_NULL, LINKTYPE_NULL },
+ { DLT_EN10MB, LINKTYPE_ETHERNET },
+ { DLT_EN3MB, LINKTYPE_EXP_ETHERNET },
+ { DLT_AX25, LINKTYPE_AX25 },
+ { DLT_PRONET, LINKTYPE_PRONET },
+ { DLT_CHAOS, LINKTYPE_CHAOS },
+ { DLT_IEEE802, LINKTYPE_IEEE802_5 },
+ { DLT_ARCNET, LINKTYPE_ARCNET_BSD },
+ { DLT_SLIP, LINKTYPE_SLIP },
+ { DLT_PPP, LINKTYPE_PPP },
+ { DLT_FDDI, LINKTYPE_FDDI },
+ { DLT_SYMANTEC_FIREWALL, LINKTYPE_SYMANTEC_FIREWALL },
+
+ /*
+ * These DLT_* codes have different values on different
+ * platforms; we map them to LINKTYPE_* codes that
+ * have values that should never be equal to any DLT_*
+ * code.
+ */
+#ifdef DLT_FR
+ /* BSD/OS Frame Relay */
+ { DLT_FR, LINKTYPE_FRELAY },
+#endif
+
+ { DLT_ATM_RFC1483, LINKTYPE_ATM_RFC1483 },
+ { DLT_RAW, LINKTYPE_RAW },
+ { DLT_SLIP_BSDOS, LINKTYPE_SLIP_BSDOS },
+ { DLT_PPP_BSDOS, LINKTYPE_PPP_BSDOS },
+
+ /* BSD/OS Cisco HDLC */
+ { DLT_C_HDLC, LINKTYPE_C_HDLC },
+
+ /*
+ * These DLT_* codes are not on all platforms, but, so far,
+ * there don't appear to be any platforms that define
+ * other codes with those values; we map them to
+ * different LINKTYPE_* values anyway, just in case.
+ */
+
+ /* Linux ATM Classical IP */
+ { DLT_ATM_CLIP, LINKTYPE_ATM_CLIP },
+
+ /* NetBSD sync/async serial PPP (or Cisco HDLC) */
+ { DLT_PPP_SERIAL, LINKTYPE_PPP_HDLC },
+
+ /* NetBSD PPP over Ethernet */
+ { DLT_PPP_ETHER, LINKTYPE_PPP_ETHER },
+
+ /*
+ * All LINKTYPE_ values between LINKTYPE_MATCHING_MIN
+ * and LINKTYPE_MATCHING_MAX are mapped to identical
+ * DLT_ values.
+ */
+
+ { -1, -1 }
+};
+
+int
+dlt_to_linktype(int dlt)
+{
+ int i;
+
+ /*
+ * DLTs that, on some platforms, have values in the matching range
+ * but that *don't* have the same value as the corresponding
+ * LINKTYPE because, for some reason, not all OSes have the
+ * same value for that DLT (note that the DLT's value might be
+ * outside the matching range on some of those OSes).
+ */
+ if (dlt == DLT_PFSYNC)
+ return (LINKTYPE_PFSYNC);
+ if (dlt == DLT_PKTAP)
+ return (LINKTYPE_PKTAP);
+
+ /*
+ * For all other values in the matching range, the DLT
+ * value is the same as the LINKTYPE value.
+ */
+ if (dlt >= DLT_MATCHING_MIN && dlt <= DLT_MATCHING_MAX)
+ return (dlt);
+
+ /*
+ * Map the values outside that range.
+ */
+ for (i = 0; map[i].dlt != -1; i++) {
+ if (map[i].dlt == dlt)
+ return (map[i].linktype);
+ }
+
+ /*
+ * If we don't have a mapping for this DLT, return an
+ * error; that means that this is a value with no corresponding
+ * LINKTYPE, and we need to assign one.
+ */
+ return (-1);
+}
+
+int
+linktype_to_dlt(int linktype)
+{
+ int i;
+
+ /*
+ * LINKTYPEs in the matching range that *don't*
+ * have the same value as the corresponding DLTs
+ * because, for some reason, not all OSes have the
+ * same value for that DLT.
+ */
+ if (linktype == LINKTYPE_PFSYNC)
+ return (DLT_PFSYNC);
+ if (linktype == LINKTYPE_PKTAP)
+ return (DLT_PKTAP);
+
+ /*
+ * For all other values in the matching range, the LINKTYPE
+ * value is the same as the DLT value.
+ */
+ if (linktype >= LINKTYPE_MATCHING_MIN &&
+ linktype <= LINKTYPE_MATCHING_MAX)
+ return (linktype);
+
+ /*
+ * Map the values outside that range.
+ */
+ for (i = 0; map[i].linktype != -1; i++) {
+ if (map[i].linktype == linktype)
+ return (map[i].dlt);
+ }
+
+ /*
+ * If we don't have an entry for this LINKTYPE, return
+ * the link type value; it may be a DLT from an older
+ * version of libpcap.
+ */
+ return linktype;
+}
+
+/*
+ * Return the maximum snapshot length for a given DLT_ value.
+ *
+ * For most link-layer types, we use MAXIMUM_SNAPLEN.
+ *
+ * For DLT_DBUS, the maximum is 128MiB, as per
+ *
+ * https://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * For DLT_USBPCAP, the maximum is 1MiB, as per
+ *
+ * https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=15985
+ */
+u_int
+max_snaplen_for_dlt(int dlt)
+{
+ switch (dlt) {
+
+ case DLT_DBUS:
+ return 128*1024*1024;
+
+ case DLT_USBPCAP:
+ return 1024*1024;
+
+ default:
+ return MAXIMUM_SNAPLEN;
+ }
+}
+
+/*
+ * DLT_LINUX_SLL packets with a protocol type of LINUX_SLL_P_CAN or
+ * LINUX_SLL_P_CANFD have SocketCAN headers in front of the payload,
+ * with the CAN ID being in host byte order.
+ *
+ * When reading a DLT_LINUX_SLL capture file, we need to check for those
+ * packets and convert the CAN ID from the byte order of the host that
+ * wrote the file to this host's byte order.
+ */
+static void
+swap_linux_sll_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+ u_int caplen = hdr->caplen;
+ u_int length = hdr->len;
+ struct sll_header *shdr = (struct sll_header *)buf;
+ uint16_t protocol;
+ pcap_can_socketcan_hdr *chdr;
+
+ if (caplen < (u_int) sizeof(struct sll_header) ||
+ length < (u_int) sizeof(struct sll_header)) {
+ /* Not enough data to have the protocol field */
+ return;
+ }
+
+ protocol = EXTRACT_16BITS(&shdr->sll_protocol);
+ if (protocol != LINUX_SLL_P_CAN && protocol != LINUX_SLL_P_CANFD)
+ return;
+
+ /*
+ * SocketCAN packet; fix up the packet's header.
+ */
+ chdr = (pcap_can_socketcan_hdr *)(buf + sizeof(struct sll_header));
+ if (caplen < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id) ||
+ length < (u_int) sizeof(struct sll_header) + sizeof(chdr->can_id)) {
+ /* Not enough data to have the CAN ID */
+ return;
+ }
+ chdr->can_id = SWAPLONG(chdr->can_id);
+}
+
+/*
+ * The DLT_USB_LINUX and DLT_USB_LINUX_MMAPPED headers are in host
+ * byte order when capturing (it's supplied directly from a
+ * memory-mapped buffer shared by the kernel).
+ *
+ * When reading a DLT_USB_LINUX or DLT_USB_LINUX_MMAPPED capture file,
+ * we need to convert it from the byte order of the host that wrote
+ * the file to this host's byte order.
+ */
+static void
+swap_linux_usb_header(const struct pcap_pkthdr *hdr, u_char *buf,
+ int header_len_64_bytes)
+{
+ pcap_usb_header_mmapped *uhdr = (pcap_usb_header_mmapped *)buf;
+ bpf_u_int32 offset = 0;
+
+ /*
+ * "offset" is the offset *past* the field we're swapping;
+ * we skip the field *before* checking to make sure
+ * the captured data length includes the entire field.
+ */
+
+ /*
+ * The URB id is a totally opaque value; do we really need to
+ * convert it to the reading host's byte order???
+ */
+ offset += 8; /* skip past id */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->id = SWAPLL(uhdr->id);
+
+ offset += 4; /* skip past various 1-byte fields */
+
+ offset += 2; /* skip past bus_id */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->bus_id = SWAPSHORT(uhdr->bus_id);
+
+ offset += 2; /* skip past various 1-byte fields */
+
+ offset += 8; /* skip past ts_sec */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->ts_sec = SWAPLL(uhdr->ts_sec);
+
+ offset += 4; /* skip past ts_usec */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->ts_usec = SWAPLONG(uhdr->ts_usec);
+
+ offset += 4; /* skip past status */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->status = SWAPLONG(uhdr->status);
+
+ offset += 4; /* skip past urb_len */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->urb_len = SWAPLONG(uhdr->urb_len);
+
+ offset += 4; /* skip past data_len */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->data_len = SWAPLONG(uhdr->data_len);
+
+ if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+ offset += 4; /* skip past s.iso.error_count */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->s.iso.error_count = SWAPLONG(uhdr->s.iso.error_count);
+
+ offset += 4; /* skip past s.iso.numdesc */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->s.iso.numdesc = SWAPLONG(uhdr->s.iso.numdesc);
+ } else
+ offset += 8; /* skip USB setup header */
+
+ /*
+ * With the old header, there are no isochronous descriptors
+ * after the header.
+ *
+ * With the new header, the actual number of descriptors in
+ * the header is not s.iso.numdesc, it's ndesc - only the
+ * first N descriptors, for some value of N, are put into
+ * the header, and ndesc is set to the actual number copied.
+ * In addition, if s.iso.numdesc is negative, no descriptors
+ * are captured, and ndesc is set to 0.
+ */
+ if (header_len_64_bytes) {
+ /*
+ * This is either the "version 1" header, with
+ * 16 bytes of additional fields at the end, or
+ * a "version 0" header from a memory-mapped
+ * capture, with 16 bytes of zeroed-out padding
+ * at the end. Byte swap them as if this were
+ * a "version 1" header.
+ */
+ offset += 4; /* skip past interval */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->interval = SWAPLONG(uhdr->interval);
+
+ offset += 4; /* skip past start_frame */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->start_frame = SWAPLONG(uhdr->start_frame);
+
+ offset += 4; /* skip past xfer_flags */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->xfer_flags = SWAPLONG(uhdr->xfer_flags);
+
+ offset += 4; /* skip past ndesc */
+ if (hdr->caplen < offset)
+ return;
+ uhdr->ndesc = SWAPLONG(uhdr->ndesc);
+
+ if (uhdr->transfer_type == URB_ISOCHRONOUS) {
+ /* swap the values in struct linux_usb_isodesc */
+ usb_isodesc *pisodesc;
+ uint32_t i;
+
+ pisodesc = (usb_isodesc *)(void *)(buf+offset);
+ for (i = 0; i < uhdr->ndesc; i++) {
+ offset += 4; /* skip past status */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->status = SWAPLONG(pisodesc->status);
+
+ offset += 4; /* skip past offset */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->offset = SWAPLONG(pisodesc->offset);
+
+ offset += 4; /* skip past len */
+ if (hdr->caplen < offset)
+ return;
+ pisodesc->len = SWAPLONG(pisodesc->len);
+
+ offset += 4; /* skip past padding */
+
+ pisodesc++;
+ }
+ }
+ }
+}
+
+/*
+ * The DLT_NFLOG "packets" have a mixture of big-endian and host-byte-order
+ * data. They begin with a fixed-length header with big-endian fields,
+ * followed by a set of TLVs, where the type and length are in host
+ * byte order but the values are either big-endian or are a raw byte
+ * sequence that's the same regardless of the host's byte order.
+ *
+ * When reading a DLT_NFLOG capture file, we need to convert the type
+ * and length values from the byte order of the host that wrote the
+ * file to the byte order of this host.
+ */
+static void
+swap_nflog_header(const struct pcap_pkthdr *hdr, u_char *buf)
+{
+ u_char *p = buf;
+ nflog_hdr_t *nfhdr = (nflog_hdr_t *)buf;
+ nflog_tlv_t *tlv;
+ u_int caplen = hdr->caplen;
+ u_int length = hdr->len;
+ uint16_t size;
+
+ if (caplen < (u_int) sizeof(nflog_hdr_t) ||
+ length < (u_int) sizeof(nflog_hdr_t)) {
+ /* Not enough data to have any TLVs. */
+ return;
+ }
+
+ if (nfhdr->nflog_version != 0) {
+ /* Unknown NFLOG version */
+ return;
+ }
+
+ length -= sizeof(nflog_hdr_t);
+ caplen -= sizeof(nflog_hdr_t);
+ p += sizeof(nflog_hdr_t);
+
+ while (caplen >= sizeof(nflog_tlv_t)) {
+ tlv = (nflog_tlv_t *) p;
+
+ /* Swap the type and length. */
+ tlv->tlv_type = SWAPSHORT(tlv->tlv_type);
+ tlv->tlv_length = SWAPSHORT(tlv->tlv_length);
+
+ /* Get the length of the TLV. */
+ size = tlv->tlv_length;
+ if (size % 4 != 0)
+ size += 4 - size % 4;
+
+ /* Is the TLV's length less than the minimum? */
+ if (size < sizeof(nflog_tlv_t)) {
+ /* Yes. Give up now. */
+ return;
+ }
+
+ /* Do we have enough data for the full TLV? */
+ if (caplen < size || length < size) {
+ /* No. */
+ return;
+ }
+
+ /* Skip over the TLV. */
+ length -= size;
+ caplen -= size;
+ p += size;
+ }
+}
+
+void
+swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr, u_char *data)
+{
+ /*
+ * Convert pseudo-headers from the byte order of
+ * the host on which the file was saved to our
+ * byte order, as necessary.
+ */
+ switch (linktype) {
+
+ case DLT_LINUX_SLL:
+ swap_linux_sll_header(hdr, data);
+ break;
+
+ case DLT_USB_LINUX:
+ swap_linux_usb_header(hdr, data, 0);
+ break;
+
+ case DLT_USB_LINUX_MMAPPED:
+ swap_linux_usb_header(hdr, data, 1);
+ break;
+
+ case DLT_NFLOG:
+ swap_nflog_header(hdr, data);
+ break;
+ }
+}
diff --git a/lib/libpcap/libpcap/pcap-common.h b/lib/libpcap/libpcap/pcap-common.h
new file mode 100644
index 0000000..e97b587
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-common.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * pcap-common.h - common code for pcap and pcapng files
+ */
+
+/*
+ * We use the "receiver-makes-right" approach to byte order,
+ * because time is at a premium when we are writing the file.
+ * In other words, the pcap_file_header and pcap_pkthdr,
+ * records are written in host byte order.
+ * Note that the bytes of packet data are written out in the order in
+ * which they were received, so multi-byte fields in packets are not
+ * written in host byte order, they're written in whatever order the
+ * sending machine put them in.
+ *
+ * ntoh[ls] aren't sufficient because we might need to swap on a big-endian
+ * machine (if the file was written in little-end order).
+ */
+#define SWAPLONG(y) \
+ (((((u_int)(y))&0xff)<<24) | \
+ ((((u_int)(y))&0xff00)<<8) | \
+ ((((u_int)(y))&0xff0000)>>8) | \
+ ((((u_int)(y))>>24)&0xff))
+#define SWAPSHORT(y) \
+ ((u_short)(((((u_int)(y))&0xff)<<8) | \
+ ((((u_int)(y))&0xff00)>>8)))
+
+#ifdef __APPLE__
+#define SWAPLONGLONG(y) \
+(((unsigned long long)SWAPLONG((unsigned long)(y)) << 32) | (SWAPLONG((unsigned long)((y) >> 32))))
+#endif /* __APPLE__ */
+
+extern int dlt_to_linktype(int dlt);
+
+extern int linktype_to_dlt(int linktype);
+
+extern void swap_pseudo_headers(int linktype, struct pcap_pkthdr *hdr,
+ u_char *data);
+
+extern u_int max_snaplen_for_dlt(int dlt);
diff --git a/lib/libpcap/libpcap/pcap-config b/lib/libpcap/libpcap/pcap-config
new file mode 100644
index 0000000..ec9e8f1
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-config
@@ -0,0 +1,89 @@
+#! /bin/sh
+
+#
+# Script to give the appropriate compiler flags and linker flags
+# to use when building code that uses libpcap.
+#
+prefix="/usr/local"
+exec_prefix="${prefix}"
+includedir="${prefix}/include"
+libdir="${exec_prefix}/lib"
+V_RPATH_OPT=""
+LIBS=""
+
+static=0
+show_cflags=0
+show_libs=0
+while [ "$#" != 0 ]
+do
+ case "$1" in
+
+ --static)
+ static=1
+ ;;
+
+ --cflags)
+ show_cflags=1
+ ;;
+
+ --libs)
+ show_libs=1
+ ;;
+
+ --additional-libs)
+ show_additional_libs=1
+ ;;
+ esac
+ shift
+done
+if [ "$V_RPATH_OPT" != "" ]
+then
+ #
+ # If libdir isn't /usr/lib, add it to the run-time linker path.
+ #
+ if [ "$libdir" != "/usr/lib" ]
+ then
+ RPATH=$V_RPATH_OPT$libdir
+ fi
+fi
+if [ "$static" = 1 ]
+then
+ #
+ # Include LIBS so that the flags include libraries containing
+ # routines that libpcap uses.
+ #
+ if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
+ then
+ echo "-I$includedir -L$libdir -lpcap $LIBS"
+ elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
+ then
+ echo "-I$includedir -L$libdir $LIBS"
+ elif [ "$show_cflags" = 1 ]
+ then
+ echo "-I$includedir"
+ elif [ "$show_libs" = 1 ]
+ then
+ echo "-L$libdir -lpcap $LIBS"
+ elif [ "$show_additional_libs" = 1 ]
+ then
+ echo "$LIBS"
+ fi
+else
+ #
+ # Omit LIBS - libpcap is assumed to be linked with those
+ # libraries, so there's no need to do so explicitly.
+ #
+ if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
+ then
+ echo "-I$includedir -L$libdir $RPATH -lpcap"
+ elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
+ then
+ echo "-I$includedir"
+ elif [ "$show_cflags" = 1 ]
+ then
+ echo "-I$includedir"
+ elif [ "$show_libs" = 1 ]
+ then
+ echo "-L$libdir $RPATH -lpcap"
+ fi
+fi
diff --git a/lib/libpcap/libpcap/pcap-config.1 b/lib/libpcap/libpcap/pcap-config.1
new file mode 100644
index 0000000..0388d0f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-config.1
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-CONFIG 1 "15 February 2015"
+.SH NAME
+pcap-config \- write libpcap compiler and linker flags to standard output
+.SH SYNOPSIS
+.na
+.B pcap-config
+[
+.B \-\-static
+]
+[
+.B \-\-cflags | \-\-libs | \-\-additional-libs
+]
+.ad
+.SH DESCRIPTION
+.LP
+When run with the
+.B \-\-cflags
+option,
+.I pcap-config
+writes to the standard output the
+.B \-I
+compiler flags required to include libpcap's header files.
+When run with the
+.B \-\-libs
+option,
+.I pcap-config
+writes to the standard output the
+.B \-L
+and
+.B \-l
+linker flags required to link with libpcap, including
+.B \-l
+flags for libraries required by libpcap.
+When run with the
+.B \-\-additional-libs
+option,
+.I pcap-config
+writes to the standard output the
+.B \-L
+and
+.B \-l
+flags for libraries required by libpcap, but not the
+.B \-lpcap
+flag to link with libpcap itself.
+.LP
+By default, it writes flags appropriate for compiling with a
+dynamically-linked version of libpcap; the
+.B \-\-static
+flag causes it to write flags appropriate for compiling with a
+statically-linked version of libpcap.
+.SH "SEE ALSO"
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap-config.in b/lib/libpcap/libpcap/pcap-config.in
new file mode 100644
index 0000000..54ca42f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-config.in
@@ -0,0 +1,94 @@
+#! /bin/sh
+
+#
+# Script to give the appropriate compiler flags and linker flags
+# to use when building code that uses libpcap.
+#
+# These variables come from the configure script, so includedir and
+# libdir may be defined in terms of prefix and exec_prefix, so the
+# latter must be defined as well.
+#
+prefix="@prefix@"
+exec_prefix="@exec_prefix@"
+includedir="@includedir@"
+libdir="@libdir@"
+V_RPATH_OPT="@V_RPATH_OPT@"
+LIBS="@LIBS@"
+PACKAGE_NAME="@PACKAGE_NAME@"
+
+static=0
+show_cflags=0
+show_libs=0
+while [ "$#" != 0 ]
+do
+ case "$1" in
+
+ --static)
+ static=1
+ ;;
+
+ --cflags)
+ show_cflags=1
+ ;;
+
+ --libs)
+ show_libs=1
+ ;;
+
+ --additional-libs)
+ show_additional_libs=1
+ ;;
+ esac
+ shift
+done
+if [ "$V_RPATH_OPT" != "" ]
+then
+ #
+ # If libdir isn't /usr/lib, add it to the run-time linker path.
+ #
+ if [ "$libdir" != "/usr/lib" ]
+ then
+ RPATH=$V_RPATH_OPT$libdir
+ fi
+fi
+if [ "$static" = 1 ]
+then
+ #
+ # Include LIBS so that the flags include libraries containing
+ # routines that libpcap uses.
+ #
+ if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
+ then
+ echo "-I$includedir -L$libdir -lpcap $LIBS"
+ elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
+ then
+ echo "-I$includedir -L$libdir $LIBS"
+ elif [ "$show_cflags" = 1 ]
+ then
+ echo "-I$includedir"
+ elif [ "$show_libs" = 1 ]
+ then
+ echo "-L$libdir -lpcap $LIBS"
+ elif [ "$show_additional_libs" = 1 ]
+ then
+ echo "$LIBS"
+ fi
+else
+ #
+ # Omit LIBS - libpcap is assumed to be linked with those
+ # libraries, so there's no need to do so explicitly.
+ #
+ if [ "$show_cflags" = 1 -a "$show_libs" = 1 ]
+ then
+ echo "-I$includedir -L$libdir $RPATH -l$PACKAGE_NAME"
+ elif [ "$show_cflags" = 1 -a "$show_additional_libs" = 1 ]
+ then
+ echo "-I$includedir"
+ elif [ "$show_cflags" = 1 ]
+ then
+ echo "-I$includedir"
+ elif [ "$show_libs" = 1 ]
+ then
+ echo "-L$libdir $RPATH -l$PACKAGE_NAME"
+ fi
+fi
diff --git a/lib/libpcap/libpcap/pcap-dag.c b/lib/libpcap/libpcap/pcap-dag.c
new file mode 100644
index 0000000..e076676
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dag.c
@@ -0,0 +1,1467 @@
+/*
+ * pcap-dag.c: Packet capture interface for Endace DAG cards.
+ *
+ * Authors: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
+ * Modifications: Jesper Peterson
+ * Koryn Grant
+ * Stephen Donnelly <stephen.donnelly@endace.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/param.h> /* optionally get BSD define */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pcap-int.h"
+
+#include <ctype.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+struct mbuf; /* Squelch compiler warnings on some platforms for */
+struct rtentry; /* declarations in <net/if.h> */
+#include <net/if.h>
+
+#include "dagnew.h"
+#include "dagapi.h"
+#include "dagpci.h"
+#include "dag_config_api.h"
+
+#include "pcap-dag.h"
+
+/*
+ * DAG devices have names beginning with "dag", followed by a number
+ * from 0 to DAG_MAX_BOARDS, then optionally a colon and a stream number
+ * from 0 to DAG_STREAM_MAX.
+ */
+#ifndef DAG_MAX_BOARDS
+#define DAG_MAX_BOARDS 32
+#endif
+
+
+#ifndef ERF_TYPE_AAL5
+#define ERF_TYPE_AAL5 4
+#endif
+
+#ifndef ERF_TYPE_MC_HDLC
+#define ERF_TYPE_MC_HDLC 5
+#endif
+
+#ifndef ERF_TYPE_MC_RAW
+#define ERF_TYPE_MC_RAW 6
+#endif
+
+#ifndef ERF_TYPE_MC_ATM
+#define ERF_TYPE_MC_ATM 7
+#endif
+
+#ifndef ERF_TYPE_MC_RAW_CHANNEL
+#define ERF_TYPE_MC_RAW_CHANNEL 8
+#endif
+
+#ifndef ERF_TYPE_MC_AAL5
+#define ERF_TYPE_MC_AAL5 9
+#endif
+
+#ifndef ERF_TYPE_COLOR_HDLC_POS
+#define ERF_TYPE_COLOR_HDLC_POS 10
+#endif
+
+#ifndef ERF_TYPE_COLOR_ETH
+#define ERF_TYPE_COLOR_ETH 11
+#endif
+
+#ifndef ERF_TYPE_MC_AAL2
+#define ERF_TYPE_MC_AAL2 12
+#endif
+
+#ifndef ERF_TYPE_IP_COUNTER
+#define ERF_TYPE_IP_COUNTER 13
+#endif
+
+#ifndef ERF_TYPE_TCP_FLOW_COUNTER
+#define ERF_TYPE_TCP_FLOW_COUNTER 14
+#endif
+
+#ifndef ERF_TYPE_DSM_COLOR_HDLC_POS
+#define ERF_TYPE_DSM_COLOR_HDLC_POS 15
+#endif
+
+#ifndef ERF_TYPE_DSM_COLOR_ETH
+#define ERF_TYPE_DSM_COLOR_ETH 16
+#endif
+
+#ifndef ERF_TYPE_COLOR_MC_HDLC_POS
+#define ERF_TYPE_COLOR_MC_HDLC_POS 17
+#endif
+
+#ifndef ERF_TYPE_AAL2
+#define ERF_TYPE_AAL2 18
+#endif
+
+#ifndef ERF_TYPE_COLOR_HASH_POS
+#define ERF_TYPE_COLOR_HASH_POS 19
+#endif
+
+#ifndef ERF_TYPE_COLOR_HASH_ETH
+#define ERF_TYPE_COLOR_HASH_ETH 20
+#endif
+
+#ifndef ERF_TYPE_INFINIBAND
+#define ERF_TYPE_INFINIBAND 21
+#endif
+
+#ifndef ERF_TYPE_IPV4
+#define ERF_TYPE_IPV4 22
+#endif
+
+#ifndef ERF_TYPE_IPV6
+#define ERF_TYPE_IPV6 23
+#endif
+
+#ifndef ERF_TYPE_RAW_LINK
+#define ERF_TYPE_RAW_LINK 24
+#endif
+
+#ifndef ERF_TYPE_INFINIBAND_LINK
+#define ERF_TYPE_INFINIBAND_LINK 25
+#endif
+
+#ifndef ERF_TYPE_META
+#define ERF_TYPE_META 27
+#endif
+
+#ifndef ERF_TYPE_PAD
+#define ERF_TYPE_PAD 48
+#endif
+
+#define ATM_CELL_SIZE 52
+#define ATM_HDR_SIZE 4
+
+/*
+ * A header containing additional MTP information.
+ */
+#define MTP2_SENT_OFFSET 0 /* 1 byte */
+#define MTP2_ANNEX_A_USED_OFFSET 1 /* 1 byte */
+#define MTP2_LINK_NUMBER_OFFSET 2 /* 2 bytes */
+#define MTP2_HDR_LEN 4 /* length of the header */
+
+#define MTP2_ANNEX_A_NOT_USED 0
+#define MTP2_ANNEX_A_USED 1
+#define MTP2_ANNEX_A_USED_UNKNOWN 2
+
+/* SunATM pseudo header */
+struct sunatm_hdr {
+ unsigned char flags; /* destination and traffic type */
+ unsigned char vpi; /* VPI */
+ unsigned short vci; /* VCI */
+};
+
+/*
+ * Private data for capturing on DAG devices.
+ */
+struct pcap_dag {
+ struct pcap_stat stat;
+ u_char *dag_mem_bottom; /* DAG card current memory bottom pointer */
+ u_char *dag_mem_top; /* DAG card current memory top pointer */
+ int dag_fcs_bits; /* Number of checksum bits from link layer */
+ int dag_flags; /* Flags */
+ int dag_stream; /* DAG stream number */
+ int dag_timeout; /* timeout specified to pcap_open_live.
+ * Same as in linux above, introduce
+ * generally? */
+ dag_card_ref_t dag_ref; /* DAG Configuration/Status API card reference */
+ dag_component_t dag_root; /* DAG CSAPI Root component */
+ attr_uuid_t drop_attr; /* DAG Stream Drop Attribute handle, if available */
+ struct timeval required_select_timeout;
+ /* Timeout caller must use in event loops */
+};
+
+typedef struct pcap_dag_node {
+ struct pcap_dag_node *next;
+ pcap_t *p;
+ pid_t pid;
+} pcap_dag_node_t;
+
+static pcap_dag_node_t *pcap_dags = NULL;
+static int atexit_handler_installed = 0;
+static const unsigned short endian_test_word = 0x0100;
+
+#define IS_BIGENDIAN() (*((unsigned char *)&endian_test_word))
+
+#define MAX_DAG_PACKET 65536
+
+static unsigned char TempPkt[MAX_DAG_PACKET];
+
+#ifndef HAVE_DAG_LARGE_STREAMS_API
+#define dag_attach_stream64(a, b, c, d) dag_attach_stream(a, b, c, d)
+#define dag_get_stream_poll64(a, b, c, d, e) dag_get_stream_poll(a, b, c, d, e)
+#define dag_set_stream_poll64(a, b, c, d, e) dag_set_stream_poll(a, b, c, d, e)
+#define dag_size_t uint32_t
+#endif
+
+static int dag_setfilter(pcap_t *p, struct bpf_program *fp);
+static int dag_stats(pcap_t *p, struct pcap_stat *ps);
+static int dag_set_datalink(pcap_t *p, int dlt);
+static int dag_get_datalink(pcap_t *p);
+static int dag_setnonblock(pcap_t *p, int nonblock);
+
+static void
+delete_pcap_dag(pcap_t *p)
+{
+ pcap_dag_node_t *curr = NULL, *prev = NULL;
+
+ for (prev = NULL, curr = pcap_dags; curr != NULL && curr->p != p; prev = curr, curr = curr->next) {
+ /* empty */
+ }
+
+ if (curr != NULL && curr->p == p) {
+ if (prev != NULL) {
+ prev->next = curr->next;
+ } else {
+ pcap_dags = curr->next;
+ }
+ }
+}
+
+/*
+ * Performs a graceful shutdown of the DAG card, frees dynamic memory held
+ * in the pcap_t structure, and closes the file descriptor for the DAG card.
+ */
+
+static void
+dag_platform_cleanup(pcap_t *p)
+{
+ struct pcap_dag *pd = p->priv;
+
+ if(dag_stop_stream(p->fd, pd->dag_stream) < 0)
+ fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
+
+ if(dag_detach_stream(p->fd, pd->dag_stream) < 0)
+ fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+
+ if(pd->dag_ref != NULL) {
+ dag_config_dispose(pd->dag_ref);
+ /*
+ * Note: we don't need to call close(p->fd) or
+ * dag_close(p->fd), as dag_config_dispose(pd->dag_ref)
+ * does this.
+ *
+ * Set p->fd to -1 to make sure that's not done.
+ */
+ p->fd = -1;
+ pd->dag_ref = NULL;
+ }
+ delete_pcap_dag(p);
+ pcap_cleanup_live_common(p);
+}
+
+static void
+atexit_handler(void)
+{
+ while (pcap_dags != NULL) {
+ if (pcap_dags->pid == getpid()) {
+ if (pcap_dags->p != NULL)
+ dag_platform_cleanup(pcap_dags->p);
+ } else {
+ delete_pcap_dag(pcap_dags->p);
+ }
+ }
+}
+
+static int
+new_pcap_dag(pcap_t *p)
+{
+ pcap_dag_node_t *node = NULL;
+
+ if ((node = malloc(sizeof(pcap_dag_node_t))) == NULL) {
+ return -1;
+ }
+
+ if (!atexit_handler_installed) {
+ atexit(atexit_handler);
+ atexit_handler_installed = 1;
+ }
+
+ node->next = pcap_dags;
+ node->p = p;
+ node->pid = getpid();
+
+ pcap_dags = node;
+
+ return 0;
+}
+
+static unsigned int
+dag_erf_ext_header_count(uint8_t * erf, size_t len)
+{
+ uint32_t hdr_num = 0;
+ uint8_t hdr_type;
+
+ /* basic sanity checks */
+ if ( erf == NULL )
+ return 0;
+ if ( len < 16 )
+ return 0;
+
+ /* check if we have any extension headers */
+ if ( (erf[8] & 0x80) == 0x00 )
+ return 0;
+
+ /* loop over the extension headers */
+ do {
+
+ /* sanity check we have enough bytes */
+ if ( len < (24 + (hdr_num * 8)) )
+ return hdr_num;
+
+ /* get the header type */
+ hdr_type = erf[(16 + (hdr_num * 8))];
+ hdr_num++;
+
+ } while ( hdr_type & 0x80 );
+
+ return hdr_num;
+}
+
+/*
+ * Read at most max_packets from the capture stream and call the callback
+ * for each of them. Returns the number of packets handled, -1 if an
+ * error occured, or -2 if we were told to break out of the loop.
+ */
+static int
+dag_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_dag *pd = p->priv;
+ unsigned int processed = 0;
+ unsigned int nonblocking = pd->dag_flags & DAGF_NONBLOCK;
+ unsigned int num_ext_hdr = 0;
+ unsigned int ticks_per_second;
+
+ /* Get the next bufferful of packets (if necessary). */
+ while (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size) {
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that
+ * it has, and return -2 to indicate that
+ * we were told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return -2;
+ }
+
+ /* dag_advance_stream() will block (unless nonblock is called)
+ * until 64kB of data has accumulated.
+ * If to_ms is set, it will timeout before 64kB has accumulated.
+ * We wait for 64kB because processing a few packets at a time
+ * can cause problems at high packet rates (>200kpps) due
+ * to inefficiencies.
+ * This does mean if to_ms is not specified the capture may 'hang'
+ * for long periods if the data rate is extremely slow (<64kB/sec)
+ * If non-block is specified it will return immediately. The user
+ * is then responsible for efficiency.
+ */
+ if ( NULL == (pd->dag_mem_top = dag_advance_stream(p->fd, pd->dag_stream, &(pd->dag_mem_bottom))) ) {
+ return -1;
+ }
+
+ if (nonblocking && (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
+ {
+ /* Pcap is configured to process only available packets, and there aren't any, return immediately. */
+ return 0;
+ }
+
+ if(!nonblocking &&
+ pd->dag_timeout &&
+ (pd->dag_mem_top - pd->dag_mem_bottom < dag_record_size))
+ {
+ /* Blocking mode, but timeout set and no data has arrived, return anyway.*/
+ return 0;
+ }
+
+ }
+
+ /* Process the packets. */
+ while (pd->dag_mem_top - pd->dag_mem_bottom >= dag_record_size) {
+
+ unsigned short packet_len = 0;
+ int caplen = 0;
+ struct pcap_pkthdr pcap_header;
+
+ dag_record_t *header = (dag_record_t *)(pd->dag_mem_bottom);
+
+ u_char *dp = ((u_char *)header); /* + dag_record_size; */
+ unsigned short rlen;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that
+ * it has, and return -2 to indicate that
+ * we were told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return -2;
+ }
+
+ rlen = ntohs(header->rlen);
+ if (rlen < dag_record_size)
+ {
+ strncpy(p->errbuf, "dag_read: record too small", PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+ pd->dag_mem_bottom += rlen;
+
+ /* Count lost packets. */
+ switch((header->type & 0x7f)) {
+ /* in these types the color value overwrites the lctr */
+ case ERF_TYPE_COLOR_HDLC_POS:
+ case ERF_TYPE_COLOR_ETH:
+ case ERF_TYPE_DSM_COLOR_HDLC_POS:
+ case ERF_TYPE_DSM_COLOR_ETH:
+ case ERF_TYPE_COLOR_MC_HDLC_POS:
+ case ERF_TYPE_COLOR_HASH_ETH:
+ case ERF_TYPE_COLOR_HASH_POS:
+ break;
+
+ default:
+ if ( (pd->drop_attr == kNullAttributeUuid) && (header->lctr) ) {
+ pd->stat.ps_drop += ntohs(header->lctr);
+ }
+ }
+
+ if ((header->type & 0x7f) == ERF_TYPE_PAD) {
+ continue;
+ }
+
+ num_ext_hdr = dag_erf_ext_header_count(dp, rlen);
+
+ /* ERF encapsulation */
+ /* The Extensible Record Format is not dropped for this kind of encapsulation,
+ * and will be handled as a pseudo header by the decoding application.
+ * The information carried in the ERF header and in the optional subheader (if present)
+ * could be merged with the libpcap information, to offer a better decoding.
+ * The packet length is
+ * o the length of the packet on the link (header->wlen),
+ * o plus the length of the ERF header (dag_record_size), as the length of the
+ * pseudo header will be adjusted during the decoding,
+ * o plus the length of the optional subheader (if present).
+ *
+ * The capture length is header.rlen and the byte stuffing for alignment will be dropped
+ * if the capture length is greater than the packet length.
+ */
+ if (p->linktype == DLT_ERF) {
+ packet_len = ntohs(header->wlen) + dag_record_size;
+ caplen = rlen;
+ switch ((header->type & 0x7f)) {
+ case ERF_TYPE_MC_AAL5:
+ case ERF_TYPE_MC_ATM:
+ case ERF_TYPE_MC_HDLC:
+ case ERF_TYPE_MC_RAW_CHANNEL:
+ case ERF_TYPE_MC_RAW:
+ case ERF_TYPE_MC_AAL2:
+ case ERF_TYPE_COLOR_MC_HDLC_POS:
+ packet_len += 4; /* MC header */
+ break;
+
+ case ERF_TYPE_COLOR_HASH_ETH:
+ case ERF_TYPE_DSM_COLOR_ETH:
+ case ERF_TYPE_COLOR_ETH:
+ case ERF_TYPE_ETH:
+ packet_len += 2; /* ETH header */
+ break;
+ } /* switch type */
+
+ /* Include ERF extension headers */
+ packet_len += (8 * num_ext_hdr);
+
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ } else {
+ /* Other kind of encapsulation according to the header Type */
+
+ /* Skip over generic ERF header */
+ dp += dag_record_size;
+ /* Skip over extension headers */
+ dp += 8 * num_ext_hdr;
+
+ switch((header->type & 0x7f)) {
+ case ERF_TYPE_ATM:
+ case ERF_TYPE_AAL5:
+ if ((header->type & 0x7f) == ERF_TYPE_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ }
+ case ERF_TYPE_MC_ATM:
+ if ((header->type & 0x7f) == ERF_TYPE_MC_ATM) {
+ caplen = packet_len = ATM_CELL_SIZE;
+ dp+=4;
+ }
+ case ERF_TYPE_MC_AAL5:
+ if ((header->type & 0x7f) == ERF_TYPE_MC_AAL5) {
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size - 4;
+ dp+=4;
+ }
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+
+ if ((header->type & 0x7f) == ERF_TYPE_ATM) {
+ caplen = packet_len = ATM_CELL_SIZE;
+ }
+ if (p->linktype == DLT_SUNATM) {
+ struct sunatm_hdr *sunatm = (struct sunatm_hdr *)dp;
+ unsigned long rawatm;
+
+ rawatm = ntohl(*((unsigned long *)dp));
+ sunatm->vci = htons((rawatm >> 4) & 0xffff);
+ sunatm->vpi = (rawatm >> 20) & 0x00ff;
+ sunatm->flags = ((header->flags.iface & 1) ? 0x80 : 0x00) |
+ ((sunatm->vpi == 0 && sunatm->vci == htons(5)) ? 6 :
+ ((sunatm->vpi == 0 && sunatm->vci == htons(16)) ? 5 :
+ ((dp[ATM_HDR_SIZE] == 0xaa &&
+ dp[ATM_HDR_SIZE+1] == 0xaa &&
+ dp[ATM_HDR_SIZE+2] == 0x03) ? 2 : 1)));
+
+ } else if (p->linktype == DLT_ATM_RFC1483) {
+ packet_len -= ATM_HDR_SIZE;
+ caplen -= ATM_HDR_SIZE;
+ dp += ATM_HDR_SIZE;
+ } else
+ continue;
+ break;
+
+ case ERF_TYPE_COLOR_HASH_ETH:
+ case ERF_TYPE_DSM_COLOR_ETH:
+ case ERF_TYPE_COLOR_ETH:
+ case ERF_TYPE_ETH:
+ if ((p->linktype != DLT_EN10MB) &&
+ (p->linktype != DLT_DOCSIS))
+ continue;
+ packet_len = ntohs(header->wlen);
+ packet_len -= (pd->dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size - 2;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ dp += 2;
+ break;
+
+ case ERF_TYPE_COLOR_HASH_POS:
+ case ERF_TYPE_DSM_COLOR_HDLC_POS:
+ case ERF_TYPE_COLOR_HDLC_POS:
+ case ERF_TYPE_HDLC_POS:
+ if ((p->linktype != DLT_CHDLC) &&
+ (p->linktype != DLT_PPP_SERIAL) &&
+ (p->linktype != DLT_FRELAY))
+ continue;
+ packet_len = ntohs(header->wlen);
+ packet_len -= (pd->dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ break;
+
+ case ERF_TYPE_COLOR_MC_HDLC_POS:
+ case ERF_TYPE_MC_HDLC:
+ if ((p->linktype != DLT_CHDLC) &&
+ (p->linktype != DLT_PPP_SERIAL) &&
+ (p->linktype != DLT_FRELAY) &&
+ (p->linktype != DLT_MTP2) &&
+ (p->linktype != DLT_MTP2_WITH_PHDR) &&
+ (p->linktype != DLT_LAPD))
+ continue;
+ packet_len = ntohs(header->wlen);
+ packet_len -= (pd->dag_fcs_bits >> 3);
+ caplen = rlen - dag_record_size - 4;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ /* jump the MC_HDLC_HEADER */
+ dp += 4;
+#ifdef DLT_MTP2_WITH_PHDR
+ if (p->linktype == DLT_MTP2_WITH_PHDR) {
+ /* Add the MTP2 Pseudo Header */
+ caplen += MTP2_HDR_LEN;
+ packet_len += MTP2_HDR_LEN;
+
+ TempPkt[MTP2_SENT_OFFSET] = 0;
+ TempPkt[MTP2_ANNEX_A_USED_OFFSET] = MTP2_ANNEX_A_USED_UNKNOWN;
+ *(TempPkt+MTP2_LINK_NUMBER_OFFSET) = ((header->rec.mc_hdlc.mc_header>>16)&0x01);
+ *(TempPkt+MTP2_LINK_NUMBER_OFFSET+1) = ((header->rec.mc_hdlc.mc_header>>24)&0xff);
+ memcpy(TempPkt+MTP2_HDR_LEN, dp, caplen);
+ dp = TempPkt;
+ }
+#endif
+ break;
+
+ case ERF_TYPE_IPV4:
+ if ((p->linktype != DLT_RAW) &&
+ (p->linktype != DLT_IPV4))
+ continue;
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ break;
+
+ case ERF_TYPE_IPV6:
+ if ((p->linktype != DLT_RAW) &&
+ (p->linktype != DLT_IPV6))
+ continue;
+ packet_len = ntohs(header->wlen);
+ caplen = rlen - dag_record_size;
+ /* Skip over extension headers */
+ caplen -= (8 * num_ext_hdr);
+ if (caplen > packet_len) {
+ caplen = packet_len;
+ }
+ break;
+
+ /* These types have no matching 'native' DLT, but can be used with DLT_ERF above */
+ case ERF_TYPE_MC_RAW:
+ case ERF_TYPE_MC_RAW_CHANNEL:
+ case ERF_TYPE_IP_COUNTER:
+ case ERF_TYPE_TCP_FLOW_COUNTER:
+ case ERF_TYPE_INFINIBAND:
+ case ERF_TYPE_RAW_LINK:
+ case ERF_TYPE_INFINIBAND_LINK:
+ default:
+ /* Unhandled ERF type.
+ * Ignore rather than generating error
+ */
+ continue;
+ } /* switch type */
+
+ } /* ERF encapsulation */
+
+ if (caplen > p->snapshot)
+ caplen = p->snapshot;
+
+ /* Run the packet filter if there is one. */
+ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
+
+ /* convert between timestamp formats */
+ register unsigned long long ts;
+
+ if (IS_BIGENDIAN()) {
+ ts = SWAPLL(header->ts);
+ } else {
+ ts = header->ts;
+ }
+
+ switch (p->opt.tstamp_precision) {
+ case PCAP_TSTAMP_PRECISION_NANO:
+ ticks_per_second = 1000000000;
+ break;
+ case PCAP_TSTAMP_PRECISION_MICRO:
+ default:
+ ticks_per_second = 1000000;
+ break;
+
+ }
+ pcap_header.ts.tv_sec = ts >> 32;
+ ts = (ts & 0xffffffffULL) * ticks_per_second;
+ ts += 0x80000000; /* rounding */
+ pcap_header.ts.tv_usec = ts >> 32;
+ if (pcap_header.ts.tv_usec >= ticks_per_second) {
+ pcap_header.ts.tv_usec -= ticks_per_second;
+ pcap_header.ts.tv_sec++;
+ }
+
+ /* Fill in our own header data */
+ pcap_header.caplen = caplen;
+ pcap_header.len = packet_len;
+
+ /* Count the packet. */
+ pd->stat.ps_recv++;
+
+ /* Call the user supplied callback function */
+ callback(user, &pcap_header, dp);
+
+ /* Only count packets that pass the filter, for consistency with standard Linux behaviour. */
+ processed++;
+ if (processed == cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
+ {
+ /* Reached the user-specified limit. */
+ return cnt;
+ }
+ }
+ }
+
+ return processed;
+}
+
+static int
+dag_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+ pcap_strlcpy(p->errbuf, "Sending packets isn't supported on DAG cards",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+
+/*
+ * Get a handle for a live capture from the given DAG device. Passing a NULL
+ * device will result in a failure. The promisc flag is ignored because DAG
+ * cards are always promiscuous. The to_ms parameter is used in setting the
+ * API polling parameters.
+ *
+ * snaplen is now also ignored, until we get per-stream slen support. Set
+ * slen with approprite DAG tool BEFORE pcap_activate().
+ *
+ * See also pcap(3).
+ */
+static int dag_activate(pcap_t* p)
+{
+ struct pcap_dag *pd = p->priv;
+ char *s;
+ int n;
+ daginf_t* daginf;
+ char * newDev = NULL;
+ char * device = p->opt.device;
+ int ret;
+ dag_size_t mindata;
+ struct timeval maxwait;
+ struct timeval poll;
+
+ if (device == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
+ return PCAP_ERROR;
+ }
+
+ /* Initialize some components of the pcap structure. */
+ newDev = (char *)malloc(strlen(device) + 16);
+ if (newDev == NULL) {
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't allocate string for device name");
+ goto fail;
+ }
+
+ /* Parse input name to get dag device and stream number if provided */
+ if (dag_parse_name(device, newDev, strlen(device) + 16, &pd->dag_stream) < 0) {
+ /*
+ * XXX - it'd be nice if this indicated what was wrong
+ * with the name. Does this reliably set errno?
+ * Should this return PCAP_ERROR_NO_SUCH_DEVICE in some
+ * cases?
+ */
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_parse_name");
+ goto fail;
+ }
+ device = newDev;
+
+ if (pd->dag_stream%2) {
+ ret = PCAP_ERROR;
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "dag_parse_name: tx (even numbered) streams not supported for capture");
+ goto fail;
+ }
+
+ /* setup device parameters */
+ if((pd->dag_ref = dag_config_init((char *)device)) == NULL) {
+ /*
+ * XXX - does this reliably set errno?
+ */
+ if (errno == ENOENT)
+ ret = PCAP_ERROR_NO_SUCH_DEVICE;
+ else if (errno == EPERM || errno == EACCES)
+ ret = PCAP_ERROR_PERM_DENIED;
+ else
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_config_init %s", device);
+ goto fail;
+ }
+
+ if((p->fd = dag_config_get_card_fd(pd->dag_ref)) < 0) {
+ /*
+ * XXX - does this reliably set errno?
+ */
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_config_get_card_fd %s", device);
+ goto failclose;
+ }
+
+ /* Open requested stream. Can fail if already locked or on error */
+ if (dag_attach_stream64(p->fd, pd->dag_stream, 0, 0) < 0) {
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_attach_stream");
+ goto failclose;
+ }
+
+ /* Try to find Stream Drop attribute */
+ pd->drop_attr = kNullAttributeUuid;
+ pd->dag_root = dag_config_get_root_component(pd->dag_ref);
+ if ( dag_component_get_subcomponent(pd->dag_root, kComponentStreamFeatures, 0) )
+ {
+ pd->drop_attr = dag_config_get_indexed_attribute_uuid(pd->dag_ref, kUint32AttributeStreamDropCount, pd->dag_stream/2);
+ }
+
+ /* Set up default poll parameters for stream
+ * Can be overridden by pcap_set_nonblock()
+ */
+ if (dag_get_stream_poll64(p->fd, pd->dag_stream,
+ &mindata, &maxwait, &poll) < 0) {
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_get_stream_poll");
+ goto faildetach;
+ }
+
+ /* Use the poll time as the required select timeout for callers
+ * who are using select()/etc. in an event loop waiting for
+ * packets to arrive.
+ */
+ pd->required_select_timeout = poll;
+ p->required_select_timeout = &pd->required_select_timeout;
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ if (p->opt.immediate) {
+ /* Call callback immediately.
+ * XXX - is this the right way to p this?
+ */
+ mindata = 0;
+ } else {
+ /* Amount of data to collect in Bytes before calling callbacks.
+ * Important for efficiency, but can introduce latency
+ * at low packet rates if to_ms not set!
+ */
+ mindata = 65536;
+ }
+
+ /* Obey opt.timeout (was to_ms) if supplied. This is a good idea!
+ * Recommend 10-100ms. Calls will time out even if no data arrived.
+ */
+ maxwait.tv_sec = p->opt.timeout/1000;
+ maxwait.tv_usec = (p->opt.timeout%1000) * 1000;
+
+ if (dag_set_stream_poll64(p->fd, pd->dag_stream,
+ mindata, &maxwait, &poll) < 0) {
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_set_stream_poll");
+ goto faildetach;
+ }
+
+ /* XXX Not calling dag_configure() to set slen; this is unsafe in
+ * multi-stream environments as the gpp config is global.
+ * Once the firmware provides 'per-stream slen' this can be supported
+ * again via the Config API without side-effects */
+#if 0
+ /* set the card snap length to the specified snaplen parameter */
+ /* This is a really bad idea, as different cards have different
+ * valid slen ranges. Should fix in Config API. */
+ if (p->snapshot == 0 || p->snapshot > MAX_DAG_SNAPLEN) {
+ p->snapshot = MAX_DAG_SNAPLEN;
+ } else if (snaplen < MIN_DAG_SNAPLEN) {
+ p->snapshot = MIN_DAG_SNAPLEN;
+ }
+ /* snap len has to be a multiple of 4 */
+#endif
+
+ if(dag_start_stream(p->fd, pd->dag_stream) < 0) {
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_start_stream %s", device);
+ goto faildetach;
+ }
+
+ /*
+ * Important! You have to ensure bottom is properly
+ * initialized to zero on startup, it won't give you
+ * a compiler warning if you make this mistake!
+ */
+ pd->dag_mem_bottom = 0;
+ pd->dag_mem_top = 0;
+
+ /*
+ * Find out how many FCS bits we should strip.
+ * First, query the card to see if it strips the FCS.
+ */
+ daginf = dag_info(p->fd);
+ if ((0x4200 == daginf->device_code) || (0x4230 == daginf->device_code)) {
+ /* DAG 4.2S and 4.23S already strip the FCS. Stripping the final word again truncates the packet. */
+ pd->dag_fcs_bits = 0;
+
+ /* Note that no FCS will be supplied. */
+ p->linktype_ext = LT_FCS_DATALINK_EXT(0);
+ } else {
+ /*
+ * Start out assuming it's 32 bits.
+ */
+ pd->dag_fcs_bits = 32;
+
+ /* Allow an environment variable to override. */
+ if ((s = getenv("ERF_FCS_BITS")) != NULL) {
+ if ((n = atoi(s)) == 0 || n == 16 || n == 32) {
+ pd->dag_fcs_bits = n;
+ } else {
+ ret = PCAP_ERROR;
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "pcap_activate %s: bad ERF_FCS_BITS value (%d) in environment", device, n);
+ goto failstop;
+ }
+ }
+
+ /*
+ * Did the user request that they not be stripped?
+ */
+ if ((s = getenv("ERF_DONT_STRIP_FCS")) != NULL) {
+ /* Yes. Note the number of bytes that will be
+ supplied. */
+ p->linktype_ext = LT_FCS_DATALINK_EXT(pd->dag_fcs_bits/16);
+
+ /* And don't strip them. */
+ pd->dag_fcs_bits = 0;
+ }
+ }
+
+ pd->dag_timeout = p->opt.timeout;
+
+ p->linktype = -1;
+ if (dag_get_datalink(p) < 0) {
+ ret = PCAP_ERROR;
+ goto failstop;
+ }
+
+ p->bufsize = 0;
+
+ if (new_pcap_dag(p) < 0) {
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "new_pcap_dag %s", device);
+ goto failstop;
+ }
+
+ /*
+ * "select()" and "poll()" don't work on DAG device descriptors.
+ */
+ p->selectable_fd = -1;
+
+ if (newDev != NULL) {
+ free((char *)newDev);
+ }
+
+ p->read_op = dag_read;
+ p->inject_op = dag_inject;
+ p->setfilter_op = dag_setfilter;
+ p->setdirection_op = NULL; /* Not implemented.*/
+ p->set_datalink_op = dag_set_datalink;
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = dag_setnonblock;
+ p->stats_op = dag_stats;
+ p->cleanup_op = dag_platform_cleanup;
+ pd->stat.ps_drop = 0;
+ pd->stat.ps_recv = 0;
+ pd->stat.ps_ifdrop = 0;
+ return 0;
+
+failstop:
+ if (dag_stop_stream(p->fd, pd->dag_stream) < 0) {
+ fprintf(stderr,"dag_stop_stream: %s\n", strerror(errno));
+ }
+
+faildetach:
+ if (dag_detach_stream(p->fd, pd->dag_stream) < 0)
+ fprintf(stderr,"dag_detach_stream: %s\n", strerror(errno));
+
+failclose:
+ dag_config_dispose(pd->dag_ref);
+ /*
+ * Note: we don't need to call close(p->fd) or dag_close(p->fd),
+ * as dag_config_dispose(pd->dag_ref) does this.
+ *
+ * Set p->fd to -1 to make sure that's not done.
+ */
+ p->fd = -1;
+ pd->dag_ref = NULL;
+ delete_pcap_dag(p);
+
+fail:
+ pcap_cleanup_live_common(p);
+ if (newDev != NULL) {
+ free((char *)newDev);
+ }
+
+ return ret;
+}
+
+pcap_t *dag_create(const char *device, char *ebuf, int *is_ours)
+{
+ const char *cp;
+ char *cpend;
+ long devnum;
+ pcap_t *p;
+ long stream = 0;
+
+ /* Does this look like a DAG device? */
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+ /* Does it begin with "dag"? */
+ if (strncmp(cp, "dag", 3) != 0) {
+ /* Nope, doesn't begin with "dag" */
+ *is_ours = 0;
+ return NULL;
+ }
+ /* Yes - is "dag" followed by a number from 0 to DAG_MAX_BOARDS-1 */
+ cp += 3;
+ devnum = strtol(cp, &cpend, 10);
+ if (*cpend == ':') {
+ /* Followed by a stream number. */
+ stream = strtol(++cpend, &cpend, 10);
+ }
+
+ if (cpend == cp || *cpend != '\0') {
+ /* Not followed by a number. */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ if (devnum < 0 || devnum >= DAG_MAX_BOARDS) {
+ /* Followed by a non-valid number. */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ if (stream <0 || stream >= DAG_STREAM_MAX) {
+ /* Followed by a non-valid stream number. */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dag));
+ if (p == NULL)
+ return NULL;
+
+ p->activate_op = dag_activate;
+
+ /*
+ * We claim that we support microsecond and nanosecond time
+ * stamps.
+ *
+ * XXX Our native precision is 2^-32s, but libpcap doesn't support
+ * power of two precisions yet. We can convert to either MICRO or NANO.
+ */
+ p->tstamp_precision_count = 2;
+ p->tstamp_precision_list = malloc(2 * sizeof(u_int));
+ if (p->tstamp_precision_list == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ pcap_close(p);
+ return NULL;
+ }
+ p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+ p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+ return p;
+}
+
+static int
+dag_stats(pcap_t *p, struct pcap_stat *ps) {
+ struct pcap_dag *pd = p->priv;
+ uint32_t stream_drop;
+ dag_err_t dag_error;
+
+ /*
+ * Packet records received (ps_recv) are counted in dag_read().
+ * Packet records dropped (ps_drop) are read from Stream Drop attribute if present,
+ * otherwise integrate the ERF Header lctr counts (if available) in dag_read().
+ * We are reporting that no records are dropped by the card/driver (ps_ifdrop).
+ */
+
+ if(pd->drop_attr != kNullAttributeUuid) {
+ /* Note this counter is cleared at start of capture and will wrap at UINT_MAX.
+ * The application is responsible for polling ps_drop frequently enough
+ * to detect each wrap and integrate total drop with a wider counter */
+ if ((dag_error = dag_config_get_uint32_attribute_ex(pd->dag_ref, pd->drop_attr, &stream_drop) == kDagErrNone)) {
+ pd->stat.ps_drop = stream_drop;
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "reading stream drop attribute: %s",
+ dag_config_strerror(dag_error));
+ return -1;
+ }
+ }
+
+ *ps = pd->stat;
+
+ return 0;
+}
+
+/*
+ * Add all DAG devices.
+ */
+int
+dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ char name[12]; /* XXX - pick a size */
+ int c;
+ char dagname[DAGNAME_BUFSIZE];
+ int dagstream;
+ int dagfd;
+ dag_card_inf_t *inf;
+ char *description;
+ int stream, rxstreams;
+
+ /* Try all the DAGs 0-DAG_MAX_BOARDS */
+ for (c = 0; c < DAG_MAX_BOARDS; c++) {
+ pcap_snprintf(name, 12, "dag%d", c);
+ if (-1 == dag_parse_name(name, dagname, DAGNAME_BUFSIZE, &dagstream))
+ {
+ (void) pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "dag: device name %s can't be parsed", name);
+ return (-1);
+ }
+ if ( (dagfd = dag_open(dagname)) >= 0 ) {
+ description = NULL;
+ if ((inf = dag_pciinfo(dagfd)))
+ description = dag_device_name(inf->device_code, 1);
+ /*
+ * XXX - is there a way to determine whether
+ * the card is plugged into a network or not?
+ * If so, we should check that and set
+ * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+ * PCAP_IF_CONNECTION_STATUS_DISCONNECTED.
+ *
+ * Also, are there notions of "up" and "running"?
+ */
+ if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
+ /*
+ * Failure.
+ */
+ return (-1);
+ }
+ rxstreams = dag_rx_get_stream_count(dagfd);
+ for(stream=0;stream<DAG_STREAM_MAX;stream+=2) {
+ if (0 == dag_attach_stream64(dagfd, stream, 0, 0)) {
+ dag_detach_stream(dagfd, stream);
+
+ pcap_snprintf(name, 10, "dag%d:%d", c, stream);
+ if (add_dev(devlistp, name, 0, description, errbuf) == NULL) {
+ /*
+ * Failure.
+ */
+ return (-1);
+ }
+
+ rxstreams--;
+ if(rxstreams <= 0) {
+ break;
+ }
+ }
+ }
+ dag_close(dagfd);
+ }
+
+ }
+ return (0);
+}
+
+/*
+ * Installs the given bpf filter program in the given pcap structure. There is
+ * no attempt to store the filter in kernel memory as that is not supported
+ * with DAG cards.
+ */
+static int
+dag_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+ if (!p)
+ return -1;
+ if (!fp) {
+ strncpy(p->errbuf, "setfilter: No filter specified",
+ sizeof(p->errbuf));
+ return -1;
+ }
+
+ /* Make our private copy of the filter */
+
+ if (install_bpf_program(p, fp) < 0)
+ return -1;
+
+ return (0);
+}
+
+static int
+dag_set_datalink(pcap_t *p, int dlt)
+{
+ p->linktype = dlt;
+
+ return (0);
+}
+
+static int
+dag_setnonblock(pcap_t *p, int nonblock)
+{
+ struct pcap_dag *pd = p->priv;
+ dag_size_t mindata;
+ struct timeval maxwait;
+ struct timeval poll;
+
+ /*
+ * Set non-blocking mode on the FD.
+ * XXX - is that necessary? If not, don't bother calling it,
+ * and have a "dag_getnonblock()" function that looks at
+ * "pd->dag_flags".
+ */
+ if (pcap_setnonblock_fd(p, nonblock) < 0)
+ return (-1);
+
+ if (dag_get_stream_poll64(p->fd, pd->dag_stream,
+ &mindata, &maxwait, &poll) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_get_stream_poll");
+ return -1;
+ }
+
+ /* Amount of data to collect in Bytes before calling callbacks.
+ * Important for efficiency, but can introduce latency
+ * at low packet rates if to_ms not set!
+ */
+ if(nonblock)
+ mindata = 0;
+ else
+ mindata = 65536;
+
+ if (dag_set_stream_poll64(p->fd, pd->dag_stream,
+ mindata, &maxwait, &poll) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "dag_set_stream_poll");
+ return -1;
+ }
+
+ if (nonblock) {
+ pd->dag_flags |= DAGF_NONBLOCK;
+ } else {
+ pd->dag_flags &= ~DAGF_NONBLOCK;
+ }
+ return (0);
+}
+
+static int
+dag_get_datalink(pcap_t *p)
+{
+ struct pcap_dag *pd = p->priv;
+ int index=0, dlt_index=0;
+ uint8_t types[255];
+
+ memset(types, 0, 255);
+
+ if (p->dlt_list == NULL && (p->dlt_list = malloc(255*sizeof(*(p->dlt_list)))) == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "malloc");
+ return (-1);
+ }
+
+ p->linktype = 0;
+
+#ifdef HAVE_DAG_GET_STREAM_ERF_TYPES
+ /* Get list of possible ERF types for this card */
+ if (dag_get_stream_erf_types(p->fd, pd->dag_stream, types, 255) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "dag_get_stream_erf_types");
+ return (-1);
+ }
+
+ while (types[index]) {
+
+#elif defined HAVE_DAG_GET_ERF_TYPES
+ /* Get list of possible ERF types for this card */
+ if (dag_get_erf_types(p->fd, types, 255) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "dag_get_erf_types");
+ return (-1);
+ }
+
+ while (types[index]) {
+#else
+ /* Check the type through a dagapi call. */
+ types[index] = dag_linktype(p->fd);
+
+ {
+#endif
+ switch((types[index] & 0x7f)) {
+
+ case ERF_TYPE_HDLC_POS:
+ case ERF_TYPE_COLOR_HDLC_POS:
+ case ERF_TYPE_DSM_COLOR_HDLC_POS:
+ case ERF_TYPE_COLOR_HASH_POS:
+
+ if (p->dlt_list != NULL) {
+ p->dlt_list[dlt_index++] = DLT_CHDLC;
+ p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
+ p->dlt_list[dlt_index++] = DLT_FRELAY;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_CHDLC;
+ break;
+
+ case ERF_TYPE_ETH:
+ case ERF_TYPE_COLOR_ETH:
+ case ERF_TYPE_DSM_COLOR_ETH:
+ case ERF_TYPE_COLOR_HASH_ETH:
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[dlt_index++] = DLT_EN10MB;
+ p->dlt_list[dlt_index++] = DLT_DOCSIS;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_EN10MB;
+ break;
+
+ case ERF_TYPE_ATM:
+ case ERF_TYPE_AAL5:
+ case ERF_TYPE_MC_ATM:
+ case ERF_TYPE_MC_AAL5:
+ if (p->dlt_list != NULL) {
+ p->dlt_list[dlt_index++] = DLT_ATM_RFC1483;
+ p->dlt_list[dlt_index++] = DLT_SUNATM;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_ATM_RFC1483;
+ break;
+
+ case ERF_TYPE_COLOR_MC_HDLC_POS:
+ case ERF_TYPE_MC_HDLC:
+ if (p->dlt_list != NULL) {
+ p->dlt_list[dlt_index++] = DLT_CHDLC;
+ p->dlt_list[dlt_index++] = DLT_PPP_SERIAL;
+ p->dlt_list[dlt_index++] = DLT_FRELAY;
+ p->dlt_list[dlt_index++] = DLT_MTP2;
+ p->dlt_list[dlt_index++] = DLT_MTP2_WITH_PHDR;
+ p->dlt_list[dlt_index++] = DLT_LAPD;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_CHDLC;
+ break;
+
+ case ERF_TYPE_IPV4:
+ if (p->dlt_list != NULL) {
+ p->dlt_list[dlt_index++] = DLT_RAW;
+ p->dlt_list[dlt_index++] = DLT_IPV4;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_RAW;
+ break;
+
+ case ERF_TYPE_IPV6:
+ if (p->dlt_list != NULL) {
+ p->dlt_list[dlt_index++] = DLT_RAW;
+ p->dlt_list[dlt_index++] = DLT_IPV6;
+ }
+ if(!p->linktype)
+ p->linktype = DLT_RAW;
+ break;
+
+ case ERF_TYPE_LEGACY:
+ case ERF_TYPE_MC_RAW:
+ case ERF_TYPE_MC_RAW_CHANNEL:
+ case ERF_TYPE_IP_COUNTER:
+ case ERF_TYPE_TCP_FLOW_COUNTER:
+ case ERF_TYPE_INFINIBAND:
+ case ERF_TYPE_RAW_LINK:
+ case ERF_TYPE_INFINIBAND_LINK:
+ case ERF_TYPE_META:
+ default:
+ /* Libpcap cannot deal with these types yet */
+ /* Add no 'native' DLTs, but still covered by DLT_ERF */
+ break;
+
+ } /* switch */
+ index++;
+ }
+
+ p->dlt_list[dlt_index++] = DLT_ERF;
+
+ p->dlt_count = dlt_index;
+
+ if(!p->linktype)
+ p->linktype = DLT_ERF;
+
+ return p->linktype;
+}
+
+#ifdef DAG_ONLY
+/*
+ * This libpcap build supports only DAG cards, not regular network
+ * interfaces.
+ */
+
+/*
+ * There are no regular interfaces, just DAG interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf)
+{
+ return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "This version of libpcap only supports DAG cards");
+ return NULL;
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING " (DAG-only)");
+}
+#endif
diff --git a/lib/libpcap/libpcap/pcap-dag.h b/lib/libpcap/libpcap/pcap-dag.h
new file mode 100644
index 0000000..67361af
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dag.h
@@ -0,0 +1,12 @@
+/*
+ * pcap-dag.c: Packet capture interface for Endace DAG card.
+ *
+ * The functionality of this code attempts to mimic that of pcap-linux as much
+ * as possible. This code is only needed when compiling in the DAG card code
+ * at the same time as another type of device.
+ *
+ * Author: Richard Littin, Sean Irvine ({richard,sean}@reeltwo.com)
+ */
+
+pcap_t *dag_create(const char *, char *, int *);
+int dag_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/lib/libpcap/libpcap/pcap-darwin.c b/lib/libpcap/libpcap/pcap-darwin.c
new file mode 100644
index 0000000..1a13966
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-darwin.c
@@ -0,0 +1,1428 @@
+/*
+ * Copyright (c) 2013-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/*
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
+ * native OS version, as we need "struct bpf_config" from it.
+ */
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+
+#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/ioctl.h>
+#include <sys/kern_event.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <net/bpf.h>
+#include <net/pktap.h>
+#include <net/iptap.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <libproc.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <assert.h>
+
+#include "pcap-int.h"
+#include "pcap-util.h"
+#include "pcap-pktap.h"
+
+static int pcap_cleanup_pktap_interface_internal(const char *ifname, char *ebuf);
+
+/*
+ * We append the procname + PID to the description
+ */
+#define AUTO_CLONE_IF_DESCRIPTION "libpcap auto cloned device"
+#define AUTO_CLONE_IF_DESC_LEN (sizeof(AUTO_CLONE_IF_DESCRIPTION) -1)
+
+#define _CASSERT(x) _Static_assert(x, "compile-time assertion failed " #x)
+
+_CASSERT(offsetof(struct bpf_hdr_ext, bh_tstamp) == offsetof(struct bpf_hdr, bh_tstamp));
+_CASSERT(offsetof(struct bpf_hdr_ext, bh_caplen) == offsetof(struct bpf_hdr, bh_caplen));
+_CASSERT(offsetof(struct bpf_hdr_ext, bh_datalen) == offsetof(struct bpf_hdr, bh_datalen));
+_CASSERT(offsetof(struct bpf_hdr_ext, bh_hdrlen) == offsetof(struct bpf_hdr, bh_hdrlen));
+_CASSERT(MAXIMUM_SNAPLEN == BPF_MAXBUFSIZE);
+
+
+static int
+pcap_get_if_attach_count(const char *ifname, char *errbuf)
+{
+ int fd;
+ int n = 0;
+ char device[sizeof "/dev/bpf0000000000"];
+ struct ifreq ifr;
+ int count = -1;
+
+ /*
+ * Find an available device
+ */
+ do {
+ (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++);
+
+ fd = open(device, O_RDONLY);
+ } while (fd < 0 && errno == EBUSY);
+
+ if (fd >= 0) {
+ bzero(&ifr, sizeof(ifr));
+
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (ioctl(fd, BIOCGIFATTACHCOUNT, &ifr) == -1) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "ioctl BIOCGIFATTACHCOUNT %s failed - %s",
+ ifname, strerror(errno));
+ } else {
+ count = ifr.ifr_intval;
+ }
+ close(fd);
+ }
+ return (count);
+}
+
+static int
+pcap_cleanup_pktap_interface_internal(const char *ifname, char *ebuf)
+{
+ int s = -1;
+ struct if_descreq if_descreq;
+ struct ifreq ifr;
+ int status = 0;
+
+ /*
+ * Destroy the pktap instance we created
+ */
+ if (ifname != NULL) {
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s == -1) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: socket failed - %s",
+ __func__, strerror(errno));
+ goto failed;
+ } else {
+ /*
+ * Verify it's been cloned by libpcap
+ */
+ bzero(&if_descreq, sizeof(struct if_descreq));
+ strlcpy(if_descreq.ifdr_name, ifname, sizeof(if_descreq.ifdr_name));
+ if (ioctl(s, SIOCGIFDESC, &if_descreq) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: ioctl SIOCGIFDESC %s - %s",
+ __func__, ifname, strerror(errno));
+ goto failed;
+ }
+ if (if_descreq.ifdr_len == 0) {
+ goto done;
+ }
+ if (strncmp((char *)if_descreq.ifdr_desc, AUTO_CLONE_IF_DESCRIPTION,
+ AUTO_CLONE_IF_DESC_LEN) != 0) {
+ goto done;
+ }
+ /*
+ * Verify the interface is not already attached to another BPF
+ * (and yes, there's a race with this kind of check)
+ */
+ if (pcap_get_if_attach_count(ifname, ebuf) != 1) {
+ goto done;
+ }
+ /*
+ * Now we assume it's ours
+ */
+ bzero(&ifr, sizeof(struct ifreq));
+ strlcpy(ifr.ifr_name, ifname, sizeof (ifr.ifr_name));
+ if (ioctl(s, SIOCIFDESTROY, &ifr) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: ioctl(SIOCIFDESTROY) fail - %s",
+ __func__, strerror(errno));
+ goto failed;
+ }
+ }
+ }
+done:
+ if (s != -1) {
+ close(s);
+ }
+ return (status);
+failed:
+ status = -1;
+ goto done;
+}
+
+void
+pcap_cleanup_pktap_interface(const char *ifname)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ if (pcap_cleanup_pktap_interface_internal(ifname, errbuf) != 0) {
+ fprintf(stderr, "%s\n", errbuf);
+ }
+}
+
+
+char *
+pcap_setup_pktap_interface(const char *device, char *ebuf)
+{
+ struct ifreq ifr;
+ int s = -1;
+ struct if_nameindex *ifnameindices = NULL, *ifnameindex;
+ int foundmatch = 0;
+ struct if_descreq if_descreq;
+ char *pktap_param = NULL;
+ int unit = -1;
+ const char *if_prefix = NULL;
+ char *ifname = NULL;
+
+ ifname = calloc(1, PKTAP_IFXNAMESIZE);
+ if (ifname == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc(): %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s == -1) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket(): %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+
+ /*
+ * Use a pktap interface to tap on multiple physical interfaces
+ */
+ if (strncmp(device, PKTAP_IFNAME, strlen(PKTAP_IFNAME)) == 0) {
+ size_t tocopy;
+
+ if_prefix = PKTAP_IFNAME;
+ /*
+ * The comma marks the optional paramaters
+ */
+ pktap_param = strchr(device, ',');
+
+ /*
+ * Copy the interface name
+ */
+ if (pktap_param != NULL)
+ tocopy = pktap_param - device;
+ else
+ tocopy = strlen(device);
+ if (tocopy + 1 > PKTAP_IFXNAMESIZE) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "device name too long: %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+ bcopy(device, ifname, tocopy);
+ ifname[tocopy] = 0;
+
+ /*
+ * Create a device instance when no unit number is specified
+ */
+ sscanf(ifname, PKTAP_IFNAME "%d", &unit);
+ } else if (strcmp(device, "all") == 0 || strcmp(device, "any") == 0) {
+ if_prefix = PKTAP_IFNAME;
+ pktap_param = "all";
+ unit = -1;
+ } else if (strncmp(device, IPTAP_IFNAME, strlen(IPTAP_IFNAME)) == 0) {
+ if_prefix = IPTAP_IFNAME;
+
+ /*
+ * Copy the interface name
+ */
+ if (strlcpy(ifname, device, PKTAP_IFXNAMESIZE) >= PKTAP_IFXNAMESIZE) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "device name too long: %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+ /*
+ * Create a device instance when no unit number is specified
+ */
+ sscanf(ifname, IPTAP_IFNAME "%d", &unit);
+ } else {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "bad device name: %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+
+ if (unit == -1) {
+ int desclen;
+
+ /*
+ * Check if there is a pktap that was created by libpcap as it was
+ * most likely leaked by a previous crash
+ */
+ if ((ifnameindices = if_nameindex()) == NULL) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "if_nameindex: %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+ for (ifnameindex = ifnameindices; ifnameindex->if_index != 0; ifnameindex++) {
+ if (strncmp(ifnameindex->if_name, if_prefix, strlen(if_prefix)) != 0)
+ continue;
+
+ bzero(&if_descreq, sizeof(struct if_descreq));
+ strlcpy(if_descreq.ifdr_name, ifnameindex->if_name, sizeof(if_descreq.ifdr_name));
+ if (ioctl(s, SIOCGIFDESC, &if_descreq) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "ioctl(SIOCGIFDESC): %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+
+ if (if_descreq.ifdr_len == 0)
+ continue;
+ if (strncmp((const char *)if_descreq.ifdr_desc, AUTO_CLONE_IF_DESCRIPTION,
+ AUTO_CLONE_IF_DESC_LEN) != 0)
+ continue;
+ /*
+ * Verify the interface is not already attached to another BPF
+ * (and yes, there's a race with this kind of check)
+ */
+ if (pcap_get_if_attach_count(ifnameindex->if_name, ebuf) != 0) {
+ /*
+ * Ignore the error
+ */
+ ebuf[0] = 0;
+ continue;
+ }
+ /*
+ * Keep the name of the matching interface around
+ */
+ strlcpy(ifname, ifnameindex->if_name, PKTAP_IFXNAMESIZE);
+
+ foundmatch = 1;
+ }
+
+ if (foundmatch == 0) {
+
+ /*
+ * We're creating a new instance of a pktap that should be destroyed
+ * before exiting
+ *
+ * Note: we may leak the interface when exiting abnormaly, by
+ * crashing or by not calling pcap_close()
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ (void) strlcpy(ifr.ifr_name, if_prefix, sizeof(ifr.ifr_name));
+ if (ioctl(s, SIOCIFCREATE, &ifr) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "ioctl(SIOCIFCREATE): %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+ snprintf(ifname, PKTAP_IFXNAMESIZE, "%s", ifr.ifr_name);
+ }
+
+ /*
+ * Mark the interface as being created by libpcap along with
+ * the current process name + pid
+ */
+ bzero(&if_descreq, sizeof(struct if_descreq));
+ strlcpy(if_descreq.ifdr_name, ifname, sizeof(if_descreq.ifdr_name));
+
+ desclen = snprintf((char *)if_descreq.ifdr_desc, sizeof (if_descreq.ifdr_desc),
+ "%s - %s.%d", AUTO_CLONE_IF_DESCRIPTION, getprogname(), getpid());
+ if (desclen < sizeof(if_descreq.ifdr_desc))
+ if_descreq.ifdr_len = desclen + 1;
+ else
+ if_descreq.ifdr_len = sizeof(if_descreq.ifdr_desc);
+
+ if (ioctl(s, SIOCSIFDESC, &if_descreq) < 0) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "ioctl(SIOCSIFDESC): %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+ }
+
+ if (pktap_param != NULL) {
+ int num_filter_entries = 0;
+ struct pktap_filter pktap_if_filter[PKTAP_MAX_FILTERS];
+
+ bzero(pktap_if_filter, sizeof(pktap_if_filter));
+
+ /*
+ * The comma separated parameters is a list of interfaces for
+ * pktap to filter on
+ */
+ while (*pktap_param != '\0') {
+ char *end_ptr;
+ struct pktap_filter entry;
+ size_t len;
+
+ /* This makes sure the strings are zero terminated */
+ bzero(&entry, sizeof(struct pktap_filter));
+
+ if (*pktap_param == ',') {
+ pktap_param++;
+ continue;
+ }
+ if (num_filter_entries >= PKTAP_MAX_FILTERS) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "Too many pktap parameters, max is %u", PKTAP_MAX_FILTERS);
+ goto fail;
+ }
+
+ end_ptr = strchr(pktap_param, ',');
+ if (end_ptr == NULL)
+ len = strlen(pktap_param);
+ else
+ len = end_ptr - pktap_param;
+
+ if (len > sizeof(entry.filter_param_if_name) - 1) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "Interface name too big for filter");
+ goto fail;
+ }
+
+ if (strcmp(pktap_param, "all") == 0 || strcmp(pktap_param, "any") == 0) {
+ entry.filter_op = PKTAP_FILTER_OP_PASS;
+ entry.filter_param = PKTAP_FILTER_PARAM_IF_TYPE;
+ entry.filter_param_if_type = 0;
+ } else {
+ entry.filter_op = PKTAP_FILTER_OP_PASS;
+ entry.filter_param = PKTAP_FILTER_PARAM_IF_NAME;
+ /*
+ * filter_param_if_name is not a zero terminated string so
+ * do not use strlcpy(3)
+ */
+ strncpy(entry.filter_param_if_name, pktap_param,
+ MIN(sizeof(entry.filter_param_if_name), len));
+ }
+ pktap_if_filter[num_filter_entries] = entry;
+ num_filter_entries++;
+ pktap_param += len;
+ }
+
+ if (num_filter_entries > 0) {
+ struct ifdrv ifdr;
+
+ bzero(&ifdr, sizeof(struct ifdrv));
+ snprintf(ifdr.ifd_name, sizeof(ifdr.ifd_name), "%s", ifname);
+ ifdr.ifd_cmd = PKTP_CMD_FILTER_SET;
+ ifdr.ifd_len = sizeof(pktap_if_filter);
+ ifdr.ifd_data = &pktap_if_filter[0];
+
+ if (ioctl(s, SIOCSDRVSPEC, &ifdr) == -1) {
+ snprintf(ebuf, PCAP_ERRBUF_SIZE, "ioctl(SIOCSDRVSPEC): %s",
+ pcap_strerror(errno));
+ goto fail;
+ }
+ }
+ }
+cleanup:
+ if (ifnameindices != NULL)
+ if_freenameindex(ifnameindices);
+ if (s != -1)
+ close(s);
+ return (ifname);
+
+fail:
+ if (ifname != NULL) {
+ free(ifname);
+ ifname = NULL;
+ }
+ goto cleanup;;
+}
+
+void
+pktap_cleanup(pcap_t *p)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ if (p->cleanup_interface_op != NULL)
+ p->cleanup_interface_op(p->opt.device, errbuf);
+
+ p->pktap_cleanup_op(p);
+}
+
+int
+pktap_activate(pcap_t *p)
+{
+ int status = 0;
+
+ free(p->opt.device);
+ p->opt.device = p->pktap_ifname;
+ p->pktap_ifname = NULL;
+
+ /*
+ * Just like pcap_set_snaplen() turn invalid value into the max value
+ * The snapshot must be adjusted before calling the actual callback
+ */
+ if (p->snapshot < sizeof(struct pktap_header)) {
+ p->snapshot = MAXIMUM_SNAPLEN;
+ }
+
+ status = p->pktap_activate_op(p);
+ if (status != 0)
+ return (status);
+
+ p->pktap_cleanup_op = p->cleanup_op;
+ p->cleanup_op = pktap_cleanup;
+
+ return (status);
+}
+
+pcap_t *
+pktap_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *p = NULL;
+ char *ifname = NULL;
+
+ /*
+ * By default, when device is NULL, we use a pktap
+ * to capture on physical interfaces (exclude loopback and
+ * virtual and tunner interfaces).
+ *
+ * To capture on all interfaces, device can be either "any",
+ * or "all" or even "pktap,all"
+ */
+ if (device == NULL)
+ device = "pktap";
+ if (strncmp(device, PKTAP_IFNAME, strlen(PKTAP_IFNAME)) != 0 &&
+ strncmp(device, IPTAP_IFNAME, strlen(IPTAP_IFNAME)) != 0 &&
+ strcmp(device, "all") != 0 &&
+ strcmp(device, "any") != 0) {
+ *is_ours = 0;
+ return (NULL);
+ }
+ *is_ours = 1;
+
+ /*
+ * Create a regular BPF network interface.
+ */
+ p = pcap_create_interface(ebuf, 0);
+ if (p == NULL)
+ goto failed;
+
+ ifname = pcap_setup_pktap_interface(device, ebuf);
+ if (ifname == NULL)
+ goto failed;
+ p->pktap_ifname = ifname;
+ p->cleanup_interface_op = pcap_cleanup_pktap_interface_internal;
+
+ p->pktap_activate_op = p->activate_op;
+ p->activate_op = pktap_activate;
+
+
+ return (p);
+
+failed:
+ if (p != NULL)
+ pcap_close(p);
+ if (ifname != NULL)
+ pcap_cleanup_pktap_interface_internal(ifname, ebuf);
+
+ return (NULL);
+}
+
+/*
+ * Returns zero if the packet doesn't match, non-zero if it matches
+ */
+static int
+pcap_filter_pktap(pcap_t *pcap, pcap_dumper_t *dumper, struct pcap_if_info *if_info,
+ const struct pcap_pkthdr *h, const u_char *sp)
+{
+ struct pktap_header *pktp_hdr;
+ const u_char *pkt_data;
+ int match = 0;
+
+ pktp_hdr = (struct pktap_header *)sp;
+
+ if (h->len < sizeof(struct pktap_header) ||
+ h->caplen < sizeof(struct pktap_header) ||
+ pktp_hdr->pth_length > h->caplen) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Packet too short", __func__);
+ return (0);
+ }
+
+ if (if_info == NULL) {
+ if_info = pcap_if_info_set_find_by_name(&dumper->dump_if_info_set, pktp_hdr->pth_ifname);
+ /*
+ * New interface
+ */
+ if (if_info == NULL) {
+ if_info = pcap_if_info_set_add(&dumper->dump_if_info_set, pktp_hdr->pth_ifname, -1,
+ pktp_hdr->pth_dlt, pcap->snapshot,
+ pcap->filter_str, pcap->errbuf);
+ if (if_info == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_add_if_info(%s) failed",
+ __func__, pktp_hdr->pth_ifname);
+ return (0);
+ }
+ }
+ }
+
+ if (if_info->if_filter_program.bf_insns == NULL)
+ match = 1;
+ else {
+ /*
+ * The actual data packet is past the packet tap header
+ */
+ struct pcap_pkthdr tmp_hdr;
+
+ bcopy(h, &tmp_hdr, sizeof(struct pcap_pkthdr));
+
+ tmp_hdr.caplen -= pktp_hdr->pth_length;
+ tmp_hdr.len -= pktp_hdr->pth_length;
+
+ pkt_data = sp + pktp_hdr->pth_length;
+
+ match = pcap_offline_filter(&if_info->if_filter_program, &tmp_hdr, pkt_data);
+
+ }
+
+ return (match);
+}
+
+/*
+ * Add a section header block when needed
+ */
+static int
+pcapng_dump_shb(pcap_t *pcap, pcap_dumper_t *dumper)
+{
+ pcapng_block_t block = NULL;
+ int retval;
+ static struct utsname utsname;
+ static struct proc_bsdshortinfo bsdinfo;
+ static int info_done = 0;
+
+ if (info_done == 0) {
+ if (uname(&utsname) == -1) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: uname() failed", __func__);
+ return (0);
+ }
+ if (proc_pidinfo(getpid(), PROC_PIDT_SHORTBSDINFO, 1, &bsdinfo, sizeof(bsdinfo)) < 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: proc_pidinfo(PROC_PIDT_SHORTBSDINFO) failed", __func__);
+ return (0);
+ }
+ info_done = 1;
+ }
+
+ if (dumper->dump_block == NULL) {
+ /*
+ * The snaplen represent the maximum length of the data so
+ * 4 KBytes should be more than enough to fit the block header, fields,
+ * options and trailer.
+ */
+ dumper->dump_block = pcap_ng_block_alloc(pcap->snapshot + 4096);
+ if (dumper->dump_block == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_alloc() failed ", __func__);
+ return (0);
+ }
+ }
+ block = dumper->dump_block;
+
+ if (pcap->shb_added == 0 || dumper->shb_added == 0) {
+
+ char buf[256];
+
+ retval = pcap_ng_block_reset(block, PCAPNG_BT_SHB);
+ if (retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_reset(PCAPNG_BT_SHB) failed", __func__);
+ return (0);
+ }
+ retval = pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT,
+ "section header block");
+ if(retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_add_option_with_string(PCAPNG_OPT_COMMENT) failed", __func__);
+ return (0);
+ }
+
+ retval = pcap_ng_block_add_option_with_string(block, PCAPNG_SHB_HARDWARE,
+ utsname.machine);
+ if(retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_add_option_with_string(PCAPNG_SHB_HARDWARE) failed", __func__);
+ return (0);
+ }
+
+ snprintf(buf, sizeof(buf), "%s %s", utsname.sysname, utsname.release);
+ retval = pcap_ng_block_add_option_with_string(block, PCAPNG_SHB_OS, buf);
+ if(retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_add_option_with_string(PCAPNG_SHB_OS) failed", __func__);
+ return (0);
+ }
+
+ snprintf(buf, sizeof(buf), "%s (%s)", bsdinfo.pbsi_comm, pcap_lib_version());
+ retval = pcap_ng_block_add_option_with_string(block, PCAPNG_SHB_USERAPPL, buf);
+ if(retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_add_option_with_string(PCAPNG_SHB_USERAPPL) failed", __func__);
+ return (0);
+ }
+
+ (void) pcap_ng_dump_block(dumper, block);
+
+ pcap->shb_added = 1;
+ dumper->shb_added = 1;
+ }
+ return (1);
+}
+
+struct pcap_proc_info *
+pcap_ng_dump_proc_info(pcap_t *pcap, pcap_dumper_t *dumper, pcapng_block_t block,
+ struct pcap_proc_info *proc_info)
+{
+ int retval;
+ struct pcapng_process_information_fields *pib;
+
+ /*
+ * We're done when the process info block has already been saved
+ */
+ if (proc_info->proc_block_dumped != 0)
+ return (proc_info);
+
+ retval = pcap_ng_block_reset(block, PCAPNG_BT_PIB);
+ if (retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_reset(PCAPNG_BT_PIB) failed", __func__);
+ return (NULL);
+ }
+ pib = pcap_ng_get_process_information_fields(block);
+ pib->process_id = proc_info->proc_pid;
+
+ if (pcap_ng_block_add_option_with_string(block, PCAPNG_PIB_NAME, proc_info->proc_name) != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_add_option_with_string(PCAPNG_PIB_NAME, %s) failed",
+ __func__, proc_info->proc_name);
+ return (NULL);
+ }
+
+ if (uuid_is_null(proc_info->proc_uuid) == 0) {
+ if (pcap_ng_block_add_option_with_uuid(block, PCAPNG_PIB_UUID, proc_info->proc_uuid) != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_add_option_with_uuid(PCAPNG_PIB_UUID) failed",
+ __func__);
+ return (NULL);
+ }
+ }
+
+ (void) pcap_ng_dump_block(dumper, block);
+
+ proc_info->proc_block_dumped = 1;
+ proc_info->proc_dump_index = dumper->dump_proc_info_set.proc_dump_index++;
+
+ return (proc_info);
+}
+
+static struct pcap_proc_info *
+pcap_ng_dump_proc(pcap_t *pcap, pcap_dumper_t *dumper, pcapng_block_t block,
+ pid_t pid, const char *pcomm, const uuid_t uu)
+{
+ struct pcap_proc_info *proc_info;
+
+ /*
+ * Add a process info block if needed
+ */
+ proc_info = pcap_proc_info_set_find_uuid(&dumper->dump_proc_info_set, pid, pcomm, uu);
+ if (proc_info == NULL) {
+ proc_info = pcap_proc_info_set_add_uuid(&dumper->dump_proc_info_set, pid, pcomm,
+ uu, pcap->errbuf);
+ if (proc_info == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: allocate_proc_info(%s) failed",
+ __func__, pcomm);
+ return (NULL);
+ }
+ }
+
+ proc_info = pcap_ng_dump_proc_info(pcap, dumper, block, proc_info);
+
+ return (proc_info);
+}
+
+int
+pcap_ng_dump_kern_event(pcap_t *pcap, pcap_dumper_t *dumper,
+ struct kern_event_msg *kev, struct timeval *ts)
+{
+ int retval;
+ pcapng_block_t block = NULL;
+ struct pcapng_os_event_fields *osev_fields;
+
+ if (pcapng_dump_shb(pcap, dumper) == 0)
+ return (0);
+
+ block = dumper->dump_block;
+
+ retval = pcap_ng_block_reset(block, PCAPNG_BT_OSEV);
+ if (retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_reset(PCAPNG_BT_OSEV) failed", __func__);
+ return (0);
+ }
+ osev_fields = pcap_ng_get_os_event_fields(block);
+ osev_fields->type = PCAPNG_OSEV_KEV;
+ osev_fields->timestamp_high = (u_int32_t)ts->tv_sec;
+ osev_fields->timestamp_low = ts->tv_usec;
+ osev_fields->len = kev->total_size;
+ pcap_ng_block_packet_set_data(block, kev, kev->total_size);
+
+ (void) pcap_ng_dump_block(dumper, block);
+
+ return (1);
+}
+
+struct pcap_if_info *
+pcap_ng_dump_if_info(pcap_t *pcap, pcap_dumper_t *dumper, pcapng_block_t block,
+ struct pcap_if_info *if_info)
+{
+ int retval;
+ struct pcapng_interface_description_fields *idb = NULL;
+
+ /*
+ * We're done when the interface block has already been saved
+ */
+ if (if_info->if_block_dumped != 0) {
+ return (if_info);
+ }
+
+ retval = pcap_ng_block_reset(block, PCAPNG_BT_IDB);
+ if (retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_reset(PCAPNG_BT_IDB) failed", __func__);
+ return (0);
+ }
+ idb = pcap_ng_get_interface_description_fields(block);
+ idb->idb_linktype = dlt_to_linktype(if_info->if_linktype);
+ idb->idb_snaplen = if_info->if_snaplen;
+
+ if (pcap_ng_block_add_option_with_string(block, PCAPNG_IF_NAME,
+ if_info->if_name) != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_add_option_with_string(PCAPNG_IF_NAME, %s) failed",
+ __func__, if_info->if_name);
+ return (0);
+ }
+
+ (void) pcap_ng_dump_block(dumper, block);
+
+ if_info->if_block_dumped = 1;
+ if_info->if_dump_id = dumper->dump_if_info_set.if_dump_id++;
+
+ return (if_info);
+}
+
+/*
+ * To minimize memory allocation we use a single block object that
+ * we reuse by calling pcap_ng_block_reset()
+ */
+int
+pcap_ng_dump_pktap_comment(pcap_t *pcap, pcap_dumper_t *dumper,
+ const struct pcap_pkthdr *h, const u_char *sp,
+ const char *comment)
+{
+ pcapng_block_t block = NULL;
+ struct pktap_header *pktp_hdr;
+ const u_char *pkt_data;
+ struct pcap_if_info *if_info = NULL;
+ struct pcapng_enhanced_packet_fields *epb;
+ uint64_t ts;
+ struct pcap_proc_info *proc_info = NULL;
+ struct pcap_proc_info *e_proc_info = NULL;
+ uint32_t pktflags = 0;
+ uint32_t pmdflags = 0;
+ int retval;
+
+ pktp_hdr = (struct pktap_header *)sp;
+
+ if (h->len < sizeof(struct pktap_header) ||
+ h->caplen < sizeof(struct pktap_header) ||
+ pktp_hdr->pth_length > h->caplen) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Packet too short", __func__);
+ return (0);
+ }
+
+ if (pcapng_dump_shb(pcap, dumper) == 0)
+ return (0);
+
+ block = dumper->dump_block;
+
+ /*
+ * Add an interface info block for a new interface before filtering
+ */
+ if_info = pcap_if_info_set_find_by_name(&dumper->dump_if_info_set, pktp_hdr->pth_ifname);
+ if (if_info == NULL) {
+ if_info = pcap_if_info_set_add(&dumper->dump_if_info_set, pktp_hdr->pth_ifname, -1,
+ pktp_hdr->pth_dlt, pcap->snapshot,
+ pcap->filter_str, pcap->errbuf);
+ if (if_info == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_add_if_info(%s) failed",
+ __func__, pktp_hdr->pth_ifname);
+ return (0);
+ }
+ }
+
+ /*
+ * Check the packet matches the filter
+ */
+ if (pcap_filter_pktap(pcap, dumper, if_info, h, sp) == 0)
+ return (0);
+
+ /*
+ * Dump the interface info block (if needed)
+ */
+ if_info = pcap_ng_dump_if_info(pcap, dumper, block, if_info);
+ if (if_info == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_dump_if_info(%s) failed",
+ __func__, pktp_hdr->pth_ifname);
+ return (0);
+ }
+
+ if ((pktp_hdr->pth_pid != -1 && pktp_hdr->pth_pid != 0) ||
+ pktp_hdr->pth_comm[0] != 0 || uuid_is_null(pktp_hdr->pth_uuid) == 0) {
+ proc_info = pcap_ng_dump_proc(pcap, dumper, block,
+ pktp_hdr->pth_pid, pktp_hdr->pth_comm, pktp_hdr->pth_uuid);
+ if (proc_info == NULL)
+ return (0);
+ }
+ if ((pktp_hdr->pth_epid != -1 && pktp_hdr->pth_epid != 0) ||
+ pktp_hdr->pth_ecomm[0] != 0 || uuid_is_null(pktp_hdr->pth_euuid) == 0) {
+ e_proc_info = pcap_ng_dump_proc(pcap, dumper, block,
+ pktp_hdr->pth_epid, pktp_hdr->pth_ecomm, pktp_hdr->pth_euuid);
+ if (e_proc_info == NULL)
+ return (0);
+ }
+
+ retval = pcap_ng_block_reset(block, PCAPNG_BT_EPB);
+ if (retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_reset(PCAPNG_BT_EPB) failed", __func__);
+ return (0);
+ }
+ /*
+ * The actual data packet is past the packet tap header
+ */
+ pkt_data = sp + pktp_hdr->pth_length;
+ epb = pcap_ng_get_enhanced_packet_fields(block);
+ epb->caplen = h->caplen - pktp_hdr->pth_length;
+ epb->interface_id = if_info->if_dump_id;
+ epb->len = h->len - pktp_hdr->pth_length;
+ /* Microsecond resolution */
+ ts = ((uint64_t)h->ts.tv_sec) * 1000000 + (uint64_t)h->ts.tv_usec;
+ epb->timestamp_high = ts >> 32;
+ epb->timestamp_low = ts & 0xffffffff;
+
+ pcap_ng_block_packet_set_data(block, pkt_data, epb->caplen);
+
+ if (proc_info != NULL)
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PIB_INDEX, &proc_info->proc_dump_index, 4);
+ if (e_proc_info != NULL)
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_E_PIB_INDEX, &e_proc_info->proc_dump_index, 4);
+
+ if ((pktp_hdr->pth_flags & PTH_FLAG_DIR_IN))
+ pktflags = PCAPNG_PBF_DIR_INBOUND;
+ else if ((pktp_hdr->pth_flags & PTH_FLAG_DIR_OUT))
+ pktflags = PCAPNG_PBF_DIR_OUTBOUND;
+ if (pktflags != 0)
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_FLAGS , &pktflags, 4);
+
+ if (pktp_hdr->pth_svc != -1)
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_SVC , &pktp_hdr->pth_svc, 4);
+
+ if (comment != NULL)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ if (pktp_hdr->pth_flags & PTH_FLAG_NEW_FLOW) {
+ pmdflags |= PCAPNG_EPB_PMDF_NEW_FLOW;
+ }
+
+#ifdef PTH_FLAG_REXMIT
+ if (pktp_hdr->pth_flags & PTH_FLAG_REXMIT) {
+ pmdflags |= PCAPNG_EPB_PMDF_REXMIT;
+ }
+#endif /* PTH_FLAG_REXMIT */
+
+#ifdef PTH_FLAG_KEEP_ALIVE
+ if (pktp_hdr->pth_flags & PTH_FLAG_KEEP_ALIVE) {
+ pmdflags |= PCAPNG_EPB_PMDF_KEEP_ALIVE;
+ }
+#endif /* PTH_FLAG_KEEP_ALIVE */
+
+#ifdef PTH_FLAG_SOCKET
+ if (pktp_hdr->pth_flags & PTH_FLAG_SOCKET) {
+ pmdflags |= PCAPNG_EPB_PMDF_SOCKET;
+ }
+#endif /* PTH_FLAG_SOCKET */
+
+#ifdef PTH_FLAG_NEXUS_CHAN
+ if (pktp_hdr->pth_flags & PTH_FLAG_NEXUS_CHAN) {
+ pmdflags |= PCAPNG_EPB_PMDF_NEXUS_CHANNEL;
+ }
+#endif /* PTH_FLAG_NEXUS_CHAN */
+
+ if (pmdflags != 0) {
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PMD_FLAGS, &pmdflags, 4);
+ }
+
+ (void) pcap_ng_dump_block(dumper, block);
+
+ return (1);
+}
+
+int
+pcap_ng_dump_pktap(pcap_t *pcap, pcap_dumper_t *dumper,
+ const struct pcap_pkthdr *h, const u_char *sp)
+{
+ return (pcap_ng_dump_pktap_comment(pcap, dumper, h, sp, NULL));
+}
+
+int
+pcap_ng_dump_decryption_secrets(pcap_t *pcap, pcap_dumper_t *dumper,
+ const uint32_t type, const size_t len, const uint8_t *sp)
+{
+ int retval;
+ pcapng_block_t block = NULL;
+ struct pcapng_decryption_secrets_fields *dsb_fields;
+
+ if (len > UINT32_MAX) {
+ return 0;
+ }
+
+ if (pcapng_dump_shb(pcap, dumper) == 0)
+ return (0);
+
+ block = dumper->dump_block;
+
+ retval = pcap_ng_block_reset(block, PCAPNG_BT_DSB);
+ if (retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_reset(PCAPNG_BT_DSB) failed", __func__);
+ return (0);
+ }
+ dsb_fields = pcap_ng_get_decryption_secrets_fields(block);
+ dsb_fields->secrets_type = type;
+ dsb_fields->secrets_length = (uint32_t)len;
+ pcap_ng_block_packet_set_data(block, sp, (uint32_t)len);
+
+ (void) pcap_ng_dump_block(dumper, block);
+
+ return (1);
+}
+
+int
+pcap_apple_set_exthdr(pcap_t *p, int v)
+{
+ int status = -1;
+
+#ifdef BIOCSEXTHDR
+ if (ioctl(p->fd, BIOCSEXTHDR, (caddr_t)&v) < 0) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSEXTHDR: %s",
+ pcap_strerror(errno));
+ status = PCAP_ERROR;
+ } else {
+ p->extendedhdr = !!v;
+ status = 0;
+ }
+#endif /* BIOCSEXTHDR */
+
+ return (status);
+}
+
+int
+pcap_set_want_pktap(pcap_t *p, int v)
+{
+ p->wantpktap = !!v;
+
+ return (0);
+}
+
+int
+pcap_set_truncation_mode(pcap_t *p, bool on)
+{
+ int status = PCAP_ERROR;
+
+#ifdef BIOCSTRUNCATE
+ p->truncation = on;
+ status = 0;
+#endif /* BIOCSTRUNCATE */
+
+ return (status);
+}
+
+int
+pcap_set_pktap_hdr_v2(pcap_t *p, bool on)
+{
+ int status = PCAP_ERROR;
+
+#ifdef BIOCSPKTHDRV2
+ p->pktaphdrv2 = on;
+ status = 0;
+#endif /* BIOCSPKTHDRV2 */
+
+ return (status);
+}
+
+static char *
+pcap_svc2str(uint32_t svc)
+{
+ static char svcstr[10];
+
+ switch (svc) {
+ case SO_TC_BK_SYS:
+ return "BK_SYS";
+ case SO_TC_BK:
+ return "BK";
+ case SO_TC_BE:
+ return "BE";
+ case SO_TC_RD:
+ return "RD";
+ case SO_TC_OAM:
+ return "OAM";
+ case SO_TC_AV:
+ return "AV";
+ case SO_TC_RV:
+ return "RV";
+ case SO_TC_VI:
+ return "VI";
+ case SO_TC_VO:
+ return "VO";
+ case SO_TC_CTL:
+ return "CTL";
+ default:
+ snprintf(svcstr, sizeof(svcstr), "%u", svc);
+ return svcstr;
+ }
+}
+
+void
+pcap_read_bpf_header(pcap_t *p, u_char *bp, struct pcap_pkthdr *pkthdr)
+{
+ struct bpf_hdr_ext *bhep = ((struct bpf_hdr_ext *)bp);
+ char tmpbuf[100];
+ int tlen;
+
+ pkthdr->comment[0] = 0;
+
+ if (p->extendedhdr == 0)
+ return;
+
+ if (bhep->bh_comm[0] != 0) {
+ bzero(&tmpbuf, sizeof (tmpbuf));
+ tlen = snprintf(tmpbuf, sizeof (tmpbuf),
+ "pid %s.%d svc %s", bhep->bh_comm,
+ bhep->bh_pid, pcap_svc2str(bhep->bh_svc));
+ if (tlen > 0)
+ strlcat(pkthdr->comment,
+ tmpbuf,
+ sizeof (pkthdr->comment));
+ }
+ if (bhep->bh_pktflags > 0) {
+ bzero(&tmpbuf, sizeof (tmpbuf));
+ tlen = snprintf(tmpbuf, sizeof (tmpbuf),
+ " pktflags 0x%x",
+ bhep->bh_pktflags);
+ if (tlen > 0)
+ strlcat(pkthdr->comment,
+ tmpbuf,
+ sizeof (pkthdr->comment));
+ }
+
+ if (bhep->bh_unsent_bytes > 0) {
+ bzero(&tmpbuf, sizeof (tmpbuf));
+ tlen = snprintf(tmpbuf, sizeof (tmpbuf),
+ " unsent %u",
+ bhep->bh_unsent_bytes);
+ if (tlen > 0)
+ strlcat(pkthdr->comment,
+ tmpbuf,
+ sizeof (pkthdr->comment));
+ }
+}
+
+#ifdef PTH_FLAG_V2_HDR
+/*
+ * Returns zero if the packet doesn't match, non-zero if it matches
+ */
+static int
+pcap_filter_pktap_v2(pcap_t *pcap, pcap_dumper_t *dumper, struct pcap_if_info *if_info,
+ const struct pcap_pkthdr *h, const u_char *sp)
+{
+ struct pktap_v2_hdr *pktap_v2_hdr;
+ const u_char *pkt_data;
+ int match = 0;
+ const char *ifname;
+
+ pktap_v2_hdr = (struct pktap_v2_hdr *)sp;
+
+ if (h->len < sizeof(struct pktap_v2_hdr) ||
+ h->caplen < sizeof(struct pktap_v2_hdr) ||
+ pktap_v2_hdr->pth_length > h->caplen) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Packet too short", __func__);
+ return (0);
+ }
+
+ if (pktap_v2_hdr->pth_ifname_offset == 0) {
+ return (0);
+ }
+ ifname = ((char *) pktap_v2_hdr) + pktap_v2_hdr->pth_ifname_offset;
+
+ if (if_info == NULL) {
+ if_info = pcap_if_info_set_find_by_name(&dumper->dump_if_info_set, ifname);
+ /*
+ * New interface
+ */
+ if (if_info == NULL) {
+ if_info = pcap_if_info_set_add(&dumper->dump_if_info_set, ifname, -1,
+ pktap_v2_hdr->pth_dlt, pcap->snapshot,
+ pcap->filter_str, pcap->errbuf);
+ if (if_info == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_add_if_info(%s) failed",
+ __func__, ifname);
+ return (0);
+ }
+ }
+ }
+
+ if (if_info->if_filter_program.bf_insns == NULL) {
+ match = 1;
+ } else {
+ /*
+ * The actual data packet is past the packet tap header
+ */
+ struct pcap_pkthdr tmp_hdr;
+
+ bcopy(h, &tmp_hdr, sizeof(struct pcap_pkthdr));
+
+ tmp_hdr.caplen -= pktap_v2_hdr->pth_length;
+ tmp_hdr.len -= pktap_v2_hdr->pth_length;
+
+ pkt_data = sp + pktap_v2_hdr->pth_length;
+
+ match = pcap_offline_filter(&if_info->if_filter_program, &tmp_hdr, pkt_data);
+ }
+
+ return (match);
+}
+#endif /* PTH_FLAG_V2_HDR */
+
+int
+pcap_ng_dump_pktap_v2(pcap_t *pcap, pcap_dumper_t *dumper,
+ const struct pcap_pkthdr *h, const u_char *sp,
+ const char *comment)
+{
+#ifdef PTH_FLAG_V2_HDR
+ pcapng_block_t block = NULL;
+ struct pktap_v2_hdr *pktap_v2_hdr;
+ const u_char *pkt_data;
+ struct pcap_if_info *if_info = NULL;
+ struct pcapng_enhanced_packet_fields *epb;
+ uint64_t ts;
+ struct pcap_proc_info *proc_info = NULL;
+ struct pcap_proc_info *e_proc_info = NULL;
+ uint32_t pktflags = 0;
+ uint32_t pmdflags = 0;
+ int retval;
+ const char *ifname = NULL;
+ const char *comm = NULL;
+ const uuid_t *uuid = NULL;
+ const char *e_comm = NULL;
+ const uuid_t *e_uuid = NULL;
+
+ pktap_v2_hdr = (struct pktap_v2_hdr *)sp;
+
+ if (h->len < sizeof(struct pktap_v2_hdr) ||
+ h->caplen < sizeof(struct pktap_v2_hdr) ||
+ pktap_v2_hdr->pth_length > h->caplen) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Packet too short", __func__);
+ return (0);
+ }
+
+ if (pktap_v2_hdr->pth_ifname_offset == 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: No ifame", __func__);
+ return (0);
+ }
+ ifname = ((char *) pktap_v2_hdr) + pktap_v2_hdr->pth_ifname_offset;
+
+ if (pcapng_dump_shb(pcap, dumper) == 0)
+ return (0);
+
+ block = dumper->dump_block;
+
+ /*
+ * Add an interface info block for a new interface before filtering
+ */
+ if_info = pcap_if_info_set_find_by_name(&dumper->dump_if_info_set, ifname);
+ if (if_info == NULL) {
+ if_info = pcap_if_info_set_add(&dumper->dump_if_info_set, ifname, -1,
+ pktap_v2_hdr->pth_dlt, pcap->snapshot,
+ pcap->filter_str, pcap->errbuf);
+ if (if_info == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_add_if_info(%s) failed",
+ __func__, ifname);
+ return (0);
+ }
+ }
+
+ /*
+ * Check the packet matches the filter
+ */
+ if (pcap_filter_pktap_v2(pcap, dumper, if_info, h, sp) == 0)
+ return (0);
+
+ /*
+ * Dump the interface info block (if needed)
+ */
+ if_info = pcap_ng_dump_if_info(pcap, dumper, block, if_info);
+ if (if_info == NULL) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_dump_if_info(%s) failed",
+ __func__, ifname);
+ return (0);
+ }
+
+ if (pktap_v2_hdr->pth_comm_offset != 0)
+ comm = ((char *) pktap_v2_hdr) + pktap_v2_hdr->pth_comm_offset;
+ if (pktap_v2_hdr->pth_uuid_offset != 0)
+ uuid = (uuid_t *)(((char *) pktap_v2_hdr) + pktap_v2_hdr->pth_uuid_offset);
+ if ((pktap_v2_hdr->pth_pid != 0 && pktap_v2_hdr->pth_pid != -1) ||
+ comm != NULL || uuid != NULL) {
+ proc_info = pcap_ng_dump_proc(pcap, dumper, block,
+ pktap_v2_hdr->pth_pid,
+ comm,
+ *uuid);
+ if (proc_info == NULL)
+ return (0);
+ }
+
+ if (pktap_v2_hdr->pth_e_comm_offset != 0)
+ e_comm = ((char *) pktap_v2_hdr) + pktap_v2_hdr->pth_e_comm_offset;
+ if (pktap_v2_hdr->pth_e_uuid_offset != 0)
+ e_uuid = (uuid_t *)(((char *) pktap_v2_hdr) + pktap_v2_hdr->pth_e_uuid_offset);
+
+ if ((pktap_v2_hdr->pth_e_pid != 0 && pktap_v2_hdr->pth_e_pid != -1) ||
+ e_comm != NULL || e_uuid != NULL) {
+ e_proc_info = pcap_ng_dump_proc(pcap, dumper, block,
+ pktap_v2_hdr->pth_e_pid,
+ e_comm,
+ *e_uuid);
+ if (e_proc_info == NULL)
+ return (0);
+ }
+
+ retval = pcap_ng_block_reset(block, PCAPNG_BT_EPB);
+ if (retval != 0) {
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_ng_block_reset(PCAPNG_BT_EPB) failed", __func__);
+ return (0);
+ }
+ /*
+ * The actual data packet is past the packet tap header
+ */
+ pkt_data = sp + pktap_v2_hdr->pth_length;
+ epb = pcap_ng_get_enhanced_packet_fields(block);
+ epb->caplen = h->caplen - pktap_v2_hdr->pth_length;
+ epb->interface_id = if_info->if_dump_id;
+ epb->len = h->len - pktap_v2_hdr->pth_length;
+ /* Microsecond resolution */
+ ts = ((uint64_t)h->ts.tv_sec) * 1000000 + (uint64_t)h->ts.tv_usec;
+ epb->timestamp_high = ts >> 32;
+ epb->timestamp_low = ts & 0xffffffff;
+
+ pcap_ng_block_packet_set_data(block, pkt_data, epb->caplen);
+
+ if (proc_info != NULL) {
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PIB_INDEX, &proc_info->proc_dump_index, 4);
+ }
+ if (e_proc_info != NULL) {
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_E_PIB_INDEX, &e_proc_info->proc_dump_index, 4);
+ }
+ if ((pktap_v2_hdr->pth_flags & PTH_FLAG_DIR_IN)) {
+ pktflags = PCAPNG_PBF_DIR_INBOUND;
+ } else if ((pktap_v2_hdr->pth_flags & PTH_FLAG_DIR_OUT)) {
+ pktflags = PCAPNG_PBF_DIR_OUTBOUND;
+ }
+ if (pktflags != 0) {
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_FLAGS , &pktflags, 4);
+ }
+ if (pktap_v2_hdr->pth_svc != (uint16_t)-1) {
+ uint32_t svc = pktap_v2_hdr->pth_svc;
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_SVC , &svc, 4);
+ }
+ if (comment != NULL) {
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+ }
+ if (pktap_v2_hdr->pth_flags & PTH_FLAG_NEW_FLOW) {
+ pmdflags |= PCAPNG_EPB_PMDF_NEW_FLOW;
+ }
+#ifdef PTH_FLAG_REXMIT
+ if (pktap_v2_hdr->pth_flags & PTH_FLAG_REXMIT) {
+ pmdflags |= PCAPNG_EPB_PMDF_REXMIT;
+ }
+#endif /* PTH_FLAG_REXMIT */
+
+#ifdef PTH_FLAG_KEEP_ALIVE
+ if (pktap_v2_hdr->pth_flags & PTH_FLAG_KEEP_ALIVE) {
+ pmdflags |= PCAPNG_EPB_PMDF_KEEP_ALIVE;
+ }
+#endif /* PTH_FLAG_KEEP_ALIVE */
+
+#ifdef PTH_FLAG_SOCKET
+ if (pktap_v2_hdr->pth_flags & PTH_FLAG_SOCKET) {
+ pmdflags |= PCAPNG_EPB_PMDF_SOCKET;
+ }
+#endif /* PTH_FLAG_SOCKET */
+
+#ifdef PTH_FLAG_NEXUS_CHAN
+ if (pktap_v2_hdr->pth_flags & PTH_FLAG_NEXUS_CHAN) {
+ pmdflags |= PCAPNG_EPB_PMDF_NEXUS_CHANNEL;
+ }
+#endif /* PTH_FLAG_NEXUS_CHAN */
+
+ if (pmdflags != 0) {
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PMD_FLAGS, &pmdflags, 4);
+ }
+
+ (void) pcap_ng_dump_block(dumper, block);
+
+ return (1);
+#else /* PTH_FLAG_V2_HDR */
+#pragma unused(dumper, h, sp, comment)
+ snprintf(pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Packet too short", __func__);
+ return (0);
+#endif /* PTH_FLAG_V2_HDR */
+}
+
+void
+pcap_ng_dump_init_section_info(pcap_dumper_t *dumper)
+{
+ dumper->shb_added = 0;
+ pcap_if_info_set_clear(&dumper->dump_if_info_set);
+ pcap_proc_info_set_clear(&dumper->dump_proc_info_set);
+}
diff --git a/lib/libpcap/libpcap/pcap-dbus.c b/lib/libpcap/libpcap/pcap-dbus.c
new file mode 100644
index 0000000..1252975
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dbus.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (c) 2012 Jakub Zawadzki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include <time.h>
+#include <sys/time.h>
+
+#include <dbus/dbus.h>
+
+#include "pcap-int.h"
+#include "pcap-dbus.h"
+
+/*
+ * Private data for capturing on D-Bus.
+ */
+struct pcap_dbus {
+ DBusConnection *conn;
+ u_int packets_read; /* count of packets read */
+};
+
+static int
+dbus_read(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
+{
+ struct pcap_dbus *handlep = handle->priv;
+
+ struct pcap_pkthdr pkth;
+ DBusMessage *message;
+
+ char *raw_msg;
+ int raw_msg_len;
+
+ int count = 0;
+
+ message = dbus_connection_pop_message(handlep->conn);
+
+ while (!message) {
+ /* XXX handle->opt.timeout = timeout_ms; */
+ if (!dbus_connection_read_write(handlep->conn, 100)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Connection closed");
+ return -1;
+ }
+
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return -2;
+ }
+
+ message = dbus_connection_pop_message(handlep->conn);
+ }
+
+ if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Disconnected");
+ return -1;
+ }
+
+ if (dbus_message_marshal(message, &raw_msg, &raw_msg_len)) {
+ pkth.caplen = pkth.len = raw_msg_len;
+ /* pkth.caplen = min (payload_len, handle->snapshot); */
+
+ gettimeofday(&pkth.ts, NULL);
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, (u_char *)raw_msg, pkth.len, pkth.caplen)) {
+ handlep->packets_read++;
+ callback(user, &pkth, (u_char *)raw_msg);
+ count++;
+ }
+
+ dbus_free(raw_msg);
+ }
+ return count;
+}
+
+static int
+dbus_write(pcap_t *handle, const void *buf, size_t size)
+{
+ /* XXX, not tested */
+ struct pcap_dbus *handlep = handle->priv;
+
+ DBusError error = DBUS_ERROR_INIT;
+ DBusMessage *msg;
+
+ if (!(msg = dbus_message_demarshal(buf, size, &error))) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "dbus_message_demarshal() failed: %s", error.message);
+ dbus_error_free(&error);
+ return -1;
+ }
+
+ dbus_connection_send(handlep->conn, msg, NULL);
+ dbus_connection_flush(handlep->conn);
+
+ dbus_message_unref(msg);
+ return 0;
+}
+
+static int
+dbus_stats(pcap_t *handle, struct pcap_stat *stats)
+{
+ struct pcap_dbus *handlep = handle->priv;
+
+ stats->ps_recv = handlep->packets_read;
+ stats->ps_drop = 0;
+ stats->ps_ifdrop = 0;
+ return 0;
+}
+
+static void
+dbus_cleanup(pcap_t *handle)
+{
+ struct pcap_dbus *handlep = handle->priv;
+
+ dbus_connection_unref(handlep->conn);
+
+ pcap_cleanup_live_common(handle);
+}
+
+/*
+ * We don't support non-blocking mode. I'm not sure what we'd
+ * do to support it and, given that we don't support select()/
+ * poll()/epoll_wait()/kevent() etc., it probably doesn't
+ * matter.
+ */
+static int
+dbus_getnonblock(pcap_t *p)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Non-blocking mode isn't supported for capturing on D-Bus");
+ return (-1);
+}
+
+static int
+dbus_setnonblock(pcap_t *p, int nonblock _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Non-blocking mode isn't supported for capturing on D-Bus");
+ return (-1);
+}
+
+static int
+dbus_activate(pcap_t *handle)
+{
+#define EAVESDROPPING_RULE "eavesdrop=true,"
+
+ static const char *rules[] = {
+ EAVESDROPPING_RULE "type='signal'",
+ EAVESDROPPING_RULE "type='method_call'",
+ EAVESDROPPING_RULE "type='method_return'",
+ EAVESDROPPING_RULE "type='error'",
+ };
+
+ #define N_RULES sizeof(rules)/sizeof(rules[0])
+
+ struct pcap_dbus *handlep = handle->priv;
+ const char *dev = handle->opt.device;
+
+ DBusError error = DBUS_ERROR_INIT;
+ u_int i;
+
+ if (strcmp(dev, "dbus-system") == 0) {
+ if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get system bus: %s", error.message);
+ dbus_error_free(&error);
+ return PCAP_ERROR;
+ }
+
+ } else if (strcmp(dev, "dbus-session") == 0) {
+ if (!(handlep->conn = dbus_bus_get(DBUS_BUS_SESSION, &error))) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to get session bus: %s", error.message);
+ dbus_error_free(&error);
+ return PCAP_ERROR;
+ }
+
+ } else if (strncmp(dev, "dbus://", 7) == 0) {
+ const char *addr = dev + 7;
+
+ if (!(handlep->conn = dbus_connection_open(addr, &error))) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to open connection to: %s: %s", addr, error.message);
+ dbus_error_free(&error);
+ return PCAP_ERROR;
+ }
+
+ if (!dbus_bus_register(handlep->conn, &error)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to register bus %s: %s\n", addr, error.message);
+ dbus_error_free(&error);
+ return PCAP_ERROR;
+ }
+
+ } else {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Can't get bus address from %s", handle->opt.device);
+ return PCAP_ERROR;
+ }
+
+ /* Initialize some components of the pcap structure. */
+ handle->bufsize = 0;
+ handle->offset = 0;
+ handle->linktype = DLT_DBUS;
+ handle->read_op = dbus_read;
+ handle->inject_op = dbus_write;
+ handle->setfilter_op = install_bpf_program; /* XXX, later add support for dbus_bus_add_match() */
+ handle->setdirection_op = NULL;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = dbus_getnonblock;
+ handle->setnonblock_op = dbus_setnonblock;
+ handle->stats_op = dbus_stats;
+ handle->cleanup_op = dbus_cleanup;
+
+#ifndef _WIN32
+ /*
+ * Unfortunately, trying to do a select()/poll()/epoll_wait()/
+ * kevent()/etc. on a D-Bus connection isn't a simple
+ * case of "give me an FD on which to wait".
+ *
+ * Apparently, you have to register "add watch", "remove watch",
+ * and "toggle watch" functions with
+ * dbus_connection_set_watch_functions(),
+ * keep a *set* of FDs, add to that set in the "add watch"
+ * function, subtract from it in the "remove watch" function,
+ * and either add to or subtract from that set in the "toggle
+ * watch" function, and do the wait on *all* of the FDs in the
+ * set. (Yes, you need the "toggle watch" function, so that
+ * the main loop doesn't itself need to check for whether
+ * a given watch is enabled or disabled - most libpcap programs
+ * know nothing about D-Bus and shouldn't *have* to know anything
+ * about D-Bus other than how to decode D-Bus messages.)
+ *
+ * Implementing that would require considerable changes in
+ * the way libpcap exports "selectable FDs" to its client.
+ * Until that's done, we just say "you can't do that".
+ */
+ handle->selectable_fd = handle->fd = -1;
+#endif
+
+ if (handle->opt.rfmon) {
+ /*
+ * Monitor mode doesn't apply to dbus connections.
+ */
+ dbus_cleanup(handle);
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum message length for D-Bus (128MB).
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > 134217728)
+ handle->snapshot = 134217728;
+
+ /* dbus_connection_set_max_message_size(handlep->conn, handle->snapshot); */
+ if (handle->opt.buffer_size != 0)
+ dbus_connection_set_max_received_size(handlep->conn, handle->opt.buffer_size);
+
+ for (i = 0; i < N_RULES; i++) {
+ dbus_bus_add_match(handlep->conn, rules[i], &error);
+ if (dbus_error_is_set(&error)) {
+ dbus_error_free(&error);
+
+ /* try without eavesdrop */
+ dbus_bus_add_match(handlep->conn, rules[i] + strlen(EAVESDROPPING_RULE), &error);
+ if (dbus_error_is_set(&error)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Failed to add bus match: %s\n", error.message);
+ dbus_error_free(&error);
+ dbus_cleanup(handle);
+ return PCAP_ERROR;
+ }
+ }
+ }
+
+ return 0;
+}
+
+pcap_t *
+dbus_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *p;
+
+ if (strcmp(device, "dbus-system") &&
+ strcmp(device, "dbus-session") &&
+ strncmp(device, "dbus://", 7))
+ {
+ *is_ours = 0;
+ return NULL;
+ }
+
+ *is_ours = 1;
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dbus));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = dbus_activate;
+ /*
+ * Set these up front, so that, even if our client tries
+ * to set non-blocking mode before we're activated, or
+ * query the state of non-blocking mode, they get an error,
+ * rather than having the non-blocking mode option set
+ * for use later.
+ */
+ p->getnonblock_op = dbus_getnonblock;
+ p->setnonblock_op = dbus_setnonblock;
+ return (p);
+}
+
+int
+dbus_findalldevs(pcap_if_list_t *devlistp, char *err_str)
+{
+ /*
+ * The notion of "connected" vs. "disconnected" doesn't apply.
+ * XXX - what about the notions of "up" and "running"?
+ */
+ if (add_dev(devlistp, "dbus-system",
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "D-Bus system bus",
+ err_str) == NULL)
+ return -1;
+ if (add_dev(devlistp, "dbus-session",
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, "D-Bus session bus",
+ err_str) == NULL)
+ return -1;
+ return 0;
+}
+
diff --git a/lib/libpcap/libpcap/pcap-dbus.h b/lib/libpcap/libpcap/pcap-dbus.h
new file mode 100644
index 0000000..c97f2e1
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dbus.h
@@ -0,0 +1,2 @@
+pcap_t *dbus_create(const char *, char *, int *);
+int dbus_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/lib/libpcap/libpcap/pcap-dll.rc b/lib/libpcap/libpcap/pcap-dll.rc
new file mode 100644
index 0000000..fc4f42b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dll.rc
@@ -0,0 +1,36 @@
+#include "config.h"
+#include <winver.h>
+
+ VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PACKAGE_VERSION_DLL
+ PRODUCTVERSION PACKAGE_VERSION_DLL
+ FILEFLAGSMASK 0x3fL
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_DLL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "https://github.com/the-tcpdump-group/libpcap/"
+ VALUE "CompanyName", "The TCPdump Group"
+ VALUE "FileDescription", "System-Independent Interface for User-Level Packet Capture"
+ VALUE "FileVersion", "PACKAGE_VERSION_DLL"
+ VALUE "InternalName", PACKAGE_NAME
+ VALUE "LegalCopyright", "Copyright (c) The TCPdump Group"
+ VALUE "LegalTrademarks", ""
+ VALUE "OriginalFilename", "wpcap.dll"
+ VALUE "ProductName", PACKAGE_NAME
+ VALUE "ProductVersion", PACKAGE_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+ END
diff --git a/lib/libpcap/libpcap/pcap-dlpi.c b/lib/libpcap/libpcap/pcap-dlpi.c
new file mode 100644
index 0000000..3ed8fa7
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dlpi.c
@@ -0,0 +1,1909 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This code contributed by Atanu Ghosh (atanu@cs.ucl.ac.uk),
+ * University College London, and subsequently modified by
+ * Guy Harris (guy@alum.mit.edu), Mark Pizzolato
+ * <List-tcpdump-workers@subscriptions.pizzolato.net>,
+ * Mark C. Brown (mbrown@hp.com), and Sagun Shakya <Sagun.Shakya@Sun.COM>.
+ */
+
+/*
+ * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX.
+ *
+ * Notes:
+ *
+ * - The DLIOCRAW ioctl() is specific to SunOS.
+ *
+ * - There is a bug in bufmod(7) such that setting the snapshot
+ * length results in data being left of the front of the packet.
+ *
+ * - It might be desirable to use pfmod(7) to filter packets in the
+ * kernel when possible.
+ *
+ * - An older version of the HP-UX DLPI Programmer's Guide, which
+ * I think was advertised as the 10.20 version, used to be available
+ * at
+ *
+ * http://docs.hp.com/hpux/onlinedocs/B2355-90093/B2355-90093.html
+ *
+ * but is no longer available; it can still be found at
+ *
+ * http://h21007.www2.hp.com/dspp/files/unprotected/Drivers/Docs/Refs/B2355-90093.pdf
+ *
+ * in PDF form.
+ *
+ * - The HP-UX 10.x, 11.0, and 11i v1.6 version of the HP-UX DLPI
+ * Programmer's Guide, which I think was once advertised as the
+ * 11.00 version is available at
+ *
+ * http://docs.hp.com/en/B2355-90139/index.html
+ *
+ * - The HP-UX 11i v2 version of the HP-UX DLPI Programmer's Guide
+ * is available at
+ *
+ * http://docs.hp.com/en/B2355-90871/index.html
+ *
+ * - All of the HP documents describe raw-mode services, which are
+ * what we use if DL_HP_RAWDLS is defined. XXX - we use __hpux
+ * in some places to test for HP-UX, but use DL_HP_RAWDLS in
+ * other places; do we support any versions of HP-UX without
+ * DL_HP_RAWDLS?
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#ifdef HAVE_SYS_BUFMOD_H
+#include <sys/bufmod.h>
+#endif
+#include <sys/dlpi.h>
+#ifdef HAVE_SYS_DLPI_EXT_H
+#include <sys/dlpi_ext.h>
+#endif
+#ifdef HAVE_HPUX9
+#include <sys/socket.h>
+#endif
+#ifdef DL_HP_PPA_REQ
+#include <sys/stat.h>
+#endif
+#include <sys/stream.h>
+#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
+#include <sys/systeminfo.h>
+#endif
+
+#ifdef HAVE_HPUX9
+#include <net/if.h>
+#endif
+
+#include <ctype.h>
+#ifdef HAVE_HPUX9
+#include <nlist.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stropts.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#if defined(__hpux)
+ /*
+ * HP-UX has a /dev/dlpi device; you open it and set the PPA of the actual
+ * network device you want.
+ */
+ #define HAVE_DEV_DLPI
+#elif defined(_AIX)
+ /*
+ * AIX has a /dev/dlpi directory, with devices named after the interfaces
+ * underneath it.
+ */
+ #define PCAP_DEV_PREFIX "/dev/dlpi"
+#elif defined(HAVE_SOLARIS)
+ /*
+ * Solaris has devices named after the interfaces underneath /dev.
+ */
+ #define PCAP_DEV_PREFIX "/dev"
+#endif
+
+#define MAXDLBUF 8192
+
+/* Forwards */
+static char *split_dname(char *, u_int *, char *);
+static int dl_doattach(int, int, char *);
+#ifdef DL_HP_RAWDLS
+static int dl_dohpuxbind(int, char *);
+#endif
+static int dlpromiscon(pcap_t *, bpf_u_int32);
+static int dlbindreq(int, bpf_u_int32, char *);
+static int dlbindack(int, char *, char *, int *);
+static int dlokack(int, const char *, char *, char *);
+static int dlinforeq(int, char *);
+static int dlinfoack(int, char *, char *);
+
+#ifdef HAVE_DL_PASSIVE_REQ_T
+static void dlpassive(int, char *);
+#endif
+
+#ifdef DL_HP_RAWDLS
+static int dlrawdatareq(int, const u_char *, int);
+#endif
+static int recv_ack(int, int, const char *, char *, char *, int *);
+static char *dlstrerror(char *, size_t, bpf_u_int32);
+static char *dlprim(char *, size_t, bpf_u_int32);
+#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
+#define GET_RELEASE_BUFSIZE 32
+static void get_release(char *, size_t, bpf_u_int32 *, bpf_u_int32 *,
+ bpf_u_int32 *);
+#endif
+static int send_request(int, char *, int, char *, char *);
+#ifdef HAVE_HPUX9
+static int dlpi_kread(int, off_t, void *, u_int, char *);
+#endif
+#ifdef HAVE_DEV_DLPI
+static int get_dlpi_ppa(int, const char *, u_int, u_int *, char *);
+#endif
+
+/*
+ * Cast a buffer to "union DL_primitives" without provoking warnings
+ * from the compiler.
+ */
+#define MAKE_DL_PRIMITIVES(ptr) ((union DL_primitives *)(void *)(ptr))
+
+static int
+pcap_read_dlpi(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ int cc;
+ u_char *bp;
+ int flags;
+ bpf_u_int32 ctlbuf[MAXDLBUF];
+ struct strbuf ctl = {
+ MAXDLBUF,
+ 0,
+ (char *)ctlbuf
+ };
+ struct strbuf data;
+
+ flags = 0;
+ cc = p->cc;
+ if (cc == 0) {
+ data.buf = (char *)p->buffer + p->offset;
+ data.maxlen = p->bufsize;
+ data.len = 0;
+ do {
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates
+ * that it has, and return -2 to
+ * indicate that we were told to
+ * break out of the loop.
+ */
+ p->break_loop = 0;
+ return (-2);
+ }
+ /*
+ * XXX - check for the DLPI primitive, which
+ * would be DL_HP_RAWDATA_IND on HP-UX
+ * if we're in raw mode?
+ */
+ ctl.buf = (char *)ctlbuf;
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
+ if (getmsg(p->fd, &ctl, &data, &flags) < 0) {
+ /* Don't choke when we get ptraced */
+ switch (errno) {
+
+ case EINTR:
+ cc = 0;
+ continue;
+
+ case EAGAIN:
+ return (0);
+ }
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ sizeof(p->errbuf), errno, "getmsg");
+ return (-1);
+ }
+ cc = data.len;
+ } while (cc == 0);
+ bp = (u_char *)p->buffer + p->offset;
+ } else
+ bp = p->bp;
+
+ return (pcap_process_pkts(p, callback, user, cnt, bp, cc));
+}
+
+static int
+pcap_inject_dlpi(pcap_t *p, const void *buf, size_t size)
+{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->priv;
+#endif
+ int ret;
+
+#if defined(DLIOCRAW)
+ ret = write(p->fd, buf, size);
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (-1);
+ }
+#elif defined(DL_HP_RAWDLS)
+ if (pd->send_fd < 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "send: Output FD couldn't be opened");
+ return (-1);
+ }
+ ret = dlrawdatareq(pd->send_fd, buf, size);
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (-1);
+ }
+ /*
+ * putmsg() returns either 0 or -1; it doesn't indicate how
+ * many bytes were written (presumably they were all written
+ * or none of them were written). OpenBSD's pcap_inject()
+ * returns the number of bytes written, so, for API compatibility,
+ * we return the number of bytes we were told to write.
+ */
+ ret = size;
+#else /* no raw mode */
+ /*
+ * XXX - this is a pain, because you might have to extract
+ * the address from the packet and use it in a DL_UNITDATA_REQ
+ * request. That would be dependent on the link-layer type.
+ *
+ * I also don't know what SAP you'd have to bind the descriptor
+ * to, or whether you'd need separate "receive" and "send" FDs,
+ * nor do I know whether you'd need different bindings for
+ * D/I/X Ethernet and 802.3, or for {FDDI,Token Ring} plus
+ * 802.2 and {FDDI,Token Ring} plus 802.2 plus SNAP.
+ *
+ * So, for now, we just return a "you can't send" indication,
+ * and leave it up to somebody with a DLPI-based system lacking
+ * both DLIOCRAW and DL_HP_RAWDLS to supply code to implement
+ * packet transmission on that system. If they do, they should
+ * send it to us - but should not send us code that assumes
+ * Ethernet; if the code doesn't work on non-Ethernet interfaces,
+ * it should check "p->linktype" and reject the send request if
+ * it's anything other than DLT_EN10MB.
+ */
+ pcap_strlcpy(p->errbuf, "send: Not supported on this version of this OS",
+ PCAP_ERRBUF_SIZE);
+ ret = -1;
+#endif /* raw mode */
+ return (ret);
+}
+
+#ifndef DL_IPATM
+#define DL_IPATM 0x12 /* ATM Classical IP interface */
+#endif
+
+#ifdef HAVE_SOLARIS
+/*
+ * For SunATM.
+ */
+#ifndef A_GET_UNITS
+#define A_GET_UNITS (('A'<<8)|118)
+#endif /* A_GET_UNITS */
+#ifndef A_PROMISCON_REQ
+#define A_PROMISCON_REQ (('A'<<8)|121)
+#endif /* A_PROMISCON_REQ */
+#endif /* HAVE_SOLARIS */
+
+static void
+pcap_cleanup_dlpi(pcap_t *p)
+{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->priv;
+
+ if (pd->send_fd >= 0) {
+ close(pd->send_fd);
+ pd->send_fd = -1;
+ }
+#endif
+ pcap_cleanup_live_common(p);
+}
+
+static int
+open_dlpi_device(const char *name, u_int *ppa, char *errbuf)
+{
+ int status;
+ char dname[100];
+ char *cp;
+ int fd;
+#ifdef HAVE_DEV_DLPI
+ u_int unit;
+#else
+ char dname2[100];
+#endif
+
+#ifdef HAVE_DEV_DLPI
+ /*
+ ** Remove any "/dev/" on the front of the device.
+ */
+ cp = strrchr(name, '/');
+ if (cp == NULL)
+ pcap_strlcpy(dname, name, sizeof(dname));
+ else
+ pcap_strlcpy(dname, cp + 1, sizeof(dname));
+
+ /*
+ * Split the device name into a device type name and a unit number;
+ * chop off the unit number, so "dname" is just a device type name.
+ */
+ cp = split_dname(dname, &unit, errbuf);
+ if (cp == NULL)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ *cp = '\0';
+
+ /*
+ * Use "/dev/dlpi" as the device.
+ *
+ * XXX - HP's DLPI Programmer's Guide for HP-UX 11.00 says that
+ * the "dl_mjr_num" field is for the "major number of interface
+ * driver"; that's the major of "/dev/dlpi" on the system on
+ * which I tried this, but there may be DLPI devices that
+ * use a different driver, in which case we may need to
+ * search "/dev" for the appropriate device with that major
+ * device number, rather than hardwiring "/dev/dlpi".
+ */
+ cp = "/dev/dlpi";
+ if ((fd = open(cp, O_RDWR)) < 0) {
+ if (errno == EPERM || errno == EACCES)
+ status = PCAP_ERROR_PERM_DENIED;
+ else
+ status = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s", cp);
+ return (status);
+ }
+
+ /*
+ * Get a table of all PPAs for that device, and search that
+ * table for the specified device type name and unit number.
+ */
+ status = get_dlpi_ppa(fd, dname, unit, ppa, errbuf);
+ if (status < 0) {
+ close(fd);
+ return (status);
+ }
+#else
+ /*
+ * If the device name begins with "/", assume it begins with
+ * the pathname of the directory containing the device to open;
+ * otherwise, concatenate the device directory name and the
+ * device name.
+ */
+ if (*name == '/')
+ pcap_strlcpy(dname, name, sizeof(dname));
+ else
+ pcap_snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX,
+ name);
+
+ /*
+ * Get the unit number, and a pointer to the end of the device
+ * type name.
+ */
+ cp = split_dname(dname, ppa, errbuf);
+ if (cp == NULL)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+
+ /*
+ * Make a copy of the device pathname, and then remove the unit
+ * number from the device pathname.
+ */
+ pcap_strlcpy(dname2, dname, sizeof(dname));
+ *cp = '\0';
+
+ /* Try device without unit number */
+ if ((fd = open(dname, O_RDWR)) < 0) {
+ if (errno != ENOENT) {
+ if (errno == EPERM || errno == EACCES)
+ status = PCAP_ERROR_PERM_DENIED;
+ else
+ status = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s", dname);
+ return (status);
+ }
+
+ /* Try again with unit number */
+ if ((fd = open(dname2, O_RDWR)) < 0) {
+ if (errno == ENOENT) {
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+
+ /*
+ * We provide an error message even
+ * for this error, for diagnostic
+ * purposes (so that, for example,
+ * the app can show the message if the
+ * user requests it).
+ *
+ * In it, we just report "No DLPI device
+ * found" with the device name, so people
+ * don't get confused and think, for example,
+ * that if they can't capture on "lo0"
+ * on Solaris prior to Solaris 11 the fix
+ * is to change libpcap (or the application
+ * that uses it) to look for something other
+ * than "/dev/lo0", as the fix is to use
+ * Solaris 11 or some operating system
+ * other than Solaris - you just *can't*
+ * capture on a loopback interface
+ * on Solaris prior to Solaris 11, the lack
+ * of a DLPI device for the loopback
+ * interface is just a symptom of that
+ * inability.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: No DLPI device found", name);
+ } else {
+ if (errno == EPERM || errno == EACCES)
+ status = PCAP_ERROR_PERM_DENIED;
+ else
+ status = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno, "%s", dname2);
+ }
+ return (status);
+ }
+ /* XXX Assume unit zero */
+ *ppa = 0;
+ }
+#endif
+ return (fd);
+}
+
+static int
+pcap_activate_dlpi(pcap_t *p)
+{
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd = p->priv;
+#endif
+ int status = 0;
+ int retv;
+ u_int ppa;
+#ifdef HAVE_SOLARIS
+ int isatm = 0;
+#endif
+ register dl_info_ack_t *infop;
+#ifdef HAVE_SYS_BUFMOD_H
+ bpf_u_int32 ss;
+#ifdef HAVE_SOLARIS
+ char release[GET_RELEASE_BUFSIZE];
+ bpf_u_int32 osmajor, osminor, osmicro;
+#endif
+#endif
+ bpf_u_int32 buf[MAXDLBUF];
+
+ p->fd = open_dlpi_device(p->opt.device, &ppa, p->errbuf);
+ if (p->fd < 0) {
+ status = p->fd;
+ goto bad;
+ }
+
+#ifdef DL_HP_RAWDLS
+ /*
+ * XXX - HP-UX 10.20 and 11.xx don't appear to support sending and
+ * receiving packets on the same descriptor - you need separate
+ * descriptors for sending and receiving, bound to different SAPs.
+ *
+ * If the open fails, we just leave -1 in "pd->send_fd" and reject
+ * attempts to send packets, just as if, in pcap-bpf.c, we fail
+ * to open the BPF device for reading and writing, we just try
+ * to open it for reading only and, if that succeeds, just let
+ * the send attempts fail.
+ */
+ pd->send_fd = open("/dev/dlpi", O_RDWR);
+#endif
+
+ /*
+ ** Attach if "style 2" provider
+ */
+ if (dlinforeq(p->fd, p->errbuf) < 0 ||
+ dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
+#ifdef HAVE_SOLARIS
+ if (infop->dl_mac_type == DL_IPATM)
+ isatm = 1;
+#endif
+ if (infop->dl_provider_style == DL_STYLE2) {
+ retv = dl_doattach(p->fd, ppa, p->errbuf);
+ if (retv < 0) {
+ status = retv;
+ goto bad;
+ }
+#ifdef DL_HP_RAWDLS
+ if (pd->send_fd >= 0) {
+ retv = dl_doattach(pd->send_fd, ppa, p->errbuf);
+ if (retv < 0) {
+ status = retv;
+ goto bad;
+ }
+ }
+#endif
+ }
+
+ if (p->opt.rfmon) {
+ /*
+ * This device exists, but we don't support monitor mode
+ * any platforms that support DLPI.
+ */
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+
+#ifdef HAVE_DL_PASSIVE_REQ_T
+ /*
+ * Enable Passive mode to be able to capture on aggregated link.
+ * Not supported in all Solaris versions.
+ */
+ dlpassive(p->fd, p->errbuf);
+#endif
+ /*
+ ** Bind (defer if using HP-UX 9 or HP-UX 10.20 or later, totally
+ ** skip if using SINIX)
+ */
+#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20_OR_LATER) && !defined(sinix)
+#ifdef _AIX
+ /*
+ ** AIX.
+ ** According to IBM's AIX Support Line, the dl_sap value
+ ** should not be less than 0x600 (1536) for standard Ethernet.
+ ** However, we seem to get DL_BADADDR - "DLSAP addr in improper
+ ** format or invalid" - errors if we use 1537 on the "tr0"
+ ** device, which, given that its name starts with "tr" and that
+ ** it's IBM, probably means a Token Ring device. (Perhaps we
+ ** need to use 1537 on "/dev/dlpi/en" because that device is for
+ ** D/I/X Ethernet, the "SAP" is actually an Ethernet type, and
+ ** it rejects invalid Ethernet types.)
+ **
+ ** So if 1537 fails, we try 2, as Hyung Sik Yoon of IBM Korea
+ ** says that works on Token Ring (he says that 0 does *not*
+ ** work; perhaps that's considered an invalid LLC SAP value - I
+ ** assume the SAP value in a DLPI bind is an LLC SAP for network
+ ** types that use 802.2 LLC).
+ */
+ if ((dlbindreq(p->fd, 1537, p->errbuf) < 0 &&
+ dlbindreq(p->fd, 2, p->errbuf) < 0) ||
+ dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#elif defined(DL_HP_RAWDLS)
+ /*
+ ** HP-UX 10.0x and 10.1x.
+ */
+ if (dl_dohpuxbind(p->fd, p->errbuf) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ if (pd->send_fd >= 0) {
+ /*
+ ** XXX - if this fails, just close send_fd and
+ ** set it to -1, so that you can't send but can
+ ** still receive?
+ */
+ if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ }
+#else /* neither AIX nor HP-UX */
+ /*
+ ** Not Sinix, and neither AIX nor HP-UX - Solaris, and any other
+ ** OS using DLPI.
+ **/
+ if (dlbindreq(p->fd, 0, p->errbuf) < 0 ||
+ dlbindack(p->fd, (char *)buf, p->errbuf, NULL) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif /* AIX vs. HP-UX vs. other */
+#endif /* !HP-UX 9 and !HP-UX 10.20 or later and !SINIX */
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+#ifdef HAVE_SOLARIS
+ if (isatm) {
+ /*
+ ** Have to turn on some special ATM promiscuous mode
+ ** for SunATM.
+ ** Do *NOT* turn regular promiscuous mode on; it doesn't
+ ** help, and may break things.
+ */
+ if (strioctl(p->fd, A_PROMISCON_REQ, 0, NULL) < 0) {
+ status = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "A_PROMISCON_REQ");
+ goto bad;
+ }
+ } else
+#endif
+ if (p->opt.promisc) {
+ /*
+ ** Enable promiscuous (not necessary on send FD)
+ */
+ retv = dlpromiscon(p, DL_PROMISC_PHYS);
+ if (retv < 0) {
+ if (retv == PCAP_ERROR_PERM_DENIED)
+ status = PCAP_ERROR_PROMISC_PERM_DENIED;
+ else
+ status = retv;
+ goto bad;
+ }
+
+ /*
+ ** Try to enable multicast (you would have thought
+ ** promiscuous would be sufficient). (Skip if using
+ ** HP-UX or SINIX) (Not necessary on send FD)
+ */
+#if !defined(__hpux) && !defined(sinix)
+ retv = dlpromiscon(p, DL_PROMISC_MULTI);
+ if (retv < 0)
+ status = PCAP_WARNING;
+#endif
+ }
+ /*
+ ** Try to enable SAP promiscuity (when not in promiscuous mode
+ ** when using HP-UX, when not doing SunATM on Solaris, and never
+ ** under SINIX) (Not necessary on send FD)
+ */
+#ifndef sinix
+#if defined(__hpux)
+ /* HP-UX - only do this when not in promiscuous mode */
+ if (!p->opt.promisc) {
+#elif defined(HAVE_SOLARIS)
+ /* Solaris - don't do this on SunATM devices */
+ if (!isatm) {
+#else
+ /* Everything else (except for SINIX) - always do this */
+ {
+#endif
+ retv = dlpromiscon(p, DL_PROMISC_SAP);
+ if (retv < 0) {
+ if (p->opt.promisc) {
+ /*
+ * Not fatal, since the DL_PROMISC_PHYS mode
+ * worked.
+ *
+ * Report it as a warning, however.
+ */
+ status = PCAP_WARNING;
+ } else {
+ /*
+ * Fatal.
+ */
+ status = retv;
+ goto bad;
+ }
+ }
+ }
+#endif /* sinix */
+
+ /*
+ ** HP-UX 9, and HP-UX 10.20 or later, must bind after setting
+ ** promiscuous options.
+ */
+#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20_OR_LATER)
+ if (dl_dohpuxbind(p->fd, p->errbuf) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ /*
+ ** We don't set promiscuous mode on the send FD, but we'll defer
+ ** binding it anyway, just to keep the HP-UX 9/10.20 or later
+ ** code together.
+ */
+ if (pd->send_fd >= 0) {
+ /*
+ ** XXX - if this fails, just close send_fd and
+ ** set it to -1, so that you can't send but can
+ ** still receive?
+ */
+ if (dl_dohpuxbind(pd->send_fd, p->errbuf) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+ }
+#endif
+
+ /*
+ ** Determine link type
+ ** XXX - get SAP length and address length as well, for use
+ ** when sending packets.
+ */
+ if (dlinforeq(p->fd, p->errbuf) < 0 ||
+ dlinfoack(p->fd, (char *)buf, p->errbuf) < 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ infop = &(MAKE_DL_PRIMITIVES(buf))->info_ack;
+ if (pcap_process_mactype(p, infop->dl_mac_type) != 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+#ifdef DLIOCRAW
+ /*
+ ** This is a non standard SunOS hack to get the full raw link-layer
+ ** header.
+ */
+ if (strioctl(p->fd, DLIOCRAW, 0, NULL) < 0) {
+ status = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "DLIOCRAW");
+ goto bad;
+ }
+#endif
+
+#ifdef HAVE_SYS_BUFMOD_H
+ ss = p->snapshot;
+
+ /*
+ ** There is a bug in bufmod(7). When dealing with messages of
+ ** less than snaplen size it strips data from the beginning not
+ ** the end.
+ **
+ ** This bug is fixed in 5.3.2. Also, there is a patch available.
+ ** Ask for bugid 1149065.
+ */
+#ifdef HAVE_SOLARIS
+ get_release(release, sizeof (release), &osmajor, &osminor, &osmicro);
+ if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) &&
+ getenv("BUFMOD_FIXED") == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.",
+ release);
+ ss = 0;
+ status = PCAP_WARNING;
+ }
+#endif
+
+ /* Push and configure bufmod. */
+ if (pcap_conf_bufmod(p, ss) != 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+#endif
+
+ /*
+ ** As the last operation flush the read side.
+ */
+ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
+ status = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "FLUSHR");
+ goto bad;
+ }
+
+ /* Allocate data buffer. */
+ if (pcap_alloc_databuf(p) != 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Success.
+ *
+ * "p->fd" is an FD for a STREAMS device, so "select()" and
+ * "poll()" should work on it.
+ */
+ p->selectable_fd = p->fd;
+
+ p->read_op = pcap_read_dlpi;
+ p->inject_op = pcap_inject_dlpi;
+ p->setfilter_op = install_bpf_program; /* no kernel filtering */
+ p->setdirection_op = NULL; /* Not implemented.*/
+ p->set_datalink_op = NULL; /* can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_stats_dlpi;
+ p->cleanup_op = pcap_cleanup_dlpi;
+
+ return (status);
+bad:
+ pcap_cleanup_dlpi(p);
+ return (status);
+}
+
+/*
+ * Split a device name into a device type name and a unit number;
+ * return the a pointer to the beginning of the unit number, which
+ * is the end of the device type name, and set "*unitp" to the unit
+ * number.
+ *
+ * Returns NULL on error, and fills "ebuf" with an error message.
+ */
+static char *
+split_dname(char *device, u_int *unitp, char *ebuf)
+{
+ char *cp;
+ char *eos;
+ long unit;
+
+ /*
+ * Look for a number at the end of the device name string.
+ */
+ cp = device + strlen(device) - 1;
+ if (*cp < '0' || *cp > '9') {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s missing unit number",
+ device);
+ return (NULL);
+ }
+
+ /* Digits at end of string are unit number */
+ while (cp-1 >= device && *(cp-1) >= '0' && *(cp-1) <= '9')
+ cp--;
+
+ errno = 0;
+ unit = strtol(cp, &eos, 10);
+ if (*eos != '\0') {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device);
+ return (NULL);
+ }
+ if (errno == ERANGE || unit > INT_MAX) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number too large",
+ device);
+ return (NULL);
+ }
+ if (unit < 0) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s unit number is negative",
+ device);
+ return (NULL);
+ }
+ *unitp = (u_int)unit;
+ return (cp);
+}
+
+static int
+dl_doattach(int fd, int ppa, char *ebuf)
+{
+ dl_attach_req_t req;
+ bpf_u_int32 buf[MAXDLBUF];
+ int err;
+
+ req.dl_primitive = DL_ATTACH_REQ;
+ req.dl_ppa = ppa;
+ if (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf) < 0)
+ return (PCAP_ERROR);
+
+ err = dlokack(fd, "attach", (char *)buf, ebuf);
+ if (err < 0)
+ return (err);
+ return (0);
+}
+
+#ifdef DL_HP_RAWDLS
+static int
+dl_dohpuxbind(int fd, char *ebuf)
+{
+ int hpsap;
+ int uerror;
+ bpf_u_int32 buf[MAXDLBUF];
+
+ /*
+ * XXX - we start at 22 because we used to use only 22, but
+ * that was just because that was the value used in some
+ * sample code from HP. With what value *should* we start?
+ * Does it matter, given that we're enabling SAP promiscuity
+ * on the input FD?
+ */
+ hpsap = 22;
+ for (;;) {
+ if (dlbindreq(fd, hpsap, ebuf) < 0)
+ return (-1);
+ if (dlbindack(fd, (char *)buf, ebuf, &uerror) >= 0)
+ break;
+ /*
+ * For any error other than a UNIX EBUSY, give up.
+ */
+ if (uerror != EBUSY) {
+ /*
+ * dlbindack() has already filled in ebuf for
+ * this error.
+ */
+ return (-1);
+ }
+
+ /*
+ * For EBUSY, try the next SAP value; that means that
+ * somebody else is using that SAP. Clear ebuf so
+ * that application doesn't report the "Device busy"
+ * error as a warning.
+ */
+ *ebuf = '\0';
+ hpsap++;
+ if (hpsap > 100) {
+ pcap_strlcpy(ebuf,
+ "All SAPs from 22 through 100 are in use",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+ }
+ return (0);
+}
+#endif
+
+#define STRINGIFY(n) #n
+
+static int
+dlpromiscon(pcap_t *p, bpf_u_int32 level)
+{
+ dl_promiscon_req_t req;
+ bpf_u_int32 buf[MAXDLBUF];
+ int err;
+
+ req.dl_primitive = DL_PROMISCON_REQ;
+ req.dl_level = level;
+ if (send_request(p->fd, (char *)&req, sizeof(req), "promiscon",
+ p->errbuf) < 0)
+ return (PCAP_ERROR);
+ err = dlokack(p->fd, "promiscon" STRINGIFY(level), (char *)buf,
+ p->errbuf);
+ if (err < 0)
+ return (err);
+ return (0);
+}
+
+/*
+ * Not all interfaces are DLPI interfaces, and thus not all interfaces
+ * can be opened with DLPI (for example, the loopback interface is not
+ * a DLPI interface on Solaris prior to Solaris 11), so try to open
+ * the specified interface; return 0 if we fail with PCAP_ERROR_NO_SUCH_DEVICE
+ * and 1 otherwise.
+ */
+static int
+is_dlpi_interface(const char *name)
+{
+ int fd;
+ u_int ppa;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ fd = open_dlpi_device(name, &ppa, errbuf);
+ if (fd < 0) {
+ /*
+ * Error - was it PCAP_ERROR_NO_SUCH_DEVICE?
+ */
+ if (fd == PCAP_ERROR_NO_SUCH_DEVICE) {
+ /*
+ * Yes, so we can't open this because it's
+ * not a DLPI interface.
+ */
+ return (0);
+ }
+ /*
+ * No, so, in the case where there's a single DLPI
+ * device for all interfaces of this type ("style
+ * 2" providers?), we don't know whether it's a DLPI
+ * interface or not, as we didn't try an attach.
+ * Say it is a DLPI device, so that the user can at
+ * least try to open it and report the error (which
+ * is probably "you don't have permission to open that
+ * DLPI device"; reporting those interfaces means
+ * users will ask "why am I getting a permissions error
+ * when I try to capture" rather than "why am I not
+ * seeing any interfaces", making the underlying problem
+ * clearer).
+ */
+ return (1);
+ }
+
+ /*
+ * Success.
+ */
+ close(fd);
+ return (1);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do other than mark loopback devices as "the
+ * connected/disconnected status doesn't apply".
+ *
+ * XXX - on Solaris, can we do what the dladm command does,
+ * i.e. get a connected/disconnected indication from a kstat?
+ * (Note that you can also get the link speed, and possibly
+ * other information, from a kstat as well.)
+ */
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback devices aren't wireless, and "connected"/
+ * "disconnected" doesn't apply to them.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return (0);
+ }
+ return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+#ifdef HAVE_SOLARIS
+ int fd;
+ union {
+ u_int nunits;
+ char pad[516]; /* XXX - must be at least 513; is 516
+ in "atmgetunits" */
+ } buf;
+ char baname[2+1+1];
+ u_int i;
+#endif
+
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(devlistp, errbuf, is_dlpi_interface,
+ get_if_flags) == -1)
+ return (-1); /* failure */
+
+#ifdef HAVE_SOLARIS
+ /*
+ * We may have to do special magic to get ATM devices.
+ */
+ if ((fd = open("/dev/ba", O_RDWR)) < 0) {
+ /*
+ * We couldn't open the "ba" device.
+ * For now, just give up; perhaps we should
+ * return an error if the problem is neither
+ * a "that device doesn't exist" error (ENOENT,
+ * ENXIO, etc.) or a "you're not allowed to do
+ * that" error (EPERM, EACCES).
+ */
+ return (0);
+ }
+
+ if (strioctl(fd, A_GET_UNITS, sizeof(buf), (char *)&buf) < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "A_GET_UNITS");
+ return (-1);
+ }
+ for (i = 0; i < buf.nunits; i++) {
+ pcap_snprintf(baname, sizeof baname, "ba%u", i);
+ /*
+ * XXX - is there a notion of "up" and "running"?
+ * And is there a way to determine whether the
+ * interface is plugged into a network?
+ */
+ if (add_dev(devlistp, baname, 0, NULL, errbuf) == NULL)
+ return (-1);
+ }
+#endif
+
+ return (0);
+}
+
+static int
+send_request(int fd, char *ptr, int len, char *what, char *ebuf)
+{
+ struct strbuf ctl;
+ int flags;
+
+ ctl.maxlen = 0;
+ ctl.len = len;
+ ctl.buf = ptr;
+
+ flags = 0;
+ if (putmsg(fd, &ctl, (struct strbuf *) NULL, flags) < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "send_request: putmsg \"%s\"", what);
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf, int *uerror)
+{
+ union DL_primitives *dlp;
+ struct strbuf ctl;
+ int flags;
+ char errmsgbuf[PCAP_ERRBUF_SIZE];
+ char dlprimbuf[64];
+
+ /*
+ * Clear out "*uerror", so it's only set for DL_ERROR_ACK/DL_SYSERR,
+ * making that the only place where EBUSY is treated specially.
+ */
+ if (uerror != NULL)
+ *uerror = 0;
+
+ ctl.maxlen = MAXDLBUF;
+ ctl.len = 0;
+ ctl.buf = bufp;
+
+ flags = 0;
+ if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "recv_ack: %s getmsg", what);
+ return (PCAP_ERROR);
+ }
+
+ dlp = MAKE_DL_PRIMITIVES(ctl.buf);
+ switch (dlp->dl_primitive) {
+
+ case DL_INFO_ACK:
+ case DL_BIND_ACK:
+ case DL_OK_ACK:
+#ifdef DL_HP_PPA_ACK
+ case DL_HP_PPA_ACK:
+#endif
+ /* These are OK */
+ break;
+
+ case DL_ERROR_ACK:
+ switch (dlp->error_ack.dl_errno) {
+
+ case DL_SYSERR:
+ if (uerror != NULL)
+ *uerror = dlp->error_ack.dl_unix_errno;
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ dlp->error_ack.dl_unix_errno,
+ "recv_ack: %s: UNIX error", what);
+ if (dlp->error_ack.dl_unix_errno == EPERM ||
+ dlp->error_ack.dl_unix_errno == EACCES)
+ return (PCAP_ERROR_PERM_DENIED);
+ break;
+
+ default:
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "recv_ack: %s: %s", what,
+ dlstrerror(errmsgbuf, sizeof (errmsgbuf), dlp->error_ack.dl_errno));
+ if (dlp->error_ack.dl_errno == DL_BADPPA)
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ else if (dlp->error_ack.dl_errno == DL_ACCESS)
+ return (PCAP_ERROR_PERM_DENIED);
+ break;
+ }
+ return (PCAP_ERROR);
+
+ default:
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "recv_ack: %s: Unexpected primitive ack %s",
+ what, dlprim(dlprimbuf, sizeof (dlprimbuf), dlp->dl_primitive));
+ return (PCAP_ERROR);
+ }
+
+ if (ctl.len < size) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "recv_ack: %s: Ack too small (%d < %d)",
+ what, ctl.len, size);
+ return (PCAP_ERROR);
+ }
+ return (ctl.len);
+}
+
+static char *
+dlstrerror(char *errbuf, size_t errbufsize, bpf_u_int32 dl_errno)
+{
+ switch (dl_errno) {
+
+ case DL_ACCESS:
+ return ("Improper permissions for request");
+
+ case DL_BADADDR:
+ return ("DLSAP addr in improper format or invalid");
+
+ case DL_BADCORR:
+ return ("Seq number not from outstand DL_CONN_IND");
+
+ case DL_BADDATA:
+ return ("User data exceeded provider limit");
+
+ case DL_BADPPA:
+#ifdef HAVE_DEV_DLPI
+ /*
+ * With a single "/dev/dlpi" device used for all
+ * DLPI providers, PPAs have nothing to do with
+ * unit numbers.
+ */
+ return ("Specified PPA was invalid");
+#else
+ /*
+ * We have separate devices for separate devices;
+ * the PPA is just the unit number.
+ */
+ return ("Specified PPA (device unit) was invalid");
+#endif
+
+ case DL_BADPRIM:
+ return ("Primitive received not known by provider");
+
+ case DL_BADQOSPARAM:
+ return ("QOS parameters contained invalid values");
+
+ case DL_BADQOSTYPE:
+ return ("QOS structure type is unknown/unsupported");
+
+ case DL_BADSAP:
+ return ("Bad LSAP selector");
+
+ case DL_BADTOKEN:
+ return ("Token used not an active stream");
+
+ case DL_BOUND:
+ return ("Attempted second bind with dl_max_conind");
+
+ case DL_INITFAILED:
+ return ("Physical link initialization failed");
+
+ case DL_NOADDR:
+ return ("Provider couldn't allocate alternate address");
+
+ case DL_NOTINIT:
+ return ("Physical link not initialized");
+
+ case DL_OUTSTATE:
+ return ("Primitive issued in improper state");
+
+ case DL_SYSERR:
+ return ("UNIX system error occurred");
+
+ case DL_UNSUPPORTED:
+ return ("Requested service not supplied by provider");
+
+ case DL_UNDELIVERABLE:
+ return ("Previous data unit could not be delivered");
+
+ case DL_NOTSUPPORTED:
+ return ("Primitive is known but not supported");
+
+ case DL_TOOMANY:
+ return ("Limit exceeded");
+
+ case DL_NOTENAB:
+ return ("Promiscuous mode not enabled");
+
+ case DL_BUSY:
+ return ("Other streams for PPA in post-attached");
+
+ case DL_NOAUTO:
+ return ("Automatic handling XID&TEST not supported");
+
+ case DL_NOXIDAUTO:
+ return ("Automatic handling of XID not supported");
+
+ case DL_NOTESTAUTO:
+ return ("Automatic handling of TEST not supported");
+
+ case DL_XIDAUTO:
+ return ("Automatic handling of XID response");
+
+ case DL_TESTAUTO:
+ return ("Automatic handling of TEST response");
+
+ case DL_PENDING:
+ return ("Pending outstanding connect indications");
+
+ default:
+ pcap_snprintf(errbuf, errbufsize, "Error %02x", dl_errno);
+ return (errbuf);
+ }
+}
+
+static char *
+dlprim(char *primbuf, size_t primbufsize, bpf_u_int32 prim)
+{
+ switch (prim) {
+
+ case DL_INFO_REQ:
+ return ("DL_INFO_REQ");
+
+ case DL_INFO_ACK:
+ return ("DL_INFO_ACK");
+
+ case DL_ATTACH_REQ:
+ return ("DL_ATTACH_REQ");
+
+ case DL_DETACH_REQ:
+ return ("DL_DETACH_REQ");
+
+ case DL_BIND_REQ:
+ return ("DL_BIND_REQ");
+
+ case DL_BIND_ACK:
+ return ("DL_BIND_ACK");
+
+ case DL_UNBIND_REQ:
+ return ("DL_UNBIND_REQ");
+
+ case DL_OK_ACK:
+ return ("DL_OK_ACK");
+
+ case DL_ERROR_ACK:
+ return ("DL_ERROR_ACK");
+
+ case DL_SUBS_BIND_REQ:
+ return ("DL_SUBS_BIND_REQ");
+
+ case DL_SUBS_BIND_ACK:
+ return ("DL_SUBS_BIND_ACK");
+
+ case DL_UNITDATA_REQ:
+ return ("DL_UNITDATA_REQ");
+
+ case DL_UNITDATA_IND:
+ return ("DL_UNITDATA_IND");
+
+ case DL_UDERROR_IND:
+ return ("DL_UDERROR_IND");
+
+ case DL_UDQOS_REQ:
+ return ("DL_UDQOS_REQ");
+
+ case DL_CONNECT_REQ:
+ return ("DL_CONNECT_REQ");
+
+ case DL_CONNECT_IND:
+ return ("DL_CONNECT_IND");
+
+ case DL_CONNECT_RES:
+ return ("DL_CONNECT_RES");
+
+ case DL_CONNECT_CON:
+ return ("DL_CONNECT_CON");
+
+ case DL_TOKEN_REQ:
+ return ("DL_TOKEN_REQ");
+
+ case DL_TOKEN_ACK:
+ return ("DL_TOKEN_ACK");
+
+ case DL_DISCONNECT_REQ:
+ return ("DL_DISCONNECT_REQ");
+
+ case DL_DISCONNECT_IND:
+ return ("DL_DISCONNECT_IND");
+
+ case DL_RESET_REQ:
+ return ("DL_RESET_REQ");
+
+ case DL_RESET_IND:
+ return ("DL_RESET_IND");
+
+ case DL_RESET_RES:
+ return ("DL_RESET_RES");
+
+ case DL_RESET_CON:
+ return ("DL_RESET_CON");
+
+ default:
+ pcap_snprintf(primbuf, primbufsize, "unknown primitive 0x%x",
+ prim);
+ return (primbuf);
+ }
+}
+
+static int
+dlbindreq(int fd, bpf_u_int32 sap, char *ebuf)
+{
+
+ dl_bind_req_t req;
+
+ memset((char *)&req, 0, sizeof(req));
+ req.dl_primitive = DL_BIND_REQ;
+ /* XXX - what if neither of these are defined? */
+#if defined(DL_HP_RAWDLS)
+ req.dl_max_conind = 1; /* XXX magic number */
+ req.dl_service_mode = DL_HP_RAWDLS;
+#elif defined(DL_CLDLS)
+ req.dl_service_mode = DL_CLDLS;
+#endif
+ req.dl_sap = sap;
+
+ return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf));
+}
+
+static int
+dlbindack(int fd, char *bufp, char *ebuf, int *uerror)
+{
+
+ return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf, uerror));
+}
+
+static int
+dlokack(int fd, const char *what, char *bufp, char *ebuf)
+{
+
+ return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf, NULL));
+}
+
+
+static int
+dlinforeq(int fd, char *ebuf)
+{
+ dl_info_req_t req;
+
+ req.dl_primitive = DL_INFO_REQ;
+
+ return (send_request(fd, (char *)&req, sizeof(req), "info", ebuf));
+}
+
+static int
+dlinfoack(int fd, char *bufp, char *ebuf)
+{
+
+ return (recv_ack(fd, DL_INFO_ACK_SIZE, "info", bufp, ebuf, NULL));
+}
+
+#ifdef HAVE_DL_PASSIVE_REQ_T
+/*
+ * Enable DLPI passive mode. We do not care if this request fails, as this
+ * indicates the underlying DLPI device does not support link aggregation.
+ */
+static void
+dlpassive(int fd, char *ebuf)
+{
+ dl_passive_req_t req;
+ bpf_u_int32 buf[MAXDLBUF];
+
+ req.dl_primitive = DL_PASSIVE_REQ;
+
+ if (send_request(fd, (char *)&req, sizeof(req), "dlpassive", ebuf) == 0)
+ (void) dlokack(fd, "dlpassive", (char *)buf, ebuf);
+}
+#endif
+
+#ifdef DL_HP_RAWDLS
+/*
+ * There's an ack *if* there's an error.
+ */
+static int
+dlrawdatareq(int fd, const u_char *datap, int datalen)
+{
+ struct strbuf ctl, data;
+ long buf[MAXDLBUF]; /* XXX - char? */
+ union DL_primitives *dlp;
+ int dlen;
+
+ dlp = MAKE_DL_PRIMITIVES(buf);
+
+ dlp->dl_primitive = DL_HP_RAWDATA_REQ;
+ dlen = DL_HP_RAWDATA_REQ_SIZE;
+
+ /*
+ * HP's documentation doesn't appear to show us supplying any
+ * address pointed to by the control part of the message.
+ * I think that's what raw mode means - you just send the raw
+ * packet, you don't specify where to send it to, as that's
+ * implied by the destination address.
+ */
+ ctl.maxlen = 0;
+ ctl.len = dlen;
+ ctl.buf = (void *)buf;
+
+ data.maxlen = 0;
+ data.len = datalen;
+ data.buf = (void *)datap;
+
+ return (putmsg(fd, &ctl, &data, 0));
+}
+#endif /* DL_HP_RAWDLS */
+
+#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H)
+static void
+get_release(char *buf, size_t bufsize, bpf_u_int32 *majorp,
+ bpf_u_int32 *minorp, bpf_u_int32 *microp)
+{
+ char *cp;
+
+ *majorp = 0;
+ *minorp = 0;
+ *microp = 0;
+ if (sysinfo(SI_RELEASE, buf, bufsize) < 0) {
+ pcap_strlcpy(buf, "?", bufsize);
+ return;
+ }
+ cp = buf;
+ if (!isdigit((unsigned char)*cp))
+ return;
+ *majorp = strtol(cp, &cp, 10);
+ if (*cp++ != '.')
+ return;
+ *minorp = strtol(cp, &cp, 10);
+ if (*cp++ != '.')
+ return;
+ *microp = strtol(cp, &cp, 10);
+}
+#endif
+
+#ifdef DL_HP_PPA_REQ
+/*
+ * Under HP-UX 10 and HP-UX 11, we can ask for the ppa
+ */
+
+
+/*
+ * Determine ppa number that specifies ifname.
+ *
+ * If the "dl_hp_ppa_info_t" doesn't have a "dl_module_id_1" member,
+ * the code that's used here is the old code for HP-UX 10.x.
+ *
+ * However, HP-UX 10.20, at least, appears to have such a member
+ * in its "dl_hp_ppa_info_t" structure, so the new code is used.
+ * The new code didn't work on an old 10.20 system on which Rick
+ * Jones of HP tried it, but with later patches installed, it
+ * worked - it appears that the older system had those members but
+ * didn't put anything in them, so, if the search by name fails, we
+ * do the old search.
+ *
+ * Rick suggests that making sure your system is "up on the latest
+ * lancommon/DLPI/driver patches" is probably a good idea; it'd fix
+ * that problem, as well as allowing libpcap to see packets sent
+ * from the system on which the libpcap application is being run.
+ * (On 10.20, in addition to getting the latest patches, you need
+ * to turn the kernel "lanc_outbound_promisc_flag" flag on with ADB;
+ * a posting to "comp.sys.hp.hpux" at
+ *
+ * http://www.deja.com/[ST_rn=ps]/getdoc.xp?AN=558092266
+ *
+ * says that, to see the machine's outgoing traffic, you'd need to
+ * apply the right patches to your system, and also set that variable
+ * with:
+
+echo 'lanc_outbound_promisc_flag/W1' | /usr/bin/adb -w /stand/vmunix /dev/kmem
+
+ * which could be put in, for example, "/sbin/init.d/lan".
+ *
+ * Setting the variable is not necessary on HP-UX 11.x.
+ */
+static int
+get_dlpi_ppa(register int fd, register const char *device, register u_int unit,
+ u_int *ppa, register char *ebuf)
+{
+ register dl_hp_ppa_ack_t *ap;
+ register dl_hp_ppa_info_t *ipstart, *ip;
+ register u_int i;
+ char dname[100];
+ register u_long majdev;
+ struct stat statbuf;
+ dl_hp_ppa_req_t req;
+ char buf[MAXDLBUF];
+ char *ppa_data_buf;
+ dl_hp_ppa_ack_t *dlp;
+ struct strbuf ctl;
+ int flags;
+
+ memset((char *)&req, 0, sizeof(req));
+ req.dl_primitive = DL_HP_PPA_REQ;
+
+ memset((char *)buf, 0, sizeof(buf));
+ if (send_request(fd, (char *)&req, sizeof(req), "hpppa", ebuf) < 0)
+ return (PCAP_ERROR);
+
+ ctl.maxlen = DL_HP_PPA_ACK_SIZE;
+ ctl.len = 0;
+ ctl.buf = (char *)buf;
+
+ flags = 0;
+ /*
+ * DLPI may return a big chunk of data for a DL_HP_PPA_REQ. The normal
+ * recv_ack will fail because it set the maxlen to MAXDLBUF (8192)
+ * which is NOT big enough for a DL_HP_PPA_REQ.
+ *
+ * This causes libpcap applications to fail on a system with HP-APA
+ * installed.
+ *
+ * To figure out how big the returned data is, we first call getmsg
+ * to get the small head and peek at the head to get the actual data
+ * length, and then issue another getmsg to get the actual PPA data.
+ */
+ /* get the head first */
+ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "get_dlpi_ppa: hpppa getmsg");
+ return (PCAP_ERROR);
+ }
+ if (ctl.len == -1) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
+ return (PCAP_ERROR);
+ }
+
+ dlp = (dl_hp_ppa_ack_t *)ctl.buf;
+ if (dlp->dl_primitive != DL_HP_PPA_ACK) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x",
+ (bpf_u_int32)dlp->dl_primitive);
+ return (PCAP_ERROR);
+ }
+
+ if ((size_t)ctl.len < DL_HP_PPA_ACK_SIZE) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
+ ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE);
+ return (PCAP_ERROR);
+ }
+
+ /* allocate buffer */
+ if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "get_dlpi_ppa: hpppa malloc");
+ return (PCAP_ERROR);
+ }
+ ctl.maxlen = dlp->dl_length;
+ ctl.len = 0;
+ ctl.buf = (char *)ppa_data_buf;
+ /* get the data */
+ if (getmsg(fd, &ctl, (struct strbuf *)NULL, &flags) < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "get_dlpi_ppa: hpppa getmsg");
+ free(ppa_data_buf);
+ return (PCAP_ERROR);
+ }
+ if (ctl.len == -1) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "get_dlpi_ppa: hpppa getmsg: control buffer has no data");
+ return (PCAP_ERROR);
+ }
+ if ((u_int)ctl.len < dlp->dl_length) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "get_dlpi_ppa: hpppa ack too small (%d < %lu)",
+ ctl.len, (unsigned long)dlp->dl_length);
+ free(ppa_data_buf);
+ return (PCAP_ERROR);
+ }
+
+ ap = (dl_hp_ppa_ack_t *)buf;
+ ipstart = (dl_hp_ppa_info_t *)ppa_data_buf;
+ ip = ipstart;
+
+#ifdef HAVE_DL_HP_PPA_INFO_T_DL_MODULE_ID_1
+ /*
+ * The "dl_hp_ppa_info_t" structure has a "dl_module_id_1"
+ * member that should, in theory, contain the part of the
+ * name for the device that comes before the unit number,
+ * and should also have a "dl_module_id_2" member that may
+ * contain an alternate name (e.g., I think Ethernet devices
+ * have both "lan", for "lanN", and "snap", for "snapN", with
+ * the former being for Ethernet packets and the latter being
+ * for 802.3/802.2 packets).
+ *
+ * Search for the device that has the specified name and
+ * instance number.
+ */
+ for (i = 0; i < ap->dl_count; i++) {
+ if ((strcmp((const char *)ip->dl_module_id_1, device) == 0 ||
+ strcmp((const char *)ip->dl_module_id_2, device) == 0) &&
+ ip->dl_instance_num == unit)
+ break;
+
+ ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
+ }
+#else
+ /*
+ * We don't have that member, so the search is impossible; make it
+ * look as if the search failed.
+ */
+ i = ap->dl_count;
+#endif
+
+ if (i == ap->dl_count) {
+ /*
+ * Well, we didn't, or can't, find the device by name.
+ *
+ * HP-UX 10.20, whilst it has "dl_module_id_1" and
+ * "dl_module_id_2" fields in the "dl_hp_ppa_info_t",
+ * doesn't seem to fill them in unless the system is
+ * at a reasonably up-to-date patch level.
+ *
+ * Older HP-UX 10.x systems might not have those fields
+ * at all.
+ *
+ * Therefore, we'll search for the entry with the major
+ * device number of a device with the name "/dev/<dev><unit>",
+ * if such a device exists, as the old code did.
+ */
+ pcap_snprintf(dname, sizeof(dname), "/dev/%s%u", device, unit);
+ if (stat(dname, &statbuf) < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "stat: %s", dname);
+ return (PCAP_ERROR);
+ }
+ majdev = major(statbuf.st_rdev);
+
+ ip = ipstart;
+
+ for (i = 0; i < ap->dl_count; i++) {
+ if (ip->dl_mjr_num == majdev &&
+ ip->dl_instance_num == unit)
+ break;
+
+ ip = (dl_hp_ppa_info_t *)((u_char *)ipstart + ip->dl_next_offset);
+ }
+ }
+ if (i == ap->dl_count) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "can't find /dev/dlpi PPA for %s%u", device, unit);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ }
+ if (ip->dl_hdw_state == HDW_DEAD) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "%s%d: hardware state: DOWN\n", device, unit);
+ free(ppa_data_buf);
+ return (PCAP_ERROR);
+ }
+ *ppa = ip->dl_ppa;
+ free(ppa_data_buf);
+ return (0);
+}
+#endif
+
+#ifdef HAVE_HPUX9
+/*
+ * Under HP-UX 9, there is no good way to determine the ppa.
+ * So punt and read it from /dev/kmem.
+ */
+static struct nlist nl[] = {
+#define NL_IFNET 0
+ { "ifnet" },
+ { "" }
+};
+
+static char path_vmunix[] = "/hp-ux";
+
+/* Determine ppa number that specifies ifname */
+static int
+get_dlpi_ppa(register int fd, register const char *ifname, register u_int unit,
+ u_int *ppa, register char *ebuf)
+{
+ register const char *cp;
+ register int kd;
+ void *addr;
+ struct ifnet ifnet;
+ char if_name[sizeof(ifnet.if_name) + 1];
+
+ cp = strrchr(ifname, '/');
+ if (cp != NULL)
+ ifname = cp + 1;
+ if (nlist(path_vmunix, &nl) < 0) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed",
+ path_vmunix);
+ return (PCAP_ERROR);
+ }
+ if (nl[NL_IFNET].n_value == 0) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "could't find %s kernel symbol",
+ nl[NL_IFNET].n_name);
+ return (PCAP_ERROR);
+ }
+ kd = open("/dev/kmem", O_RDONLY);
+ if (kd < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "kmem open");
+ return (PCAP_ERROR);
+ }
+ if (dlpi_kread(kd, nl[NL_IFNET].n_value,
+ &addr, sizeof(addr), ebuf) < 0) {
+ close(kd);
+ return (PCAP_ERROR);
+ }
+ for (; addr != NULL; addr = ifnet.if_next) {
+ if (dlpi_kread(kd, (off_t)addr,
+ &ifnet, sizeof(ifnet), ebuf) < 0 ||
+ dlpi_kread(kd, (off_t)ifnet.if_name,
+ if_name, sizeof(ifnet.if_name), ebuf) < 0) {
+ (void)close(kd);
+ return (PCAP_ERROR);
+ }
+ if_name[sizeof(ifnet.if_name)] = '\0';
+ if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) {
+ *ppa = ifnet.if_index;
+ return (0);
+ }
+ }
+
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname);
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+}
+
+static int
+dlpi_kread(register int fd, register off_t addr,
+ register void *buf, register u_int len, register char *ebuf)
+{
+ register int cc;
+
+ if (lseek(fd, addr, SEEK_SET) < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "lseek");
+ return (-1);
+ }
+ cc = read(fd, buf, len);
+ if (cc < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "read");
+ return (-1);
+ } else if (cc != len) {
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc,
+ len);
+ return (-1);
+ }
+ return (cc);
+}
+#endif
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+#ifdef DL_HP_RAWDLS
+ struct pcap_dlpi *pd;
+#endif
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
+ if (p == NULL)
+ return (NULL);
+
+#ifdef DL_HP_RAWDLS
+ pd = p->priv;
+ pd->send_fd = -1; /* it hasn't been opened yet */
+#endif
+
+ p->activate_op = pcap_activate_dlpi;
+ return (p);
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-dos.c b/lib/libpcap/libpcap/pcap-dos.c
new file mode 100644
index 0000000..c159b55
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dos.c
@@ -0,0 +1,1536 @@
+/*
+ * This file is part of DOS-libpcap
+ * Ported to DOS/DOSX by G. Vanem <gvanem@yahoo.no>
+ *
+ * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
+ * network drivers.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <float.h>
+#include <fcntl.h>
+#include <io.h>
+
+#if defined(USE_32BIT_DRIVERS)
+ #include "msdos/pm_drvr/pmdrvr.h"
+ #include "msdos/pm_drvr/pci.h"
+ #include "msdos/pm_drvr/bios32.h"
+ #include "msdos/pm_drvr/module.h"
+ #include "msdos/pm_drvr/3c501.h"
+ #include "msdos/pm_drvr/3c503.h"
+ #include "msdos/pm_drvr/3c509.h"
+ #include "msdos/pm_drvr/3c59x.h"
+ #include "msdos/pm_drvr/3c515.h"
+ #include "msdos/pm_drvr/3c90x.h"
+ #include "msdos/pm_drvr/3c575_cb.h"
+ #include "msdos/pm_drvr/ne.h"
+ #include "msdos/pm_drvr/wd.h"
+ #include "msdos/pm_drvr/accton.h"
+ #include "msdos/pm_drvr/cs89x0.h"
+ #include "msdos/pm_drvr/rtl8139.h"
+ #include "msdos/pm_drvr/ne2k-pci.h"
+#endif
+
+#include "pcap.h"
+#include "pcap-dos.h"
+#include "pcap-int.h"
+#include "msdos/pktdrvr.h"
+
+#ifdef USE_NDIS2
+#include "msdos/ndis2.h"
+#endif
+
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#include <net/if_ether.h>
+#include <net/if_packe.h>
+#include <tcp.h>
+
+#if defined(USE_32BIT_DRIVERS)
+ #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0)
+ #define NDIS_NEXT_DEV &rtl8139_dev
+
+ static char *rx_pool = NULL;
+ static void init_32bit (void);
+
+ static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool);
+ static int pktq_check (struct rx_ringbuf *q);
+ static int pktq_inc_out (struct rx_ringbuf *q);
+ static int pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC;
+ static void pktq_clear (struct rx_ringbuf *q) LOCKED_FUNC;
+
+ static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) LOCKED_FUNC;
+ static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q);
+
+#else
+ #define FLUSHK() ((void)0)
+ #define NDIS_NEXT_DEV NULL
+#endif
+
+/*
+ * Internal variables/functions in Watt-32
+ */
+extern WORD _pktdevclass;
+extern BOOL _eth_is_init;
+extern int _w32_dynamic_host;
+extern int _watt_do_exit;
+extern int _watt_is_init;
+extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;
+extern void (*_w32_usr_post_init) (void);
+extern void (*_w32_print_hook)();
+
+extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */
+extern int pkt_get_mtu (void);
+
+static int ref_count = 0;
+
+static u_long mac_count = 0;
+static u_long filter_count = 0;
+
+static volatile BOOL exc_occured = 0;
+
+static struct device *handle_to_device [20];
+
+static int pcap_activate_dos (pcap_t *p);
+static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
+ u_char *data);
+static void pcap_cleanup_dos (pcap_t *p);
+static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
+static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
+static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
+
+static int ndis_probe (struct device *dev);
+static int pkt_probe (struct device *dev);
+
+static void close_driver (void);
+static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);
+static int first_init (const char *name, char *ebuf, int promisc);
+
+static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
+ const u_char *buf);
+
+/*
+ * These are the device we always support
+ */
+static struct device ndis_dev = {
+ "ndis",
+ "NDIS2 LanManager",
+ 0,
+ 0,0,0,0,0,0,
+ NDIS_NEXT_DEV, /* NULL or a 32-bit device */
+ ndis_probe
+ };
+
+static struct device pkt_dev = {
+ "pkt",
+ "Packet-Driver",
+ 0,
+ 0,0,0,0,0,0,
+ &ndis_dev,
+ pkt_probe
+ };
+
+static struct device *get_device (int fd)
+{
+ if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))
+ return (NULL);
+ return handle_to_device [fd-1];
+}
+
+/*
+ * Private data for capturing on MS-DOS.
+ */
+struct pcap_dos {
+ void (*wait_proc)(void); /* call proc while waiting */
+ struct pcap_stat stat;
+};
+
+pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dos));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_dos;
+ return (p);
+}
+
+/*
+ * Open MAC-driver with name 'device_name' for live capture of
+ * network packets.
+ */
+static int pcap_activate_dos (pcap_t *pcap)
+{
+ if (pcap->opt.rfmon) {
+ /*
+ * No monitor mode on DOS.
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (pcap->snapshot <= 0 || pcap->snapshot > MAXIMUM_SNAPLEN)
+ pcap->snapshot = MAXIMUM_SNAPLEN;
+
+ if (pcap->snapshot < ETH_MIN+8)
+ pcap->snapshot = ETH_MIN+8;
+
+ if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */
+ pcap->snapshot = ETH_MAX;
+
+ pcap->linktype = DLT_EN10MB; /* !! */
+ pcap->cleanup_op = pcap_cleanup_dos;
+ pcap->read_op = pcap_read_dos;
+ pcap->stats_op = pcap_stats_dos;
+ pcap->inject_op = pcap_sendpacket_dos;
+ pcap->setfilter_op = pcap_setfilter_dos;
+ pcap->setdirection_op = NULL; /* Not implemented.*/
+ pcap->fd = ++ref_count;
+
+ pcap->bufsize = ETH_MAX+100; /* add some margin */
+ pcap->buffer = calloc (pcap->bufsize, 1);
+
+ if (pcap->fd == 1) /* first time we're called */
+ {
+ if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
+ !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
+ {
+ /* XXX - free pcap->buffer? */
+ return (PCAP_ERROR);
+ }
+ atexit (close_driver);
+ }
+ else if (stricmp(active_dev->name,pcap->opt.device))
+ {
+ pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
+ "Cannot use different devices simultaneously "
+ "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
+ /* XXX - free pcap->buffer? */
+ return (PCAP_ERROR);
+ }
+ handle_to_device [pcap->fd-1] = active_dev;
+ return (0);
+}
+
+/*
+ * Poll the receiver queue and call the pcap callback-handler
+ * with the packet.
+ */
+static int
+pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
+{
+ struct pcap_dos *pd = p->priv;
+ struct pcap_pkthdr pcap;
+ struct timeval now, expiry = { 0,0 };
+ int rx_len = 0;
+
+ if (p->opt.timeout > 0)
+ {
+ gettimeofday2 (&now, NULL);
+ expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
+ expiry.tv_sec = now.tv_sec;
+ while (expiry.tv_usec >= 1000000L)
+ {
+ expiry.tv_usec -= 1000000L;
+ expiry.tv_sec++;
+ }
+ }
+
+ while (!exc_occured)
+ {
+ volatile struct device *dev; /* might be reset by sig_handler */
+
+ dev = get_device (p->fd);
+ if (!dev)
+ break;
+
+ PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);
+ FLUSHK();
+
+ /* If driver has a zero-copy receive facility, peek at the queue,
+ * filter it, do the callback and release the buffer.
+ */
+ if (dev->peek_rx_buf)
+ {
+ PCAP_ASSERT (dev->release_rx_buf);
+ rx_len = (*dev->peek_rx_buf) (&p->buffer);
+ }
+ else
+ {
+ rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot);
+ }
+
+ if (rx_len > 0) /* got a packet */
+ {
+ mac_count++;
+
+ FLUSHK();
+
+ pcap.caplen = min (rx_len, p->snapshot);
+ pcap.len = rx_len;
+
+ if (callback &&
+ (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
+ {
+ filter_count++;
+
+ /* Fix-me!! Should be time of arrival. Not time of
+ * capture.
+ */
+ gettimeofday2 (&pcap.ts, NULL);
+ (*callback) (data, &pcap, p->buffer);
+ }
+
+ if (dev->release_rx_buf)
+ (*dev->release_rx_buf) (p->buffer);
+
+ if (pcap_pkt_debug > 0)
+ {
+ if (callback == watt32_recv_hook)
+ dbug_write ("pcap_recv_hook\n");
+ else dbug_write ("pcap_read_op\n");
+ }
+ FLUSHK();
+ return (1);
+ }
+
+ /* Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return -2 to indicate that we were
+ * told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return (-2);
+ }
+
+ /* If not to wait for a packet or pcap_cleanup_dos() called from
+ * e.g. SIGINT handler, exit loop now.
+ */
+ if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
+ break;
+
+ gettimeofday2 (&now, NULL);
+
+ if (timercmp(&now, &expiry, >))
+ break;
+
+#ifndef DJGPP
+ kbhit(); /* a real CPU hog */
+#endif
+
+ if (pd->wait_proc)
+ (*pd->wait_proc)(); /* call yield func */
+ }
+
+ if (rx_len < 0) /* receive error */
+ {
+ pd->stat.ps_drop++;
+#ifdef USE_32BIT_DRIVERS
+ if (pcap_pkt_debug > 1)
+ printk ("pkt-err %s\n", pktInfo.error);
+#endif
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
+{
+ int rc, num = 0;
+
+ while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
+ {
+ if (p->fd <= 0)
+ return (-1);
+ rc = pcap_read_one (p, callback, data);
+ if (rc > 0)
+ num++;
+ if (rc < 0)
+ break;
+ _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */
+ }
+ return (num);
+}
+
+/*
+ * Return network statistics
+ */
+static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
+{
+ struct net_device_stats *stats;
+ struct pcap_dos *pd;
+ struct device *dev = p ? get_device(p->fd) : NULL;
+
+ if (!dev)
+ {
+ strcpy (p->errbuf, "illegal pcap handle");
+ return (-1);
+ }
+
+ if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)
+ {
+ strcpy (p->errbuf, "device statistics not available");
+ return (-1);
+ }
+
+ FLUSHK();
+
+ pd = p->priv;
+ pd->stat.ps_recv = stats->rx_packets;
+ pd->stat.ps_drop += stats->rx_missed_errors;
+ pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */
+ stats->rx_errors; /* HW errors */
+ if (ps)
+ *ps = pd->stat;
+
+ return (0);
+}
+
+/*
+ * Return detailed network/device statistics.
+ * May be called after 'dev->close' is called.
+ */
+int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
+{
+ struct device *dev = p ? get_device (p->fd) : NULL;
+
+ if (!dev || !dev->get_stats)
+ {
+ pcap_strlcpy (p->errbuf, "detailed device statistics not available",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+
+ if (!strnicmp(dev->name,"pkt",3))
+ {
+ pcap_strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+ memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
+ return (0);
+}
+
+/*
+ * Simply store the filter-code for the pcap_read_dos() callback
+ * Some day the filter-code could be handed down to the active
+ * device (pkt_rx1.s or 32-bit device interrupt handler).
+ */
+static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp)
+{
+ if (!p)
+ return (-1);
+ p->fcode = *fp;
+ return (0);
+}
+
+/*
+ * Return # of packets received in pcap_read_dos()
+ */
+u_long pcap_mac_packets (void)
+{
+ return (mac_count);
+}
+
+/*
+ * Return # of packets passed through filter in pcap_read_dos()
+ */
+u_long pcap_filter_packets (void)
+{
+ return (filter_count);
+}
+
+/*
+ * Close pcap device. Not called for offline captures.
+ */
+static void pcap_cleanup_dos (pcap_t *p)
+{
+ struct pcap_dos *pd;
+
+ if (!exc_occured)
+ {
+ pd = p->priv;
+ if (pcap_stats(p,NULL) < 0)
+ pd->stat.ps_drop = 0;
+ if (!get_device(p->fd))
+ return;
+
+ handle_to_device [p->fd-1] = NULL;
+ p->fd = 0;
+ if (ref_count > 0)
+ ref_count--;
+ if (ref_count > 0)
+ return;
+ }
+ close_driver();
+ /* XXX - call pcap_cleanup_live_common? */
+}
+
+/*
+ * Return the name of the 1st network interface,
+ * or NULL if none can be found.
+ */
+char *pcap_lookupdev (char *ebuf)
+{
+ struct device *dev;
+
+#ifdef USE_32BIT_DRIVERS
+ init_32bit();
+#endif
+
+ for (dev = (struct device*)dev_base; dev; dev = dev->next)
+ {
+ PCAP_ASSERT (dev->probe);
+
+ if ((*dev->probe)(dev))
+ {
+ FLUSHK();
+ probed_dev = (struct device*) dev; /* remember last probed device */
+ return (char*) dev->name;
+ }
+ }
+
+ if (ebuf)
+ strcpy (ebuf, "No driver found");
+ return (NULL);
+}
+
+/*
+ * Gets localnet & netmask from Watt-32.
+ */
+int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
+ bpf_u_int32 *netmask, char *errbuf)
+{
+ DWORD mask, net;
+
+ if (!_watt_is_init)
+ {
+ strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
+ "called first");
+ return (-1);
+ }
+
+ mask = _w32_sin_mask;
+ net = my_ip_addr & mask;
+ if (net == 0)
+ {
+ if (IN_CLASSA(*netmask))
+ net = IN_CLASSA_NET;
+ else if (IN_CLASSB(*netmask))
+ net = IN_CLASSB_NET;
+ else if (IN_CLASSC(*netmask))
+ net = IN_CLASSC_NET;
+ else
+ {
+ pcap_snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
+ return (-1);
+ }
+ }
+ *localnet = htonl (net);
+ *netmask = htonl (mask);
+
+ ARGSUSED (device);
+ return (0);
+}
+
+/*
+ * Get a list of all interfaces that are present and that we probe okay.
+ * Returns -1 on error, 0 otherwise.
+ * The list may be NULL epty if no interfaces were up and could be opened.
+ */
+int pcap_platform_finddevs (pcap_if_list_t *devlistp, char *errbuf)
+{
+ struct device *dev;
+ pcap_if_t *curdev;
+#if 0 /* Pkt drivers should have no addresses */
+ struct sockaddr_in sa_ll_1, sa_ll_2;
+ struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
+#endif
+ int ret = 0;
+ int found = 0;
+
+ for (dev = (struct device*)dev_base; dev; dev = dev->next)
+ {
+ PCAP_ASSERT (dev->probe);
+
+ if (!(*dev->probe)(dev))
+ continue;
+
+ PCAP_ASSERT (dev->close); /* set by probe routine */
+ FLUSHK();
+ (*dev->close) (dev);
+
+ /*
+ * XXX - find out whether it's up or running? Does that apply here?
+ * Can we find out if anything's plugged into the adapter, if it's
+ * a wired device, and set PCAP_IF_CONNECTION_STATUS_CONNECTED
+ * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
+ */
+ if ((curdev = add_dev(devlistp, dev->name, 0,
+ dev->long_name, errbuf)) == NULL)
+ {
+ ret = -1;
+ break;
+ }
+ found = 1;
+#if 0 /* Pkt drivers should have no addresses */
+ memset (&sa_ll_1, 0, sizeof(sa_ll_1));
+ memset (&sa_ll_2, 0, sizeof(sa_ll_2));
+ sa_ll_1.sin_family = AF_INET;
+ sa_ll_2.sin_family = AF_INET;
+
+ addr = (struct sockaddr*) &sa_ll_1;
+ netmask = (struct sockaddr*) &sa_ll_1;
+ dstaddr = (struct sockaddr*) &sa_ll_1;
+ broadaddr = (struct sockaddr*) &sa_ll_2;
+ memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr));
+
+ if (add_addr_to_dev(curdev, addr, sizeof(*addr),
+ netmask, sizeof(*netmask),
+ broadaddr, sizeof(*broadaddr),
+ dstaddr, sizeof(*dstaddr), errbuf) < 0)
+ {
+ ret = -1;
+ break;
+ }
+#endif
+ }
+
+ if (ret == 0 && !found)
+ strcpy (errbuf, "No drivers found");
+
+ return (ret);
+}
+
+/*
+ * pcap_assert() is mainly used for debugging
+ */
+void pcap_assert (const char *what, const char *file, unsigned line)
+{
+ FLUSHK();
+ fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n",
+ file, line, what);
+ close_driver();
+ _exit (-1);
+}
+
+/*
+ * For pcap_offline_read(): wait and yield between printing packets
+ * to simulate the pace packets where actually recorded.
+ */
+void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
+{
+ if (p)
+ {
+ struct pcap_dos *pd = p->priv;
+
+ pd->wait_proc = yield;
+ p->opt.timeout = wait;
+ }
+}
+
+/*
+ * Initialise a named network device.
+ */
+static struct device *
+open_driver (const char *dev_name, char *ebuf, int promisc)
+{
+ struct device *dev;
+
+ for (dev = (struct device*)dev_base; dev; dev = dev->next)
+ {
+ PCAP_ASSERT (dev->name);
+
+ if (strcmp (dev_name,dev->name))
+ continue;
+
+ if (!probed_dev) /* user didn't call pcap_lookupdev() first */
+ {
+ PCAP_ASSERT (dev->probe);
+
+ if (!(*dev->probe)(dev)) /* call the xx_probe() function */
+ {
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
+ return (NULL);
+ }
+ probed_dev = dev; /* device is probed okay and may be used */
+ }
+ else if (dev != probed_dev)
+ {
+ goto not_probed;
+ }
+
+ FLUSHK();
+
+ /* Select what traffic to receive
+ */
+ if (promisc)
+ dev->flags |= (IFF_ALLMULTI | IFF_PROMISC);
+ else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC);
+
+ PCAP_ASSERT (dev->open);
+
+ if (!(*dev->open)(dev))
+ {
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
+ if (pktInfo.error && !strncmp(dev->name,"pkt",3))
+ {
+ strcat (ebuf, ": ");
+ strcat (ebuf, pktInfo.error);
+ }
+ return (NULL);
+ }
+
+ /* Some devices need this to operate in promiscous mode
+ */
+ if (promisc && dev->set_multicast_list)
+ (*dev->set_multicast_list) (dev);
+
+ active_dev = dev; /* remember our active device */
+ break;
+ }
+
+ /* 'dev_name' not matched in 'dev_base' list.
+ */
+ if (!dev)
+ {
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
+ return (NULL);
+ }
+
+not_probed:
+ if (!probed_dev)
+ {
+ pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
+ return (NULL);
+ }
+ return (dev);
+}
+
+/*
+ * Deinitialise MAC driver.
+ * Set receive mode back to default mode.
+ */
+static void close_driver (void)
+{
+ /* !!todo: loop over all 'handle_to_device[]' ? */
+ struct device *dev = active_dev;
+
+ if (dev && dev->close)
+ {
+ (*dev->close) (dev);
+ FLUSHK();
+ }
+
+ active_dev = NULL;
+
+#ifdef USE_32BIT_DRIVERS
+ if (rx_pool)
+ {
+ k_free (rx_pool);
+ rx_pool = NULL;
+ }
+ if (dev)
+ pcibios_exit();
+#endif
+}
+
+
+#ifdef __DJGPP__
+static void setup_signals (void (*handler)(int))
+{
+ signal (SIGSEGV,handler);
+ signal (SIGILL, handler);
+ signal (SIGFPE, handler);
+}
+
+static void exc_handler (int sig)
+{
+#ifdef USE_32BIT_DRIVERS
+ if (active_dev->irq > 0) /* excludes IRQ 0 */
+ {
+ disable_irq (active_dev->irq);
+ irq_eoi_cmd (active_dev->irq);
+ _printk_safe = 1;
+ }
+#endif
+
+ switch (sig)
+ {
+ case SIGSEGV:
+ fputs ("Catching SIGSEGV.\n", stderr);
+ break;
+ case SIGILL:
+ fputs ("Catching SIGILL.\n", stderr);
+ break;
+ case SIGFPE:
+ _fpreset();
+ fputs ("Catching SIGFPE.\n", stderr);
+ break;
+ default:
+ fprintf (stderr, "Catching signal %d.\n", sig);
+ }
+ exc_occured = 1;
+ close_driver();
+}
+#endif /* __DJGPP__ */
+
+
+/*
+ * Open the pcap device for the first client calling pcap_activate()
+ */
+static int first_init (const char *name, char *ebuf, int promisc)
+{
+ struct device *dev;
+
+#ifdef USE_32BIT_DRIVERS
+ rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE);
+ if (!rx_pool)
+ {
+ strcpy (ebuf, "Not enough memory (Rx pool)");
+ return (0);
+ }
+#endif
+
+#ifdef __DJGPP__
+ setup_signals (exc_handler);
+#endif
+
+#ifdef USE_32BIT_DRIVERS
+ init_32bit();
+#endif
+
+ dev = open_driver (name, ebuf, promisc);
+ if (!dev)
+ {
+#ifdef USE_32BIT_DRIVERS
+ k_free (rx_pool);
+ rx_pool = NULL;
+#endif
+
+#ifdef __DJGPP__
+ setup_signals (SIG_DFL);
+#endif
+ return (0);
+ }
+
+#ifdef USE_32BIT_DRIVERS
+ /*
+ * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf'
+ * set in it's probe handler), initialise near-memory ring-buffer for
+ * the 32-bit device.
+ */
+ if (dev->copy_rx_buf == NULL)
+ {
+ dev->get_rx_buf = get_rxbuf;
+ dev->peek_rx_buf = peek_rxbuf;
+ dev->release_rx_buf = release_rxbuf;
+ pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool);
+ }
+#endif
+ return (1);
+}
+
+#ifdef USE_32BIT_DRIVERS
+static void init_32bit (void)
+{
+ static int init_pci = 0;
+
+ if (!_printk_file)
+ _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */
+
+ if (!init_pci)
+ (void)pci_init(); /* init BIOS32+PCI interface */
+ init_pci = 1;
+}
+#endif
+
+
+/*
+ * Hook functions for using Watt-32 together with pcap
+ */
+static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */
+static WORD etype;
+static pcap_t pcap_save;
+
+static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
+ const u_char *buf)
+{
+ /* Fix me: assumes Ethernet II only */
+ struct ether_header *ep = (struct ether_header*) buf;
+
+ memcpy (rxbuf, buf, pcap->caplen);
+ etype = ep->ether_type;
+ ARGSUSED (dummy);
+}
+
+#if (WATTCP_VER >= 0x0224)
+/*
+ * This function is used by Watt-32 to poll for a packet.
+ * i.e. it's set to bypass _eth_arrived()
+ */
+static void *pcap_recv_hook (WORD *type)
+{
+ int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL);
+
+ if (len < 0)
+ return (NULL);
+
+ *type = etype;
+ return (void*) &rxbuf;
+}
+
+/*
+ * This function is called by Watt-32 (via _eth_xmit_hook).
+ * If dbug_init() was called, we should trace packets sent.
+ */
+static int pcap_xmit_hook (const void *buf, unsigned len)
+{
+ int rc = 0;
+
+ if (pcap_pkt_debug > 0)
+ dbug_write ("pcap_xmit_hook: ");
+
+ if (active_dev && active_dev->xmit)
+ if ((*active_dev->xmit) (active_dev, buf, len) > 0)
+ rc = len;
+
+ if (pcap_pkt_debug > 0)
+ dbug_write (rc ? "ok\n" : "fail\n");
+ return (rc);
+}
+#endif
+
+static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len)
+{
+ struct device *dev = p ? get_device(p->fd) : NULL;
+
+ if (!dev || !dev->xmit)
+ return (-1);
+ return (*dev->xmit) (dev, buf, len);
+}
+
+/*
+ * This function is called by Watt-32 in tcp_post_init().
+ * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc.
+ */
+static void (*prev_post_hook) (void);
+
+static void pcap_init_hook (void)
+{
+ _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0;
+ _w32__do_mask_req = 0;
+ _w32_dynamic_host = 0;
+ if (prev_post_hook)
+ (*prev_post_hook)();
+}
+
+/*
+ * Supress PRINT message from Watt-32's sock_init()
+ */
+static void null_print (void) {}
+
+/*
+ * To use features of Watt-32 (netdb functions and socket etc.)
+ * we must call sock_init(). But we set various hooks to prevent
+ * using normal PKTDRVR functions in pcpkt.c. This should hopefully
+ * make Watt-32 and pcap co-operate.
+ */
+static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
+{
+ char *env;
+ int rc, MTU, has_ip_addr;
+ int using_pktdrv = 1;
+
+ /* If user called sock_init() first, we need to reinit in
+ * order to open debug/trace-file properly
+ */
+ if (_watt_is_init)
+ sock_exit();
+
+ env = getenv ("PCAP_TRACE");
+ if (env && atoi(env) > 0 &&
+ pcap_pkt_debug < 0) /* if not already set */
+ {
+ dbug_init();
+ pcap_pkt_debug = atoi (env);
+ }
+
+ _watt_do_exit = 0; /* prevent sock_init() calling exit() */
+ prev_post_hook = _w32_usr_post_init;
+ _w32_usr_post_init = pcap_init_hook;
+ _w32_print_hook = null_print;
+
+ if (dev_name && strncmp(dev_name,"pkt",3))
+ using_pktdrv = FALSE;
+
+ rc = sock_init();
+ has_ip_addr = (rc != 8); /* IP-address assignment failed */
+
+ /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we
+ * just pretend Watt-32 is initialised okay.
+ *
+ * !! fix-me: The Watt-32 config isn't done if no pktdrvr
+ * was found. In that case my_ip_addr + sin_mask
+ * have default values. Should be taken from another
+ * ini-file/environment in any case (ref. tcpdump.ini)
+ */
+ _watt_is_init = 1;
+
+ if (!using_pktdrv || !has_ip_addr) /* for now .... */
+ {
+ static const char myip[] = "192.168.0.1";
+ static const char mask[] = "255.255.255.0";
+
+ printf ("Just guessing, using IP %s and netmask %s\n", myip, mask);
+ my_ip_addr = aton (myip);
+ _w32_sin_mask = aton (mask);
+ }
+ else if (rc && using_pktdrv)
+ {
+ pcap_snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
+ return (0);
+ }
+
+ /* Set recv-hook for peeking in _eth_arrived().
+ */
+#if (WATTCP_VER >= 0x0224)
+ _eth_recv_hook = pcap_recv_hook;
+ _eth_xmit_hook = pcap_xmit_hook;
+#endif
+
+ /* Free the pkt-drvr handle allocated in pkt_init().
+ * The above hooks should thus use the handle reopened in open_driver()
+ */
+ if (using_pktdrv)
+ {
+ _eth_release();
+/* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */
+ }
+
+ memcpy (&pcap_save, pcap, sizeof(pcap_save));
+ MTU = pkt_get_mtu();
+ pcap_save.fcode.bf_insns = NULL;
+ pcap_save.linktype = _eth_get_hwtype (NULL, NULL);
+ pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
+
+#if 1
+ /* prevent use of resolve() and resolve_ip()
+ */
+ last_nameserver = 0;
+#endif
+ return (1);
+}
+
+int EISA_bus = 0; /* Where is natural place for this? */
+
+/*
+ * Application config hooks to set various driver parameters.
+ */
+
+static const struct config_table debug_tab[] = {
+ { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug },
+ { "PKT.VECTOR", ARG_ATOX_W, NULL },
+ { "NDIS.DEBUG", ARG_ATOI, NULL },
+#ifdef USE_32BIT_DRIVERS
+ { "3C503.DEBUG", ARG_ATOI, &ei_debug },
+ { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr },
+ { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start },
+ { "3C503.IRQ", ARG_ATOI, &el2_dev.irq },
+ { "3C505.DEBUG", ARG_ATOI, NULL },
+ { "3C505.BASE", ARG_ATOX_W, NULL },
+ { "3C507.DEBUG", ARG_ATOI, NULL },
+ { "3C509.DEBUG", ARG_ATOI, &el3_debug },
+ { "3C509.ILOOP", ARG_ATOI, &el3_max_loop },
+ { "3C529.DEBUG", ARG_ATOI, NULL },
+ { "3C575.DEBUG", ARG_ATOI, &debug_3c575 },
+ { "3C59X.DEBUG", ARG_ATOI, &vortex_debug },
+ { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] },
+ { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] },
+ { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] },
+ { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] },
+ { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug },
+ { "ACCT.DEBUG", ARG_ATOI, &ethpk_debug },
+ { "CS89.DEBUG", ARG_ATOI, &cs89_debug },
+ { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug },
+ /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */
+ { "SMC.DEBUG", ARG_ATOI, &ei_debug },
+ /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */
+ { "PCI.DEBUG", ARG_ATOI, &pci_debug },
+ { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug },
+ { "IRQ.DEBUG", ARG_ATOI, &irq_debug },
+ { "TIMER.IRQ", ARG_ATOI, &timer_irq },
+#endif
+ { NULL }
+ };
+
+/*
+ * pcap_config_hook() is an extension to application's config
+ * handling. Uses Watt-32's config-table function.
+ */
+int pcap_config_hook (const char *keyword, const char *value)
+{
+ return parse_config_table (debug_tab, NULL, keyword, value);
+}
+
+/*
+ * Linked list of supported devices
+ */
+struct device *active_dev = NULL; /* the device we have opened */
+struct device *probed_dev = NULL; /* the device we have probed */
+const struct device *dev_base = &pkt_dev; /* list of network devices */
+
+/*
+ * PKTDRVR device functions
+ */
+int pcap_pkt_debug = -1;
+
+static void pkt_close (struct device *dev)
+{
+ BOOL okay = PktExitDriver();
+
+ if (pcap_pkt_debug > 1)
+ fprintf (stderr, "pkt_close(): %d\n", okay);
+
+ if (dev->priv)
+ free (dev->priv);
+ dev->priv = NULL;
+}
+
+static int pkt_open (struct device *dev)
+{
+ PKT_RX_MODE mode;
+
+ if (dev->flags & IFF_PROMISC)
+ mode = PDRX_ALL_PACKETS;
+ else mode = PDRX_BROADCAST;
+
+ if (!PktInitDriver(mode))
+ return (0);
+
+ PktResetStatistics (pktInfo.handle);
+ PktQueueBusy (FALSE);
+ return (1);
+}
+
+static int pkt_xmit (struct device *dev, const void *buf, int len)
+{
+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+ if (pcap_pkt_debug > 0)
+ dbug_write ("pcap_xmit\n");
+
+ if (!PktTransmit(buf,len))
+ {
+ stats->tx_errors++;
+ return (0);
+ }
+ return (len);
+}
+
+static void *pkt_stats (struct device *dev)
+{
+ struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
+
+ if (!stats || !PktSessStatistics(pktInfo.handle))
+ return (NULL);
+
+ stats->rx_packets = pktStat.inPackets;
+ stats->rx_errors = pktStat.lost;
+ stats->rx_missed_errors = PktRxDropped();
+ return (stats);
+}
+
+static int pkt_probe (struct device *dev)
+{
+ if (!PktSearchDriver())
+ return (0);
+
+ dev->open = pkt_open;
+ dev->xmit = pkt_xmit;
+ dev->close = pkt_close;
+ dev->get_stats = pkt_stats;
+ dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */
+ dev->get_rx_buf = NULL;
+ dev->peek_rx_buf = NULL;
+ dev->release_rx_buf = NULL;
+ dev->priv = calloc (sizeof(struct net_device_stats), 1);
+ if (!dev->priv)
+ return (0);
+ return (1);
+}
+
+/*
+ * NDIS device functions
+ */
+static void ndis_close (struct device *dev)
+{
+#ifdef USE_NDIS2
+ NdisShutdown();
+#endif
+ ARGSUSED (dev);
+}
+
+static int ndis_open (struct device *dev)
+{
+ int promis = (dev->flags & IFF_PROMISC);
+
+#ifdef USE_NDIS2
+ if (!NdisInit(promis))
+ return (0);
+ return (1);
+#else
+ ARGSUSED (promis);
+ return (0);
+#endif
+}
+
+static void *ndis_stats (struct device *dev)
+{
+ static struct net_device_stats stats;
+
+ /* to-do */
+ ARGSUSED (dev);
+ return (&stats);
+}
+
+static int ndis_probe (struct device *dev)
+{
+#ifdef USE_NDIS2
+ if (!NdisOpen())
+ return (0);
+#endif
+
+ dev->open = ndis_open;
+ dev->xmit = NULL;
+ dev->close = ndis_close;
+ dev->get_stats = ndis_stats;
+ dev->copy_rx_buf = NULL; /* to-do */
+ dev->get_rx_buf = NULL; /* upcall is from rmode driver */
+ dev->peek_rx_buf = NULL;
+ dev->release_rx_buf = NULL;
+ return (0);
+}
+
+/*
+ * Search & probe for supported 32-bit (pmode) pcap devices
+ */
+#if defined(USE_32BIT_DRIVERS)
+
+struct device el2_dev LOCKED_VAR = {
+ "3c503",
+ "EtherLink II",
+ 0,
+ 0,0,0,0,0,0,
+ NULL,
+ el2_probe
+ };
+
+struct device el3_dev LOCKED_VAR = {
+ "3c509",
+ "EtherLink III",
+ 0,
+ 0,0,0,0,0,0,
+ &el2_dev,
+ el3_probe
+ };
+
+struct device tc515_dev LOCKED_VAR = {
+ "3c515",
+ "EtherLink PCI",
+ 0,
+ 0,0,0,0,0,0,
+ &el3_dev,
+ tc515_probe
+ };
+
+struct device tc59_dev LOCKED_VAR = {
+ "3c59x",
+ "EtherLink PCI",
+ 0,
+ 0,0,0,0,0,0,
+ &tc515_dev,
+ tc59x_probe
+ };
+
+struct device tc90xbc_dev LOCKED_VAR = {
+ "3c90x",
+ "EtherLink 90X",
+ 0,
+ 0,0,0,0,0,0,
+ &tc59_dev,
+ tc90xbc_probe
+ };
+
+struct device wd_dev LOCKED_VAR = {
+ "wd",
+ "Westen Digital",
+ 0,
+ 0,0,0,0,0,0,
+ &tc90xbc_dev,
+ wd_probe
+ };
+
+struct device ne_dev LOCKED_VAR = {
+ "ne",
+ "NEx000",
+ 0,
+ 0,0,0,0,0,0,
+ &wd_dev,
+ ne_probe
+ };
+
+struct device acct_dev LOCKED_VAR = {
+ "acct",
+ "Accton EtherPocket",
+ 0,
+ 0,0,0,0,0,0,
+ &ne_dev,
+ ethpk_probe
+ };
+
+struct device cs89_dev LOCKED_VAR = {
+ "cs89",
+ "Crystal Semiconductor",
+ 0,
+ 0,0,0,0,0,0,
+ &acct_dev,
+ cs89x0_probe
+ };
+
+struct device rtl8139_dev LOCKED_VAR = {
+ "rtl8139",
+ "RealTek PCI",
+ 0,
+ 0,0,0,0,0,0,
+ &cs89_dev,
+ rtl8139_probe /* dev->probe routine */
+ };
+
+/*
+ * Dequeue routine is called by polling.
+ * NOTE: the queue-element is not copied, only a pointer is
+ * returned at '*buf'
+ */
+int peek_rxbuf (BYTE **buf)
+{
+ struct rx_elem *tail, *head;
+
+ PCAP_ASSERT (pktq_check (&active_dev->queue));
+
+ DISABLE();
+ tail = pktq_out_elem (&active_dev->queue);
+ head = pktq_in_elem (&active_dev->queue);
+ ENABLE();
+
+ if (head != tail)
+ {
+ PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2);
+
+ *buf = &tail->data[0];
+ return (tail->size);
+ }
+ *buf = NULL;
+ return (0);
+}
+
+/*
+ * Release buffer we peeked at above.
+ */
+int release_rxbuf (BYTE *buf)
+{
+#ifndef NDEBUG
+ struct rx_elem *tail = pktq_out_elem (&active_dev->queue);
+
+ PCAP_ASSERT (&tail->data[0] == buf);
+#else
+ ARGSUSED (buf);
+#endif
+ pktq_inc_out (&active_dev->queue);
+ return (1);
+}
+
+/*
+ * get_rxbuf() routine (in locked code) is called from IRQ handler
+ * to request a buffer. Interrupts are disabled and we have a 32kB stack.
+ */
+BYTE *get_rxbuf (int len)
+{
+ int idx;
+
+ if (len < ETH_MIN || len > ETH_MAX)
+ return (NULL);
+
+ idx = pktq_in_index (&active_dev->queue);
+
+#ifdef DEBUG
+ {
+ static int fan_idx LOCKED_VAR = 0;
+ writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */
+ 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */
+ fan_idx &= 3;
+ }
+/* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */
+#endif
+
+ if (idx != active_dev->queue.out_index)
+ {
+ struct rx_elem *head = pktq_in_elem (&active_dev->queue);
+
+ head->size = len;
+ active_dev->queue.in_index = idx;
+ return (&head->data[0]);
+ }
+
+ /* !!to-do: drop 25% of the oldest element
+ */
+ pktq_clear (&active_dev->queue);
+ return (NULL);
+}
+
+/*
+ * Simple ring-buffer queue handler for reception of packets
+ * from network driver.
+ */
+#define PKTQ_MARKER 0xDEADBEEF
+
+static int pktq_check (struct rx_ringbuf *q)
+{
+#ifndef NDEBUG
+ int i;
+ char *buf;
+#endif
+
+ if (!q || !q->num_elem || !q->buf_start)
+ return (0);
+
+#ifndef NDEBUG
+ buf = q->buf_start;
+
+ for (i = 0; i < q->num_elem; i++)
+ {
+ buf += q->elem_size;
+ if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER)
+ return (0);
+ }
+#endif
+ return (1);
+}
+
+static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool)
+{
+ int i;
+
+ q->elem_size = size;
+ q->num_elem = num;
+ q->buf_start = pool;
+ q->in_index = 0;
+ q->out_index = 0;
+
+ PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD));
+ PCAP_ASSERT (num);
+ PCAP_ASSERT (pool);
+
+ for (i = 0; i < num; i++)
+ {
+#if 0
+ struct rx_elem *elem = (struct rx_elem*) pool;
+
+ /* assert dword aligned elements
+ */
+ PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0);
+#endif
+ pool += size;
+ *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER;
+ }
+ return (1);
+}
+
+/*
+ * Increment the queue 'out_index' (tail).
+ * Check for wraps.
+ */
+static int pktq_inc_out (struct rx_ringbuf *q)
+{
+ q->out_index++;
+ if (q->out_index >= q->num_elem)
+ q->out_index = 0;
+ return (q->out_index);
+}
+
+/*
+ * Return the queue's next 'in_index' (head).
+ * Check for wraps.
+ */
+static int pktq_in_index (struct rx_ringbuf *q)
+{
+ volatile int index = q->in_index + 1;
+
+ if (index >= q->num_elem)
+ index = 0;
+ return (index);
+}
+
+/*
+ * Return the queue's head-buffer.
+ */
+static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q)
+{
+ return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index));
+}
+
+/*
+ * Return the queue's tail-buffer.
+ */
+static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q)
+{
+ return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index));
+}
+
+/*
+ * Clear the queue ring-buffer by setting head=tail.
+ */
+static void pktq_clear (struct rx_ringbuf *q)
+{
+ q->in_index = q->out_index;
+}
+
+/*
+ * Symbols that must be linkable for "gcc -O0"
+ */
+#undef __IOPORT_H
+#undef __DMA_H
+
+#define extern
+#define __inline__
+
+#include "msdos/pm_drvr/ioport.h"
+#include "msdos/pm_drvr/dma.h"
+
+#endif /* USE_32BIT_DRIVERS */
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return ("DOS-" PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-dos.h b/lib/libpcap/libpcap/pcap-dos.h
new file mode 100644
index 0000000..bf47fb5
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-dos.h
@@ -0,0 +1,225 @@
+/*
+ * Internal details for libpcap on DOS.
+ * 32-bit targets: djgpp, Pharlap or DOS4GW.
+ */
+
+#ifndef __PCAP_DOS_H
+#define __PCAP_DOS_H
+
+#ifdef __DJGPP__
+#include <pc.h> /* simple non-conio kbhit */
+#else
+#include <conio.h>
+#endif
+
+typedef int BOOL;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned long DWORD;
+typedef BYTE ETHER[6];
+
+#define ETH_ALEN sizeof(ETHER) /* Ether address length */
+#define ETH_HLEN (2*ETH_ALEN+2) /* Ether header length */
+#define ETH_MTU 1500
+#define ETH_MIN 60
+#define ETH_MAX (ETH_MTU+ETH_HLEN)
+
+#ifndef TRUE
+ #define TRUE 1
+ #define FALSE 0
+#endif
+
+#define PHARLAP 1
+#define DJGPP 2
+#define DOS4GW 4
+
+#ifdef __DJGPP__
+ #undef DOSX
+ #define DOSX DJGPP
+#endif
+
+#ifdef __WATCOMC__
+ #undef DOSX
+ #define DOSX DOS4GW
+#endif
+
+#ifdef __HIGHC__
+ #include <pharlap.h>
+ #undef DOSX
+ #define DOSX PHARLAP
+ #define inline
+#else
+ typedef unsigned int UINT;
+#endif
+
+
+#if defined(__GNUC__) || defined(__HIGHC__)
+ typedef unsigned long long uint64;
+ typedef unsigned long long QWORD;
+#endif
+
+#if defined(__WATCOMC__)
+ typedef unsigned __int64 uint64;
+ typedef unsigned __int64 QWORD;
+#endif
+
+#define ARGSUSED(x) (void) x
+
+#if defined (__SMALL__) || defined(__LARGE__)
+ #define DOSX 0
+
+#elif !defined(DOSX)
+ #error DOSX not defined; 1 = PharLap, 2 = djgpp, 4 = DOS4GW
+#endif
+
+#ifdef __HIGHC__
+#define min(a,b) _min(a,b)
+#define max(a,b) _max(a,b)
+#endif
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef max
+#define max(a,b) ((a) < (b) ? (b) : (a))
+#endif
+
+#if !defined(_U_) && defined(__GNUC__)
+#define _U_ __attribute__((unused))
+#endif
+
+#ifndef _U_
+#define _U_
+#endif
+
+#if defined(USE_32BIT_DRIVERS)
+ #include "msdos/pm_drvr/lock.h"
+
+ #ifndef RECEIVE_QUEUE_SIZE
+ #define RECEIVE_QUEUE_SIZE 60
+ #endif
+
+ #ifndef RECEIVE_BUF_SIZE
+ #define RECEIVE_BUF_SIZE (ETH_MAX+20)
+ #endif
+
+ extern struct device el2_dev LOCKED_VAR; /* 3Com EtherLink II */
+ extern struct device el3_dev LOCKED_VAR; /* EtherLink III */
+ extern struct device tc59_dev LOCKED_VAR; /* 3Com Vortex Card (?) */
+ extern struct device tc515_dev LOCKED_VAR;
+ extern struct device tc90x_dev LOCKED_VAR;
+ extern struct device tc90bcx_dev LOCKED_VAR;
+ extern struct device wd_dev LOCKED_VAR;
+ extern struct device ne_dev LOCKED_VAR;
+ extern struct device acct_dev LOCKED_VAR;
+ extern struct device cs89_dev LOCKED_VAR;
+ extern struct device rtl8139_dev LOCKED_VAR;
+
+ struct rx_ringbuf {
+ volatile int in_index; /* queue index head */
+ int out_index; /* queue index tail */
+ int elem_size; /* size of each element */
+ int num_elem; /* number of elements */
+ char *buf_start; /* start of buffer pool */
+ };
+
+ struct rx_elem {
+ DWORD size; /* size copied to this element */
+ BYTE data[ETH_MAX+10]; /* add some margin. data[0] should be */
+ }; /* dword aligned */
+
+ extern BYTE *get_rxbuf (int len) LOCKED_FUNC;
+ extern int peek_rxbuf (BYTE **buf);
+ extern int release_rxbuf (BYTE *buf);
+
+#else
+ #define LOCKED_VAR
+ #define LOCKED_FUNC
+
+ struct device {
+ const char *name;
+ const char *long_name;
+ DWORD base_addr; /* device I/O address */
+ int irq; /* device IRQ number */
+ int dma; /* DMA channel */
+ DWORD mem_start; /* shared mem start */
+ DWORD mem_end; /* shared mem end */
+ DWORD rmem_start; /* shmem "recv" start */
+ DWORD rmem_end; /* shared "recv" end */
+
+ struct device *next; /* next device in list */
+
+ /* interface service routines */
+ int (*probe)(struct device *dev);
+ int (*open) (struct device *dev);
+ void (*close)(struct device *dev);
+ int (*xmit) (struct device *dev, const void *buf, int len);
+ void *(*get_stats)(struct device *dev);
+ void (*set_multicast_list)(struct device *dev);
+
+ /* driver-to-pcap receive buffer routines */
+ int (*copy_rx_buf) (BYTE *buf, int max); /* rx-copy (pktdrvr only) */
+ BYTE *(*get_rx_buf) (int len); /* rx-buf fetch/enqueue */
+ int (*peek_rx_buf) (BYTE **buf); /* rx-non-copy at queue */
+ int (*release_rx_buf) (BYTE *buf); /* release after peek */
+
+ WORD flags; /* Low-level status flags. */
+ void *priv; /* private data */
+ };
+
+ /*
+ * Network device statistics
+ */
+ typedef struct net_device_stats {
+ DWORD rx_packets; /* total packets received */
+ DWORD tx_packets; /* total packets transmitted */
+ DWORD rx_bytes; /* total bytes received */
+ DWORD tx_bytes; /* total bytes transmitted */
+ DWORD rx_errors; /* bad packets received */
+ DWORD tx_errors; /* packet transmit problems */
+ DWORD rx_dropped; /* no space in Rx buffers */
+ DWORD tx_dropped; /* no space available for Tx */
+ DWORD multicast; /* multicast packets received */
+
+ /* detailed rx_errors: */
+ DWORD rx_length_errors;
+ DWORD rx_over_errors; /* recv'r overrun error */
+ DWORD rx_osize_errors; /* recv'r over-size error */
+ DWORD rx_crc_errors; /* recv'd pkt with crc error */
+ DWORD rx_frame_errors; /* recv'd frame alignment error */
+ DWORD rx_fifo_errors; /* recv'r fifo overrun */
+ DWORD rx_missed_errors; /* recv'r missed packet */
+
+ /* detailed tx_errors */
+ DWORD tx_aborted_errors;
+ DWORD tx_carrier_errors;
+ DWORD tx_fifo_errors;
+ DWORD tx_heartbeat_errors;
+ DWORD tx_window_errors;
+ DWORD tx_collisions;
+ DWORD tx_jabbers;
+ } NET_STATS;
+#endif
+
+extern struct device *active_dev LOCKED_VAR;
+extern const struct device *dev_base LOCKED_VAR;
+extern struct device *probed_dev;
+
+extern int pcap_pkt_debug;
+
+extern void _w32_os_yield (void); /* Watt-32's misc.c */
+
+#ifdef NDEBUG
+ #define PCAP_ASSERT(x) ((void)0)
+
+#else
+ void pcap_assert (const char *what, const char *file, unsigned line);
+
+ #define PCAP_ASSERT(x) do { \
+ if (!(x)) \
+ pcap_assert (#x, __FILE__, __LINE__); \
+ } while (0)
+#endif
+
+#endif /* __PCAP_DOS_H */
diff --git a/lib/libpcap/libpcap/pcap-enet.c b/lib/libpcap/libpcap/pcap-enet.c
new file mode 100644
index 0000000..cd8cdbb
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-enet.c
@@ -0,0 +1,231 @@
+/*
+ * Stanford Enetfilter subroutines for tcpdump
+ *
+ * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c
+ * subroutines.
+ *
+ * Rayan Zachariassen, CA*Net
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <pcap/bpf.h>
+#include <net/enet.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "interface.h"
+
+struct packet_header {
+#ifdef IBMRTPC
+ struct LengthWords length;
+ struct tap_header tap;
+#endif /* IBMRTPC */
+ u_char packet[8]
+};
+
+extern int errno;
+
+#define BUFSPACE (4*1024)
+
+/* Forwards */
+static void efReadError(int, char *);
+
+void
+readloop(int cnt, int if_fd, struct bpf_program *fp, printfunc printit)
+{
+#ifdef IBMRTPC
+ register struct packet_header *ph;
+ register u_char *bp;
+ register int inc;
+#else /* !IBMRTPC */
+ static struct timeval tv = { 0 };
+#endif /* IBMRTPC */
+ register int cc, caplen;
+ register struct bpf_insn *fcode = fp->bf_insns;
+ union {
+ struct packet_header hdr;
+ u_char p[BUFSPACE];
+ u_short s;
+ } buf;
+
+ while (1) {
+ if ((cc = read(if_fd, (char *)buf.p, sizeof(buf))) < 0)
+ efReadError(if_fd, "reader");
+
+#ifdef IBMRTPC
+ /*
+ * Loop through each packet.
+ */
+ bp = buf.p;
+ while (cc > 0) {
+ ph = (struct packet_header *)bp;
+ caplen = ph->tap.th_wirelen > snaplen ? snaplen : ph->tap
+.th_wirelen ;
+ if (bpf_filter(fcode, (char *)ph->packet,
+ ph->tap.th_wirelen, caplen)) {
+ if (cnt >= 0 && --cnt < 0)
+ goto out;
+ (*printit)((char *)ph->packet,
+ (struct timeval *)ph->tap.th_timestamp,
+ ph->tap.th_wirelen, caplen);
+ }
+ inc = ph->length.PacketOffset;
+ cc -= inc;
+ bp += inc;
+ }
+#else /* !IBMRTPC */
+ caplen = cc > snaplen ? snaplen : cc ;
+ if (bpf_filter(fcode, buf.hdr.packet, cc, caplen)) {
+ if (cnt >= 0 && --cnt < 0)
+ goto out;
+ (*printit)(buf.hdr.packet, &tv, cc, caplen);
+ }
+#endif /* IBMRTPC */
+ }
+ out:
+ wrapup(if_fd);
+}
+
+/* Call ONLY if read() has returned an error on packet filter */
+static void
+efReadError(int fid, char *msg)
+{
+ if (errno == EINVAL) { /* read MAXINT bytes already! */
+ if (lseek(fid, 0, 0) < 0) {
+ perror("tcpdump: efReadError/lseek");
+ exit(-1);
+ }
+ else
+ return;
+ }
+ else {
+ (void) fprintf(stderr, "tcpdump: ");
+ perror(msg);
+ exit(-1);
+ }
+}
+
+void
+wrapup(int fd)
+{
+#ifdef IBMRTPC
+ struct enstats es;
+
+ if (ioctl(fd, EIOSTATS, &es) == -1) {
+ perror("tcpdump: enet ioctl EIOSTATS error");
+ exit(-1);
+ }
+
+ fprintf(stderr, "%d packets queued", es.enStat_Rcnt);
+ if (es.enStat_Rdrops > 0)
+ fprintf(stderr, ", %d dropped", es.enStat_Rdrops);
+ if (es.enStat_Reads > 0)
+ fprintf(stderr, ", %d tcpdump %s", es.enStat_Reads,
+ es.enStat_Reads > 1 ? "reads" : "read");
+ if (es.enStat_MaxRead > 1)
+ fprintf(stderr, ", %d packets in largest read",
+ es.enStat_MaxRead);
+ putc('\n', stderr);
+#endif /* IBMRTPC */
+ close(fd);
+}
+
+int
+initdevice(char *device, int pflag, int *linktype)
+{
+ struct eniocb ctl;
+ struct enfilter filter;
+ u_int maxwaiting;
+ int if_fd;
+
+#ifdef IBMRTPC
+ GETENETDEVICE(0, O_RDONLY, &if_fd);
+#else /* !IBMRTPC */
+ if_fd = open("/dev/enet", O_RDONLY, 0);
+#endif /* IBMRTPC */
+
+ if (if_fd == -1) {
+ perror("tcpdump: enet open error");
+ error(
+"your system may not be properly configured; see \"man enet(4)\"");
+ exit(-1);
+ }
+
+ /* Get operating parameters. */
+
+ if (ioctl(if_fd, EIOCGETP, (char *)&ctl) == -1) {
+ perror("tcpdump: enet ioctl EIOCGETP error");
+ exit(-1);
+ }
+
+ /* Set operating parameters. */
+
+#ifdef IBMRTPC
+ ctl.en_rtout = 1 * ctl.en_hz;
+ ctl.en_tr_etherhead = 1;
+ ctl.en_tap_network = 1;
+ ctl.en_multi_packet = 1;
+ ctl.en_maxlen = BUFSPACE;
+#else /* !IBMRTPC */
+ ctl.en_rtout = 64; /* randomly picked value for HZ */
+#endif /* IBMRTPC */
+ if (ioctl(if_fd, EIOCSETP, &ctl) == -1) {
+ perror("tcpdump: enet ioctl EIOCSETP error");
+ exit(-1);
+ }
+
+ /* Flush the receive queue, since we've changed
+ the operating parameters and we otherwise might
+ receive data without headers. */
+
+ if (ioctl(if_fd, EIOCFLUSH) == -1) {
+ perror("tcpdump: enet ioctl EIOCFLUSH error");
+ exit(-1);
+ }
+
+ /* Set the receive queue depth to its maximum. */
+
+ maxwaiting = ctl.en_maxwaiting;
+ if (ioctl(if_fd, EIOCSETW, &maxwaiting) == -1) {
+ perror("tcpdump: enet ioctl EIOCSETW error");
+ exit(-1);
+ }
+
+#ifdef IBMRTPC
+ /* Clear statistics. */
+
+ if (ioctl(if_fd, EIOCLRSTAT, 0) == -1) {
+ perror("tcpdump: enet ioctl EIOCLRSTAT error");
+ exit(-1);
+ }
+#endif /* IBMRTPC */
+
+ /* Set the filter (accept all packets). */
+
+ filter.enf_Priority = 3;
+ filter.enf_FilterLen = 0;
+ if (ioctl(if_fd, EIOCSETF, &filter) == -1) {
+ perror("tcpdump: enet ioctl EIOCSETF error");
+ exit(-1);
+ }
+ /*
+ * "enetfilter" supports only ethernets.
+ */
+ *linktype = DLT_EN10MB;
+
+ return(if_fd);
+}
diff --git a/lib/libpcap/libpcap/pcap-filter.manmisc b/lib/libpcap/libpcap/pcap-filter.manmisc
new file mode 100644
index 0000000..d8385f5
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-filter.manmisc
@@ -0,0 +1,1052 @@
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-FILTER 7 "5 November 2017"
+.SH NAME
+pcap-filter \- packet filter syntax
+.br
+.ad
+.SH DESCRIPTION
+.LP
+.B pcap_compile()
+is used to compile a string into a filter program.
+The resulting filter program can then be applied to
+some stream of packets to determine which packets will be supplied to
+.BR pcap_loop(3PCAP) ,
+.BR pcap_dispatch(3PCAP) ,
+.BR pcap_next(3PCAP) ,
+or
+.BR pcap_next_ex(3PCAP) .
+.LP
+The \fIfilter expression\fP consists of one or more
+.IR primitives .
+Primitives usually consist of an
+.I id
+(name or number) preceded by one or more qualifiers.
+There are three
+different kinds of qualifier:
+.IP \fItype\fP
+.I type
+qualifiers say what kind of thing the id name or number refers to.
+Possible types are
+.BR host ,
+.B net ,
+.B port
+and
+.BR portrange .
+E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
+If there is no type
+qualifier,
+.B host
+is assumed.
+.IP \fIdir\fP
+.I dir
+qualifiers specify a particular transfer direction to and/or from
+.IR id .
+Possible directions are
+.BR src ,
+.BR dst ,
+.BR "src or dst" ,
+.BR "src and dst" ,
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.BR addr4 .
+E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
+If
+there is no dir qualifier,
+.B "src or dst"
+is assumed.
+The
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.B addr4
+qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
+.IP \fIproto\fP
+.I proto
+qualifiers restrict the match to a particular protocol.
+Possible
+protos are:
+.BR ether ,
+.BR fddi ,
+.BR tr ,
+.BR wlan ,
+.BR ip ,
+.BR ip6 ,
+.BR arp ,
+.BR rarp ,
+.BR decnet ,
+.B tcp
+and
+.BR udp .
+E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange
+7000-7009', `wlan addr2 0:2:3:4:5:6'.
+If there is
+no proto qualifier, all protocols consistent with the type are
+assumed.
+E.g., `src foo' means `(ip or arp or rarp) src foo'
+(except the latter is not legal syntax), `net bar' means `(ip or
+arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
+.LP
+[`fddi' is actually an alias for `ether'; the parser treats them
+identically as meaning ``the data link level used on the specified
+network interface.'' FDDI headers contain Ethernet-like source
+and destination addresses, and often contain Ethernet-like packet
+types, so you can filter on these FDDI fields just as with the
+analogous Ethernet fields.
+FDDI headers also contain other fields,
+but you cannot name them explicitly in a filter expression.
+.LP
+Similarly, `tr' and `wlan' are aliases for `ether'; the previous
+paragraph's statements about FDDI headers also apply to Token Ring
+and 802.11 wireless LAN headers. For 802.11 headers, the destination
+address is the DA field and the source address is the SA field; the
+BSSID, RA, and TA fields aren't tested.]
+.LP
+In addition to the above, there are some special `primitive' keywords
+that don't follow the pattern:
+.BR gateway ,
+.BR broadcast ,
+.BR less ,
+.B greater
+and arithmetic expressions.
+All of these are described below.
+.LP
+More complex filter expressions are built up by using the words
+.BR and ,
+.B or
+and
+.B not
+to combine primitives.
+E.g., `host foo and not port ftp and not port ftp-data'.
+To save typing, identical qualifier lists can be omitted.
+E.g.,
+`tcp dst port ftp or ftp-data or domain' is exactly the same as
+`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
+.LP
+Allowable primitives are:
+.IP "\fBdst host \fIhost\fR"
+True if the IPv4/v6 destination field of the packet is \fIhost\fP,
+which may be either an address or a name.
+.IP "\fBsrc host \fIhost\fR"
+True if the IPv4/v6 source field of the packet is \fIhost\fP.
+.IP "\fBhost \fIhost\fP"
+True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
+.IP
+Any of the above host expressions can be prepended with the keywords,
+\fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in:
+.in +.5i
+.nf
+\fBip host \fIhost\fR
+.fi
+.in -.5i
+which is equivalent to:
+.in +.5i
+.nf
+\fBether proto \fI\\ip\fB and host \fIhost\fR
+.fi
+.in -.5i
+If \fIhost\fR is a name with multiple IP addresses, each address will
+be checked for a match.
+.IP "\fBether dst \fIehost\fP"
+True if the Ethernet destination address is \fIehost\fP.
+\fIEhost\fP
+may be either a name from /etc/ethers or a numerical MAC address of the
+form "xx:xx:xx:xx:xx:xx", "xx.xx.xx.xx.xx.xx", "xx-xx-xx-xx-xx-xx",
+"xxxx.xxxx.xxxx", "xxxxxxxxxxxx", or various mixes of ':', '.', and '-',
+where each "x" is a hex digit (0-9, a-f, or A-F).
+.IP "\fBether src \fIehost\fP"
+True if the Ethernet source address is \fIehost\fP.
+.IP "\fBether host \fIehost\fP"
+True if either the Ethernet source or destination address is \fIehost\fP.
+.IP "\fBgateway\fP \fIhost\fP"
+True if the packet used \fIhost\fP as a gateway.
+I.e., the Ethernet
+source or destination address was \fIhost\fP but neither the IP source
+nor the IP destination was \fIhost\fP.
+\fIHost\fP must be a name and
+must be found both by the machine's host-name-to-IP-address resolution
+mechanisms (host name file, DNS, NIS, etc.) and by the machine's
+host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.).
+(An equivalent expression is
+.in +.5i
+.nf
+\fBether host \fIehost \fBand not host \fIhost\fR
+.fi
+.in -.5i
+which can be used with either names or numbers for \fIhost / ehost\fP.)
+This syntax does not work in IPv6-enabled configuration at this moment.
+.IP "\fBdst net \fInet\fR"
+True if the IPv4/v6 destination address of the packet has a network
+number of \fInet\fP.
+\fINet\fP may be either a name from the networks database
+(/etc/networks, etc.) or a network number.
+An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0),
+dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single
+number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad
+(which means that it's really a host match), 255.255.255.0 for a dotted
+triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number.
+An IPv6 network number must be written out fully; the netmask is
+ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always
+host matches, and a network match requires a netmask length.
+.IP "\fBsrc net \fInet\fR"
+True if the IPv4/v6 source address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR"
+True if either the IPv4/v6 source or destination address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR \fBmask \fInetmask\fR"
+True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+Note that this syntax is not valid for IPv6 \fInet\fR.
+.IP "\fBnet \fInet\fR/\fIlen\fR"
+True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR
+bits wide.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+.IP "\fBdst port \fIport\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value of \fIport\fP.
+The \fIport\fP can be a number or a name used in /etc/services (see
+.IR tcp (4P)
+and
+.IR udp (4P)).
+If a name is used, both the port
+number and protocol are checked.
+If a number or ambiguous name is used,
+only the port number is checked (e.g., \fBdst port 513\fR will print both
+tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
+both tcp/domain and udp/domain traffic).
+.IP "\fBsrc port \fIport\fR"
+True if the packet has a source port value of \fIport\fP.
+.IP "\fBport \fIport\fR"
+True if either the source or destination port of the packet is \fIport\fP.
+.IP "\fBdst portrange \fIport1\fB-\fIport2\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value between \fIport1\fP and \fIport2\fP.
+.I port1
+and
+.I port2
+are interpreted in the same fashion as the
+.I port
+parameter for
+.BR port .
+.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
+True if the packet has a source port value between \fIport1\fP and
+\fIport2\fP.
+.IP "\fBportrange \fIport1\fB-\fIport2\fR"
+True if either the source or destination port of the packet is between
+\fIport1\fP and \fIport2\fP.
+.IP
+Any of the above port or port range expressions can be prepended with
+the keywords, \fBtcp\fP or \fBudp\fP, as in:
+.in +.5i
+.nf
+\fBtcp src port \fIport\fR
+.fi
+.in -.5i
+which matches only tcp packets whose source port is \fIport\fP.
+.IP "\fBless \fIlength\fR"
+True if the packet has a length less than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen <= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBgreater \fIlength\fR"
+True if the packet has a length greater than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen >= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBip proto \fIprotocol\fR"
+True if the packet is an IPv4 packet (see
+.IR ip (4P))
+of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
+\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
+Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
+keywords and must be escaped via backslash (\\).
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 proto \fIprotocol\fR"
+True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBproto \fIprotocol\fR"
+True if the packet is an IPv4 or IPv6 packet of protocol type
+\fIprotocol\fP. Note that this primitive does not chase the protocol
+header chain.
+.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBproto \fIp\fR\fB
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBip6 protochain \fIprotocol\fR"
+True if the packet is IPv6 packet,
+and contains protocol header with type \fIprotocol\fR
+in its protocol header chain.
+For example,
+.in +.5i
+.nf
+\fBip6 protochain 6\fR
+.fi
+.in -.5i
+matches any IPv6 packet with TCP protocol header in the protocol header chain.
+The packet may contain, for example,
+authentication header, routing header, or hop-by-hop option header,
+between IPv6 header and TCP header.
+The BPF code emitted by this primitive is complex and
+cannot be optimized by the BPF optimizer code, and is not supported by
+filter engines in the kernel, so this can be somewhat slow, and may
+cause more packets to be dropped.
+.IP "\fBip protochain \fIprotocol\fR"
+Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
+.IP "\fBprotochain \fIprotocol\fR"
+True if the packet is an IPv4 or IPv6 packet of protocol type
+\fIprotocol\fP. Note that this primitive chases the protocol
+header chain.
+.IP "\fBether broadcast\fR"
+True if the packet is an Ethernet broadcast packet.
+The \fIether\fP
+keyword is optional.
+.IP "\fBip broadcast\fR"
+True if the packet is an IPv4 broadcast packet.
+It checks for both the all-zeroes and all-ones broadcast conventions,
+and looks up the subnet mask on the interface on which the capture is
+being done.
+.IP
+If the subnet mask of the interface on which the capture is being done
+is not available, either because the interface on which capture is being
+done has no netmask or because the capture is being done on the Linux
+"any" interface, which can capture on more than one interface, this
+check will not work correctly.
+.IP "\fBether multicast\fR"
+True if the packet is an Ethernet multicast packet.
+The \fBether\fP
+keyword is optional.
+This is shorthand for `\fBether[0] & 1 != 0\fP'.
+.IP "\fBip multicast\fR"
+True if the packet is an IPv4 multicast packet.
+.IP "\fBip6 multicast\fR"
+True if the packet is an IPv6 multicast packet.
+.IP "\fBether proto \fIprotocol\fR"
+True if the packet is of ether type \fIprotocol\fR.
+\fIProtocol\fP can be a number or one of the names
+\fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP,
+\fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP,
+\fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP.
+Note these identifiers are also keywords
+and must be escaped via backslash (\\).
+.IP
+[In the case of FDDI (e.g., `\fBfddi proto arp\fR'), Token Ring
+(e.g., `\fBtr proto arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan proto arp\fR'), for most of those protocols, the
+protocol identification comes from the 802.2 Logical Link Control (LLC)
+header, which is usually layered on top of the FDDI, Token Ring, or
+802.11 header.
+.IP
+When filtering for most protocol identifiers on FDDI, Token Ring, or
+802.11, the filter checks only the protocol ID field of an LLC header
+in so-called SNAP format with an Organizational Unit Identifier (OUI) of
+0x000000, for encapsulated Ethernet; it doesn't check whether the packet
+is in SNAP format with an OUI of 0x000000.
+The exceptions are:
+.RS
+.TP
+\fBiso\fP
+the filter checks the DSAP (Destination Service Access Point) and
+SSAP (Source Service Access Point) fields of the LLC header;
+.TP
+\fBstp\fP and \fBnetbeui\fP
+the filter checks the DSAP of the LLC header;
+.TP
+\fBatalk\fP
+the filter checks for a SNAP-format packet with an OUI of 0x080007
+and the AppleTalk etype.
+.RE
+.IP
+In the case of Ethernet, the filter checks the Ethernet type field
+for most of those protocols. The exceptions are:
+.RS
+.TP
+\fBiso\fP, \fBstp\fP, and \fBnetbeui\fP
+the filter checks for an 802.3 frame and then checks the LLC header as
+it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBatalk\fP
+the filter checks both for the AppleTalk etype in an Ethernet frame and
+for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBaarp\fP
+the filter checks for the AppleTalk ARP etype in either an Ethernet
+frame or an 802.2 SNAP frame with an OUI of 0x000000;
+.TP
+\fBipx\fP
+the filter checks for the IPX etype in an Ethernet frame, the IPX
+DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
+IPX, and the IPX etype in a SNAP frame.
+.RE
+.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+Note that not all applications using
+.BR pcap (3PCAP)
+currently know how to parse these protocols.
+.IP "\fBdecnet src \fIhost\fR"
+True if the DECNET source address is
+.IR host ,
+which may be an address of the form ``10.123'', or a DECNET host
+name.
+[DECNET host name support is only available on ULTRIX systems
+that are configured to run DECNET.]
+.IP "\fBdecnet dst \fIhost\fR"
+True if the DECNET destination address is
+.IR host .
+.IP "\fBdecnet host \fIhost\fR"
+True if either the DECNET source or destination address is
+.IR host .
+.IP \fBllc\fP
+True if the packet has an 802.2 LLC header. This includes:
+.IP
+Ethernet packets with a length field rather than a type field that
+aren't raw NetWare-over-802.3 packets;
+.IP
+IEEE 802.11 data packets;
+.IP
+Token Ring packets (no check is done for LLC frames);
+.IP
+FDDI packets (no check is done for LLC frames);
+.IP
+LLC-encapsulated ATM packets, for SunATM on Solaris.
+.IP "\fBllc\fP \Fitype\fR"
+True if the packet has an 802.2 LLC header and has the specified
+.IR type .
+.I type
+can be one of:
+.RS
+.TP
+\fBi\fR
+Information (I) PDUs
+.TP
+\fBs\fR
+Supervisory (S) PDUs
+.TP
+\fBu\fR
+Unnumbered (U) PDUs
+.TP
+\fBrr\fR
+Receiver Ready (RR) S PDUs
+.TP
+\fBrnr\fR
+Receiver Not Ready (RNR) S PDUs
+.TP
+\fBrej\fR
+Reject (REJ) S PDUs
+.TP
+\fBui\fR
+Unnumbered Information (UI) U PDUs
+.TP
+\fBua\fR
+Unnumbered Acknowledgment (UA) U PDUs
+.TP
+\fBdisc\fR
+Disconnect (DISC) U PDUs
+.TP
+\fBsabme\fR
+Set Asynchronous Balanced Mode Extended (SABME) U PDUs
+.TP
+\fBtest\fR
+Test (TEST) U PDUs
+.TP
+\fBxid\fR
+Exchange Identification (XID) U PDUs
+.TP
+\fBfrmr\fR
+Frame Reject (FRMR) U PDUs
+.RE
+.IP \fBinbound\fP
+Packet was received by the host performing the capture rather than being
+sent by that host. This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
+.IP \fBoutbound\fP
+Packet was sent by the host performing the capture rather than being
+received by that host. This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
+.IP "\fBifname \fIinterface\fR"
+True if the packet was logged as coming from the specified interface (applies
+only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBon \fIinterface\fR"
+Synonymous with the
+.B ifname
+modifier.
+.IP "\fBrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrulenum \fInum\fR"
+Synonymous with the
+.B rnr
+modifier.
+.IP "\fBreason \fIcode\fR"
+True if the packet was logged with the specified PF reason code. The known
+codes are:
+.BR match ,
+.BR bad-offset ,
+.BR fragment ,
+.BR short ,
+.BR normalize ,
+and
+.B memory
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrset \fIname\fR"
+True if the packet was logged as matching the specified PF ruleset
+name of an anchored ruleset (applies only to packets logged by OpenBSD's
+or FreeBSD's
+.BR pf (4)).
+.IP "\fBruleset \fIname\fR"
+Synonymous with the
+.B rset
+modifier.
+.IP "\fBsrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+of an anchored ruleset (applies only to packets logged by OpenBSD's or
+FreeBSD's
+.BR pf (4)).
+.IP "\fBsubrulenum \fInum\fR"
+Synonymous with the
+.B srnr
+modifier.
+.IP "\fBaction \fIact\fR"
+True if PF took the specified action when the packet was logged. Known actions
+are:
+.B pass
+and
+.B block
+and, with later versions of
+.BR pf (4),
+.BR nat ,
+.BR rdr ,
+.B binat
+and
+.B scrub
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBwlan ra \fIehost\fR"
+True if the IEEE 802.11 RA is
+.IR ehost .
+The RA field is used in all frames except for management frames.
+.IP "\fBwlan ta \fIehost\fR"
+True if the IEEE 802.11 TA is
+.IR ehost .
+The TA field is used in all frames except for management frames and
+CTS (Clear To Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr1 \fIehost\fR"
+True if the first IEEE 802.11 address is
+.IR ehost .
+.IP "\fBwlan addr2 \fIehost\fR"
+True if the second IEEE 802.11 address, if present, is
+.IR ehost .
+The second address field is used in all frames except for CTS (Clear To
+Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr3 \fIehost\fR"
+True if the third IEEE 802.11 address, if present, is
+.IR ehost .
+The third address field is used in management and data frames, but not
+in control frames.
+.IP "\fBwlan addr4 \fIehost\fR"
+True if the fourth IEEE 802.11 address, if present, is
+.IR ehost .
+The fourth address field is only used for
+WDS (Wireless Distribution System) frames.
+.IP "\fBtype \fIwlan_type\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR.
+Valid \fIwlan_type\fRs are:
+\fBmgt\fP,
+\fBctl\fP
+and \fBdata\fP.
+.IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR
+and frame subtype matches the specified \fIwlan_subtype\fR.
+.IP
+If the specified \fIwlan_type\fR is \fBmgt\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBassoc-req\fP,
+\fBassoc-resp\fP,
+\fBreassoc-req\fP,
+\fBreassoc-resp\fP,
+\fBprobe-req\fP,
+\fBprobe-resp\fP,
+\fBbeacon\fP,
+\fBatim\fP,
+\fBdisassoc\fP,
+\fBauth\fP and
+\fBdeauth\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBctl\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBps-poll\fP,
+\fBrts\fP,
+\fBcts\fP,
+\fBack\fP,
+\fBcf-end\fP and
+\fBcf-end-ack\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBdata\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBdata\fP,
+\fBdata-cf-ack\fP,
+\fBdata-cf-poll\fP,
+\fBdata-cf-ack-poll\fP,
+\fBnull\fP,
+\fBcf-ack\fP,
+\fBcf-poll\fP,
+\fBcf-ack-poll\fP,
+\fBqos-data\fP,
+\fBqos-data-cf-ack\fP,
+\fBqos-data-cf-poll\fP,
+\fBqos-data-cf-ack-poll\fP,
+\fBqos\fP,
+\fBqos-cf-poll\fP and
+\fBqos-cf-ack-poll\fP.
+.IP "\fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR
+and frame has the type to which the specified \fIwlan_subtype\fR belongs.
+.IP "\fBdir \fIdir\fR"
+True if the IEEE 802.11 frame direction matches the specified
+.IR dir .
+Valid directions are:
+.BR nods ,
+.BR tods ,
+.BR fromds ,
+.BR dstods ,
+or a numeric value.
+.IP "\fBvlan \fI[vlan_id]\fR"
+True if the packet is an IEEE 802.1Q VLAN packet.
+If \fI[vlan_id]\fR is specified, only true if the packet has the specified
+\fIvlan_id\fR.
+Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a VLAN packet. The \fBvlan
+\fI[vlan_id]\fR expression may be used more than once, to filter on VLAN
+hierarchies. Each use of that expression increments the filter offsets
+by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBvlan 100 && vlan 200\fR
+.fi
+.in -.5i
+filters on VLAN 200 encapsulated within VLAN 100, and
+.in +.5i
+.nf
+\fBvlan && vlan 300 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
+higher order VLAN.
+.IP "\fBmpls \fI[label_num]\fR"
+True if the packet is an MPLS packet.
+If \fI[label_num]\fR is specified, only true is the packet has the specified
+\fIlabel_num\fR.
+Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a MPLS-encapsulated IP packet. The
+\fBmpls \fI[label_num]\fR expression may be used more than once, to
+filter on MPLS hierarchies. Each use of that expression increments the
+filter offsets by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBmpls 100000 && mpls 1024\fR
+.fi
+.in -.5i
+filters packets with an outer label of 100000 and an inner label of
+1024, and
+.in +.5i
+.nf
+\fBmpls && mpls 1024 && host 192.9.200.1\fR
+.fi
+.in -.5i
+filters packets to or from 192.9.200.1 with an inner label of 1024 and
+any outer label.
+.IP \fBpppoed\fP
+True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
+type 0x8863).
+.IP "\fBpppoes \fI[session_id]\fR"
+True if the packet is a PPP-over-Ethernet Session packet (Ethernet
+type 0x8864).
+If \fI[session_id]\fR is specified, only true if the packet has the specified
+\fIsession_id\fR.
+Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a PPPoE session packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBpppoes 0x27 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in PPPoE session id 0x27.
+.IP "\fBgeneve \fI[vni]\fR"
+True if the packet is a Geneve packet (UDP port 6081). If \fI[vni]\fR
+is specified, only true if the packet has the specified \fIvni\fR.
+Note that when the \fBgeneve\fR keyword is encountered in
+\fIexpression\fR, it changes the decoding offsets for the remainder of
+\fIexpression\fR on the assumption that the packet is a Geneve packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBgeneve 0xb && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in Geneve with VNI 0xb. This will
+match both IP directly encapsulated in Geneve as well as IP contained
+inside an Ethernet frame.
+.IP "\fBiso proto \fIprotocol\fR"
+True if the packet is an OSI packet of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBclnp\fP, \fBesis\fP, or \fBisis\fP.
+.IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBiso proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
+Abbreviations for IS-IS PDU types.
+.IP "\fBvpi\fP \fIn\fR"
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual path identifier of
+.IR n .
+.IP "\fBvci\fP \fIn\fR"
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual channel identifier of
+.IR n .
+.IP \fBlane\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an ATM LANE packet.
+Note that the first \fBlane\fR keyword encountered in \fIexpression\fR
+changes the tests done in the remainder of \fIexpression\fR
+on the assumption that the packet is either a LANE emulated Ethernet
+packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the
+tests are done under the assumption that the packet is an
+LLC-encapsulated packet.
+.IP \fBoamf4s\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment OAM F4 flow cell (VPI=0 & VCI=3).
+.IP \fBoamf4e\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an end-to-end OAM F4 flow cell (VPI=0 & VCI=4).
+.IP \fBoamf4\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBoam\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBmetac\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit (VPI=0 & VCI=1).
+.IP \fBbcc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a broadcast signaling circuit (VPI=0 & VCI=2).
+.IP \fBsc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit (VPI=0 & VCI=5).
+.IP \fBilmic\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on an ILMI circuit (VPI=0 & VCI=16).
+.IP \fBconnectmsg\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Connect Ack, Release, or Release Done message.
+.IP \fBmetaconnect\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Release, or Release Done message.
+.IP "\fIexpr relop expr\fR"
+True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =,
+!=, and \fIexpr\fR is an arithmetic expression composed of integer
+constants (expressed in standard C syntax), the normal binary operators
+[+, -, *, /, %, &, |, ^, <<, >>], a length operator, and special packet data
+accessors. Note that all comparisons are unsigned, so that, for example,
+0x80000000 and 0xffffffff are > 0.
+.IP
+The % and ^ operators are currently only supported for filtering in the
+kernel on Linux with 3.7 and later kernels; on all other systems, if
+those operators are used, filtering will be done in user mode, which
+will increase the overhead of capturing packets and may cause more
+packets to be dropped.
+.IP
+To access data inside the packet, use the following syntax:
+.in +.5i
+.nf
+\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
+.fi
+.in -.5i
+\fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link,
+ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and
+indicates the protocol layer for the index operation.
+(\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the
+link layer. \fBradio\fR refers to the "radio header" added to some
+802.11 captures.)
+Note that \fItcp, udp\fR and other upper-layer protocol types only
+apply to IPv4, not IPv6 (this will be fixed in the future).
+The byte offset, relative to the indicated protocol layer, is
+given by \fIexpr\fR.
+\fISize\fR is optional and indicates the number of bytes in the
+field of interest; it can be either one, two, or four, and defaults to one.
+The length operator, indicated by the keyword \fBlen\fP, gives the
+length of the packet.
+
+For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
+The expression `\fBip[0] & 0xf != 5\fP'
+catches all IPv4 packets with options.
+The expression
+`\fBip[6:2] & 0x1fff = 0\fP'
+catches only unfragmented IPv4 datagrams and frag zero of fragmented
+IPv4 datagrams.
+This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
+index operations.
+For instance, \fBtcp[0]\fP always means the first
+byte of the TCP \fIheader\fP, and never means the first byte of an
+intervening fragment.
+
+Some offsets and field values may be expressed as names rather than
+as numeric values.
+The following protocol header field offsets are
+available: \fBicmptype\fP (ICMP type field), \fBicmp6type (ICMP v6 type field)
+\fBicmpcode\fP (ICMP code field), \fBicmp6code\fP (ICMP v6 code field), and
+\fBtcpflags\fP (TCP flags field).
+
+The following ICMP type field values are available: \fBicmp-echoreply\fP,
+\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
+\fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP,
+\fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP,
+\fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
+\fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
+
+The following ICMPv6 type fields are available: \fBicmp6-echo\fP,
+\fBicmp6-echoreply\fP, \fBicmp6-multicastlistenerquery\fP,
+\fBicmp6-multicastlistenerreportv1\fP, \fBicmp6-multicastlistenerdone\fP,
+\fBicmp6-routersolicit\fP, \fBicmp6-routeradvert\fP,
+\fBicmp6-neighborsolicit\fP, \fBicmp6-neighboradvert\fP, \fBicmp6-redirect\fP,
+\fBicmp6-routerrenum\fP, \fBicmp6-nodeinformationquery\fP,
+\fBicmp6-nodeinformationresponse\fP, \fBicmp6-ineighbordiscoverysolicit\fP,
+\fBicmp6-ineighbordiscoveryadvert\fP, \fBicmp6-multicastlistenerreportv2\fP,
+\fBicmp6-homeagentdiscoveryrequest\fP, \fBicmp6-homeagentdiscoveryreply\fP,
+\fBicmp6-mobileprefixsolicit\fP, \fBicmp6-mobileprefixadvert\fP,
+\fBicmp6-certpathsolicit\fP, \fBicmp6-certpathadvert\fP,
+\fBicmp6-multicastrouteradvert\fP, \fBicmp6-multicastroutersolicit\fP,
+\fBicmp6-multicastrouterterm\fP.
+
+The following TCP flags field values are available: \fBtcp-fin\fP,
+\fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
+\fBtcp-ack\fP, \fBtcp-urg\fP, \fBtcp-ece\fP,
+\fBtcp-cwr\fP.
+.LP
+Primitives may be combined using:
+.IP
+A parenthesized group of primitives and operators.
+.IP
+Negation (`\fB!\fP' or `\fBnot\fP').
+.IP
+Concatenation (`\fB&&\fP' or `\fBand\fP').
+.IP
+Alternation (`\fB||\fP' or `\fBor\fP').
+.LP
+Negation has highest precedence.
+Alternation and concatenation have equal precedence and associate
+left to right.
+Note that explicit \fBand\fR tokens, not juxtaposition,
+are now required for concatenation.
+.LP
+If an identifier is given without a keyword, the most recent keyword
+is assumed.
+For example,
+.in +.5i
+.nf
+\fBnot host vs and ace\fR
+.fi
+.in -.5i
+is short for
+.in +.5i
+.nf
+\fBnot host vs and host ace\fR
+.fi
+.in -.5i
+which should not be confused with
+.in +.5i
+.nf
+\fBnot ( host vs or ace )\fR
+.fi
+.in -.5i
+.SH EXAMPLES
+.LP
+To select all packets arriving at or departing from \fIsundown\fP:
+.RS
+.nf
+\fBhost sundown\fP
+.fi
+.RE
+.LP
+To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+.RS
+.nf
+\fBhost helios and \\( hot or ace \\)\fP
+.fi
+.RE
+.LP
+To select all IP packets between \fIace\fR and any host except \fIhelios\fR:
+.RS
+.nf
+\fBip host ace and not helios\fP
+.fi
+.RE
+.LP
+To select all traffic between local hosts and hosts at Berkeley:
+.RS
+.nf
+.B
+net ucb-ether
+.fi
+.RE
+.LP
+To select all ftp traffic through internet gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and (port ftp or ftp-data)
+.fi
+.RE
+.LP
+To select traffic neither sourced from nor destined for local hosts
+(if you gateway to one other net, this stuff should never make it
+onto your local net).
+.RS
+.nf
+.B
+ip and not net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select the start and end packets (the SYN and FIN packets) of each
+TCP conversation that involves a non-local host.
+.RS
+.nf
+.B
+tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select all IPv4 HTTP packets to and from port 80, i.e. print only
+packets that contain data, not, for example, SYN and FIN packets and
+ACK-only packets. (IPv6 is left as an exercise for the reader.)
+.RS
+.nf
+.B
+tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)
+.fi
+.RE
+.LP
+To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and ip[2:2] > 576
+.fi
+.RE
+.LP
+To select IP broadcast or multicast packets that were
+.I not
+sent via Ethernet broadcast or multicast:
+.RS
+.nf
+.B
+ether[0] & 1 = 0 and ip[16] >= 224
+.fi
+.RE
+.LP
+To select all ICMP packets that are not echo requests/replies (i.e., not
+ping packets):
+.RS
+.nf
+.B
+icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
+.fi
+.RE
+.SH "SEE ALSO"
+pcap(3PCAP)
+.SH BUGS
+To report a security issue please send an e-mail to security@tcpdump.org.
+.LP
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+.I CONTRIBUTING
+in the libpcap source tree root.
+.LP
+Filter expressions on fields other than those in Token Ring headers will
+not correctly handle source-routed Token Ring packets.
+.LP
+Filter expressions on fields other than those in 802.11 headers will not
+correctly handle 802.11 data packets with both To DS and From DS set.
+.LP
+.BR "ip6 proto"
+should chase header chain, but at this moment it does not.
+.BR "ip6 protochain"
+is supplied for this behavior.
+.LP
+Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
+does not work against IPv6 packets.
+It only looks at IPv4 packets.
diff --git a/lib/libpcap/libpcap/pcap-filter.manmisc.in b/lib/libpcap/libpcap/pcap-filter.manmisc.in
new file mode 100644
index 0000000..777e735
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-filter.manmisc.in
@@ -0,0 +1,1052 @@
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-FILTER @MAN_MISC_INFO@ "5 November 2017"
+.SH NAME
+pcap-filter \- packet filter syntax
+.br
+.ad
+.SH DESCRIPTION
+.LP
+.B pcap_compile()
+is used to compile a string into a filter program.
+The resulting filter program can then be applied to
+some stream of packets to determine which packets will be supplied to
+.BR pcap_loop(3PCAP) ,
+.BR pcap_dispatch(3PCAP) ,
+.BR pcap_next(3PCAP) ,
+or
+.BR pcap_next_ex(3PCAP) .
+.LP
+The \fIfilter expression\fP consists of one or more
+.IR primitives .
+Primitives usually consist of an
+.I id
+(name or number) preceded by one or more qualifiers.
+There are three
+different kinds of qualifier:
+.IP \fItype\fP
+.I type
+qualifiers say what kind of thing the id name or number refers to.
+Possible types are
+.BR host ,
+.B net ,
+.B port
+and
+.BR portrange .
+E.g., `host foo', `net 128.3', `port 20', `portrange 6000-6008'.
+If there is no type
+qualifier,
+.B host
+is assumed.
+.IP \fIdir\fP
+.I dir
+qualifiers specify a particular transfer direction to and/or from
+.IR id .
+Possible directions are
+.BR src ,
+.BR dst ,
+.BR "src or dst" ,
+.BR "src and dst" ,
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.BR addr4 .
+E.g., `src foo', `dst net 128.3', `src or dst port ftp-data'.
+If
+there is no dir qualifier,
+.B "src or dst"
+is assumed.
+The
+.BR ra ,
+.BR ta ,
+.BR addr1 ,
+.BR addr2 ,
+.BR addr3 ,
+and
+.B addr4
+qualifiers are only valid for IEEE 802.11 Wireless LAN link layers.
+.IP \fIproto\fP
+.I proto
+qualifiers restrict the match to a particular protocol.
+Possible
+protos are:
+.BR ether ,
+.BR fddi ,
+.BR tr ,
+.BR wlan ,
+.BR ip ,
+.BR ip6 ,
+.BR arp ,
+.BR rarp ,
+.BR decnet ,
+.B tcp
+and
+.BR udp .
+E.g., `ether src foo', `arp net 128.3', `tcp port 21', `udp portrange
+7000-7009', `wlan addr2 0:2:3:4:5:6'.
+If there is
+no proto qualifier, all protocols consistent with the type are
+assumed.
+E.g., `src foo' means `(ip or arp or rarp) src foo'
+(except the latter is not legal syntax), `net bar' means `(ip or
+arp or rarp) net bar' and `port 53' means `(tcp or udp) port 53'.
+.LP
+[`fddi' is actually an alias for `ether'; the parser treats them
+identically as meaning ``the data link level used on the specified
+network interface.'' FDDI headers contain Ethernet-like source
+and destination addresses, and often contain Ethernet-like packet
+types, so you can filter on these FDDI fields just as with the
+analogous Ethernet fields.
+FDDI headers also contain other fields,
+but you cannot name them explicitly in a filter expression.
+.LP
+Similarly, `tr' and `wlan' are aliases for `ether'; the previous
+paragraph's statements about FDDI headers also apply to Token Ring
+and 802.11 wireless LAN headers. For 802.11 headers, the destination
+address is the DA field and the source address is the SA field; the
+BSSID, RA, and TA fields aren't tested.]
+.LP
+In addition to the above, there are some special `primitive' keywords
+that don't follow the pattern:
+.BR gateway ,
+.BR broadcast ,
+.BR less ,
+.B greater
+and arithmetic expressions.
+All of these are described below.
+.LP
+More complex filter expressions are built up by using the words
+.BR and ,
+.B or
+and
+.B not
+to combine primitives.
+E.g., `host foo and not port ftp and not port ftp-data'.
+To save typing, identical qualifier lists can be omitted.
+E.g.,
+`tcp dst port ftp or ftp-data or domain' is exactly the same as
+`tcp dst port ftp or tcp dst port ftp-data or tcp dst port domain'.
+.LP
+Allowable primitives are:
+.IP "\fBdst host \fIhost\fR"
+True if the IPv4/v6 destination field of the packet is \fIhost\fP,
+which may be either an address or a name.
+.IP "\fBsrc host \fIhost\fR"
+True if the IPv4/v6 source field of the packet is \fIhost\fP.
+.IP "\fBhost \fIhost\fP"
+True if either the IPv4/v6 source or destination of the packet is \fIhost\fP.
+.IP
+Any of the above host expressions can be prepended with the keywords,
+\fBip\fP, \fBarp\fP, \fBrarp\fP, or \fBip6\fP as in:
+.in +.5i
+.nf
+\fBip host \fIhost\fR
+.fi
+.in -.5i
+which is equivalent to:
+.in +.5i
+.nf
+\fBether proto \fI\\ip\fB and host \fIhost\fR
+.fi
+.in -.5i
+If \fIhost\fR is a name with multiple IP addresses, each address will
+be checked for a match.
+.IP "\fBether dst \fIehost\fP"
+True if the Ethernet destination address is \fIehost\fP.
+\fIEhost\fP
+may be either a name from /etc/ethers or a numerical MAC address of the
+form "xx:xx:xx:xx:xx:xx", "xx.xx.xx.xx.xx.xx", "xx-xx-xx-xx-xx-xx",
+"xxxx.xxxx.xxxx", "xxxxxxxxxxxx", or various mixes of ':', '.', and '-',
+where each "x" is a hex digit (0-9, a-f, or A-F).
+.IP "\fBether src \fIehost\fP"
+True if the Ethernet source address is \fIehost\fP.
+.IP "\fBether host \fIehost\fP"
+True if either the Ethernet source or destination address is \fIehost\fP.
+.IP "\fBgateway\fP \fIhost\fP"
+True if the packet used \fIhost\fP as a gateway.
+I.e., the Ethernet
+source or destination address was \fIhost\fP but neither the IP source
+nor the IP destination was \fIhost\fP.
+\fIHost\fP must be a name and
+must be found both by the machine's host-name-to-IP-address resolution
+mechanisms (host name file, DNS, NIS, etc.) and by the machine's
+host-name-to-Ethernet-address resolution mechanism (/etc/ethers, etc.).
+(An equivalent expression is
+.in +.5i
+.nf
+\fBether host \fIehost \fBand not host \fIhost\fR
+.fi
+.in -.5i
+which can be used with either names or numbers for \fIhost / ehost\fP.)
+This syntax does not work in IPv6-enabled configuration at this moment.
+.IP "\fBdst net \fInet\fR"
+True if the IPv4/v6 destination address of the packet has a network
+number of \fInet\fP.
+\fINet\fP may be either a name from the networks database
+(/etc/networks, etc.) or a network number.
+An IPv4 network number can be written as a dotted quad (e.g., 192.168.1.0),
+dotted triple (e.g., 192.168.1), dotted pair (e.g, 172.16), or single
+number (e.g., 10); the netmask is 255.255.255.255 for a dotted quad
+(which means that it's really a host match), 255.255.255.0 for a dotted
+triple, 255.255.0.0 for a dotted pair, or 255.0.0.0 for a single number.
+An IPv6 network number must be written out fully; the netmask is
+ff:ff:ff:ff:ff:ff:ff:ff, so IPv6 "network" matches are really always
+host matches, and a network match requires a netmask length.
+.IP "\fBsrc net \fInet\fR"
+True if the IPv4/v6 source address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR"
+True if either the IPv4/v6 source or destination address of the packet has a network
+number of \fInet\fP.
+.IP "\fBnet \fInet\fR \fBmask \fInetmask\fR"
+True if the IPv4 address matches \fInet\fR with the specific \fInetmask\fR.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+Note that this syntax is not valid for IPv6 \fInet\fR.
+.IP "\fBnet \fInet\fR/\fIlen\fR"
+True if the IPv4/v6 address matches \fInet\fR with a netmask \fIlen\fR
+bits wide.
+May be qualified with \fBsrc\fR or \fBdst\fR.
+.IP "\fBdst port \fIport\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value of \fIport\fP.
+The \fIport\fP can be a number or a name used in /etc/services (see
+.IR tcp (4P)
+and
+.IR udp (4P)).
+If a name is used, both the port
+number and protocol are checked.
+If a number or ambiguous name is used,
+only the port number is checked (e.g., \fBdst port 513\fR will print both
+tcp/login traffic and udp/who traffic, and \fBport domain\fR will print
+both tcp/domain and udp/domain traffic).
+.IP "\fBsrc port \fIport\fR"
+True if the packet has a source port value of \fIport\fP.
+.IP "\fBport \fIport\fR"
+True if either the source or destination port of the packet is \fIport\fP.
+.IP "\fBdst portrange \fIport1\fB-\fIport2\fR"
+True if the packet is ip/tcp, ip/udp, ip6/tcp or ip6/udp and has a
+destination port value between \fIport1\fP and \fIport2\fP.
+.I port1
+and
+.I port2
+are interpreted in the same fashion as the
+.I port
+parameter for
+.BR port .
+.IP "\fBsrc portrange \fIport1\fB-\fIport2\fR"
+True if the packet has a source port value between \fIport1\fP and
+\fIport2\fP.
+.IP "\fBportrange \fIport1\fB-\fIport2\fR"
+True if either the source or destination port of the packet is between
+\fIport1\fP and \fIport2\fP.
+.IP
+Any of the above port or port range expressions can be prepended with
+the keywords, \fBtcp\fP or \fBudp\fP, as in:
+.in +.5i
+.nf
+\fBtcp src port \fIport\fR
+.fi
+.in -.5i
+which matches only tcp packets whose source port is \fIport\fP.
+.IP "\fBless \fIlength\fR"
+True if the packet has a length less than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen <= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBgreater \fIlength\fR"
+True if the packet has a length greater than or equal to \fIlength\fP.
+This is equivalent to:
+.in +.5i
+.nf
+\fBlen >= \fIlength\fP.
+.fi
+.in -.5i
+.IP "\fBip proto \fIprotocol\fR"
+True if the packet is an IPv4 packet (see
+.IR ip (4P))
+of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBicmp\fP, \fBicmp6\fP, \fBigmp\fP, \fBigrp\fP, \fBpim\fP, \fBah\fP,
+\fBesp\fP, \fBvrrp\fP, \fBudp\fP, or \fBtcp\fP.
+Note that the identifiers \fBtcp\fP, \fBudp\fP, and \fBicmp\fP are also
+keywords and must be escaped via backslash (\\).
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBip6 proto \fIprotocol\fR"
+True if the packet is an IPv6 packet of protocol type \fIprotocol\fP.
+Note that this primitive does not chase the protocol header chain.
+.IP "\fBproto \fIprotocol\fR"
+True if the packet is an IPv4 or IPv6 packet of protocol type
+\fIprotocol\fP. Note that this primitive does not chase the protocol
+header chain.
+.IP "\fBtcp\fR, \fBudp\fR, \fBicmp\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBproto \fIp\fR\fB
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBip6 protochain \fIprotocol\fR"
+True if the packet is IPv6 packet,
+and contains protocol header with type \fIprotocol\fR
+in its protocol header chain.
+For example,
+.in +.5i
+.nf
+\fBip6 protochain 6\fR
+.fi
+.in -.5i
+matches any IPv6 packet with TCP protocol header in the protocol header chain.
+The packet may contain, for example,
+authentication header, routing header, or hop-by-hop option header,
+between IPv6 header and TCP header.
+The BPF code emitted by this primitive is complex and
+cannot be optimized by the BPF optimizer code, and is not supported by
+filter engines in the kernel, so this can be somewhat slow, and may
+cause more packets to be dropped.
+.IP "\fBip protochain \fIprotocol\fR"
+Equivalent to \fBip6 protochain \fIprotocol\fR, but this is for IPv4.
+.IP "\fBprotochain \fIprotocol\fR"
+True if the packet is an IPv4 or IPv6 packet of protocol type
+\fIprotocol\fP. Note that this primitive chases the protocol
+header chain.
+.IP "\fBether broadcast\fR"
+True if the packet is an Ethernet broadcast packet.
+The \fIether\fP
+keyword is optional.
+.IP "\fBip broadcast\fR"
+True if the packet is an IPv4 broadcast packet.
+It checks for both the all-zeroes and all-ones broadcast conventions,
+and looks up the subnet mask on the interface on which the capture is
+being done.
+.IP
+If the subnet mask of the interface on which the capture is being done
+is not available, either because the interface on which capture is being
+done has no netmask or because the capture is being done on the Linux
+"any" interface, which can capture on more than one interface, this
+check will not work correctly.
+.IP "\fBether multicast\fR"
+True if the packet is an Ethernet multicast packet.
+The \fBether\fP
+keyword is optional.
+This is shorthand for `\fBether[0] & 1 != 0\fP'.
+.IP "\fBip multicast\fR"
+True if the packet is an IPv4 multicast packet.
+.IP "\fBip6 multicast\fR"
+True if the packet is an IPv6 multicast packet.
+.IP "\fBether proto \fIprotocol\fR"
+True if the packet is of ether type \fIprotocol\fR.
+\fIProtocol\fP can be a number or one of the names
+\fBip\fP, \fBip6\fP, \fBarp\fP, \fBrarp\fP, \fBatalk\fP, \fBaarp\fP,
+\fBdecnet\fP, \fBsca\fP, \fBlat\fP, \fBmopdl\fP, \fBmoprc\fP,
+\fBiso\fP, \fBstp\fP, \fBipx\fP, or \fBnetbeui\fP.
+Note these identifiers are also keywords
+and must be escaped via backslash (\\).
+.IP
+[In the case of FDDI (e.g., `\fBfddi proto arp\fR'), Token Ring
+(e.g., `\fBtr proto arp\fR'), and IEEE 802.11 wireless LANS (e.g.,
+`\fBwlan proto arp\fR'), for most of those protocols, the
+protocol identification comes from the 802.2 Logical Link Control (LLC)
+header, which is usually layered on top of the FDDI, Token Ring, or
+802.11 header.
+.IP
+When filtering for most protocol identifiers on FDDI, Token Ring, or
+802.11, the filter checks only the protocol ID field of an LLC header
+in so-called SNAP format with an Organizational Unit Identifier (OUI) of
+0x000000, for encapsulated Ethernet; it doesn't check whether the packet
+is in SNAP format with an OUI of 0x000000.
+The exceptions are:
+.RS
+.TP
+\fBiso\fP
+the filter checks the DSAP (Destination Service Access Point) and
+SSAP (Source Service Access Point) fields of the LLC header;
+.TP
+\fBstp\fP and \fBnetbeui\fP
+the filter checks the DSAP of the LLC header;
+.TP
+\fBatalk\fP
+the filter checks for a SNAP-format packet with an OUI of 0x080007
+and the AppleTalk etype.
+.RE
+.IP
+In the case of Ethernet, the filter checks the Ethernet type field
+for most of those protocols. The exceptions are:
+.RS
+.TP
+\fBiso\fP, \fBstp\fP, and \fBnetbeui\fP
+the filter checks for an 802.3 frame and then checks the LLC header as
+it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBatalk\fP
+the filter checks both for the AppleTalk etype in an Ethernet frame and
+for a SNAP-format packet as it does for FDDI, Token Ring, and 802.11;
+.TP
+\fBaarp\fP
+the filter checks for the AppleTalk ARP etype in either an Ethernet
+frame or an 802.2 SNAP frame with an OUI of 0x000000;
+.TP
+\fBipx\fP
+the filter checks for the IPX etype in an Ethernet frame, the IPX
+DSAP in the LLC header, the 802.3-with-no-LLC-header encapsulation of
+IPX, and the IPX etype in a SNAP frame.
+.RE
+.IP "\fBip\fR, \fBip6\fR, \fBarp\fR, \fBrarp\fR, \fBatalk\fR, \fBaarp\fR, \fBdecnet\fR, \fBiso\fR, \fBstp\fR, \fBipx\fR, \fBnetbeui\fP"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBlat\fR, \fBmoprc\fR, \fBmopdl\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBether proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+Note that not all applications using
+.BR pcap (3PCAP)
+currently know how to parse these protocols.
+.IP "\fBdecnet src \fIhost\fR"
+True if the DECNET source address is
+.IR host ,
+which may be an address of the form ``10.123'', or a DECNET host
+name.
+[DECNET host name support is only available on ULTRIX systems
+that are configured to run DECNET.]
+.IP "\fBdecnet dst \fIhost\fR"
+True if the DECNET destination address is
+.IR host .
+.IP "\fBdecnet host \fIhost\fR"
+True if either the DECNET source or destination address is
+.IR host .
+.IP \fBllc\fP
+True if the packet has an 802.2 LLC header. This includes:
+.IP
+Ethernet packets with a length field rather than a type field that
+aren't raw NetWare-over-802.3 packets;
+.IP
+IEEE 802.11 data packets;
+.IP
+Token Ring packets (no check is done for LLC frames);
+.IP
+FDDI packets (no check is done for LLC frames);
+.IP
+LLC-encapsulated ATM packets, for SunATM on Solaris.
+.IP "\fBllc\fP \Fitype\fR"
+True if the packet has an 802.2 LLC header and has the specified
+.IR type .
+.I type
+can be one of:
+.RS
+.TP
+\fBi\fR
+Information (I) PDUs
+.TP
+\fBs\fR
+Supervisory (S) PDUs
+.TP
+\fBu\fR
+Unnumbered (U) PDUs
+.TP
+\fBrr\fR
+Receiver Ready (RR) S PDUs
+.TP
+\fBrnr\fR
+Receiver Not Ready (RNR) S PDUs
+.TP
+\fBrej\fR
+Reject (REJ) S PDUs
+.TP
+\fBui\fR
+Unnumbered Information (UI) U PDUs
+.TP
+\fBua\fR
+Unnumbered Acknowledgment (UA) U PDUs
+.TP
+\fBdisc\fR
+Disconnect (DISC) U PDUs
+.TP
+\fBsabme\fR
+Set Asynchronous Balanced Mode Extended (SABME) U PDUs
+.TP
+\fBtest\fR
+Test (TEST) U PDUs
+.TP
+\fBxid\fR
+Exchange Identification (XID) U PDUs
+.TP
+\fBfrmr\fR
+Frame Reject (FRMR) U PDUs
+.RE
+.IP \fBinbound\fP
+Packet was received by the host performing the capture rather than being
+sent by that host. This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
+.IP \fBoutbound\fP
+Packet was sent by the host performing the capture rather than being
+received by that host. This is only supported for certain link-layer types,
+such as SLIP and the ``cooked'' Linux capture mode
+used for the ``any'' device and for some other device types.
+.IP "\fBifname \fIinterface\fR"
+True if the packet was logged as coming from the specified interface (applies
+only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBon \fIinterface\fR"
+Synonymous with the
+.B ifname
+modifier.
+.IP "\fBrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrulenum \fInum\fR"
+Synonymous with the
+.B rnr
+modifier.
+.IP "\fBreason \fIcode\fR"
+True if the packet was logged with the specified PF reason code. The known
+codes are:
+.BR match ,
+.BR bad-offset ,
+.BR fragment ,
+.BR short ,
+.BR normalize ,
+and
+.B memory
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBrset \fIname\fR"
+True if the packet was logged as matching the specified PF ruleset
+name of an anchored ruleset (applies only to packets logged by OpenBSD's
+or FreeBSD's
+.BR pf (4)).
+.IP "\fBruleset \fIname\fR"
+Synonymous with the
+.B rset
+modifier.
+.IP "\fBsrnr \fInum\fR"
+True if the packet was logged as matching the specified PF rule number
+of an anchored ruleset (applies only to packets logged by OpenBSD's or
+FreeBSD's
+.BR pf (4)).
+.IP "\fBsubrulenum \fInum\fR"
+Synonymous with the
+.B srnr
+modifier.
+.IP "\fBaction \fIact\fR"
+True if PF took the specified action when the packet was logged. Known actions
+are:
+.B pass
+and
+.B block
+and, with later versions of
+.BR pf (4),
+.BR nat ,
+.BR rdr ,
+.B binat
+and
+.B scrub
+(applies only to packets logged by OpenBSD's or FreeBSD's
+.BR pf (4)).
+.IP "\fBwlan ra \fIehost\fR"
+True if the IEEE 802.11 RA is
+.IR ehost .
+The RA field is used in all frames except for management frames.
+.IP "\fBwlan ta \fIehost\fR"
+True if the IEEE 802.11 TA is
+.IR ehost .
+The TA field is used in all frames except for management frames and
+CTS (Clear To Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr1 \fIehost\fR"
+True if the first IEEE 802.11 address is
+.IR ehost .
+.IP "\fBwlan addr2 \fIehost\fR"
+True if the second IEEE 802.11 address, if present, is
+.IR ehost .
+The second address field is used in all frames except for CTS (Clear To
+Send) and ACK (Acknowledgment) control frames.
+.IP "\fBwlan addr3 \fIehost\fR"
+True if the third IEEE 802.11 address, if present, is
+.IR ehost .
+The third address field is used in management and data frames, but not
+in control frames.
+.IP "\fBwlan addr4 \fIehost\fR"
+True if the fourth IEEE 802.11 address, if present, is
+.IR ehost .
+The fourth address field is only used for
+WDS (Wireless Distribution System) frames.
+.IP "\fBtype \fIwlan_type\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR.
+Valid \fIwlan_type\fRs are:
+\fBmgt\fP,
+\fBctl\fP
+and \fBdata\fP.
+.IP "\fBtype \fIwlan_type \fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame type matches the specified \fIwlan_type\fR
+and frame subtype matches the specified \fIwlan_subtype\fR.
+.IP
+If the specified \fIwlan_type\fR is \fBmgt\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBassoc-req\fP,
+\fBassoc-resp\fP,
+\fBreassoc-req\fP,
+\fBreassoc-resp\fP,
+\fBprobe-req\fP,
+\fBprobe-resp\fP,
+\fBbeacon\fP,
+\fBatim\fP,
+\fBdisassoc\fP,
+\fBauth\fP and
+\fBdeauth\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBctl\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBps-poll\fP,
+\fBrts\fP,
+\fBcts\fP,
+\fBack\fP,
+\fBcf-end\fP and
+\fBcf-end-ack\fP.
+.IP
+If the specified \fIwlan_type\fR is \fBdata\fP,
+then valid \fIwlan_subtype\fRs are:
+\fBdata\fP,
+\fBdata-cf-ack\fP,
+\fBdata-cf-poll\fP,
+\fBdata-cf-ack-poll\fP,
+\fBnull\fP,
+\fBcf-ack\fP,
+\fBcf-poll\fP,
+\fBcf-ack-poll\fP,
+\fBqos-data\fP,
+\fBqos-data-cf-ack\fP,
+\fBqos-data-cf-poll\fP,
+\fBqos-data-cf-ack-poll\fP,
+\fBqos\fP,
+\fBqos-cf-poll\fP and
+\fBqos-cf-ack-poll\fP.
+.IP "\fBsubtype \fIwlan_subtype\fR"
+True if the IEEE 802.11 frame subtype matches the specified \fIwlan_subtype\fR
+and frame has the type to which the specified \fIwlan_subtype\fR belongs.
+.IP "\fBdir \fIdir\fR"
+True if the IEEE 802.11 frame direction matches the specified
+.IR dir .
+Valid directions are:
+.BR nods ,
+.BR tods ,
+.BR fromds ,
+.BR dstods ,
+or a numeric value.
+.IP "\fBvlan \fI[vlan_id]\fR"
+True if the packet is an IEEE 802.1Q VLAN packet.
+If \fI[vlan_id]\fR is specified, only true if the packet has the specified
+\fIvlan_id\fR.
+Note that the first \fBvlan\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a VLAN packet. The \fBvlan
+\fI[vlan_id]\fR expression may be used more than once, to filter on VLAN
+hierarchies. Each use of that expression increments the filter offsets
+by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBvlan 100 && vlan 200\fR
+.fi
+.in -.5i
+filters on VLAN 200 encapsulated within VLAN 100, and
+.in +.5i
+.nf
+\fBvlan && vlan 300 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in VLAN 300 encapsulated within any
+higher order VLAN.
+.IP "\fBmpls \fI[label_num]\fR"
+True if the packet is an MPLS packet.
+If \fI[label_num]\fR is specified, only true is the packet has the specified
+\fIlabel_num\fR.
+Note that the first \fBmpls\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a MPLS-encapsulated IP packet. The
+\fBmpls \fI[label_num]\fR expression may be used more than once, to
+filter on MPLS hierarchies. Each use of that expression increments the
+filter offsets by 4.
+.IP
+For example:
+.in +.5i
+.nf
+\fBmpls 100000 && mpls 1024\fR
+.fi
+.in -.5i
+filters packets with an outer label of 100000 and an inner label of
+1024, and
+.in +.5i
+.nf
+\fBmpls && mpls 1024 && host 192.9.200.1\fR
+.fi
+.in -.5i
+filters packets to or from 192.9.200.1 with an inner label of 1024 and
+any outer label.
+.IP \fBpppoed\fP
+True if the packet is a PPP-over-Ethernet Discovery packet (Ethernet
+type 0x8863).
+.IP "\fBpppoes \fI[session_id]\fR"
+True if the packet is a PPP-over-Ethernet Session packet (Ethernet
+type 0x8864).
+If \fI[session_id]\fR is specified, only true if the packet has the specified
+\fIsession_id\fR.
+Note that the first \fBpppoes\fR keyword encountered in \fIexpression\fR
+changes the decoding offsets for the remainder of \fIexpression\fR on
+the assumption that the packet is a PPPoE session packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBpppoes 0x27 && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in PPPoE session id 0x27.
+.IP "\fBgeneve \fI[vni]\fR"
+True if the packet is a Geneve packet (UDP port 6081). If \fI[vni]\fR
+is specified, only true if the packet has the specified \fIvni\fR.
+Note that when the \fBgeneve\fR keyword is encountered in
+\fIexpression\fR, it changes the decoding offsets for the remainder of
+\fIexpression\fR on the assumption that the packet is a Geneve packet.
+.IP
+For example:
+.in +.5i
+.nf
+\fBgeneve 0xb && ip\fR
+.fi
+.in -.5i
+filters IPv4 protocols encapsulated in Geneve with VNI 0xb. This will
+match both IP directly encapsulated in Geneve as well as IP contained
+inside an Ethernet frame.
+.IP "\fBiso proto \fIprotocol\fR"
+True if the packet is an OSI packet of protocol type \fIprotocol\fP.
+\fIProtocol\fP can be a number or one of the names
+\fBclnp\fP, \fBesis\fP, or \fBisis\fP.
+.IP "\fBclnp\fR, \fBesis\fR, \fBisis\fR"
+Abbreviations for:
+.in +.5i
+.nf
+\fBiso proto \fIp\fR
+.fi
+.in -.5i
+where \fIp\fR is one of the above protocols.
+.IP "\fBl1\fR, \fBl2\fR, \fBiih\fR, \fBlsp\fR, \fBsnp\fR, \fBcsnp\fR, \fBpsnp\fR"
+Abbreviations for IS-IS PDU types.
+.IP "\fBvpi\fP \fIn\fR"
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual path identifier of
+.IR n .
+.IP "\fBvci\fP \fIn\fR"
+True if the packet is an ATM packet, for SunATM on Solaris, with a
+virtual channel identifier of
+.IR n .
+.IP \fBlane\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an ATM LANE packet.
+Note that the first \fBlane\fR keyword encountered in \fIexpression\fR
+changes the tests done in the remainder of \fIexpression\fR
+on the assumption that the packet is either a LANE emulated Ethernet
+packet or a LANE LE Control packet. If \fBlane\fR isn't specified, the
+tests are done under the assumption that the packet is an
+LLC-encapsulated packet.
+.IP \fBoamf4s\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment OAM F4 flow cell (VPI=0 & VCI=3).
+.IP \fBoamf4e\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+an end-to-end OAM F4 flow cell (VPI=0 & VCI=4).
+.IP \fBoamf4\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBoam\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+a segment or end-to-end OAM F4 flow cell (VPI=0 & (VCI=3 | VCI=4)).
+.IP \fBmetac\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit (VPI=0 & VCI=1).
+.IP \fBbcc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a broadcast signaling circuit (VPI=0 & VCI=2).
+.IP \fBsc\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit (VPI=0 & VCI=5).
+.IP \fBilmic\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on an ILMI circuit (VPI=0 & VCI=16).
+.IP \fBconnectmsg\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Connect Ack, Release, or Release Done message.
+.IP \fBmetaconnect\fP
+True if the packet is an ATM packet, for SunATM on Solaris, and is
+on a meta signaling circuit and is a Q.2931 Setup, Call Proceeding, Connect,
+Release, or Release Done message.
+.IP "\fIexpr relop expr\fR"
+True if the relation holds, where \fIrelop\fR is one of >, <, >=, <=, =,
+!=, and \fIexpr\fR is an arithmetic expression composed of integer
+constants (expressed in standard C syntax), the normal binary operators
+[+, -, *, /, %, &, |, ^, <<, >>], a length operator, and special packet data
+accessors. Note that all comparisons are unsigned, so that, for example,
+0x80000000 and 0xffffffff are > 0.
+.IP
+The % and ^ operators are currently only supported for filtering in the
+kernel on Linux with 3.7 and later kernels; on all other systems, if
+those operators are used, filtering will be done in user mode, which
+will increase the overhead of capturing packets and may cause more
+packets to be dropped.
+.IP
+To access data inside the packet, use the following syntax:
+.in +.5i
+.nf
+\fIproto\fB [ \fIexpr\fB : \fIsize\fB ]\fR
+.fi
+.in -.5i
+\fIProto\fR is one of \fBether, fddi, tr, wlan, ppp, slip, link,
+ip, arp, rarp, tcp, udp, icmp, ip6\fR or \fBradio\fR, and
+indicates the protocol layer for the index operation.
+(\fBether, fddi, wlan, tr, ppp, slip\fR and \fBlink\fR all refer to the
+link layer. \fBradio\fR refers to the "radio header" added to some
+802.11 captures.)
+Note that \fItcp, udp\fR and other upper-layer protocol types only
+apply to IPv4, not IPv6 (this will be fixed in the future).
+The byte offset, relative to the indicated protocol layer, is
+given by \fIexpr\fR.
+\fISize\fR is optional and indicates the number of bytes in the
+field of interest; it can be either one, two, or four, and defaults to one.
+The length operator, indicated by the keyword \fBlen\fP, gives the
+length of the packet.
+
+For example, `\fBether[0] & 1 != 0\fP' catches all multicast traffic.
+The expression `\fBip[0] & 0xf != 5\fP'
+catches all IPv4 packets with options.
+The expression
+`\fBip[6:2] & 0x1fff = 0\fP'
+catches only unfragmented IPv4 datagrams and frag zero of fragmented
+IPv4 datagrams.
+This check is implicitly applied to the \fBtcp\fP and \fBudp\fP
+index operations.
+For instance, \fBtcp[0]\fP always means the first
+byte of the TCP \fIheader\fP, and never means the first byte of an
+intervening fragment.
+
+Some offsets and field values may be expressed as names rather than
+as numeric values.
+The following protocol header field offsets are
+available: \fBicmptype\fP (ICMP type field), \fBicmp6type (ICMP v6 type field)
+\fBicmpcode\fP (ICMP code field), \fBicmp6code\fP (ICMP v6 code field), and
+\fBtcpflags\fP (TCP flags field).
+
+The following ICMP type field values are available: \fBicmp-echoreply\fP,
+\fBicmp-unreach\fP, \fBicmp-sourcequench\fP, \fBicmp-redirect\fP,
+\fBicmp-echo\fP, \fBicmp-routeradvert\fP, \fBicmp-routersolicit\fP,
+\fBicmp-timxceed\fP, \fBicmp-paramprob\fP, \fBicmp-tstamp\fP,
+\fBicmp-tstampreply\fP, \fBicmp-ireq\fP, \fBicmp-ireqreply\fP,
+\fBicmp-maskreq\fP, \fBicmp-maskreply\fP.
+
+The following ICMPv6 type fields are available: \fBicmp6-echo\fP,
+\fBicmp6-echoreply\fP, \fBicmp6-multicastlistenerquery\fP,
+\fBicmp6-multicastlistenerreportv1\fP, \fBicmp6-multicastlistenerdone\fP,
+\fBicmp6-routersolicit\fP, \fBicmp6-routeradvert\fP,
+\fBicmp6-neighborsolicit\fP, \fBicmp6-neighboradvert\fP, \fBicmp6-redirect\fP,
+\fBicmp6-routerrenum\fP, \fBicmp6-nodeinformationquery\fP,
+\fBicmp6-nodeinformationresponse\fP, \fBicmp6-ineighbordiscoverysolicit\fP,
+\fBicmp6-ineighbordiscoveryadvert\fP, \fBicmp6-multicastlistenerreportv2\fP,
+\fBicmp6-homeagentdiscoveryrequest\fP, \fBicmp6-homeagentdiscoveryreply\fP,
+\fBicmp6-mobileprefixsolicit\fP, \fBicmp6-mobileprefixadvert\fP,
+\fBicmp6-certpathsolicit\fP, \fBicmp6-certpathadvert\fP,
+\fBicmp6-multicastrouteradvert\fP, \fBicmp6-multicastroutersolicit\fP,
+\fBicmp6-multicastrouterterm\fP.
+
+The following TCP flags field values are available: \fBtcp-fin\fP,
+\fBtcp-syn\fP, \fBtcp-rst\fP, \fBtcp-push\fP,
+\fBtcp-ack\fP, \fBtcp-urg\fP, \fBtcp-ece\fP,
+\fBtcp-cwr\fP.
+.LP
+Primitives may be combined using:
+.IP
+A parenthesized group of primitives and operators.
+.IP
+Negation (`\fB!\fP' or `\fBnot\fP').
+.IP
+Concatenation (`\fB&&\fP' or `\fBand\fP').
+.IP
+Alternation (`\fB||\fP' or `\fBor\fP').
+.LP
+Negation has highest precedence.
+Alternation and concatenation have equal precedence and associate
+left to right.
+Note that explicit \fBand\fR tokens, not juxtaposition,
+are now required for concatenation.
+.LP
+If an identifier is given without a keyword, the most recent keyword
+is assumed.
+For example,
+.in +.5i
+.nf
+\fBnot host vs and ace\fR
+.fi
+.in -.5i
+is short for
+.in +.5i
+.nf
+\fBnot host vs and host ace\fR
+.fi
+.in -.5i
+which should not be confused with
+.in +.5i
+.nf
+\fBnot ( host vs or ace )\fR
+.fi
+.in -.5i
+.SH EXAMPLES
+.LP
+To select all packets arriving at or departing from \fIsundown\fP:
+.RS
+.nf
+\fBhost sundown\fP
+.fi
+.RE
+.LP
+To select traffic between \fIhelios\fR and either \fIhot\fR or \fIace\fR:
+.RS
+.nf
+\fBhost helios and \\( hot or ace \\)\fP
+.fi
+.RE
+.LP
+To select all IP packets between \fIace\fR and any host except \fIhelios\fR:
+.RS
+.nf
+\fBip host ace and not helios\fP
+.fi
+.RE
+.LP
+To select all traffic between local hosts and hosts at Berkeley:
+.RS
+.nf
+.B
+net ucb-ether
+.fi
+.RE
+.LP
+To select all ftp traffic through internet gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and (port ftp or ftp-data)
+.fi
+.RE
+.LP
+To select traffic neither sourced from nor destined for local hosts
+(if you gateway to one other net, this stuff should never make it
+onto your local net).
+.RS
+.nf
+.B
+ip and not net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select the start and end packets (the SYN and FIN packets) of each
+TCP conversation that involves a non-local host.
+.RS
+.nf
+.B
+tcp[tcpflags] & (tcp-syn|tcp-fin) != 0 and not src and dst net \fIlocalnet\fP
+.fi
+.RE
+.LP
+To select all IPv4 HTTP packets to and from port 80, i.e. print only
+packets that contain data, not, for example, SYN and FIN packets and
+ACK-only packets. (IPv6 is left as an exercise for the reader.)
+.RS
+.nf
+.B
+tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)
+.fi
+.RE
+.LP
+To select IP packets longer than 576 bytes sent through gateway \fIsnup\fP:
+.RS
+.nf
+.B
+gateway snup and ip[2:2] > 576
+.fi
+.RE
+.LP
+To select IP broadcast or multicast packets that were
+.I not
+sent via Ethernet broadcast or multicast:
+.RS
+.nf
+.B
+ether[0] & 1 = 0 and ip[16] >= 224
+.fi
+.RE
+.LP
+To select all ICMP packets that are not echo requests/replies (i.e., not
+ping packets):
+.RS
+.nf
+.B
+icmp[icmptype] != icmp-echo and icmp[icmptype] != icmp-echoreply
+.fi
+.RE
+.SH "SEE ALSO"
+pcap(3PCAP)
+.SH BUGS
+To report a security issue please send an e-mail to security@tcpdump.org.
+.LP
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+.I CONTRIBUTING
+in the libpcap source tree root.
+.LP
+Filter expressions on fields other than those in Token Ring headers will
+not correctly handle source-routed Token Ring packets.
+.LP
+Filter expressions on fields other than those in 802.11 headers will not
+correctly handle 802.11 data packets with both To DS and From DS set.
+.LP
+.BR "ip6 proto"
+should chase header chain, but at this moment it does not.
+.BR "ip6 protochain"
+is supplied for this behavior.
+.LP
+Arithmetic expression against transport layer headers, like \fBtcp[0]\fP,
+does not work against IPv6 packets.
+It only looks at IPv4 packets.
diff --git a/lib/libpcap/libpcap/pcap-int.h b/lib/libpcap/libpcap/pcap-int.h
new file mode 100644
index 0000000..0fd63e1
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-int.h
@@ -0,0 +1,599 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef pcap_int_h
+#define pcap_int_h
+
+#include <signal.h>
+
+#include <pcap/pcap.h>
+
+#ifdef __APPLE__
+#include <stdbool.h>
+#include "pcap/pcap-ng.h"
+#include "pcap-util.h"
+#endif /* __APPLE__ */
+#include "varattrs.h"
+#include "fmtutils.h"
+
+/*
+ * Version string.
+ * Uses PACKAGE_VERSION from config.h.
+ */
+#define PCAP_VERSION_STRING "libpcap version " PACKAGE_VERSION
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef MSDOS
+ #include <fcntl.h>
+ #include <io.h>
+#endif
+
+/*
+ * Swap byte ordering of unsigned long long timestamp on a big endian
+ * machine.
+ */
+#define SWAPLL(ull) ((ull & 0xff00000000000000ULL) >> 56) | \
+ ((ull & 0x00ff000000000000ULL) >> 40) | \
+ ((ull & 0x0000ff0000000000ULL) >> 24) | \
+ ((ull & 0x000000ff00000000ULL) >> 8) | \
+ ((ull & 0x00000000ff000000ULL) << 8) | \
+ ((ull & 0x0000000000ff0000ULL) << 24) | \
+ ((ull & 0x000000000000ff00ULL) << 40) | \
+ ((ull & 0x00000000000000ffULL) << 56)
+
+/*
+ * Maximum snapshot length.
+ *
+ * Somewhat arbitrary, but chosen to be:
+ *
+ * 1) big enough for maximum-size Linux loopback packets (65549)
+ * and some USB packets captured with USBPcap:
+ *
+ * http://desowin.org/usbpcap/
+ *
+ * (> 131072, < 262144)
+ *
+ * and
+ *
+ * 2) small enough not to cause attempts to allocate huge amounts of
+ * memory; some applications might use the snapshot length in a
+ * savefile header to control the size of the buffer they allocate,
+ * so a size of, say, 2^31-1 might not work well. (libpcap uses it
+ * as a hint, but doesn't start out allocating a buffer bigger than
+ * 2 KiB, and grows the buffer as necessary, but not beyond the
+ * per-linktype maximum snapshot length. Other code might naively
+ * use it; we want to avoid writing a too-large snapshot length,
+ * in order not to cause that code problems.)
+ *
+ * We don't enforce this in pcap_set_snaplen(), but we use it internally.
+ */
+
+#ifdef __APPLE__
+/*
+ * Note: Keep in sync with BPF_MAXBUFSIZE
+ */
+#define MAXIMUM_SNAPLEN 0x80000
+#else
+#define MAXIMUM_SNAPLEN 262144
+#endif
+
+struct pcap_opt {
+ char *device;
+ int timeout; /* timeout for buffering */
+ u_int buffer_size;
+ int promisc;
+ int rfmon; /* monitor mode */
+ int immediate; /* immediate mode - deliver packets as soon as they arrive */
+ int nonblock; /* non-blocking mode - don't wait for packets to be delivered, return "no packets available" */
+ int tstamp_type;
+ int tstamp_precision;
+
+ /*
+ * Platform-dependent options.
+ */
+#ifdef __linux__
+ int protocol; /* protocol to use when creating PF_PACKET socket */
+#endif
+#ifdef _WIN32
+ int nocapture_local;/* disable NPF loopback */
+#endif
+};
+
+typedef int (*activate_op_t)(pcap_t *);
+typedef int (*can_set_rfmon_op_t)(pcap_t *);
+typedef int (*read_op_t)(pcap_t *, int cnt, pcap_handler, u_char *);
+typedef int (*next_packet_op_t)(pcap_t *, struct pcap_pkthdr *, u_char **);
+typedef int (*inject_op_t)(pcap_t *, const void *, size_t);
+typedef void (*save_current_filter_op_t)(pcap_t *, const char *);
+typedef int (*setfilter_op_t)(pcap_t *, struct bpf_program *);
+typedef int (*setdirection_op_t)(pcap_t *, pcap_direction_t);
+typedef int (*set_datalink_op_t)(pcap_t *, int);
+typedef int (*getnonblock_op_t)(pcap_t *);
+typedef int (*setnonblock_op_t)(pcap_t *, int);
+typedef int (*stats_op_t)(pcap_t *, struct pcap_stat *);
+#ifdef _WIN32
+typedef struct pcap_stat *(*stats_ex_op_t)(pcap_t *, int *);
+typedef int (*setbuff_op_t)(pcap_t *, int);
+typedef int (*setmode_op_t)(pcap_t *, int);
+typedef int (*setmintocopy_op_t)(pcap_t *, int);
+typedef HANDLE (*getevent_op_t)(pcap_t *);
+typedef int (*oid_get_request_op_t)(pcap_t *, bpf_u_int32, void *, size_t *);
+typedef int (*oid_set_request_op_t)(pcap_t *, bpf_u_int32, const void *, size_t *);
+typedef u_int (*sendqueue_transmit_op_t)(pcap_t *, pcap_send_queue *, int);
+typedef int (*setuserbuffer_op_t)(pcap_t *, int);
+typedef int (*live_dump_op_t)(pcap_t *, char *, int, int);
+typedef int (*live_dump_ended_op_t)(pcap_t *, int);
+typedef PAirpcapHandle (*get_airpcap_handle_op_t)(pcap_t *);
+#endif
+typedef void (*cleanup_op_t)(pcap_t *);
+#ifdef __APPLE__
+typedef int (*cleanup_interface_op_t)(const char *, char *);
+
+#endif /* __APPLE__ */
+
+/*
+ * We put all the stuff used in the read code path at the beginning,
+ * to try to keep it together in the same cache line or lines.
+ */
+struct pcap {
+ /*
+ * Method to call to read packets on a live capture.
+ */
+ read_op_t read_op;
+
+ /*
+ * Method to call to read the next packet from a savefile.
+ */
+ next_packet_op_t next_packet_op;
+
+#ifdef _WIN32
+ HANDLE handle;
+#else
+ int fd;
+#endif /* _WIN32 */
+
+ /*
+ * Read buffer.
+ */
+ u_int bufsize;
+ void *buffer;
+ u_char *bp;
+ int cc;
+
+ sig_atomic_t break_loop; /* flag set to force break from packet-reading loop */
+
+ void *priv; /* private data for methods */
+
+#ifdef ENABLE_REMOTE
+ struct pcap_samp rmt_samp; /* parameters related to the sampling process. */
+#endif
+
+ int swapped;
+ FILE *rfile; /* null if live capture, non-null if savefile */
+ u_int fddipad;
+ struct pcap *next; /* list of open pcaps that need stuff cleared on close */
+
+ /*
+ * File version number; meaningful only for a savefile, but we
+ * keep it here so that apps that (mistakenly) ask for the
+ * version numbers will get the same zero values that they
+ * always did.
+ */
+ int version_major;
+ int version_minor;
+
+ int snapshot;
+ int linktype; /* Network linktype */
+ int linktype_ext; /* Extended information stored in the linktype field of a file */
+ int tzoff; /* timezone offset */
+ int offset; /* offset for proper alignment */
+ int activated; /* true if the capture is really started */
+ int oldstyle; /* if we're opening with pcap_open_live() */
+
+ struct pcap_opt opt;
+
+ /*
+ * Place holder for pcap_next().
+ */
+ u_char *pkt;
+
+#ifdef _WIN32
+ struct pcap_stat stat; /* used for pcap_stats_ex() */
+#endif
+
+ /* We're accepting only packets in this direction/these directions. */
+ pcap_direction_t direction;
+
+ /*
+ * Flags to affect BPF code generation.
+ */
+ int bpf_codegen_flags;
+
+#if !defined(_WIN32) && !defined(MSDOS)
+ int selectable_fd; /* FD on which select()/poll()/epoll_wait()/kevent()/etc. can be done */
+
+ /*
+ * In case there either is no selectable FD, or there is but
+ * it doesn't necessarily work (e.g., if it doesn't get notified
+ * if the packet capture timeout expires before the buffer
+ * fills up), this points to a timeout that should be used
+ * in select()/poll()/epoll_wait()/kevent() call. The pcap_t should
+ * be put into non-blocking mode, and, if the timeout expires on
+ * the call, an attempt should be made to read packets from all
+ * pcap_t's with a required timeout, and the code must be
+ * prepared not to see any packets from the attempt.
+ */
+ struct timeval *required_select_timeout;
+#endif
+
+ /*
+ * Placeholder for filter code if bpf not in kernel.
+ */
+ struct bpf_program fcode;
+
+ char errbuf[PCAP_ERRBUF_SIZE + 1];
+ int dlt_count;
+ u_int *dlt_list;
+ int tstamp_type_count;
+ u_int *tstamp_type_list;
+ int tstamp_precision_count;
+ u_int *tstamp_precision_list;
+
+ struct pcap_pkthdr pcap_header; /* This is needed for the pcap_next_ex() to work */
+
+ /*
+ * More methods.
+ */
+ activate_op_t activate_op;
+ can_set_rfmon_op_t can_set_rfmon_op;
+ inject_op_t inject_op;
+ save_current_filter_op_t save_current_filter_op;
+ setfilter_op_t setfilter_op;
+ setdirection_op_t setdirection_op;
+ set_datalink_op_t set_datalink_op;
+ getnonblock_op_t getnonblock_op;
+ setnonblock_op_t setnonblock_op;
+ stats_op_t stats_op;
+
+ /*
+ * Routine to use as callback for pcap_next()/pcap_next_ex().
+ */
+ pcap_handler oneshot_callback;
+
+#ifdef _WIN32
+ /*
+ * These are, at least currently, specific to the Win32 NPF
+ * driver.
+ */
+ stats_ex_op_t stats_ex_op;
+ setbuff_op_t setbuff_op;
+ setmode_op_t setmode_op;
+ setmintocopy_op_t setmintocopy_op;
+ getevent_op_t getevent_op;
+ oid_get_request_op_t oid_get_request_op;
+ oid_set_request_op_t oid_set_request_op;
+ sendqueue_transmit_op_t sendqueue_transmit_op;
+ setuserbuffer_op_t setuserbuffer_op;
+ live_dump_op_t live_dump_op;
+ live_dump_ended_op_t live_dump_ended_op;
+ get_airpcap_handle_op_t get_airpcap_handle_op;
+#endif
+ cleanup_op_t cleanup_op;
+
+#ifdef __APPLE__
+ /*
+ * Apple additions below
+ */
+ int *selectable_fd_list;
+ int selectable_fd_count;
+
+ /*
+ * The following needs to be 'int' as required by the corresponding BPF ioctls
+ */
+ int extendedhdr;
+ int wantpktap;
+ int truncation;
+ int pktaphdrv2;
+
+ cleanup_interface_op_t cleanup_interface_op;
+ char *pktap_ifname;
+ activate_op_t pktap_activate_op;
+ cleanup_op_t pktap_cleanup_op;
+
+ char *filter_str;
+ int shb_added;
+
+ struct pcap_if_info_set if_info_set;
+
+ struct pcap_proc_info_set proc_info_set;
+
+ cleanup_op_t cleanup_extra_op;
+#endif /* __APPLE__ */
+};
+
+/*
+ * BPF code generation flags.
+ */
+#define BPF_SPECIAL_VLAN_HANDLING 0x00000001 /* special VLAN handling for Linux */
+
+/*
+ * This is a timeval as stored in a savefile.
+ * It has to use the same types everywhere, independent of the actual
+ * `struct timeval'; `struct timeval' has 32-bit tv_sec values on some
+ * platforms and 64-bit tv_sec values on other platforms, and writing
+ * out native `struct timeval' values would mean files could only be
+ * read on systems with the same tv_sec size as the system on which
+ * the file was written.
+ */
+
+struct pcap_timeval {
+ bpf_int32 tv_sec; /* seconds */
+ bpf_int32 tv_usec; /* microseconds */
+};
+
+/*
+ * This is a `pcap_pkthdr' as actually stored in a savefile.
+ *
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure),
+ * and do not make the time stamp anything other than seconds and
+ * microseconds (e.g., seconds and nanoseconds). Instead:
+ *
+ * introduce a new structure for the new format;
+ *
+ * send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ * a new magic number for your new capture file format, and, when
+ * you get the new magic number, put it in "savefile.c";
+ *
+ * use that magic number for save files with the changed record
+ * header;
+ *
+ * make the code in "savefile.c" capable of reading files with
+ * the old record header as well as files with the new record header
+ * (using the magic number to determine the header format).
+ *
+ * Then supply the changes by forking the branch at
+ *
+ * https://github.com/the-tcpdump-group/libpcap/issues
+ *
+ * and issuing a pull request, so that future versions of libpcap and
+ * programs that use it (such as tcpdump) will be able to read your new
+ * capture file format.
+ */
+
+struct pcap_sf_pkthdr {
+ struct pcap_timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+};
+
+/*
+ * How a `pcap_pkthdr' is actually stored in savefiles written
+ * by some patched versions of libpcap (e.g. the ones in Red
+ * Hat Linux 6.1 and 6.2).
+ *
+ * Do not change the format of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ * Instead, introduce a new structure, as per the above.
+ */
+
+struct pcap_sf_patched_pkthdr {
+ struct pcap_timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+ int index;
+ unsigned short protocol;
+ unsigned char pkt_type;
+};
+
+/*
+ * User data structure for the one-shot callback used for pcap_next()
+ * and pcap_next_ex().
+ */
+struct oneshot_userdata {
+ struct pcap_pkthdr *hdr;
+ const u_char **pkt;
+ pcap_t *pd;
+};
+
+#ifndef min
+#define min(a, b) ((a) > (b) ? (b) : (a))
+#endif
+
+int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *);
+
+#ifdef __APPLE__
+int pcap_ng_offline_read(pcap_t *, int , pcap_handler , u_char *);
+void pcap_ng_cleanup(pcap_t *);
+
+struct pcap_dumper {
+ FILE *f;
+
+ int shb_added;
+ pcapng_block_t dump_block;
+
+ struct pcap_if_info_set dump_if_info_set;
+
+ struct pcap_proc_info_set dump_proc_info_set;
+};
+
+pcap_dumper_t *pcap_alloc_dumper(pcap_t *, FILE *);
+
+#endif /* __APPLE__ */
+
+#include <stdarg.h>
+
+#include "portability.h"
+
+/*
+ * Does the packet count argument to a module's read routine say
+ * "supply packets until you run out of packets"?
+ */
+#define PACKET_COUNT_IS_UNLIMITED(count) ((count) <= 0)
+
+/*
+ * Routines that most pcap implementations can use for non-blocking mode.
+ */
+#if !defined(_WIN32) && !defined(MSDOS)
+int pcap_getnonblock_fd(pcap_t *);
+int pcap_setnonblock_fd(pcap_t *p, int);
+#endif
+
+/*
+ * Internal interfaces for "pcap_create()".
+ *
+ * "pcap_create_interface()" is the routine to do a pcap_create on
+ * a regular network interface. There are multiple implementations
+ * of this, one for each platform type (Linux, BPF, DLPI, etc.),
+ * with the one used chosen by the configure script.
+ *
+ * "pcap_create_common()" allocates and fills in a pcap_t, for use
+ * by pcap_create routines.
+ */
+pcap_t *pcap_create_interface(const char *, char *);
+pcap_t *pcap_create_common(char *, size_t);
+int pcap_do_addexit(pcap_t *);
+void pcap_add_to_pcaps_to_close(pcap_t *);
+void pcap_remove_from_pcaps_to_close(pcap_t *);
+void pcap_cleanup_live_common(pcap_t *);
+int pcap_check_activated(pcap_t *);
+
+/*
+ * Internal interfaces for "pcap_findalldevs()".
+ *
+ * A pcap_if_list_t * is a reference to a list of devices.
+ *
+ * A get_if_flags_func is a platform-dependent function called to get
+ * additional interface flags.
+ *
+ * "pcap_platform_finddevs()" is the platform-dependent routine to
+ * find local network interfaces.
+ *
+ * "pcap_findalldevs_interfaces()" is a helper to find those interfaces
+ * using the "standard" mechanisms (SIOCGIFCONF, "getifaddrs()", etc.).
+ *
+ * "add_dev()" adds an entry to a pcap_if_list_t.
+ *
+ * "find_dev()" tries to find a device, by name, in a pcap_if_list_t.
+ *
+ * "find_or_add_dev()" checks whether a device is already in a pcap_if_list_t
+ * and, if not, adds an entry for it.
+ */
+struct pcap_if_list;
+typedef struct pcap_if_list pcap_if_list_t;
+typedef int (*get_if_flags_func)(const char *, bpf_u_int32 *, char *);
+int pcap_platform_finddevs(pcap_if_list_t *, char *);
+#if !defined(_WIN32) && !defined(MSDOS)
+int pcap_findalldevs_interfaces(pcap_if_list_t *, char *,
+ int (*)(const char *), get_if_flags_func);
+#endif
+pcap_if_t *find_or_add_dev(pcap_if_list_t *, const char *, bpf_u_int32,
+ get_if_flags_func, const char *, char *);
+pcap_if_t *find_dev(pcap_if_list_t *, const char *);
+pcap_if_t *add_dev(pcap_if_list_t *, const char *, bpf_u_int32, const char *,
+ char *);
+int add_addr_to_dev(pcap_if_t *, struct sockaddr *, size_t,
+ struct sockaddr *, size_t, struct sockaddr *, size_t,
+ struct sockaddr *dstaddr, size_t, char *errbuf);
+#ifndef _WIN32
+pcap_if_t *find_or_add_if(pcap_if_list_t *, const char *, bpf_u_int32,
+ get_if_flags_func, char *);
+int add_addr_to_if(pcap_if_list_t *, const char *, bpf_u_int32,
+ get_if_flags_func,
+ struct sockaddr *, size_t, struct sockaddr *, size_t,
+ struct sockaddr *, size_t, struct sockaddr *, size_t, char *);
+#endif
+
+/*
+ * Internal interfaces for "pcap_open_offline()".
+ *
+ * "pcap_open_offline_common()" allocates and fills in a pcap_t, for use
+ * by pcap_open_offline routines.
+ *
+ * "pcap_adjust_snapshot()" adjusts the snapshot to be non-zero and
+ * fit within an int.
+ *
+ * "sf_cleanup()" closes the file handle associated with a pcap_t, if
+ * appropriate, and frees all data common to all modules for handling
+ * savefile types.
+ */
+pcap_t *pcap_open_offline_common(char *ebuf, size_t size);
+bpf_u_int32 pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen);
+void sf_cleanup(pcap_t *p);
+
+/*
+ * Internal interfaces for doing user-mode filtering of packets and
+ * validating filter programs.
+ */
+/*
+ * Auxiliary data, for use when interpreting a filter intended for the
+ * Linux kernel when the kernel rejects the filter (requiring us to
+ * run it in userland). It contains VLAN tag information.
+ */
+struct bpf_aux_data {
+ u_short vlan_tag_present;
+ u_short vlan_tag;
+};
+
+/*
+ * Filtering routine that takes the auxiliary data as an additional
+ * argument.
+ */
+u_int bpf_filter_with_aux_data(const struct bpf_insn *,
+ const u_char *, u_int, u_int, const struct bpf_aux_data *);
+
+/*
+ * Internal interfaces for both "pcap_create()" and routines that
+ * open savefiles.
+ *
+ * "pcap_oneshot()" is the standard one-shot callback for "pcap_next()"
+ * and "pcap_next_ex()".
+ */
+void pcap_oneshot(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+int install_bpf_program(pcap_t *, struct bpf_program *);
+
+int pcap_strcasecmp(const char *, const char *);
+
+#ifdef YYDEBUG
+extern int pcap_debug;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap-libdlpi.c b/lib/libpcap/libpcap/pcap-libdlpi.c
new file mode 100644
index 0000000..a38da8b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-libdlpi.c
@@ -0,0 +1,495 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * This code contributed by Sagun Shakya (sagun.shakya@sun.com)
+ */
+/*
+ * Packet capture routines for DLPI using libdlpi under SunOS 5.11.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/bufmod.h>
+#include <sys/stream.h>
+#include <libdlpi.h>
+#include <errno.h>
+#include <memory.h>
+#include <stropts.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcap-int.h"
+#include "dlpisubs.h"
+
+/* Forwards. */
+static int dlpromiscon(pcap_t *, bpf_u_int32);
+static int pcap_read_libdlpi(pcap_t *, int, pcap_handler, u_char *);
+static int pcap_inject_libdlpi(pcap_t *, const void *, size_t);
+static void pcap_libdlpi_err(const char *, const char *, int, char *);
+static void pcap_cleanup_libdlpi(pcap_t *);
+
+/*
+ * list_interfaces() will list all the network links that are
+ * available on a system.
+ */
+static boolean_t list_interfaces(const char *, void *);
+
+typedef struct linknamelist {
+ char linkname[DLPI_LINKNAME_MAX];
+ struct linknamelist *lnl_next;
+} linknamelist_t;
+
+typedef struct linkwalk {
+ linknamelist_t *lw_list;
+ int lw_err;
+} linkwalk_t;
+
+/*
+ * The caller of this function should free the memory allocated
+ * for each linknamelist_t "entry" allocated.
+ */
+static boolean_t
+list_interfaces(const char *linkname, void *arg)
+{
+ linkwalk_t *lwp = arg;
+ linknamelist_t *entry;
+
+ if ((entry = calloc(1, sizeof(linknamelist_t))) == NULL) {
+ lwp->lw_err = ENOMEM;
+ return (B_TRUE);
+ }
+ (void) pcap_strlcpy(entry->linkname, linkname, DLPI_LINKNAME_MAX);
+
+ if (lwp->lw_list == NULL) {
+ lwp->lw_list = entry;
+ } else {
+ entry->lnl_next = lwp->lw_list;
+ lwp->lw_list = entry;
+ }
+
+ return (B_FALSE);
+}
+
+static int
+pcap_activate_libdlpi(pcap_t *p)
+{
+ struct pcap_dlpi *pd = p->priv;
+ int status = 0;
+ int retv;
+ dlpi_handle_t dh;
+ dlpi_info_t dlinfo;
+
+ /*
+ * Enable Solaris raw and passive DLPI extensions;
+ * dlpi_open() will not fail if the underlying link does not support
+ * passive mode. See dlpi(7P) for details.
+ */
+ retv = dlpi_open(p->opt.device, &dh, DLPI_RAW|DLPI_PASSIVE);
+ if (retv != DLPI_SUCCESS) {
+ if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK)
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+ else if (retv == DL_SYSERR &&
+ (errno == EPERM || errno == EACCES))
+ status = PCAP_ERROR_PERM_DENIED;
+ else
+ status = PCAP_ERROR;
+ pcap_libdlpi_err(p->opt.device, "dlpi_open", retv,
+ p->errbuf);
+ return (status);
+ }
+ pd->dlpi_hd = dh;
+
+ if (p->opt.rfmon) {
+ /*
+ * This device exists, but we don't support monitor mode
+ * any platforms that support DLPI.
+ */
+ status = PCAP_ERROR_RFMON_NOTSUP;
+ goto bad;
+ }
+
+ /* Bind with DLPI_ANY_SAP. */
+ if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) {
+ status = PCAP_ERROR;
+ pcap_libdlpi_err(p->opt.device, "dlpi_bind", retv, p->errbuf);
+ goto bad;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ /* Enable promiscuous mode. */
+ if (p->opt.promisc) {
+ retv = dlpromiscon(p, DL_PROMISC_PHYS);
+ if (retv < 0) {
+ /*
+ * "You don't have permission to capture on
+ * this device" and "you don't have permission
+ * to capture in promiscuous mode on this
+ * device" are different; let the user know,
+ * so if they can't get permission to
+ * capture in promiscuous mode, they can at
+ * least try to capture in non-promiscuous
+ * mode.
+ *
+ * XXX - you might have to capture in
+ * promiscuous mode to see outgoing packets.
+ */
+ if (retv == PCAP_ERROR_PERM_DENIED)
+ status = PCAP_ERROR_PROMISC_PERM_DENIED;
+ else
+ status = retv;
+ goto bad;
+ }
+ } else {
+ /* Try to enable multicast. */
+ retv = dlpromiscon(p, DL_PROMISC_MULTI);
+ if (retv < 0) {
+ status = retv;
+ goto bad;
+ }
+ }
+
+ /* Try to enable SAP promiscuity. */
+ retv = dlpromiscon(p, DL_PROMISC_SAP);
+ if (retv < 0) {
+ /*
+ * Not fatal, since the DL_PROMISC_PHYS mode worked.
+ * Report it as a warning, however.
+ */
+ if (p->opt.promisc)
+ status = PCAP_WARNING;
+ else {
+ status = retv;
+ goto bad;
+ }
+ }
+
+ /* Determine link type. */
+ if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) {
+ status = PCAP_ERROR;
+ pcap_libdlpi_err(p->opt.device, "dlpi_info", retv, p->errbuf);
+ goto bad;
+ }
+
+ if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ p->fd = dlpi_fd(pd->dlpi_hd);
+
+ /* Push and configure bufmod. */
+ if (pcap_conf_bufmod(p, p->snapshot) != 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * Flush the read side.
+ */
+ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) {
+ status = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "FLUSHR");
+ goto bad;
+ }
+
+ /* Allocate data buffer. */
+ if (pcap_alloc_databuf(p) != 0) {
+ status = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * "p->fd" is a FD for a STREAMS device, so "select()" and
+ * "poll()" should work on it.
+ */
+ p->selectable_fd = p->fd;
+
+ p->read_op = pcap_read_libdlpi;
+ p->inject_op = pcap_inject_libdlpi;
+ p->setfilter_op = install_bpf_program; /* No kernel filtering */
+ p->setdirection_op = NULL; /* Not implemented */
+ p->set_datalink_op = NULL; /* Can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_stats_dlpi;
+ p->cleanup_op = pcap_cleanup_libdlpi;
+
+ return (status);
+bad:
+ pcap_cleanup_libdlpi(p);
+ return (status);
+}
+
+#define STRINGIFY(n) #n
+
+static int
+dlpromiscon(pcap_t *p, bpf_u_int32 level)
+{
+ struct pcap_dlpi *pd = p->priv;
+ int retv;
+ int err;
+
+ retv = dlpi_promiscon(pd->dlpi_hd, level);
+ if (retv != DLPI_SUCCESS) {
+ if (retv == DL_SYSERR &&
+ (errno == EPERM || errno == EACCES))
+ err = PCAP_ERROR_PERM_DENIED;
+ else
+ err = PCAP_ERROR;
+ pcap_libdlpi_err(p->opt.device, "dlpi_promiscon" STRINGIFY(level),
+ retv, p->errbuf);
+ return (err);
+ }
+ return (0);
+}
+
+/*
+ * Presumably everything returned by dlpi_walk() is a DLPI device,
+ * so there's no work to be done here to check whether name refers
+ * to a DLPI device.
+ */
+static int
+is_dlpi_interface(const char *name _U_)
+{
+ return (1);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do other than mark loopback devices as "the
+ * connected/disconnected status doesn't apply".
+ *
+ * XXX - on Solaris, can we do what the dladm command does,
+ * i.e. get a connected/disconnected indication from a kstat?
+ * (Note that you can also get the link speed, and possibly
+ * other information, from a kstat as well.)
+ */
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback devices aren't wireless, and "connected"/
+ * "disconnected" doesn't apply to them.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return (0);
+ }
+ return (0);
+}
+
+/*
+ * In Solaris, the "standard" mechanism" i.e SIOCGLIFCONF will only find
+ * network links that are plumbed and are up. dlpi_walk(3DLPI) will find
+ * additional network links present in the system.
+ */
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ int retv = 0;
+
+ linknamelist_t *entry, *next;
+ linkwalk_t lw = {NULL, 0};
+ int save_errno;
+
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(devlistp, errbuf,
+ is_dlpi_interface, get_if_flags) == -1)
+ return (-1); /* failure */
+
+ /* dlpi_walk() for loopback will be added here. */
+
+ /*
+ * Find all DLPI devices in the current zone.
+ *
+ * XXX - will pcap_findalldevs_interfaces() find any devices
+ * outside the current zone? If not, the only reason to call
+ * it would be to get the interface addresses.
+ */
+ dlpi_walk(list_interfaces, &lw, 0);
+
+ if (lw.lw_err != 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ lw.lw_err, "dlpi_walk");
+ retv = -1;
+ goto done;
+ }
+
+ /* Add linkname if it does not exist on the list. */
+ for (entry = lw.lw_list; entry != NULL; entry = entry->lnl_next) {
+ /*
+ * If it isn't already in the list of devices, try to
+ * add it.
+ */
+ if (find_or_add_dev(devlistp, entry->linkname, 0, get_if_flags,
+ NULL, errbuf) == NULL)
+ retv = -1;
+ }
+done:
+ save_errno = errno;
+ for (entry = lw.lw_list; entry != NULL; entry = next) {
+ next = entry->lnl_next;
+ free(entry);
+ }
+ errno = save_errno;
+
+ return (retv);
+}
+
+/*
+ * Read data received on DLPI handle. Returns -2 if told to terminate, else
+ * returns the number of packets read.
+ */
+static int
+pcap_read_libdlpi(pcap_t *p, int count, pcap_handler callback, u_char *user)
+{
+ struct pcap_dlpi *pd = p->priv;
+ int len;
+ u_char *bufp;
+ size_t msglen;
+ int retv;
+
+ len = p->cc;
+ if (len != 0) {
+ bufp = p->bp;
+ goto process_pkts;
+ }
+ do {
+ /* Has "pcap_breakloop()" been called? */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it has,
+ * and return -2 to indicate that we were told to
+ * break out of the loop.
+ */
+ p->break_loop = 0;
+ return (-2);
+ }
+
+ msglen = p->bufsize;
+ bufp = (u_char *)p->buffer + p->offset;
+
+ retv = dlpi_recv(pd->dlpi_hd, NULL, NULL, bufp,
+ &msglen, -1, NULL);
+ if (retv != DLPI_SUCCESS) {
+ /*
+ * This is most likely a call to terminate out of the
+ * loop. So, do not return an error message, instead
+ * check if "pcap_breakloop()" has been called above.
+ */
+ if (retv == DL_SYSERR && errno == EINTR) {
+ len = 0;
+ continue;
+ }
+ pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd),
+ "dlpi_recv", retv, p->errbuf);
+ return (-1);
+ }
+ len = msglen;
+ } while (len == 0);
+
+process_pkts:
+ return (pcap_process_pkts(p, callback, user, count, bufp, len));
+}
+
+static int
+pcap_inject_libdlpi(pcap_t *p, const void *buf, size_t size)
+{
+ struct pcap_dlpi *pd = p->priv;
+ int retv;
+
+ retv = dlpi_send(pd->dlpi_hd, NULL, 0, buf, size, NULL);
+ if (retv != DLPI_SUCCESS) {
+ pcap_libdlpi_err(dlpi_linkname(pd->dlpi_hd), "dlpi_send", retv,
+ p->errbuf);
+ return (-1);
+ }
+ /*
+ * dlpi_send(3DLPI) does not provide a way to return the number of
+ * bytes sent on the wire. Based on the fact that DLPI_SUCCESS was
+ * returned we are assuming 'size' bytes were sent.
+ */
+ return (size);
+}
+
+/*
+ * Close dlpi handle.
+ */
+static void
+pcap_cleanup_libdlpi(pcap_t *p)
+{
+ struct pcap_dlpi *pd = p->priv;
+
+ if (pd->dlpi_hd != NULL) {
+ dlpi_close(pd->dlpi_hd);
+ pd->dlpi_hd = NULL;
+ p->fd = -1;
+ }
+ pcap_cleanup_live_common(p);
+}
+
+/*
+ * Write error message to buffer.
+ */
+static void
+pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
+{
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
+ func, linkname, dlpi_strerror(err));
+}
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_dlpi));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_libdlpi;
+ return (p);
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-linktype.manmisc b/lib/libpcap/libpcap/pcap-linktype.manmisc
new file mode 100644
index 0000000..a0dc167
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-linktype.manmisc
@@ -0,0 +1,48 @@
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-LINKTYPE 7 "7 April 2014"
+.SH NAME
+pcap-linktype \- link-layer header types supported by libpcap
+.SH DESCRIPTION
+For a live capture or ``savefile'', libpcap supplies, as the return
+value of the
+.BR pcap_datalink (3PCAP)
+routine, a value that indicates the type of link-layer header at the
+beginning of the packets it provides. This is not necessarily the type
+of link-layer header that the packets being captured have on the network
+from which they're being captured; for example, packets from an IEEE
+802.11 network might be provided by libpcap with Ethernet headers that
+the network adapter or the network adapter driver generates from the
+802.11 headers. The names for those values begin with
+.BR DLT_ ,
+so they are sometimes called "DLT_ values".
+.PP
+The values stored in the link-layer header type field in the savefile
+header are, in most but not all cases, the same as the values returned
+by
+.BR pcap_datalink() .
+The names for those values begin with
+.BR LINKTYPE_ .
+.PP
+The link-layer header types supported by libpcap are described at
+https://www.tcpdump.org/linktypes.html.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap-linktype.manmisc.in b/lib/libpcap/libpcap/pcap-linktype.manmisc.in
new file mode 100644
index 0000000..777e9dc
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-linktype.manmisc.in
@@ -0,0 +1,48 @@
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-LINKTYPE @MAN_MISC_INFO@ "7 April 2014"
+.SH NAME
+pcap-linktype \- link-layer header types supported by libpcap
+.SH DESCRIPTION
+For a live capture or ``savefile'', libpcap supplies, as the return
+value of the
+.BR pcap_datalink (3PCAP)
+routine, a value that indicates the type of link-layer header at the
+beginning of the packets it provides. This is not necessarily the type
+of link-layer header that the packets being captured have on the network
+from which they're being captured; for example, packets from an IEEE
+802.11 network might be provided by libpcap with Ethernet headers that
+the network adapter or the network adapter driver generates from the
+802.11 headers. The names for those values begin with
+.BR DLT_ ,
+so they are sometimes called "DLT_ values".
+.PP
+The values stored in the link-layer header type field in the savefile
+header are, in most but not all cases, the same as the values returned
+by
+.BR pcap_datalink() .
+The names for those values begin with
+.BR LINKTYPE_ .
+.PP
+The link-layer header types supported by libpcap are described at
+https://www.tcpdump.org/linktypes.html.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap-linux.c b/lib/libpcap/libpcap/pcap-linux.c
new file mode 100644
index 0000000..70334b3
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-linux.c
@@ -0,0 +1,7534 @@
+/*
+ * pcap-linux.c: Packet capture interface to the Linux kernel
+ *
+ * Copyright (c) 2000 Torsten Landschoff <torsten@debian.org>
+ * Sebastian Krahmer <krahmer@cs.uni-potsdam.de>
+ *
+ * License: BSD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Modifications: Added PACKET_MMAP support
+ * Paolo Abeni <paolo.abeni@email.it>
+ * Added TPACKET_V3 support
+ * Gabor Tatarka <gabor.tatarka@ericsson.com>
+ *
+ * based on previous works of:
+ * Simon Patarin <patarin@cs.unibo.it>
+ * Phil Wood <cpw@lanl.gov>
+ *
+ * Monitor-mode support for mac80211 includes code taken from the iw
+ * command; the copyright notice for that code is
+ *
+ * Copyright (c) 2007, 2008 Johannes Berg
+ * Copyright (c) 2007 Andy Lutomirski
+ * Copyright (c) 2007 Mike Kershaw
+ * Copyright (c) 2008 Gábor Stefanik
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * 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.
+ */
+
+/*
+ * Known problems with 2.0[.x] kernels:
+ *
+ * - The loopback device gives every packet twice; on 2.2[.x] kernels,
+ * if we use PF_PACKET, we can filter out the transmitted version
+ * of the packet by using data in the "sockaddr_ll" returned by
+ * "recvfrom()", but, on 2.0[.x] kernels, we have to use
+ * PF_INET/SOCK_PACKET, which means "recvfrom()" supplies a
+ * "sockaddr_pkt" which doesn't give us enough information to let
+ * us do that.
+ *
+ * - We have to set the interface's IFF_PROMISC flag ourselves, if
+ * we're to run in promiscuous mode, which means we have to turn
+ * it off ourselves when we're done; the kernel doesn't keep track
+ * of how many sockets are listening promiscuously, which means
+ * it won't get turned off automatically when no sockets are
+ * listening promiscuously. We catch "pcap_close()" and, for
+ * interfaces we put into promiscuous mode, take them out of
+ * promiscuous mode - which isn't necessarily the right thing to
+ * do, if another socket also requested promiscuous mode between
+ * the time when we opened the socket and the time when we close
+ * the socket.
+ *
+ * - MSG_TRUNC isn't supported, so you can't specify that "recvfrom()"
+ * return the amount of data that you could have read, rather than
+ * the amount that was returned, so we can't just allocate a buffer
+ * whose size is the snapshot length and pass the snapshot length
+ * as the byte count, and also pass MSG_TRUNC, so that the return
+ * value tells us how long the packet was on the wire.
+ *
+ * This means that, if we want to get the actual size of the packet,
+ * so we can return it in the "len" field of the packet header,
+ * we have to read the entire packet, not just the part that fits
+ * within the snapshot length, and thus waste CPU time copying data
+ * from the kernel that our caller won't see.
+ *
+ * We have to get the actual size, and supply it in "len", because
+ * otherwise, the IP dissector in tcpdump, for example, will complain
+ * about "truncated-ip", as the packet will appear to have been
+ * shorter, on the wire, than the IP header said it should have been.
+ */
+
+
+#define _GNU_SOURCE
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/utsname.h>
+#include <sys/mman.h>
+#include <linux/if.h>
+#include <linux/if_packet.h>
+#include <linux/sockios.h>
+#include <netinet/in.h>
+#include <linux/if_ether.h>
+#include <net/if_arp.h>
+#include <poll.h>
+#include <dirent.h>
+
+#include "pcap-int.h"
+#include "pcap/sll.h"
+#include "pcap/vlan.h"
+
+/*
+ * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
+ * sockets rather than SOCK_PACKET sockets.
+ *
+ * To use them, we include <linux/if_packet.h> rather than
+ * <netpacket/packet.h>; we do so because
+ *
+ * some Linux distributions (e.g., Slackware 4.0) have 2.2 or
+ * later kernels and libc5, and don't provide a <netpacket/packet.h>
+ * file;
+ *
+ * not all versions of glibc2 have a <netpacket/packet.h> file
+ * that defines stuff needed for some of the 2.4-or-later-kernel
+ * features, so if the system has a 2.4 or later kernel, we
+ * still can't use those features.
+ *
+ * We're already including a number of other <linux/XXX.h> headers, and
+ * this code is Linux-specific (no other OS has PF_PACKET sockets as
+ * a raw packet capture mechanism), so it's not as if you gain any
+ * useful portability by using <netpacket/packet.h>
+ *
+ * XXX - should we just include <linux/if_packet.h> even if PF_PACKET
+ * isn't defined? It only defines one data structure in 2.0.x, so
+ * it shouldn't cause any problems.
+ */
+#ifdef PF_PACKET
+# include <linux/if_packet.h>
+
+ /*
+ * On at least some Linux distributions (for example, Red Hat 5.2),
+ * there's no <netpacket/packet.h> file, but PF_PACKET is defined if
+ * you include <sys/socket.h>, but <linux/if_packet.h> doesn't define
+ * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of
+ * the PACKET_xxx stuff.
+ *
+ * So we check whether PACKET_HOST is defined, and assume that we have
+ * PF_PACKET sockets only if it is defined.
+ */
+# ifdef PACKET_HOST
+# define HAVE_PF_PACKET_SOCKETS
+# ifdef PACKET_AUXDATA
+# define HAVE_PACKET_AUXDATA
+# endif /* PACKET_AUXDATA */
+# endif /* PACKET_HOST */
+
+
+ /* check for memory mapped access avaibility. We assume every needed
+ * struct is defined if the macro TPACKET_HDRLEN is defined, because it
+ * uses many ring related structs and macros */
+# ifdef PCAP_SUPPORT_PACKET_RING
+# ifdef TPACKET_HDRLEN
+# define HAVE_PACKET_RING
+# ifdef TPACKET3_HDRLEN
+# define HAVE_TPACKET3
+# endif /* TPACKET3_HDRLEN */
+# ifdef TPACKET2_HDRLEN
+# define HAVE_TPACKET2
+# else /* TPACKET2_HDRLEN */
+# define TPACKET_V1 0 /* Old kernel with only V1, so no TPACKET_Vn defined */
+# endif /* TPACKET2_HDRLEN */
+# endif /* TPACKET_HDRLEN */
+# endif /* PCAP_SUPPORT_PACKET_RING */
+#endif /* PF_PACKET */
+
+#ifdef SO_ATTACH_FILTER
+#include <linux/types.h>
+#include <linux/filter.h>
+#endif
+
+#ifdef HAVE_LINUX_NET_TSTAMP_H
+#include <linux/net_tstamp.h>
+#endif
+
+#ifdef HAVE_LINUX_SOCKIOS_H
+#include <linux/sockios.h>
+#endif
+
+#ifdef HAVE_LINUX_IF_BONDING_H
+#include <linux/if_bonding.h>
+
+/*
+ * The ioctl code to use to check whether a device is a bonding device.
+ */
+#if defined(SIOCBONDINFOQUERY)
+ #define BOND_INFO_QUERY_IOCTL SIOCBONDINFOQUERY
+#elif defined(BOND_INFO_QUERY_OLD)
+ #define BOND_INFO_QUERY_IOCTL BOND_INFO_QUERY_OLD
+#endif
+#endif /* HAVE_LINUX_IF_BONDING_H */
+
+/*
+ * Got Wireless Extensions?
+ */
+#ifdef HAVE_LINUX_WIRELESS_H
+#include <linux/wireless.h>
+#endif /* HAVE_LINUX_WIRELESS_H */
+
+/*
+ * Got libnl?
+ */
+#ifdef HAVE_LIBNL
+#include <linux/nl80211.h>
+
+#include <netlink/genl/genl.h>
+#include <netlink/genl/family.h>
+#include <netlink/genl/ctrl.h>
+#include <netlink/msg.h>
+#include <netlink/attr.h>
+#endif /* HAVE_LIBNL */
+
+/*
+ * Got ethtool support?
+ */
+#ifdef HAVE_LINUX_ETHTOOL_H
+#include <linux/ethtool.h>
+#endif
+
+#ifndef HAVE_SOCKLEN_T
+typedef int socklen_t;
+#endif
+
+#ifndef MSG_TRUNC
+/*
+ * This is being compiled on a system that lacks MSG_TRUNC; define it
+ * with the value it has in the 2.2 and later kernels, so that, on
+ * those kernels, when we pass it in the flags argument to "recvfrom()"
+ * we're passing the right value and thus get the MSG_TRUNC behavior
+ * we want. (We don't get that behavior on 2.0[.x] kernels, because
+ * they didn't support MSG_TRUNC.)
+ */
+#define MSG_TRUNC 0x20
+#endif
+
+#ifndef SOL_PACKET
+/*
+ * This is being compiled on a system that lacks SOL_PACKET; define it
+ * with the value it has in the 2.2 and later kernels, so that we can
+ * set promiscuous mode in the good modern way rather than the old
+ * 2.0-kernel crappy way.
+ */
+#define SOL_PACKET 263
+#endif
+
+#define MAX_LINKHEADER_SIZE 256
+
+/*
+ * When capturing on all interfaces we use this as the buffer size.
+ * Should be bigger then all MTUs that occur in real life.
+ * 64kB should be enough for now.
+ */
+#define BIGGER_THAN_ALL_MTUS (64*1024)
+
+/*
+ * Private data for capturing on Linux SOCK_PACKET or PF_PACKET sockets.
+ */
+struct pcap_linux {
+ u_int packets_read; /* count of packets read with recvfrom() */
+ long proc_dropped; /* packets reported dropped by /proc/net/dev */
+ struct pcap_stat stat;
+
+ char *device; /* device name */
+ int filter_in_userland; /* must filter in userland */
+ int blocks_to_filter_in_userland;
+ int must_do_on_close; /* stuff we must do when we close */
+ int timeout; /* timeout for buffering */
+ int sock_packet; /* using Linux 2.0 compatible interface */
+ int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */
+ int ifindex; /* interface index of device we're bound to */
+ int lo_ifindex; /* interface index of the loopback device */
+ bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */
+ char *mondevice; /* mac80211 monitor device we created */
+ u_char *mmapbuf; /* memory-mapped region pointer */
+ size_t mmapbuflen; /* size of region */
+ int vlan_offset; /* offset at which to insert vlan tags; if -1, don't insert */
+ u_int tp_version; /* version of tpacket_hdr for mmaped ring */
+ u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */
+ u_char *oneshot_buffer; /* buffer for copy of packet */
+ int poll_timeout; /* timeout to use in poll() */
+#ifdef HAVE_TPACKET3
+ unsigned char *current_packet; /* Current packet within the TPACKET_V3 block. Move to next block if NULL. */
+ int packets_left; /* Unhandled packets left within the block from previous call to pcap_read_linux_mmap_v3 in case of TPACKET_V3. */
+#endif
+};
+
+/*
+ * Stuff to do when we close.
+ */
+#define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */
+#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */
+#define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */
+
+/*
+ * Prototypes for internal functions and methods.
+ */
+static int get_if_flags(const char *, bpf_u_int32 *, char *);
+static int is_wifi(int, const char *);
+static void map_arphrd_to_dlt(pcap_t *, int, int, const char *, int);
+static int pcap_activate_linux(pcap_t *);
+static int activate_old(pcap_t *);
+static int activate_new(pcap_t *);
+static int activate_mmap(pcap_t *, int *);
+static int pcap_can_set_rfmon_linux(pcap_t *);
+static int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
+static int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
+static int pcap_inject_linux(pcap_t *, const void *, size_t);
+static int pcap_stats_linux(pcap_t *, struct pcap_stat *);
+static int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
+static int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
+static int pcap_set_datalink_linux(pcap_t *, int);
+static void pcap_cleanup_linux(pcap_t *);
+
+/*
+ * This is what the header structure looks like in a 64-bit kernel;
+ * we use this, rather than struct tpacket_hdr, if we're using
+ * TPACKET_V1 in 32-bit code running on a 64-bit kernel.
+ */
+struct tpacket_hdr_64 {
+ uint64_t tp_status;
+ unsigned int tp_len;
+ unsigned int tp_snaplen;
+ unsigned short tp_mac;
+ unsigned short tp_net;
+ unsigned int tp_sec;
+ unsigned int tp_usec;
+};
+
+/*
+ * We use this internally as the tpacket version for TPACKET_V1 in
+ * 32-bit code on a 64-bit kernel.
+ */
+#define TPACKET_V1_64 99
+
+union thdr {
+ struct tpacket_hdr *h1;
+ struct tpacket_hdr_64 *h1_64;
+#ifdef HAVE_TPACKET2
+ struct tpacket2_hdr *h2;
+#endif
+#ifdef HAVE_TPACKET3
+ struct tpacket_block_desc *h3;
+#endif
+ void *raw;
+};
+
+#ifdef HAVE_PACKET_RING
+#define RING_GET_FRAME_AT(h, offset) (((union thdr **)h->buffer)[(offset)])
+#define RING_GET_CURRENT_FRAME(h) RING_GET_FRAME_AT(h, h->offset)
+
+static void destroy_ring(pcap_t *handle);
+static int create_ring(pcap_t *handle, int *status);
+static int prepare_tpacket_socket(pcap_t *handle);
+static void pcap_cleanup_linux_mmap(pcap_t *);
+static int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler , u_char *);
+static int pcap_read_linux_mmap_v1_64(pcap_t *, int, pcap_handler , u_char *);
+#ifdef HAVE_TPACKET2
+static int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *);
+#endif
+#ifdef HAVE_TPACKET3
+static int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *);
+#endif
+static int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
+static int pcap_setnonblock_mmap(pcap_t *p, int nonblock);
+static int pcap_getnonblock_mmap(pcap_t *p);
+static void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
+ const u_char *bytes);
+#endif
+
+/*
+ * In pre-3.0 kernels, the tp_vlan_tci field is set to whatever the
+ * vlan_tci field in the skbuff is. 0 can either mean "not on a VLAN"
+ * or "on VLAN 0". There is no flag set in the tp_status field to
+ * distinguish between them.
+ *
+ * In 3.0 and later kernels, if there's a VLAN tag present, the tp_vlan_tci
+ * field is set to the VLAN tag, and the TP_STATUS_VLAN_VALID flag is set
+ * in the tp_status field, otherwise the tp_vlan_tci field is set to 0 and
+ * the TP_STATUS_VLAN_VALID flag isn't set in the tp_status field.
+ *
+ * With a pre-3.0 kernel, we cannot distinguish between packets with no
+ * VLAN tag and packets on VLAN 0, so we will mishandle some packets, and
+ * there's nothing we can do about that.
+ *
+ * So, on those systems, which never set the TP_STATUS_VLAN_VALID flag, we
+ * continue the behavior of earlier libpcaps, wherein we treated packets
+ * with a VLAN tag of 0 as being packets without a VLAN tag rather than packets
+ * on VLAN 0. We do this by treating packets with a tp_vlan_tci of 0 and
+ * with the TP_STATUS_VLAN_VALID flag not set in tp_status as not having
+ * VLAN tags. This does the right thing on 3.0 and later kernels, and
+ * continues the old unfixably-imperfect behavior on pre-3.0 kernels.
+ *
+ * If TP_STATUS_VLAN_VALID isn't defined, we test it as the 0x10 bit; it
+ * has that value in 3.0 and later kernels.
+ */
+#ifdef TP_STATUS_VLAN_VALID
+ #define VLAN_VALID(hdr, hv) ((hv)->tp_vlan_tci != 0 || ((hdr)->tp_status & TP_STATUS_VLAN_VALID))
+#else
+ /*
+ * This is being compiled on a system that lacks TP_STATUS_VLAN_VALID,
+ * so we testwith the value it has in the 3.0 and later kernels, so
+ * we can test it if we're running on a system that has it. (If we're
+ * running on a system that doesn't have it, it won't be set in the
+ * tp_status field, so the tests of it will always fail; that means
+ * we behave the way we did before we introduced this macro.)
+ */
+ #define VLAN_VALID(hdr, hv) ((hv)->tp_vlan_tci != 0 || ((hdr)->tp_status & 0x10))
+#endif
+
+#ifdef TP_STATUS_VLAN_TPID_VALID
+# define VLAN_TPID(hdr, hv) (((hv)->tp_vlan_tpid || ((hdr)->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? (hv)->tp_vlan_tpid : ETH_P_8021Q)
+#else
+# define VLAN_TPID(hdr, hv) ETH_P_8021Q
+#endif
+
+/*
+ * Wrap some ioctl calls
+ */
+#ifdef HAVE_PF_PACKET_SOCKETS
+static int iface_get_id(int fd, const char *device, char *ebuf);
+#endif /* HAVE_PF_PACKET_SOCKETS */
+static int iface_get_mtu(int fd, const char *device, char *ebuf);
+static int iface_get_arptype(int fd, const char *device, char *ebuf);
+#ifdef HAVE_PF_PACKET_SOCKETS
+static int iface_bind(int fd, int ifindex, char *ebuf, int protocol);
+#ifdef IW_MODE_MONITOR
+static int has_wext(int sock_fd, const char *device, char *ebuf);
+#endif /* IW_MODE_MONITOR */
+static int enter_rfmon_mode(pcap_t *handle, int sock_fd,
+ const char *device);
+#endif /* HAVE_PF_PACKET_SOCKETS */
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+static int iface_ethtool_get_ts_info(const char *device, pcap_t *handle,
+ char *ebuf);
+#endif
+#ifdef HAVE_PACKET_RING
+static int iface_get_offload(pcap_t *handle);
+#endif
+static int iface_bind_old(int fd, const char *device, char *ebuf);
+
+#ifdef SO_ATTACH_FILTER
+static int fix_program(pcap_t *handle, struct sock_fprog *fcode,
+ int is_mapped);
+static int fix_offset(pcap_t *handle, struct bpf_insn *p);
+static int set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode);
+static int reset_kernel_filter(pcap_t *handle);
+
+static struct sock_filter total_insn
+ = BPF_STMT(BPF_RET | BPF_K, 0);
+static struct sock_fprog total_fcode
+ = { 1, &total_insn };
+#endif /* SO_ATTACH_FILTER */
+
+pcap_t *
+pcap_create_interface(const char *device, char *ebuf)
+{
+ pcap_t *handle;
+
+ handle = pcap_create_common(ebuf, sizeof (struct pcap_linux));
+ if (handle == NULL)
+ return NULL;
+
+ handle->activate_op = pcap_activate_linux;
+ handle->can_set_rfmon_op = pcap_can_set_rfmon_linux;
+
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+ /*
+ * See what time stamp types we support.
+ */
+ if (iface_ethtool_get_ts_info(device, handle, ebuf) == -1) {
+ pcap_close(handle);
+ return NULL;
+ }
+#endif
+
+#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
+ /*
+ * We claim that we support microsecond and nanosecond time
+ * stamps.
+ *
+ * XXX - with adapter-supplied time stamps, can we choose
+ * microsecond or nanosecond time stamps on arbitrary
+ * adapters?
+ */
+ handle->tstamp_precision_count = 2;
+ handle->tstamp_precision_list = malloc(2 * sizeof(u_int));
+ if (handle->tstamp_precision_list == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ pcap_close(handle);
+ return NULL;
+ }
+ handle->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+ handle->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
+
+ return handle;
+}
+
+#ifdef HAVE_LIBNL
+/*
+ * If interface {if} is a mac80211 driver, the file
+ * /sys/class/net/{if}/phy80211 is a symlink to
+ * /sys/class/ieee80211/{phydev}, for some {phydev}.
+ *
+ * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
+ * least, has a "wmaster0" device and a "wlan0" device; the
+ * latter is the one with the IP address. Both show up in
+ * "tcpdump -D" output. Capturing on the wmaster0 device
+ * captures with 802.11 headers.
+ *
+ * airmon-ng searches through /sys/class/net for devices named
+ * monN, starting with mon0; as soon as one *doesn't* exist,
+ * it chooses that as the monitor device name. If the "iw"
+ * command exists, it does "iw dev {if} interface add {monif}
+ * type monitor", where {monif} is the monitor device. It
+ * then (sigh) sleeps .1 second, and then configures the
+ * device up. Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
+ * is a file, it writes {mondev}, without a newline, to that file,
+ * and again (sigh) sleeps .1 second, and then iwconfig's that
+ * device into monitor mode and configures it up. Otherwise,
+ * you can't do monitor mode.
+ *
+ * All these devices are "glued" together by having the
+ * /sys/class/net/{device}/phy80211 links pointing to the same
+ * place, so, given a wmaster, wlan, or mon device, you can
+ * find the other devices by looking for devices with
+ * the same phy80211 link.
+ *
+ * To turn monitor mode off, delete the monitor interface,
+ * either with "iw dev {monif} interface del" or by sending
+ * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
+ *
+ * Note: if you try to create a monitor device named "monN", and
+ * there's already a "monN" device, it fails, as least with
+ * the netlink interface (which is what iw uses), with a return
+ * value of -ENFILE. (Return values are negative errnos.) We
+ * could probably use that to find an unused device.
+ *
+ * Yes, you can have multiple monitor devices for a given
+ * physical device.
+ */
+
+/*
+ * Is this a mac80211 device? If so, fill in the physical device path and
+ * return 1; if not, return 0. On an error, fill in handle->errbuf and
+ * return PCAP_ERROR.
+ */
+static int
+get_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
+ size_t phydev_max_pathlen)
+{
+ char *pathstr;
+ ssize_t bytes_read;
+
+ /*
+ * Generate the path string for the symlink to the physical device.
+ */
+ if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Can't generate path name string for /sys/class/net device",
+ device);
+ return PCAP_ERROR;
+ }
+ bytes_read = readlink(pathstr, phydev_path, phydev_max_pathlen);
+ if (bytes_read == -1) {
+ if (errno == ENOENT || errno == EINVAL) {
+ /*
+ * Doesn't exist, or not a symlink; assume that
+ * means it's not a mac80211 device.
+ */
+ free(pathstr);
+ return 0;
+ }
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s: Can't readlink %s", device, pathstr);
+ free(pathstr);
+ return PCAP_ERROR;
+ }
+ free(pathstr);
+ phydev_path[bytes_read] = '\0';
+ return 1;
+}
+
+#ifdef HAVE_LIBNL_SOCKETS
+#define get_nl_errmsg nl_geterror
+#else
+/* libnl 2.x compatibility code */
+
+#define nl_sock nl_handle
+
+static inline struct nl_handle *
+nl_socket_alloc(void)
+{
+ return nl_handle_alloc();
+}
+
+static inline void
+nl_socket_free(struct nl_handle *h)
+{
+ nl_handle_destroy(h);
+}
+
+#define get_nl_errmsg strerror
+
+static inline int
+__genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache)
+{
+ struct nl_cache *tmp = genl_ctrl_alloc_cache(h);
+ if (!tmp)
+ return -ENOMEM;
+ *cache = tmp;
+ return 0;
+}
+#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
+#endif /* !HAVE_LIBNL_SOCKETS */
+
+struct nl80211_state {
+ struct nl_sock *nl_sock;
+ struct nl_cache *nl_cache;
+ struct genl_family *nl80211;
+};
+
+static int
+nl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device)
+{
+ int err;
+
+ state->nl_sock = nl_socket_alloc();
+ if (!state->nl_sock) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: failed to allocate netlink handle", device);
+ return PCAP_ERROR;
+ }
+
+ if (genl_connect(state->nl_sock)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: failed to connect to generic netlink", device);
+ goto out_handle_destroy;
+ }
+
+ err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
+ if (err < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: failed to allocate generic netlink cache: %s",
+ device, get_nl_errmsg(-err));
+ goto out_handle_destroy;
+ }
+
+ state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
+ if (!state->nl80211) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: nl80211 not found", device);
+ goto out_cache_free;
+ }
+
+ return 0;
+
+out_cache_free:
+ nl_cache_free(state->nl_cache);
+out_handle_destroy:
+ nl_socket_free(state->nl_sock);
+ return PCAP_ERROR;
+}
+
+static void
+nl80211_cleanup(struct nl80211_state *state)
+{
+ genl_family_put(state->nl80211);
+ nl_cache_free(state->nl_cache);
+ nl_socket_free(state->nl_sock);
+}
+
+static int
+del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
+ const char *device, const char *mondevice);
+
+static int
+add_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
+ const char *device, const char *mondevice)
+{
+ struct pcap_linux *handlep = handle->priv;
+ int ifindex;
+ struct nl_msg *msg;
+ int err;
+
+ ifindex = iface_get_id(sock_fd, device, handle->errbuf);
+ if (ifindex == -1)
+ return PCAP_ERROR;
+
+ msg = nlmsg_alloc();
+ if (!msg) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: failed to allocate netlink msg", device);
+ return PCAP_ERROR;
+ }
+
+ genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+ 0, NL80211_CMD_NEW_INTERFACE, 0);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
+ NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
+
+ err = nl_send_auto_complete(state->nl_sock, msg);
+ if (err < 0) {
+#if defined HAVE_LIBNL_NLE
+ if (err == -NLE_FAILURE) {
+#else
+ if (err == -ENFILE) {
+#endif
+ /*
+ * Device not available; our caller should just
+ * keep trying. (libnl 2.x maps ENFILE to
+ * NLE_FAILURE; it can also map other errors
+ * to that, but there's not much we can do
+ * about that.)
+ */
+ nlmsg_free(msg);
+ return 0;
+ } else {
+ /*
+ * Real failure, not just "that device is not
+ * available.
+ */
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: nl_send_auto_complete failed adding %s interface: %s",
+ device, mondevice, get_nl_errmsg(-err));
+ nlmsg_free(msg);
+ return PCAP_ERROR;
+ }
+ }
+ err = nl_wait_for_ack(state->nl_sock);
+ if (err < 0) {
+#if defined HAVE_LIBNL_NLE
+ if (err == -NLE_FAILURE) {
+#else
+ if (err == -ENFILE) {
+#endif
+ /*
+ * Device not available; our caller should just
+ * keep trying. (libnl 2.x maps ENFILE to
+ * NLE_FAILURE; it can also map other errors
+ * to that, but there's not much we can do
+ * about that.)
+ */
+ nlmsg_free(msg);
+ return 0;
+ } else {
+ /*
+ * Real failure, not just "that device is not
+ * available.
+ */
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: nl_wait_for_ack failed adding %s interface: %s",
+ device, mondevice, get_nl_errmsg(-err));
+ nlmsg_free(msg);
+ return PCAP_ERROR;
+ }
+ }
+
+ /*
+ * Success.
+ */
+ nlmsg_free(msg);
+
+ /*
+ * Try to remember the monitor device.
+ */
+ handlep->mondevice = strdup(mondevice);
+ if (handlep->mondevice == NULL) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "strdup");
+ /*
+ * Get rid of the monitor device.
+ */
+ del_mon_if(handle, sock_fd, state, device, mondevice);
+ return PCAP_ERROR;
+ }
+ return 1;
+
+nla_put_failure:
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: nl_put failed adding %s interface",
+ device, mondevice);
+ nlmsg_free(msg);
+ return PCAP_ERROR;
+}
+
+static int
+del_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
+ const char *device, const char *mondevice)
+{
+ int ifindex;
+ struct nl_msg *msg;
+ int err;
+
+ ifindex = iface_get_id(sock_fd, mondevice, handle->errbuf);
+ if (ifindex == -1)
+ return PCAP_ERROR;
+
+ msg = nlmsg_alloc();
+ if (!msg) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: failed to allocate netlink msg", device);
+ return PCAP_ERROR;
+ }
+
+ genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
+ 0, NL80211_CMD_DEL_INTERFACE, 0);
+ NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
+
+ err = nl_send_auto_complete(state->nl_sock, msg);
+ if (err < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: nl_send_auto_complete failed deleting %s interface: %s",
+ device, mondevice, get_nl_errmsg(-err));
+ nlmsg_free(msg);
+ return PCAP_ERROR;
+ }
+ err = nl_wait_for_ack(state->nl_sock);
+ if (err < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: nl_wait_for_ack failed adding %s interface: %s",
+ device, mondevice, get_nl_errmsg(-err));
+ nlmsg_free(msg);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * Success.
+ */
+ nlmsg_free(msg);
+ return 1;
+
+nla_put_failure:
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: nl_put failed deleting %s interface",
+ device, mondevice);
+ nlmsg_free(msg);
+ return PCAP_ERROR;
+}
+
+static int
+enter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
+{
+ struct pcap_linux *handlep = handle->priv;
+ int ret;
+ char phydev_path[PATH_MAX+1];
+ struct nl80211_state nlstate;
+ struct ifreq ifr;
+ u_int n;
+
+ /*
+ * Is this a mac80211 device?
+ */
+ ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX);
+ if (ret < 0)
+ return ret; /* error */
+ if (ret == 0)
+ return 0; /* no error, but not mac80211 device */
+
+ /*
+ * XXX - is this already a monN device?
+ * If so, we're done.
+ * Is that determined by old Wireless Extensions ioctls?
+ */
+
+ /*
+ * OK, it's apparently a mac80211 device.
+ * Try to find an unused monN device for it.
+ */
+ ret = nl80211_init(handle, &nlstate, device);
+ if (ret != 0)
+ return ret;
+ for (n = 0; n < UINT_MAX; n++) {
+ /*
+ * Try mon{n}.
+ */
+ char mondevice[3+10+1]; /* mon{UINT_MAX}\0 */
+
+ pcap_snprintf(mondevice, sizeof mondevice, "mon%u", n);
+ ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
+ if (ret == 1) {
+ /*
+ * Success. We don't clean up the libnl state
+ * yet, as we'll be using it later.
+ */
+ goto added;
+ }
+ if (ret < 0) {
+ /*
+ * Hard failure. Just return ret; handle->errbuf
+ * has already been set.
+ */
+ nl80211_cleanup(&nlstate);
+ return ret;
+ }
+ }
+
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: No free monN interfaces", device);
+ nl80211_cleanup(&nlstate);
+ return PCAP_ERROR;
+
+added:
+
+#if 0
+ /*
+ * Sleep for .1 seconds.
+ */
+ delay.tv_sec = 0;
+ delay.tv_nsec = 500000000;
+ nanosleep(&delay, NULL);
+#endif
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(handle)) {
+ /*
+ * "atexit()" failed; don't put the interface
+ * in rfmon mode, just give up.
+ */
+ del_mon_if(handle, sock_fd, &nlstate, device,
+ handlep->mondevice);
+ nl80211_cleanup(&nlstate);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * Now configure the monitor interface up.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
+ if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s: Can't get flags for %s", device,
+ handlep->mondevice);
+ del_mon_if(handle, sock_fd, &nlstate, device,
+ handlep->mondevice);
+ nl80211_cleanup(&nlstate);
+ return PCAP_ERROR;
+ }
+ ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s: Can't set flags for %s", device,
+ handlep->mondevice);
+ del_mon_if(handle, sock_fd, &nlstate, device,
+ handlep->mondevice);
+ nl80211_cleanup(&nlstate);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * Success. Clean up the libnl state.
+ */
+ nl80211_cleanup(&nlstate);
+
+ /*
+ * Note that we have to delete the monitor device when we close
+ * the handle.
+ */
+ handlep->must_do_on_close |= MUST_DELETE_MONIF;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(handle);
+
+ return 1;
+}
+#endif /* HAVE_LIBNL */
+
+#ifdef IW_MODE_MONITOR
+/*
+ * Bonding devices mishandle unknown ioctls; they fail with ENODEV
+ * rather than ENOTSUP, EOPNOTSUPP, or ENOTTY, so Wireless Extensions
+ * will fail with ENODEV if we try to do them on a bonding device,
+ * making us return a "no such device" indication rather than just
+ * saying "no Wireless Extensions".
+ *
+ * So we check for bonding devices, if we can, before trying those
+ * ioctls, by trying a bonding device information query ioctl to see
+ * whether it succeeds.
+ */
+static int
+is_bonding_device(int fd, const char *device)
+{
+#ifdef BOND_INFO_QUERY_IOCTL
+ struct ifreq ifr;
+ ifbond ifb;
+
+ memset(&ifr, 0, sizeof ifr);
+ pcap_strlcpy(ifr.ifr_name, device, sizeof ifr.ifr_name);
+ memset(&ifb, 0, sizeof ifb);
+ ifr.ifr_data = (caddr_t)&ifb;
+ if (ioctl(fd, BOND_INFO_QUERY_IOCTL, &ifr) == 0)
+ return 1; /* success, so it's a bonding device */
+#endif /* BOND_INFO_QUERY_IOCTL */
+
+ return 0; /* no, it's not a bonding device */
+}
+#endif /* IW_MODE_MONITOR */
+
+static int pcap_protocol(pcap_t *handle)
+{
+ int protocol;
+
+ protocol = handle->opt.protocol;
+ if (protocol == 0)
+ protocol = ETH_P_ALL;
+
+ return htons(protocol);
+}
+
+static int
+pcap_can_set_rfmon_linux(pcap_t *handle)
+{
+#ifdef HAVE_LIBNL
+ char phydev_path[PATH_MAX+1];
+ int ret;
+#endif
+#ifdef IW_MODE_MONITOR
+ int sock_fd;
+ struct iwreq ireq;
+#endif
+
+ if (strcmp(handle->opt.device, "any") == 0) {
+ /*
+ * Monitor mode makes no sense on the "any" device.
+ */
+ return 0;
+ }
+
+#ifdef HAVE_LIBNL
+ /*
+ * Bleah. There doesn't seem to be a way to ask a mac80211
+ * device, through libnl, whether it supports monitor mode;
+ * we'll just check whether the device appears to be a
+ * mac80211 device and, if so, assume the device supports
+ * monitor mode.
+ *
+ * wmaster devices don't appear to support the Wireless
+ * Extensions, but we can create a mon device for a
+ * wmaster device, so we don't bother checking whether
+ * a mac80211 device supports the Wireless Extensions.
+ */
+ ret = get_mac80211_phydev(handle, handle->opt.device, phydev_path,
+ PATH_MAX);
+ if (ret < 0)
+ return ret; /* error */
+ if (ret == 1)
+ return 1; /* mac80211 device */
+#endif
+
+#ifdef IW_MODE_MONITOR
+ /*
+ * Bleah. There doesn't appear to be an ioctl to use to ask
+ * whether a device supports monitor mode; we'll just do
+ * SIOCGIWMODE and, if it succeeds, assume the device supports
+ * monitor mode.
+ *
+ * Open a socket on which to attempt to get the mode.
+ * (We assume that if we have Wireless Extensions support
+ * we also have PF_PACKET support.)
+ */
+ sock_fd = socket(PF_PACKET, SOCK_RAW, pcap_protocol(handle));
+ if (sock_fd == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ return PCAP_ERROR;
+ }
+
+ if (is_bonding_device(sock_fd, handle->opt.device)) {
+ /* It's a bonding device, so don't even try. */
+ close(sock_fd);
+ return 0;
+ }
+
+ /*
+ * Attempt to get the current mode.
+ */
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
+ /*
+ * Well, we got the mode; assume we can set it.
+ */
+ close(sock_fd);
+ return 1;
+ }
+ if (errno == ENODEV) {
+ /* The device doesn't even exist. */
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIWMODE failed");
+ close(sock_fd);
+ return PCAP_ERROR_NO_SUCH_DEVICE;
+ }
+ close(sock_fd);
+#endif
+ return 0;
+}
+
+/*
+ * Grabs the number of dropped packets by the interface from /proc/net/dev.
+ *
+ * XXX - what about /sys/class/net/{interface name}/rx_*? There are
+ * individual devices giving, in ASCII, various rx_ and tx_ statistics.
+ *
+ * Or can we get them in binary form from netlink?
+ */
+static long int
+linux_if_drops(const char * if_name)
+{
+ char buffer[512];
+ FILE *file;
+ char *bufptr, *nameptr, *colonptr;
+ int field_to_convert = 3;
+ long int dropped_pkts = 0;
+
+ file = fopen("/proc/net/dev", "r");
+ if (!file)
+ return 0;
+
+ while (fgets(buffer, sizeof(buffer), file) != NULL)
+ {
+ /* search for 'bytes' -- if its in there, then
+ that means we need to grab the fourth field. otherwise
+ grab the third field. */
+ if (field_to_convert != 4 && strstr(buffer, "bytes"))
+ {
+ field_to_convert = 4;
+ continue;
+ }
+
+ /*
+ * See whether this line corresponds to this device.
+ * The line should have zero or more leading blanks,
+ * followed by a device name, followed by a colon,
+ * followed by the statistics.
+ */
+ bufptr = buffer;
+ /* Skip leading blanks */
+ while (*bufptr == ' ')
+ bufptr++;
+ nameptr = bufptr;
+ /* Look for the colon */
+ colonptr = strchr(nameptr, ':');
+ if (colonptr == NULL)
+ {
+ /*
+ * Not found; this could, for example, be the
+ * header line.
+ */
+ continue;
+ }
+ /* Null-terminate the interface name. */
+ *colonptr = '\0';
+ if (strcmp(if_name, nameptr) == 0)
+ {
+ /*
+ * OK, this line has the statistics for the interface.
+ * Skip past the interface name.
+ */
+ bufptr = colonptr + 1;
+
+ /* grab the nth field from it */
+ while (--field_to_convert && *bufptr != '\0')
+ {
+ /*
+ * This isn't the field we want.
+ * First, skip any leading blanks before
+ * the field.
+ */
+ while (*bufptr == ' ')
+ bufptr++;
+
+ /*
+ * Now skip the non-blank characters of
+ * the field.
+ */
+ while (*bufptr != '\0' && *bufptr != ' ')
+ bufptr++;
+ }
+
+ if (field_to_convert == 0)
+ {
+ /*
+ * We've found the field we want.
+ * Skip any leading blanks before it.
+ */
+ while (*bufptr == ' ')
+ bufptr++;
+
+ /*
+ * Now extract the value, if we have one.
+ */
+ if (*bufptr != '\0')
+ dropped_pkts = strtol(bufptr, NULL, 10);
+ }
+ break;
+ }
+ }
+
+ fclose(file);
+ return dropped_pkts;
+}
+
+
+/*
+ * With older kernels promiscuous mode is kind of interesting because we
+ * have to reset the interface before exiting. The problem can't really
+ * be solved without some daemon taking care of managing usage counts.
+ * If we put the interface into promiscuous mode, we set a flag indicating
+ * that we must take it out of that mode when the interface is closed,
+ * and, when closing the interface, if that flag is set we take it out
+ * of promiscuous mode.
+ *
+ * Even with newer kernels, we have the same issue with rfmon mode.
+ */
+
+static void pcap_cleanup_linux( pcap_t *handle )
+{
+ struct pcap_linux *handlep = handle->priv;
+ struct ifreq ifr;
+#ifdef HAVE_LIBNL
+ struct nl80211_state nlstate;
+ int ret;
+#endif /* HAVE_LIBNL */
+#ifdef IW_MODE_MONITOR
+ int oldflags;
+ struct iwreq ireq;
+#endif /* IW_MODE_MONITOR */
+
+ if (handlep->must_do_on_close != 0) {
+ /*
+ * There's something we have to do when closing this
+ * pcap_t.
+ */
+ if (handlep->must_do_on_close & MUST_CLEAR_PROMISC) {
+ /*
+ * We put the interface into promiscuous mode;
+ * take it out of promiscuous mode.
+ *
+ * XXX - if somebody else wants it in promiscuous
+ * mode, this code cannot know that, so it'll take
+ * it out of promiscuous mode. That's not fixable
+ * in 2.0[.x] kernels.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, handlep->device,
+ sizeof(ifr.ifr_name));
+ if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
+ fprintf(stderr,
+ "Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n"
+ "Please adjust manually.\n"
+ "Hint: This can't happen with Linux >= 2.2.0.\n",
+ handlep->device, strerror(errno));
+ } else {
+ if (ifr.ifr_flags & IFF_PROMISC) {
+ /*
+ * Promiscuous mode is currently on;
+ * turn it off.
+ */
+ ifr.ifr_flags &= ~IFF_PROMISC;
+ if (ioctl(handle->fd, SIOCSIFFLAGS,
+ &ifr) == -1) {
+ fprintf(stderr,
+ "Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n"
+ "Please adjust manually.\n"
+ "Hint: This can't happen with Linux >= 2.2.0.\n",
+ handlep->device,
+ strerror(errno));
+ }
+ }
+ }
+ }
+
+#ifdef HAVE_LIBNL
+ if (handlep->must_do_on_close & MUST_DELETE_MONIF) {
+ ret = nl80211_init(handle, &nlstate, handlep->device);
+ if (ret >= 0) {
+ ret = del_mon_if(handle, handle->fd, &nlstate,
+ handlep->device, handlep->mondevice);
+ nl80211_cleanup(&nlstate);
+ }
+ if (ret < 0) {
+ fprintf(stderr,
+ "Can't delete monitor interface %s (%s).\n"
+ "Please delete manually.\n",
+ handlep->mondevice, handle->errbuf);
+ }
+ }
+#endif /* HAVE_LIBNL */
+
+#ifdef IW_MODE_MONITOR
+ if (handlep->must_do_on_close & MUST_CLEAR_RFMON) {
+ /*
+ * We put the interface into rfmon mode;
+ * take it out of rfmon mode.
+ *
+ * XXX - if somebody else wants it in rfmon
+ * mode, this code cannot know that, so it'll take
+ * it out of rfmon mode.
+ */
+
+ /*
+ * First, take the interface down if it's up;
+ * otherwise, we might get EBUSY.
+ * If we get errors, just drive on and print
+ * a warning if we can't restore the mode.
+ */
+ oldflags = 0;
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, handlep->device,
+ sizeof(ifr.ifr_name));
+ if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) {
+ if (ifr.ifr_flags & IFF_UP) {
+ oldflags = ifr.ifr_flags;
+ ifr.ifr_flags &= ~IFF_UP;
+ if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1)
+ oldflags = 0; /* didn't set, don't restore */
+ }
+ }
+
+ /*
+ * Now restore the mode.
+ */
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, handlep->device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.u.mode = handlep->oldmode;
+ if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
+ /*
+ * Scientist, you've failed.
+ */
+ fprintf(stderr,
+ "Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n"
+ "Please adjust manually.\n",
+ handlep->device, strerror(errno));
+ }
+
+ /*
+ * Now bring the interface back up if we brought
+ * it down.
+ */
+ if (oldflags != 0) {
+ ifr.ifr_flags = oldflags;
+ if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
+ fprintf(stderr,
+ "Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n"
+ "Please adjust manually.\n",
+ handlep->device, strerror(errno));
+ }
+ }
+ }
+#endif /* IW_MODE_MONITOR */
+
+ /*
+ * Take this pcap out of the list of pcaps for which we
+ * have to take the interface out of some mode.
+ */
+ pcap_remove_from_pcaps_to_close(handle);
+ }
+
+ if (handlep->mondevice != NULL) {
+ free(handlep->mondevice);
+ handlep->mondevice = NULL;
+ }
+ if (handlep->device != NULL) {
+ free(handlep->device);
+ handlep->device = NULL;
+ }
+ pcap_cleanup_live_common(handle);
+}
+
+/*
+ * Set the timeout to be used in poll() with memory-mapped packet capture.
+ */
+static void
+set_poll_timeout(struct pcap_linux *handlep)
+{
+#ifdef HAVE_TPACKET3
+ struct utsname utsname;
+ char *version_component, *endp;
+ int major, minor;
+ int broken_tpacket_v3 = 1;
+
+ /*
+ * Some versions of TPACKET_V3 have annoying bugs/misfeatures
+ * around which we have to work. Determine if we have those
+ * problems or not.
+ */
+ if (uname(&utsname) == 0) {
+ /*
+ * 3.19 is the first release with a fixed version of
+ * TPACKET_V3. We treat anything before that as
+ * not haveing a fixed version; that may really mean
+ * it has *no* version.
+ */
+ version_component = utsname.release;
+ major = strtol(version_component, &endp, 10);
+ if (endp != version_component && *endp == '.') {
+ /*
+ * OK, that was a valid major version.
+ * Get the minor version.
+ */
+ version_component = endp + 1;
+ minor = strtol(version_component, &endp, 10);
+ if (endp != version_component &&
+ (*endp == '.' || *endp == '\0')) {
+ /*
+ * OK, that was a valid minor version.
+ * Is this 3.19 or newer?
+ */
+ if (major >= 4 || (major == 3 && minor >= 19)) {
+ /* Yes. TPACKET_V3 works correctly. */
+ broken_tpacket_v3 = 0;
+ }
+ }
+ }
+ }
+#endif
+ if (handlep->timeout == 0) {
+#ifdef HAVE_TPACKET3
+ /*
+ * XXX - due to a set of (mis)features in the TPACKET_V3
+ * kernel code prior to the 3.19 kernel, blocking forever
+ * with a TPACKET_V3 socket can, if few packets are
+ * arriving and passing the socket filter, cause most
+ * packets to be dropped. See libpcap issue #335 for the
+ * full painful story.
+ *
+ * The workaround is to have poll() time out very quickly,
+ * so we grab the frames handed to us, and return them to
+ * the kernel, ASAP.
+ */
+ if (handlep->tp_version == TPACKET_V3 && broken_tpacket_v3)
+ handlep->poll_timeout = 1; /* don't block for very long */
+ else
+#endif
+ handlep->poll_timeout = -1; /* block forever */
+ } else if (handlep->timeout > 0) {
+#ifdef HAVE_TPACKET3
+ /*
+ * For TPACKET_V3, the timeout is handled by the kernel,
+ * so block forever; that way, we don't get extra timeouts.
+ * Don't do that if we have a broken TPACKET_V3, though.
+ */
+ if (handlep->tp_version == TPACKET_V3 && !broken_tpacket_v3)
+ handlep->poll_timeout = -1; /* block forever, let TPACKET_V3 wake us up */
+ else
+#endif
+ handlep->poll_timeout = handlep->timeout; /* block for that amount of time */
+ } else {
+ /*
+ * Non-blocking mode; we call poll() to pick up error
+ * indications, but we don't want it to wait for
+ * anything.
+ */
+ handlep->poll_timeout = 0;
+ }
+}
+
+/*
+ * Get a handle for a live capture from the given device. You can
+ * pass NULL as device to get all packages (without link level
+ * information of course). If you pass 1 as promisc the interface
+ * will be set to promiscous mode (XXX: I think this usage should
+ * be deprecated and functions be added to select that later allow
+ * modification of that values -- Torsten).
+ */
+static int
+pcap_activate_linux(pcap_t *handle)
+{
+ struct pcap_linux *handlep = handle->priv;
+ const char *device;
+ struct ifreq ifr;
+ int status = 0;
+ int ret;
+
+ device = handle->opt.device;
+
+ /*
+ * Make sure the name we were handed will fit into the ioctls we
+ * might perform on the device; if not, return a "No such device"
+ * indication, as the Linux kernel shouldn't support creating
+ * a device whose name won't fit into those ioctls.
+ *
+ * "Will fit" means "will fit, complete with a null terminator",
+ * so if the length, which does *not* include the null terminator,
+ * is greater than *or equal to* the size of the field into which
+ * we'll be copying it, that won't fit.
+ */
+ if (strlen(device) >= sizeof(ifr.ifr_name)) {
+ status = PCAP_ERROR_NO_SUCH_DEVICE;
+ goto fail;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+ handle->snapshot = MAXIMUM_SNAPLEN;
+
+ handle->inject_op = pcap_inject_linux;
+ handle->setfilter_op = pcap_setfilter_linux;
+ handle->setdirection_op = pcap_setdirection_linux;
+ handle->set_datalink_op = pcap_set_datalink_linux;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->cleanup_op = pcap_cleanup_linux;
+ handle->read_op = pcap_read_linux;
+ handle->stats_op = pcap_stats_linux;
+
+ /*
+ * The "any" device is a special device which causes us not
+ * to bind to a particular device and thus to look at all
+ * devices.
+ */
+ if (strcmp(device, "any") == 0) {
+ if (handle->opt.promisc) {
+ handle->opt.promisc = 0;
+ /* Just a warning. */
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Promiscuous mode not supported on the \"any\" device");
+ status = PCAP_WARNING_PROMISC_NOTSUP;
+ }
+ }
+
+ handlep->device = strdup(device);
+ if (handlep->device == NULL) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "strdup");
+ status = PCAP_ERROR;
+ goto fail;
+ }
+
+ /* copy timeout value */
+ handlep->timeout = handle->opt.timeout;
+
+ /*
+ * If we're in promiscuous mode, then we probably want
+ * to see when the interface drops packets too, so get an
+ * initial count from /proc/net/dev
+ */
+ if (handle->opt.promisc)
+ handlep->proc_dropped = linux_if_drops(handlep->device);
+
+ /*
+ * Current Linux kernels use the protocol family PF_PACKET to
+ * allow direct access to all packets on the network while
+ * older kernels had a special socket type SOCK_PACKET to
+ * implement this feature.
+ * While this old implementation is kind of obsolete we need
+ * to be compatible with older kernels for a while so we are
+ * trying both methods with the newer method preferred.
+ */
+ ret = activate_new(handle);
+ if (ret < 0) {
+ /*
+ * Fatal error with the new way; just fail.
+ * ret has the error return; if it's PCAP_ERROR,
+ * handle->errbuf has been set appropriately.
+ */
+ status = ret;
+ goto fail;
+ }
+ if (ret == 1) {
+ /*
+ * Success.
+ * Try to use memory-mapped access.
+ */
+ switch (activate_mmap(handle, &status)) {
+
+ case 1:
+ /*
+ * We succeeded. status has been
+ * set to the status to return,
+ * which might be 0, or might be
+ * a PCAP_WARNING_ value.
+ *
+ * Set the timeout to use in poll() before
+ * returning.
+ */
+ set_poll_timeout(handlep);
+ return status;
+
+ case 0:
+ /*
+ * Kernel doesn't support it - just continue
+ * with non-memory-mapped access.
+ */
+ break;
+
+ case -1:
+ /*
+ * We failed to set up to use it, or the kernel
+ * supports it, but we failed to enable it.
+ * status has been set to the error status to
+ * return and, if it's PCAP_ERROR, handle->errbuf
+ * contains the error message.
+ */
+ goto fail;
+ }
+ }
+ else if (ret == 0) {
+ /* Non-fatal error; try old way */
+ if ((ret = activate_old(handle)) != 1) {
+ /*
+ * Both methods to open the packet socket failed.
+ * Tidy up and report our failure (handle->errbuf
+ * is expected to be set by the functions above).
+ */
+ status = ret;
+ goto fail;
+ }
+ }
+
+ /*
+ * We set up the socket, but not with memory-mapped access.
+ */
+ if (handle->opt.buffer_size != 0) {
+ /*
+ * Set the socket buffer size to the specified value.
+ */
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
+ &handle->opt.buffer_size,
+ sizeof(handle->opt.buffer_size)) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SO_RCVBUF");
+ status = PCAP_ERROR;
+ goto fail;
+ }
+ }
+
+ /* Allocate the buffer */
+
+ handle->buffer = malloc(handle->bufsize + handle->offset);
+ if (!handle->buffer) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ status = PCAP_ERROR;
+ goto fail;
+ }
+
+ /*
+ * "handle->fd" is a socket, so "select()" and "poll()"
+ * should work on it.
+ */
+ handle->selectable_fd = handle->fd;
+
+ return status;
+
+fail:
+ pcap_cleanup_linux(handle);
+ return status;
+}
+
+/*
+ * Read at most max_packets from the capture stream and call the callback
+ * for each of them. Returns the number of packets handled or -1 if an
+ * error occured.
+ */
+static int
+pcap_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
+{
+ /*
+ * Currently, on Linux only one packet is delivered per read,
+ * so we don't loop.
+ */
+ return pcap_read_packet(handle, callback, user);
+}
+
+static int
+pcap_set_datalink_linux(pcap_t *handle, int dlt)
+{
+ handle->linktype = dlt;
+ return 0;
+}
+
+/*
+ * linux_check_direction()
+ *
+ * Do checks based on packet direction.
+ */
+static inline int
+linux_check_direction(const pcap_t *handle, const struct sockaddr_ll *sll)
+{
+ struct pcap_linux *handlep = handle->priv;
+
+ if (sll->sll_pkttype == PACKET_OUTGOING) {
+ /*
+ * Outgoing packet.
+ * If this is from the loopback device, reject it;
+ * we'll see the packet as an incoming packet as well,
+ * and we don't want to see it twice.
+ */
+ if (sll->sll_ifindex == handlep->lo_ifindex)
+ return 0;
+
+ /*
+ * If this is an outgoing CAN or CAN FD frame, and
+ * the user doesn't only want outgoing packets,
+ * reject it; CAN devices and drivers, and the CAN
+ * stack, always arrange to loop back transmitted
+ * packets, so they also appear as incoming packets.
+ * We don't want duplicate packets, and we can't
+ * easily distinguish packets looped back by the CAN
+ * layer than those received by the CAN layer, so we
+ * eliminate this packet instead.
+ */
+ if ((sll->sll_protocol == LINUX_SLL_P_CAN ||
+ sll->sll_protocol == LINUX_SLL_P_CANFD) &&
+ handle->direction != PCAP_D_OUT)
+ return 0;
+
+ /*
+ * If the user only wants incoming packets, reject it.
+ */
+ if (handle->direction == PCAP_D_IN)
+ return 0;
+ } else {
+ /*
+ * Incoming packet.
+ * If the user only wants outgoing packets, reject it.
+ */
+ if (handle->direction == PCAP_D_OUT)
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Read a packet from the socket calling the handler provided by
+ * the user. Returns the number of packets received or -1 if an
+ * error occured.
+ */
+static int
+pcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
+{
+ struct pcap_linux *handlep = handle->priv;
+ u_char *bp;
+ int offset;
+#ifdef HAVE_PF_PACKET_SOCKETS
+ struct sockaddr_ll from;
+#else
+ struct sockaddr from;
+#endif
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
+ struct iovec iov;
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ union {
+ struct cmsghdr cmsg;
+ char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
+ } cmsg_buf;
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
+ socklen_t fromlen;
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
+ int packet_len, caplen;
+ struct pcap_pkthdr pcap_header;
+
+ struct bpf_aux_data aux_data;
+#ifdef HAVE_PF_PACKET_SOCKETS
+ /*
+ * If this is a cooked device, leave extra room for a
+ * fake packet header.
+ */
+ if (handlep->cooked) {
+ if (handle->linktype == DLT_LINUX_SLL2)
+ offset = SLL2_HDR_LEN;
+ else
+ offset = SLL_HDR_LEN;
+ } else
+ offset = 0;
+#else
+ /*
+ * This system doesn't have PF_PACKET sockets, so it doesn't
+ * support cooked devices.
+ */
+ offset = 0;
+#endif
+
+ /*
+ * Receive a single packet from the kernel.
+ * We ignore EINTR, as that might just be due to a signal
+ * being delivered - if the signal should interrupt the
+ * loop, the signal handler should call pcap_breakloop()
+ * to set handle->break_loop (we ignore it on other
+ * platforms as well).
+ * We also ignore ENETDOWN, so that we can continue to
+ * capture traffic if the interface goes down and comes
+ * back up again; comments in the kernel indicate that
+ * we'll just block waiting for packets if we try to
+ * receive from a socket that delivered ENETDOWN, and,
+ * if we're using a memory-mapped buffer, we won't even
+ * get notified of "network down" events.
+ */
+ bp = (u_char *)handle->buffer + handle->offset;
+
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
+ msg.msg_name = &from;
+ msg.msg_namelen = sizeof(from);
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &cmsg_buf;
+ msg.msg_controllen = sizeof(cmsg_buf);
+ msg.msg_flags = 0;
+
+ iov.iov_len = handle->bufsize - offset;
+ iov.iov_base = bp + offset;
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
+
+ do {
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (handle->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it has,
+ * and return PCAP_ERROR_BREAK as an indication that
+ * we were told to break out of the loop.
+ */
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
+ packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC);
+#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
+ fromlen = sizeof(from);
+ packet_len = recvfrom(
+ handle->fd, bp + offset,
+ handle->bufsize - offset, MSG_TRUNC,
+ (struct sockaddr *) &from, &fromlen);
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
+ } while (packet_len == -1 && errno == EINTR);
+
+ /* Check if an error occured */
+
+ if (packet_len == -1) {
+ switch (errno) {
+
+ case EAGAIN:
+ return 0; /* no packet there */
+
+ case ENETDOWN:
+ /*
+ * The device on which we're capturing went away.
+ *
+ * XXX - we should really return
+ * PCAP_ERROR_IFACE_NOT_UP, but pcap_dispatch()
+ * etc. aren't defined to return that.
+ */
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "The interface went down");
+ return PCAP_ERROR;
+
+ default:
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "recvfrom");
+ return PCAP_ERROR;
+ }
+ }
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+ if (!handlep->sock_packet) {
+ /*
+ * Unfortunately, there is a window between socket() and
+ * bind() where the kernel may queue packets from any
+ * interface. If we're bound to a particular interface,
+ * discard packets not from that interface.
+ *
+ * (If socket filters are supported, we could do the
+ * same thing we do when changing the filter; however,
+ * that won't handle packet sockets without socket
+ * filter support, and it's a bit more complicated.
+ * It would save some instructions per packet, however.)
+ */
+ if (handlep->ifindex != -1 &&
+ from.sll_ifindex != handlep->ifindex)
+ return 0;
+
+ /*
+ * Do checks based on packet direction.
+ * We can only do this if we're using PF_PACKET; the
+ * address returned for SOCK_PACKET is a "sockaddr_pkt"
+ * which lacks the relevant packet type information.
+ */
+ if (!linux_check_direction(handle, &from))
+ return 0;
+ }
+#endif
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+ /*
+ * If this is a cooked device, fill in the fake packet header.
+ */
+ if (handlep->cooked) {
+ /*
+ * Add the length of the fake header to the length
+ * of packet data we read.
+ */
+ if (handle->linktype == DLT_LINUX_SLL2) {
+ struct sll2_header *hdrp;
+
+ packet_len += SLL2_HDR_LEN;
+
+ hdrp = (struct sll2_header *)bp;
+ hdrp->sll2_protocol = from.sll_protocol;
+ hdrp->sll2_reserved_mbz = 0;
+ hdrp->sll2_if_index = htonl(from.sll_ifindex);
+ hdrp->sll2_hatype = htons(from.sll_hatype);
+ hdrp->sll2_pkttype = from.sll_pkttype;
+ hdrp->sll2_halen = from.sll_halen;
+ memcpy(hdrp->sll2_addr, from.sll_addr,
+ (from.sll_halen > SLL_ADDRLEN) ?
+ SLL_ADDRLEN :
+ from.sll_halen);
+ } else {
+ struct sll_header *hdrp;
+
+ packet_len += SLL_HDR_LEN;
+
+ hdrp = (struct sll_header *)bp;
+ hdrp->sll_pkttype = htons(from.sll_pkttype);
+ hdrp->sll_hatype = htons(from.sll_hatype);
+ hdrp->sll_halen = htons(from.sll_halen);
+ memcpy(hdrp->sll_addr, from.sll_addr,
+ (from.sll_halen > SLL_ADDRLEN) ?
+ SLL_ADDRLEN :
+ from.sll_halen);
+ hdrp->sll_protocol = from.sll_protocol;
+ }
+ }
+
+ /*
+ * Start out with no VLAN information.
+ */
+ aux_data.vlan_tag_present = 0;
+ aux_data.vlan_tag = 0;
+#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI)
+ if (handlep->vlan_offset != -1) {
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ struct tpacket_auxdata *aux;
+ unsigned int len;
+ struct vlan_tag *tag;
+
+ if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
+ cmsg->cmsg_level != SOL_PACKET ||
+ cmsg->cmsg_type != PACKET_AUXDATA) {
+ /*
+ * This isn't a PACKET_AUXDATA auxiliary
+ * data item.
+ */
+ continue;
+ }
+
+ aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
+ if (!VLAN_VALID(aux, aux)) {
+ /*
+ * There is no VLAN information in the
+ * auxiliary data.
+ */
+ continue;
+ }
+
+ len = (u_int)packet_len > iov.iov_len ? iov.iov_len : (u_int)packet_len;
+ if (len < (u_int)handlep->vlan_offset)
+ break;
+
+ /*
+ * Move everything in the header, except the
+ * type field, down VLAN_TAG_LEN bytes, to
+ * allow us to insert the VLAN tag between
+ * that stuff and the type field.
+ */
+ bp -= VLAN_TAG_LEN;
+ memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
+
+ /*
+ * Now insert the tag.
+ */
+ tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
+ tag->vlan_tpid = htons(VLAN_TPID(aux, aux));
+ tag->vlan_tci = htons(aux->tp_vlan_tci);
+
+ /*
+ * Save a flag indicating that we have a VLAN tag,
+ * and the VLAN TCI, to bpf_aux_data struct for
+ * use by the BPF filter if we're doing the
+ * filtering in userland.
+ */
+ aux_data.vlan_tag_present = 1;
+ aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff;
+
+ /*
+ * Add the tag to the packet lengths.
+ */
+ packet_len += VLAN_TAG_LEN;
+ }
+ }
+#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */
+#endif /* HAVE_PF_PACKET_SOCKETS */
+
+ /*
+ * XXX: According to the kernel source we should get the real
+ * packet len if calling recvfrom with MSG_TRUNC set. It does
+ * not seem to work here :(, but it is supported by this code
+ * anyway.
+ * To be honest the code RELIES on that feature so this is really
+ * broken with 2.2.x kernels.
+ * I spend a day to figure out what's going on and I found out
+ * that the following is happening:
+ *
+ * The packet comes from a random interface and the packet_rcv
+ * hook is called with a clone of the packet. That code inserts
+ * the packet into the receive queue of the packet socket.
+ * If a filter is attached to that socket that filter is run
+ * first - and there lies the problem. The default filter always
+ * cuts the packet at the snaplen:
+ *
+ * # tcpdump -d
+ * (000) ret #68
+ *
+ * So the packet filter cuts down the packet. The recvfrom call
+ * says "hey, it's only 68 bytes, it fits into the buffer" with
+ * the result that we don't get the real packet length. This
+ * is valid at least until kernel 2.2.17pre6.
+ *
+ * We currently handle this by making a copy of the filter
+ * program, fixing all "ret" instructions with non-zero
+ * operands to have an operand of MAXIMUM_SNAPLEN so that the
+ * filter doesn't truncate the packet, and supplying that modified
+ * filter to the kernel.
+ */
+
+ caplen = packet_len;
+ if (caplen > handle->snapshot)
+ caplen = handle->snapshot;
+
+ /* Run the packet filter if not using kernel filter */
+ if (handlep->filter_in_userland && handle->fcode.bf_insns) {
+ if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp,
+ packet_len, caplen, &aux_data) == 0) {
+ /* rejected by filter */
+ return 0;
+ }
+ }
+
+ /* Fill in our own header data */
+
+ /* get timestamp for this packet */
+#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
+ if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
+ if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMPNS");
+ return PCAP_ERROR;
+ }
+ } else
+#endif
+ {
+ if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMP");
+ return PCAP_ERROR;
+ }
+ }
+
+ pcap_header.caplen = caplen;
+ pcap_header.len = packet_len;
+
+ /*
+ * Count the packet.
+ *
+ * Arguably, we should count them before we check the filter,
+ * as on many other platforms "ps_recv" counts packets
+ * handed to the filter rather than packets that passed
+ * the filter, but if filtering is done in the kernel, we
+ * can't get a count of packets that passed the filter,
+ * and that would mean the meaning of "ps_recv" wouldn't
+ * be the same on all Linux systems.
+ *
+ * XXX - it's not the same on all systems in any case;
+ * ideally, we should have a "get the statistics" call
+ * that supplies more counts and indicates which of them
+ * it supplies, so that we supply a count of packets
+ * handed to the filter only on platforms where that
+ * information is available.
+ *
+ * We count them here even if we can get the packet count
+ * from the kernel, as we can only determine at run time
+ * whether we'll be able to get it from the kernel (if
+ * HAVE_STRUCT_TPACKET_STATS isn't defined, we can't get it from
+ * the kernel, but if it is defined, the library might
+ * have been built with a 2.4 or later kernel, but we
+ * might be running on a 2.2[.x] kernel without Alexey
+ * Kuznetzov's turbopacket patches, and thus the kernel
+ * might not be able to supply those statistics). We
+ * could, I guess, try, when opening the socket, to get
+ * the statistics, and if we can not increment the count
+ * here, but it's not clear that always incrementing
+ * the count is more expensive than always testing a flag
+ * in memory.
+ *
+ * We keep the count in "handlep->packets_read", and use that
+ * for "ps_recv" if we can't get the statistics from the kernel.
+ * We do that because, if we *can* get the statistics from
+ * the kernel, we use "handlep->stat.ps_recv" and
+ * "handlep->stat.ps_drop" as running counts, as reading the
+ * statistics from the kernel resets the kernel statistics,
+ * and if we directly increment "handlep->stat.ps_recv" here,
+ * that means it will count packets *twice* on systems where
+ * we can get kernel statistics - once here, and once in
+ * pcap_stats_linux().
+ */
+ handlep->packets_read++;
+
+ /* Call the user supplied callback function */
+ callback(userdata, &pcap_header, bp);
+
+ return 1;
+}
+
+static int
+pcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
+{
+ struct pcap_linux *handlep = handle->priv;
+ int ret;
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+ if (!handlep->sock_packet) {
+ /* PF_PACKET socket */
+ if (handlep->ifindex == -1) {
+ /*
+ * We don't support sending on the "any" device.
+ */
+ pcap_strlcpy(handle->errbuf,
+ "Sending packets isn't supported on the \"any\" device",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+
+ if (handlep->cooked) {
+ /*
+ * We don't support sending on cooked-mode sockets.
+ *
+ * XXX - how do you send on a bound cooked-mode
+ * socket?
+ * Is a "sendto()" required there?
+ */
+ pcap_strlcpy(handle->errbuf,
+ "Sending packets isn't supported in cooked mode",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+ }
+ }
+#endif
+
+ ret = send(handle->fd, buf, size, 0);
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (-1);
+ }
+ return (ret);
+}
+
+/*
+ * Get the statistics for the given packet capture handle.
+ * Reports the number of dropped packets iff the kernel supports
+ * the PACKET_STATISTICS "getsockopt()" argument (2.4 and later
+ * kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket
+ * patches); otherwise, that information isn't available, and we lie
+ * and report 0 as the count of dropped packets.
+ */
+static int
+pcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+ struct pcap_linux *handlep = handle->priv;
+#ifdef HAVE_STRUCT_TPACKET_STATS
+#ifdef HAVE_TPACKET3
+ /*
+ * For sockets using TPACKET_V1 or TPACKET_V2, the extra
+ * stuff at the end of a struct tpacket_stats_v3 will not
+ * be filled in, and we don't look at it so this is OK even
+ * for those sockets. In addition, the PF_PACKET socket
+ * code in the kernel only uses the length parameter to
+ * compute how much data to copy out and to indicate how
+ * much data was copied out, so it's OK to base it on the
+ * size of a struct tpacket_stats.
+ *
+ * XXX - it's probably OK, in fact, to just use a
+ * struct tpacket_stats for V3 sockets, as we don't
+ * care about the tp_freeze_q_cnt stat.
+ */
+ struct tpacket_stats_v3 kstats;
+#else /* HAVE_TPACKET3 */
+ struct tpacket_stats kstats;
+#endif /* HAVE_TPACKET3 */
+ socklen_t len = sizeof (struct tpacket_stats);
+#endif /* HAVE_STRUCT_TPACKET_STATS */
+
+ long if_dropped = 0;
+
+ /*
+ * To fill in ps_ifdrop, we parse /proc/net/dev for the number
+ */
+ if (handle->opt.promisc)
+ {
+ if_dropped = handlep->proc_dropped;
+ handlep->proc_dropped = linux_if_drops(handlep->device);
+ handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped);
+ }
+
+#ifdef HAVE_STRUCT_TPACKET_STATS
+ /*
+ * Try to get the packet counts from the kernel.
+ */
+ if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS,
+ &kstats, &len) > -1) {
+ /*
+ * On systems where the PACKET_STATISTICS "getsockopt()"
+ * argument is supported on PF_PACKET sockets:
+ *
+ * "ps_recv" counts only packets that *passed* the
+ * filter, not packets that didn't pass the filter.
+ * This includes packets later dropped because we
+ * ran out of buffer space.
+ *
+ * "ps_drop" counts packets dropped because we ran
+ * out of buffer space. It doesn't count packets
+ * dropped by the interface driver. It counts only
+ * packets that passed the filter.
+ *
+ * See above for ps_ifdrop.
+ *
+ * Both statistics include packets not yet read from
+ * the kernel by libpcap, and thus not yet seen by
+ * the application.
+ *
+ * In "linux/net/packet/af_packet.c", at least in the
+ * 2.4.9 kernel, "tp_packets" is incremented for every
+ * packet that passes the packet filter *and* is
+ * successfully queued on the socket; "tp_drops" is
+ * incremented for every packet dropped because there's
+ * not enough free space in the socket buffer.
+ *
+ * When the statistics are returned for a PACKET_STATISTICS
+ * "getsockopt()" call, "tp_drops" is added to "tp_packets",
+ * so that "tp_packets" counts all packets handed to
+ * the PF_PACKET socket, including packets dropped because
+ * there wasn't room on the socket buffer - but not
+ * including packets that didn't pass the filter.
+ *
+ * In the BSD BPF, the count of received packets is
+ * incremented for every packet handed to BPF, regardless
+ * of whether it passed the filter.
+ *
+ * We can't make "pcap_stats()" work the same on both
+ * platforms, but the best approximation is to return
+ * "tp_packets" as the count of packets and "tp_drops"
+ * as the count of drops.
+ *
+ * Keep a running total because each call to
+ * getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, ....
+ * resets the counters to zero.
+ */
+ handlep->stat.ps_recv += kstats.tp_packets;
+ handlep->stat.ps_drop += kstats.tp_drops;
+ *stats = handlep->stat;
+ return 0;
+ }
+ else
+ {
+ /*
+ * If the error was EOPNOTSUPP, fall through, so that
+ * if you build the library on a system with
+ * "struct tpacket_stats" and run it on a system
+ * that doesn't, it works as it does if the library
+ * is built on a system without "struct tpacket_stats".
+ */
+ if (errno != EOPNOTSUPP) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "pcap_stats");
+ return -1;
+ }
+ }
+#endif
+ /*
+ * On systems where the PACKET_STATISTICS "getsockopt()" argument
+ * is not supported on PF_PACKET sockets:
+ *
+ * "ps_recv" counts only packets that *passed* the filter,
+ * not packets that didn't pass the filter. It does not
+ * count packets dropped because we ran out of buffer
+ * space.
+ *
+ * "ps_drop" is not supported.
+ *
+ * "ps_ifdrop" is supported. It will return the number
+ * of drops the interface reports in /proc/net/dev,
+ * if that is available.
+ *
+ * "ps_recv" doesn't include packets not yet read from
+ * the kernel by libpcap.
+ *
+ * We maintain the count of packets processed by libpcap in
+ * "handlep->packets_read", for reasons described in the comment
+ * at the end of pcap_read_packet(). We have no idea how many
+ * packets were dropped by the kernel buffers -- but we know
+ * how many the interface dropped, so we can return that.
+ */
+
+ stats->ps_recv = handlep->packets_read;
+ stats->ps_drop = 0;
+ stats->ps_ifdrop = handlep->stat.ps_ifdrop;
+ return 0;
+}
+
+static int
+add_linux_if(pcap_if_list_t *devlistp, const char *ifname, int fd, char *errbuf)
+{
+ const char *p;
+ char name[512]; /* XXX - pick a size */
+ char *q, *saveq;
+ struct ifreq ifrflags;
+
+ /*
+ * Get the interface name.
+ */
+ p = ifname;
+ q = &name[0];
+ while (*p != '\0' && isascii(*p) && !isspace(*p)) {
+ if (*p == ':') {
+ /*
+ * This could be the separator between a
+ * name and an alias number, or it could be
+ * the separator between a name with no
+ * alias number and the next field.
+ *
+ * If there's a colon after digits, it
+ * separates the name and the alias number,
+ * otherwise it separates the name and the
+ * next field.
+ */
+ saveq = q;
+ while (isascii(*p) && isdigit(*p))
+ *q++ = *p++;
+ if (*p != ':') {
+ /*
+ * That was the next field,
+ * not the alias number.
+ */
+ q = saveq;
+ }
+ break;
+ } else
+ *q++ = *p++;
+ }
+ *q = '\0';
+
+ /*
+ * Get the flags for this interface.
+ */
+ pcap_strlcpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
+ if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
+ if (errno == ENXIO || errno == ENODEV)
+ return (0); /* device doesn't actually exist - ignore it */
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFFLAGS: %.*s",
+ (int)sizeof(ifrflags.ifr_name),
+ ifrflags.ifr_name);
+ return (-1);
+ }
+
+ /*
+ * Add an entry for this interface, with no addresses, if it's
+ * not already in the list.
+ */
+ if (find_or_add_if(devlistp, name, ifrflags.ifr_flags,
+ get_if_flags, errbuf) == NULL) {
+ /*
+ * Failure.
+ */
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * Get from "/sys/class/net" all interfaces listed there; if they're
+ * already in the list of interfaces we have, that won't add another
+ * instance, but if they're not, that'll add them.
+ *
+ * We don't bother getting any addresses for them; it appears you can't
+ * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
+ * although some other types of addresses can be fetched with SIOCGIFADDR,
+ * we don't bother with them for now.
+ *
+ * We also don't fail if we couldn't open "/sys/class/net"; we just leave
+ * the list of interfaces as is, and return 0, so that we can try
+ * scanning /proc/net/dev.
+ *
+ * Otherwise, we return 1 if we don't get an error and -1 if we do.
+ */
+static int
+scan_sys_class_net(pcap_if_list_t *devlistp, char *errbuf)
+{
+ DIR *sys_class_net_d;
+ int fd;
+ struct dirent *ent;
+ char subsystem_path[PATH_MAX+1];
+ struct stat statb;
+ int ret = 1;
+
+ sys_class_net_d = opendir("/sys/class/net");
+ if (sys_class_net_d == NULL) {
+ /*
+ * Don't fail if it doesn't exist at all.
+ */
+ if (errno == ENOENT)
+ return (0);
+
+ /*
+ * Fail if we got some other error.
+ */
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't open /sys/class/net");
+ return (-1);
+ }
+
+ /*
+ * Create a socket from which to fetch interface information.
+ */
+ fd = socket(PF_UNIX, SOCK_RAW, 0);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ (void)closedir(sys_class_net_d);
+ return (-1);
+ }
+
+ for (;;) {
+ errno = 0;
+ ent = readdir(sys_class_net_d);
+ if (ent == NULL) {
+ /*
+ * Error or EOF; if errno != 0, it's an error.
+ */
+ break;
+ }
+
+ /*
+ * Ignore "." and "..".
+ */
+ if (strcmp(ent->d_name, ".") == 0 ||
+ strcmp(ent->d_name, "..") == 0)
+ continue;
+
+ /*
+ * Ignore plain files; they do not have subdirectories
+ * and thus have no attributes.
+ */
+ if (ent->d_type == DT_REG)
+ continue;
+
+ /*
+ * Is there an "ifindex" file under that name?
+ * (We don't care whether it's a directory or
+ * a symlink; older kernels have directories
+ * for devices, newer kernels have symlinks to
+ * directories.)
+ */
+ pcap_snprintf(subsystem_path, sizeof subsystem_path,
+ "/sys/class/net/%s/ifindex", ent->d_name);
+ if (lstat(subsystem_path, &statb) != 0) {
+ /*
+ * Stat failed. Either there was an error
+ * other than ENOENT, and we don't know if
+ * this is an interface, or it's ENOENT,
+ * and either some part of "/sys/class/net/{if}"
+ * disappeared, in which case it probably means
+ * the interface disappeared, or there's no
+ * "ifindex" file, which means it's not a
+ * network interface.
+ */
+ continue;
+ }
+
+ /*
+ * Attempt to add the interface.
+ */
+ if (add_linux_if(devlistp, &ent->d_name[0], fd, errbuf) == -1) {
+ /* Fail. */
+ ret = -1;
+ break;
+ }
+ }
+ if (ret != -1) {
+ /*
+ * Well, we didn't fail for any other reason; did we
+ * fail due to an error reading the directory?
+ */
+ if (errno != 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Error reading /sys/class/net");
+ ret = -1;
+ }
+ }
+
+ (void)close(fd);
+ (void)closedir(sys_class_net_d);
+ return (ret);
+}
+
+/*
+ * Get from "/proc/net/dev" all interfaces listed there; if they're
+ * already in the list of interfaces we have, that won't add another
+ * instance, but if they're not, that'll add them.
+ *
+ * See comments from scan_sys_class_net().
+ */
+static int
+scan_proc_net_dev(pcap_if_list_t *devlistp, char *errbuf)
+{
+ FILE *proc_net_f;
+ int fd;
+ char linebuf[512];
+ int linenum;
+ char *p;
+ int ret = 0;
+
+ proc_net_f = fopen("/proc/net/dev", "r");
+ if (proc_net_f == NULL) {
+ /*
+ * Don't fail if it doesn't exist at all.
+ */
+ if (errno == ENOENT)
+ return (0);
+
+ /*
+ * Fail if we got some other error.
+ */
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't open /proc/net/dev");
+ return (-1);
+ }
+
+ /*
+ * Create a socket from which to fetch interface information.
+ */
+ fd = socket(PF_UNIX, SOCK_RAW, 0);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ (void)fclose(proc_net_f);
+ return (-1);
+ }
+
+ for (linenum = 1;
+ fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
+ /*
+ * Skip the first two lines - they're headers.
+ */
+ if (linenum <= 2)
+ continue;
+
+ p = &linebuf[0];
+
+ /*
+ * Skip leading white space.
+ */
+ while (*p != '\0' && isascii(*p) && isspace(*p))
+ p++;
+ if (*p == '\0' || *p == '\n')
+ continue; /* blank line */
+
+ /*
+ * Attempt to add the interface.
+ */
+ if (add_linux_if(devlistp, p, fd, errbuf) == -1) {
+ /* Fail. */
+ ret = -1;
+ break;
+ }
+ }
+ if (ret != -1) {
+ /*
+ * Well, we didn't fail for any other reason; did we
+ * fail due to an error reading the file?
+ */
+ if (ferror(proc_net_f)) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Error reading /proc/net/dev");
+ ret = -1;
+ }
+ }
+
+ (void)close(fd);
+ (void)fclose(proc_net_f);
+ return (ret);
+}
+
+/*
+ * Description string for the "any" device.
+ */
+static const char any_descr[] = "Pseudo-device that captures on all interfaces";
+
+/*
+ * A SOCK_PACKET or PF_PACKET socket can be bound to any network interface.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
+/*
+ * Get additional flags for a device, using SIOCGIFMEDIA.
+ */
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+ int sock;
+ FILE *fh;
+ unsigned int arptype;
+ struct ifreq ifr;
+ struct ethtool_value info;
+
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback devices aren't wireless, and "connected"/
+ * "disconnected" doesn't apply to them.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return 0;
+ }
+
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock == -1) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno,
+ "Can't create socket to get ethtool information for %s",
+ name);
+ return -1;
+ }
+
+ /*
+ * OK, what type of network is this?
+ * In particular, is it wired or wireless?
+ */
+ if (is_wifi(sock, name)) {
+ /*
+ * Wi-Fi, hence wireless.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ } else {
+ /*
+ * OK, what does /sys/class/net/{if}/type contain?
+ * (We don't use that for Wi-Fi, as it'll report
+ * "Ethernet", i.e. ARPHRD_ETHER, for non-monitor-
+ * mode devices.)
+ */
+ char *pathstr;
+
+ if (asprintf(&pathstr, "/sys/class/net/%s/type", name) == -1) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Can't generate path name string for /sys/class/net device",
+ name);
+ close(sock);
+ return -1;
+ }
+ fh = fopen(pathstr, "r");
+ if (fh != NULL) {
+ if (fscanf(fh, "%u", &arptype) == 1) {
+ /*
+ * OK, we got an ARPHRD_ type; what is it?
+ */
+ switch (arptype) {
+
+#ifdef ARPHRD_LOOPBACK
+ case ARPHRD_LOOPBACK:
+ /*
+ * These are types to which
+ * "connected" and "disconnected"
+ * don't apply, so don't bother
+ * asking about it.
+ *
+ * XXX - add other types?
+ */
+ close(sock);
+ fclose(fh);
+ free(pathstr);
+ return 0;
+#endif
+
+ case ARPHRD_IRDA:
+ case ARPHRD_IEEE80211:
+ case ARPHRD_IEEE80211_PRISM:
+ case ARPHRD_IEEE80211_RADIOTAP:
+#ifdef ARPHRD_IEEE802154
+ case ARPHRD_IEEE802154:
+#endif
+#ifdef ARPHRD_IEEE802154_MONITOR
+ case ARPHRD_IEEE802154_MONITOR:
+#endif
+#ifdef ARPHRD_6LOWPAN
+ case ARPHRD_6LOWPAN:
+#endif
+ /*
+ * Various wireless types.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ break;
+ }
+ }
+ fclose(fh);
+ free(pathstr);
+ }
+ }
+
+#ifdef ETHTOOL_GLINK
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name));
+ info.cmd = ETHTOOL_GLINK;
+ ifr.ifr_data = (caddr_t)&info;
+ if (ioctl(sock, SIOCETHTOOL, &ifr) == -1) {
+ int save_errno = errno;
+
+ switch (save_errno) {
+
+ case EOPNOTSUPP:
+ case EINVAL:
+ /*
+ * OK, this OS version or driver doesn't support
+ * asking for this information.
+ * XXX - distinguish between "this doesn't
+ * support ethtool at all because it's not
+ * that type of device" vs. "this doesn't
+ * support ethtool even though it's that
+ * type of device", and return "unknown".
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ close(sock);
+ return 0;
+
+ case ENODEV:
+ /*
+ * OK, no such device.
+ * The user will find that out when they try to
+ * activate the device; just say "OK" and
+ * don't set anything.
+ */
+ close(sock);
+ return 0;
+
+ default:
+ /*
+ * Other error.
+ */
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ save_errno,
+ "%s: SIOCETHTOOL(ETHTOOL_GLINK) ioctl failed",
+ name);
+ close(sock);
+ return -1;
+ }
+ }
+
+ /*
+ * Is it connected?
+ */
+ if (info.data) {
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ } else {
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ }
+#endif
+
+ close(sock);
+ return 0;
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ int ret;
+
+ /*
+ * Get the list of regular interfaces first.
+ */
+ if (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+ get_if_flags) == -1)
+ return (-1); /* failure */
+
+ /*
+ * Read "/sys/class/net", and add to the list of interfaces all
+ * interfaces listed there that we don't already have, because,
+ * on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses,
+ * and even getifaddrs() won't return information about
+ * interfaces with no addresses, so you need to read "/sys/class/net"
+ * to get the names of the rest of the interfaces.
+ */
+ ret = scan_sys_class_net(devlistp, errbuf);
+ if (ret == -1)
+ return (-1); /* failed */
+ if (ret == 0) {
+ /*
+ * No /sys/class/net; try reading /proc/net/dev instead.
+ */
+ if (scan_proc_net_dev(devlistp, errbuf) == -1)
+ return (-1);
+ }
+
+ /*
+ * Add the "any" device.
+ * As it refers to all network devices, not to any particular
+ * network device, the notion of "connected" vs. "disconnected"
+ * doesn't apply.
+ */
+ if (add_dev(devlistp, "any",
+ PCAP_IF_UP|PCAP_IF_RUNNING|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ any_descr, errbuf) == NULL)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * Attach the given BPF code to the packet capture device.
+ */
+static int
+pcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
+ int is_mmapped)
+{
+ struct pcap_linux *handlep;
+#ifdef SO_ATTACH_FILTER
+ struct sock_fprog fcode;
+ int can_filter_in_kernel;
+ int err = 0;
+#endif
+
+ if (!handle)
+ return -1;
+ if (!filter) {
+ pcap_strlcpy(handle->errbuf, "setfilter: No filter specified",
+ PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ handlep = handle->priv;
+
+ /* Make our private copy of the filter */
+
+ if (install_bpf_program(handle, filter) < 0)
+ /* install_bpf_program() filled in errbuf */
+ return -1;
+
+ /*
+ * Run user level packet filter by default. Will be overriden if
+ * installing a kernel filter succeeds.
+ */
+ handlep->filter_in_userland = 1;
+
+ /* Install kernel level filter if possible */
+
+#ifdef SO_ATTACH_FILTER
+#ifdef USHRT_MAX
+ if (handle->fcode.bf_len > USHRT_MAX) {
+ /*
+ * fcode.len is an unsigned short for current kernel.
+ * I have yet to see BPF-Code with that much
+ * instructions but still it is possible. So for the
+ * sake of correctness I added this check.
+ */
+ fprintf(stderr, "Warning: Filter too complex for kernel\n");
+ fcode.len = 0;
+ fcode.filter = NULL;
+ can_filter_in_kernel = 0;
+ } else
+#endif /* USHRT_MAX */
+ {
+ /*
+ * Oh joy, the Linux kernel uses struct sock_fprog instead
+ * of struct bpf_program and of course the length field is
+ * of different size. Pointed out by Sebastian
+ *
+ * Oh, and we also need to fix it up so that all "ret"
+ * instructions with non-zero operands have MAXIMUM_SNAPLEN
+ * as the operand if we're not capturing in memory-mapped
+ * mode, and so that, if we're in cooked mode, all memory-
+ * reference instructions use special magic offsets in
+ * references to the link-layer header and assume that the
+ * link-layer payload begins at 0; "fix_program()" will do
+ * that.
+ */
+ switch (fix_program(handle, &fcode, is_mmapped)) {
+
+ case -1:
+ default:
+ /*
+ * Fatal error; just quit.
+ * (The "default" case shouldn't happen; we
+ * return -1 for that reason.)
+ */
+ return -1;
+
+ case 0:
+ /*
+ * The program performed checks that we can't make
+ * work in the kernel.
+ */
+ can_filter_in_kernel = 0;
+ break;
+
+ case 1:
+ /*
+ * We have a filter that'll work in the kernel.
+ */
+ can_filter_in_kernel = 1;
+ break;
+ }
+ }
+
+ /*
+ * NOTE: at this point, we've set both the "len" and "filter"
+ * fields of "fcode". As of the 2.6.32.4 kernel, at least,
+ * those are the only members of the "sock_fprog" structure,
+ * so we initialize every member of that structure.
+ *
+ * If there is anything in "fcode" that is not initialized,
+ * it is either a field added in a later kernel, or it's
+ * padding.
+ *
+ * If a new field is added, this code needs to be updated
+ * to set it correctly.
+ *
+ * If there are no other fields, then:
+ *
+ * if the Linux kernel looks at the padding, it's
+ * buggy;
+ *
+ * if the Linux kernel doesn't look at the padding,
+ * then if some tool complains that we're passing
+ * uninitialized data to the kernel, then the tool
+ * is buggy and needs to understand that it's just
+ * padding.
+ */
+ if (can_filter_in_kernel) {
+ if ((err = set_kernel_filter(handle, &fcode)) == 0)
+ {
+ /*
+ * Installation succeded - using kernel filter,
+ * so userland filtering not needed.
+ */
+ handlep->filter_in_userland = 0;
+ }
+ else if (err == -1) /* Non-fatal error */
+ {
+ /*
+ * Print a warning if we weren't able to install
+ * the filter for a reason other than "this kernel
+ * isn't configured to support socket filters.
+ */
+ if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) {
+ fprintf(stderr,
+ "Warning: Kernel filter failed: %s\n",
+ pcap_strerror(errno));
+ }
+ }
+ }
+
+ /*
+ * If we're not using the kernel filter, get rid of any kernel
+ * filter that might've been there before, e.g. because the
+ * previous filter could work in the kernel, or because some other
+ * code attached a filter to the socket by some means other than
+ * calling "pcap_setfilter()". Otherwise, the kernel filter may
+ * filter out packets that would pass the new userland filter.
+ */
+ if (handlep->filter_in_userland) {
+ if (reset_kernel_filter(handle) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "can't remove kernel filter");
+ err = -2; /* fatal error */
+ }
+ }
+
+ /*
+ * Free up the copy of the filter that was made by "fix_program()".
+ */
+ if (fcode.filter != NULL)
+ free(fcode.filter);
+
+ if (err == -2)
+ /* Fatal error */
+ return -1;
+#endif /* SO_ATTACH_FILTER */
+
+ return 0;
+}
+
+static int
+pcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
+{
+ return pcap_setfilter_linux_common(handle, filter, 0);
+}
+
+
+/*
+ * Set direction flag: Which packets do we accept on a forwarding
+ * single device? IN, OUT or both?
+ */
+static int
+pcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
+{
+#ifdef HAVE_PF_PACKET_SOCKETS
+ struct pcap_linux *handlep = handle->priv;
+
+ if (!handlep->sock_packet) {
+ handle->direction = d;
+ return 0;
+ }
+#endif
+ /*
+ * We're not using PF_PACKET sockets, so we can't determine
+ * the direction of the packet.
+ */
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Setting direction is not supported on SOCK_PACKET sockets");
+ return -1;
+}
+
+static int
+is_wifi(int sock_fd
+#ifndef IW_MODE_MONITOR
+_U_
+#endif
+, const char *device)
+{
+ char *pathstr;
+ struct stat statb;
+#ifdef IW_MODE_MONITOR
+ char errbuf[PCAP_ERRBUF_SIZE];
+#endif
+
+ /*
+ * See if there's a sysfs wireless directory for it.
+ * If so, it's a wireless interface.
+ */
+ if (asprintf(&pathstr, "/sys/class/net/%s/wireless", device) == -1) {
+ /*
+ * Just give up here.
+ */
+ return 0;
+ }
+ if (stat(pathstr, &statb) == 0) {
+ free(pathstr);
+ return 1;
+ }
+ free(pathstr);
+
+#ifdef IW_MODE_MONITOR
+ /*
+ * OK, maybe it's not wireless, or maybe this kernel doesn't
+ * support sysfs. Try the wireless extensions.
+ */
+ if (has_wext(sock_fd, device, errbuf) == 1) {
+ /*
+ * It supports the wireless extensions, so it's a Wi-Fi
+ * device.
+ */
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Linux uses the ARP hardware type to identify the type of an
+ * interface. pcap uses the DLT_xxx constants for this. This
+ * function takes a pointer to a "pcap_t", and an ARPHRD_xxx
+ * constant, as arguments, and sets "handle->linktype" to the
+ * appropriate DLT_XXX constant and sets "handle->offset" to
+ * the appropriate value (to make "handle->offset" plus link-layer
+ * header length be a multiple of 4, so that the link-layer payload
+ * will be aligned on a 4-byte boundary when capturing packets).
+ * (If the offset isn't set here, it'll be 0; add code as appropriate
+ * for cases where it shouldn't be 0.)
+ *
+ * If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture
+ * in cooked mode; otherwise, we can't use cooked mode, so we have
+ * to pick some type that works in raw mode, or fail.
+ *
+ * Sets the link type to -1 if unable to map the type.
+ */
+static void map_arphrd_to_dlt(pcap_t *handle, int sock_fd, int arptype,
+ const char *device, int cooked_ok)
+{
+ static const char cdma_rmnet[] = "cdma_rmnet";
+
+ switch (arptype) {
+
+ case ARPHRD_ETHER:
+ /*
+ * For various annoying reasons having to do with DHCP
+ * software, some versions of Android give the mobile-
+ * phone-network interface an ARPHRD_ value of
+ * ARPHRD_ETHER, even though the packets supplied by
+ * that interface have no link-layer header, and begin
+ * with an IP header, so that the ARPHRD_ value should
+ * be ARPHRD_NONE.
+ *
+ * Detect those devices by checking the device name, and
+ * use DLT_RAW for them.
+ */
+ if (strncmp(device, cdma_rmnet, sizeof cdma_rmnet - 1) == 0) {
+ handle->linktype = DLT_RAW;
+ return;
+ }
+
+ /*
+ * Is this a real Ethernet device? If so, give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ *
+ * XXX - are there any other sorts of "fake Ethernet" that
+ * have ARPHRD_ETHER but that shouldn't offer DLT_DOCSIS as
+ * a Cisco CMTS won't put traffic onto it or get traffic
+ * bridged onto it? ISDN is handled in "activate_new()",
+ * as we fall back on cooked mode there, and we use
+ * is_wifi() to check for 802.11 devices; are there any
+ * others?
+ */
+ if (!is_wifi(sock_fd, device)) {
+ /*
+ * It's not a Wi-Fi device; offer DOCSIS.
+ */
+ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (handle->dlt_list != NULL) {
+ handle->dlt_list[0] = DLT_EN10MB;
+ handle->dlt_list[1] = DLT_DOCSIS;
+ handle->dlt_count = 2;
+ }
+ }
+ /* FALLTHROUGH */
+
+ case ARPHRD_METRICOM:
+ case ARPHRD_LOOPBACK:
+ handle->linktype = DLT_EN10MB;
+ handle->offset = 2;
+ break;
+
+ case ARPHRD_EETHER:
+ handle->linktype = DLT_EN3MB;
+ break;
+
+ case ARPHRD_AX25:
+ handle->linktype = DLT_AX25_KISS;
+ break;
+
+ case ARPHRD_PRONET:
+ handle->linktype = DLT_PRONET;
+ break;
+
+ case ARPHRD_CHAOS:
+ handle->linktype = DLT_CHAOS;
+ break;
+#ifndef ARPHRD_CAN
+#define ARPHRD_CAN 280
+#endif
+ case ARPHRD_CAN:
+ /*
+ * Map this to DLT_LINUX_SLL; that way, CAN frames will
+ * have ETH_P_CAN/LINUX_SLL_P_CAN as the protocol and
+ * CAN FD frames will have ETH_P_CANFD/LINUX_SLL_P_CANFD
+ * as the protocol, so they can be distinguished by the
+ * protocol in the SLL header.
+ */
+ handle->linktype = DLT_LINUX_SLL;
+ break;
+
+#ifndef ARPHRD_IEEE802_TR
+#define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */
+#endif
+ case ARPHRD_IEEE802_TR:
+ case ARPHRD_IEEE802:
+ handle->linktype = DLT_IEEE802;
+ handle->offset = 2;
+ break;
+
+ case ARPHRD_ARCNET:
+ handle->linktype = DLT_ARCNET_LINUX;
+ break;
+
+#ifndef ARPHRD_FDDI /* From Linux 2.2.13 */
+#define ARPHRD_FDDI 774
+#endif
+ case ARPHRD_FDDI:
+ handle->linktype = DLT_FDDI;
+ handle->offset = 3;
+ break;
+
+#ifndef ARPHRD_ATM /* FIXME: How to #include this? */
+#define ARPHRD_ATM 19
+#endif
+ case ARPHRD_ATM:
+ /*
+ * The Classical IP implementation in ATM for Linux
+ * supports both what RFC 1483 calls "LLC Encapsulation",
+ * in which each packet has an LLC header, possibly
+ * with a SNAP header as well, prepended to it, and
+ * what RFC 1483 calls "VC Based Multiplexing", in which
+ * different virtual circuits carry different network
+ * layer protocols, and no header is prepended to packets.
+ *
+ * They both have an ARPHRD_ type of ARPHRD_ATM, so
+ * you can't use the ARPHRD_ type to find out whether
+ * captured packets will have an LLC header, and,
+ * while there's a socket ioctl to *set* the encapsulation
+ * type, there's no ioctl to *get* the encapsulation type.
+ *
+ * This means that
+ *
+ * programs that dissect Linux Classical IP frames
+ * would have to check for an LLC header and,
+ * depending on whether they see one or not, dissect
+ * the frame as LLC-encapsulated or as raw IP (I
+ * don't know whether there's any traffic other than
+ * IP that would show up on the socket, or whether
+ * there's any support for IPv6 in the Linux
+ * Classical IP code);
+ *
+ * filter expressions would have to compile into
+ * code that checks for an LLC header and does
+ * the right thing.
+ *
+ * Both of those are a nuisance - and, at least on systems
+ * that support PF_PACKET sockets, we don't have to put
+ * up with those nuisances; instead, we can just capture
+ * in cooked mode. That's what we'll do, if we can.
+ * Otherwise, we'll just fail.
+ */
+ if (cooked_ok)
+ handle->linktype = DLT_LINUX_SLL;
+ else
+ handle->linktype = -1;
+ break;
+
+#ifndef ARPHRD_IEEE80211 /* From Linux 2.4.6 */
+#define ARPHRD_IEEE80211 801
+#endif
+ case ARPHRD_IEEE80211:
+ handle->linktype = DLT_IEEE802_11;
+ break;
+
+#ifndef ARPHRD_IEEE80211_PRISM /* From Linux 2.4.18 */
+#define ARPHRD_IEEE80211_PRISM 802
+#endif
+ case ARPHRD_IEEE80211_PRISM:
+ handle->linktype = DLT_PRISM_HEADER;
+ break;
+
+#ifndef ARPHRD_IEEE80211_RADIOTAP /* new */
+#define ARPHRD_IEEE80211_RADIOTAP 803
+#endif
+ case ARPHRD_IEEE80211_RADIOTAP:
+ handle->linktype = DLT_IEEE802_11_RADIO;
+ break;
+
+ case ARPHRD_PPP:
+ /*
+ * Some PPP code in the kernel supplies no link-layer
+ * header whatsoever to PF_PACKET sockets; other PPP
+ * code supplies PPP link-layer headers ("syncppp.c");
+ * some PPP code might supply random link-layer
+ * headers (PPP over ISDN - there's code in Ethereal,
+ * for example, to cope with PPP-over-ISDN captures
+ * with which the Ethereal developers have had to cope,
+ * heuristically trying to determine which of the
+ * oddball link-layer headers particular packets have).
+ *
+ * As such, we just punt, and run all PPP interfaces
+ * in cooked mode, if we can; otherwise, we just treat
+ * it as DLT_RAW, for now - if somebody needs to capture,
+ * on a 2.0[.x] kernel, on PPP devices that supply a
+ * link-layer header, they'll have to add code here to
+ * map to the appropriate DLT_ type (possibly adding a
+ * new DLT_ type, if necessary).
+ */
+ if (cooked_ok)
+ handle->linktype = DLT_LINUX_SLL;
+ else {
+ /*
+ * XXX - handle ISDN types here? We can't fall
+ * back on cooked sockets, so we'd have to
+ * figure out from the device name what type of
+ * link-layer encapsulation it's using, and map
+ * that to an appropriate DLT_ value, meaning
+ * we'd map "isdnN" devices to DLT_RAW (they
+ * supply raw IP packets with no link-layer
+ * header) and "isdY" devices to a new DLT_I4L_IP
+ * type that has only an Ethernet packet type as
+ * a link-layer header.
+ *
+ * But sometimes we seem to get random crap
+ * in the link-layer header when capturing on
+ * ISDN devices....
+ */
+ handle->linktype = DLT_RAW;
+ }
+ break;
+
+#ifndef ARPHRD_CISCO
+#define ARPHRD_CISCO 513 /* previously ARPHRD_HDLC */
+#endif
+ case ARPHRD_CISCO:
+ handle->linktype = DLT_C_HDLC;
+ break;
+
+ /* Not sure if this is correct for all tunnels, but it
+ * works for CIPE */
+ case ARPHRD_TUNNEL:
+#ifndef ARPHRD_SIT
+#define ARPHRD_SIT 776 /* From Linux 2.2.13 */
+#endif
+ case ARPHRD_SIT:
+ case ARPHRD_CSLIP:
+ case ARPHRD_SLIP6:
+ case ARPHRD_CSLIP6:
+ case ARPHRD_ADAPT:
+ case ARPHRD_SLIP:
+#ifndef ARPHRD_RAWHDLC
+#define ARPHRD_RAWHDLC 518
+#endif
+ case ARPHRD_RAWHDLC:
+#ifndef ARPHRD_DLCI
+#define ARPHRD_DLCI 15
+#endif
+ case ARPHRD_DLCI:
+ /*
+ * XXX - should some of those be mapped to DLT_LINUX_SLL
+ * instead? Should we just map all of them to DLT_LINUX_SLL?
+ */
+ handle->linktype = DLT_RAW;
+ break;
+
+#ifndef ARPHRD_FRAD
+#define ARPHRD_FRAD 770
+#endif
+ case ARPHRD_FRAD:
+ handle->linktype = DLT_FRELAY;
+ break;
+
+ case ARPHRD_LOCALTLK:
+ handle->linktype = DLT_LTALK;
+ break;
+
+ case 18:
+ /*
+ * RFC 4338 defines an encapsulation for IP and ARP
+ * packets that's compatible with the RFC 2625
+ * encapsulation, but that uses a different ARP
+ * hardware type and hardware addresses. That
+ * ARP hardware type is 18; Linux doesn't define
+ * any ARPHRD_ value as 18, but if it ever officially
+ * supports RFC 4338-style IP-over-FC, it should define
+ * one.
+ *
+ * For now, we map it to DLT_IP_OVER_FC, in the hopes
+ * that this will encourage its use in the future,
+ * should Linux ever officially support RFC 4338-style
+ * IP-over-FC.
+ */
+ handle->linktype = DLT_IP_OVER_FC;
+ break;
+
+#ifndef ARPHRD_FCPP
+#define ARPHRD_FCPP 784
+#endif
+ case ARPHRD_FCPP:
+#ifndef ARPHRD_FCAL
+#define ARPHRD_FCAL 785
+#endif
+ case ARPHRD_FCAL:
+#ifndef ARPHRD_FCPL
+#define ARPHRD_FCPL 786
+#endif
+ case ARPHRD_FCPL:
+#ifndef ARPHRD_FCFABRIC
+#define ARPHRD_FCFABRIC 787
+#endif
+ case ARPHRD_FCFABRIC:
+ /*
+ * Back in 2002, Donald Lee at Cray wanted a DLT_ for
+ * IP-over-FC:
+ *
+ * http://www.mail-archive.com/tcpdump-workers@sandelman.ottawa.on.ca/msg01043.html
+ *
+ * and one was assigned.
+ *
+ * In a later private discussion (spun off from a message
+ * on the ethereal-users list) on how to get that DLT_
+ * value in libpcap on Linux, I ended up deciding that
+ * the best thing to do would be to have him tweak the
+ * driver to set the ARPHRD_ value to some ARPHRD_FCxx
+ * type, and map all those types to DLT_IP_OVER_FC:
+ *
+ * I've checked into the libpcap and tcpdump CVS tree
+ * support for DLT_IP_OVER_FC. In order to use that,
+ * you'd have to modify your modified driver to return
+ * one of the ARPHRD_FCxxx types, in "fcLINUXfcp.c" -
+ * change it to set "dev->type" to ARPHRD_FCFABRIC, for
+ * example (the exact value doesn't matter, it can be
+ * any of ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, or
+ * ARPHRD_FCFABRIC).
+ *
+ * 11 years later, Christian Svensson wanted to map
+ * various ARPHRD_ values to DLT_FC_2 and
+ * DLT_FC_2_WITH_FRAME_DELIMS for raw Fibre Channel
+ * frames:
+ *
+ * https://github.com/mcr/libpcap/pull/29
+ *
+ * There doesn't seem to be any network drivers that uses
+ * any of the ARPHRD_FC* values for IP-over-FC, and
+ * it's not exactly clear what the "Dummy types for non
+ * ARP hardware" are supposed to mean (link-layer
+ * header type? Physical network type?), so it's
+ * not exactly clear why the ARPHRD_FC* types exist
+ * in the first place.
+ *
+ * For now, we map them to DLT_FC_2, and provide an
+ * option of DLT_FC_2_WITH_FRAME_DELIMS, as well as
+ * DLT_IP_OVER_FC just in case there's some old
+ * driver out there that uses one of those types for
+ * IP-over-FC on which somebody wants to capture
+ * packets.
+ */
+ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 3);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (handle->dlt_list != NULL) {
+ handle->dlt_list[0] = DLT_FC_2;
+ handle->dlt_list[1] = DLT_FC_2_WITH_FRAME_DELIMS;
+ handle->dlt_list[2] = DLT_IP_OVER_FC;
+ handle->dlt_count = 3;
+ }
+ handle->linktype = DLT_FC_2;
+ break;
+
+#ifndef ARPHRD_IRDA
+#define ARPHRD_IRDA 783
+#endif
+ case ARPHRD_IRDA:
+ /* Don't expect IP packet out of this interfaces... */
+ handle->linktype = DLT_LINUX_IRDA;
+ /* We need to save packet direction for IrDA decoding,
+ * so let's use "Linux-cooked" mode. Jean II
+ *
+ * XXX - this is handled in activate_new(). */
+ /* handlep->cooked = 1; */
+ break;
+
+ /* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation
+ * is needed, please report it to <daniele@orlandi.com> */
+#ifndef ARPHRD_LAPD
+#define ARPHRD_LAPD 8445
+#endif
+ case ARPHRD_LAPD:
+ /* Don't expect IP packet out of this interfaces... */
+ handle->linktype = DLT_LINUX_LAPD;
+ break;
+
+#ifndef ARPHRD_NONE
+#define ARPHRD_NONE 0xFFFE
+#endif
+ case ARPHRD_NONE:
+ /*
+ * No link-layer header; packets are just IP
+ * packets, so use DLT_RAW.
+ */
+ handle->linktype = DLT_RAW;
+ break;
+
+#ifndef ARPHRD_IEEE802154
+#define ARPHRD_IEEE802154 804
+#endif
+ case ARPHRD_IEEE802154:
+ handle->linktype = DLT_IEEE802_15_4_NOFCS;
+ break;
+
+#ifndef ARPHRD_NETLINK
+#define ARPHRD_NETLINK 824
+#endif
+ case ARPHRD_NETLINK:
+ handle->linktype = DLT_NETLINK;
+ /*
+ * We need to use cooked mode, so that in sll_protocol we
+ * pick up the netlink protocol type such as NETLINK_ROUTE,
+ * NETLINK_GENERIC, NETLINK_FIB_LOOKUP, etc.
+ *
+ * XXX - this is handled in activate_new().
+ */
+ /* handlep->cooked = 1; */
+ break;
+
+#ifndef ARPHRD_VSOCKMON
+#define ARPHRD_VSOCKMON 826
+#endif
+ case ARPHRD_VSOCKMON:
+ handle->linktype = DLT_VSOCK;
+ break;
+
+ default:
+ handle->linktype = -1;
+ break;
+ }
+}
+
+/* ===== Functions to interface to the newer kernels ================== */
+
+#ifdef PACKET_RESERVE
+static void
+set_dlt_list_cooked(pcap_t *handle, int sock_fd)
+{
+ socklen_t len;
+ unsigned int tp_reserve;
+
+ /*
+ * If we can't do PACKET_RESERVE, we can't reserve extra space
+ * for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2.
+ */
+ len = sizeof(tp_reserve);
+ if (getsockopt(sock_fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve,
+ &len) == 0) {
+ /*
+ * Yes, we can do DLL_LINUX_SLL2.
+ */
+ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (handle->dlt_list != NULL) {
+ handle->dlt_list[0] = DLT_LINUX_SLL;
+ handle->dlt_list[1] = DLT_LINUX_SLL2;
+ handle->dlt_count = 2;
+ }
+ }
+}
+#else
+/*
+ * The build environment doesn't define PACKET_RESERVE, so we can't reserve
+ * extra space for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2.
+ */
+static void
+set_dlt_list_cooked(pcap_t *handle _U_, int sock_fd _U_)
+{
+}
+#endif
+
+/*
+ * Try to open a packet socket using the new kernel PF_PACKET interface.
+ * Returns 1 on success, 0 on an error that means the new interface isn't
+ * present (so the old SOCK_PACKET interface should be tried), and a
+ * PCAP_ERROR_ value on an error that means that the old mechanism won't
+ * work either (so it shouldn't be tried).
+ */
+static int
+activate_new(pcap_t *handle)
+{
+#ifdef HAVE_PF_PACKET_SOCKETS
+ struct pcap_linux *handlep = handle->priv;
+ const char *device = handle->opt.device;
+ int is_any_device = (strcmp(device, "any") == 0);
+ int protocol = pcap_protocol(handle);
+ int sock_fd = -1, arptype, ret;
+#ifdef HAVE_PACKET_AUXDATA
+ int val;
+#endif
+ int err = 0;
+ struct packet_mreq mr;
+#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT)
+ int bpf_extensions;
+ socklen_t len = sizeof(bpf_extensions);
+#endif
+
+ /*
+ * Open a socket with protocol family packet. If the
+ * "any" device was specified, we open a SOCK_DGRAM
+ * socket for the cooked interface, otherwise we first
+ * try a SOCK_RAW socket for the raw interface.
+ */
+ sock_fd = is_any_device ?
+ socket(PF_PACKET, SOCK_DGRAM, protocol) :
+ socket(PF_PACKET, SOCK_RAW, protocol);
+
+ if (sock_fd == -1) {
+ if (errno == EINVAL || errno == EAFNOSUPPORT) {
+ /*
+ * We don't support PF_PACKET/SOCK_whatever
+ * sockets; try the old mechanism.
+ */
+ return 0;
+ }
+ if (errno == EPERM || errno == EACCES) {
+ /*
+ * You don't have permission to open the
+ * socket.
+ */
+ ret = PCAP_ERROR_PERM_DENIED;
+ } else {
+ /*
+ * Other error.
+ */
+ ret = PCAP_ERROR;
+ }
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ return ret;
+ }
+
+ /* It seems the kernel supports the new interface. */
+ handlep->sock_packet = 0;
+
+ /*
+ * Get the interface index of the loopback device.
+ * If the attempt fails, don't fail, just set the
+ * "handlep->lo_ifindex" to -1.
+ *
+ * XXX - can there be more than one device that loops
+ * packets back, i.e. devices other than "lo"? If so,
+ * we'd need to find them all, and have an array of
+ * indices for them, and check all of them in
+ * "pcap_read_packet()".
+ */
+ handlep->lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf);
+
+ /*
+ * Default value for offset to align link-layer payload
+ * on a 4-byte boundary.
+ */
+ handle->offset = 0;
+
+ /*
+ * What kind of frames do we have to deal with? Fall back
+ * to cooked mode if we have an unknown interface type
+ * or a type we know doesn't work well in raw mode.
+ */
+ if (!is_any_device) {
+ /* Assume for now we don't need cooked mode. */
+ handlep->cooked = 0;
+
+ if (handle->opt.rfmon) {
+ /*
+ * We were asked to turn on monitor mode.
+ * Do so before we get the link-layer type,
+ * because entering monitor mode could change
+ * the link-layer type.
+ */
+ err = enter_rfmon_mode(handle, sock_fd, device);
+ if (err < 0) {
+ /* Hard failure */
+ close(sock_fd);
+ return err;
+ }
+ if (err == 0) {
+ /*
+ * Nothing worked for turning monitor mode
+ * on.
+ */
+ close(sock_fd);
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * Either monitor mode has been turned on for
+ * the device, or we've been given a different
+ * device to open for monitor mode. If we've
+ * been given a different device, use it.
+ */
+ if (handlep->mondevice != NULL)
+ device = handlep->mondevice;
+ }
+ arptype = iface_get_arptype(sock_fd, device, handle->errbuf);
+ if (arptype < 0) {
+ close(sock_fd);
+ return arptype;
+ }
+ map_arphrd_to_dlt(handle, sock_fd, arptype, device, 1);
+ if (handle->linktype == -1 ||
+ handle->linktype == DLT_LINUX_SLL ||
+ handle->linktype == DLT_LINUX_IRDA ||
+ handle->linktype == DLT_LINUX_LAPD ||
+ handle->linktype == DLT_NETLINK ||
+ (handle->linktype == DLT_EN10MB &&
+ (strncmp("isdn", device, 4) == 0 ||
+ strncmp("isdY", device, 4) == 0))) {
+ /*
+ * Unknown interface type (-1), or a
+ * device we explicitly chose to run
+ * in cooked mode (e.g., PPP devices),
+ * or an ISDN device (whose link-layer
+ * type we can only determine by using
+ * APIs that may be different on different
+ * kernels) - reopen in cooked mode.
+ */
+ if (close(sock_fd) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "close");
+ return PCAP_ERROR;
+ }
+ sock_fd = socket(PF_PACKET, SOCK_DGRAM, protocol);
+ if (sock_fd == -1) {
+ if (errno == EPERM || errno == EACCES) {
+ /*
+ * You don't have permission to
+ * open the socket.
+ */
+ ret = PCAP_ERROR_PERM_DENIED;
+ } else {
+ /*
+ * Other error.
+ */
+ ret = PCAP_ERROR;
+ }
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "socket");
+ return ret;
+ }
+ handlep->cooked = 1;
+
+ /*
+ * Get rid of any link-layer type list
+ * we allocated - this only supports cooked
+ * capture.
+ */
+ if (handle->dlt_list != NULL) {
+ free(handle->dlt_list);
+ handle->dlt_list = NULL;
+ handle->dlt_count = 0;
+ set_dlt_list_cooked(handle, sock_fd);
+ }
+
+ if (handle->linktype == -1) {
+ /*
+ * Warn that we're falling back on
+ * cooked mode; we may want to
+ * update "map_arphrd_to_dlt()"
+ * to handle the new type.
+ */
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "arptype %d not "
+ "supported by libpcap - "
+ "falling back to cooked "
+ "socket",
+ arptype);
+ }
+
+ /*
+ * IrDA capture is not a real "cooked" capture,
+ * it's IrLAP frames, not IP packets. The
+ * same applies to LAPD capture.
+ */
+ if (handle->linktype != DLT_LINUX_IRDA &&
+ handle->linktype != DLT_LINUX_LAPD &&
+ handle->linktype != DLT_NETLINK)
+ handle->linktype = DLT_LINUX_SLL;
+ }
+
+ handlep->ifindex = iface_get_id(sock_fd, device,
+ handle->errbuf);
+ if (handlep->ifindex == -1) {
+ close(sock_fd);
+ return PCAP_ERROR;
+ }
+
+ if ((err = iface_bind(sock_fd, handlep->ifindex,
+ handle->errbuf, protocol)) != 1) {
+ close(sock_fd);
+ if (err < 0)
+ return err;
+ else
+ return 0; /* try old mechanism */
+ }
+ } else {
+ /*
+ * The "any" device.
+ */
+ if (handle->opt.rfmon) {
+ /*
+ * It doesn't support monitor mode.
+ */
+ close(sock_fd);
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * It uses cooked mode.
+ */
+ handlep->cooked = 1;
+ handle->linktype = DLT_LINUX_SLL;
+ handle->dlt_list = NULL;
+ handle->dlt_count = 0;
+ set_dlt_list_cooked(handle, sock_fd);
+
+ /*
+ * We're not bound to a device.
+ * For now, we're using this as an indication
+ * that we can't transmit; stop doing that only
+ * if we figure out how to transmit in cooked
+ * mode.
+ */
+ handlep->ifindex = -1;
+ }
+
+ /*
+ * Select promiscuous mode on if "promisc" is set.
+ *
+ * Do not turn allmulti mode on if we don't select
+ * promiscuous mode - on some devices (e.g., Orinoco
+ * wireless interfaces), allmulti mode isn't supported
+ * and the driver implements it by turning promiscuous
+ * mode on, and that screws up the operation of the
+ * card as a normal networking interface, and on no
+ * other platform I know of does starting a non-
+ * promiscuous capture affect which multicast packets
+ * are received by the interface.
+ */
+
+ /*
+ * Hmm, how can we set promiscuous mode on all interfaces?
+ * I am not sure if that is possible at all. For now, we
+ * silently ignore attempts to turn promiscuous mode on
+ * for the "any" device (so you don't have to explicitly
+ * disable it in programs such as tcpdump).
+ */
+
+ if (!is_any_device && handle->opt.promisc) {
+ memset(&mr, 0, sizeof(mr));
+ mr.mr_ifindex = handlep->ifindex;
+ mr.mr_type = PACKET_MR_PROMISC;
+ if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
+ &mr, sizeof(mr)) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_ADD_MEMBERSHIP)");
+ close(sock_fd);
+ return PCAP_ERROR;
+ }
+ }
+
+ /* Enable auxillary data if supported and reserve room for
+ * reconstructing VLAN headers. */
+#ifdef HAVE_PACKET_AUXDATA
+ val = 1;
+ if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
+ sizeof(val)) == -1 && errno != ENOPROTOOPT) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "setsockopt (PACKET_AUXDATA)");
+ close(sock_fd);
+ return PCAP_ERROR;
+ }
+ handle->offset += VLAN_TAG_LEN;
+#endif /* HAVE_PACKET_AUXDATA */
+
+ /*
+ * This is a 2.2[.x] or later kernel (we know that
+ * because we're not using a SOCK_PACKET socket -
+ * PF_PACKET is supported only in 2.2 and later
+ * kernels).
+ *
+ * We can safely pass "recvfrom()" a byte count
+ * based on the snapshot length.
+ *
+ * If we're in cooked mode, make the snapshot length
+ * large enough to hold a "cooked mode" header plus
+ * 1 byte of packet data (so we don't pass a byte
+ * count of 0 to "recvfrom()").
+ * XXX - we don't know whether this will be DLT_LINUX_SLL
+ * or DLT_LINUX_SLL2, so make sure it's big enough for
+ * a DLT_LINUX_SLL2 "cooked mode" header; a snapshot length
+ * that small is silly anyway.
+ */
+ if (handlep->cooked) {
+ if (handle->snapshot < SLL2_HDR_LEN + 1)
+ handle->snapshot = SLL2_HDR_LEN + 1;
+ }
+ handle->bufsize = handle->snapshot;
+
+ /*
+ * Set the offset at which to insert VLAN tags.
+ * That should be the offset of the type field.
+ */
+ switch (handle->linktype) {
+
+ case DLT_EN10MB:
+ /*
+ * The type field is after the destination and source
+ * MAC address.
+ */
+ handlep->vlan_offset = 2 * ETH_ALEN;
+ break;
+
+ case DLT_LINUX_SLL:
+ /*
+ * The type field is in the last 2 bytes of the
+ * DLT_LINUX_SLL header.
+ */
+ handlep->vlan_offset = SLL_HDR_LEN - 2;
+ break;
+
+ default:
+ handlep->vlan_offset = -1; /* unknown */
+ break;
+ }
+
+#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
+ if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
+ int nsec_tstamps = 1;
+
+ if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPNS, &nsec_tstamps, sizeof(nsec_tstamps)) < 0) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
+ close(sock_fd);
+ return PCAP_ERROR;
+ }
+ }
+#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
+
+ /*
+ * We've succeeded. Save the socket FD in the pcap structure.
+ */
+ handle->fd = sock_fd;
+
+#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT)
+ /*
+ * Can we generate special code for VLAN checks?
+ * (XXX - what if we need the special code but it's not supported
+ * by the OS? Is that possible?)
+ */
+ if (getsockopt(sock_fd, SOL_SOCKET, SO_BPF_EXTENSIONS,
+ &bpf_extensions, &len) == 0) {
+ if (bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT) {
+ /*
+ * Yes, we can. Request that we do so.
+ */
+ handle->bpf_codegen_flags |= BPF_SPECIAL_VLAN_HANDLING;
+ }
+ }
+#endif /* defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT) */
+
+ return 1;
+#else /* HAVE_PF_PACKET_SOCKETS */
+ pcap_strlcpy(ebuf,
+ "New packet capturing interface not supported by build "
+ "environment", PCAP_ERRBUF_SIZE);
+ return 0;
+#endif /* HAVE_PF_PACKET_SOCKETS */
+}
+
+#ifdef HAVE_PACKET_RING
+/*
+ * Attempt to activate with memory-mapped access.
+ *
+ * On success, returns 1, and sets *status to 0 if there are no warnings
+ * or to a PCAP_WARNING_ code if there is a warning.
+ *
+ * On failure due to lack of support for memory-mapped capture, returns
+ * 0.
+ *
+ * On error, returns -1, and sets *status to the appropriate error code;
+ * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
+ */
+static int
+activate_mmap(pcap_t *handle, int *status)
+{
+ struct pcap_linux *handlep = handle->priv;
+ int ret;
+
+ /*
+ * Attempt to allocate a buffer to hold the contents of one
+ * packet, for use by the oneshot callback.
+ */
+ handlep->oneshot_buffer = malloc(handle->snapshot);
+ if (handlep->oneshot_buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't allocate oneshot buffer");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+
+ if (handle->opt.buffer_size == 0) {
+ /* by default request 2M for the ring buffer */
+ handle->opt.buffer_size = 2*1024*1024;
+ }
+ ret = prepare_tpacket_socket(handle);
+ if (ret == -1) {
+ free(handlep->oneshot_buffer);
+ *status = PCAP_ERROR;
+ return ret;
+ }
+ ret = create_ring(handle, status);
+ if (ret == 0) {
+ /*
+ * We don't support memory-mapped capture; our caller
+ * will fall back on reading from the socket.
+ */
+ free(handlep->oneshot_buffer);
+ return 0;
+ }
+ if (ret == -1) {
+ /*
+ * Error attempting to enable memory-mapped capture;
+ * fail. create_ring() has set *status.
+ */
+ free(handlep->oneshot_buffer);
+ return -1;
+ }
+
+ /*
+ * Success. *status has been set either to 0 if there are no
+ * warnings or to a PCAP_WARNING_ value if there is a warning.
+ *
+ * Override some defaults and inherit the other fields from
+ * activate_new.
+ * handle->offset is used to get the current position into the rx ring.
+ * handle->cc is used to store the ring size.
+ */
+
+ switch (handlep->tp_version) {
+ case TPACKET_V1:
+ handle->read_op = pcap_read_linux_mmap_v1;
+ break;
+ case TPACKET_V1_64:
+ handle->read_op = pcap_read_linux_mmap_v1_64;
+ break;
+#ifdef HAVE_TPACKET2
+ case TPACKET_V2:
+ handle->read_op = pcap_read_linux_mmap_v2;
+ break;
+#endif
+#ifdef HAVE_TPACKET3
+ case TPACKET_V3:
+ handle->read_op = pcap_read_linux_mmap_v3;
+ break;
+#endif
+ }
+ handle->cleanup_op = pcap_cleanup_linux_mmap;
+ handle->setfilter_op = pcap_setfilter_linux_mmap;
+ handle->setnonblock_op = pcap_setnonblock_mmap;
+ handle->getnonblock_op = pcap_getnonblock_mmap;
+ handle->oneshot_callback = pcap_oneshot_mmap;
+ handle->selectable_fd = handle->fd;
+ return 1;
+}
+#else /* HAVE_PACKET_RING */
+static int
+activate_mmap(pcap_t *handle _U_, int *status _U_)
+{
+ return 0;
+}
+#endif /* HAVE_PACKET_RING */
+
+#ifdef HAVE_PACKET_RING
+
+#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
+/*
+ * Attempt to set the socket to the specified version of the memory-mapped
+ * header.
+ *
+ * Return 0 if we succeed; return 1 if we fail because that version isn't
+ * supported; return -1 on any other error, and set handle->errbuf.
+ */
+static int
+init_tpacket(pcap_t *handle, int version, const char *version_str)
+{
+ struct pcap_linux *handlep = handle->priv;
+ int val = version;
+ socklen_t len = sizeof(val);
+
+ /*
+ * Probe whether kernel supports the specified TPACKET version;
+ * this also gets the length of the header for that version.
+ *
+ * This socket option was introduced in 2.6.27, which was
+ * also the first release with TPACKET_V2 support.
+ */
+ if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
+ if (errno == ENOPROTOOPT || errno == EINVAL) {
+ /*
+ * ENOPROTOOPT means the kernel is too old to
+ * support PACKET_HDRLEN at all, which means
+ * it either doesn't support TPACKET at all
+ * or supports only TPACKET_V1.
+ */
+ return 1; /* no */
+ }
+
+ /* Failed to even find out; this is a fatal error. */
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't get %s header len on packet socket",
+ version_str);
+ return -1;
+ }
+ handlep->tp_hdrlen = val;
+
+ val = version;
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
+ sizeof(val)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't activate %s on packet socket", version_str);
+ return -1;
+ }
+ handlep->tp_version = version;
+
+ /*
+ * Reserve space for VLAN tag reconstruction.
+ * This option was also introduced in 2.6.27.
+ */
+ val = VLAN_TAG_LEN;
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
+ sizeof(val)) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't set up reserve on packet socket");
+ return -1;
+ }
+
+ return 0;
+}
+#endif /* defined HAVE_TPACKET2 || defined HAVE_TPACKET3 */
+
+/*
+ * If the instruction set for which we're compiling has both 32-bit
+ * and 64-bit versions, and Linux support for the 64-bit version
+ * predates TPACKET_V2, define ISA_64_BIT as the .machine value
+ * you get from uname() for the 64-bit version. Otherwise, leave
+ * it undefined. (This includes ARM, which has a 64-bit version,
+ * but Linux support for it appeared well after TPACKET_V2 support
+ * did, so there should never be a case where 32-bit ARM code is
+ * running o a 64-bit kernel that only supports TPACKET_V1.)
+ *
+ * If we've omitted your favorite such architecture, please contribute
+ * a patch. (No patch is needed for architectures that are 32-bit-only
+ * or for which Linux has no support for 32-bit userland - or for which,
+ * as noted, 64-bit support appeared in Linux after TPACKET_V2 support
+ * did.)
+ */
+#if defined(__i386__)
+#define ISA_64_BIT "x86_64"
+#elif defined(__ppc__)
+#define ISA_64_BIT "ppc64"
+#elif defined(__sparc__)
+#define ISA_64_BIT "sparc64"
+#elif defined(__s390__)
+#define ISA_64_BIT "s390x"
+#elif defined(__mips__)
+#define ISA_64_BIT "mips64"
+#elif defined(__hppa__)
+#define ISA_64_BIT "parisc64"
+#endif
+
+/*
+ * Attempt to set the socket to version 3 of the memory-mapped header and,
+ * if that fails because version 3 isn't supported, attempt to fall
+ * back to version 2. If version 2 isn't supported, just leave it at
+ * version 1.
+ *
+ * Return 1 if we succeed or if we fail because neither version 2 nor 3 is
+ * supported; return -1 on any other error, and set handle->errbuf.
+ */
+static int
+prepare_tpacket_socket(pcap_t *handle)
+{
+ struct pcap_linux *handlep = handle->priv;
+#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
+ int ret;
+#endif
+
+#ifdef HAVE_TPACKET3
+ /*
+ * Try setting the version to TPACKET_V3.
+ *
+ * The only mode in which buffering is done on PF_PACKET
+ * sockets, so that packets might not be delivered
+ * immediately, is TPACKET_V3 mode.
+ *
+ * The buffering cannot be disabled in that mode, so
+ * if the user has requested immediate mode, we don't
+ * use TPACKET_V3.
+ */
+ if (!handle->opt.immediate) {
+ ret = init_tpacket(handle, TPACKET_V3, "TPACKET_V3");
+ if (ret == 0) {
+ /*
+ * Success.
+ */
+ return 1;
+ }
+ if (ret == -1) {
+ /*
+ * We failed for some reason other than "the
+ * kernel doesn't support TPACKET_V3".
+ */
+ return -1;
+ }
+ }
+#endif /* HAVE_TPACKET3 */
+
+#ifdef HAVE_TPACKET2
+ /*
+ * Try setting the version to TPACKET_V2.
+ */
+ ret = init_tpacket(handle, TPACKET_V2, "TPACKET_V2");
+ if (ret == 0) {
+ /*
+ * Success.
+ */
+ return 1;
+ }
+ if (ret == -1) {
+ /*
+ * We failed for some reason other than "the
+ * kernel doesn't support TPACKET_V2".
+ */
+ return -1;
+ }
+#endif /* HAVE_TPACKET2 */
+
+ /*
+ * OK, we're using TPACKET_V1, as either that's all the kernel
+ * supports or it doesn't support TPACKET at all. In the latter
+ * case, create_ring() will fail, and we'll fall back on non-
+ * memory-mapped capture.
+ */
+ handlep->tp_version = TPACKET_V1;
+ handlep->tp_hdrlen = sizeof(struct tpacket_hdr);
+
+#ifdef ISA_64_BIT
+ /*
+ * 32-bit userspace + 64-bit kernel + TPACKET_V1 are not compatible with
+ * each other due to platform-dependent data type size differences.
+ *
+ * If we have a 32-bit userland and a 64-bit kernel, use an
+ * internally-defined TPACKET_V1_64, with which we use a 64-bit
+ * version of the data structures.
+ */
+ if (sizeof(long) == 4) {
+ /*
+ * This is 32-bit code.
+ */
+ struct utsname utsname;
+
+ if (uname(&utsname) == -1) {
+ /*
+ * Failed.
+ */
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "uname failed");
+ return -1;
+ }
+ if (strcmp(utsname.machine, ISA_64_BIT) == 0) {
+ /*
+ * uname() tells us the machine is 64-bit,
+ * so we presumably have a 64-bit kernel.
+ *
+ * XXX - this presumes that uname() won't lie
+ * in 32-bit code and claim that the machine
+ * has the 32-bit version of the ISA.
+ */
+ handlep->tp_version = TPACKET_V1_64;
+ handlep->tp_hdrlen = sizeof(struct tpacket_hdr_64);
+ }
+ }
+#endif
+
+ return 1;
+}
+
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
+/*
+ * Attempt to set up memory-mapped access.
+ *
+ * On success, returns 1, and sets *status to 0 if there are no warnings
+ * or to a PCAP_WARNING_ code if there is a warning.
+ *
+ * On failure due to lack of support for memory-mapped capture, returns
+ * 0.
+ *
+ * On error, returns -1, and sets *status to the appropriate error code;
+ * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
+ */
+static int
+create_ring(pcap_t *handle, int *status)
+{
+ struct pcap_linux *handlep = handle->priv;
+ unsigned i, j, frames_per_block;
+#ifdef HAVE_TPACKET3
+ /*
+ * For sockets using TPACKET_V1 or TPACKET_V2, the extra
+ * stuff at the end of a struct tpacket_req3 will be
+ * ignored, so this is OK even for those sockets.
+ */
+ struct tpacket_req3 req;
+#else
+ struct tpacket_req req;
+#endif
+ socklen_t len;
+ unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff;
+ unsigned int frame_size;
+
+ /*
+ * Start out assuming no warnings or errors.
+ */
+ *status = 0;
+
+ switch (handlep->tp_version) {
+
+ case TPACKET_V1:
+ case TPACKET_V1_64:
+#ifdef HAVE_TPACKET2
+ case TPACKET_V2:
+#endif
+ /* Note that with large snapshot length (say 256K, which is
+ * the default for recent versions of tcpdump, Wireshark,
+ * TShark, dumpcap or 64K, the value that "-s 0" has given for
+ * a long time with tcpdump), if we use the snapshot
+ * length to calculate the frame length, only a few frames
+ * will be available in the ring even with pretty
+ * large ring size (and a lot of memory will be unused).
+ *
+ * Ideally, we should choose a frame length based on the
+ * minimum of the specified snapshot length and the maximum
+ * packet size. That's not as easy as it sounds; consider,
+ * for example, an 802.11 interface in monitor mode, where
+ * the frame would include a radiotap header, where the
+ * maximum radiotap header length is device-dependent.
+ *
+ * So, for now, we just do this for Ethernet devices, where
+ * there's no metadata header, and the link-layer header is
+ * fixed length. We can get the maximum packet size by
+ * adding 18, the Ethernet header length plus the CRC length
+ * (just in case we happen to get the CRC in the packet), to
+ * the MTU of the interface; we fetch the MTU in the hopes
+ * that it reflects support for jumbo frames. (Even if the
+ * interface is just being used for passive snooping, the
+ * driver might set the size of buffers in the receive ring
+ * based on the MTU, so that the MTU limits the maximum size
+ * of packets that we can receive.)
+ *
+ * If segmentation/fragmentation or receive offload are
+ * enabled, we can get reassembled/aggregated packets larger
+ * than MTU, but bounded to 65535 plus the Ethernet overhead,
+ * due to kernel and protocol constraints */
+ frame_size = handle->snapshot;
+ if (handle->linktype == DLT_EN10MB) {
+ unsigned int max_frame_len;
+ int mtu;
+ int offload;
+
+ mtu = iface_get_mtu(handle->fd, handle->opt.device,
+ handle->errbuf);
+ if (mtu == -1) {
+ *status = PCAP_ERROR;
+ return -1;
+ }
+ offload = iface_get_offload(handle);
+ if (offload == -1) {
+ *status = PCAP_ERROR;
+ return -1;
+ }
+ if (offload)
+ max_frame_len = MAX(mtu, 65535);
+ else
+ max_frame_len = mtu;
+ max_frame_len += 18;
+
+ if (frame_size > max_frame_len)
+ frame_size = max_frame_len;
+ }
+
+ /* NOTE: calculus matching those in tpacket_rcv()
+ * in linux-2.6/net/packet/af_packet.c
+ */
+ len = sizeof(sk_type);
+ if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type,
+ &len) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "getsockopt (SO_TYPE)");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+#ifdef PACKET_RESERVE
+ len = sizeof(tp_reserve);
+ if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+ &tp_reserve, &len) < 0) {
+ if (errno != ENOPROTOOPT) {
+ /*
+ * ENOPROTOOPT means "kernel doesn't support
+ * PACKET_RESERVE", in which case we fall back
+ * as best we can.
+ */
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "getsockopt (PACKET_RESERVE)");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+ /*
+ * Older kernel, so we can't use PACKET_RESERVE;
+ * this means we can't reserver extra space
+ * for a DLT_LINUX_SLL2 header.
+ */
+ tp_reserve = 0;
+ } else {
+ /*
+ * We can reserve extra space for a DLT_LINUX_SLL2
+ * header. Do so.
+ *
+ * XXX - we assume that the kernel is still adding
+ * 16 bytes of extra space; that happens to
+ * correspond to SLL_HDR_LEN (whether intentionally
+ * or not - the kernel code has a raw "16" in
+ * the expression), so we subtract SLL_HDR_LEN
+ * from SLL2_HDR_LEN to get the additional space
+ * needed.
+ *
+ * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)?
+ */
+ tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN;
+ len = sizeof(tp_reserve);
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+ &tp_reserve, len) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "setsockopt (PACKET_RESERVE)");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+ }
+#else
+ /*
+ * Build environment for an older kernel, so we can't
+ * use PACKET_RESERVE; this means we can't reserve
+ * extra space for a DLT_LINUX_SLL2 header.
+ */
+ tp_reserve = 0;
+#endif
+ maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE;
+ /* XXX: in the kernel maclen is calculated from
+ * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len
+ * in: packet_snd() in linux-2.6/net/packet/af_packet.c
+ * then packet_alloc_skb() in linux-2.6/net/packet/af_packet.c
+ * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c
+ * but I see no way to get those sizes in userspace,
+ * like for instance with an ifreq ioctl();
+ * the best thing I've found so far is MAX_HEADER in
+ * the kernel part of linux-2.6/include/linux/netdevice.h
+ * which goes up to 128+48=176; since pcap-linux.c
+ * defines a MAX_LINKHEADER_SIZE of 256 which is
+ * greater than that, let's use it.. maybe is it even
+ * large enough to directly replace macoff..
+ */
+ tp_hdrlen = TPACKET_ALIGN(handlep->tp_hdrlen) + sizeof(struct sockaddr_ll) ;
+ netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve;
+ /* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN
+ * of netoff, which contradicts
+ * linux-2.6/Documentation/networking/packet_mmap.txt
+ * documenting that:
+ * "- Gap, chosen so that packet data (Start+tp_net)
+ * aligns to TPACKET_ALIGNMENT=16"
+ */
+ /* NOTE: in linux-2.6/include/linux/skbuff.h:
+ * "CPUs often take a performance hit
+ * when accessing unaligned memory locations"
+ */
+ macoff = netoff - maclen;
+ req.tp_frame_size = TPACKET_ALIGN(macoff + frame_size);
+ /*
+ * Round the buffer size up to a multiple of the
+ * frame size (rather than rounding down, which
+ * would give a buffer smaller than our caller asked
+ * for, and possibly give zero frames if the requested
+ * buffer size is too small for one frame).
+ */
+ req.tp_frame_nr = (handle->opt.buffer_size + req.tp_frame_size - 1)/req.tp_frame_size;
+ break;
+
+#ifdef HAVE_TPACKET3
+ case TPACKET_V3:
+ /*
+ * If we have TPACKET_V3, we have PACKET_RESERVE.
+ */
+ len = sizeof(tp_reserve);
+ if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+ &tp_reserve, &len) < 0) {
+ /*
+ * Even ENOPROTOOPT is an error - we wouldn't
+ * be here if the kernel didn't support
+ * TPACKET_V3, which means it supports
+ * PACKET_RESERVE.
+ */
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "getsockopt (PACKET_RESERVE)");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+ /*
+ * We can reserve extra space for a DLT_LINUX_SLL2
+ * header. Do so.
+ *
+ * XXX - we assume that the kernel is still adding
+ * 16 bytes of extra space; that happens to
+ * correspond to SLL_HDR_LEN (whether intentionally
+ * or not - the kernel code has a raw "16" in
+ * the expression), so we subtract SLL_HDR_LEN
+ * from SLL2_HDR_LEN to get the additional space
+ * needed.
+ *
+ * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)?
+ */
+ tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN;
+ len = sizeof(tp_reserve);
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
+ &tp_reserve, len) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "setsockopt (PACKET_RESERVE)");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+
+ /* The "frames" for this are actually buffers that
+ * contain multiple variable-sized frames.
+ *
+ * We pick a "frame" size of MAXIMUM_SNAPLEN to leave
+ * enough room for at least one reasonably-sized packet
+ * in the "frame". */
+ req.tp_frame_size = MAXIMUM_SNAPLEN;
+ /*
+ * Round the buffer size up to a multiple of the
+ * "frame" size (rather than rounding down, which
+ * would give a buffer smaller than our caller asked
+ * for, and possibly give zero "frames" if the requested
+ * buffer size is too small for one "frame").
+ */
+ req.tp_frame_nr = (handle->opt.buffer_size + req.tp_frame_size - 1)/req.tp_frame_size;
+ break;
+#endif
+ default:
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Internal error: unknown TPACKET_ value %u",
+ handlep->tp_version);
+ *status = PCAP_ERROR;
+ return -1;
+ }
+
+ /* compute the minumum block size that will handle this frame.
+ * The block has to be page size aligned.
+ * The max block size allowed by the kernel is arch-dependent and
+ * it's not explicitly checked here. */
+ req.tp_block_size = getpagesize();
+ while (req.tp_block_size < req.tp_frame_size)
+ req.tp_block_size <<= 1;
+
+ frames_per_block = req.tp_block_size/req.tp_frame_size;
+
+ /*
+ * PACKET_TIMESTAMP was added after linux/net_tstamp.h was,
+ * so we check for PACKET_TIMESTAMP. We check for
+ * linux/net_tstamp.h just in case a system somehow has
+ * PACKET_TIMESTAMP but not linux/net_tstamp.h; that might
+ * be unnecessary.
+ *
+ * SIOCSHWTSTAMP was introduced in the patch that introduced
+ * linux/net_tstamp.h, so we don't bother checking whether
+ * SIOCSHWTSTAMP is defined (if your Linux system has
+ * linux/net_tstamp.h but doesn't define SIOCSHWTSTAMP, your
+ * Linux system is badly broken).
+ */
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+ /*
+ * If we were told to do so, ask the kernel and the driver
+ * to use hardware timestamps.
+ *
+ * Hardware timestamps are only supported with mmapped
+ * captures.
+ */
+ if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER ||
+ handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER_UNSYNCED) {
+ struct hwtstamp_config hwconfig;
+ struct ifreq ifr;
+ int timesource;
+
+ /*
+ * Ask for hardware time stamps on all packets,
+ * including transmitted packets.
+ */
+ memset(&hwconfig, 0, sizeof(hwconfig));
+ hwconfig.tx_type = HWTSTAMP_TX_ON;
+ hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
+
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
+ ifr.ifr_data = (void *)&hwconfig;
+
+ if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) {
+ switch (errno) {
+
+ case EPERM:
+ /*
+ * Treat this as an error, as the
+ * user should try to run this
+ * with the appropriate privileges -
+ * and, if they can't, shouldn't
+ * try requesting hardware time stamps.
+ */
+ *status = PCAP_ERROR_PERM_DENIED;
+ return -1;
+
+ case EOPNOTSUPP:
+ case ERANGE:
+ /*
+ * Treat this as a warning, as the
+ * only way to fix the warning is to
+ * get an adapter that supports hardware
+ * time stamps for *all* packets.
+ * (ERANGE means "we support hardware
+ * time stamps, but for packets matching
+ * that particular filter", so it means
+ * "we don't support hardware time stamps
+ * for all incoming packets" here.)
+ *
+ * We'll just fall back on the standard
+ * host time stamps.
+ */
+ *status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP;
+ break;
+
+ default:
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "SIOCSHWTSTAMP failed");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+ } else {
+ /*
+ * Well, that worked. Now specify the type of
+ * hardware time stamp we want for this
+ * socket.
+ */
+ if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) {
+ /*
+ * Hardware timestamp, synchronized
+ * with the system clock.
+ */
+ timesource = SOF_TIMESTAMPING_SYS_HARDWARE;
+ } else {
+ /*
+ * PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware
+ * timestamp, not synchronized with the
+ * system clock.
+ */
+ timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
+ }
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
+ (void *)&timesource, sizeof(timesource))) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "can't set PACKET_TIMESTAMP");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+ }
+ }
+#endif /* HAVE_LINUX_NET_TSTAMP_H && PACKET_TIMESTAMP */
+
+ /* ask the kernel to create the ring */
+retry:
+ req.tp_block_nr = req.tp_frame_nr / frames_per_block;
+
+ /* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */
+ req.tp_frame_nr = req.tp_block_nr * frames_per_block;
+
+#ifdef HAVE_TPACKET3
+ /* timeout value to retire block - use the configured buffering timeout, or default if <0. */
+ if (handlep->timeout > 0) {
+ /* Use the user specified timeout as the block timeout */
+ req.tp_retire_blk_tov = handlep->timeout;
+ } else if (handlep->timeout == 0) {
+ /*
+ * In pcap, this means "infinite timeout"; TPACKET_V3
+ * doesn't support that, so just set it to UINT_MAX
+ * milliseconds. In the TPACKET_V3 loop, if the
+ * timeout is 0, and we haven't yet seen any packets,
+ * and we block and still don't have any packets, we
+ * keep blocking until we do.
+ */
+ req.tp_retire_blk_tov = UINT_MAX;
+ } else {
+ /*
+ * XXX - this is not valid; use 0, meaning "have the
+ * kernel pick a default", for now.
+ */
+ req.tp_retire_blk_tov = 0;
+ }
+ /* private data not used */
+ req.tp_sizeof_priv = 0;
+ /* Rx ring - feature request bits - none (rxhash will not be filled) */
+ req.tp_feature_req_word = 0;
+#endif
+
+ if (setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
+ (void *) &req, sizeof(req))) {
+ if ((errno == ENOMEM) && (req.tp_block_nr > 1)) {
+ /*
+ * Memory failure; try to reduce the requested ring
+ * size.
+ *
+ * We used to reduce this by half -- do 5% instead.
+ * That may result in more iterations and a longer
+ * startup, but the user will be much happier with
+ * the resulting buffer size.
+ */
+ if (req.tp_frame_nr < 20)
+ req.tp_frame_nr -= 1;
+ else
+ req.tp_frame_nr -= req.tp_frame_nr/20;
+ goto retry;
+ }
+ if (errno == ENOPROTOOPT) {
+ /*
+ * We don't have ring buffer support in this kernel.
+ */
+ return 0;
+ }
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't create rx ring on packet socket");
+ *status = PCAP_ERROR;
+ return -1;
+ }
+
+ /* memory map the rx ring */
+ handlep->mmapbuflen = req.tp_block_nr * req.tp_block_size;
+ handlep->mmapbuf = mmap(0, handlep->mmapbuflen,
+ PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
+ if (handlep->mmapbuf == MAP_FAILED) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't mmap rx ring");
+
+ /* clear the allocated ring on error*/
+ destroy_ring(handle);
+ *status = PCAP_ERROR;
+ return -1;
+ }
+
+ /* allocate a ring for each frame header pointer*/
+ handle->cc = req.tp_frame_nr;
+ handle->buffer = malloc(handle->cc * sizeof(union thdr *));
+ if (!handle->buffer) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "can't allocate ring of frame headers");
+
+ destroy_ring(handle);
+ *status = PCAP_ERROR;
+ return -1;
+ }
+
+ /* fill the header ring with proper frame ptr*/
+ handle->offset = 0;
+ for (i=0; i<req.tp_block_nr; ++i) {
+ void *base = &handlep->mmapbuf[i*req.tp_block_size];
+ for (j=0; j<frames_per_block; ++j, ++handle->offset) {
+ RING_GET_CURRENT_FRAME(handle) = base;
+ base += req.tp_frame_size;
+ }
+ }
+
+ handle->bufsize = req.tp_frame_size;
+ handle->offset = 0;
+ return 1;
+}
+
+/* free all ring related resources*/
+static void
+destroy_ring(pcap_t *handle)
+{
+ struct pcap_linux *handlep = handle->priv;
+
+ /* tell the kernel to destroy the ring*/
+ struct tpacket_req req;
+ memset(&req, 0, sizeof(req));
+ /* do not test for setsockopt failure, as we can't recover from any error */
+ (void)setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
+ (void *) &req, sizeof(req));
+
+ /* if ring is mapped, unmap it*/
+ if (handlep->mmapbuf) {
+ /* do not test for mmap failure, as we can't recover from any error */
+ (void)munmap(handlep->mmapbuf, handlep->mmapbuflen);
+ handlep->mmapbuf = NULL;
+ }
+}
+
+/*
+ * Special one-shot callback, used for pcap_next() and pcap_next_ex(),
+ * for Linux mmapped capture.
+ *
+ * The problem is that pcap_next() and pcap_next_ex() expect the packet
+ * data handed to the callback to be valid after the callback returns,
+ * but pcap_read_linux_mmap() has to release that packet as soon as
+ * the callback returns (otherwise, the kernel thinks there's still
+ * at least one unprocessed packet available in the ring, so a select()
+ * will immediately return indicating that there's data to process), so,
+ * in the callback, we have to make a copy of the packet.
+ *
+ * Yes, this means that, if the capture is using the ring buffer, using
+ * pcap_next() or pcap_next_ex() requires more copies than using
+ * pcap_loop() or pcap_dispatch(). If that bothers you, don't use
+ * pcap_next() or pcap_next_ex().
+ */
+static void
+pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
+ const u_char *bytes)
+{
+ struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
+ pcap_t *handle = sp->pd;
+ struct pcap_linux *handlep = handle->priv;
+
+ *sp->hdr = *h;
+ memcpy(handlep->oneshot_buffer, bytes, h->caplen);
+ *sp->pkt = handlep->oneshot_buffer;
+}
+
+static void
+pcap_cleanup_linux_mmap( pcap_t *handle )
+{
+ struct pcap_linux *handlep = handle->priv;
+
+ destroy_ring(handle);
+ if (handlep->oneshot_buffer != NULL) {
+ free(handlep->oneshot_buffer);
+ handlep->oneshot_buffer = NULL;
+ }
+ pcap_cleanup_linux(handle);
+}
+
+
+static int
+pcap_getnonblock_mmap(pcap_t *handle)
+{
+ struct pcap_linux *handlep = handle->priv;
+
+ /* use negative value of timeout to indicate non blocking ops */
+ return (handlep->timeout<0);
+}
+
+static int
+pcap_setnonblock_mmap(pcap_t *handle, int nonblock)
+{
+ struct pcap_linux *handlep = handle->priv;
+
+ /*
+ * Set the file descriptor to non-blocking mode, as we use
+ * it for sending packets.
+ */
+ if (pcap_setnonblock_fd(handle, nonblock) == -1)
+ return -1;
+
+ /*
+ * Map each value to their corresponding negation to
+ * preserve the timeout value provided with pcap_set_timeout.
+ */
+ if (nonblock) {
+ if (handlep->timeout >= 0) {
+ /*
+ * Indicate that we're switching to
+ * non-blocking mode.
+ */
+ handlep->timeout = ~handlep->timeout;
+ }
+ } else {
+ if (handlep->timeout < 0) {
+ handlep->timeout = ~handlep->timeout;
+ }
+ }
+ /* Update the timeout to use in poll(). */
+ set_poll_timeout(handlep);
+ return 0;
+}
+
+/*
+ * Get the status field of the ring buffer frame at a specified offset.
+ */
+static inline int
+pcap_get_ring_frame_status(pcap_t *handle, int offset)
+{
+ struct pcap_linux *handlep = handle->priv;
+ union thdr h;
+
+ h.raw = RING_GET_FRAME_AT(handle, offset);
+ switch (handlep->tp_version) {
+ case TPACKET_V1:
+ return (h.h1->tp_status);
+ break;
+ case TPACKET_V1_64:
+ return (h.h1_64->tp_status);
+ break;
+#ifdef HAVE_TPACKET2
+ case TPACKET_V2:
+ return (h.h2->tp_status);
+ break;
+#endif
+#ifdef HAVE_TPACKET3
+ case TPACKET_V3:
+ return (h.h3->hdr.bh1.block_status);
+ break;
+#endif
+ }
+ /* This should not happen. */
+ return 0;
+}
+
+#ifndef POLLRDHUP
+#define POLLRDHUP 0
+#endif
+
+/*
+ * Block waiting for frames to be available.
+ */
+static int pcap_wait_for_frames_mmap(pcap_t *handle)
+{
+ struct pcap_linux *handlep = handle->priv;
+ char c;
+ struct pollfd pollinfo;
+ int ret;
+
+ pollinfo.fd = handle->fd;
+ pollinfo.events = POLLIN;
+
+ do {
+ /*
+ * Yes, we do this even in non-blocking mode, as it's
+ * the only way to get error indications from a
+ * tpacket socket.
+ *
+ * The timeout is 0 in non-blocking mode, so poll()
+ * returns immediately.
+ */
+ ret = poll(&pollinfo, 1, handlep->poll_timeout);
+ if (ret < 0 && errno != EINTR) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "can't poll on packet socket");
+ return PCAP_ERROR;
+ } else if (ret > 0 &&
+ (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
+ /*
+ * There's some indication other than
+ * "you can read on this descriptor" on
+ * the descriptor.
+ */
+ if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
+ pcap_snprintf(handle->errbuf,
+ PCAP_ERRBUF_SIZE,
+ "Hangup on packet socket");
+ return PCAP_ERROR;
+ }
+ if (pollinfo.revents & POLLERR) {
+ /*
+ * A recv() will give us the actual error code.
+ *
+ * XXX - make the socket non-blocking?
+ */
+ if (recv(handle->fd, &c, sizeof c,
+ MSG_PEEK) != -1)
+ continue; /* what, no error? */
+ if (errno == ENETDOWN) {
+ /*
+ * The device on which we're
+ * capturing went away.
+ *
+ * XXX - we should really return
+ * PCAP_ERROR_IFACE_NOT_UP, but
+ * pcap_dispatch() etc. aren't
+ * defined to return that.
+ */
+ pcap_snprintf(handle->errbuf,
+ PCAP_ERRBUF_SIZE,
+ "The interface went down");
+ } else {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Error condition on packet socket");
+ }
+ return PCAP_ERROR;
+ }
+ if (pollinfo.revents & POLLNVAL) {
+ pcap_snprintf(handle->errbuf,
+ PCAP_ERRBUF_SIZE,
+ "Invalid polling request on packet socket");
+ return PCAP_ERROR;
+ }
+ }
+ /* check for break loop condition on interrupted syscall*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ } while (ret < 0);
+ return 0;
+}
+
+/* handle a single memory mapped packet */
+static int pcap_handle_packet_mmap(
+ pcap_t *handle,
+ pcap_handler callback,
+ u_char *user,
+ unsigned char *frame,
+ unsigned int tp_len,
+ unsigned int tp_mac,
+ unsigned int tp_snaplen,
+ unsigned int tp_sec,
+ unsigned int tp_usec,
+ int tp_vlan_tci_valid,
+ __u16 tp_vlan_tci,
+ __u16 tp_vlan_tpid)
+{
+ struct pcap_linux *handlep = handle->priv;
+ unsigned char *bp;
+ struct sockaddr_ll *sll;
+ struct pcap_pkthdr pcaphdr;
+ unsigned int snaplen = tp_snaplen;
+ struct utsname utsname;
+
+ /* perform sanity check on internal offset. */
+ if (tp_mac + tp_snaplen > handle->bufsize) {
+ /*
+ * Report some system information as a debugging aid.
+ */
+ if (uname(&utsname) != -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "corrupted frame on kernel ring mac "
+ "offset %u + caplen %u > frame len %d "
+ "(kernel %.32s version %s, machine %.16s)",
+ tp_mac, tp_snaplen, handle->bufsize,
+ utsname.release, utsname.version,
+ utsname.machine);
+ } else {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "corrupted frame on kernel ring mac "
+ "offset %u + caplen %u > frame len %d",
+ tp_mac, tp_snaplen, handle->bufsize);
+ }
+ return -1;
+ }
+
+ /* run filter on received packet
+ * If the kernel filtering is enabled we need to run the
+ * filter until all the frames present into the ring
+ * at filter creation time are processed.
+ * In this case, blocks_to_filter_in_userland is used
+ * as a counter for the packet we need to filter.
+ * Note: alternatively it could be possible to stop applying
+ * the filter when the ring became empty, but it can possibly
+ * happen a lot later... */
+ bp = frame + tp_mac;
+
+ /* if required build in place the sll header*/
+ sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);
+ if (handlep->cooked) {
+ if (handle->linktype == DLT_LINUX_SLL2) {
+ struct sll2_header *hdrp;
+
+ /*
+ * The kernel should have left us with enough
+ * space for an sll header; back up the packet
+ * data pointer into that space, as that'll be
+ * the beginning of the packet we pass to the
+ * callback.
+ */
+ bp -= SLL2_HDR_LEN;
+
+ /*
+ * Let's make sure that's past the end of
+ * the tpacket header, i.e. >=
+ * ((u_char *)thdr + TPACKET_HDRLEN), so we
+ * don't step on the header when we construct
+ * the sll header.
+ */
+ if (bp < (u_char *)frame +
+ TPACKET_ALIGN(handlep->tp_hdrlen) +
+ sizeof(struct sockaddr_ll)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "cooked-mode frame doesn't have room for sll header");
+ return -1;
+ }
+
+ /*
+ * OK, that worked; construct the sll header.
+ */
+ hdrp = (struct sll2_header *)bp;
+ hdrp->sll2_protocol = sll->sll_protocol;
+ hdrp->sll2_reserved_mbz = 0;
+ hdrp->sll2_if_index = htonl(sll->sll_ifindex);
+ hdrp->sll2_hatype = htons(sll->sll_hatype);
+ hdrp->sll2_pkttype = sll->sll_pkttype;
+ hdrp->sll2_halen = sll->sll_halen;
+ memcpy(hdrp->sll2_addr, sll->sll_addr, SLL_ADDRLEN);
+
+ snaplen += sizeof(struct sll2_header);
+ } else {
+ struct sll_header *hdrp;
+
+ /*
+ * The kernel should have left us with enough
+ * space for an sll header; back up the packet
+ * data pointer into that space, as that'll be
+ * the beginning of the packet we pass to the
+ * callback.
+ */
+ bp -= SLL_HDR_LEN;
+
+ /*
+ * Let's make sure that's past the end of
+ * the tpacket header, i.e. >=
+ * ((u_char *)thdr + TPACKET_HDRLEN), so we
+ * don't step on the header when we construct
+ * the sll header.
+ */
+ if (bp < (u_char *)frame +
+ TPACKET_ALIGN(handlep->tp_hdrlen) +
+ sizeof(struct sockaddr_ll)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "cooked-mode frame doesn't have room for sll header");
+ return -1;
+ }
+
+ /*
+ * OK, that worked; construct the sll header.
+ */
+ hdrp = (struct sll_header *)bp;
+ hdrp->sll_pkttype = htons(sll->sll_pkttype);
+ hdrp->sll_hatype = htons(sll->sll_hatype);
+ hdrp->sll_halen = htons(sll->sll_halen);
+ memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
+ hdrp->sll_protocol = sll->sll_protocol;
+
+ snaplen += sizeof(struct sll_header);
+ }
+ }
+
+ if (handlep->filter_in_userland && handle->fcode.bf_insns) {
+ struct bpf_aux_data aux_data;
+
+ aux_data.vlan_tag_present = tp_vlan_tci_valid;
+ aux_data.vlan_tag = tp_vlan_tci & 0x0fff;
+
+ if (bpf_filter_with_aux_data(handle->fcode.bf_insns,
+ bp,
+ tp_len,
+ snaplen,
+ &aux_data) == 0)
+ return 0;
+ }
+
+ if (!linux_check_direction(handle, sll))
+ return 0;
+
+ /* get required packet info from ring header */
+ pcaphdr.ts.tv_sec = tp_sec;
+ pcaphdr.ts.tv_usec = tp_usec;
+ pcaphdr.caplen = tp_snaplen;
+ pcaphdr.len = tp_len;
+
+ /* if required build in place the sll header*/
+ if (handlep->cooked) {
+ /* update packet len */
+ if (handle->linktype == DLT_LINUX_SLL2) {
+ pcaphdr.caplen += SLL2_HDR_LEN;
+ pcaphdr.len += SLL2_HDR_LEN;
+ } else {
+ pcaphdr.caplen += SLL_HDR_LEN;
+ pcaphdr.len += SLL_HDR_LEN;
+ }
+ }
+
+#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
+ if (tp_vlan_tci_valid &&
+ handlep->vlan_offset != -1 &&
+ tp_snaplen >= (unsigned int) handlep->vlan_offset)
+ {
+ struct vlan_tag *tag;
+
+ /*
+ * Move everything in the header, except the type field,
+ * down VLAN_TAG_LEN bytes, to allow us to insert the
+ * VLAN tag between that stuff and the type field.
+ */
+ bp -= VLAN_TAG_LEN;
+ memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
+
+ /*
+ * Now insert the tag.
+ */
+ tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
+ tag->vlan_tpid = htons(tp_vlan_tpid);
+ tag->vlan_tci = htons(tp_vlan_tci);
+
+ /*
+ * Add the tag to the packet lengths.
+ */
+ pcaphdr.caplen += VLAN_TAG_LEN;
+ pcaphdr.len += VLAN_TAG_LEN;
+ }
+#endif
+
+ /*
+ * The only way to tell the kernel to cut off the
+ * packet at a snapshot length is with a filter program;
+ * if there's no filter program, the kernel won't cut
+ * the packet off.
+ *
+ * Trim the snapshot length to be no longer than the
+ * specified snapshot length.
+ */
+ if (pcaphdr.caplen > (bpf_u_int32)handle->snapshot)
+ pcaphdr.caplen = handle->snapshot;
+
+ /* pass the packet to the user */
+ callback(user, &pcaphdr, bp);
+
+ return 1;
+}
+
+static int
+pcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
+ u_char *user)
+{
+ struct pcap_linux *handlep = handle->priv;
+ union thdr h;
+ int pkts = 0;
+ int ret;
+
+ /* wait for frames availability.*/
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1->tp_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait for
+ * a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ /* non-positive values of max_packets are used to require all
+ * packets currently available in the ring */
+ while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ /*
+ * Get the current ring buffer frame, and break if
+ * it's still owned by the kernel.
+ */
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1->tp_status == TP_STATUS_KERNEL)
+ break;
+
+ ret = pcap_handle_packet_mmap(
+ handle,
+ callback,
+ user,
+ h.raw,
+ h.h1->tp_len,
+ h.h1->tp_mac,
+ h.h1->tp_snaplen,
+ h.h1->tp_sec,
+ h.h1->tp_usec,
+ 0,
+ 0,
+ 0);
+ if (ret == 1) {
+ pkts++;
+ handlep->packets_read++;
+ } else if (ret < 0) {
+ return ret;
+ }
+
+ /*
+ * Hand this block back to the kernel, and, if we're
+ * counting blocks that need to be filtered in userland
+ * after having been filtered by the kernel, count
+ * the one we've just processed.
+ */
+ h.h1->tp_status = TP_STATUS_KERNEL;
+ if (handlep->blocks_to_filter_in_userland > 0) {
+ handlep->blocks_to_filter_in_userland--;
+ if (handlep->blocks_to_filter_in_userland == 0) {
+ /*
+ * No more blocks need to be filtered
+ * in userland.
+ */
+ handlep->filter_in_userland = 0;
+ }
+ }
+
+ /* next block */
+ if (++handle->offset >= handle->cc)
+ handle->offset = 0;
+
+ /* check for break loop condition*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+ return pkts;
+}
+
+static int
+pcap_read_linux_mmap_v1_64(pcap_t *handle, int max_packets, pcap_handler callback,
+ u_char *user)
+{
+ struct pcap_linux *handlep = handle->priv;
+ union thdr h;
+ int pkts = 0;
+ int ret;
+
+ /* wait for frames availability.*/
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1_64->tp_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait for
+ * a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ /* non-positive values of max_packets are used to require all
+ * packets currently available in the ring */
+ while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ /*
+ * Get the current ring buffer frame, and break if
+ * it's still owned by the kernel.
+ */
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h1_64->tp_status == TP_STATUS_KERNEL)
+ break;
+
+ ret = pcap_handle_packet_mmap(
+ handle,
+ callback,
+ user,
+ h.raw,
+ h.h1_64->tp_len,
+ h.h1_64->tp_mac,
+ h.h1_64->tp_snaplen,
+ h.h1_64->tp_sec,
+ h.h1_64->tp_usec,
+ 0,
+ 0,
+ 0);
+ if (ret == 1) {
+ pkts++;
+ handlep->packets_read++;
+ } else if (ret < 0) {
+ return ret;
+ }
+
+ /*
+ * Hand this block back to the kernel, and, if we're
+ * counting blocks that need to be filtered in userland
+ * after having been filtered by the kernel, count
+ * the one we've just processed.
+ */
+ h.h1_64->tp_status = TP_STATUS_KERNEL;
+ if (handlep->blocks_to_filter_in_userland > 0) {
+ handlep->blocks_to_filter_in_userland--;
+ if (handlep->blocks_to_filter_in_userland == 0) {
+ /*
+ * No more blocks need to be filtered
+ * in userland.
+ */
+ handlep->filter_in_userland = 0;
+ }
+ }
+
+ /* next block */
+ if (++handle->offset >= handle->cc)
+ handle->offset = 0;
+
+ /* check for break loop condition*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+ return pkts;
+}
+
+#ifdef HAVE_TPACKET2
+static int
+pcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
+ u_char *user)
+{
+ struct pcap_linux *handlep = handle->priv;
+ union thdr h;
+ int pkts = 0;
+ int ret;
+
+ /* wait for frames availability.*/
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h2->tp_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait for
+ * a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ /* non-positive values of max_packets are used to require all
+ * packets currently available in the ring */
+ while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ /*
+ * Get the current ring buffer frame, and break if
+ * it's still owned by the kernel.
+ */
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h2->tp_status == TP_STATUS_KERNEL)
+ break;
+
+ ret = pcap_handle_packet_mmap(
+ handle,
+ callback,
+ user,
+ h.raw,
+ h.h2->tp_len,
+ h.h2->tp_mac,
+ h.h2->tp_snaplen,
+ h.h2->tp_sec,
+ handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? h.h2->tp_nsec : h.h2->tp_nsec / 1000,
+ VLAN_VALID(h.h2, h.h2),
+ h.h2->tp_vlan_tci,
+ VLAN_TPID(h.h2, h.h2));
+ if (ret == 1) {
+ pkts++;
+ handlep->packets_read++;
+ } else if (ret < 0) {
+ return ret;
+ }
+
+ /*
+ * Hand this block back to the kernel, and, if we're
+ * counting blocks that need to be filtered in userland
+ * after having been filtered by the kernel, count
+ * the one we've just processed.
+ */
+ h.h2->tp_status = TP_STATUS_KERNEL;
+ if (handlep->blocks_to_filter_in_userland > 0) {
+ handlep->blocks_to_filter_in_userland--;
+ if (handlep->blocks_to_filter_in_userland == 0) {
+ /*
+ * No more blocks need to be filtered
+ * in userland.
+ */
+ handlep->filter_in_userland = 0;
+ }
+ }
+
+ /* next block */
+ if (++handle->offset >= handle->cc)
+ handle->offset = 0;
+
+ /* check for break loop condition*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+ return pkts;
+}
+#endif /* HAVE_TPACKET2 */
+
+#ifdef HAVE_TPACKET3
+static int
+pcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
+ u_char *user)
+{
+ struct pcap_linux *handlep = handle->priv;
+ union thdr h;
+ int pkts = 0;
+ int ret;
+
+again:
+ if (handlep->current_packet == NULL) {
+ /* wait for frames availability.*/
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+ /*
+ * The current frame is owned by the kernel; wait
+ * for a frame to be handed to us.
+ */
+ ret = pcap_wait_for_frames_mmap(handle);
+ if (ret) {
+ return ret;
+ }
+ }
+ }
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) {
+ if (pkts == 0 && handlep->timeout == 0) {
+ /* Block until we see a packet. */
+ goto again;
+ }
+ return pkts;
+ }
+
+ /* non-positive values of max_packets are used to require all
+ * packets currently available in the ring */
+ while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ int packets_to_read;
+
+ if (handlep->current_packet == NULL) {
+ h.raw = RING_GET_CURRENT_FRAME(handle);
+ if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL)
+ break;
+
+ handlep->current_packet = h.raw + h.h3->hdr.bh1.offset_to_first_pkt;
+ handlep->packets_left = h.h3->hdr.bh1.num_pkts;
+ }
+ packets_to_read = handlep->packets_left;
+
+ if (!PACKET_COUNT_IS_UNLIMITED(max_packets) &&
+ packets_to_read > (max_packets - pkts)) {
+ /*
+ * We've been given a maximum number of packets
+ * to process, and there are more packets in
+ * this buffer than that. Only process enough
+ * of them to get us up to that maximum.
+ */
+ packets_to_read = max_packets - pkts;
+ }
+
+ while (packets_to_read-- && !handle->break_loop) {
+ struct tpacket3_hdr* tp3_hdr = (struct tpacket3_hdr*) handlep->current_packet;
+ ret = pcap_handle_packet_mmap(
+ handle,
+ callback,
+ user,
+ handlep->current_packet,
+ tp3_hdr->tp_len,
+ tp3_hdr->tp_mac,
+ tp3_hdr->tp_snaplen,
+ tp3_hdr->tp_sec,
+ handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? tp3_hdr->tp_nsec : tp3_hdr->tp_nsec / 1000,
+ VLAN_VALID(tp3_hdr, &tp3_hdr->hv1),
+ tp3_hdr->hv1.tp_vlan_tci,
+ VLAN_TPID(tp3_hdr, &tp3_hdr->hv1));
+ if (ret == 1) {
+ pkts++;
+ handlep->packets_read++;
+ } else if (ret < 0) {
+ handlep->current_packet = NULL;
+ return ret;
+ }
+ handlep->current_packet += tp3_hdr->tp_next_offset;
+ handlep->packets_left--;
+ }
+
+ if (handlep->packets_left <= 0) {
+ /*
+ * Hand this block back to the kernel, and, if
+ * we're counting blocks that need to be
+ * filtered in userland after having been
+ * filtered by the kernel, count the one we've
+ * just processed.
+ */
+ h.h3->hdr.bh1.block_status = TP_STATUS_KERNEL;
+ if (handlep->blocks_to_filter_in_userland > 0) {
+ handlep->blocks_to_filter_in_userland--;
+ if (handlep->blocks_to_filter_in_userland == 0) {
+ /*
+ * No more blocks need to be filtered
+ * in userland.
+ */
+ handlep->filter_in_userland = 0;
+ }
+ }
+
+ /* next block */
+ if (++handle->offset >= handle->cc)
+ handle->offset = 0;
+
+ handlep->current_packet = NULL;
+ }
+
+ /* check for break loop condition*/
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+ if (pkts == 0 && handlep->timeout == 0) {
+ /* Block until we see a packet. */
+ goto again;
+ }
+ return pkts;
+}
+#endif /* HAVE_TPACKET3 */
+
+static int
+pcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
+{
+ struct pcap_linux *handlep = handle->priv;
+ int n, offset;
+ int ret;
+
+ /*
+ * Don't rewrite "ret" instructions; we don't need to, as
+ * we're not reading packets with recvmsg(), and we don't
+ * want to, as, by not rewriting them, the kernel can avoid
+ * copying extra data.
+ */
+ ret = pcap_setfilter_linux_common(handle, filter, 1);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * If we're filtering in userland, there's nothing to do;
+ * the new filter will be used for the next packet.
+ */
+ if (handlep->filter_in_userland)
+ return ret;
+
+ /*
+ * We're filtering in the kernel; the packets present in
+ * all blocks currently in the ring were already filtered
+ * by the old filter, and so will need to be filtered in
+ * userland by the new filter.
+ *
+ * Get an upper bound for the number of such blocks; first,
+ * walk the ring backward and count the free blocks.
+ */
+ offset = handle->offset;
+ if (--offset < 0)
+ offset = handle->cc - 1;
+ for (n=0; n < handle->cc; ++n) {
+ if (--offset < 0)
+ offset = handle->cc - 1;
+ if (pcap_get_ring_frame_status(handle, offset) != TP_STATUS_KERNEL)
+ break;
+ }
+
+ /*
+ * If we found free blocks, decrement the count of free
+ * blocks by 1, just in case we lost a race with another
+ * thread of control that was adding a packet while
+ * we were counting and that had run the filter before
+ * we changed it.
+ *
+ * XXX - could there be more than one block added in
+ * this fashion?
+ *
+ * XXX - is there a way to avoid that race, e.g. somehow
+ * wait for all packets that passed the old filter to
+ * be added to the ring?
+ */
+ if (n != 0)
+ n--;
+
+ /*
+ * Set the count of blocks worth of packets to filter
+ * in userland to the total number of blocks in the
+ * ring minus the number of free blocks we found, and
+ * turn on userland filtering. (The count of blocks
+ * worth of packets to filter in userland is guaranteed
+ * not to be zero - n, above, couldn't be set to a
+ * value > handle->cc, and if it were equal to
+ * handle->cc, it wouldn't be zero, and thus would
+ * be decremented to handle->cc - 1.)
+ */
+ handlep->blocks_to_filter_in_userland = handle->cc - n;
+ handlep->filter_in_userland = 1;
+ return ret;
+}
+
+#endif /* HAVE_PACKET_RING */
+
+
+#ifdef HAVE_PF_PACKET_SOCKETS
+/*
+ * Return the index of the given device name. Fill ebuf and return
+ * -1 on failure.
+ */
+static int
+iface_get_id(int fd, const char *device, char *ebuf)
+{
+ struct ifreq ifr;
+
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+
+ if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFINDEX");
+ return -1;
+ }
+
+ return ifr.ifr_ifindex;
+}
+
+/*
+ * Bind the socket associated with FD to the given device.
+ * Return 1 on success, 0 if we should try a SOCK_PACKET socket,
+ * or a PCAP_ERROR_ value on a hard error.
+ */
+static int
+iface_bind(int fd, int ifindex, char *ebuf, int protocol)
+{
+ struct sockaddr_ll sll;
+ int err;
+ socklen_t errlen = sizeof(err);
+
+ memset(&sll, 0, sizeof(sll));
+ sll.sll_family = AF_PACKET;
+ sll.sll_ifindex = ifindex;
+ sll.sll_protocol = protocol;
+
+ if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
+ if (errno == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return PCAP_ERROR_IFACE_NOT_UP;
+ } else {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "bind");
+ return PCAP_ERROR;
+ }
+ }
+
+ /* Any pending errors, e.g., network is down? */
+
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "getsockopt (SO_ERROR)");
+ return 0;
+ }
+
+ if (err == ENETDOWN) {
+ /*
+ * Return a "network down" indication, so that
+ * the application can report that rather than
+ * saying we had a mysterious failure and
+ * suggest that they report a problem to the
+ * libpcap developers.
+ */
+ return PCAP_ERROR_IFACE_NOT_UP;
+ } else if (err > 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ err, "bind");
+ return 0;
+ }
+
+ return 1;
+}
+
+#ifdef IW_MODE_MONITOR
+/*
+ * Check whether the device supports the Wireless Extensions.
+ * Returns 1 if it does, 0 if it doesn't, PCAP_ERROR_NO_SUCH_DEVICE
+ * if the device doesn't even exist.
+ */
+static int
+has_wext(int sock_fd, const char *device, char *ebuf)
+{
+ struct iwreq ireq;
+ int ret;
+
+ if (is_bonding_device(sock_fd, device))
+ return 0; /* bonding device, so don't even try */
+
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
+ return 1; /* yes */
+ if (errno == ENODEV)
+ ret = PCAP_ERROR_NO_SUCH_DEVICE;
+ else
+ ret = 0;
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+ "%s: SIOCGIWNAME", device);
+ return ret;
+}
+
+/*
+ * Per me si va ne la citta dolente,
+ * Per me si va ne l'etterno dolore,
+ * ...
+ * Lasciate ogne speranza, voi ch'intrate.
+ *
+ * XXX - airmon-ng does special stuff with the Orinoco driver and the
+ * wlan-ng driver.
+ */
+typedef enum {
+ MONITOR_WEXT,
+ MONITOR_HOSTAP,
+ MONITOR_PRISM,
+ MONITOR_PRISM54,
+ MONITOR_ACX100,
+ MONITOR_RT2500,
+ MONITOR_RT2570,
+ MONITOR_RT73,
+ MONITOR_RTL8XXX
+} monitor_type;
+
+/*
+ * Use the Wireless Extensions, if we have them, to try to turn monitor mode
+ * on if it's not already on.
+ *
+ * Returns 1 on success, 0 if we don't support the Wireless Extensions
+ * on this device, or a PCAP_ERROR_ value if we do support them but
+ * we weren't able to turn monitor mode on.
+ */
+static int
+enter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
+{
+ /*
+ * XXX - at least some adapters require non-Wireless Extensions
+ * mechanisms to turn monitor mode on.
+ *
+ * Atheros cards might require that a separate "monitor virtual access
+ * point" be created, with later versions of the madwifi driver.
+ * airmon-ng does "wlanconfig ath create wlandev {if} wlanmode
+ * monitor -bssid", which apparently spits out a line "athN"
+ * where "athN" is the monitor mode device. To leave monitor
+ * mode, it destroys the monitor mode device.
+ *
+ * Some Intel Centrino adapters might require private ioctls to get
+ * radio headers; the ipw2200 and ipw3945 drivers allow you to
+ * configure a separate "rtapN" interface to capture in monitor
+ * mode without preventing the adapter from operating normally.
+ * (airmon-ng doesn't appear to use that, though.)
+ *
+ * It would be Truly Wonderful if mac80211 and nl80211 cleaned this
+ * up, and if all drivers were converted to mac80211 drivers.
+ *
+ * If interface {if} is a mac80211 driver, the file
+ * /sys/class/net/{if}/phy80211 is a symlink to
+ * /sys/class/ieee80211/{phydev}, for some {phydev}.
+ *
+ * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
+ * least, has a "wmaster0" device and a "wlan0" device; the
+ * latter is the one with the IP address. Both show up in
+ * "tcpdump -D" output. Capturing on the wmaster0 device
+ * captures with 802.11 headers.
+ *
+ * airmon-ng searches through /sys/class/net for devices named
+ * monN, starting with mon0; as soon as one *doesn't* exist,
+ * it chooses that as the monitor device name. If the "iw"
+ * command exists, it does "iw dev {if} interface add {monif}
+ * type monitor", where {monif} is the monitor device. It
+ * then (sigh) sleeps .1 second, and then configures the
+ * device up. Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
+ * is a file, it writes {mondev}, without a newline, to that file,
+ * and again (sigh) sleeps .1 second, and then iwconfig's that
+ * device into monitor mode and configures it up. Otherwise,
+ * you can't do monitor mode.
+ *
+ * All these devices are "glued" together by having the
+ * /sys/class/net/{device}/phy80211 links pointing to the same
+ * place, so, given a wmaster, wlan, or mon device, you can
+ * find the other devices by looking for devices with
+ * the same phy80211 link.
+ *
+ * To turn monitor mode off, delete the monitor interface,
+ * either with "iw dev {monif} interface del" or by sending
+ * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
+ *
+ * Note: if you try to create a monitor device named "monN", and
+ * there's already a "monN" device, it fails, as least with
+ * the netlink interface (which is what iw uses), with a return
+ * value of -ENFILE. (Return values are negative errnos.) We
+ * could probably use that to find an unused device.
+ */
+ struct pcap_linux *handlep = handle->priv;
+ int err;
+ struct iwreq ireq;
+ struct iw_priv_args *priv;
+ monitor_type montype;
+ int i;
+ __u32 cmd;
+ struct ifreq ifr;
+ int oldflags;
+ int args[2];
+ int channel;
+
+ /*
+ * Does this device *support* the Wireless Extensions?
+ */
+ err = has_wext(sock_fd, device, handle->errbuf);
+ if (err <= 0)
+ return err; /* either it doesn't or the device doesn't even exist */
+ /*
+ * Start out assuming we have no private extensions to control
+ * radio metadata.
+ */
+ montype = MONITOR_WEXT;
+ cmd = 0;
+
+ /*
+ * Try to get all the Wireless Extensions private ioctls
+ * supported by this device.
+ *
+ * First, get the size of the buffer we need, by supplying no
+ * buffer and a length of 0. If the device supports private
+ * ioctls, it should return E2BIG, with ireq.u.data.length set
+ * to the length we need. If it doesn't support them, it should
+ * return EOPNOTSUPP.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.u.data.pointer = (void *)args;
+ ireq.u.data.length = 0;
+ ireq.u.data.flags = 0;
+ if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!",
+ device);
+ return PCAP_ERROR;
+ }
+ if (errno != EOPNOTSUPP) {
+ /*
+ * OK, it's not as if there are no private ioctls.
+ */
+ if (errno != E2BIG) {
+ /*
+ * Failed.
+ */
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * OK, try to get the list of private ioctls.
+ */
+ priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
+ if (priv == NULL) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "malloc");
+ return PCAP_ERROR;
+ }
+ ireq.u.data.pointer = (void *)priv;
+ if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device);
+ free(priv);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * Look for private ioctls to turn monitor mode on or, if
+ * monitor mode is on, to set the header type.
+ */
+ for (i = 0; i < ireq.u.data.length; i++) {
+ if (strcmp(priv[i].name, "monitor_type") == 0) {
+ /*
+ * Hostap driver, use this one.
+ * Set monitor mode first.
+ * You can set it to 0 to get DLT_IEEE80211,
+ * 1 to get DLT_PRISM, 2 to get
+ * DLT_IEEE80211_RADIO_AVS, and, with more
+ * recent versions of the driver, 3 to get
+ * DLT_IEEE80211_RADIO.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_HOSTAP;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "set_prismhdr") == 0) {
+ /*
+ * Prism54 driver, use this one.
+ * Set monitor mode first.
+ * You can set it to 2 to get DLT_IEEE80211
+ * or 3 or get DLT_PRISM.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_PRISM54;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "forceprismheader") == 0) {
+ /*
+ * RT2570 driver, use this one.
+ * Do this after turning monitor mode on.
+ * You can set it to 1 to get DLT_PRISM or 2
+ * to get DLT_IEEE80211.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_RT2570;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "forceprism") == 0) {
+ /*
+ * RT73 driver, use this one.
+ * Do this after turning monitor mode on.
+ * Its argument is a *string*; you can
+ * set it to "1" to get DLT_PRISM or "2"
+ * to get DLT_IEEE80211.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR)
+ break;
+ if (priv[i].set_args & IW_PRIV_SIZE_FIXED)
+ break;
+ montype = MONITOR_RT73;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "prismhdr") == 0) {
+ /*
+ * One of the RTL8xxx drivers, use this one.
+ * It can only be done after monitor mode
+ * has been turned on. You can set it to 1
+ * to get DLT_PRISM or 0 to get DLT_IEEE80211.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
+ break;
+ montype = MONITOR_RTL8XXX;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "rfmontx") == 0) {
+ /*
+ * RT2500 or RT61 driver, use this one.
+ * It has one one-byte parameter; set
+ * u.data.length to 1 and u.data.pointer to
+ * point to the parameter.
+ * It doesn't itself turn monitor mode on.
+ * You can set it to 1 to allow transmitting
+ * in monitor mode(?) and get DLT_IEEE80211,
+ * or set it to 0 to disallow transmitting in
+ * monitor mode(?) and get DLT_PRISM.
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 2)
+ break;
+ montype = MONITOR_RT2500;
+ cmd = priv[i].cmd;
+ break;
+ }
+ if (strcmp(priv[i].name, "monitor") == 0) {
+ /*
+ * Either ACX100 or hostap, use this one.
+ * It turns monitor mode on.
+ * If it takes two arguments, it's ACX100;
+ * the first argument is 1 for DLT_PRISM
+ * or 2 for DLT_IEEE80211, and the second
+ * argument is the channel on which to
+ * run. If it takes one argument, it's
+ * HostAP, and the argument is 2 for
+ * DLT_IEEE80211 and 3 for DLT_PRISM.
+ *
+ * If we see this, we don't quit, as this
+ * might be a version of the hostap driver
+ * that also supports "monitor_type".
+ */
+ if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
+ break;
+ if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
+ break;
+ switch (priv[i].set_args & IW_PRIV_SIZE_MASK) {
+
+ case 1:
+ montype = MONITOR_PRISM;
+ cmd = priv[i].cmd;
+ break;
+
+ case 2:
+ montype = MONITOR_ACX100;
+ cmd = priv[i].cmd;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ free(priv);
+ }
+
+ /*
+ * XXX - ipw3945? islism?
+ */
+
+ /*
+ * Get the old mode.
+ */
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) {
+ /*
+ * We probably won't be able to set the mode, either.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * Is it currently in monitor mode?
+ */
+ if (ireq.u.mode == IW_MODE_MONITOR) {
+ /*
+ * Yes. Just leave things as they are.
+ * We don't offer multiple link-layer types, as
+ * changing the link-layer type out from under
+ * somebody else capturing in monitor mode would
+ * be considered rude.
+ */
+ return 1;
+ }
+ /*
+ * No. We have to put the adapter into rfmon mode.
+ */
+
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!pcap_do_addexit(handle)) {
+ /*
+ * "atexit()" failed; don't put the interface
+ * in rfmon mode, just give up.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * Save the old mode.
+ */
+ handlep->oldmode = ireq.u.mode;
+
+ /*
+ * Put the adapter in rfmon mode. How we do this depends
+ * on whether we have a special private ioctl or not.
+ */
+ if (montype == MONITOR_PRISM) {
+ /*
+ * We have the "monitor" private ioctl, but none of
+ * the other private ioctls. Use this, and select
+ * the Prism header.
+ *
+ * If it fails, just fall back on SIOCSIWMODE.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.u.data.length = 1; /* 1 argument */
+ args[0] = 3; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ if (ioctl(sock_fd, cmd, &ireq) != -1) {
+ /*
+ * Success.
+ * Note that we have to put the old mode back
+ * when we close the device.
+ */
+ handlep->must_do_on_close |= MUST_CLEAR_RFMON;
+
+ /*
+ * Add this to the list of pcaps to close
+ * when we exit.
+ */
+ pcap_add_to_pcaps_to_close(handle);
+
+ return 1;
+ }
+
+ /*
+ * Failure. Fall back on SIOCSIWMODE.
+ */
+ }
+
+ /*
+ * First, take the interface down if it's up; otherwise, we
+ * might get EBUSY.
+ */
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s: Can't get flags", device);
+ return PCAP_ERROR;
+ }
+ oldflags = 0;
+ if (ifr.ifr_flags & IFF_UP) {
+ oldflags = ifr.ifr_flags;
+ ifr.ifr_flags &= ~IFF_UP;
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
+ device);
+ return PCAP_ERROR;
+ }
+ }
+
+ /*
+ * Then turn monitor mode on.
+ */
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.u.mode = IW_MODE_MONITOR;
+ if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) {
+ /*
+ * Scientist, you've failed.
+ * Bring the interface back up if we shut it down.
+ */
+ ifr.ifr_flags = oldflags;
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
+ device);
+ return PCAP_ERROR;
+ }
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /*
+ * XXX - airmon-ng does "iwconfig {if} key off" after setting
+ * monitor mode and setting the channel, and then does
+ * "iwconfig up".
+ */
+
+ /*
+ * Now select the appropriate radio header.
+ */
+ switch (montype) {
+
+ case MONITOR_WEXT:
+ /*
+ * We don't have any private ioctl to set the header.
+ */
+ break;
+
+ case MONITOR_HOSTAP:
+ /*
+ * Try to select the radiotap header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 3; /* request radiotap header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ if (ioctl(sock_fd, cmd, &ireq) != -1)
+ break; /* success */
+
+ /*
+ * That failed. Try to select the AVS header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 2; /* request AVS header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ if (ioctl(sock_fd, cmd, &ireq) != -1)
+ break; /* success */
+
+ /*
+ * That failed. Try to select the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 1; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_PRISM:
+ /*
+ * The private ioctl failed.
+ */
+ break;
+
+ case MONITOR_PRISM54:
+ /*
+ * Select the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 3; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_ACX100:
+ /*
+ * Get the current channel.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWFREQ", device);
+ return PCAP_ERROR;
+ }
+ channel = ireq.u.freq.m;
+
+ /*
+ * Select the Prism header, and set the channel to the
+ * current value.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 1; /* request Prism header */
+ args[1] = channel; /* set channel */
+ memcpy(ireq.u.name, args, 2*sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RT2500:
+ /*
+ * Disallow transmission - that turns on the
+ * Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 0; /* disallow transmitting */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RT2570:
+ /*
+ * Force the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 1; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RT73:
+ /*
+ * Force the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ ireq.u.data.length = 1; /* 1 argument */
+ ireq.u.data.pointer = "1";
+ ireq.u.data.flags = 0;
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+
+ case MONITOR_RTL8XXX:
+ /*
+ * Force the Prism header.
+ */
+ memset(&ireq, 0, sizeof ireq);
+ pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device,
+ sizeof ireq.ifr_ifrn.ifrn_name);
+ args[0] = 1; /* request Prism header */
+ memcpy(ireq.u.name, args, sizeof (int));
+ ioctl(sock_fd, cmd, &ireq);
+ break;
+ }
+
+ /*
+ * Now bring the interface back up if we brought it down.
+ */
+ if (oldflags != 0) {
+ ifr.ifr_flags = oldflags;
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags",
+ device);
+
+ /*
+ * At least try to restore the old mode on the
+ * interface.
+ */
+ if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
+ /*
+ * Scientist, you've failed.
+ */
+ fprintf(stderr,
+ "Can't restore interface wireless mode (SIOCSIWMODE failed: %s).\n"
+ "Please adjust manually.\n",
+ strerror(errno));
+ }
+ return PCAP_ERROR;
+ }
+ }
+
+ /*
+ * Note that we have to put the old mode back when we
+ * close the device.
+ */
+ handlep->must_do_on_close |= MUST_CLEAR_RFMON;
+
+ /*
+ * Add this to the list of pcaps to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(handle);
+
+ return 1;
+}
+#endif /* IW_MODE_MONITOR */
+
+/*
+ * Try various mechanisms to enter monitor mode.
+ */
+static int
+enter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
+{
+#if defined(HAVE_LIBNL) || defined(IW_MODE_MONITOR)
+ int ret;
+#endif
+
+#ifdef HAVE_LIBNL
+ ret = enter_rfmon_mode_mac80211(handle, sock_fd, device);
+ if (ret < 0)
+ return ret; /* error attempting to do so */
+ if (ret == 1)
+ return 1; /* success */
+#endif /* HAVE_LIBNL */
+
+#ifdef IW_MODE_MONITOR
+ ret = enter_rfmon_mode_wext(handle, sock_fd, device);
+ if (ret < 0)
+ return ret; /* error attempting to do so */
+ if (ret == 1)
+ return 1; /* success */
+#endif /* IW_MODE_MONITOR */
+
+ /*
+ * Either none of the mechanisms we know about work or none
+ * of those mechanisms are available, so we can't do monitor
+ * mode.
+ */
+ return 0;
+}
+
+#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
+/*
+ * Map SOF_TIMESTAMPING_ values to PCAP_TSTAMP_ values.
+ */
+static const struct {
+ int soft_timestamping_val;
+ int pcap_tstamp_val;
+} sof_ts_type_map[3] = {
+ { SOF_TIMESTAMPING_SOFTWARE, PCAP_TSTAMP_HOST },
+ { SOF_TIMESTAMPING_SYS_HARDWARE, PCAP_TSTAMP_ADAPTER },
+ { SOF_TIMESTAMPING_RAW_HARDWARE, PCAP_TSTAMP_ADAPTER_UNSYNCED }
+};
+#define NUM_SOF_TIMESTAMPING_TYPES (sizeof sof_ts_type_map / sizeof sof_ts_type_map[0])
+
+/*
+ * Set the list of time stamping types to include all types.
+ */
+static void
+iface_set_all_ts_types(pcap_t *handle)
+{
+ u_int i;
+
+ handle->tstamp_type_count = NUM_SOF_TIMESTAMPING_TYPES;
+ handle->tstamp_type_list = malloc(NUM_SOF_TIMESTAMPING_TYPES * sizeof(u_int));
+ for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++)
+ handle->tstamp_type_list[i] = sof_ts_type_map[i].pcap_tstamp_val;
+}
+
+#ifdef ETHTOOL_GET_TS_INFO
+/*
+ * Get a list of time stamping capabilities.
+ */
+static int
+iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf)
+{
+ int fd;
+ struct ifreq ifr;
+ struct ethtool_ts_info info;
+ int num_ts_types;
+ u_int i, j;
+
+ /*
+ * This doesn't apply to the "any" device; you can't say "turn on
+ * hardware time stamping for all devices that exist now and arrange
+ * that it be turned on for any device that appears in the future",
+ * and not all devices even necessarily *support* hardware time
+ * stamping, so don't report any time stamp types.
+ */
+ if (strcmp(device, "any") == 0) {
+ handle->tstamp_type_list = NULL;
+ return 0;
+ }
+
+ /*
+ * Create a socket from which to fetch time stamping capabilities.
+ */
+ fd = socket(PF_UNIX, SOCK_RAW, 0);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO)");
+ return -1;
+ }
+
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ memset(&info, 0, sizeof(info));
+ info.cmd = ETHTOOL_GET_TS_INFO;
+ ifr.ifr_data = (caddr_t)&info;
+ if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) {
+ int save_errno = errno;
+
+ close(fd);
+ switch (save_errno) {
+
+ case EOPNOTSUPP:
+ case EINVAL:
+ /*
+ * OK, this OS version or driver doesn't support
+ * asking for the time stamping types, so let's
+ * just return all the possible types.
+ */
+ iface_set_all_ts_types(handle);
+ return 0;
+
+ case ENODEV:
+ /*
+ * OK, no such device.
+ * The user will find that out when they try to
+ * activate the device; just return an empty
+ * list of time stamp types.
+ */
+ handle->tstamp_type_list = NULL;
+ return 0;
+
+ default:
+ /*
+ * Other error.
+ */
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ save_errno,
+ "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed",
+ device);
+ return -1;
+ }
+ }
+ close(fd);
+
+ /*
+ * Do we support hardware time stamping of *all* packets?
+ */
+ if (!(info.rx_filters & (1 << HWTSTAMP_FILTER_ALL))) {
+ /*
+ * No, so don't report any time stamp types.
+ *
+ * XXX - some devices either don't report
+ * HWTSTAMP_FILTER_ALL when they do support it, or
+ * report HWTSTAMP_FILTER_ALL but map it to only
+ * time stamping a few PTP packets. See
+ * http://marc.info/?l=linux-netdev&m=146318183529571&w=2
+ */
+ handle->tstamp_type_list = NULL;
+ return 0;
+ }
+
+ num_ts_types = 0;
+ for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) {
+ if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val)
+ num_ts_types++;
+ }
+ handle->tstamp_type_count = num_ts_types;
+ if (num_ts_types != 0) {
+ handle->tstamp_type_list = malloc(num_ts_types * sizeof(u_int));
+ for (i = 0, j = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) {
+ if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val) {
+ handle->tstamp_type_list[j] = sof_ts_type_map[i].pcap_tstamp_val;
+ j++;
+ }
+ }
+ } else
+ handle->tstamp_type_list = NULL;
+
+ return 0;
+}
+#else /* ETHTOOL_GET_TS_INFO */
+static int
+iface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf _U_)
+{
+ /*
+ * This doesn't apply to the "any" device; you can't say "turn on
+ * hardware time stamping for all devices that exist now and arrange
+ * that it be turned on for any device that appears in the future",
+ * and not all devices even necessarily *support* hardware time
+ * stamping, so don't report any time stamp types.
+ */
+ if (strcmp(device, "any") == 0) {
+ handle->tstamp_type_list = NULL;
+ return 0;
+ }
+
+ /*
+ * We don't have an ioctl to use to ask what's supported,
+ * so say we support everything.
+ */
+ iface_set_all_ts_types(handle);
+ return 0;
+}
+#endif /* ETHTOOL_GET_TS_INFO */
+
+#endif /* defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) */
+
+#ifdef HAVE_PACKET_RING
+/*
+ * Find out if we have any form of fragmentation/reassembly offloading.
+ *
+ * We do so using SIOCETHTOOL checking for various types of offloading;
+ * if SIOCETHTOOL isn't defined, or we don't have any #defines for any
+ * of the types of offloading, there's nothing we can do to check, so
+ * we just say "no, we don't".
+ *
+ * We treat EOPNOTSUPP, EINVAL and, if eperm_ok is true, EPERM as
+ * indications that the operation isn't supported. We do EPERM
+ * weirdly because the SIOCETHTOOL code in later kernels 1) doesn't
+ * support ETHTOOL_GUFO, 2) also doesn't include it in the list
+ * of ethtool operations that don't require CAP_NET_ADMIN privileges,
+ * and 3) does the "is this permitted" check before doing the "is
+ * this even supported" check, so it fails with "this is not permitted"
+ * rather than "this is not even supported". To work around this
+ * annoyance, we only treat EPERM as an error for the first feature,
+ * and assume that they all do the same permission checks, so if the
+ * first one is allowed all the others are allowed if supported.
+ */
+#if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO))
+static int
+iface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname,
+ int eperm_ok)
+{
+ struct ifreq ifr;
+ struct ethtool_value eval;
+
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name));
+ eval.cmd = cmd;
+ eval.data = 0;
+ ifr.ifr_data = (caddr_t)&eval;
+ if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) {
+ if (errno == EOPNOTSUPP || errno == EINVAL ||
+ (errno == EPERM && eperm_ok)) {
+ /*
+ * OK, let's just return 0, which, in our
+ * case, either means "no, what we're asking
+ * about is not enabled" or "all the flags
+ * are clear (i.e., nothing is enabled)".
+ */
+ return 0;
+ }
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s: SIOCETHTOOL(%s) ioctl failed",
+ handle->opt.device, cmdname);
+ return -1;
+ }
+ return eval.data;
+}
+
+/*
+ * XXX - it's annoying that we have to check for offloading at all, but,
+ * given that we have to, it's still annoying that we have to check for
+ * particular types of offloading, especially that shiny new types of
+ * offloading may be added - and, worse, may not be checkable with
+ * a particular ETHTOOL_ operation; ETHTOOL_GFEATURES would, in
+ * theory, give those to you, but the actual flags being used are
+ * opaque (defined in a non-uapi header), and there doesn't seem to
+ * be any obvious way to ask the kernel what all the offloading flags
+ * are - at best, you can ask for a set of strings(!) to get *names*
+ * for various flags. (That whole mechanism appears to have been
+ * designed for the sole purpose of letting ethtool report flags
+ * by name and set flags by name, with the names having no semantics
+ * ethtool understands.)
+ */
+static int
+iface_get_offload(pcap_t *handle)
+{
+ int ret;
+
+#ifdef ETHTOOL_GTSO
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO", 0);
+ if (ret == -1)
+ return -1;
+ if (ret)
+ return 1; /* TCP segmentation offloading on */
+#endif
+
+#ifdef ETHTOOL_GGSO
+ /*
+ * XXX - will this cause large unsegmented packets to be
+ * handed to PF_PACKET sockets on transmission? If not,
+ * this need not be checked.
+ */
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO", 0);
+ if (ret == -1)
+ return -1;
+ if (ret)
+ return 1; /* generic segmentation offloading on */
+#endif
+
+#ifdef ETHTOOL_GFLAGS
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS", 0);
+ if (ret == -1)
+ return -1;
+ if (ret & ETH_FLAG_LRO)
+ return 1; /* large receive offloading on */
+#endif
+
+#ifdef ETHTOOL_GGRO
+ /*
+ * XXX - will this cause large reassembled packets to be
+ * handed to PF_PACKET sockets on receipt? If not,
+ * this need not be checked.
+ */
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO", 0);
+ if (ret == -1)
+ return -1;
+ if (ret)
+ return 1; /* generic (large) receive offloading on */
+#endif
+
+#ifdef ETHTOOL_GUFO
+ /*
+ * Do this one last, as support for it was removed in later
+ * kernels, and it fails with EPERM on those kernels rather
+ * than with EOPNOTSUPP (see explanation in comment for
+ * iface_ethtool_flag_ioctl()).
+ */
+ ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO", 1);
+ if (ret == -1)
+ return -1;
+ if (ret)
+ return 1; /* UDP fragmentation offloading on */
+#endif
+
+ return 0;
+}
+#else /* SIOCETHTOOL */
+static int
+iface_get_offload(pcap_t *handle _U_)
+{
+ /*
+ * XXX - do we need to get this information if we don't
+ * have the ethtool ioctls? If so, how do we do that?
+ */
+ return 0;
+}
+#endif /* SIOCETHTOOL */
+
+#endif /* HAVE_PACKET_RING */
+
+#endif /* HAVE_PF_PACKET_SOCKETS */
+
+/* ===== Functions to interface to the older kernels ================== */
+
+/*
+ * Try to open a packet socket using the old kernel interface.
+ * Returns 1 on success and a PCAP_ERROR_ value on an error.
+ */
+static int
+activate_old(pcap_t *handle)
+{
+ struct pcap_linux *handlep = handle->priv;
+ int err;
+ int arptype;
+ struct ifreq ifr;
+ const char *device = handle->opt.device;
+ struct utsname utsname;
+ int mtu;
+
+ /*
+ * PF_INET/SOCK_PACKET sockets must be bound to a device, so we
+ * can't support the "any" device.
+ */
+ if (strcmp(device, "any") == 0) {
+ pcap_strlcpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
+ PCAP_ERRBUF_SIZE);
+ return PCAP_ERROR;
+ }
+
+ /* Open the socket */
+ handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
+ if (handle->fd == -1) {
+ err = errno;
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ err, "socket");
+ if (err == EPERM || err == EACCES) {
+ /*
+ * You don't have permission to open the
+ * socket.
+ */
+ return PCAP_ERROR_PERM_DENIED;
+ } else {
+ /*
+ * Other error.
+ */
+ return PCAP_ERROR;
+ }
+ }
+
+ /* It worked - we are using the old interface */
+ handlep->sock_packet = 1;
+
+ /* ...which means we get the link-layer header. */
+ handlep->cooked = 0;
+
+ /* Bind to the given device */
+ if (iface_bind_old(handle->fd, device, handle->errbuf) == -1)
+ return PCAP_ERROR;
+
+ /*
+ * Try to get the link-layer type.
+ */
+ arptype = iface_get_arptype(handle->fd, device, handle->errbuf);
+ if (arptype < 0)
+ return PCAP_ERROR;
+
+ /*
+ * Try to find the DLT_ type corresponding to that
+ * link-layer type.
+ */
+ map_arphrd_to_dlt(handle, handle->fd, arptype, device, 0);
+ if (handle->linktype == -1) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "unknown arptype %d", arptype);
+ return PCAP_ERROR;
+ }
+
+ /* Go to promisc mode if requested */
+
+ if (handle->opt.promisc) {
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SIOCGIFFLAGS");
+ return PCAP_ERROR;
+ }
+ if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
+ /*
+ * Promiscuous mode isn't currently on,
+ * so turn it on, and remember that
+ * we should turn it off when the
+ * pcap_t is closed.
+ */
+
+ /*
+ * If we haven't already done so, arrange
+ * to have "pcap_close_all()" called when
+ * we exit.
+ */
+ if (!pcap_do_addexit(handle)) {
+ /*
+ * "atexit()" failed; don't put
+ * the interface in promiscuous
+ * mode, just give up.
+ */
+ return PCAP_ERROR;
+ }
+
+ ifr.ifr_flags |= IFF_PROMISC;
+ if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SIOCSIFFLAGS");
+ return PCAP_ERROR;
+ }
+ handlep->must_do_on_close |= MUST_CLEAR_PROMISC;
+
+ /*
+ * Add this to the list of pcaps
+ * to close when we exit.
+ */
+ pcap_add_to_pcaps_to_close(handle);
+ }
+ }
+
+ /*
+ * Compute the buffer size.
+ *
+ * We're using SOCK_PACKET, so this might be a 2.0[.x]
+ * kernel, and might require special handling - check.
+ */
+ if (uname(&utsname) < 0 ||
+ strncmp(utsname.release, "2.0", 3) == 0) {
+ /*
+ * Either we couldn't find out what kernel release
+ * this is, or it's a 2.0[.x] kernel.
+ *
+ * In the 2.0[.x] kernel, a "recvfrom()" on
+ * a SOCK_PACKET socket, with MSG_TRUNC set, will
+ * return the number of bytes read, so if we pass
+ * a length based on the snapshot length, it'll
+ * return the number of bytes from the packet
+ * copied to userland, not the actual length
+ * of the packet.
+ *
+ * This means that, for example, the IP dissector
+ * in tcpdump will get handed a packet length less
+ * than the length in the IP header, and will
+ * complain about "truncated-ip".
+ *
+ * So we don't bother trying to copy from the
+ * kernel only the bytes in which we're interested,
+ * but instead copy them all, just as the older
+ * versions of libpcap for Linux did.
+ *
+ * The buffer therefore needs to be big enough to
+ * hold the largest packet we can get from this
+ * device. Unfortunately, we can't get the MRU
+ * of the network; we can only get the MTU. The
+ * MTU may be too small, in which case a packet larger
+ * than the buffer size will be truncated *and* we
+ * won't get the actual packet size.
+ *
+ * However, if the snapshot length is larger than
+ * the buffer size based on the MTU, we use the
+ * snapshot length as the buffer size, instead;
+ * this means that with a sufficiently large snapshot
+ * length we won't artificially truncate packets
+ * to the MTU-based size.
+ *
+ * This mess just one of many problems with packet
+ * capture on 2.0[.x] kernels; you really want a
+ * 2.2[.x] or later kernel if you want packet capture
+ * to work well.
+ */
+ mtu = iface_get_mtu(handle->fd, device, handle->errbuf);
+ if (mtu == -1)
+ return PCAP_ERROR;
+ handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
+ if (handle->bufsize < (u_int)handle->snapshot)
+ handle->bufsize = (u_int)handle->snapshot;
+ } else {
+ /*
+ * This is a 2.2[.x] or later kernel.
+ *
+ * We can safely pass "recvfrom()" a byte count
+ * based on the snapshot length.
+ *
+ * XXX - this "should not happen", as 2.2[.x]
+ * kernels all have PF_PACKET sockets, and there's
+ * no configuration option to disable them without
+ * disabling SOCK_PACKET sockets, because
+ * SOCK_PACKET sockets are implemented in the same
+ * source file, net/packet/af_packet.c. There *is*
+ * an option to disable SOCK_PACKET sockets so that
+ * you only have PF_PACKET sockets, and the kernel
+ * will log warning messages for code that uses
+ * "obsolete (PF_INET,SOCK_PACKET)".
+ */
+ handle->bufsize = (u_int)handle->snapshot;
+ }
+
+ /*
+ * Default value for offset to align link-layer payload
+ * on a 4-byte boundary.
+ */
+ handle->offset = 0;
+
+ /*
+ * SOCK_PACKET sockets don't supply information from
+ * stripped VLAN tags.
+ */
+ handlep->vlan_offset = -1; /* unknown */
+
+ return 1;
+}
+
+/*
+ * Bind the socket associated with FD to the given device using the
+ * interface of the old kernels.
+ */
+static int
+iface_bind_old(int fd, const char *device, char *ebuf)
+{
+ struct sockaddr saddr;
+ int err;
+ socklen_t errlen = sizeof(err);
+
+ memset(&saddr, 0, sizeof(saddr));
+ pcap_strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data));
+ if (bind(fd, &saddr, sizeof(saddr)) == -1) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "bind");
+ return -1;
+ }
+
+ /* Any pending errors, e.g., network is down? */
+
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "getsockopt (SO_ERROR)");
+ return -1;
+ }
+
+ if (err > 0) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ err, "bind");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/* ===== System calls available on all supported kernels ============== */
+
+/*
+ * Query the kernel for the MTU of the given interface.
+ */
+static int
+iface_get_mtu(int fd, const char *device, char *ebuf)
+{
+ struct ifreq ifr;
+
+ if (!device)
+ return BIGGER_THAN_ALL_MTUS;
+
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+
+ if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFMTU");
+ return -1;
+ }
+
+ return ifr.ifr_mtu;
+}
+
+/*
+ * Get the hardware type of the given interface as ARPHRD_xxx constant.
+ */
+static int
+iface_get_arptype(int fd, const char *device, char *ebuf)
+{
+ struct ifreq ifr;
+ int ret;
+
+ memset(&ifr, 0, sizeof(ifr));
+ pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
+ if (errno == ENODEV) {
+ /*
+ * No such device.
+ */
+ ret = PCAP_ERROR_NO_SUCH_DEVICE;
+ } else
+ ret = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFHWADDR");
+ return ret;
+ }
+
+ return ifr.ifr_hwaddr.sa_family;
+}
+
+#ifdef SO_ATTACH_FILTER
+static int
+fix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
+{
+ struct pcap_linux *handlep = handle->priv;
+ size_t prog_size;
+ register int i;
+ register struct bpf_insn *p;
+ struct bpf_insn *f;
+ int len;
+
+ /*
+ * Make a copy of the filter, and modify that copy if
+ * necessary.
+ */
+ prog_size = sizeof(*handle->fcode.bf_insns) * handle->fcode.bf_len;
+ len = handle->fcode.bf_len;
+ f = (struct bpf_insn *)malloc(prog_size);
+ if (f == NULL) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return -1;
+ }
+ memcpy(f, handle->fcode.bf_insns, prog_size);
+ fcode->len = len;
+ fcode->filter = (struct sock_filter *) f;
+
+ for (i = 0; i < len; ++i) {
+ p = &f[i];
+ /*
+ * What type of instruction is this?
+ */
+ switch (BPF_CLASS(p->code)) {
+
+ case BPF_RET:
+ /*
+ * It's a return instruction; are we capturing
+ * in memory-mapped mode?
+ */
+ if (!is_mmapped) {
+ /*
+ * No; is the snapshot length a constant,
+ * rather than the contents of the
+ * accumulator?
+ */
+ if (BPF_MODE(p->code) == BPF_K) {
+ /*
+ * Yes - if the value to be returned,
+ * i.e. the snapshot length, is
+ * anything other than 0, make it
+ * MAXIMUM_SNAPLEN, so that the packet
+ * is truncated by "recvfrom()",
+ * not by the filter.
+ *
+ * XXX - there's nothing we can
+ * easily do if it's getting the
+ * value from the accumulator; we'd
+ * have to insert code to force
+ * non-zero values to be
+ * MAXIMUM_SNAPLEN.
+ */
+ if (p->k != 0)
+ p->k = MAXIMUM_SNAPLEN;
+ }
+ }
+ break;
+
+ case BPF_LD:
+ case BPF_LDX:
+ /*
+ * It's a load instruction; is it loading
+ * from the packet?
+ */
+ switch (BPF_MODE(p->code)) {
+
+ case BPF_ABS:
+ case BPF_IND:
+ case BPF_MSH:
+ /*
+ * Yes; are we in cooked mode?
+ */
+ if (handlep->cooked) {
+ /*
+ * Yes, so we need to fix this
+ * instruction.
+ */
+ if (fix_offset(handle, p) < 0) {
+ /*
+ * We failed to do so.
+ * Return 0, so our caller
+ * knows to punt to userland.
+ */
+ return 0;
+ }
+ }
+ break;
+ }
+ break;
+ }
+ }
+ return 1; /* we succeeded */
+}
+
+static int
+fix_offset(pcap_t *handle, struct bpf_insn *p)
+{
+ /*
+ * Existing references to auxiliary data shouldn't be adjusted.
+ *
+ * Note that SKF_AD_OFF is negative, but p->k is unsigned, so
+ * we use >= and cast SKF_AD_OFF to unsigned.
+ */
+ if (p->k >= (bpf_u_int32)SKF_AD_OFF)
+ return 0;
+ if (handle->linktype == DLT_LINUX_SLL2) {
+ /*
+ * What's the offset?
+ */
+ if (p->k >= SLL2_HDR_LEN) {
+ /*
+ * It's within the link-layer payload; that starts
+ * at an offset of 0, as far as the kernel packet
+ * filter is concerned, so subtract the length of
+ * the link-layer header.
+ */
+ p->k -= SLL2_HDR_LEN;
+ } else if (p->k == 0) {
+ /*
+ * It's the protocol field; map it to the
+ * special magic kernel offset for that field.
+ */
+ p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+ } else if (p->k == 10) {
+ /*
+ * It's the packet type field; map it to the
+ * special magic kernel offset for that field.
+ */
+ p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
+ } else if ((bpf_int32)(p->k) > 0) {
+ /*
+ * It's within the header, but it's not one of
+ * those fields; we can't do that in the kernel,
+ * so punt to userland.
+ */
+ return -1;
+ }
+ } else {
+ /*
+ * What's the offset?
+ */
+ if (p->k >= SLL_HDR_LEN) {
+ /*
+ * It's within the link-layer payload; that starts
+ * at an offset of 0, as far as the kernel packet
+ * filter is concerned, so subtract the length of
+ * the link-layer header.
+ */
+ p->k -= SLL_HDR_LEN;
+ } else if (p->k == 0) {
+ /*
+ * It's the packet type field; map it to the
+ * special magic kernel offset for that field.
+ */
+ p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
+ } else if (p->k == 14) {
+ /*
+ * It's the protocol field; map it to the
+ * special magic kernel offset for that field.
+ */
+ p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
+ } else if ((bpf_int32)(p->k) > 0) {
+ /*
+ * It's within the header, but it's not one of
+ * those fields; we can't do that in the kernel,
+ * so punt to userland.
+ */
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
+{
+ int total_filter_on = 0;
+ int save_mode;
+ int ret;
+ int save_errno;
+
+ /*
+ * The socket filter code doesn't discard all packets queued
+ * up on the socket when the filter is changed; this means
+ * that packets that don't match the new filter may show up
+ * after the new filter is put onto the socket, if those
+ * packets haven't yet been read.
+ *
+ * This means, for example, that if you do a tcpdump capture
+ * with a filter, the first few packets in the capture might
+ * be packets that wouldn't have passed the filter.
+ *
+ * We therefore discard all packets queued up on the socket
+ * when setting a kernel filter. (This isn't an issue for
+ * userland filters, as the userland filtering is done after
+ * packets are queued up.)
+ *
+ * To flush those packets, we put the socket in read-only mode,
+ * and read packets from the socket until there are no more to
+ * read.
+ *
+ * In order to keep that from being an infinite loop - i.e.,
+ * to keep more packets from arriving while we're draining
+ * the queue - we put the "total filter", which is a filter
+ * that rejects all packets, onto the socket before draining
+ * the queue.
+ *
+ * This code deliberately ignores any errors, so that you may
+ * get bogus packets if an error occurs, rather than having
+ * the filtering done in userland even if it could have been
+ * done in the kernel.
+ */
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
+ &total_fcode, sizeof(total_fcode)) == 0) {
+ char drain[1];
+
+ /*
+ * Note that we've put the total filter onto the socket.
+ */
+ total_filter_on = 1;
+
+ /*
+ * Save the socket's current mode, and put it in
+ * non-blocking mode; we drain it by reading packets
+ * until we get an error (which is normally a
+ * "nothing more to be read" error).
+ */
+ save_mode = fcntl(handle->fd, F_GETFL, 0);
+ if (save_mode == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "can't get FD flags when changing filter");
+ return -2;
+ }
+ if (fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "can't set nonblocking mode when changing filter");
+ return -2;
+ }
+ while (recv(handle->fd, &drain, sizeof drain, MSG_TRUNC) >= 0)
+ ;
+ save_errno = errno;
+ if (save_errno != EAGAIN) {
+ /*
+ * Fatal error.
+ *
+ * If we can't restore the mode or reset the
+ * kernel filter, there's nothing we can do.
+ */
+ (void)fcntl(handle->fd, F_SETFL, save_mode);
+ (void)reset_kernel_filter(handle);
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, save_errno,
+ "recv failed when changing filter");
+ return -2;
+ }
+ if (fcntl(handle->fd, F_SETFL, save_mode) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "can't restore FD flags when changing filter");
+ return -2;
+ }
+ }
+
+ /*
+ * Now attach the new filter.
+ */
+ ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
+ fcode, sizeof(*fcode));
+ if (ret == -1 && total_filter_on) {
+ /*
+ * Well, we couldn't set that filter on the socket,
+ * but we could set the total filter on the socket.
+ *
+ * This could, for example, mean that the filter was
+ * too big to put into the kernel, so we'll have to
+ * filter in userland; in any case, we'll be doing
+ * filtering in userland, so we need to remove the
+ * total filter so we see packets.
+ */
+ save_errno = errno;
+
+ /*
+ * If this fails, we're really screwed; we have the
+ * total filter on the socket, and it won't come off.
+ * Report it as a fatal error.
+ */
+ if (reset_kernel_filter(handle) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "can't remove kernel total filter");
+ return -2; /* fatal error */
+ }
+
+ errno = save_errno;
+ }
+ return ret;
+}
+
+static int
+reset_kernel_filter(pcap_t *handle)
+{
+ int ret;
+ /*
+ * setsockopt() barfs unless it get a dummy parameter.
+ * valgrind whines unless the value is initialized,
+ * as it has no idea that setsockopt() ignores its
+ * parameter.
+ */
+ int dummy = 0;
+
+ ret = setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,
+ &dummy, sizeof(dummy));
+ /*
+ * Ignore ENOENT - it means "we don't have a filter", so there
+ * was no filter to remove, and there's still no filter.
+ *
+ * Also ignore ENONET, as a lot of kernel versions had a
+ * typo where ENONET, rather than ENOENT, was returned.
+ */
+ if (ret == -1 && errno != ENOENT && errno != ENONET)
+ return -1;
+ return 0;
+}
+#endif
+
+int
+pcap_set_protocol_linux(pcap_t *p, int protocol)
+{
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ p->opt.protocol = protocol;
+ return (0);
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+#ifdef HAVE_PACKET_RING
+ #if defined(HAVE_TPACKET3)
+ return (PCAP_VERSION_STRING " (with TPACKET_V3)");
+ #elif defined(HAVE_TPACKET2)
+ return (PCAP_VERSION_STRING " (with TPACKET_V2)");
+ #else
+ return (PCAP_VERSION_STRING " (with TPACKET_V1)");
+ #endif
+#else
+ return (PCAP_VERSION_STRING " (without TPACKET)");
+#endif
+}
diff --git a/lib/libpcap/libpcap/pcap-namedb.h b/lib/libpcap/libpcap/pcap-namedb.h
new file mode 100644
index 0000000..d5908c9
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-namedb.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file! Some applications
+ * might expect to be able to include <pcap-namedb.h>.
+ */
+#include <pcap/namedb.h>
diff --git a/lib/libpcap/libpcap/pcap-netfilter-linux.c b/lib/libpcap/libpcap/pcap-netfilter-linux.c
new file mode 100644
index 0000000..91bad37
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-netfilter-linux.c
@@ -0,0 +1,761 @@
+/*
+ * Copyright (c) 2011 Jakub Zawadzki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pcap-int.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+
+#include <time.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <linux/types.h>
+
+#include <linux/netlink.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter/nfnetlink.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/netfilter/nfnetlink_queue.h>
+
+/* NOTE: if your program drops privilages after pcap_activate() it WON'T work with nfqueue.
+ * It took me quite some time to debug ;/
+ *
+ * Sending any data to nfnetlink socket requires CAP_NET_ADMIN privilages,
+ * and in nfqueue we need to send verdict reply after recving packet.
+ *
+ * In tcpdump you can disable dropping privilages with -Z root
+ */
+
+#include "pcap-netfilter-linux.h"
+
+#define HDR_LENGTH (NLMSG_LENGTH(NLMSG_ALIGN(sizeof(struct nfgenmsg))))
+
+#define NFLOG_IFACE "nflog"
+#define NFQUEUE_IFACE "nfqueue"
+
+typedef enum { OTHER = -1, NFLOG, NFQUEUE } nftype_t;
+
+/*
+ * Private data for capturing on Linux netfilter sockets.
+ */
+struct pcap_netfilter {
+ u_int packets_read; /* count of packets read with recvfrom() */
+ u_int packets_nobufs; /* ENOBUFS counter */
+};
+
+static int nfqueue_send_verdict(const pcap_t *handle, uint16_t group_id, u_int32_t id, u_int32_t verdict);
+
+
+static int
+netfilter_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+ struct pcap_netfilter *handlep = handle->priv;
+ register u_char *bp, *ep;
+ int count = 0;
+ int len;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (handle->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return PCAP_ERROR_BREAK to indicate
+ * that we were told to break out of the loop.
+ */
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ len = handle->cc;
+ if (len == 0) {
+ /*
+ * The buffer is empty; refill it.
+ *
+ * We ignore EINTR, as that might just be due to a signal
+ * being delivered - if the signal should interrupt the
+ * loop, the signal handler should call pcap_breakloop()
+ * to set handle->break_loop (we ignore it on other
+ * platforms as well).
+ */
+ do {
+ len = recv(handle->fd, handle->buffer, handle->bufsize, 0);
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ if (errno == ENOBUFS)
+ handlep->packets_nobufs++;
+ } while ((len == -1) && (errno == EINTR || errno == ENOBUFS));
+
+ if (len < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "Can't receive packet");
+ return PCAP_ERROR;
+ }
+
+ bp = (unsigned char *)handle->buffer;
+ } else
+ bp = handle->bp;
+ ep = bp + len;
+ while (bp < ep) {
+ const struct nlmsghdr *nlh = (const struct nlmsghdr *) bp;
+ uint32_t msg_len;
+ nftype_t type = OTHER;
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return PCAP_ERROR_BREAK
+ * to indicate that we were told to break out of the loop,
+ * otherwise leave the flag set, so that the *next* call
+ * will break out of the loop without having read any
+ * packets, and return the number of packets we've
+ * processed so far.
+ */
+ if (handle->break_loop) {
+ handle->bp = bp;
+ handle->cc = ep - bp;
+ if (count == 0) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ } else
+ return count;
+ }
+ if (ep - bp < NLMSG_SPACE(0)) {
+ /*
+ * There's less than one netlink message left
+ * in the buffer. Give up.
+ */
+ break;
+ }
+
+ if (nlh->nlmsg_len < sizeof(struct nlmsghdr) || (u_int)len < nlh->nlmsg_len) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Message truncated: (got: %d) (nlmsg_len: %u)", len, nlh->nlmsg_len);
+ return -1;
+ }
+
+ if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_ULOG &&
+ NFNL_MSG_TYPE(nlh->nlmsg_type) == NFULNL_MSG_PACKET)
+ type = NFLOG;
+ else if (NFNL_SUBSYS_ID(nlh->nlmsg_type) == NFNL_SUBSYS_QUEUE &&
+ NFNL_MSG_TYPE(nlh->nlmsg_type) == NFQNL_MSG_PACKET)
+ type = NFQUEUE;
+
+ if (type != OTHER) {
+ const unsigned char *payload = NULL;
+ struct pcap_pkthdr pkth;
+
+ const struct nfgenmsg *nfg = NULL;
+ int id = 0;
+
+ if (handle->linktype != DLT_NFLOG) {
+ const struct nfattr *payload_attr = NULL;
+
+ if (nlh->nlmsg_len < HDR_LENGTH) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "Malformed message: (nlmsg_len: %u)", nlh->nlmsg_len);
+ return -1;
+ }
+
+ nfg = NLMSG_DATA(nlh);
+ if (nlh->nlmsg_len > HDR_LENGTH) {
+ struct nfattr *attr = NFM_NFA(nfg);
+ int attr_len = nlh->nlmsg_len - NLMSG_ALIGN(HDR_LENGTH);
+
+ while (NFA_OK(attr, attr_len)) {
+ if (type == NFQUEUE) {
+ switch (NFA_TYPE(attr)) {
+ case NFQA_PACKET_HDR:
+ {
+ const struct nfqnl_msg_packet_hdr *pkt_hdr = (const struct nfqnl_msg_packet_hdr *) NFA_DATA(attr);
+
+ id = ntohl(pkt_hdr->packet_id);
+ break;
+ }
+ case NFQA_PAYLOAD:
+ payload_attr = attr;
+ break;
+ }
+
+ } else if (type == NFLOG) {
+ switch (NFA_TYPE(attr)) {
+ case NFULA_PAYLOAD:
+ payload_attr = attr;
+ break;
+ }
+ }
+ attr = NFA_NEXT(attr, attr_len);
+ }
+ }
+
+ if (payload_attr) {
+ payload = NFA_DATA(payload_attr);
+ pkth.len = pkth.caplen = NFA_PAYLOAD(payload_attr);
+ }
+
+ } else {
+ payload = NLMSG_DATA(nlh);
+ pkth.caplen = pkth.len = nlh->nlmsg_len-NLMSG_ALIGN(sizeof(struct nlmsghdr));
+ }
+
+ if (payload) {
+ /* pkth.caplen = min (payload_len, handle->snapshot); */
+
+ gettimeofday(&pkth.ts, NULL);
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, payload, pkth.len, pkth.caplen))
+ {
+ handlep->packets_read++;
+ callback(user, &pkth, payload);
+ count++;
+ }
+ }
+
+ if (type == NFQUEUE) {
+ /* XXX, possible responses: NF_DROP, NF_ACCEPT, NF_STOLEN, NF_QUEUE, NF_REPEAT, NF_STOP */
+ /* if type == NFQUEUE, handle->linktype is always != DLT_NFLOG,
+ so nfg is always initialized to NLMSG_DATA(nlh). */
+ if (nfg != NULL)
+ nfqueue_send_verdict(handle, ntohs(nfg->res_id), id, NF_ACCEPT);
+ }
+ }
+
+ msg_len = NLMSG_ALIGN(nlh->nlmsg_len);
+ /*
+ * If the message length would run past the end of the
+ * buffer, truncate it to the remaining space in the
+ * buffer.
+ */
+ if (msg_len > ep - bp)
+ msg_len = ep - bp;
+
+ bp += msg_len;
+ if (count >= max_packets && !PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ handle->bp = bp;
+ handle->cc = ep - bp;
+ if (handle->cc < 0)
+ handle->cc = 0;
+ return count;
+ }
+ }
+
+ handle->cc = 0;
+ return count;
+}
+
+static int
+netfilter_set_datalink(pcap_t *handle, int dlt)
+{
+ handle->linktype = dlt;
+ return 0;
+}
+
+static int
+netfilter_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+ struct pcap_netfilter *handlep = handle->priv;
+
+ stats->ps_recv = handlep->packets_read;
+ stats->ps_drop = handlep->packets_nobufs;
+ stats->ps_ifdrop = 0;
+ return 0;
+}
+
+static int
+netfilter_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
+{
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Packet injection is not supported on netfilter devices");
+ return (-1);
+}
+
+struct my_nfattr {
+ uint16_t nfa_len;
+ uint16_t nfa_type;
+ void *data;
+};
+
+static int
+netfilter_send_config_msg(const pcap_t *handle, uint16_t msg_type, int ack, u_int8_t family, u_int16_t res_id, const struct my_nfattr *mynfa)
+{
+ char buf[1024] __attribute__ ((aligned));
+ memset(buf, 0, sizeof(buf));
+
+ struct nlmsghdr *nlh = (struct nlmsghdr *) buf;
+ struct nfgenmsg *nfg = (struct nfgenmsg *) (buf + sizeof(struct nlmsghdr));
+
+ struct sockaddr_nl snl;
+ static unsigned int seq_id;
+
+ if (!seq_id)
+ seq_id = time(NULL);
+ ++seq_id;
+
+ nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct nfgenmsg));
+ nlh->nlmsg_type = msg_type;
+ nlh->nlmsg_flags = NLM_F_REQUEST | (ack ? NLM_F_ACK : 0);
+ nlh->nlmsg_pid = 0; /* to kernel */
+ nlh->nlmsg_seq = seq_id;
+
+ nfg->nfgen_family = family;
+ nfg->version = NFNETLINK_V0;
+ nfg->res_id = htons(res_id);
+
+ if (mynfa) {
+ struct nfattr *nfa = (struct nfattr *) (buf + NLMSG_ALIGN(nlh->nlmsg_len));
+
+ nfa->nfa_type = mynfa->nfa_type;
+ nfa->nfa_len = NFA_LENGTH(mynfa->nfa_len);
+ memcpy(NFA_DATA(nfa), mynfa->data, mynfa->nfa_len);
+ nlh->nlmsg_len = NLMSG_ALIGN(nlh->nlmsg_len) + NFA_ALIGN(nfa->nfa_len);
+ }
+
+ memset(&snl, 0, sizeof(snl));
+ snl.nl_family = AF_NETLINK;
+
+ if (sendto(handle->fd, nlh, nlh->nlmsg_len, 0, (struct sockaddr *) &snl, sizeof(snl)) == -1)
+ return -1;
+
+ if (!ack)
+ return 0;
+
+ /* waiting for reply loop */
+ do {
+ socklen_t addrlen = sizeof(snl);
+ int len;
+
+ /* ignore interrupt system call error */
+ do {
+ len = recvfrom(handle->fd, buf, sizeof(buf), 0, (struct sockaddr *) &snl, &addrlen);
+ } while ((len == -1) && (errno == EINTR));
+
+ if (len <= 0)
+ return len;
+
+ if (addrlen != sizeof(snl) || snl.nl_family != AF_NETLINK) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ nlh = (struct nlmsghdr *) buf;
+ if (snl.nl_pid != 0 || seq_id != nlh->nlmsg_seq) /* if not from kernel or wrong sequence skip */
+ continue;
+
+ while ((u_int)len >= NLMSG_SPACE(0) && NLMSG_OK(nlh, (u_int)len)) {
+ if (nlh->nlmsg_type == NLMSG_ERROR || (nlh->nlmsg_type == NLMSG_DONE && nlh->nlmsg_flags & NLM_F_MULTI)) {
+ if (nlh->nlmsg_len < NLMSG_ALIGN(sizeof(struct nlmsgerr))) {
+ errno = EBADMSG;
+ return -1;
+ }
+ errno = -(*((int *)NLMSG_DATA(nlh)));
+ return (errno == 0) ? 0 : -1;
+ }
+ nlh = NLMSG_NEXT(nlh, len);
+ }
+ } while (1);
+
+ return -1; /* never here */
+}
+
+static int
+nflog_send_config_msg(const pcap_t *handle, uint8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
+{
+ return netfilter_send_config_msg(handle, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG, 1, family, group_id, mynfa);
+}
+
+static int
+nflog_send_config_cmd(const pcap_t *handle, uint16_t group_id, u_int8_t cmd, u_int8_t family)
+{
+ struct nfulnl_msg_config_cmd msg;
+ struct my_nfattr nfa;
+
+ msg.command = cmd;
+
+ nfa.data = &msg;
+ nfa.nfa_type = NFULA_CFG_CMD;
+ nfa.nfa_len = sizeof(msg);
+
+ return nflog_send_config_msg(handle, family, group_id, &nfa);
+}
+
+static int
+nflog_send_config_mode(const pcap_t *handle, uint16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
+{
+ struct nfulnl_msg_config_mode msg;
+ struct my_nfattr nfa;
+
+ msg.copy_range = htonl(copy_range);
+ msg.copy_mode = copy_mode;
+
+ nfa.data = &msg;
+ nfa.nfa_type = NFULA_CFG_MODE;
+ nfa.nfa_len = sizeof(msg);
+
+ return nflog_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
+}
+
+static int
+nfqueue_send_verdict(const pcap_t *handle, uint16_t group_id, u_int32_t id, u_int32_t verdict)
+{
+ struct nfqnl_msg_verdict_hdr msg;
+ struct my_nfattr nfa;
+
+ msg.id = htonl(id);
+ msg.verdict = htonl(verdict);
+
+ nfa.data = &msg;
+ nfa.nfa_type = NFQA_VERDICT_HDR;
+ nfa.nfa_len = sizeof(msg);
+
+ return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_VERDICT, 0, AF_UNSPEC, group_id, &nfa);
+}
+
+static int
+nfqueue_send_config_msg(const pcap_t *handle, uint8_t family, u_int16_t group_id, const struct my_nfattr *mynfa)
+{
+ return netfilter_send_config_msg(handle, (NFNL_SUBSYS_QUEUE << 8) | NFQNL_MSG_CONFIG, 1, family, group_id, mynfa);
+}
+
+static int
+nfqueue_send_config_cmd(const pcap_t *handle, uint16_t group_id, u_int8_t cmd, u_int16_t pf)
+{
+ struct nfqnl_msg_config_cmd msg;
+ struct my_nfattr nfa;
+
+ msg.command = cmd;
+ msg.pf = htons(pf);
+
+ nfa.data = &msg;
+ nfa.nfa_type = NFQA_CFG_CMD;
+ nfa.nfa_len = sizeof(msg);
+
+ return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
+}
+
+static int
+nfqueue_send_config_mode(const pcap_t *handle, uint16_t group_id, u_int8_t copy_mode, u_int32_t copy_range)
+{
+ struct nfqnl_msg_config_params msg;
+ struct my_nfattr nfa;
+
+ msg.copy_range = htonl(copy_range);
+ msg.copy_mode = copy_mode;
+
+ nfa.data = &msg;
+ nfa.nfa_type = NFQA_CFG_PARAMS;
+ nfa.nfa_len = sizeof(msg);
+
+ return nfqueue_send_config_msg(handle, AF_UNSPEC, group_id, &nfa);
+}
+
+static int
+netfilter_activate(pcap_t* handle)
+{
+ const char *dev = handle->opt.device;
+ unsigned short groups[32];
+ int group_count = 0;
+ nftype_t type = OTHER;
+ int i;
+
+ if (strncmp(dev, NFLOG_IFACE, strlen(NFLOG_IFACE)) == 0) {
+ dev += strlen(NFLOG_IFACE);
+ type = NFLOG;
+
+ } else if (strncmp(dev, NFQUEUE_IFACE, strlen(NFQUEUE_IFACE)) == 0) {
+ dev += strlen(NFQUEUE_IFACE);
+ type = NFQUEUE;
+ }
+
+ if (type != OTHER && *dev == ':') {
+ dev++;
+ while (*dev) {
+ long int group_id;
+ char *end_dev;
+
+ if (group_count == 32) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Maximum 32 netfilter groups! dev: %s",
+ handle->opt.device);
+ return PCAP_ERROR;
+ }
+
+ group_id = strtol(dev, &end_dev, 0);
+ if (end_dev != dev) {
+ if (group_id < 0 || group_id > 65535) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Netfilter group range from 0 to 65535 (got %ld)",
+ group_id);
+ return PCAP_ERROR;
+ }
+
+ groups[group_count++] = (unsigned short) group_id;
+ dev = end_dev;
+ }
+ if (*dev != ',')
+ break;
+ dev++;
+ }
+ }
+
+ if (type == OTHER || *dev) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get netfilter group(s) index from %s",
+ handle->opt.device);
+ return PCAP_ERROR;
+ }
+
+ /* if no groups, add default: 0 */
+ if (!group_count) {
+ groups[0] = 0;
+ group_count = 1;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+ handle->snapshot = MAXIMUM_SNAPLEN;
+
+ /* Initialize some components of the pcap structure. */
+ handle->bufsize = 128 + handle->snapshot;
+ handle->offset = 0;
+ handle->read_op = netfilter_read_linux;
+ handle->inject_op = netfilter_inject_linux;
+ handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+ handle->setdirection_op = NULL;
+ handle->set_datalink_op = netfilter_set_datalink;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->stats_op = netfilter_stats_linux;
+
+ /* Create netlink socket */
+ handle->fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+ if (handle->fd < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't create raw socket");
+ return PCAP_ERROR;
+ }
+
+ if (type == NFLOG) {
+ handle->linktype = DLT_NFLOG;
+ handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ if (handle->dlt_list != NULL) {
+ handle->dlt_list[0] = DLT_NFLOG;
+ handle->dlt_list[1] = DLT_IPV4;
+ handle->dlt_count = 2;
+ }
+
+ } else
+ handle->linktype = DLT_IPV4;
+
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't allocate dump buffer");
+ goto close_fail;
+ }
+
+ if (type == NFLOG) {
+ if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "NFULNL_CFG_CMD_PF_UNBIND");
+ goto close_fail;
+ }
+
+ if (nflog_send_config_cmd(handle, 0, NFULNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "NFULNL_CFG_CMD_PF_BIND");
+ goto close_fail;
+ }
+
+ /* Bind socket to the nflog groups */
+ for (i = 0; i < group_count; i++) {
+ if (nflog_send_config_cmd(handle, groups[i], NFULNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't listen on group group index");
+ goto close_fail;
+ }
+
+ if (nflog_send_config_mode(handle, groups[i], NFULNL_COPY_PACKET, handle->snapshot) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "NFULNL_COPY_PACKET");
+ goto close_fail;
+ }
+ }
+
+ } else {
+ if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_UNBIND, AF_INET) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "NFQNL_CFG_CMD_PF_UNBIND");
+ goto close_fail;
+ }
+
+ if (nfqueue_send_config_cmd(handle, 0, NFQNL_CFG_CMD_PF_BIND, AF_INET) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "NFQNL_CFG_CMD_PF_BIND");
+ goto close_fail;
+ }
+
+ /* Bind socket to the nfqueue groups */
+ for (i = 0; i < group_count; i++) {
+ if (nfqueue_send_config_cmd(handle, groups[i], NFQNL_CFG_CMD_BIND, AF_UNSPEC) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't listen on group group index");
+ goto close_fail;
+ }
+
+ if (nfqueue_send_config_mode(handle, groups[i], NFQNL_COPY_PACKET, handle->snapshot) < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "NFQNL_COPY_PACKET");
+ goto close_fail;
+ }
+ }
+ }
+
+ if (handle->opt.rfmon) {
+ /*
+ * Monitor mode doesn't apply to netfilter devices.
+ */
+ pcap_cleanup_live_common(handle);
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ if (handle->opt.buffer_size != 0) {
+ /*
+ * Set the socket buffer size to the specified value.
+ */
+ if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, &handle->opt.buffer_size, sizeof(handle->opt.buffer_size)) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "SO_RCVBUF");
+ goto close_fail;
+ }
+ }
+
+ handle->selectable_fd = handle->fd;
+ return 0;
+
+close_fail:
+ pcap_cleanup_live_common(handle);
+ return PCAP_ERROR;
+}
+
+pcap_t *
+netfilter_create(const char *device, char *ebuf, int *is_ours)
+{
+ const char *cp;
+ pcap_t *p;
+
+ /* Does this look like an netfilter device? */
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+
+ /* Does it begin with NFLOG_IFACE or NFQUEUE_IFACE? */
+ if (strncmp(cp, NFLOG_IFACE, sizeof NFLOG_IFACE - 1) == 0)
+ cp += sizeof NFLOG_IFACE - 1;
+ else if (strncmp(cp, NFQUEUE_IFACE, sizeof NFQUEUE_IFACE - 1) == 0)
+ cp += sizeof NFQUEUE_IFACE - 1;
+ else {
+ /* Nope, doesn't begin with NFLOG_IFACE nor NFQUEUE_IFACE */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /*
+ * Yes - is that either the end of the name, or is it followed
+ * by a colon?
+ */
+ if (*cp != ':' && *cp != '\0') {
+ /* Nope */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_netfilter));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = netfilter_activate;
+ return (p);
+}
+
+int
+netfilter_findalldevs(pcap_if_list_t *devlistp, char *err_str)
+{
+ int sock;
+
+ sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_NETFILTER);
+ if (sock < 0) {
+ /* if netlink is not supported this is not fatal */
+ if (errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT)
+ return 0;
+ pcap_fmt_errmsg_for_errno(err_str, PCAP_ERRBUF_SIZE,
+ errno, "Can't open netlink socket");
+ return -1;
+ }
+ close(sock);
+
+ /*
+ * The notion of "connected" vs. "disconnected" doesn't apply.
+ * XXX - what about "up" and "running"?
+ */
+ if (add_dev(devlistp, NFLOG_IFACE,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ "Linux netfilter log (NFLOG) interface", err_str) == NULL)
+ return -1;
+ if (add_dev(devlistp, NFQUEUE_IFACE,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ "Linux netfilter queue (NFQUEUE) interface", err_str) == NULL)
+ return -1;
+ return 0;
+}
diff --git a/lib/libpcap/libpcap/pcap-netfilter-linux.h b/lib/libpcap/libpcap/pcap-netfilter-linux.h
new file mode 100644
index 0000000..97b7310
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-netfilter-linux.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2011 Jakub Zawadzki
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Prototypes for netlink-related functions
+ */
+int netfilter_findalldevs(pcap_if_list_t *devlistp, char *err_str);
+pcap_t *netfilter_create(const char *device, char *ebuf, int *is_ours);
diff --git a/lib/libpcap/libpcap/pcap-netmap.c b/lib/libpcap/libpcap/pcap-netmap.c
new file mode 100644
index 0000000..b2301a7
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-netmap.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2014 Luigi Rizzo. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <poll.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define NETMAP_WITH_LIBS
+#include <net/netmap_user.h>
+
+#include "pcap-int.h"
+#include "pcap-netmap.h"
+
+#ifndef __FreeBSD__
+ /*
+ * On FreeBSD we use IFF_PPROMISC which is in ifr_flagshigh.
+ * Remap to IFF_PROMISC on other platforms.
+ *
+ * XXX - DragonFly BSD?
+ */
+ #define IFF_PPROMISC IFF_PROMISC
+#endif /* __FreeBSD__ */
+
+struct pcap_netmap {
+ struct nm_desc *d; /* pointer returned by nm_open() */
+ pcap_handler cb; /* callback and argument */
+ u_char *cb_arg;
+ int must_clear_promisc; /* flag */
+ uint64_t rx_pkts; /* # of pkts received before the filter */
+};
+
+
+static int
+pcap_netmap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_netmap *pn = p->priv;
+
+ ps->ps_recv = (u_int)pn->rx_pkts;
+ ps->ps_drop = 0;
+ ps->ps_ifdrop = 0;
+ return 0;
+}
+
+
+static void
+pcap_netmap_filter(u_char *arg, struct pcap_pkthdr *h, const u_char *buf)
+{
+ pcap_t *p = (pcap_t *)arg;
+ struct pcap_netmap *pn = p->priv;
+ const struct bpf_insn *pc = p->fcode.bf_insns;
+
+ ++pn->rx_pkts;
+ if (pc == NULL || bpf_filter(pc, buf, h->len, h->caplen))
+ pn->cb(pn->cb_arg, h, buf);
+}
+
+
+static int
+pcap_netmap_dispatch(pcap_t *p, int cnt, pcap_handler cb, u_char *user)
+{
+ int ret;
+ struct pcap_netmap *pn = p->priv;
+ struct nm_desc *d = pn->d;
+ struct pollfd pfd = { .fd = p->fd, .events = POLLIN, .revents = 0 };
+
+ pn->cb = cb;
+ pn->cb_arg = user;
+
+ for (;;) {
+ if (p->break_loop) {
+ p->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ /* nm_dispatch won't run forever */
+
+ ret = nm_dispatch((void *)d, cnt, (void *)pcap_netmap_filter, (void *)p);
+ if (ret != 0)
+ break;
+ errno = 0;
+ ret = poll(&pfd, 1, p->opt.timeout);
+ }
+ return ret;
+}
+
+
+/* XXX need to check the NIOCTXSYNC/poll */
+static int
+pcap_netmap_inject(pcap_t *p, const void *buf, size_t size)
+{
+ struct pcap_netmap *pn = p->priv;
+ struct nm_desc *d = pn->d;
+
+ return nm_inject(d, buf, size);
+}
+
+
+static int
+pcap_netmap_ioctl(pcap_t *p, u_long what, uint32_t *if_flags)
+{
+ struct pcap_netmap *pn = p->priv;
+ struct nm_desc *d = pn->d;
+ struct ifreq ifr;
+ int error, fd = d->fd;
+
+#ifdef linux
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ fprintf(stderr, "Error: cannot get device control socket.\n");
+ return -1;
+ }
+#endif /* linux */
+ bzero(&ifr, sizeof(ifr));
+ strncpy(ifr.ifr_name, d->req.nr_name, sizeof(ifr.ifr_name));
+ switch (what) {
+ case SIOCSIFFLAGS:
+ /*
+ * The flags we pass in are 32-bit and unsigned.
+ *
+ * On most if not all UN*Xes, ifr_flags is 16-bit and
+ * signed, and the result of assigning a longer
+ * unsigned value to a shorter signed value is
+ * implementation-defined (even if, in practice, it'll
+ * do what's intended on all platforms we support
+ * result of assigning a 32-bit unsigned value).
+ * So we mask out the upper 16 bits.
+ */
+ ifr.ifr_flags = *if_flags & 0xffff;
+#ifdef __FreeBSD__
+ /*
+ * In FreeBSD, we need to set the high-order flags,
+ * as we're using IFF_PPROMISC, which is in those bits.
+ *
+ * XXX - DragonFly BSD?
+ */
+ ifr.ifr_flagshigh = *if_flags >> 16;
+#endif /* __FreeBSD__ */
+ break;
+ }
+ error = ioctl(fd, what, &ifr);
+ if (!error) {
+ switch (what) {
+ case SIOCGIFFLAGS:
+ /*
+ * The flags we return are 32-bit.
+ *
+ * On most if not all UN*Xes, ifr_flags is
+ * 16-bit and signed, and will get sign-
+ * extended, so that the upper 16 bits of
+ * those flags will be forced on. So we
+ * mask out the upper 16 bits of the
+ * sign-extended value.
+ */
+ *if_flags = ifr.ifr_flags & 0xffff;
+#ifdef __FreeBSD__
+ /*
+ * In FreeBSD, we need to return the
+ * high-order flags, as we're using
+ * IFF_PPROMISC, which is in those bits.
+ *
+ * XXX - DragonFly BSD?
+ */
+ *if_flags |= (ifr.ifr_flagshigh << 16);
+#endif /* __FreeBSD__ */
+ }
+ }
+#ifdef linux
+ close(fd);
+#endif /* linux */
+ return error ? -1 : 0;
+}
+
+
+static void
+pcap_netmap_close(pcap_t *p)
+{
+ struct pcap_netmap *pn = p->priv;
+ struct nm_desc *d = pn->d;
+ uint32_t if_flags = 0;
+
+ if (pn->must_clear_promisc) {
+ pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+ if (if_flags & IFF_PPROMISC) {
+ if_flags &= ~IFF_PPROMISC;
+ pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+ }
+ }
+ nm_close(d);
+ pcap_cleanup_live_common(p);
+}
+
+
+static int
+pcap_netmap_activate(pcap_t *p)
+{
+ struct pcap_netmap *pn = p->priv;
+ struct nm_desc *d;
+ uint32_t if_flags = 0;
+
+ d = nm_open(p->opt.device, NULL, 0, NULL);
+ if (d == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "netmap open: cannot access %s",
+ p->opt.device);
+ pcap_cleanup_live_common(p);
+ return (PCAP_ERROR);
+ }
+#if 0
+ fprintf(stderr, "%s device %s priv %p fd %d ports %d..%d\n",
+ __FUNCTION__, p->opt.device, d, d->fd,
+ d->first_rx_ring, d->last_rx_ring);
+#endif
+ pn->d = d;
+ p->fd = d->fd;
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ if (p->opt.promisc && !(d->req.nr_ringid & NETMAP_SW_RING)) {
+ pcap_netmap_ioctl(p, SIOCGIFFLAGS, &if_flags); /* fetch flags */
+ if (!(if_flags & IFF_PPROMISC)) {
+ pn->must_clear_promisc = 1;
+ if_flags |= IFF_PPROMISC;
+ pcap_netmap_ioctl(p, SIOCSIFFLAGS, &if_flags);
+ }
+ }
+ p->linktype = DLT_EN10MB;
+ p->selectable_fd = p->fd;
+ p->read_op = pcap_netmap_dispatch;
+ p->inject_op = pcap_netmap_inject;
+ p->setfilter_op = install_bpf_program;
+ p->setdirection_op = NULL;
+ p->set_datalink_op = NULL;
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_netmap_stats;
+ p->cleanup_op = pcap_netmap_close;
+
+ return (0);
+}
+
+
+pcap_t *
+pcap_netmap_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *p;
+
+ *is_ours = (!strncmp(device, "netmap:", 7) || !strncmp(device, "vale", 4));
+ if (! *is_ours)
+ return NULL;
+ p = pcap_create_common(ebuf, sizeof (struct pcap_netmap));
+ if (p == NULL)
+ return (NULL);
+ p->activate_op = pcap_netmap_activate;
+ return (p);
+}
+
+/*
+ * The "device name" for netmap devices isn't a name for a device, it's
+ * an expression that indicates how the device should be set up, so
+ * there's no way to enumerate them.
+ */
+int
+pcap_netmap_findalldevs(pcap_if_list_t *devlistp _U_, char *err_str _U_)
+{
+ return 0;
+}
diff --git a/lib/libpcap/libpcap/pcap-netmap.h b/lib/libpcap/libpcap/pcap-netmap.h
new file mode 100644
index 0000000..6a414fc
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-netmap.h
@@ -0,0 +1,2 @@
+pcap_t *pcap_netmap_create(const char *, char *, int *);
+int pcap_netmap_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/lib/libpcap/libpcap/pcap-new.c b/lib/libpcap/libpcap/pcap-new.c
new file mode 100644
index 0000000..086defd
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-new.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (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 Politecnico di Torino, CACE Technologies
+ * nor the names 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+/*
+ * sockutils.h may include <crtdbg.h> on Windows, and pcap-int.h will
+ * include portability.h, and portability.h, on Windows, expects that
+ * <crtdbg.h> has already been included, so include sockutils.h first.
+ */
+#include "sockutils.h"
+#include "pcap-int.h" // for the details of the pcap_t structure
+#include "pcap-rpcap.h"
+#include "rpcap-protocol.h"
+#include <errno.h> // for the errno variable
+#include <stdlib.h> // for malloc(), free(), ...
+#include <string.h> // for strstr, etc
+
+#ifndef _WIN32
+#include <dirent.h> // for readdir
+#endif
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_FILE "File"
+#define PCAP_TEXT_SOURCE_FILE_LEN (sizeof PCAP_TEXT_SOURCE_FILE - 1)
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+#define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof "Network adapter" - 1)
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_LOCAL_HOST "on local host"
+#define PCAP_TEXT_SOURCE_ON_LOCAL_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_LOCAL_HOST + 1)
+
+/****************************************************
+ * *
+ * Function bodies *
+ * *
+ ****************************************************/
+
+int pcap_findalldevs_ex(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+{
+ int type;
+ char name[PCAP_BUF_SIZE], path[PCAP_BUF_SIZE], filename[PCAP_BUF_SIZE];
+ size_t pathlen;
+ size_t stringlen;
+ pcap_t *fp;
+ char tmpstring[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+ pcap_if_t *lastdev; /* Last device in the pcap_if_t list */
+ pcap_if_t *dev; /* Device we're adding to the pcap_if_t list */
+
+ /* List starts out empty. */
+ (*alldevs) = NULL;
+ lastdev = NULL;
+
+ if (strlen(source) > PCAP_BUF_SIZE)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+ return -1;
+ }
+
+ /*
+ * Determine the type of the source (file, local, remote)
+ * There are some differences if pcap_findalldevs_ex() is called to list files and remote adapters.
+ * In the first case, the name of the directory we have to look into must be present (therefore
+ * the 'name' parameter of the pcap_parsesrcstr() is present).
+ * In the second case, the name of the adapter is not required (we need just the host). So, we have
+ * to use a first time this function to get the source type, and a second time to get the appropriate
+ * info, which depends on the source type.
+ */
+ if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
+ return -1;
+
+ switch (type)
+ {
+ case PCAP_SRC_IFLOCAL:
+ if (pcap_parsesrcstr(source, &type, NULL, NULL, NULL, errbuf) == -1)
+ return -1;
+
+ /* Initialize temporary string */
+ tmpstring[PCAP_BUF_SIZE] = 0;
+
+ /* The user wants to retrieve adapters from a local host */
+ if (pcap_findalldevs(alldevs, errbuf) == -1)
+ return -1;
+
+ if (*alldevs == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "No interfaces found! Make sure libpcap/Npcap is properly installed"
+ " on the local machine.");
+ return -1;
+ }
+
+ /* Scan all the interfaces and modify name and description */
+ /* This is a trick in order to avoid the re-implementation of the pcap_findalldevs here */
+ dev = *alldevs;
+ while (dev)
+ {
+ char *localdesc, *desc;
+
+ /* Create the new device identifier */
+ if (pcap_createsrcstr(tmpstring, PCAP_SRC_IFLOCAL, NULL, NULL, dev->name, errbuf) == -1)
+ return -1;
+
+ /* Delete the old pointer */
+ free(dev->name);
+
+ /* Make a copy of the new device identifier */
+ dev->name = strdup(tmpstring);
+ if (dev->name == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc() failed");
+ pcap_freealldevs(*alldevs);
+ return -1;
+ }
+
+ /*
+ * Create the description.
+ */
+ if ((dev->description == NULL) || (dev->description[0] == 0))
+ localdesc = dev->name;
+ else
+ localdesc = dev->description;
+ if (pcap_asprintf(&desc, "%s '%s' %s",
+ PCAP_TEXT_SOURCE_ADAPTER, localdesc,
+ PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc() failed");
+ pcap_freealldevs(*alldevs);
+ return -1;
+ }
+
+ /* Now overwrite the description */
+ free(dev->description);
+ dev->description = desc;
+
+ dev = dev->next;
+ }
+
+ return 0;
+
+ case PCAP_SRC_FILE:
+ {
+#ifdef _WIN32
+ WIN32_FIND_DATA filedata;
+ HANDLE filehandle;
+#else
+ struct dirent *filedata;
+ DIR *unixdir;
+#endif
+
+ if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
+ return -1;
+
+ /* Check that the filename is correct */
+ stringlen = strlen(name);
+
+ /* The directory must end with '\' in Win32 and '/' in UNIX */
+#ifdef _WIN32
+#define ENDING_CHAR '\\'
+#else
+#define ENDING_CHAR '/'
+#endif
+
+ if (name[stringlen - 1] != ENDING_CHAR)
+ {
+ name[stringlen] = ENDING_CHAR;
+ name[stringlen + 1] = 0;
+
+ stringlen++;
+ }
+
+ /* Save the path for future reference */
+ pcap_snprintf(path, sizeof(path), "%s", name);
+ pathlen = strlen(path);
+
+#ifdef _WIN32
+ /* To perform directory listing, Win32 must have an 'asterisk' as ending char */
+ if (name[stringlen - 1] != '*')
+ {
+ name[stringlen] = '*';
+ name[stringlen + 1] = 0;
+ }
+
+ filehandle = FindFirstFile(name, &filedata);
+
+ if (filehandle == INVALID_HANDLE_VALUE)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+ return -1;
+ }
+
+#else
+ /* opening the folder */
+ unixdir= opendir(path);
+
+ /* get the first file into it */
+ filedata= readdir(unixdir);
+
+ if (filedata == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error when listing files: does folder '%s' exist?", path);
+ return -1;
+ }
+#endif
+
+ /* Add all files we find to the list. */
+ do
+ {
+#ifdef _WIN32
+ /* Skip the file if the pathname won't fit in the buffer */
+ if (pathlen + strlen(filedata.cFileName) >= sizeof(filename))
+ continue;
+ pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata.cFileName);
+#else
+ if (pathlen + strlen(filedata->d_name) >= sizeof(filename))
+ continue;
+ pcap_snprintf(filename, sizeof(filename), "%s%s", path, filedata->d_name);
+#endif
+
+ fp = pcap_open_offline(filename, errbuf);
+
+ if (fp)
+ {
+ /* allocate the main structure */
+ dev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+ if (dev == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc() failed");
+ pcap_freealldevs(*alldevs);
+ return -1;
+ }
+
+ /* Initialize the structure to 'zero' */
+ memset(dev, 0, sizeof(pcap_if_t));
+
+ /* Append it to the list. */
+ if (lastdev == NULL)
+ {
+ /*
+ * List is empty, so it's also
+ * the first device.
+ */
+ *alldevs = dev;
+ }
+ else
+ {
+ /*
+ * Append after the last device.
+ */
+ lastdev->next = dev;
+ }
+ /* It's now the last device. */
+ lastdev = dev;
+
+ /* Create the new source identifier */
+ if (pcap_createsrcstr(tmpstring, PCAP_SRC_FILE, NULL, NULL, filename, errbuf) == -1)
+ {
+ pcap_freealldevs(*alldevs);
+ return -1;
+ }
+
+ dev->name = strdup(tmpstring);
+ if (dev->name == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc() failed");
+ pcap_freealldevs(*alldevs);
+ return -1;
+ }
+
+ /*
+ * Create the description.
+ */
+ if (pcap_asprintf(&dev->description,
+ "%s '%s' %s", PCAP_TEXT_SOURCE_FILE,
+ filename, PCAP_TEXT_SOURCE_ON_LOCAL_HOST) == -1)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc() failed");
+ pcap_freealldevs(*alldevs);
+ return -1;
+ }
+
+ pcap_close(fp);
+ }
+ }
+#ifdef _WIN32
+ while (FindNextFile(filehandle, &filedata) != 0);
+#else
+ while ( (filedata= readdir(unixdir)) != NULL);
+#endif
+
+
+#ifdef _WIN32
+ /* Close the search handle. */
+ FindClose(filehandle);
+#endif
+
+ return 0;
+ }
+
+ case PCAP_SRC_IFREMOTE:
+ return pcap_findalldevs_ex_remote(source, auth, alldevs, errbuf);
+
+ default:
+ pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+}
+
+pcap_t *pcap_open(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
+{
+ char name[PCAP_BUF_SIZE];
+ int type;
+ pcap_t *fp;
+ int status;
+
+ /*
+ * A null device name is equivalent to the "any" device -
+ * which might not be supported on this platform, but
+ * this means that you'll get a "not supported" error
+ * rather than, say, a crash when we try to dereference
+ * the null pointer.
+ */
+ if (source == NULL)
+ source = "any";
+
+ if (strlen(source) > PCAP_BUF_SIZE)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The source string is too long. Cannot handle it correctly.");
+ return NULL;
+ }
+
+ /*
+ * Determine the type of the source (file, local, remote) and,
+ * if it's file or local, the name of the file or capture device.
+ */
+ if (pcap_parsesrcstr(source, &type, NULL, NULL, name, errbuf) == -1)
+ return NULL;
+
+ switch (type)
+ {
+ case PCAP_SRC_FILE:
+ return pcap_open_offline(name, errbuf);
+
+ case PCAP_SRC_IFLOCAL:
+ fp = pcap_create(name, errbuf);
+ break;
+
+ case PCAP_SRC_IFREMOTE:
+ /*
+ * Although we already have host, port and iface, we prefer
+ * to pass only 'source' to pcap_open_rpcap(), so that it
+ * has to call pcap_parsesrcstr() again.
+ * This is less optimized, but much clearer.
+ */
+ return pcap_open_rpcap(source, snaplen, flags, read_timeout, auth, errbuf);
+
+ default:
+ pcap_strlcpy(errbuf, "Source type not supported", PCAP_ERRBUF_SIZE);
+ return NULL;
+ }
+
+ if (fp == NULL)
+ return (NULL);
+ status = pcap_set_snaplen(fp, snaplen);
+ if (status < 0)
+ goto fail;
+ if (flags & PCAP_OPENFLAG_PROMISCUOUS)
+ {
+ status = pcap_set_promisc(fp, 1);
+ if (status < 0)
+ goto fail;
+ }
+ if (flags & PCAP_OPENFLAG_MAX_RESPONSIVENESS)
+ {
+ status = pcap_set_immediate_mode(fp, 1);
+ if (status < 0)
+ goto fail;
+ }
+#ifdef _WIN32
+ /*
+ * This flag is supported on Windows only.
+ * XXX - is there a way to support it with
+ * the capture mechanisms on UN*X? It's not
+ * exactly a "set direction" operation; I
+ * think it means "do not capture packets
+ * injected with pcap_sendpacket() or
+ * pcap_inject()".
+ */
+ /* disable loopback capture if requested */
+ if (flags & PCAP_OPENFLAG_NOCAPTURE_LOCAL)
+ fp->opt.nocapture_local = 1;
+#endif /* _WIN32 */
+ status = pcap_set_timeout(fp, read_timeout);
+ if (status < 0)
+ goto fail;
+ status = pcap_activate(fp);
+ if (status < 0)
+ goto fail;
+ return fp;
+
+fail:
+ if (status == PCAP_ERROR)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ name, fp->errbuf);
+ else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
+ status == PCAP_ERROR_PERM_DENIED ||
+ status == PCAP_ERROR_PROMISC_PERM_DENIED)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%s)",
+ name, pcap_statustostr(status), fp->errbuf);
+ else
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ name, pcap_statustostr(status));
+ pcap_close(fp);
+ return NULL;
+}
+
+struct pcap_samp *pcap_setsampling(pcap_t *p)
+{
+ return &p->rmt_samp;
+}
diff --git a/lib/libpcap/libpcap/pcap-nit.c b/lib/libpcap/libpcap/pcap-nit.c
new file mode 100644
index 0000000..6a1a77c
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-nit.c
@@ -0,0 +1,417 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <net/nit.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * The chunk size for NIT. This is the amount of buffering
+ * done for read calls.
+ */
+#define CHUNKSIZE (2*1024)
+
+/*
+ * The total buffer space used by NIT.
+ */
+#define BUFSPACE (4*CHUNKSIZE)
+
+/* Forwards */
+static int nit_setflags(int, int, int, char *);
+
+/*
+ * Private data for capturing on NIT devices.
+ */
+struct pcap_nit {
+ struct pcap_stat stat;
+};
+
+static int
+pcap_stats_nit(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_nit *pn = p->priv;
+
+ /*
+ * "ps_recv" counts packets handed to the filter, not packets
+ * that passed the filter. As filtering is done in userland,
+ * this does not include packets dropped because we ran out
+ * of buffer space.
+ *
+ * "ps_drop" presumably counts packets dropped by the socket
+ * because of flow control requirements or resource exhaustion;
+ * it doesn't count packets dropped by the interface driver.
+ * As filtering is done in userland, it counts packets regardless
+ * of whether they would've passed the filter.
+ *
+ * These statistics don't include packets not yet read from the
+ * kernel by libpcap or packets not yet read from libpcap by the
+ * application.
+ */
+ *ps = pn->stat;
+ return (0);
+}
+
+static int
+pcap_read_nit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_nit *pn = p->priv;
+ register int cc, n;
+ register u_char *bp, *cp, *ep;
+ register struct nit_hdr *nh;
+ register int caplen;
+
+ cc = p->cc;
+ if (cc == 0) {
+ cc = read(p->fd, (char *)p->buffer, p->bufsize);
+ if (cc < 0) {
+ if (errno == EWOULDBLOCK)
+ return (0);
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "pcap_read");
+ return (-1);
+ }
+ bp = (u_char *)p->buffer;
+ } else
+ bp = p->bp;
+
+ /*
+ * Loop through each packet. The increment expression
+ * rounds up to the next int boundary past the end of
+ * the previous packet.
+ */
+ n = 0;
+ ep = bp + cc;
+ while (bp < ep) {
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else {
+ p->cc = ep - bp;
+ p->bp = bp;
+ return (n);
+ }
+ }
+
+ nh = (struct nit_hdr *)bp;
+ cp = bp + sizeof(*nh);
+
+ switch (nh->nh_state) {
+
+ case NIT_CATCH:
+ break;
+
+ case NIT_NOMBUF:
+ case NIT_NOCLUSTER:
+ case NIT_NOSPACE:
+ pn->stat.ps_drop = nh->nh_dropped;
+ continue;
+
+ case NIT_SEQNO:
+ continue;
+
+ default:
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "bad nit state %d", nh->nh_state);
+ return (-1);
+ }
+ ++pn->stat.ps_recv;
+ bp += ((sizeof(struct nit_hdr) + nh->nh_datalen +
+ sizeof(int) - 1) & ~(sizeof(int) - 1));
+
+ caplen = nh->nh_wirelen;
+ if (caplen > p->snapshot)
+ caplen = p->snapshot;
+ if (bpf_filter(p->fcode.bf_insns, cp, nh->nh_wirelen, caplen)) {
+ struct pcap_pkthdr h;
+ h.ts = nh->nh_timestamp;
+ h.len = nh->nh_wirelen;
+ h.caplen = caplen;
+ (*callback)(user, &h, cp);
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
+ p->cc = ep - bp;
+ p->bp = bp;
+ return (n);
+ }
+ }
+ }
+ p->cc = 0;
+ return (n);
+}
+
+static int
+pcap_inject_nit(pcap_t *p, const void *buf, size_t size)
+{
+ struct sockaddr sa;
+ int ret;
+
+ memset(&sa, 0, sizeof(sa));
+ strncpy(sa.sa_data, device, sizeof(sa.sa_data));
+ ret = sendto(p->fd, buf, size, 0, &sa, sizeof(sa));
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
+nit_setflags(pcap_t *p)
+{
+ struct nit_ioc nioc;
+
+ memset(&nioc, 0, sizeof(nioc));
+ nioc.nioc_typetomatch = NT_ALLTYPES;
+ nioc.nioc_snaplen = p->snapshot;
+ nioc.nioc_bufalign = sizeof(int);
+ nioc.nioc_bufoffset = 0;
+
+ if (p->opt.buffer_size != 0)
+ nioc.nioc_bufspace = p->opt.buffer_size;
+ else {
+ /* Default buffer size */
+ nioc.nioc_bufspace = BUFSPACE;
+ }
+
+ if (p->opt.immediate) {
+ /*
+ * XXX - will this cause packets to be delivered immediately?
+ * XXX - given that this is for SunOS prior to 4.0, do
+ * we care?
+ */
+ nioc.nioc_chunksize = 0;
+ } else
+ nioc.nioc_chunksize = CHUNKSIZE;
+ if (p->opt.timeout != 0) {
+ nioc.nioc_flags |= NF_TIMEOUT;
+ nioc.nioc_timeout.tv_sec = p->opt.timeout / 1000;
+ nioc.nioc_timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
+ }
+ if (p->opt.promisc)
+ nioc.nioc_flags |= NF_PROMISC;
+
+ if (ioctl(p->fd, SIOCSNIT, &nioc) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCSNIT");
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+pcap_activate_nit(pcap_t *p)
+{
+ int fd;
+ struct sockaddr_nit snit;
+
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on SunOS 3.x or earlier (no
+ * Wi-Fi *devices* for the hardware that supported
+ * them!).
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ if (p->snapshot < 96)
+ /*
+ * NIT requires a snapshot length of at least 96.
+ */
+ p->snapshot = 96;
+
+ memset(p, 0, sizeof(*p));
+ p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ goto bad;
+ }
+ snit.snit_family = AF_NIT;
+ (void)strncpy(snit.snit_ifname, p->opt.device, NITIFSIZ);
+
+ if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) {
+ /*
+ * XXX - there's probably a particular bind error that
+ * means "there's no such device" and a particular bind
+ * error that means "that device doesn't support NIT";
+ * they might be the same error, if they both end up
+ * meaning "NIT doesn't know about that device".
+ */
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "bind: %s", snit.snit_ifname);
+ goto bad;
+ }
+ if (nit_setflags(p) < 0)
+ goto bad;
+
+ /*
+ * NIT supports only ethernets.
+ */
+ p->linktype = DLT_EN10MB;
+
+ p->bufsize = BUFSPACE;
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ goto bad;
+ }
+
+ /*
+ * "p->fd" is a socket, so "select()" should work on it.
+ */
+ p->selectable_fd = p->fd;
+
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+
+ p->read_op = pcap_read_nit;
+ p->inject_op = pcap_inject_nit;
+ p->setfilter_op = install_bpf_program; /* no kernel filtering */
+ p->setdirection_op = NULL; /* Not implemented. */
+ p->set_datalink_op = NULL; /* can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_stats_nit;
+
+ return (0);
+ bad:
+ pcap_cleanup_live_common(p);
+ return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_nit));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_nit;
+ return (p);
+}
+
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support NIT"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+ get_if_flags));
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-npf.c b/lib/libpcap/libpcap/pcap-npf.c
new file mode 100644
index 0000000..da4641f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-npf.c
@@ -0,0 +1,2114 @@
+/*
+ * Copyright (c) 1999 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2010 CACE Technologies, Davis (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 Politecnico di Torino, CACE Technologies
+ * nor the names 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <Packet32.h>
+#include <pcap-int.h>
+#include <pcap/dlt.h>
+
+/* Old-school MinGW have these headers in a different place.
+ */
+#if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
+ #include <ddk/ntddndis.h>
+ #include <ddk/ndis.h>
+#else
+ #include <ntddndis.h> /* MSVC/TDM-MinGW/MinGW64 */
+#endif
+
+#ifdef HAVE_DAG_API
+ #include <dagnew.h>
+ #include <dagapi.h>
+#endif /* HAVE_DAG_API */
+
+static int pcap_setfilter_npf(pcap_t *, struct bpf_program *);
+static int pcap_setfilter_win32_dag(pcap_t *, struct bpf_program *);
+static int pcap_getnonblock_npf(pcap_t *);
+static int pcap_setnonblock_npf(pcap_t *, int);
+
+/*dimension of the buffer in the pcap_t structure*/
+#define WIN32_DEFAULT_USER_BUFFER_SIZE 256000
+
+/*dimension of the buffer in the kernel driver NPF */
+#define WIN32_DEFAULT_KERNEL_BUFFER_SIZE 1000000
+
+/* Equivalent to ntohs(), but a lot faster under Windows */
+#define SWAPS(_X) ((_X & 0xff) << 8) | (_X >> 8)
+
+/*
+ * Private data for capturing on WinPcap/Npcap devices.
+ */
+struct pcap_win {
+ ADAPTER *adapter; /* the packet32 ADAPTER for the device */
+ int nonblock;
+ int rfmon_selfstart; /* a flag tells whether the monitor mode is set by itself */
+ int filtering_in_kernel; /* using kernel filter */
+
+#ifdef HAVE_DAG_API
+ int dag_fcs_bits; /* Number of checksum bits from link layer */
+#endif
+
+#ifdef ENABLE_REMOTE
+ int samp_npkt; /* parameter needed for sampling, with '1 out of N' method has been requested */
+ struct timeval samp_time; /* parameter needed for sampling, with '1 every N ms' method has been requested */
+#endif
+};
+
+/*
+ * Define stub versions of the monitor-mode support routines if this
+ * isn't Npcap. HAVE_NPCAP_PACKET_API is defined by Npcap but not
+ * WinPcap.
+ */
+#ifndef HAVE_NPCAP_PACKET_API
+static int
+PacketIsMonitorModeSupported(PCHAR AdapterName _U_)
+{
+ /*
+ * We don't support monitor mode.
+ */
+ return (0);
+}
+
+static int
+PacketSetMonitorMode(PCHAR AdapterName _U_, int mode _U_)
+{
+ /*
+ * This should never be called, as PacketIsMonitorModeSupported()
+ * will return 0, meaning "we don't support monitor mode, so
+ * don't try to turn it on or off".
+ */
+ return (0);
+}
+
+static int
+PacketGetMonitorMode(PCHAR AdapterName _U_)
+{
+ /*
+ * This should fail, so that pcap_activate_npf() returns
+ * PCAP_ERROR_RFMON_NOTSUP if our caller requested monitor
+ * mode.
+ */
+ return (-1);
+}
+#endif
+
+/*
+ * Sigh. PacketRequest() will have made a DeviceIoControl()
+ * call to the NPF driver to perform the OID request, with a
+ * BIOCQUERYOID ioctl. The kernel code should get back one
+ * of NDIS_STATUS_INVALID_OID, NDIS_STATUS_NOT_SUPPORTED,
+ * or NDIS_STATUS_NOT_RECOGNIZED if the OID request isn't
+ * supported by the OS or the driver, but that doesn't seem
+ * to make it to the caller of PacketRequest() in a
+ * reliable fashion.
+ */
+#define NDIS_STATUS_INVALID_OID 0xc0010017
+#define NDIS_STATUS_NOT_SUPPORTED 0xc00000bb /* STATUS_NOT_SUPPORTED */
+#define NDIS_STATUS_NOT_RECOGNIZED 0x00010001
+
+static int
+oid_get_request(ADAPTER *adapter, bpf_u_int32 oid, void *data, size_t *lenp,
+ char *errbuf)
+{
+ PACKET_OID_DATA *oid_data_arg;
+
+ /*
+ * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
+ * It should be big enough to hold "*lenp" bytes of data; it
+ * will actually be slightly larger, as PACKET_OID_DATA has a
+ * 1-byte data array at the end, standing in for the variable-length
+ * data that's actually there.
+ */
+ oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
+ if (oid_data_arg == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Couldn't allocate argument buffer for PacketRequest");
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * No need to copy the data - we're doing a fetch.
+ */
+ oid_data_arg->Oid = oid;
+ oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
+ if (!PacketRequest(adapter, FALSE, oid_data_arg)) {
+ pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "Error calling PacketRequest");
+ free(oid_data_arg);
+ return (-1);
+ }
+
+ /*
+ * Get the length actually supplied.
+ */
+ *lenp = oid_data_arg->Length;
+
+ /*
+ * Copy back the data we fetched.
+ */
+ memcpy(data, oid_data_arg->Data, *lenp);
+ free(oid_data_arg);
+ return (0);
+}
+
+static int
+pcap_stats_npf(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_win *pw = p->priv;
+ struct bpf_stat bstats;
+
+ /*
+ * Try to get statistics.
+ *
+ * (Please note - "struct pcap_stat" is *not* the same as
+ * WinPcap's "struct bpf_stat". It might currently have the
+ * same layout, but let's not cheat.
+ *
+ * Note also that we don't fill in ps_capt, as we might have
+ * been called by code compiled against an earlier version of
+ * WinPcap that didn't have ps_capt, in which case filling it
+ * in would stomp on whatever comes after the structure passed
+ * to us.
+ */
+ if (!PacketGetStats(pw->adapter, &bstats)) {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "PacketGetStats error");
+ return (-1);
+ }
+ ps->ps_recv = bstats.bs_recv;
+ ps->ps_drop = bstats.bs_drop;
+
+ /*
+ * XXX - PacketGetStats() doesn't fill this in, so we just
+ * return 0.
+ */
+#if 0
+ ps->ps_ifdrop = bstats.ps_ifdrop;
+#else
+ ps->ps_ifdrop = 0;
+#endif
+
+ return (0);
+}
+
+/*
+ * Win32-only routine for getting statistics.
+ *
+ * This way is definitely safer than passing the pcap_stat * from the userland.
+ * In fact, there could happen than the user allocates a variable which is not
+ * big enough for the new structure, and the library will write in a zone
+ * which is not allocated to this variable.
+ *
+ * In this way, we're pretty sure we are writing on memory allocated to this
+ * variable.
+ *
+ * XXX - but this is the wrong way to handle statistics. Instead, we should
+ * have an API that returns data in a form like the Options section of a
+ * pcapng Interface Statistics Block:
+ *
+ * http://xml2rfc.tools.ietf.org/cgi-bin/xml2rfc.cgi?url=https://raw.githubusercontent.com/pcapng/pcapng/master/draft-tuexen-opsawg-pcapng.xml&modeAsFormat=html/ascii&type=ascii#rfc.section.4.6
+ *
+ * which would let us add new statistics straightforwardly and indicate which
+ * statistics we are and are *not* providing, rather than having to provide
+ * possibly-bogus values for statistics we can't provide.
+ */
+struct pcap_stat *
+pcap_stats_ex_npf(pcap_t *p, int *pcap_stat_size)
+{
+ struct pcap_win *pw = p->priv;
+ struct bpf_stat bstats;
+
+ *pcap_stat_size = sizeof (p->stat);
+
+ /*
+ * Try to get statistics.
+ *
+ * (Please note - "struct pcap_stat" is *not* the same as
+ * WinPcap's "struct bpf_stat". It might currently have the
+ * same layout, but let's not cheat.)
+ */
+ if (!PacketGetStatsEx(pw->adapter, &bstats)) {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "PacketGetStatsEx error");
+ return (NULL);
+ }
+ p->stat.ps_recv = bstats.bs_recv;
+ p->stat.ps_drop = bstats.bs_drop;
+ p->stat.ps_ifdrop = bstats.ps_ifdrop;
+#ifdef ENABLE_REMOTE
+ p->stat.ps_capt = bstats.bs_capt;
+#endif
+ return (&p->stat);
+}
+
+/* Set the dimension of the kernel-level capture buffer */
+static int
+pcap_setbuff_npf(pcap_t *p, int dim)
+{
+ struct pcap_win *pw = p->priv;
+
+ if(PacketSetBuff(pw->adapter,dim)==FALSE)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+ return (-1);
+ }
+ return (0);
+}
+
+/* Set the driver working mode */
+static int
+pcap_setmode_npf(pcap_t *p, int mode)
+{
+ struct pcap_win *pw = p->priv;
+
+ if(PacketSetMode(pw->adapter,mode)==FALSE)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized");
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*set the minimum amount of data that will release a read call*/
+static int
+pcap_setmintocopy_npf(pcap_t *p, int size)
+{
+ struct pcap_win *pw = p->priv;
+
+ if(PacketSetMinToCopy(pw->adapter, size)==FALSE)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size");
+ return (-1);
+ }
+ return (0);
+}
+
+static HANDLE
+pcap_getevent_npf(pcap_t *p)
+{
+ struct pcap_win *pw = p->priv;
+
+ return (PacketGetReadEvent(pw->adapter));
+}
+
+static int
+pcap_oid_get_request_npf(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
+{
+ struct pcap_win *pw = p->priv;
+
+ return (oid_get_request(pw->adapter, oid, data, lenp, p->errbuf));
+}
+
+static int
+pcap_oid_set_request_npf(pcap_t *p, bpf_u_int32 oid, const void *data,
+ size_t *lenp)
+{
+ struct pcap_win *pw = p->priv;
+ PACKET_OID_DATA *oid_data_arg;
+
+ /*
+ * Allocate a PACKET_OID_DATA structure to hand to PacketRequest().
+ * It should be big enough to hold "*lenp" bytes of data; it
+ * will actually be slightly larger, as PACKET_OID_DATA has a
+ * 1-byte data array at the end, standing in for the variable-length
+ * data that's actually there.
+ */
+ oid_data_arg = malloc(sizeof (PACKET_OID_DATA) + *lenp);
+ if (oid_data_arg == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Couldn't allocate argument buffer for PacketRequest");
+ return (PCAP_ERROR);
+ }
+
+ oid_data_arg->Oid = oid;
+ oid_data_arg->Length = (ULONG)(*lenp); /* XXX - check for ridiculously large value? */
+ memcpy(oid_data_arg->Data, data, *lenp);
+ if (!PacketRequest(pw->adapter, TRUE, oid_data_arg)) {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "Error calling PacketRequest");
+ free(oid_data_arg);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Get the length actually copied.
+ */
+ *lenp = oid_data_arg->Length;
+
+ /*
+ * No need to copy the data - we're doing a set.
+ */
+ free(oid_data_arg);
+ return (0);
+}
+
+static u_int
+pcap_sendqueue_transmit_npf(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ struct pcap_win *pw = p->priv;
+ u_int res;
+
+ if (pw->adapter==NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Cannot transmit a queue to an offline capture or to a TurboCap port");
+ return (0);
+ }
+
+ res = PacketSendPackets(pw->adapter,
+ queue->buffer,
+ queue->len,
+ (BOOLEAN)sync);
+
+ if(res != queue->len){
+ pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "Error opening adapter");
+ }
+
+ return (res);
+}
+
+static int
+pcap_setuserbuffer_npf(pcap_t *p, int size)
+{
+ unsigned char *new_buff;
+
+ if (size<=0) {
+ /* Bogus parameter */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error: invalid size %d",size);
+ return (-1);
+ }
+
+ /* Allocate the buffer */
+ new_buff=(unsigned char*)malloc(sizeof(char)*size);
+
+ if (!new_buff) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error: not enough memory");
+ return (-1);
+ }
+
+ free(p->buffer);
+
+ p->buffer=new_buff;
+ p->bufsize=size;
+
+ return (0);
+}
+
+static int
+pcap_live_dump_npf(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ struct pcap_win *pw = p->priv;
+ BOOLEAN res;
+
+ /* Set the packet driver in dump mode */
+ res = PacketSetMode(pw->adapter, PACKET_MODE_DUMP);
+ if(res == FALSE){
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error setting dump mode");
+ return (-1);
+ }
+
+ /* Set the name of the dump file */
+ res = PacketSetDumpName(pw->adapter, filename, (int)strlen(filename));
+ if(res == FALSE){
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error setting kernel dump file name");
+ return (-1);
+ }
+
+ /* Set the limits of the dump file */
+ res = PacketSetDumpLimits(pw->adapter, maxsize, maxpacks);
+ if(res == FALSE) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Error setting dump limit");
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+pcap_live_dump_ended_npf(pcap_t *p, int sync)
+{
+ struct pcap_win *pw = p->priv;
+
+ return (PacketIsDumpEnded(pw->adapter, (BOOLEAN)sync));
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_npf(pcap_t *p)
+{
+#ifdef HAVE_AIRPCAP_API
+ struct pcap_win *pw = p->priv;
+
+ return (PacketGetAirPcapHandle(pw->adapter));
+#else
+ return (NULL);
+#endif /* HAVE_AIRPCAP_API */
+}
+
+static int
+pcap_read_npf(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ PACKET Packet;
+ int cc;
+ int n = 0;
+ register u_char *bp, *ep;
+ u_char *datap;
+ struct pcap_win *pw = p->priv;
+
+ cc = p->cc;
+ if (p->cc == 0) {
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return PCAP_ERROR_BREAK to indicate
+ * that we were told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return (PCAP_ERROR_BREAK);
+ }
+
+ /*
+ * Capture the packets.
+ *
+ * The PACKET structure had a bunch of extra stuff for
+ * Windows 9x/Me, but the only interesting data in it
+ * in the versions of Windows that we support is just
+ * a copy of p->buffer, a copy of p->buflen, and the
+ * actual number of bytes read returned from
+ * PacketReceivePacket(), none of which has to be
+ * retained from call to call, so we just keep one on
+ * the stack.
+ */
+ PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
+ if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) {
+ /*
+ * Did the device go away?
+ * If so, the error we get is ERROR_GEN_FAILURE.
+ */
+ DWORD errcode = GetLastError();
+
+ if (errcode == ERROR_GEN_FAILURE) {
+ /*
+ * The device on which we're capturing
+ * went away, or it became unusable
+ * by NPF due to a suspend/resume.
+ *
+ * XXX - hopefully no other error
+ * conditions are indicated by this.
+ *
+ * XXX - we really should return an
+ * appropriate error for that, but
+ * pcap_dispatch() etc. aren't
+ * documented as having error returns
+ * other than PCAP_ERROR or PCAP_ERROR_BREAK.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The interface disappeared");
+ } else {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf,
+ PCAP_ERRBUF_SIZE, errcode,
+ "PacketReceivePacket error");
+ }
+ return (PCAP_ERROR);
+ }
+
+ cc = Packet.ulBytesReceived;
+
+ bp = p->buffer;
+ }
+ else
+ bp = p->bp;
+
+ /*
+ * Loop through each packet.
+ */
+#define bhp ((struct bpf_hdr *)bp)
+ ep = bp + cc;
+ for (;;) {
+ register int caplen, hdrlen;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return PCAP_ERROR_BREAK
+ * to indicate that we were told to break out of the loop,
+ * otherwise leave the flag set, so that the *next* call
+ * will break out of the loop without having read any
+ * packets, and return the number of packets we've
+ * processed so far.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (PCAP_ERROR_BREAK);
+ } else {
+ p->bp = bp;
+ p->cc = (int) (ep - bp);
+ return (n);
+ }
+ }
+ if (bp >= ep)
+ break;
+
+ caplen = bhp->bh_caplen;
+ hdrlen = bhp->bh_hdrlen;
+ datap = bp + hdrlen;
+
+ /*
+ * Short-circuit evaluation: if using BPF filter
+ * in kernel, no need to do it now - we already know
+ * the packet passed the filter.
+ *
+ * XXX - bpf_filter() should always return TRUE if
+ * handed a null pointer for the program, but it might
+ * just try to "run" the filter, so we check here.
+ */
+ if (pw->filtering_in_kernel ||
+ p->fcode.bf_insns == NULL ||
+ bpf_filter(p->fcode.bf_insns, datap, bhp->bh_datalen, caplen)) {
+#ifdef ENABLE_REMOTE
+ switch (p->rmt_samp.method) {
+
+ case PCAP_SAMP_1_EVERY_N:
+ pw->samp_npkt = (pw->samp_npkt + 1) % p->rmt_samp.value;
+
+ /* Discard all packets that are not '1 out of N' */
+ if (pw->samp_npkt != 0) {
+ bp += Packet_WORDALIGN(caplen + hdrlen);
+ continue;
+ }
+ break;
+
+ case PCAP_SAMP_FIRST_AFTER_N_MS:
+ {
+ struct pcap_pkthdr *pkt_header = (struct pcap_pkthdr*) bp;
+
+ /*
+ * Check if the timestamp of the arrived
+ * packet is smaller than our target time.
+ */
+ if (pkt_header->ts.tv_sec < pw->samp_time.tv_sec ||
+ (pkt_header->ts.tv_sec == pw->samp_time.tv_sec && pkt_header->ts.tv_usec < pw->samp_time.tv_usec)) {
+ bp += Packet_WORDALIGN(caplen + hdrlen);
+ continue;
+ }
+
+ /*
+ * The arrived packet is suitable for being
+ * delivered to our caller, so let's update
+ * the target time.
+ */
+ pw->samp_time.tv_usec = pkt_header->ts.tv_usec + p->rmt_samp.value * 1000;
+ if (pw->samp_time.tv_usec > 1000000) {
+ pw->samp_time.tv_sec = pkt_header->ts.tv_sec + pw->samp_time.tv_usec / 1000000;
+ pw->samp_time.tv_usec = pw->samp_time.tv_usec % 1000000;
+ }
+ }
+ }
+#endif /* ENABLE_REMOTE */
+
+ /*
+ * XXX A bpf_hdr matches a pcap_pkthdr.
+ */
+ (*callback)(user, (struct pcap_pkthdr*)bp, datap);
+ bp += Packet_WORDALIGN(caplen + hdrlen);
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
+ p->bp = bp;
+ p->cc = (int) (ep - bp);
+ return (n);
+ }
+ } else {
+ /*
+ * Skip this packet.
+ */
+ bp += Packet_WORDALIGN(caplen + hdrlen);
+ }
+ }
+#undef bhp
+ p->cc = 0;
+ return (n);
+}
+
+#ifdef HAVE_DAG_API
+static int
+pcap_read_win32_dag(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_win *pw = p->priv;
+ PACKET Packet;
+ u_char *dp = NULL;
+ int packet_len = 0, caplen = 0;
+ struct pcap_pkthdr pcap_header;
+ u_char *endofbuf;
+ int n = 0;
+ dag_record_t *header;
+ unsigned erf_record_len;
+ ULONGLONG ts;
+ int cc;
+ unsigned swt;
+ unsigned dfp = pw->adapter->DagFastProcess;
+
+ cc = p->cc;
+ if (cc == 0) /* Get new packets only if we have processed all the ones of the previous read */
+ {
+ /*
+ * Get new packets from the network.
+ *
+ * The PACKET structure had a bunch of extra stuff for
+ * Windows 9x/Me, but the only interesting data in it
+ * in the versions of Windows that we support is just
+ * a copy of p->buffer, a copy of p->buflen, and the
+ * actual number of bytes read returned from
+ * PacketReceivePacket(), none of which has to be
+ * retained from call to call, so we just keep one on
+ * the stack.
+ */
+ PacketInitPacket(&Packet, (BYTE *)p->buffer, p->bufsize);
+ if (!PacketReceivePacket(pw->adapter, &Packet, TRUE)) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed");
+ return (-1);
+ }
+
+ cc = Packet.ulBytesReceived;
+ if(cc == 0)
+ /* The timeout has expired but we no packets arrived */
+ return (0);
+ header = (dag_record_t*)pw->adapter->DagBuffer;
+ }
+ else
+ header = (dag_record_t*)p->bp;
+
+ endofbuf = (char*)header + cc;
+
+ /*
+ * Cycle through the packets
+ */
+ do
+ {
+ erf_record_len = SWAPS(header->rlen);
+ if((char*)header + erf_record_len > endofbuf)
+ break;
+
+ /* Increase the number of captured packets */
+ p->stat.ps_recv++;
+
+ /* Find the beginning of the packet */
+ dp = ((u_char *)header) + dag_record_size;
+
+ /* Determine actual packet len */
+ switch(header->type)
+ {
+ case TYPE_ATM:
+ packet_len = ATM_SNAPLEN;
+ caplen = ATM_SNAPLEN;
+ dp += 4;
+
+ break;
+
+ case TYPE_ETH:
+ swt = SWAPS(header->wlen);
+ packet_len = swt - (pw->dag_fcs_bits);
+ caplen = erf_record_len - dag_record_size - 2;
+ if (caplen > packet_len)
+ {
+ caplen = packet_len;
+ }
+ dp += 2;
+
+ break;
+
+ case TYPE_HDLC_POS:
+ swt = SWAPS(header->wlen);
+ packet_len = swt - (pw->dag_fcs_bits);
+ caplen = erf_record_len - dag_record_size;
+ if (caplen > packet_len)
+ {
+ caplen = packet_len;
+ }
+
+ break;
+ }
+
+ if(caplen > p->snapshot)
+ caplen = p->snapshot;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop)
+ {
+ if (n == 0)
+ {
+ p->break_loop = 0;
+ return (-2);
+ }
+ else
+ {
+ p->bp = (char*)header;
+ p->cc = endofbuf - (char*)header;
+ return (n);
+ }
+ }
+
+ if(!dfp)
+ {
+ /* convert between timestamp formats */
+ ts = header->ts;
+ pcap_header.ts.tv_sec = (int)(ts >> 32);
+ ts = (ts & 0xffffffffi64) * 1000000;
+ ts += 0x80000000; /* rounding */
+ pcap_header.ts.tv_usec = (int)(ts >> 32);
+ if (pcap_header.ts.tv_usec >= 1000000) {
+ pcap_header.ts.tv_usec -= 1000000;
+ pcap_header.ts.tv_sec++;
+ }
+ }
+
+ /* No underlaying filtering system. We need to filter on our own */
+ if (p->fcode.bf_insns)
+ {
+ if (bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen) == 0)
+ {
+ /* Move to next packet */
+ header = (dag_record_t*)((char*)header + erf_record_len);
+ continue;
+ }
+ }
+
+ /* Fill the header for the user suppplied callback function */
+ pcap_header.caplen = caplen;
+ pcap_header.len = packet_len;
+
+ /* Call the callback function */
+ (*callback)(user, &pcap_header, dp);
+
+ /* Move to next packet */
+ header = (dag_record_t*)((char*)header + erf_record_len);
+
+ /* Stop if the number of packets requested by user has been reached*/
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt))
+ {
+ p->bp = (char*)header;
+ p->cc = endofbuf - (char*)header;
+ return (n);
+ }
+ }
+ while((u_char*)header < endofbuf);
+
+ return (1);
+}
+#endif /* HAVE_DAG_API */
+
+/* Send a packet to the network */
+static int
+pcap_inject_npf(pcap_t *p, const void *buf, size_t size)
+{
+ struct pcap_win *pw = p->priv;
+ PACKET pkt;
+
+ PacketInitPacket(&pkt, (PVOID)buf, size);
+ if(PacketSendPacket(pw->adapter,&pkt,TRUE) == FALSE) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: PacketSendPacket failed");
+ return (-1);
+ }
+
+ /*
+ * We assume it all got sent if "PacketSendPacket()" succeeded.
+ * "pcap_inject()" is expected to return the number of bytes
+ * sent.
+ */
+ return ((int)size);
+}
+
+static void
+pcap_cleanup_npf(pcap_t *p)
+{
+ struct pcap_win *pw = p->priv;
+
+ if (pw->adapter != NULL) {
+ PacketCloseAdapter(pw->adapter);
+ pw->adapter = NULL;
+ }
+ if (pw->rfmon_selfstart)
+ {
+ PacketSetMonitorMode(p->opt.device, 0);
+ }
+ pcap_cleanup_live_common(p);
+}
+
+static int
+pcap_activate_npf(pcap_t *p)
+{
+ struct pcap_win *pw = p->priv;
+ NetType type;
+ int res;
+ int status = 0;
+
+ if (p->opt.rfmon) {
+ /*
+ * Monitor mode is supported on Windows Vista and later.
+ */
+ if (PacketGetMonitorMode(p->opt.device) == 1)
+ {
+ pw->rfmon_selfstart = 0;
+ }
+ else
+ {
+ if ((res = PacketSetMonitorMode(p->opt.device, 1)) != 1)
+ {
+ pw->rfmon_selfstart = 0;
+ // Monitor mode is not supported.
+ if (res == 0)
+ {
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+ else
+ {
+ return PCAP_ERROR;
+ }
+ }
+ else
+ {
+ pw->rfmon_selfstart = 1;
+ }
+ }
+ }
+
+ /* Init WinSock */
+ pcap_wsockinit();
+
+ pw->adapter = PacketOpenAdapter(p->opt.device);
+
+ if (pw->adapter == NULL)
+ {
+ DWORD errcode = GetLastError();
+
+ /*
+ * What error did we get when trying to open the adapter?
+ */
+ if (errcode == ERROR_BAD_UNIT) {
+ /*
+ * There's no such device.
+ */
+ return (PCAP_ERROR_NO_SUCH_DEVICE);
+ } else {
+ /*
+ * Unknown - report details.
+ */
+ pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+ errcode, "Error opening adapter");
+ if (pw->rfmon_selfstart)
+ {
+ PacketSetMonitorMode(p->opt.device, 0);
+ }
+ return (PCAP_ERROR);
+ }
+ }
+
+ /*get network type*/
+ if(PacketGetNetType (pw->adapter,&type) == FALSE)
+ {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "Cannot determine the network type");
+ goto bad;
+ }
+
+ /*Set the linktype*/
+ switch (type.LinkType)
+ {
+ case NdisMediumWan:
+ p->linktype = DLT_EN10MB;
+ break;
+
+ case NdisMedium802_3:
+ p->linktype = DLT_EN10MB;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+ break;
+
+ case NdisMediumFddi:
+ p->linktype = DLT_FDDI;
+ break;
+
+ case NdisMedium802_5:
+ p->linktype = DLT_IEEE802;
+ break;
+
+ case NdisMediumArcnetRaw:
+ p->linktype = DLT_ARCNET;
+ break;
+
+ case NdisMediumArcnet878_2:
+ p->linktype = DLT_ARCNET;
+ break;
+
+ case NdisMediumAtm:
+ p->linktype = DLT_ATM_RFC1483;
+ break;
+
+ case NdisMediumCHDLC:
+ p->linktype = DLT_CHDLC;
+ break;
+
+ case NdisMediumPPPSerial:
+ p->linktype = DLT_PPP_SERIAL;
+ break;
+
+ case NdisMediumNull:
+ p->linktype = DLT_NULL;
+ break;
+
+ case NdisMediumBare80211:
+ p->linktype = DLT_IEEE802_11;
+ break;
+
+ case NdisMediumRadio80211:
+ p->linktype = DLT_IEEE802_11_RADIO;
+ break;
+
+ case NdisMediumPpi:
+ p->linktype = DLT_PPI;
+ break;
+
+#ifdef NdisMediumWirelessWan
+ case NdisMediumWirelessWan:
+ p->linktype = DLT_RAW;
+ break;
+#endif
+
+ default:
+ /*
+ * An unknown medium type is assumed to supply Ethernet
+ * headers; if not, the user will have to report it,
+ * so that the medium type and link-layer header type
+ * can be determined. If we were to fail here, we
+ * might get the link-layer type in the error, but
+ * the user wouldn't get a capture, so we wouldn't
+ * be able to determine the link-layer type; we report
+ * a warning with the link-layer type, so at least
+ * some programs will report the warning.
+ */
+ p->linktype = DLT_EN10MB;
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Unknown NdisMedium value %d, defaulting to DLT_EN10MB",
+ type.LinkType);
+ status = PCAP_WARNING;
+ break;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ /* Set promiscuous mode */
+ if (p->opt.promisc)
+ {
+
+ if (PacketSetHwFilter(pw->adapter,NDIS_PACKET_TYPE_PROMISCUOUS) == FALSE)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to promiscuous mode");
+ goto bad;
+ }
+ }
+ else
+ {
+ /* NDIS_PACKET_TYPE_ALL_LOCAL selects "All packets sent by installed
+ * protocols and all packets indicated by the NIC" but if no protocol
+ * drivers (like TCP/IP) are installed, NDIS_PACKET_TYPE_DIRECTED,
+ * NDIS_PACKET_TYPE_BROADCAST, and NDIS_PACKET_TYPE_MULTICAST are needed to
+ * capture incoming frames.
+ */
+ if (PacketSetHwFilter(pw->adapter,
+ NDIS_PACKET_TYPE_ALL_LOCAL |
+ NDIS_PACKET_TYPE_DIRECTED |
+ NDIS_PACKET_TYPE_BROADCAST |
+ NDIS_PACKET_TYPE_MULTICAST) == FALSE)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "failed to set hardware filter to non-promiscuous mode");
+ goto bad;
+ }
+ }
+
+ /* Set the buffer size */
+ p->bufsize = WIN32_DEFAULT_USER_BUFFER_SIZE;
+
+ if(!(pw->adapter->Flags & INFO_FLAG_DAG_CARD))
+ {
+ /*
+ * Traditional Adapter
+ */
+ /*
+ * If the buffer size wasn't explicitly set, default to
+ * WIN32_DEFAULT_KERNEL_BUFFER_SIZE.
+ */
+ if (p->opt.buffer_size == 0)
+ p->opt.buffer_size = WIN32_DEFAULT_KERNEL_BUFFER_SIZE;
+
+ if(PacketSetBuff(pw->adapter,p->opt.buffer_size)==FALSE)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer");
+ goto bad;
+ }
+
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ goto bad;
+ }
+
+ if (p->opt.immediate)
+ {
+ /* tell the driver to copy the buffer as soon as data arrives */
+ if(PacketSetMinToCopy(pw->adapter,0)==FALSE)
+ {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf,
+ PCAP_ERRBUF_SIZE, GetLastError(),
+ "Error calling PacketSetMinToCopy");
+ goto bad;
+ }
+ }
+ else
+ {
+ /* tell the driver to copy the buffer only if it contains at least 16K */
+ if(PacketSetMinToCopy(pw->adapter,16000)==FALSE)
+ {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf,
+ PCAP_ERRBUF_SIZE, GetLastError(),
+ "Error calling PacketSetMinToCopy");
+ goto bad;
+ }
+ }
+ } else {
+ /*
+ * Dag Card
+ */
+#ifdef HAVE_DAG_API
+ /*
+ * We have DAG support.
+ */
+ LONG status;
+ HKEY dagkey;
+ DWORD lptype;
+ DWORD lpcbdata;
+ int postype = 0;
+ char keyname[512];
+
+ pcap_snprintf(keyname, sizeof(keyname), "%s\\CardParams\\%s",
+ "SYSTEM\\CurrentControlSet\\Services\\DAG",
+ strstr(_strlwr(p->opt.device), "dag"));
+ do
+ {
+ status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyname, 0, KEY_READ, &dagkey);
+ if(status != ERROR_SUCCESS)
+ break;
+
+ status = RegQueryValueEx(dagkey,
+ "PosType",
+ NULL,
+ &lptype,
+ (char*)&postype,
+ &lpcbdata);
+
+ if(status != ERROR_SUCCESS)
+ {
+ postype = 0;
+ }
+
+ RegCloseKey(dagkey);
+ }
+ while(FALSE);
+
+
+ p->snapshot = PacketSetSnapLen(pw->adapter, p->snapshot);
+
+ /* Set the length of the FCS associated to any packet. This value
+ * will be subtracted to the packet length */
+ pw->dag_fcs_bits = pw->adapter->DagFcsLen;
+#else /* HAVE_DAG_API */
+ /*
+ * No DAG support.
+ */
+ goto bad;
+#endif /* HAVE_DAG_API */
+ }
+
+ PacketSetReadTimeout(pw->adapter, p->opt.timeout);
+
+ /* disable loopback capture if requested */
+ if (p->opt.nocapture_local)
+ {
+ if (!PacketSetLoopbackBehavior(pw->adapter, NPF_DISABLE_LOOPBACK))
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Unable to disable the capture of loopback packets.");
+ goto bad;
+ }
+ }
+
+#ifdef HAVE_DAG_API
+ if(pw->adapter->Flags & INFO_FLAG_DAG_CARD)
+ {
+ /* install dag specific handlers for read and setfilter */
+ p->read_op = pcap_read_win32_dag;
+ p->setfilter_op = pcap_setfilter_win32_dag;
+ }
+ else
+ {
+#endif /* HAVE_DAG_API */
+ /* install traditional npf handlers for read and setfilter */
+ p->read_op = pcap_read_npf;
+ p->setfilter_op = pcap_setfilter_npf;
+#ifdef HAVE_DAG_API
+ }
+#endif /* HAVE_DAG_API */
+ p->setdirection_op = NULL; /* Not implemented. */
+ /* XXX - can this be implemented on some versions of Windows? */
+ p->inject_op = pcap_inject_npf;
+ p->set_datalink_op = NULL; /* can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_npf;
+ p->setnonblock_op = pcap_setnonblock_npf;
+ p->stats_op = pcap_stats_npf;
+ p->stats_ex_op = pcap_stats_ex_npf;
+ p->setbuff_op = pcap_setbuff_npf;
+ p->setmode_op = pcap_setmode_npf;
+ p->setmintocopy_op = pcap_setmintocopy_npf;
+ p->getevent_op = pcap_getevent_npf;
+ p->oid_get_request_op = pcap_oid_get_request_npf;
+ p->oid_set_request_op = pcap_oid_set_request_npf;
+ p->sendqueue_transmit_op = pcap_sendqueue_transmit_npf;
+ p->setuserbuffer_op = pcap_setuserbuffer_npf;
+ p->live_dump_op = pcap_live_dump_npf;
+ p->live_dump_ended_op = pcap_live_dump_ended_npf;
+ p->get_airpcap_handle_op = pcap_get_airpcap_handle_npf;
+ p->cleanup_op = pcap_cleanup_npf;
+
+ /*
+ * XXX - this is only done because WinPcap supported
+ * pcap_fileno() returning the hFile HANDLE from the
+ * ADAPTER structure. We make no general guarantees
+ * that the caller can do anything useful with it.
+ *
+ * (Not that we make any general guarantee of that
+ * sort on UN*X, either, any more, given that not
+ * all capture devices are regular OS network
+ * interfaces.)
+ */
+ p->handle = pw->adapter->hFile;
+
+ return (status);
+bad:
+ pcap_cleanup_npf(p);
+ return (PCAP_ERROR);
+}
+
+/*
+* Check if rfmon mode is supported on the pcap_t for Windows systems.
+*/
+static int
+pcap_can_set_rfmon_npf(pcap_t *p)
+{
+ return (PacketIsMonitorModeSupported(p->opt.device) == 1);
+}
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof(struct pcap_win));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_npf;
+ p->can_set_rfmon_op = pcap_can_set_rfmon_npf;
+ return (p);
+}
+
+static int
+pcap_setfilter_npf(pcap_t *p, struct bpf_program *fp)
+{
+ struct pcap_win *pw = p->priv;
+
+ if(PacketSetBpf(pw->adapter,fp)==FALSE){
+ /*
+ * Kernel filter not installed.
+ *
+ * XXX - we don't know whether this failed because:
+ *
+ * the kernel rejected the filter program as invalid,
+ * in which case we should fall back on userland
+ * filtering;
+ *
+ * the kernel rejected the filter program as too big,
+ * in which case we should again fall back on
+ * userland filtering;
+ *
+ * there was some other problem, in which case we
+ * should probably report an error.
+ *
+ * For NPF devices, the Win32 status will be
+ * STATUS_INVALID_DEVICE_REQUEST for invalid
+ * filters, but I don't know what it'd be for
+ * other problems, and for some other devices
+ * it might not be set at all.
+ *
+ * So we just fall back on userland filtering in
+ * all cases.
+ */
+
+ /*
+ * install_bpf_program() validates the program.
+ *
+ * XXX - what if we already have a filter in the kernel?
+ */
+ if (install_bpf_program(p, fp) < 0)
+ return (-1);
+ pw->filtering_in_kernel = 0; /* filtering in userland */
+ return (0);
+ }
+
+ /*
+ * It worked.
+ */
+ pw->filtering_in_kernel = 1; /* filtering in the kernel */
+
+ /*
+ * Discard any previously-received packets, as they might have
+ * passed whatever filter was formerly in effect, but might
+ * not pass this filter (BIOCSETF discards packets buffered
+ * in the kernel, so you can lose packets in any case).
+ */
+ p->cc = 0;
+ return (0);
+}
+
+/*
+ * We filter at user level, since the kernel driver does't process the packets
+ */
+static int
+pcap_setfilter_win32_dag(pcap_t *p, struct bpf_program *fp) {
+
+ if(!fp)
+ {
+ pcap_strlcpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+ return (-1);
+ }
+
+ /* Install a user level filter */
+ if (install_bpf_program(p, fp) < 0)
+ return (-1);
+
+ return (0);
+}
+
+static int
+pcap_getnonblock_npf(pcap_t *p)
+{
+ struct pcap_win *pw = p->priv;
+
+ /*
+ * XXX - if there were a PacketGetReadTimeout() call, we
+ * would use it, and return 1 if the timeout is -1
+ * and 0 otherwise.
+ */
+ return (pw->nonblock);
+}
+
+static int
+pcap_setnonblock_npf(pcap_t *p, int nonblock)
+{
+ struct pcap_win *pw = p->priv;
+ int newtimeout;
+
+ if (nonblock) {
+ /*
+ * Set the packet buffer timeout to -1 for non-blocking
+ * mode.
+ */
+ newtimeout = -1;
+ } else {
+ /*
+ * Restore the timeout set when the device was opened.
+ * (Note that this may be -1, in which case we're not
+ * really leaving non-blocking mode. However, although
+ * the timeout argument to pcap_set_timeout() and
+ * pcap_open_live() is an int, you're not supposed to
+ * supply a negative value, so that "shouldn't happen".)
+ */
+ newtimeout = p->opt.timeout;
+ }
+ if (!PacketSetReadTimeout(pw->adapter, newtimeout)) {
+ pcap_fmt_errmsg_for_win32_err(p->errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "PacketSetReadTimeout");
+ return (-1);
+ }
+ pw->nonblock = (newtimeout == -1);
+ return (0);
+}
+
+static int
+pcap_add_if_npf(pcap_if_list_t *devlistp, char *name, bpf_u_int32 flags,
+ const char *description, char *errbuf)
+{
+ pcap_if_t *curdev;
+ npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
+ LONG if_addr_size;
+ int res = 0;
+
+ if_addr_size = MAX_NETWORK_ADDRESSES;
+
+ /*
+ * Add an entry for this interface, with no addresses.
+ */
+ curdev = add_dev(devlistp, name, flags, description, errbuf);
+ if (curdev == NULL) {
+ /*
+ * Failure.
+ */
+ return (-1);
+ }
+
+ /*
+ * Get the list of addresses for the interface.
+ */
+ if (!PacketGetNetInfoEx((void *)name, if_addrs, &if_addr_size)) {
+ /*
+ * Failure.
+ *
+ * We don't return an error, because this can happen with
+ * NdisWan interfaces, and we want to supply them even
+ * if we can't supply their addresses.
+ *
+ * We return an entry with an empty address list.
+ */
+ return (0);
+ }
+
+ /*
+ * Now add the addresses.
+ */
+ while (if_addr_size-- > 0) {
+ /*
+ * "curdev" is an entry for this interface; add an entry for
+ * this address to its list of addresses.
+ */
+ res = add_addr_to_dev(curdev,
+ (struct sockaddr *)&if_addrs[if_addr_size].IPAddress,
+ sizeof (struct sockaddr_storage),
+ (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask,
+ sizeof (struct sockaddr_storage),
+ (struct sockaddr *)&if_addrs[if_addr_size].Broadcast,
+ sizeof (struct sockaddr_storage),
+ NULL,
+ 0,
+ errbuf);
+ if (res == -1) {
+ /*
+ * Failure.
+ */
+ break;
+ }
+ }
+
+ return (res);
+}
+
+static int
+get_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf)
+{
+ char *name_copy;
+ ADAPTER *adapter;
+ int status;
+ size_t len;
+ NDIS_HARDWARE_STATUS hardware_status;
+#ifdef OID_GEN_PHYSICAL_MEDIUM
+ NDIS_PHYSICAL_MEDIUM phys_medium;
+ bpf_u_int32 gen_physical_medium_oids[] = {
+ #ifdef OID_GEN_PHYSICAL_MEDIUM_EX
+ OID_GEN_PHYSICAL_MEDIUM_EX,
+ #endif
+ OID_GEN_PHYSICAL_MEDIUM
+ };
+#define N_GEN_PHYSICAL_MEDIUM_OIDS (sizeof gen_physical_medium_oids / sizeof gen_physical_medium_oids[0])
+ size_t i;
+#endif /* OID_GEN_PHYSICAL_MEDIUM */
+#ifdef OID_GEN_LINK_STATE
+ NDIS_LINK_STATE link_state;
+#endif
+ int connect_status;
+
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback interface, so the connection status doesn't
+ * apply. and it's not wireless (or wired, for that
+ * matter...). We presume it's up and running.
+ */
+ *flags |= PCAP_IF_UP | PCAP_IF_RUNNING | PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return (0);
+ }
+
+ /*
+ * We need to open the adapter to get this information.
+ *
+ * XXX - PacketOpenAdapter() takes a non-const pointer
+ * as an argument, so we make a copy of the argument and
+ * pass that to it.
+ */
+ name_copy = strdup(name);
+ adapter = PacketOpenAdapter(name_copy);
+ free(name_copy);
+ if (adapter == NULL) {
+ /*
+ * Give up; if they try to open this device, it'll fail.
+ */
+ return (0);
+ }
+
+#ifdef HAVE_AIRPCAP_API
+ /*
+ * Airpcap.sys do not support the below 'OID_GEN_x' values.
+ * Just set these flags (and none of the '*flags' entered with).
+ */
+ if (PacketGetAirPcapHandle(adapter)) {
+ /*
+ * Must be "up" and "running" if the above if succeeded.
+ */
+ *flags = PCAP_IF_UP | PCAP_IF_RUNNING;
+
+ /*
+ * An airpcap device is a wireless device (duh!)
+ */
+ *flags |= PCAP_IF_WIRELESS;
+
+ /*
+ * A "network assosiation state" makes no sense for airpcap.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ PacketCloseAdapter(adapter);
+ return (0);
+ }
+#endif
+
+ /*
+ * Get the hardware status, and derive "up" and "running" from
+ * that.
+ */
+ len = sizeof (hardware_status);
+ status = oid_get_request(adapter, OID_GEN_HARDWARE_STATUS,
+ &hardware_status, &len, errbuf);
+ if (status == 0) {
+ switch (hardware_status) {
+
+ case NdisHardwareStatusReady:
+ /*
+ * "Available and capable of sending and receiving
+ * data over the wire", so up and running.
+ */
+ *flags |= PCAP_IF_UP | PCAP_IF_RUNNING;
+ break;
+
+ case NdisHardwareStatusInitializing:
+ case NdisHardwareStatusReset:
+ /*
+ * "Initializing" or "Resetting", so up, but
+ * not running.
+ */
+ *flags |= PCAP_IF_UP;
+ break;
+
+ case NdisHardwareStatusClosing:
+ case NdisHardwareStatusNotReady:
+ /*
+ * "Closing" or "Not ready", so neither up nor
+ * running.
+ */
+ break;
+ }
+ } else {
+ /*
+ * Can't get the hardware status, so assume both up and
+ * running.
+ */
+ *flags |= PCAP_IF_UP | PCAP_IF_RUNNING;
+ }
+
+ /*
+ * Get the network type.
+ */
+#ifdef OID_GEN_PHYSICAL_MEDIUM
+ /*
+ * Try the OIDs we have for this, in order.
+ */
+ for (i = 0; i < N_GEN_PHYSICAL_MEDIUM_OIDS; i++) {
+ len = sizeof (phys_medium);
+ status = oid_get_request(adapter, gen_physical_medium_oids[i],
+ &phys_medium, &len, errbuf);
+ if (status == 0) {
+ /*
+ * Success.
+ */
+ break;
+ }
+ /*
+ * Failed. We can't determine whether it failed
+ * because that particular OID isn't supported
+ * or because some other problem occurred, so we
+ * just drive on and try the next OID.
+ */
+ }
+ if (status == 0) {
+ /*
+ * We got the physical medium.
+ */
+ switch (phys_medium) {
+
+ case NdisPhysicalMediumWirelessLan:
+ case NdisPhysicalMediumWirelessWan:
+ case NdisPhysicalMediumNative802_11:
+ case NdisPhysicalMediumBluetooth:
+ case NdisPhysicalMediumUWB:
+ case NdisPhysicalMediumIrda:
+ /*
+ * Wireless.
+ */
+ *flags |= PCAP_IF_WIRELESS;
+ break;
+
+ default:
+ /*
+ * Not wireless.
+ */
+ break;
+ }
+ }
+#endif
+
+ /*
+ * Get the connection status.
+ */
+#ifdef OID_GEN_LINK_STATE
+ len = sizeof(link_state);
+ status = oid_get_request(adapter, OID_GEN_LINK_STATE, &link_state,
+ &len, errbuf);
+ if (status == 0) {
+ /*
+ * NOTE: this also gives us the receive and transmit
+ * link state.
+ */
+ switch (link_state.MediaConnectState) {
+
+ case MediaConnectStateConnected:
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ break;
+
+ case MediaConnectStateDisconnected:
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ break;
+ }
+ }
+#else
+ /*
+ * OID_GEN_LINK_STATE isn't supported because it's not in our SDK.
+ */
+ status = -1;
+#endif
+ if (status == -1) {
+ /*
+ * OK, OID_GEN_LINK_STATE didn't work, try
+ * OID_GEN_MEDIA_CONNECT_STATUS.
+ */
+ status = oid_get_request(adapter, OID_GEN_MEDIA_CONNECT_STATUS,
+ &connect_status, &len, errbuf);
+ if (status == 0) {
+ switch (connect_status) {
+
+ case NdisMediaStateConnected:
+ /*
+ * It's connected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED;
+ break;
+
+ case NdisMediaStateDisconnected:
+ /*
+ * It's disconnected.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED;
+ break;
+ }
+ }
+ }
+ PacketCloseAdapter(adapter);
+ return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ int ret = 0;
+ const char *desc;
+ char *AdaptersName;
+ ULONG NameLength;
+ char *name;
+
+ /*
+ * Find out how big a buffer we need.
+ *
+ * This call should always return FALSE; if the error is
+ * ERROR_INSUFFICIENT_BUFFER, NameLength will be set to
+ * the size of the buffer we need, otherwise there's a
+ * problem, and NameLength should be set to 0.
+ *
+ * It shouldn't require NameLength to be set, but,
+ * at least as of WinPcap 4.1.3, it checks whether
+ * NameLength is big enough before it checks for a
+ * NULL buffer argument, so, while it'll still do
+ * the right thing if NameLength is uninitialized and
+ * whatever junk happens to be there is big enough
+ * (because the pointer argument will be null), it's
+ * still reading an uninitialized variable.
+ */
+ NameLength = 0;
+ if (!PacketGetAdapterNames(NULL, &NameLength))
+ {
+ DWORD last_error = GetLastError();
+
+ if (last_error != ERROR_INSUFFICIENT_BUFFER)
+ {
+ pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+ last_error, "PacketGetAdapterNames");
+ return (-1);
+ }
+ }
+
+ if (NameLength <= 0)
+ return 0;
+ AdaptersName = (char*) malloc(NameLength);
+ if (AdaptersName == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot allocate enough memory to list the adapters.");
+ return (-1);
+ }
+
+ if (!PacketGetAdapterNames(AdaptersName, &NameLength)) {
+ pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "PacketGetAdapterNames");
+ free(AdaptersName);
+ return (-1);
+ }
+
+ /*
+ * "PacketGetAdapterNames()" returned a list of
+ * null-terminated ASCII interface name strings,
+ * terminated by a null string, followed by a list
+ * of null-terminated ASCII interface description
+ * strings, terminated by a null string.
+ * This means there are two ASCII nulls at the end
+ * of the first list.
+ *
+ * Find the end of the first list; that's the
+ * beginning of the second list.
+ */
+ desc = &AdaptersName[0];
+ while (*desc != '\0' || *(desc + 1) != '\0')
+ desc++;
+
+ /*
+ * Found it - "desc" points to the first of the two
+ * nulls at the end of the list of names, so the
+ * first byte of the list of descriptions is two bytes
+ * after it.
+ */
+ desc += 2;
+
+ /*
+ * Loop over the elements in the first list.
+ */
+ name = &AdaptersName[0];
+ while (*name != '\0') {
+ bpf_u_int32 flags = 0;
+#ifdef HAVE_PACKET_IS_LOOPBACK_ADAPTER
+ /*
+ * Is this a loopback interface?
+ */
+ if (PacketIsLoopbackAdapter(name)) {
+ /* Yes */
+ flags |= PCAP_IF_LOOPBACK;
+ }
+#endif
+ /*
+ * Get additional flags.
+ */
+ if (get_if_flags(name, &flags, errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ ret = -1;
+ break;
+ }
+
+ /*
+ * Add an entry for this interface.
+ */
+ if (pcap_add_if_npf(devlistp, name, flags, desc,
+ errbuf) == -1) {
+ /*
+ * Failure.
+ */
+ ret = -1;
+ break;
+ }
+ name += strlen(name) + 1;
+ desc += strlen(desc) + 1;
+ }
+
+ free(AdaptersName);
+ return (ret);
+}
+
+/*
+ * Return the name of a network interface attached to the system, or NULL
+ * if none can be found. The interface must be configured up; the
+ * lowest unit number is preferred; loopback is ignored.
+ *
+ * In the best of all possible worlds, this would be the same as on
+ * UN*X, but there may be software that expects this to return a
+ * full list of devices after the first device.
+ */
+#define ADAPTERSNAME_LEN 8192
+char *
+pcap_lookupdev(char *errbuf)
+{
+ DWORD dwVersion;
+ DWORD dwWindowsMajorVersion;
+
+#pragma warning (push)
+#pragma warning (disable: 4996) /* disable MSVC's GetVersion() deprecated warning here */
+ dwVersion = GetVersion(); /* get the OS version */
+#pragma warning (pop)
+ dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
+
+ if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) {
+ /*
+ * Windows 95, 98, ME.
+ */
+ ULONG NameLength = ADAPTERSNAME_LEN;
+ static char AdaptersName[ADAPTERSNAME_LEN];
+
+ if (PacketGetAdapterNames(AdaptersName,&NameLength) )
+ return (AdaptersName);
+ else
+ return NULL;
+ } else {
+ /*
+ * Windows NT (NT 4.0 and later).
+ * Convert the names to Unicode for backward compatibility.
+ */
+ ULONG NameLength = ADAPTERSNAME_LEN;
+ static WCHAR AdaptersName[ADAPTERSNAME_LEN];
+ size_t BufferSpaceLeft;
+ char *tAstr;
+ WCHAR *Unameptr;
+ char *Adescptr;
+ size_t namelen, i;
+ WCHAR *TAdaptersName = (WCHAR*)malloc(ADAPTERSNAME_LEN * sizeof(WCHAR));
+ int NAdapts = 0;
+
+ if(TAdaptersName == NULL)
+ {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "memory allocation failure");
+ return NULL;
+ }
+
+ if ( !PacketGetAdapterNames((PTSTR)TAdaptersName,&NameLength) )
+ {
+ pcap_fmt_errmsg_for_win32_err(errbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "PacketGetAdapterNames");
+ free(TAdaptersName);
+ return NULL;
+ }
+
+
+ BufferSpaceLeft = ADAPTERSNAME_LEN * sizeof(WCHAR);
+ tAstr = (char*)TAdaptersName;
+ Unameptr = AdaptersName;
+
+ /*
+ * Convert the device names to Unicode into AdapterName.
+ */
+ do {
+ /*
+ * Length of the name, including the terminating
+ * NUL.
+ */
+ namelen = strlen(tAstr) + 1;
+
+ /*
+ * Do we have room for the name in the Unicode
+ * buffer?
+ */
+ if (BufferSpaceLeft < namelen * sizeof(WCHAR)) {
+ /*
+ * No.
+ */
+ goto quit;
+ }
+ BufferSpaceLeft -= namelen * sizeof(WCHAR);
+
+ /*
+ * Copy the name, converting ASCII to Unicode.
+ * namelen includes the NUL, so we copy it as
+ * well.
+ */
+ for (i = 0; i < namelen; i++)
+ *Unameptr++ = *tAstr++;
+
+ /*
+ * Count this adapter.
+ */
+ NAdapts++;
+ } while (namelen != 1);
+
+ /*
+ * Copy the descriptions, but don't convert them from
+ * ASCII to Unicode.
+ */
+ Adescptr = (char *)Unameptr;
+ while(NAdapts--)
+ {
+ size_t desclen;
+
+ desclen = strlen(tAstr) + 1;
+
+ /*
+ * Do we have room for the name in the Unicode
+ * buffer?
+ */
+ if (BufferSpaceLeft < desclen) {
+ /*
+ * No.
+ */
+ goto quit;
+ }
+
+ /*
+ * Just copy the ASCII string.
+ * namelen includes the NUL, so we copy it as
+ * well.
+ */
+ memcpy(Adescptr, tAstr, desclen);
+ Adescptr += desclen;
+ tAstr += desclen;
+ BufferSpaceLeft -= desclen;
+ }
+
+ quit:
+ free(TAdaptersName);
+ return (char *)(AdaptersName);
+ }
+}
+
+/*
+ * We can't use the same code that we use on UN*X, as that's doing
+ * UN*X-specific calls.
+ *
+ * We don't just fetch the entire list of devices, search for the
+ * particular device, and use its first IPv4 address, as that's too
+ * much work to get just one device's netmask.
+ */
+int
+pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
+ char *errbuf)
+{
+ /*
+ * We need only the first IPv4 address, so we must scan the array returned by PacketGetNetInfo()
+ * in order to skip non IPv4 (i.e. IPv6 addresses)
+ */
+ npf_if_addr if_addrs[MAX_NETWORK_ADDRESSES];
+ LONG if_addr_size = MAX_NETWORK_ADDRESSES;
+ struct sockaddr_in *t_addr;
+ LONG i;
+
+ if (!PacketGetNetInfoEx((void *)device, if_addrs, &if_addr_size)) {
+ *netp = *maskp = 0;
+ return (0);
+ }
+
+ for(i = 0; i < if_addr_size; i++)
+ {
+ if(if_addrs[i].IPAddress.ss_family == AF_INET)
+ {
+ t_addr = (struct sockaddr_in *) &(if_addrs[i].IPAddress);
+ *netp = t_addr->sin_addr.S_un.S_addr;
+ t_addr = (struct sockaddr_in *) &(if_addrs[i].SubnetMask);
+ *maskp = t_addr->sin_addr.S_un.S_addr;
+
+ *netp &= *maskp;
+ return (0);
+ }
+
+ }
+
+ *netp = *maskp = 0;
+ return (0);
+}
+
+static const char *pcap_lib_version_string;
+
+#ifdef HAVE_VERSION_H
+/*
+ * libpcap being built for Windows, as part of a WinPcap/Npcap source
+ * tree. Include version.h from that source tree to get the WinPcap/Npcap
+ * version.
+ *
+ * XXX - it'd be nice if we could somehow generate the WinPcap/Npcap version
+ * number when building as part of WinPcap/Npcap. (It'd be nice to do so
+ * for the packet.dll version number as well.)
+ */
+#include "../../version.h"
+
+static const char pcap_version_string[] =
+ WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING ", based on " PCAP_VERSION_STRING;
+
+const char *
+pcap_lib_version(void)
+{
+ if (pcap_lib_version_string == NULL) {
+ /*
+ * Generate the version string.
+ */
+ char *packet_version_string = PacketGetVersion();
+
+ if (strcmp(WINPCAP_VER_STRING, packet_version_string) == 0) {
+ /*
+ * WinPcap/Npcap version string and packet.dll version
+ * string are the same; just report the WinPcap/Npcap
+ * version.
+ */
+ pcap_lib_version_string = pcap_version_string;
+ } else {
+ /*
+ * WinPcap/Npcap version string and packet.dll version
+ * string are different; that shouldn't be the
+ * case (the two libraries should come from the
+ * same version of WinPcap/Npcap), so we report both
+ * versions.
+ */
+ char *full_pcap_version_string;
+
+ if (pcap_asprintf(&full_pcap_version_string,
+ WINPCAP_PRODUCT_NAME " version " WINPCAP_VER_STRING " (packet.dll version %s), based on " PCAP_VERSION_STRING,
+ packet_version_string) != -1) {
+ /* Success */
+ pcap_lib_version_string = full_pcap_version_string;
+ }
+ }
+ }
+ return (pcap_lib_version_string);
+}
+
+#else /* HAVE_VERSION_H */
+
+/*
+ * libpcap being built for Windows, not as part of a WinPcap/Npcap source
+ * tree.
+ */
+const char *
+pcap_lib_version(void)
+{
+ if (pcap_lib_version_string == NULL) {
+ /*
+ * Generate the version string. Report the packet.dll
+ * version.
+ */
+ char *full_pcap_version_string;
+
+ if (pcap_asprintf(&full_pcap_version_string,
+ PCAP_VERSION_STRING " (packet.dll version %s)",
+ PacketGetVersion()) != -1) {
+ /* Success */
+ pcap_lib_version_string = full_pcap_version_string;
+ }
+ }
+ return (pcap_lib_version_string);
+}
+#endif /* HAVE_VERSION_H */
diff --git a/lib/libpcap/libpcap/pcap-null.c b/lib/libpcap/libpcap/pcap-null.c
new file mode 100644
index 0000000..2ae27bf
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-null.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+
+#include "pcap-int.h"
+
+static char nosup[] = "live packet capture not supported on this system";
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ (void)pcap_strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE);
+ return (NULL);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp _U_, char *errbuf _U_)
+{
+ /*
+ * There are no interfaces on which we can capture.
+ */
+ return (0);
+}
+
+#ifdef _WIN32
+int
+pcap_lookupnet(const char *device _U_, bpf_u_int32 *netp _U_,
+ bpf_u_int32 *maskp _U_, char *errbuf)
+{
+ (void)pcap_strlcpy(errbuf, nosup, PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+#endif
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-pf.c b/lib/libpcap/libpcap/pcap-pf.c
new file mode 100644
index 0000000..fde97ba
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-pf.c
@@ -0,0 +1,683 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * packet filter subroutines for tcpdump
+ * Extraction/creation by Jeffrey Mogul, DECWRL
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <net/pfilt.h>
+
+struct mbuf;
+struct rtentry;
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
+ * native OS version, as we need various BPF ioctls from it.
+ */
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <net/bpf.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * FDDI packets are padded to make everything line up on a nice boundary.
+ */
+#define PCAP_FDDIPAD 3
+
+/*
+ * Private data for capturing on Ultrix and DEC OSF/1^WDigital UNIX^W^W
+ * Tru64 UNIX packetfilter devices.
+ */
+struct pcap_pf {
+ int filtering_in_kernel; /* using kernel filter */
+ u_long TotPkts; /* can't oflow for 79 hrs on ether */
+ u_long TotAccepted; /* count accepted by filter */
+ u_long TotDrops; /* count of dropped packets */
+ long TotMissed; /* missed by i/f during this run */
+ long OrigMissed; /* missed by i/f before this run */
+};
+
+static int pcap_setfilter_pf(pcap_t *, struct bpf_program *);
+
+/*
+ * BUFSPACE is the size in bytes of the packet read buffer. Most tcpdump
+ * applications aren't going to need more than 200 bytes of packet header
+ * and the read shouldn't return more packets than packetfilter's internal
+ * queue limit (bounded at 256).
+ */
+#define BUFSPACE (200 * 256)
+
+static int
+pcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_pf *pf = pc->priv;
+ register u_char *p, *bp;
+ register int cc, n, buflen, inc;
+ register struct enstamp *sp;
+#ifdef LBL_ALIGN
+ struct enstamp stamp;
+#endif
+ register u_int pad;
+
+ again:
+ cc = pc->cc;
+ if (cc == 0) {
+ cc = read(pc->fd, (char *)pc->buffer + pc->offset, pc->bufsize);
+ if (cc < 0) {
+ if (errno == EWOULDBLOCK)
+ return (0);
+ if (errno == EINVAL &&
+ lseek(pc->fd, 0L, SEEK_CUR) + pc->bufsize < 0) {
+ /*
+ * Due to a kernel bug, after 2^31 bytes,
+ * the kernel file offset overflows and
+ * read fails with EINVAL. The lseek()
+ * to 0 will fix things.
+ */
+ (void)lseek(pc->fd, 0L, SEEK_SET);
+ goto again;
+ }
+ pcap_fmt_errmsg_for_errno(pc->errbuf,
+ sizeof(pc->errbuf), errno, "pf read");
+ return (-1);
+ }
+ bp = (u_char *)pc->buffer + pc->offset;
+ } else
+ bp = pc->bp;
+ /*
+ * Loop through each packet.
+ */
+ n = 0;
+ pad = pc->fddipad;
+ while (cc > 0) {
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (pc->break_loop) {
+ if (n == 0) {
+ pc->break_loop = 0;
+ return (-2);
+ } else {
+ pc->cc = cc;
+ pc->bp = bp;
+ return (n);
+ }
+ }
+ if (cc < sizeof(*sp)) {
+ pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
+ "pf short read (%d)", cc);
+ return (-1);
+ }
+#ifdef LBL_ALIGN
+ if ((long)bp & 3) {
+ sp = &stamp;
+ memcpy((char *)sp, (char *)bp, sizeof(*sp));
+ } else
+#endif
+ sp = (struct enstamp *)bp;
+ if (sp->ens_stamplen != sizeof(*sp)) {
+ pcap_snprintf(pc->errbuf, sizeof(pc->errbuf),
+ "pf short stamplen (%d)",
+ sp->ens_stamplen);
+ return (-1);
+ }
+
+ p = bp + sp->ens_stamplen;
+ buflen = sp->ens_count;
+ if (buflen > pc->snapshot)
+ buflen = pc->snapshot;
+
+ /* Calculate inc before possible pad update */
+ inc = ENALIGN(buflen + sp->ens_stamplen);
+ cc -= inc;
+ bp += inc;
+ pf->TotPkts++;
+ pf->TotDrops += sp->ens_dropped;
+ pf->TotMissed = sp->ens_ifoverflows;
+ if (pf->OrigMissed < 0)
+ pf->OrigMissed = pf->TotMissed;
+
+ /*
+ * Short-circuit evaluation: if using BPF filter
+ * in kernel, no need to do it now - we already know
+ * the packet passed the filter.
+ *
+ * Note: the filter code was generated assuming
+ * that pc->fddipad was the amount of padding
+ * before the header, as that's what's required
+ * in the kernel, so we run the filter before
+ * skipping that padding.
+ */
+ if (pf->filtering_in_kernel ||
+ bpf_filter(pc->fcode.bf_insns, p, sp->ens_count, buflen)) {
+ struct pcap_pkthdr h;
+ pf->TotAccepted++;
+ h.ts = sp->ens_tstamp;
+ h.len = sp->ens_count - pad;
+ p += pad;
+ buflen -= pad;
+ h.caplen = buflen;
+ (*callback)(user, &h, p);
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
+ pc->cc = cc;
+ pc->bp = bp;
+ return (n);
+ }
+ }
+ }
+ pc->cc = 0;
+ return (n);
+}
+
+static int
+pcap_inject_pf(pcap_t *p, const void *buf, size_t size)
+{
+ int ret;
+
+ ret = write(p->fd, buf, size);
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
+pcap_stats_pf(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_pf *pf = p->priv;
+
+ /*
+ * If packet filtering is being done in the kernel:
+ *
+ * "ps_recv" counts only packets that passed the filter.
+ * This does not include packets dropped because we
+ * ran out of buffer space. (XXX - perhaps it should,
+ * by adding "ps_drop" to "ps_recv", for compatibility
+ * with some other platforms. On the other hand, on
+ * some platforms "ps_recv" counts only packets that
+ * passed the filter, and on others it counts packets
+ * that didn't pass the filter....)
+ *
+ * "ps_drop" counts packets that passed the kernel filter
+ * (if any) but were dropped because the input queue was
+ * full.
+ *
+ * "ps_ifdrop" counts packets dropped by the network
+ * inteface (regardless of whether they would have passed
+ * the input filter, of course).
+ *
+ * If packet filtering is not being done in the kernel:
+ *
+ * "ps_recv" counts only packets that passed the filter.
+ *
+ * "ps_drop" counts packets that were dropped because the
+ * input queue was full, regardless of whether they passed
+ * the userland filter.
+ *
+ * "ps_ifdrop" counts packets dropped by the network
+ * inteface (regardless of whether they would have passed
+ * the input filter, of course).
+ *
+ * These statistics don't include packets not yet read from
+ * the kernel by libpcap, but they may include packets not
+ * yet read from libpcap by the application.
+ */
+ ps->ps_recv = pf->TotAccepted;
+ ps->ps_drop = pf->TotDrops;
+ ps->ps_ifdrop = pf->TotMissed - pf->OrigMissed;
+ return (0);
+}
+
+/*
+ * We include the OS's <net/bpf.h>, not our "pcap/bpf.h", so we probably
+ * don't get DLT_DOCSIS defined.
+ */
+#ifndef DLT_DOCSIS
+#define DLT_DOCSIS 143
+#endif
+
+static int
+pcap_activate_pf(pcap_t *p)
+{
+ struct pcap_pf *pf = p->priv;
+ short enmode;
+ int backlog = -1; /* request the most */
+ struct enfilter Filter;
+ struct endevp devparams;
+ int err;
+
+ /*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ *
+ * XXX - we assume here that "pfopen()" does not, in fact, modify
+ * its argument, even though it takes a "char *" rather than a
+ * "const char *" as its first argument. That appears to be
+ * the case, at least on Digital UNIX 4.0.
+ *
+ * XXX - is there an error that means "no such device"? Is
+ * there one that means "that device doesn't support pf"?
+ */
+ p->fd = pfopen(p->opt.device, O_RDWR);
+ if (p->fd == -1 && errno == EACCES)
+ p->fd = pfopen(p->opt.device, O_RDONLY);
+ if (p->fd < 0) {
+ if (errno == EACCES) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "pf open: %s: Permission denied\n"
+"your system may not be properly configured; see the packetfilter(4) man page",
+ p->opt.device);
+ err = PCAP_ERROR_PERM_DENIED;
+ } else {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "pf open: %s", p->opt.device);
+ err = PCAP_ERROR;
+ }
+ goto bad;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ pf->OrigMissed = -1;
+ enmode = ENTSTAMP|ENNONEXCL;
+ if (!p->opt.immediate)
+ enmode |= ENBATCH;
+ if (p->opt.promisc)
+ enmode |= ENPROMISC;
+ if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "EIOCMBIS");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+#ifdef ENCOPYALL
+ /* Try to set COPYALL mode so that we see packets to ourself */
+ enmode = ENCOPYALL;
+ (void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */
+#endif
+ /* set the backlog */
+ if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "EIOCSETW");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ /* discover interface type */
+ if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "EIOCDEVP");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ /* HACK: to compile prior to Ultrix 4.2 */
+#ifndef ENDT_FDDI
+#define ENDT_FDDI 4
+#endif
+ switch (devparams.end_dev_type) {
+
+ case ENDT_10MB:
+ p->linktype = DLT_EN10MB;
+ p->offset = 2;
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+ break;
+
+ case ENDT_FDDI:
+ p->linktype = DLT_FDDI;
+ break;
+
+#ifdef ENDT_SLIP
+ case ENDT_SLIP:
+ p->linktype = DLT_SLIP;
+ break;
+#endif
+
+#ifdef ENDT_PPP
+ case ENDT_PPP:
+ p->linktype = DLT_PPP;
+ break;
+#endif
+
+#ifdef ENDT_LOOPBACK
+ case ENDT_LOOPBACK:
+ /*
+ * It appears to use Ethernet framing, at least on
+ * Digital UNIX 4.0.
+ */
+ p->linktype = DLT_EN10MB;
+ p->offset = 2;
+ break;
+#endif
+
+#ifdef ENDT_TRN
+ case ENDT_TRN:
+ p->linktype = DLT_IEEE802;
+ break;
+#endif
+
+ default:
+ /*
+ * XXX - what about ENDT_IEEE802? The pfilt.h header
+ * file calls this "IEEE 802 networks (non-Ethernet)",
+ * but that doesn't specify a specific link layer type;
+ * it could be 802.4, or 802.5 (except that 802.5 is
+ * ENDT_TRN), or 802.6, or 802.11, or.... That's why
+ * DLT_IEEE802 was hijacked to mean Token Ring in various
+ * BSDs, and why we went along with that hijacking.
+ *
+ * XXX - what about ENDT_HDLC and ENDT_NULL?
+ * Presumably, as ENDT_OTHER is just "Miscellaneous
+ * framing", there's not much we can do, as that
+ * doesn't specify a particular type of header.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "unknown data-link type %u", devparams.end_dev_type);
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ /* set truncation */
+ if (p->linktype == DLT_FDDI) {
+ p->fddipad = PCAP_FDDIPAD;
+
+ /* packetfilter includes the padding in the snapshot */
+ p->snapshot += PCAP_FDDIPAD;
+ } else
+ p->fddipad = 0;
+ if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&p->snapshot) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "EIOCTRUNCATE");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ /* accept all packets */
+ memset(&Filter, 0, sizeof(Filter));
+ Filter.enf_Priority = 37; /* anything > 2 */
+ Filter.enf_FilterLen = 0; /* means "always true" */
+ if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "EIOCSETF");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+
+ if (p->opt.timeout != 0) {
+ struct timeval timeout;
+ timeout.tv_sec = p->opt.timeout / 1000;
+ timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
+ if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "EIOCSRTIMEOUT");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ }
+
+ p->bufsize = BUFSPACE;
+ p->buffer = malloc(p->bufsize + p->offset);
+ if (p->buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * "select()" and "poll()" work on packetfilter devices.
+ */
+ p->selectable_fd = p->fd;
+
+ p->read_op = pcap_read_pf;
+ p->inject_op = pcap_inject_pf;
+ p->setfilter_op = pcap_setfilter_pf;
+ p->setdirection_op = NULL; /* Not implemented. */
+ p->set_datalink_op = NULL; /* can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_stats_pf;
+
+ return (0);
+ bad:
+ pcap_cleanup_live_common(p);
+ return (err);
+}
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_pf));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_pf;
+ return (p);
+}
+
+/*
+ * XXX - is there an error from pfopen() that means "no such device"?
+ * Is there one that means "that device doesn't support pf"?
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do other than mark loopback devices as "the
+ * connected/disconnected status doesn't apply".
+ *
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ if (*flags & PCAP_IF_LOOPBACK) {
+ /*
+ * Loopback devices aren't wireless, and "connected"/
+ * "disconnected" doesn't apply to them.
+ */
+ *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE;
+ return (0);
+ }
+ return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+ get_if_flags));
+}
+
+static int
+pcap_setfilter_pf(pcap_t *p, struct bpf_program *fp)
+{
+ struct pcap_pf *pf = p->priv;
+ struct bpf_version bv;
+
+ /*
+ * See if BIOCVERSION works. If not, we assume the kernel doesn't
+ * support BPF-style filters (it's not documented in the bpf(7)
+ * or packetfiler(7) man pages, but the code used to fail if
+ * BIOCSETF worked but BIOCVERSION didn't, and I've seen it do
+ * kernel filtering in DU 4.0, so presumably BIOCVERSION works
+ * there, at least).
+ */
+ if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) >= 0) {
+ /*
+ * OK, we have the version of the BPF interpreter;
+ * is it the same major version as us, and the same
+ * or better minor version?
+ */
+ if (bv.bv_major == BPF_MAJOR_VERSION &&
+ bv.bv_minor >= BPF_MINOR_VERSION) {
+ /*
+ * Yes. Try to install the filter.
+ */
+ if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ sizeof(p->errbuf), errno, "BIOCSETF");
+ return (-1);
+ }
+
+ /*
+ * OK, that succeeded. We're doing filtering in
+ * the kernel. (We assume we don't have a
+ * userland filter installed - that'd require
+ * a previous version check to have failed but
+ * this one to succeed.)
+ *
+ * XXX - this message should be supplied to the
+ * application as a warning of some sort,
+ * except that if it's a GUI application, it's
+ * not clear that it should be displayed in
+ * a window to annoy the user.
+ */
+ fprintf(stderr, "tcpdump: Using kernel BPF filter\n");
+ pf->filtering_in_kernel = 1;
+
+ /*
+ * Discard any previously-received packets,
+ * as they might have passed whatever filter
+ * was formerly in effect, but might not pass
+ * this filter (BIOCSETF discards packets buffered
+ * in the kernel, so you can lose packets in any
+ * case).
+ */
+ p->cc = 0;
+ return (0);
+ }
+
+ /*
+ * We can't use the kernel's BPF interpreter; don't give
+ * up, just log a message and be inefficient.
+ *
+ * XXX - this should really be supplied to the application
+ * as a warning of some sort.
+ */
+ fprintf(stderr,
+ "tcpdump: Requires BPF language %d.%d or higher; kernel is %d.%d\n",
+ BPF_MAJOR_VERSION, BPF_MINOR_VERSION,
+ bv.bv_major, bv.bv_minor);
+ }
+
+ /*
+ * We couldn't do filtering in the kernel; do it in userland.
+ */
+ if (install_bpf_program(p, fp) < 0)
+ return (-1);
+
+ /*
+ * XXX - this message should be supplied by the application as
+ * a warning of some sort.
+ */
+ fprintf(stderr, "tcpdump: Filtering in user process\n");
+ pf->filtering_in_kernel = 0;
+ return (0);
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-pktap.h b/lib/libpcap/libpcap/pcap-pktap.h
new file mode 100644
index 0000000..cec8c46
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-pktap.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef pcap_pktap_h
+#define pcap_pktap_h
+
+#include <net/pktap.h>
+
+#include <stdbool.h>
+
+#ifndef PTH_FLAG_REXMIT
+#define PTH_FLAG_REXMIT 0x00008000 /* Packet is a retransmission */
+#endif /* PTH_FLAG_REXMIT */
+
+#ifndef PTH_FLAG_KEEP_ALIVE
+#define PTH_FLAG_KEEP_ALIVE 0x00010000 /* Is keep alive packet */
+#endif /* PTH_FLAG_KEEP_ALIVE */
+
+#ifndef PTH_FLAG_SOCKET
+#define PTH_FLAG_SOCKET 0x00020000 /* Packet on a Socket */
+#endif /* PTH_FLAG_SOCKET */
+
+#ifndef PTH_FLAG_NEXUS_CHAN
+#define PTH_FLAG_NEXUS_CHAN 0x00040000 /* Packet on a nexus channel */
+#endif /* PTH_FLAG_NEXUS_CHAN */
+
+#ifndef PTH_FLAG_V2_HDR
+#define PTH_FLAG_V2_HDR 0x00080000 /* Version 2 of pktap */
+#endif /* PTH_FLAG_V2_HDR */
+
+
+pcap_t *pktap_create(const char *device, char *ebuf, int *is_ours);
+
+
+#endif /* pcap_pktap_h */
diff --git a/lib/libpcap/libpcap/pcap-rdmasniff.c b/lib/libpcap/libpcap/pcap-rdmasniff.c
new file mode 100644
index 0000000..c50fe3f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-rdmasniff.c
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2017 Pure Storage, 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. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "pcap-int.h"
+#include "pcap-rdmasniff.h"
+
+#include <infiniband/verbs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+
+#if !defined(IBV_FLOW_ATTR_SNIFFER)
+#define IBV_FLOW_ATTR_SNIFFER 3
+#endif
+
+static const int RDMASNIFF_NUM_RECEIVES = 128;
+static const int RDMASNIFF_RECEIVE_SIZE = 10000;
+
+struct pcap_rdmasniff {
+ struct ibv_device * rdma_device;
+ struct ibv_context * context;
+ struct ibv_comp_channel * channel;
+ struct ibv_pd * pd;
+ struct ibv_cq * cq;
+ struct ibv_qp * qp;
+ struct ibv_flow * flow;
+ struct ibv_mr * mr;
+ u_char * oneshot_buffer;
+ unsigned port_num;
+ int cq_event;
+ u_int packets_recv;
+};
+
+static int
+rdmasniff_stats(pcap_t *handle, struct pcap_stat *stat)
+{
+ struct pcap_rdmasniff *priv = handle->priv;
+
+ stat->ps_recv = priv->packets_recv;
+ stat->ps_drop = 0;
+ stat->ps_ifdrop = 0;
+
+ return 0;
+}
+
+static void
+rdmasniff_cleanup(pcap_t *handle)
+{
+ struct pcap_rdmasniff *priv = handle->priv;
+
+ ibv_dereg_mr(priv->mr);
+ ibv_destroy_flow(priv->flow);
+ ibv_destroy_qp(priv->qp);
+ ibv_destroy_cq(priv->cq);
+ ibv_dealloc_pd(priv->pd);
+ ibv_destroy_comp_channel(priv->channel);
+ ibv_close_device(priv->context);
+ free(priv->oneshot_buffer);
+
+ pcap_cleanup_live_common(handle);
+}
+
+static void
+rdmasniff_post_recv(pcap_t *handle, uint64_t wr_id)
+{
+ struct pcap_rdmasniff *priv = handle->priv;
+ struct ibv_sge sg_entry;
+ struct ibv_recv_wr wr, *bad_wr;
+
+ sg_entry.length = RDMASNIFF_RECEIVE_SIZE;
+ sg_entry.addr = (uintptr_t) handle->buffer + RDMASNIFF_RECEIVE_SIZE * wr_id;
+ sg_entry.lkey = priv->mr->lkey;
+
+ wr.wr_id = wr_id;
+ wr.num_sge = 1;
+ wr.sg_list = &sg_entry;
+ wr.next = NULL;
+
+ ibv_post_recv(priv->qp, &wr, &bad_wr);
+}
+
+static int
+rdmasniff_read(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+ struct pcap_rdmasniff *priv = handle->priv;
+ struct ibv_cq *ev_cq;
+ void *ev_ctx;
+ struct ibv_wc wc;
+ struct pcap_pkthdr pkth;
+ u_char *pktd;
+ int count = 0;
+
+ if (!priv->cq_event) {
+ while (ibv_get_cq_event(priv->channel, &ev_cq, &ev_ctx) < 0) {
+ if (errno != EINTR) {
+ return PCAP_ERROR;
+ }
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+ ibv_ack_cq_events(priv->cq, 1);
+ ibv_req_notify_cq(priv->cq, 0);
+ priv->cq_event = 1;
+ }
+
+ while (count < max_packets || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
+ if (ibv_poll_cq(priv->cq, 1, &wc) != 1) {
+ priv->cq_event = 0;
+ break;
+ }
+
+ if (wc.status != IBV_WC_SUCCESS) {
+ fprintf(stderr, "failed WC wr_id %lld status %d/%s\n",
+ (unsigned long long) wc.wr_id,
+ wc.status, ibv_wc_status_str(wc.status));
+ continue;
+ }
+
+ pkth.len = wc.byte_len;
+ pkth.caplen = min(pkth.len, (u_int)handle->snapshot);
+ gettimeofday(&pkth.ts, NULL);
+
+ pktd = (u_char *) handle->buffer + wc.wr_id * RDMASNIFF_RECEIVE_SIZE;
+
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, pktd, pkth.len, pkth.caplen)) {
+ callback(user, &pkth, pktd);
+ ++priv->packets_recv;
+ ++count;
+ }
+
+ rdmasniff_post_recv(handle, wc.wr_id);
+
+ if (handle->break_loop) {
+ handle->break_loop = 0;
+ return PCAP_ERROR_BREAK;
+ }
+ }
+
+ return count;
+}
+
+static void
+rdmasniff_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
+{
+ struct oneshot_userdata *sp = (struct oneshot_userdata *) user;
+ pcap_t *handle = sp->pd;
+ struct pcap_rdmasniff *priv = handle->priv;
+
+ *sp->hdr = *h;
+ memcpy(priv->oneshot_buffer, bytes, h->caplen);
+ *sp->pkt = priv->oneshot_buffer;
+}
+
+static int
+rdmasniff_activate(pcap_t *handle)
+{
+ struct pcap_rdmasniff *priv = handle->priv;
+ struct ibv_qp_init_attr qp_init_attr;
+ struct ibv_qp_attr qp_attr;
+ struct ibv_flow_attr flow_attr;
+ struct ibv_port_attr port_attr;
+ int i;
+
+ priv->context = ibv_open_device(priv->rdma_device);
+ if (!priv->context) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to open device %s", handle->opt.device);
+ goto error;
+ }
+
+ priv->pd = ibv_alloc_pd(priv->context);
+ if (!priv->pd) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to alloc PD for device %s", handle->opt.device);
+ goto error;
+ }
+
+ priv->channel = ibv_create_comp_channel(priv->context);
+ if (!priv->channel) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to create comp channel for device %s", handle->opt.device);
+ goto error;
+ }
+
+ priv->cq = ibv_create_cq(priv->context, RDMASNIFF_NUM_RECEIVES,
+ NULL, priv->channel, 0);
+ if (!priv->cq) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to create CQ for device %s", handle->opt.device);
+ goto error;
+ }
+
+ ibv_req_notify_cq(priv->cq, 0);
+
+ memset(&qp_init_attr, 0, sizeof qp_init_attr);
+ qp_init_attr.send_cq = qp_init_attr.recv_cq = priv->cq;
+ qp_init_attr.cap.max_recv_wr = RDMASNIFF_NUM_RECEIVES;
+ qp_init_attr.cap.max_recv_sge = 1;
+ qp_init_attr.qp_type = IBV_QPT_RAW_PACKET;
+ priv->qp = ibv_create_qp(priv->pd, &qp_init_attr);
+ if (!priv->qp) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to create QP for device %s", handle->opt.device);
+ goto error;
+ }
+
+ memset(&qp_attr, 0, sizeof qp_attr);
+ qp_attr.qp_state = IBV_QPS_INIT;
+ qp_attr.port_num = priv->port_num;
+ if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE | IBV_QP_PORT)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to modify QP to INIT for device %s", handle->opt.device);
+ goto error;
+ }
+
+ memset(&qp_attr, 0, sizeof qp_attr);
+ qp_attr.qp_state = IBV_QPS_RTR;
+ if (ibv_modify_qp(priv->qp, &qp_attr, IBV_QP_STATE)) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to modify QP to RTR for device %s", handle->opt.device);
+ goto error;
+ }
+
+ memset(&flow_attr, 0, sizeof flow_attr);
+ flow_attr.type = IBV_FLOW_ATTR_SNIFFER;
+ flow_attr.size = sizeof flow_attr;
+ flow_attr.port = priv->port_num;
+ priv->flow = ibv_create_flow(priv->qp, &flow_attr);
+ if (!priv->flow) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to create flow for device %s", handle->opt.device);
+ goto error;
+ }
+
+ handle->bufsize = RDMASNIFF_NUM_RECEIVES * RDMASNIFF_RECEIVE_SIZE;
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to allocate receive buffer for device %s", handle->opt.device);
+ goto error;
+ }
+
+ priv->oneshot_buffer = malloc(RDMASNIFF_RECEIVE_SIZE);
+ if (!priv->oneshot_buffer) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to allocate oneshot buffer for device %s", handle->opt.device);
+ goto error;
+ }
+
+ priv->mr = ibv_reg_mr(priv->pd, handle->buffer, handle->bufsize, IBV_ACCESS_LOCAL_WRITE);
+ if (!priv->mr) {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Failed to register MR for device %s", handle->opt.device);
+ goto error;
+ }
+
+
+ for (i = 0; i < RDMASNIFF_NUM_RECEIVES; ++i) {
+ rdmasniff_post_recv(handle, i);
+ }
+
+ if (!ibv_query_port(priv->context, priv->port_num, &port_attr) &&
+ port_attr.link_layer == IBV_LINK_LAYER_INFINIBAND) {
+ handle->linktype = DLT_INFINIBAND;
+ } else {
+ handle->linktype = DLT_EN10MB;
+ }
+
+ if (handle->snapshot <= 0 || handle->snapshot > RDMASNIFF_RECEIVE_SIZE)
+ handle->snapshot = RDMASNIFF_RECEIVE_SIZE;
+
+ handle->offset = 0;
+ handle->read_op = rdmasniff_read;
+ handle->stats_op = rdmasniff_stats;
+ handle->cleanup_op = rdmasniff_cleanup;
+ handle->setfilter_op = install_bpf_program;
+ handle->setdirection_op = NULL;
+ handle->set_datalink_op = NULL;
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->oneshot_callback = rdmasniff_oneshot;
+ handle->selectable_fd = priv->channel->fd;
+
+ return 0;
+
+error:
+ if (priv->mr) {
+ ibv_dereg_mr(priv->mr);
+ }
+
+ if (priv->flow) {
+ ibv_destroy_flow(priv->flow);
+ }
+
+ if (priv->qp) {
+ ibv_destroy_qp(priv->qp);
+ }
+
+ if (priv->cq) {
+ ibv_destroy_cq(priv->cq);
+ }
+
+ if (priv->channel) {
+ ibv_destroy_comp_channel(priv->channel);
+ }
+
+ if (priv->pd) {
+ ibv_dealloc_pd(priv->pd);
+ }
+
+ if (priv->context) {
+ ibv_close_device(priv->context);
+ }
+
+ if (priv->oneshot_buffer) {
+ free(priv->oneshot_buffer);
+ }
+
+ return PCAP_ERROR;
+}
+
+pcap_t *
+rdmasniff_create(const char *device, char *ebuf, int *is_ours)
+{
+ struct pcap_rdmasniff *priv;
+ struct ibv_device **dev_list;
+ int numdev;
+ size_t namelen;
+ const char *port;
+ unsigned port_num;
+ int i;
+ pcap_t *p = NULL;
+
+ *is_ours = 0;
+
+ dev_list = ibv_get_device_list(&numdev);
+ if (!dev_list || !numdev) {
+ return NULL;
+ }
+
+ namelen = strlen(device);
+
+ port = strchr(device, ':');
+ if (port) {
+ port_num = strtoul(port + 1, NULL, 10);
+ if (port_num > 0) {
+ namelen = port - device;
+ } else {
+ port_num = 1;
+ }
+ } else {
+ port_num = 1;
+ }
+
+ for (i = 0; i < numdev; ++i) {
+ if (strlen(dev_list[i]->name) == namelen &&
+ !strncmp(device, dev_list[i]->name, namelen)) {
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_rdmasniff));
+ if (p) {
+ p->activate_op = rdmasniff_activate;
+ priv = p->priv;
+ priv->rdma_device = dev_list[i];
+ priv->port_num = port_num;
+ }
+ break;
+ }
+ }
+
+ ibv_free_device_list(dev_list);
+ return p;
+}
+
+int
+rdmasniff_findalldevs(pcap_if_list_t *devlistp, char *err_str)
+{
+ struct ibv_device **dev_list;
+ int numdev;
+ int i;
+ int ret = 0;
+
+ dev_list = ibv_get_device_list(&numdev);
+ if (!dev_list || !numdev) {
+ return 0;
+ }
+
+ for (i = 0; i < numdev; ++i) {
+ /*
+ * XXX - do the notions of "up", "running", or
+ * "connected" apply here?
+ */
+ if (!add_dev(devlistp, dev_list[i]->name, 0, "RDMA sniffer", err_str)) {
+ ret = -1;
+ goto out;
+ }
+ }
+
+out:
+ ibv_free_device_list(dev_list);
+ return ret;
+}
diff --git a/lib/libpcap/libpcap/pcap-rdmasniff.h b/lib/libpcap/libpcap/pcap-rdmasniff.h
new file mode 100644
index 0000000..ff1f3c2
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-rdmasniff.h
@@ -0,0 +1,2 @@
+pcap_t *rdmasniff_create(const char *device, char *ebuf, int *is_ours);
+int rdmasniff_findalldevs(pcap_if_list_t *devlistp, char *err_str);
diff --git a/lib/libpcap/libpcap/pcap-rpcap-int.h b/lib/libpcap/libpcap/pcap-rpcap-int.h
new file mode 100644
index 0000000..e707a85
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-rpcap-int.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (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 Politecnico di Torino, CACE Technologies
+ * nor the names 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.
+ *
+ */
+
+#ifndef __PCAP_RPCAP_INT_H__
+#define __PCAP_RPCAP_INT_H__
+
+#include "pcap.h"
+#include "sockutils.h" /* Needed for some structures (like SOCKET, sockaddr_in) which are used here */
+
+/*
+ * \file pcap-rpcap-int.h
+ *
+ * This file keeps all the definitions used by the RPCAP client and server,
+ * other than the protocol definitions.
+ *
+ * \warning All the RPCAP functions that are allowed to return a buffer containing
+ * the error description can return max PCAP_ERRBUF_SIZE characters.
+ * However there is no guarantees that the string will be zero-terminated.
+ * Best practice is to define the errbuf variable as a char of size 'PCAP_ERRBUF_SIZE+1'
+ * and to insert manually the termination char at the end of the buffer. This will
+ * guarantee that no buffer overflows occur even if we use the printf() to show
+ * the error on the screen.
+ */
+
+/*********************************************************
+ * *
+ * General definitions / typedefs for the RPCAP protocol *
+ * *
+ *********************************************************/
+
+/*
+ * \brief Buffer used by socket functions to send-receive packets.
+ * In case you plan to have messages larger than this value, you have to increase it.
+ */
+#define RPCAP_NETBUF_SIZE 64000
+
+/*********************************************************
+ * *
+ * Exported function prototypes *
+ * *
+ *********************************************************/
+void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length);
+int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, char *errbuf);
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap-rpcap.c b/lib/libpcap/libpcap/pcap-rpcap.c
new file mode 100644
index 0000000..705f06f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-rpcap.c
@@ -0,0 +1,3233 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (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 Politecnico di Torino, CACE Technologies
+ * nor the names 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+#include <string.h> /* for strlen(), ... */
+#include <stdlib.h> /* for malloc(), free(), ... */
+#include <stdarg.h> /* for functions with variable number of arguments */
+#include <errno.h> /* for the errno variable */
+#include "sockutils.h"
+#include "pcap-int.h"
+#include "rpcap-protocol.h"
+#include "pcap-rpcap.h"
+
+/*
+ * This file contains the pcap module for capturing from a remote machine's
+ * interfaces using the RPCAP protocol.
+ *
+ * WARNING: All the RPCAP functions that are allowed to return a buffer
+ * containing the error description can return max PCAP_ERRBUF_SIZE characters.
+ * However there is no guarantees that the string will be zero-terminated.
+ * Best practice is to define the errbuf variable as a char of size
+ * 'PCAP_ERRBUF_SIZE+1' and to insert manually a NULL character at the end
+ * of the buffer. This will guarantee that no buffer overflows occur even
+ * if we use the printf() to show the error on the screen.
+ *
+ * XXX - actually, null-terminating the error string is part of the
+ * contract for the pcap API; if there's any place in the pcap code
+ * that doesn't guarantee null-termination, even at the expense of
+ * cutting the message short, that's a bug and needs to be fixed.
+ */
+
+#define PCAP_STATS_STANDARD 0 /* Used by pcap_stats_rpcap to see if we want standard or extended statistics */
+#ifdef _WIN32
+#define PCAP_STATS_EX 1 /* Used by pcap_stats_rpcap to see if we want standard or extended statistics */
+#endif
+
+/*
+ * \brief Keeps a list of all the opened connections in the active mode.
+ *
+ * This structure defines a linked list of items that are needed to keep the info required to
+ * manage the active mode.
+ * In other words, when a new connection in active mode starts, this structure is updated so that
+ * it reflects the list of active mode connections currently opened.
+ * This structure is required by findalldevs() and open_remote() to see if they have to open a new
+ * control connection toward the host, or they already have a control connection in place.
+ */
+struct activehosts
+{
+ struct sockaddr_storage host;
+ SOCKET sockctrl;
+ uint8 protocol_version;
+ struct activehosts *next;
+};
+
+/* Keeps a list of all the opened connections in the active mode. */
+static struct activehosts *activeHosts;
+
+/*
+ * Keeps the main socket identifier when we want to accept a new remote
+ * connection (active mode only).
+ * See the documentation of pcap_remoteact_accept() and
+ * pcap_remoteact_cleanup() for more details.
+ */
+static SOCKET sockmain;
+
+/*
+ * Private data for capturing remotely using the rpcap protocol.
+ */
+struct pcap_rpcap {
+ /*
+ * This is '1' if we're the network client; it is needed by several
+ * functions (such as pcap_setfilter()) to know whether they have
+ * to use the socket or have to open the local adapter.
+ */
+ int rmt_clientside;
+
+ SOCKET rmt_sockctrl; /* socket ID of the socket used for the control connection */
+ SOCKET rmt_sockdata; /* socket ID of the socket used for the data connection */
+ int rmt_flags; /* we have to save flags, since they are passed by the pcap_open_live(), but they are used by the pcap_startcapture() */
+ int rmt_capstarted; /* 'true' if the capture is already started (needed to knoe if we have to call the pcap_startcapture() */
+ char *currentfilter; /* Pointer to a buffer (allocated at run-time) that stores the current filter. Needed when flag PCAP_OPENFLAG_NOCAPTURE_RPCAP is turned on. */
+
+ uint8 protocol_version; /* negotiated protocol version */
+
+ unsigned int TotNetDrops; /* keeps the number of packets that have been dropped by the network */
+
+ /*
+ * This keeps the number of packets that have been received by the
+ * application.
+ *
+ * Packets dropped by the kernel buffer are not counted in this
+ * variable. It is always equal to (TotAccepted - TotDrops),
+ * except for the case of remote capture, in which we have also
+ * packets in flight, i.e. that have been transmitted by the remote
+ * host, but that have not been received (yet) from the client.
+ * In this case, (TotAccepted - TotDrops - TotNetDrops) gives a
+ * wrong result, since this number does not corresponds always to
+ * the number of packet received by the application. For this reason,
+ * in the remote capture we need another variable that takes into
+ * account of the number of packets actually received by the
+ * application.
+ */
+ unsigned int TotCapt;
+
+ struct pcap_stat stat;
+ /* XXX */
+ struct pcap *next; /* list of open pcaps that need stuff cleared on close */
+};
+
+/****************************************************
+ * *
+ * Locally defined functions *
+ * *
+ ****************************************************/
+static struct pcap_stat *rpcap_stats_rpcap(pcap_t *p, struct pcap_stat *ps, int mode);
+static int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog);
+static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog);
+static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog);
+static void pcap_save_current_filter_rpcap(pcap_t *fp, const char *filter);
+static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog);
+static int pcap_setsampling_remote(pcap_t *fp);
+static int pcap_startcapture_remote(pcap_t *fp);
+static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf);
+static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf);
+static int rpcap_process_msg_header(SOCKET sock, uint8 ver, uint8 request_type, struct rpcap_header *header, char *errbuf);
+static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf);
+static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf);
+static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf);
+static int rpcap_read_packet_msg(SOCKET sock, pcap_t *p, size_t size);
+
+/****************************************************
+ * *
+ * Function bodies *
+ * *
+ ****************************************************/
+
+/*
+ * This function translates (i.e. de-serializes) a 'rpcap_sockaddr'
+ * structure from the network byte order to a 'sockaddr_in" or
+ * 'sockaddr_in6' structure in the host byte order.
+ *
+ * It accepts an 'rpcap_sockaddr' structure as it is received from the
+ * network, and checks the address family field against various values
+ * to see whether it looks like an IPv4 address, an IPv6 address, or
+ * neither of those. It checks for multiple values in order to try
+ * to handle older rpcap daemons that sent the native OS's 'sockaddr_in'
+ * or 'sockaddr_in6' structures over the wire with some members
+ * byte-swapped, and to handle the fact that AF_INET6 has different
+ * values on different OSes.
+ *
+ * For IPv4 addresses, it converts the address family to host byte
+ * order from network byte order and puts it into the structure,
+ * sets the length if a sockaddr structure has a length, converts the
+ * port number to host byte order from network byte order and puts
+ * it into the structure, copies over the IPv4 address, and zeroes
+ * out the zero padding.
+ *
+ * For IPv6 addresses, it converts the address family to host byte
+ * order from network byte order and puts it into the structure,
+ * sets the length if a sockaddr structure has a length, converts the
+ * port number and flow information to host byte order from network
+ * byte order and puts them into the structure, copies over the IPv6
+ * address, and converts the scope ID to host byte order from network
+ * byte order and puts it into the structure.
+ *
+ * The function will allocate the 'sockaddrout' variable according to the
+ * address family in use. In case the address does not belong to the
+ * AF_INET nor AF_INET6 families, 'sockaddrout' is not allocated and a
+ * NULL pointer is returned. This usually happens because that address
+ * does not exist on the other host, or is of an address family other
+ * than AF_INET or AF_INET6, so the RPCAP daemon sent a 'sockaddr_storage'
+ * structure containing all 'zero' values.
+ *
+ * Older RPCAPDs sent the addresses over the wire in the OS's native
+ * structure format. For most OSes, this looks like the over-the-wire
+ * format, but might have a different value for AF_INET6 than the value
+ * on the machine receiving the reply. For OSes with the newer BSD-style
+ * sockaddr structures, this has, instead of a 2-byte address family,
+ * a 1-byte structure length followed by a 1-byte address family. The
+ * RPCAPD code would put the address family in network byte order before
+ * sending it; that would set it to 0 on a little-endian machine, as
+ * htons() of any value between 1 and 255 would result in a value > 255,
+ * with its lower 8 bits zero, so putting that back into a 1-byte field
+ * would set it to 0.
+ *
+ * Therefore, for older RPCAPDs running on an OS with newer BSD-style
+ * sockaddr structures, the family field, if treated as a big-endian
+ * (network byte order) 16-bit field, would be:
+ *
+ * (length << 8) | family if sent by a big-endian machine
+ * (length << 8) if sent by a little-endian machine
+ *
+ * For current RPCAPDs, and for older RPCAPDs running on an OS with
+ * older BSD-style sockaddr structures, the family field, if treated
+ * as a big-endian 16-bit field, would just contain the family.
+ *
+ * \param sockaddrin: a 'rpcap_sockaddr' pointer to the variable that has
+ * to be de-serialized.
+ *
+ * \param sockaddrout: a 'sockaddr_storage' pointer to the variable that will contain
+ * the de-serialized data. The structure returned can be either a 'sockaddr_in' or 'sockaddr_in6'.
+ * This variable will be allocated automatically inside this function.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
+ * that will contain the error message (in case there is one).
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. Basically, the error
+ * can be only the fact that the malloc() failed to allocate memory.
+ * The error message is returned in the 'errbuf' variable, while the deserialized address
+ * is returned into the 'sockaddrout' variable.
+ *
+ * \warning This function supports only AF_INET and AF_INET6 address families.
+ *
+ * \warning The sockaddrout (if not NULL) must be deallocated by the user.
+ */
+
+/*
+ * Possible IPv4 family values other than the designated over-the-wire value,
+ * which is 2 (because everybody uses 2 for AF_INET4).
+ */
+#define SOCKADDR_IN_LEN 16 /* length of struct sockaddr_in */
+#define SOCKADDR_IN6_LEN 28 /* length of struct sockaddr_in6 */
+#define NEW_BSD_AF_INET_BE ((SOCKADDR_IN_LEN << 8) | 2)
+#define NEW_BSD_AF_INET_LE (SOCKADDR_IN_LEN << 8)
+
+/*
+ * Possible IPv6 family values other than the designated over-the-wire value,
+ * which is 23 (because that's what Windows uses, and most RPCAP servers
+ * out there are probably running Windows, as WinPcap includes the server
+ * but few if any UN*Xes build and ship it).
+ *
+ * The new BSD sockaddr structure format was in place before 4.4-Lite, so
+ * all the free-software BSDs use it.
+ */
+#define NEW_BSD_AF_INET6_BSD_BE ((SOCKADDR_IN6_LEN << 8) | 24) /* NetBSD, OpenBSD, BSD/OS */
+#define NEW_BSD_AF_INET6_FREEBSD_BE ((SOCKADDR_IN6_LEN << 8) | 28) /* FreeBSD, DragonFly BSD */
+#define NEW_BSD_AF_INET6_DARWIN_BE ((SOCKADDR_IN6_LEN << 8) | 30) /* macOS, iOS, anything else Darwin-based */
+#define NEW_BSD_AF_INET6_LE (SOCKADDR_IN6_LEN << 8)
+#define LINUX_AF_INET6 10
+#define HPUX_AF_INET6 22
+#define AIX_AF_INET6 24
+#define SOLARIS_AF_INET6 26
+
+static int
+rpcap_deseraddr(struct rpcap_sockaddr *sockaddrin, struct sockaddr_storage **sockaddrout, char *errbuf)
+{
+ /* Warning: we support only AF_INET and AF_INET6 */
+ switch (ntohs(sockaddrin->family))
+ {
+ case RPCAP_AF_INET:
+ case NEW_BSD_AF_INET_BE:
+ case NEW_BSD_AF_INET_LE:
+ {
+ struct rpcap_sockaddr_in *sockaddrin_ipv4;
+ struct sockaddr_in *sockaddrout_ipv4;
+
+ (*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in));
+ if ((*sockaddrout) == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc() failed");
+ return -1;
+ }
+ sockaddrin_ipv4 = (struct rpcap_sockaddr_in *) sockaddrin;
+ sockaddrout_ipv4 = (struct sockaddr_in *) (*sockaddrout);
+ sockaddrout_ipv4->sin_family = AF_INET;
+ sockaddrout_ipv4->sin_port = ntohs(sockaddrin_ipv4->port);
+ memcpy(&sockaddrout_ipv4->sin_addr, &sockaddrin_ipv4->addr, sizeof(sockaddrout_ipv4->sin_addr));
+ memset(sockaddrout_ipv4->sin_zero, 0, sizeof(sockaddrout_ipv4->sin_zero));
+ break;
+ }
+
+#ifdef AF_INET6
+ case RPCAP_AF_INET6:
+ case NEW_BSD_AF_INET6_BSD_BE:
+ case NEW_BSD_AF_INET6_FREEBSD_BE:
+ case NEW_BSD_AF_INET6_DARWIN_BE:
+ case NEW_BSD_AF_INET6_LE:
+ case LINUX_AF_INET6:
+ case HPUX_AF_INET6:
+ case AIX_AF_INET6:
+ case SOLARIS_AF_INET6:
+ {
+ struct rpcap_sockaddr_in6 *sockaddrin_ipv6;
+ struct sockaddr_in6 *sockaddrout_ipv6;
+
+ (*sockaddrout) = (struct sockaddr_storage *) malloc(sizeof(struct sockaddr_in6));
+ if ((*sockaddrout) == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc() failed");
+ return -1;
+ }
+ sockaddrin_ipv6 = (struct rpcap_sockaddr_in6 *) sockaddrin;
+ sockaddrout_ipv6 = (struct sockaddr_in6 *) (*sockaddrout);
+ sockaddrout_ipv6->sin6_family = AF_INET6;
+ sockaddrout_ipv6->sin6_port = ntohs(sockaddrin_ipv6->port);
+ sockaddrout_ipv6->sin6_flowinfo = ntohl(sockaddrin_ipv6->flowinfo);
+ memcpy(&sockaddrout_ipv6->sin6_addr, &sockaddrin_ipv6->addr, sizeof(sockaddrout_ipv6->sin6_addr));
+ sockaddrout_ipv6->sin6_scope_id = ntohl(sockaddrin_ipv6->scope_id);
+ break;
+ }
+#endif
+
+ default:
+ /*
+ * It is neither AF_INET nor AF_INET6 (or, if the OS doesn't
+ * support AF_INET6, it's not AF_INET).
+ */
+ *sockaddrout = NULL;
+ break;
+ }
+ return 0;
+}
+
+/*
+ * This function reads a packet from the network socket. It does not
+ * deliver the packet to a pcap_dispatch()/pcap_loop() callback (hence
+ * the "nocb" string into its name).
+ *
+ * This function is called by pcap_read_rpcap().
+ *
+ * WARNING: By choice, this function does not make use of semaphores. A smarter
+ * implementation should put a semaphore into the data thread, and a signal will
+ * be raised as soon as there is data into the socket buffer.
+ * However this is complicated and it does not bring any advantages when reading
+ * from the network, in which network delays can be much more important than
+ * these optimizations. Therefore, we chose the following approach:
+ * - the 'timeout' chosen by the user is split in two (half on the server side,
+ * with the usual meaning, and half on the client side)
+ * - this function checks for packets; if there are no packets, it waits for
+ * timeout/2 and then it checks again. If packets are still missing, it returns,
+ * otherwise it reads packets.
+ */
+static int pcap_read_nocb_remote(pcap_t *p, struct pcap_pkthdr *pkt_header, u_char **pkt_data)
+{
+ struct pcap_rpcap *pr = p->priv; /* structure used when doing a remote live capture */
+ struct rpcap_header *header; /* general header according to the RPCAP format */
+ struct rpcap_pkthdr *net_pkt_header; /* header of the packet, from the message */
+ u_char *net_pkt_data; /* packet data from the message */
+ uint32 plen;
+ int retval; /* generic return value */
+ int msglen;
+
+ /* Structures needed for the select() call */
+ struct timeval tv; /* maximum time the select() can block waiting for data */
+ fd_set rfds; /* set of socket descriptors we have to check */
+
+ /*
+ * Define the packet buffer timeout, to be used in the select()
+ * 'timeout', in pcap_t, is in milliseconds; we have to convert it into sec and microsec
+ */
+ tv.tv_sec = p->opt.timeout / 1000;
+ tv.tv_usec = (p->opt.timeout - tv.tv_sec * 1000) * 1000;
+
+ /* Watch out sockdata to see if it has input */
+ FD_ZERO(&rfds);
+
+ /*
+ * 'fp->rmt_sockdata' has always to be set before calling the select(),
+ * since it is cleared by the select()
+ */
+ FD_SET(pr->rmt_sockdata, &rfds);
+
+ retval = select((int) pr->rmt_sockdata + 1, &rfds, NULL, NULL, &tv);
+ if (retval == -1)
+ {
+#ifndef _WIN32
+ if (errno == EINTR)
+ {
+ /* Interrupted. */
+ return 0;
+ }
+#endif
+ sock_geterror("select()", p->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* There is no data waiting, so return '0' */
+ if (retval == 0)
+ return 0;
+
+ /*
+ * We have to define 'header' as a pointer to a larger buffer,
+ * because in case of UDP we have to read all the message within a single call
+ */
+ header = (struct rpcap_header *) p->buffer;
+ net_pkt_header = (struct rpcap_pkthdr *) ((char *)p->buffer + sizeof(struct rpcap_header));
+ net_pkt_data = (u_char *)p->buffer + sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr);
+
+ if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+ {
+ /* Read the entire message from the network */
+ msglen = sock_recv_dgram(pr->rmt_sockdata, p->buffer,
+ p->bufsize, p->errbuf, PCAP_ERRBUF_SIZE);
+ if (msglen == -1)
+ {
+ /* Network error. */
+ return -1;
+ }
+ if (msglen == -3)
+ {
+ /* Interrupted receive. */
+ return 0;
+ }
+ if ((size_t)msglen < sizeof(struct rpcap_header))
+ {
+ /*
+ * Message is shorter than an rpcap header.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "UDP packet message is shorter than an rpcap header");
+ return -1;
+ }
+ plen = ntohl(header->plen);
+ if ((size_t)msglen < sizeof(struct rpcap_header) + plen)
+ {
+ /*
+ * Message is shorter than the header claims it
+ * is.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "UDP packet message is shorter than its rpcap header claims");
+ return -1;
+ }
+ }
+ else
+ {
+ int status;
+
+ if ((size_t)p->cc < sizeof(struct rpcap_header))
+ {
+ /*
+ * We haven't read any of the packet header yet.
+ * The size we should get is the size of the
+ * packet header.
+ */
+ status = rpcap_read_packet_msg(pr->rmt_sockdata, p,
+ sizeof(struct rpcap_header));
+ if (status == -1)
+ {
+ /* Network error. */
+ return -1;
+ }
+ if (status == -3)
+ {
+ /* Interrupted receive. */
+ return 0;
+ }
+ }
+
+ /*
+ * We have the header, so we know how long the
+ * message payload is. The size we should get
+ * is the size of the packet header plus the
+ * size of the payload.
+ */
+ plen = ntohl(header->plen);
+ if (plen > p->bufsize - sizeof(struct rpcap_header))
+ {
+ /*
+ * This is bigger than the largest
+ * record we'd expect. (We do it by
+ * subtracting in order to avoid an
+ * overflow.)
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Server sent us a message larger than the largest expected packet message");
+ return -1;
+ }
+ status = rpcap_read_packet_msg(pr->rmt_sockdata, p,
+ sizeof(struct rpcap_header) + plen);
+ if (status == -1)
+ {
+ /* Network error. */
+ return -1;
+ }
+ if (status == -3)
+ {
+ /* Interrupted receive. */
+ return 0;
+ }
+
+ /*
+ * We have the entire message; reset the buffer pointer
+ * and count, as the next read should start a new
+ * message.
+ */
+ p->bp = p->buffer;
+ p->cc = 0;
+ }
+
+ /*
+ * We have the entire message.
+ */
+ header->plen = plen;
+
+ /*
+ * Did the server specify the version we negotiated?
+ */
+ if (rpcap_check_msg_ver(pr->rmt_sockdata, pr->protocol_version,
+ header, p->errbuf) == -1)
+ {
+ return 0; /* Return 'no packets received' */
+ }
+
+ /*
+ * Is this a RPCAP_MSG_PACKET message?
+ */
+ if (header->type != RPCAP_MSG_PACKET)
+ {
+ return 0; /* Return 'no packets received' */
+ }
+
+ if (ntohl(net_pkt_header->caplen) > plen)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packet's captured data goes past the end of the received packet message.");
+ return -1;
+ }
+
+ /* Fill in packet header */
+ pkt_header->caplen = ntohl(net_pkt_header->caplen);
+ pkt_header->len = ntohl(net_pkt_header->len);
+ pkt_header->ts.tv_sec = ntohl(net_pkt_header->timestamp_sec);
+ pkt_header->ts.tv_usec = ntohl(net_pkt_header->timestamp_usec);
+
+ /* Supply a pointer to the beginning of the packet data */
+ *pkt_data = net_pkt_data;
+
+ /*
+ * I don't update the counter of the packets dropped by the network since we're using TCP,
+ * therefore no packets are dropped. Just update the number of packets received correctly
+ */
+ pr->TotCapt++;
+
+ if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+ {
+ unsigned int npkt;
+
+ /* We're using UDP, so we need to update the counter of the packets dropped by the network */
+ npkt = ntohl(net_pkt_header->npkt);
+
+ if (pr->TotCapt != npkt)
+ {
+ pr->TotNetDrops += (npkt - pr->TotCapt);
+ pr->TotCapt = npkt;
+ }
+ }
+
+ /* Packet read successfully */
+ return 1;
+}
+
+/*
+ * This function reads a packet from the network socket.
+ *
+ * This function relies on the pcap_read_nocb_remote to deliver packets. The
+ * difference, here, is that as soon as a packet is read, it is delivered
+ * to the application by means of a callback function.
+ */
+static int pcap_read_rpcap(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_rpcap *pr = p->priv; /* structure used when doing a remote live capture */
+ struct pcap_pkthdr pkt_header;
+ u_char *pkt_data;
+ int n = 0;
+ int ret;
+
+ /*
+ * If this is client-side, and we haven't already started
+ * the capture, start it now.
+ */
+ if (pr->rmt_clientside)
+ {
+ /* We are on an remote capture */
+ if (!pr->rmt_capstarted)
+ {
+ /*
+ * The capture isn't started yet, so try to
+ * start it.
+ */
+ if (pcap_startcapture_remote(p))
+ return -1;
+ }
+ }
+
+ while (n < cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
+ {
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return PCAP_ERROR_BREAK to indicate
+ * that we were told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return (PCAP_ERROR_BREAK);
+ }
+
+ /*
+ * Read some packets.
+ */
+ ret = pcap_read_nocb_remote(p, &pkt_header, &pkt_data);
+ if (ret == 1)
+ {
+ /*
+ * We got a packet. Hand it to the callback
+ * and count it so we can return the count.
+ */
+ (*callback)(user, &pkt_header, pkt_data);
+ n++;
+ }
+ else if (ret == -1)
+ {
+ /* Error. */
+ return ret;
+ }
+ else
+ {
+ /*
+ * No packet; this could mean that we timed
+ * out, or that we got interrupted, or that
+ * we got a bad packet.
+ *
+ * Were we told to break out of the loop?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes.
+ */
+ p->break_loop = 0;
+ return (PCAP_ERROR_BREAK);
+ }
+ /* No - return the number of packets we've processed. */
+ return n;
+ }
+ }
+ return n;
+}
+
+/*
+ * This function sends a CLOSE command to the capture server.
+ *
+ * It is called when the user calls pcap_close(). It sends a command
+ * to our peer that says 'ok, let's stop capturing'.
+ *
+ * WARNING: Since we're closing the connection, we do not check for errors.
+ */
+static void pcap_cleanup_rpcap(pcap_t *fp)
+{
+ struct pcap_rpcap *pr = fp->priv; /* structure used when doing a remote live capture */
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct activehosts *temp; /* temp var needed to scan the host list chain, to detect if we're in active mode */
+ int active = 0; /* active mode or not? */
+
+ /* detect if we're in active mode */
+ temp = activeHosts;
+ while (temp)
+ {
+ if (temp->sockctrl == pr->rmt_sockctrl)
+ {
+ active = 1;
+ break;
+ }
+ temp = temp->next;
+ }
+
+ if (!active)
+ {
+ rpcap_createhdr(&header, pr->protocol_version,
+ RPCAP_MSG_CLOSE, 0, 0);
+
+ /*
+ * Send the close request; don't report any errors, as
+ * we're closing this pcap_t, and have no place to report
+ * the error. No reply is sent to this message.
+ */
+ (void)sock_send(pr->rmt_sockctrl, (char *)&header,
+ sizeof(struct rpcap_header), NULL, 0);
+ }
+ else
+ {
+ rpcap_createhdr(&header, pr->protocol_version,
+ RPCAP_MSG_ENDCAP_REQ, 0, 0);
+
+ /*
+ * Send the end capture request; don't report any errors,
+ * as we're closing this pcap_t, and have no place to
+ * report the error.
+ */
+ if (sock_send(pr->rmt_sockctrl, (char *)&header,
+ sizeof(struct rpcap_header), NULL, 0) == 0)
+ {
+ /*
+ * Wait for the answer; don't report any errors,
+ * as we're closing this pcap_t, and have no
+ * place to report the error.
+ */
+ if (rpcap_process_msg_header(pr->rmt_sockctrl,
+ pr->protocol_version, RPCAP_MSG_ENDCAP_REQ,
+ &header, NULL) == 0)
+ {
+ (void)rpcap_discard(pr->rmt_sockctrl,
+ header.plen, NULL);
+ }
+ }
+ }
+
+ if (pr->rmt_sockdata)
+ {
+ sock_close(pr->rmt_sockdata, NULL, 0);
+ pr->rmt_sockdata = 0;
+ }
+
+ if ((!active) && (pr->rmt_sockctrl))
+ sock_close(pr->rmt_sockctrl, NULL, 0);
+
+ pr->rmt_sockctrl = 0;
+
+ if (pr->currentfilter)
+ {
+ free(pr->currentfilter);
+ pr->currentfilter = NULL;
+ }
+
+ pcap_cleanup_live_common(fp);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+}
+
+/*
+ * This function retrieves network statistics from our peer;
+ * it provides only the standard statistics.
+ */
+static int pcap_stats_rpcap(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_stat *retval;
+
+ retval = rpcap_stats_rpcap(p, ps, PCAP_STATS_STANDARD);
+
+ if (retval)
+ return 0;
+ else
+ return -1;
+}
+
+#ifdef _WIN32
+/*
+ * This function retrieves network statistics from our peer;
+ * it provides the additional statistics supported by pcap_stats_ex().
+ */
+static struct pcap_stat *pcap_stats_ex_rpcap(pcap_t *p, int *pcap_stat_size)
+{
+ *pcap_stat_size = sizeof (p->stat);
+
+ /* PCAP_STATS_EX (third param) means 'extended pcap_stats()' */
+ return (rpcap_stats_rpcap(p, &(p->stat), PCAP_STATS_EX));
+}
+#endif
+
+/*
+ * This function retrieves network statistics from our peer. It
+ * is used by the two previous functions.
+ *
+ * It can be called in two modes:
+ * - PCAP_STATS_STANDARD: if we want just standard statistics (i.e.,
+ * for pcap_stats())
+ * - PCAP_STATS_EX: if we want extended statistics (i.e., for
+ * pcap_stats_ex())
+ *
+ * This 'mode' parameter is needed because in pcap_stats() the variable that
+ * keeps the statistics is allocated by the user. On Windows, this structure
+ * has been extended in order to keep new stats. However, if the user has a
+ * smaller structure and it passes it to pcap_stats(), this function will
+ * try to fill in more data than the size of the structure, so that memory
+ * after the structure will be overwritten.
+ *
+ * So, we need to know it we have to copy just the standard fields, or the
+ * extended fields as well.
+ *
+ * In case we want to copy the extended fields as well, the problem of
+ * memory overflow no longer exists because the structure that's filled
+ * in is part of the pcap_t, so that it can be guaranteed to be large
+ * enough for the additional statistics.
+ *
+ * \param p: the pcap_t structure related to the current instance.
+ *
+ * \param ps: a pointer to a 'pcap_stat' structure, needed for compatibility
+ * with pcap_stat(), where the structure is allocated by the user. In case
+ * of pcap_stats_ex(), this structure and the function return value point
+ * to the same variable.
+ *
+ * \param mode: one of PCAP_STATS_STANDARD or PCAP_STATS_EX.
+ *
+ * \return The structure that keeps the statistics, or NULL in case of error.
+ * The error string is placed in the pcap_t structure.
+ */
+static struct pcap_stat *rpcap_stats_rpcap(pcap_t *p, struct pcap_stat *ps, int mode)
+{
+ struct pcap_rpcap *pr = p->priv; /* structure used when doing a remote live capture */
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct rpcap_stats netstats; /* statistics sent on the network */
+ uint32 plen; /* data remaining in the message */
+
+#ifdef _WIN32
+ if (mode != PCAP_STATS_STANDARD && mode != PCAP_STATS_EX)
+#else
+ if (mode != PCAP_STATS_STANDARD)
+#endif
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Invalid stats mode %d", mode);
+ return NULL;
+ }
+
+ /*
+ * If the capture has not yet started, we cannot request statistics
+ * for the capture from our peer, so we return 0 for all statistics,
+ * as nothing's been seen yet.
+ */
+ if (!pr->rmt_capstarted)
+ {
+ ps->ps_drop = 0;
+ ps->ps_ifdrop = 0;
+ ps->ps_recv = 0;
+#ifdef _WIN32
+ if (mode == PCAP_STATS_EX)
+ {
+ ps->ps_capt = 0;
+ ps->ps_sent = 0;
+ ps->ps_netdrop = 0;
+ }
+#endif /* _WIN32 */
+
+ return ps;
+ }
+
+ rpcap_createhdr(&header, pr->protocol_version,
+ RPCAP_MSG_STATS_REQ, 0, 0);
+
+ /* Send the PCAP_STATS command */
+ if (sock_send(pr->rmt_sockctrl, (char *)&header,
+ sizeof(struct rpcap_header), p->errbuf, PCAP_ERRBUF_SIZE) < 0)
+ return NULL; /* Unrecoverable network error */
+
+ /* Receive and process the reply message header. */
+ if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+ RPCAP_MSG_STATS_REQ, &header, p->errbuf) == -1)
+ return NULL; /* Error */
+
+ plen = header.plen;
+
+ /* Read the reply body */
+ if (rpcap_recv(pr->rmt_sockctrl, (char *)&netstats,
+ sizeof(struct rpcap_stats), &plen, p->errbuf) == -1)
+ goto error;
+
+ ps->ps_drop = ntohl(netstats.krnldrop);
+ ps->ps_ifdrop = ntohl(netstats.ifdrop);
+ ps->ps_recv = ntohl(netstats.ifrecv);
+#ifdef _WIN32
+ if (mode == PCAP_STATS_EX)
+ {
+ ps->ps_capt = pr->TotCapt;
+ ps->ps_netdrop = pr->TotNetDrops;
+ ps->ps_sent = ntohl(netstats.svrcapt);
+ }
+#endif /* _WIN32 */
+
+ /* Discard the rest of the message. */
+ if (rpcap_discard(pr->rmt_sockctrl, plen, p->errbuf) == -1)
+ goto error_nodiscard;
+
+ return ps;
+
+error:
+ /*
+ * Discard the rest of the message.
+ * We already reported an error; if this gets an error, just
+ * drive on.
+ */
+ (void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+
+error_nodiscard:
+ return NULL;
+}
+
+/*
+ * This function returns the entry in the list of active hosts for this
+ * active connection (active mode only), or NULL if there is no
+ * active connection or an error occurred. It is just for internal
+ * use.
+ *
+ * \param host: a string that keeps the host name of the host for which we
+ * want to get the socket ID for that active connection.
+ *
+ * \param error: a pointer to an int that is set to 1 if an error occurred
+ * and 0 otherwise.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size
+ * PCAP_ERRBUF_SIZE) that will contain the error message (in case
+ * there is one).
+ *
+ * \return the entry for this host in the list of active connections
+ * if found, NULL if it's not found or there's an error.
+ */
+static struct activehosts *
+rpcap_remoteact_getsock(const char *host, int *error, char *errbuf)
+{
+ struct activehosts *temp; /* temp var needed to scan the host list chain */
+ struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
+ int retval;
+
+ /* retrieve the network address corresponding to 'host' */
+ addrinfo = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ retval = getaddrinfo(host, "0", &hints, &addrinfo);
+ if (retval != 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s",
+ gai_strerror(retval));
+ *error = 1;
+ return NULL;
+ }
+
+ temp = activeHosts;
+
+ while (temp)
+ {
+ ai_next = addrinfo;
+ while (ai_next)
+ {
+ if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+ {
+ *error = 0;
+ freeaddrinfo(addrinfo);
+ return temp;
+ }
+
+ ai_next = ai_next->ai_next;
+ }
+ temp = temp->next;
+ }
+
+ if (addrinfo)
+ freeaddrinfo(addrinfo);
+
+ /*
+ * The host for which you want to get the socket ID does not have an
+ * active connection.
+ */
+ *error = 0;
+ return NULL;
+}
+
+/*
+ * This function starts a remote capture.
+ *
+ * This function is required since the RPCAP protocol decouples the 'open'
+ * from the 'start capture' functions.
+ * This function takes all the parameters needed (which have been stored
+ * into the pcap_t structure) and sends them to the server.
+ *
+ * \param fp: the pcap_t descriptor of the device currently open.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message
+ * (if one) is returned into the 'errbuf' field of the pcap_t structure.
+ */
+static int pcap_startcapture_remote(pcap_t *fp)
+{
+ struct pcap_rpcap *pr = fp->priv; /* structure used when doing a remote live capture */
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ char portdata[PCAP_BUF_SIZE]; /* temp variable needed to keep the network port for the data connection */
+ uint32 plen;
+ int active = 0; /* '1' if we're in active mode */
+ struct activehosts *temp; /* temp var needed to scan the host list chain, to detect if we're in active mode */
+ char host[INET6_ADDRSTRLEN + 1]; /* numeric name of the other host */
+
+ /* socket-related variables*/
+ struct addrinfo hints; /* temp, needed to open a socket connection */
+ struct addrinfo *addrinfo; /* temp, needed to open a socket connection */
+ SOCKET sockdata = 0; /* socket descriptor of the data connection */
+ struct sockaddr_storage saddr; /* temp, needed to retrieve the network data port chosen on the local machine */
+ socklen_t saddrlen; /* temp, needed to retrieve the network data port chosen on the local machine */
+ int ai_family; /* temp, keeps the address family used by the control connection */
+
+ /* RPCAP-related variables*/
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct rpcap_startcapreq *startcapreq; /* start capture request message */
+ struct rpcap_startcapreply startcapreply; /* start capture reply message */
+
+ /* Variables related to the buffer setting */
+ int res;
+ socklen_t itemp;
+ int sockbufsize = 0;
+ uint32 server_sockbufsize;
+
+ /*
+ * Let's check if sampling has been required.
+ * If so, let's set it first
+ */
+ if (pcap_setsampling_remote(fp) != 0)
+ return -1;
+
+ /* detect if we're in active mode */
+ temp = activeHosts;
+ while (temp)
+ {
+ if (temp->sockctrl == pr->rmt_sockctrl)
+ {
+ active = 1;
+ break;
+ }
+ temp = temp->next;
+ }
+
+ addrinfo = NULL;
+
+ /*
+ * Gets the complete sockaddr structure used in the ctrl connection
+ * This is needed to get the address family of the control socket
+ * Tip: I cannot save the ai_family of the ctrl sock in the pcap_t struct,
+ * since the ctrl socket can already be open in case of active mode;
+ * so I would have to call getpeername() anyway
+ */
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getpeername(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error_nodiscard;
+ }
+ ai_family = ((struct sockaddr_storage *) &saddr)->ss_family;
+
+ /* Get the numeric address of the remote host we are connected to */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, host,
+ sizeof(host), NULL, 0, NI_NUMERICHOST))
+ {
+ sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error_nodiscard;
+ }
+
+ /*
+ * Data connection is opened by the server toward the client if:
+ * - we're using TCP, and the user wants us to be in active mode
+ * - we're using UDP
+ */
+ if ((active) || (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+ {
+ /*
+ * We have to create a new socket to receive packets
+ * We have to do that immediately, since we have to tell the other
+ * end which network port we picked up
+ */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ /* TEMP addrinfo is NULL in case of active */
+ hints.ai_family = ai_family; /* Use the same address family of the control socket */
+ hints.ai_socktype = (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_flags = AI_PASSIVE; /* Data connection is opened by the server toward the client */
+
+ /* Let's the server pick up a free network port for us */
+ if (sock_initaddress(NULL, "0", &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error_nodiscard;
+
+ if ((sockdata = sock_open(addrinfo, SOCKOPEN_SERVER,
+ 1 /* max 1 connection in queue */, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ goto error_nodiscard;
+
+ /* addrinfo is no longer used */
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ /* get the complete sockaddr structure used in the data connection */
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error_nodiscard;
+ }
+
+ /* Get the local port the system picked up */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
+ 0, portdata, sizeof(portdata), NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error_nodiscard;
+ }
+ }
+
+ /*
+ * Now it's time to start playing with the RPCAP protocol
+ * RPCAP start capture command: create the request message
+ */
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error_nodiscard;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf,
+ pr->protocol_version, RPCAP_MSG_STARTCAP_REQ, 0,
+ sizeof(struct rpcap_startcapreq) + sizeof(struct rpcap_filter) + fp->fcode.bf_len * sizeof(struct rpcap_filterbpf_insn));
+
+ /* Fill the structure needed to open an adapter remotely */
+ startcapreq = (struct rpcap_startcapreq *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_startcapreq), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ goto error_nodiscard;
+
+ memset(startcapreq, 0, sizeof(struct rpcap_startcapreq));
+
+ /* By default, apply half the timeout on one side, half of the other */
+ fp->opt.timeout = fp->opt.timeout / 2;
+ startcapreq->read_timeout = htonl(fp->opt.timeout);
+
+ /* portdata on the openreq is meaningful only if we're in active mode */
+ if ((active) || (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+ {
+ sscanf(portdata, "%d", (int *)&(startcapreq->portdata)); /* cast to avoid a compiler warning */
+ startcapreq->portdata = htons(startcapreq->portdata);
+ }
+
+ startcapreq->snaplen = htonl(fp->snapshot);
+ startcapreq->flags = 0;
+
+ if (pr->rmt_flags & PCAP_OPENFLAG_PROMISCUOUS)
+ startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_PROMISC;
+ if (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP)
+ startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_DGRAM;
+ if (active)
+ startcapreq->flags |= RPCAP_STARTCAPREQ_FLAG_SERVEROPEN;
+
+ startcapreq->flags = htons(startcapreq->flags);
+
+ /* Pack the capture filter */
+ if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, &fp->fcode))
+ goto error_nodiscard;
+
+ if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+ PCAP_ERRBUF_SIZE) < 0)
+ goto error_nodiscard;
+
+ /* Receive and process the reply message header. */
+ if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+ RPCAP_MSG_STARTCAP_REQ, &header, fp->errbuf) == -1)
+ goto error_nodiscard;
+
+ plen = header.plen;
+
+ if (rpcap_recv(pr->rmt_sockctrl, (char *)&startcapreply,
+ sizeof(struct rpcap_startcapreply), &plen, fp->errbuf) == -1)
+ goto error;
+
+ /*
+ * In case of UDP data stream, the connection is always opened by the daemon
+ * So, this case is already covered by the code above.
+ * Now, we have still to handle TCP connections, because:
+ * - if we're in active mode, we have to wait for a remote connection
+ * - if we're in passive more, we have to start a connection
+ *
+ * We have to do he job in two steps because in case we're opening a TCP connection, we have
+ * to tell the port we're using to the remote side; in case we're accepting a TCP
+ * connection, we have to wait this info from the remote side.
+ */
+ if (!(pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP))
+ {
+ if (!active)
+ {
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = ai_family; /* Use the same address family of the control socket */
+ hints.ai_socktype = (pr->rmt_flags & PCAP_OPENFLAG_DATATX_UDP) ? SOCK_DGRAM : SOCK_STREAM;
+ pcap_snprintf(portdata, PCAP_BUF_SIZE, "%d", ntohs(startcapreply.portdata));
+
+ /* Let's the server pick up a free network port for us */
+ if (sock_initaddress(host, portdata, &hints, &addrinfo, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if ((sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, fp->errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ goto error;
+
+ /* addrinfo is no longer used */
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+ }
+ else
+ {
+ SOCKET socktemp; /* We need another socket, since we're going to accept() a connection */
+
+ /* Connection creation */
+ saddrlen = sizeof(struct sockaddr_storage);
+
+ socktemp = accept(sockdata, (struct sockaddr *) &saddr, &saddrlen);
+
+ if (socktemp == INVALID_SOCKET)
+ {
+ sock_geterror("accept()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ /* Now that I accepted the connection, the server socket is no longer needed */
+ sock_close(sockdata, fp->errbuf, PCAP_ERRBUF_SIZE);
+ sockdata = socktemp;
+ }
+ }
+
+ /* Let's save the socket of the data connection */
+ pr->rmt_sockdata = sockdata;
+
+ /*
+ * Set the size of the socket buffer for the data socket.
+ * It has the same size as the local capture buffer used
+ * on the other side of the connection.
+ */
+ server_sockbufsize = ntohl(startcapreply.bufsize);
+
+ /* Let's get the actual size of the socket buffer */
+ itemp = sizeof(sockbufsize);
+
+ res = getsockopt(sockdata, SOL_SOCKET, SO_RCVBUF, (char *)&sockbufsize, &itemp);
+ if (res == -1)
+ {
+ sock_geterror("pcap_startcapture_remote(): getsockopt() failed", fp->errbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ /*
+ * Warning: on some kernels (e.g. Linux), the size of the user
+ * buffer does not take into account the pcap_header and such,
+ * and it is set equal to the snaplen.
+ *
+ * In my view, this is wrong (the meaning of the bufsize became
+ * a bit strange). So, here bufsize is the whole size of the
+ * user buffer. In case the bufsize returned is too small,
+ * let's adjust it accordingly.
+ */
+ if (server_sockbufsize <= (u_int) fp->snapshot)
+ server_sockbufsize += sizeof(struct pcap_pkthdr);
+
+ /* if the current socket buffer is smaller than the desired one */
+ if ((u_int) sockbufsize < server_sockbufsize)
+ {
+ /*
+ * Loop until the buffer size is OK or the original
+ * socket buffer size is larger than this one.
+ */
+ for (;;)
+ {
+ res = setsockopt(sockdata, SOL_SOCKET, SO_RCVBUF,
+ (char *)&(server_sockbufsize),
+ sizeof(server_sockbufsize));
+
+ if (res == 0)
+ break;
+
+ /*
+ * If something goes wrong, halve the buffer size
+ * (checking that it does not become smaller than
+ * the current one).
+ */
+ server_sockbufsize /= 2;
+
+ if ((u_int) sockbufsize >= server_sockbufsize)
+ {
+ server_sockbufsize = sockbufsize;
+ break;
+ }
+ }
+ }
+
+ /*
+ * Let's allocate the packet; this is required in order to put
+ * the packet somewhere when extracting data from the socket.
+ * Since buffering has already been done in the socket buffer,
+ * here we need just a buffer whose size is equal to the
+ * largest possible packet message for the snapshot size,
+ * namely the length of the message header plus the length
+ * of the packet header plus the snapshot length.
+ */
+ fp->bufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + fp->snapshot;
+
+ fp->buffer = (u_char *)malloc(fp->bufsize);
+ if (fp->buffer == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(fp->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ goto error;
+ }
+
+ /*
+ * The buffer is currently empty.
+ */
+ fp->bp = fp->buffer;
+ fp->cc = 0;
+
+ /* Discard the rest of the message. */
+ if (rpcap_discard(pr->rmt_sockctrl, plen, fp->errbuf) == -1)
+ goto error_nodiscard;
+
+ /*
+ * In case the user does not want to capture RPCAP packets, let's update the filter
+ * We have to update it here (instead of sending it into the 'StartCapture' message
+ * because when we generate the 'start capture' we do not know (yet) all the ports
+ * we're currently using.
+ */
+ if (pr->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+ {
+ struct bpf_program fcode;
+
+ if (pcap_createfilter_norpcappkt(fp, &fcode) == -1)
+ goto error;
+
+ /* We cannot use 'pcap_setfilter_rpcap' because formally the capture has not been started yet */
+ /* (the 'pr->rmt_capstarted' variable will be updated some lines below) */
+ if (pcap_updatefilter_remote(fp, &fcode) == -1)
+ goto error;
+
+ pcap_freecode(&fcode);
+ }
+
+ pr->rmt_capstarted = 1;
+ return 0;
+
+error:
+ /*
+ * When the connection has been established, we have to close it. So, at the
+ * beginning of this function, if an error occur we return immediately with
+ * a return NULL; when the connection is established, we have to come here
+ * ('goto error;') in order to close everything properly.
+ */
+
+ /*
+ * Discard the rest of the message.
+ * We already reported an error; if this gets an error, just
+ * drive on.
+ */
+ (void)rpcap_discard(pr->rmt_sockctrl, plen, NULL);
+
+error_nodiscard:
+ if ((sockdata) && (sockdata != -1)) /* we can be here because sockdata said 'error' */
+ sock_close(sockdata, NULL, 0);
+
+ if (!active)
+ sock_close(pr->rmt_sockctrl, NULL, 0);
+
+ if (addrinfo != NULL)
+ freeaddrinfo(addrinfo);
+
+ /*
+ * We do not have to call pcap_close() here, because this function is always called
+ * by the user in case something bad happens
+ */
+#if 0
+ if (fp)
+ {
+ pcap_close(fp);
+ fp= NULL;
+ }
+#endif
+
+ return -1;
+}
+
+/*
+ * This function takes a bpf program and sends it to the other host.
+ *
+ * This function can be called in two cases:
+ * - pcap_startcapture_remote() is called (we have to send the filter
+ * along with the 'start capture' command)
+ * - we want to udpate the filter during a capture (i.e. pcap_setfilter()
+ * after the capture has been started)
+ *
+ * This function serializes the filter into the sending buffer ('sendbuf',
+ * passed as a parameter) and return back. It does not send anything on
+ * the network.
+ *
+ * \param fp: the pcap_t descriptor of the device currently opened.
+ *
+ * \param sendbuf: the buffer on which the serialized data has to copied.
+ *
+ * \param sendbufidx: it is used to return the abounf of bytes copied into the buffer.
+ *
+ * \param prog: the bpf program we have to copy.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+static int pcap_pack_bpffilter(pcap_t *fp, char *sendbuf, int *sendbufidx, struct bpf_program *prog)
+{
+ struct rpcap_filter *filter;
+ struct rpcap_filterbpf_insn *insn;
+ struct bpf_insn *bf_insn;
+ struct bpf_program fake_prog; /* To be used just in case the user forgot to set a filter */
+ unsigned int i;
+
+ if (prog->bf_len == 0) /* No filters have been specified; so, let's apply a "fake" filter */
+ {
+ if (pcap_compile(fp, &fake_prog, NULL /* buffer */, 1, 0) == -1)
+ return -1;
+
+ prog = &fake_prog;
+ }
+
+ filter = (struct rpcap_filter *) sendbuf;
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_filter), NULL, sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ filter->filtertype = htons(RPCAP_UPDATEFILTER_BPF);
+ filter->nitems = htonl((int32)prog->bf_len);
+
+ if (sock_bufferize(NULL, prog->bf_len * sizeof(struct rpcap_filterbpf_insn),
+ NULL, sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ insn = (struct rpcap_filterbpf_insn *) (filter + 1);
+ bf_insn = prog->bf_insns;
+
+ for (i = 0; i < prog->bf_len; i++)
+ {
+ insn->code = htons(bf_insn->code);
+ insn->jf = bf_insn->jf;
+ insn->jt = bf_insn->jt;
+ insn->k = htonl(bf_insn->k);
+
+ insn++;
+ bf_insn++;
+ }
+
+ return 0;
+}
+
+/*
+ * This function updates a filter on a remote host.
+ *
+ * It is called when the user wants to update a filter.
+ * In case we're capturing from the network, it sends the filter to our
+ * peer.
+ * This function is *not* called automatically when the user calls
+ * pcap_setfilter().
+ * There will be two cases:
+ * - the capture has been started: in this case, pcap_setfilter_rpcap()
+ * calls pcap_updatefilter_remote()
+ * - the capture has not started yet: in this case, pcap_setfilter_rpcap()
+ * stores the filter into the pcap_t structure, and then the filter is
+ * sent with pcap_startcap().
+ *
+ * WARNING This function *does not* clear the packet currently into the
+ * buffers. Therefore, the user has to expect to receive some packets
+ * that are related to the previous filter. If you want to discard all
+ * the packets before applying a new filter, you have to close the
+ * current capture session and start a new one.
+ *
+ * XXX - we really should have pcap_setfilter() always discard packets
+ * received with the old filter, and have a separate pcap_setfilter_noflush()
+ * function that doesn't discard any packets.
+ */
+static int pcap_updatefilter_remote(pcap_t *fp, struct bpf_program *prog)
+{
+ struct pcap_rpcap *pr = fp->priv; /* structure used when doing a remote live capture */
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ struct rpcap_header header; /* To keep the reply message */
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf,
+ pr->protocol_version, RPCAP_MSG_UPDATEFILTER_REQ, 0,
+ sizeof(struct rpcap_filter) + prog->bf_len * sizeof(struct rpcap_filterbpf_insn));
+
+ if (pcap_pack_bpffilter(fp, &sendbuf[sendbufidx], &sendbufidx, prog))
+ return -1;
+
+ if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+ PCAP_ERRBUF_SIZE) < 0)
+ return -1;
+
+ /* Receive and process the reply message header. */
+ if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+ RPCAP_MSG_UPDATEFILTER_REQ, &header, fp->errbuf) == -1)
+ return -1;
+
+ /*
+ * It shouldn't have any contents; discard it if it does.
+ */
+ if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+ return -1;
+
+ return 0;
+}
+
+static void
+pcap_save_current_filter_rpcap(pcap_t *fp, const char *filter)
+{
+ struct pcap_rpcap *pr = fp->priv; /* structure used when doing a remote live capture */
+
+ /*
+ * Check if:
+ * - We are on an remote capture
+ * - we do not want to capture RPCAP traffic
+ *
+ * If so, we have to save the current filter, because we have to
+ * add some piece of stuff later
+ */
+ if (pr->rmt_clientside &&
+ (pr->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP))
+ {
+ if (pr->currentfilter)
+ free(pr->currentfilter);
+
+ if (filter == NULL)
+ filter = "";
+
+ pr->currentfilter = strdup(filter);
+ }
+}
+
+/*
+ * This function sends a filter to a remote host.
+ *
+ * This function is called when the user wants to set a filter.
+ * It sends the filter to our peer.
+ * This function is called automatically when the user calls pcap_setfilter().
+ *
+ * Parameters and return values are exactly the same of pcap_setfilter().
+ */
+static int pcap_setfilter_rpcap(pcap_t *fp, struct bpf_program *prog)
+{
+ struct pcap_rpcap *pr = fp->priv; /* structure used when doing a remote live capture */
+
+ if (!pr->rmt_capstarted)
+ {
+ /* copy filter into the pcap_t structure */
+ if (install_bpf_program(fp, prog) == -1)
+ return -1;
+ return 0;
+ }
+
+ /* we have to update a filter during run-time */
+ if (pcap_updatefilter_remote(fp, prog))
+ return -1;
+
+ return 0;
+}
+
+/*
+ * This function updates the current filter in order not to capture rpcap
+ * packets.
+ *
+ * This function is called *only* when the user wants exclude RPCAP packets
+ * related to the current session from the captured packets.
+ *
+ * \return '0' if everything is fine, '-1' otherwise. The error message (if one)
+ * is returned into the 'errbuf' field of the pcap_t structure.
+ */
+static int pcap_createfilter_norpcappkt(pcap_t *fp, struct bpf_program *prog)
+{
+ struct pcap_rpcap *pr = fp->priv; /* structure used when doing a remote live capture */
+ int RetVal = 0;
+
+ /* We do not want to capture our RPCAP traffic. So, let's update the filter */
+ if (pr->rmt_flags & PCAP_OPENFLAG_NOCAPTURE_RPCAP)
+ {
+ struct sockaddr_storage saddr; /* temp, needed to retrieve the network data port chosen on the local machine */
+ socklen_t saddrlen; /* temp, needed to retrieve the network data port chosen on the local machine */
+ char myaddress[128];
+ char myctrlport[128];
+ char mydataport[128];
+ char peeraddress[128];
+ char peerctrlport[128];
+ char *newfilter;
+
+ /* Get the name/port of our peer */
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getpeername(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getpeername()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peeraddress,
+ sizeof(peeraddress), peerctrlport, sizeof(peerctrlport), NI_NUMERICHOST | NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* We cannot check the data port, because this is available only in case of TCP sockets */
+ /* Get the name/port of the current host */
+ if (getsockname(pr->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* Get the local port the system picked up */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, myaddress,
+ sizeof(myaddress), myctrlport, sizeof(myctrlport), NI_NUMERICHOST | NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* Let's now check the data port */
+ if (getsockname(pr->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ /* Get the local port the system picked up */
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL, 0, mydataport, sizeof(mydataport), NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo()", fp->errbuf, PCAP_ERRBUF_SIZE);
+ return -1;
+ }
+
+ if (pr->currentfilter && pr->currentfilter[0] != '\0')
+ {
+ /*
+ * We have a current filter; add items to it to
+ * filter out this rpcap session.
+ */
+ if (pcap_asprintf(&newfilter,
+ "(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+ pr->currentfilter, myaddress, peeraddress,
+ myctrlport, peerctrlport, myaddress, peeraddress,
+ mydataport) == -1)
+ {
+ /* Failed. */
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't allocate memory for new filter");
+ return -1;
+ }
+ }
+ else
+ {
+ /*
+ * We have no current filter; construct a filter to
+ * filter out this rpcap session.
+ */
+ if (pcap_asprintf(&newfilter,
+ "not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
+ myaddress, peeraddress, myctrlport, peerctrlport,
+ myaddress, peeraddress, mydataport) == -1)
+ {
+ /* Failed. */
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't allocate memory for new filter");
+ return -1;
+ }
+ }
+
+ /*
+ * This is only an hack to prevent the save_current_filter
+ * routine, which will be called when we call pcap_compile(),
+ * from saving the modified filter.
+ */
+ pr->rmt_clientside = 0;
+
+ if (pcap_compile(fp, prog, newfilter, 1, 0) == -1)
+ RetVal = -1;
+
+ /* Undo the hack. */
+ pr->rmt_clientside = 1;
+
+ free(newfilter);
+ }
+
+ return RetVal;
+}
+
+/*
+ * This function sets sampling parameters in the remote host.
+ *
+ * It is called when the user wants to set activate sampling on the
+ * remote host.
+ *
+ * Sampling parameters are defined into the 'pcap_t' structure.
+ *
+ * \param p: the pcap_t descriptor of the device currently opened.
+ *
+ * \return '0' if everything is OK, '-1' is something goes wrong. The
+ * error message is returned in the 'errbuf' member of the pcap_t structure.
+ */
+static int pcap_setsampling_remote(pcap_t *fp)
+{
+ struct pcap_rpcap *pr = fp->priv; /* structure used when doing a remote live capture */
+ char sendbuf[RPCAP_NETBUF_SIZE];/* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ struct rpcap_header header; /* To keep the reply message */
+ struct rpcap_sampling *sampling_pars; /* Structure that is needed to send sampling parameters to the remote host */
+
+ /* If no samping is requested, return 'ok' */
+ if (fp->rmt_samp.method == PCAP_SAMP_NOSAMP)
+ return 0;
+
+ /*
+ * Check for sampling parameters that don't fit in a message.
+ * We'll let the server complain about invalid parameters
+ * that do fit into the message.
+ */
+ if (fp->rmt_samp.method < 0 || fp->rmt_samp.method > 255) {
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+ "Invalid sampling method %d", fp->rmt_samp.method);
+ return -1;
+ }
+ if (fp->rmt_samp.value < 0 || fp->rmt_samp.value > 65535) {
+ pcap_snprintf(fp->errbuf, PCAP_ERRBUF_SIZE,
+ "Invalid sampling value %d", fp->rmt_samp.value);
+ return -1;
+ }
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf,
+ pr->protocol_version, RPCAP_MSG_SETSAMPLING_REQ, 0,
+ sizeof(struct rpcap_sampling));
+
+ /* Fill the structure needed to open an adapter remotely */
+ sampling_pars = (struct rpcap_sampling *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ memset(sampling_pars, 0, sizeof(struct rpcap_sampling));
+
+ sampling_pars->method = (uint8)fp->rmt_samp.method;
+ sampling_pars->value = (uint16)htonl(fp->rmt_samp.value);
+
+ if (sock_send(pr->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf,
+ PCAP_ERRBUF_SIZE) < 0)
+ return -1;
+
+ /* Receive and process the reply message header. */
+ if (rpcap_process_msg_header(pr->rmt_sockctrl, pr->protocol_version,
+ RPCAP_MSG_SETSAMPLING_REQ, &header, fp->errbuf) == -1)
+ return -1;
+
+ /*
+ * It shouldn't have any contents; discard it if it does.
+ */
+ if (rpcap_discard(pr->rmt_sockctrl, header.plen, fp->errbuf) == -1)
+ return -1;
+
+ return 0;
+}
+
+/*********************************************************
+ * *
+ * Miscellaneous functions *
+ * *
+ *********************************************************/
+
+/*
+ * This function performs authentication and protocol version
+ * negotiation. It is required in order to open the connection
+ * with the other end party.
+ *
+ * It sends authentication parameters on the control socket and
+ * reads the reply. If the reply is a success indication, it
+ * checks whether the reply includes minimum and maximum supported
+ * versions from the server; if not, it assumes both are 0, as
+ * that means it's an older server that doesn't return supported
+ * version numbers in authentication replies, so it only supports
+ * version 0. It then tries to determine the maximum version
+ * supported both by us and by the server. If it can find such a
+ * version, it sets us up to use that version; otherwise, it fails,
+ * indicating that there is no version supported by us and by the
+ * server.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param ver: pointer to variable to which to set the protocol version
+ * number we selected.
+ *
+ * \param auth: authentication parameters that have to be sent.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size
+ * PCAP_ERRBUF_SIZE) that will contain the error message (in case there
+ * is one). It could be a network problem or the fact that the authorization
+ * failed.
+ *
+ * \return '0' if everything is fine, '-1' for an error. For errors,
+ * an error message string is returned in the 'errbuf' variable.
+ */
+static int rpcap_doauth(SOCKET sockctrl, uint8 *ver, struct pcap_rmtauth *auth, char *errbuf)
+{
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data that has to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ uint16 length; /* length of the payload of this message */
+ struct rpcap_auth *rpauth;
+ uint16 auth_type;
+ struct rpcap_header header;
+ size_t str_length;
+ uint32 plen;
+ struct rpcap_authreply authreply; /* authentication reply message */
+ uint8 ourvers;
+
+ if (auth)
+ {
+ switch (auth->type)
+ {
+ case RPCAP_RMTAUTH_NULL:
+ length = sizeof(struct rpcap_auth);
+ break;
+
+ case RPCAP_RMTAUTH_PWD:
+ length = sizeof(struct rpcap_auth);
+ if (auth->username)
+ {
+ str_length = strlen(auth->username);
+ if (str_length > 65535)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "User name is too long (> 65535 bytes)");
+ return -1;
+ }
+ length += (uint16)str_length;
+ }
+ if (auth->password)
+ {
+ str_length = strlen(auth->password);
+ if (str_length > 65535)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Password is too long (> 65535 bytes)");
+ return -1;
+ }
+ length += (uint16)str_length;
+ }
+ break;
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
+ return -1;
+ }
+
+ auth_type = (uint16)auth->type;
+ }
+ else
+ {
+ auth_type = RPCAP_RMTAUTH_NULL;
+ length = sizeof(struct rpcap_auth);
+ }
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
+ RPCAP_MSG_AUTH_REQ, 0, length);
+
+ rpauth = (struct rpcap_auth *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ memset(rpauth, 0, sizeof(struct rpcap_auth));
+
+ rpauth->type = htons(auth_type);
+
+ if (auth_type == RPCAP_RMTAUTH_PWD)
+ {
+ if (auth->username)
+ rpauth->slen1 = (uint16)strlen(auth->username);
+ else
+ rpauth->slen1 = 0;
+
+ if (sock_bufferize(auth->username, rpauth->slen1, sendbuf,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ if (auth->password)
+ rpauth->slen2 = (uint16)strlen(auth->password);
+ else
+ rpauth->slen2 = 0;
+
+ if (sock_bufferize(auth->password, rpauth->slen2, sendbuf,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ rpauth->slen1 = htons(rpauth->slen1);
+ rpauth->slen2 = htons(rpauth->slen2);
+ }
+
+ if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf,
+ PCAP_ERRBUF_SIZE) < 0)
+ return -1;
+
+ /* Receive and process the reply message header */
+ if (rpcap_process_msg_header(sockctrl, 0, RPCAP_MSG_AUTH_REQ,
+ &header, errbuf) == -1)
+ return -1;
+
+ /*
+ * OK, it's an authentication reply, so we're logged in.
+ *
+ * Did it send any additional information?
+ */
+ plen = header.plen;
+ if (plen != 0)
+ {
+ /* Yes - is it big enough to be version information? */
+ if (plen < sizeof(struct rpcap_authreply))
+ {
+ /* No - discard it and fail. */
+ (void)rpcap_discard(sockctrl, plen, NULL);
+ return -1;
+ }
+
+ /* Read the reply body */
+ if (rpcap_recv(sockctrl, (char *)&authreply,
+ sizeof(struct rpcap_authreply), &plen, errbuf) == -1)
+ {
+ (void)rpcap_discard(sockctrl, plen, NULL);
+ return -1;
+ }
+
+ /* Discard the rest of the message, if there is any. */
+ if (rpcap_discard(sockctrl, plen, errbuf) == -1)
+ return -1;
+
+ /*
+ * Check the minimum and maximum versions for sanity;
+ * the minimum must be <= the maximum.
+ */
+ if (authreply.minvers > authreply.maxvers)
+ {
+ /*
+ * Bogus - give up on this server.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "The server's minimum supported protocol version is greater than its maximum supported protocol version");
+ return -1;
+ }
+ }
+ else
+ {
+ /* No - it supports only version 0. */
+ authreply.minvers = 0;
+ authreply.maxvers = 0;
+ }
+
+ /*
+ * OK, let's start with the maximum version the server supports.
+ */
+ ourvers = authreply.maxvers;
+
+#if RPCAP_MIN_VERSION != 0
+ /*
+ * If that's less than the minimum version we support, we
+ * can't communicate.
+ */
+ if (ourvers < RPCAP_MIN_VERSION)
+ goto novers;
+#endif
+
+ /*
+ * If that's greater than the maximum version we support,
+ * choose the maximum version we support.
+ */
+ if (ourvers > RPCAP_MAX_VERSION)
+ {
+ ourvers = RPCAP_MAX_VERSION;
+
+ /*
+ * If that's less than the minimum version they
+ * support, we can't communicate.
+ */
+ if (ourvers < authreply.minvers)
+ goto novers;
+ }
+
+ *ver = ourvers;
+ return 0;
+
+novers:
+ /*
+ * There is no version we both support; that is a fatal error.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "The server doesn't support any protocol version that we support");
+ return -1;
+}
+
+/* We don't currently support non-blocking mode. */
+static int
+pcap_getnonblock_rpcap(pcap_t *p)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Non-blocking mode isn't supported for capturing remotely with rpcap");
+ return (-1);
+}
+
+static int
+pcap_setnonblock_rpcap(pcap_t *p, int nonblock _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Non-blocking mode isn't supported for capturing remotely with rpcap");
+ return (-1);
+}
+
+static int
+rpcap_setup_session(const char *source, struct pcap_rmtauth *auth,
+ int *activep, SOCKET *sockctrlp, uint8 *protocol_versionp,
+ char *host, char *port, char *iface, char *errbuf)
+{
+ int type;
+ struct activehosts *activeconn; /* active connection, if there is one */
+ int error; /* 1 if rpcap_remoteact_getsock got an error */
+
+ /*
+ * Determine the type of the source (NULL, file, local, remote).
+ * You must have a valid source string even if we're in active mode,
+ * because otherwise the call to the following function will fail.
+ */
+ if (pcap_parsesrcstr(source, &type, host, port, iface, errbuf) == -1)
+ return -1;
+
+ /*
+ * It must be remote.
+ */
+ if (type != PCAP_SRC_IFREMOTE)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Non-remote interface passed to remote capture routine");
+ return -1;
+ }
+
+ /* Warning: this call can be the first one called by the user. */
+ /* For this reason, we have to initialize the WinSock support. */
+ if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+
+ /* Check for active mode */
+ activeconn = rpcap_remoteact_getsock(host, &error, errbuf);
+ if (activeconn != NULL)
+ {
+ *activep = 1;
+ *sockctrlp = activeconn->sockctrl;
+ *protocol_versionp = activeconn->protocol_version;
+ }
+ else
+ {
+ *activep = 0;
+ struct addrinfo hints; /* temp variable needed to resolve hostnames into to socket representation */
+ struct addrinfo *addrinfo; /* temp variable needed to resolve hostnames into to socket representation */
+
+ if (error)
+ {
+ /*
+ * Call failed.
+ */
+ return -1;
+ }
+
+ /*
+ * We're not in active mode; let's try to open a new
+ * control connection.
+ */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ if (port[0] == 0)
+ {
+ /* the user chose not to specify the port */
+ if (sock_initaddress(host, RPCAP_DEFAULT_NETPORT,
+ &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+ else
+ {
+ if (sock_initaddress(host, port, &hints, &addrinfo,
+ errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return -1;
+ }
+
+ if ((*sockctrlp = sock_open(addrinfo, SOCKOPEN_CLIENT, 0,
+ errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ {
+ freeaddrinfo(addrinfo);
+ return -1;
+ }
+
+ /* addrinfo is no longer used */
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ if (rpcap_doauth(*sockctrlp, protocol_versionp, auth,
+ errbuf) == -1)
+ {
+ sock_close(*sockctrlp, NULL, 0);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * This function opens a remote adapter by opening an RPCAP connection and
+ * so on.
+ *
+ * It does the job of pcap_open_live() for a remote interface; it's called
+ * by pcap_open() for remote interfaces.
+ *
+ * We do not start the capture until pcap_startcapture_remote() is called.
+ *
+ * This is because, when doing a remote capture, we cannot start capturing
+ * data as soon as the 'open adapter' command is sent. Suppose the remote
+ * adapter is already overloaded; if we start a capture (which, by default,
+ * has a NULL filter) the new traffic can saturate the network.
+ *
+ * Instead, we want to "open" the adapter, then send a "start capture"
+ * command only when we're ready to start the capture.
+ * This function does this job: it sends an "open adapter" command
+ * (according to the RPCAP protocol), but it does not start the capture.
+ *
+ * Since the other libpcap functions do not share this way of life, we
+ * have to do some dirty things in order to make everything work.
+ *
+ * \param source: see pcap_open().
+ * \param snaplen: see pcap_open().
+ * \param flags: see pcap_open().
+ * \param read_timeout: see pcap_open().
+ * \param auth: see pcap_open().
+ * \param errbuf: see pcap_open().
+ *
+ * \return a pcap_t pointer in case of success, NULL otherwise. In case of
+ * success, the pcap_t pointer can be used as a parameter to the following
+ * calls (pcap_compile() and so on). In case of problems, errbuf contains
+ * a text explanation of error.
+ *
+ * WARNING: In case we call pcap_compile() and the capture has not yet
+ * been started, the filter will be saved into the pcap_t structure,
+ * and it will be sent to the other host later (when
+ * pcap_startcapture_remote() is called).
+ */
+pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf)
+{
+ pcap_t *fp;
+ char *source_str;
+ struct pcap_rpcap *pr; /* structure used when doing a remote live capture */
+ char host[PCAP_BUF_SIZE], ctrlport[PCAP_BUF_SIZE], iface[PCAP_BUF_SIZE];
+ SOCKET sockctrl;
+ uint8 protocol_version; /* negotiated protocol version */
+ int active;
+ uint32 plen;
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+
+ /* RPCAP-related variables */
+ struct rpcap_header header; /* header of the RPCAP packet */
+ struct rpcap_openreply openreply; /* open reply message */
+
+ fp = pcap_create_common(errbuf, sizeof (struct pcap_rpcap));
+ if (fp == NULL)
+ {
+ return NULL;
+ }
+ source_str = strdup(source);
+ if (source_str == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return NULL;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ *
+ * XXX - should we leave this up to the remote server to
+ * do?
+ */
+ if (snaplen <= 0 || snaplen > MAXIMUM_SNAPLEN)
+ snaplen = MAXIMUM_SNAPLEN;
+
+ fp->opt.device = source_str;
+ fp->snapshot = snaplen;
+ fp->opt.timeout = read_timeout;
+ pr = fp->priv;
+ pr->rmt_flags = flags;
+
+ /*
+ * Attempt to set up the session with the server.
+ */
+ if (rpcap_setup_session(fp->opt.device, auth, &active, &sockctrl,
+ &protocol_version, host, ctrlport, iface, errbuf) == -1)
+ {
+ /* Session setup failed. */
+ pcap_close(fp);
+ return NULL;
+ }
+
+ /*
+ * Now it's time to start playing with the RPCAP protocol
+ * RPCAP open command: create the request message
+ */
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+ goto error_nodiscard;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, protocol_version,
+ RPCAP_MSG_OPEN_REQ, 0, (uint32) strlen(iface));
+
+ if (sock_bufferize(iface, (int) strlen(iface), sendbuf, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+ goto error_nodiscard;
+
+ if (sock_send(sockctrl, sendbuf, sendbufidx, errbuf,
+ PCAP_ERRBUF_SIZE) < 0)
+ goto error_nodiscard;
+
+ /* Receive and process the reply message header. */
+ if (rpcap_process_msg_header(sockctrl, protocol_version,
+ RPCAP_MSG_OPEN_REQ, &header, errbuf) == -1)
+ goto error_nodiscard;
+ plen = header.plen;
+
+ /* Read the reply body */
+ if (rpcap_recv(sockctrl, (char *)&openreply,
+ sizeof(struct rpcap_openreply), &plen, errbuf) == -1)
+ goto error;
+
+ /* Discard the rest of the message, if there is any. */
+ if (rpcap_discard(sockctrl, plen, errbuf) == -1)
+ goto error_nodiscard;
+
+ /* Set proper fields into the pcap_t struct */
+ fp->linktype = ntohl(openreply.linktype);
+ fp->tzoff = ntohl(openreply.tzoff);
+ pr->rmt_sockctrl = sockctrl;
+ pr->protocol_version = protocol_version;
+ pr->rmt_clientside = 1;
+
+ /* This code is duplicated from the end of this function */
+ fp->read_op = pcap_read_rpcap;
+ fp->save_current_filter_op = pcap_save_current_filter_rpcap;
+ fp->setfilter_op = pcap_setfilter_rpcap;
+ fp->getnonblock_op = pcap_getnonblock_rpcap;
+ fp->setnonblock_op = pcap_setnonblock_rpcap;
+ fp->stats_op = pcap_stats_rpcap;
+#ifdef _WIN32
+ fp->stats_ex_op = pcap_stats_ex_rpcap;
+#endif
+ fp->cleanup_op = pcap_cleanup_rpcap;
+
+ fp->activated = 1;
+ return fp;
+
+error:
+ /*
+ * When the connection has been established, we have to close it. So, at the
+ * beginning of this function, if an error occur we return immediately with
+ * a return NULL; when the connection is established, we have to come here
+ * ('goto error;') in order to close everything properly.
+ */
+
+ /*
+ * Discard the rest of the message.
+ * We already reported an error; if this gets an error, just
+ * drive on.
+ */
+ (void)rpcap_discard(sockctrl, plen, NULL);
+
+error_nodiscard:
+ if (!active)
+ sock_close(sockctrl, NULL, 0);
+
+ pcap_close(fp);
+ return NULL;
+}
+
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ADAPTER "Network adapter"
+#define PCAP_TEXT_SOURCE_ADAPTER_LEN (sizeof PCAP_TEXT_SOURCE_ADAPTER - 1)
+/* String identifier to be used in the pcap_findalldevs_ex() */
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST "on remote node"
+#define PCAP_TEXT_SOURCE_ON_REMOTE_HOST_LEN (sizeof PCAP_TEXT_SOURCE_ON_REMOTE_HOST - 1)
+
+static void
+freeaddr(struct pcap_addr *addr)
+{
+ free(addr->addr);
+ free(addr->netmask);
+ free(addr->broadaddr);
+ free(addr->dstaddr);
+ free(addr);
+}
+
+int
+pcap_findalldevs_ex_remote(const char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf)
+{
+ uint8 protocol_version; /* protocol version */
+ SOCKET sockctrl; /* socket descriptor of the control connection */
+ uint32 plen;
+ struct rpcap_header header; /* structure that keeps the general header of the rpcap protocol */
+ int i, j; /* temp variables */
+ int nif; /* Number of interfaces listed */
+ int active; /* 'true' if we the other end-party is in active mode */
+ char host[PCAP_BUF_SIZE], port[PCAP_BUF_SIZE];
+ char tmpstring[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+ pcap_if_t *lastdev; /* Last device in the pcap_if_t list */
+ pcap_if_t *dev; /* Device we're adding to the pcap_if_t list */
+
+ /* List starts out empty. */
+ (*alldevs) = NULL;
+ lastdev = NULL;
+
+ /*
+ * Attempt to set up the session with the server.
+ */
+ if (rpcap_setup_session(source, auth, &active, &sockctrl,
+ &protocol_version, host, port, NULL, errbuf) == -1)
+ {
+ /* Session setup failed. */
+ return -1;
+ }
+
+ /* RPCAP findalldevs command */
+ rpcap_createhdr(&header, protocol_version, RPCAP_MSG_FINDALLIF_REQ,
+ 0, 0);
+
+ if (sock_send(sockctrl, (char *)&header, sizeof(struct rpcap_header),
+ errbuf, PCAP_ERRBUF_SIZE) < 0)
+ goto error_nodiscard;
+
+ /* Receive and process the reply message header. */
+ if (rpcap_process_msg_header(sockctrl, protocol_version,
+ RPCAP_MSG_FINDALLIF_REQ, &header, errbuf) == -1)
+ goto error_nodiscard;
+
+ plen = header.plen;
+
+ /* read the number of interfaces */
+ nif = ntohs(header.value);
+
+ /* loop until all interfaces have been received */
+ for (i = 0; i < nif; i++)
+ {
+ struct rpcap_findalldevs_if findalldevs_if;
+ char tmpstring2[PCAP_BUF_SIZE + 1]; /* Needed to convert names and descriptions from 'old' syntax to the 'new' one */
+ struct pcap_addr *addr, *prevaddr;
+
+ tmpstring2[PCAP_BUF_SIZE] = 0;
+
+ /* receive the findalldevs structure from remote host */
+ if (rpcap_recv(sockctrl, (char *)&findalldevs_if,
+ sizeof(struct rpcap_findalldevs_if), &plen, errbuf) == -1)
+ goto error;
+
+ findalldevs_if.namelen = ntohs(findalldevs_if.namelen);
+ findalldevs_if.desclen = ntohs(findalldevs_if.desclen);
+ findalldevs_if.naddr = ntohs(findalldevs_if.naddr);
+
+ /* allocate the main structure */
+ dev = (pcap_if_t *)malloc(sizeof(pcap_if_t));
+ if (dev == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc() failed");
+ goto error;
+ }
+
+ /* Initialize the structure to 'zero' */
+ memset(dev, 0, sizeof(pcap_if_t));
+
+ /* Append it to the list. */
+ if (lastdev == NULL)
+ {
+ /*
+ * List is empty, so it's also the first device.
+ */
+ *alldevs = dev;
+ }
+ else
+ {
+ /*
+ * Append after the last device.
+ */
+ lastdev->next = dev;
+ }
+ /* It's now the last device. */
+ lastdev = dev;
+
+ /* allocate mem for name and description */
+ if (findalldevs_if.namelen)
+ {
+
+ if (findalldevs_if.namelen >= sizeof(tmpstring))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
+ goto error;
+ }
+
+ /* Retrieve adapter name */
+ if (rpcap_recv(sockctrl, tmpstring,
+ findalldevs_if.namelen, &plen, errbuf) == -1)
+ goto error;
+
+ tmpstring[findalldevs_if.namelen] = 0;
+
+ /* Create the new device identifier */
+ if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE,
+ host, port, tmpstring, errbuf) == -1)
+ goto error;
+
+ dev->name = strdup(tmpstring2);
+ if (dev->name == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+ goto error;
+ }
+ }
+
+ if (findalldevs_if.desclen)
+ {
+ if (findalldevs_if.desclen >= sizeof(tmpstring))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
+ goto error;
+ }
+
+ /* Retrieve adapter description */
+ if (rpcap_recv(sockctrl, tmpstring,
+ findalldevs_if.desclen, &plen, errbuf) == -1)
+ goto error;
+
+ tmpstring[findalldevs_if.desclen] = 0;
+
+ if (pcap_asprintf(&dev->description,
+ "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
+ tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host) == -1)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+ goto error;
+ }
+ }
+
+ dev->flags = ntohl(findalldevs_if.flags);
+
+ prevaddr = NULL;
+ /* loop until all addresses have been received */
+ for (j = 0; j < findalldevs_if.naddr; j++)
+ {
+ struct rpcap_findalldevs_ifaddr ifaddr;
+
+ /* Retrieve the interface addresses */
+ if (rpcap_recv(sockctrl, (char *)&ifaddr,
+ sizeof(struct rpcap_findalldevs_ifaddr),
+ &plen, errbuf) == -1)
+ goto error;
+
+ /*
+ * Deserialize all the address components.
+ */
+ addr = (struct pcap_addr *) malloc(sizeof(struct pcap_addr));
+ if (addr == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+ goto error;
+ }
+ addr->next = NULL;
+ addr->addr = NULL;
+ addr->netmask = NULL;
+ addr->broadaddr = NULL;
+ addr->dstaddr = NULL;
+
+ if (rpcap_deseraddr(&ifaddr.addr,
+ (struct sockaddr_storage **) &addr->addr, errbuf) == -1)
+ {
+ freeaddr(addr);
+ goto error;
+ }
+ if (rpcap_deseraddr(&ifaddr.netmask,
+ (struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
+ {
+ freeaddr(addr);
+ goto error;
+ }
+ if (rpcap_deseraddr(&ifaddr.broadaddr,
+ (struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
+ {
+ freeaddr(addr);
+ goto error;
+ }
+ if (rpcap_deseraddr(&ifaddr.dstaddr,
+ (struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
+ {
+ freeaddr(addr);
+ goto error;
+ }
+
+ if ((addr->addr == NULL) && (addr->netmask == NULL) &&
+ (addr->broadaddr == NULL) && (addr->dstaddr == NULL))
+ {
+ /*
+ * None of the addresses are IPv4 or IPv6
+ * addresses, so throw this entry away.
+ */
+ free(addr);
+ }
+ else
+ {
+ /*
+ * Add this entry to the list.
+ */
+ if (prevaddr == NULL)
+ {
+ dev->addresses = addr;
+ }
+ else
+ {
+ prevaddr->next = addr;
+ }
+ prevaddr = addr;
+ }
+ }
+ }
+
+ /* Discard the rest of the message. */
+ if (rpcap_discard(sockctrl, plen, errbuf) == 1)
+ goto error_nodiscard;
+
+ /* Control connection has to be closed only in case the remote machine is in passive mode */
+ if (!active)
+ {
+ /* DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources */
+ if (sock_close(sockctrl, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+ }
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ return 0;
+
+error:
+ /*
+ * In case there has been an error, I don't want to overwrite it with a new one
+ * if the following call fails. I want to return always the original error.
+ *
+ * Take care: this connection can already be closed when we try to close it.
+ * This happens because a previous error in the rpcapd, which requested to
+ * closed the connection. In that case, we already recognized that into the
+ * rpspck_isheaderok() and we already acknowledged the closing.
+ * In that sense, this call is useless here (however it is needed in case
+ * the client generates the error).
+ *
+ * Checks if all the data has been read; if not, discard the data in excess
+ */
+ (void) rpcap_discard(sockctrl, plen, NULL);
+
+error_nodiscard:
+ /* Control connection has to be closed only in case the remote machine is in passive mode */
+ if (!active)
+ sock_close(sockctrl, NULL, 0);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ /* Free whatever interfaces we've allocated. */
+ pcap_freealldevs(*alldevs);
+
+ return -1;
+}
+
+/*
+ * Active mode routines.
+ *
+ * The old libpcap API is somewhat ugly, and makes active mode difficult
+ * to implement; we provide some APIs for it that work only with rpcap.
+ */
+
+SOCKET pcap_remoteact_accept(const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf)
+{
+ /* socket-related variables */
+ struct addrinfo hints; /* temporary struct to keep settings needed to open the new socket */
+ struct addrinfo *addrinfo; /* keeps the addrinfo chain; required to open a new socket */
+ struct sockaddr_storage from; /* generic sockaddr_storage variable */
+ socklen_t fromlen; /* keeps the length of the sockaddr_storage variable */
+ SOCKET sockctrl; /* keeps the main socket identifier */
+ uint8 protocol_version; /* negotiated protocol version */
+ struct activehosts *temp, *prev; /* temp var needed to scan he host list chain */
+
+ *connectinghost = 0; /* just in case */
+
+ /* Prepare to open a new server socket */
+ memset(&hints, 0, sizeof(struct addrinfo));
+ /* WARNING Currently it supports only ONE socket family among ipv4 and IPv6 */
+ hints.ai_family = AF_INET; /* PF_UNSPEC to have both IPv4 and IPv6 server */
+ hints.ai_flags = AI_PASSIVE; /* Ready to a bind() socket */
+ hints.ai_socktype = SOCK_STREAM;
+
+ /* Warning: this call can be the first one called by the user. */
+ /* For this reason, we have to initialize the WinSock support. */
+ if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+ return (SOCKET)-1;
+
+ /* Do the work */
+ if ((port == NULL) || (port[0] == 0))
+ {
+ if (sock_initaddress(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ return (SOCKET)-2;
+ }
+ }
+ else
+ {
+ if (sock_initaddress(address, port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ return (SOCKET)-2;
+ }
+ }
+
+
+ if ((sockmain = sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ {
+ freeaddrinfo(addrinfo);
+ return (SOCKET)-2;
+ }
+ freeaddrinfo(addrinfo);
+
+ /* Connection creation */
+ fromlen = sizeof(struct sockaddr_storage);
+
+ sockctrl = accept(sockmain, (struct sockaddr *) &from, &fromlen);
+
+ /* We're not using sock_close, since we do not want to send a shutdown */
+ /* (which is not allowed on a non-connected socket) */
+ closesocket(sockmain);
+ sockmain = 0;
+
+ if (sockctrl == INVALID_SOCKET)
+ {
+ sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
+ return (SOCKET)-2;
+ }
+
+ /* Get the numeric for of the name of the connecting host */
+ if (getnameinfo((struct sockaddr *) &from, fromlen, connectinghost, RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST))
+ {
+ sock_geterror("getnameinfo()", errbuf, PCAP_ERRBUF_SIZE);
+ rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return (SOCKET)-1;
+ }
+
+ /* checks if the connecting host is among the ones allowed */
+ if (sock_check_hostlist((char *)hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf, PCAP_ERRBUF_SIZE) < 0)
+ {
+ rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return (SOCKET)-1;
+ }
+
+ /*
+ * Send authentication to the remote machine.
+ */
+ if (rpcap_doauth(sockctrl, &protocol_version, auth, errbuf) == -1)
+ {
+ /* Unrecoverable error. */
+ rpcap_senderror(sockctrl, 0, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return (SOCKET)-3;
+ }
+
+ /* Checks that this host does not already have a cntrl connection in place */
+
+ /* Initialize pointers */
+ temp = activeHosts;
+ prev = NULL;
+
+ while (temp)
+ {
+ /* This host already has an active connection in place, so I don't have to update the host list */
+ if (sock_cmpaddr(&temp->host, &from) == 0)
+ return sockctrl;
+
+ prev = temp;
+ temp = temp->next;
+ }
+
+ /* The host does not exist in the list; so I have to update the list */
+ if (prev)
+ {
+ prev->next = (struct activehosts *) malloc(sizeof(struct activehosts));
+ temp = prev->next;
+ }
+ else
+ {
+ activeHosts = (struct activehosts *) malloc(sizeof(struct activehosts));
+ temp = activeHosts;
+ }
+
+ if (temp == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc() failed");
+ rpcap_senderror(sockctrl, protocol_version, PCAP_ERR_REMOTEACCEPT, errbuf, NULL);
+ sock_close(sockctrl, NULL, 0);
+ return (SOCKET)-1;
+ }
+
+ memcpy(&temp->host, &from, fromlen);
+ temp->sockctrl = sockctrl;
+ temp->protocol_version = protocol_version;
+ temp->next = NULL;
+
+ return sockctrl;
+}
+
+int pcap_remoteact_close(const char *host, char *errbuf)
+{
+ struct activehosts *temp, *prev; /* temp var needed to scan the host list chain */
+ struct addrinfo hints, *addrinfo, *ai_next; /* temp var needed to translate between hostname to its address */
+ int retval;
+
+ temp = activeHosts;
+ prev = NULL;
+
+ /* retrieve the network address corresponding to 'host' */
+ addrinfo = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ retval = getaddrinfo(host, "0", &hints, &addrinfo);
+ if (retval != 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
+ return -1;
+ }
+
+ while (temp)
+ {
+ ai_next = addrinfo;
+ while (ai_next)
+ {
+ if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+ {
+ struct rpcap_header header;
+ int status = 0;
+
+ /* Close this connection */
+ rpcap_createhdr(&header, temp->protocol_version,
+ RPCAP_MSG_CLOSE, 0, 0);
+
+ /*
+ * Don't check for errors, since we're
+ * just cleaning up.
+ */
+ if (sock_send(temp->sockctrl,
+ (char *)&header,
+ sizeof(struct rpcap_header), errbuf,
+ PCAP_ERRBUF_SIZE) < 0)
+ {
+ /*
+ * Let that error be the one we
+ * report.
+ */
+ (void)sock_close(temp->sockctrl, NULL,
+ 0);
+ status = -1;
+ }
+ else
+ {
+ if (sock_close(temp->sockctrl, errbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ status = -1;
+ }
+
+ /*
+ * Remove the host from the list of active
+ * hosts.
+ */
+ if (prev)
+ prev->next = temp->next;
+ else
+ activeHosts = temp->next;
+
+ freeaddrinfo(addrinfo);
+
+ free(temp);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ return status;
+ }
+
+ ai_next = ai_next->ai_next;
+ }
+ prev = temp;
+ temp = temp->next;
+ }
+
+ if (addrinfo)
+ freeaddrinfo(addrinfo);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
+ return -1;
+}
+
+void pcap_remoteact_cleanup(void)
+{
+ /* Very dirty, but it works */
+ if (sockmain)
+ {
+ closesocket(sockmain);
+
+ /* To avoid inconsistencies in the number of sock_init() */
+ sock_cleanup();
+ }
+
+}
+
+int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
+{
+ struct activehosts *temp; /* temp var needed to scan the host list chain */
+ size_t len;
+ char hoststr[RPCAP_HOSTLIST_SIZE + 1];
+
+ temp = activeHosts;
+
+ len = 0;
+ *hostlist = 0;
+
+ while (temp)
+ {
+ /*int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen) */
+
+ /* Get the numeric form of the name of the connecting host */
+ if (sock_getascii_addrport((struct sockaddr_storage *) &temp->host, hoststr,
+ RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST, errbuf, PCAP_ERRBUF_SIZE) != -1)
+ /* if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr, */
+ /* RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) ) */
+ {
+ /* sock_geterror("getnameinfo()", errbuf, PCAP_ERRBUF_SIZE); */
+ return -1;
+ }
+
+ len = len + strlen(hoststr) + 1 /* the separator */;
+
+ if ((size < 0) || (len >= (size_t)size))
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
+ "the hostnames for all the active connections");
+ return -1;
+ }
+
+ pcap_strlcat(hostlist, hoststr, PCAP_ERRBUF_SIZE);
+ hostlist[len - 1] = sep;
+ hostlist[len] = 0;
+
+ temp = temp->next;
+ }
+
+ return 0;
+}
+
+/*
+ * Receive the header of a message.
+ */
+static int rpcap_recv_msg_header(SOCKET sock, struct rpcap_header *header, char *errbuf)
+{
+ int nrecv;
+
+ nrecv = sock_recv(sock, (char *) header, sizeof(struct rpcap_header),
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+ PCAP_ERRBUF_SIZE);
+ if (nrecv == -1)
+ {
+ /* Network error. */
+ return -1;
+ }
+ header->plen = ntohl(header->plen);
+ return 0;
+}
+
+/*
+ * Make sure the protocol version of a received message is what we were
+ * expecting.
+ */
+static int rpcap_check_msg_ver(SOCKET sock, uint8 expected_ver, struct rpcap_header *header, char *errbuf)
+{
+ /*
+ * Did the server specify the version we negotiated?
+ */
+ if (header->ver != expected_ver)
+ {
+ /*
+ * Discard the rest of the message.
+ */
+ if (rpcap_discard(sock, header->plen, errbuf) == -1)
+ return -1;
+
+ /*
+ * Tell our caller that it's not the negotiated version.
+ */
+ if (errbuf != NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Server sent us a message with version %u when we were expecting %u",
+ header->ver, expected_ver);
+ }
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * Check the message type of a received message, which should either be
+ * the expected message type or RPCAP_MSG_ERROR.
+ */
+static int rpcap_check_msg_type(SOCKET sock, uint8 request_type, struct rpcap_header *header, uint16 *errcode, char *errbuf)
+{
+ const char *request_type_string;
+ const char *msg_type_string;
+
+ /*
+ * What type of message is it?
+ */
+ if (header->type == RPCAP_MSG_ERROR)
+ {
+ /*
+ * The server reported an error.
+ * Hand that error back to our caller.
+ */
+ *errcode = ntohs(header->value);
+ rpcap_msg_err(sock, header->plen, errbuf);
+ return -1;
+ }
+
+ *errcode = 0;
+
+ /*
+ * For a given request type value, the expected reply type value
+ * is the request type value with ORed with RPCAP_MSG_IS_REPLY.
+ */
+ if (header->type != (request_type | RPCAP_MSG_IS_REPLY))
+ {
+ /*
+ * This isn't a reply to the request we sent.
+ */
+
+ /*
+ * Discard the rest of the message.
+ */
+ if (rpcap_discard(sock, header->plen, errbuf) == -1)
+ return -1;
+
+ /*
+ * Tell our caller about it.
+ */
+ request_type_string = rpcap_msg_type_string(request_type);
+ msg_type_string = rpcap_msg_type_string(header->type);
+ if (errbuf != NULL)
+ {
+ if (request_type_string == NULL)
+ {
+ /* This should not happen. */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "rpcap_check_msg_type called for request message with type %u",
+ request_type);
+ return -1;
+ }
+ if (msg_type_string != NULL)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s message received in response to a %s message",
+ msg_type_string, request_type_string);
+ else
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Message of unknown type %u message received in response to a %s request",
+ header->type, request_type_string);
+ }
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Receive and process the header of a message.
+ */
+static int rpcap_process_msg_header(SOCKET sock, uint8 expected_ver, uint8 request_type, struct rpcap_header *header, char *errbuf)
+{
+ uint16 errcode;
+
+ if (rpcap_recv_msg_header(sock, header, errbuf) == -1)
+ {
+ /* Network error. */
+ return -1;
+ }
+
+ /*
+ * Did the server specify the version we negotiated?
+ */
+ if (rpcap_check_msg_ver(sock, expected_ver, header, errbuf) == -1)
+ return -1;
+
+ /*
+ * Check the message type.
+ */
+ return rpcap_check_msg_type(sock, request_type, header,
+ &errcode, errbuf);
+}
+
+/*
+ * Read data from a message.
+ * If we're trying to read more data that remains, puts an error
+ * message into errmsgbuf and returns -2. Otherwise, tries to read
+ * the data and, if that succeeds, subtracts the amount read from
+ * the number of bytes of data that remains.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int rpcap_recv(SOCKET sock, void *buffer, size_t toread, uint32 *plen, char *errbuf)
+{
+ int nread;
+
+ if (toread > *plen)
+ {
+ /* The server sent us a bad message */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
+ return -1;
+ }
+ nread = sock_recv(sock, buffer, toread,
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ {
+ return -1;
+ }
+ *plen -= nread;
+ return 0;
+}
+
+/*
+ * This handles the RPCAP_MSG_ERROR message.
+ */
+static void rpcap_msg_err(SOCKET sockctrl, uint32 plen, char *remote_errbuf)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ if (plen >= PCAP_ERRBUF_SIZE)
+ {
+ /*
+ * Message is too long; just read as much of it as we
+ * can into the buffer provided, and discard the rest.
+ */
+ if (sock_recv(sockctrl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ {
+ // Network error.
+ pcap_snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
+ return;
+ }
+
+ /*
+ * Null-terminate it.
+ */
+ remote_errbuf[PCAP_ERRBUF_SIZE - 1] = '\0';
+
+ /*
+ * Throw away the rest.
+ */
+ (void)rpcap_discard(sockctrl, plen - (PCAP_ERRBUF_SIZE - 1), remote_errbuf);
+ }
+ else if (plen == 0)
+ {
+ /* Empty error string. */
+ remote_errbuf[0] = '\0';
+ }
+ else
+ {
+ if (sock_recv(sockctrl, remote_errbuf, plen,
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ {
+ // Network error.
+ pcap_snprintf(remote_errbuf, PCAP_ERRBUF_SIZE, "Read of error message from client failed: %s", errbuf);
+ return;
+ }
+
+ /*
+ * Null-terminate it.
+ */
+ remote_errbuf[plen] = '\0';
+ }
+}
+
+/*
+ * Discard data from a connection.
+ * Mostly used to discard wrong-sized messages.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int rpcap_discard(SOCKET sock, uint32 len, char *errbuf)
+{
+ if (len != 0)
+ {
+ if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ // Network error.
+ return -1;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Read bytes into the pcap_t's buffer until we have the specified
+ * number of bytes read or we get an error or interrupt indication.
+ */
+static int rpcap_read_packet_msg(SOCKET sock, pcap_t *p, size_t size)
+{
+ u_char *bp;
+ int cc;
+ int bytes_read;
+
+ bp = p->bp;
+ cc = p->cc;
+
+ /*
+ * Loop until we have the amount of data requested or we get
+ * an error or interrupt.
+ */
+ while ((size_t)cc < size)
+ {
+ /*
+ * We haven't read all of the packet header yet.
+ * Read what remains, which could be all of it.
+ */
+ bytes_read = sock_recv(sock, bp, size - cc,
+ SOCK_RECEIVEALL_NO|SOCK_EOF_IS_ERROR, p->errbuf,
+ PCAP_ERRBUF_SIZE);
+ if (bytes_read == -1)
+ {
+ /*
+ * Network error. Update the read pointer and
+ * byte count, and return an error indication.
+ */
+ p->bp = bp;
+ p->cc = cc;
+ return -1;
+ }
+ if (bytes_read == -3)
+ {
+ /*
+ * Interrupted receive. Update the read
+ * pointer and byte count, and return
+ * an interrupted indication.
+ */
+ p->bp = bp;
+ p->cc = cc;
+ return -3;
+ }
+ if (bytes_read == 0)
+ {
+ /*
+ * EOF - server terminated the connection.
+ * Update the read pointer and byte count, and
+ * return an error indication.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The server terminated the connection.");
+ return -1;
+ }
+ bp += bytes_read;
+ cc += bytes_read;
+ }
+ p->bp = bp;
+ p->cc = cc;
+ return 0;
+}
diff --git a/lib/libpcap/libpcap/pcap-rpcap.h b/lib/libpcap/libpcap/pcap-rpcap.h
new file mode 100644
index 0000000..6ad6d98
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-rpcap.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef pcap_rpcap_h
+#define pcap_rpcap_h
+
+/*
+ * Internal interfaces for "pcap_open()".
+ */
+pcap_t *pcap_open_rpcap(const char *source, int snaplen, int flags,
+ int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+
+/*
+ * Internal interfaces for "pcap_findalldevs_ex()".
+ */
+int pcap_findalldevs_ex_remote(const char *source,
+ struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap-savefile.manfile b/lib/libpcap/libpcap/pcap-savefile.manfile
new file mode 100644
index 0000000..c2de543
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-savefile.manfile
@@ -0,0 +1,133 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-SAVEFILE 5 "8 March 2015"
+.SH NAME
+pcap-savefile \- libpcap savefile format
+.SH DESCRIPTION
+NOTE: applications and libraries should, if possible, use libpcap to
+read savefiles, rather than having their own code to read savefiles.
+If, in the future, a new file format is supported by libpcap,
+applications and libraries using libpcap to read savefiles will be able
+to read the new format of savefiles, but applications and libraries
+using their own code to read savefiles will have to be changed to
+support the new file format.
+.PP
+``Savefiles'' read and written by libpcap and applications using libpcap
+start with a per-file header. The format of the per-file header is:
+.RS
+.TS
+box;
+c s
+c | c
+c s.
+Magic number
+_
+Major version Minor version
+_
+Time zone offset
+_
+Time stamp accuracy
+_
+Snapshot length
+_
+Link-layer header type
+.TE
+.RE
+.PP
+All fields in the per-file header are in the byte order of the host
+writing the file. Normally, the first field in the per-file header is a
+4-byte magic number, with the value 0xa1b2c3d4. The magic number, when
+read by a host with the same byte order as the host that wrote the file,
+will have the value 0xa1b2c3d4, and, when read by a host with the
+opposite byte order as the host that wrote the file, will have the value
+0xd4c3b2a1. That allows software reading the file to determine whether
+the byte order of the host that wrote the file is the same as the byte
+order of the host on which the file is being read, and thus whether the
+values in the per-file and per-packet headers need to be byte-swapped.
+.PP
+If the magic number has the value 0xa1b23c4d (with the two nibbles of
+the two lower-order bytes of the magic number swapped), which would be
+read as 0xa1b23c4d by a host with the same byte order as the host that
+wrote the file and as 0x4d3cb2a1 by a host with the opposite byte order
+as the host that wrote the file, the file format is the same as for
+regular files, except that the time stamps for packets are given in
+seconds and nanoseconds rather than seconds and microseconds.
+.PP
+Following this are:
+.IP
+A 2-byte file format major version number; the current version number is
+2.
+.IP
+A 2-byte file format minor version number; the current version number is
+4.
+.IP
+A 4-byte time zone offset; this is always 0.
+.IP
+A 4-byte number giving the accuracy of time stamps in the file; this is
+always 0.
+.IP
+A 4-byte number giving the "snapshot length" of the capture; packets
+longer than the snapshot length are truncated to the snapshot length, so
+that, if the snapshot length is
+.IR N ,
+only the first
+.I N
+bytes of a packet longer than
+.I N
+bytes will be saved in the capture.
+.IP
+a 4-byte number giving the link-layer header type for packets in the
+capture; see
+.BR pcap-linktype (7)
+for the
+.B LINKTYPE_
+values that can appear in this field.
+.PP
+Following the per-file header are zero or more packets; each packet
+begins with a per-packet header, which is immediately followed by the
+raw packet data. The format of the per-packet header is:
+.RS
+.TS
+box;
+c.
+Time stamp, seconds value
+_
+Time stamp, microseconds or nanoseconds value
+_
+Length of captured packet data
+_
+Un-truncated length of the packet data
+.TE
+.RE
+.PP
+All fields in the per-packet header are in the byte order of the host
+writing the file. The per-packet header begins with a time stamp giving
+the approximate time the packet was captured; the time stamp consists of
+a 4-byte value, giving the time in seconds since January 1, 1970,
+00:00:00 UTC, followed by a 4-byte value, giving the time in
+microseconds or nanoseconds since that second, depending on the magic
+number in the file header. Following that are a 4-byte value giving the
+number of bytes of captured data that follow the per-packet header and a
+4-byte value giving the number of bytes that would have been present had
+the packet not been truncated by the snapshot length. The two lengths
+will be equal if the number of bytes of packet data are less than or
+equal to the snapshot length.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap-savefile.manfile.in b/lib/libpcap/libpcap/pcap-savefile.manfile.in
new file mode 100644
index 0000000..748d7af
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-savefile.manfile.in
@@ -0,0 +1,133 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-SAVEFILE @MAN_FILE_FORMATS@ "8 March 2015"
+.SH NAME
+pcap-savefile \- libpcap savefile format
+.SH DESCRIPTION
+NOTE: applications and libraries should, if possible, use libpcap to
+read savefiles, rather than having their own code to read savefiles.
+If, in the future, a new file format is supported by libpcap,
+applications and libraries using libpcap to read savefiles will be able
+to read the new format of savefiles, but applications and libraries
+using their own code to read savefiles will have to be changed to
+support the new file format.
+.PP
+``Savefiles'' read and written by libpcap and applications using libpcap
+start with a per-file header. The format of the per-file header is:
+.RS
+.TS
+box;
+c s
+c | c
+c s.
+Magic number
+_
+Major version Minor version
+_
+Time zone offset
+_
+Time stamp accuracy
+_
+Snapshot length
+_
+Link-layer header type
+.TE
+.RE
+.PP
+All fields in the per-file header are in the byte order of the host
+writing the file. Normally, the first field in the per-file header is a
+4-byte magic number, with the value 0xa1b2c3d4. The magic number, when
+read by a host with the same byte order as the host that wrote the file,
+will have the value 0xa1b2c3d4, and, when read by a host with the
+opposite byte order as the host that wrote the file, will have the value
+0xd4c3b2a1. That allows software reading the file to determine whether
+the byte order of the host that wrote the file is the same as the byte
+order of the host on which the file is being read, and thus whether the
+values in the per-file and per-packet headers need to be byte-swapped.
+.PP
+If the magic number has the value 0xa1b23c4d (with the two nibbles of
+the two lower-order bytes of the magic number swapped), which would be
+read as 0xa1b23c4d by a host with the same byte order as the host that
+wrote the file and as 0x4d3cb2a1 by a host with the opposite byte order
+as the host that wrote the file, the file format is the same as for
+regular files, except that the time stamps for packets are given in
+seconds and nanoseconds rather than seconds and microseconds.
+.PP
+Following this are:
+.IP
+A 2-byte file format major version number; the current version number is
+2.
+.IP
+A 2-byte file format minor version number; the current version number is
+4.
+.IP
+A 4-byte time zone offset; this is always 0.
+.IP
+A 4-byte number giving the accuracy of time stamps in the file; this is
+always 0.
+.IP
+A 4-byte number giving the "snapshot length" of the capture; packets
+longer than the snapshot length are truncated to the snapshot length, so
+that, if the snapshot length is
+.IR N ,
+only the first
+.I N
+bytes of a packet longer than
+.I N
+bytes will be saved in the capture.
+.IP
+a 4-byte number giving the link-layer header type for packets in the
+capture; see
+.BR pcap-linktype (@MAN_MISC_INFO@)
+for the
+.B LINKTYPE_
+values that can appear in this field.
+.PP
+Following the per-file header are zero or more packets; each packet
+begins with a per-packet header, which is immediately followed by the
+raw packet data. The format of the per-packet header is:
+.RS
+.TS
+box;
+c.
+Time stamp, seconds value
+_
+Time stamp, microseconds or nanoseconds value
+_
+Length of captured packet data
+_
+Un-truncated length of the packet data
+.TE
+.RE
+.PP
+All fields in the per-packet header are in the byte order of the host
+writing the file. The per-packet header begins with a time stamp giving
+the approximate time the packet was captured; the time stamp consists of
+a 4-byte value, giving the time in seconds since January 1, 1970,
+00:00:00 UTC, followed by a 4-byte value, giving the time in
+microseconds or nanoseconds since that second, depending on the magic
+number in the file header. Following that are a 4-byte value giving the
+number of bytes of captured data that follow the per-packet header and a
+4-byte value giving the number of bytes that would have been present had
+the packet not been truncated by the snapshot length. The two lengths
+will be equal if the number of bytes of packet data are less than or
+equal to the snapshot length.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap-septel.c b/lib/libpcap/libpcap/pcap-septel.c
new file mode 100644
index 0000000..24cb47b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-septel.c
@@ -0,0 +1,354 @@
+/*
+ * pcap-septel.c: Packet capture interface for Intel/Septel card.
+ *
+ * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
+ * (+961 3 485243)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/param.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "pcap-int.h"
+
+#include <ctype.h>
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <msg.h>
+#include <ss7_inc.h>
+#include <sysgct.h>
+#include <pack.h>
+#include <system.h>
+
+#include "pcap-septel.h"
+
+static int septel_setfilter(pcap_t *p, struct bpf_program *fp);
+static int septel_stats(pcap_t *p, struct pcap_stat *ps);
+static int septel_getnonblock(pcap_t *p);
+static int septel_setnonblock(pcap_t *p, int nonblock);
+
+/*
+ * Private data for capturing on Septel devices.
+ */
+struct pcap_septel {
+ struct pcap_stat stat;
+}
+
+/*
+ * Read at most max_packets from the capture queue and call the callback
+ * for each of them. Returns the number of packets handled, -1 if an
+ * error occured, or -2 if we were told to break out of the loop.
+ */
+static int septel_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) {
+
+ struct pcap_septel *ps = p->priv;
+ HDR *h;
+ MSG *m;
+ int processed = 0 ;
+ int t = 0 ;
+
+ /* identifier for the message queue of the module(upe) from which we are capturing
+ * packets.These IDs are defined in system.txt . By default it is set to 0x2d
+ * so change it to 0xdd for technical reason and therefore the module id for upe becomes:
+ * LOCAL 0xdd * upe - Example user part task */
+ unsigned int id = 0xdd;
+
+ /* process the packets */
+ do {
+
+ unsigned short packet_len = 0;
+ int caplen = 0;
+ int counter = 0;
+ struct pcap_pkthdr pcap_header;
+ u_char *dp ;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+loop:
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that
+ * it has, and return -2 to indicate that
+ * we were told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return -2;
+ }
+
+ /*repeat until a packet is read
+ *a NULL message means :
+ * when no packet is in queue or all packets in queue already read */
+ do {
+ /* receive packet in non-blocking mode
+ * GCT_grab is defined in the septel library software */
+ h = GCT_grab(id);
+
+ m = (MSG*)h;
+ /* a couter is added here to avoid an infinite loop
+ * that will cause our capture program GUI to freeze while waiting
+ * for a packet*/
+ counter++ ;
+
+ }
+ while ((m == NULL)&& (counter< 100)) ;
+
+ if (m != NULL) {
+
+ t = h->type ;
+
+ /* catch only messages with type = 0xcf00 or 0x8f01 corrsponding to ss7 messages*/
+ /* XXX = why not use API_MSG_TX_REQ for 0xcf00 and API_MSG_RX_IND
+ * for 0x8f01? */
+ if ((t != 0xcf00) && (t != 0x8f01)) {
+ relm(h);
+ goto loop ;
+ }
+
+ /* XXX - is API_MSG_RX_IND for an MTP2 or MTP3 message? */
+ dp = get_param(m);/* get pointer to MSG parameter area (m->param) */
+ packet_len = m->len;
+ caplen = p->snapshot ;
+
+
+ if (caplen > packet_len) {
+
+ caplen = packet_len;
+ }
+ /* Run the packet filter if there is one. */
+ if ((p->fcode.bf_insns == NULL) || bpf_filter(p->fcode.bf_insns, dp, packet_len, caplen)) {
+
+
+ /* get a time stamp , consisting of :
+ *
+ * pcap_header.ts.tv_sec:
+ * ----------------------
+ * a UNIX format time-in-seconds when he packet was captured,
+ * i.e. the number of seconds since Epoch time (January 1,1970, 00:00:00 GMT)
+ *
+ * pcap_header.ts.tv_usec :
+ * ------------------------
+ * the number of microseconds since that second
+ * when the packet was captured
+ */
+
+ (void)gettimeofday(&pcap_header.ts, NULL);
+
+ /* Fill in our own header data */
+ pcap_header.caplen = caplen;
+ pcap_header.len = packet_len;
+
+ /* Count the packet. */
+ ps->stat.ps_recv++;
+
+ /* Call the user supplied callback function */
+ callback(user, &pcap_header, dp);
+
+ processed++ ;
+
+ }
+ /* after being processed the packet must be
+ *released in order to receive another one */
+ relm(h);
+ }else
+ processed++;
+
+ }
+ while (processed < cnt) ;
+
+ return processed ;
+}
+
+
+static int
+septel_inject(pcap_t *handle, const void *buf _U_, size_t size _U_)
+{
+ pcap_strlcpy(handle->errbuf, "Sending packets isn't supported on Septel cards",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+
+/*
+ * Activate a handle for a live capture from the given Septel device. Always pass a NULL device
+ * The promisc flag is ignored because Septel cards have built-in tracing.
+ * The timeout is also ignored as it is not supported in hardware.
+ *
+ * See also pcap(3).
+ */
+static pcap_t *septel_activate(pcap_t* handle) {
+ /* Initialize some components of the pcap structure. */
+ handle->linktype = DLT_MTP2;
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+ handle->snapshot = MAXIMUM_SNAPLEN;
+
+ handle->bufsize = 0;
+
+ /*
+ * "select()" and "poll()" don't work on Septel queues
+ */
+ handle->selectable_fd = -1;
+
+ handle->read_op = septel_read;
+ handle->inject_op = septel_inject;
+ handle->setfilter_op = septel_setfilter;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = septel_getnonblock;
+ handle->setnonblock_op = septel_setnonblock;
+ handle->stats_op = septel_stats;
+
+ return 0;
+}
+
+pcap_t *septel_create(const char *device, char *ebuf, int *is_ours) {
+ const char *cp;
+ pcap_t *p;
+
+ /* Does this look like the Septel device? */
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+ if (strcmp(cp, "septel") != 0) {
+ /* Nope, it's not "septel" */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_septel));
+ if (p == NULL)
+ return NULL;
+
+ p->activate_op = septel_activate;
+ /*
+ * Set these up front, so that, even if our client tries
+ * to set non-blocking mode before we're activated, or
+ * query the state of non-blocking mode, they get an error,
+ * rather than having the non-blocking mode option set
+ * for use later.
+ */
+ p->getnonblock_op = septel_getnonblock;
+ p->setnonblock_op = septel_setnonblock;
+ return p;
+}
+
+static int septel_stats(pcap_t *p, struct pcap_stat *ps) {
+ struct pcap_septel *handlep = p->priv;
+ /*handlep->stat.ps_recv = 0;*/
+ /*handlep->stat.ps_drop = 0;*/
+
+ *ps = handlep->stat;
+
+ return 0;
+}
+
+
+int
+septel_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ /*
+ * XXX - do the notions of "up", "running", or "connected" apply here?
+ */
+ if (add_dev(devlistp,"septel",0,"Intel/Septel device",errbuf) == NULL)
+ return -1;
+ return 0;
+}
+
+
+/*
+ * Installs the given bpf filter program in the given pcap structure. There is
+ * no attempt to store the filter in kernel memory as that is not supported
+ * with Septel cards.
+ */
+static int septel_setfilter(pcap_t *p, struct bpf_program *fp) {
+ if (!p)
+ return -1;
+ if (!fp) {
+ strncpy(p->errbuf, "setfilter: No filter specified",
+ sizeof(p->errbuf));
+ return -1;
+ }
+
+ /* Make our private copy of the filter */
+
+ if (install_bpf_program(p, fp) < 0)
+ return -1;
+
+ return (0);
+}
+
+/*
+ * We don't support non-blocking mode. I'm not sure what we'd
+ * do to support it and, given that we don't support select()/
+ * poll()/epoll_wait()/kevent() etc., it probably doesn't
+ * matter.
+ */
+static int
+septel_getnonblock(pcap_t *p)
+{
+ fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
+ return (-1);
+}
+
+static int
+septel_setnonblock(pcap_t *p, int nonblock _U_)
+{
+ fprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Non-blocking mode not supported on Septel devices");
+ return (-1);
+}
+
+#ifdef SEPTEL_ONLY
+/*
+ * This libpcap build supports only Septel cards, not regular network
+ * interfaces.
+ */
+
+/*
+ * There are no regular interfaces, just Septel interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "This version of libpcap only supports Septel cards");
+ return (NULL);
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING " (Septel-only)");
+}
+#endif
diff --git a/lib/libpcap/libpcap/pcap-septel.h b/lib/libpcap/libpcap/pcap-septel.h
new file mode 100644
index 0000000..0e648b2
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-septel.h
@@ -0,0 +1,13 @@
+/*
+ * pcap-septel.c: Packet capture interface for Intel Septel card
+ *
+ * The functionality of this code attempts to mimic that of pcap-linux as much
+ * as possible. This code is only needed when compiling in the Intel/Septel
+ * card code at the same time as another type of device.
+ *
+ * Authors: Gilbert HOYEK (gil_hoyek@hotmail.com), Elias M. KHOURY
+ * (+961 3 485343);
+ */
+
+pcap_t *septel_create(const char *device, char *ebuf, int *is_ours);
+int septel_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/lib/libpcap/libpcap/pcap-sita.c b/lib/libpcap/libpcap/pcap-sita.c
new file mode 100644
index 0000000..b9dda9c
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-sita.c
@@ -0,0 +1,1087 @@
+/*
+ * pcap-sita.c: Packet capture interface additions for SITA ACN devices
+ *
+ * Copyright (c) 2007 Fulko Hew, SITA INC Canada, Inc <fulko.hew@sita.aero>
+ *
+ * License: BSD
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "pcap-int.h"
+
+#include "pcap-sita.h"
+
+ /* non-configureable manifests follow */
+
+#define IOP_SNIFFER_PORT 49152 /* TCP port on the IOP used for 'distributed pcap' usage */
+#define MAX_LINE_SIZE 255 /* max size of a buffer/line in /etc/hosts we allow */
+#define MAX_CHASSIS 8 /* number of chassis in an ACN site */
+#define MAX_GEOSLOT 8 /* max number of access units in an ACN site */
+
+#define FIND 0
+#define LIVE 1
+
+typedef struct iface {
+ struct iface *next; /* a pointer to the next interface */
+ char *name; /* this interface's name */
+ char *IOPname; /* this interface's name on an IOP */
+ uint32_t iftype; /* the type of interface (DLT values) */
+} iface_t;
+
+typedef struct unit {
+ char *ip; /* this unit's IP address (as extracted from /etc/hosts) */
+ int fd; /* the connection to this unit (if it exists) */
+ int find_fd; /* a big kludge to avoid my programming limitations since I could have this unit open for findalldevs purposes */
+ int first_time; /* 0 = just opened via acn_open_live(), ie. the first time, NZ = nth time */
+ struct sockaddr_in *serv_addr; /* the address control block for comms to this unit */
+ int chassis;
+ int geoslot;
+ iface_t *iface; /* a pointer to a linked list of interface structures */
+ char *imsg; /* a pointer to an inbound message */
+ int len; /* the current size of the inbound message */
+} unit_t;
+
+static unit_t units[MAX_CHASSIS+1][MAX_GEOSLOT+1]; /* we use indexes of 1 through 8, but we reserve/waste index 0 */
+static fd_set readfds; /* a place to store the file descriptors for the connections to the IOPs */
+static int max_fs;
+
+pcap_if_t *acn_if_list; /* pcap's list of available interfaces */
+
+static void dump_interface_list(void) {
+ pcap_if_t *iff;
+ pcap_addr_t *addr;
+ int longest_name_len = 0;
+ char *n, *d, *f;
+ int if_number = 0;
+
+ iff = acn_if_list;
+ while (iff) {
+ if (iff->name && (strlen(iff->name) > longest_name_len)) longest_name_len = strlen(iff->name);
+ iff = iff->next;
+ }
+ iff = acn_if_list;
+ printf("Interface List:\n");
+ while (iff) {
+ n = (iff->name) ? iff->name : "";
+ d = (iff->description) ? iff->description : "";
+ f = (iff->flags == PCAP_IF_LOOPBACK) ? "L" : "";
+ printf("%3d: %*s %s '%s'\n", if_number++, longest_name_len, n, f, d);
+ addr = iff->addresses;
+ while (addr) {
+ printf("%*s ", (5 + longest_name_len), ""); /* add some indentation */
+ printf("%15s ", (addr->addr) ? inet_ntoa(((struct sockaddr_in *)addr->addr)->sin_addr) : "");
+ printf("%15s ", (addr->netmask) ? inet_ntoa(((struct sockaddr_in *)addr->netmask)->sin_addr) : "");
+ printf("%15s ", (addr->broadaddr) ? inet_ntoa(((struct sockaddr_in *)addr->broadaddr)->sin_addr) : "");
+ printf("%15s ", (addr->dstaddr) ? inet_ntoa(((struct sockaddr_in *)addr->dstaddr)->sin_addr) : "");
+ printf("\n");
+ addr = addr->next;
+ }
+ iff = iff->next;
+ }
+}
+
+static void dump(unsigned char *ptr, int i, int indent) {
+ fprintf(stderr, "%*s", indent, " ");
+ for (; i > 0; i--) {
+ fprintf(stderr, "%2.2x ", *ptr++);
+ }
+ fprintf(stderr, "\n");
+}
+
+static void dump_interface_list_p(void) {
+ pcap_if_t *iff;
+ pcap_addr_t *addr;
+ int if_number = 0;
+
+ iff = acn_if_list;
+ printf("Interface Pointer @ %p is %p:\n", &acn_if_list, iff);
+ while (iff) {
+ printf("%3d: %p %p next: %p\n", if_number++, iff->name, iff->description, iff->next);
+ dump((unsigned char *)iff, sizeof(pcap_if_t), 5);
+ addr = iff->addresses;
+ while (addr) {
+ printf(" %p %p %p %p, next: %p\n", addr->addr, addr->netmask, addr->broadaddr, addr->dstaddr, addr->next);
+ dump((unsigned char *)addr, sizeof(pcap_addr_t), 10);
+ addr = addr->next;
+ }
+ iff = iff->next;
+ }
+}
+
+static void dump_unit_table(void) {
+ int chassis, geoslot;
+ iface_t *p;
+
+ printf("%c:%c %s %s\n", 'C', 'S', "fd", "IP Address");
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ if (units[chassis][geoslot].ip != NULL)
+ printf("%d:%d %2d %s\n", chassis, geoslot, units[chassis][geoslot].fd, units[chassis][geoslot].ip);
+ p = units[chassis][geoslot].iface;
+ while (p) {
+ char *n = (p->name) ? p->name : "";
+ char *i = (p->IOPname) ? p->IOPname : "";
+ p = p->next;
+ printf(" %12s -> %12s\n", i, n);
+ }
+ }
+ }
+}
+
+static int find_unit_by_fd(int fd, int *chassis, int *geoslot, unit_t **unit_ptr) {
+ int c, s;
+
+ for (c = 0; c <= MAX_CHASSIS; c++) {
+ for (s = 0; s <= MAX_GEOSLOT; s++) {
+ if (units[c][s].fd == fd || units[c][s].find_fd == fd) {
+ if (chassis) *chassis = c;
+ if (geoslot) *geoslot = s;
+ if (unit_ptr) *unit_ptr = &units[c][s];
+ return 1;
+ }
+ }
+ }
+ return 0;
+}
+
+static int read_client_nbytes(int fd, int count, unsigned char *buf) {
+ unit_t *u;
+ int chassis, geoslot;
+ int len;
+
+ find_unit_by_fd(fd, &chassis, &geoslot, &u);
+ while (count) {
+ if ((len = recv(fd, buf, count, 0)) <= 0) return -1; /* read in whatever data was sent to us */
+ count -= len;
+ buf += len;
+ } /* till we have everything we are looking for */
+ return 0;
+}
+
+static void empty_unit_iface(unit_t *u) {
+ iface_t *p, *cur;
+
+ cur = u->iface;
+ while (cur) { /* loop over all the interface entries */
+ if (cur->name) free(cur->name); /* throwing away the contents if they exist */
+ if (cur->IOPname) free(cur->IOPname);
+ p = cur->next;
+ free(cur); /* then throw away the structure itself */
+ cur = p;
+ }
+ u->iface = 0; /* and finally remember that there are no remaining structure */
+}
+
+static void empty_unit(int chassis, int geoslot) {
+ unit_t *u = &units[chassis][geoslot];
+
+ empty_unit_iface(u);
+ if (u->imsg) { /* then if an inbound message buffer exists */
+ void *bigger_buffer;
+
+ bigger_buffer = (char *)realloc(u->imsg, 1); /* and re-allocate the old large buffer into a new small one */
+ if (bigger_buffer == NULL) { /* oops, realloc call failed */
+ fprintf(stderr, "Warning...call to realloc() failed, value of errno is %d\n", errno);
+ return;
+ }
+ u->imsg = bigger_buffer;
+ }
+}
+
+static void empty_unit_table(void) {
+ int chassis, geoslot;
+
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ if (units[chassis][geoslot].ip != NULL) {
+ free(units[chassis][geoslot].ip); /* get rid of the malloc'ed space that holds the IP address */
+ units[chassis][geoslot].ip = 0; /* then set the pointer to NULL */
+ }
+ empty_unit(chassis, geoslot);
+ }
+ }
+}
+
+static char *find_nth_interface_name(int n) {
+ int chassis, geoslot;
+ iface_t *p;
+ char *last_name = 0;
+
+ if (n < 0) n = 0; /* ensure we are working with a valid number */
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ if (units[chassis][geoslot].ip != NULL) {
+ p = units[chassis][geoslot].iface;
+ while (p) { /* and all interfaces... */
+ if (p->IOPname) last_name = p->name; /* remembering the last name found */
+ if (n-- == 0) return last_name; /* and if we hit the instance requested */
+ p = p->next;
+ }
+ }
+ }
+ }
+ /* if we couldn't fine the selected entry */
+ if (last_name) return last_name; /* ... but we did have at least one entry... return the last entry found */
+ return ""; /* ... but if there wasn't any entry... return an empty string instead */
+}
+
+int acn_parse_hosts_file(char *errbuf) { /* returns: -1 = error, 0 = OK */
+ FILE *fp;
+ char buf[MAX_LINE_SIZE];
+ char *ptr, *ptr2;
+ int pos;
+ int chassis, geoslot;
+ unit_t *u;
+
+ empty_unit_table();
+ if ((fp = fopen("/etc/hosts", "r")) == NULL) { /* try to open the hosts file and if it fails */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Cannot open '/etc/hosts' for reading."); /* return the nohostsfile error response */
+ return -1;
+ }
+ while (fgets(buf, MAX_LINE_SIZE-1, fp)) { /* while looping over the file */
+
+ pos = strcspn(buf, "#\n\r"); /* find the first comment character or EOL */
+ *(buf + pos) = '\0'; /* and clobber it and anything that follows it */
+
+ pos = strspn(buf, " \t"); /* then find the first non-white space */
+ if (pos == strlen(buf)) /* if there is nothing but white space on the line */
+ continue; /* ignore that empty line */
+ ptr = buf + pos; /* and skip over any of that leading whitespace */
+
+ if ((ptr2 = strstr(ptr, "_I_")) == NULL) /* skip any lines that don't have names that look like they belong to IOPs */
+ continue;
+ if (*(ptr2 + 4) != '_') /* and skip other lines that have names that don't look like ACN components */
+ continue;
+ *(ptr + strcspn(ptr, " \t")) = '\0'; /* null terminate the IP address so its a standalone string */
+
+ chassis = *(ptr2 + 3) - '0'; /* extract the chassis number */
+ geoslot = *(ptr2 + 5) - '0'; /* and geo-slot number */
+ if (chassis < 1 || chassis > MAX_CHASSIS ||
+ geoslot < 1 || geoslot > MAX_GEOSLOT) { /* if the chassis and/or slot numbers appear to be bad... */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Invalid ACN name in '/etc/hosts'."); /* warn the user */
+ continue; /* and ignore the entry */
+ }
+ if ((ptr2 = (char *)malloc(strlen(ptr) + 1)) == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ continue;
+ }
+ strcpy(ptr2, ptr); /* copy the IP address into our malloc'ed memory */
+ u = &units[chassis][geoslot];
+ u->ip = ptr2; /* and remember the whole shebang */
+ u->chassis = chassis;
+ u->geoslot = geoslot;
+ }
+ fclose(fp);
+ if (*errbuf) return -1;
+ else return 0;
+}
+
+static int open_with_IOP(unit_t *u, int flag) {
+ int sockfd;
+ char *ip;
+
+ if (u->serv_addr == NULL) {
+ u->serv_addr = malloc(sizeof(struct sockaddr_in));
+
+ /* since we called malloc(), lets check to see if we actually got the memory */
+ if (u->serv_addr == NULL) { /* oops, we didn't get the memory requested */
+ fprintf(stderr, "malloc() request for u->serv_addr failed, value of errno is: %d\n", errno);
+ return 0;
+ }
+
+ }
+ ip = u->ip;
+ /* bzero() is deprecated, replaced with memset() */
+ memset((char *)u->serv_addr, 0, sizeof(struct sockaddr_in));
+ u->serv_addr->sin_family = AF_INET;
+ u->serv_addr->sin_addr.s_addr = inet_addr(ip);
+ u->serv_addr->sin_port = htons(IOP_SNIFFER_PORT);
+
+ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+ fprintf(stderr, "pcap can't open a socket for connecting to IOP at %s\n", ip);
+ return 0;
+ }
+ if (connect(sockfd, (struct sockaddr *)u->serv_addr, sizeof(struct sockaddr_in)) < 0) {
+ fprintf(stderr, "pcap can't connect to IOP at %s\n", ip);
+ return 0;
+ }
+ if (flag == LIVE) u->fd = sockfd;
+ else u->find_fd = sockfd;
+ u->first_time = 0;
+ return sockfd; /* return the non-zero file descriptor as a 'success' indicator */
+}
+
+static void close_with_IOP(int chassis, int geoslot, int flag) {
+ int *id;
+
+ if (flag == LIVE) id = &units[chassis][geoslot].fd;
+ else id = &units[chassis][geoslot].find_fd;
+
+ if (*id) { /* this was the last time, so... if we are connected... */
+ close(*id); /* disconnect us */
+ *id = 0; /* and forget that the descriptor exists because we are not open */
+ }
+}
+
+static void pcap_cleanup_acn(pcap_t *handle) {
+ int chassis, geoslot;
+ unit_t *u;
+
+ if (find_unit_by_fd(handle->fd, &chassis, &geoslot, &u) == 0)
+ return;
+ close_with_IOP(chassis, geoslot, LIVE);
+ if (u)
+ u->first_time = 0;
+ pcap_cleanup_live_common(handle);
+}
+
+static void send_to_fd(int fd, int len, unsigned char *str) {
+ int nwritten;
+ int chassis, geoslot;
+
+ while (len > 0) {
+ if ((nwritten = write(fd, str, len)) <= 0) {
+ find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+ if (units[chassis][geoslot].fd == fd) close_with_IOP(chassis, geoslot, LIVE);
+ else if (units[chassis][geoslot].find_fd == fd) close_with_IOP(chassis, geoslot, FIND);
+ empty_unit(chassis, geoslot);
+ return;
+ }
+ len -= nwritten;
+ str += nwritten;
+ }
+}
+
+static void acn_freealldevs(void) {
+
+ pcap_if_t *iff, *next_iff;
+ pcap_addr_t *addr, *next_addr;
+
+ for (iff = acn_if_list; iff != NULL; iff = next_iff) {
+ next_iff = iff->next;
+ for (addr = iff->addresses; addr != NULL; addr = next_addr) {
+ next_addr = addr->next;
+ if (addr->addr) free(addr->addr);
+ if (addr->netmask) free(addr->netmask);
+ if (addr->broadaddr) free(addr->broadaddr);
+ if (addr->dstaddr) free(addr->dstaddr);
+ free(addr);
+ }
+ if (iff->name) free(iff->name);
+ if (iff->description) free(iff->description);
+ free(iff);
+ }
+}
+
+static void nonUnified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u) {
+
+ pcap_snprintf(buf, bufsize, "%s_%d_%d", proto, u->chassis, u->geoslot);
+}
+
+static void unified_IOP_port_name(char *buf, size_t bufsize, const char *proto, unit_t *u, int IOPportnum) {
+ int portnum;
+
+ portnum = ((u->chassis - 1) * 64) + ((u->geoslot - 1) * 8) + IOPportnum + 1;
+ pcap_snprintf(buf, bufsize, "%s_%d", proto, portnum);
+}
+
+static char *translate_IOP_to_pcap_name(unit_t *u, char *IOPname, bpf_u_int32 iftype) {
+ iface_t *iface_ptr, *iface;
+ char *name;
+ char buf[32];
+ char *proto;
+ char *port;
+ int IOPportnum = 0;
+
+ iface = malloc(sizeof(iface_t)); /* get memory for a structure */
+ if (iface == NULL) { /* oops, we didn't get the memory requested */
+ fprintf(stderr, "Error...couldn't allocate memory for interface structure...value of errno is: %d\n", errno);
+ return NULL;
+ }
+ memset((char *)iface, 0, sizeof(iface_t)); /* bzero is deprecated(), replaced with memset() */
+
+ iface->iftype = iftype; /* remember the interface type of this interface */
+
+ name = malloc(strlen(IOPname) + 1); /* get memory for the IOP's name */
+ if (name == NULL) { /* oops, we didn't get the memory requested */
+ fprintf(stderr, "Error...couldn't allocate memory for IOPname...value of errno is: %d\n", errno);
+ return NULL;
+ }
+
+ strcpy(name, IOPname); /* and copy it in */
+ iface->IOPname = name; /* and stick it into the structure */
+
+ if (strncmp(IOPname, "lo", 2) == 0) {
+ IOPportnum = atoi(&IOPname[2]);
+ switch (iftype) {
+ case DLT_EN10MB:
+ nonUnified_IOP_port_name(buf, sizeof buf, "lo", u);
+ break;
+ default:
+ unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
+ break;
+ }
+ } else if (strncmp(IOPname, "eth", 3) == 0) {
+ IOPportnum = atoi(&IOPname[3]);
+ switch (iftype) {
+ case DLT_EN10MB:
+ nonUnified_IOP_port_name(buf, sizeof buf, "eth", u);
+ break;
+ default:
+ unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
+ break;
+ }
+ } else if (strncmp(IOPname, "wan", 3) == 0) {
+ IOPportnum = atoi(&IOPname[3]);
+ switch (iftype) {
+ case DLT_SITA:
+ unified_IOP_port_name(buf, sizeof buf, "wan", u, IOPportnum);
+ break;
+ default:
+ unified_IOP_port_name(buf, sizeof buf, "???", u, IOPportnum);
+ break;
+ }
+ } else {
+ fprintf(stderr, "Error... invalid IOP name %s\n", IOPname);
+ return NULL;
+ }
+
+ name = malloc(strlen(buf) + 1); /* get memory for that name */
+ if (name == NULL) { /* oops, we didn't get the memory requested */
+ fprintf(stderr, "Error...couldn't allocate memory for IOP port name...value of errno is: %d\n", errno);
+ return NULL;
+ }
+
+ strcpy(name, buf); /* and copy it in */
+ iface->name = name; /* and stick it into the structure */
+
+ if (u->iface == 0) { /* if this is the first name */
+ u->iface = iface; /* stick this entry at the head of the list */
+ } else {
+ iface_ptr = u->iface;
+ while (iface_ptr->next) { /* othewise scan the list */
+ iface_ptr = iface_ptr->next; /* till we're at the last entry */
+ }
+ iface_ptr->next = iface; /* then tack this entry on the end of the list */
+ }
+ return iface->name;
+}
+
+static int if_sort(char *s1, char *s2) {
+ char *s1_p2, *s2_p2;
+ char str1[MAX_LINE_SIZE], str2[MAX_LINE_SIZE];
+ int s1_p1_len, s2_p1_len;
+ int retval;
+
+ if ((s1_p2 = strchr(s1, '_'))) { /* if an underscore is found... */
+ s1_p1_len = s1_p2 - s1; /* the prefix length is the difference in pointers */
+ s1_p2++; /* the suffix actually starts _after_ the underscore */
+ } else { /* otherwise... */
+ s1_p1_len = strlen(s1); /* the prefix length is the length of the string itself */
+ s1_p2 = 0; /* and there is no suffix */
+ }
+ if ((s2_p2 = strchr(s2, '_'))) { /* now do the same for the second string */
+ s2_p1_len = s2_p2 - s2;
+ s2_p2++;
+ } else {
+ s2_p1_len = strlen(s2);
+ s2_p2 = 0;
+ }
+ strncpy(str1, s1, (s1_p1_len > sizeof(str1)) ? s1_p1_len : sizeof(str1)); *(str1 + s1_p1_len) = 0;
+ strncpy(str2, s2, (s2_p1_len > sizeof(str2)) ? s2_p1_len : sizeof(str2)); *(str2 + s2_p1_len) = 0;
+ retval = strcmp(str1, str2);
+ if (retval != 0) return retval; /* if they are not identical, then we can quit now and return the indication */
+ return strcmp(s1_p2, s2_p2); /* otherwise we return the result of comparing the 2nd half of the string */
+}
+
+static void sort_if_table(void) {
+ pcap_if_t *p1, *p2, *prev, *temp;
+ int has_swapped;
+
+ if (!acn_if_list) return; /* nothing to do if the list is empty */
+
+ while (1) {
+ p1 = acn_if_list; /* start at the head of the list */
+ prev = 0;
+ has_swapped = 0;
+ while ((p2 = p1->next)) {
+ if (if_sort(p1->name, p2->name) > 0) {
+ if (prev) { /* we are swapping things that are _not_ at the head of the list */
+ temp = p2->next;
+ prev->next = p2;
+ p2->next = p1;
+ p1->next = temp;
+ } else { /* special treatment if we are swapping with the head of the list */
+ temp = p2->next;
+ acn_if_list= p2;
+ p2->next = p1;
+ p1->next = temp;
+ }
+ p1 = p2;
+ prev = p1;
+ has_swapped = 1;
+ }
+ prev = p1;
+ p1 = p1->next;
+ }
+ if (has_swapped == 0)
+ return;
+ }
+ return;
+}
+
+static int process_client_data (char *errbuf) { /* returns: -1 = error, 0 = OK */
+ int chassis, geoslot;
+ unit_t *u;
+ pcap_if_t *iff, *prev_iff;
+ pcap_addr_t *addr, *prev_addr;
+ char *ptr;
+ int address_count;
+ struct sockaddr_in *s;
+ char *newname;
+ bpf_u_int32 interfaceType;
+ unsigned char flags;
+ void *bigger_buffer;
+
+ prev_iff = 0;
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) { /* now loop over all the devices */
+ u = &units[chassis][geoslot];
+ empty_unit_iface(u);
+ ptr = u->imsg; /* point to the start of the msg for this IOP */
+ while (ptr < (u->imsg + u->len)) {
+ if ((iff = malloc(sizeof(pcap_if_t))) == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno, "malloc");
+ return -1;
+ }
+ memset((char *)iff, 0, sizeof(pcap_if_t)); /* bzero() is deprecated, replaced with memset() */
+ if (acn_if_list == 0) acn_if_list = iff; /* remember the head of the list */
+ if (prev_iff) prev_iff->next = iff; /* insert a forward link */
+
+ if (*ptr) { /* if there is a count for the name */
+ if ((iff->name = malloc(*ptr + 1)) == NULL) { /* get that amount of space */
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc");
+ return -1;
+ }
+ memcpy(iff->name, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */
+ *(iff->name + *ptr) = 0; /* and null terminate the string */
+ ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */
+ }
+ ptr++;
+
+ if (*ptr) { /* if there is a count for the description */
+ if ((iff->description = malloc(*ptr + 1)) == NULL) { /* get that amount of space */
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc");
+ return -1;
+ }
+ memcpy(iff->description, (ptr + 1), *ptr); /* copy the name into the malloc'ed space */
+ *(iff->description + *ptr) = 0; /* and null terminate the string */
+ ptr += *ptr; /* now move the pointer forwards by the length of the count plus the length of the string */
+ }
+ ptr++;
+
+ interfaceType = ntohl(*(bpf_u_int32 *)ptr);
+ ptr += 4; /* skip over the interface type */
+
+ flags = *ptr++;
+ if (flags) iff->flags = PCAP_IF_LOOPBACK; /* if this is a loopback style interface, lets mark it as such */
+
+ address_count = *ptr++;
+
+ prev_addr = 0;
+ while (address_count--) {
+ if ((addr = malloc(sizeof(pcap_addr_t))) == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc");
+ return -1;
+ }
+ memset((char *)addr, 0, sizeof(pcap_addr_t)); /* bzero() is deprecated, replaced with memset() */
+ if (iff->addresses == 0) iff->addresses = addr;
+ if (prev_addr) prev_addr->next = addr; /* insert a forward link */
+ if (*ptr) { /* if there is a count for the address */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) { /* get that amount of space */
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return -1;
+ }
+ memset((char *)s, 0, sizeof(struct sockaddr_in)); /* bzero() is deprecated, replaced with memset() */
+ addr->addr = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32 *)(ptr + 1); /* copy the address in */
+ ptr += *ptr; /* now move the pointer forwards according to the specified length of the address */
+ }
+ ptr++; /* then forwards one more for the 'length of the address' field */
+ if (*ptr) { /* process any netmask */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return -1;
+ }
+ /* bzero() is deprecated, replaced with memset() */
+ memset((char *)s, 0, sizeof(struct sockaddr_in));
+
+ addr->netmask = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
+ ptr += *ptr;
+ }
+ ptr++;
+ if (*ptr) { /* process any broadcast address */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return -1;
+ }
+ /* bzero() is deprecated, replaced with memset() */
+ memset((char *)s, 0, sizeof(struct sockaddr_in));
+
+ addr->broadaddr = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
+ ptr += *ptr;
+ }
+ ptr++;
+ if (*ptr) { /* process any destination address */
+ if ((s = malloc(sizeof(struct sockaddr_in))) == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return -1;
+ }
+ /* bzero() is deprecated, replaced with memset() */
+ memset((char *)s, 0, sizeof(struct sockaddr_in));
+
+ addr->dstaddr = (struct sockaddr *)s;
+ s->sin_family = AF_INET;
+ s->sin_addr.s_addr = *(bpf_u_int32*)(ptr + 1);
+ ptr += *ptr;
+ }
+ ptr++;
+ prev_addr = addr;
+ }
+ prev_iff = iff;
+
+ newname = translate_IOP_to_pcap_name(u, iff->name, interfaceType); /* add a translation entry and get a point to the mangled name */
+ bigger_buffer = realloc(iff->name, strlen(newname) + 1));
+ if (bigger_buffer == NULL) { /* we now re-write the name stored in the interface list */
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno, "realloc");
+ return -1;
+ }
+ iff->name = bigger_buffer;
+ strcpy(iff->name, newname); /* to this new name */
+ }
+ }
+ }
+ return 0;
+}
+
+static int read_client_data (int fd) {
+ unsigned char buf[256];
+ int chassis, geoslot;
+ unit_t *u;
+ int len;
+
+ find_unit_by_fd(fd, &chassis, &geoslot, &u);
+
+ if ((len = recv(fd, buf, sizeof(buf), 0)) <= 0) return 0; /* read in whatever data was sent to us */
+
+ if ((u->imsg = realloc(u->imsg, (u->len + len))) == NULL) /* extend the buffer for the new data */
+ return 0;
+ memcpy((u->imsg + u->len), buf, len); /* append the new data */
+ u->len += len;
+ return 1;
+}
+
+static void wait_for_all_answers(void) {
+ int retval;
+ struct timeval tv;
+ int fd;
+ int chassis, geoslot;
+
+ tv.tv_sec = 2;
+ tv.tv_usec = 0;
+
+ while (1) {
+ int flag = 0;
+ fd_set working_set;
+
+ for (fd = 0; fd <= max_fs; fd++) { /* scan the list of descriptors we may be listening to */
+ if (FD_ISSET(fd, &readfds)) flag = 1; /* and see if there are any still set */
+ }
+ if (flag == 0) return; /* we are done, when they are all gone */
+
+ memcpy(&working_set, &readfds, sizeof(readfds)); /* otherwise, we still have to listen for more stuff, till we timeout */
+ retval = select(max_fs + 1, &working_set, NULL, NULL, &tv);
+ if (retval == -1) { /* an error occured !!!!! */
+ return;
+ } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */
+ printf("timeout\n");
+ return;
+ } else {
+ for (fd = 0; fd <= max_fs; fd++) { /* scan the list of things to do, and do them */
+ if (FD_ISSET(fd, &working_set)) {
+ if (read_client_data(fd) == 0) { /* if the socket has closed */
+ FD_CLR(fd, &readfds); /* and descriptors we listen to for errors */
+ find_unit_by_fd(fd, &chassis, &geoslot, NULL);
+ close_with_IOP(chassis, geoslot, FIND); /* and close out connection to him */
+ }
+ }
+ }
+ }
+ }
+}
+
+static char *get_error_response(int fd, char *errbuf) { /* return a pointer on error, NULL on no error */
+ char byte;
+ int len = 0;
+
+ while (1) {
+ recv(fd, &byte, 1, 0); /* read another byte in */
+ if (errbuf && (len++ < PCAP_ERRBUF_SIZE)) { /* and if there is still room in the buffer */
+ *errbuf++ = byte; /* stick it in */
+ *errbuf = '\0'; /* ensure the string is null terminated just in case we might exceed the buffer's size */
+ }
+ if (byte == '\0') {
+ if (len > 1) { return errbuf; }
+ else { return NULL; }
+ }
+ }
+}
+
+int acn_findalldevs(char *errbuf) { /* returns: -1 = error, 0 = OK */
+ int chassis, geoslot;
+ unit_t *u;
+
+ FD_ZERO(&readfds);
+ max_fs = 0;
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) {
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ u = &units[chassis][geoslot];
+ if (u->ip && (open_with_IOP(u, FIND))) { /* connect to the remote IOP */
+ send_to_fd(u->find_fd, 1, (unsigned char *)"\0");
+ if (get_error_response(u->find_fd, errbuf))
+ close_with_IOP(chassis, geoslot, FIND);
+ else {
+ if (u->find_fd > max_fs)
+ max_fs = u->find_fd; /* remember the highest number currently in use */
+ FD_SET(u->find_fd, &readfds); /* we are going to want to read this guy's response to */
+ u->len = 0;
+ send_to_fd(u->find_fd, 1, (unsigned char *)"Q"); /* this interface query request */
+ }
+ }
+ }
+ }
+ wait_for_all_answers();
+ if (process_client_data(errbuf))
+ return -1;
+ sort_if_table();
+ return 0;
+}
+
+static int pcap_stats_acn(pcap_t *handle, struct pcap_stat *ps) {
+ unsigned char buf[12];
+
+ send_to_fd(handle->fd, 1, (unsigned char *)"S"); /* send the get_stats command to the IOP */
+
+ if (read_client_nbytes(handle->fd, sizeof(buf), buf) == -1) return -1; /* try reading the required bytes */
+
+ ps->ps_recv = ntohl(*(uint32_t *)&buf[0]); /* break the buffer into its three 32 bit components */
+ ps->ps_drop = ntohl(*(uint32_t *)&buf[4]);
+ ps->ps_ifdrop = ntohl(*(uint32_t *)&buf[8]);
+
+ return 0;
+}
+
+static int acn_open_live(const char *name, char *errbuf, int *linktype) { /* returns 0 on error, else returns the file descriptor */
+ int chassis, geoslot;
+ unit_t *u;
+ iface_t *p;
+ pcap_if_list_t devlist;
+
+ pcap_platform_finddevs(&devlist, errbuf);
+ for (chassis = 0; chassis <= MAX_CHASSIS; chassis++) { /* scan the table... */
+ for (geoslot = 0; geoslot <= MAX_GEOSLOT; geoslot++) {
+ u = &units[chassis][geoslot];
+ if (u->ip != NULL) {
+ p = u->iface;
+ while (p) { /* and all interfaces... */
+ if (p->IOPname && p->name && (strcmp(p->name, name) == 0)) { /* and if we found the interface we want... */
+ *linktype = p->iftype;
+ open_with_IOP(u, LIVE); /* start a connection with that IOP */
+ send_to_fd(u->fd, strlen(p->IOPname)+1, (unsigned char *)p->IOPname); /* send the IOP's interface name, and a terminating null */
+ if (get_error_response(u->fd, errbuf)) {
+ return -1;
+ }
+ return u->fd; /* and return that open descriptor */
+ }
+ p = p->next;
+ }
+ }
+ }
+ }
+ return -1; /* if the interface wasn't found, return an error */
+}
+
+static void acn_start_monitor(int fd, int snaplen, int timeout, int promiscuous, int direction) {
+ unsigned char buf[8];
+ unit_t *u;
+
+ //printf("acn_start_monitor()\n"); // fulko
+ find_unit_by_fd(fd, NULL, NULL, &u);
+ if (u->first_time == 0) {
+ buf[0] = 'M';
+ *(uint32_t *)&buf[1] = htonl(snaplen);
+ buf[5] = timeout;
+ buf[6] = promiscuous;
+ buf[7] = direction;
+ //printf("acn_start_monitor() first time\n"); // fulko
+ send_to_fd(fd, 8, buf); /* send the start monitor command with its parameters to the IOP */
+ u->first_time = 1;
+ }
+ //printf("acn_start_monitor() complete\n"); // fulko
+}
+
+static int pcap_inject_acn(pcap_t *p, const void *buf _U_, size_t size _U_) {
+ pcap_strlcpy(p->errbuf, "Sending packets isn't supported on ACN adapters",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+
+static int pcap_setfilter_acn(pcap_t *handle, struct bpf_program *bpf) {
+ int fd = handle->fd;
+ int count;
+ struct bpf_insn *p;
+ uint16_t shortInt;
+ uint32_t longInt;
+
+ send_to_fd(fd, 1, (unsigned char *)"F"); /* BPF filter follows command */
+ count = bpf->bf_len;
+ longInt = htonl(count);
+ send_to_fd(fd, 4, (unsigned char *)&longInt); /* send the instruction sequence count */
+ p = bpf->bf_insns;
+ while (count--) { /* followed by the list of instructions */
+ shortInt = htons(p->code);
+ longInt = htonl(p->k);
+ send_to_fd(fd, 2, (unsigned char *)&shortInt);
+ send_to_fd(fd, 1, (unsigned char *)&p->jt);
+ send_to_fd(fd, 1, (unsigned char *)&p->jf);
+ send_to_fd(fd, 4, (unsigned char *)&longInt);
+ p++;
+ }
+ if (get_error_response(fd, NULL))
+ return -1;
+ return 0;
+}
+
+static int pcap_setdirection_acn(pcap_t *handle, pcap_direction_t d) {
+ pcap_snprintf(handle->errbuf, sizeof(handle->errbuf),
+ "Setting direction is not supported on ACN adapters");
+ return -1;
+}
+
+static int acn_read_n_bytes_with_timeout(pcap_t *handle, int count) {
+ struct timeval tv;
+ int retval, fd;
+ fd_set r_fds;
+ fd_set w_fds;
+ u_char *bp;
+ int len = 0;
+ int offset = 0;
+
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+
+ fd = handle->fd;
+ FD_ZERO(&r_fds);
+ FD_SET(fd, &r_fds);
+ memcpy(&w_fds, &r_fds, sizeof(r_fds));
+ bp = handle->bp;
+ while (count) {
+ retval = select(fd + 1, &w_fds, NULL, NULL, &tv);
+ if (retval == -1) { /* an error occured !!!!! */
+// fprintf(stderr, "error during packet data read\n");
+ return -1; /* but we need to return a good indication to prevent unneccessary popups */
+ } else if (retval == 0) { /* timeout occured, so process what we've got sofar and return */
+// fprintf(stderr, "timeout during packet data read\n");
+ return -1;
+ } else {
+ if ((len = recv(fd, (bp + offset), count, 0)) <= 0) {
+// fprintf(stderr, "premature exit during packet data rx\n");
+ return -1;
+ }
+ count -= len;
+ offset += len;
+ }
+ }
+ return 0;
+}
+
+static int pcap_read_acn(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user) {
+ #define HEADER_SIZE (4 * 4)
+ unsigned char packet_header[HEADER_SIZE];
+ struct pcap_pkthdr pcap_header;
+
+ //printf("pcap_read_acn()\n"); // fulko
+ acn_start_monitor(handle->fd, handle->snapshot, handle->opt.timeout, handle->opt.promisc, handle->direction); /* maybe tell him to start monitoring */
+ //printf("pcap_read_acn() after start monitor\n"); // fulko
+
+ handle->bp = packet_header;
+ if (acn_read_n_bytes_with_timeout(handle, HEADER_SIZE) == -1) return 0; /* try to read a packet header in so we can get the sizeof the packet data */
+
+ pcap_header.ts.tv_sec = ntohl(*(uint32_t *)&packet_header[0]); /* tv_sec */
+ pcap_header.ts.tv_usec = ntohl(*(uint32_t *)&packet_header[4]); /* tv_usec */
+ pcap_header.caplen = ntohl(*(uint32_t *)&packet_header[8]); /* caplen */
+ pcap_header.len = ntohl(*(uint32_t *)&packet_header[12]); /* len */
+
+ handle->bp = (u_char *)handle->buffer + handle->offset; /* start off the receive pointer at the right spot */
+ if (acn_read_n_bytes_with_timeout(handle, pcap_header.caplen) == -1) return 0; /* then try to read in the rest of the data */
+
+ callback(user, &pcap_header, handle->bp); /* call the user supplied callback function */
+ return 1;
+}
+
+static int pcap_activate_sita(pcap_t *handle) {
+ int fd;
+
+ if (handle->opt.rfmon) {
+ /*
+ * No monitor mode on SITA devices (they're not Wi-Fi
+ * devices).
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /* Initialize some components of the pcap structure. */
+
+ handle->inject_op = pcap_inject_acn;
+ handle->setfilter_op = pcap_setfilter_acn;
+ handle->setdirection_op = pcap_setdirection_acn;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+ handle->cleanup_op = pcap_cleanup_acn;
+ handle->read_op = pcap_read_acn;
+ handle->stats_op = pcap_stats_acn;
+
+ fd = acn_open_live(handle->opt.device, handle->errbuf,
+ &handle->linktype);
+ if (fd == -1)
+ return PCAP_ERROR;
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+ handle->snapshot = MAXIMUM_SNAPLEN;
+
+ handle->fd = fd;
+ handle->bufsize = handle->snapshot;
+
+ /* Allocate the buffer */
+
+ handle->buffer = malloc(handle->bufsize + handle->offset);
+ if (!handle->buffer) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ pcap_cleanup_acn(handle);
+ return PCAP_ERROR;
+ }
+
+ /*
+ * "handle->fd" is a socket, so "select()" and "poll()"
+ * should work on it.
+ */
+ handle->selectable_fd = handle->fd;
+
+ return 0;
+}
+
+pcap_t *pcap_create_interface(const char *device _U_, char *ebuf) {
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, 0);
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_sita;
+ return (p);
+}
+
+int pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) {
+
+ //printf("pcap_findalldevs()\n"); // fulko
+
+ *alldevsp = 0; /* initialize the returned variables before we do anything */
+ strcpy(errbuf, "");
+ if (acn_parse_hosts_file(errbuf)) /* scan the hosts file for potential IOPs */
+ {
+ //printf("pcap_findalldevs() returning BAD after parsehosts\n"); // fulko
+ return -1;
+ }
+ //printf("pcap_findalldevs() got hostlist now finding devs\n"); // fulko
+ if (acn_findalldevs(errbuf)) /* then ask the IOPs for their monitorable devices */
+ {
+ //printf("pcap_findalldevs() returning BAD after findalldevs\n"); // fulko
+ return -1;
+ }
+ devlistp->beginning = acn_if_list;
+ acn_if_list = 0; /* then forget our list head, because someone will call pcap_freealldevs() to empty the malloc'ed stuff */
+ //printf("pcap_findalldevs() returning ZERO OK\n"); // fulko
+ return 0;
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return PCAP_VERSION_STRING " (SITA-only)";
+}
diff --git a/lib/libpcap/libpcap/pcap-sita.h b/lib/libpcap/libpcap/pcap-sita.h
new file mode 100644
index 0000000..9c35c6a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-sita.h
@@ -0,0 +1,8 @@
+/*
+ * pcap-sita.h: Packet capture interface for SITA WAN devices
+ *
+ * Authors: Fulko Hew (fulko.hew@sita.aero) (+1 905 6815570);
+ */
+
+extern int acn_parse_hosts_file(char *errbuf);
+extern int acn_findalldevs(char *errbuf);
diff --git a/lib/libpcap/libpcap/pcap-sita.html b/lib/libpcap/libpcap/pcap-sita.html
new file mode 100644
index 0000000..4a8fe1a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-sita.html
@@ -0,0 +1,943 @@
+<HTML><HEAD>
+<STYLE type="text/css">
+<!--
+A { text-decoration:none }
+-->
+</STYLE>
+</HEAD>
+<BODY>
+
+<TABLE WIDTH=100%><TR>
+ <TD ALIGN=LEFT VALIGN=TOP>
+ <FONT SIZE=+0 FACE="COURIER"><B>A "Distributed Pcap" for<BR>Remote Monitoring LANs & WANs</B><BR>
+ (Design Notes for the SITA ACN device)</FONT>
+ </TD>
+ <TD ALIGN=RIGHT VALIGN=TOP>
+ Fulko Hew<BR>SITA INC Canada, Inc.<BR>Revised: October 2, 2007
+ </TD>
+</TR></TABLE>
+
+
+<H3>SUMMARY</H3>
+<UL>
+ <STRONG>Note:</STRONG> This document is part of the libpcap Git and was derived from 'pcap.3' (circa Aug/07).
+ <P>
+ The ACN provides a customized/distributed version of this library that alows SMPs to
+ interact with the various IOPs within the site providing a standard mechanism
+ to capture LAN and WAN message traffic.
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3 WIDTH=75%>
+ <TR>
+ <TH VALIGN=TOP>SMP</TH>
+ <TD VALIGN=TOP>The Supervisory Management Processor where Wireshark (or equivalent)
+ runs in conjuction with a libpcap front-end.</TD>
+ </TR>
+ <TR>
+ <TH VALIGN=TOP>IOP</TH>
+ <TD VALIGN=TOP>I/O Processors where the monitored ports exist in conjunction
+ with a custom device driver/libpcap back-end.</TD>
+ </TR>
+ </TABLE>
+ </CENTER>
+ <P>
+ Each IOP will be capable of supporting multiple connections from an SMP
+ enabling monitoring of more than one interface at a time, each through
+ its own seperate connection. The IOP is responsible to ensure and report
+ an error if any attempt is made to monitor the same interface more than once.
+ <P>
+ There are three applications that will be supported by the ACN version of libpcap.
+ They each use a slightly different mode for looping/capturing and termination
+ as summarized in the following table:
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR><TH>Application</TH> <TH>Capture</TH> <TH>Termination</TH></TR>
+ <TR><TH VALIGN=TOP NOWRAP>wireshark</TH>
+ <TD VALIGN=TOP>pcap_dispatch(all packets in one buffer of capture only)</TD>
+ <TD VALIGN=TOP>pcap_breakloop()</TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>tshark</TH>
+ <TD VALIGN=TOP>pcap_dispatch(one buffer of capture only)</TD>
+ <TD VALIGN=TOP>Since a CTRL-C was used to terminate the application, pcap_breakloop() is never called.</TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>tcpdump</TH>
+ <TD VALIGN=TOP>pcap_loop(all packets in the next buffer, and loop forever)</TD>
+ <TD VALIGN=TOP>pcap_breakloop()</TD>
+ </TR>
+ </TABLE>
+ </CENTER>
+ <P>
+ <B>Note: </B>In all cases, the termination of capturing is always (apparently) followed by
+ pcap_close(). Pcap_breakloop() is only used to stop/suspend looping/processing,
+ and upon close interpretation of the function definitions, it is possible to resume
+ capturing following a pcap_breakloop() without any re-initialization.
+ <P>
+ <H4>ACN Limitations</H4>
+ <OL>
+ <LI>Monitoring of backup IOPs is not currently supported.
+ <LI>Ethernet interfaces cannot be monitored in promiscuous mode.
+ </OL>
+
+</UL>
+
+<H3>ROUTINES</H3>
+<UL>
+ The following list of functions is the sub-set of Pcap functions that have been
+ altered/enhanced to support the ACN remote monitoring facility. The remainder of the Pcap
+ functions continue to perform their duties un-altered. Libpcap only supports this
+ mode of operation if it has been configured/compiled for SITA/ACN support.
+ <P>
+ <UL><FONT FACE=COURIER>
+ pcap_findalldevs<BR>
+ pcap_freealldevs<BR>
+ pcap_open_live<BR>
+ pcap_close<BR>
+ pcap_setfilter<BR>
+ pcap_dispatch<BR>
+ pcap_loop<BR>
+ pcap_next<BR>
+ pcap_next_ex<BR>
+ pcap_stats<BR>
+ </FONT></UL>
+
+ These subroutines have been modified for the ACN specific distributed and remote monitoring
+ ability perform the following basic functions. More detail is provided in the
+ "SMP/IOP Inter-Process Communication Protocol" section.
+ <P>
+<TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_open_live()</B></TD>
+ <TD VALIGN=TOP>Used to obtain a packet capture descriptor to look at packets on the network.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP will open a connection to the selected IOP on its 'sniffer' port
+ to ensure it is available. It sends a null terminated string identifying
+ the interface to be monitored.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ After any required processing is complete, the IOP will return a
+ null terminated string containing an error message if one occured.
+ If no error occured, a empty string is still returned.
+ Errors are:
+ <UL>
+ <LI>"Interface (xxx) does not exist."
+ <LI>"Interface (xxx) not configured."
+ <LI>"Interface (xxx) already being monitored."
+ </UL>
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_findalldevs()</B></TD>
+ <TD VALIGN=TOP>It constructs a list of network devices that can be opened with pcap_open_live().</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ It obtains a list of IOPs currently available (via /etc/hosts).
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP will sequentially open a connection to each IOP on its 'sniffer' port to ensure
+ the IOP is available.
+ It sends a null terminated empty interface ID followed by the query request command.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>The IOP returns an error response and its list of devices.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP closes the TCP connection with each IOP.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP adds the received information to its internal structure.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_freealldevs()</B></TD>
+ <TD VALIGN=TOP>Used to free a list allocated by pcap_findalldevs().</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP frees the structure it built as a result of the previous
+ invocation of pcap_findalldevs().
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_dispatch()</B></TD>
+ <TD VALIGN=TOP>Used to collect and process packets.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP will read the reverse channel of the connection between the SMP and the
+ IOP that provides the captured data (via 'p->read_op' which is 'pcap_read_linux()'
+ until the select() call returns a 'no more data' indication.
+ It will the process (at most) the next 'cnt' packets and invoke the specified
+ callback function for each packet processed.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_loop()</B></TD>
+ <TD VALIGN=TOP>
+ Is similar to pcap_dispatch() except it keeps reading packets until
+ the requested number of packets are processed or an error occurs.
+ </TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP continuously reads the next packet from the reverse channel of the connection
+ between the SMP and the IOP that provides the captured data (via 'p->read_op'
+ which is 'pcap_read_linux()' until 'cnt' packets have been received.
+ The specified callback function will be invoked for each packet received.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_next()</B></TD>
+ <TD VALIGN=TOP>
+ It reads the next packet (by calling pcap_dispatch() with a count of 1)
+ and returns a pointer to the data in that packet.
+ </TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP reads only the next packet from the reverse channel of the connection
+ between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+ with a count of 1) and returns a pointer to that data by invoking an internal callback.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_next_ex()</B></TD>
+ <TD VALIGN=TOP>Reads the next packet and returns a success/failure indication.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ On the first invocation of pcap_dispatch(), pcap_loop(), or pcap_next(), or pcap_next_ex() following a pcap_open_live(),
+ the SMP will pass down the monitor start command and various parameters the IOP should use.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP now sends a stream of captured data.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP reads only the next packet from the reverse channel of the connection
+ between the SMP and the IOP that provides the captured data (via calling pcap_dispatch()
+ with a count of 1) and returns seperate pointers to both the
+ packet header and packet data by invoking an internal callback.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ The IOP continues to listen for additional commands as well as capturing and forwarding data to the SMP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_setfilter()</B></TD>
+ <TD VALIGN=TOP>Used to specify a filter program.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP sends a 'set filter' command followed by the BPF commands.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP returns a null terminated error string if it failed to accept the filter.
+ If no error occured, then a NULL terminated empty string is returned instead.
+ Errors are:
+ <UL>
+ <LI>"Invalid BPF."
+ <LI>"Insufficient resources for BPF."
+ </UL>
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_stats()</B></TD>
+ <TD VALIGN=TOP>Fills in a pcap_stat struct with packet statistics.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP sends a message to the IOP requesting its statistics.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP -> SMP</TH>
+ <TD>
+ The IOP returns the statistics.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>SMP</TH>
+ <TD>
+ The SMP fills in the structure provided with the information retrieved from the IOP.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2><B>pcap_close()</B></TD>
+ <TD VALIGN=TOP>Closes the file and deallocates resources.</TD>
+ </TR>
+ <TR><TD><TABLE BORDER=0 CELLSPACING=0 CELLPADDING=3 WIDTH=100%>
+ <TR><TH VALIGN=TOP NOWRAP>SMP -> IOP</TH>
+ <TD>
+ The SMP closes the file descriptor, and if the descriptor is that of
+ the comminucation session with an IOP, it too is terminated.
+ </TD>
+ </TR>
+ <TR><TH VALIGN=TOP NOWRAP>IOP</TH>
+ <TD>
+ If the IOP detects that its communication session with an SMP
+ has closed, it will terminate any monitoring in progress,
+ release any resources and close its end of the session.
+ It will not maintain persistance of any information or prior mode of operation.
+ </TD>
+ </TR>
+ </TABLE></TD></TR>
+</TABLE>
+</UL>
+
+<P>
+<H3>SMP/IOP Inter-Process Communication Protocol</H3>
+
+<UL>
+ <LI><P>Communications between an SMP and an IOP consists of a TCP session
+ between an ephemeral port on the SMP and the well known port of 49152
+ (which is the first available port in the 'dynamic and/or private port'
+ range) on an IOP.
+ <LI><P>Following a TCP open operation the IOP receives a null terminated
+ 'interface ID' string to determine the type of operation that follows:
+ <LI><P>Every command received by an IOP implies a 'stop trace/stop forwarding' operation must
+ occur before executing the received command.
+ <LI><P>A session is closed when the SMP closes the TCP session with the IOP.
+ Obviously monitoring and forwarding is also stopped at that time.
+
+ <B>Note: </B>All multi-octet entities are sent in network neutral order.
+ <P>
+
+ <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=5>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=6>pcap_findalldevs()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Open socket (to each IOP), and sends:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>Interface ID</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A NULL to indicate an empty 'interface ID'.</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Send its (possibly empty) NULL terminated error response string.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Sends the 'interface query request':
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>Interface ID</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A 'Q' (indicating 'interface query request').</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>The IOP returns a list of sequences of information as
+ defined by the return parameter of this function call (as shown in the following table).
+ Elements are specified by providing an unsigned byte preceeding the actual data that contains length information.
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Notes:</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD ROWSPAN=7>&nbsp;</TD>
+ <TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the name field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Name</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+ <TD VALIGN=TOP>The name of the interface. The format of the name is an alphabetic string (indicating
+ the type of interface) followed by an optional numeric string (indicating the interface's
+ sequence number).
+ Sequence numbers (if needed) will begin at zero and progress monotonically upwards.
+ (i.e. 'eth0', 'lo', 'wan0', etc.)
+ <P>
+ For an IOP, the alphabetic string will be one of: 'eth', 'wan', and 'lo'
+ for Ethernet, WAN ports and the IP loopback device respectively.
+ An IOP currently supports: 'eth0', 'eth1', 'lo', 'wan0' ... 'wan7'.
+ <P>
+ <B>Note:</B> IOPs and ACNs will not currently support the concept of 'any' interface.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the interface description field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Interface Description</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>A description of the interface or it may be an empty string. (i.e. 'ALC')</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Interface Type</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The type of interface as defined in the description for pcap_datalink() (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Loopback Flag</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>1 = if the interface is a loopback interface, zero = otherwise.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>count</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP># of address entries that follow.
+ Each entry is a series of bytes in network neutral order.
+ See the parameter definition above for more details.</TD>
+ </TR>
+ <TR>
+ <TD ALIGN=CENTER ROWSPAN=8 WIDTH=1%>Repeated 'count' number of times.</TD>
+ <TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the address field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Address</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1-255</TD>
+ <TD VALIGN=TOP>The address of this interface (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the netmask field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Network Mask</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>The network mask used on this interface (if applicable) (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the broadcast address field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Broadcast Address</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>The broadcast address of this interface (if applicable) (in network neutral order).</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=RIGHT>length</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The number of octets in the destination address field that follows.</TD>
+ </TR>
+ <TR><TD VALIGN=TOP ALIGN=LEFT>Destination Address</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>0-255</TD>
+ <TD VALIGN=TOP>The destination address of this interface (if applicable) (in network neutral order).</TD>
+ </TR>
+ </TABLE>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Close the socket.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Close the socket.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2>pcap_open_live()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>Open socket, and sends:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>Interface ID</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+ <TD VALIGN=TOP>'n' octets containing a NULL terminated interface name string.</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Send its NULL terminated error response string.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP NOWRAP ROWSPAN=2>pcap_dispatch()<BR>pcap_loop()<BR>pcap_next()<BR>pcap_next_ex()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>On the first invocation following a pcap_open_live() or pcap_breakloop() additional information is sent:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>command</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>'M' (indicating 'monitor start')</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>snaplen</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>snaplen</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>timeout</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>timeout value (in milliseconds)</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>promiscuous</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A flag indicating that the interface being monitored show operate
+ in promiscuous mode. [off(0) / on(NZ)]</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>direction</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>A flag indicating the direction of traffic that should be captuted [both(0) / in(1) / out(2)]</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>Sends captured packets.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2>pcap_setfilter()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>At any time, the SMP can issue a set filter command which contains
+ an indicator, a count of the number of statements in the filter,
+ followed by the sequence of filter commands represented as a sequence
+ of C-style structures.
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>command</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>'F' (indicating 'filter')</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>count</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of command in the Berkeley Packet Filter that follow.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>BPF program</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>'n'</TD>
+ <TD VALIGN=TOP>8 bytes of each command (repeated 'n' times).<BR>
+ Each command consists of that C-style structure which contains:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>opcode</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>2</TD>
+ <TD VALIGN=TOP>The command's opcode.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>'jt'</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The 'jump if true' program counter offset.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>'jf'</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>The 'jump if false' program counter offset.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>'k'</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The 'other' data field.</TD>
+ </TR>
+ </TABLE>
+ <P>
+ Refer to the bpf(4) man page for more details.
+ </TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>In return the IOP will send its (possibly empty) NULL terminated error response string.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=2>pcap_stats()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>At any time, the SMP can issue a 'retrieve statistics' command which contains:<BR>
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>command</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>1</TD>
+ <TD VALIGN=TOP>'S' (indicating 'request statistics')</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>IOP -> SMP</TD>
+ <TD VALIGN=TOP>In return the IOP will send:
+ <P>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TH VALIGN=TOP ALIGN=CENTER>Name/<BR>Purpose</TH>
+ <TH VALIGN=TOP ALIGN=CENTER NOWRAP>Size<BR>(in bytes)</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Description</TH>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>ps_recv</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of packets that passed the filter.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>ps_drop</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of packets that were dropped because the input queue was full,
+ regardless of whether they passed the filter.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>ps_ifdrop</TD>
+ <TD VALIGN=TOP ALIGN=CENTER>4</TD>
+ <TD VALIGN=TOP>The number of packets dropped by the network inteface
+ (regardless of whether they would have passed the input filter).</TD>
+ </TR>
+ </TABLE>
+ </TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ <TR>
+ <TD VALIGN=TOP ROWSPAN=1>pcap_close()</TD>
+ <TD VALIGN=TOP ALIGN=CENTER NOWRAP>SMP -> IOP</TD>
+ <TD VALIGN=TOP>At any time, the SMP can close the TCP session with the IOP.</TD>
+ </TR>
+ <TR><TH COLSPAN=3><HR WIDTH=100%></TH></TR>
+ </TABLE>
+</UL>
+
+<H3>Interface ID Naming Convention</H3>
+<UL>
+ Each interface within an IOP will be referred to uniquely. Since an currently contains
+ 8 monitorable WAN ports and a monitorable Ethernet port, the naming convention is:
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR><TH>Interface #</TH> <TH>Type</TH> <TH>Name</TH></TR>
+ <TR><TD ALIGN=CENTER>1</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan0</TD></TR>
+ <TR><TD ALIGN=CENTER>2</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan1</TD></TR>
+ <TR><TD ALIGN=CENTER>3</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan2</TD></TR>
+ <TR><TD ALIGN=CENTER>4</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan3</TD></TR>
+ <TR><TD ALIGN=CENTER>5</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan4</TD></TR>
+ <TR><TD ALIGN=CENTER>6</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan5</TD></TR>
+ <TR><TD ALIGN=CENTER>7</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan6</TD></TR>
+ <TR><TD ALIGN=CENTER>8</TD> <TD ALIGN=CENTER>WAN</TD> <TD ALIGN=CENTER>wan7</TD></TR>
+ <TR><TD ALIGN=CENTER>9</TD> <TD ALIGN=CENTER>Ethernet</TD> <TD ALIGN=CENTER>eth0</TD></TR>
+ <TR><TD ALIGN=CENTER>10</TD> <TD ALIGN=CENTER>Ethernet</TD> <TD ALIGN=CENTER>eth1</TD></TR>
+ </TABLE>
+ </CENTER>
+</UL>
+
+<H3>Packet Trace Data Format</H3>
+<UL>
+ The format of the trace data that is sent to the SMP follows a portion of the libpcap file format
+ and is summarized here. This format specifies the generic requirements needed to
+ be able to decode packets, but does not cover ACN specifics such as custom MAC addressing
+ and WAN protocol support.
+ <P>
+
+ Although a libpcap file begins with a global header followed by zero or
+ more records for each captured packet, trace data sent to the SMP does NOT begin with a global header.
+ A trace sequence looks like this:
+ <P>
+ <TABLE>
+ <TR>
+ <TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Header]&nbsp;</TD>
+ <TD STYLE="background-color: #c0FFc0">&nbsp;[Packet Data]&nbsp;</TD>
+ <TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Header]&nbsp;</TD>
+ <TD STYLE="background-color: #c0c0FF">&nbsp;[Packet Data]&nbsp;</TD>
+ <TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Header]&nbsp;</TD>
+ <TD STYLE="background-color: #e0c0c0">&nbsp;[Packet Data]&nbsp;</TD>
+ <TD>...</TD>
+ </TR>
+ </TABLE>
+
+<H4>Packet Header</H4>
+ <UL>
+ Each captured packet starts with a header that contains the following values
+ (in network neutral order):
+
+ <FONT SIZE=-1>
+ <PRE>
+ uint32 tv_sec; /* timestamp seconds */
+ uint32 tv_usec; /* timestamp microseconds */
+ uint32 caplen; /* number of octets in the following packet */
+ uint32 len; /* original length of packet on the wire */
+ </PRE>
+ </FONT>
+
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR>
+ <TD VALIGN=TOP>tv_sec</TD>
+ <TD>The date and time when this packet was captured.
+ This value is in seconds since January 1, 1970 00:00:00 GMT;
+ this is also known as a UN*X time_t. You can use the ANSI C
+ <em>time()</em> function from <em>time.h</em> to get this value,
+ but you might use a more optimized way to get this timestamp value.
+ If this timestamp isn't based on GMT (UTC), use <em>thiszone</em>
+ from the global header for adjustments.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>tv_usec</TD>
+ <TD>The microseconds when this packet was captured, as an offset to <em>ts_sec</em>.
+ <B>Beware: </B>this value must never reach 1 second (1,000,000),
+ in this case <em>ts_sec</em> must be increased instead!</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>caplen</TD>
+ <TD>The number of bytes actually provided in the capture record.
+ This value should never become larger than <em>len</em> or the
+ <em>snaplen</em> value specified during the capture.</TD>
+ </TR>
+ <TR>
+ <TD VALIGN=TOP>len</TD>
+ <TD>The length of the packet "on the wire" when it was captured.
+ If <em>caplen</em> and <em>len</em> differ, the actually
+ saved packet size was limited by the value of <em>snaplen</em> specified
+ during one of the capture directives such as pcap_dispatch().</TD>
+ </TR>
+ </TABLE>
+ </UL>
+
+<H4>Packet Data</H4>
+ <UL>
+ The actual packet data will immediately follow the packet header as a sequence of <em>caplen</em> octets.
+ Depending on the DLT encoding number assigned to the interface, the packet data will contain an additional
+ custom header used to convey WAN port related information.
+ </UL>
+
+<H4>ACN Custom Packet Header</H4>
+ <UL>
+ PCAP, Wireshark and Tcpdump enhancements have been added to the ACN to support
+ monitoring of its ports, however each of these facilities were focused on capturing
+ and displaying traffic from LAN interfaces. The SITA extentions to these facilities
+ are used to also provide the ability to capture, filter, and display information from
+ an ACN's WAN ports.
+ <P>
+ Although each packet follows the standard libpcap format, since there are
+ two types of interfaces that can be monitored, the format of the data
+ packet varies slightly.
+ <P>
+ <UL TYPE=DISC>
+ <LI>For Ethernet (like) devices, the packet format is unchanged from the standard Pcap format.
+ <LI>For WAN devices, the packet contains a 5 byte header that preceeds the actual captured data
+ described by the following table:
+ </UL>
+ <P>
+ <CENTER>
+ <TABLE BORDER=1 CELLSPACING=0 CELLPADDING=3>
+ <TR> <TH>Octet</TH>
+ <TH>Name</TH>
+ <TH>Mask/Value</TH>
+ <TH COLSPAN=2>Definition</TH> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>0</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=3>Control / Status</TH>
+
+ <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx0</FONT></TD>
+ <TD>Transmitted by capture device</TD>
+ <TD ROWSPAN=2 ALIGN=CENTER>(see 'Errors' octets)</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD>
+ <TD>Received by capture device</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD>
+ <TD COLSPAN=2>No buffer was available during capture of previous packet.</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>1</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=8>Signals</TH>
+
+ <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD> <TD COLSPAN=2>DSR asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD> <TD COLSPAN=2>DTR asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD> <TD COLSPAN=2>CTS asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD> <TD COLSPAN=2>RTS asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD> <TD COLSPAN=2>DCD asserted</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD> <TD COLSPAN=2>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD> <TD COLSPAN=2>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD> <TD COLSPAN=2>Undefined</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>2</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 1)</TH>
+
+ <TH>&nbsp;</TH> <TH>Tx</TH> <TH>Rx</TH> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD> <TD>Underrun</TD> <TD>Framing</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD> <TD>CTS Lost</TD> <TD>Parity</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD> <TD>UART Error</TD> <TD>Collision</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD> <TD>Re-Tx Limit Reached</TD> <TD>Long Frame</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD> <TD>Undefined</TD> <TD>Short Frame</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD> <TD>Undefined</TD> <TD>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD> <TD>Undefined</TD> <TD>Undefined</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD> <TD>Undefined</TD> <TD>Undefined</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>3</TH>
+ <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=9>Errors<BR>(octet 2)</TH>
+
+ <TH>&nbsp;</TH> <TH>Tx</TH> <TH>Rx</TH> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxxx1</FONT></TD> <TD>Undefined</TD> <TD>Non-Octet Aligned</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxxx1x</FONT></TD> <TD>Undefined</TD> <TD>Abort Received</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxxx1xx</FONT></TD> <TD>Undefined</TD> <TD>CD Lost</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxxx1xxx</FONT></TD> <TD>Undefined</TD> <TD>Digital PLL Error</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xxx1xxxx</FONT></TD> <TD>Undefined</TD> <TD>Overrun</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">xx1xxxxx</FONT></TD> <TD>Undefined</TD> <TD>Frame Length Violation</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">x1xxxxxx</FONT></TD> <TD>Undefined</TD> <TD>CRC Error</TD> </TR>
+ <TR> <TD VALIGN=TOP ALIGN=CENTER><FONT FACE="COURIER">1xxxxxxx</FONT></TD> <TD>Undefined</TD> <TD>Break Received</TD> </TR>
+
+ <TR> <TH VALIGN=TOP ALIGN=CENTER ROWSPAN=12>4</TH>
+ <TH VALIGN=TOP ALIGN=CENTER>Protocol</TH>
+
+ <TD COLSPAN=3>
+ <CENTER>
+ <TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x01</TD> <TD>-</TD> <TD>LAPB (BOP) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x02</TD> <TD>-</TD> <TD>Ethernet <SUP>1</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x03</TD> <TD>-</TD> <TD>Async (Interrupt IO) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x04</TD> <TD>-</TD> <TD>Async (Block IO) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x05</TD> <TD>-</TD> <TD>IPARS <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x06</TD> <TD>-</TD> <TD>UTS <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x07</TD> <TD>-</TD> <TD>PPP (HDLC) <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x08</TD> <TD>-</TD> <TD>SDLC <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x09</TD> <TD>-</TD> <TD>Token Ring <SUP>1</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x10</TD> <TD>-</TD> <TD>I2C <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x11</TD> <TD>-</TD> <TD>DPM Link <SUP>&nbsp;</SUP> </TD> </TR>
+ <TR VALIGN=BOTTOM><TD ALIGN=CENTER>0x12</TD> <TD>-</TD> <TD>Frame Relay (BOP) <SUP>&nbsp;</SUP> </TD> </TR>
+ </TABLE>
+ </CENTER>
+ <P>
+ <STRONG>Note 1:</STRONG>
+ Ethernet and Token Ring frames will never be sent as DLT_SITA (with the 5 octet header),
+ but will be sent as their corresponding DLT types instead.
+ </TD>
+ </TR>
+ </TABLE>
+ </CENTER>
+</UL>
+<P>
+</UL>
+</UL>
diff --git a/lib/libpcap/libpcap/pcap-snf.c b/lib/libpcap/libpcap/pcap-snf.c
new file mode 100644
index 0000000..50d92cd
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-snf.c
@@ -0,0 +1,621 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifndef _WIN32
+#include <sys/param.h>
+#endif /* !_WIN32 */
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <ctype.h>
+#ifndef _WIN32
+#include <netinet/in.h>
+#include <sys/mman.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif /* !_WIN32 */
+
+#include <snf.h>
+#if SNF_VERSION_API >= 0x0003
+#define SNF_HAVE_INJECT_API
+#endif
+
+#include "pcap-int.h"
+#include "pcap-snf.h"
+
+/*
+ * Private data for capturing on SNF devices.
+ */
+struct pcap_snf {
+ snf_handle_t snf_handle; /* opaque device handle */
+ snf_ring_t snf_ring; /* opaque device ring handle */
+#ifdef SNF_HAVE_INJECT_API
+ snf_inject_t snf_inj; /* inject handle, if inject is used */
+#endif
+ int snf_timeout;
+ int snf_boardnum;
+};
+
+static int
+snf_set_datalink(pcap_t *p, int dlt)
+{
+ p->linktype = dlt;
+ return (0);
+}
+
+static int
+snf_pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+ struct snf_ring_stats stats;
+ struct pcap_snf *snfps = p->priv;
+ int rc;
+
+ if ((rc = snf_ring_getstats(snfps->snf_ring, &stats))) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ rc, "snf_get_stats");
+ return -1;
+ }
+ ps->ps_recv = stats.ring_pkt_recv + stats.ring_pkt_overflow;
+ ps->ps_drop = stats.ring_pkt_overflow;
+ ps->ps_ifdrop = stats.nic_pkt_overflow + stats.nic_pkt_bad;
+ return 0;
+}
+
+static void
+snf_platform_cleanup(pcap_t *p)
+{
+ struct pcap_snf *ps = p->priv;
+
+#ifdef SNF_HAVE_INJECT_API
+ if (ps->snf_inj)
+ snf_inject_close(ps->snf_inj);
+#endif
+ snf_ring_close(ps->snf_ring);
+ snf_close(ps->snf_handle);
+ pcap_cleanup_live_common(p);
+}
+
+static int
+snf_getnonblock(pcap_t *p)
+{
+ struct pcap_snf *ps = p->priv;
+
+ return (ps->snf_timeout == 0);
+}
+
+static int
+snf_setnonblock(pcap_t *p, int nonblock)
+{
+ struct pcap_snf *ps = p->priv;
+
+ if (nonblock)
+ ps->snf_timeout = 0;
+ else {
+ if (p->opt.timeout <= 0)
+ ps->snf_timeout = -1; /* forever */
+ else
+ ps->snf_timeout = p->opt.timeout;
+ }
+ return (0);
+}
+
+#define _NSEC_PER_SEC 1000000000
+
+static inline
+struct timeval
+snf_timestamp_to_timeval(const int64_t ts_nanosec, const int tstamp_precision)
+{
+ struct timeval tv;
+ long tv_nsec;
+ const static struct timeval zero_timeval;
+
+ if (ts_nanosec == 0)
+ return zero_timeval;
+
+ tv.tv_sec = ts_nanosec / _NSEC_PER_SEC;
+ tv_nsec = (ts_nanosec % _NSEC_PER_SEC);
+
+ /* libpcap expects tv_usec to be nanos if using nanosecond precision. */
+ if (tstamp_precision == PCAP_TSTAMP_PRECISION_NANO)
+ tv.tv_usec = tv_nsec;
+ else
+ tv.tv_usec = tv_nsec / 1000;
+
+ return tv;
+}
+
+static int
+snf_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_snf *ps = p->priv;
+ struct pcap_pkthdr hdr;
+ int i, flags, err, caplen, n;
+ struct snf_recv_req req;
+ int nonblock, timeout;
+
+ if (!p)
+ return -1;
+
+ n = 0;
+ timeout = ps->snf_timeout;
+ while (n < cnt || PACKET_COUNT_IS_UNLIMITED(cnt)) {
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else {
+ return (n);
+ }
+ }
+
+ err = snf_ring_recv(ps->snf_ring, timeout, &req);
+
+ if (err) {
+ if (err == EBUSY || err == EAGAIN) {
+ return (n);
+ }
+ else if (err == EINTR) {
+ timeout = 0;
+ continue;
+ }
+ else {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, err, "snf_read");
+ return -1;
+ }
+ }
+
+ caplen = req.length;
+ if (caplen > p->snapshot)
+ caplen = p->snapshot;
+
+ if ((p->fcode.bf_insns == NULL) ||
+ bpf_filter(p->fcode.bf_insns, req.pkt_addr, req.length, caplen)) {
+ hdr.ts = snf_timestamp_to_timeval(req.timestamp, p->opt.tstamp_precision);
+ hdr.caplen = caplen;
+ hdr.len = req.length;
+ callback(user, &hdr, req.pkt_addr);
+ n++;
+ }
+
+ /* After one successful packet is received, we won't block
+ * again for that timeout. */
+ if (timeout != 0)
+ timeout = 0;
+ }
+ return (n);
+}
+
+static int
+snf_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+ if (!p)
+ return -1;
+ if (!fp) {
+ strncpy(p->errbuf, "setfilter: No filter specified",
+ sizeof(p->errbuf));
+ return -1;
+ }
+
+ /* Make our private copy of the filter */
+
+ if (install_bpf_program(p, fp) < 0)
+ return -1;
+
+ return (0);
+}
+
+static int
+snf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+#ifdef SNF_HAVE_INJECT_API
+ struct pcap_snf *ps = p->priv;
+ int rc;
+ if (ps->snf_inj == NULL) {
+ rc = snf_inject_open(ps->snf_boardnum, 0, &ps->snf_inj);
+ if (rc) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ rc, "snf_inject_open");
+ return (-1);
+ }
+ }
+
+ rc = snf_inject_send(ps->snf_inj, -1, 0, buf, size);
+ if (!rc) {
+ return (size);
+ }
+ else {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ rc, "snf_inject_send");
+ return (-1);
+ }
+#else
+ pcap_strlcpy(p->errbuf, "Sending packets isn't supported with this snf version",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+#endif
+}
+
+static int
+snf_activate(pcap_t* p)
+{
+ struct pcap_snf *ps = p->priv;
+ char *device = p->opt.device;
+ const char *nr = NULL;
+ int err;
+ int flags = -1, ring_id = -1;
+
+ if (device == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "device is NULL");
+ return -1;
+ }
+
+ /* In Libpcap, we set pshared by default if NUM_RINGS is set to > 1.
+ * Since libpcap isn't thread-safe */
+ if ((nr = getenv("SNF_FLAGS")) && *nr)
+ flags = strtol(nr, NULL, 0);
+ else if ((nr = getenv("SNF_NUM_RINGS")) && *nr && atoi(nr) > 1)
+ flags = SNF_F_PSHARED;
+ else
+ nr = NULL;
+
+
+ /* Allow pcap_set_buffer_size() to set dataring_size.
+ * Default is zero which allows setting from env SNF_DATARING_SIZE.
+ * pcap_set_buffer_size() is in bytes while snf_open() accepts values
+ * between 0 and 1048576 in Megabytes. Values in this range are
+ * mapped to 1MB.
+ */
+ err = snf_open(ps->snf_boardnum,
+ 0, /* let SNF API parse SNF_NUM_RINGS, if set */
+ NULL, /* default RSS, or use SNF_RSS_FLAGS env */
+ (p->opt.buffer_size > 0 && p->opt.buffer_size < 1048576) ? 1048576 : p->opt.buffer_size, /* default to SNF_DATARING_SIZE from env */
+ flags, /* may want pshared */
+ &ps->snf_handle);
+ if (err != 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ err, "snf_open failed");
+ return -1;
+ }
+
+ if ((nr = getenv("SNF_PCAP_RING_ID")) && *nr) {
+ ring_id = (int) strtol(nr, NULL, 0);
+ }
+ err = snf_ring_open_id(ps->snf_handle, ring_id, &ps->snf_ring);
+ if (err != 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ err, "snf_ring_open_id(ring=%d) failed", ring_id);
+ return -1;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ if (p->opt.timeout <= 0)
+ ps->snf_timeout = -1;
+ else
+ ps->snf_timeout = p->opt.timeout;
+
+ err = snf_start(ps->snf_handle);
+ if (err != 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ err, "snf_start failed");
+ return -1;
+ }
+
+ /*
+ * "select()" and "poll()" don't work on snf descriptors.
+ */
+#ifndef _WIN32
+ p->selectable_fd = -1;
+#endif /* !_WIN32 */
+ p->linktype = DLT_EN10MB;
+ p->read_op = snf_read;
+ p->inject_op = snf_inject;
+ p->setfilter_op = snf_setfilter;
+ p->setdirection_op = NULL; /* Not implemented.*/
+ p->set_datalink_op = snf_set_datalink;
+ p->getnonblock_op = snf_getnonblock;
+ p->setnonblock_op = snf_setnonblock;
+ p->stats_op = snf_pcap_stats;
+ p->cleanup_op = snf_platform_cleanup;
+#ifdef SNF_HAVE_INJECT_API
+ ps->snf_inj = NULL;
+#endif
+ return 0;
+}
+
+#define MAX_DESC_LENGTH 128
+int
+snf_findalldevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ pcap_if_t *dev;
+#ifdef _WIN32
+ struct sockaddr_in addr;
+#endif
+ struct snf_ifaddrs *ifaddrs, *ifa;
+ char name[MAX_DESC_LENGTH];
+ char desc[MAX_DESC_LENGTH];
+ int ret, allports = 0, merge = 0;
+ const char *nr = NULL;
+
+ if (snf_init(SNF_VERSION_API)) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "snf_getifaddrs: snf_init failed");
+ return (-1);
+ }
+
+ if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "snf_getifaddrs");
+ return (-1);
+ }
+ if ((nr = getenv("SNF_FLAGS")) && *nr) {
+ errno = 0;
+ merge = strtol(nr, NULL, 0);
+ if (errno) {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "snf_getifaddrs: SNF_FLAGS is not a valid number");
+ return (-1);
+ }
+ merge = merge & SNF_F_AGGREGATE_PORTMASK;
+ }
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->snf_ifa_next) {
+ /*
+ * Myricom SNF adapter ports may appear as regular
+ * network interfaces, which would already have been
+ * added to the list of adapters by pcap_platform_finddevs()
+ * if this isn't an SNF-only version of libpcap.
+ *
+ * Our create routine intercepts pcap_create() calls for
+ * those interfaces and arranges that they will be
+ * opened using the SNF API instead.
+ *
+ * So if we already have an entry for the device, we
+ * don't add an additional entry for it, we just
+ * update the description for it, if any, to indicate
+ * which snfN device it is. Otherwise, we add an entry
+ * for it.
+ *
+ * In either case, if SNF_F_AGGREGATE_PORTMASK is set
+ * in SNF_FLAGS, we add this port to the bitmask
+ * of ports, which we use to generate a device
+ * we can use to capture on all ports.
+ *
+ * Generate the description string. If port aggregation
+ * is set, use 2^{port number} as the unit number,
+ * rather than {port number}.
+ *
+ * XXX - do entries in this list have IP addresses for
+ * the port? If so, should we add them to the
+ * entry for the device, if they're not already in the
+ * list of IP addresses for the device?
+ */
+ (void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom %ssnf%d",
+ merge ? "Merge Bitmask Port " : "",
+ merge ? 1 << ifa->snf_ifa_portnum : ifa->snf_ifa_portnum);
+ /*
+ * Add the port to the bitmask.
+ */
+ if (merge)
+ allports |= 1 << ifa->snf_ifa_portnum;
+ /*
+ * See if there's already an entry for the device
+ * with the name ifa->snf_ifa_name.
+ */
+ dev = find_dev(devlistp, ifa->snf_ifa_name);
+ if (dev != NULL) {
+ /*
+ * Yes. Update its description.
+ */
+ char *desc_str;
+
+ desc_str = strdup(desc);
+ if (desc_str == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "snf_findalldevs strdup");
+ return -1;
+ }
+ free(dev->description);
+ dev->description = desc_str;
+ } else {
+ /*
+ * No. Add an entry for it.
+ *
+ * XXX - is there a notion of "up" or "running",
+ * and can we determine whether something's
+ * plugged into the adapter and set
+ * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+ * PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
+ */
+ dev = add_dev(devlistp, ifa->snf_ifa_name, 0, desc,
+ errbuf);
+ if (dev == NULL)
+ return -1;
+#ifdef _WIN32
+ /*
+ * On Windows, fill in IP# from device name
+ */
+ ret = inet_pton(AF_INET, dev->name, &addr.sin_addr);
+ if (ret == 1) {
+ /*
+ * Successful conversion of device name
+ * to IPv4 address.
+ */
+ addr.sin_family = AF_INET;
+ if (add_addr_to_dev(dev, &addr, sizeof(addr),
+ NULL, 0, NULL, 0, NULL, 0, errbuf) == -1)
+ return -1;
+ } else if (ret == -1) {
+ /*
+ * Error.
+ */
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "sinf_findalldevs inet_pton");
+ return -1;
+ }
+#endif _WIN32
+ }
+ }
+ snf_freeifaddrs(ifaddrs);
+ /*
+ * Create a snfX entry if port aggregation is enabled
+ */
+ if (merge) {
+ /*
+ * Add a new entry with all ports bitmask
+ */
+ (void)pcap_snprintf(name,MAX_DESC_LENGTH,"snf%d",allports);
+ (void)pcap_snprintf(desc,MAX_DESC_LENGTH,"Myricom Merge Bitmask All Ports snf%d",
+ allports);
+ /*
+ * XXX - is there any notion of "up" and "running" that
+ * would apply to this device, given that it handles
+ * multiple ports?
+ *
+ * Presumably, there's no notion of "connected" vs.
+ * "disconnected", as "is this plugged into a network?"
+ * would be a per-port property.
+ */
+ if (add_dev(devlistp, name,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, desc,
+ errbuf) == NULL)
+ return (-1);
+ /*
+ * XXX - should we give it a list of addresses with all
+ * the addresses for all the ports?
+ */
+ }
+
+ return 0;
+}
+
+pcap_t *
+snf_create(const char *device, char *ebuf, int *is_ours)
+{
+ pcap_t *p;
+ int boardnum = -1;
+ struct snf_ifaddrs *ifaddrs, *ifa;
+ size_t devlen;
+ struct pcap_snf *ps;
+
+ if (snf_init(SNF_VERSION_API)) {
+ /* Can't initialize the API, so no SNF devices */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /*
+ * Match a given interface name to our list of interface names, from
+ * which we can obtain the intended board number
+ */
+ if (snf_getifaddrs(&ifaddrs) || ifaddrs == NULL) {
+ /* Can't get SNF addresses */
+ *is_ours = 0;
+ return NULL;
+ }
+ devlen = strlen(device) + 1;
+ ifa = ifaddrs;
+ while (ifa) {
+ if (strncmp(device, ifa->snf_ifa_name, devlen) == 0) {
+ boardnum = ifa->snf_ifa_boardnum;
+ break;
+ }
+ ifa = ifa->snf_ifa_next;
+ }
+ snf_freeifaddrs(ifaddrs);
+
+ if (ifa == NULL) {
+ /*
+ * If we can't find the device by name, support the name "snfX"
+ * and "snf10gX" where X is the board number.
+ */
+ if (sscanf(device, "snf10g%d", &boardnum) != 1 &&
+ sscanf(device, "snf%d", &boardnum) != 1) {
+ /* Nope, not a supported name */
+ *is_ours = 0;
+ return NULL;
+ }
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_snf));
+ if (p == NULL)
+ return NULL;
+ ps = p->priv;
+
+ /*
+ * We support microsecond and nanosecond time stamps.
+ */
+ p->tstamp_precision_count = 2;
+ p->tstamp_precision_list = malloc(2 * sizeof(u_int));
+ if (p->tstamp_precision_list == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno,
+ "malloc");
+ pcap_close(p);
+ return NULL;
+ }
+ p->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
+ p->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
+
+ p->activate_op = snf_activate;
+ ps->snf_boardnum = boardnum;
+ return p;
+}
+
+#ifdef SNF_ONLY
+/*
+ * This libpcap build supports only SNF cards, not regular network
+ * interfaces..
+ */
+
+/*
+ * There are no regular interfaces, just SNF interfaces.
+ */
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ return (0);
+}
+
+/*
+ * Attempts to open a regular interface fail.
+ */
+pcap_t *
+pcap_create_interface(const char *device, char *errbuf)
+{
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "This version of libpcap only supports SNF cards");
+ return NULL;
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING " (SNF-only)");
+}
+#endif
diff --git a/lib/libpcap/libpcap/pcap-snf.h b/lib/libpcap/libpcap/pcap-snf.h
new file mode 100644
index 0000000..ffc64ad
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-snf.h
@@ -0,0 +1,2 @@
+pcap_t *snf_create(const char *, char *, int *);
+int snf_findalldevs(pcap_if_list_t *devlistp, char *errbuf);
diff --git a/lib/libpcap/libpcap/pcap-snit.c b/lib/libpcap/libpcap/pcap-snit.c
new file mode 100644
index 0000000..9c6fbd4
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-snit.c
@@ -0,0 +1,506 @@
+/*
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * Modifications made to accommodate the new SunOS4.0 NIT facility by
+ * Micky Liu, micky@cunixc.cc.columbia.edu, Columbia University in May, 1989.
+ * This module now handles the STREAMS based NIT.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/timeb.h>
+#include <sys/dir.h>
+#include <sys/fcntlcom.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/stropts.h>
+
+#include <net/if.h>
+#include <net/nit.h>
+#include <net/nit_if.h>
+#include <net/nit_pf.h>
+#include <net/nit_buf.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * The chunk size for NIT. This is the amount of buffering
+ * done for read calls.
+ */
+#define CHUNKSIZE (2*1024)
+
+/*
+ * The total buffer space used by NIT.
+ */
+#define BUFSPACE (4*CHUNKSIZE)
+
+/* Forwards */
+static int nit_setflags(int, int, int, char *);
+
+/*
+ * Private data for capturing on STREAMS NIT devices.
+ */
+struct pcap_snit {
+ struct pcap_stat stat;
+};
+
+static int
+pcap_stats_snit(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_snit *psn = p->priv;
+
+ /*
+ * "ps_recv" counts packets handed to the filter, not packets
+ * that passed the filter. As filtering is done in userland,
+ * this does not include packets dropped because we ran out
+ * of buffer space.
+ *
+ * "ps_drop" counts packets dropped inside the "/dev/nit"
+ * device because of flow control requirements or resource
+ * exhaustion; it doesn't count packets dropped by the
+ * interface driver, or packets dropped upstream. As filtering
+ * is done in userland, it counts packets regardless of whether
+ * they would've passed the filter.
+ *
+ * These statistics don't include packets not yet read from the
+ * kernel by libpcap or packets not yet read from libpcap by the
+ * application.
+ */
+ *ps = psn->stat;
+ return (0);
+}
+
+static int
+pcap_read_snit(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_snit *psn = p->priv;
+ register int cc, n;
+ register u_char *bp, *cp, *ep;
+ register struct nit_bufhdr *hdrp;
+ register struct nit_iftime *ntp;
+ register struct nit_iflen *nlp;
+ register struct nit_ifdrops *ndp;
+ register int caplen;
+
+ cc = p->cc;
+ if (cc == 0) {
+ cc = read(p->fd, (char *)p->buffer, p->bufsize);
+ if (cc < 0) {
+ if (errno == EWOULDBLOCK)
+ return (0);
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "pcap_read");
+ return (-1);
+ }
+ bp = (u_char *)p->buffer;
+ } else
+ bp = p->bp;
+
+ /*
+ * loop through each snapshot in the chunk
+ */
+ n = 0;
+ ep = bp + cc;
+ while (bp < ep) {
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else {
+ p->bp = bp;
+ p->cc = ep - bp;
+ return (n);
+ }
+ }
+
+ ++psn->stat.ps_recv;
+ cp = bp;
+
+ /* get past NIT buffer */
+ hdrp = (struct nit_bufhdr *)cp;
+ cp += sizeof(*hdrp);
+
+ /* get past NIT timer */
+ ntp = (struct nit_iftime *)cp;
+ cp += sizeof(*ntp);
+
+ ndp = (struct nit_ifdrops *)cp;
+ psn->stat.ps_drop = ndp->nh_drops;
+ cp += sizeof *ndp;
+
+ /* get past packet len */
+ nlp = (struct nit_iflen *)cp;
+ cp += sizeof(*nlp);
+
+ /* next snapshot */
+ bp += hdrp->nhb_totlen;
+
+ caplen = nlp->nh_pktlen;
+ if (caplen > p->snapshot)
+ caplen = p->snapshot;
+
+ if (bpf_filter(p->fcode.bf_insns, cp, nlp->nh_pktlen, caplen)) {
+ struct pcap_pkthdr h;
+ h.ts = ntp->nh_timestamp;
+ h.len = nlp->nh_pktlen;
+ h.caplen = caplen;
+ (*callback)(user, &h, cp);
+ if (++n >= cnt && !PACKET_COUNT_IS_UNLIMITED(cnt)) {
+ p->cc = ep - bp;
+ p->bp = bp;
+ return (n);
+ }
+ }
+ }
+ p->cc = 0;
+ return (n);
+}
+
+static int
+pcap_inject_snit(pcap_t *p, const void *buf, size_t size)
+{
+ struct strbuf ctl, data;
+
+ /*
+ * XXX - can we just do
+ *
+ ret = write(pd->f, buf, size);
+ */
+ ctl.len = sizeof(*sa); /* XXX - what was this? */
+ ctl.buf = (char *)sa;
+ data.buf = buf;
+ data.len = size;
+ ret = putmsg(p->fd, &ctl, &data);
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
+nit_setflags(pcap_t *p)
+{
+ bpf_u_int32 flags;
+ struct strioctl si;
+ u_int zero = 0;
+ struct timeval timeout;
+
+ if (p->opt.immediate) {
+ /*
+ * Set the chunk size to zero, so that chunks get sent
+ * up immediately.
+ */
+ si.ic_cmd = NIOCSCHUNK;
+ si.ic_len = sizeof(zero);
+ si.ic_dp = (char *)&zero;
+ if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "NIOCSCHUNK");
+ return (-1);
+ }
+ }
+ si.ic_timout = INFTIM;
+ if (p->opt.timeout != 0) {
+ timeout.tv_sec = p->opt.timeout / 1000;
+ timeout.tv_usec = (p->opt.timeout * 1000) % 1000000;
+ si.ic_cmd = NIOCSTIME;
+ si.ic_len = sizeof(timeout);
+ si.ic_dp = (char *)&timeout;
+ if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "NIOCSTIME");
+ return (-1);
+ }
+ }
+ flags = NI_TIMESTAMP | NI_LEN | NI_DROPS;
+ if (p->opt.promisc)
+ flags |= NI_PROMISC;
+ si.ic_cmd = NIOCSFLAGS;
+ si.ic_len = sizeof(flags);
+ si.ic_dp = (char *)&flags;
+ if (ioctl(p->fd, I_STR, (char *)&si) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "NIOCSFLAGS");
+ return (-1);
+ }
+ return (0);
+}
+
+static int
+pcap_activate_snit(pcap_t *p)
+{
+ struct strioctl si; /* struct for ioctl() */
+ struct ifreq ifr; /* interface request struct */
+ int chunksize = CHUNKSIZE;
+ int fd;
+ static const char dev[] = "/dev/nit";
+ int err;
+
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on SunOS 4.x (no Wi-Fi devices on
+ * hardware supported by SunOS 4.x).
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ if (p->snapshot < 96)
+ /*
+ * NIT requires a snapshot length of at least 96.
+ */
+ p->snapshot = 96;
+
+ /*
+ * Initially try a read/write open (to allow the inject
+ * method to work). If that fails due to permission
+ * issues, fall back to read-only. This allows a
+ * non-root user to be granted specific access to pcap
+ * capabilities via file permissions.
+ *
+ * XXX - we should have an API that has a flag that
+ * controls whether to open read-only or read-write,
+ * so that denial of permission to send (or inability
+ * to send, if sending packets isn't supported on
+ * the device in question) can be indicated at open
+ * time.
+ */
+ p->fd = fd = open(dev, O_RDWR);
+ if (fd < 0 && errno == EACCES)
+ p->fd = fd = open(dev, O_RDONLY);
+ if (fd < 0) {
+ if (errno == EACCES)
+ err = PCAP_ERROR_PERM_DENIED;
+ else
+ err = PCAP_ERROR;
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s", dev);
+ goto bad;
+ }
+
+ /* arrange to get discrete messages from the STREAM and use NIT_BUF */
+ if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "I_SRDOPT");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ if (ioctl(fd, I_PUSH, "nbuf") < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "push nbuf");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ /* set the chunksize */
+ si.ic_cmd = NIOCSCHUNK;
+ si.ic_timout = INFTIM;
+ si.ic_len = sizeof(chunksize);
+ si.ic_dp = (char *)&chunksize;
+ if (ioctl(fd, I_STR, (char *)&si) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "NIOCSCHUNK");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+
+ /* request the interface */
+ strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+ ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
+ si.ic_cmd = NIOCBIND;
+ si.ic_len = sizeof(ifr);
+ si.ic_dp = (char *)&ifr;
+ if (ioctl(fd, I_STR, (char *)&si) < 0) {
+ /*
+ * XXX - is there an error that means "no such device"?
+ * Is there one that means "that device doesn't support
+ * STREAMS NIT"?
+ */
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "NIOCBIND: %s", ifr.ifr_name);
+ err = PCAP_ERROR;
+ goto bad;
+ }
+
+ /* set the snapshot length */
+ si.ic_cmd = NIOCSSNAP;
+ si.ic_len = sizeof(p->snapshot);
+ si.ic_dp = (char *)&p->snapshot;
+ if (ioctl(fd, I_STR, (char *)&si) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "NIOCSSNAP");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+ if (nit_setflags(p) < 0) {
+ err = PCAP_ERROR;
+ goto bad;
+ }
+
+ (void)ioctl(fd, I_FLUSH, (char *)FLUSHR);
+ /*
+ * NIT supports only ethernets.
+ */
+ p->linktype = DLT_EN10MB;
+
+ p->bufsize = BUFSPACE;
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ err = PCAP_ERROR;
+ goto bad;
+ }
+
+ /*
+ * "p->fd" is an FD for a STREAMS device, so "select()" and
+ * "poll()" should work on it.
+ */
+ p->selectable_fd = p->fd;
+
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+
+ p->read_op = pcap_read_snit;
+ p->inject_op = pcap_inject_snit;
+ p->setfilter_op = install_bpf_program; /* no kernel filtering */
+ p->setdirection_op = NULL; /* Not implemented. */
+ p->set_datalink_op = NULL; /* can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_stats_snit;
+
+ return (0);
+ bad:
+ pcap_cleanup_live_common(p);
+ return (err);
+}
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_snit));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_snit;
+ return (p);
+}
+
+/*
+ * XXX - there's probably a NIOCBIND error that means "that device
+ * doesn't support NIT"; if so, we should try an NIOCBIND and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+ get_if_flags));
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-snoop.c b/lib/libpcap/libpcap/pcap-snoop.c
new file mode 100644
index 0000000..a598bae
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-snoop.c
@@ -0,0 +1,467 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <sys/param.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <net/raw.h>
+#include <net/if.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/if_ether.h>
+#include <netinet/ip_var.h>
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <netinet/tcp.h>
+#include <netinet/tcpip.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+/*
+ * Private data for capturing on snoop devices.
+ */
+struct pcap_snoop {
+ struct pcap_stat stat;
+};
+
+static int
+pcap_read_snoop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_snoop *psn = p->priv;
+ int cc;
+ register struct snoopheader *sh;
+ register u_int datalen;
+ register u_int caplen;
+ register u_char *cp;
+
+again:
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop) {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return -2 to indicate that we were
+ * told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return (-2);
+ }
+ cc = read(p->fd, (char *)p->buffer, p->bufsize);
+ if (cc < 0) {
+ /* Don't choke when we get ptraced */
+ switch (errno) {
+
+ case EINTR:
+ goto again;
+
+ case EWOULDBLOCK:
+ return (0); /* XXX */
+ }
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "read");
+ return (-1);
+ }
+ sh = (struct snoopheader *)p->buffer;
+ datalen = sh->snoop_packetlen;
+
+ /*
+ * XXX - Sigh, snoop_packetlen is a 16 bit quantity. If we
+ * got a short length, but read a full sized snoop pakcet,
+ * assume we overflowed and add back the 64K...
+ */
+ if (cc == (p->snapshot + sizeof(struct snoopheader)) &&
+ (datalen < p->snapshot))
+ datalen += (64 * 1024);
+
+ caplen = (datalen < p->snapshot) ? datalen : p->snapshot;
+ cp = (u_char *)(sh + 1) + p->offset; /* XXX */
+
+ /*
+ * XXX unfortunately snoop loopback isn't exactly like
+ * BSD's. The address family is encoded in the first 2
+ * bytes rather than the first 4 bytes! Luckily the last
+ * two snoop loopback bytes are zeroed.
+ */
+ if (p->linktype == DLT_NULL && *((short *)(cp + 2)) == 0) {
+ u_int *uip = (u_int *)cp;
+ *uip >>= 16;
+ }
+
+ if (p->fcode.bf_insns == NULL ||
+ bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) {
+ struct pcap_pkthdr h;
+ ++psn->stat.ps_recv;
+ h.ts.tv_sec = sh->snoop_timestamp.tv_sec;
+ h.ts.tv_usec = sh->snoop_timestamp.tv_usec;
+ h.len = datalen;
+ h.caplen = caplen;
+ (*callback)(user, &h, cp);
+ return (1);
+ }
+ return (0);
+}
+
+static int
+pcap_inject_snoop(pcap_t *p, const void *buf, size_t size)
+{
+ int ret;
+
+ /*
+ * XXX - libnet overwrites the source address with what I
+ * presume is the interface's address; is that required?
+ */
+ ret = write(p->fd, buf, size);
+ if (ret == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "send");
+ return (-1);
+ }
+ return (ret);
+}
+
+static int
+pcap_stats_snoop(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_snoop *psn = p->priv;
+ register struct rawstats *rs;
+ struct rawstats rawstats;
+
+ rs = &rawstats;
+ memset(rs, 0, sizeof(*rs));
+ if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "SIOCRAWSTATS");
+ return (-1);
+ }
+
+ /*
+ * "ifdrops" are those dropped by the network interface
+ * due to resource shortages or hardware errors.
+ *
+ * "sbdrops" are those dropped due to socket buffer limits.
+ *
+ * As filter is done in userland, "sbdrops" counts packets
+ * regardless of whether they would've passed the filter.
+ *
+ * XXX - does this count *all* Snoop or Drain sockets,
+ * rather than just this socket? If not, why does it have
+ * both Snoop and Drain statistics?
+ */
+ psn->stat.ps_drop =
+ rs->rs_snoop.ss_ifdrops + rs->rs_snoop.ss_sbdrops +
+ rs->rs_drain.ds_ifdrops + rs->rs_drain.ds_sbdrops;
+
+ /*
+ * "ps_recv" counts only packets that passed the filter.
+ * As filtering is done in userland, this does not include
+ * packets dropped because we ran out of buffer space.
+ */
+ *ps = psn->stat;
+ return (0);
+}
+
+/* XXX can't disable promiscuous */
+static int
+pcap_activate_snoop(pcap_t *p)
+{
+ int fd;
+ struct sockaddr_raw sr;
+ struct snoopfilter sf;
+ u_int v;
+ int ll_hdrlen;
+ int snooplen;
+ struct ifreq ifr;
+
+ fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "snoop socket");
+ goto bad;
+ }
+ p->fd = fd;
+ memset(&sr, 0, sizeof(sr));
+ sr.sr_family = AF_RAW;
+ (void)strncpy(sr.sr_ifname, p->opt.device, sizeof(sr.sr_ifname));
+ if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) {
+ /*
+ * XXX - there's probably a particular bind error that
+ * means "there's no such device" and a particular bind
+ * error that means "that device doesn't support snoop";
+ * they might be the same error, if they both end up
+ * meaning "snoop doesn't know about that device".
+ */
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "snoop bind");
+ goto bad;
+ }
+ memset(&sf, 0, sizeof(sf));
+ if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCADDSNOOP");
+ goto bad;
+ }
+ if (p->opt.buffer_size != 0)
+ v = p->opt.buffer_size;
+ else
+ v = 64 * 1024; /* default to 64K buffer size */
+ (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v));
+ /*
+ * XXX hack - map device name to link layer type
+ */
+ if (strncmp("et", p->opt.device, 2) == 0 || /* Challenge 10 Mbit */
+ strncmp("ec", p->opt.device, 2) == 0 || /* Indigo/Indy 10 Mbit,
+ O2 10/100 */
+ strncmp("ef", p->opt.device, 2) == 0 || /* O200/2000 10/100 Mbit */
+ strncmp("eg", p->opt.device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */
+ strncmp("gfe", p->opt.device, 3) == 0 || /* GIO 100 Mbit */
+ strncmp("fxp", p->opt.device, 3) == 0 || /* Challenge VME Enet */
+ strncmp("ep", p->opt.device, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */
+ strncmp("vfe", p->opt.device, 3) == 0 || /* Challenge VME 100Mbit */
+ strncmp("fa", p->opt.device, 2) == 0 ||
+ strncmp("qaa", p->opt.device, 3) == 0 ||
+ strncmp("cip", p->opt.device, 3) == 0 ||
+ strncmp("el", p->opt.device, 2) == 0) {
+ p->linktype = DLT_EN10MB;
+ p->offset = RAW_HDRPAD(sizeof(struct ether_header));
+ ll_hdrlen = sizeof(struct ether_header);
+ /*
+ * This is (presumably) a real Ethernet capture; give it a
+ * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
+ * that an application can let you choose it, in case you're
+ * capturing DOCSIS traffic that a Cisco Cable Modem
+ * Termination System is putting out onto an Ethernet (it
+ * doesn't put an Ethernet header onto the wire, it puts raw
+ * DOCSIS frames out on the wire inside the low-level
+ * Ethernet framing).
+ *
+ * XXX - are there any sorts of "fake Ethernet" that have
+ * Ethernet link-layer headers but that *shouldn't offer
+ * DLT_DOCSIS as a Cisco CMTS won't put traffic onto it
+ * or get traffic bridged onto it? "el" is for ATM LANE
+ * Ethernet devices, so that might be the case for them;
+ * the same applies for "qaa" classical IP devices. If
+ * "fa" devices are for FORE SPANS, that'd apply to them
+ * as well; what are "cip" devices - some other ATM
+ * Classical IP devices?
+ */
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_DOCSIS;
+ p->dlt_count = 2;
+ }
+ } else if (strncmp("ipg", p->opt.device, 3) == 0 ||
+ strncmp("rns", p->opt.device, 3) == 0 || /* O2/200/2000 FDDI */
+ strncmp("xpi", p->opt.device, 3) == 0) {
+ p->linktype = DLT_FDDI;
+ p->offset = 3; /* XXX yeah? */
+ ll_hdrlen = 13;
+ } else if (strncmp("ppp", p->opt.device, 3) == 0) {
+ p->linktype = DLT_RAW;
+ ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */
+ } else if (strncmp("qfa", p->opt.device, 3) == 0) {
+ p->linktype = DLT_IP_OVER_FC;
+ ll_hdrlen = 24;
+ } else if (strncmp("pl", p->opt.device, 2) == 0) {
+ p->linktype = DLT_RAW;
+ ll_hdrlen = 0; /* Cray UNICOS/mp pseudo link */
+ } else if (strncmp("lo", p->opt.device, 2) == 0) {
+ p->linktype = DLT_NULL;
+ ll_hdrlen = 4;
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "snoop: unknown physical layer type");
+ goto bad;
+ }
+
+ if (p->opt.rfmon) {
+ /*
+ * No monitor mode on Irix (no Wi-Fi devices on
+ * hardware supported by Irix).
+ */
+ return (PCAP_ERROR_RFMON_NOTSUP);
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+#ifdef SIOCGIFMTU
+ /*
+ * XXX - IRIX appears to give you an error if you try to set the
+ * capture length to be greater than the MTU, so let's try to get
+ * the MTU first and, if that succeeds, trim the snap length
+ * to be no greater than the MTU.
+ */
+ (void)strncpy(ifr.ifr_name, p->opt.device, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFMTU");
+ goto bad;
+ }
+ /*
+ * OK, we got it.
+ *
+ * XXX - some versions of IRIX 6.5 define "ifr_mtu" and have an
+ * "ifru_metric" member of the "ifr_ifru" union in an "ifreq"
+ * structure, others don't.
+ *
+ * I've no idea what's going on, so, if "ifr_mtu" isn't defined,
+ * we define it as "ifr_metric", as using that field appears to
+ * work on the versions that lack "ifr_mtu" (and, on those that
+ * don't lack it, "ifru_metric" and "ifru_mtu" are both "int"
+ * members of the "ifr_ifru" union, which suggests that they
+ * may be interchangeable in this case).
+ */
+#ifndef ifr_mtu
+#define ifr_mtu ifr_metric
+#endif
+ if (p->snapshot > ifr.ifr_mtu + ll_hdrlen)
+ p->snapshot = ifr.ifr_mtu + ll_hdrlen;
+#endif
+
+ /*
+ * The argument to SIOCSNOOPLEN is the number of link-layer
+ * payload bytes to capture - it doesn't count link-layer
+ * header bytes.
+ */
+ snooplen = p->snapshot - ll_hdrlen;
+ if (snooplen < 0)
+ snooplen = 0;
+ if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCSNOOPLEN");
+ goto bad;
+ }
+ v = 1;
+ if (ioctl(fd, SIOCSNOOPING, &v) < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCSNOOPING");
+ goto bad;
+ }
+
+ p->bufsize = 4096; /* XXX */
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ goto bad;
+ }
+
+ /*
+ * "p->fd" is a socket, so "select()" should work on it.
+ */
+ p->selectable_fd = p->fd;
+
+ p->read_op = pcap_read_snoop;
+ p->inject_op = pcap_inject_snoop;
+ p->setfilter_op = install_bpf_program; /* no kernel filtering */
+ p->setdirection_op = NULL; /* Not implemented. */
+ p->set_datalink_op = NULL; /* can't change data link type */
+ p->getnonblock_op = pcap_getnonblock_fd;
+ p->setnonblock_op = pcap_setnonblock_fd;
+ p->stats_op = pcap_stats_snoop;
+
+ return (0);
+ bad:
+ pcap_cleanup_live_common(p);
+ return (PCAP_ERROR);
+}
+
+pcap_t *
+pcap_create_interface(const char *device _U_, char *ebuf)
+{
+ pcap_t *p;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_snoop));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = pcap_activate_snoop;
+ return (p);
+}
+
+/*
+ * XXX - there's probably a particular bind error that means "that device
+ * doesn't support snoop"; if so, we should try a bind and use that.
+ */
+static int
+can_be_bound(const char *name _U_)
+{
+ return (1);
+}
+
+static int
+get_if_flags(const char *name _U_, bpf_u_int32 *flags _U_, char *errbuf _U_)
+{
+ /*
+ * Nothing we can do.
+ * XXX - is there a way to find out whether an adapter has
+ * something plugged into it?
+ */
+ return (0);
+}
+
+int
+pcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf)
+{
+ return (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound,
+ get_if_flags));
+}
+
+/*
+ * Libpcap version string.
+ */
+const char *
+pcap_lib_version(void)
+{
+ return (PCAP_VERSION_STRING);
+}
diff --git a/lib/libpcap/libpcap/pcap-tc.c b/lib/libpcap/libpcap/pcap-tc.c
new file mode 100644
index 0000000..65fb0e2
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-tc.c
@@ -0,0 +1,1292 @@
+/*
+ * Copyright (c) 2008 CACE Technologies, Davis (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 CACE Technologies nor the names 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap.h>
+#include <pcap-int.h>
+
+#include "pcap-tc.h"
+
+#include <malloc.h>
+#include <memory.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef _WIN32
+#include <tchar.h>
+#endif
+
+typedef TC_STATUS (TC_CALLCONV *TcFcnQueryPortList) (PTC_PORT *ppPorts, PULONG pLength);
+typedef TC_STATUS (TC_CALLCONV *TcFcnFreePortList) (TC_PORT *pPorts);
+
+typedef PCHAR (TC_CALLCONV *TcFcnStatusGetString) (TC_STATUS status);
+
+typedef PCHAR (TC_CALLCONV *TcFcnPortGetName) (TC_PORT port);
+typedef PCHAR (TC_CALLCONV *TcFcnPortGetDescription) (TC_PORT port);
+
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceOpenByName) (PCHAR name, PTC_INSTANCE pInstance);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceClose) (TC_INSTANCE instance);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceSetFeature) (TC_INSTANCE instance, ULONG feature, ULONG value);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceQueryFeature) (TC_INSTANCE instance, ULONG feature, PULONG pValue);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceReceivePackets) (TC_INSTANCE instance, PTC_PACKETS_BUFFER pBuffer);
+typedef HANDLE (TC_CALLCONV *TcFcnInstanceGetReceiveWaitHandle) (TC_INSTANCE instance);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceTransmitPackets) (TC_INSTANCE instance, TC_PACKETS_BUFFER pBuffer);
+typedef TC_STATUS (TC_CALLCONV *TcFcnInstanceQueryStatistics) (TC_INSTANCE instance, PTC_STATISTICS pStatistics);
+
+typedef TC_STATUS (TC_CALLCONV *TcFcnPacketsBufferCreate) (ULONG size, PTC_PACKETS_BUFFER pBuffer);
+typedef VOID (TC_CALLCONV *TcFcnPacketsBufferDestroy) (TC_PACKETS_BUFFER buffer);
+typedef TC_STATUS (TC_CALLCONV *TcFcnPacketsBufferQueryNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID *ppData);
+typedef TC_STATUS (TC_CALLCONV *TcFcnPacketsBufferCommitNextPacket)(TC_PACKETS_BUFFER buffer, PTC_PACKET_HEADER pHeader, PVOID pData);
+
+typedef VOID (TC_CALLCONV *TcFcnStatisticsDestroy) (TC_STATISTICS statistics);
+typedef TC_STATUS (TC_CALLCONV *TcFcnStatisticsUpdate) (TC_STATISTICS statistics);
+typedef TC_STATUS (TC_CALLCONV *TcFcnStatisticsQueryValue) (TC_STATISTICS statistics, ULONG counterId, PULONGLONG pValue);
+
+typedef enum LONG
+{
+ TC_API_UNLOADED = 0,
+ TC_API_LOADED,
+ TC_API_CANNOT_LOAD,
+ TC_API_LOADING
+}
+ TC_API_LOAD_STATUS;
+
+
+typedef struct _TC_FUNCTIONS
+{
+ TC_API_LOAD_STATUS LoadStatus;
+#ifdef _WIN32
+ HMODULE hTcApiDllHandle;
+#endif
+ TcFcnQueryPortList QueryPortList;
+ TcFcnFreePortList FreePortList;
+ TcFcnStatusGetString StatusGetString;
+
+ TcFcnPortGetName PortGetName;
+ TcFcnPortGetDescription PortGetDescription;
+
+ TcFcnInstanceOpenByName InstanceOpenByName;
+ TcFcnInstanceClose InstanceClose;
+ TcFcnInstanceSetFeature InstanceSetFeature;
+ TcFcnInstanceQueryFeature InstanceQueryFeature;
+ TcFcnInstanceReceivePackets InstanceReceivePackets;
+#ifdef _WIN32
+ TcFcnInstanceGetReceiveWaitHandle InstanceGetReceiveWaitHandle;
+#endif
+ TcFcnInstanceTransmitPackets InstanceTransmitPackets;
+ TcFcnInstanceQueryStatistics InstanceQueryStatistics;
+
+ TcFcnPacketsBufferCreate PacketsBufferCreate;
+ TcFcnPacketsBufferDestroy PacketsBufferDestroy;
+ TcFcnPacketsBufferQueryNextPacket PacketsBufferQueryNextPacket;
+ TcFcnPacketsBufferCommitNextPacket PacketsBufferCommitNextPacket;
+
+ TcFcnStatisticsDestroy StatisticsDestroy;
+ TcFcnStatisticsUpdate StatisticsUpdate;
+ TcFcnStatisticsQueryValue StatisticsQueryValue;
+}
+ TC_FUNCTIONS;
+
+static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port);
+static int TcSetDatalink(pcap_t *p, int dlt);
+static int TcGetNonBlock(pcap_t *p);
+static int TcSetNonBlock(pcap_t *p, int nonblock);
+static void TcCleanup(pcap_t *p);
+static int TcInject(pcap_t *p, const void *buf, int size);
+static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user);
+static int TcStats(pcap_t *p, struct pcap_stat *ps);
+static int TcSetFilter(pcap_t *p, struct bpf_program *fp);
+#ifdef _WIN32
+static struct pcap_stat *TcStatsEx(pcap_t *p, int *pcap_stat_size);
+static int TcSetBuff(pcap_t *p, int dim);
+static int TcSetMode(pcap_t *p, int mode);
+static int TcSetMinToCopy(pcap_t *p, int size);
+static HANDLE TcGetReceiveWaitHandle(pcap_t *p);
+static int TcOidGetRequest(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp);
+static int TcOidSetRequest(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp);
+static u_int TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue, int sync);
+static int TcSetUserBuffer(pcap_t *p, int size);
+static int TcLiveDump(pcap_t *p, char *filename, int maxsize, int maxpacks);
+static int TcLiveDumpEnded(pcap_t *p, int sync);
+static PAirpcapHandle TcGetAirPcapHandle(pcap_t *p);
+#endif
+
+#ifdef _WIN32
+TC_FUNCTIONS g_TcFunctions =
+{
+ TC_API_UNLOADED, /* LoadStatus */
+ NULL, /* hTcApiDllHandle */
+ NULL, /* QueryPortList */
+ NULL, /* FreePortList */
+ NULL, /* StatusGetString */
+ NULL, /* PortGetName */
+ NULL, /* PortGetDescription */
+ NULL, /* InstanceOpenByName */
+ NULL, /* InstanceClose */
+ NULL, /* InstanceSetFeature */
+ NULL, /* InstanceQueryFeature */
+ NULL, /* InstanceReceivePackets */
+ NULL, /* InstanceGetReceiveWaitHandle */
+ NULL, /* InstanceTransmitPackets */
+ NULL, /* InstanceQueryStatistics */
+ NULL, /* PacketsBufferCreate */
+ NULL, /* PacketsBufferDestroy */
+ NULL, /* PacketsBufferQueryNextPacket */
+ NULL, /* PacketsBufferCommitNextPacket */
+ NULL, /* StatisticsDestroy */
+ NULL, /* StatisticsUpdate */
+ NULL /* StatisticsQueryValue */
+};
+#else
+TC_FUNCTIONS g_TcFunctions =
+{
+ TC_API_LOADED, /* LoadStatus */
+ TcQueryPortList,
+ TcFreePortList,
+ TcStatusGetString,
+ TcPortGetName,
+ TcPortGetDescription,
+ TcInstanceOpenByName,
+ TcInstanceClose,
+ TcInstanceSetFeature,
+ TcInstanceQueryFeature,
+ TcInstanceReceivePackets,
+#ifdef _WIN32
+ TcInstanceGetReceiveWaitHandle,
+#endif
+ TcInstanceTransmitPackets,
+ TcInstanceQueryStatistics,
+ TcPacketsBufferCreate,
+ TcPacketsBufferDestroy,
+ TcPacketsBufferQueryNextPacket,
+ TcPacketsBufferCommitNextPacket,
+ TcStatisticsDestroy,
+ TcStatisticsUpdate,
+ TcStatisticsQueryValue,
+};
+#endif
+
+#define MAX_TC_PACKET_SIZE 9500
+
+#pragma pack(push, 1)
+
+#define PPH_PH_FLAG_PADDING ((UCHAR)0x01)
+#define PPH_PH_VERSION ((UCHAR)0x00)
+
+typedef struct _PPI_PACKET_HEADER
+{
+ UCHAR PphVersion;
+ UCHAR PphFlags;
+ USHORT PphLength;
+ ULONG PphDlt;
+}
+ PPI_PACKET_HEADER, *PPPI_PACKET_HEADER;
+
+typedef struct _PPI_FIELD_HEADER
+{
+ USHORT PfhType;
+ USHORT PfhLength;
+}
+ PPI_FIELD_HEADER, *PPPI_FIELD_HEADER;
+
+
+#define PPI_FIELD_TYPE_AGGREGATION_EXTENSION ((UCHAR)0x08)
+
+typedef struct _PPI_FIELD_AGGREGATION_EXTENSION
+{
+ ULONG InterfaceId;
+}
+ PPI_FIELD_AGGREGATION_EXTENSION, *PPPI_FIELD_AGGREGATION_EXTENSION;
+
+
+#define PPI_FIELD_TYPE_802_3_EXTENSION ((UCHAR)0x09)
+
+#define PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT ((ULONG)0x00000001)
+
+typedef struct _PPI_FIELD_802_3_EXTENSION
+{
+ ULONG Flags;
+ ULONG Errors;
+}
+ PPI_FIELD_802_3_EXTENSION, *PPPI_FIELD_802_3_EXTENSION;
+
+typedef struct _PPI_HEADER
+{
+ PPI_PACKET_HEADER PacketHeader;
+ PPI_FIELD_HEADER AggregationFieldHeader;
+ PPI_FIELD_AGGREGATION_EXTENSION AggregationField;
+ PPI_FIELD_HEADER Dot3FieldHeader;
+ PPI_FIELD_802_3_EXTENSION Dot3Field;
+}
+ PPI_HEADER, *PPPI_HEADER;
+#pragma pack(pop)
+
+#ifdef _WIN32
+//
+// This wrapper around loadlibrary appends the system folder (usually c:\windows\system32)
+// to the relative path of the DLL, so that the DLL is always loaded from an absolute path
+// (It's no longer possible to load airpcap.dll from the application folder).
+// This solves the DLL Hijacking issue discovered in August 2010
+// http://blog.metasploit.com/2010/08/exploiting-dll-hijacking-flaws.html
+//
+HMODULE LoadLibrarySafe(LPCTSTR lpFileName)
+{
+ TCHAR path[MAX_PATH];
+ TCHAR fullFileName[MAX_PATH];
+ UINT res;
+ HMODULE hModule = NULL;
+ do
+ {
+ res = GetSystemDirectory(path, MAX_PATH);
+
+ if (res == 0)
+ {
+ //
+ // some bad failure occurred;
+ //
+ break;
+ }
+
+ if (res > MAX_PATH)
+ {
+ //
+ // the buffer was not big enough
+ //
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ break;
+ }
+
+ if (res + 1 + _tcslen(lpFileName) + 1 < MAX_PATH)
+ {
+ memcpy(fullFileName, path, res * sizeof(TCHAR));
+ fullFileName[res] = _T('\\');
+ memcpy(&fullFileName[res + 1], lpFileName, (_tcslen(lpFileName) + 1) * sizeof(TCHAR));
+
+ hModule = LoadLibrary(fullFileName);
+ }
+ else
+ {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ }
+
+ }while(FALSE);
+
+ return hModule;
+}
+
+/*
+ * NOTE: this function should be called by the pcap functions that can theoretically
+ * deal with the Tc library for the first time, namely listing the adapters and
+ * opening one. All the other ones (close, read, write, set parameters) work
+ * on an open instance of TC, so we do not care to call this function
+ */
+TC_API_LOAD_STATUS LoadTcFunctions(void)
+{
+ TC_API_LOAD_STATUS currentStatus;
+
+ do
+ {
+ currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_UNLOADED);
+
+ while(currentStatus == TC_API_LOADING)
+ {
+ currentStatus = InterlockedCompareExchange((LONG*)&g_TcFunctions.LoadStatus, TC_API_LOADING, TC_API_LOADING);
+ Sleep(10);
+ }
+
+ /*
+ * at this point we are either in the LOADED state, unloaded state (i.e. we are the ones loading everything)
+ * or in cannot load
+ */
+ if(currentStatus == TC_API_LOADED)
+ {
+ return TC_API_LOADED;
+ }
+
+ if (currentStatus == TC_API_CANNOT_LOAD)
+ {
+ return TC_API_CANNOT_LOAD;
+ }
+
+ currentStatus = TC_API_CANNOT_LOAD;
+
+ g_TcFunctions.hTcApiDllHandle = LoadLibrarySafe("TcApi.dll");
+ if (g_TcFunctions.hTcApiDllHandle == NULL) break;
+
+ g_TcFunctions.QueryPortList = (TcFcnQueryPortList) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcQueryPortList");
+ g_TcFunctions.FreePortList = (TcFcnFreePortList) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcFreePortList");
+
+ g_TcFunctions.StatusGetString = (TcFcnStatusGetString) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatusGetString");
+
+ g_TcFunctions.PortGetName = (TcFcnPortGetName) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetName");
+ g_TcFunctions.PortGetDescription = (TcFcnPortGetDescription) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPortGetDescription");
+
+ g_TcFunctions.InstanceOpenByName = (TcFcnInstanceOpenByName) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceOpenByName");
+ g_TcFunctions.InstanceClose = (TcFcnInstanceClose) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceClose");
+ g_TcFunctions.InstanceSetFeature = (TcFcnInstanceSetFeature) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceSetFeature");
+ g_TcFunctions.InstanceQueryFeature = (TcFcnInstanceQueryFeature) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryFeature");
+ g_TcFunctions.InstanceReceivePackets = (TcFcnInstanceReceivePackets) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceReceivePackets");
+ g_TcFunctions.InstanceGetReceiveWaitHandle = (TcFcnInstanceGetReceiveWaitHandle)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceGetReceiveWaitHandle");
+ g_TcFunctions.InstanceTransmitPackets = (TcFcnInstanceTransmitPackets)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceTransmitPackets");
+ g_TcFunctions.InstanceQueryStatistics = (TcFcnInstanceQueryStatistics)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcInstanceQueryStatistics");
+
+ g_TcFunctions.PacketsBufferCreate = (TcFcnPacketsBufferCreate) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCreate");
+ g_TcFunctions.PacketsBufferDestroy = (TcFcnPacketsBufferDestroy) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferDestroy");
+ g_TcFunctions.PacketsBufferQueryNextPacket = (TcFcnPacketsBufferQueryNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferQueryNextPacket");
+ g_TcFunctions.PacketsBufferCommitNextPacket = (TcFcnPacketsBufferCommitNextPacket)GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcPacketsBufferCommitNextPacket");
+
+ g_TcFunctions.StatisticsDestroy = (TcFcnStatisticsDestroy) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsDestroy");
+ g_TcFunctions.StatisticsUpdate = (TcFcnStatisticsUpdate) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsUpdate");
+ g_TcFunctions.StatisticsQueryValue = (TcFcnStatisticsQueryValue) GetProcAddress(g_TcFunctions.hTcApiDllHandle, "TcStatisticsQueryValue");
+
+ if ( g_TcFunctions.QueryPortList == NULL
+ || g_TcFunctions.FreePortList == NULL
+ || g_TcFunctions.StatusGetString == NULL
+ || g_TcFunctions.PortGetName == NULL
+ || g_TcFunctions.PortGetDescription == NULL
+ || g_TcFunctions.InstanceOpenByName == NULL
+ || g_TcFunctions.InstanceClose == NULL
+ || g_TcFunctions.InstanceSetFeature == NULL
+ || g_TcFunctions.InstanceQueryFeature == NULL
+ || g_TcFunctions.InstanceReceivePackets == NULL
+ || g_TcFunctions.InstanceGetReceiveWaitHandle == NULL
+ || g_TcFunctions.InstanceTransmitPackets == NULL
+ || g_TcFunctions.InstanceQueryStatistics == NULL
+ || g_TcFunctions.PacketsBufferCreate == NULL
+ || g_TcFunctions.PacketsBufferDestroy == NULL
+ || g_TcFunctions.PacketsBufferQueryNextPacket == NULL
+ || g_TcFunctions.PacketsBufferCommitNextPacket == NULL
+ || g_TcFunctions.StatisticsDestroy == NULL
+ || g_TcFunctions.StatisticsUpdate == NULL
+ || g_TcFunctions.StatisticsQueryValue == NULL
+ )
+ {
+ break;
+ }
+
+ /*
+ * everything got loaded, yay!!
+ */
+ currentStatus = TC_API_LOADED;
+ }while(FALSE);
+
+ if (currentStatus != TC_API_LOADED)
+ {
+ if (g_TcFunctions.hTcApiDllHandle != NULL)
+ {
+ FreeLibrary(g_TcFunctions.hTcApiDllHandle);
+ g_TcFunctions.hTcApiDllHandle = NULL;
+ }
+ }
+
+ InterlockedExchange((LONG*)&g_TcFunctions.LoadStatus, currentStatus);
+
+ return currentStatus;
+}
+#else
+// static linking
+TC_API_LOAD_STATUS LoadTcFunctions(void)
+{
+ return TC_API_LOADED;
+}
+#endif
+
+/*
+ * Private data for capturing on TurboCap devices.
+ */
+struct pcap_tc {
+ TC_INSTANCE TcInstance;
+ TC_PACKETS_BUFFER TcPacketsBuffer;
+ ULONG TcAcceptedCount;
+ u_char *PpiPacket;
+};
+
+int
+TcFindAllDevs(pcap_if_list_t *devlist, char *errbuf)
+{
+ TC_API_LOAD_STATUS loadStatus;
+ ULONG numPorts;
+ PTC_PORT pPorts = NULL;
+ TC_STATUS status;
+ int result = 0;
+ pcap_if_t *dev;
+ ULONG i;
+
+ do
+ {
+ loadStatus = LoadTcFunctions();
+
+ if (loadStatus != TC_API_LOADED)
+ {
+ result = 0;
+ break;
+ }
+
+ /*
+ * enumerate the ports, and add them to the list
+ */
+ status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
+
+ if (status != TC_SUCCESS)
+ {
+ result = 0;
+ break;
+ }
+
+ for (i = 0; i < numPorts; i++)
+ {
+ /*
+ * transform the port into an entry in the list
+ */
+ dev = TcCreatePcapIfFromPort(pPorts[i]);
+
+ if (dev != NULL)
+ add_dev(devlist, dev->name, dev->flags, dev->description, errbuf);
+ }
+
+ if (numPorts > 0)
+ {
+ /*
+ * ignore the result here
+ */
+ status = g_TcFunctions.FreePortList(pPorts);
+ }
+
+ }while(FALSE);
+
+ return result;
+}
+
+static pcap_if_t* TcCreatePcapIfFromPort(TC_PORT port)
+{
+ CHAR *name;
+ CHAR *description;
+ pcap_if_t *newIf = NULL;
+
+ newIf = (pcap_if_t*)malloc(sizeof(*newIf));
+ if (newIf == NULL)
+ {
+ return NULL;
+ }
+
+ memset(newIf, 0, sizeof(*newIf));
+
+ name = g_TcFunctions.PortGetName(port);
+ description = g_TcFunctions.PortGetDescription(port);
+
+ newIf->name = (char*)malloc(strlen(name) + 1);
+ if (newIf->name == NULL)
+ {
+ free(newIf);
+ return NULL;
+ }
+
+ newIf->description = (char*)malloc(strlen(description) + 1);
+ if (newIf->description == NULL)
+ {
+ free(newIf->name);
+ free(newIf);
+ return NULL;
+ }
+
+ strcpy(newIf->name, name);
+ strcpy(newIf->description, description);
+
+ newIf->addresses = NULL;
+ newIf->next = NULL;
+ newIf->flags = 0;
+
+ return newIf;
+
+}
+
+static int
+TcActivate(pcap_t *p)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+ ULONG timeout;
+ PPPI_HEADER pPpiHeader;
+
+ if (p->opt.rfmon)
+ {
+ /*
+ * No monitor mode on Tc cards; they're Ethernet
+ * capture adapters.
+ */
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ pt->PpiPacket = malloc(sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE);
+
+ if (pt->PpiPacket == NULL)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error allocating memory");
+ return PCAP_ERROR;
+ }
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (p->snapshot <= 0 || p->snapshot > MAXIMUM_SNAPLEN)
+ p->snapshot = MAXIMUM_SNAPLEN;
+
+ /*
+ * Initialize the PPI fixed fields
+ */
+ pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
+ pPpiHeader->PacketHeader.PphDlt = DLT_EN10MB;
+ pPpiHeader->PacketHeader.PphLength = sizeof(PPI_HEADER);
+ pPpiHeader->PacketHeader.PphFlags = 0;
+ pPpiHeader->PacketHeader.PphVersion = 0;
+
+ pPpiHeader->AggregationFieldHeader.PfhLength = sizeof(PPI_FIELD_AGGREGATION_EXTENSION);
+ pPpiHeader->AggregationFieldHeader.PfhType = PPI_FIELD_TYPE_AGGREGATION_EXTENSION;
+
+ pPpiHeader->Dot3FieldHeader.PfhLength = sizeof(PPI_FIELD_802_3_EXTENSION);
+ pPpiHeader->Dot3FieldHeader.PfhType = PPI_FIELD_TYPE_802_3_EXTENSION;
+
+ status = g_TcFunctions.InstanceOpenByName(p->opt.device, &pt->TcInstance);
+
+ if (status != TC_SUCCESS)
+ {
+ /* Adapter detected but we are not able to open it. Return failure. */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Error opening TurboCap adapter: %s", g_TcFunctions.StatusGetString(status));
+ return PCAP_ERROR;
+ }
+
+ p->linktype = DLT_EN10MB;
+ p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
+ /*
+ * If that fails, just leave the list empty.
+ */
+ if (p->dlt_list != NULL) {
+ p->dlt_list[0] = DLT_EN10MB;
+ p->dlt_list[1] = DLT_PPI;
+ p->dlt_count = 2;
+ }
+
+ /*
+ * ignore promiscuous mode
+ * p->opt.promisc
+ */
+
+
+ /*
+ * ignore all the buffer sizes
+ */
+
+ /*
+ * enable reception
+ */
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_RX_STATUS, 1);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error enabling reception on a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+ goto bad;
+ }
+
+ /*
+ * enable transmission
+ */
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_TX_STATUS, 1);
+ /*
+ * Ignore the error here.
+ */
+
+ p->inject_op = TcInject;
+ /*
+ * if the timeout is -1, it means immediate return, no timeout
+ * if the timeout is 0, it means INFINITE
+ */
+
+ if (p->opt.timeout == 0)
+ {
+ timeout = 0xFFFFFFFF;
+ }
+ else
+ if (p->opt.timeout < 0)
+ {
+ /*
+ * we insert a minimal timeout here
+ */
+ timeout = 10;
+ }
+ else
+ {
+ timeout = p->opt.timeout;
+ }
+
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_READ_TIMEOUT, timeout);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,"Error setting the read timeout a TurboCap instance: %s", g_TcFunctions.StatusGetString(status));
+ goto bad;
+ }
+
+ p->read_op = TcRead;
+ p->setfilter_op = TcSetFilter;
+ p->setdirection_op = NULL; /* Not implemented. */
+ p->set_datalink_op = TcSetDatalink;
+ p->getnonblock_op = TcGetNonBlock;
+ p->setnonblock_op = TcSetNonBlock;
+ p->stats_op = TcStats;
+#ifdef _WIN32
+ p->stats_ex_op = TcStatsEx;
+ p->setbuff_op = TcSetBuff;
+ p->setmode_op = TcSetMode;
+ p->setmintocopy_op = TcSetMinToCopy;
+ p->getevent_op = TcGetReceiveWaitHandle;
+ p->oid_get_request_op = TcOidGetRequest;
+ p->oid_set_request_op = TcOidSetRequest;
+ p->sendqueue_transmit_op = TcSendqueueTransmit;
+ p->setuserbuffer_op = TcSetUserBuffer;
+ p->live_dump_op = TcLiveDump;
+ p->live_dump_ended_op = TcLiveDumpEnded;
+ p->get_airpcap_handle_op = TcGetAirPcapHandle;
+#else
+ p->selectable_fd = -1;
+#endif
+
+ p->cleanup_op = TcCleanup;
+
+ return 0;
+bad:
+ TcCleanup(p);
+ return PCAP_ERROR;
+}
+
+pcap_t *
+TcCreate(const char *device, char *ebuf, int *is_ours)
+{
+ ULONG numPorts;
+ PTC_PORT pPorts = NULL;
+ TC_STATUS status;
+ int is_tc;
+ ULONG i;
+ pcap_t *p;
+
+ if (LoadTcFunctions() != TC_API_LOADED)
+ {
+ /*
+ * XXX - report this as an error rather than as
+ * "not a TurboCap device"?
+ */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /*
+ * enumerate the ports, and add them to the list
+ */
+ status = g_TcFunctions.QueryPortList(&pPorts, &numPorts);
+
+ if (status != TC_SUCCESS)
+ {
+ /*
+ * XXX - report this as an error rather than as
+ * "not a TurboCap device"?
+ */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ is_tc = FALSE;
+ for (i = 0; i < numPorts; i++)
+ {
+ if (strcmp(g_TcFunctions.PortGetName(pPorts[i]), device) == 0)
+ {
+ is_tc = TRUE;
+ break;
+ }
+ }
+
+ if (numPorts > 0)
+ {
+ /*
+ * ignore the result here
+ */
+ (void)g_TcFunctions.FreePortList(pPorts);
+ }
+
+ if (!is_tc)
+ {
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_tc));
+ if (p == NULL)
+ return NULL;
+
+ p->activate_op = TcActivate;
+ /*
+ * Set these up front, so that, even if our client tries
+ * to set non-blocking mode before we're activated, or
+ * query the state of non-blocking mode, they get an error,
+ * rather than having the non-blocking mode option set
+ * for use later.
+ */
+ p->getnonblock_op = TcGetNonBlock;
+ p->setnonblock_op = TcSetNonBlock;
+ return p;
+}
+
+static int TcSetDatalink(pcap_t *p, int dlt)
+{
+ /*
+ * We don't have to do any work here; pcap_set_datalink() checks
+ * whether the value is in the list of DLT_ values we
+ * supplied, so we don't have to, and, if it is valid, sets
+ * p->linktype to the new value; we don't have to do anything
+ * in hardware, we just use what's in p->linktype.
+ *
+ * We do have to have a routine, however, so that pcap_set_datalink()
+ * doesn't think we don't support setting the link-layer header
+ * type at all.
+ */
+ return 0;
+}
+
+static int TcGetNonBlock(pcap_t *p)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Non-blocking mode isn't supported for TurboCap ports");
+ return -1;
+}
+
+static int TcSetNonBlock(pcap_t *p, int nonblock)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Non-blocking mode isn't supported for TurboCap ports");
+ return -1;
+}
+
+static void TcCleanup(pcap_t *p)
+{
+ struct pcap_tc *pt = p->priv;
+
+ if (pt->TcPacketsBuffer != NULL)
+ {
+ g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
+ pt->TcPacketsBuffer = NULL;
+ }
+ if (pt->TcInstance != NULL)
+ {
+ /*
+ * here we do not check for the error values
+ */
+ g_TcFunctions.InstanceClose(pt->TcInstance);
+ pt->TcInstance = NULL;
+ }
+
+ if (pt->PpiPacket != NULL)
+ {
+ free(pt->PpiPacket);
+ pt->PpiPacket = NULL;
+ }
+
+ pcap_cleanup_live_common(p);
+}
+
+/* Send a packet to the network */
+static int TcInject(pcap_t *p, const void *buf, int size)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+ TC_PACKETS_BUFFER buffer;
+ TC_PACKET_HEADER header;
+
+ if (size >= 0xFFFF)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: the TurboCap API does not support packets larger than 64k");
+ return -1;
+ }
+
+ status = g_TcFunctions.PacketsBufferCreate(sizeof(TC_PACKET_HEADER) + TC_ALIGN_USHORT_TO_64BIT((USHORT)size), &buffer);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCreate failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+
+ /*
+ * we assume that the packet is without the checksum, as common with WinPcap
+ */
+ memset(&header, 0, sizeof(header));
+
+ header.Length = (USHORT)size;
+ header.CapturedLength = header.Length;
+
+ status = g_TcFunctions.PacketsBufferCommitNextPacket(buffer, &header, (PVOID)buf);
+
+ if (status == TC_SUCCESS)
+ {
+ status = g_TcFunctions.InstanceTransmitPackets(pt->TcInstance, buffer);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcInstanceTransmitPackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ }
+ }
+ else
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send error: TcPacketsBufferCommitNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ }
+
+ g_TcFunctions.PacketsBufferDestroy(buffer);
+
+ if (status != TC_SUCCESS)
+ {
+ return -1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static int TcRead(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+ int n = 0;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ */
+ if (p->break_loop)
+ {
+ /*
+ * Yes - clear the flag that indicates that it
+ * has, and return -2 to indicate that we were
+ * told to break out of the loop.
+ */
+ p->break_loop = 0;
+ return -2;
+ }
+
+ if (pt->TcPacketsBuffer == NULL)
+ {
+ status = g_TcFunctions.InstanceReceivePackets(pt->TcInstance, &pt->TcPacketsBuffer);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcInstanceReceivePackets failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+ }
+
+ while (TRUE)
+ {
+ struct pcap_pkthdr hdr;
+ TC_PACKET_HEADER tcHeader;
+ PVOID data;
+ ULONG filterResult;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop)
+ {
+ if (n == 0)
+ {
+ p->break_loop = 0;
+ return -2;
+ }
+ else
+ {
+ return n;
+ }
+ }
+
+ if (pt->TcPacketsBuffer == NULL)
+ {
+ break;
+ }
+
+ status = g_TcFunctions.PacketsBufferQueryNextPacket(pt->TcPacketsBuffer, &tcHeader, &data);
+
+ if (status == TC_ERROR_END_OF_BUFFER)
+ {
+ g_TcFunctions.PacketsBufferDestroy(pt->TcPacketsBuffer);
+ pt->TcPacketsBuffer = NULL;
+ break;
+ }
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error, TcPacketsBufferQueryNextPacket failure: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+
+ /* No underlaying filtering system. We need to filter on our own */
+ if (p->fcode.bf_insns)
+ {
+ filterResult = bpf_filter(p->fcode.bf_insns, data, tcHeader.Length, tcHeader.CapturedLength);
+
+ if (filterResult == 0)
+ {
+ continue;
+ }
+
+ if (filterResult > tcHeader.CapturedLength)
+ {
+ filterResult = tcHeader.CapturedLength;
+ }
+ }
+ else
+ {
+ filterResult = tcHeader.CapturedLength;
+ }
+
+ pt->TcAcceptedCount ++;
+
+ hdr.ts.tv_sec = (bpf_u_int32)(tcHeader.Timestamp / (ULONGLONG)(1000 * 1000 * 1000));
+ hdr.ts.tv_usec = (bpf_u_int32)((tcHeader.Timestamp % (ULONGLONG)(1000 * 1000 * 1000)) / 1000);
+
+ if (p->linktype == DLT_EN10MB)
+ {
+ hdr.caplen = filterResult;
+ hdr.len = tcHeader.Length;
+ (*callback)(user, &hdr, data);
+ }
+ else
+ {
+ PPPI_HEADER pPpiHeader = (PPPI_HEADER)pt->PpiPacket;
+ PVOID data2 = pPpiHeader + 1;
+
+ pPpiHeader->AggregationField.InterfaceId = TC_PH_FLAGS_RX_PORT_ID(tcHeader.Flags);
+ pPpiHeader->Dot3Field.Errors = tcHeader.Errors;
+ if (tcHeader.Flags & TC_PH_FLAGS_CHECKSUM)
+ {
+ pPpiHeader->Dot3Field.Flags = PPI_FLD_802_3_EXT_FLAG_FCS_PRESENT;
+ }
+ else
+ {
+ pPpiHeader->Dot3Field.Flags = 0;
+ }
+
+ if (filterResult <= MAX_TC_PACKET_SIZE)
+ {
+ memcpy(data2, data, filterResult);
+ hdr.caplen = sizeof(PPI_HEADER) + filterResult;
+ hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
+ }
+ else
+ {
+ memcpy(data2, data, MAX_TC_PACKET_SIZE);
+ hdr.caplen = sizeof(PPI_HEADER) + MAX_TC_PACKET_SIZE;
+ hdr.len = sizeof(PPI_HEADER) + tcHeader.Length;
+ }
+
+ (*callback)(user, &hdr, pt->PpiPacket);
+
+ }
+
+ if (++n >= cnt && cnt > 0)
+ {
+ return n;
+ }
+ }
+
+ return n;
+}
+
+static int
+TcStats(pcap_t *p, struct pcap_stat *ps)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATISTICS statistics;
+ TC_STATUS status;
+ ULONGLONG counter;
+ struct pcap_stat s;
+
+ status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+
+ memset(&s, 0, sizeof(s));
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ s.ps_recv = (ULONG)counter;
+ }
+ else
+ {
+ s.ps_recv = 0xFFFFFFFF;
+ }
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return -1;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ s.ps_ifdrop = (ULONG)counter;
+ s.ps_drop = (ULONG)counter;
+ }
+ else
+ {
+ s.ps_ifdrop = 0xFFFFFFFF;
+ s.ps_drop = 0xFFFFFFFF;
+ }
+
+#if defined(_WIN32) && defined(ENABLE_REMOTE)
+ s.ps_capt = pt->TcAcceptedCount;
+#endif
+ *ps = s;
+
+ return 0;
+}
+
+
+/*
+ * We filter at user level, since the kernel driver does't process the packets
+ */
+static int
+TcSetFilter(pcap_t *p, struct bpf_program *fp)
+{
+ if(!fp)
+ {
+ strncpy(p->errbuf, "setfilter: No filter specified", sizeof(p->errbuf));
+ return -1;
+ }
+
+ /* Install a user level filter */
+ if (install_bpf_program(p, fp) < 0)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+#ifdef _WIN32
+static struct pcap_stat *
+TcStatsEx(pcap_t *p, int *pcap_stat_size)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATISTICS statistics;
+ TC_STATUS status;
+ ULONGLONG counter;
+
+ *pcap_stat_size = sizeof (p->stat);
+
+ status = g_TcFunctions.InstanceQueryStatistics(pt->TcInstance, &statistics);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcInstanceQueryStatistics: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return NULL;
+ }
+
+ memset(&p->stat, 0, sizeof(p->stat));
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_TOTAL_RX_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return NULL;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ p->stat.ps_recv = (ULONG)counter;
+ }
+ else
+ {
+ p->stat.ps_recv = 0xFFFFFFFF;
+ }
+
+ status = g_TcFunctions.StatisticsQueryValue(statistics, TC_COUNTER_INSTANCE_RX_DROPPED_PACKETS, &counter);
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error in TcStatisticsQueryValue: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ return NULL;
+ }
+ if (counter <= (ULONGLONG)0xFFFFFFFF)
+ {
+ p->stat.ps_ifdrop = (ULONG)counter;
+ p->stat.ps_drop = (ULONG)counter;
+ }
+ else
+ {
+ p->stat.ps_ifdrop = 0xFFFFFFFF;
+ p->stat.ps_drop = 0xFFFFFFFF;
+ }
+
+#if defined(_WIN32) && defined(ENABLE_REMOTE)
+ p->stat.ps_capt = pt->TcAcceptedCount;
+#endif
+
+ return &p->stat;
+}
+
+/* Set the dimension of the kernel-level capture buffer */
+static int
+TcSetBuff(pcap_t *p, int dim)
+{
+ /*
+ * XXX turbocap has an internal way of managing buffers.
+ * And at the moment it's not configurable, so we just
+ * silently ignore the request to set the buffer.
+ */
+ return 0;
+}
+
+static int
+TcSetMode(pcap_t *p, int mode)
+{
+ if (mode != MODE_CAPT)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mode %u not supported by TurboCap devices. TurboCap only supports capture.", mode);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+TcSetMinToCopy(pcap_t *p, int size)
+{
+ struct pcap_tc *pt = p->priv;
+ TC_STATUS status;
+
+ if (size < 0)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Mintocopy cannot be less than 0.");
+ return -1;
+ }
+
+ status = g_TcFunctions.InstanceSetFeature(pt->TcInstance, TC_INST_FT_MINTOCOPY, (ULONG)size);
+
+ if (status != TC_SUCCESS)
+ {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "TurboCap error setting the mintocopy: %s (%08x)", g_TcFunctions.StatusGetString(status), status);
+ }
+
+ return 0;
+}
+
+static HANDLE
+TcGetReceiveWaitHandle(pcap_t *p)
+{
+ struct pcap_tc *pt = p->priv;
+
+ return g_TcFunctions.InstanceGetReceiveWaitHandle(pt->TcInstance);
+}
+
+static int
+TcOidGetRequest(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_, size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID get request cannot be performed on a TurboCap device");
+ return PCAP_ERROR;
+}
+
+static int
+TcOidSetRequest(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID set request cannot be performed on a TurboCap device");
+ return PCAP_ERROR;
+}
+
+static u_int
+TcSendqueueTransmit(pcap_t *p, pcap_send_queue *queue _U_, int sync _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packets cannot be bulk transmitted on a TurboCap device");
+ return 0;
+}
+
+static int
+TcSetUserBuffer(pcap_t *p, int size _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The user buffer cannot be set on a TurboCap device");
+ return -1;
+}
+
+static int
+TcLiveDump(pcap_t *p, char *filename _U_, int maxsize _U_, int maxpacks _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a TurboCap device");
+ return -1;
+}
+
+static int
+TcLiveDumpEnded(pcap_t *p, int sync _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a TurboCap device");
+ return -1;
+}
+
+static PAirpcapHandle
+TcGetAirPcapHandle(pcap_t *p _U_)
+{
+ return NULL;
+}
+#endif
diff --git a/lib/libpcap/libpcap/pcap-tc.h b/lib/libpcap/libpcap/pcap-tc.h
new file mode 100644
index 0000000..f7b2d12
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-tc.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2008 CACE Technologies, Davis (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 CACE Technologies nor the names 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.
+ *
+ */
+
+#ifndef __PCAP_TC_H__
+#define __PCAP_TC_H__
+
+/*
+ * needed because gcc headers do not have C_ASSERT
+ */
+#ifndef C_ASSERT
+#define C_ASSERT(a)
+#endif
+
+#include <TcApi.h>
+
+/*
+ * functions used effectively by the pcap library
+ */
+
+pcap_t *
+TcCreate(const char *device, char *ebuf, int *is_ours);
+
+int
+TcFindAllDevs(pcap_if_list_t *devlistp, char *errbuf);
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap-tstamp.manmisc b/lib/libpcap/libpcap/pcap-tstamp.manmisc
new file mode 100644
index 0000000..22e0317
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-tstamp.manmisc
@@ -0,0 +1,168 @@
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-TSTAMP 7 "8 March 2015"
+.SH NAME
+pcap-tstamp \- packet time stamps in libpcap
+.SH DESCRIPTION
+When capturing traffic, each packet is given a time stamp representing,
+for incoming packets, the arrival time of the packet and, for outgoing
+packets, the transmission time of the packet. This time is an
+approximation of the arrival or transmission time. If it is supplied by
+the operating system running on the host on which the capture is being
+done, there are several reasons why it might not precisely represent the
+arrival or transmission time:
+.IP
+if the time stamp is applied to the packet when the networking stack
+receives the packet, the networking stack might not see the packet until
+an interrupt is delivered for the packet or a timer event causes the
+networking device driver to poll for packets, and the time stamp might
+not be applied until the packet has had some processing done by other
+code in the networking stack, so there might be a significant delay
+between the time when the last bit of the packet is received by the
+capture device and when the networking stack time-stamps the packet;
+.IP
+the timer used to generate the time stamps might have low resolution,
+for example, it might be a timer updated once per host operating system
+timer tick, with the host operating system timer ticking once every few
+milliseconds;
+.IP
+a high-resolution timer might use a counter that runs at a rate
+dependent on the processor clock speed, and that clock speed might be
+adjusted upwards or downwards over time and the timer might not be able
+to compensate for all those adjustments;
+.IP
+the host operating system's clock might be adjusted over time to match a
+time standard to which the host is being synchronized, which might be
+done by temporarily slowing down or speeding up the clock or by making a
+single adjustment;
+.IP
+different CPU cores on a multi-core or multi-processor system might be
+running at different speeds, or might not have time counters all
+synchronized, so packets time-stamped by different cores might not have
+consistent time stamps.
+.LP
+In addition, packets time-stamped by different cores might be
+time-stamped in one order and added to the queue of packets for libpcap
+to read in another order, so time stamps might not be monotonically
+increasing.
+.LP
+Some capture devices on some platforms can provide time stamps for
+packets; those time stamps are usually high-resolution time stamps, and
+are usually applied to the packet when the first or last bit of the
+packet arrives, and are thus more accurate than time stamps provided by
+the host operating system. Those time stamps might not, however, be
+synchronized with the host operating system's clock, so that, for
+example, the time stamp of a packet might not correspond to the time
+stamp of an event on the host triggered by the arrival of that packet.
+.LP
+Depending on the capture device and the software on the host, libpcap
+might allow different types of time stamp to be used. The
+.BR pcap_list_tstamp_types (3PCAP)
+routine provides, for a packet capture handle created by
+.BR pcap_create (3PCAP)
+but not yet activated by
+.BR pcap_activate (3PCAP),
+a list of time stamp types supported by the capture device for that
+handle.
+The list might be empty, in which case no choice of time stamp type is
+offered for that capture device. If the list is not empty, the
+.BR pcap_set_tstamp_type (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and before a
+.B pcap_activate()
+call to specify the type of time stamp to be used on the device.
+The time stamp types are listed here; the first value is the #define to
+use in code, the second value is the value returned by
+.B pcap_tstamp_type_val_to_name(3PCAP)
+and accepted by
+.BR pcap_tstamp_type_name_to_val(3PCAP) .
+.RS 5
+.TP 5
+.BR PCAP_TSTAMP_HOST " - " host
+Time stamp provided by the host on which the capture is being done. The
+precision of this time stamp is unspecified; it might or might not be
+synchronized with the host operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_LOWPREC " - " host_lowprec
+Time stamp provided by the host on which the capture is being done.
+This is a low-precision time stamp, synchronized with the host operating
+system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_HIPREC " - " host_hiprec
+Time stamp provided by the host on which the capture is being done.
+This is a high-precision time stamp; it might or might not be
+synchronized with the host operating system's clock. It might be more
+expensive to fetch than
+.BR PCAP_TSTAMP_HOST_LOWPREC .
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER " - " adapter
+Time stamp provided by the network adapter on which the capture is being
+done. This is a high-precision time stamp, synchronized with the host
+operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER_UNSYNCED " - " adapter_unsynced
+Time stamp provided by the network adapter on which the capture is being
+done. This is a high-precision time stamp; it is not synchronized with
+the host operating system's clock.
+.RE
+.LP
+By default, when performing a live capture or reading from a savefile,
+time stamps are supplied as seconds since January 1, 1970, 00:00:00 UTC,
+and microseconds since that seconds value, even if higher-resolution
+time stamps are available from the capture device or in the savefile.
+If, when reading a savefile, the time stamps in the file have a higher
+resolution than one microsecond, the additional digits of resolution are
+discarded.
+.LP
+The
+.BR pcap_set_tstamp_precision (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and after a
+.B pcap_activate()
+call to specify the resolution of the time stamps to get for the device.
+If the hardware or software cannot supply a higher-resolution time
+stamp, the
+.B pcap_set_tstamp_precision()
+call will fail, and the time stamps supplied after the
+.B pcap_activate()
+call will have microsecond resolution.
+.LP
+When opening a savefile, the
+.BR \%pcap_open_offline_with_tstamp_precision (3PCAP)
+and
+.BR \%pcap_fopen_offline_with_tstamp_precision (3PCAP)
+routines can be used to specify the resolution of time stamps to be read
+from the file; if the time stamps in the file have a lower resolution,
+the fraction-of-a-second portion of the time stamps will be scaled to
+the specified resolution.
+.LP
+The
+.BR pcap_get_tstamp_precision (3PCAP)
+routine returns the resolution of time stamps that will be supplied;
+when capturing packets, this does not reflect the actual precision of
+the time stamp supplied by the hardware or operating system and, when
+reading a savefile, this does not indicate the actual precision of time
+stamps in the file.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap-tstamp.manmisc.in b/lib/libpcap/libpcap/pcap-tstamp.manmisc.in
new file mode 100644
index 0000000..6437e80
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-tstamp.manmisc.in
@@ -0,0 +1,168 @@
+.\"
+.\" Copyright (c) 1987, 1988, 1989, 1990, 1991, 1992, 1994, 1995, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP-TSTAMP @MAN_MISC_INFO@ "8 March 2015"
+.SH NAME
+pcap-tstamp \- packet time stamps in libpcap
+.SH DESCRIPTION
+When capturing traffic, each packet is given a time stamp representing,
+for incoming packets, the arrival time of the packet and, for outgoing
+packets, the transmission time of the packet. This time is an
+approximation of the arrival or transmission time. If it is supplied by
+the operating system running on the host on which the capture is being
+done, there are several reasons why it might not precisely represent the
+arrival or transmission time:
+.IP
+if the time stamp is applied to the packet when the networking stack
+receives the packet, the networking stack might not see the packet until
+an interrupt is delivered for the packet or a timer event causes the
+networking device driver to poll for packets, and the time stamp might
+not be applied until the packet has had some processing done by other
+code in the networking stack, so there might be a significant delay
+between the time when the last bit of the packet is received by the
+capture device and when the networking stack time-stamps the packet;
+.IP
+the timer used to generate the time stamps might have low resolution,
+for example, it might be a timer updated once per host operating system
+timer tick, with the host operating system timer ticking once every few
+milliseconds;
+.IP
+a high-resolution timer might use a counter that runs at a rate
+dependent on the processor clock speed, and that clock speed might be
+adjusted upwards or downwards over time and the timer might not be able
+to compensate for all those adjustments;
+.IP
+the host operating system's clock might be adjusted over time to match a
+time standard to which the host is being synchronized, which might be
+done by temporarily slowing down or speeding up the clock or by making a
+single adjustment;
+.IP
+different CPU cores on a multi-core or multi-processor system might be
+running at different speeds, or might not have time counters all
+synchronized, so packets time-stamped by different cores might not have
+consistent time stamps.
+.LP
+In addition, packets time-stamped by different cores might be
+time-stamped in one order and added to the queue of packets for libpcap
+to read in another order, so time stamps might not be monotonically
+increasing.
+.LP
+Some capture devices on some platforms can provide time stamps for
+packets; those time stamps are usually high-resolution time stamps, and
+are usually applied to the packet when the first or last bit of the
+packet arrives, and are thus more accurate than time stamps provided by
+the host operating system. Those time stamps might not, however, be
+synchronized with the host operating system's clock, so that, for
+example, the time stamp of a packet might not correspond to the time
+stamp of an event on the host triggered by the arrival of that packet.
+.LP
+Depending on the capture device and the software on the host, libpcap
+might allow different types of time stamp to be used. The
+.BR pcap_list_tstamp_types (3PCAP)
+routine provides, for a packet capture handle created by
+.BR pcap_create (3PCAP)
+but not yet activated by
+.BR pcap_activate (3PCAP),
+a list of time stamp types supported by the capture device for that
+handle.
+The list might be empty, in which case no choice of time stamp type is
+offered for that capture device. If the list is not empty, the
+.BR pcap_set_tstamp_type (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and before a
+.B pcap_activate()
+call to specify the type of time stamp to be used on the device.
+The time stamp types are listed here; the first value is the #define to
+use in code, the second value is the value returned by
+.B pcap_tstamp_type_val_to_name(3PCAP)
+and accepted by
+.BR pcap_tstamp_type_name_to_val(3PCAP) .
+.RS 5
+.TP 5
+.BR PCAP_TSTAMP_HOST " - " host
+Time stamp provided by the host on which the capture is being done. The
+precision of this time stamp is unspecified; it might or might not be
+synchronized with the host operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_LOWPREC " - " host_lowprec
+Time stamp provided by the host on which the capture is being done.
+This is a low-precision time stamp, synchronized with the host operating
+system's clock.
+.TP 5
+.BR PCAP_TSTAMP_HOST_HIPREC " - " host_hiprec
+Time stamp provided by the host on which the capture is being done.
+This is a high-precision time stamp; it might or might not be
+synchronized with the host operating system's clock. It might be more
+expensive to fetch than
+.BR PCAP_TSTAMP_HOST_LOWPREC .
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER " - " adapter
+Time stamp provided by the network adapter on which the capture is being
+done. This is a high-precision time stamp, synchronized with the host
+operating system's clock.
+.TP 5
+.BR PCAP_TSTAMP_ADAPTER_UNSYNCED " - " adapter_unsynced
+Time stamp provided by the network adapter on which the capture is being
+done. This is a high-precision time stamp; it is not synchronized with
+the host operating system's clock.
+.RE
+.LP
+By default, when performing a live capture or reading from a savefile,
+time stamps are supplied as seconds since January 1, 1970, 00:00:00 UTC,
+and microseconds since that seconds value, even if higher-resolution
+time stamps are available from the capture device or in the savefile.
+If, when reading a savefile, the time stamps in the file have a higher
+resolution than one microsecond, the additional digits of resolution are
+discarded.
+.LP
+The
+.BR pcap_set_tstamp_precision (3PCAP)
+routine can be used after a
+.B pcap_create()
+call and after a
+.B pcap_activate()
+call to specify the resolution of the time stamps to get for the device.
+If the hardware or software cannot supply a higher-resolution time
+stamp, the
+.B pcap_set_tstamp_precision()
+call will fail, and the time stamps supplied after the
+.B pcap_activate()
+call will have microsecond resolution.
+.LP
+When opening a savefile, the
+.BR \%pcap_open_offline_with_tstamp_precision (3PCAP)
+and
+.BR \%pcap_fopen_offline_with_tstamp_precision (3PCAP)
+routines can be used to specify the resolution of time stamps to be read
+from the file; if the time stamps in the file have a lower resolution,
+the fraction-of-a-second portion of the time stamps will be scaled to
+the specified resolution.
+.LP
+The
+.BR pcap_get_tstamp_precision (3PCAP)
+routine returns the resolution of time stamps that will be supplied;
+when capturing packets, this does not reflect the actual precision of
+the time stamp supplied by the hardware or operating system and, when
+reading a savefile, this does not indicate the actual precision of time
+stamps in the file.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap-types.h b/lib/libpcap/libpcap/pcap-types.h
new file mode 100644
index 0000000..9614f9f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-types.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (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 Politecnico di Torino nor the names 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.
+ */
+#ifndef pcap_types_h
+#define pcap_types_h
+
+/*
+ * Get u_int defined, by hook or by crook.
+ */
+#ifdef _WIN32
+
+ /*
+ * This defines u_int.
+ */
+ #include <winsock2.h>
+#else /* _WIN32 */
+ /*
+ * This defines u_int, among other types.
+ */
+ #include <sys/types.h>
+#endif
+
+#endif /* pcap_types_h */
diff --git a/lib/libpcap/libpcap/pcap-usb-linux.c b/lib/libpcap/libpcap/pcap-usb-linux.c
new file mode 100644
index 0000000..b306dca
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-usb-linux.c
@@ -0,0 +1,1363 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * USB sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ * Modifications: Kris Katterjohn <katterjohn@gmail.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "pcap-int.h"
+#include "pcap-usb-linux.h"
+#include "pcap/usb.h"
+
+#ifdef NEED_STRERROR_H
+#include "strerror.h"
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <string.h>
+#include <dirent.h>
+#include <byteswap.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/utsname.h>
+#ifdef HAVE_LINUX_USBDEVICE_FS_H
+/*
+ * We might need <linux/compiler.h> to define __user for
+ * <linux/usbdevice_fs.h>.
+ */
+#ifdef HAVE_LINUX_COMPILER_H
+#include <linux/compiler.h>
+#endif /* HAVE_LINUX_COMPILER_H */
+#include <linux/usbdevice_fs.h>
+#endif /* HAVE_LINUX_USBDEVICE_FS_H */
+
+#define USB_IFACE "usbmon"
+#define USB_TEXT_DIR_OLD "/sys/kernel/debug/usbmon"
+#define USB_TEXT_DIR "/sys/kernel/debug/usb/usbmon"
+#define SYS_USB_BUS_DIR "/sys/bus/usb/devices"
+#define PROC_USB_BUS_DIR "/proc/bus/usb"
+#define USB_LINE_LEN 4096
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define htols(s) s
+#define htoll(l) l
+#define htol64(ll) ll
+#else
+#define htols(s) bswap_16(s)
+#define htoll(l) bswap_32(l)
+#define htol64(ll) bswap_64(ll)
+#endif
+
+struct mon_bin_stats {
+ uint32_t queued;
+ uint32_t dropped;
+};
+
+struct mon_bin_get {
+ pcap_usb_header *hdr;
+ void *data;
+ size_t data_len; /* Length of data (can be zero) */
+};
+
+struct mon_bin_mfetch {
+ int32_t *offvec; /* Vector of events fetched */
+ int32_t nfetch; /* Number of events to fetch (out: fetched) */
+ int32_t nflush; /* Number of events to flush */
+};
+
+#define MON_IOC_MAGIC 0x92
+
+#define MON_IOCQ_URB_LEN _IO(MON_IOC_MAGIC, 1)
+#define MON_IOCX_URB _IOWR(MON_IOC_MAGIC, 2, struct mon_bin_hdr)
+#define MON_IOCG_STATS _IOR(MON_IOC_MAGIC, 3, struct mon_bin_stats)
+#define MON_IOCT_RING_SIZE _IO(MON_IOC_MAGIC, 4)
+#define MON_IOCQ_RING_SIZE _IO(MON_IOC_MAGIC, 5)
+#define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get)
+#define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch)
+#define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8)
+
+#define MON_BIN_SETUP 0x1 /* setup hdr is present*/
+#define MON_BIN_SETUP_ZERO 0x2 /* setup buffer is not available */
+#define MON_BIN_DATA_ZERO 0x4 /* data buffer is not available */
+#define MON_BIN_ERROR 0x8
+
+/*
+ * Private data for capturing on Linux USB.
+ */
+struct pcap_usb_linux {
+ u_char *mmapbuf; /* memory-mapped region pointer */
+ size_t mmapbuflen; /* size of region */
+ int bus_index;
+ u_int packets_read;
+};
+
+/* forward declaration */
+static int usb_activate(pcap_t *);
+static int usb_stats_linux(pcap_t *, struct pcap_stat *);
+static int usb_stats_linux_bin(pcap_t *, struct pcap_stat *);
+static int usb_read_linux(pcap_t *, int , pcap_handler , u_char *);
+static int usb_read_linux_bin(pcap_t *, int , pcap_handler , u_char *);
+static int usb_read_linux_mmap(pcap_t *, int , pcap_handler , u_char *);
+static int usb_inject_linux(pcap_t *, const void *, size_t);
+static int usb_setdirection_linux(pcap_t *, pcap_direction_t);
+static void usb_cleanup_linux_mmap(pcap_t *);
+
+static int
+have_binary_usbmon(void)
+{
+ struct utsname utsname;
+ char *version_component, *endp;
+ int major, minor, subminor;
+
+ if (uname(&utsname) == 0) {
+ /*
+ * 2.6.21 is the first release with the binary-mode
+ * USB monitoring.
+ */
+ version_component = utsname.release;
+ major = strtol(version_component, &endp, 10);
+ if (endp != version_component && *endp == '.') {
+ /*
+ * OK, that was a valid major version.
+ * Is it 3 or greater? If so, we have binary
+ * mode support.
+ */
+ if (major >= 3)
+ return 1;
+
+ /*
+ * Is it 1 or less? If so, we don't have binary
+ * mode support. (In fact, we don't have any
+ * USB monitoring....)
+ */
+ if (major <= 1)
+ return 0;
+ }
+
+ /*
+ * OK, this is a 2.x kernel.
+ * What's the minor version?
+ */
+ version_component = endp + 1;
+ minor = strtol(version_component, &endp, 10);
+ if (endp != version_component &&
+ (*endp == '.' || *endp == '\0')) {
+ /*
+ * OK, that was a valid minor version.
+ * Is is 2.6 or later? (There shouldn't be a
+ * "later", as 2.6.x went to 3.x, but we'll
+ * check anyway.)
+ */
+ if (minor < 6) {
+ /*
+ * No, so no binary support (did 2.4 have
+ * any USB monitoring at all?)
+ */
+ return 0;
+ }
+
+ /*
+ * OK, this is a 2.6.x kernel.
+ * What's the subminor version?
+ */
+ version_component = endp + 1;
+ subminor = strtol(version_component, &endp, 10);
+ if (endp != version_component &&
+ (*endp == '.' || *endp == '\0')) {
+ /*
+ * OK, that was a valid subminor version.
+ * Is it 21 or greater?
+ */
+ if (subminor >= 21) {
+ /*
+ * Yes - we have binary mode
+ * support.
+ */
+ return 1;
+ }
+ }
+ }
+ }
+
+ /*
+ * Either uname() failed, in which case we just say "no binary
+ * mode support", or we don't have binary mode support.
+ */
+ return 0;
+}
+
+/* facility to add an USB device to the device list*/
+static int
+usb_dev_add(pcap_if_list_t *devlistp, int n, char *err_str)
+{
+ char dev_name[10];
+ char dev_descr[30];
+ pcap_snprintf(dev_name, 10, USB_IFACE"%d", n);
+ /*
+ * XXX - is there any notion of "up" and "running"?
+ */
+ if (n == 0) {
+ /*
+ * As this refers to all buses, there's no notion of
+ * "connected" vs. "disconnected", as that's a property
+ * that would apply to a particular USB interface.
+ */
+ if (add_dev(devlistp, dev_name,
+ PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE,
+ "Raw USB traffic, all USB buses", err_str) == NULL)
+ return -1;
+ } else {
+ /*
+ * XXX - is there a way to determine whether anything's
+ * plugged into this bus interface or not, and set
+ * PCAP_IF_CONNECTION_STATUS_CONNECTED or
+ * PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
+ */
+ pcap_snprintf(dev_descr, 30, "Raw USB traffic, bus number %d", n);
+ if (add_dev(devlistp, dev_name, 0, dev_descr, err_str) == NULL)
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+usb_findalldevs(pcap_if_list_t *devlistp, char *err_str)
+{
+ char usb_mon_dir[PATH_MAX];
+ char *usb_mon_prefix;
+ size_t usb_mon_prefix_len;
+ struct dirent* data;
+ int ret = 0;
+ DIR* dir;
+ int n;
+ char* name;
+ size_t len;
+
+ if (have_binary_usbmon()) {
+ /*
+ * We have binary-mode support.
+ * What do the device names look like?
+ * Split LINUX_USB_MON_DEV into a directory that we'll
+ * scan and a file name prefix that we'll check for.
+ */
+ pcap_strlcpy(usb_mon_dir, LINUX_USB_MON_DEV, sizeof usb_mon_dir);
+ usb_mon_prefix = strrchr(usb_mon_dir, '/');
+ if (usb_mon_prefix == NULL) {
+ /*
+ * This "shouldn't happen". Just give up if it
+ * does.
+ */
+ return 0;
+ }
+ *usb_mon_prefix++ = '\0';
+ usb_mon_prefix_len = strlen(usb_mon_prefix);
+
+ /*
+ * Open the directory and scan it.
+ */
+ dir = opendir(usb_mon_dir);
+ if (dir != NULL) {
+ while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+ name = data->d_name;
+
+ /*
+ * Is this a usbmon device?
+ */
+ if (strncmp(name, usb_mon_prefix, usb_mon_prefix_len) != 0)
+ continue; /* no */
+
+ /*
+ * What's the device number?
+ */
+ if (sscanf(&name[usb_mon_prefix_len], "%d", &n) == 0)
+ continue; /* failed */
+
+ ret = usb_dev_add(devlistp, n, err_str);
+ }
+
+ closedir(dir);
+ }
+ return 0;
+ } else {
+ /*
+ * We have only text mode support.
+ * We don't look for the text devices because we can't
+ * look for them without root privileges, and we don't
+ * want to require root privileges to enumerate devices
+ * (we want to let the user to try a device and get
+ * an error, rather than seeing no devices and asking
+ * "why am I not seeing devices" and forcing a long
+ * process of poking to figure out whether it's "no
+ * privileges" or "your kernel is too old" or "the
+ * usbmon module isn't loaded" or...).
+ *
+ * Instead, we look to see what buses we have.
+ * If the kernel is so old that it doesn't have
+ * binary-mode support, it's also so old that
+ * it doesn't have a "scan all buses" device.
+ *
+ * First, try scanning sysfs USB bus directory.
+ */
+ dir = opendir(SYS_USB_BUS_DIR);
+ if (dir != NULL) {
+ while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+ name = data->d_name;
+
+ if (strncmp(name, "usb", 3) != 0)
+ continue;
+
+ if (sscanf(&name[3], "%d", &n) == 0)
+ continue;
+
+ ret = usb_dev_add(devlistp, n, err_str);
+ }
+
+ closedir(dir);
+ return 0;
+ }
+
+ /* That didn't work; try scanning procfs USB bus directory. */
+ dir = opendir(PROC_USB_BUS_DIR);
+ if (dir != NULL) {
+ while ((ret == 0) && ((data = readdir(dir)) != 0)) {
+ name = data->d_name;
+ len = strlen(name);
+
+ /* if this file name does not end with a number it's not of our interest */
+ if ((len < 1) || !isdigit(name[--len]))
+ continue;
+ while (isdigit(name[--len]));
+ if (sscanf(&name[len+1], "%d", &n) != 1)
+ continue;
+
+ ret = usb_dev_add(devlistp, n, err_str);
+ }
+
+ closedir(dir);
+ return ret;
+ }
+
+ /* neither of them worked */
+ return 0;
+ }
+}
+
+/*
+ * Matches what's in mon_bin.c in the Linux kernel.
+ */
+#define MIN_RING_SIZE (8*1024)
+#define MAX_RING_SIZE (1200*1024)
+
+static int
+usb_set_ring_size(pcap_t* handle, int header_size)
+{
+ /*
+ * A packet from binary usbmon has:
+ *
+ * 1) a fixed-length header, of size header_size;
+ * 2) descriptors, for isochronous transfers;
+ * 3) the payload.
+ *
+ * The kernel buffer has a size, defaulting to 300KB, with a
+ * minimum of 8KB and a maximum of 1200KB. The size is set with
+ * the MON_IOCT_RING_SIZE ioctl; the size passed in is rounded up
+ * to a page size.
+ *
+ * No more than {buffer size}/5 bytes worth of payload is saved.
+ * Therefore, if we subtract the fixed-length size from the
+ * snapshot length, we have the biggest payload we want (we
+ * don't worry about the descriptors - if we have descriptors,
+ * we'll just discard the last bit of the payload to get it
+ * to fit). We multiply that result by 5 and set the buffer
+ * size to that value.
+ */
+ int ring_size;
+
+ if (handle->snapshot < header_size)
+ handle->snapshot = header_size;
+ /* The maximum snapshot size is small enough that this won't overflow */
+ ring_size = (handle->snapshot - header_size) * 5;
+
+ /*
+ * Will this get an error?
+ * (There's no wqy to query the minimum or maximum, so we just
+ * copy the value from the kernel source. We don't round it
+ * up to a multiple of the page size.)
+ */
+ if (ring_size > MAX_RING_SIZE) {
+ /*
+ * Yes. Lower the ring size to the maximum, and set the
+ * snapshot length to the value that would give us a
+ * maximum-size ring.
+ */
+ ring_size = MAX_RING_SIZE;
+ handle->snapshot = header_size + (MAX_RING_SIZE/5);
+ } else if (ring_size < MIN_RING_SIZE) {
+ /*
+ * Yes. Raise the ring size to the minimum, but leave
+ * the snapshot length unchanged, so we show the
+ * callback no more data than specified by the
+ * snapshot length.
+ */
+ ring_size = MIN_RING_SIZE;
+ }
+
+ if (ioctl(handle->fd, MON_IOCT_RING_SIZE, ring_size) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't set ring size from fd %d", handle->fd);
+ return -1;
+ }
+ return ring_size;
+}
+
+static
+int usb_mmap(pcap_t* handle)
+{
+ struct pcap_usb_linux *handlep = handle->priv;
+ int len;
+
+ /*
+ * Attempt to set the ring size as appropriate for the snapshot
+ * length, reducing the snapshot length if that'd make the ring
+ * bigger than the kernel supports.
+ */
+ len = usb_set_ring_size(handle, (int)sizeof(pcap_usb_header_mmapped));
+ if (len == -1) {
+ /* Failed. Fall back on non-memory-mapped access. */
+ return 0;
+ }
+
+ handlep->mmapbuflen = len;
+ handlep->mmapbuf = mmap(0, handlep->mmapbuflen, PROT_READ,
+ MAP_SHARED, handle->fd, 0);
+ if (handlep->mmapbuf == MAP_FAILED) {
+ /*
+ * Failed. We don't treat that as a fatal error, we
+ * just try to fall back on non-memory-mapped access.
+ */
+ return 0;
+ }
+ return 1;
+}
+
+#ifdef HAVE_LINUX_USBDEVICE_FS_H
+
+#define CTRL_TIMEOUT (5*1000) /* milliseconds */
+
+#define USB_DIR_IN 0x80
+#define USB_TYPE_STANDARD 0x00
+#define USB_RECIP_DEVICE 0x00
+
+#define USB_REQ_GET_DESCRIPTOR 6
+
+#define USB_DT_DEVICE 1
+
+/* probe the descriptors of the devices attached to the bus */
+/* the descriptors will end up in the captured packet stream */
+/* and be decoded by external apps like wireshark */
+/* without these identifying probes packet data can't be fully decoded */
+static void
+probe_devices(int bus)
+{
+ struct usbdevfs_ctrltransfer ctrl;
+ struct dirent* data;
+ int ret = 0;
+ char buf[sizeof("/dev/bus/usb/000/") + NAME_MAX];
+ DIR* dir;
+
+ /* scan usb bus directories for device nodes */
+ pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d", bus);
+ dir = opendir(buf);
+ if (!dir)
+ return;
+
+ while ((ret >= 0) && ((data = readdir(dir)) != 0)) {
+ int fd;
+ char* name = data->d_name;
+
+ if (name[0] == '.')
+ continue;
+
+ pcap_snprintf(buf, sizeof(buf), "/dev/bus/usb/%03d/%s", bus, data->d_name);
+
+ fd = open(buf, O_RDWR);
+ if (fd == -1)
+ continue;
+
+ /*
+ * Sigh. Different kernels have different member names
+ * for this structure.
+ */
+#ifdef HAVE_STRUCT_USBDEVFS_CTRLTRANSFER_BREQUESTTYPE
+ ctrl.bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+ ctrl.bRequest = USB_REQ_GET_DESCRIPTOR;
+ ctrl.wValue = USB_DT_DEVICE << 8;
+ ctrl.wIndex = 0;
+ ctrl.wLength = sizeof(buf);
+#else
+ ctrl.requesttype = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+ ctrl.request = USB_REQ_GET_DESCRIPTOR;
+ ctrl.value = USB_DT_DEVICE << 8;
+ ctrl.index = 0;
+ ctrl.length = sizeof(buf);
+#endif
+ ctrl.data = buf;
+ ctrl.timeout = CTRL_TIMEOUT;
+
+ ret = ioctl(fd, USBDEVFS_CONTROL, &ctrl);
+
+ close(fd);
+ }
+ closedir(dir);
+}
+#endif /* HAVE_LINUX_USBDEVICE_FS_H */
+
+pcap_t *
+usb_create(const char *device, char *ebuf, int *is_ours)
+{
+ const char *cp;
+ char *cpend;
+ long devnum;
+ pcap_t *p;
+
+ /* Does this look like a USB monitoring device? */
+ cp = strrchr(device, '/');
+ if (cp == NULL)
+ cp = device;
+ /* Does it begin with USB_IFACE? */
+ if (strncmp(cp, USB_IFACE, sizeof USB_IFACE - 1) != 0) {
+ /* Nope, doesn't begin with USB_IFACE */
+ *is_ours = 0;
+ return NULL;
+ }
+ /* Yes - is USB_IFACE followed by a number? */
+ cp += sizeof USB_IFACE - 1;
+ devnum = strtol(cp, &cpend, 10);
+ if (cpend == cp || *cpend != '\0') {
+ /* Not followed by a number. */
+ *is_ours = 0;
+ return NULL;
+ }
+ if (devnum < 0) {
+ /* Followed by a non-valid number. */
+ *is_ours = 0;
+ return NULL;
+ }
+
+ /* OK, it's probably ours. */
+ *is_ours = 1;
+
+ p = pcap_create_common(ebuf, sizeof (struct pcap_usb_linux));
+ if (p == NULL)
+ return (NULL);
+
+ p->activate_op = usb_activate;
+ return (p);
+}
+
+static int
+usb_activate(pcap_t* handle)
+{
+ struct pcap_usb_linux *handlep = handle->priv;
+ char full_path[USB_LINE_LEN];
+ int ret;
+
+ /*
+ * Turn a negative snapshot value (invalid), a snapshot value of
+ * 0 (unspecified), or a value bigger than the normal maximum
+ * value, into the maximum allowed value.
+ *
+ * If some application really *needs* a bigger snapshot
+ * length, we should just increase MAXIMUM_SNAPLEN.
+ */
+ if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN)
+ handle->snapshot = MAXIMUM_SNAPLEN;
+
+ /* Initialize some components of the pcap structure. */
+ handle->bufsize = handle->snapshot;
+ handle->offset = 0;
+ handle->linktype = DLT_USB_LINUX;
+
+ handle->inject_op = usb_inject_linux;
+ handle->setfilter_op = install_bpf_program; /* no kernel filtering */
+ handle->setdirection_op = usb_setdirection_linux;
+ handle->set_datalink_op = NULL; /* can't change data link type */
+ handle->getnonblock_op = pcap_getnonblock_fd;
+ handle->setnonblock_op = pcap_setnonblock_fd;
+
+ /*get usb bus index from device name */
+ if (sscanf(handle->opt.device, USB_IFACE"%d", &handlep->bus_index) != 1)
+ {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't get USB bus index from %s", handle->opt.device);
+ return PCAP_ERROR;
+ }
+
+ if (have_binary_usbmon())
+ {
+ /*
+ * We have binary-mode support.
+ * Try to open the binary interface.
+ */
+ pcap_snprintf(full_path, USB_LINE_LEN, LINUX_USB_MON_DEV"%d", handlep->bus_index);
+ handle->fd = open(full_path, O_RDONLY, 0);
+ if (handle->fd < 0)
+ {
+ /*
+ * The attempt failed; why?
+ */
+ switch (errno) {
+
+ case ENOENT:
+ /*
+ * The device doesn't exist.
+ * That could either mean that there's
+ * no support for monitoring USB buses
+ * (which probably means "the usbmon
+ * module isn't loaded") or that there
+ * is but that *particular* device
+ * doesn't exist (no "scan all buses"
+ * device if the bus index is 0, no
+ * such bus if the bus index isn't 0).
+ */
+ return PCAP_ERROR_NO_SUCH_DEVICE;
+
+ case EACCES:
+ /*
+ * We didn't have permission to open it.
+ */
+ return PCAP_ERROR_PERM_DENIED;
+
+ default:
+ /*
+ * Something went wrong.
+ */
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't open USB bus file %s", full_path);
+ return PCAP_ERROR;
+ }
+ }
+
+ if (handle->opt.rfmon)
+ {
+ /*
+ * Monitor mode doesn't apply to USB devices.
+ */
+ close(handle->fd);
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ /* try to use fast mmap access */
+ if (usb_mmap(handle))
+ {
+ /* We succeeded. */
+ handle->linktype = DLT_USB_LINUX_MMAPPED;
+ handle->stats_op = usb_stats_linux_bin;
+ handle->read_op = usb_read_linux_mmap;
+ handle->cleanup_op = usb_cleanup_linux_mmap;
+#ifdef HAVE_LINUX_USBDEVICE_FS_H
+ probe_devices(handlep->bus_index);
+#endif
+
+ /*
+ * "handle->fd" is a real file, so
+ * "select()" and "poll()" work on it.
+ */
+ handle->selectable_fd = handle->fd;
+ return 0;
+ }
+
+ /*
+ * We failed; try plain binary interface access.
+ *
+ * Attempt to set the ring size as appropriate for
+ * the snapshot length, reducing the snapshot length
+ * if that'd make the ring bigger than the kernel
+ * supports.
+ */
+ if (usb_set_ring_size(handle, (int)sizeof(pcap_usb_header)) == -1) {
+ /* Failed. */
+ close(handle->fd);
+ return PCAP_ERROR;
+ }
+ handle->stats_op = usb_stats_linux_bin;
+ handle->read_op = usb_read_linux_bin;
+#ifdef HAVE_LINUX_USBDEVICE_FS_H
+ probe_devices(handlep->bus_index);
+#endif
+ }
+ else {
+ /*
+ * We don't have binary mode support.
+ * Try opening the text-mode device.
+ */
+ pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR"/%dt", handlep->bus_index);
+ handle->fd = open(full_path, O_RDONLY, 0);
+ if (handle->fd < 0)
+ {
+ if (errno == ENOENT)
+ {
+ /*
+ * Not found at the new location; try
+ * the old location.
+ */
+ pcap_snprintf(full_path, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%dt", handlep->bus_index);
+ handle->fd = open(full_path, O_RDONLY, 0);
+ }
+ if (handle->fd < 0) {
+ if (errno == ENOENT)
+ {
+ /*
+ * The problem is that the file
+ * doesn't exist. Report that as
+ * "no such device". (That could
+ * mean "no such USB bus" or
+ * "monitoring not supported".)
+ */
+ ret = PCAP_ERROR_NO_SUCH_DEVICE;
+ }
+ else if (errno == EACCES)
+ {
+ /*
+ * The problem is that we don't
+ * have sufficient permission to
+ * open the file. Report that.
+ */
+ ret = PCAP_ERROR_PERM_DENIED;
+ }
+ else
+ {
+ /*
+ * Some other error.
+ */
+ ret = PCAP_ERROR;
+ }
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't open USB bus file %s",
+ full_path);
+ return ret;
+ }
+ }
+
+ if (handle->opt.rfmon)
+ {
+ /*
+ * Monitor mode doesn't apply to USB devices.
+ */
+ close(handle->fd);
+ return PCAP_ERROR_RFMON_NOTSUP;
+ }
+
+ handle->stats_op = usb_stats_linux;
+ handle->read_op = usb_read_linux;
+ }
+
+ /*
+ * "handle->fd" is a real file, so "select()" and "poll()"
+ * work on it.
+ */
+ handle->selectable_fd = handle->fd;
+
+ /* for plain binary access and text access we need to allocate the read
+ * buffer */
+ handle->buffer = malloc(handle->bufsize);
+ if (!handle->buffer) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ close(handle->fd);
+ return PCAP_ERROR;
+ }
+ return 0;
+}
+
+static inline int
+ascii_to_int(char c)
+{
+ return c < 'A' ? c- '0': ((c<'a') ? c - 'A' + 10: c-'a'+10);
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * <linux-kernel-source>/drivers/usb/mon/mon_text.c for urb string
+ * format description
+ */
+static int
+usb_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
+{
+ /* see:
+ * /usr/src/linux/Documentation/usb/usbmon.txt
+ * for message format
+ */
+ struct pcap_usb_linux *handlep = handle->priv;
+ unsigned timestamp;
+ int tag, cnt, ep_num, dev_addr, dummy, ret, urb_len, data_len;
+ char etype, pipeid1, pipeid2, status[16], urb_tag, line[USB_LINE_LEN];
+ char *string = line;
+ u_char * rawdata = handle->buffer;
+ struct pcap_pkthdr pkth;
+ pcap_usb_header* uhdr = (pcap_usb_header*)handle->buffer;
+ u_char urb_transfer=0;
+ int incoming=0;
+
+ /* ignore interrupt system call errors */
+ do {
+ ret = read(handle->fd, line, USB_LINE_LEN - 1);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ return 0; /* no data there */
+
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't read from fd %d", handle->fd);
+ return -1;
+ }
+
+ /* read urb header; %n argument may increment return value, but it's
+ * not mandatory, so does not count on it*/
+ string[ret] = 0;
+ ret = sscanf(string, "%x %d %c %c%c:%d:%d %s%n", &tag, &timestamp, &etype,
+ &pipeid1, &pipeid2, &dev_addr, &ep_num, status,
+ &cnt);
+ if (ret < 8)
+ {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse USB bus message '%s', too few tokens (expected 8 got %d)",
+ string, ret);
+ return -1;
+ }
+ uhdr->id = tag;
+ uhdr->device_address = dev_addr;
+ uhdr->bus_id = handlep->bus_index;
+ uhdr->status = 0;
+ string += cnt;
+
+ /* don't use usbmon provided timestamp, since it have low precision*/
+ if (gettimeofday(&pkth.ts, NULL) < 0)
+ {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't get timestamp for message '%s'", string);
+ return -1;
+ }
+ uhdr->ts_sec = pkth.ts.tv_sec;
+ uhdr->ts_usec = pkth.ts.tv_usec;
+
+ /* parse endpoint information */
+ if (pipeid1 == 'C')
+ urb_transfer = URB_CONTROL;
+ else if (pipeid1 == 'Z')
+ urb_transfer = URB_ISOCHRONOUS;
+ else if (pipeid1 == 'I')
+ urb_transfer = URB_INTERRUPT;
+ else if (pipeid1 == 'B')
+ urb_transfer = URB_BULK;
+ if (pipeid2 == 'i') {
+ ep_num |= URB_TRANSFER_IN;
+ incoming = 1;
+ }
+ if (etype == 'C')
+ incoming = !incoming;
+
+ /* direction check*/
+ if (incoming)
+ {
+ if (handle->direction == PCAP_D_OUT)
+ return 0;
+ }
+ else
+ if (handle->direction == PCAP_D_IN)
+ return 0;
+ uhdr->event_type = etype;
+ uhdr->transfer_type = urb_transfer;
+ uhdr->endpoint_number = ep_num;
+ pkth.caplen = sizeof(pcap_usb_header);
+ rawdata += sizeof(pcap_usb_header);
+
+ /* check if this is a setup packet */
+ ret = sscanf(status, "%d", &dummy);
+ if (ret != 1)
+ {
+ /* this a setup packet, setup data can be filled with underscore if
+ * usbmon has not been able to read them, so we must parse this fields as
+ * strings */
+ pcap_usb_setup* shdr;
+ char str1[3], str2[3], str3[5], str4[5], str5[5];
+ ret = sscanf(string, "%s %s %s %s %s%n", str1, str2, str3, str4,
+ str5, &cnt);
+ if (ret < 5)
+ {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse USB bus message '%s', too few tokens (expected 5 got %d)",
+ string, ret);
+ return -1;
+ }
+ string += cnt;
+
+ /* try to convert to corresponding integer */
+ shdr = &uhdr->setup;
+ shdr->bmRequestType = strtoul(str1, 0, 16);
+ shdr->bRequest = strtoul(str2, 0, 16);
+ shdr->wValue = htols(strtoul(str3, 0, 16));
+ shdr->wIndex = htols(strtoul(str4, 0, 16));
+ shdr->wLength = htols(strtoul(str5, 0, 16));
+
+ uhdr->setup_flag = 0;
+ }
+ else
+ uhdr->setup_flag = 1;
+
+ /* read urb data */
+ ret = sscanf(string, " %d%n", &urb_len, &cnt);
+ if (ret < 1)
+ {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse urb length from '%s'", string);
+ return -1;
+ }
+ string += cnt;
+
+ /* urb tag is not present if urb length is 0, so we can stop here
+ * text parsing */
+ pkth.len = urb_len+pkth.caplen;
+ uhdr->urb_len = urb_len;
+ uhdr->data_flag = 1;
+ data_len = 0;
+ if (uhdr->urb_len == 0)
+ goto got;
+
+ /* check for data presence; data is present if and only if urb tag is '=' */
+ if (sscanf(string, " %c", &urb_tag) != 1)
+ {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't parse urb tag from '%s'", string);
+ return -1;
+ }
+
+ if (urb_tag != '=')
+ goto got;
+
+ /* skip urb tag and following space */
+ string += 3;
+
+ /* if we reach this point we got some urb data*/
+ uhdr->data_flag = 0;
+
+ /* read all urb data; if urb length is greater then the usbmon internal
+ * buffer length used by the kernel to spool the URB, we get only
+ * a partial information.
+ * At least until linux 2.6.17 there is no way to set usbmon intenal buffer
+ * length and default value is 130. */
+ while ((string[0] != 0) && (string[1] != 0) && (pkth.caplen < (bpf_u_int32)handle->snapshot))
+ {
+ rawdata[0] = ascii_to_int(string[0]) * 16 + ascii_to_int(string[1]);
+ rawdata++;
+ string+=2;
+ if (string[0] == ' ')
+ string++;
+ pkth.caplen++;
+ data_len++;
+ }
+
+got:
+ uhdr->data_len = data_len;
+ if (pkth.caplen > (bpf_u_int32)handle->snapshot)
+ pkth.caplen = (bpf_u_int32)handle->snapshot;
+
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, handle->buffer,
+ pkth.len, pkth.caplen)) {
+ handlep->packets_read++;
+ callback(user, &pkth, handle->buffer);
+ return 1;
+ }
+ return 0; /* didn't pass filter */
+}
+
+static int
+usb_inject_linux(pcap_t *handle, const void *buf _U_, size_t size _U_)
+{
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Packet injection is not supported on USB devices");
+ return (-1);
+}
+
+static int
+usb_stats_linux(pcap_t *handle, struct pcap_stat *stats)
+{
+ struct pcap_usb_linux *handlep = handle->priv;
+ int dummy, ret, consumed, cnt;
+ char string[USB_LINE_LEN];
+ char token[USB_LINE_LEN];
+ char * ptr = string;
+ int fd;
+
+ pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR"/%ds", handlep->bus_index);
+ fd = open(string, O_RDONLY, 0);
+ if (fd < 0)
+ {
+ if (errno == ENOENT)
+ {
+ /*
+ * Not found at the new location; try the old
+ * location.
+ */
+ pcap_snprintf(string, USB_LINE_LEN, USB_TEXT_DIR_OLD"/%ds", handlep->bus_index);
+ fd = open(string, O_RDONLY, 0);
+ }
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "Can't open USB stats file %s", string);
+ return -1;
+ }
+ }
+
+ /* read stats line */
+ do {
+ ret = read(fd, string, USB_LINE_LEN-1);
+ } while ((ret == -1) && (errno == EINTR));
+ close(fd);
+
+ if (ret < 0)
+ {
+ pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
+ "Can't read stats from fd %d ", fd);
+ return -1;
+ }
+ string[ret] = 0;
+
+ stats->ps_recv = handlep->packets_read;
+ stats->ps_drop = 0; /* unless we find text_lost */
+ stats->ps_ifdrop = 0;
+
+ /* extract info on dropped urbs */
+ for (consumed=0; consumed < ret; ) {
+ /* from the sscanf man page:
+ * The C standard says: "Execution of a %n directive does
+ * not increment the assignment count returned at the completion
+ * of execution" but the Corrigendum seems to contradict this.
+ * Do not make any assumptions on the effect of %n conversions
+ * on the return value and explicitly check for cnt assignmet*/
+ int ntok;
+
+ cnt = -1;
+ ntok = sscanf(ptr, "%s%n", token, &cnt);
+ if ((ntok < 1) || (cnt < 0))
+ break;
+ consumed += cnt;
+ ptr += cnt;
+ if (strcmp(token, "text_lost") == 0)
+ ntok = sscanf(ptr, "%d%n", &stats->ps_drop, &cnt);
+ else
+ ntok = sscanf(ptr, "%d%n", &dummy, &cnt);
+ if ((ntok != 1) || (cnt < 0))
+ break;
+ consumed += cnt;
+ ptr += cnt;
+ }
+
+ return 0;
+}
+
+static int
+usb_setdirection_linux(pcap_t *p, pcap_direction_t d)
+{
+ p->direction = d;
+ return 0;
+}
+
+
+static int
+usb_stats_linux_bin(pcap_t *handle, struct pcap_stat *stats)
+{
+ struct pcap_usb_linux *handlep = handle->priv;
+ int ret;
+ struct mon_bin_stats st;
+ ret = ioctl(handle->fd, MON_IOCG_STATS, &st);
+ if (ret < 0)
+ {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't read stats from fd %d", handle->fd);
+ return -1;
+ }
+
+ stats->ps_recv = handlep->packets_read + st.queued;
+ stats->ps_drop = st.dropped;
+ stats->ps_ifdrop = 0;
+ return 0;
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
+ */
+static int
+usb_read_linux_bin(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user)
+{
+ struct pcap_usb_linux *handlep = handle->priv;
+ struct mon_bin_get info;
+ int ret;
+ struct pcap_pkthdr pkth;
+ u_int clen = handle->snapshot - sizeof(pcap_usb_header);
+
+ /* the usb header is going to be part of 'packet' data*/
+ info.hdr = (pcap_usb_header*) handle->buffer;
+ info.data = (u_char *)handle->buffer + sizeof(pcap_usb_header);
+ info.data_len = clen;
+
+ /* ignore interrupt system call errors */
+ do {
+ ret = ioctl(handle->fd, MON_IOCX_GET, &info);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ return 0; /* no data there */
+
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't read from fd %d", handle->fd);
+ return -1;
+ }
+
+ /*
+ * info.hdr->data_len is the number of bytes of isochronous
+ * descriptors (if any) plus the number of bytes of data
+ * provided. There are no isochronous descriptors here,
+ * because we're using the old 48-byte header.
+ *
+ * If info.hdr->data_flag is non-zero, there's no URB data;
+ * info.hdr->urb_len is the size of the buffer into which
+ * data is to be placed; it does not represent the amount
+ * of data transferred. If info.hdr->data_flag is zero,
+ * there is URB data, and info.hdr->urb_len is the number
+ * of bytes transmitted or received; it doesn't include
+ * isochronous descriptors.
+ *
+ * The kernel may give us more data than the snaplen; if it did,
+ * reduce the data length so that the total number of bytes we
+ * tell our client we have is not greater than the snaplen.
+ */
+ if (info.hdr->data_len < clen)
+ clen = info.hdr->data_len;
+ info.hdr->data_len = clen;
+ pkth.caplen = sizeof(pcap_usb_header) + clen;
+ if (info.hdr->data_flag) {
+ /*
+ * No data; just base the on-the-wire length on
+ * info.hdr->data_len (so that it's >= the captured
+ * length).
+ */
+ pkth.len = sizeof(pcap_usb_header) + info.hdr->data_len;
+ } else {
+ /*
+ * We got data; base the on-the-wire length on
+ * info.hdr->urb_len, so that it includes data
+ * discarded by the USB monitor device due to
+ * its buffer being too small.
+ */
+ pkth.len = sizeof(pcap_usb_header) + info.hdr->urb_len;
+ }
+ pkth.ts.tv_sec = info.hdr->ts_sec;
+ pkth.ts.tv_usec = info.hdr->ts_usec;
+
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, handle->buffer,
+ pkth.len, pkth.caplen)) {
+ handlep->packets_read++;
+ callback(user, &pkth, handle->buffer);
+ return 1;
+ }
+
+ return 0; /* didn't pass filter */
+}
+
+/*
+ * see <linux-kernel-source>/Documentation/usb/usbmon.txt and
+ * <linux-kernel-source>/drivers/usb/mon/mon_bin.c binary ABI
+ */
+#define VEC_SIZE 32
+static int
+usb_read_linux_mmap(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
+{
+ struct pcap_usb_linux *handlep = handle->priv;
+ struct mon_bin_mfetch fetch;
+ int32_t vec[VEC_SIZE];
+ struct pcap_pkthdr pkth;
+ pcap_usb_header_mmapped* hdr;
+ int nflush = 0;
+ int packets = 0;
+ u_int clen, max_clen;
+
+ max_clen = handle->snapshot - sizeof(pcap_usb_header_mmapped);
+
+ for (;;) {
+ int i, ret;
+ int limit = max_packets - packets;
+ if (limit <= 0)
+ limit = VEC_SIZE;
+ if (limit > VEC_SIZE)
+ limit = VEC_SIZE;
+
+ /* try to fetch as many events as possible*/
+ fetch.offvec = vec;
+ fetch.nfetch = limit;
+ fetch.nflush = nflush;
+ /* ignore interrupt system call errors */
+ do {
+ ret = ioctl(handle->fd, MON_IOCX_MFETCH, &fetch);
+ if (handle->break_loop)
+ {
+ handle->break_loop = 0;
+ return -2;
+ }
+ } while ((ret == -1) && (errno == EINTR));
+ if (ret < 0)
+ {
+ if (errno == EAGAIN)
+ return 0; /* no data there */
+
+ pcap_fmt_errmsg_for_errno(handle->errbuf,
+ PCAP_ERRBUF_SIZE, errno, "Can't mfetch fd %d",
+ handle->fd);
+ return -1;
+ }
+
+ /* keep track of processed events, we will flush them later */
+ nflush = fetch.nfetch;
+ for (i=0; i<fetch.nfetch; ++i) {
+ /* discard filler */
+ hdr = (pcap_usb_header_mmapped*) &handlep->mmapbuf[vec[i]];
+ if (hdr->event_type == '@')
+ continue;
+
+ /*
+ * hdr->data_len is the number of bytes of
+ * isochronous descriptors (if any) plus the
+ * number of bytes of data provided.
+ *
+ * If hdr->data_flag is non-zero, there's no
+ * URB data; hdr->urb_len is the size of the
+ * buffer into which data is to be placed; it does
+ * not represent the amount of data transferred.
+ * If hdr->data_flag is zero, there is URB data,
+ * and hdr->urb_len is the number of bytes
+ * transmitted or received; it doesn't include
+ * isochronous descriptors.
+ *
+ * The kernel may give us more data than the
+ * snaplen; if it did, reduce the data length
+ * so that the total number of bytes we
+ * tell our client we have is not greater than
+ * the snaplen.
+ */
+ clen = max_clen;
+ if (hdr->data_len < clen)
+ clen = hdr->data_len;
+ pkth.caplen = sizeof(pcap_usb_header_mmapped) + clen;
+ if (hdr->data_flag) {
+ /*
+ * No data; just base the on-the-wire length
+ * on hdr->data_len (so that it's >= the
+ * captured length).
+ */
+ pkth.len = sizeof(pcap_usb_header_mmapped) +
+ hdr->data_len;
+ } else {
+ /*
+ * We got data; base the on-the-wire length
+ * on hdr->urb_len, so that it includes
+ * data discarded by the USB monitor device
+ * due to its buffer being too small.
+ */
+ pkth.len = sizeof(pcap_usb_header_mmapped) +
+ (hdr->ndesc * sizeof (usb_isodesc)) + hdr->urb_len;
+ }
+ pkth.ts.tv_sec = hdr->ts_sec;
+ pkth.ts.tv_usec = hdr->ts_usec;
+
+ if (handle->fcode.bf_insns == NULL ||
+ bpf_filter(handle->fcode.bf_insns, (u_char*) hdr,
+ pkth.len, pkth.caplen)) {
+ handlep->packets_read++;
+ callback(user, &pkth, (u_char*) hdr);
+ packets++;
+ }
+ }
+
+ /* with max_packets specifying "unlimited" we stop afer the first chunk*/
+ if (PACKET_COUNT_IS_UNLIMITED(max_packets) || (packets == max_packets))
+ break;
+ }
+
+ /* flush pending events*/
+ if (ioctl(handle->fd, MON_IOCH_MFLUSH, nflush) == -1) {
+ pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't mflush fd %d", handle->fd);
+ return -1;
+ }
+ return packets;
+}
+
+static void
+usb_cleanup_linux_mmap(pcap_t* handle)
+{
+ struct pcap_usb_linux *handlep = handle->priv;
+
+ /* if we have a memory-mapped buffer, unmap it */
+ if (handlep->mmapbuf != NULL) {
+ munmap(handlep->mmapbuf, handlep->mmapbuflen);
+ handlep->mmapbuf = NULL;
+ }
+ pcap_cleanup_live_common(handle);
+}
diff --git a/lib/libpcap/libpcap/pcap-usb-linux.h b/lib/libpcap/libpcap/pcap-usb-linux.h
new file mode 100644
index 0000000..3ddc12f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-usb-linux.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * USB sniffing API implementation for Linux platform
+ * By Paolo Abeni <paolo.abeni@email.it>
+ */
+
+/*
+ * Prototypes for USB-related functions
+ */
+int usb_findalldevs(pcap_if_list_t *devlistp, char *err_str);
+pcap_t *usb_create(const char *device, char *ebuf, int *is_ours);
diff --git a/lib/libpcap/libpcap/pcap-util.c b/lib/libpcap/libpcap/pcap-util.c
new file mode 100644
index 0000000..f028414
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-util.c
@@ -0,0 +1,437 @@
+/*
+ * Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "pcap-int.h"
+#include "pcap-util.h"
+
+static int null_uu_inited = 0;
+static uuid_t null_uu;
+
+void
+pcap_if_info_set_clear(struct pcap_if_info_set *if_info_set)
+{
+ int i;
+
+ if (if_info_set->if_infos != NULL) {
+ for (i = 0; i < if_info_set->if_info_count; i++)
+ pcap_if_info_set_free(if_info_set, if_info_set->if_infos[i]);
+
+ free(if_info_set->if_infos);
+ if_info_set->if_infos = NULL;
+ }
+ if_info_set->if_info_count = 0;
+ if_info_set->if_dump_id = 0;
+}
+
+struct pcap_if_info *
+pcap_if_info_set_find_by_name(struct pcap_if_info_set *if_info_set, const char *name)
+{
+ int i;
+
+ for (i = 0; i < if_info_set->if_info_count; i++) {
+ if (strcmp(name, if_info_set->if_infos[i]->if_name) == 0)
+ return (if_info_set->if_infos[i]);
+ }
+ return (NULL);
+}
+
+struct pcap_if_info *
+pcap_if_info_set_find_by_id(struct pcap_if_info_set *if_info_set, int if_id)
+{
+ int i;
+
+ if (if_id == -1)
+ return (NULL);
+
+ for (i = 0; i < if_info_set->if_info_count; i++) {
+ if (if_id == if_info_set->if_infos[i]->if_id)
+ return (if_info_set->if_infos[i]);
+ }
+ return (NULL);
+}
+
+void
+pcap_if_info_set_free(struct pcap_if_info_set *if_info_set, struct pcap_if_info *if_info)
+{
+ if (if_info != NULL) {
+ int i;
+
+ for (i = 0; i < if_info_set->if_info_count; i++) {
+ if (if_info_set->if_infos[i] == if_info) {
+ if_info_set->if_infos[i] = NULL;
+ break;
+ }
+ }
+
+ pcap_freecode(&if_info->if_filter_program);
+ free(if_info);
+ }
+}
+
+struct pcap_if_info *
+pcap_if_info_set_add(struct pcap_if_info_set *if_info_set, const char *name,
+ int if_id, int linktype, int snaplen,
+ const char *filter_str, char *errbuf)
+{
+ struct pcap_if_info *if_info = NULL;
+ size_t ifname_len = strlen(name);
+ struct pcap_if_info **newarray;
+
+ /*
+ * Stash the interface name after the structure
+ */
+ if_info = calloc(1, sizeof(struct pcap_if_info) + ifname_len + 1);
+ if (if_info == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: calloc() failed", __func__);
+ }
+ return (NULL);
+ }
+ if_info->if_name = (char *)(if_info + 1);
+ if (ifname_len > 0)
+ bcopy(name, if_info->if_name, ifname_len);
+ if_info->if_name[ifname_len] = 0;
+ if (if_id == -1)
+ if_info->if_id = if_info_set->if_info_count;
+ else
+ if_info->if_id = if_id;
+ if_info->if_linktype = linktype;
+ if_info->if_snaplen = snaplen;
+
+ /*
+ * The compilation of a BPF filter expression depends on
+ * the DLT so we store the program in the if_info
+ */
+ if (filter_str != NULL && *filter_str != 0) {
+ if (pcap_compile_nopcap(if_info->if_snaplen,
+ if_info->if_linktype,
+ &if_info->if_filter_program,
+ filter_str, 0, PCAP_NETMASK_UNKNOWN) == -1) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: pcap_compile_nopcap() failed", __func__);
+ }
+ free(if_info);
+ return (NULL);
+ }
+ }
+
+ /*
+ * Resize pointer array
+ */
+ newarray = realloc(if_info_set->if_infos,
+ (if_info_set->if_info_count + 1) * sizeof(struct pcap_if_info *));
+ if (newarray == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: realloc() failed", __func__);
+ }
+ pcap_if_info_set_free(if_info_set, if_info);
+ return (NULL);
+ }
+ if_info_set->if_infos = newarray;
+ if_info_set->if_infos[if_info_set->if_info_count] = if_info;
+ if_info_set->if_info_count += 1;
+
+ return (if_info);
+}
+
+void
+pcap_clear_if_infos(pcap_t * pcap)
+{
+ pcap_if_info_set_clear(&pcap->if_info_set);
+}
+
+struct pcap_if_info *
+pcap_find_if_info_by_name(pcap_t * pcap, const char *name)
+{
+ return (pcap_if_info_set_find_by_name(&pcap->if_info_set, name));
+}
+
+struct pcap_if_info *
+pcap_find_if_info_by_id(pcap_t * pcap, int if_id)
+{
+ return (pcap_if_info_set_find_by_id(&pcap->if_info_set, if_id));
+}
+
+void
+pcap_free_if_info(pcap_t * pcap, struct pcap_if_info *if_info)
+{
+ pcap_if_info_set_free(&pcap->if_info_set, if_info);
+}
+
+struct pcap_if_info *
+pcap_add_if_info(pcap_t * pcap, const char *name,
+ int if_id, int linktype, int snaplen)
+{
+ struct pcap_if_info *if_info = NULL;
+
+ pcap->cleanup_extra_op = pcap_ng_init_section_info;
+
+ if_info = pcap_if_info_set_add(&pcap->if_info_set,
+ name, if_id, linktype, snaplen,
+ pcap->filter_str, pcap->errbuf);
+
+ return (if_info);
+}
+
+void
+pcap_proc_info_set_clear(struct pcap_proc_info_set *proc_info_set)
+{
+ int i;
+
+ if (proc_info_set->proc_infos != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++)
+ pcap_proc_info_set_free(proc_info_set, proc_info_set->proc_infos[i]);
+
+ free(proc_info_set->proc_infos);
+ proc_info_set->proc_infos = NULL;
+ }
+ proc_info_set->proc_info_count = 0;
+ proc_info_set->proc_dump_index = 0;
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_find(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name)
+{
+ return (pcap_proc_info_set_find_uuid(proc_info_set, pid, name, NULL));
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_find_uuid(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name, const uuid_t uu)
+{
+ int i;
+
+ if (name != NULL && uu != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (pid == proc_info->proc_pid &&
+ strcmp(name, proc_info->proc_name) == 0 &&
+ uuid_compare(uu, proc_info->proc_uuid) == 0)
+ return (proc_info);
+ }
+ } else if (name != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (pid == proc_info->proc_pid &&
+ strcmp(name, proc_info->proc_name) == 0)
+ return (proc_info);
+ }
+ } else if (uu != NULL) {
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (pid == proc_info->proc_pid &&
+ uuid_compare(uu, proc_info->proc_uuid) == 0)
+ return (proc_info);
+ }
+ }
+ return (NULL);
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_find_by_index(struct pcap_proc_info_set *proc_info_set,
+ uint32_t index)
+{
+ int i;
+
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ struct pcap_proc_info *proc_info = proc_info_set->proc_infos[i];
+
+ if (index == proc_info->proc_index)
+ return (proc_info);
+ }
+ return (NULL);
+}
+
+void
+pcap_proc_info_set_free(struct pcap_proc_info_set *proc_info_set,
+ struct pcap_proc_info *proc_info)
+{
+
+ if (proc_info != NULL) {
+ int i;
+
+ for (i = 0; i < proc_info_set->proc_info_count; i++) {
+ if (proc_info_set->proc_infos[i] == proc_info) {
+ proc_info_set->proc_infos[i] = NULL;
+ break;
+ }
+ }
+ free(proc_info);
+ }
+}
+
+struct pcap_proc_info *
+pcap_proc_info_set_add_uuid(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name, const uuid_t uu, char *errbuf)
+{
+ struct pcap_proc_info *proc_info = NULL;
+ size_t name_len = name != NULL ? strlen(name) : 0;
+ struct pcap_proc_info **newarray;
+ uuid_string_t uu_str;
+
+ if (uu == NULL && null_uu_inited == 0) {
+ uuid_clear(null_uu);
+ null_uu_inited = 1;
+ }
+
+ /*
+ * Stash the process name after the structure
+ */
+ proc_info = calloc(1, sizeof(struct pcap_proc_info) + name_len + 1);
+ if (proc_info == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: calloc() failed", __func__);
+ }
+ return (NULL);
+ }
+ proc_info->proc_name = (char *)(proc_info + 1);
+ if (name_len > 0)
+ bcopy(name, proc_info->proc_name, name_len);
+ proc_info->proc_name[name_len] = 0;
+ proc_info->proc_pid = pid;
+ proc_info->proc_index = proc_info_set->proc_info_count;
+ uuid_copy(proc_info->proc_uuid, uu != NULL ? uu : null_uu);
+
+ uuid_unparse_lower(proc_info->proc_uuid, uu_str);
+
+ /*
+ * Resize pointer array
+ */
+ newarray = realloc(proc_info_set->proc_infos,
+ (proc_info_set->proc_info_count + 1) * sizeof(struct pcap_proc_info *));
+ if (newarray == NULL) {
+ if (errbuf != NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: malloc() failed", __func__);
+ }
+ free(proc_info);
+ return (NULL);
+ }
+ proc_info_set->proc_infos = newarray;
+ proc_info_set->proc_infos[proc_info_set->proc_info_count] = proc_info;
+ proc_info_set->proc_info_count += 1;
+
+ return (proc_info);
+}
+
+void
+pcap_clear_proc_infos(pcap_t * pcap)
+{
+ pcap_proc_info_set_clear(&pcap->proc_info_set);
+}
+
+struct pcap_proc_info *
+pcap_find_proc_info(pcap_t * pcap, uint32_t pid, const char *name)
+{
+ return (pcap_proc_info_set_find(&pcap->proc_info_set, pid, name));
+}
+
+struct pcap_proc_info *
+pcap_find_proc_info_uuid(pcap_t * pcap, uint32_t pid, const char *name, const uuid_t uu)
+{
+ return (pcap_proc_info_set_find_uuid(&pcap->proc_info_set, pid, name, uu));
+}
+
+struct pcap_proc_info *
+pcap_find_proc_info_by_index(pcap_t * pcap, uint32_t index)
+{
+ return (pcap_proc_info_set_find_by_index(&pcap->proc_info_set, index));
+}
+
+void
+pcap_free_proc_info(pcap_t * pcap, struct pcap_proc_info *proc_info)
+{
+ pcap_proc_info_set_free(&pcap->proc_info_set, proc_info);
+}
+
+struct pcap_proc_info *
+pcap_add_proc_info_uuid(pcap_t * pcap, uint32_t pid, const char *name, const uuid_t uu)
+{
+ struct pcap_proc_info *proc_info = NULL;
+
+ pcap->cleanup_extra_op = pcap_ng_init_section_info;
+
+ proc_info = pcap_proc_info_set_add_uuid(&pcap->proc_info_set,
+ pid, name,
+ uu,
+ pcap->errbuf);
+
+ return (proc_info);
+}
+
+
+struct pcap_proc_info *
+pcap_add_proc_info(pcap_t * pcap, uint32_t pid, const char *name)
+{
+ return (pcap_add_proc_info_uuid(pcap, pid, name, NULL));
+}
+
+int
+pcap_set_filter_info(pcap_t *pcap, const char *str, int optimize, bpf_u_int32 netmask)
+{
+ if (pcap->filter_str != NULL)
+ free(pcap->filter_str);
+
+ if (str == NULL) {
+ pcap->filter_str = NULL;
+ } else {
+ pcap->filter_str = strdup(str);
+ if (pcap->filter_str == NULL)
+ return (PCAP_ERROR);
+ }
+
+ return (0);
+}
+
+void
+pcap_ng_init_section_info(pcap_t *p)
+{
+ p->shb_added = 0;
+ pcap_clear_if_infos(p);
+ pcap_clear_proc_infos(p);
+}
+
diff --git a/lib/libpcap/libpcap/pcap-util.h b/lib/libpcap/libpcap/pcap-util.h
new file mode 100644
index 0000000..0018842
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap-util.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2012-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#ifndef libpcap_pcap_util_h
+#define libpcap_pcap_util_h
+
+#ifdef PRIVATE
+
+#include <stdbool.h>
+#include <pcap/pcap.h>
+#include <uuid/uuid.h>
+
+struct pcap_if_info {
+ int if_id;
+ int if_dump_id; /* may be different from if_id because of filtering */
+ char *if_name;
+ int if_linktype;
+ int if_snaplen;
+ struct bpf_program if_filter_program;
+ int if_block_dumped;
+};
+extern struct pcap_if_info * pcap_find_if_info_by_name(pcap_t *, const char *);
+extern struct pcap_if_info * pcap_find_if_info_by_id(pcap_t *, int);
+extern struct pcap_if_info * pcap_add_if_info(pcap_t *, const char *, int, int, int);
+extern void pcap_free_if_info(pcap_t *, struct pcap_if_info *);
+extern void pcap_clear_if_infos(pcap_t *);
+
+int pcap_set_filter_info(pcap_t *, const char *, int, bpf_u_int32);
+
+struct pcap_proc_info {
+ uint32_t proc_index;
+ uint32_t proc_dump_index; /* may be different from proc_index because of filtering */
+ uint32_t proc_pid;
+ char *proc_name;
+ int proc_block_dumped;
+ uuid_t proc_uuid;
+};
+extern struct pcap_proc_info * pcap_find_proc_info(pcap_t *, uint32_t, const char *);
+extern struct pcap_proc_info * pcap_find_proc_info_uuid(pcap_t *, uint32_t, const char *, const uuid_t);
+extern struct pcap_proc_info * pcap_find_proc_info_by_index(pcap_t *, uint32_t);
+extern struct pcap_proc_info * pcap_add_proc_info(pcap_t *, uint32_t, const char *);
+extern struct pcap_proc_info * pcap_add_proc_info_uuid(pcap_t *, uint32_t, const char *, const uuid_t);
+extern void pcap_free_proc_info(pcap_t *, struct pcap_proc_info *);
+extern void pcap_clear_proc_infos(pcap_t *);
+
+
+struct pcap_if_info_set {
+ int if_info_count;
+ struct pcap_if_info **if_infos;
+ int if_dump_id;
+};
+
+void pcap_if_info_set_clear(struct pcap_if_info_set *if_info_set);
+struct pcap_if_info * pcap_if_info_set_find_by_name(struct pcap_if_info_set *if_info_set, const char *name);
+struct pcap_if_info * pcap_if_info_set_find_by_id(struct pcap_if_info_set *if_info_set, int if_id);
+void pcap_if_info_set_free(struct pcap_if_info_set *if_info_set, struct pcap_if_info *if_info);
+struct pcap_if_info * pcap_if_info_set_add(struct pcap_if_info_set *if_info_set, const char *name,
+ int if_id, int linktype, int snaplen,
+ const char *filter_str, char *errbuf);
+
+struct pcap_proc_info_set {
+ int proc_info_count;
+ struct pcap_proc_info **proc_infos;
+ int proc_dump_index;
+
+};
+
+void pcap_proc_info_set_clear(struct pcap_proc_info_set *proc_info_set);
+struct pcap_proc_info * pcap_proc_info_set_find(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name);
+struct pcap_proc_info * pcap_proc_info_set_find_uuid(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name, const uuid_t uu);
+struct pcap_proc_info * pcap_proc_info_set_find_by_index(struct pcap_proc_info_set *proc_info_set,
+ uint32_t index);
+void pcap_proc_info_set_free(struct pcap_proc_info_set *proc_info_set,
+ struct pcap_proc_info *proc_info);
+struct pcap_proc_info * pcap_proc_info_set_add_uuid(struct pcap_proc_info_set *proc_info_set,
+ uint32_t pid, const char *name, const uuid_t uu, char *errbuf);
+
+/*
+ * To reset information that are specific to each section.
+ * Should be called when adding a new section header block.
+ */
+extern void pcap_ng_init_section_info(pcap_t *);
+
+extern char * pcap_setup_pktap_interface(const char *, char *);
+extern void pcap_cleanup_pktap_interface(const char *);
+
+extern int pcap_ng_dump_pktap(pcap_t *, pcap_dumper_t *, const struct pcap_pkthdr *, const u_char *);
+extern int pcap_ng_dump_pktap_comment(pcap_t *, pcap_dumper_t *, const struct pcap_pkthdr *, const u_char *, const char *);
+extern int pcap_ng_dump_pktap_v2(pcap_t *, pcap_dumper_t *, const struct pcap_pkthdr *, const u_char *, const char *);
+
+struct kern_event_msg;
+extern int pcap_ng_dump_kern_event(pcap_t *, pcap_dumper_t *,
+ struct kern_event_msg *, struct timeval *);
+
+extern struct pcap_if_info *pcap_ng_dump_if_info(pcap_t *, pcap_dumper_t *, pcapng_block_t,
+ struct pcap_if_info *);
+
+extern struct pcap_proc_info *pcap_ng_dump_proc_info(pcap_t *, pcap_dumper_t *, pcapng_block_t,
+ struct pcap_proc_info *);
+
+extern void pcap_ng_dump_init_section_info(pcap_dumper_t *);
+
+extern void pcap_read_bpf_header(pcap_t *p, u_char *bp, struct pcap_pkthdr *pkthdr);
+
+int pcap_set_truncation_mode(pcap_t *p, bool on);
+int pcap_set_pktap_hdr_v2(pcap_t *p, bool on);
+
+#endif /* PRIVATE */
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap.3pcap b/lib/libpcap/libpcap/pcap.3pcap
new file mode 100644
index 0000000..238f7d3
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap.3pcap
@@ -0,0 +1,982 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP 3PCAP "25 July 2018"
+.SH NAME
+pcap \- Packet Capture library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+.ft
+.fi
+.SH DESCRIPTION
+The Packet Capture library
+provides a high level interface to packet capture systems. All packets
+on the network, even those destined for other hosts, are accessible
+through this mechanism.
+It also supports saving captured packets to a ``savefile'', and reading
+packets from a ``savefile''.
+.SS Opening a capture handle for reading
+To open a handle for a live capture, given the name of the network or
+other interface on which the capture should be done, call
+.BR pcap_create (),
+set the appropriate options on the handle, and then activate it with
+.BR pcap_activate ().
+.PP
+To obtain a list of devices that can be opened for a live capture, call
+.BR pcap_findalldevs ();
+to free the list returned by
+.BR pcap_findalldevs (),
+call
+.BR pcap_freealldevs ().
+.BR pcap_lookupdev ()
+will return the first device on that list that is not a ``loopback``
+network interface.
+.PP
+To open a handle for a ``savefile'' from which to read packets, given the
+pathname of the ``savefile'', call
+.BR pcap_open_offline ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for reading, call
+.BR pcap_fopen_offline ().
+.PP
+In order to get a ``fake''
+.B pcap_t
+for use in routines that require a
+.B pcap_t
+as an argument, such as routines to open a ``savefile'' for writing and
+to compile a filter expression, call
+.BR pcap_open_dead ().
+.PP
+.BR pcap_create (),
+.BR pcap_open_offline (),
+.BR pcap_fopen_offline (),
+and
+.BR pcap_open_dead ()
+return a pointer to a
+.BR pcap_t ,
+which is the handle used for reading packets from the capture stream or
+the ``savefile'', and for finding out information about the capture
+stream or ``savefile''.
+To close a handle, use
+.BR pcap_close ().
+.PP
+The options that can be set on a capture handle include
+.IP "snapshot length"
+If, when capturing, you capture the entire contents of the packet, that
+requires more CPU time to copy the packet to your application, more disk
+and possibly network bandwidth to write the packet data to a file, and
+more disk space to save the packet. If you don't need the entire
+contents of the packet - for example, if you are only interested in the
+TCP headers of packets - you can set the "snapshot length" for the
+capture to an appropriate value. If the snapshot length is set to
+.IR snaplen ,
+and
+.I snaplen
+is less
+than the size of a packet that is captured, only the first
+.I snaplen
+bytes of that packet will be captured and provided as packet data.
+.IP
+A snapshot length of 65535 should be sufficient, on most if not all
+networks, to capture all the data available from the packet.
+.IP
+The snapshot length is set with
+.BR pcap_set_snaplen ().
+.IP "promiscuous mode"
+On broadcast LANs such as Ethernet, if the network isn't switched, or if
+the adapter is connected to a "mirror port" on a switch to which all
+packets passing through the switch are sent, a network adapter receives
+all packets on the LAN, including unicast or multicast packets not sent
+to a network address that the network adapter isn't configured to
+recognize.
+.IP
+Normally, the adapter will discard those packets; however, many network
+adapters support "promiscuous mode", which is a mode in which all
+packets, even if they are not sent to an address that the adapter
+recognizes, are provided to the host. This is useful for passively
+capturing traffic between two or more other hosts for analysis.
+.IP
+Note that even if an application does not set promiscuous mode, the
+adapter could well be in promiscuous mode for some other reason.
+.IP
+For now, this doesn't work on the "any" device; if an argument of "any"
+or NULL is supplied, the setting of promiscuous mode is ignored.
+.IP
+Promiscuous mode is set with
+.BR pcap_set_promisc ().
+.IP "monitor mode"
+On IEEE 802.11 wireless LANs, even if an adapter is in promiscuous mode,
+it will supply to the host only frames for the network with which it's
+associated. It might also supply only data frames, not management or
+control frames, and might not provide the 802.11 header or radio
+information pseudo-header for those frames.
+.IP
+In "monitor mode", sometimes also called "rfmon mode" (for "Radio
+Frequency MONitor"), the adapter will supply all frames that it
+receives, with 802.11 headers, and might supply a pseudo-header with
+radio information about the frame as well.
+.IP
+Note that in monitor mode the adapter might disassociate from the
+network with which it's associated, so that you will not be able to use
+any wireless networks with that adapter. This could prevent accessing
+files on a network server, or resolving host names or network addresses,
+if you are capturing in monitor mode and are not connected to another
+network with another adapter.
+.IP
+Monitor mode is set with
+.BR pcap_set_rfmon (),
+and
+.BR pcap_can_set_rfmon ()
+can be used to determine whether an adapter can be put into monitor
+mode.
+.IP "packet buffer timeout"
+If, when capturing, packets are delivered as soon as they arrive, the
+application capturing the packets will be woken up for each packet as it
+arrives, and might have to make one or more calls to the operating
+system to fetch each packet.
+.IP
+If, instead, packets are not delivered as soon as they arrive, but are
+delivered after a short delay (called a "packet buffer timeout"), more
+than one packet can be accumulated before the packets are delivered, so
+that a single wakeup would be done for multiple packets, and each set of
+calls made to the operating system would supply multiple packets, rather
+than a single packet. This reduces the per-packet CPU overhead if
+packets are arriving at a high rate, increasing the number of packets
+per second that can be captured.
+.IP
+The packet buffer timeout is required so that an application won't wait
+for the operating system's capture buffer to fill up before packets are
+delivered; if packets are arriving slowly, that wait could take an
+arbitrarily long period of time.
+.IP
+Not all platforms support a packet buffer timeout; on platforms that
+don't, the packet buffer timeout is ignored. A zero value for the
+timeout, on platforms that support a packet buffer timeout, will cause a
+read to wait forever to allow enough packets to arrive, with no timeout.
+A negative value is invalid; the result of setting the timeout to a
+negative value is unpredictable.
+.IP
+.BR NOTE :
+the packet buffer timeout cannot be used to cause calls that read
+packets to return within a limited period of time, because, on some
+platforms, the packet buffer timeout isn't supported, and, on other
+platforms, the timer doesn't start until at least one packet arrives.
+This means that the packet buffer timeout should
+.B NOT
+be used, for example, in an interactive application to allow the packet
+capture loop to ``poll'' for user input periodically, as there's no
+guarantee that a call reading packets will return after the timeout
+expires even if no packets have arrived.
+.IP
+The packet buffer timeout is set with
+.BR pcap_set_timeout ().
+.IP "immediate mode"
+In immediate mode, packets are always delivered as soon as they arrive,
+with no buffering. Immediate mode is set with
+.BR pcap_set_immediate_mode ().
+.IP "buffer size"
+Packets that arrive for a capture are stored in a buffer, so that they
+do not have to be read by the application as soon as they arrive. On
+some platforms, the buffer's size can be set; a size that's too small
+could mean that, if too many packets are being captured and the snapshot
+length doesn't limit the amount of data that's buffered, packets could
+be dropped if the buffer fills up before the application can read
+packets from it, while a size that's too large could use more
+non-pageable operating system memory than is necessary to prevent
+packets from being dropped.
+.IP
+The buffer size is set with
+.BR pcap_set_buffer_size ().
+.IP "timestamp type"
+On some platforms, the time stamp given to packets on live captures can
+come from different sources that can have different resolutions or that
+can have different relationships to the time values for the current time
+supplied by routines on the native operating system. See
+.BR pcap-tstamp (7)
+for a list of time stamp types.
+.IP
+The time stamp type is set with
+.BR pcap_set_tstamp_type ().
+.PP
+Reading packets from a network interface may require that you have
+special privileges:
+.TP
+.B Under SunOS 3.x or 4.x with NIT or BPF:
+You must have read access to
+.I /dev/nit
+or
+.IR /dev/bpf* .
+.TP
+.B Under Solaris with DLPI:
+You must have read/write access to the network pseudo device, e.g.
+.IR /dev/le .
+On at least some versions of Solaris, however, this is not sufficient to
+allow
+.I tcpdump
+to capture in promiscuous mode; on those versions of Solaris, you must
+be root, or the application capturing packets
+must be installed setuid to root, in order to capture in promiscuous
+mode. Note that, on many (perhaps all) interfaces, if you don't capture
+in promiscuous mode, you will not see any outgoing packets, so a capture
+not done in promiscuous mode may not be very useful.
+.IP
+In newer versions of Solaris, you must have been given the
+.B net_rawaccess
+privilege; this is both necessary and sufficient to give you access to the
+network pseudo-device - there is no need to change the privileges on
+that device. A user can be given that privilege by, for example, adding
+that privilege to the user's
+.B defaultpriv
+key with the
+.B usermod (8)
+command.
+.TP
+.B Under HP-UX with DLPI:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under IRIX with snoop:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under Linux:
+You must be root or the application capturing packets must be installed
+setuid to root (unless your distribution has a kernel
+that supports capability bits such as CAP_NET_RAW and code to allow
+those capability bits to be given to particular accounts and to cause
+those bits to be set on a user's initial processes when they log in, in
+which case you must have CAP_NET_RAW in order to capture and
+CAP_NET_ADMIN to enumerate network devices with, for example, the
+.B \-D
+flag).
+.TP
+.B Under ULTRIX and Digital UNIX/Tru64 UNIX:
+Any user may capture network traffic.
+However, no user (not even the super-user) can capture in promiscuous
+mode on an interface unless the super-user has enabled promiscuous-mode
+operation on that interface using
+.IR pfconfig (8),
+and no user (not even the super-user) can capture unicast traffic
+received by or sent by the machine on an interface unless the super-user
+has enabled copy-all-mode operation on that interface using
+.IR pfconfig ,
+so
+.I useful
+packet capture on an interface probably requires that either
+promiscuous-mode or copy-all-mode operation, or both modes of
+operation, be enabled on that interface.
+.TP
+.B Under BSD (this includes macOS):
+You must have read access to
+.I /dev/bpf*
+on systems that don't have a cloning BPF device, or to
+.I /dev/bpf
+on systems that do.
+On BSDs with a devfs (this includes macOS), this might involve more
+than just having somebody with super-user access setting the ownership
+or permissions on the BPF devices - it might involve configuring devfs
+to set the ownership or permissions every time the system is booted,
+if the system even supports that; if it doesn't support that, you might
+have to find some other way to make that happen at boot time.
+.PP
+Reading a saved packet file doesn't require special privileges.
+.PP
+The packets read from the handle may include a ``pseudo-header''
+containing various forms of packet meta-data, and probably includes a
+link-layer header whose contents can differ for different network
+interfaces. To determine the format of the packets supplied by the
+handle, call
+.BR pcap_datalink ();
+.I https://www.tcpdump.org/linktypes.html
+lists the values it returns and describes the packet formats that
+correspond to those values.
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet. For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.PP
+To obtain the
+.B "FILE\ *"
+corresponding to a
+.B pcap_t
+opened for a ``savefile'', call
+.BR pcap_file ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_create (3PCAP)
+get a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_activate (3PCAP)
+activate a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_findalldevs (3PCAP)
+get a list of devices that can be opened for a live capture
+.TP
+.BR pcap_freealldevs (3PCAP)
+free list of devices
+.TP
+.BR pcap_lookupdev (3PCAP)
+get first non-loopback device on that list
+.TP
+.BR pcap_open_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname
+.TP
+.BR pcap_open_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname, and specify the precision to
+provide for packet time stamps
+.TP
+.BR pcap_fopen_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.B "FILE\ *"
+.TP
+.BR pcap_fopen_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.BR "FILE\ *" ,
+and specify the precision to provide for packet time stamps
+.TP
+.BR pcap_open_dead (3PCAP)
+create a ``fake''
+.B pcap_t
+.TP
+.BR pcap_close (3PCAP)
+close a
+.B pcap_t
+.TP
+.BR pcap_set_snaplen (3PCAP)
+set the snapshot length for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_snapshot (3PCAP)
+get the snapshot length for a
+.B pcap_t
+.TP
+.BR pcap_set_promisc (3PCAP)
+set promiscuous mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_protocol_linux (3PCAP)
+set capture protocol for a not-yet-activated
+.B pcap_t
+for live capture (Linux only)
+.TP
+.BR pcap_set_rfmon (3PCAP)
+set monitor mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_can_set_rfmon (3PCAP)
+determine whether monitor mode can be set for a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_timeout (3PCAP)
+set packet buffer timeout for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_immediate_mode (3PCAP)
+set immediate mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_buffer_size (3PCAP)
+set buffer size for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_tstamp_type (3PCAP)
+set time stamp type for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_list_tstamp_types (3PCAP)
+get list of available time stamp types for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_free_tstamp_types (3PCAP)
+free list of available time stamp types
+.TP
+.BR pcap_tstamp_type_val_to_name (3PCAP)
+get name for a time stamp type
+.TP
+.BR pcap_tstamp_type_val_to_description (3PCAP)
+get description for a time stamp type
+.TP
+.BR pcap_tstamp_type_name_to_val (3PCAP)
+get time stamp type corresponding to a name
+.TP
+.BR pcap_set_tstamp_precision (3PCAP)
+set time stamp precision for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_get_tstamp_precision (3PCAP)
+get the time stamp precision of a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_datalink (3PCAP)
+get link-layer header type for a
+.B pcap_t
+.TP
+.BR pcap_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_t
+opened for a ``savefile''
+.TP
+.BR pcap_is_swapped (3PCAP)
+determine whether a ``savefile'' being read came from a machine with the
+opposite byte order
+.TP
+.BR pcap_major_version (3PCAP)
+.PD 0
+.TP
+.BR pcap_minor_version (3PCAP)
+get the major and minor version of the file format version for a
+``savefile''
+.PD
+.RE
+.SS Selecting a link-layer header type for a live capture
+Some devices may provide more than one link-layer header type. To
+obtain a list of all link-layer header types provided by a device, call
+.BR pcap_list_datalinks ()
+on an activated
+.B pcap_t
+for the device.
+To free a list of link-layer header types, call
+.BR pcap_free_datalinks ().
+To set the link-layer header type for a device, call
+.BR pcap_set_datalink ().
+This should be done after the device has been activated but before any
+packets are read and before any filters are compiled or installed.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_list_datalinks (3PCAP)
+get a list of link-layer header types for a device
+.TP
+.BR pcap_free_datalinks (3PCAP)
+free list of link-layer header types
+.TP
+.BR pcap_set_datalink (3PCAP)
+set link-layer header type for a device
+.TP
+.BR pcap_datalink_val_to_name (3PCAP)
+get name for a link-layer header type
+.TP
+.BR pcap_datalink_val_to_description (3PCAP)
+get description for a link-layer header type
+.TP
+.BR pcap_datalink_name_to_val (3PCAP)
+get link-layer header type corresponding to a name
+.RE
+.SS Reading packets
+Packets are read with
+.BR pcap_dispatch ()
+or
+.BR pcap_loop (),
+which process one or more packets, calling a callback routine for each
+packet, or with
+.BR pcap_next ()
+or
+.BR pcap_next_ex (),
+which return the next packet.
+The callback for
+.BR pcap_dispatch ()
+and
+.BR pcap_loop ()
+is supplied a pointer to a
+.IR "struct pcap_pkthdr" ,
+which includes the following members:
+.RS
+.TP
+.B ts
+a
+.I struct timeval
+containing the time when the packet was captured
+.TP
+.B caplen
+a
+.I bpf_u_int32
+giving the number of bytes of the packet that are available from the
+capture
+.TP
+.B len
+a
+.I bpf_u_int32
+giving the length of the packet, in bytes (which might be more than the
+number of bytes available from the capture, if the length of the packet
+is larger than the maximum number of bytes to capture).
+.RE
+.PP
+The callback is also supplied a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+mentioned above)
+bytes of data from the packet. This won't necessarily be the entire
+packet; to capture the entire packet, you will have to provide a value
+for
+.I snaplen
+in your call to
+.BR pcap_set_snaplen ()
+that is sufficiently large to get all of the packet's data - a value of
+65535 should be sufficient on most if not all networks). When reading
+from a ``savefile'', the snapshot length specified when the capture was
+performed will limit the amount of packet data available.
+.PP
+.BR pcap_next ()
+is passed an argument that points to a
+.I struct pcap_pkthdr
+structure, and fills it in with the time stamp and length values for the
+packet. It returns a
+.I const u_char
+to the first
+.B caplen
+bytes of the packet on success, and NULL on error.
+.PP
+.BR pcap_next_ex ()
+is passed two pointer arguments, one of which points to a
+.IR struct pcap_pkthdr *
+and one of which points to a
+.IR "const u_char" *.
+It sets the first pointer to point to a
+.I struct pcap_pkthdr
+structure with the time stamp and length values for the packet, and sets
+the second pointer to point to the first
+.B caplen
+bytes of the packet.
+.PP
+To force the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+to terminate, call
+.BR pcap_breakloop ().
+.PP
+By default, when reading packets from an interface opened for a live
+capture,
+.BR pcap_dispatch (),
+.BR pcap_next (),
+and
+.BR pcap_next_ex ()
+will, if no packets are currently available to be read, block waiting
+for packets to become available. On some, but
+.I not
+all, platforms, if a packet buffer timeout was specified, the wait will
+terminate after the packet buffer timeout expires; applications should
+be prepared for this, as it happens on some platforms, but should not
+rely on it, as it does not happen on other platforms. Note that the
+wait might, or might not, terminate even if no packets are available;
+applications should be prepared for this to happen, but must not rely on
+it happening.
+.PP
+A handle can be put into ``non-blocking mode'', so that those routines
+will, rather than blocking, return an indication that no packets are
+available to read. Call
+.BR pcap_setnonblock ()
+to put a handle into non-blocking mode or to take it out of non-blocking
+mode; call
+.BR pcap_getnonblock ()
+to determine whether a handle is in non-blocking mode. Note that
+non-blocking mode does not work correctly in Mac OS X 10.6.
+.PP
+Non-blocking mode is often combined with routines such as
+.BR select (2)
+or
+.BR poll (2)
+or other routines a platform offers to wait for any of a set of
+descriptors to be ready to read. To obtain, for a handle, a descriptor
+that can be used in those routines, call
+.BR pcap_get_selectable_fd ().
+If the routine indicates that data is
+available to read on the descriptor, an attempt should be made to read
+from the device.
+.PP
+Not all handles have such a descriptor available;
+.BR pcap_get_selectable_fd ()
+will return
+.B PCAP_ERROR
+if no such descriptor is available. If no such
+descriptor is available, this may be because the device must be polled
+periodically for packets; in that case,
+.BR pcap_get_required_select_timeout ()
+will return a pointer to a
+.B struct timeval
+whose value can be used as a timeout in those routines. When the
+routine returns, an attmept should be made to read packets from the
+device. If
+.BR pcap_get_required_select_timeout ()
+returns NULL, no such timeout is available, and those routines cannot be
+used with the device.
+.PP
+In addition, for various
+reasons, one or more of those routines will not work properly with the
+descriptor; the documentation for
+.BR pcap_get_selectable_fd ()
+gives details. Note that, just as an attempt to read packets from a
+.B pcap_t
+may not return any packets if the packet buffer timeout expires, a
+.BR select (),
+.BR poll (),
+or other such call may, if the packet buffer timeout expires, indicate
+that a descriptor is ready to read even if there are no packets
+available to read.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dispatch (3PCAP)
+read a bufferful of packets from a
+.B pcap_t
+open for a live capture or the full set of packets from a
+.B pcap_t
+open for a ``savefile''
+.TP
+.BR pcap_loop (3PCAP)
+read packets from a
+.B pcap_t
+until an interrupt or error occurs
+.TP
+.BR pcap_next (3PCAP)
+read the next packet from a
+.B pcap_t
+without an indication whether an error occurred
+.TP
+.BR pcap_next_ex (3PCAP)
+read the next packet from a
+.B pcap_t
+with an error indication on an error
+.TP
+.BR pcap_breakloop (3PCAP)
+prematurely terminate the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+.TP
+.BR pcap_setnonblock (3PCAP)
+set or clear non-blocking mode on a
+.B pcap_t
+.TP
+.BR pcap_getnonblock (3PCAP)
+get the state of non-blocking mode for a
+.B pcap_t
+.TP
+.BR pcap_get_selectable_fd (3PCAP)
+attempt to get a descriptor for a
+.B pcap_t
+that can be used in calls such as
+.BR select (2)
+and
+.BR poll (2)
+.TP
+.BR pcap_get_required_select_timeout (3PCAP)
+if no descriptor usable with
+.BR select (2)
+and
+.BR poll (2)
+is available for the
+.BR pcap_t ,
+attempt to get a timeout usable with those routines
+.RE
+.SS Filters
+In order to cause only certain packets to be returned when reading
+packets, a filter can be set on a handle. For a live capture, the
+filtering will be performed in kernel mode, if possible, to avoid
+copying ``uninteresting'' packets from the kernel to user mode.
+.PP
+A filter can be specified as a text string; the syntax and semantics of
+the string are as described by
+.BR pcap-filter (7).
+A filter string is compiled into a program in a pseudo-machine-language
+by
+.BR pcap_compile ()
+and the resulting program can be made a filter for a handle with
+.BR pcap_setfilter ().
+The result of
+.BR pcap_compile ()
+can be freed with a call to
+.BR pcap_freecode ().
+.BR pcap_compile ()
+may require a network mask for certain expressions in the filter string;
+.BR pcap_lookupnet ()
+can be used to find the network address and network mask for a given
+capture device.
+.PP
+A compiled filter can also be applied directly to a packet that has been
+read using
+.BR pcap_offline_filter ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_compile (3PCAP)
+compile filter expression to a pseudo-machine-language code program
+.TP
+.BR pcap_freecode (3PCAP)
+free a filter program
+.TP
+.BR pcap_setfilter (3PCAP)
+set filter for a
+.B pcap_t
+.TP
+.BR pcap_lookupnet (3PCAP)
+get network address and network mask for a capture device
+.TP
+.BR pcap_offline_filter (3PCAP)
+apply a filter program to a packet
+.RE
+.SS Incoming and outgoing packets
+By default, libpcap will attempt to capture both packets sent by the
+machine and packets received by the machine. To limit it to capturing
+only packets received by the machine or, if possible, only packets sent
+by the machine, call
+.BR pcap_setdirection ().
+.TP
+.BR Routines
+.RS
+.TP
+.BR pcap_setdirection (3PCAP)
+specify whether to capture incoming packets, outgoing packets, or both
+.RE
+.SS Capture statistics
+To get statistics about packets received and dropped in a live capture,
+call
+.BR pcap_stats ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_stats (3PCAP)
+get capture statistics
+.RE
+.SS Opening a handle for writing captured packets
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ().
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for writing, call
+.BR pcap_dump_fopen ().
+They each return pointers to a
+.BR pcap_dumper_t ,
+which is the handle used for writing packets to the ``savefile''. If it
+succeeds, it will have created the file if it doesn't exist and
+truncated the file if it does exist.
+To close a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_close ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump_open (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a pathname
+.TP
+.BR pcap_dump_fopen (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a
+.B "FILE\ *"
+.TP
+.BR pcap_dump_close (3PCAP)
+close a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_dumper_t
+opened for a ``savefile''
+.RE
+.SS Writing packets
+To write a packet to a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump ().
+Packets written with
+.BR pcap_dump ()
+may be buffered, rather than being immediately written to the
+``savefile''. Closing the
+.B pcap_dumper_t
+will cause all buffered-but-not-yet-written packets to be written to the
+``savefile''.
+To force all packets written to the
+.BR pcap_dumper_t ,
+and not yet written to the ``savefile'' because they're buffered by the
+.BR pcap_dumper_t ,
+to be written to the ``savefile'', without closing the
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_flush ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump (3PCAP)
+write packet to a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_flush (3PCAP)
+flush buffered packets written to a
+.B pcap_dumper_t
+to the ``savefile''
+.TP
+.BR pcap_dump_ftell (3PCAP)
+get current file position for a
+.B pcap_dumper_t
+.RE
+.SS Injecting packets
+If you have the required privileges, you can inject packets onto a
+network with a
+.B pcap_t
+for a live capture, using
+.BR pcap_inject ()
+or
+.BR pcap_sendpacket ().
+(The two routines exist for compatibility with both OpenBSD and WinPcap;
+they perform the same function, but have different return values.)
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_inject (3PCAP)
+.PD 0
+.TP
+.BR pcap_sendpacket (3PCAP)
+transmit a packet
+.PD
+.RE
+.SS Reporting errors
+Some routines return error or warning status codes; to convert them to a
+string, use
+.BR pcap_statustostr ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_statustostr (3PCAP)
+get a string for an error or warning status code
+.RE
+.SS Getting library version information
+To get a string giving version information about libpcap, call
+.BR pcap_lib_version ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_lib_version (3PCAP)
+get library version string
+.RE
+.SH BACKWARD COMPATIBILITY
+.PP
+In versions of libpcap prior to 1.0, the
+.B pcap.h
+header file was not in a
+.B pcap
+directory on most platforms; if you are writing an application that must
+work on versions of libpcap prior to 1.0, include
+.BR <pcap.h> ,
+which will include
+.B <pcap/pcap.h>
+for you, rather than including
+.BR <pcap/pcap.h> .
+.PP
+.BR pcap_create ()
+and
+.BR pcap_activate ()
+were not available in versions of libpcap prior to 1.0; if you are
+writing an application that must work on versions of libpcap prior to
+1.0, either use
+.BR pcap_open_live ()
+to get a handle for a live capture or, if you want to be able to use the
+additional capabilities offered by using
+.BR pcap_create ()
+and
+.BR pcap_activate (),
+use an
+.BR autoconf (1)
+script or some other configuration script to check whether the libpcap
+1.0 APIs are available and use them only if they are.
+.SH SEE ALSO
+autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(7), pfconfig(8),
+usermod(8)
+.SH AUTHORS
+The original authors of libpcap are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+The current version is available from "The Tcpdump Group"'s Web site at
+.LP
+.RS
+.I https://www.tcpdump.org/
+.RE
+.SH BUGS
+To report a security issue please send an e-mail to security@tcpdump.org.
+.LP
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+.I CONTRIBUTING
+in the libpcap source tree root.
diff --git a/lib/libpcap/libpcap/pcap.3pcap.in b/lib/libpcap/libpcap/pcap.3pcap.in
new file mode 100644
index 0000000..8010140
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap.3pcap.in
@@ -0,0 +1,982 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP 3PCAP "25 July 2018"
+.SH NAME
+pcap \- Packet Capture library
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+.ft
+.fi
+.SH DESCRIPTION
+The Packet Capture library
+provides a high level interface to packet capture systems. All packets
+on the network, even those destined for other hosts, are accessible
+through this mechanism.
+It also supports saving captured packets to a ``savefile'', and reading
+packets from a ``savefile''.
+.SS Opening a capture handle for reading
+To open a handle for a live capture, given the name of the network or
+other interface on which the capture should be done, call
+.BR pcap_create (),
+set the appropriate options on the handle, and then activate it with
+.BR pcap_activate ().
+.PP
+To obtain a list of devices that can be opened for a live capture, call
+.BR pcap_findalldevs ();
+to free the list returned by
+.BR pcap_findalldevs (),
+call
+.BR pcap_freealldevs ().
+.BR pcap_lookupdev ()
+will return the first device on that list that is not a ``loopback``
+network interface.
+.PP
+To open a handle for a ``savefile'' from which to read packets, given the
+pathname of the ``savefile'', call
+.BR pcap_open_offline ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for reading, call
+.BR pcap_fopen_offline ().
+.PP
+In order to get a ``fake''
+.B pcap_t
+for use in routines that require a
+.B pcap_t
+as an argument, such as routines to open a ``savefile'' for writing and
+to compile a filter expression, call
+.BR pcap_open_dead ().
+.PP
+.BR pcap_create (),
+.BR pcap_open_offline (),
+.BR pcap_fopen_offline (),
+and
+.BR pcap_open_dead ()
+return a pointer to a
+.BR pcap_t ,
+which is the handle used for reading packets from the capture stream or
+the ``savefile'', and for finding out information about the capture
+stream or ``savefile''.
+To close a handle, use
+.BR pcap_close ().
+.PP
+The options that can be set on a capture handle include
+.IP "snapshot length"
+If, when capturing, you capture the entire contents of the packet, that
+requires more CPU time to copy the packet to your application, more disk
+and possibly network bandwidth to write the packet data to a file, and
+more disk space to save the packet. If you don't need the entire
+contents of the packet - for example, if you are only interested in the
+TCP headers of packets - you can set the "snapshot length" for the
+capture to an appropriate value. If the snapshot length is set to
+.IR snaplen ,
+and
+.I snaplen
+is less
+than the size of a packet that is captured, only the first
+.I snaplen
+bytes of that packet will be captured and provided as packet data.
+.IP
+A snapshot length of 65535 should be sufficient, on most if not all
+networks, to capture all the data available from the packet.
+.IP
+The snapshot length is set with
+.BR pcap_set_snaplen ().
+.IP "promiscuous mode"
+On broadcast LANs such as Ethernet, if the network isn't switched, or if
+the adapter is connected to a "mirror port" on a switch to which all
+packets passing through the switch are sent, a network adapter receives
+all packets on the LAN, including unicast or multicast packets not sent
+to a network address that the network adapter isn't configured to
+recognize.
+.IP
+Normally, the adapter will discard those packets; however, many network
+adapters support "promiscuous mode", which is a mode in which all
+packets, even if they are not sent to an address that the adapter
+recognizes, are provided to the host. This is useful for passively
+capturing traffic between two or more other hosts for analysis.
+.IP
+Note that even if an application does not set promiscuous mode, the
+adapter could well be in promiscuous mode for some other reason.
+.IP
+For now, this doesn't work on the "any" device; if an argument of "any"
+or NULL is supplied, the setting of promiscuous mode is ignored.
+.IP
+Promiscuous mode is set with
+.BR pcap_set_promisc ().
+.IP "monitor mode"
+On IEEE 802.11 wireless LANs, even if an adapter is in promiscuous mode,
+it will supply to the host only frames for the network with which it's
+associated. It might also supply only data frames, not management or
+control frames, and might not provide the 802.11 header or radio
+information pseudo-header for those frames.
+.IP
+In "monitor mode", sometimes also called "rfmon mode" (for "Radio
+Frequency MONitor"), the adapter will supply all frames that it
+receives, with 802.11 headers, and might supply a pseudo-header with
+radio information about the frame as well.
+.IP
+Note that in monitor mode the adapter might disassociate from the
+network with which it's associated, so that you will not be able to use
+any wireless networks with that adapter. This could prevent accessing
+files on a network server, or resolving host names or network addresses,
+if you are capturing in monitor mode and are not connected to another
+network with another adapter.
+.IP
+Monitor mode is set with
+.BR pcap_set_rfmon (),
+and
+.BR pcap_can_set_rfmon ()
+can be used to determine whether an adapter can be put into monitor
+mode.
+.IP "packet buffer timeout"
+If, when capturing, packets are delivered as soon as they arrive, the
+application capturing the packets will be woken up for each packet as it
+arrives, and might have to make one or more calls to the operating
+system to fetch each packet.
+.IP
+If, instead, packets are not delivered as soon as they arrive, but are
+delivered after a short delay (called a "packet buffer timeout"), more
+than one packet can be accumulated before the packets are delivered, so
+that a single wakeup would be done for multiple packets, and each set of
+calls made to the operating system would supply multiple packets, rather
+than a single packet. This reduces the per-packet CPU overhead if
+packets are arriving at a high rate, increasing the number of packets
+per second that can be captured.
+.IP
+The packet buffer timeout is required so that an application won't wait
+for the operating system's capture buffer to fill up before packets are
+delivered; if packets are arriving slowly, that wait could take an
+arbitrarily long period of time.
+.IP
+Not all platforms support a packet buffer timeout; on platforms that
+don't, the packet buffer timeout is ignored. A zero value for the
+timeout, on platforms that support a packet buffer timeout, will cause a
+read to wait forever to allow enough packets to arrive, with no timeout.
+A negative value is invalid; the result of setting the timeout to a
+negative value is unpredictable.
+.IP
+.BR NOTE :
+the packet buffer timeout cannot be used to cause calls that read
+packets to return within a limited period of time, because, on some
+platforms, the packet buffer timeout isn't supported, and, on other
+platforms, the timer doesn't start until at least one packet arrives.
+This means that the packet buffer timeout should
+.B NOT
+be used, for example, in an interactive application to allow the packet
+capture loop to ``poll'' for user input periodically, as there's no
+guarantee that a call reading packets will return after the timeout
+expires even if no packets have arrived.
+.IP
+The packet buffer timeout is set with
+.BR pcap_set_timeout ().
+.IP "immediate mode"
+In immediate mode, packets are always delivered as soon as they arrive,
+with no buffering. Immediate mode is set with
+.BR pcap_set_immediate_mode ().
+.IP "buffer size"
+Packets that arrive for a capture are stored in a buffer, so that they
+do not have to be read by the application as soon as they arrive. On
+some platforms, the buffer's size can be set; a size that's too small
+could mean that, if too many packets are being captured and the snapshot
+length doesn't limit the amount of data that's buffered, packets could
+be dropped if the buffer fills up before the application can read
+packets from it, while a size that's too large could use more
+non-pageable operating system memory than is necessary to prevent
+packets from being dropped.
+.IP
+The buffer size is set with
+.BR pcap_set_buffer_size ().
+.IP "timestamp type"
+On some platforms, the time stamp given to packets on live captures can
+come from different sources that can have different resolutions or that
+can have different relationships to the time values for the current time
+supplied by routines on the native operating system. See
+.BR pcap-tstamp (@MAN_MISC_INFO@)
+for a list of time stamp types.
+.IP
+The time stamp type is set with
+.BR pcap_set_tstamp_type ().
+.PP
+Reading packets from a network interface may require that you have
+special privileges:
+.TP
+.B Under SunOS 3.x or 4.x with NIT or BPF:
+You must have read access to
+.I /dev/nit
+or
+.IR /dev/bpf* .
+.TP
+.B Under Solaris with DLPI:
+You must have read/write access to the network pseudo device, e.g.
+.IR /dev/le .
+On at least some versions of Solaris, however, this is not sufficient to
+allow
+.I tcpdump
+to capture in promiscuous mode; on those versions of Solaris, you must
+be root, or the application capturing packets
+must be installed setuid to root, in order to capture in promiscuous
+mode. Note that, on many (perhaps all) interfaces, if you don't capture
+in promiscuous mode, you will not see any outgoing packets, so a capture
+not done in promiscuous mode may not be very useful.
+.IP
+In newer versions of Solaris, you must have been given the
+.B net_rawaccess
+privilege; this is both necessary and sufficient to give you access to the
+network pseudo-device - there is no need to change the privileges on
+that device. A user can be given that privilege by, for example, adding
+that privilege to the user's
+.B defaultpriv
+key with the
+.B usermod (@MAN_ADMIN_COMMANDS@)
+command.
+.TP
+.B Under HP-UX with DLPI:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under IRIX with snoop:
+You must be root or the application capturing packets must be installed
+setuid to root.
+.TP
+.B Under Linux:
+You must be root or the application capturing packets must be installed
+setuid to root (unless your distribution has a kernel
+that supports capability bits such as CAP_NET_RAW and code to allow
+those capability bits to be given to particular accounts and to cause
+those bits to be set on a user's initial processes when they log in, in
+which case you must have CAP_NET_RAW in order to capture and
+CAP_NET_ADMIN to enumerate network devices with, for example, the
+.B \-D
+flag).
+.TP
+.B Under ULTRIX and Digital UNIX/Tru64 UNIX:
+Any user may capture network traffic.
+However, no user (not even the super-user) can capture in promiscuous
+mode on an interface unless the super-user has enabled promiscuous-mode
+operation on that interface using
+.IR pfconfig (8),
+and no user (not even the super-user) can capture unicast traffic
+received by or sent by the machine on an interface unless the super-user
+has enabled copy-all-mode operation on that interface using
+.IR pfconfig ,
+so
+.I useful
+packet capture on an interface probably requires that either
+promiscuous-mode or copy-all-mode operation, or both modes of
+operation, be enabled on that interface.
+.TP
+.B Under BSD (this includes macOS):
+You must have read access to
+.I /dev/bpf*
+on systems that don't have a cloning BPF device, or to
+.I /dev/bpf
+on systems that do.
+On BSDs with a devfs (this includes macOS), this might involve more
+than just having somebody with super-user access setting the ownership
+or permissions on the BPF devices - it might involve configuring devfs
+to set the ownership or permissions every time the system is booted,
+if the system even supports that; if it doesn't support that, you might
+have to find some other way to make that happen at boot time.
+.PP
+Reading a saved packet file doesn't require special privileges.
+.PP
+The packets read from the handle may include a ``pseudo-header''
+containing various forms of packet meta-data, and probably includes a
+link-layer header whose contents can differ for different network
+interfaces. To determine the format of the packets supplied by the
+handle, call
+.BR pcap_datalink ();
+.I https://www.tcpdump.org/linktypes.html
+lists the values it returns and describes the packet formats that
+correspond to those values.
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet. For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.PP
+To obtain the
+.B "FILE\ *"
+corresponding to a
+.B pcap_t
+opened for a ``savefile'', call
+.BR pcap_file ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_create (3PCAP)
+get a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_activate (3PCAP)
+activate a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_findalldevs (3PCAP)
+get a list of devices that can be opened for a live capture
+.TP
+.BR pcap_freealldevs (3PCAP)
+free list of devices
+.TP
+.BR pcap_lookupdev (3PCAP)
+get first non-loopback device on that list
+.TP
+.BR pcap_open_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname
+.TP
+.BR pcap_open_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a pathname, and specify the precision to
+provide for packet time stamps
+.TP
+.BR pcap_fopen_offline (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.B "FILE\ *"
+.TP
+.BR pcap_fopen_offline_with_tstamp_precision (3PCAP)
+open a
+.B pcap_t
+for a ``savefile'', given a
+.BR "FILE\ *" ,
+and specify the precision to provide for packet time stamps
+.TP
+.BR pcap_open_dead (3PCAP)
+create a ``fake''
+.B pcap_t
+.TP
+.BR pcap_close (3PCAP)
+close a
+.B pcap_t
+.TP
+.BR pcap_set_snaplen (3PCAP)
+set the snapshot length for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_snapshot (3PCAP)
+get the snapshot length for a
+.B pcap_t
+.TP
+.BR pcap_set_promisc (3PCAP)
+set promiscuous mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_protocol_linux (3PCAP)
+set capture protocol for a not-yet-activated
+.B pcap_t
+for live capture (Linux only)
+.TP
+.BR pcap_set_rfmon (3PCAP)
+set monitor mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_can_set_rfmon (3PCAP)
+determine whether monitor mode can be set for a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_timeout (3PCAP)
+set packet buffer timeout for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_immediate_mode (3PCAP)
+set immediate mode for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_buffer_size (3PCAP)
+set buffer size for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_set_tstamp_type (3PCAP)
+set time stamp type for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_list_tstamp_types (3PCAP)
+get list of available time stamp types for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_free_tstamp_types (3PCAP)
+free list of available time stamp types
+.TP
+.BR pcap_tstamp_type_val_to_name (3PCAP)
+get name for a time stamp type
+.TP
+.BR pcap_tstamp_type_val_to_description (3PCAP)
+get description for a time stamp type
+.TP
+.BR pcap_tstamp_type_name_to_val (3PCAP)
+get time stamp type corresponding to a name
+.TP
+.BR pcap_set_tstamp_precision (3PCAP)
+set time stamp precision for a not-yet-activated
+.B pcap_t
+for live capture
+.TP
+.BR pcap_get_tstamp_precision (3PCAP)
+get the time stamp precision of a
+.B pcap_t
+for live capture
+.TP
+.BR pcap_datalink (3PCAP)
+get link-layer header type for a
+.B pcap_t
+.TP
+.BR pcap_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_t
+opened for a ``savefile''
+.TP
+.BR pcap_is_swapped (3PCAP)
+determine whether a ``savefile'' being read came from a machine with the
+opposite byte order
+.TP
+.BR pcap_major_version (3PCAP)
+.PD 0
+.TP
+.BR pcap_minor_version (3PCAP)
+get the major and minor version of the file format version for a
+``savefile''
+.PD
+.RE
+.SS Selecting a link-layer header type for a live capture
+Some devices may provide more than one link-layer header type. To
+obtain a list of all link-layer header types provided by a device, call
+.BR pcap_list_datalinks ()
+on an activated
+.B pcap_t
+for the device.
+To free a list of link-layer header types, call
+.BR pcap_free_datalinks ().
+To set the link-layer header type for a device, call
+.BR pcap_set_datalink ().
+This should be done after the device has been activated but before any
+packets are read and before any filters are compiled or installed.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_list_datalinks (3PCAP)
+get a list of link-layer header types for a device
+.TP
+.BR pcap_free_datalinks (3PCAP)
+free list of link-layer header types
+.TP
+.BR pcap_set_datalink (3PCAP)
+set link-layer header type for a device
+.TP
+.BR pcap_datalink_val_to_name (3PCAP)
+get name for a link-layer header type
+.TP
+.BR pcap_datalink_val_to_description (3PCAP)
+get description for a link-layer header type
+.TP
+.BR pcap_datalink_name_to_val (3PCAP)
+get link-layer header type corresponding to a name
+.RE
+.SS Reading packets
+Packets are read with
+.BR pcap_dispatch ()
+or
+.BR pcap_loop (),
+which process one or more packets, calling a callback routine for each
+packet, or with
+.BR pcap_next ()
+or
+.BR pcap_next_ex (),
+which return the next packet.
+The callback for
+.BR pcap_dispatch ()
+and
+.BR pcap_loop ()
+is supplied a pointer to a
+.IR "struct pcap_pkthdr" ,
+which includes the following members:
+.RS
+.TP
+.B ts
+a
+.I struct timeval
+containing the time when the packet was captured
+.TP
+.B caplen
+a
+.I bpf_u_int32
+giving the number of bytes of the packet that are available from the
+capture
+.TP
+.B len
+a
+.I bpf_u_int32
+giving the length of the packet, in bytes (which might be more than the
+number of bytes available from the capture, if the length of the packet
+is larger than the maximum number of bytes to capture).
+.RE
+.PP
+The callback is also supplied a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+mentioned above)
+bytes of data from the packet. This won't necessarily be the entire
+packet; to capture the entire packet, you will have to provide a value
+for
+.I snaplen
+in your call to
+.BR pcap_set_snaplen ()
+that is sufficiently large to get all of the packet's data - a value of
+65535 should be sufficient on most if not all networks). When reading
+from a ``savefile'', the snapshot length specified when the capture was
+performed will limit the amount of packet data available.
+.PP
+.BR pcap_next ()
+is passed an argument that points to a
+.I struct pcap_pkthdr
+structure, and fills it in with the time stamp and length values for the
+packet. It returns a
+.I const u_char
+to the first
+.B caplen
+bytes of the packet on success, and NULL on error.
+.PP
+.BR pcap_next_ex ()
+is passed two pointer arguments, one of which points to a
+.IR struct pcap_pkthdr *
+and one of which points to a
+.IR "const u_char" *.
+It sets the first pointer to point to a
+.I struct pcap_pkthdr
+structure with the time stamp and length values for the packet, and sets
+the second pointer to point to the first
+.B caplen
+bytes of the packet.
+.PP
+To force the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+to terminate, call
+.BR pcap_breakloop ().
+.PP
+By default, when reading packets from an interface opened for a live
+capture,
+.BR pcap_dispatch (),
+.BR pcap_next (),
+and
+.BR pcap_next_ex ()
+will, if no packets are currently available to be read, block waiting
+for packets to become available. On some, but
+.I not
+all, platforms, if a packet buffer timeout was specified, the wait will
+terminate after the packet buffer timeout expires; applications should
+be prepared for this, as it happens on some platforms, but should not
+rely on it, as it does not happen on other platforms. Note that the
+wait might, or might not, terminate even if no packets are available;
+applications should be prepared for this to happen, but must not rely on
+it happening.
+.PP
+A handle can be put into ``non-blocking mode'', so that those routines
+will, rather than blocking, return an indication that no packets are
+available to read. Call
+.BR pcap_setnonblock ()
+to put a handle into non-blocking mode or to take it out of non-blocking
+mode; call
+.BR pcap_getnonblock ()
+to determine whether a handle is in non-blocking mode. Note that
+non-blocking mode does not work correctly in Mac OS X 10.6.
+.PP
+Non-blocking mode is often combined with routines such as
+.BR select (2)
+or
+.BR poll (2)
+or other routines a platform offers to wait for any of a set of
+descriptors to be ready to read. To obtain, for a handle, a descriptor
+that can be used in those routines, call
+.BR pcap_get_selectable_fd ().
+If the routine indicates that data is
+available to read on the descriptor, an attempt should be made to read
+from the device.
+.PP
+Not all handles have such a descriptor available;
+.BR pcap_get_selectable_fd ()
+will return
+.B PCAP_ERROR
+if no such descriptor is available. If no such
+descriptor is available, this may be because the device must be polled
+periodically for packets; in that case,
+.BR pcap_get_required_select_timeout ()
+will return a pointer to a
+.B struct timeval
+whose value can be used as a timeout in those routines. When the
+routine returns, an attmept should be made to read packets from the
+device. If
+.BR pcap_get_required_select_timeout ()
+returns NULL, no such timeout is available, and those routines cannot be
+used with the device.
+.PP
+In addition, for various
+reasons, one or more of those routines will not work properly with the
+descriptor; the documentation for
+.BR pcap_get_selectable_fd ()
+gives details. Note that, just as an attempt to read packets from a
+.B pcap_t
+may not return any packets if the packet buffer timeout expires, a
+.BR select (),
+.BR poll (),
+or other such call may, if the packet buffer timeout expires, indicate
+that a descriptor is ready to read even if there are no packets
+available to read.
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dispatch (3PCAP)
+read a bufferful of packets from a
+.B pcap_t
+open for a live capture or the full set of packets from a
+.B pcap_t
+open for a ``savefile''
+.TP
+.BR pcap_loop (3PCAP)
+read packets from a
+.B pcap_t
+until an interrupt or error occurs
+.TP
+.BR pcap_next (3PCAP)
+read the next packet from a
+.B pcap_t
+without an indication whether an error occurred
+.TP
+.BR pcap_next_ex (3PCAP)
+read the next packet from a
+.B pcap_t
+with an error indication on an error
+.TP
+.BR pcap_breakloop (3PCAP)
+prematurely terminate the loop in
+.BR pcap_dispatch ()
+or
+.BR pcap_loop ()
+.TP
+.BR pcap_setnonblock (3PCAP)
+set or clear non-blocking mode on a
+.B pcap_t
+.TP
+.BR pcap_getnonblock (3PCAP)
+get the state of non-blocking mode for a
+.B pcap_t
+.TP
+.BR pcap_get_selectable_fd (3PCAP)
+attempt to get a descriptor for a
+.B pcap_t
+that can be used in calls such as
+.BR select (2)
+and
+.BR poll (2)
+.TP
+.BR pcap_get_required_select_timeout (3PCAP)
+if no descriptor usable with
+.BR select (2)
+and
+.BR poll (2)
+is available for the
+.BR pcap_t ,
+attempt to get a timeout usable with those routines
+.RE
+.SS Filters
+In order to cause only certain packets to be returned when reading
+packets, a filter can be set on a handle. For a live capture, the
+filtering will be performed in kernel mode, if possible, to avoid
+copying ``uninteresting'' packets from the kernel to user mode.
+.PP
+A filter can be specified as a text string; the syntax and semantics of
+the string are as described by
+.BR pcap-filter (@MAN_MISC_INFO@).
+A filter string is compiled into a program in a pseudo-machine-language
+by
+.BR pcap_compile ()
+and the resulting program can be made a filter for a handle with
+.BR pcap_setfilter ().
+The result of
+.BR pcap_compile ()
+can be freed with a call to
+.BR pcap_freecode ().
+.BR pcap_compile ()
+may require a network mask for certain expressions in the filter string;
+.BR pcap_lookupnet ()
+can be used to find the network address and network mask for a given
+capture device.
+.PP
+A compiled filter can also be applied directly to a packet that has been
+read using
+.BR pcap_offline_filter ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_compile (3PCAP)
+compile filter expression to a pseudo-machine-language code program
+.TP
+.BR pcap_freecode (3PCAP)
+free a filter program
+.TP
+.BR pcap_setfilter (3PCAP)
+set filter for a
+.B pcap_t
+.TP
+.BR pcap_lookupnet (3PCAP)
+get network address and network mask for a capture device
+.TP
+.BR pcap_offline_filter (3PCAP)
+apply a filter program to a packet
+.RE
+.SS Incoming and outgoing packets
+By default, libpcap will attempt to capture both packets sent by the
+machine and packets received by the machine. To limit it to capturing
+only packets received by the machine or, if possible, only packets sent
+by the machine, call
+.BR pcap_setdirection ().
+.TP
+.BR Routines
+.RS
+.TP
+.BR pcap_setdirection (3PCAP)
+specify whether to capture incoming packets, outgoing packets, or both
+.RE
+.SS Capture statistics
+To get statistics about packets received and dropped in a live capture,
+call
+.BR pcap_stats ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_stats (3PCAP)
+get capture statistics
+.RE
+.SS Opening a handle for writing captured packets
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ().
+To open a ``savefile`` to which to write packets, given the pathname the
+``savefile'' should have, call
+.BR pcap_dump_open ();
+to set up a handle for a ``savefile'', given a
+.B "FILE\ *"
+referring to a file already opened for writing, call
+.BR pcap_dump_fopen ().
+They each return pointers to a
+.BR pcap_dumper_t ,
+which is the handle used for writing packets to the ``savefile''. If it
+succeeds, it will have created the file if it doesn't exist and
+truncated the file if it does exist.
+To close a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_close ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump_open (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a pathname
+.TP
+.BR pcap_dump_fopen (3PCAP)
+open a
+.B pcap_dumper_t
+for a ``savefile``, given a
+.B "FILE\ *"
+.TP
+.BR pcap_dump_close (3PCAP)
+close a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_file (3PCAP)
+get the
+.B "FILE\ *"
+for a
+.B pcap_dumper_t
+opened for a ``savefile''
+.RE
+.SS Writing packets
+To write a packet to a
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump ().
+Packets written with
+.BR pcap_dump ()
+may be buffered, rather than being immediately written to the
+``savefile''. Closing the
+.B pcap_dumper_t
+will cause all buffered-but-not-yet-written packets to be written to the
+``savefile''.
+To force all packets written to the
+.BR pcap_dumper_t ,
+and not yet written to the ``savefile'' because they're buffered by the
+.BR pcap_dumper_t ,
+to be written to the ``savefile'', without closing the
+.BR pcap_dumper_t ,
+call
+.BR pcap_dump_flush ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_dump (3PCAP)
+write packet to a
+.B pcap_dumper_t
+.TP
+.BR pcap_dump_flush (3PCAP)
+flush buffered packets written to a
+.B pcap_dumper_t
+to the ``savefile''
+.TP
+.BR pcap_dump_ftell (3PCAP)
+get current file position for a
+.B pcap_dumper_t
+.RE
+.SS Injecting packets
+If you have the required privileges, you can inject packets onto a
+network with a
+.B pcap_t
+for a live capture, using
+.BR pcap_inject ()
+or
+.BR pcap_sendpacket ().
+(The two routines exist for compatibility with both OpenBSD and WinPcap;
+they perform the same function, but have different return values.)
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_inject (3PCAP)
+.PD 0
+.TP
+.BR pcap_sendpacket (3PCAP)
+transmit a packet
+.PD
+.RE
+.SS Reporting errors
+Some routines return error or warning status codes; to convert them to a
+string, use
+.BR pcap_statustostr ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_statustostr (3PCAP)
+get a string for an error or warning status code
+.RE
+.SS Getting library version information
+To get a string giving version information about libpcap, call
+.BR pcap_lib_version ().
+.TP
+.B Routines
+.RS
+.TP
+.BR pcap_lib_version (3PCAP)
+get library version string
+.RE
+.SH BACKWARD COMPATIBILITY
+.PP
+In versions of libpcap prior to 1.0, the
+.B pcap.h
+header file was not in a
+.B pcap
+directory on most platforms; if you are writing an application that must
+work on versions of libpcap prior to 1.0, include
+.BR <pcap.h> ,
+which will include
+.B <pcap/pcap.h>
+for you, rather than including
+.BR <pcap/pcap.h> .
+.PP
+.BR pcap_create ()
+and
+.BR pcap_activate ()
+were not available in versions of libpcap prior to 1.0; if you are
+writing an application that must work on versions of libpcap prior to
+1.0, either use
+.BR pcap_open_live ()
+to get a handle for a live capture or, if you want to be able to use the
+additional capabilities offered by using
+.BR pcap_create ()
+and
+.BR pcap_activate (),
+use an
+.BR autoconf (1)
+script or some other configuration script to check whether the libpcap
+1.0 APIs are available and use them only if they are.
+.SH SEE ALSO
+autoconf(1), tcpdump(1), tcpslice(1), pcap-filter(@MAN_MISC_INFO@), pfconfig(8),
+usermod(@MAN_ADMIN_COMMANDS@)
+.SH AUTHORS
+The original authors of libpcap are:
+.LP
+Van Jacobson,
+Craig Leres and
+Steven McCanne, all of the
+Lawrence Berkeley National Laboratory, University of California, Berkeley, CA.
+.LP
+The current version is available from "The Tcpdump Group"'s Web site at
+.LP
+.RS
+.I https://www.tcpdump.org/
+.RE
+.SH BUGS
+To report a security issue please send an e-mail to security@tcpdump.org.
+.LP
+To report bugs and other problems, contribute patches, request a
+feature, provide generic feedback etc please see the file
+.I CONTRIBUTING
+in the libpcap source tree root.
diff --git a/lib/libpcap/libpcap/pcap.c b/lib/libpcap/libpcap/pcap.c
new file mode 100644
index 0000000..90d0a5a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap.c
@@ -0,0 +1,4134 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+#ifndef _WIN32
+#include <sys/param.h>
+#ifndef MSDOS
+#include <sys/file.h>
+#endif
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+struct mbuf; /* Squelch compiler warnings on some platforms for */
+struct rtentry; /* declarations in <net/if.h> */
+#include <net/if.h>
+#include <netinet/in.h>
+#endif /* _WIN32 */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#if !defined(_MSC_VER) && !defined(__BORLANDC__) && !defined(__MINGW32__)
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#ifdef MSDOS
+#include "pcap-dos.h"
+#endif
+
+#include "pcap-int.h"
+
+#include "optimize.h"
+
+#ifdef HAVE_DAG_API
+#include "pcap-dag.h"
+#endif /* HAVE_DAG_API */
+
+#ifdef HAVE_SEPTEL_API
+#include "pcap-septel.h"
+#endif /* HAVE_SEPTEL_API */
+
+#ifdef HAVE_SNF_API
+#include "pcap-snf.h"
+#endif /* HAVE_SNF_API */
+
+#ifdef HAVE_TC_API
+#include "pcap-tc.h"
+#endif /* HAVE_TC_API */
+
+#ifdef PCAP_SUPPORT_USB
+#include "pcap-usb-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_BT
+#include "pcap-bt-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_BT_MONITOR
+#include "pcap-bt-monitor-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_NETFILTER
+#include "pcap-netfilter-linux.h"
+#endif
+
+#ifdef PCAP_SUPPORT_NETMAP
+#include "pcap-netmap.h"
+#endif
+
+#ifdef PCAP_SUPPORT_DBUS
+#include "pcap-dbus.h"
+#endif
+
+#ifdef PCAP_SUPPORT_RDMASNIFF
+#include "pcap-rdmasniff.h"
+#endif
+
+#ifdef __APPLE__
+
+#ifdef HAVE_PKTAP_API
+#include "pcap-pktap.h"
+#endif
+#endif /* __APPLE__ */
+
+#ifdef _WIN32
+/*
+ * DllMain(), required when built as a Windows DLL.
+ */
+BOOL WINAPI DllMain(
+ HANDLE hinstDLL,
+ DWORD dwReason,
+ LPVOID lpvReserved
+)
+{
+ return (TRUE);
+}
+
+/*
+ * Start WinSock.
+ * Exported in case some applications using WinPcap/Npcap called it,
+ * even though it wasn't exported.
+ */
+int
+wsockinit(void)
+{
+ WORD wVersionRequested;
+ WSADATA wsaData;
+ static int err = -1;
+ static int done = 0;
+
+ if (done)
+ return (err);
+
+ wVersionRequested = MAKEWORD( 1, 1);
+ err = WSAStartup( wVersionRequested, &wsaData );
+ atexit ((void(*)(void))WSACleanup);
+ done = 1;
+
+ if ( err != 0 )
+ err = -1;
+ return (err);
+}
+
+/*
+ * This is the exported function; new programs should call this.
+ */
+int
+pcap_wsockinit(void)
+{
+ return (wsockinit());
+}
+#endif /* _WIN32 */
+
+/*
+ * String containing the library version.
+ * Not explicitly exported via a header file - the right API to use
+ * is pcap_lib_version() - but some programs included it, so we
+ * provide it.
+ *
+ * We declare it here, right before defining it, to squelch any
+ * warnings we might get from compilers about the lack of a
+ * declaration.
+ */
+PCAP_API char pcap_version[];
+PCAP_API_DEF char pcap_version[] = PACKAGE_VERSION;
+
+static void
+pcap_set_not_initialized_message(pcap_t *pcap)
+{
+ if (pcap->activated) {
+ /* A module probably forgot to set the function pointer */
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "This operation isn't properly handled by that device");
+ return;
+ }
+ /* in case the caller doesn't check for PCAP_ERROR_NOT_ACTIVATED */
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "This handle hasn't been activated yet");
+}
+
+static int
+pcap_read_not_initialized(pcap_t *pcap, int cnt _U_, pcap_handler callback _U_,
+ u_char *user _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_inject_not_initialized(pcap_t *pcap, const void * buf _U_, size_t size _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setfilter_not_initialized(pcap_t *pcap, struct bpf_program *fp _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setdirection_not_initialized(pcap_t *pcap, pcap_direction_t d _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_set_datalink_not_initialized(pcap_t *pcap, int dlt _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_getnonblock_not_initialized(pcap_t *pcap)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_stats_not_initialized(pcap_t *pcap, struct pcap_stat *ps _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+#ifdef _WIN32
+struct pcap_stat *
+pcap_stats_ex_not_initialized(pcap_t *pcap, int *pcap_stat_size _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (NULL);
+}
+
+static int
+pcap_setbuff_not_initialized(pcap_t *pcap, int dim _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setmode_not_initialized(pcap_t *pcap, int mode _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_setmintocopy_not_initialized(pcap_t *pcap, int size _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ /* this means 'not initialized' */
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static HANDLE
+pcap_getevent_not_initialized(pcap_t *pcap)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (INVALID_HANDLE_VALUE);
+}
+
+static int
+pcap_oid_get_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
+ void *data _U_, size_t *lenp _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_oid_set_request_not_initialized(pcap_t *pcap, bpf_u_int32 oid _U_,
+ const void *data _U_, size_t *lenp _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static u_int
+pcap_sendqueue_transmit_not_initialized(pcap_t *pcap, pcap_send_queue* queue, int sync)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (0);
+}
+
+static int
+pcap_setuserbuffer_not_initialized(pcap_t *pcap, int size _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_live_dump_not_initialized(pcap_t *pcap, char *filename _U_, int maxsize _U_,
+ int maxpacks _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static int
+pcap_live_dump_ended_not_initialized(pcap_t *pcap, int sync _U_)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (PCAP_ERROR_NOT_ACTIVATED);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_not_initialized(pcap_t *pcap)
+{
+ pcap_set_not_initialized_message(pcap);
+ return (NULL);
+}
+#endif
+
+/*
+ * Returns 1 if rfmon mode can be set on the pcap_t, 0 if it can't,
+ * a PCAP_ERROR value on an error.
+ */
+int
+pcap_can_set_rfmon(pcap_t *p)
+{
+ return (p->can_set_rfmon_op(p));
+}
+
+/*
+ * For systems where rfmon mode is never supported.
+ */
+static int
+pcap_cant_set_rfmon(pcap_t *p _U_)
+{
+ return (0);
+}
+
+/*
+ * Sets *tstamp_typesp to point to an array 1 or more supported time stamp
+ * types; the return value is the number of supported time stamp types.
+ * The list should be freed by a call to pcap_free_tstamp_types() when
+ * you're done with it.
+ *
+ * A return value of 0 means "you don't get a choice of time stamp type",
+ * in which case *tstamp_typesp is set to null.
+ *
+ * PCAP_ERROR is returned on error.
+ */
+int
+pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp)
+{
+ if (p->tstamp_type_count == 0) {
+ /*
+ * We don't support multiple time stamp types.
+ * That means the only type we support is PCAP_TSTAMP_HOST;
+ * set up a list containing only that type.
+ */
+ *tstamp_typesp = (int*)malloc(sizeof(**tstamp_typesp));
+ if (*tstamp_typesp == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "malloc");
+ return (PCAP_ERROR);
+ }
+ **tstamp_typesp = PCAP_TSTAMP_HOST;
+ return (1);
+ } else {
+ *tstamp_typesp = (int*)calloc(sizeof(**tstamp_typesp),
+ p->tstamp_type_count);
+ if (*tstamp_typesp == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "malloc");
+ return (PCAP_ERROR);
+ }
+ (void)memcpy(*tstamp_typesp, p->tstamp_type_list,
+ sizeof(**tstamp_typesp) * p->tstamp_type_count);
+ return (p->tstamp_type_count);
+}
+}
+
+/*
+ * In Windows, you might have a library built with one version of the
+ * C runtime library and an application built with another version of
+ * the C runtime library, which means that the library might use one
+ * version of malloc() and free() and the application might use another
+ * version of malloc() and free(). If so, that means something
+ * allocated by the library cannot be freed by the application, so we
+ * need to have a pcap_free_tstamp_types() routine to free up the list
+ * allocated by pcap_list_tstamp_types(), even though it's just a wrapper
+ * around free().
+ */
+void
+pcap_free_tstamp_types(int *tstamp_type_list)
+{
+ free(tstamp_type_list);
+}
+
+/*
+ * Default one-shot callback; overridden for capture types where the
+ * packet data cannot be guaranteed to be available after the callback
+ * returns, so that a copy must be made.
+ */
+void
+pcap_oneshot(u_char *user, const struct pcap_pkthdr *h, const u_char *pkt)
+{
+ struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
+
+ *sp->hdr = *h;
+ *sp->pkt = pkt;
+}
+
+const u_char *
+pcap_next(pcap_t *p, struct pcap_pkthdr *h)
+{
+ struct oneshot_userdata s;
+ const u_char *pkt;
+
+ s.hdr = h;
+ s.pkt = &pkt;
+ s.pd = p;
+ if (pcap_dispatch(p, 1, p->oneshot_callback, (u_char *)&s) <= 0)
+ return (0);
+ return (pkt);
+}
+
+int
+pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
+ const u_char **pkt_data)
+{
+ struct oneshot_userdata s;
+
+ s.hdr = &p->pcap_header;
+ s.pkt = pkt_data;
+ s.pd = p;
+
+ /* Saves a pointer to the packet headers */
+ *pkt_header= &p->pcap_header;
+
+ if (p->rfile != NULL) {
+ int status;
+
+ /* We are on an offline capture */
+#ifdef __APPLE__
+ status = p->read_op(p, 1, p->oneshot_callback,
+ (u_char *)&s);
+#else
+ status = pcap_offline_read(p, 1, p->oneshot_callback,
+ (u_char *)&s);
+#endif /* __APPLE__ */
+
+ /*
+ * Return codes for pcap_offline_read() are:
+ * - 0: EOF
+ * - -1: error
+ * - >1: OK
+ * The first one ('0') conflicts with the return code of
+ * 0 from pcap_read() meaning "no packets arrived before
+ * the timeout expired", so we map it to -2 so you can
+ * distinguish between an EOF from a savefile and a
+ * "no packets arrived before the timeout expired, try
+ * again" from a live capture.
+ */
+ if (status == 0)
+ return (-2);
+ else
+ return (status);
+ }
+
+ /*
+ * Return codes for pcap_read() are:
+ * - 0: timeout
+ * - -1: error
+ * - -2: loop was broken out of with pcap_breakloop()
+ * - >1: OK
+ * The first one ('0') conflicts with the return code of 0 from
+ * pcap_offline_read() meaning "end of file".
+ */
+ return (p->read_op(p, 1, p->oneshot_callback, (u_char *)&s));
+}
+
+/*
+ * Implementation of a pcap_if_list_t.
+ */
+struct pcap_if_list {
+ pcap_if_t *beginning;
+};
+
+static struct capture_source_type {
+ int (*findalldevs_op)(pcap_if_list_t *, char *);
+ pcap_t *(*create_op)(const char *, char *, int *);
+} capture_source_types[] = {
+#ifdef __APPLE__
+#ifdef HAVE_PKTAP_API
+ { NULL, pktap_create },
+#endif
+#endif /* __APPLE__ */
+#ifdef HAVE_DAG_API
+ { dag_findalldevs, dag_create },
+#endif
+#ifdef HAVE_SEPTEL_API
+ { septel_findalldevs, septel_create },
+#endif
+#ifdef HAVE_SNF_API
+ { snf_findalldevs, snf_create },
+#endif
+#ifdef HAVE_TC_API
+ { TcFindAllDevs, TcCreate },
+#endif
+#ifdef PCAP_SUPPORT_BT
+ { bt_findalldevs, bt_create },
+#endif
+#ifdef PCAP_SUPPORT_BT_MONITOR
+ { bt_monitor_findalldevs, bt_monitor_create },
+#endif
+#ifdef PCAP_SUPPORT_USB
+ { usb_findalldevs, usb_create },
+#endif
+#ifdef PCAP_SUPPORT_NETFILTER
+ { netfilter_findalldevs, netfilter_create },
+#endif
+#ifdef PCAP_SUPPORT_NETMAP
+ { pcap_netmap_findalldevs, pcap_netmap_create },
+#endif
+#ifdef PCAP_SUPPORT_DBUS
+ { dbus_findalldevs, dbus_create },
+#endif
+#ifdef PCAP_SUPPORT_RDMASNIFF
+ { rdmasniff_findalldevs, rdmasniff_create },
+#endif
+ { NULL, NULL }
+};
+
+/*
+ * Get a list of all capture sources that are up and that we can open.
+ * Returns -1 on error, 0 otherwise.
+ * The list, as returned through "alldevsp", may be null if no interfaces
+ * were up and could be opened.
+ */
+int
+pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf)
+{
+ size_t i;
+ pcap_if_list_t devlist;
+
+ /*
+ * Find all the local network interfaces on which we
+ * can capture.
+ */
+ devlist.beginning = NULL;
+ if (pcap_platform_finddevs(&devlist, errbuf) == -1) {
+ /*
+ * Failed - free all of the entries we were given
+ * before we failed.
+ */
+ if (devlist.beginning != NULL)
+ pcap_freealldevs(devlist.beginning);
+ *alldevsp = NULL;
+ return (-1);
+ }
+
+ /*
+ * Ask each of the non-local-network-interface capture
+ * source types what interfaces they have.
+ */
+ for (i = 0; capture_source_types[i].findalldevs_op != NULL; i++) {
+ if (capture_source_types[i].findalldevs_op(&devlist, errbuf) == -1) {
+ /*
+ * We had an error; free the list we've been
+ * constructing.
+ */
+ if (devlist.beginning != NULL)
+ pcap_freealldevs(devlist.beginning);
+ *alldevsp = NULL;
+ return (-1);
+ }
+ }
+
+ /*
+ * Return the first entry of the list of all devices.
+ */
+ *alldevsp = devlist.beginning;
+ return (0);
+}
+
+static struct sockaddr *
+dup_sockaddr(struct sockaddr *sa, size_t sa_length)
+{
+ struct sockaddr *newsa;
+
+ if ((newsa = malloc(sa_length)) == NULL)
+ return (NULL);
+ return (memcpy(newsa, sa, sa_length));
+}
+
+/*
+ * Construct a "figure of merit" for an interface, for use when sorting
+ * the list of interfaces, in which interfaces that are up are superior
+ * to interfaces that aren't up, interfaces that are up and running are
+ * superior to interfaces that are up but not running, and non-loopback
+ * interfaces that are up and running are superior to loopback interfaces,
+ * and interfaces with the same flags have a figure of merit that's higher
+ * the lower the instance number.
+ *
+ * The goal is to try to put the interfaces most likely to be useful for
+ * capture at the beginning of the list.
+ *
+ * The figure of merit, which is lower the "better" the interface is,
+ * has the uppermost bit set if the interface isn't running, the bit
+ * below that set if the interface isn't up, the bit below that set
+ * if the interface is a loopback interface, and the interface index
+ * in the 29 bits below that. (Yes, we assume u_int is 32 bits.)
+ */
+static u_int
+get_figure_of_merit(pcap_if_t *dev)
+{
+ const char *cp;
+ u_int n;
+
+ if (strcmp(dev->name, "any") == 0) {
+ /*
+ * Give the "any" device an artificially high instance
+ * number, so it shows up after all other non-loopback
+ * interfaces.
+ */
+ n = 0x1FFFFFFF; /* 29 all-1 bits */
+ } else {
+ /*
+ * A number at the end of the device name string is
+ * assumed to be an instance number. Add 1 to the
+ * instance number, and use 0 for "no instance
+ * number", so we don't put "no instance number"
+ * devices and "instance 0" devices together.
+ */
+ cp = dev->name + strlen(dev->name) - 1;
+ while (cp-1 >= dev->name && *(cp-1) >= '0' && *(cp-1) <= '9')
+ cp--;
+ if (*cp >= '0' && *cp <= '9')
+ n = atoi(cp) + 1;
+ else
+ n = 0;
+ }
+ if (!(dev->flags & PCAP_IF_RUNNING))
+ n |= 0x80000000;
+ if (!(dev->flags & PCAP_IF_UP))
+ n |= 0x40000000;
+
+ /*
+ * Give non-wireless interfaces that aren't disconnected a better
+ * figure of merit than interfaces that are disconnected, as
+ * "disconnected" should indicate that the interface isn't
+ * plugged into a network and thus won't give you any traffic.
+ *
+ * For wireless interfaces, it means "associated with a network",
+ * which we presume not to necessarily prevent capture, as you
+ * might run the adapter in some flavor of monitor mode.
+ */
+ if (!(dev->flags & PCAP_IF_WIRELESS) &&
+ (dev->flags & PCAP_IF_CONNECTION_STATUS) == PCAP_IF_CONNECTION_STATUS_DISCONNECTED)
+ n |= 0x20000000;
+
+ /*
+ * Sort loopback devices after non-loopback devices, *except* for
+ * disconnected devices.
+ */
+ if (dev->flags & PCAP_IF_LOOPBACK)
+ n |= 0x10000000;
+
+ return (n);
+}
+
+#ifndef _WIN32
+/*
+ * Try to get a description for a given device.
+ * Returns a mallocated description if it could and NULL if it couldn't.
+ *
+ * XXX - on FreeBSDs that support it, should it get the sysctl named
+ * "dev.{adapter family name}.{adapter unit}.%desc" to get a description
+ * of the adapter? Note that "dev.an.0.%desc" is "Aironet PC4500/PC4800"
+ * with my Cisco 350 card, so the name isn't entirely descriptive. The
+ * "dev.an.0.%pnpinfo" has a better description, although one might argue
+ * that the problem is really a driver bug - if it can find out that it's
+ * a Cisco 340 or 350, rather than an old Aironet card, it should use
+ * that in the description.
+ *
+ * Do NetBSD, DragonflyBSD, or OpenBSD support this as well? FreeBSD
+ * and OpenBSD let you get a description, but it's not generated by the OS,
+ * it's set with another ioctl that ifconfig supports; we use that to get
+ * a description in FreeBSD and OpenBSD, but if there is no such
+ * description available, it still might be nice to get some description
+ * string based on the device type or something such as that.
+ *
+ * In macOS, the System Configuration framework can apparently return
+ * names in 10.4 and later.
+ *
+ * It also appears that freedesktop.org's HAL offers an "info.product"
+ * string, but the HAL specification says it "should not be used in any
+ * UI" and "subsystem/capability specific properties" should be used
+ * instead and, in any case, I think HAL is being deprecated in
+ * favor of other stuff such as DeviceKit. DeviceKit doesn't appear
+ * to have any obvious product information for devices, but maybe
+ * I haven't looked hard enough.
+ *
+ * Using the System Configuration framework, or HAL, or DeviceKit, or
+ * whatever, would require that libpcap applications be linked with
+ * the frameworks/libraries in question. That shouldn't be a problem
+ * for programs linking with the shared version of libpcap (unless
+ * you're running on AIX - which I think is the only UN*X that doesn't
+ * support linking a shared library with other libraries on which it
+ * depends, and having an executable linked only with the first shared
+ * library automatically pick up the other libraries when started -
+ * and using HAL or whatever). Programs linked with the static
+ * version of libpcap would have to use pcap-config with the --static
+ * flag in order to get the right linker flags in order to pick up
+ * the additional libraries/frameworks; those programs need that anyway
+ * for libpcap 1.1 and beyond on Linux, as, by default, it requires
+ * -lnl.
+ *
+ * Do any other UN*Xes, or desktop environments support getting a
+ * description?
+ */
+static char *
+#ifdef SIOCGIFDESCR
+get_if_description(const char *name)
+{
+ char *description = NULL;
+ int s;
+ struct ifreq ifrdesc;
+#ifndef IFDESCRSIZE
+ size_t descrlen = 64;
+#else
+ size_t descrlen = IFDESCRSIZE;
+#endif /* IFDESCRSIZE */
+
+ /*
+ * Get the description for the interface.
+ */
+ memset(&ifrdesc, 0, sizeof ifrdesc);
+ pcap_strlcpy(ifrdesc.ifr_name, name, sizeof ifrdesc.ifr_name);
+ s = socket(AF_INET, SOCK_DGRAM, 0);
+ if (s >= 0) {
+#ifdef __FreeBSD__
+ /*
+ * On FreeBSD, if the buffer isn't big enough for the
+ * description, the ioctl succeeds, but the description
+ * isn't copied, ifr_buffer.length is set to the description
+ * length, and ifr_buffer.buffer is set to NULL.
+ */
+ for (;;) {
+ free(description);
+ if ((description = malloc(descrlen)) != NULL) {
+ ifrdesc.ifr_buffer.buffer = description;
+ ifrdesc.ifr_buffer.length = descrlen;
+ if (ioctl(s, SIOCGIFDESCR, &ifrdesc) == 0) {
+ if (ifrdesc.ifr_buffer.buffer ==
+ description)
+ break;
+ else
+ descrlen = ifrdesc.ifr_buffer.length;
+ } else {
+ /*
+ * Failed to get interface description.
+ */
+ free(description);
+ description = NULL;
+ break;
+ }
+ } else
+ break;
+ }
+#else /* __FreeBSD__ */
+ /*
+ * The only other OS that currently supports
+ * SIOCGIFDESCR is OpenBSD, and it has no way
+ * to get the description length - it's clamped
+ * to a maximum of IFDESCRSIZE.
+ */
+ if ((description = malloc(descrlen)) != NULL) {
+ ifrdesc.ifr_data = (caddr_t)description;
+ if (ioctl(s, SIOCGIFDESCR, &ifrdesc) != 0) {
+ /*
+ * Failed to get interface description.
+ */
+ free(description);
+ description = NULL;
+ }
+ }
+#endif /* __FreeBSD__ */
+ close(s);
+ if (description != NULL && description[0] == '\0') {
+ /*
+ * Description is empty, so discard it.
+ */
+ free(description);
+ description = NULL;
+ }
+ }
+
+#ifdef __FreeBSD__
+ /*
+ * For FreeBSD, if we didn't get a description, and this is
+ * a device with a name of the form usbusN, label it as a USB
+ * bus.
+ */
+ if (description == NULL) {
+ if (strncmp(name, "usbus", 5) == 0) {
+ /*
+ * OK, it begins with "usbus".
+ */
+ long busnum;
+ char *p;
+
+ errno = 0;
+ busnum = strtol(name + 5, &p, 10);
+ if (errno == 0 && p != name + 5 && *p == '\0' &&
+ busnum >= 0 && busnum <= INT_MAX) {
+ /*
+ * OK, it's a valid number that's not
+ * bigger than INT_MAX. Construct
+ * a description from it.
+ * (If that fails, we don't worry about
+ * it, we just return NULL.)
+ */
+ if (pcap_asprintf(&description,
+ "USB bus number %ld", busnum) == -1) {
+ /* Failed. */
+ description = NULL;
+ }
+ }
+ }
+ }
+#endif
+ return (description);
+#else /* SIOCGIFDESCR */
+get_if_description(const char *name _U_)
+{
+ return (NULL);
+#endif /* SIOCGIFDESCR */
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return a pointer to its entry.
+ *
+ * If we don't find it, attempt to add an entry for it, with the specified
+ * IFF_ flags and description, and, if that succeeds, return a pointer to
+ * the new entry, otherwise return NULL and set errbuf to an error message.
+ */
+pcap_if_t *
+find_or_add_if(pcap_if_list_t *devlistp, const char *name,
+ bpf_u_int32 if_flags, get_if_flags_func get_flags_func, char *errbuf)
+{
+ bpf_u_int32 pcap_flags;
+
+ /*
+ * Convert IFF_ flags to pcap flags.
+ */
+ pcap_flags = 0;
+#ifdef IFF_LOOPBACK
+ if (if_flags & IFF_LOOPBACK)
+ pcap_flags |= PCAP_IF_LOOPBACK;
+#else
+ /*
+ * We don't have IFF_LOOPBACK, so look at the device name to
+ * see if it looks like a loopback device.
+ */
+ if (name[0] == 'l' && name[1] == 'o' &&
+ (isdigit((unsigned char)(name[2])) || name[2] == '\0')
+ pcap_flags |= PCAP_IF_LOOPBACK;
+#endif
+#ifdef IFF_UP
+ if (if_flags & IFF_UP)
+ pcap_flags |= PCAP_IF_UP;
+#endif
+#ifdef IFF_RUNNING
+ if (if_flags & IFF_RUNNING)
+ pcap_flags |= PCAP_IF_RUNNING;
+#endif
+
+ /*
+ * Attempt to find an entry for this device; if we don't find one,
+ * attempt to add one.
+ */
+ return (find_or_add_dev(devlistp, name, pcap_flags,
+ get_flags_func, get_if_description(name), errbuf));
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, then, if the specified address isn't null, add it to
+ * the list of addresses for the device and return 0.
+ *
+ * If we don't find it, attempt to add an entry for it, with the specified
+ * IFF_ flags and description, and, if that succeeds, add the specified
+ * address to its list of addresses if that address is non-null, and
+ * return 0, otherwise return -1 and set errbuf to an error message.
+ *
+ * (We can get called with a null address because we might get a list
+ * of interface name/address combinations from the underlying OS, with
+ * the address being absent in some cases, rather than a list of
+ * interfaces with each interface having a list of addresses, so this
+ * call may be the only call made to add to the list, and we want to
+ * add interfaces even if they have no addresses.)
+ */
+int
+add_addr_to_if(pcap_if_list_t *devlistp, const char *name,
+ bpf_u_int32 if_flags, get_if_flags_func get_flags_func,
+ struct sockaddr *addr, size_t addr_size,
+ struct sockaddr *netmask, size_t netmask_size,
+ struct sockaddr *broadaddr, size_t broadaddr_size,
+ struct sockaddr *dstaddr, size_t dstaddr_size,
+ char *errbuf)
+{
+ pcap_if_t *curdev;
+
+ /*
+ * Check whether the device exists and, if not, add it.
+ */
+ curdev = find_or_add_if(devlistp, name, if_flags, get_flags_func,
+ errbuf);
+ if (curdev == NULL) {
+ /*
+ * Error - give up.
+ */
+ return (-1);
+ }
+
+ if (addr == NULL) {
+ /*
+ * There's no address to add; this entry just meant
+ * "here's a new interface".
+ */
+ return (0);
+ }
+
+ /*
+ * "curdev" is an entry for this interface, and we have an
+ * address for it; add an entry for that address to the
+ * interface's list of addresses.
+ */
+ return (add_addr_to_dev(curdev, addr, addr_size, netmask,
+ netmask_size, broadaddr, broadaddr_size, dstaddr,
+ dstaddr_size, errbuf));
+}
+#endif /* _WIN32 */
+
+/*
+ * Add an entry to the list of addresses for an interface.
+ * "curdev" is the entry for that interface.
+ */
+int
+add_addr_to_dev(pcap_if_t *curdev,
+ struct sockaddr *addr, size_t addr_size,
+ struct sockaddr *netmask, size_t netmask_size,
+ struct sockaddr *broadaddr, size_t broadaddr_size,
+ struct sockaddr *dstaddr, size_t dstaddr_size,
+ char *errbuf)
+{
+ pcap_addr_t *curaddr, *prevaddr, *nextaddr;
+
+ /*
+ * Allocate the new entry and fill it in.
+ */
+ curaddr = (pcap_addr_t *)malloc(sizeof(pcap_addr_t));
+ if (curaddr == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+
+ curaddr->next = NULL;
+ if (addr != NULL && addr_size != 0) {
+ curaddr->addr = (struct sockaddr *)dup_sockaddr(addr, addr_size);
+ if (curaddr->addr == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->addr = NULL;
+
+ if (netmask != NULL && netmask_size != 0) {
+ curaddr->netmask = (struct sockaddr *)dup_sockaddr(netmask, netmask_size);
+ if (curaddr->netmask == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ if (curaddr->addr != NULL)
+ free(curaddr->addr);
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->netmask = NULL;
+
+ if (broadaddr != NULL && broadaddr_size != 0) {
+ curaddr->broadaddr = (struct sockaddr *)dup_sockaddr(broadaddr, broadaddr_size);
+ if (curaddr->broadaddr == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ if (curaddr->netmask != NULL)
+ free(curaddr->netmask);
+ if (curaddr->addr != NULL)
+ free(curaddr->addr);
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->broadaddr = NULL;
+
+ if (dstaddr != NULL && dstaddr_size != 0) {
+ curaddr->dstaddr = (struct sockaddr *)dup_sockaddr(dstaddr, dstaddr_size);
+ if (curaddr->dstaddr == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ if (curaddr->broadaddr != NULL)
+ free(curaddr->broadaddr);
+ if (curaddr->netmask != NULL)
+ free(curaddr->netmask);
+ if (curaddr->addr != NULL)
+ free(curaddr->addr);
+ free(curaddr);
+ return (-1);
+ }
+ } else
+ curaddr->dstaddr = NULL;
+
+ /*
+ * Find the end of the list of addresses.
+ */
+ for (prevaddr = curdev->addresses; prevaddr != NULL; prevaddr = nextaddr) {
+ nextaddr = prevaddr->next;
+ if (nextaddr == NULL) {
+ /*
+ * This is the end of the list.
+ */
+ break;
+ }
+ }
+
+ if (prevaddr == NULL) {
+ /*
+ * The list was empty; this is the first member.
+ */
+ curdev->addresses = curaddr;
+ } else {
+ /*
+ * "prevaddr" is the last member of the list; append
+ * this member to it.
+ */
+ prevaddr->next = curaddr;
+ }
+
+ return (0);
+}
+
+/*
+ * Look for a given device in the specified list of devices.
+ *
+ * If we find it, return 0 and set *curdev_ret to point to it.
+ *
+ * If we don't find it, attempt to add an entry for it, with the specified
+ * flags and description, and, if that succeeds, return 0, otherwise
+ * return -1 and set errbuf to an error message.
+ */
+pcap_if_t *
+find_or_add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
+ get_if_flags_func get_flags_func, const char *description, char *errbuf)
+{
+ pcap_if_t *curdev;
+
+ /*
+ * Is there already an entry in the list for this device?
+ */
+ curdev = find_dev(devlistp, name);
+ if (curdev != NULL) {
+ /*
+ * Yes, return it.
+ */
+ return (curdev);
+ }
+
+ /*
+ * No, we didn't find it.
+ */
+
+ /*
+ * Try to get additional flags for the device.
+ */
+ if ((*get_flags_func)(name, &flags, errbuf) == -1) {
+ /*
+ * Failed.
+ */
+ return (NULL);
+ }
+
+ /*
+ * Now, try to add it to the list of devices.
+ */
+ return (add_dev(devlistp, name, flags, description, errbuf));
+}
+
+/*
+ * Look for a given device in the specified list of devices, and return
+ * the entry for it if we find it or NULL if we don't.
+ */
+pcap_if_t *
+find_dev(pcap_if_list_t *devlistp, const char *name)
+{
+ pcap_if_t *curdev;
+
+ /*
+ * Is there an entry in the list for this device?
+ */
+ for (curdev = devlistp->beginning; curdev != NULL;
+ curdev = curdev->next) {
+ if (strcmp(name, curdev->name) == 0) {
+ /*
+ * We found it, so, yes, there is. No need to
+ * add it. Provide the entry we found to our
+ * caller.
+ */
+ return (curdev);
+ }
+ }
+
+ /*
+ * No.
+ */
+ return (NULL);
+}
+
+/*
+ * Attempt to add an entry for a device, with the specified flags
+ * and description, and, if that succeeds, return 0 and return a pointer
+ * to the new entry, otherwise return NULL and set errbuf to an error
+ * message.
+ *
+ * If we weren't given a description, try to get one.
+ */
+pcap_if_t *
+add_dev(pcap_if_list_t *devlistp, const char *name, bpf_u_int32 flags,
+ const char *description, char *errbuf)
+{
+ pcap_if_t *curdev, *prevdev, *nextdev;
+ u_int this_figure_of_merit, nextdev_figure_of_merit;
+
+ curdev = malloc(sizeof(pcap_if_t));
+ if (curdev == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (NULL);
+ }
+
+ /*
+ * Fill in the entry.
+ */
+ curdev->next = NULL;
+ curdev->name = strdup(name);
+ if (curdev->name == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ free(curdev);
+ return (NULL);
+ }
+ if (description == NULL) {
+ /*
+ * We weren't handed a description for the interface.
+ */
+ curdev->description = NULL;
+ } else {
+ /*
+ * We were handed a description; make a copy.
+ */
+ curdev->description = strdup(description);
+ if (curdev->description == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ free(curdev->name);
+ free(curdev);
+ return (NULL);
+ }
+ }
+ curdev->addresses = NULL; /* list starts out as empty */
+ curdev->flags = flags;
+
+ /*
+ * Add it to the list, in the appropriate location.
+ * First, get the "figure of merit" for this interface.
+ */
+ this_figure_of_merit = get_figure_of_merit(curdev);
+
+ /*
+ * Now look for the last interface with an figure of merit
+ * less than or equal to the new interface's figure of merit.
+ *
+ * We start with "prevdev" being NULL, meaning we're before
+ * the first element in the list.
+ */
+ prevdev = NULL;
+ for (;;) {
+ /*
+ * Get the interface after this one.
+ */
+ if (prevdev == NULL) {
+ /*
+ * The next element is the first element.
+ */
+ nextdev = devlistp->beginning;
+ } else
+ nextdev = prevdev->next;
+
+ /*
+ * Are we at the end of the list?
+ */
+ if (nextdev == NULL) {
+ /*
+ * Yes - we have to put the new entry after "prevdev".
+ */
+ break;
+ }
+
+ /*
+ * Is the new interface's figure of merit less
+ * than the next interface's figure of merit,
+ * meaning that the new interface is better
+ * than the next interface?
+ */
+ nextdev_figure_of_merit = get_figure_of_merit(nextdev);
+ if (this_figure_of_merit < nextdev_figure_of_merit) {
+ /*
+ * Yes - we should put the new entry
+ * before "nextdev", i.e. after "prevdev".
+ */
+ break;
+ }
+
+ prevdev = nextdev;
+ }
+
+ /*
+ * Insert before "nextdev".
+ */
+ curdev->next = nextdev;
+
+ /*
+ * Insert after "prevdev" - unless "prevdev" is null,
+ * in which case this is the first interface.
+ */
+ if (prevdev == NULL) {
+ /*
+ * This is the first interface. Make it
+ * the first element in the list of devices.
+ */
+ devlistp->beginning = curdev;
+ } else
+ prevdev->next = curdev;
+ return (curdev);
+}
+
+/*
+ * Free a list of interfaces.
+ */
+void
+pcap_freealldevs(pcap_if_t *alldevs)
+{
+ pcap_if_t *curdev, *nextdev;
+ pcap_addr_t *curaddr, *nextaddr;
+
+ for (curdev = alldevs; curdev != NULL; curdev = nextdev) {
+ nextdev = curdev->next;
+
+ /*
+ * Free all addresses.
+ */
+ for (curaddr = curdev->addresses; curaddr != NULL; curaddr = nextaddr) {
+ nextaddr = curaddr->next;
+ if (curaddr->addr)
+ free(curaddr->addr);
+ if (curaddr->netmask)
+ free(curaddr->netmask);
+ if (curaddr->broadaddr)
+ free(curaddr->broadaddr);
+ if (curaddr->dstaddr)
+ free(curaddr->dstaddr);
+ free(curaddr);
+ }
+
+ /*
+ * Free the name string.
+ */
+ free(curdev->name);
+
+ /*
+ * Free the description string, if any.
+ */
+ if (curdev->description != NULL)
+ free(curdev->description);
+
+ /*
+ * Free the interface.
+ */
+ free(curdev);
+ }
+}
+
+/*
+ * pcap-npf.c has its own pcap_lookupdev(), for compatibility reasons, as
+ * it actually returns the names of all interfaces, with a NUL separator
+ * between them; some callers may depend on that.
+ *
+ * MS-DOS has its own pcap_lookupdev(), but that might be useful only
+ * as an optimization.
+ *
+ * In all other cases, we just use pcap_findalldevs() to get a list of
+ * devices, and pick from that list.
+ */
+#if !defined(HAVE_PACKET32) && !defined(MSDOS)
+/*
+ * Return the name of a network interface attached to the system, or NULL
+ * if none can be found. The interface must be configured up; the
+ * lowest unit number is preferred; loopback is ignored.
+ */
+char *
+pcap_lookupdev(char *errbuf)
+{
+ pcap_if_t *alldevs;
+#ifdef _WIN32
+ /*
+ * Windows - use the same size as the old WinPcap 3.1 code.
+ * XXX - this is probably bigger than it needs to be.
+ */
+ #define IF_NAMESIZE 8192
+#else
+ /*
+ * UN*X - use the system's interface name size.
+ * XXX - that might not be large enough for capture devices
+ * that aren't regular network interfaces.
+ */
+ /* for old BSD systems, including bsdi3 */
+ #ifndef IF_NAMESIZE
+ #define IF_NAMESIZE IFNAMSIZ
+ #endif
+#endif
+ static char device[IF_NAMESIZE + 1];
+ char *ret;
+
+ if (pcap_findalldevs(&alldevs, errbuf) == -1)
+ return (NULL);
+
+ if (alldevs == NULL || (alldevs->flags & PCAP_IF_LOOPBACK)) {
+ /*
+ * There are no devices on the list, or the first device
+ * on the list is a loopback device, which means there
+ * are no non-loopback devices on the list. This means
+ * we can't return any device.
+ *
+ * XXX - why not return a loopback device? If we can't
+ * capture on it, it won't be on the list, and if it's
+ * on the list, there aren't any non-loopback devices,
+ * so why not just supply it as the default device?
+ */
+ (void)pcap_strlcpy(errbuf, "no suitable device found",
+ PCAP_ERRBUF_SIZE);
+ ret = NULL;
+ } else {
+ /*
+ * Return the name of the first device on the list.
+ */
+ (void)pcap_strlcpy(device, alldevs->name, sizeof(device));
+ ret = device;
+ }
+
+ pcap_freealldevs(alldevs);
+ return (ret);
+}
+#endif /* !defined(HAVE_PACKET32) && !defined(MSDOS) */
+
+#if !defined(_WIN32) && !defined(MSDOS)
+/*
+ * We don't just fetch the entire list of devices, search for the
+ * particular device, and use its first IPv4 address, as that's too
+ * much work to get just one device's netmask.
+ *
+ * If we had an API to get attributes for a given device, we could
+ * use that.
+ */
+int
+pcap_lookupnet(const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp,
+ char *errbuf)
+{
+ register int fd;
+ register struct sockaddr_in *sin4;
+ struct ifreq ifr;
+
+ /*
+ * The pseudo-device "any" listens on all interfaces and therefore
+ * has the network address and -mask "0.0.0.0" therefore catching
+ * all traffic. Using NULL for the interface is the same as "any".
+ */
+ if (!device || strcmp(device, "any") == 0
+#ifdef HAVE_DAG_API
+ || strstr(device, "dag") != NULL
+#endif
+#ifdef HAVE_SEPTEL_API
+ || strstr(device, "septel") != NULL
+#endif
+#ifdef PCAP_SUPPORT_BT
+ || strstr(device, "bluetooth") != NULL
+#endif
+#ifdef PCAP_SUPPORT_USB
+ || strstr(device, "usbmon") != NULL
+#endif
+#ifdef HAVE_SNF_API
+ || strstr(device, "snf") != NULL
+#endif
+#ifdef PCAP_SUPPORT_NETMAP
+ || strncmp(device, "netmap:", 7) == 0
+ || strncmp(device, "vale", 4) == 0
+#endif
+ ) {
+ *netp = *maskp = 0;
+ return 0;
+ }
+
+ fd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "socket");
+ return (-1);
+ }
+ memset(&ifr, 0, sizeof(ifr));
+#ifdef linux
+ /* XXX Work around Linux kernel bug */
+ ifr.ifr_addr.sa_family = AF_INET;
+#endif
+ (void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) {
+ if (errno == EADDRNOTAVAIL) {
+#ifdef __APPLE__
+ /* No reason fail if there is no IPv4 address */
+ *netp = *maskp = 0;
+ (void)close(fd);
+ return 0;
+#else
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "%s: no IPv4 address assigned", device);
+#endif /* __APPLE__ */
+ } else {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFADDR: %s", device);
+ }
+ (void)close(fd);
+ return (-1);
+ }
+ sin4 = (struct sockaddr_in *)&ifr.ifr_addr;
+ *netp = sin4->sin_addr.s_addr;
+ memset(&ifr, 0, sizeof(ifr));
+#ifdef linux
+ /* XXX Work around Linux kernel bug */
+ ifr.ifr_addr.sa_family = AF_INET;
+#endif
+ (void)pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
+ if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "SIOCGIFNETMASK: %s", device);
+ (void)close(fd);
+ return (-1);
+ }
+ (void)close(fd);
+ *maskp = sin4->sin_addr.s_addr;
+ if (*maskp == 0) {
+ if (IN_CLASSA(*netp))
+ *maskp = IN_CLASSA_NET;
+ else if (IN_CLASSB(*netp))
+ *maskp = IN_CLASSB_NET;
+ else if (IN_CLASSC(*netp))
+ *maskp = IN_CLASSC_NET;
+ else {
+ (void)pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "inet class for 0x%x unknown", *netp);
+ return (-1);
+ }
+ }
+ *netp &= *maskp;
+ return (0);
+}
+#endif /* !defined(_WIN32) && !defined(MSDOS) */
+
+#ifdef ENABLE_REMOTE
+#include "pcap-rpcap.h"
+
+/*
+ * Extract a substring from a string.
+ */
+static char *
+get_substring(const char *p, size_t len, char *ebuf)
+{
+ char *token;
+
+ token = malloc(len + 1);
+ if (token == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (NULL);
+ }
+ memcpy(token, p, len);
+ token[len] = '\0';
+ return (token);
+}
+
+/*
+ * Parse a capture source that might be a URL.
+ *
+ * If the source is not a URL, *schemep, *userinfop, *hostp, and *portp
+ * are set to NULL, *pathp is set to point to the source, and 0 is
+ * returned.
+ *
+ * If source is a URL, and the URL refers to a local device (a special
+ * case of rpcap:), *schemep, *userinfop, *hostp, and *portp are set
+ * to NULL, *pathp is set to point to the device name, and 0 is returned.
+ *
+ * If source is a URL, and it's not a special case that refers to a local
+ * device, and the parse succeeds:
+ *
+ * *schemep is set to point to an allocated string containing the scheme;
+ *
+ * if user information is present in the URL, *userinfop is set to point
+ * to an allocated string containing the user information, otherwise
+ * it's set to NULL;
+ *
+ * if host information is present in the URL, *hostp is set to point
+ * to an allocated string containing the host information, otherwise
+ * it's set to NULL;
+ *
+ * if a port number is present in the URL, *portp is set to point
+ * to an allocated string containing the port number, otherwise
+ * it's set to NULL;
+ *
+ * *pathp is set to point to an allocated string containing the
+ * path;
+ *
+ * and 0 is returned.
+ *
+ * If the parse fails, ebuf is set to an error string, and -1 is returned.
+ */
+static int
+pcap_parse_source(const char *source, char **schemep, char **userinfop,
+ char **hostp, char **portp, char **pathp, char *ebuf)
+{
+ char *colonp;
+ size_t scheme_len;
+ char *scheme;
+ const char *endp;
+ size_t authority_len;
+ char *authority;
+ char *parsep, *atsignp, *bracketp;
+ char *userinfo, *host, *port, *path;
+
+ /*
+ * Start out returning nothing.
+ */
+ *schemep = NULL;
+ *userinfop = NULL;
+ *hostp = NULL;
+ *portp = NULL;
+ *pathp = NULL;
+
+ /*
+ * RFC 3986 says:
+ *
+ * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+ *
+ * hier-part = "//" authority path-abempty
+ * / path-absolute
+ * / path-rootless
+ * / path-empty
+ *
+ * authority = [ userinfo "@" ] host [ ":" port ]
+ *
+ * userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ *
+ * Step 1: look for the ":" at the end of the scheme.
+ * A colon in the source is *NOT* sufficient to indicate that
+ * this is a URL, as interface names on some platforms might
+ * include colons (e.g., I think some Solaris interfaces
+ * might).
+ */
+ colonp = strchr(source, ':');
+ if (colonp == NULL) {
+ /*
+ * The source is the device to open.
+ * Return a NULL pointer for the scheme, user information,
+ * host, and port, and return the device as the path.
+ */
+ *pathp = strdup(source);
+ if (*pathp == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+ return (0);
+ }
+
+ /*
+ * All schemes must have "//" after them, i.e. we only support
+ * hier-part = "//" authority path-abempty, not
+ * hier-part = path-absolute
+ * hier-part = path-rootless
+ * hier-part = path-empty
+ *
+ * We need that in order to distinguish between a local device
+ * name that happens to contain a colon and a URI.
+ */
+ if (strncmp(colonp + 1, "//", 2) != 0) {
+ /*
+ * The source is the device to open.
+ * Return a NULL pointer for the scheme, user information,
+ * host, and port, and return the device as the path.
+ */
+ *pathp = strdup(source);
+ if (*pathp == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+ return (0);
+ }
+
+ /*
+ * XXX - check whether the purported scheme could be a scheme?
+ */
+
+ /*
+ * OK, this looks like a URL.
+ * Get the scheme.
+ */
+ scheme_len = colonp - source;
+ scheme = malloc(scheme_len + 1);
+ if (scheme == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+ memcpy(scheme, source, scheme_len);
+ scheme[scheme_len] = '\0';
+
+ /*
+ * Treat file: specially - take everything after file:// as
+ * the pathname.
+ */
+ if (pcap_strcasecmp(scheme, "file") == 0) {
+ *pathp = strdup(colonp + 3);
+ if (*pathp == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ free(scheme);
+ return (-1);
+ }
+ *schemep = scheme;
+ return (0);
+ }
+
+ /*
+ * The WinPcap documentation says you can specify a local
+ * interface with "rpcap://{device}"; we special-case
+ * that here. If the scheme is "rpcap", and there are
+ * no slashes past the "//", we just return the device.
+ *
+ * XXX - %-escaping?
+ */
+ if (pcap_strcasecmp(scheme, "rpcap") == 0 &&
+ strchr(colonp + 3, '/') == NULL) {
+ /*
+ * Local device.
+ *
+ * Return a NULL pointer for the scheme, user information,
+ * host, and port, and return the device as the path.
+ */
+ free(scheme);
+ *pathp = strdup(colonp + 3);
+ if (*pathp == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (-1);
+ }
+ return (0);
+ }
+
+ /*
+ * OK, now start parsing the authority.
+ * Get token, terminated with / or terminated at the end of
+ * the string.
+ */
+ authority_len = strcspn(colonp + 3, "/");
+ authority = get_substring(colonp + 3, authority_len, ebuf);
+ if (authority == NULL) {
+ /*
+ * Error.
+ */
+ free(scheme);
+ return (-1);
+ }
+ endp = colonp + 3 + authority_len;
+
+ /*
+ * Now carve the authority field into its components.
+ */
+ parsep = authority;
+
+ /*
+ * Is there a userinfo field?
+ */
+ atsignp = strchr(parsep, '@');
+ if (atsignp != NULL) {
+ /*
+ * Yes.
+ */
+ size_t userinfo_len;
+
+ userinfo_len = atsignp - parsep;
+ userinfo = get_substring(parsep, userinfo_len, ebuf);
+ if (userinfo == NULL) {
+ /*
+ * Error.
+ */
+ free(authority);
+ free(scheme);
+ return (-1);
+ }
+ parsep = atsignp + 1;
+ } else {
+ /*
+ * No.
+ */
+ userinfo = NULL;
+ }
+
+ /*
+ * Is there a host field?
+ */
+ if (*parsep == '\0') {
+ /*
+ * No; there's no host field or port field.
+ */
+ host = NULL;
+ port = NULL;
+ } else {
+ /*
+ * Yes.
+ */
+ size_t host_len;
+
+ /*
+ * Is it an IP-literal?
+ */
+ if (*parsep == '[') {
+ /*
+ * Yes.
+ * Treat verything up to the closing square
+ * bracket as the IP-Literal; we don't worry
+ * about whether it's a valid IPv6address or
+ * IPvFuture (or an IPv4address, for that
+ * matter, just in case we get handed a
+ * URL with an IPv4 IP-Literal, of the sort
+ * that pcap_createsrcstr() used to generate,
+ * and that pcap_parsesrcstr(), in the original
+ * WinPcap code, accepted).
+ */
+ bracketp = strchr(parsep, ']');
+ if (bracketp == NULL) {
+ /*
+ * There's no closing square bracket.
+ */
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "IP-literal in URL doesn't end with ]");
+ free(userinfo);
+ free(authority);
+ free(scheme);
+ return (-1);
+ }
+ if (*(bracketp + 1) != '\0' &&
+ *(bracketp + 1) != ':') {
+ /*
+ * There's extra crud after the
+ * closing square bracketn.
+ */
+ pcap_snprintf(ebuf, PCAP_ERRBUF_SIZE,
+ "Extra text after IP-literal in URL");
+ free(userinfo);
+ free(authority);
+ free(scheme);
+ return (-1);
+ }
+ host_len = (bracketp - 1) - parsep;
+ host = get_substring(parsep + 1, host_len, ebuf);
+ if (host == NULL) {
+ /*
+ * Error.
+ */
+ free(userinfo);
+ free(authority);
+ free(scheme);
+ return (-1);
+ }
+ parsep = bracketp + 1;
+ } else {
+ /*
+ * No.
+ * Treat everything up to a : or the end of
+ * the string as the host.
+ */
+ host_len = strcspn(parsep, ":");
+ host = get_substring(parsep, host_len, ebuf);
+ if (host == NULL) {
+ /*
+ * Error.
+ */
+ free(userinfo);
+ free(authority);
+ free(scheme);
+ return (-1);
+ }
+ parsep = parsep + host_len;
+ }
+
+ /*
+ * Is there a port field?
+ */
+ if (*parsep == ':') {
+ /*
+ * Yes. It's the rest of the authority field.
+ */
+ size_t port_len;
+
+ parsep++;
+ port_len = strlen(parsep);
+ port = get_substring(parsep, port_len, ebuf);
+ if (port == NULL) {
+ /*
+ * Error.
+ */
+ free(host);
+ free(userinfo);
+ free(authority);
+ free(scheme);
+ return (-1);
+ }
+ } else {
+ /*
+ * No.
+ */
+ port = NULL;
+ }
+ }
+ free(authority);
+
+ /*
+ * Everything else is the path. Strip off the leading /.
+ */
+ if (*endp == '\0')
+ path = strdup("");
+ else
+ path = strdup(endp + 1);
+ if (path == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ free(port);
+ free(host);
+ free(userinfo);
+ free(scheme);
+ return (-1);
+ }
+ *schemep = scheme;
+ *userinfop = userinfo;
+ *hostp = host;
+ *portp = port;
+ *pathp = path;
+ return (0);
+}
+
+int
+pcap_createsrcstr(char *source, int type, const char *host, const char *port,
+ const char *name, char *errbuf)
+{
+ switch (type) {
+
+ case PCAP_SRC_FILE:
+ pcap_strlcpy(source, PCAP_SRC_FILE_STRING, PCAP_BUF_SIZE);
+ if (name != NULL && *name != '\0') {
+ pcap_strlcat(source, name, PCAP_BUF_SIZE);
+ return (0);
+ } else {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "The file name cannot be NULL.");
+ return (-1);
+ }
+
+ case PCAP_SRC_IFREMOTE:
+ pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+ if (host != NULL && *host != '\0') {
+ if (strchr(host, ':') != NULL) {
+ /*
+ * The host name contains a colon, so it's
+ * probably an IPv6 address, and needs to
+ * be included in square brackets.
+ */
+ pcap_strlcat(source, "[", PCAP_BUF_SIZE);
+ pcap_strlcat(source, host, PCAP_BUF_SIZE);
+ pcap_strlcat(source, "]", PCAP_BUF_SIZE);
+ } else
+ pcap_strlcat(source, host, PCAP_BUF_SIZE);
+
+ if (port != NULL && *port != '\0') {
+ pcap_strlcat(source, ":", PCAP_BUF_SIZE);
+ pcap_strlcat(source, port, PCAP_BUF_SIZE);
+ }
+
+ pcap_strlcat(source, "/", PCAP_BUF_SIZE);
+ } else {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "The host name cannot be NULL.");
+ return (-1);
+ }
+
+ if (name != NULL && *name != '\0')
+ pcap_strlcat(source, name, PCAP_BUF_SIZE);
+
+ return (0);
+
+ case PCAP_SRC_IFLOCAL:
+ pcap_strlcpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
+
+ if (name != NULL && *name != '\0')
+ pcap_strlcat(source, name, PCAP_BUF_SIZE);
+
+ return (0);
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "The interface type is not valid.");
+ return (-1);
+ }
+}
+
+int
+pcap_parsesrcstr(const char *source, int *type, char *host, char *port,
+ char *name, char *errbuf)
+{
+ char *scheme, *tmpuserinfo, *tmphost, *tmpport, *tmppath;
+
+ /* Initialization stuff */
+ if (host)
+ *host = '\0';
+ if (port)
+ *port = '\0';
+ if (name)
+ *name = '\0';
+
+ /* Parse the source string */
+ if (pcap_parse_source(source, &scheme, &tmpuserinfo, &tmphost,
+ &tmpport, &tmppath, errbuf) == -1) {
+ /*
+ * Fail.
+ */
+ return (-1);
+ }
+
+ if (scheme == NULL) {
+ /*
+ * Local device.
+ */
+ if (name && tmppath)
+ pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
+ if (type)
+ *type = PCAP_SRC_IFLOCAL;
+ free(tmppath);
+ free(tmpport);
+ free(tmphost);
+ free(tmpuserinfo);
+ return (0);
+ }
+
+ if (strcmp(scheme, "rpcap") == 0) {
+ /*
+ * rpcap://
+ *
+ * pcap_parse_source() has already handled the case of
+ * rpcap://device
+ */
+ if (host && tmphost) {
+ if (tmpuserinfo)
+ pcap_snprintf(host, PCAP_BUF_SIZE, "%s@%s",
+ tmpuserinfo, tmphost);
+ else
+ pcap_strlcpy(host, tmphost, PCAP_BUF_SIZE);
+ }
+ if (port && tmpport)
+ pcap_strlcpy(port, tmpport, PCAP_BUF_SIZE);
+ if (name && tmppath)
+ pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
+ if (type)
+ *type = PCAP_SRC_IFREMOTE;
+ free(tmppath);
+ free(tmpport);
+ free(tmphost);
+ free(tmpuserinfo);
+ free(scheme);
+ return (0);
+ }
+
+ if (strcmp(scheme, "file") == 0) {
+ /*
+ * file://
+ */
+ if (name && tmppath)
+ pcap_strlcpy(name, tmppath, PCAP_BUF_SIZE);
+ if (type)
+ *type = PCAP_SRC_FILE;
+ free(tmppath);
+ free(tmpport);
+ free(tmphost);
+ free(tmpuserinfo);
+ free(scheme);
+ return (0);
+ }
+
+ /*
+ * Neither rpcap: nor file:; just treat the entire string
+ * as a local device.
+ */
+ if (name)
+ pcap_strlcpy(name, source, PCAP_BUF_SIZE);
+ if (type)
+ *type = PCAP_SRC_IFLOCAL;
+ free(tmppath);
+ free(tmpport);
+ free(tmphost);
+ free(tmpuserinfo);
+ free(scheme);
+ return (0);
+}
+#endif
+
+pcap_t *
+pcap_create(const char *device, char *errbuf)
+{
+ size_t i;
+ int is_theirs;
+ pcap_t *p;
+ char *device_str;
+
+ /*
+ * A null device name is equivalent to the "any" device -
+ * which might not be supported on this platform, but
+ * this means that you'll get a "not supported" error
+ * rather than, say, a crash when we try to dereference
+ * the null pointer.
+ */
+ if (device == NULL)
+ device_str = strdup("any");
+ else {
+#ifdef _WIN32
+ /*
+ * On Windows, for backwards compatibility reasons,
+ * pcap_lookupdev() returns a pointer to a sequence of
+ * pairs of UTF-16LE device names and local code page
+ * description strings.
+ *
+ * This means that if a program uses pcap_lookupdev()
+ * to get a default device, and hands that to an API
+ * that opens devices, we'll get handed a UTF-16LE
+ * string, not a string in the local code page.
+ *
+ * To work around that, we check whether the string
+ * looks as if it might be a UTF-16LE strinh and, if
+ * so, convert it back to the local code page's
+ * extended ASCII.
+ *
+ * XXX - you *cannot* reliably detect whether a
+ * string is UTF-16LE or not; "a" could either
+ * be a one-character ASCII string or the first
+ * character of a UTF-16LE string. This particular
+ * version of this heuristic dates back to WinPcap
+ * 4.1.1; PacketOpenAdapter() does uses the same
+ * heuristic, with the exact same vulnerability.
+ */
+ if (device[0] != '\0' && device[1] == '\0') {
+ size_t length;
+
+ length = wcslen((wchar_t *)device);
+ device_str = (char *)malloc(length + 1);
+ if (device_str == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "malloc");
+ return (NULL);
+ }
+
+ pcap_snprintf(device_str, length + 1, "%ws",
+ (const wchar_t *)device);
+ } else
+#endif
+ device_str = strdup(device);
+ }
+ if (device_str == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (NULL);
+ }
+
+ /*
+ * Try each of the non-local-network-interface capture
+ * source types until we find one that works for this
+ * device or run out of types.
+ */
+ for (i = 0; capture_source_types[i].create_op != NULL; i++) {
+ is_theirs = 0;
+ p = capture_source_types[i].create_op(device_str, errbuf,
+ &is_theirs);
+ if (is_theirs) {
+ /*
+ * The device name refers to a device of the
+ * type in question; either it succeeded,
+ * in which case p refers to a pcap_t to
+ * later activate for the device, or it
+ * failed, in which case p is null and we
+ * should return that to report the failure
+ * to create.
+ */
+ if (p == NULL) {
+ /*
+ * We assume the caller filled in errbuf.
+ */
+ free(device_str);
+ return (NULL);
+ }
+ p->opt.device = device_str;
+ return (p);
+ }
+ }
+
+ /*
+ * OK, try it as a regular network interface.
+ */
+ p = pcap_create_interface(device_str, errbuf);
+ if (p == NULL) {
+ /*
+ * We assume the caller filled in errbuf.
+ */
+ free(device_str);
+ return (NULL);
+ }
+ p->opt.device = device_str;
+ return (p);
+}
+
+/*
+ * Set nonblocking mode on an unactivated pcap_t; this sets a flag
+ * checked by pcap_activate(), which sets the mode after calling
+ * the activate routine.
+ */
+static int
+pcap_setnonblock_unactivated(pcap_t *p, int nonblock)
+{
+ p->opt.nonblock = nonblock;
+ return (0);
+}
+
+static void
+initialize_ops(pcap_t *p)
+{
+ /*
+ * Set operation pointers for operations that only work on
+ * an activated pcap_t to point to a routine that returns
+ * a "this isn't activated" error.
+ */
+ p->read_op = pcap_read_not_initialized;
+ p->inject_op = pcap_inject_not_initialized;
+ p->setfilter_op = pcap_setfilter_not_initialized;
+ p->setdirection_op = pcap_setdirection_not_initialized;
+ p->set_datalink_op = pcap_set_datalink_not_initialized;
+ p->getnonblock_op = pcap_getnonblock_not_initialized;
+ p->stats_op = pcap_stats_not_initialized;
+#ifdef _WIN32
+ p->stats_ex_op = pcap_stats_ex_not_initialized;
+ p->setbuff_op = pcap_setbuff_not_initialized;
+ p->setmode_op = pcap_setmode_not_initialized;
+ p->setmintocopy_op = pcap_setmintocopy_not_initialized;
+ p->getevent_op = pcap_getevent_not_initialized;
+ p->oid_get_request_op = pcap_oid_get_request_not_initialized;
+ p->oid_set_request_op = pcap_oid_set_request_not_initialized;
+ p->sendqueue_transmit_op = pcap_sendqueue_transmit_not_initialized;
+ p->setuserbuffer_op = pcap_setuserbuffer_not_initialized;
+ p->live_dump_op = pcap_live_dump_not_initialized;
+ p->live_dump_ended_op = pcap_live_dump_ended_not_initialized;
+ p->get_airpcap_handle_op = pcap_get_airpcap_handle_not_initialized;
+#endif
+
+ /*
+ * Default cleanup operation - implementations can override
+ * this, but should call pcap_cleanup_live_common() after
+ * doing their own additional cleanup.
+ */
+ p->cleanup_op = pcap_cleanup_live_common;
+
+ /*
+ * In most cases, the standard one-shot callback can
+ * be used for pcap_next()/pcap_next_ex().
+ */
+ p->oneshot_callback = pcap_oneshot;
+}
+
+static pcap_t *
+pcap_alloc_pcap_t(char *ebuf, size_t size)
+{
+ char *chunk;
+ pcap_t *p;
+
+ /*
+ * Allocate a chunk of memory big enough for a pcap_t
+ * plus a structure following it of size "size". The
+ * structure following it is a private data structure
+ * for the routines that handle this pcap_t.
+ *
+ * The structure following it must be aligned on
+ * the appropriate alignment boundary for this platform.
+ * We align on an 8-byte boundary as that's probably what
+ * at least some platforms do, even with 32-bit integers,
+ * and because we can't be sure that some values won't
+ * require 8-byte alignment even on platforms with 32-bit
+ * integers.
+ */
+#define PCAP_T_ALIGNED_SIZE ((sizeof(pcap_t) + 7U) & ~0x7U)
+ chunk = malloc(PCAP_T_ALIGNED_SIZE + size);
+ if (chunk == NULL) {
+ pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc");
+ return (NULL);
+ }
+ memset(chunk, 0, PCAP_T_ALIGNED_SIZE + size);
+
+ /*
+ * Get a pointer to the pcap_t at the beginning.
+ */
+ p = (pcap_t *)chunk;
+
+#ifdef _WIN32
+ p->handle = INVALID_HANDLE_VALUE; /* not opened yet */
+#else /* _WIN32 */
+ p->fd = -1; /* not opened yet */
+#ifndef MSDOS
+ p->selectable_fd = -1;
+ p->required_select_timeout = NULL;
+#endif /* MSDOS */
+#endif /* _WIN32 */
+
+ if (size == 0) {
+ /* No private data was requested. */
+ p->priv = NULL;
+ } else {
+ /*
+ * Set the pointer to the private data; that's the structure
+ * of size "size" following the pcap_t.
+ */
+ p->priv = (void *)(chunk + PCAP_T_ALIGNED_SIZE);
+ }
+
+ return (p);
+}
+
+pcap_t *
+pcap_create_common(char *ebuf, size_t size)
+{
+ pcap_t *p;
+
+ p = pcap_alloc_pcap_t(ebuf, size);
+ if (p == NULL)
+ return (NULL);
+
+ /*
+ * Default to "can't set rfmon mode"; if it's supported by
+ * a platform, the create routine that called us can set
+ * the op to its routine to check whether a particular
+ * device supports it.
+ */
+ p->can_set_rfmon_op = pcap_cant_set_rfmon;
+
+ /*
+ * If pcap_setnonblock() is called on a not-yet-activated
+ * pcap_t, default to setting a flag and turning
+ * on non-blocking mode when activated.
+ */
+ p->setnonblock_op = pcap_setnonblock_unactivated;
+
+ initialize_ops(p);
+
+ /* put in some defaults*/
+ p->snapshot = 0; /* max packet size unspecified */
+ p->opt.timeout = 0; /* no timeout specified */
+ p->opt.buffer_size = 0; /* use the platform's default */
+ p->opt.promisc = 0;
+ p->opt.rfmon = 0;
+ p->opt.immediate = 0;
+ p->opt.tstamp_type = -1; /* default to not setting time stamp type */
+ p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
+ /*
+ * Platform-dependent options.
+ */
+#ifdef __linux__
+ p->opt.protocol = 0;
+#endif
+#ifdef _WIN32
+ p->opt.nocapture_local = 0;
+#endif
+
+ /*
+ * Start out with no BPF code generation flags set.
+ */
+ p->bpf_codegen_flags = 0;
+
+ return (p);
+}
+
+int
+pcap_check_activated(pcap_t *p)
+{
+ if (p->activated) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "can't perform "
+ " operation on activated capture");
+ return (-1);
+ }
+ return (0);
+}
+
+int
+pcap_set_snaplen(pcap_t *p, int snaplen)
+{
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ p->snapshot = snaplen;
+ return (0);
+}
+
+int
+pcap_set_promisc(pcap_t *p, int promisc)
+{
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ p->opt.promisc = promisc;
+ return (0);
+}
+
+int
+pcap_set_rfmon(pcap_t *p, int rfmon)
+{
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ p->opt.rfmon = rfmon;
+ return (0);
+}
+
+int
+pcap_set_timeout(pcap_t *p, int timeout_ms)
+{
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ p->opt.timeout = timeout_ms;
+ return (0);
+}
+
+int
+pcap_set_tstamp_type(pcap_t *p, int tstamp_type)
+{
+ int i;
+
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+
+ /*
+ * The argument should have been u_int, but that's too late
+ * to change now - it's an API.
+ */
+ if (tstamp_type < 0)
+ return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
+
+ /*
+ * If p->tstamp_type_count is 0, we only support PCAP_TSTAMP_HOST;
+ * the default time stamp type is PCAP_TSTAMP_HOST.
+ */
+ if (p->tstamp_type_count == 0) {
+ if (tstamp_type == PCAP_TSTAMP_HOST) {
+ p->opt.tstamp_type = tstamp_type;
+ return (0);
+ }
+ } else {
+ /*
+ * Check whether we claim to support this type of time stamp.
+ */
+ for (i = 0; i < p->tstamp_type_count; i++) {
+ if (p->tstamp_type_list[i] == (u_int)tstamp_type) {
+ /*
+ * Yes.
+ */
+ p->opt.tstamp_type = tstamp_type;
+ return (0);
+ }
+ }
+ }
+
+ /*
+ * We don't support this type of time stamp.
+ */
+ return (PCAP_WARNING_TSTAMP_TYPE_NOTSUP);
+}
+
+int
+pcap_set_immediate_mode(pcap_t *p, int immediate)
+{
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ p->opt.immediate = immediate;
+ return (0);
+}
+
+int
+pcap_set_buffer_size(pcap_t *p, int buffer_size)
+{
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ if (buffer_size <= 0) {
+ /*
+ * Silently ignore invalid values.
+ */
+ return (0);
+ }
+ p->opt.buffer_size = buffer_size;
+ return (0);
+}
+
+int
+pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision)
+{
+ int i;
+
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+
+ /*
+ * The argument should have been u_int, but that's too late
+ * to change now - it's an API.
+ */
+ if (tstamp_precision < 0)
+ return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
+
+ /*
+ * If p->tstamp_precision_count is 0, we only support setting
+ * the time stamp precision to microsecond precision; every
+ * pcap module *MUST* support microsecond precision, even if
+ * it does so by converting the native precision to
+ * microseconds.
+ */
+ if (p->tstamp_precision_count == 0) {
+ if (tstamp_precision == PCAP_TSTAMP_PRECISION_MICRO) {
+ p->opt.tstamp_precision = tstamp_precision;
+ return (0);
+ }
+ } else {
+ /*
+ * Check whether we claim to support this precision of
+ * time stamp.
+ */
+ for (i = 0; i < p->tstamp_precision_count; i++) {
+ if (p->tstamp_precision_list[i] == (u_int)tstamp_precision) {
+ /*
+ * Yes.
+ */
+ p->opt.tstamp_precision = tstamp_precision;
+ return (0);
+ }
+ }
+ }
+
+ /*
+ * We don't support this time stamp precision.
+ */
+ return (PCAP_ERROR_TSTAMP_PRECISION_NOTSUP);
+}
+
+int
+pcap_get_tstamp_precision(pcap_t *p)
+{
+ return (p->opt.tstamp_precision);
+}
+
+int
+pcap_activate(pcap_t *p)
+{
+ int status;
+
+ /*
+ * Catch attempts to re-activate an already-activated
+ * pcap_t; this should, for example, catch code that
+ * calls pcap_open_live() followed by pcap_activate(),
+ * as some code that showed up in a Stack Exchange
+ * question did.
+ */
+ if (pcap_check_activated(p))
+ return (PCAP_ERROR_ACTIVATED);
+ status = p->activate_op(p);
+ if (status >= 0) {
+ /*
+ * If somebody requested non-blocking mode before
+ * calling pcap_activate(), turn it on now.
+ */
+ if (p->opt.nonblock) {
+ status = p->setnonblock_op(p, 1);
+ if (status < 0) {
+ /*
+ * Failed. Undo everything done by
+ * the activate operation.
+ */
+ p->cleanup_op(p);
+ initialize_ops(p);
+ return (status);
+ }
+ }
+ p->activated = 1;
+ } else {
+ if (p->errbuf[0] == '\0') {
+ /*
+ * No error message supplied by the activate routine;
+ * for the benefit of programs that don't specially
+ * handle errors other than PCAP_ERROR, return the
+ * error message corresponding to the status.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s",
+ pcap_statustostr(status));
+ }
+
+ /*
+ * Undo any operation pointer setting, etc. done by
+ * the activate operation.
+ */
+ initialize_ops(p);
+ }
+ return (status);
+}
+
+pcap_t *
+pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, char *errbuf)
+{
+ pcap_t *p;
+ int status;
+#ifdef ENABLE_REMOTE
+ char host[PCAP_BUF_SIZE + 1];
+ char port[PCAP_BUF_SIZE + 1];
+ char name[PCAP_BUF_SIZE + 1];
+ int srctype;
+
+ /*
+ * A null device name is equivalent to the "any" device -
+ * which might not be supported on this platform, but
+ * this means that you'll get a "not supported" error
+ * rather than, say, a crash when we try to dereference
+ * the null pointer.
+ */
+ if (device == NULL)
+ device = "any";
+
+ /*
+ * Retrofit - we have to make older applications compatible with
+ * remote capture.
+ * So we're calling pcap_open_remote() from here; this is a very
+ * dirty hack.
+ * Obviously, we cannot exploit all the new features; for instance,
+ * we cannot send authentication, we cannot use a UDP data connection,
+ * and so on.
+ */
+ if (pcap_parsesrcstr(device, &srctype, host, port, name, errbuf))
+ return (NULL);
+
+ if (srctype == PCAP_SRC_IFREMOTE) {
+ /*
+ * Although we already have host, port and iface, we prefer
+ * to pass only 'device' to pcap_open_rpcap(), so that it has
+ * to call pcap_parsesrcstr() again.
+ * This is less optimized, but much clearer.
+ */
+ return (pcap_open_rpcap(device, snaplen,
+ promisc ? PCAP_OPENFLAG_PROMISCUOUS : 0, to_ms,
+ NULL, errbuf));
+ }
+ if (srctype == PCAP_SRC_FILE) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown URL scheme \"file\"");
+ return (NULL);
+ }
+ if (srctype == PCAP_SRC_IFLOCAL) {
+ /*
+ * If it starts with rpcap://, that refers to a local device
+ * (no host part in the URL). Remove the rpcap://, and
+ * fall through to the regular open path.
+ */
+ if (strncmp(device, PCAP_SRC_IF_STRING, strlen(PCAP_SRC_IF_STRING)) == 0) {
+ size_t len = strlen(device) - strlen(PCAP_SRC_IF_STRING) + 1;
+
+ if (len > 0)
+ device += strlen(PCAP_SRC_IF_STRING);
+ }
+ }
+#endif /* ENABLE_REMOTE */
+
+ p = pcap_create(device, errbuf);
+ if (p == NULL)
+ return (NULL);
+ status = pcap_set_snaplen(p, snaplen);
+ if (status < 0)
+ goto fail;
+ status = pcap_set_promisc(p, promisc);
+ if (status < 0)
+ goto fail;
+ status = pcap_set_timeout(p, to_ms);
+ if (status < 0)
+ goto fail;
+ /*
+ * Mark this as opened with pcap_open_live(), so that, for
+ * example, we show the full list of DLT_ values, rather
+ * than just the ones that are compatible with capturing
+ * when not in monitor mode. That allows existing applications
+ * to work the way they used to work, but allows new applications
+ * that know about the new open API to, for example, find out the
+ * DLT_ values that they can select without changing whether
+ * the adapter is in monitor mode or not.
+ */
+ p->oldstyle = 1;
+ status = pcap_activate(p);
+ if (status < 0)
+ goto fail;
+ return (p);
+fail:
+ if (status == PCAP_ERROR)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %.*s", device,
+ PCAP_ERRBUF_SIZE - 3, p->errbuf);
+ else if (status == PCAP_ERROR_NO_SUCH_DEVICE ||
+ status == PCAP_ERROR_PERM_DENIED ||
+ status == PCAP_ERROR_PROMISC_PERM_DENIED)
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s (%.*s)", device,
+ pcap_statustostr(status), PCAP_ERRBUF_SIZE - 6, p->errbuf);
+ else
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", device,
+ pcap_statustostr(status));
+ pcap_close(p);
+ return (NULL);
+}
+
+pcap_t *
+pcap_open_offline_common(char *ebuf, size_t size)
+{
+ pcap_t *p;
+
+ p = pcap_alloc_pcap_t(ebuf, size);
+ if (p == NULL)
+ return (NULL);
+
+ p->opt.tstamp_precision = PCAP_TSTAMP_PRECISION_MICRO;
+
+ return (p);
+}
+
+int
+pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ return (p->read_op(p, cnt, callback, user));
+}
+
+int
+pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ register int n;
+
+ for (;;) {
+ if (p->rfile != NULL) {
+ /*
+ * 0 means EOF, so don't loop if we get 0.
+ */
+#ifdef __APPLE__
+ n = p->read_op(p, cnt, callback, user);
+#else
+ n = pcap_offline_read(p, cnt, callback, user);
+#endif /* __APPLE__ */
+ } else {
+ /*
+ * XXX keep reading until we get something
+ * (or an error occurs)
+ */
+ do {
+ n = p->read_op(p, cnt, callback, user);
+ } while (n == 0);
+ }
+ if (n <= 0)
+ return (n);
+ if (!PACKET_COUNT_IS_UNLIMITED(cnt)) {
+ cnt -= n;
+ if (cnt <= 0)
+ return (0);
+ }
+ }
+}
+
+/*
+ * Force the loop in "pcap_read()" or "pcap_read_offline()" to terminate.
+ */
+void
+pcap_breakloop(pcap_t *p)
+{
+ p->break_loop = 1;
+}
+
+int
+pcap_datalink(pcap_t *p)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ return (p->linktype);
+}
+
+int
+pcap_datalink_ext(pcap_t *p)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ return (p->linktype_ext);
+}
+
+int
+pcap_list_datalinks(pcap_t *p, int **dlt_buffer)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ if (p->dlt_count == 0) {
+ /*
+ * We couldn't fetch the list of DLTs, which means
+ * this platform doesn't support changing the
+ * DLT for an interface. Return a list of DLTs
+ * containing only the DLT this device supports.
+ */
+ *dlt_buffer = (int*)malloc(sizeof(**dlt_buffer));
+ if (*dlt_buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "malloc");
+ return (PCAP_ERROR);
+ }
+ **dlt_buffer = p->linktype;
+ return (1);
+ } else {
+ *dlt_buffer = (int*)calloc(sizeof(**dlt_buffer), p->dlt_count);
+ if (*dlt_buffer == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, sizeof(p->errbuf),
+ errno, "malloc");
+ return (PCAP_ERROR);
+ }
+ (void)memcpy(*dlt_buffer, p->dlt_list,
+ sizeof(**dlt_buffer) * p->dlt_count);
+ return (p->dlt_count);
+ }
+}
+
+/*
+ * In Windows, you might have a library built with one version of the
+ * C runtime library and an application built with another version of
+ * the C runtime library, which means that the library might use one
+ * version of malloc() and free() and the application might use another
+ * version of malloc() and free(). If so, that means something
+ * allocated by the library cannot be freed by the application, so we
+ * need to have a pcap_free_datalinks() routine to free up the list
+ * allocated by pcap_list_datalinks(), even though it's just a wrapper
+ * around free().
+ */
+void
+pcap_free_datalinks(int *dlt_list)
+{
+ free(dlt_list);
+}
+
+int
+pcap_set_datalink(pcap_t *p, int dlt)
+{
+ int i;
+ const char *dlt_name;
+
+ if (dlt < 0)
+ goto unsupported;
+
+ if (p->dlt_count == 0 || p->set_datalink_op == NULL) {
+ /*
+ * We couldn't fetch the list of DLTs, or we don't
+ * have a "set datalink" operation, which means
+ * this platform doesn't support changing the
+ * DLT for an interface. Check whether the new
+ * DLT is the one this interface supports.
+ */
+ if (p->linktype != dlt)
+ goto unsupported;
+
+ /*
+ * It is, so there's nothing we need to do here.
+ */
+ return (0);
+ }
+ for (i = 0; i < p->dlt_count; i++)
+ if (p->dlt_list[i] == (u_int)dlt)
+ break;
+ if (i >= p->dlt_count)
+ goto unsupported;
+ if (p->dlt_count == 2 && p->dlt_list[0] == DLT_EN10MB &&
+ dlt == DLT_DOCSIS) {
+ /*
+ * This is presumably an Ethernet device, as the first
+ * link-layer type it offers is DLT_EN10MB, and the only
+ * other type it offers is DLT_DOCSIS. That means that
+ * we can't tell the driver to supply DOCSIS link-layer
+ * headers - we're just pretending that's what we're
+ * getting, as, presumably, we're capturing on a dedicated
+ * link to a Cisco Cable Modem Termination System, and
+ * it's putting raw DOCSIS frames on the wire inside low-level
+ * Ethernet framing.
+ */
+ p->linktype = dlt;
+ return (0);
+ }
+ if (p->set_datalink_op(p, dlt) == -1)
+ return (-1);
+ p->linktype = dlt;
+ return (0);
+
+unsupported:
+ dlt_name = pcap_datalink_val_to_name(dlt);
+ if (dlt_name != NULL) {
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "%s is not one of the DLTs supported by this device",
+ dlt_name);
+ } else {
+ (void) pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "DLT %d is not one of the DLTs supported by this device",
+ dlt);
+ }
+ return (-1);
+}
+
+/*
+ * This array is designed for mapping upper and lower case letter
+ * together for a case independent comparison. The mappings are
+ * based upon ascii character sequences.
+ */
+static const u_char charmap[] = {
+ (u_char)'\000', (u_char)'\001', (u_char)'\002', (u_char)'\003',
+ (u_char)'\004', (u_char)'\005', (u_char)'\006', (u_char)'\007',
+ (u_char)'\010', (u_char)'\011', (u_char)'\012', (u_char)'\013',
+ (u_char)'\014', (u_char)'\015', (u_char)'\016', (u_char)'\017',
+ (u_char)'\020', (u_char)'\021', (u_char)'\022', (u_char)'\023',
+ (u_char)'\024', (u_char)'\025', (u_char)'\026', (u_char)'\027',
+ (u_char)'\030', (u_char)'\031', (u_char)'\032', (u_char)'\033',
+ (u_char)'\034', (u_char)'\035', (u_char)'\036', (u_char)'\037',
+ (u_char)'\040', (u_char)'\041', (u_char)'\042', (u_char)'\043',
+ (u_char)'\044', (u_char)'\045', (u_char)'\046', (u_char)'\047',
+ (u_char)'\050', (u_char)'\051', (u_char)'\052', (u_char)'\053',
+ (u_char)'\054', (u_char)'\055', (u_char)'\056', (u_char)'\057',
+ (u_char)'\060', (u_char)'\061', (u_char)'\062', (u_char)'\063',
+ (u_char)'\064', (u_char)'\065', (u_char)'\066', (u_char)'\067',
+ (u_char)'\070', (u_char)'\071', (u_char)'\072', (u_char)'\073',
+ (u_char)'\074', (u_char)'\075', (u_char)'\076', (u_char)'\077',
+ (u_char)'\100', (u_char)'\141', (u_char)'\142', (u_char)'\143',
+ (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
+ (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
+ (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
+ (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
+ (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
+ (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\133',
+ (u_char)'\134', (u_char)'\135', (u_char)'\136', (u_char)'\137',
+ (u_char)'\140', (u_char)'\141', (u_char)'\142', (u_char)'\143',
+ (u_char)'\144', (u_char)'\145', (u_char)'\146', (u_char)'\147',
+ (u_char)'\150', (u_char)'\151', (u_char)'\152', (u_char)'\153',
+ (u_char)'\154', (u_char)'\155', (u_char)'\156', (u_char)'\157',
+ (u_char)'\160', (u_char)'\161', (u_char)'\162', (u_char)'\163',
+ (u_char)'\164', (u_char)'\165', (u_char)'\166', (u_char)'\167',
+ (u_char)'\170', (u_char)'\171', (u_char)'\172', (u_char)'\173',
+ (u_char)'\174', (u_char)'\175', (u_char)'\176', (u_char)'\177',
+ (u_char)'\200', (u_char)'\201', (u_char)'\202', (u_char)'\203',
+ (u_char)'\204', (u_char)'\205', (u_char)'\206', (u_char)'\207',
+ (u_char)'\210', (u_char)'\211', (u_char)'\212', (u_char)'\213',
+ (u_char)'\214', (u_char)'\215', (u_char)'\216', (u_char)'\217',
+ (u_char)'\220', (u_char)'\221', (u_char)'\222', (u_char)'\223',
+ (u_char)'\224', (u_char)'\225', (u_char)'\226', (u_char)'\227',
+ (u_char)'\230', (u_char)'\231', (u_char)'\232', (u_char)'\233',
+ (u_char)'\234', (u_char)'\235', (u_char)'\236', (u_char)'\237',
+ (u_char)'\240', (u_char)'\241', (u_char)'\242', (u_char)'\243',
+ (u_char)'\244', (u_char)'\245', (u_char)'\246', (u_char)'\247',
+ (u_char)'\250', (u_char)'\251', (u_char)'\252', (u_char)'\253',
+ (u_char)'\254', (u_char)'\255', (u_char)'\256', (u_char)'\257',
+ (u_char)'\260', (u_char)'\261', (u_char)'\262', (u_char)'\263',
+ (u_char)'\264', (u_char)'\265', (u_char)'\266', (u_char)'\267',
+ (u_char)'\270', (u_char)'\271', (u_char)'\272', (u_char)'\273',
+ (u_char)'\274', (u_char)'\275', (u_char)'\276', (u_char)'\277',
+ (u_char)'\300', (u_char)'\341', (u_char)'\342', (u_char)'\343',
+ (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
+ (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
+ (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
+ (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
+ (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
+ (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\333',
+ (u_char)'\334', (u_char)'\335', (u_char)'\336', (u_char)'\337',
+ (u_char)'\340', (u_char)'\341', (u_char)'\342', (u_char)'\343',
+ (u_char)'\344', (u_char)'\345', (u_char)'\346', (u_char)'\347',
+ (u_char)'\350', (u_char)'\351', (u_char)'\352', (u_char)'\353',
+ (u_char)'\354', (u_char)'\355', (u_char)'\356', (u_char)'\357',
+ (u_char)'\360', (u_char)'\361', (u_char)'\362', (u_char)'\363',
+ (u_char)'\364', (u_char)'\365', (u_char)'\366', (u_char)'\367',
+ (u_char)'\370', (u_char)'\371', (u_char)'\372', (u_char)'\373',
+ (u_char)'\374', (u_char)'\375', (u_char)'\376', (u_char)'\377',
+};
+
+int
+pcap_strcasecmp(const char *s1, const char *s2)
+{
+ register const u_char *cm = charmap,
+ *us1 = (const u_char *)s1,
+ *us2 = (const u_char *)s2;
+
+ while (cm[*us1] == cm[*us2++])
+ if (*us1++ == '\0')
+ return(0);
+ return (cm[*us1] - cm[*--us2]);
+}
+
+struct dlt_choice {
+ const char *name;
+ const char *description;
+ int dlt;
+};
+
+#define DLT_CHOICE(code, description) { #code, description, DLT_ ## code }
+#define DLT_CHOICE_SENTINEL { NULL, NULL, 0 }
+
+static struct dlt_choice dlt_choices[] = {
+#ifdef __APPLE__
+ DLT_CHOICE(PCAPNG, "pcapng"),
+#endif /* __APPLE__ */
+ DLT_CHOICE(NULL, "BSD loopback"),
+ DLT_CHOICE(EN10MB, "Ethernet"),
+ DLT_CHOICE(IEEE802, "Token ring"),
+ DLT_CHOICE(ARCNET, "BSD ARCNET"),
+ DLT_CHOICE(SLIP, "SLIP"),
+ DLT_CHOICE(PPP, "PPP"),
+ DLT_CHOICE(FDDI, "FDDI"),
+ DLT_CHOICE(ATM_RFC1483, "RFC 1483 LLC-encapsulated ATM"),
+ DLT_CHOICE(RAW, "Raw IP"),
+ DLT_CHOICE(SLIP_BSDOS, "BSD/OS SLIP"),
+ DLT_CHOICE(PPP_BSDOS, "BSD/OS PPP"),
+ DLT_CHOICE(ATM_CLIP, "Linux Classical IP-over-ATM"),
+ DLT_CHOICE(PPP_SERIAL, "PPP over serial"),
+ DLT_CHOICE(PPP_ETHER, "PPPoE"),
+ DLT_CHOICE(SYMANTEC_FIREWALL, "Symantec Firewall"),
+ DLT_CHOICE(C_HDLC, "Cisco HDLC"),
+ DLT_CHOICE(IEEE802_11, "802.11"),
+ DLT_CHOICE(FRELAY, "Frame Relay"),
+ DLT_CHOICE(LOOP, "OpenBSD loopback"),
+ DLT_CHOICE(ENC, "OpenBSD encapsulated IP"),
+ DLT_CHOICE(LINUX_SLL, "Linux cooked v1"),
+ DLT_CHOICE(LTALK, "Localtalk"),
+ DLT_CHOICE(PFLOG, "OpenBSD pflog file"),
+ DLT_CHOICE(PFSYNC, "Packet filter state syncing"),
+ DLT_CHOICE(PRISM_HEADER, "802.11 plus Prism header"),
+ DLT_CHOICE(IP_OVER_FC, "RFC 2625 IP-over-Fibre Channel"),
+ DLT_CHOICE(SUNATM, "Sun raw ATM"),
+ DLT_CHOICE(IEEE802_11_RADIO, "802.11 plus radiotap header"),
+ DLT_CHOICE(ARCNET_LINUX, "Linux ARCNET"),
+ DLT_CHOICE(JUNIPER_MLPPP, "Juniper Multi-Link PPP"),
+ DLT_CHOICE(JUNIPER_MLFR, "Juniper Multi-Link Frame Relay"),
+ DLT_CHOICE(JUNIPER_ES, "Juniper Encryption Services PIC"),
+ DLT_CHOICE(JUNIPER_GGSN, "Juniper GGSN PIC"),
+ DLT_CHOICE(JUNIPER_MFR, "Juniper FRF.16 Frame Relay"),
+ DLT_CHOICE(JUNIPER_ATM2, "Juniper ATM2 PIC"),
+ DLT_CHOICE(JUNIPER_SERVICES, "Juniper Advanced Services PIC"),
+ DLT_CHOICE(JUNIPER_ATM1, "Juniper ATM1 PIC"),
+ DLT_CHOICE(APPLE_IP_OVER_IEEE1394, "Apple IP-over-IEEE 1394"),
+ DLT_CHOICE(MTP2_WITH_PHDR, "SS7 MTP2 with Pseudo-header"),
+ DLT_CHOICE(MTP2, "SS7 MTP2"),
+ DLT_CHOICE(MTP3, "SS7 MTP3"),
+ DLT_CHOICE(SCCP, "SS7 SCCP"),
+ DLT_CHOICE(DOCSIS, "DOCSIS"),
+ DLT_CHOICE(LINUX_IRDA, "Linux IrDA"),
+ DLT_CHOICE(IEEE802_11_RADIO_AVS, "802.11 plus AVS radio information header"),
+ DLT_CHOICE(JUNIPER_MONITOR, "Juniper Passive Monitor PIC"),
+ DLT_CHOICE(BACNET_MS_TP, "BACnet MS/TP"),
+ DLT_CHOICE(PPP_PPPD, "PPP for pppd, with direction flag"),
+ DLT_CHOICE(JUNIPER_PPPOE, "Juniper PPPoE"),
+ DLT_CHOICE(JUNIPER_PPPOE_ATM, "Juniper PPPoE/ATM"),
+ DLT_CHOICE(GPRS_LLC, "GPRS LLC"),
+ DLT_CHOICE(GPF_T, "GPF-T"),
+ DLT_CHOICE(GPF_F, "GPF-F"),
+ DLT_CHOICE(JUNIPER_PIC_PEER, "Juniper PIC Peer"),
+ DLT_CHOICE(ERF_ETH, "Ethernet with Endace ERF header"),
+ DLT_CHOICE(ERF_POS, "Packet-over-SONET with Endace ERF header"),
+ DLT_CHOICE(LINUX_LAPD, "Linux vISDN LAPD"),
+ DLT_CHOICE(JUNIPER_ETHER, "Juniper Ethernet"),
+ DLT_CHOICE(JUNIPER_PPP, "Juniper PPP"),
+ DLT_CHOICE(JUNIPER_FRELAY, "Juniper Frame Relay"),
+ DLT_CHOICE(JUNIPER_CHDLC, "Juniper C-HDLC"),
+ DLT_CHOICE(MFR, "FRF.16 Frame Relay"),
+ DLT_CHOICE(JUNIPER_VP, "Juniper Voice PIC"),
+ DLT_CHOICE(A429, "Arinc 429"),
+ DLT_CHOICE(A653_ICM, "Arinc 653 Interpartition Communication"),
+ DLT_CHOICE(USB_FREEBSD, "USB with FreeBSD header"),
+ DLT_CHOICE(BLUETOOTH_HCI_H4, "Bluetooth HCI UART transport layer"),
+ DLT_CHOICE(IEEE802_16_MAC_CPS, "IEEE 802.16 MAC Common Part Sublayer"),
+ DLT_CHOICE(USB_LINUX, "USB with Linux header"),
+ DLT_CHOICE(CAN20B, "Controller Area Network (CAN) v. 2.0B"),
+ DLT_CHOICE(IEEE802_15_4_LINUX, "IEEE 802.15.4 with Linux padding"),
+ DLT_CHOICE(PPI, "Per-Packet Information"),
+ DLT_CHOICE(IEEE802_16_MAC_CPS_RADIO, "IEEE 802.16 MAC Common Part Sublayer plus radiotap header"),
+ DLT_CHOICE(JUNIPER_ISM, "Juniper Integrated Service Module"),
+ DLT_CHOICE(IEEE802_15_4, "IEEE 802.15.4 with FCS"),
+ DLT_CHOICE(SITA, "SITA pseudo-header"),
+ DLT_CHOICE(ERF, "Endace ERF header"),
+ DLT_CHOICE(RAIF1, "Ethernet with u10 Networks pseudo-header"),
+ DLT_CHOICE(IPMB_KONTRON, "IPMB with Kontron pseudo-header"),
+ DLT_CHOICE(JUNIPER_ST, "Juniper Secure Tunnel"),
+ DLT_CHOICE(BLUETOOTH_HCI_H4_WITH_PHDR, "Bluetooth HCI UART transport layer plus pseudo-header"),
+ DLT_CHOICE(AX25_KISS, "AX.25 with KISS header"),
+ DLT_CHOICE(IPMB_LINUX, "IPMB with Linux/Pigeon Point pseudo-header"),
+ DLT_CHOICE(IEEE802_15_4_NONASK_PHY, "IEEE 802.15.4 with non-ASK PHY data"),
+ DLT_CHOICE(MPLS, "MPLS with label as link-layer header"),
+ DLT_CHOICE(LINUX_EVDEV, "Linux evdev events"),
+ DLT_CHOICE(USB_LINUX_MMAPPED, "USB with padded Linux header"),
+ DLT_CHOICE(DECT, "DECT"),
+ DLT_CHOICE(AOS, "AOS Space Data Link protocol"),
+ DLT_CHOICE(WIHART, "Wireless HART"),
+ DLT_CHOICE(FC_2, "Fibre Channel FC-2"),
+ DLT_CHOICE(FC_2_WITH_FRAME_DELIMS, "Fibre Channel FC-2 with frame delimiters"),
+ DLT_CHOICE(IPNET, "Solaris ipnet"),
+ DLT_CHOICE(CAN_SOCKETCAN, "CAN-bus with SocketCAN headers"),
+ DLT_CHOICE(IPV4, "Raw IPv4"),
+ DLT_CHOICE(IPV6, "Raw IPv6"),
+ DLT_CHOICE(IEEE802_15_4_NOFCS, "IEEE 802.15.4 without FCS"),
+ DLT_CHOICE(DBUS, "D-Bus"),
+ DLT_CHOICE(JUNIPER_VS, "Juniper Virtual Server"),
+ DLT_CHOICE(JUNIPER_SRX_E2E, "Juniper SRX E2E"),
+ DLT_CHOICE(JUNIPER_FIBRECHANNEL, "Juniper Fibre Channel"),
+ DLT_CHOICE(DVB_CI, "DVB-CI"),
+ DLT_CHOICE(MUX27010, "MUX27010"),
+ DLT_CHOICE(STANAG_5066_D_PDU, "STANAG 5066 D_PDUs"),
+ DLT_CHOICE(JUNIPER_ATM_CEMIC, "Juniper ATM CEMIC"),
+ DLT_CHOICE(NFLOG, "Linux netfilter log messages"),
+ DLT_CHOICE(NETANALYZER, "Ethernet with Hilscher netANALYZER pseudo-header"),
+ DLT_CHOICE(NETANALYZER_TRANSPARENT, "Ethernet with Hilscher netANALYZER pseudo-header and with preamble and SFD"),
+ DLT_CHOICE(IPOIB, "RFC 4391 IP-over-Infiniband"),
+ DLT_CHOICE(MPEG_2_TS, "MPEG-2 transport stream"),
+ DLT_CHOICE(NG40, "ng40 protocol tester Iub/Iur"),
+ DLT_CHOICE(NFC_LLCP, "NFC LLCP PDUs with pseudo-header"),
+ DLT_CHOICE(INFINIBAND, "InfiniBand"),
+ DLT_CHOICE(SCTP, "SCTP"),
+ DLT_CHOICE(USBPCAP, "USB with USBPcap header"),
+ DLT_CHOICE(RTAC_SERIAL, "Schweitzer Engineering Laboratories RTAC packets"),
+ DLT_CHOICE(BLUETOOTH_LE_LL, "Bluetooth Low Energy air interface"),
+ DLT_CHOICE(NETLINK, "Linux netlink"),
+ DLT_CHOICE(BLUETOOTH_LINUX_MONITOR, "Bluetooth Linux Monitor"),
+ DLT_CHOICE(BLUETOOTH_BREDR_BB, "Bluetooth Basic Rate/Enhanced Data Rate baseband packets"),
+ DLT_CHOICE(BLUETOOTH_LE_LL_WITH_PHDR, "Bluetooth Low Energy air interface with pseudo-header"),
+ DLT_CHOICE(PROFIBUS_DL, "PROFIBUS data link layer"),
+ DLT_CHOICE(PKTAP, "Apple DLT_PKTAP"),
+ DLT_CHOICE(EPON, "Ethernet with 802.3 Clause 65 EPON preamble"),
+ DLT_CHOICE(IPMI_HPM_2, "IPMI trace packets"),
+ DLT_CHOICE(ZWAVE_R1_R2, "Z-Wave RF profile R1 and R2 packets"),
+ DLT_CHOICE(ZWAVE_R3, "Z-Wave RF profile R3 packets"),
+ DLT_CHOICE(WATTSTOPPER_DLM, "WattStopper Digital Lighting Management (DLM) and Legrand Nitoo Open protocol"),
+ DLT_CHOICE(ISO_14443, "ISO 14443 messages"),
+ DLT_CHOICE(RDS, "IEC 62106 Radio Data System groups"),
+ DLT_CHOICE(USB_DARWIN, "USB with Darwin header"),
+ DLT_CHOICE(OPENFLOW, "OpenBSD DLT_OPENFLOW"),
+ DLT_CHOICE(SDLC, "IBM SDLC frames"),
+ DLT_CHOICE(TI_LLN_SNIFFER, "TI LLN sniffer frames"),
+ DLT_CHOICE(VSOCK, "Linux vsock"),
+ DLT_CHOICE(NORDIC_BLE, "Nordic Semiconductor Bluetooth LE sniffer frames"),
+ DLT_CHOICE(DOCSIS31_XRA31, "Excentis XRA-31 DOCSIS 3.1 RF sniffer frames"),
+ DLT_CHOICE(ETHERNET_MPACKET, "802.3br mPackets"),
+ DLT_CHOICE(DISPLAYPORT_AUX, "DisplayPort AUX channel monitoring data"),
+ DLT_CHOICE(LINUX_SLL2, "Linux cooked v2"),
+ DLT_CHOICE_SENTINEL
+};
+
+int
+pcap_datalink_name_to_val(const char *name)
+{
+ int i;
+
+ for (i = 0; dlt_choices[i].name != NULL; i++) {
+ if (pcap_strcasecmp(dlt_choices[i].name, name) == 0)
+ return (dlt_choices[i].dlt);
+ }
+ return (-1);
+}
+
+const char *
+pcap_datalink_val_to_name(int dlt)
+{
+ int i;
+
+ for (i = 0; dlt_choices[i].name != NULL; i++) {
+ if (dlt_choices[i].dlt == dlt)
+ return (dlt_choices[i].name);
+ }
+ return (NULL);
+}
+
+const char *
+pcap_datalink_val_to_description(int dlt)
+{
+ int i;
+
+ for (i = 0; dlt_choices[i].name != NULL; i++) {
+ if (dlt_choices[i].dlt == dlt)
+ return (dlt_choices[i].description);
+ }
+ return (NULL);
+}
+
+const char *
+pcap_datalink_val_to_description_or_dlt(int dlt)
+{
+ static char unkbuf[40];
+ const char *description;
+
+ description = pcap_datalink_val_to_description(dlt);
+ if (description != NULL) {
+ return description;
+ } else {
+ (void)pcap_snprintf(unkbuf, sizeof(unkbuf), "DLT %u", dlt);
+ return unkbuf;
+ }
+}
+
+struct tstamp_type_choice {
+ const char *name;
+ const char *description;
+ int type;
+};
+
+static struct tstamp_type_choice tstamp_type_choices[] = {
+ { "host", "Host", PCAP_TSTAMP_HOST },
+ { "host_lowprec", "Host, low precision", PCAP_TSTAMP_HOST_LOWPREC },
+ { "host_hiprec", "Host, high precision", PCAP_TSTAMP_HOST_HIPREC },
+ { "adapter", "Adapter", PCAP_TSTAMP_ADAPTER },
+ { "adapter_unsynced", "Adapter, not synced with system time", PCAP_TSTAMP_ADAPTER_UNSYNCED },
+ { NULL, NULL, 0 }
+};
+
+int
+pcap_tstamp_type_name_to_val(const char *name)
+{
+ int i;
+
+ for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
+ if (pcap_strcasecmp(tstamp_type_choices[i].name, name) == 0)
+ return (tstamp_type_choices[i].type);
+ }
+ return (PCAP_ERROR);
+}
+
+const char *
+pcap_tstamp_type_val_to_name(int tstamp_type)
+{
+ int i;
+
+ for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
+ if (tstamp_type_choices[i].type == tstamp_type)
+ return (tstamp_type_choices[i].name);
+ }
+ return (NULL);
+}
+
+const char *
+pcap_tstamp_type_val_to_description(int tstamp_type)
+{
+ int i;
+
+ for (i = 0; tstamp_type_choices[i].name != NULL; i++) {
+ if (tstamp_type_choices[i].type == tstamp_type)
+ return (tstamp_type_choices[i].description);
+ }
+ return (NULL);
+}
+
+int
+pcap_snapshot(pcap_t *p)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ return (p->snapshot);
+}
+
+int
+pcap_is_swapped(pcap_t *p)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ return (p->swapped);
+}
+
+int
+pcap_major_version(pcap_t *p)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ return (p->version_major);
+}
+
+int
+pcap_minor_version(pcap_t *p)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ return (p->version_minor);
+}
+
+int
+pcap_bufsize(pcap_t *p)
+{
+ if (!p->activated)
+ return (PCAP_ERROR_NOT_ACTIVATED);
+ return (p->bufsize);
+}
+
+FILE *
+pcap_file(pcap_t *p)
+{
+ return (p->rfile);
+}
+
+int
+pcap_fileno(pcap_t *p)
+{
+#ifndef _WIN32
+ return (p->fd);
+#else
+ if (p->handle != INVALID_HANDLE_VALUE)
+ return ((int)(DWORD)p->handle);
+ else
+ return (PCAP_ERROR);
+#endif
+}
+
+#if !defined(_WIN32) && !defined(MSDOS)
+int
+pcap_get_selectable_fd(pcap_t *p)
+{
+ return (p->selectable_fd);
+}
+
+struct timeval *
+pcap_get_required_select_timeout(pcap_t *p)
+{
+ return (p->required_select_timeout);
+}
+
+#ifdef __APPLE__
+int
+pcap_get_selectable_fd_list(pcap_t *p, int **fds)
+{
+ int *list;
+ unsigned int size;
+
+ if (p->selectable_fd_count == 0) {
+ size = sizeof(int);
+ list = &p->selectable_fd;
+ } else {
+ size = sizeof(int) * p->selectable_fd_count;
+ list = p->selectable_fd_list;
+ }
+ *fds = malloc(size);
+ if (*fds == NULL)
+ return (PCAP_ERROR);
+ memcpy(*fds, list, size);
+
+ return (size / sizeof(int));
+}
+
+void
+pcap_free_selectable_fd_list(int *fds)
+{
+ free(fds);
+}
+#endif /* __APPLE__ */
+
+#endif
+
+void
+pcap_perror(pcap_t *p, const char *prefix)
+{
+ fprintf(stderr, "%s: %s\n", prefix, p->errbuf);
+}
+
+char *
+pcap_geterr(pcap_t *p)
+{
+ return (p->errbuf);
+}
+
+int
+pcap_getnonblock(pcap_t *p, char *errbuf)
+{
+ int ret;
+
+ ret = p->getnonblock_op(p);
+ if (ret == -1) {
+ /*
+ * The get nonblock operation sets p->errbuf; this
+ * function *shouldn't* have had a separate errbuf
+ * argument, as it didn't need one, but I goofed
+ * when adding it.
+ *
+ * We copy the error message to errbuf, so callers
+ * can find it in either place.
+ */
+ pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
+ }
+ return (ret);
+}
+
+/*
+ * Get the current non-blocking mode setting, under the assumption that
+ * it's just the standard POSIX non-blocking flag.
+ */
+#if !defined(_WIN32) && !defined(MSDOS)
+int
+pcap_getnonblock_fd(pcap_t *p)
+{
+ int fdflags;
+
+ fdflags = fcntl(p->fd, F_GETFL, 0);
+ if (fdflags == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "F_GETFL");
+ return (-1);
+ }
+ if (fdflags & O_NONBLOCK)
+ return (1);
+ else
+ return (0);
+}
+#endif
+
+int
+pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf)
+{
+ int ret;
+
+ ret = p->setnonblock_op(p, nonblock);
+ if (ret == -1) {
+ /*
+ * The set nonblock operation sets p->errbuf; this
+ * function *shouldn't* have had a separate errbuf
+ * argument, as it didn't need one, but I goofed
+ * when adding it.
+ *
+ * We copy the error message to errbuf, so callers
+ * can find it in either place.
+ */
+ pcap_strlcpy(errbuf, p->errbuf, PCAP_ERRBUF_SIZE);
+ }
+ return (ret);
+}
+
+#if !defined(_WIN32) && !defined(MSDOS)
+/*
+ * Set non-blocking mode, under the assumption that it's just the
+ * standard POSIX non-blocking flag. (This can be called by the
+ * per-platform non-blocking-mode routine if that routine also
+ * needs to do some additional work.)
+ */
+int
+pcap_setnonblock_fd(pcap_t *p, int nonblock)
+{
+ int fdflags;
+
+ fdflags = fcntl(p->fd, F_GETFL, 0);
+ if (fdflags == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "F_GETFL");
+ return (-1);
+ }
+ if (nonblock)
+ fdflags |= O_NONBLOCK;
+ else
+ fdflags &= ~O_NONBLOCK;
+ if (fcntl(p->fd, F_SETFL, fdflags) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "F_SETFL");
+ return (-1);
+ }
+ return (0);
+}
+#endif
+
+/*
+ * Generate error strings for PCAP_ERROR_ and PCAP_WARNING_ values.
+ */
+const char *
+pcap_statustostr(int errnum)
+{
+ static char ebuf[15+10+1];
+
+ switch (errnum) {
+
+ case PCAP_WARNING:
+ return("Generic warning");
+
+ case PCAP_WARNING_TSTAMP_TYPE_NOTSUP:
+ return ("That type of time stamp is not supported by that device");
+
+ case PCAP_WARNING_PROMISC_NOTSUP:
+ return ("That device doesn't support promiscuous mode");
+
+ case PCAP_ERROR:
+ return("Generic error");
+
+ case PCAP_ERROR_BREAK:
+ return("Loop terminated by pcap_breakloop");
+
+ case PCAP_ERROR_NOT_ACTIVATED:
+ return("The pcap_t has not been activated");
+
+ case PCAP_ERROR_ACTIVATED:
+ return ("The setting can't be changed after the pcap_t is activated");
+
+ case PCAP_ERROR_NO_SUCH_DEVICE:
+ return ("No such device exists");
+
+ case PCAP_ERROR_RFMON_NOTSUP:
+ return ("That device doesn't support monitor mode");
+
+ case PCAP_ERROR_NOT_RFMON:
+ return ("That operation is supported only in monitor mode");
+
+ case PCAP_ERROR_PERM_DENIED:
+ return ("You don't have permission to capture on that device");
+
+ case PCAP_ERROR_IFACE_NOT_UP:
+ return ("That device is not up");
+
+ case PCAP_ERROR_CANTSET_TSTAMP_TYPE:
+ return ("That device doesn't support setting the time stamp type");
+
+ case PCAP_ERROR_PROMISC_PERM_DENIED:
+ return ("You don't have permission to capture in promiscuous mode on that device");
+
+ case PCAP_ERROR_TSTAMP_PRECISION_NOTSUP:
+ return ("That device doesn't support that time stamp precision");
+ }
+ (void)pcap_snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum);
+ return(ebuf);
+}
+
+/*
+ * Not all systems have strerror().
+ */
+const char *
+pcap_strerror(int errnum)
+{
+#ifdef HAVE_STRERROR
+#ifdef _WIN32
+ static char errbuf[PCAP_ERRBUF_SIZE];
+ errno_t err = strerror_s(errbuf, PCAP_ERRBUF_SIZE, errnum);
+
+ if (err != 0) /* err = 0 if successful */
+ pcap_strlcpy(errbuf, "strerror_s() error", PCAP_ERRBUF_SIZE);
+ return (errbuf);
+#else
+ return (strerror(errnum));
+#endif /* _WIN32 */
+#else
+ extern int sys_nerr;
+ extern const char *const sys_errlist[];
+ static char errbuf[PCAP_ERRBUF_SIZE];
+
+ if ((unsigned int)errnum < sys_nerr)
+ return ((char *)sys_errlist[errnum]);
+ (void)pcap_snprintf(errbuf, sizeof errbuf, "Unknown error: %d", errnum);
+ return (errbuf);
+#endif
+}
+
+int
+pcap_setfilter(pcap_t *p, struct bpf_program *fp)
+{
+ return (p->setfilter_op(p, fp));
+}
+
+/*
+ * Set direction flag, which controls whether we accept only incoming
+ * packets, only outgoing packets, or both.
+ * Note that, depending on the platform, some or all direction arguments
+ * might not be supported.
+ */
+int
+pcap_setdirection(pcap_t *p, pcap_direction_t d)
+{
+ if (p->setdirection_op == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Setting direction is not implemented on this platform");
+ return (-1);
+ } else
+ return (p->setdirection_op(p, d));
+}
+
+int
+pcap_stats(pcap_t *p, struct pcap_stat *ps)
+{
+ return (p->stats_op(p, ps));
+}
+
+#ifdef _WIN32
+struct pcap_stat *
+pcap_stats_ex(pcap_t *p, int *pcap_stat_size)
+{
+ return (p->stats_ex_op(p, pcap_stat_size));
+}
+
+int
+pcap_setbuff(pcap_t *p, int dim)
+{
+ return (p->setbuff_op(p, dim));
+}
+
+int
+pcap_setmode(pcap_t *p, int mode)
+{
+ return (p->setmode_op(p, mode));
+}
+
+int
+pcap_setmintocopy(pcap_t *p, int size)
+{
+ return (p->setmintocopy_op(p, size));
+}
+
+HANDLE
+pcap_getevent(pcap_t *p)
+{
+ return (p->getevent_op(p));
+}
+
+int
+pcap_oid_get_request(pcap_t *p, bpf_u_int32 oid, void *data, size_t *lenp)
+{
+ return (p->oid_get_request_op(p, oid, data, lenp));
+}
+
+int
+pcap_oid_set_request(pcap_t *p, bpf_u_int32 oid, const void *data, size_t *lenp)
+{
+ return (p->oid_set_request_op(p, oid, data, lenp));
+}
+
+pcap_send_queue *
+pcap_sendqueue_alloc(u_int memsize)
+{
+ pcap_send_queue *tqueue;
+
+ /* Allocate the queue */
+ tqueue = (pcap_send_queue *)malloc(sizeof(pcap_send_queue));
+ if (tqueue == NULL){
+ return (NULL);
+ }
+
+ /* Allocate the buffer */
+ tqueue->buffer = (char *)malloc(memsize);
+ if (tqueue->buffer == NULL) {
+ free(tqueue);
+ return (NULL);
+ }
+
+ tqueue->maxlen = memsize;
+ tqueue->len = 0;
+
+ return (tqueue);
+}
+
+void
+pcap_sendqueue_destroy(pcap_send_queue *queue)
+{
+ free(queue->buffer);
+ free(queue);
+}
+
+int
+pcap_sendqueue_queue(pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data)
+{
+ if (queue->len + sizeof(struct pcap_pkthdr) + pkt_header->caplen > queue->maxlen){
+ return (-1);
+ }
+
+ /* Copy the pcap_pkthdr header*/
+ memcpy(queue->buffer + queue->len, pkt_header, sizeof(struct pcap_pkthdr));
+ queue->len += sizeof(struct pcap_pkthdr);
+
+ /* copy the packet */
+ memcpy(queue->buffer + queue->len, pkt_data, pkt_header->caplen);
+ queue->len += pkt_header->caplen;
+
+ return (0);
+}
+
+u_int
+pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ return (p->sendqueue_transmit_op(p, queue, sync));
+}
+
+int
+pcap_setuserbuffer(pcap_t *p, int size)
+{
+ return (p->setuserbuffer_op(p, size));
+}
+
+int
+pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ return (p->live_dump_op(p, filename, maxsize, maxpacks));
+}
+
+int
+pcap_live_dump_ended(pcap_t *p, int sync)
+{
+ return (p->live_dump_ended_op(p, sync));
+}
+
+PAirpcapHandle
+pcap_get_airpcap_handle(pcap_t *p)
+{
+ PAirpcapHandle handle;
+
+ handle = p->get_airpcap_handle_op(p);
+ if (handle == NULL) {
+ (void)pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "This isn't an AirPcap device");
+ }
+ return (handle);
+}
+#endif
+
+/*
+ * On some platforms, we need to clean up promiscuous or monitor mode
+ * when we close a device - and we want that to happen even if the
+ * application just exits without explicitl closing devices.
+ * On those platforms, we need to register a "close all the pcaps"
+ * routine to be called when we exit, and need to maintain a list of
+ * pcaps that need to be closed to clean up modes.
+ *
+ * XXX - not thread-safe.
+ */
+
+/*
+ * List of pcaps on which we've done something that needs to be
+ * cleaned up.
+ * If there are any such pcaps, we arrange to call "pcap_close_all()"
+ * when we exit, and have it close all of them.
+ */
+static struct pcap *pcaps_to_close;
+
+/*
+ * TRUE if we've already called "atexit()" to cause "pcap_close_all()" to
+ * be called on exit.
+ */
+static int did_atexit;
+
+static void
+pcap_close_all(void)
+{
+ struct pcap *handle;
+
+ while ((handle = pcaps_to_close) != NULL)
+ pcap_close(handle);
+}
+
+int
+pcap_do_addexit(pcap_t *p)
+{
+ /*
+ * If we haven't already done so, arrange to have
+ * "pcap_close_all()" called when we exit.
+ */
+ if (!did_atexit) {
+ if (atexit(pcap_close_all) != 0) {
+ /*
+ * "atexit()" failed; let our caller know.
+ */
+ pcap_strlcpy(p->errbuf, "atexit failed", PCAP_ERRBUF_SIZE);
+ return (0);
+ }
+ did_atexit = 1;
+ }
+ return (1);
+}
+
+void
+pcap_add_to_pcaps_to_close(pcap_t *p)
+{
+ p->next = pcaps_to_close;
+ pcaps_to_close = p;
+}
+
+void
+pcap_remove_from_pcaps_to_close(pcap_t *p)
+{
+ pcap_t *pc, *prevpc;
+
+ for (pc = pcaps_to_close, prevpc = NULL; pc != NULL;
+ prevpc = pc, pc = pc->next) {
+ if (pc == p) {
+ /*
+ * Found it. Remove it from the list.
+ */
+ if (prevpc == NULL) {
+ /*
+ * It was at the head of the list.
+ */
+ pcaps_to_close = pc->next;
+ } else {
+ /*
+ * It was in the middle of the list.
+ */
+ prevpc->next = pc->next;
+ }
+ break;
+ }
+ }
+}
+
+void
+pcap_cleanup_live_common(pcap_t *p)
+{
+ if (p->buffer != NULL) {
+ free(p->buffer);
+ p->buffer = NULL;
+ }
+ if (p->dlt_list != NULL) {
+ free(p->dlt_list);
+ p->dlt_list = NULL;
+ p->dlt_count = 0;
+ }
+ if (p->tstamp_type_list != NULL) {
+ free(p->tstamp_type_list);
+ p->tstamp_type_list = NULL;
+ p->tstamp_type_count = 0;
+ }
+ if (p->tstamp_precision_list != NULL) {
+ free(p->tstamp_precision_list);
+ p->tstamp_precision_list = NULL;
+ p->tstamp_precision_count = 0;
+ }
+ pcap_freecode(&p->fcode);
+#if !defined(_WIN32) && !defined(MSDOS)
+ if (p->fd >= 0) {
+ close(p->fd);
+ p->fd = -1;
+ }
+ p->selectable_fd = -1;
+#endif
+}
+
+/*
+ * API compatible with WinPcap's "send a packet" routine - returns -1
+ * on error, 0 otherwise.
+ *
+ * XXX - what if we get a short write?
+ */
+int
+pcap_sendpacket(pcap_t *p, const u_char *buf, int size)
+{
+ if (p->inject_op(p, buf, size) == -1)
+ return (-1);
+ return (0);
+}
+
+/*
+ * API compatible with OpenBSD's "send a packet" routine - returns -1 on
+ * error, number of bytes written otherwise.
+ */
+int
+pcap_inject(pcap_t *p, const void *buf, size_t size)
+{
+ return (p->inject_op(p, buf, size));
+}
+
+void
+pcap_close(pcap_t *p)
+{
+#if __APPLE__
+ p->cleanup_op(p);
+ if (p->opt.device != NULL)
+ free(p->opt.device);
+#else
+ if (p->opt.device != NULL)
+ free(p->opt.device);
+ p->cleanup_op(p);
+#endif /* __APPLE__ */
+ free(p);
+}
+
+/*
+ * Given a BPF program, a pcap_pkthdr structure for a packet, and the raw
+ * data for the packet, check whether the packet passes the filter.
+ * Returns the return value of the filter program, which will be zero if
+ * the packet doesn't pass and non-zero if the packet does pass.
+ */
+int
+pcap_offline_filter(const struct bpf_program *fp, const struct pcap_pkthdr *h,
+ const u_char *pkt)
+{
+ const struct bpf_insn *fcode = fp->bf_insns;
+
+ if (fcode != NULL)
+ return (bpf_filter(fcode, pkt, h->len, h->caplen));
+ else
+ return (0);
+}
+
+static int
+pcap_can_set_rfmon_dead(pcap_t *p)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Rfmon mode doesn't apply on a pcap_open_dead pcap_t");
+ return (PCAP_ERROR);
+}
+
+static int
+pcap_read_dead(pcap_t *p, int cnt _U_, pcap_handler callback _U_,
+ u_char *user _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packets aren't available from a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_inject_dead(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packets can't be sent on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_setfilter_dead(pcap_t *p, struct bpf_program *fp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A filter cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_setdirection_dead(pcap_t *p, pcap_direction_t d _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The packet direction cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_set_datalink_dead(pcap_t *p, int dlt _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The link-layer header type cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_getnonblock_dead(pcap_t *p)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
+ return (-1);
+}
+
+static int
+pcap_setnonblock_dead(pcap_t *p, int nonblock _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A pcap_open_dead pcap_t does not have a non-blocking mode setting");
+ return (-1);
+}
+
+static int
+pcap_stats_dead(pcap_t *p, struct pcap_stat *ps _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Statistics aren't available from a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+#ifdef _WIN32
+struct pcap_stat *
+pcap_stats_ex_dead(pcap_t *p, int *pcap_stat_size _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Statistics aren't available from a pcap_open_dead pcap_t");
+ return (NULL);
+}
+
+static int
+pcap_setbuff_dead(pcap_t *p, int dim)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The kernel buffer size cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_setmode_dead(pcap_t *p, int mode)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "impossible to set mode on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_setmintocopy_dead(pcap_t *p, int size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The mintocopy parameter cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static HANDLE
+pcap_getevent_dead(pcap_t *p)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A pcap_open_dead pcap_t has no event handle");
+ return (INVALID_HANDLE_VALUE);
+}
+
+static int
+pcap_oid_get_request_dead(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID get request cannot be performed on a pcap_open_dead pcap_t");
+ return (PCAP_ERROR);
+}
+
+static int
+pcap_oid_set_request_dead(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID set request cannot be performed on a pcap_open_dead pcap_t");
+ return (PCAP_ERROR);
+}
+
+static u_int
+pcap_sendqueue_transmit_dead(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Packets cannot be transmitted on a pcap_open_dead pcap_t");
+ return (0);
+}
+
+static int
+pcap_setuserbuffer_dead(pcap_t *p, int size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The user buffer cannot be set on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_live_dump_dead(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static int
+pcap_live_dump_ended_dead(pcap_t *p, int sync)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static PAirpcapHandle
+pcap_get_airpcap_handle_dead(pcap_t *p)
+{
+ return (NULL);
+}
+#endif /* _WIN32 */
+
+static void
+pcap_cleanup_dead(pcap_t *p _U_)
+{
+ /* Nothing to do. */
+}
+
+pcap_t *
+pcap_open_dead_with_tstamp_precision(int linktype, int snaplen, u_int precision)
+{
+ pcap_t *p;
+
+ switch (precision) {
+
+ case PCAP_TSTAMP_PRECISION_MICRO:
+ case PCAP_TSTAMP_PRECISION_NANO:
+ break;
+
+ default:
+ /*
+ * This doesn't really matter, but we don't have any way
+ * to report particular errors, so the only failure we
+ * should have is a memory allocation failure. Just
+ * pick microsecond precision.
+ */
+ precision = PCAP_TSTAMP_PRECISION_MICRO;
+ break;
+ }
+ p = malloc(sizeof(*p));
+ if (p == NULL)
+ return NULL;
+ memset (p, 0, sizeof(*p));
+ p->snapshot = snaplen;
+ p->linktype = linktype;
+ p->opt.tstamp_precision = precision;
+ p->can_set_rfmon_op = pcap_can_set_rfmon_dead;
+ p->read_op = pcap_read_dead;
+ p->inject_op = pcap_inject_dead;
+ p->setfilter_op = pcap_setfilter_dead;
+ p->setdirection_op = pcap_setdirection_dead;
+ p->set_datalink_op = pcap_set_datalink_dead;
+ p->getnonblock_op = pcap_getnonblock_dead;
+ p->setnonblock_op = pcap_setnonblock_dead;
+ p->stats_op = pcap_stats_dead;
+#ifdef _WIN32
+ p->stats_ex_op = pcap_stats_ex_dead;
+ p->setbuff_op = pcap_setbuff_dead;
+ p->setmode_op = pcap_setmode_dead;
+ p->setmintocopy_op = pcap_setmintocopy_dead;
+ p->getevent_op = pcap_getevent_dead;
+ p->oid_get_request_op = pcap_oid_get_request_dead;
+ p->oid_set_request_op = pcap_oid_set_request_dead;
+ p->sendqueue_transmit_op = pcap_sendqueue_transmit_dead;
+ p->setuserbuffer_op = pcap_setuserbuffer_dead;
+ p->live_dump_op = pcap_live_dump_dead;
+ p->live_dump_ended_op = pcap_live_dump_ended_dead;
+ p->get_airpcap_handle_op = pcap_get_airpcap_handle_dead;
+#endif
+ p->cleanup_op = pcap_cleanup_dead;
+
+ /*
+ * A "dead" pcap_t never requires special BPF code generation.
+ */
+ p->bpf_codegen_flags = 0;
+
+ p->activated = 1;
+ return (p);
+}
+
+pcap_t *
+pcap_open_dead(int linktype, int snaplen)
+{
+ return (pcap_open_dead_with_tstamp_precision(linktype, snaplen,
+ PCAP_TSTAMP_PRECISION_MICRO));
+}
+
+#ifdef YYDEBUG
+/*
+ * Set the internal "debug printout" flag for the filter expression parser.
+ * The code to print that stuff is present only if YYDEBUG is defined, so
+ * the flag, and the routine to set it, are defined only if YYDEBUG is
+ * defined.
+ *
+ * This is intended for libpcap developers, not for general use.
+ * If you want to set these in a program, you'll have to declare this
+ * routine yourself, with the appropriate DLL import attribute on Windows;
+ * it's not declared in any header file, and won't be declared in any
+ * header file provided by libpcap.
+ */
+PCAP_API void pcap_set_parser_debug(int value);
+
+PCAP_API_DEF void
+pcap_set_parser_debug(int value)
+{
+ pcap_debug = value;
+}
+#endif
diff --git a/lib/libpcap/libpcap/pcap.h b/lib/libpcap/libpcap/pcap.h
new file mode 100644
index 0000000..174e32d
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+/*
+ * For backwards compatibility.
+ *
+ * Note to OS vendors: do NOT get rid of this file! Many applications
+ * expect to be able to include <pcap.h>, and at least some of them
+ * go through contortions in their configure scripts to try to detect
+ * OSes that have "helpfully" moved pcap.h to <pcap/pcap.h> without
+ * leaving behind a <pcap.h> file.
+ */
+#include <pcap/pcap.h>
diff --git a/lib/libpcap/libpcap/pcap/bluetooth.h b/lib/libpcap/libpcap/pcap/bluetooth.h
new file mode 100644
index 0000000..15dc5a8
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/bluetooth.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * bluetooth data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ */
+
+#ifndef lib_pcap_bluetooth_h
+#define lib_pcap_bluetooth_h
+
+#include <pcap/pcap-inttypes.h>
+
+/*
+ * Header prepended libpcap to each bluetooth h4 frame,
+ * fields are in network byte order
+ */
+typedef struct _pcap_bluetooth_h4_header {
+ uint32_t direction; /* if first bit is set direction is incoming */
+} pcap_bluetooth_h4_header;
+
+/*
+ * Header prepended libpcap to each bluetooth linux monitor frame,
+ * fields are in network byte order
+ */
+typedef struct _pcap_bluetooth_linux_monitor_header {
+ uint16_t adapter_id;
+ uint16_t opcode;
+} pcap_bluetooth_linux_monitor_header;
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap/bpf.h b/lib/libpcap/libpcap/pcap/bpf.h
new file mode 100644
index 0000000..9d74895
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/bpf.h
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ */
+
+/*
+ * This is libpcap's cut-down version of bpf.h; it includes only
+ * the stuff needed for the code generator and the userland BPF
+ * interpreter, and the libpcap APIs for setting filters, etc..
+ *
+ * "pcap-bpf.c" will include the native OS version, as it deals with
+ * the OS's BPF implementation.
+ *
+ * At least two programs found by Google Code Search explicitly includes
+ * <pcap/bpf.h> (even though <pcap.h>/<pcap/pcap.h> includes it for you),
+ * so moving that stuff to <pcap/pcap.h> would break the build for some
+ * programs.
+ */
+
+/*
+ * If we've already included <net/bpf.h>, don't re-define this stuff.
+ * We assume BSD-style multiple-include protection in <net/bpf.h>,
+ * which is true of all but the oldest versions of FreeBSD and NetBSD,
+ * or Tru64 UNIX-style multiple-include protection (or, at least,
+ * Tru64 UNIX 5.x-style; I don't have earlier versions available to check),
+ * or AIX-style multiple-include protection (or, at least, AIX 5.x-style;
+ * I don't have earlier versions available to check), or QNX-style
+ * multiple-include protection (as per GitHub pull request #394).
+ *
+ * We do not check for BPF_MAJOR_VERSION, as that's defined by
+ * <linux/filter.h>, which is directly or indirectly included in some
+ * programs that also include pcap.h, and <linux/filter.h> doesn't
+ * define stuff we need.
+ *
+ * This also provides our own multiple-include protection.
+ */
+#if !defined(_NET_BPF_H_) && !defined(_NET_BPF_H_INCLUDED) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h)
+#define lib_pcap_bpf_h
+
+#include <pcap/funcattrs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* BSD style release date */
+#define BPF_RELEASE 199606
+
+#ifdef MSDOS /* must be 32-bit */
+typedef long bpf_int32;
+typedef unsigned long bpf_u_int32;
+#else
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+/*
+ * Alignment macros. BPF_WORDALIGN rounds up to the next
+ * even multiple of BPF_ALIGNMENT.
+ *
+ * Tcpdump's print-pflog.c uses this, so we define it here.
+ */
+#ifndef __NetBSD__
+#define BPF_ALIGNMENT sizeof(bpf_int32)
+#else
+#define BPF_ALIGNMENT sizeof(long)
+#endif
+#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1))
+
+/*
+ * Structure for "pcap_compile()", "pcap_setfilter()", etc..
+ */
+struct bpf_program {
+ u_int bf_len;
+ struct bpf_insn *bf_insns;
+};
+
+#include <pcap/dlt.h>
+
+/*
+ * The instruction encodings.
+ *
+ * Please inform tcpdump-workers@lists.tcpdump.org if you use any
+ * of the reserved values, so that we can note that they're used
+ * (and perhaps implement it in the reference BPF implementation
+ * and encourage its implementation elsewhere).
+ */
+
+/*
+ * The upper 8 bits of the opcode aren't used. BSD/OS used 0x8000.
+ */
+
+/* instruction classes */
+#define BPF_CLASS(code) ((code) & 0x07)
+#define BPF_LD 0x00
+#define BPF_LDX 0x01
+#define BPF_ST 0x02
+#define BPF_STX 0x03
+#define BPF_ALU 0x04
+#define BPF_JMP 0x05
+#define BPF_RET 0x06
+#define BPF_MISC 0x07
+
+/* ld/ldx fields */
+#define BPF_SIZE(code) ((code) & 0x18)
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+/* 0x18 reserved; used by BSD/OS */
+#define BPF_MODE(code) ((code) & 0xe0)
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+/* 0xc0 reserved; used by BSD/OS */
+/* 0xe0 reserved; used by BSD/OS */
+
+/* alu/jmp fields */
+#define BPF_OP(code) ((code) & 0xf0)
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR 0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_MOD 0x90
+#define BPF_XOR 0xa0
+/* 0xb0 reserved */
+/* 0xc0 reserved */
+/* 0xd0 reserved */
+/* 0xe0 reserved */
+/* 0xf0 reserved */
+
+#define BPF_JA 0x00
+#define BPF_JEQ 0x10
+#define BPF_JGT 0x20
+#define BPF_JGE 0x30
+#define BPF_JSET 0x40
+/* 0x50 reserved; used on BSD/OS */
+/* 0x60 reserved */
+/* 0x70 reserved */
+/* 0x80 reserved */
+/* 0x90 reserved */
+/* 0xa0 reserved */
+/* 0xb0 reserved */
+/* 0xc0 reserved */
+/* 0xd0 reserved */
+/* 0xe0 reserved */
+/* 0xf0 reserved */
+#define BPF_SRC(code) ((code) & 0x08)
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+/* ret - BPF_K and BPF_X also apply */
+#define BPF_RVAL(code) ((code) & 0x18)
+#define BPF_A 0x10
+/* 0x18 reserved */
+
+/* misc */
+#define BPF_MISCOP(code) ((code) & 0xf8)
+#define BPF_TAX 0x00
+/* 0x08 reserved */
+/* 0x10 reserved */
+/* 0x18 reserved */
+/* #define BPF_COP 0x20 NetBSD "coprocessor" extensions */
+/* 0x28 reserved */
+/* 0x30 reserved */
+/* 0x38 reserved */
+/* #define BPF_COPX 0x40 NetBSD "coprocessor" extensions */
+/* also used on BSD/OS */
+/* 0x48 reserved */
+/* 0x50 reserved */
+/* 0x58 reserved */
+/* 0x60 reserved */
+/* 0x68 reserved */
+/* 0x70 reserved */
+/* 0x78 reserved */
+#define BPF_TXA 0x80
+/* 0x88 reserved */
+/* 0x90 reserved */
+/* 0x98 reserved */
+/* 0xa0 reserved */
+/* 0xa8 reserved */
+/* 0xb0 reserved */
+/* 0xb8 reserved */
+/* 0xc0 reserved; used on BSD/OS */
+/* 0xc8 reserved */
+/* 0xd0 reserved */
+/* 0xd8 reserved */
+/* 0xe0 reserved */
+/* 0xe8 reserved */
+/* 0xf0 reserved */
+/* 0xf8 reserved */
+
+/*
+ * The instruction data structure.
+ */
+struct bpf_insn {
+ u_short code;
+ u_char jt;
+ u_char jf;
+ bpf_u_int32 k;
+};
+
+/*
+ * Macros for insn array initializers.
+ */
+#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
+#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
+
+PCAP_API int bpf_validate(const struct bpf_insn *, int);
+PCAP_API u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+
+/*
+ * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST).
+ */
+#define BPF_MEMWORDS 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !defined(_NET_BPF_H_) && !defined(_BPF_H_) && !defined(_H_BPF) && !defined(lib_pcap_bpf_h) */
diff --git a/lib/libpcap/libpcap/pcap/can_socketcan.h b/lib/libpcap/libpcap/pcap/can_socketcan.h
new file mode 100644
index 0000000..332d9ff
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/can_socketcan.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lib_pcap_can_socketcan_h
+#define lib_pcap_can_socketcan_h
+
+#include <pcap/pcap-inttypes.h>
+
+/*
+ * SocketCAN header, as per Documentation/networking/can.txt in the
+ * Linux source.
+ */
+typedef struct {
+ uint32_t can_id;
+ uint8_t payload_length;
+ uint8_t pad;
+ uint8_t reserved1;
+ uint8_t reserved2;
+} pcap_can_socketcan_hdr;
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap/compiler-tests.h b/lib/libpcap/libpcap/pcap/compiler-tests.h
new file mode 100644
index 0000000..ea5962c
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/compiler-tests.h
@@ -0,0 +1,163 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#ifndef lib_pcap_compiler_tests_h
+#define lib_pcap_compiler_tests_h
+
+/*
+ * This was introduced by Clang:
+ *
+ * http://clang.llvm.org/docs/LanguageExtensions.html#has-attribute
+ *
+ * in some version (which version?); it has been picked up by GCC 5.0.
+ */
+#ifndef __has_attribute
+ /*
+ * It's a macro, so you can check whether it's defined to check
+ * whether it's supported.
+ *
+ * If it's not, define it to always return 0, so that we move on to
+ * the fallback checks.
+ */
+ #define __has_attribute(x) 0
+#endif
+
+/*
+ * Note that the C90 spec's "6.8.1 Conditional inclusion" and the
+ * C99 spec's and C11 spec's "6.10.1 Conditional inclusion" say:
+ *
+ * Prior to evaluation, macro invocations in the list of preprocessing
+ * tokens that will become the controlling constant expression are
+ * replaced (except for those macro names modified by the defined unary
+ * operator), just as in normal text. If the token "defined" is
+ * generated as a result of this replacement process or use of the
+ * "defined" unary operator does not match one of the two specified
+ * forms prior to macro replacement, the behavior is undefined.
+ *
+ * so you shouldn't use defined() in a #define that's used in #if or
+ * #elif. Some versions of Clang, for example, will warn about this.
+ *
+ * Instead, we check whether the pre-defined macros for particular
+ * compilers are defined and, if not, define the "is this version XXX
+ * or a later version of this compiler" macros as 0.
+ */
+
+/*
+ * Check whether this is GCC major.minor or a later release, or some
+ * compiler that claims to be "just like GCC" of that version or a
+ * later release.
+ */
+
+#if ! defined(__GNUC__)
+#define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) 0
+#else
+#define PCAP_IS_AT_LEAST_GNUC_VERSION(major, minor) \
+ (__GNUC__ > (major) || \
+ (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
+#endif
+
+/*
+ * Check whether this is Clang major.minor or a later release.
+ */
+
+#if !defined(__clang__)
+#define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) 0
+#else
+#define PCAP_IS_AT_LEAST_CLANG_VERSION(major, minor) \
+ (__clang_major__ > (major) || \
+ (__clang_major__ == (major) && __clang_minor__ >= (minor)))
+#endif
+
+/*
+ * Check whether this is Sun C/SunPro C/Oracle Studio major.minor
+ * or a later release.
+ *
+ * The version number in __SUNPRO_C is encoded in hex BCD, with the
+ * uppermost hex digit being the major version number, the next
+ * one or two hex digits being the minor version number, and
+ * the last digit being the patch version.
+ *
+ * It represents the *compiler* version, not the product version;
+ * see
+ *
+ * https://sourceforge.net/p/predef/wiki/Compilers/
+ *
+ * for a partial mapping, which we assume continues for later
+ * 12.x product releases.
+ */
+
+#if ! defined(__SUNPRO_C)
+#define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) 0
+#else
+#define PCAP_SUNPRO_VERSION_TO_BCD(major, minor) \
+ (((minor) >= 10) ? \
+ (((major) << 12) | (((minor)/10) << 8) | (((minor)%10) << 4)) : \
+ (((major) << 8) | ((minor) << 4)))
+#define PCAP_IS_AT_LEAST_SUNC_VERSION(major,minor) \
+ (__SUNPRO_C >= PCAP_SUNPRO_VERSION_TO_BCD((major), (minor)))
+#endif
+
+/*
+ * Check whether this is IBM XL C major.minor or a later release.
+ *
+ * The version number in __xlC__ has the major version in the
+ * upper 8 bits and the minor version in the lower 8 bits.
+ */
+
+#if ! defined(__xlC__)
+#define PCAP_IS_AT_LEAST_XL_C_VERSION(major,minor) 0
+#else
+#define PCAP_IS_AT_LEAST_XL_C_VERSION(major, minor) \
+ (__xlC__ >= (((major) << 8) | (minor)))
+#endif
+
+/*
+ * Check whether this is HP aC++/HP C major.minor or a later release.
+ *
+ * The version number in __HP_aCC is encoded in zero-padded decimal BCD,
+ * with the "A." stripped off, the uppermost two decimal digits being
+ * the major version number, the next two decimal digits being the minor
+ * version number, and the last two decimal digits being the patch version.
+ * (Strip off the A., remove the . between the major and minor version
+ * number, and add two digits of patch.)
+ */
+
+#if ! defined(__HP_aCC)
+#define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) 0
+#else
+#define PCAP_IS_AT_LEAST_HP_C_VERSION(major,minor) \
+ (__HP_aCC >= ((major)*10000 + (minor)*100))
+#endif
+
+#endif /* lib_pcap_compiler_tests_h */
diff --git a/lib/libpcap/libpcap/pcap/dlt.h b/lib/libpcap/libpcap/pcap/dlt.h
new file mode 100644
index 0000000..d61bcee
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/dlt.h
@@ -0,0 +1,1438 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)bpf.h 7.1 (Berkeley) 5/7/91
+ */
+
+#ifndef lib_pcap_dlt_h
+#define lib_pcap_dlt_h
+
+/*
+ * Link-layer header type codes.
+ *
+ * Do *NOT* add new values to this list without asking
+ * "tcpdump-workers@lists.tcpdump.org" for a value. Otherwise, you run
+ * the risk of using a value that's already being used for some other
+ * purpose, and of having tools that read libpcap-format captures not
+ * being able to handle captures with your new DLT_ value, with no hope
+ * that they will ever be changed to do so (as that would destroy their
+ * ability to read captures using that value for that other purpose).
+ *
+ * See
+ *
+ * https://www.tcpdump.org/linktypes.html
+ *
+ * for detailed descriptions of some of these link-layer header types.
+ */
+
+/*
+ * These are the types that are the same on all platforms, and that
+ * have been defined by <net/bpf.h> for ages.
+ */
+#define DLT_NULL 0 /* BSD loopback encapsulation */
+#define DLT_EN10MB 1 /* Ethernet (10Mb) */
+#define DLT_EN3MB 2 /* Experimental Ethernet (3Mb) */
+#define DLT_AX25 3 /* Amateur Radio AX.25 */
+#define DLT_PRONET 4 /* Proteon ProNET Token Ring */
+#define DLT_CHAOS 5 /* Chaos */
+#define DLT_IEEE802 6 /* 802.5 Token Ring */
+#define DLT_ARCNET 7 /* ARCNET, with BSD-style header */
+#define DLT_SLIP 8 /* Serial Line IP */
+#define DLT_PPP 9 /* Point-to-point Protocol */
+#define DLT_FDDI 10 /* FDDI */
+
+/*
+ * These are types that are different on some platforms, and that
+ * have been defined by <net/bpf.h> for ages. We use #ifdefs to
+ * detect the BSDs that define them differently from the traditional
+ * libpcap <net/bpf.h>
+ *
+ * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
+ * but I don't know what the right #define is for BSD/OS.
+ */
+#define DLT_ATM_RFC1483 11 /* LLC-encapsulated ATM */
+
+#ifdef __OpenBSD__
+#define DLT_RAW 14 /* raw IP */
+#else
+#define DLT_RAW 12 /* raw IP */
+#endif
+
+/*
+ * Given that the only OS that currently generates BSD/OS SLIP or PPP
+ * is, well, BSD/OS, arguably everybody should have chosen its values
+ * for DLT_SLIP_BSDOS and DLT_PPP_BSDOS, which are 15 and 16, but they
+ * didn't. So it goes.
+ */
+#if defined(__NetBSD__) || defined(__FreeBSD__)
+#ifndef DLT_SLIP_BSDOS
+#define DLT_SLIP_BSDOS 13 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 14 /* BSD/OS Point-to-point Protocol */
+#endif
+#else
+#define DLT_SLIP_BSDOS 15 /* BSD/OS Serial Line IP */
+#define DLT_PPP_BSDOS 16 /* BSD/OS Point-to-point Protocol */
+#endif
+
+/*
+ * 17 was used for DLT_PFLOG in OpenBSD; it no longer is.
+ *
+ * It was DLT_LANE8023 in SuSE 6.3, so we defined LINKTYPE_PFLOG
+ * as 117 so that pflog captures would use a link-layer header type
+ * value that didn't collide with any other values. On all
+ * platforms other than OpenBSD, we defined DLT_PFLOG as 117,
+ * and we mapped between LINKTYPE_PFLOG and DLT_PFLOG.
+ *
+ * OpenBSD eventually switched to using 117 for DLT_PFLOG as well.
+ *
+ * Don't use 17 for anything else.
+ */
+
+/*
+ * 18 is used for DLT_PFSYNC in OpenBSD, NetBSD, DragonFly BSD and
+ * macOS; don't use it for anything else. (FreeBSD uses 121, which
+ * collides with DLT_HHDLC, even though it doesn't use 18 for
+ * anything and doesn't appear to have ever used it for anything.)
+ *
+ * We define it as 18 on those platforms; it is, unfortunately, used
+ * for DLT_CIP in Suse 6.3, so we don't define it as DLT_PFSYNC
+ * in general. As the packet format for it, like that for
+ * DLT_PFLOG, is not only OS-dependent but OS-version-dependent,
+ * we don't support printing it in tcpdump except on OSes that
+ * have the relevant header files, so it's not that useful on
+ * other platforms.
+ */
+#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__APPLE__)
+#define DLT_PFSYNC 18
+#endif
+
+#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */
+
+/*
+ * Apparently Redback uses this for its SmartEdge 400/800. I hope
+ * nobody else decided to use it, too.
+ */
+#define DLT_REDBACK_SMARTEDGE 32
+
+/*
+ * These values are defined by NetBSD; other platforms should refrain from
+ * using them for other purposes, so that NetBSD savefiles with link
+ * types of 50 or 51 can be read as this type on all platforms.
+ */
+#define DLT_PPP_SERIAL 50 /* PPP over serial with HDLC encapsulation */
+#define DLT_PPP_ETHER 51 /* PPP over Ethernet */
+
+/*
+ * The Axent Raptor firewall - now the Symantec Enterprise Firewall - uses
+ * a link-layer type of 99 for the tcpdump it supplies. The link-layer
+ * header has 6 bytes of unknown data, something that appears to be an
+ * Ethernet type, and 36 bytes that appear to be 0 in at least one capture
+ * I've seen.
+ */
+#define DLT_SYMANTEC_FIREWALL 99
+
+/*
+ * Values between 100 and 103 are used in capture file headers as
+ * link-layer header type LINKTYPE_ values corresponding to DLT_ types
+ * that differ between platforms; don't use those values for new DLT_
+ * new types.
+ */
+
+/*
+ * Values starting with 104 are used for newly-assigned link-layer
+ * header type values; for those link-layer header types, the DLT_
+ * value returned by pcap_datalink() and passed to pcap_open_dead(),
+ * and the LINKTYPE_ value that appears in capture files, are the
+ * same.
+ *
+ * DLT_MATCHING_MIN is the lowest such value; DLT_MATCHING_MAX is
+ * the highest such value.
+ */
+#define DLT_MATCHING_MIN 104
+
+/*
+ * This value was defined by libpcap 0.5; platforms that have defined
+ * it with a different value should define it here with that value -
+ * a link type of 104 in a save file will be mapped to DLT_C_HDLC,
+ * whatever value that happens to be, so programs will correctly
+ * handle files with that link type regardless of the value of
+ * DLT_C_HDLC.
+ *
+ * The name DLT_C_HDLC was used by BSD/OS; we use that name for source
+ * compatibility with programs written for BSD/OS.
+ *
+ * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well,
+ * for source compatibility with programs written for libpcap 0.5.
+ */
+#define DLT_C_HDLC 104 /* Cisco HDLC */
+#define DLT_CHDLC DLT_C_HDLC
+
+#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */
+
+/*
+ * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW,
+ * except when it isn't. (I.e., sometimes it's just raw IP, and
+ * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL,
+ * so that we don't have to worry about the link-layer header.)
+ */
+
+/*
+ * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides
+ * with other values.
+ * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header
+ * (DLCI, etc.).
+ */
+#define DLT_FRELAY 107
+
+/*
+ * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except
+ * that the AF_ type in the link-layer header is in network byte order.
+ *
+ * DLT_LOOP is 12 in OpenBSD, but that's DLT_RAW in other OSes, so
+ * we don't use 12 for it in OSes other than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_LOOP 12
+#else
+#define DLT_LOOP 108
+#endif
+
+/*
+ * Encapsulated packets for IPsec; DLT_ENC is 13 in OpenBSD, but that's
+ * DLT_SLIP_BSDOS in NetBSD, so we don't use 13 for it in OSes other
+ * than OpenBSD.
+ */
+#ifdef __OpenBSD__
+#define DLT_ENC 13
+#else
+#define DLT_ENC 109
+#endif
+
+/*
+ * Values between 110 and 112 are reserved for use in capture file headers
+ * as link-layer types corresponding to DLT_ types that might differ
+ * between platforms; don't use those values for new DLT_ types
+ * other than the corresponding DLT_ types.
+ */
+
+/*
+ * Linux cooked sockets.
+ */
+#define DLT_LINUX_SLL 113
+
+/*
+ * Apple LocalTalk hardware.
+ */
+#define DLT_LTALK 114
+
+/*
+ * Acorn Econet.
+ */
+#define DLT_ECONET 115
+
+/*
+ * Reserved for use with OpenBSD ipfilter.
+ */
+#define DLT_IPFILTER 116
+
+/*
+ * OpenBSD DLT_PFLOG.
+ */
+#define DLT_PFLOG 117
+
+/*
+ * Registered for Cisco-internal use.
+ */
+#define DLT_CISCO_IOS 118
+
+/*
+ * For 802.11 cards using the Prism II chips, with a link-layer
+ * header including Prism monitor mode information plus an 802.11
+ * header.
+ */
+#define DLT_PRISM_HEADER 119
+
+/*
+ * Reserved for Aironet 802.11 cards, with an Aironet link-layer header
+ * (see Doug Ambrisko's FreeBSD patches).
+ */
+#define DLT_AIRONET_HEADER 120
+
+/*
+ * Sigh.
+ *
+ * 121 was reserved for Siemens HiPath HDLC on 2002-01-25, as
+ * requested by Tomas Kukosa.
+ *
+ * On 2004-02-25, a FreeBSD checkin to sys/net/bpf.h was made that
+ * assigned 121 as DLT_PFSYNC. In current versions, its libpcap
+ * does DLT_ <-> LINKTYPE_ mapping, mapping DLT_PFSYNC to a
+ * LINKTYPE_PFSYNC value of 246, so it should write out DLT_PFSYNC
+ * dump files with 246 as the link-layer header type. (Earlier
+ * versions might not have done mapping, in which case they would
+ * have written them out with a link-layer header type of 121.)
+ *
+ * OpenBSD, from which pf came, however, uses 18 for DLT_PFSYNC;
+ * its libpcap does no DLT_ <-> LINKTYPE_ mapping, so it would
+ * write out DLT_PFSYNC dump files with use 18 as the link-layer
+ * header type.
+ *
+ * NetBSD, DragonFly BSD, and Darwin also use 18 for DLT_PFSYNC; in
+ * current versions, their libpcaps do DLT_ <-> LINKTYPE_ mapping,
+ * mapping DLT_PFSYNC to a LINKTYPE_PFSYNC value of 246, so they
+ * should write out DLT_PFSYNC dump files with 246 as the link-layer
+ * header type. (Earlier versions might not have done mapping,
+ * in which case they'd work the same way OpenBSD does, writing
+ * them out with a link-layer header type of 18.)
+ *
+ * We'll define DLT_PFSYNC as:
+ *
+ * 18 on NetBSD, OpenBSD, DragonFly BSD, and Darwin;
+ *
+ * 121 on FreeBSD;
+ *
+ * 246 everywhere else.
+ *
+ * We'll define DLT_HHDLC as 121 on everything except for FreeBSD;
+ * anybody who wants to compile, on FreeBSD, code that uses DLT_HHDLC
+ * is out of luck.
+ *
+ * We'll define LINKTYPE_PFSYNC as 246 on *all* platforms, so that
+ * savefiles written using *this* code won't use 18 or 121 for PFSYNC,
+ * they'll all use 246.
+ *
+ * Code that uses pcap_datalink() to determine the link-layer header
+ * type of a savefile won't, when built and run on FreeBSD, be able
+ * to distinguish between LINKTYPE_PFSYNC and LINKTYPE_HHDLC capture
+ * files, as pcap_datalink() will give 121 for both of them. Code
+ * that doesn't, such as the code in Wireshark, will be able to
+ * distinguish between them.
+ *
+ * FreeBSD's libpcap won't map a link-layer header type of 18 - i.e.,
+ * DLT_PFSYNC files from OpenBSD and possibly older versions of NetBSD,
+ * DragonFly BSD, and macOS - to DLT_PFSYNC, so code built with FreeBSD's
+ * libpcap won't treat those files as DLT_PFSYNC files.
+ *
+ * Other libpcaps won't map a link-layer header type of 121 to DLT_PFSYNC;
+ * this means they can read DLT_HHDLC files, if any exist, but won't
+ * treat pcap files written by any older versions of FreeBSD libpcap that
+ * didn't map to 246 as DLT_PFSYNC files.
+ */
+#ifdef __FreeBSD__
+#define DLT_PFSYNC 121
+#else
+#define DLT_HHDLC 121
+#endif
+
+/*
+ * This is for RFC 2625 IP-over-Fibre Channel.
+ *
+ * This is not for use with raw Fibre Channel, where the link-layer
+ * header starts with a Fibre Channel frame header; it's for IP-over-FC,
+ * where the link-layer header starts with an RFC 2625 Network_Header
+ * field.
+ */
+#define DLT_IP_OVER_FC 122
+
+/*
+ * This is for Full Frontal ATM on Solaris with SunATM, with a
+ * pseudo-header followed by an AALn PDU.
+ *
+ * There may be other forms of Full Frontal ATM on other OSes,
+ * with different pseudo-headers.
+ *
+ * If ATM software returns a pseudo-header with VPI/VCI information
+ * (and, ideally, packet type information, e.g. signalling, ILMI,
+ * LANE, LLC-multiplexed traffic, etc.), it should not use
+ * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump
+ * and the like don't have to infer the presence or absence of a
+ * pseudo-header and the form of the pseudo-header.
+ */
+#define DLT_SUNATM 123 /* Solaris+SunATM */
+
+/*
+ * Reserved as per request from Kent Dahlgren <kent@praesum.com>
+ * for private use.
+ */
+#define DLT_RIO 124 /* RapidIO */
+#define DLT_PCI_EXP 125 /* PCI Express */
+#define DLT_AURORA 126 /* Xilinx Aurora link layer */
+
+/*
+ * Header for 802.11 plus a number of bits of link-layer information
+ * including radio information, used by some recent BSD drivers as
+ * well as the madwifi Atheros driver for Linux.
+ */
+#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus radiotap radio header */
+
+/*
+ * Reserved for the TZSP encapsulation, as per request from
+ * Chris Waters <chris.waters@networkchemistry.com>
+ * TZSP is a generic encapsulation for any other link type,
+ * which includes a means to include meta-information
+ * with the packet, e.g. signal strength and channel
+ * for 802.11 packets.
+ */
+#define DLT_TZSP 128 /* Tazmen Sniffer Protocol */
+
+/*
+ * BSD's ARCNET headers have the source host, destination host,
+ * and type at the beginning of the packet; that's what's handed
+ * up to userland via BPF.
+ *
+ * Linux's ARCNET headers, however, have a 2-byte offset field
+ * between the host IDs and the type; that's what's handed up
+ * to userland via PF_PACKET sockets.
+ *
+ * We therefore have to have separate DLT_ values for them.
+ */
+#define DLT_ARCNET_LINUX 129 /* ARCNET */
+
+/*
+ * Juniper-private data link types, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MLPPP 130
+#define DLT_JUNIPER_MLFR 131
+#define DLT_JUNIPER_ES 132
+#define DLT_JUNIPER_GGSN 133
+#define DLT_JUNIPER_MFR 134
+#define DLT_JUNIPER_ATM2 135
+#define DLT_JUNIPER_SERVICES 136
+#define DLT_JUNIPER_ATM1 137
+
+/*
+ * Apple IP-over-IEEE 1394, as per a request from Dieter Siegmund
+ * <dieter@apple.com>. The header that's presented is an Ethernet-like
+ * header:
+ *
+ * #define FIREWIRE_EUI64_LEN 8
+ * struct firewire_header {
+ * u_char firewire_dhost[FIREWIRE_EUI64_LEN];
+ * u_char firewire_shost[FIREWIRE_EUI64_LEN];
+ * u_short firewire_type;
+ * };
+ *
+ * with "firewire_type" being an Ethernet type value, rather than,
+ * for example, raw GASP frames being handed up.
+ */
+#define DLT_APPLE_IP_OVER_IEEE1394 138
+
+/*
+ * Various SS7 encapsulations, as per a request from Jeff Morriss
+ * <jeff.morriss[AT]ulticom.com> and subsequent discussions.
+ */
+#define DLT_MTP2_WITH_PHDR 139 /* pseudo-header with various info, followed by MTP2 */
+#define DLT_MTP2 140 /* MTP2, without pseudo-header */
+#define DLT_MTP3 141 /* MTP3, without pseudo-header or MTP2 */
+#define DLT_SCCP 142 /* SCCP, without pseudo-header or MTP2 or MTP3 */
+
+/*
+ * DOCSIS MAC frames.
+ */
+#define DLT_DOCSIS 143
+
+/*
+ * Linux-IrDA packets. Protocol defined at http://www.irda.org.
+ * Those packets include IrLAP headers and above (IrLMP...), but
+ * don't include Phy framing (SOF/EOF/CRC & byte stuffing), because Phy
+ * framing can be handled by the hardware and depend on the bitrate.
+ * This is exactly the format you would get capturing on a Linux-IrDA
+ * interface (irdaX), but not on a raw serial port.
+ * Note the capture is done in "Linux-cooked" mode, so each packet include
+ * a fake packet header (struct sll_header). This is because IrDA packet
+ * decoding is dependant on the direction of the packet (incomming or
+ * outgoing).
+ * When/if other platform implement IrDA capture, we may revisit the
+ * issue and define a real DLT_IRDA...
+ * Jean II
+ */
+#define DLT_LINUX_IRDA 144
+
+/*
+ * Reserved for IBM SP switch and IBM Next Federation switch.
+ */
+#define DLT_IBM_SP 145
+#define DLT_IBM_SN 146
+
+/*
+ * Reserved for private use. If you have some link-layer header type
+ * that you want to use within your organization, with the capture files
+ * using that link-layer header type not ever be sent outside your
+ * organization, you can use these values.
+ *
+ * No libpcap release will use these for any purpose, nor will any
+ * tcpdump release use them, either.
+ *
+ * Do *NOT* use these in capture files that you expect anybody not using
+ * your private versions of capture-file-reading tools to read; in
+ * particular, do *NOT* use them in products, otherwise you may find that
+ * people won't be able to use tcpdump, or snort, or Ethereal, or... to
+ * read capture files from your firewall/intrusion detection/traffic
+ * monitoring/etc. appliance, or whatever product uses that DLT_ value,
+ * and you may also find that the developers of those applications will
+ * not accept patches to let them read those files.
+ *
+ * Also, do not use them if somebody might send you a capture using them
+ * for *their* private type and tools using them for *your* private type
+ * would have to read them.
+ *
+ * Instead, ask "tcpdump-workers@lists.tcpdump.org" for a new DLT_ value,
+ * as per the comment above, and use the type you're given.
+ */
+#define DLT_USER0 147
+#define DLT_USER1 148
+#define DLT_USER2 149
+#define DLT_USER3 150
+#define DLT_USER4 151
+#define DLT_USER5 152
+#define DLT_USER6 153
+#define DLT_USER7 154
+#define DLT_USER8 155
+#define DLT_USER9 156
+#define DLT_USER10 157
+#define DLT_USER11 158
+#define DLT_USER12 159
+#define DLT_USER13 160
+#define DLT_USER14 161
+#define DLT_USER15 162
+
+#ifdef __APPLE__
+#define DLT_PCAPNG DLT_USER4
+#endif
+
+/*
+ * For future use with 802.11 captures - defined by AbsoluteValue
+ * Systems to store a number of bits of link-layer information
+ * including radio information:
+ *
+ * http://www.shaftnet.org/~pizza/software/capturefrm.txt
+ *
+ * but it might be used by some non-AVS drivers now or in the
+ * future.
+ */
+#define DLT_IEEE802_11_RADIO_AVS 163 /* 802.11 plus AVS radio header */
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, etc..
+ */
+#define DLT_JUNIPER_MONITOR 164
+
+/*
+ * BACnet MS/TP frames.
+ */
+#define DLT_BACNET_MS_TP 165
+
+/*
+ * Another PPP variant as per request from Karsten Keil <kkeil@suse.de>.
+ *
+ * This is used in some OSes to allow a kernel socket filter to distinguish
+ * between incoming and outgoing packets, on a socket intended to
+ * supply pppd with outgoing packets so it can do dial-on-demand and
+ * hangup-on-lack-of-demand; incoming packets are filtered out so they
+ * don't cause pppd to hold the connection up (you don't want random
+ * input packets such as port scans, packets from old lost connections,
+ * etc. to force the connection to stay up).
+ *
+ * The first byte of the PPP header (0xff03) is modified to accomodate
+ * the direction - 0x00 = IN, 0x01 = OUT.
+ */
+#define DLT_PPP_PPPD 166
+
+/*
+ * Names for backwards compatibility with older versions of some PPP
+ * software; new software should use DLT_PPP_PPPD.
+ */
+#define DLT_PPP_WITH_DIRECTION DLT_PPP_PPPD
+#define DLT_LINUX_PPP_WITHDIRECTION DLT_PPP_PPPD
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_s are used
+ * for passing on chassis-internal metainformation such as
+ * QOS profiles, cookies, etc..
+ */
+#define DLT_JUNIPER_PPPOE 167
+#define DLT_JUNIPER_PPPOE_ATM 168
+
+#define DLT_GPRS_LLC 169 /* GPRS LLC */
+#define DLT_GPF_T 170 /* GPF-T (ITU-T G.7041/Y.1303) */
+#define DLT_GPF_F 171 /* GPF-F (ITU-T G.7041/Y.1303) */
+
+/*
+ * Requested by Oolan Zimmer <oz@gcom.com> for use in Gcom's T1/E1 line
+ * monitoring equipment.
+ */
+#define DLT_GCOM_T1E1 172
+#define DLT_GCOM_SERIAL 173
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>. The DLT_ is used
+ * for internal communication to Physical Interface Cards (PIC)
+ */
+#define DLT_JUNIPER_PIC_PEER 174
+
+/*
+ * Link types requested by Gregor Maier <gregor@endace.com> of Endace
+ * Measurement Systems. They add an ERF header (see
+ * http://www.endace.com/support/EndaceRecordFormat.pdf) in front of
+ * the link-layer header.
+ */
+#define DLT_ERF_ETH 175 /* Ethernet */
+#define DLT_ERF_POS 176 /* Packet-over-SONET */
+
+/*
+ * Requested by Daniele Orlandi <daniele@orlandi.com> for raw LAPD
+ * for vISDN (http://www.orlandi.com/visdn/). Its link-layer header
+ * includes additional information before the LAPD header, so it's
+ * not necessarily a generic LAPD header.
+ */
+#define DLT_LINUX_LAPD 177
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ are used for prepending meta-information
+ * like interface index, interface name
+ * before standard Ethernet, PPP, Frelay & C-HDLC Frames
+ */
+#define DLT_JUNIPER_ETHER 178
+#define DLT_JUNIPER_PPP 179
+#define DLT_JUNIPER_FRELAY 180
+#define DLT_JUNIPER_CHDLC 181
+
+/*
+ * Multi Link Frame Relay (FRF.16)
+ */
+#define DLT_MFR 182
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * voice Adapter Card (PIC)
+ */
+#define DLT_JUNIPER_VP 183
+
+/*
+ * Arinc 429 frames.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Every frame contains a 32bit A429 label.
+ * More documentation on Arinc 429 can be found at
+ * http://www.condoreng.com/support/downloads/tutorials/ARINCTutorial.pdf
+ */
+#define DLT_A429 184
+
+/*
+ * Arinc 653 Interpartition Communication messages.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Please refer to the A653-1 standard for more information.
+ */
+#define DLT_A653_ICM 185
+
+/*
+ * This used to be "USB packets, beginning with a USB setup header;
+ * requested by Paolo Abeni <paolo.abeni@email.it>."
+ *
+ * However, that header didn't work all that well - it left out some
+ * useful information - and was abandoned in favor of the DLT_USB_LINUX
+ * header.
+ *
+ * This is now used by FreeBSD for its BPF taps for USB; that has its
+ * own headers. So it is written, so it is done.
+ *
+ * For source-code compatibility, we also define DLT_USB to have this
+ * value. We do it numerically so that, if code that includes this
+ * file (directly or indirectly) also includes an OS header that also
+ * defines DLT_USB as 186, we don't get a redefinition warning.
+ * (NetBSD 7 does that.)
+ */
+#define DLT_USB_FREEBSD 186
+#define DLT_USB 186
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4); requested by
+ * Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4 187
+
+/*
+ * IEEE 802.16 MAC Common Part Sublayer; requested by Maria Cruz
+ * <cruz_petagay@bah.com>.
+ */
+#define DLT_IEEE802_16_MAC_CPS 188
+
+/*
+ * USB packets, beginning with a Linux USB header; requested by
+ * Paolo Abeni <paolo.abeni@email.it>.
+ */
+#define DLT_USB_LINUX 189
+
+/*
+ * Controller Area Network (CAN) v. 2.0B packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ * Used to dump CAN packets coming from a CAN Vector board.
+ * More documentation on the CAN v2.0B frames can be found at
+ * http://www.can-cia.org/downloads/?269
+ */
+#define DLT_CAN20B 190
+
+/*
+ * IEEE 802.15.4, with address fields padded, as is done by Linux
+ * drivers; requested by Juergen Schimmer.
+ */
+#define DLT_IEEE802_15_4_LINUX 191
+
+/*
+ * Per Packet Information encapsulated packets.
+ * DLT_ requested by Gianluca Varenni <gianluca.varenni@cacetech.com>.
+ */
+#define DLT_PPI 192
+
+/*
+ * Header for 802.16 MAC Common Part Sublayer plus a radiotap radio header;
+ * requested by Charles Clancy.
+ */
+#define DLT_IEEE802_16_MAC_CPS_RADIO 193
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for internal communication with a
+ * integrated service module (ISM).
+ */
+#define DLT_JUNIPER_ISM 194
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing); requested by Mikko Saarnivala <mikko.saarnivala@sensinode.com>.
+ * For this one, we expect the FCS to be present at the end of the frame;
+ * if the frame has no FCS, DLT_IEEE802_15_4_NOFCS should be used.
+ *
+ * We keep the name DLT_IEEE802_15_4 as an alias for backwards
+ * compatibility, but, again, this should *only* be used for 802.15.4
+ * frames that include the FCS.
+ */
+#define DLT_IEEE802_15_4_WITHFCS 195
+#define DLT_IEEE802_15_4 DLT_IEEE802_15_4_WITHFCS
+
+/*
+ * Various link-layer types, with a pseudo-header, for SITA
+ * (http://www.sita.aero/); requested by Fulko Hew (fulko.hew@gmail.com).
+ */
+#define DLT_SITA 196
+
+/*
+ * Various link-layer types, with a pseudo-header, for Endace DAG cards;
+ * encapsulates Endace ERF records. Requested by Stephen Donnelly
+ * <stephen@endace.com>.
+ */
+#define DLT_ERF 197
+
+/*
+ * Special header prepended to Ethernet packets when capturing from a
+ * u10 Networks board. Requested by Phil Mulholland
+ * <phil@u10networks.com>.
+ */
+#define DLT_RAIF1 198
+
+/*
+ * IPMB packet for IPMI, beginning with a 2-byte header, followed by
+ * the I2C slave address, followed by the netFn and LUN, etc..
+ * Requested by Chanthy Toeung <chanthy.toeung@ca.kontron.com>.
+ *
+ * XXX - this used to be called DLT_IPMB, back when we got the
+ * impression from the email thread requesting it that the packet
+ * had no extra 2-byte header. We've renamed it; if anybody used
+ * DLT_IPMB and assumed no 2-byte header, this will cause the compile
+ * to fail, at which point we'll have to figure out what to do about
+ * the two header types using the same DLT_/LINKTYPE_ value. If that
+ * doesn't happen, we'll assume nobody used it and that the redefinition
+ * is safe.
+ */
+#define DLT_IPMB_KONTRON 199
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ * The DLT_ is used for capturing data on a secure tunnel interface.
+ */
+#define DLT_JUNIPER_ST 200
+
+/*
+ * Bluetooth HCI UART transport layer (part H:4), with pseudo-header
+ * that includes direction information; requested by Paolo Abeni.
+ */
+#define DLT_BLUETOOTH_HCI_H4_WITH_PHDR 201
+
+/*
+ * AX.25 packet with a 1-byte KISS header; see
+ *
+ * http://www.ax25.net/kiss.htm
+ *
+ * as per Richard Stearn <richard@rns-stearn.demon.co.uk>.
+ */
+#define DLT_AX25_KISS 202
+
+/*
+ * LAPD packets from an ISDN channel, starting with the address field,
+ * with no pseudo-header.
+ * Requested by Varuna De Silva <varunax@gmail.com>.
+ */
+#define DLT_LAPD 203
+
+/*
+ * PPP, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host", non-zero (any non-zero value) means "sent by
+ * this host" - as per Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_PPP_WITH_DIR 204 /* Don't confuse with DLT_PPP_WITH_DIRECTION */
+
+/*
+ * Cisco HDLC, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host", non-zero (any non-zero value) means
+ * "sent by this host" - as per Will Barker <w.barker@zen.co.uk>.
+ */
+#define DLT_C_HDLC_WITH_DIR 205
+
+/*
+ * Frame Relay, with a one-byte direction pseudo-header prepended - zero
+ * means "received by this host" (DCE -> DTE), non-zero (any non-zero
+ * value) means "sent by this host" (DTE -> DCE) - as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define DLT_FRELAY_WITH_DIR 206
+
+/*
+ * LAPB, with a one-byte direction pseudo-header prepended - zero means
+ * "received by this host" (DCE -> DTE), non-zero (any non-zero value)
+ * means "sent by this host" (DTE -> DCE)- as per Will Barker
+ * <w.barker@zen.co.uk>.
+ */
+#define DLT_LAPB_WITH_DIR 207
+
+/*
+ * 208 is reserved for an as-yet-unspecified proprietary link-layer
+ * type, as requested by Will Barker.
+ */
+
+/*
+ * IPMB with a Linux-specific pseudo-header; as requested by Alexey Neyman
+ * <avn@pigeonpoint.com>.
+ */
+#define DLT_IPMB_LINUX 209
+
+/*
+ * FlexRay automotive bus - http://www.flexray.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_FLEXRAY 210
+
+/*
+ * Media Oriented Systems Transport (MOST) bus for multimedia
+ * transport - http://www.mostcooperation.com/ - as requested
+ * by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_MOST 211
+
+/*
+ * Local Interconnect Network (LIN) bus for vehicle networks -
+ * http://www.lin-subbus.org/ - as requested by Hannes Kaelber
+ * <hannes.kaelber@x2e.de>.
+ */
+#define DLT_LIN 212
+
+/*
+ * X2E-private data link type used for serial line capture,
+ * as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_SERIAL 213
+
+/*
+ * X2E-private data link type used for the Xoraya data logger
+ * family, as requested by Hannes Kaelber <hannes.kaelber@x2e.de>.
+ */
+#define DLT_X2E_XORAYA 214
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), but with the PHY-level data for non-ASK PHYs (4 octets
+ * of 0 as preamble, one octet of SFD, one octet of frame length+
+ * reserved bit, and then the MAC-layer data, starting with the
+ * frame control field).
+ *
+ * Requested by Max Filippov <jcmvbkbc@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NONASK_PHY 215
+
+/*
+ * David Gibson <david@gibson.dropbear.id.au> requested this for
+ * captures from the Linux kernel /dev/input/eventN devices. This
+ * is used to communicate keystrokes and mouse movements from the
+ * Linux kernel to display systems, such as Xorg.
+ */
+#define DLT_LINUX_EVDEV 216
+
+/*
+ * GSM Um and Abis interfaces, preceded by a "gsmtap" header.
+ *
+ * Requested by Harald Welte <laforge@gnumonks.org>.
+ */
+#define DLT_GSMTAP_UM 217
+#define DLT_GSMTAP_ABIS 218
+
+/*
+ * MPLS, with an MPLS label as the link-layer header.
+ * Requested by Michele Marchetto <michele@openbsd.org> on behalf
+ * of OpenBSD.
+ */
+#define DLT_MPLS 219
+
+/*
+ * USB packets, beginning with a Linux USB header, with the USB header
+ * padded to 64 bytes; required for memory-mapped access.
+ */
+#define DLT_USB_LINUX_MMAPPED 220
+
+/*
+ * DECT packets, with a pseudo-header; requested by
+ * Matthias Wenzel <tcpdump@mazzoo.de>.
+ */
+#define DLT_DECT 221
+
+/*
+ * From: "Lidwa, Eric (GSFC-582.0)[SGT INC]" <eric.lidwa-1@nasa.gov>
+ * Date: Mon, 11 May 2009 11:18:30 -0500
+ *
+ * DLT_AOS. We need it for AOS Space Data Link Protocol.
+ * I have already written dissectors for but need an OK from
+ * legal before I can submit a patch.
+ *
+ */
+#define DLT_AOS 222
+
+/*
+ * Wireless HART (Highway Addressable Remote Transducer)
+ * From the HART Communication Foundation
+ * IES/PAS 62591
+ *
+ * Requested by Sam Roberts <vieuxtech@gmail.com>.
+ */
+#define DLT_WIHART 223
+
+/*
+ * Fibre Channel FC-2 frames, beginning with a Frame_Header.
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2 224
+
+/*
+ * Fibre Channel FC-2 frames, beginning with an encoding of the
+ * SOF, and ending with an encoding of the EOF.
+ *
+ * The encodings represent the frame delimiters as 4-byte sequences
+ * representing the corresponding ordered sets, with K28.5
+ * represented as 0xBC, and the D symbols as the corresponding
+ * byte values; for example, SOFi2, which is K28.5 - D21.5 - D1.2 - D21.2,
+ * is represented as 0xBC 0xB5 0x55 0x55.
+ *
+ * Requested by Kahou Lei <kahou82@gmail.com>.
+ */
+#define DLT_FC_2_WITH_FRAME_DELIMS 225
+
+/*
+ * Solaris ipnet pseudo-header; requested by Darren Reed <Darren.Reed@Sun.COM>.
+ *
+ * The pseudo-header starts with a one-byte version number; for version 2,
+ * the pseudo-header is:
+ *
+ * struct dl_ipnetinfo {
+ * uint8_t dli_version;
+ * uint8_t dli_family;
+ * uint16_t dli_htype;
+ * uint32_t dli_pktlen;
+ * uint32_t dli_ifindex;
+ * uint32_t dli_grifindex;
+ * uint32_t dli_zsrc;
+ * uint32_t dli_zdst;
+ * };
+ *
+ * dli_version is 2 for the current version of the pseudo-header.
+ *
+ * dli_family is a Solaris address family value, so it's 2 for IPv4
+ * and 26 for IPv6.
+ *
+ * dli_htype is a "hook type" - 0 for incoming packets, 1 for outgoing
+ * packets, and 2 for packets arriving from another zone on the same
+ * machine.
+ *
+ * dli_pktlen is the length of the packet data following the pseudo-header
+ * (so the captured length minus dli_pktlen is the length of the
+ * pseudo-header, assuming the entire pseudo-header was captured).
+ *
+ * dli_ifindex is the interface index of the interface on which the
+ * packet arrived.
+ *
+ * dli_grifindex is the group interface index number (for IPMP interfaces).
+ *
+ * dli_zsrc is the zone identifier for the source of the packet.
+ *
+ * dli_zdst is the zone identifier for the destination of the packet.
+ *
+ * A zone number of 0 is the global zone; a zone number of 0xffffffff
+ * means that the packet arrived from another host on the network, not
+ * from another zone on the same machine.
+ *
+ * An IPv4 or IPv6 datagram follows the pseudo-header; dli_family indicates
+ * which of those it is.
+ */
+#define DLT_IPNET 226
+
+/*
+ * CAN (Controller Area Network) frames, with a pseudo-header as supplied
+ * by Linux SocketCAN, and with multi-byte numerical fields in that header
+ * in big-endian byte order.
+ *
+ * See Documentation/networking/can.txt in the Linux source.
+ *
+ * Requested by Felix Obenhuber <felix@obenhuber.de>.
+ */
+#define DLT_CAN_SOCKETCAN 227
+
+/*
+ * Raw IPv4/IPv6; different from DLT_RAW in that the DLT_ value specifies
+ * whether it's v4 or v6. Requested by Darren Reed <Darren.Reed@Sun.COM>.
+ */
+#define DLT_IPV4 228
+#define DLT_IPV6 229
+
+/*
+ * IEEE 802.15.4, exactly as it appears in the spec (no padding, no
+ * nothing), and with no FCS at the end of the frame; requested by
+ * Jon Smirl <jonsmirl@gmail.com>.
+ */
+#define DLT_IEEE802_15_4_NOFCS 230
+
+/*
+ * Raw D-Bus:
+ *
+ * http://www.freedesktop.org/wiki/Software/dbus
+ *
+ * messages:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#message-protocol-messages
+ *
+ * starting with the endianness flag, followed by the message type, etc.,
+ * but without the authentication handshake before the message sequence:
+ *
+ * http://dbus.freedesktop.org/doc/dbus-specification.html#auth-protocol
+ *
+ * Requested by Martin Vidner <martin@vidner.net>.
+ */
+#define DLT_DBUS 231
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_VS 232
+#define DLT_JUNIPER_SRX_E2E 233
+#define DLT_JUNIPER_FIBRECHANNEL 234
+
+/*
+ * DVB-CI (DVB Common Interface for communication between a PC Card
+ * module and a DVB receiver). See
+ *
+ * http://www.kaiser.cx/pcap-dvbci.html
+ *
+ * for the specification.
+ *
+ * Requested by Martin Kaiser <martin@kaiser.cx>.
+ */
+#define DLT_DVB_CI 235
+
+/*
+ * Variant of 3GPP TS 27.010 multiplexing protocol (similar to, but
+ * *not* the same as, 27.010). Requested by Hans-Christoph Schemmel
+ * <hans-christoph.schemmel@cinterion.com>.
+ */
+#define DLT_MUX27010 236
+
+/*
+ * STANAG 5066 D_PDUs. Requested by M. Baris Demiray
+ * <barisdemiray@gmail.com>.
+ */
+#define DLT_STANAG_5066_D_PDU 237
+
+/*
+ * Juniper-private data link type, as per request from
+ * Hannes Gredler <hannes@juniper.net>.
+ */
+#define DLT_JUNIPER_ATM_CEMIC 238
+
+/*
+ * NetFilter LOG messages
+ * (payload of netlink NFNL_SUBSYS_ULOG/NFULNL_MSG_PACKET packets)
+ *
+ * Requested by Jakub Zawadzki <darkjames-ws@darkjames.pl>
+ */
+#define DLT_NFLOG 239
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and always
+ * with the payload including the FCS, as supplied by their
+ * netANALYZER hardware and software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER 240
+
+/*
+ * Hilscher Gesellschaft fuer Systemautomation mbH link-layer type
+ * for Ethernet packets with a 4-byte pseudo-header and FCS and
+ * with the Ethernet header preceded by 7 bytes of preamble and
+ * 1 byte of SFD, as supplied by their netANALYZER hardware and
+ * software.
+ *
+ * Requested by Holger P. Frommer <HPfrommer@hilscher.com>
+ */
+#define DLT_NETANALYZER_TRANSPARENT 241
+
+/*
+ * IP-over-InfiniBand, as specified by RFC 4391.
+ *
+ * Requested by Petr Sumbera <petr.sumbera@oracle.com>.
+ */
+#define DLT_IPOIB 242
+
+/*
+ * MPEG-2 transport stream (ISO 13818-1/ITU-T H.222.0).
+ *
+ * Requested by Guy Martin <gmsoft@tuxicoman.be>.
+ */
+#define DLT_MPEG_2_TS 243
+
+/*
+ * ng4T GmbH's UMTS Iub/Iur-over-ATM and Iub/Iur-over-IP format as
+ * used by their ng40 protocol tester.
+ *
+ * Requested by Jens Grimmer <jens.grimmer@ng4t.com>.
+ */
+#define DLT_NG40 244
+
+/*
+ * Pseudo-header giving adapter number and flags, followed by an NFC
+ * (Near-Field Communications) Logical Link Control Protocol (LLCP) PDU,
+ * as specified by NFC Forum Logical Link Control Protocol Technical
+ * Specification LLCP 1.1.
+ *
+ * Requested by Mike Wakerly <mikey@google.com>.
+ */
+#define DLT_NFC_LLCP 245
+
+/*
+ * 246 is used as LINKTYPE_PFSYNC; do not use it for any other purpose.
+ *
+ * DLT_PFSYNC has different values on different platforms, and all of
+ * them collide with something used elsewhere. On platforms that
+ * don't already define it, define it as 246.
+ */
+#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) && !defined(__DragonFly__) && !defined(__APPLE__)
+#define DLT_PFSYNC 246
+#endif
+
+/*
+ * Raw InfiniBand packets, starting with the Local Routing Header.
+ *
+ * Requested by Oren Kladnitsky <orenk@mellanox.com>.
+ */
+#define DLT_INFINIBAND 247
+
+/*
+ * SCTP, with no lower-level protocols (i.e., no IPv4 or IPv6).
+ *
+ * Requested by Michael Tuexen <Michael.Tuexen@lurchi.franken.de>.
+ */
+#define DLT_SCTP 248
+
+/*
+ * USB packets, beginning with a USBPcap header.
+ *
+ * Requested by Tomasz Mon <desowin@gmail.com>
+ */
+#define DLT_USBPCAP 249
+
+/*
+ * Schweitzer Engineering Laboratories "RTAC" product serial-line
+ * packets.
+ *
+ * Requested by Chris Bontje <chris_bontje@selinc.com>.
+ */
+#define DLT_RTAC_SERIAL 250
+
+/*
+ * Bluetooth Low Energy air interface link-layer packets.
+ *
+ * Requested by Mike Kershaw <dragorn@kismetwireless.net>.
+ */
+#define DLT_BLUETOOTH_LE_LL 251
+
+/*
+ * DLT type for upper-protocol layer PDU saves from wireshark.
+ *
+ * the actual contents are determined by two TAGs stored with each
+ * packet:
+ * EXP_PDU_TAG_LINKTYPE the link type (LINKTYPE_ value) of the
+ * original packet.
+ *
+ * EXP_PDU_TAG_PROTO_NAME the name of the wireshark dissector
+ * that can make sense of the data stored.
+ */
+#define DLT_WIRESHARK_UPPER_PDU 252
+
+/*
+ * DLT type for the netlink protocol (nlmon devices).
+ */
+#define DLT_NETLINK 253
+
+/*
+ * Bluetooth Linux Monitor headers for the BlueZ stack.
+ */
+#define DLT_BLUETOOTH_LINUX_MONITOR 254
+
+/*
+ * Bluetooth Basic Rate/Enhanced Data Rate baseband packets, as
+ * captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_BREDR_BB 255
+
+/*
+ * Bluetooth Low Energy link layer packets, as captured by Ubertooth.
+ */
+#define DLT_BLUETOOTH_LE_LL_WITH_PHDR 256
+
+/*
+ * PROFIBUS data link layer.
+ */
+#define DLT_PROFIBUS_DL 257
+
+/*
+ * Apple's DLT_PKTAP headers.
+ *
+ * Sadly, the folks at Apple either had no clue that the DLT_USERn values
+ * are for internal use within an organization and partners only, and
+ * didn't know that the right way to get a link-layer header type is to
+ * ask tcpdump.org for one, or knew and didn't care, so they just
+ * used DLT_USER2, which causes problems for everything except for
+ * their version of tcpdump.
+ *
+ * So I'll just give them one; hopefully this will show up in a
+ * libpcap release in time for them to get this into 10.10 Big Sur
+ * or whatever Mavericks' successor is called. LINKTYPE_PKTAP
+ * will be 258 *even on macOS*; that is *intentional*, so that
+ * PKTAP files look the same on *all* OSes (different OSes can have
+ * different numerical values for a given DLT_, but *MUST NOT* have
+ * different values for what goes in a file, as files can be moved
+ * between OSes!).
+ *
+ * When capturing, on a system with a Darwin-based OS, on a device
+ * that returns 149 (DLT_USER2 and Apple's DLT_PKTAP) with this
+ * version of libpcap, the DLT_ value for the pcap_t will be DLT_PKTAP,
+ * and that will continue to be DLT_USER2 on Darwin-based OSes. That way,
+ * binary compatibility with Mavericks is preserved for programs using
+ * this version of libpcap. This does mean that if you were using
+ * DLT_USER2 for some capture device on macOS, you can't do so with
+ * this version of libpcap, just as you can't with Apple's libpcap -
+ * on macOS, they define DLT_PKTAP to be DLT_USER2, so programs won't
+ * be able to distinguish between PKTAP and whatever you were using
+ * DLT_USER2 for.
+ *
+ * If the program saves the capture to a file using this version of
+ * libpcap's pcap_dump code, the LINKTYPE_ value in the file will be
+ * LINKTYPE_PKTAP, which will be 258, even on Darwin-based OSes.
+ * That way, the file will *not* be a DLT_USER2 file. That means
+ * that the latest version of tcpdump, when built with this version
+ * of libpcap, and sufficiently recent versions of Wireshark will
+ * be able to read those files and interpret them correctly; however,
+ * Apple's version of tcpdump in OS X 10.9 won't be able to handle
+ * them. (Hopefully, Apple will pick up this version of libpcap,
+ * and the corresponding version of tcpdump, so that tcpdump will
+ * be able to handle the old LINKTYPE_USER2 captures *and* the new
+ * LINKTYPE_PKTAP captures.)
+ */
+#ifdef __APPLE__
+#define DLT_PKTAP DLT_USER2
+#else
+#define DLT_PKTAP 258
+#endif
+
+/*
+ * Ethernet packets preceded by a header giving the last 6 octets
+ * of the preamble specified by 802.3-2012 Clause 65, section
+ * 65.1.3.2 "Transmit".
+ */
+#define DLT_EPON 259
+
+/*
+ * IPMI trace packets, as specified by Table 3-20 "Trace Data Block Format"
+ * in the PICMG HPM.2 specification.
+ */
+#define DLT_IPMI_HPM_2 260
+
+/*
+ * per Joshua Wright <jwright@hasborg.com>, formats for Zwave captures.
+ */
+#define DLT_ZWAVE_R1_R2 261
+#define DLT_ZWAVE_R3 262
+
+/*
+ * per Steve Karg <skarg@users.sourceforge.net>, formats for Wattstopper
+ * Digital Lighting Management room bus serial protocol captures.
+ */
+#define DLT_WATTSTOPPER_DLM 263
+
+/*
+ * ISO 14443 contactless smart card messages.
+ */
+#define DLT_ISO_14443 264
+
+/*
+ * Radio data system (RDS) groups. IEC 62106.
+ * Per Jonathan Brucker <jonathan.brucke@gmail.com>.
+ */
+#define DLT_RDS 265
+
+/*
+ * USB packets, beginning with a Darwin (macOS, etc.) header.
+ */
+#define DLT_USB_DARWIN 266
+
+/*
+ * OpenBSD DLT_OPENFLOW.
+ */
+#define DLT_OPENFLOW 267
+
+/*
+ * SDLC frames containing SNA PDUs.
+ */
+#define DLT_SDLC 268
+
+/*
+ * per "Selvig, Bjorn" <b.selvig@ti.com> used for
+ * TI protocol sniffer.
+ */
+#define DLT_TI_LLN_SNIFFER 269
+
+/*
+ * per: Erik de Jong <erikdejong at gmail.com> for
+ * https://github.com/eriknl/LoRaTap/releases/tag/v0.1
+ */
+#define DLT_LORATAP 270
+
+/*
+ * per: Stefanha at gmail.com for
+ * http://lists.sandelman.ca/pipermail/tcpdump-workers/2017-May/000772.html
+ * and: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/vsockmon.h
+ * for: http://qemu-project.org/Features/VirtioVsock
+ */
+#define DLT_VSOCK 271
+
+/*
+ * Nordic Semiconductor Bluetooth LE sniffer.
+ */
+#define DLT_NORDIC_BLE 272
+
+/*
+ * Excentis DOCSIS 3.1 RF sniffer (XRA-31)
+ * per: bruno.verstuyft at excentis.com
+ * http://www.xra31.com/xra-header
+ */
+#define DLT_DOCSIS31_XRA31 273
+
+/*
+ * mPackets, as specified by IEEE 802.3br Figure 99-4, starting
+ * with the preamble and always ending with a CRC field.
+ */
+#define DLT_ETHERNET_MPACKET 274
+
+/*
+ * DisplayPort AUX channel monitoring data as specified by VESA
+ * DisplayPort(DP) Standard preceeded by a pseudo-header.
+ * per dirk.eibach at gdsys.cc
+ */
+#define DLT_DISPLAYPORT_AUX 275
+
+/*
+ * Linux cooked sockets v2.
+ */
+#define DLT_LINUX_SLL2 276
+
+/*
+ * In case the code that includes this file (directly or indirectly)
+ * has also included OS files that happen to define DLT_MATCHING_MAX,
+ * with a different value (perhaps because that OS hasn't picked up
+ * the latest version of our DLT definitions), we undefine the
+ * previous value of DLT_MATCHING_MAX.
+ */
+#ifdef DLT_MATCHING_MAX
+#undef DLT_MATCHING_MAX
+#endif
+#define DLT_MATCHING_MAX 276 /* highest value in the "matching" range */
+
+/*
+ * DLT and savefile link type values are split into a class and
+ * a member of that class. A class value of 0 indicates a regular
+ * DLT_/LINKTYPE_ value.
+ */
+#define DLT_CLASS(x) ((x) & 0x03ff0000)
+
+/*
+ * NetBSD-specific generic "raw" link type. The class value indicates
+ * that this is the generic raw type, and the lower 16 bits are the
+ * address family we're dealing with. Those values are NetBSD-specific;
+ * do not assume that they correspond to AF_ values for your operating
+ * system.
+ */
+#define DLT_CLASS_NETBSD_RAWAF 0x02240000
+#define DLT_NETBSD_RAWAF(af) (DLT_CLASS_NETBSD_RAWAF | (af))
+#define DLT_NETBSD_RAWAF_AF(x) ((x) & 0x0000ffff)
+#define DLT_IS_NETBSD_RAWAF(x) (DLT_CLASS(x) == DLT_CLASS_NETBSD_RAWAF)
+
+#endif /* !defined(lib_pcap_dlt_h) */
diff --git a/lib/libpcap/libpcap/pcap/funcattrs.h b/lib/libpcap/libpcap/pcap/funcattrs.h
new file mode 100644
index 0000000..e64da93
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/funcattrs.h
@@ -0,0 +1,263 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#ifndef lib_pcap_funcattrs_h
+#define lib_pcap_funcattrs_h
+
+#include <pcap/compiler-tests.h>
+
+/*
+ * Attributes to apply to functions and their arguments, using various
+ * compiler-specific extensions.
+ */
+
+/*
+ * PCAP_API_DEF must be used when defining *data* exported from
+ * libpcap. It can be used when defining *functions* exported
+ * from libpcap, but it doesn't have to be used there. It
+ * should not be used in declarations in headers.
+ *
+ * PCAP_API must be used when *declaring* data or functions
+ * exported from libpcap; PCAP_API_DEF won't work on all platforms.
+ */
+
+#if defined(_WIN32)
+ /*
+ * For Windows:
+ *
+ * when building libpcap:
+ *
+ * if we're building it as a DLL, we have to declare API
+ * functions with __declspec(dllexport);
+ *
+ * if we're building it as a static library, we don't want
+ * to do so.
+ *
+ * when using libpcap:
+ *
+ * if we're using the DLL, calls to its functions are a
+ * little more efficient if they're declared with
+ * __declspec(dllimport);
+ *
+ * if we're not using the dll, we don't want to declare
+ * them that way.
+ *
+ * So:
+ *
+ * if pcap_EXPORTS is defined, we define PCAP_API_DEF as
+ * __declspec(dllexport);
+ *
+ * if PCAP_DLL is defined, we define PCAP_API_DEF as
+ * __declspec(dllimport);
+ *
+ * otherwise, we define PCAP_API_DEF as nothing.
+ */
+ #if defined(pcap_EXPORTS)
+ /*
+ * We're compiling libpcap as a DLL, so we should export functions
+ * in our API.
+ */
+ #define PCAP_API_DEF __declspec(dllexport)
+ #elif defined(PCAP_DLL)
+ /*
+ * We're using libpcap as a DLL, so the calls will be a little more
+ * efficient if we explicitly import the functions.
+ */
+ #define PCAP_API_DEF __declspec(dllimport)
+ #else
+ /*
+ * Either we're building libpcap as a static library, or we're using
+ * it as a static library, or we don't know for certain that we're
+ * using it as a dynamic library, so neither import nor export the
+ * functions explicitly.
+ */
+ #define PCAP_API_DEF
+ #endif
+#elif defined(MSDOS)
+ /* XXX - does this need special treatment? */
+ #define PCAP_API_DEF
+#else /* UN*X */
+ #ifdef pcap_EXPORTS
+ /*
+ * We're compiling libpcap as a (dynamic) shared library, so we should
+ * export functions in our API. The compiler might be configured not
+ * to export functions from a shared library by default, so we might
+ * have to explicitly mark functions as exported.
+ */
+ #if PCAP_IS_AT_LEAST_GNUC_VERSION(3,4) \
+ || PCAP_IS_AT_LEAST_XL_C_VERSION(12,0)
+ /*
+ * GCC 3.4 or later, or some compiler asserting compatibility with
+ * GCC 3.4 or later, or XL C 13.0 or later, so we have
+ * __attribute__((visibility()).
+ */
+ #define PCAP_API_DEF __attribute__((visibility("default")))
+ #elif PCAP_IS_AT_LEAST_SUNC_VERSION(5,5)
+ /*
+ * Sun C 5.5 or later, so we have __global.
+ * (Sun C 5.9 and later also have __attribute__((visibility()),
+ * but there's no reason to prefer it with Sun C.)
+ */
+ #define PCAP_API_DEF __global
+ #else
+ /*
+ * We don't have anything to say.
+ */
+ #define PCAP_API_DEF
+ #endif
+ #else
+ /*
+ * We're not building libpcap.
+ */
+ #define PCAP_API_DEF
+ #endif
+#endif /* _WIN32/MSDOS/UN*X */
+
+#define PCAP_API PCAP_API_DEF extern
+
+/*
+ * PCAP_NORETURN, before a function declaration, means "this function
+ * never returns". (It must go before the function declaration, e.g.
+ * "extern PCAP_NORETURN func(...)" rather than after the function
+ * declaration, as the MSVC version has to go before the declaration.)
+ *
+ * PCAP_NORETURN_DEF, before a function *definition*, means "this
+ * function never returns"; it would be used only for static functions
+ * that are defined before any use, and thus have no declaration.
+ * (MSVC doesn't support that; I guess the "decl" in "__declspec"
+ * means "declaration", and __declspec doesn't work with definitions.)
+ */
+#if __has_attribute(noreturn) \
+ || PCAP_IS_AT_LEAST_GNUC_VERSION(2,5) \
+ || PCAP_IS_AT_LEAST_SUNC_VERSION(5,9) \
+ || PCAP_IS_AT_LEAST_XL_C_VERSION(10,1) \
+ || PCAP_IS_AT_LEAST_HP_C_VERSION(6,10)
+ /*
+ * Compiler with support for __attribute((noreturn)), or GCC 2.5 or
+ * later, or some compiler asserting compatibility with GCC 2.5 or
+ * later, or Solaris Studio 12 (Sun C 5.9) or later, or IBM XL C 10.1
+ * or later (do any earlier versions of XL C support this?), or HP aCC
+ * A.06.10 or later.
+ */
+ #define PCAP_NORETURN __attribute((noreturn))
+ #define PCAP_NORETURN_DEF __attribute((noreturn))
+#elif defined(_MSC_VER)
+ /*
+ * MSVC.
+ */
+ #define PCAP_NORETURN __declspec(noreturn)
+ #define PCAP_NORETURN_DEF
+#else
+ #define PCAP_NORETURN
+ #define PCAP_NORETURN_DEF
+#endif
+
+/*
+ * PCAP_PRINTFLIKE(x,y), after a function declaration, means "this function
+ * does printf-style formatting, with the xth argument being the format
+ * string and the yth argument being the first argument for the format
+ * string".
+ */
+#if __has_attribute(__format__) \
+ || PCAP_IS_AT_LEAST_GNUC_VERSION(2,3) \
+ || PCAP_IS_AT_LEAST_XL_C_VERSION(10,1) \
+ || PCAP_IS_AT_LEAST_HP_C_VERSION(6,10)
+ /*
+ * Compiler with support for it, or GCC 2.3 or later, or some compiler
+ * asserting compatibility with GCC 2.3 or later, or IBM XL C 10.1
+ * and later (do any earlier versions of XL C support this?),
+ * or HP aCC A.06.10 and later.
+ */
+ #define PCAP_PRINTFLIKE(x,y) __attribute__((__format__(__printf__,x,y)))
+#else
+ #define PCAP_PRINTFLIKE(x,y)
+#endif
+
+/*
+ * PCAP_DEPRECATED(func, msg), after a function declaration, marks the
+ * function as deprecated.
+ *
+ * The first argument is the name of the function; the second argument is
+ * a string giving the warning message to use if the compiler supports that.
+ *
+ * (Thank you, Microsoft, for requiring the function name.)
+ */
+#if __has_attribute(deprecated) \
+ || PCAP_IS_AT_LEAST_GNUC_VERSION(4,5) \
+ || PCAP_IS_AT_LEAST_SUNC_VERSION(5,13)
+ /*
+ * Compiler that supports __has_attribute and __attribute__((deprecated)),
+ * or GCC 4.5 or later, or Sun/Oracle C 12.4 (Sun C 5.13) or later.
+ *
+ * Those support __attribute__((deprecated(msg))) (we assume, perhaps
+ * incorrectly, that anything that supports __has_attribute() is
+ * recent enough to support __attribute__((deprecated(msg)))).
+ */
+ #define PCAP_DEPRECATED(func, msg) __attribute__((deprecated(msg)))
+#elif PCAP_IS_AT_LEAST_GNUC_VERSION(3,1)
+ /*
+ * GCC 3.1 through 4.4.
+ *
+ * Those support __attribute__((deprecated)) but not
+ * __attribute__((deprecated(msg))).
+ */
+ #define PCAP_DEPRECATED(func, msg) __attribute__((deprecated))
+#elif (defined(_MSC_VER) && (_MSC_VER >= 1500)) && !defined(BUILDING_PCAP)
+ /*
+ * MSVC from Visual Studio 2008 or later, and we're not building
+ * libpcap itself.
+ *
+ * If we *are* building libpcap, we don't want this, as it'll warn
+ * us even if we *define* the function.
+ */
+ #define PCAP_DEPRECATED(func, msg) __pragma(deprecated(func))
+#else
+ #define PCAP_DEPRECATED(func, msg)
+#endif
+
+/*
+ * For flagging arguments as format strings in MSVC.
+ */
+#ifdef _MSC_VER
+ #include <sal.h>
+ #if _MSC_VER > 1400
+ #define PCAP_FORMAT_STRING(p) _Printf_format_string_ p
+ #else
+ #define PCAP_FORMAT_STRING(p) __format_string p
+ #endif
+#else
+ #define PCAP_FORMAT_STRING(p) p
+#endif
+
+#endif /* lib_pcap_funcattrs_h */
diff --git a/lib/libpcap/libpcap/pcap/ipnet.h b/lib/libpcap/libpcap/pcap/ipnet.h
new file mode 100644
index 0000000..5330847
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/ipnet.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#define IPH_AF_INET 2 /* Matches Solaris's AF_INET */
+#define IPH_AF_INET6 26 /* Matches Solaris's AF_INET6 */
+
+#define IPNET_OUTBOUND 1
+#define IPNET_INBOUND 2
diff --git a/lib/libpcap/libpcap/pcap/namedb.h b/lib/libpcap/libpcap/pcap/namedb.h
new file mode 100644
index 0000000..c66846d
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/namedb.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1994, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lib_pcap_namedb_h
+#define lib_pcap_namedb_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * As returned by the pcap_next_etherent()
+ * XXX this stuff doesn't belong in this interface, but this
+ * library already must do name to address translation, so
+ * on systems that don't have support for /etc/ethers, we
+ * export these hooks since they're already being used by
+ * some applications (such as tcpdump) and already being
+ * marked as exported in some OSes offering libpcap (such
+ * as Debian).
+ */
+struct pcap_etherent {
+ u_char addr[6];
+ char name[122];
+};
+#ifndef PCAP_ETHERS_FILE
+#define PCAP_ETHERS_FILE "/etc/ethers"
+#endif
+PCAP_API struct pcap_etherent *pcap_next_etherent(FILE *);
+PCAP_API u_char *pcap_ether_hostton(const char*);
+PCAP_API u_char *pcap_ether_aton(const char *);
+
+PCAP_API bpf_u_int32 **pcap_nametoaddr(const char *);
+PCAP_API struct addrinfo *pcap_nametoaddrinfo(const char *);
+PCAP_API bpf_u_int32 pcap_nametonetaddr(const char *);
+
+PCAP_API int pcap_nametoport(const char *, int *, int *);
+PCAP_API int pcap_nametoportrange(const char *, int *, int *, int *);
+PCAP_API int pcap_nametoproto(const char *);
+PCAP_API int pcap_nametoeproto(const char *);
+PCAP_API int pcap_nametollc(const char *);
+/*
+ * If a protocol is unknown, PROTO_UNDEF is returned.
+ * Also, pcap_nametoport() returns the protocol along with the port number.
+ * If there are ambiguous entried in /etc/services (i.e. domain
+ * can be either tcp or udp) PROTO_UNDEF is returned.
+ */
+#define PROTO_UNDEF -1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap/nflog.h b/lib/libpcap/libpcap/pcap/nflog.h
new file mode 100644
index 0000000..f7c85b5
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/nflog.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2013, Petar Alilovic,
+ * Faculty of Electrical Engineering and Computing, University of Zagreb
+ * 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 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 lib_pcap_nflog_h
+#define lib_pcap_nflog_h
+
+#include <pcap/pcap-inttypes.h>
+
+/*
+ * Structure of an NFLOG header and TLV parts, as described at
+ * https://www.tcpdump.org/linktypes/LINKTYPE_NFLOG.html
+ *
+ * The NFLOG header is big-endian.
+ *
+ * The TLV length and type are in host byte order. The value is either
+ * big-endian or is an array of bytes in some externally-specified byte
+ * order (text string, link-layer address, link-layer header, packet
+ * data, etc.).
+ */
+typedef struct nflog_hdr {
+ uint8_t nflog_family; /* address family */
+ uint8_t nflog_version; /* version */
+ uint16_t nflog_rid; /* resource ID */
+} nflog_hdr_t;
+
+typedef struct nflog_tlv {
+ uint16_t tlv_length; /* tlv length */
+ uint16_t tlv_type; /* tlv type */
+ /* value follows this */
+} nflog_tlv_t;
+
+typedef struct nflog_packet_hdr {
+ uint16_t hw_protocol; /* hw protocol */
+ uint8_t hook; /* netfilter hook */
+ uint8_t pad; /* padding to 32 bits */
+} nflog_packet_hdr_t;
+
+typedef struct nflog_hwaddr {
+ uint16_t hw_addrlen; /* address length */
+ uint16_t pad; /* padding to 32-bit boundary */
+ uint8_t hw_addr[8]; /* address, up to 8 bytes */
+} nflog_hwaddr_t;
+
+typedef struct nflog_timestamp {
+ uint64_t sec;
+ uint64_t usec;
+} nflog_timestamp_t;
+
+/*
+ * TLV types.
+ */
+#define NFULA_PACKET_HDR 1 /* nflog_packet_hdr_t */
+#define NFULA_MARK 2 /* packet mark from skbuff */
+#define NFULA_TIMESTAMP 3 /* nflog_timestamp_t for skbuff's time stamp */
+#define NFULA_IFINDEX_INDEV 4 /* ifindex of device on which packet received (possibly bridge group) */
+#define NFULA_IFINDEX_OUTDEV 5 /* ifindex of device on which packet transmitted (possibly bridge group) */
+#define NFULA_IFINDEX_PHYSINDEV 6 /* ifindex of physical device on which packet received (not bridge group) */
+#define NFULA_IFINDEX_PHYSOUTDEV 7 /* ifindex of physical device on which packet transmitted (not bridge group) */
+#define NFULA_HWADDR 8 /* nflog_hwaddr_t for hardware address */
+#define NFULA_PAYLOAD 9 /* packet payload */
+#define NFULA_PREFIX 10 /* text string - null-terminated, count includes NUL */
+#define NFULA_UID 11 /* UID owning socket on which packet was sent/received */
+#define NFULA_SEQ 12 /* sequence number of packets on this NFLOG socket */
+#define NFULA_SEQ_GLOBAL 13 /* sequence number of pakets on all NFLOG sockets */
+#define NFULA_GID 14 /* GID owning socket on which packet was sent/received */
+#define NFULA_HWTYPE 15 /* ARPHRD_ type of skbuff's device */
+#define NFULA_HWHEADER 16 /* skbuff's MAC-layer header */
+#define NFULA_HWLEN 17 /* length of skbuff's MAC-layer header */
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap/pcap-inttypes.h b/lib/libpcap/libpcap/pcap/pcap-inttypes.h
new file mode 100644
index 0000000..8b1eb8b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/pcap-inttypes.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2009 CACE Technologies, Inc. Davis (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 Politecnico di Torino nor the names 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.
+ */
+#ifndef pcap_pcap_inttypes_h
+#define pcap_pcap_inttypes_h
+
+/*
+ * Get the integer types and PRi[doux]64 values from C99 <inttypes.h>
+ * defined, by hook or by crook.
+ */
+#if defined(_MSC_VER)
+ /*
+ * Compiler is MSVC.
+ */
+ #if _MSC_VER >= 1800
+ /*
+ * VS 2013 or newer; we have <inttypes.h>.
+ */
+ #include <inttypes.h>
+ #else
+ /*
+ * Earlier VS; we have to define this stuff ourselves.
+ */
+ typedef unsigned char uint8_t;
+ typedef signed char int8_t;
+ typedef unsigned short uint16_t;
+ typedef signed short int16_t;
+ typedef unsigned int uint32_t;
+ typedef signed int int32_t;
+ #ifdef _MSC_EXTENSIONS
+ typedef unsigned _int64 uint64_t;
+ typedef _int64 int64_t;
+ #else /* _MSC_EXTENSIONS */
+ typedef unsigned long long uint64_t;
+ typedef long long int64_t;
+ #endif
+ #endif
+
+ /*
+ * These may be defined by <inttypes.h>.
+ *
+ * XXX - for MSVC, we always want the _MSC_EXTENSIONS versions.
+ * What about other compilers? If, as the MinGW Web site says MinGW
+ * does, the other compilers just use Microsoft's run-time library,
+ * then they should probably use the _MSC_EXTENSIONS even if the
+ * compiler doesn't define _MSC_EXTENSIONS.
+ *
+ * XXX - we currently aren't using any of these, but this allows
+ * their use in the future.
+ */
+ #ifndef PRId64
+ #ifdef _MSC_EXTENSIONS
+ #define PRId64 "I64d"
+ #else
+ #define PRId64 "lld"
+ #endif
+ #endif /* PRId64 */
+
+ #ifndef PRIo64
+ #ifdef _MSC_EXTENSIONS
+ #define PRIo64 "I64o"
+ #else
+ #define PRIo64 "llo"
+ #endif
+ #endif /* PRIo64 */
+
+ #ifndef PRIx64
+ #ifdef _MSC_EXTENSIONS
+ #define PRIx64 "I64x"
+ #else
+ #define PRIx64 "llx"
+ #endif
+ #endif
+
+ #ifndef PRIu64
+ #ifdef _MSC_EXTENSIONS
+ #define PRIu64 "I64u"
+ #else
+ #define PRIu64 "llu"
+ #endif
+ #endif
+
+ /*
+ * MSVC's support library doesn't support %zu to print a size_t until
+ * Visual Studio 2017, but supports %Iu earlier, so use that.
+ */
+ #define PRIsize "Iu"
+#elif defined(__MINGW32__) || !defined(_WIN32)
+ /*
+ * Compiler is MinGW or target is UN*X or MS-DOS. Just use
+ * <inttypes.h>.
+ */
+ #include <inttypes.h>
+
+ /*
+ * Assume the support library supports %zu; it's required by C99.
+ */
+ #define PRIsize "zu"
+#endif
+
+#endif /* pcap/pcap-inttypes.h */
diff --git a/lib/libpcap/libpcap/pcap/pcap-ng.h b/lib/libpcap/libpcap/pcap/pcap-ng.h
new file mode 100644
index 0000000..928b0cf
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/pcap-ng.h
@@ -0,0 +1,563 @@
+/*
+ * Copyright (c) 2012-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef libpcap_pcap_ng_h
+#define libpcap_pcap_ng_h
+
+#include <pcap/pcap.h>
+
+#ifdef PRIVATE
+
+#include <uuid/uuid.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Reference: https://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
+ */
+
+/*
+ * A useful and efficient macro to round up a number to a multiple of 4
+ */
+#define PCAPNG_ROUNDUP32(x) (((x) + 3) & ~3)
+
+/*
+ * Pcapng blocks share a similar format:
+ * - a block header composed of the block type and the block length
+ * - a set of fixed fields specific to the block type
+ * - for some block types a list of records
+ * - a list of option
+ * - a block trailer that repeats the block length
+ */
+
+/*
+ * Common part at the beginning of all blocks.
+ */
+struct pcapng_block_header {
+ bpf_u_int32 block_type;
+ bpf_u_int32 total_length;
+};
+
+/*
+ * Common trailer at the end of all blocks.
+ */
+struct pcapng_block_trailer {
+ bpf_u_int32 total_length;
+};
+
+/*
+ * Option header.
+ */
+struct pcapng_option_header {
+ u_short option_code;
+ u_short option_length; /* Actual length of option value, not rounded up */
+ /* Followed by option value that is aligned to 32 bits */
+};
+
+/*
+ * Common options that may appear within most types of blocks
+ */
+#define PCAPNG_OPT_ENDOFOPT 0 /* Zero length option to mark the end of list of options */
+#define PCAPNG_OPT_COMMENT 1 /* UTF-8 string */
+
+/*
+ * The pcap_ng_xxx_fields structures describe for each type of block
+ * the part of the block body that follows the common block header.
+ *
+ * When using the raw block APIs and format, numbers are in the byte order of the host
+ * that created the blokck.
+ *
+ * When using the high level API, numbers are in the local host byte order.
+ *
+ * Note that addresses and port are always in network byte order.
+ */
+
+/*
+ * Section Header Block.
+ */
+#define PCAPNG_BT_SHB 0x0A0D0D0A
+
+struct pcapng_section_header_fields {
+ bpf_u_int32 byte_order_magic;
+ u_short major_version;
+ u_short minor_version;
+ u_int64_t section_length; /* 0xFFFFFFFFFFFFFFFF means length not specified */
+ /* followed by options and trailer */
+};
+
+/*
+ * Byte-order magic value.
+ */
+#define PCAPNG_BYTE_ORDER_MAGIC 0x1A2B3C4D
+
+/*
+ * Current version number.
+ * If major_version isn't PCAPNG_VERSION_MAJOR,
+ * that means that this code can't read the file.
+ */
+#define PCAPNG_VERSION_MAJOR 1
+#define PCAPNG_VERSION_MINOR 0
+
+/*
+ * Option codes for Section Header Block
+ */
+#define PCAPNG_SHB_HARDWARE 0x00000002 /* UTF-8 string */
+#define PCAPNG_SHB_OS 0x00000003 /* UTF-8 string */
+#define PCAPNG_SHB_USERAPPL 0x00000004 /* UTF-8 string */
+
+/*
+ * Interface Description Block.
+ *
+ * Integer values are in the local host byte order
+ */
+#define PCAPNG_BT_IDB 0x00000001
+
+struct pcapng_interface_description_fields {
+ u_short idb_linktype;
+ u_short idb_reserved;
+ bpf_u_int32 idb_snaplen;
+ /* followed by options and trailer */
+};
+
+/*
+ * Options in the IDB.
+ */
+#define PCAPNG_IF_NAME 2 /* UTF-8 string with the interface name */
+#define PCAPNG_IF_DESCRIPTION 3 /* UTF-8 string with the interface description */
+#define PCAPNG_IF_IPV4ADDR 4 /* 8 bytes long IPv4 address and netmask (may be repeated) */
+#define PCAPNG_IF_IPV6ADDR 5 /* 17 bytes long IPv6 address and prefix length (may be repeated) */
+#define PCAPNG_IF_MACADDR 6 /* 6 bytes long interface's MAC address */
+#define PCAPNG_IF_EUIADDR 7 /* 8 bytes long interface's EUI address */
+#define PCAPNG_IF_SPEED 8 /* 64 bits number for the interface's speed, in bits/s */
+#define PCAPNG_IF_TSRESOL 9 /* 8 bits number with interface's time stamp resolution */
+#define PCAPNG_IF_TZONE 10 /* interface's time zone */
+#define PCAPNG_IF_FILTER 11 /* variable length filter used when capturing on interface */
+#define PCAPNG_IF_OS 12 /* UTF-8 string with the OS on which the interface was installed */
+#define PCAPNG_IF_FCSLEN 13 /* 8 bits number with the FCS length for this interface */
+#define PCAPNG_IF_TSOFFSET 14 /* 64 bits number offset to add to get absolute time stamps */
+
+/*
+ * The following options are experimental Apple additions
+ */
+#define PCAPNG_IF_E_IF_ID 0x8001 /* Interface index of the effective interface */
+
+/*
+ * Packet Block.
+ *
+ * This block type is obsolete and should not be used to create new capture files.
+ * Use instead Simple Packet Block or Enhanced Packet Block.
+ */
+#define PCAPNG_BT_PB 0x00000002
+
+struct pcapng_packet_fields {
+ u_short interface_id;
+ u_short drops_count;
+ bpf_u_int32 timestamp_high;
+ bpf_u_int32 timestamp_low;
+ bpf_u_int32 caplen;
+ bpf_u_int32 len;
+ /* followed by packet data, options, and trailer */
+};
+
+#define PCAPNG_PACK_FLAGS 2 /* 32 bits flags word containing link-layer information */
+#define PCAPNG_PACK_HASH 3 /* Variable length */
+
+/*
+ * Simple Packet Block.
+ */
+#define PCAPNG_BT_SPB 0x00000003
+
+struct pcapng_simple_packet_fields {
+ bpf_u_int32 len;
+ /* followed by packet data and trailer */
+};
+
+/*
+ * Name Resolution Block
+ *
+ * Block body has no fields and is made of list of name records followed by options
+ */
+#define PCAPNG_BT_NRB 0x00000004 /* Name Resolution Block */
+
+/*
+ * Record header
+ * Looks very much like an option header
+ */
+struct pcapng_record_header {
+ u_short record_type;
+ u_short record_length; /* Actual length of record value, not rounded up */
+ /* Followed by record value that is aligned to 32 bits */
+};
+
+/*
+ * Name Resolution Record
+ */
+#define PCAPNG_NRES_ENDOFRECORD 0 /* Zero length record to mark end of list of records */
+#define PCAPNG_NRES_IP4RECORD 1 /* Variable: 4 bytes IPv4 address followed by zero-terminated strings */
+#define PCAPNG_NRES_IP6RECORD 2 /* Variable: 16 bytes IPv6 address followed by zero-terminated strings */
+
+/*
+ * Options for Name Resolution Block
+ */
+#define PCAPNG_NS_DNSNAME 2 /* UTF-8 string with the name of the DNS server */
+#define PCAPNG_NS_DNSIP4ADDR 3 /* 4 bytes IPv4 address of the DNS server */
+#define PCAPNG_NS_DNSIP6ADDR 4 /* 16 bytes IPv6 address of the DNS server */
+
+
+/*
+ * Interface Statistics Block
+ */
+#define PCAPNG_BT_ISB 0x00000005
+
+struct pcapng_interface_statistics_fields {
+ u_short interface_id;
+ bpf_u_int32 timestamp_high;
+ bpf_u_int32 timestamp_low;
+};
+
+/*
+ * Options for Interface Statistics Block
+ */
+#define PCAPNG_ISB_STARTTIIME 2 /* 64 bits timestamp in same format as timestamp in packets */
+#define PCAPNG_ISB_ENDTIME 3 /* 64 bits timestamp in same format as timestamp in packets */
+#define PCAPNG_ISB_IFRECV 4 /* 64 bits number of packet received during capture */
+#define PCAPNG_ISB_IFDROP 5 /* 64 bits number of packet dropped due to lack of resources */
+#define PCAPNG_ISB_FILTERACCEPT 6 /* 64 bits number of packet accepted by filter */
+#define PCAPNG_ISB_OSDROP 7 /* 64 bits number of packet dropped by OS */
+#define PCAPNG_ISB_USRDELIV 8 /* 64 bits number of packets delivered to the user */
+
+/*
+ * Enhanced Packet Block.
+ */
+#define PCAPNG_BT_EPB 0x00000006
+
+struct pcapng_enhanced_packet_fields {
+ bpf_u_int32 interface_id;
+ bpf_u_int32 timestamp_high;
+ bpf_u_int32 timestamp_low;
+ bpf_u_int32 caplen;
+ bpf_u_int32 len;
+ /* followed by packet data, options, and trailer */
+};
+
+#define PCAPNG_EPB_FLAGS 2 /* 32 bits flags word containing link-layer information */
+#define PCAPNG_EPB_HASH 3 /* Variable length */
+#define PCAPNG_EPB_DROPCOUNT 4 /* 64 bits number of packets lost between this packet and the preceding one */
+
+/*
+ * Packet Block Flags (PCAPNG_EPB_FLAGS option)
+ */
+#define PCAPNG_PBF_DIR_MASK 0x00000003 /* Bits 0-1 Direction */
+#define PCAPNG_PBF_DIR_INBOUND 0x00000001
+#define PCAPNG_PBF_DIR_OUTBOUND 0x00000002
+
+#define PCAPNG_PBF_RT_MASK 0x0000001C /* Bits 2-4 Reception Type */
+#define PCAPNG_PBF_RT_UNICAST 0x00000004
+#define PCAPNG_PBF_RT_MULTICAST 0x00000008
+#define PCAPNG_PBF_RT_BROADCAST 0x0000000C
+#define PCAPNG_PBF_RT_PROMISC 0x00000010
+
+#define PCAPNG_PBF_FCS_LEN_MASK 0x000001E0 /* Bits 5-8 FCS length */
+#define PCAPNG_PBF_FCS_LEN_SHIFT 5
+
+#define PCAPNG_PBF_RESERVED 0x0000FE00 /* Bits 9-15 Reserved (must be zero) */
+
+#define PCAPNG_PBF_LL_SYMBOL_ERR 0x80000000 /* Bit 31 Symbol Error */
+#define PCAPNG_PBF_LL_PREAMBLE_ERR 0x40000000 /* Bit 30 Preamble Error */
+#define PCAPNG_PBF_LL_STRT_FRM_DEL_ERR 0x20000000 /* Bit 29 Start Frame Delimiter Error */
+#define PCAPNG_PBF_LL_UNALIGN_FR_ERR 0x10000000 /* Bit 28 Unaligned Frame Error */
+#define PCAPNG_PBF_LL_INTR_FR_GAP_ERR 0x08000000 /* Bit 27 wrong Inter Frame Gap error */
+#define PCAPNG_PBF_LL_PKT_TOO_SHORT_ERR 0x04000000 /* Bit 26 Packet Too Short Error */
+#define PCAPNG_PBF_LL_PKT_TOO_LONG_ERR 0x02000000 /* Bit 25 Packet Too Short Error */
+#define PCAPNG_PBF_LL_CRC_ERROR 0x01000000 /* Bit 24 CRC Error */
+
+/*
+ * Decryption Secrets Block
+ *
+ * based on: https://tools.ietf.org/html/draft-tuexen-opsawg-pcapng-01#section-4.8
+ */
+#define PCAPNG_BT_DSB 0x0000000A
+
+struct pcapng_decryption_secrets_fields {
+ bpf_u_int32 secrets_type;
+ bpf_u_int32 secrets_length; /* Nnpadded length of secrets data */
+ /* followed by secrets data, options, and trailer */
+};
+
+#define PCAPNG_DST_TLS_KEY_LOG 0x544c534b /* TLS Key Log secrets type */
+#define PCAPNG_DST_WG_KEY_LOG 0x57474b4c /* WireGuard Key Log secrets type */
+
+/*
+ * The following options are experimental Apple additions
+ */
+#define PCAPNG_EPB_PIB_INDEX 0x8001 /* 32 bits number of process information block within the section */
+#define PCAPNG_EPB_SVC 0x8002 /* 32 bits number with type of service code */
+#define PCAPNG_EPB_E_PIB_INDEX 0x8003 /* 32 bits number of the effective process information block */
+#define PCAPNG_EPB_PMD_FLAGS 0x8004 /* 32 bits flags word of packet metadata flags */
+
+/*
+ * Packet Metadata Flags (PCAPNG_EPB_PMD_FLAGS option)
+ */
+#define PCAPNG_EPB_PMDF_NEW_FLOW 0x00000001 /* New Flow */
+#define PCAPNG_EPB_PMDF_KEEP_ALIVE 0x00000002 /* Keep Alive */
+#define PCAPNG_EPB_PMDF_REXMIT 0x00000004 /* Retransmit */
+#define PCAPNG_EPB_PMDF_SOCKET 0x00000008 /* Socket */
+#define PCAPNG_EPB_PMDF_NEXUS_CHANNEL 0x00000010 /* Nexus Channel */
+
+/*
+ * Process Information Block
+ *
+ * NOTE: Experimental, this block type is not standardized
+ */
+#define PCAPNG_BT_PIB 0x80000001
+
+struct pcapng_process_information_fields {
+ bpf_u_int32 process_id; /* As reported by OS, may wrap */
+ /* followed by options and trailer */
+};
+
+#define PCAPNG_PIB_NAME 2 /* UTF-8 string with name of process */
+#define PCAPNG_PIB_PATH 3 /* UTF-8 string with path of process */
+#define PCAPNG_PIB_UUID 4 /* 16 bytes of the process UUID */
+
+/*
+ * Process Information Block
+ *
+ * NOTE: Experimental, this block type is not standardized
+ *
+ * Format simiar to simple packet block
+ */
+#define PCAPNG_BT_OSEV 0x80000002
+
+struct pcapng_os_event_fields {
+ bpf_u_int32 type;
+ bpf_u_int32 timestamp_high;
+ bpf_u_int32 timestamp_low;
+ bpf_u_int32 len;
+ /* followed by event structure (of size len), options and trailer */
+};
+
+#define PCAPNG_OSEV_KEV 0x0001
+
+/*
+ * To open for reading a file in pcap-ng file format
+ */
+pcap_t *pcap_ng_fopen_offline(FILE *, char *);
+pcap_t *pcap_ng_open_offline(const char *, char *);
+
+/*
+ * Open for writing a capture file -- a "savefile" in pcap-ng file format
+ */
+pcap_dumper_t *pcap_ng_dump_open(pcap_t *, const char *);
+pcap_dumper_t *pcap_ng_dump_fopen(pcap_t *, FILE *);
+
+/*
+ * Close a "savefile" being written to
+ */
+void pcap_ng_dump_close(pcap_dumper_t *);
+
+/*
+ * Write a packet to of a save file
+ * This assume the packet are all of the same link type
+ * pcap_ng_dump() is obsolete
+ */
+void pcap_ng_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+/*
+ * Opaque type for internalized pcap-ng blocks
+ *
+ * Internalized pcap-ng blocks provide a convenient way to
+ * read and write pcap-ng blocks by hidding most of the detail
+ * of the block format
+ */
+typedef struct pcapng_block * pcapng_block_t;
+
+/*
+ * Allocate an internalized pcap-ng block data structure.
+ * This allocate a work buffer of the given size to
+ * hold raw data block content.
+ * The size should be large enough to hold the largest
+ * expected block size.
+ * If the given size is greater than the value returned by
+ * pcap_ng_block_size_max() the allocation fails and NULL
+ * is returned.
+ */
+pcapng_block_t pcap_ng_block_alloc(size_t );
+
+/*
+ * Returns the maximum size that can be passed to pcap_ng_block_alloc().
+ */
+size_t pcap_ng_block_size_max(void);
+
+/*
+ * To intialize or reuse a existing internalized pcap-ng block.
+ * Re-using pcapng_block_t is more efficient than using
+ * pcap_ng_block_alloc() for each block.
+ */
+int pcap_ng_block_reset(pcapng_block_t, bpf_u_int32 );
+
+/*
+ * Free the memory associated internalized pcap-ng block
+ */
+void pcap_ng_free_block(pcapng_block_t);
+
+/*
+ * Write a internalized pcap-ng block into a savefile
+ */
+bpf_u_int32 pcap_ng_dump_block(pcap_dumper_t *, pcapng_block_t);
+
+/*
+ * Write a internalized pcap-ng block into a memory buffer
+ */
+bpf_u_int32 pcap_ng_externalize_block(void *, size_t, pcapng_block_t );
+
+/*
+ * To allocate or initialize a raw block read from pcap-ng file
+ */
+pcapng_block_t pcap_ng_block_alloc_with_raw_block(pcap_t *, u_char *);
+int pcap_ng_block_init_with_raw_block(pcapng_block_t block, pcap_t *p, u_char *);
+
+/*
+ * Essential accessors
+ */
+bpf_u_int32 pcap_ng_block_get_type(pcapng_block_t);
+bpf_u_int32 pcap_ng_block_get_len(pcapng_block_t);
+int pcap_ng_block_is_swapped(pcapng_block_t);
+
+/*
+ * Provide access to field of the block header in the native host byte order
+ */
+struct pcapng_section_header_fields *pcap_ng_get_section_header_fields(pcapng_block_t );
+struct pcapng_interface_description_fields *pcap_ng_get_interface_description_fields(pcapng_block_t );
+struct pcapng_enhanced_packet_fields *pcap_ng_get_enhanced_packet_fields(pcapng_block_t );
+struct pcapng_simple_packet_fields *pcap_ng_get_simple_packet_fields(pcapng_block_t );
+struct pcapng_packet_fields *pcap_ng_get_packet_fields(pcapng_block_t );
+struct pcapng_process_information_fields *pcap_ng_get_process_information_fields(pcapng_block_t );
+struct pcapng_os_event_fields *pcap_ng_get_os_event_fields(pcapng_block_t );
+struct pcapng_decryption_secrets_fields *pcap_ng_get_decryption_secrets_fields(pcapng_block_t );
+
+/*
+ * Set the packet data to the passed buffer by copying into the internal block buffer
+ */
+bpf_u_int32 pcap_ng_block_packet_copy_data(pcapng_block_t, const void *, bpf_u_int32 );
+
+/*
+ * Set the packet data by referencing an external buffer.
+ */
+bpf_u_int32 pcap_ng_block_packet_set_data(pcapng_block_t block, const void *, bpf_u_int32 );
+
+/*
+ * Return the first byte of the packet data (if any, or NULL otherwise)
+ */
+void *pcap_ng_block_packet_get_data_ptr(pcapng_block_t);
+
+/*
+ * Returns the length of the packet data
+ */
+bpf_u_int32 pcap_ng_block_packet_get_data_len(pcapng_block_t);
+
+/*
+ * Returns zero if the block does not support packet data
+ */
+int pcap_ng_block_does_support_data(pcapng_block_t);
+
+/*
+ * Add a option with the given code and value
+ */
+int pcap_ng_block_add_option_with_value(pcapng_block_t, u_short, const void *, u_short );
+int pcap_ng_block_add_option_with_string(pcapng_block_t, u_short, const char *);
+int pcap_ng_block_add_option_with_uuid(pcapng_block_t, u_short, const uuid_t);
+
+/*
+ * To access option of an internalized block
+ * The fields code and length are in the natural host byte order
+ * The value content may be byte swapped if the block was read from a savefile
+ */
+struct pcapng_option_info {
+ u_short code;
+ u_short length;
+ void *value;
+};
+
+/*
+ * Get an option of the give code
+ * This should be used for otions that may appear at most once in a block as
+ * this returns the first option with the given code
+ * Returns zero their is no option with that code in the block
+ */
+int pcap_ng_block_get_option(pcapng_block_t block, u_short code, struct pcapng_option_info *option_info);
+
+/*
+ * To walk the list of options in a block.
+ */
+typedef void (*pcapng_option_iterator_func)(pcapng_block_t ,
+ struct pcapng_option_info *,
+ void *);
+int pcnapng_block_iterate_options(pcapng_block_t block,
+ pcapng_option_iterator_func opt_iterator_func,
+ void *context);
+int pcap_ng_block_iterate_options(pcapng_block_t block,
+ pcapng_option_iterator_func opt_iterator_func,
+ void *context);
+
+/*
+ * To access name records
+ * The fields code and length are in the natural host byte order
+ */
+
+struct pcapng_name_record_info {
+ u_short code;
+ u_short length;
+ void *value;
+};
+typedef void (*pcapng_name_record_iterator_func)(pcapng_block_t ,
+ struct pcapng_name_record_info *,
+ void * );
+
+int pcnapng_block_iterate_name_records(pcapng_block_t ,
+ pcapng_name_record_iterator_func ,
+ void *);
+int pcap_ng_block_iterate_name_records(pcapng_block_t ,
+ pcapng_name_record_iterator_func ,
+ void *);
+struct in_addr;
+struct in6_addr;
+
+int pcap_ng_block_add_name_record_with_ip4(pcapng_block_t, struct in_addr *, const char **);
+int pcap_ng_block_add_name_record_with_ip6(pcapng_block_t, struct in6_addr *, const char **);
+
+/*
+ * To map between DLT and Link Type
+ */
+int dlt_to_linktype(int );
+int linktype_to_dlt(int );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PRIVATE */
+
+#endif /* libpcap_pcap_ng_h */
diff --git a/lib/libpcap/libpcap/pcap/pcap.h b/lib/libpcap/libpcap/pcap/pcap.h
new file mode 100644
index 0000000..05a552d
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/pcap.h
@@ -0,0 +1,995 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+/*
+ * Remote packet capture mechanisms and extensions from WinPcap:
+ *
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifndef lib_pcap_pcap_h
+#define lib_pcap_pcap_h
+
+#include <pcap/funcattrs.h>
+
+#include <pcap/pcap-inttypes.h>
+
+#if defined(_WIN32)
+ #include <winsock2.h> /* u_int, u_char etc. */
+ #include <io.h> /* _get_osfhandle() */
+#elif defined(MSDOS)
+ #include <sys/types.h> /* u_int, u_char etc. */
+ #include <sys/socket.h>
+#else /* UN*X */
+ #include <sys/types.h> /* u_int, u_char etc. */
+ #include <sys/time.h>
+#endif /* _WIN32/MSDOS/UN*X */
+
+#include <pcap/socket.h> /* for SOCKET, as the active-mode rpcap APIs use it */
+
+#ifndef PCAP_DONT_INCLUDE_PCAP_BPF_H
+#include <pcap/bpf.h>
+#endif
+
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Version number of the current version of the pcap file format.
+ *
+ * NOTE: this is *NOT* the version number of the libpcap library.
+ * To fetch the version information for the version of libpcap
+ * you're using, use pcap_lib_version().
+ */
+#define PCAP_VERSION_MAJOR 2
+#define PCAP_VERSION_MINOR 4
+
+#define PCAP_ERRBUF_SIZE 256
+
+/*
+ * Compatibility for systems that have a bpf.h that
+ * predates the bpf typedefs for 64-bit support.
+ */
+#if BPF_RELEASE - 0 < 199406
+typedef int bpf_int32;
+typedef u_int bpf_u_int32;
+#endif
+
+typedef struct pcap pcap_t;
+typedef struct pcap_dumper pcap_dumper_t;
+typedef struct pcap_if pcap_if_t;
+typedef struct pcap_addr pcap_addr_t;
+
+/*
+ * The first record in the file contains saved values for some
+ * of the flags used in the printout phases of tcpdump.
+ * Many fields here are 32 bit ints so compilers won't insert unwanted
+ * padding; these files need to be interchangeable across architectures.
+ *
+ * Do not change the layout of this structure, in any way (this includes
+ * changes that only affect the length of fields in this structure).
+ *
+ * Also, do not change the interpretation of any of the members of this
+ * structure, in any way (this includes using values other than
+ * LINKTYPE_ values, as defined in "savefile.c", in the "linktype"
+ * field).
+ *
+ * Instead:
+ *
+ * introduce a new structure for the new format, if the layout
+ * of the structure changed;
+ *
+ * send mail to "tcpdump-workers@lists.tcpdump.org", requesting
+ * a new magic number for your new capture file format, and, when
+ * you get the new magic number, put it in "savefile.c";
+ *
+ * use that magic number for save files with the changed file
+ * header;
+ *
+ * make the code in "savefile.c" capable of reading files with
+ * the old file header as well as files with the new file header
+ * (using the magic number to determine the header format).
+ *
+ * Then supply the changes by forking the branch at
+ *
+ * https://github.com/the-tcpdump-group/libpcap/issues
+ *
+ * and issuing a pull request, so that future versions of libpcap and
+ * programs that use it (such as tcpdump) will be able to read your new
+ * capture file format.
+ */
+struct pcap_file_header {
+ bpf_u_int32 magic;
+ u_short version_major;
+ u_short version_minor;
+ bpf_int32 thiszone; /* gmt to local correction */
+ bpf_u_int32 sigfigs; /* accuracy of timestamps */
+ bpf_u_int32 snaplen; /* max length saved portion of each pkt */
+ bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */
+};
+
+/*
+ * Macros for the value returned by pcap_datalink_ext().
+ *
+ * If LT_FCS_LENGTH_PRESENT(x) is true, the LT_FCS_LENGTH(x) macro
+ * gives the FCS length of packets in the capture.
+ */
+#define LT_FCS_LENGTH_PRESENT(x) ((x) & 0x04000000)
+#define LT_FCS_LENGTH(x) (((x) & 0xF0000000) >> 28)
+#define LT_FCS_DATALINK_EXT(x) ((((x) & 0xF) << 28) | 0x04000000)
+
+typedef enum {
+ PCAP_D_INOUT = 0,
+ PCAP_D_IN,
+ PCAP_D_OUT
+} pcap_direction_t;
+
+/*
+ * Generic per-packet information, as supplied by libpcap.
+ *
+ * The time stamp can and should be a "struct timeval", regardless of
+ * whether your system supports 32-bit tv_sec in "struct timeval",
+ * 64-bit tv_sec in "struct timeval", or both if it supports both 32-bit
+ * and 64-bit applications. The on-disk format of savefiles uses 32-bit
+ * tv_sec (and tv_usec); this structure is irrelevant to that. 32-bit
+ * and 64-bit versions of libpcap, even if they're on the same platform,
+ * should supply the appropriate version of "struct timeval", even if
+ * that's not what the underlying packet capture mechanism supplies.
+ */
+struct pcap_pkthdr {
+ struct timeval ts; /* time stamp */
+ bpf_u_int32 caplen; /* length of portion present */
+ bpf_u_int32 len; /* length this packet (off wire) */
+#ifdef __APPLE__
+ char comment[256];
+#endif
+};
+
+/*
+ * As returned by the pcap_stats()
+ */
+struct pcap_stat {
+ u_int ps_recv; /* number of packets received */
+ u_int ps_drop; /* number of packets dropped */
+ u_int ps_ifdrop; /* drops by interface -- only supported on some platforms */
+#ifdef _WIN32
+ u_int ps_capt; /* number of packets that reach the application */
+ u_int ps_sent; /* number of packets sent by the server on the network */
+ u_int ps_netdrop; /* number of packets lost on the network */
+#endif /* _WIN32 */
+};
+
+#ifdef MSDOS
+/*
+ * As returned by the pcap_stats_ex()
+ */
+struct pcap_stat_ex {
+ u_long rx_packets; /* total packets received */
+ u_long tx_packets; /* total packets transmitted */
+ u_long rx_bytes; /* total bytes received */
+ u_long tx_bytes; /* total bytes transmitted */
+ u_long rx_errors; /* bad packets received */
+ u_long tx_errors; /* packet transmit problems */
+ u_long rx_dropped; /* no space in Rx buffers */
+ u_long tx_dropped; /* no space available for Tx */
+ u_long multicast; /* multicast packets received */
+ u_long collisions;
+
+ /* detailed rx_errors: */
+ u_long rx_length_errors;
+ u_long rx_over_errors; /* receiver ring buff overflow */
+ u_long rx_crc_errors; /* recv'd pkt with crc error */
+ u_long rx_frame_errors; /* recv'd frame alignment error */
+ u_long rx_fifo_errors; /* recv'r fifo overrun */
+ u_long rx_missed_errors; /* recv'r missed packet */
+
+ /* detailed tx_errors */
+ u_long tx_aborted_errors;
+ u_long tx_carrier_errors;
+ u_long tx_fifo_errors;
+ u_long tx_heartbeat_errors;
+ u_long tx_window_errors;
+ };
+#endif
+
+/*
+ * Item in a list of interfaces.
+ */
+struct pcap_if {
+ struct pcap_if *next;
+ char *name; /* name to hand to "pcap_open_live()" */
+ char *description; /* textual description of interface, or NULL */
+ struct pcap_addr *addresses;
+ bpf_u_int32 flags; /* PCAP_IF_ interface flags */
+};
+
+#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */
+#define PCAP_IF_UP 0x00000002 /* interface is up */
+#define PCAP_IF_RUNNING 0x00000004 /* interface is running */
+#define PCAP_IF_WIRELESS 0x00000008 /* interface is wireless (*NOT* necessarily Wi-Fi!) */
+#define PCAP_IF_CONNECTION_STATUS 0x00000030 /* connection status: */
+#define PCAP_IF_CONNECTION_STATUS_UNKNOWN 0x00000000 /* unknown */
+#define PCAP_IF_CONNECTION_STATUS_CONNECTED 0x00000010 /* connected */
+#define PCAP_IF_CONNECTION_STATUS_DISCONNECTED 0x00000020 /* disconnected */
+#define PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE 0x00000030 /* not applicable */
+
+/*
+ * Representation of an interface address.
+ */
+struct pcap_addr {
+ struct pcap_addr *next;
+ struct sockaddr *addr; /* address */
+ struct sockaddr *netmask; /* netmask for that address */
+ struct sockaddr *broadaddr; /* broadcast address for that address */
+ struct sockaddr *dstaddr; /* P2P destination address for that address */
+};
+
+typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *,
+ const u_char *);
+
+/*
+ * Error codes for the pcap API.
+ * These will all be negative, so you can check for the success or
+ * failure of a call that returns these codes by checking for a
+ * negative value.
+ */
+#define PCAP_ERROR -1 /* generic error code */
+#define PCAP_ERROR_BREAK -2 /* loop terminated by pcap_breakloop */
+#define PCAP_ERROR_NOT_ACTIVATED -3 /* the capture needs to be activated */
+#define PCAP_ERROR_ACTIVATED -4 /* the operation can't be performed on already activated captures */
+#define PCAP_ERROR_NO_SUCH_DEVICE -5 /* no such device exists */
+#define PCAP_ERROR_RFMON_NOTSUP -6 /* this device doesn't support rfmon (monitor) mode */
+#define PCAP_ERROR_NOT_RFMON -7 /* operation supported only in monitor mode */
+#define PCAP_ERROR_PERM_DENIED -8 /* no permission to open the device */
+#define PCAP_ERROR_IFACE_NOT_UP -9 /* interface isn't up */
+#define PCAP_ERROR_CANTSET_TSTAMP_TYPE -10 /* this device doesn't support setting the time stamp type */
+#define PCAP_ERROR_PROMISC_PERM_DENIED -11 /* you don't have permission to capture in promiscuous mode */
+#define PCAP_ERROR_TSTAMP_PRECISION_NOTSUP -12 /* the requested time stamp precision is not supported */
+
+/*
+ * Warning codes for the pcap API.
+ * These will all be positive and non-zero, so they won't look like
+ * errors.
+ */
+#define PCAP_WARNING 1 /* generic warning code */
+#define PCAP_WARNING_PROMISC_NOTSUP 2 /* this device doesn't support promiscuous mode */
+#define PCAP_WARNING_TSTAMP_TYPE_NOTSUP 3 /* the requested time stamp type is not supported */
+
+/*
+ * Value to pass to pcap_compile() as the netmask if you don't know what
+ * the netmask is.
+ */
+#define PCAP_NETMASK_UNKNOWN 0xffffffff
+
+/*
+ * We're deprecating pcap_lookupdev() for various reasons (not
+ * thread-safe, can behave weirdly with WinPcap). Callers
+ * should use pcap_findalldevs() and use the first device.
+ */
+PCAP_API char *pcap_lookupdev(char *)
+PCAP_DEPRECATED(pcap_lookupdev, "use 'pcap_findalldevs' and use the first device");
+
+PCAP_API int pcap_lookupnet(const char *, bpf_u_int32 *, bpf_u_int32 *, char *);
+
+PCAP_API pcap_t *pcap_create(const char *, char *);
+PCAP_API int pcap_set_snaplen(pcap_t *, int);
+PCAP_API int pcap_set_promisc(pcap_t *, int);
+PCAP_API int pcap_can_set_rfmon(pcap_t *);
+PCAP_API int pcap_set_rfmon(pcap_t *, int);
+PCAP_API int pcap_set_timeout(pcap_t *, int);
+PCAP_API int pcap_set_tstamp_type(pcap_t *, int);
+PCAP_API int pcap_set_immediate_mode(pcap_t *, int);
+PCAP_API int pcap_set_buffer_size(pcap_t *, int);
+PCAP_API int pcap_set_tstamp_precision(pcap_t *, int);
+PCAP_API int pcap_get_tstamp_precision(pcap_t *);
+PCAP_API int pcap_activate(pcap_t *);
+
+#ifdef __APPLE__
+ int pcap_apple_set_exthdr(pcap_t *p, int);
+#if PRIVATE
+ /*
+ * To access DLT_PKPTAP, pcap_set_want_pktap() must be called before pcap_activate()
+ */
+ int pcap_set_want_pktap(pcap_t *, int);
+#endif /* PRIVATE */
+#endif /* __APPLE__ */
+
+PCAP_API int pcap_list_tstamp_types(pcap_t *, int **);
+PCAP_API void pcap_free_tstamp_types(int *);
+PCAP_API int pcap_tstamp_type_name_to_val(const char *);
+PCAP_API const char *pcap_tstamp_type_val_to_name(int);
+PCAP_API const char *pcap_tstamp_type_val_to_description(int);
+
+#ifdef __linux__
+PCAP_API int pcap_set_protocol_linux(pcap_t *, int);
+#endif
+
+/*
+ * Time stamp types.
+ * Not all systems and interfaces will necessarily support all of these.
+ *
+ * A system that supports PCAP_TSTAMP_HOST is offering time stamps
+ * provided by the host machine, rather than by the capture device,
+ * but not committing to any characteristics of the time stamp;
+ * it will not offer any of the PCAP_TSTAMP_HOST_ subtypes.
+ *
+ * PCAP_TSTAMP_HOST_LOWPREC is a time stamp, provided by the host machine,
+ * that's low-precision but relatively cheap to fetch; it's normally done
+ * using the system clock, so it's normally synchronized with times you'd
+ * fetch from system calls.
+ *
+ * PCAP_TSTAMP_HOST_HIPREC is a time stamp, provided by the host machine,
+ * that's high-precision; it might be more expensive to fetch. It might
+ * or might not be synchronized with the system clock, and might have
+ * problems with time stamps for packets received on different CPUs,
+ * depending on the platform.
+ *
+ * PCAP_TSTAMP_ADAPTER is a high-precision time stamp supplied by the
+ * capture device; it's synchronized with the system clock.
+ *
+ * PCAP_TSTAMP_ADAPTER_UNSYNCED is a high-precision time stamp supplied by
+ * the capture device; it's not synchronized with the system clock.
+ *
+ * Note that time stamps synchronized with the system clock can go
+ * backwards, as the system clock can go backwards. If a clock is
+ * not in sync with the system clock, that could be because the
+ * system clock isn't keeping accurate time, because the other
+ * clock isn't keeping accurate time, or both.
+ *
+ * Note that host-provided time stamps generally correspond to the
+ * time when the time-stamping code sees the packet; this could
+ * be some unknown amount of time after the first or last bit of
+ * the packet is received by the network adapter, due to batching
+ * of interrupts for packet arrival, queueing delays, etc..
+ */
+#define PCAP_TSTAMP_HOST 0 /* host-provided, unknown characteristics */
+#define PCAP_TSTAMP_HOST_LOWPREC 1 /* host-provided, low precision */
+#define PCAP_TSTAMP_HOST_HIPREC 2 /* host-provided, high precision */
+#define PCAP_TSTAMP_ADAPTER 3 /* device-provided, synced with the system clock */
+#define PCAP_TSTAMP_ADAPTER_UNSYNCED 4 /* device-provided, not synced with the system clock */
+
+/*
+ * Time stamp resolution types.
+ * Not all systems and interfaces will necessarily support all of these
+ * resolutions when doing live captures; all of them can be requested
+ * when reading a savefile.
+ */
+#define PCAP_TSTAMP_PRECISION_MICRO 0 /* use timestamps with microsecond precision, default */
+#define PCAP_TSTAMP_PRECISION_NANO 1 /* use timestamps with nanosecond precision */
+
+PCAP_API pcap_t *pcap_open_live(const char *, int, int, int, char *);
+PCAP_API pcap_t *pcap_open_dead(int, int);
+PCAP_API pcap_t *pcap_open_dead_with_tstamp_precision(int, int, u_int);
+PCAP_API pcap_t *pcap_open_offline_with_tstamp_precision(const char *, u_int, char *);
+PCAP_API pcap_t *pcap_open_offline(const char *, char *);
+#ifdef _WIN32
+ PCAP_API pcap_t *pcap_hopen_offline_with_tstamp_precision(intptr_t, u_int, char *);
+ PCAP_API pcap_t *pcap_hopen_offline(intptr_t, char *);
+ /*
+ * If we're building libpcap, these are internal routines in savefile.c,
+ * so we must not define them as macros.
+ *
+ * If we're not building libpcap, given that the version of the C runtime
+ * with which libpcap was built might be different from the version
+ * of the C runtime with which an application using libpcap was built,
+ * and that a FILE structure may differ between the two versions of the
+ * C runtime, calls to _fileno() must use the version of _fileno() in
+ * the C runtime used to open the FILE *, not the version in the C
+ * runtime with which libpcap was built. (Maybe once the Universal CRT
+ * rules the world, this will cease to be a problem.)
+ */
+ #ifndef BUILDING_PCAP
+ #define pcap_fopen_offline_with_tstamp_precision(f,p,b) \
+ pcap_hopen_offline_with_tstamp_precision(_get_osfhandle(_fileno(f)), p, b)
+ #define pcap_fopen_offline(f,b) \
+ pcap_hopen_offline(_get_osfhandle(_fileno(f)), b)
+ #endif
+#else /*_WIN32*/
+ PCAP_API pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
+ PCAP_API pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif /*_WIN32*/
+
+PCAP_API void pcap_close(pcap_t *);
+PCAP_API int pcap_loop(pcap_t *, int, pcap_handler, u_char *);
+PCAP_API int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *);
+PCAP_API const u_char *pcap_next(pcap_t *, struct pcap_pkthdr *);
+PCAP_API int pcap_next_ex(pcap_t *, struct pcap_pkthdr **, const u_char **);
+PCAP_API void pcap_breakloop(pcap_t *);
+PCAP_API int pcap_stats(pcap_t *, struct pcap_stat *);
+PCAP_API int pcap_setfilter(pcap_t *, struct bpf_program *);
+PCAP_API int pcap_setdirection(pcap_t *, pcap_direction_t);
+PCAP_API int pcap_getnonblock(pcap_t *, char *);
+PCAP_API int pcap_setnonblock(pcap_t *, int, char *);
+PCAP_API int pcap_inject(pcap_t *, const void *, size_t);
+PCAP_API int pcap_sendpacket(pcap_t *, const u_char *, int);
+PCAP_API const char *pcap_statustostr(int);
+PCAP_API const char *pcap_strerror(int);
+PCAP_API char *pcap_geterr(pcap_t *);
+PCAP_API void pcap_perror(pcap_t *, const char *);
+PCAP_API int pcap_compile(pcap_t *, struct bpf_program *, const char *, int,
+ bpf_u_int32);
+PCAP_API int pcap_compile_nopcap(int, int, struct bpf_program *,
+ const char *, int, bpf_u_int32);
+PCAP_API void pcap_freecode(struct bpf_program *);
+PCAP_API int pcap_offline_filter(const struct bpf_program *,
+ const struct pcap_pkthdr *, const u_char *);
+PCAP_API int pcap_datalink(pcap_t *);
+PCAP_API int pcap_datalink_ext(pcap_t *);
+PCAP_API int pcap_list_datalinks(pcap_t *, int **);
+PCAP_API int pcap_set_datalink(pcap_t *, int);
+PCAP_API void pcap_free_datalinks(int *);
+PCAP_API int pcap_datalink_name_to_val(const char *);
+PCAP_API const char *pcap_datalink_val_to_name(int);
+PCAP_API const char *pcap_datalink_val_to_description(int);
+PCAP_API const char *pcap_datalink_val_to_description_or_dlt(int);
+PCAP_API int pcap_snapshot(pcap_t *);
+PCAP_API int pcap_is_swapped(pcap_t *);
+PCAP_API int pcap_major_version(pcap_t *);
+PCAP_API int pcap_minor_version(pcap_t *);
+PCAP_API int pcap_bufsize(pcap_t *);
+
+/* XXX */
+PCAP_API FILE *pcap_file(pcap_t *);
+PCAP_API int pcap_fileno(pcap_t *);
+
+#ifdef _WIN32
+ PCAP_API int pcap_wsockinit(void);
+#endif
+
+PCAP_API pcap_dumper_t *pcap_dump_open(pcap_t *, const char *);
+#ifdef _WIN32
+ PCAP_API pcap_dumper_t *pcap_dump_hopen(pcap_t *, intptr_t);
+ /*
+ * If we're building libpcap, this is an internal routine in sf-pcap.c, so
+ * we must not define it as a macro.
+ *
+ * If we're not building libpcap, given that the version of the C runtime
+ * with which libpcap was built might be different from the version
+ * of the C runtime with which an application using libpcap was built,
+ * and that a FILE structure may differ between the two versions of the
+ * C runtime, calls to _fileno() must use the version of _fileno() in
+ * the C runtime used to open the FILE *, not the version in the C
+ * runtime with which libpcap was built. (Maybe once the Universal CRT
+ * rules the world, this will cease to be a problem.)
+ */
+ #ifndef BUILDING_PCAP
+ #define pcap_dump_fopen(p,f) \
+ pcap_dump_hopen(p, _get_osfhandle(_fileno(f)))
+ #endif
+#else /*_WIN32*/
+PCAP_API pcap_dumper_t *pcap_dump_fopen(pcap_t *, FILE *fp);
+#endif /*_WIN32*/
+PCAP_API pcap_dumper_t *pcap_dump_open_append(pcap_t *, const char *);
+PCAP_API FILE *pcap_dump_file(pcap_dumper_t *);
+PCAP_API long pcap_dump_ftell(pcap_dumper_t *);
+PCAP_API int64_t pcap_dump_ftell64(pcap_dumper_t *);
+PCAP_API int pcap_dump_flush(pcap_dumper_t *);
+PCAP_API void pcap_dump_close(pcap_dumper_t *);
+PCAP_API void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *);
+
+PCAP_API int pcap_findalldevs(pcap_if_t **, char *);
+PCAP_API void pcap_freealldevs(pcap_if_t *);
+
+/*
+ * We return a pointer to the version string, rather than exporting the
+ * version string directly.
+ *
+ * On at least some UNIXes, if you import data from a shared library into
+ * an program, the data is bound into the program binary, so if the string
+ * in the version of the library with which the program was linked isn't
+ * the same as the string in the version of the library with which the
+ * program is being run, various undesirable things may happen (warnings,
+ * the string being the one from the version of the library with which the
+ * program was linked, or even weirder things, such as the string being the
+ * one from the library but being truncated).
+ *
+ * On Windows, the string is constructed at run time.
+ */
+PCAP_API const char *pcap_lib_version(void);
+
+/*
+ * On at least some versions of NetBSD and QNX, we don't want to declare
+ * bpf_filter() here, as it's also be declared in <net/bpf.h>, with a
+ * different signature, but, on other BSD-flavored UN*Xes, it's not
+ * declared in <net/bpf.h>, so we *do* want to declare it here, so it's
+ * declared when we build pcap-bpf.c.
+ */
+#if !defined(__NetBSD__) && !defined(__QNX__)
+ PCAP_API u_int bpf_filter(const struct bpf_insn *, const u_char *, u_int, u_int);
+#endif
+PCAP_API int bpf_validate(const struct bpf_insn *f, int len);
+PCAP_API char *bpf_image(const struct bpf_insn *, int);
+PCAP_API void bpf_dump(const struct bpf_program *, int);
+
+#if defined(_WIN32)
+
+ /*
+ * Win32 definitions
+ */
+
+ /*!
+ \brief A queue of raw packets that will be sent to the network with pcap_sendqueue_transmit().
+ */
+ struct pcap_send_queue
+ {
+ u_int maxlen; /* Maximum size of the queue, in bytes. This
+ variable contains the size of the buffer field. */
+ u_int len; /* Current size of the queue, in bytes. */
+ char *buffer; /* Buffer containing the packets to be sent. */
+ };
+
+ typedef struct pcap_send_queue pcap_send_queue;
+
+ /*!
+ \brief This typedef is a support for the pcap_get_airpcap_handle() function
+ */
+ #if !defined(AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_)
+ #define AIRPCAP_HANDLE__EAE405F5_0171_9592_B3C2_C19EC426AD34__DEFINED_
+ typedef struct _AirpcapHandle *PAirpcapHandle;
+ #endif
+
+ PCAP_API int pcap_setbuff(pcap_t *p, int dim);
+ PCAP_API int pcap_setmode(pcap_t *p, int mode);
+ PCAP_API int pcap_setmintocopy(pcap_t *p, int size);
+
+ PCAP_API HANDLE pcap_getevent(pcap_t *p);
+
+ PCAP_API int pcap_oid_get_request(pcap_t *, bpf_u_int32, void *, size_t *);
+ PCAP_API int pcap_oid_set_request(pcap_t *, bpf_u_int32, const void *, size_t *);
+
+ PCAP_API pcap_send_queue* pcap_sendqueue_alloc(u_int memsize);
+
+ PCAP_API void pcap_sendqueue_destroy(pcap_send_queue* queue);
+
+ PCAP_API int pcap_sendqueue_queue(pcap_send_queue* queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data);
+
+ PCAP_API u_int pcap_sendqueue_transmit(pcap_t *p, pcap_send_queue* queue, int sync);
+
+ PCAP_API struct pcap_stat *pcap_stats_ex(pcap_t *p, int *pcap_stat_size);
+
+ PCAP_API int pcap_setuserbuffer(pcap_t *p, int size);
+
+ PCAP_API int pcap_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks);
+
+ PCAP_API int pcap_live_dump_ended(pcap_t *p, int sync);
+
+ PCAP_API int pcap_start_oem(char* err_str, int flags);
+
+ PCAP_API PAirpcapHandle pcap_get_airpcap_handle(pcap_t *p);
+
+ #define MODE_CAPT 0
+ #define MODE_STAT 1
+ #define MODE_MON 2
+
+#elif defined(MSDOS)
+
+ /*
+ * MS-DOS definitions
+ */
+
+ PCAP_API int pcap_stats_ex (pcap_t *, struct pcap_stat_ex *);
+ PCAP_API void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait);
+ PCAP_API u_long pcap_mac_packets (void);
+
+#else /* UN*X */
+
+ /*
+ * UN*X definitions
+ */
+
+ PCAP_API int pcap_get_selectable_fd(pcap_t *);
+ PCAP_API struct timeval *pcap_get_required_select_timeout(pcap_t *);
+
+#endif /* _WIN32/MSDOS/UN*X */
+
+#ifdef __APPLE__
+ /* Internal API. */
+ int pcap_get_selectable_fd_list(pcap_t *, int **);
+ void pcap_free_selectable_fd_list(int *);
+#endif /* __APPLE__ */
+
+/*
+ * Remote capture definitions.
+ *
+ * These routines are only present if libpcap has been configured to
+ * include remote capture support.
+ */
+
+/*
+ * The maximum buffer size in which address, port, interface names are kept.
+ *
+ * In case the adapter name or such is larger than this value, it is truncated.
+ * This is not used by the user; however it must be aware that an hostname / interface
+ * name longer than this value will be truncated.
+ */
+#define PCAP_BUF_SIZE 1024
+
+/*
+ * The type of input source, passed to pcap_open().
+ */
+#define PCAP_SRC_FILE 2 /* local savefile */
+#define PCAP_SRC_IFLOCAL 3 /* local network interface */
+#define PCAP_SRC_IFREMOTE 4 /* interface on a remote host, using RPCAP */
+
+/*
+ * The formats allowed by pcap_open() are the following:
+ * - file://path_and_filename [opens a local file]
+ * - rpcap://devicename [opens the selected device devices available on the local host, without using the RPCAP protocol]
+ * - rpcap://host/devicename [opens the selected device available on a remote host]
+ * - rpcap://host:port/devicename [opens the selected device available on a remote host, using a non-standard port for RPCAP]
+ * - adaptername [to open a local adapter; kept for compability, but it is strongly discouraged]
+ * - (NULL) [to open the first local adapter; kept for compability, but it is strongly discouraged]
+ *
+ * The formats allowed by the pcap_findalldevs_ex() are the following:
+ * - file://folder/ [lists all the files in the given folder]
+ * - rpcap:// [lists all local adapters]
+ * - rpcap://host:port/ [lists the devices available on a remote host]
+ *
+ * Referring to the 'host' and 'port' parameters, they can be either numeric or literal. Since
+ * IPv6 is fully supported, these are the allowed formats:
+ *
+ * - host (literal): e.g. host.foo.bar
+ * - host (numeric IPv4): e.g. 10.11.12.13
+ * - host (numeric IPv4, IPv6 style): e.g. [10.11.12.13]
+ * - host (numeric IPv6): e.g. [1:2:3::4]
+ * - port: can be either numeric (e.g. '80') or literal (e.g. 'http')
+ *
+ * Here you find some allowed examples:
+ * - rpcap://host.foo.bar/devicename [everything literal, no port number]
+ * - rpcap://host.foo.bar:1234/devicename [everything literal, with port number]
+ * - rpcap://10.11.12.13/devicename [IPv4 numeric, no port number]
+ * - rpcap://10.11.12.13:1234/devicename [IPv4 numeric, with port number]
+ * - rpcap://[10.11.12.13]:1234/devicename [IPv4 numeric with IPv6 format, with port number]
+ * - rpcap://[1:2:3::4]/devicename [IPv6 numeric, no port number]
+ * - rpcap://[1:2:3::4]:1234/devicename [IPv6 numeric, with port number]
+ * - rpcap://[1:2:3::4]:http/devicename [IPv6 numeric, with literal port number]
+ */
+
+/*
+ * URL schemes for capture source.
+ */
+/*
+ * This string indicates that the user wants to open a capture from a
+ * local file.
+ */
+#define PCAP_SRC_FILE_STRING "file://"
+/*
+ * This string indicates that the user wants to open a capture from a
+ * network interface. This string does not necessarily involve the use
+ * of the RPCAP protocol. If the interface required resides on the local
+ * host, the RPCAP protocol is not involved and the local functions are used.
+ */
+#define PCAP_SRC_IF_STRING "rpcap://"
+
+/*
+ * Flags to pass to pcap_open().
+ */
+
+/*
+ * Specifies whether promiscuous mode is to be used.
+ */
+#define PCAP_OPENFLAG_PROMISCUOUS 0x00000001
+
+/*
+ * Specifies, for an RPCAP capture, whether the data transfer (in
+ * case of a remote capture) has to be done with UDP protocol.
+ *
+ * If it is '1' if you want a UDP data connection, '0' if you want
+ * a TCP data connection; control connection is always TCP-based.
+ * A UDP connection is much lighter, but it does not guarantee that all
+ * the captured packets arrive to the client workstation. Moreover,
+ * it could be harmful in case of network congestion.
+ * This flag is meaningless if the source is not a remote interface.
+ * In that case, it is simply ignored.
+ */
+#define PCAP_OPENFLAG_DATATX_UDP 0x00000002
+
+/*
+ * Specifies wheether the remote probe will capture its own generated
+ * traffic.
+ *
+ * In case the remote probe uses the same interface to capture traffic
+ * and to send data back to the caller, the captured traffic includes
+ * the RPCAP traffic as well. If this flag is turned on, the RPCAP
+ * traffic is excluded from the capture, so that the trace returned
+ * back to the collector is does not include this traffic.
+ *
+ * Has no effect on local interfaces or savefiles.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_RPCAP 0x00000004
+
+/*
+ * Specifies whether the local adapter will capture its own generated traffic.
+ *
+ * This flag tells the underlying capture driver to drop the packets
+ * that were sent by itself. This is useful when building applications
+ * such as bridges that should ignore the traffic they just sent.
+ *
+ * Supported only on Windows.
+ */
+#define PCAP_OPENFLAG_NOCAPTURE_LOCAL 0x00000008
+
+/*
+ * This flag configures the adapter for maximum responsiveness.
+ *
+ * In presence of a large value for nbytes, WinPcap waits for the arrival
+ * of several packets before copying the data to the user. This guarantees
+ * a low number of system calls, i.e. lower processor usage, i.e. better
+ * performance, which is good for applications like sniffers. If the user
+ * sets the PCAP_OPENFLAG_MAX_RESPONSIVENESS flag, the capture driver will
+ * copy the packets as soon as the application is ready to receive them.
+ * This is suggested for real time applications (such as, for example,
+ * a bridge) that need the best responsiveness.
+ *
+ * The equivalent with pcap_create()/pcap_activate() is "immediate mode".
+ */
+#define PCAP_OPENFLAG_MAX_RESPONSIVENESS 0x00000010
+
+/*
+ * Remote authentication methods.
+ * These are used in the 'type' member of the pcap_rmtauth structure.
+ */
+
+/*
+ * NULL authentication.
+ *
+ * The 'NULL' authentication has to be equal to 'zero', so that old
+ * applications can just put every field of struct pcap_rmtauth to zero,
+ * and it does work.
+ */
+#define RPCAP_RMTAUTH_NULL 0
+/*
+ * Username/password authentication.
+ *
+ * With this type of authentication, the RPCAP protocol will use the username/
+ * password provided to authenticate the user on the remote machine. If the
+ * authentication is successful (and the user has the right to open network
+ * devices) the RPCAP connection will continue; otherwise it will be dropped.
+ *
+ * *******NOTE********: the username and password are sent over the network
+ * to the capture server *IN CLEAR TEXT*. Don't use this on a network
+ * that you don't completely control! (And be *really* careful in your
+ * definition of "completely"!)
+ */
+#define RPCAP_RMTAUTH_PWD 1
+
+/*
+ * This structure keeps the information needed to autheticate the user
+ * on a remote machine.
+ *
+ * The remote machine can either grant or refuse the access according
+ * to the information provided.
+ * In case the NULL authentication is required, both 'username' and
+ * 'password' can be NULL pointers.
+ *
+ * This structure is meaningless if the source is not a remote interface;
+ * in that case, the functions which requires such a structure can accept
+ * a NULL pointer as well.
+ */
+struct pcap_rmtauth
+{
+ /*
+ * \brief Type of the authentication required.
+ *
+ * In order to provide maximum flexibility, we can support different types
+ * of authentication based on the value of this 'type' variable. The currently
+ * supported authentication methods are defined into the
+ * \link remote_auth_methods Remote Authentication Methods Section\endlink.
+ */
+ int type;
+ /*
+ * \brief Zero-terminated string containing the username that has to be
+ * used on the remote machine for authentication.
+ *
+ * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+ * and it can be NULL.
+ */
+ char *username;
+ /*
+ * \brief Zero-terminated string containing the password that has to be
+ * used on the remote machine for authentication.
+ *
+ * This field is meaningless in case of the RPCAP_RMTAUTH_NULL authentication
+ * and it can be NULL.
+ */
+ char *password;
+};
+
+/*
+ * This routine can open a savefile, a local device, or a device on
+ * a remote machine running an RPCAP server.
+ *
+ * For opening a savefile, the pcap_open_offline routines can be used,
+ * and will work just as well; code using them will work on more
+ * platforms than code using pcap_open() to open savefiles.
+ *
+ * For opening a local device, pcap_open_live() can be used; it supports
+ * most of the capabilities that pcap_open() supports, and code using it
+ * will work on more platforms than code using pcap_open(). pcap_create()
+ * and pcap_activate() can also be used; they support all capabilities
+ * that pcap_open() supports, except for the Windows-only
+ * PCAP_OPENFLAG_NOCAPTURE_LOCAL, and support additional capabilities.
+ *
+ * For opening a remote capture, pcap_open() is currently the only
+ * API available.
+ */
+PCAP_API pcap_t *pcap_open(const char *source, int snaplen, int flags,
+ int read_timeout, struct pcap_rmtauth *auth, char *errbuf);
+PCAP_API int pcap_createsrcstr(char *source, int type, const char *host,
+ const char *port, const char *name, char *errbuf);
+PCAP_API int pcap_parsesrcstr(const char *source, int *type, char *host,
+ char *port, char *name, char *errbuf);
+
+/*
+ * This routine can scan a directory for savefiles, list local capture
+ * devices, or list capture devices on a remote machine running an RPCAP
+ * server.
+ *
+ * For scanning for savefiles, it can be used on both UN*X systems and
+ * Windows systems; for each directory entry it sees, it tries to open
+ * the file as a savefile using pcap_open_offline(), and only includes
+ * it in the list of files if the open succeeds, so it filters out
+ * files for which the user doesn't have read permission, as well as
+ * files that aren't valid savefiles readable by libpcap.
+ *
+ * For listing local capture devices, it's just a wrapper around
+ * pcap_findalldevs(); code using pcap_findalldevs() will work on more
+ * platforms than code using pcap_findalldevs_ex().
+ *
+ * For listing remote capture devices, pcap_findalldevs_ex() is currently
+ * the only API available.
+ */
+PCAP_API int pcap_findalldevs_ex(const char *source,
+ struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf);
+
+/*
+ * Sampling methods.
+ *
+ * These allow pcap_loop(), pcap_dispatch(), pcap_next(), and pcap_next_ex()
+ * to see only a sample of packets, rather than all packets.
+ *
+ * Currently, they work only on Windows local captures.
+ */
+
+/*
+ * Specifies that no sampling is to be done on the current capture.
+ *
+ * In this case, no sampling algorithms are applied to the current capture.
+ */
+#define PCAP_SAMP_NOSAMP 0
+
+/*
+ * Specifies that only 1 out of N packets must be returned to the user.
+ *
+ * In this case, the 'value' field of the 'pcap_samp' structure indicates the
+ * number of packets (minus 1) that must be discarded before one packet got
+ * accepted.
+ * In other words, if 'value = 10', the first packet is returned to the
+ * caller, while the following 9 are discarded.
+ */
+#define PCAP_SAMP_1_EVERY_N 1
+
+/*
+ * Specifies that we have to return 1 packet every N milliseconds.
+ *
+ * In this case, the 'value' field of the 'pcap_samp' structure indicates
+ * the 'waiting time' in milliseconds before one packet got accepted.
+ * In other words, if 'value = 10', the first packet is returned to the
+ * caller; the next returned one will be the first packet that arrives
+ * when 10ms have elapsed.
+ */
+#define PCAP_SAMP_FIRST_AFTER_N_MS 2
+
+/*
+ * This structure defines the information related to sampling.
+ *
+ * In case the sampling is requested, the capturing device should read
+ * only a subset of the packets coming from the source. The returned packets
+ * depend on the sampling parameters.
+ *
+ * WARNING: The sampling process is applied *after* the filtering process.
+ * In other words, packets are filtered first, then the sampling process
+ * selects a subset of the 'filtered' packets and it returns them to the
+ * caller.
+ */
+struct pcap_samp
+{
+ /*
+ * Method used for sampling; see above.
+ */
+ int method;
+
+ /*
+ * This value depends on the sampling method defined.
+ * For its meaning, see above.
+ */
+ int value;
+};
+
+/*
+ * New functions.
+ */
+PCAP_API struct pcap_samp *pcap_setsampling(pcap_t *p);
+
+/*
+ * RPCAP active mode.
+ */
+
+/* Maximum length of an host name (needed for the RPCAP active mode) */
+#define RPCAP_HOSTLIST_SIZE 1024
+
+PCAP_API SOCKET pcap_remoteact_accept(const char *address, const char *port,
+ const char *hostlist, char *connectinghost,
+ struct pcap_rmtauth *auth, char *errbuf);
+PCAP_API int pcap_remoteact_list(char *hostlist, char sep, int size,
+ char *errbuf);
+PCAP_API int pcap_remoteact_close(const char *host, char *errbuf);
+PCAP_API void pcap_remoteact_cleanup(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* lib_pcap_pcap_h */
diff --git a/lib/libpcap/libpcap/pcap/sll.h b/lib/libpcap/libpcap/pcap/sll.h
new file mode 100644
index 0000000..392faae
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/sll.h
@@ -0,0 +1,149 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from the Stanford/CMU enet packet filter,
+ * (net/enet.c) distributed as part of 4.3BSD, and code contributed
+ * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
+ * Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * For captures on Linux cooked sockets, we construct a fake header
+ * that includes:
+ *
+ * a 2-byte "packet type" which is one of:
+ *
+ * LINUX_SLL_HOST packet was sent to us
+ * LINUX_SLL_BROADCAST packet was broadcast
+ * LINUX_SLL_MULTICAST packet was multicast
+ * LINUX_SLL_OTHERHOST packet was sent to somebody else
+ * LINUX_SLL_OUTGOING packet was sent *by* us;
+ *
+ * a 2-byte Ethernet protocol field;
+ *
+ * a 2-byte link-layer type;
+ *
+ * a 2-byte link-layer address length;
+ *
+ * an 8-byte source link-layer address, whose actual length is
+ * specified by the previous value.
+ *
+ * All fields except for the link-layer address are in network byte order.
+ *
+ * DO NOT change the layout of this structure, or change any of the
+ * LINUX_SLL_ values below. If you must change the link-layer header
+ * for a "cooked" Linux capture, introduce a new DLT_ type (ask
+ * "tcpdump-workers@lists.tcpdump.org" for one, so that you don't give it
+ * a value that collides with a value already being used), and use the
+ * new header in captures of that type, so that programs that can
+ * handle DLT_LINUX_SLL captures will continue to handle them correctly
+ * without any change, and so that capture files with different headers
+ * can be told apart and programs that read them can dissect the
+ * packets in them.
+ */
+
+#ifndef lib_pcap_sll_h
+#define lib_pcap_sll_h
+
+#include <pcap/pcap-inttypes.h>
+
+/*
+ * A DLT_LINUX_SLL fake link-layer header.
+ */
+#define SLL_HDR_LEN 16 /* total header length */
+#define SLL_ADDRLEN 8 /* length of address field */
+
+struct sll_header {
+ uint16_t sll_pkttype; /* packet type */
+ uint16_t sll_hatype; /* link-layer address type */
+ uint16_t sll_halen; /* link-layer address length */
+ uint8_t sll_addr[SLL_ADDRLEN]; /* link-layer address */
+ uint16_t sll_protocol; /* protocol */
+};
+
+/*
+ * A DLT_LINUX_SLL2 fake link-layer header.
+ */
+#define SLL2_HDR_LEN 20 /* total header length */
+
+struct sll2_header {
+ uint16_t sll2_protocol; /* protocol */
+ uint16_t sll2_reserved_mbz; /* reserved - must be zero */
+ uint32_t sll2_if_index; /* 1-based interface index */
+ uint16_t sll2_hatype; /* link-layer address type */
+ uint8_t sll2_pkttype; /* packet type */
+ uint8_t sll2_halen; /* link-layer address length */
+ uint8_t sll2_addr[SLL_ADDRLEN]; /* link-layer address */
+};
+
+/*
+ * The LINUX_SLL_ values for "sll_pkttype" and LINUX_SLL2_ values for
+ * "sll2_pkttype"; these correspond to the PACKET_ values on Linux,
+ * which are defined by a header under include/uapi in the current
+ * kernel source, and are thus not going to change on Linux. We
+ * define them here so that they're available even on systems other
+ * than Linux.
+ */
+#define LINUX_SLL_HOST 0
+#define LINUX_SLL_BROADCAST 1
+#define LINUX_SLL_MULTICAST 2
+#define LINUX_SLL_OTHERHOST 3
+#define LINUX_SLL_OUTGOING 4
+
+/*
+ * The LINUX_SLL_ values for "sll_protocol" and LINUX_SLL2_ values for
+ * "sll2_protocol"; these correspond to the ETH_P_ values on Linux, but
+ * are defined here so that they're available even on systems other than
+ * Linux. We assume, for now, that the ETH_P_ values won't change in
+ * Linux; if they do, then:
+ *
+ * if we don't translate them in "pcap-linux.c", capture files
+ * won't necessarily be readable if captured on a system that
+ * defines ETH_P_ values that don't match these values;
+ *
+ * if we do translate them in "pcap-linux.c", that makes life
+ * unpleasant for the BPF code generator, as the values you test
+ * for in the kernel aren't the values that you test for when
+ * reading a capture file, so the fixup code run on BPF programs
+ * handed to the kernel ends up having to do more work.
+ *
+ * Add other values here as necessary, for handling packet types that
+ * might show up on non-Ethernet, non-802.x networks. (Not all the ones
+ * in the Linux "if_ether.h" will, I suspect, actually show up in
+ * captures.)
+ */
+#define LINUX_SLL_P_802_3 0x0001 /* Novell 802.3 frames without 802.2 LLC header */
+#define LINUX_SLL_P_802_2 0x0004 /* 802.2 frames (not D/I/X Ethernet) */
+#define LINUX_SLL_P_CAN 0x000C /* CAN frames, with SocketCAN pseudo-headers */
+#define LINUX_SLL_P_CANFD 0x000D /* CAN FD frames, with SocketCAN pseudo-headers */
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap/socket.h b/lib/libpcap/libpcap/pcap/socket.h
new file mode 100644
index 0000000..6f27cba
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/socket.h
@@ -0,0 +1,93 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#ifndef lib_pcap_socket_h
+#define lib_pcap_socket_h
+
+/*
+ * Some minor differences between sockets on various platforms.
+ * We include whatever sockets are needed for Internet-protocol
+ * socket access on UN*X and Windows.
+ */
+#ifdef _WIN32
+ /* Need windef.h for defines used in winsock2.h under MingW32 */
+ #ifdef __MINGW32__
+ #include <windef.h>
+ #endif
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+
+ /*
+ * Winsock doesn't have this UN*X type; it's used in the UN*X
+ * sockets API.
+ *
+ * XXX - do we need to worry about UN*Xes so old that *they*
+ * don't have it, either?
+ */
+ typedef int socklen_t;
+
+ /*
+ * Winsock doesn't have this POSIX type; it's used for the
+ * tv_usec value of struct timeval.
+ */
+ typedef long suseconds_t;
+#else /* _WIN32 */
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <netdb.h> /* for struct addrinfo/getaddrinfo() */
+ #include <netinet/in.h> /* for sockaddr_in, in BSD at least */
+ #include <arpa/inet.h>
+
+ /*!
+ * \brief In Winsock, a socket handle is of type SOCKET; in UN*X, it's
+ * a file descriptor, and therefore a signed integer.
+ * We define SOCKET to be a signed integer on UN*X, so that it can
+ * be used on both platforms.
+ */
+ #ifndef SOCKET
+ #define SOCKET int
+ #endif
+
+ /*!
+ * \brief In Winsock, the error return if socket() fails is INVALID_SOCKET;
+ * in UN*X, it's -1.
+ * We define INVALID_SOCKET to be -1 on UN*X, so that it can be used on
+ * both platforms.
+ */
+ #ifndef INVALID_SOCKET
+ #define INVALID_SOCKET -1
+ #endif
+#endif /* _WIN32 */
+
+#endif /* lib_pcap_socket_h */
diff --git a/lib/libpcap/libpcap/pcap/usb.h b/lib/libpcap/libpcap/pcap/usb.h
new file mode 100644
index 0000000..e485ec8
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/usb.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2006 Paolo Abeni (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Basic USB data struct
+ * By Paolo Abeni <paolo.abeni@email.it>
+ */
+
+#ifndef lib_pcap_usb_h
+#define lib_pcap_usb_h
+
+#include <pcap/pcap-inttypes.h>
+
+/*
+ * possible transfer mode
+ */
+#define URB_TRANSFER_IN 0x80
+#define URB_ISOCHRONOUS 0x0
+#define URB_INTERRUPT 0x1
+#define URB_CONTROL 0x2
+#define URB_BULK 0x3
+
+/*
+ * possible event type
+ */
+#define URB_SUBMIT 'S'
+#define URB_COMPLETE 'C'
+#define URB_ERROR 'E'
+
+/*
+ * USB setup header as defined in USB specification.
+ * Appears at the front of each Control S-type packet in DLT_USB captures.
+ */
+typedef struct _usb_setup {
+ uint8_t bmRequestType;
+ uint8_t bRequest;
+ uint16_t wValue;
+ uint16_t wIndex;
+ uint16_t wLength;
+} pcap_usb_setup;
+
+/*
+ * Information from the URB for Isochronous transfers.
+ */
+typedef struct _iso_rec {
+ int32_t error_count;
+ int32_t numdesc;
+} iso_rec;
+
+/*
+ * Header prepended by linux kernel to each event.
+ * Appears at the front of each packet in DLT_USB_LINUX captures.
+ */
+typedef struct _usb_header {
+ uint64_t id;
+ uint8_t event_type;
+ uint8_t transfer_type;
+ uint8_t endpoint_number;
+ uint8_t device_address;
+ uint16_t bus_id;
+ char setup_flag;/*if !=0 the urb setup header is not present*/
+ char data_flag; /*if !=0 no urb data is present*/
+ int64_t ts_sec;
+ int32_t ts_usec;
+ int32_t status;
+ uint32_t urb_len;
+ uint32_t data_len; /* amount of urb data really present in this event*/
+ pcap_usb_setup setup;
+} pcap_usb_header;
+
+/*
+ * Header prepended by linux kernel to each event for the 2.6.31
+ * and later kernels; for the 2.6.21 through 2.6.30 kernels, the
+ * "iso_rec" information, and the fields starting with "interval"
+ * are zeroed-out padding fields.
+ *
+ * Appears at the front of each packet in DLT_USB_LINUX_MMAPPED captures.
+ */
+typedef struct _usb_header_mmapped {
+ uint64_t id;
+ uint8_t event_type;
+ uint8_t transfer_type;
+ uint8_t endpoint_number;
+ uint8_t device_address;
+ uint16_t bus_id;
+ char setup_flag;/*if !=0 the urb setup header is not present*/
+ char data_flag; /*if !=0 no urb data is present*/
+ int64_t ts_sec;
+ int32_t ts_usec;
+ int32_t status;
+ uint32_t urb_len;
+ uint32_t data_len; /* amount of urb data really present in this event*/
+ union {
+ pcap_usb_setup setup;
+ iso_rec iso;
+ } s;
+ int32_t interval; /* for Interrupt and Isochronous events */
+ int32_t start_frame; /* for Isochronous events */
+ uint32_t xfer_flags; /* copy of URB's transfer flags */
+ uint32_t ndesc; /* number of isochronous descriptors */
+} pcap_usb_header_mmapped;
+
+/*
+ * Isochronous descriptors; for isochronous transfers there might be
+ * one or more of these at the beginning of the packet data. The
+ * number of descriptors is given by the "ndesc" field in the header;
+ * as indicated, in older kernels that don't put the descriptors at
+ * the beginning of the packet, that field is zeroed out, so that field
+ * can be trusted even in captures from older kernels.
+ */
+typedef struct _usb_isodesc {
+ int32_t status;
+ uint32_t offset;
+ uint32_t len;
+ uint8_t pad[4];
+} usb_isodesc;
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap/vlan.h b/lib/libpcap/libpcap/pcap/vlan.h
new file mode 100644
index 0000000..b29dd73
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap/vlan.h
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 lib_pcap_vlan_h
+#define lib_pcap_vlan_h
+
+#include <pcap/pcap-inttypes.h>
+
+struct vlan_tag {
+ uint16_t vlan_tpid; /* ETH_P_8021Q */
+ uint16_t vlan_tci; /* VLAN TCI */
+};
+
+#define VLAN_TAG_LEN 4
+
+#endif
diff --git a/lib/libpcap/libpcap/pcap_activate.3pcap b/lib/libpcap/libpcap/pcap_activate.3pcap
new file mode 100644
index 0000000..162a929
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_activate.3pcap
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_ACTIVATE 3PCAP "31 July 2016"
+.SH NAME
+pcap_activate \- activate a capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_activate(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_activate()
+is used to activate a packet capture handle to look
+at packets on the network, with the options that were set on the handle
+being in effect.
+.SH RETURN VALUE
+.B pcap_activate()
+returns 0 on success without warnings, a non-zero positive value on
+success with warnings, and a negative value on error.
+A non-zero return value indicates what warning or error condition
+occurred.
+.LP
+The possible warning values are:
+.TP
+.B PCAP_WARNING_PROMISC_NOTSUP
+Promiscuous mode was requested, but the capture source doesn't support
+promiscuous mode.
+.TP
+.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
+The time stamp type specified in a previous
+.B pcap_set_tstamp_type(3PCAP)
+call isn't supported by the capture source (the time stamp type is
+left as the default),
+.TP
+.B PCAP_WARNING
+Another warning condition occurred;
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display a message describing the warning
+condition.
+.LP
+The possible error values are:
+.TP
+.B PCAP_ERROR_ACTIVATED
+The handle has already been activated.
+.TP
+.B PCAP_ERROR_NO_SUCH_DEVICE
+The capture source specified when the handle was created doesn't
+exist.
+.TP
+.B PCAP_ERROR_PERM_DENIED
+The process doesn't have permission to open the capture source.
+.TP
+.B PCAP_ERROR_PROMISC_PERM_DENIED
+The process has permission to open the capture source but doesn't
+have permission to put it into promiscuous mode.
+.TP
+.B PCAP_ERROR_RFMON_NOTSUP
+Monitor mode was specified but the capture source doesn't support
+monitor mode.
+.TP
+.B PCAP_ERROR_IFACE_NOT_UP
+The capture source device is not up.
+.TP
+.B PCAP_ERROR
+Another error occurred.
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display a message describing the error.
+.LP
+If
+.BR PCAP_WARNING_PROMISC_NOTSUP ,
+.BR PCAP_ERROR_NO_SUCH_DEVICE ,
+or
+.B PCAP_ERROR_PERM_DENIED
+is returned,
+.B pcap_geterr()
+or
+.B pcap_perror()
+may be called with
+.I p
+as an argument to fetch or display an message giving additional details
+about the problem that might be useful for debugging the problem if it's
+unexpected.
+.LP
+Additional warning and error codes may be added in the future; a program
+should check for positive, negative, and zero return codes, and treat
+all positive return codes as warnings and all negative return
+codes as errors.
+.B pcap_statustostr(3PCAP)
+can be called, with a warning or error code as an argument, to fetch a
+message describing the warning or error code.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_breakloop.3pcap b/lib/libpcap/libpcap/pcap_breakloop.3pcap
new file mode 100644
index 0000000..cc000d2
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_breakloop.3pcap
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_BREAKLOOP 3PCAP "25 July 2018"
+.SH NAME
+pcap_breakloop \- force a pcap_dispatch() or pcap_loop() call to return
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_breakloop(pcap_t *);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_breakloop()
+sets a flag that will force
+.B pcap_dispatch(3PCAP)
+or
+.B pcap_loop(3PCAP)
+to return rather than looping; they will return the number of packets
+that have been processed so far, or
+.B PCAP_ERROR_BREAK
+if no packets have been processed so far.
+.PP
+This routine is safe to use inside a signal handler on UNIX or a console
+control handler on Windows, as it merely sets a flag that is checked
+within the loop.
+.PP
+The flag is checked in loops reading packets from the OS - a signal by
+itself will not necessarily terminate those loops - as well as in loops
+processing a set of packets returned by the OS.
+.ft B
+Note that if you are catching signals on UNIX systems that support
+restarting system calls after a signal, and calling pcap_breakloop()
+in the signal handler, you must specify, when catching those signals,
+that system calls should NOT be restarted by that signal. Otherwise,
+if the signal interrupted a call reading packets in a live capture,
+when your signal handler returns after calling pcap_breakloop(), the
+call will be restarted, and the loop will not terminate until more
+packets arrive and the call completes.
+.ft R
+.PP
+.ft B
+Note also that, in a multi-threaded application, if one thread is
+blocked in pcap_dispatch(), pcap_loop(), pcap_next(3PCAP), or pcap_next_ex(3PCAP),
+a call to pcap_breakloop() in a different thread will not unblock that
+thread.
+.ft R
+You will need to use whatever mechanism the OS provides for
+breaking a thread out of blocking calls in order to unblock the thread,
+such as thread cancellation or thread signalling in systems that support
+POSIX threads, or
+.B SetEvent()
+on the result of
+.B pcap_getevent()
+on a
+.B pcap_t
+on which the thread is blocked on Windows. Asynchronous procedure calls
+will not work on Windows, as a thread blocked on a
+.B pcap_t
+will not be in an alertable state.
+.ft R
+.PP
+Note that
+.B pcap_next()
+and
+.B pcap_next_ex()
+will, on some platforms, loop reading packets from the OS; that loop
+will not necessarily be terminated by a signal, so
+.B pcap_breakloop()
+should be used to terminate packet processing even if
+.B pcap_next()
+or
+.B pcap_next_ex()
+is being used.
+.PP
+.B pcap_breakloop()
+does not guarantee that no further packets will be processed by
+.B pcap_dispatch()
+or
+.B pcap_loop()
+after it is called; at most one more packet might be processed.
+.PP
+If
+.B PCAP_ERROR_BREAK
+is returned from
+.B pcap_dispatch()
+or
+.BR pcap_loop() ,
+the flag is cleared, so a subsequent call will resume reading packets.
+If a positive number is returned, the flag is not cleared, so a
+subsequent call will return
+.B PCAP_ERROR_BREAK
+and clear the flag.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_can_set_rfmon.3pcap b/lib/libpcap/libpcap/pcap_can_set_rfmon.3pcap
new file mode 100644
index 0000000..0baac7a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_can_set_rfmon.3pcap
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CAN_SET_RFMON 3PCAP "31 July 2016"
+.SH NAME
+pcap_can_set_rfmon \- check whether monitor mode can be set for a
+not-yet-activated capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_can_set_rfmon(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_can_set_rfmon()
+checks whether monitor mode could be set on a capture handle when
+the handle is activated.
+.SH RETURN VALUE
+.B pcap_can_set_rfmon()
+returns 0 if monitor mode could not be set,
+1 if monitor mode could be set, and a negative value on error.
+A negative return value indicates what error condition occurred.
+The possible error values are:
+.TP
+.B PCAP_ERROR_NO_SUCH_DEVICE
+The capture source specified when the handle was created doesn't
+exist.
+.TP
+.B PCAP_ERROR_PERM_DENIED
+The process doesn't have permission to check whether monitor mode
+could be supported.
+.TP
+.B PCAP_ERROR_ACTIVATED
+The capture handle has already been activated.
+.TP
+.B PCAP_ERROR
+Another error occurred.
+.B pcap_geterr(3PCAP)
+or
+.B \%pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display a message describing the error.
+.LP
+Additional error codes may be added in the future; a program should
+check for 0, 1, and negative, return codes, and treat all negative
+return codes as errors.
+.B pcap_statustostr(3PCAP)
+can be called, with a warning or error code as an argument, to fetch a
+message describing the warning or error code.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_set_rfmon(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_close.3pcap b/lib/libpcap/libpcap/pcap_close.3pcap
new file mode 100644
index 0000000..e2316a4
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_close.3pcap
@@ -0,0 +1,39 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CLOSE 3PCAP "3 January 2014"
+.SH NAME
+pcap_close \- close a capture device or savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_close(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_close()
+closes the files associated with
+.I p
+and deallocates resources.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_compile.3pcap b/lib/libpcap/libpcap/pcap_compile.3pcap
new file mode 100644
index 0000000..1f1e44e
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_compile.3pcap
@@ -0,0 +1,89 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_COMPILE 3PCAP "22 August 2018"
+.SH NAME
+pcap_compile \- compile a filter expression
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_compile(pcap_t *p, struct bpf_program *fp,
+.ti +8
+const char *str, int optimize, bpf_u_int32 netmask);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_compile()
+is used to compile the string
+.I str
+into a filter program. See
+.BR pcap-filter (7)
+for the syntax of that string.
+.I program
+is a pointer to a
+.I bpf_program
+struct and is filled in by
+.BR pcap_compile() .
+.I optimize
+controls whether optimization on the resulting code is performed.
+.I netmask
+specifies the IPv4 netmask of the network on which packets are being
+captured; it is used only when checking for IPv4 broadcast addresses in
+the filter program. If the netmask of the network on which packets are
+being captured isn't known to the program, or if packets are being
+captured on the Linux "any" pseudo-interface that can capture on more
+than one network, a value of
+.B PCAP_NETMASK_UNKNOWN
+can be supplied; tests
+for IPv4 broadcast addresses will fail to compile, but all other tests in
+the filter program will be OK.
+.LP
+NOTE: in libpcap 1.8.0 and later,
+.B pcap_compile()
+can be used in multiple threads within a single process. However, in
+earlier versions of libpcap, it is
+.I not
+safe to use
+.B pcap_compile()
+in multiple threads in a single process without some form of mutual
+exclusion allowing only one thread to call it at any given time.
+.SH RETURN VALUE
+.B pcap_compile()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B PCAP_NETMASK_UNKNOWN
+constant became available in libpcap release 1.1.0.
+.SH SEE ALSO
+pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
diff --git a/lib/libpcap/libpcap/pcap_compile.3pcap.in b/lib/libpcap/libpcap/pcap_compile.3pcap.in
new file mode 100644
index 0000000..824f52b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_compile.3pcap.in
@@ -0,0 +1,89 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_COMPILE 3PCAP "22 August 2018"
+.SH NAME
+pcap_compile \- compile a filter expression
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_compile(pcap_t *p, struct bpf_program *fp,
+.ti +8
+const char *str, int optimize, bpf_u_int32 netmask);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_compile()
+is used to compile the string
+.I str
+into a filter program. See
+.BR pcap-filter (@MAN_MISC_INFO@)
+for the syntax of that string.
+.I program
+is a pointer to a
+.I bpf_program
+struct and is filled in by
+.BR pcap_compile() .
+.I optimize
+controls whether optimization on the resulting code is performed.
+.I netmask
+specifies the IPv4 netmask of the network on which packets are being
+captured; it is used only when checking for IPv4 broadcast addresses in
+the filter program. If the netmask of the network on which packets are
+being captured isn't known to the program, or if packets are being
+captured on the Linux "any" pseudo-interface that can capture on more
+than one network, a value of
+.B PCAP_NETMASK_UNKNOWN
+can be supplied; tests
+for IPv4 broadcast addresses will fail to compile, but all other tests in
+the filter program will be OK.
+.LP
+NOTE: in libpcap 1.8.0 and later,
+.B pcap_compile()
+can be used in multiple threads within a single process. However, in
+earlier versions of libpcap, it is
+.I not
+safe to use
+.B pcap_compile()
+in multiple threads in a single process without some form of mutual
+exclusion allowing only one thread to call it at any given time.
+.SH RETURN VALUE
+.B pcap_compile()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B PCAP_NETMASK_UNKNOWN
+constant became available in libpcap release 1.1.0.
+.SH SEE ALSO
+pcap(3PCAP), pcap_setfilter(3PCAP), pcap_freecode(3PCAP),
diff --git a/lib/libpcap/libpcap/pcap_create.3pcap b/lib/libpcap/libpcap/pcap_create.3pcap
new file mode 100644
index 0000000..5a15007
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_create.3pcap
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_CREATE 3PCAP "3 January 2014"
+.SH NAME
+pcap_create \- create a live capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_create(const char *source, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_create()
+is used to create a packet capture handle to look
+at packets on the network.
+.I source
+is a string that specifies the network device to open; on Linux systems
+with 2.2 or later kernels, a
+.I source
+argument of "any" or
+.B NULL
+can be used to capture packets from all interfaces.
+.PP
+The returned handle must be activated with
+.B pcap_activate(3PCAP)
+before packets can be captured
+with it; options for the capture, such as promiscuous mode, can be set
+on the handle before activating it.
+.SH RETURN VALUE
+.B pcap_create()
+returns a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_datalink.3pcap b/lib/libpcap/libpcap/pcap_datalink.3pcap
new file mode 100644
index 0000000..9e8477e
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_datalink.3pcap
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK 3PCAP "7 April 2014"
+.SH NAME
+pcap_datalink \- get the link-layer header type
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink()
+returns the link-layer header type for the live capture or ``savefile''
+specified by
+.IR p .
+.PP
+It must not be called on a pcap descriptor created by
+.B \%pcap_create(3PCAP)
+that has not yet been activated by
+.BR \%pcap_activate(3PCAP) .
+.PP
+.I https://www.tcpdump.org/linktypes.html
+lists the values
+.B pcap_datalink()
+can return and describes the packet formats that
+correspond to those values.
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet. For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.SH RETURN VALUE
+.B pcap_datalink()
+returns the link-layer header type on success and
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(7)
diff --git a/lib/libpcap/libpcap/pcap_datalink.3pcap.in b/lib/libpcap/libpcap/pcap_datalink.3pcap.in
new file mode 100644
index 0000000..2620368
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_datalink.3pcap.in
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK 3PCAP "7 April 2014"
+.SH NAME
+pcap_datalink \- get the link-layer header type
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink()
+returns the link-layer header type for the live capture or ``savefile''
+specified by
+.IR p .
+.PP
+It must not be called on a pcap descriptor created by
+.B \%pcap_create(3PCAP)
+that has not yet been activated by
+.BR \%pcap_activate(3PCAP) .
+.PP
+.I https://www.tcpdump.org/linktypes.html
+lists the values
+.B pcap_datalink()
+can return and describes the packet formats that
+correspond to those values.
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet. For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.SH RETURN VALUE
+.B pcap_datalink()
+returns the link-layer header type on success and
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap-linktype(@MAN_MISC_INFO@)
diff --git a/lib/libpcap/libpcap/pcap_datalink_name_to_val.3pcap b/lib/libpcap/libpcap/pcap_datalink_name_to_val.3pcap
new file mode 100644
index 0000000..dd4688f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_datalink_name_to_val.3pcap
@@ -0,0 +1,49 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK_NAME_TO_VAL 3PCAP "25 July 2018"
+.SH NAME
+pcap_datalink_name_to_val \- get the link-layer header type value
+corresponding to a header type name
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_datalink_name_to_val(const char *name);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink_name_to_val()
+translates a link-layer header type name, which is a
+.B DLT_
+name with the
+.B DLT_
+removed, to the corresponding link-layer header type value. The
+translation is case-insensitive.
+.SH RETURN VALUE
+.B pcap_datalink_name_to_val()
+returns the type value on success and
+.B PCAP_ERROR
+if the name is not a known
+type name..
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_datalink_val_to_name.3pcap b/lib/libpcap/libpcap/pcap_datalink_val_to_name.3pcap
new file mode 100644
index 0000000..f42165f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_datalink_val_to_name.3pcap
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DATALINK_VAL_TO_NAME 3PCAP "12 October 2016"
+.SH NAME
+pcap_datalink_val_to_name, pcap_datalink_val_to_description,
+pcap_datalink_val_to_description_or_dlt \- get a
+name or description for a link-layer header type value
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_datalink_val_to_name(int dlt);
+const char *pcap_datalink_val_to_description(int dlt);
+const char *pcap_datalink_val_to_description_or_dlt(int dlt);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_datalink_val_to_name()
+translates a link-layer header type value to the corresponding
+link-layer header type name, which is the
+.B DLT_
+name for the link-layer header type value with the
+.B DLT_
+removed.
+.B NULL
+is returned if the type value does not correspond to a known
+.B DLT_
+value.
+.PP
+.B pcap_datalink_val_to_description()
+translates a link-layer header type value to a short description of that
+link-layer header type.
+.B NULL
+is returned if the type value does not correspond to a known
+.B DLT_
+value.
+.PP
+.B pcap_datalink_val_to_description_or_dlt()
+translates a link-layer header type value to a short description of that
+link-layer header type just like pcap_datalink_val_to_description.
+If the type value does not correspond to a known
+.B DLT_
+value, the string "DLT n" is returned, where n is the value of
+the dlt argument.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_dump.3pcap b/lib/libpcap/libpcap/pcap_dump.3pcap
new file mode 100644
index 0000000..7f201b7
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_dump.3pcap
@@ -0,0 +1,50 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP 3PCAP "8 March 2015"
+.SH NAME
+pcap_dump \- write a packet to a capture file
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_dump(u_char *user, struct pcap_pkthdr *h,
+.ti +8
+u_char *sp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump()
+outputs a packet to the ``savefile'' opened with
+.BR pcap_dump_open(3PCAP) .
+Note that its calling arguments are suitable for use with
+.B pcap_dispatch(3PCAP)
+or
+.BR pcap_loop(3PCAP) .
+If called directly, the
+.I user
+parameter is of type
+.B pcap_dumper_t
+as returned by
+.BR pcap_dump_open() .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_dump_close.3pcap b/lib/libpcap/libpcap/pcap_dump_close.3pcap
new file mode 100644
index 0000000..bd95a52
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_dump_close.3pcap
@@ -0,0 +1,37 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_CLOSE 3PCAP "3 January 2014"
+.SH NAME
+pcap_dump_close \- close a savefile being written to
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_dump_close(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_close()
+closes the ``savefile.''
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP), pcap_dump(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_dump_file.3pcap b/lib/libpcap/libpcap/pcap_dump_file.3pcap
new file mode 100644
index 0000000..d207431
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_dump_file.3pcap
@@ -0,0 +1,38 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FILE 3PCAP "3 January 2014"
+.SH NAME
+pcap_dump_file \- get the standard I/O stream for a savefile being written
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+FILE *pcap_dump_file(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_file()
+returns the standard I/O stream of the ``savefile'' opened by
+.BR pcap_dump_open(3PCAP) .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_dump_flush.3pcap b/lib/libpcap/libpcap/pcap_dump_flush.3pcap
new file mode 100644
index 0000000..5d17474
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_dump_flush.3pcap
@@ -0,0 +1,45 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FLUSH 3PCAP "25 July 2018"
+.SH NAME
+pcap_dump_flush \- flush to a savefile packets dumped
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_dump_flush(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_flush()
+flushes the output buffer to the ``savefile,'' so that any packets
+written with
+.B pcap_dump(3PCAP)
+but not yet written to the ``savefile'' will be written.
+.SH RETURN VALUE
+.B pcap_dump_flush()
+returns 0 on success and
+.B PCAP_ERROR
+on failure.
+.SH SEE ALSO
+pcap(3PCAP), pcap_dump_open(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_dump_ftell.3pcap b/lib/libpcap/libpcap/pcap_dump_ftell.3pcap
new file mode 100644
index 0000000..20cb995
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_dump_ftell.3pcap
@@ -0,0 +1,58 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_FTELL 3PCAP "25 July 2018"
+.SH NAME
+pcap_dump_ftell, pcap_dump_ftell64 \- get the current file offset for a savefile being written
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+long pcap_dump_ftell(pcap_dumper_t *p);
+.ft B
+int64_t pcap_dump_ftell64(pcap_dumper_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_ftell()
+returns the current file position for the ``savefile'', representing the
+number of bytes written by
+.B pcap_dump_open(3PCAP)
+and
+.BR pcap_dump(3PCAP) .
+.B PCAP_ERROR
+is returned on error. If the current file position does not fit in a
+.BR long ,
+it will be truncated; this can happen on 32-bit UNIX-like systems with
+large file support and on Windows.
+.B pcap_dump_ftell64()
+returns the current file position in a
+.BR int64_t ,
+so if file offsets that don't fit in a
+.B long
+but that fit in a
+.B int64_t
+are supported, this will return the file offset without truncation.
+.B PCAP_ERROR
+is returned on error.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_dump_open.3pcap b/lib/libpcap/libpcap/pcap_dump_open.3pcap
new file mode 100644
index 0000000..67e7715
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_dump_open.3pcap
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_OPEN 3PCAP "22 August 2018"
+.SH NAME
+pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.nf
+.LP
+.ft B
+pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_open_append(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_open()
+is called to open a ``savefile'' for writing.
+.I fname
+specifies the name of the file to open. The file will have
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" is a synonym
+for
+.BR stdout .
+.PP
+.B pcap_dump_fopen()
+is called to write data to an existing open stream
+.IR fp ;
+this stream will be closed by a subsequent call to
+.BR pcap_dump_close(3PCAP) .
+Note that on Windows, that stream should be opened in binary mode.
+.PP
+.I p
+is a capture or ``savefile'' handle returned by an earlier call to
+.B pcap_create(3PCAP)
+and activated by an earlier call to
+.BR \%pcap_activate(3PCAP) ,
+or returned by an earlier call to
+.BR \%pcap_open_offline(3PCAP) ,
+.BR pcap_open_live(3PCAP) ,
+or
+.BR pcap_open_dead(3PCAP) .
+The time stamp precision, link-layer type, and snapshot length from
+.I p
+are used as the link-layer type and snapshot length of the output file.
+.PP
+.B pcap_dump_open_append()
+is like
+.B pcap_dump_open()
+but does not create the file if it does not exist and, if it does
+already exist, and is a pcap file with the same byte order as the host
+opening the file, and has the same time stamp precision, link-layer
+header type, and snapshot length as
+.IR p ,
+it will write new packets at the end of the file.
+.SH RETURN VALUES
+A pointer to a
+.B pcap_dumper_t
+structure to use in subsequent
+.B pcap_dump(3PCAP)
+and
+.B pcap_dump_close(3PCAP)
+calls is returned on success.
+.B NULL
+is returned on failure.
+If
+.B NULL
+is returned,
+.B pcap_geterr(3PCAP)
+can be used to get the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B pcap_dump_open_append()
+function became available in libpcap release 1.7.2. In previous
+releases, there is no support for appending packets to an existing
+savefile.
+.SH SEE ALSO
+pcap(3PCAP),
+\%pcap-savefile(5)
diff --git a/lib/libpcap/libpcap/pcap_dump_open.3pcap.in b/lib/libpcap/libpcap/pcap_dump_open.3pcap.in
new file mode 100644
index 0000000..b86696f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_dump_open.3pcap.in
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_DUMP_OPEN 3PCAP "22 August 2018"
+.SH NAME
+pcap_dump_open, pcap_dump_fopen \- open a file to which to write packets
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.nf
+.LP
+.ft B
+pcap_dumper_t *pcap_dump_open(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_open_append(pcap_t *p, const char *fname);
+pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_dump_open()
+is called to open a ``savefile'' for writing.
+.I fname
+specifies the name of the file to open. The file will have
+the same format as those used by
+.BR tcpdump (1)
+and
+.BR tcpslice (1).
+The name "-" is a synonym
+for
+.BR stdout .
+.PP
+.B pcap_dump_fopen()
+is called to write data to an existing open stream
+.IR fp ;
+this stream will be closed by a subsequent call to
+.BR pcap_dump_close(3PCAP) .
+Note that on Windows, that stream should be opened in binary mode.
+.PP
+.I p
+is a capture or ``savefile'' handle returned by an earlier call to
+.B pcap_create(3PCAP)
+and activated by an earlier call to
+.BR \%pcap_activate(3PCAP) ,
+or returned by an earlier call to
+.BR \%pcap_open_offline(3PCAP) ,
+.BR pcap_open_live(3PCAP) ,
+or
+.BR pcap_open_dead(3PCAP) .
+The time stamp precision, link-layer type, and snapshot length from
+.I p
+are used as the link-layer type and snapshot length of the output file.
+.PP
+.B pcap_dump_open_append()
+is like
+.B pcap_dump_open()
+but does not create the file if it does not exist and, if it does
+already exist, and is a pcap file with the same byte order as the host
+opening the file, and has the same time stamp precision, link-layer
+header type, and snapshot length as
+.IR p ,
+it will write new packets at the end of the file.
+.SH RETURN VALUES
+A pointer to a
+.B pcap_dumper_t
+structure to use in subsequent
+.B pcap_dump(3PCAP)
+and
+.B pcap_dump_close(3PCAP)
+calls is returned on success.
+.B NULL
+is returned on failure.
+If
+.B NULL
+is returned,
+.B pcap_geterr(3PCAP)
+can be used to get the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B pcap_dump_open_append()
+function became available in libpcap release 1.7.2. In previous
+releases, there is no support for appending packets to an existing
+savefile.
+.SH SEE ALSO
+pcap(3PCAP),
+\%pcap-savefile(@MAN_FILE_FORMATS@)
diff --git a/lib/libpcap/libpcap/pcap_file.3pcap b/lib/libpcap/libpcap/pcap_file.3pcap
new file mode 100644
index 0000000..981451b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_file.3pcap
@@ -0,0 +1,59 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FILE 3PCAP "3 January 2014"
+.SH NAME
+pcap_file \- get the standard I/O stream for a savefile being read
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+FILE *pcap_file(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_file()
+returns the standard I/O stream of the ``savefile,'' if a ``savefile''
+was opened with
+.BR pcap_open_offline(3PCAP) ,
+or
+.BR NULL ,
+if a network device was opened with
+.B pcap_create(3PCAP)
+and
+.BR \%pcap_activate(3PCAP) ,
+or with
+.BR pcap_open_live(3PCAP) .
+.PP
+Note that the Packet Capture library is usually built with large file
+support, so the standard I/O stream of the ``savefile'' might refer to
+a file larger than 2 gigabytes; applications that use
+.B pcap_file()
+should, if possible, use calls that support large files on the return
+value of
+.B pcap_file()
+or the value returned by
+.B fileno(3)
+when passed the return value of
+.BR pcap_file() .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_fileno.3pcap b/lib/libpcap/libpcap/pcap_fileno.3pcap
new file mode 100644
index 0000000..60ac129
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_fileno.3pcap
@@ -0,0 +1,65 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FILENO 3PCAP "25 July 2018"
+.SH NAME
+pcap_fileno \- get the file descriptor for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_fileno(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+If
+.I p
+refers to a network device that was opened for a live capture using
+a combination of
+.B pcap_create(3PCAP)
+and
+.BR pcap_activate(3PCAP) ,
+or using
+.BR pcap_open_live(3PCAP) ,
+.B pcap_fileno()
+returns the file descriptor from which captured packets are read.
+.LP
+If
+.I p
+refers to a ``savefile'' that was opened using functions such as
+.BR pcap_open_offline(3PCAP)
+or
+.BR pcap_fopen_offline(3PCAP) ,
+a ``dead''
+.B pcap_t
+opened using
+.BR pcap_open_dead(3PCAP) ,
+or a
+.B pcap_t
+that was created with
+.B pcap_create()
+but that has not yet been activated with
+.BR pcap_activate() ,
+it returns
+.BR PCAP_ERROR .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_findalldevs.3pcap b/lib/libpcap/libpcap/pcap_findalldevs.3pcap
new file mode 100644
index 0000000..712e255
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_findalldevs.3pcap
@@ -0,0 +1,231 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FINDALLDEVS 3PCAP "22 August 2018"
+.SH NAME
+pcap_findalldevs, pcap_freealldevs \- get a list of capture devices, and
+free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf);
+void pcap_freealldevs(pcap_if_t *alldevs);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_findalldevs()
+constructs a list of network devices that can be opened with
+.B pcap_create(3PCAP)
+and
+.B pcap_activate(3PCAP)
+or with
+.BR pcap_open_live(3PCAP) .
+(Note that there may be network devices that cannot be opened by the
+process calling
+.BR pcap_findalldevs() ,
+because, for example, that process does not have sufficient privileges
+to open them for capturing; if so, those devices will not appear on the
+list.)
+If
+.B pcap_findalldevs()
+succeeds, the pointer pointed to by
+.I alldevsp
+is set to point to the first element of the list, or to
+.B NULL
+if no devices were found (this is considered success).
+Each element of the list is of type
+.BR pcap_if_t ,
+and has the following members:
+.RS
+.TP
+.B next
+if not
+.BR NULL ,
+a pointer to the next element in the list;
+.B NULL
+for the last element of the list
+.TP
+.B name
+a pointer to a string giving a name for the device to pass to
+.B pcap_open_live()
+.TP
+.B description
+if not
+.BR NULL ,
+a pointer to a string giving a human-readable description of the device
+.TP
+.B addresses
+a pointer to the first element of a list of network addresses for the
+device,
+or
+.B NULL
+if the device has no addresses
+.TP
+.B flags
+device flags:
+.RS
+.TP
+.B PCAP_IF_LOOPBACK
+set if the device is a loopback interface
+.TP
+.B PCAP_IF_UP
+set if the device is up
+.TP
+.B PCAP_IF_RUNNING
+set if the device is running
+.TP
+.B PCAP_IF_WIRELESS
+set if the device is a wireless interface; this includes IrDA as well as
+radio-based networks such as IEEE 802.15.4 and IEEE 802.11, so it
+doesn't just mean Wi-Fi
+.TP
+.B PCAP_IF_CONNECTION_STATUS
+a bitmask for an indication of whether the adapter is connected or not;
+for wireless interfaces, "connected" means "associated with a network"
+.TP
+The possible values for the connection status bits are:
+.TP
+.B PCAP_IF_CONNECTION_STATUS_UNKNOWN
+it's unknown whether the adapter is connected or not
+.TP
+.B PCAP_IF_CONNECTION_STATUS_CONNECTED
+the adapter is connected
+.TP
+.B PCAP_IF_CONNECTION_STATUS_DISCONNECTED
+the adapter is disconnected
+.TP
+.B PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
+the notion of "connected" and "disconnected" don't apply to this
+interface; for example, it doesn't apply to a loopback device
+.RE
+.RE
+.PP
+Each element of the list of addresses is of type
+.BR pcap_addr_t ,
+and has the following members:
+.RS
+.TP
+.B next
+if not
+.BR NULL ,
+a pointer to the next element in the list;
+.B NULL
+for the last element of the list
+.TP
+.B addr
+a pointer to a
+.B "struct sockaddr"
+containing an address
+.TP
+.B netmask
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the netmask corresponding to the address pointed to by
+.B addr
+.TP
+.B broadaddr
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the broadcast address corresponding to the address pointed
+to by
+.BR addr ;
+may be null if the device doesn't support broadcasts
+.TP
+.B dstaddr
+if not
+.BR NULL ,
+a pointer to a
+.B "struct sockaddr"
+that contains the destination address corresponding to the address pointed
+to by
+.BR addr ;
+may be null if the device isn't a point-to-point interface
+.RE
+.PP
+Note that the addresses in the list of addresses might be IPv4
+addresses, IPv6 addresses, or some other type of addresses, so you must
+check the
+.B sa_family
+member of the
+.B "struct sockaddr"
+before interpreting the contents of the address; do not assume that the
+addresses are all IPv4 addresses, or even all IPv4 or IPv6 addresses.
+IPv4 addresses have the value
+.BR AF_INET ,
+IPv6 addresses have the value
+.B AF_INET6
+(which older operating systems that don't support IPv6 might not
+define), and other addresses have other values. Whether other addresses
+are returned, and what types they might have is platform-dependent.
+For IPv4 addresses, the
+.B "struct sockaddr"
+pointer can be interpreted as if it pointed to a
+.BR "struct sockaddr_in" ;
+for IPv6 addresses, it can be interpreted as if it pointed to a
+.BR "struct sockaddr_in6".
+.PP
+The list of devices must be freed with
+.BR pcap_freealldevs(3PCAP) ,
+which frees the list pointed to by
+.IR alldevs .
+.SH RETURN VALUE
+.B pcap_findalldevs()
+returns 0 on success and
+.B PCAP_ERROR
+on failure; as indicated, finding no
+devices is considered success, rather than failure, so 0 will be
+returned in that case. If
+.B PCAP_ERROR
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH BACKWARD COMPATIBILITY
+.PP
+The
+.B PCAP_IF_UP
+and
+.B PCAP_IF_RUNNING
+constants became available in libpcap release 1.6.1. The
+.BR PCAP_IF_WIRELESS ,
+.BR PCAP_IF_CONNECTION_STATUS ,
+.BR PCAP_IF_CONNECTION_STATUS_UNKNOWN ,
+.BR PCAP_IF_CONNECTION_STATUS_CONNECTED ,
+.BR PCAP_IF_CONNECTION_STATUS_DISCONNECTED ,
+and
+.B PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE
+constants became available in libpcap release 1.9.0.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_freecode.3pcap b/lib/libpcap/libpcap/pcap_freecode.3pcap
new file mode 100644
index 0000000..4e71efa
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_freecode.3pcap
@@ -0,0 +1,43 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_FREECODE 3PCAP "3 January 2014"
+.SH NAME
+pcap_freecode \- free a BPF program
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+void pcap_freecode(struct bpf_program *);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_freecode()
+is used to free up allocated memory pointed to by a
+.I bpf_program
+struct generated by
+.B pcap_compile(3PCAP)
+when that BPF program is no longer needed, for example after it
+has been made the filter program for a pcap structure by a call to
+.BR pcap_setfilter(3PCAP) .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_get_required_select_timeout.3pcap b/lib/libpcap/libpcap/pcap_get_required_select_timeout.3pcap
new file mode 100644
index 0000000..e58cb4e
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_get_required_select_timeout.3pcap
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_GET_REQUIRED_SELECT_TIMEOUT 3PCAP "25 July 2018"
+.SH NAME
+pcap_get_required_select_timeout \- get a file descriptor on which a
+select() can be done for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+struct timeval *pcap_get_required_select_timeout(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_required_select_timeout()
+returns, on UNIX, a pointer to a
+.B struct timeval
+containing a value that must be used as the minimum timeout in
+.BR select(2) ,
+.BR poll(2) ,
+.BR epoll_wait(2) ,
+and
+.B kevent()
+calls if
+.B pcap_get_selectable_fd(3PCAP)
+returns
+.BR PCAP_ERROR .
+.PP
+The timeout that should be used in those calls must be no larger than
+the smallest of all timeouts returned by
+.B \%pcap_get_required_select_timeout()
+for devices from which packets will be captured.
+.PP
+The device for which
+.B pcap_get_selectable_fd()
+returned
+.B PCAP_ERROR
+must be put in non-blocking mode with
+.BR pcap_setnonblock(3PCAP) ,
+and an attempt must always be made to read packets from the device
+when the
+.BR select() ,
+.BR poll() ,
+.BR epoll_wait() ,
+or
+.B kevent()
+call returns.
+.PP
+Note that a device on which a read can be done without blocking may,
+on some platforms, not have any packets to read if the packet buffer
+timeout has expired. A call to
+.B pcap_dispatch(3PCAP)
+or
+.B pcap_next_ex(3PCAP)
+will return 0 in this case, but will not block.
+.PP
+.B pcap_get_required_select_timeout()
+is not available on Windows.
+.SH RETURN VALUE
+A pointer to a
+.B struct timeval
+is returned if the timeout is required; otherwise
+.B NULL
+is returned.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.9.0. In previous
+releases,
+.BR select() ,
+.BR poll() ,
+.BR epoll_wait() ,
+and
+.B kevent()
+cannot be used on any capture source for which
+.B pcap_get_selectable_fd
+returns \-1.
+.SH SEE ALSO
+pcap(3PCAP), pcap_get_selectable_fd(3PCAP), select(2), poll(2),
+epoll_wait(2), kqueue(2)
diff --git a/lib/libpcap/libpcap/pcap_get_selectable_fd.3pcap b/lib/libpcap/libpcap/pcap_get_selectable_fd.3pcap
new file mode 100644
index 0000000..7f43db3
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_get_selectable_fd.3pcap
@@ -0,0 +1,151 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_GET_SELECTABLE_FD 3PCAP "25 July 2018"
+.SH NAME
+pcap_get_selectable_fd \- get a file descriptor on which a select() can
+be done for a live capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_get_selectable_fd(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_selectable_fd()
+returns, on UNIX, a file descriptor number for a file descriptor on
+which one can
+do a
+.BR select(2) ,
+.BR poll(2) ,
+.BR epoll_wait(2) ,
+.BR kevent() ,
+or other such call
+to wait for it to be possible to read packets without blocking, if such
+a descriptor exists, or
+.BR PCAP_ERROR ,
+if no such descriptor exists.
+.PP
+Some network devices opened with
+.B pcap_create(3PCAP)
+and
+.BR pcap_activate(3PCAP) ,
+or with
+.BR pcap_open_live(3PCAP) ,
+do not support those calls (for example, regular network devices on
+FreeBSD 4.3 and 4.4, and Endace DAG devices), so
+.B PCAP_ERROR
+is returned for
+those devices. In that case, those calls must be given a timeout less
+than or equal to the timeout returned by
+.B pcap_get_required_select_timeout(3PCAP)
+for the device for which
+.B pcap_get_selectable_fd()
+returned
+.BR PCAP_ERROR ,
+the device must be put in non-blocking mode with a call to
+.BR \%pcap_setnonblock(3PCAP) ,
+and an attempt must always be made to read packets from the device
+when the call returns. If
+.B \%pcap_get_required_select_timeout()
+returns
+.BR NULL ,
+it is not possible to wait for packets to arrive on the device in an
+event loop.
+.PP
+Note that a device on which a read can be done without blocking may,
+on some platforms, not have any packets to read if the packet buffer
+timeout has expired. A call to
+.B pcap_dispatch(3PCAP)
+or
+.B pcap_next_ex(3PCAP)
+will return 0 in this case, but will not block.
+.PP
+Note that in:
+.IP
+FreeBSD prior to FreeBSD 4.6;
+.IP
+NetBSD prior to NetBSD 3.0;
+.IP
+OpenBSD prior to OpenBSD 2.4;
+.IP
+Mac OS X prior to Mac OS X 10.7;
+.PP
+.BR select() ,
+.BR poll() ,
+and
+.B kevent()
+do not work correctly on BPF devices;
+.B pcap_get_selectable_fd()
+will return a file descriptor on most of those versions (the exceptions
+being FreeBSD 4.3 and 4.4), but a simple
+.BR select() ,
+.BR poll() ,
+or
+.B kevent()
+call will not indicate that the descriptor is readable until a full
+buffer's worth of packets is received, even if the packet timeout
+expires before then. To work around this, code that uses
+those calls to wait for packets to arrive must put the
+.B pcap_t
+in non-blocking mode, and must arrange that the call
+have a timeout less than or equal to the packet buffer timeout,
+and must try to read packets after that timeout expires, regardless of
+whether the call indicated that the file descriptor for the
+.B pcap_t
+is ready to be read or not. (That workaround will not work in FreeBSD
+4.3 and later; however, in FreeBSD 4.6 and later, those calls
+work correctly on BPF devices, so the workaround isn't necessary,
+although it does no harm.)
+.PP
+Note also that
+.B poll()
+and
+.B kevent()
+doesn't work on character special files, including BPF devices, in Mac
+OS X 10.4 and 10.5, so, while
+.B select()
+can be used on the descriptor returned by
+.BR pcap_get_selectable_fd() ,
+.B poll()
+and
+.B kevent()
+cannot be used on it those versions of Mac OS X.
+.BR poll() ,
+but not
+.BR kevent() ,
+works on that descriptor in Mac OS X releases prior to
+10.4;
+.B poll()
+and
+.B kevent()
+work on that descriptor in Mac OS X 10.6 and later.
+.PP
+.B pcap_get_selectable_fd()
+is not available on Windows.
+.SH RETURN VALUE
+A selectable file descriptor is returned if one exists; otherwise,
+.B PCAP_ERROR
+is returned.
+.SH SEE ALSO
+pcap(3PCAP), kqueue(2)
diff --git a/lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap b/lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap
new file mode 100644
index 0000000..9388a69
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap
@@ -0,0 +1,56 @@
+.\"Copyright (c) 2013, Michal Sekletar
+.\"All rights reserved.
+.\"
+.\"Redistribution and use in source and binary forms, with or without
+.\"modification, are permitted provided that the following conditions
+.\"are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\" products derived from this software without specific prior
+.\" written permission.
+.\"
+.\"THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "18 December 2013"
+.SH NAME
+pcap_get_tstamp_precision \- get the time stamp precision returned in
+captures
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_get_tstamp_precision(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_tstamp_precision()
+returns the precision of the time stamp returned in packet captures on the pcap
+descriptor.
+.SH RETURN VALUE
+.B pcap_get_tstamp_precision()
+returns
+.B PCAP_TSTAMP_PRECISION_MICRO
+or
+.BR PCAP_TSTAMP_PRECISION_NANO ,
+which indicates
+that pcap captures contains time stamps in microseconds or nanoseconds
+respectively.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1. In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_set_tstamp_precision(3PCAP),
+pcap-tstamp(7)
diff --git a/lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap.in b/lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap.in
new file mode 100644
index 0000000..2e72e0b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_get_tstamp_precision.3pcap.in
@@ -0,0 +1,56 @@
+.\"Copyright (c) 2013, Michal Sekletar
+.\"All rights reserved.
+.\"
+.\"Redistribution and use in source and binary forms, with or without
+.\"modification, are permitted provided that the following conditions
+.\"are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\" products derived from this software without specific prior
+.\" written permission.
+.\"
+.\"THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+.TH PCAP_GET_TSTAMP_PRECISION 3PCAP "18 December 2013"
+.SH NAME
+pcap_get_tstamp_precision \- get the time stamp precision returned in
+captures
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_get_tstamp_precision(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_get_tstamp_precision()
+returns the precision of the time stamp returned in packet captures on the pcap
+descriptor.
+.SH RETURN VALUE
+.B pcap_get_tstamp_precision()
+returns
+.B PCAP_TSTAMP_PRECISION_MICRO
+or
+.BR PCAP_TSTAMP_PRECISION_NANO ,
+which indicates
+that pcap captures contains time stamps in microseconds or nanoseconds
+respectively.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1. In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_set_tstamp_precision(3PCAP),
+pcap-tstamp(@MAN_MISC_INFO@)
diff --git a/lib/libpcap/libpcap/pcap_geterr.3pcap b/lib/libpcap/libpcap/pcap_geterr.3pcap
new file mode 100644
index 0000000..ee681c8
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_geterr.3pcap
@@ -0,0 +1,51 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_GETERR 3PCAP "15 January 2016"
+.SH NAME
+pcap_geterr, pcap_perror \- get or print libpcap error message text
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+char *pcap_geterr(pcap_t *p);
+void pcap_perror(pcap_t *p, const char *prefix);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_geterr()
+returns the error text pertaining to the last pcap library error.
+.BR NOTE :
+the pointer it returns will no longer point to a valid error message
+string after the
+.B pcap_t
+passed to it is closed; you must use or copy the string before closing
+the
+.BR pcap_t .
+.PP
+.B pcap_perror()
+prints the text of the last pcap library error on
+.BR stderr ,
+prefixed by
+.IR prefix .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_inject.3pcap b/lib/libpcap/libpcap/pcap_inject.3pcap
new file mode 100644
index 0000000..92a9263
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_inject.3pcap
@@ -0,0 +1,94 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_INJECT 3PCAP "25 July 2018"
+.SH NAME
+pcap_inject, pcap_sendpacket \- transmit a packet
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_inject(pcap_t *p, const void *buf, size_t size);
+int pcap_sendpacket(pcap_t *p, const u_char *buf, int size);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_inject()
+sends a raw packet through the network interface;
+.I buf
+points to the data of the packet, including the link-layer header, and
+.I size
+is the number of bytes in the packet.
+.PP
+Note that, even if you successfully open the network interface, you
+might not have permission to send packets on it, or it might not support
+sending packets; as
+.B pcap_open_live(3PCAP)
+doesn't have a flag to indicate whether to open for capturing, sending,
+or capturing and sending, you cannot request an open that supports
+sending and be notified at open time whether sending will be possible.
+Note also that some devices might not support sending packets.
+.PP
+Note that, on some platforms, the link-layer header of the packet that's
+sent might not be the same as the link-layer header of the packet
+supplied to
+.BR pcap_inject() ,
+as the source link-layer address, if the header contains such an
+address, might be changed to be the address assigned to the interface on
+which the packet it sent, if the platform doesn't support sending
+completely raw and unchanged packets. Even worse, some drivers on some
+platforms might change the link-layer type field to whatever value
+libpcap used when attaching to the device, even on platforms that
+.I do
+nominally support sending completely raw and unchanged packets.
+.PP
+.B pcap_sendpacket()
+is like
+.BR pcap_inject() ,
+but it returns 0 on success, rather than returning the number of bytes
+written.
+.RB ( pcap_inject()
+comes from OpenBSD;
+.B pcap_sendpacket()
+comes from WinPcap. Both are provided for compatibility.)
+.SH RETURN VALUE
+.B pcap_inject()
+returns the number of bytes written on success and
+.B PCAP_ERROR
+on failure.
+.PP
+.B pcap_sendpacket()
+returns 0 on success and
+.B PCAP_ERROR
+on failure.
+.PP
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_is_swapped.3pcap b/lib/libpcap/libpcap/pcap_is_swapped.3pcap
new file mode 100644
index 0000000..67f762f
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_is_swapped.3pcap
@@ -0,0 +1,51 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_IS_SWAPPED 3PCAP "7 April 2014"
+.SH NAME
+pcap_is_swapped \- find out whether a savefile has the native byte order
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_is_swapped(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_is_swapped()
+returns true (1) if
+.I p
+refers to a ``savefile'' that uses a different byte order
+than the current system. For a live capture, it always returns false
+(0).
+.PP
+It must not be called on a pcap descriptor created by
+.B \%pcap_create(3PCAP)
+that has not yet been activated by
+.BR \%pcap_activate(3PCAP) .
+.SH RETURN VALUE
+.B pcap_is_swapped()
+returns true (1) or false (0) on success and
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_lib_version.3pcap b/lib/libpcap/libpcap/pcap_lib_version.3pcap
new file mode 100644
index 0000000..4b86b2d
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_lib_version.3pcap
@@ -0,0 +1,39 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIB_VERSION 3PCAP "3 January 2014"
+.SH NAME
+pcap_lib_version \- get the version information for libpcap
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_lib_version(void);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lib_version()
+returns a pointer to a string giving information about the version of
+the libpcap library being used; note that it contains more information
+than just a version number.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_list_datalinks.3pcap b/lib/libpcap/libpcap/pcap_list_datalinks.3pcap
new file mode 100644
index 0000000..c73c1d4
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_list_datalinks.3pcap
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_DATALINKS 3PCAP "25 July 2018"
+.SH NAME
+pcap_list_datalinks, pcap_free_datalinks \- get a list of link-layer header
+types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
+void pcap_free_datalinks(int *dlt_list);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_datalinks()
+is used to get a list of the supported link-layer header types of the
+interface associated with the pcap descriptor.
+.B pcap_list_datalinks()
+allocates an array to hold the list and sets
+.IR *dlt_buf
+to point to that array.
+.LP
+The caller is responsible for freeing the array with
+.BR pcap_free_datalinks() ,
+which frees the list of link-layer header types pointed to by
+.IR dlt_list .
+.LP
+It must not be called on a pcap descriptor created by
+.B \%pcap_create(3PCAP)
+that has not yet been activated by
+.BR \%pcap_activate(3PCAP) .
+.SH RETURN VALUE
+.B pcap_list_datalinks()
+returns the number of link-layer header types in the array on success,
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated,
+and
+.B PCAP_ERROR
+on other errors.
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B \%pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_datalink_val_to_name(3PCAP),
+pcap-linktype(7)
diff --git a/lib/libpcap/libpcap/pcap_list_datalinks.3pcap.in b/lib/libpcap/libpcap/pcap_list_datalinks.3pcap.in
new file mode 100644
index 0000000..60ba478
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_list_datalinks.3pcap.in
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_DATALINKS 3PCAP "25 July 2018"
+.SH NAME
+pcap_list_datalinks, pcap_free_datalinks \- get a list of link-layer header
+types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_datalinks(pcap_t *p, int **dlt_buf);
+void pcap_free_datalinks(int *dlt_list);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_datalinks()
+is used to get a list of the supported link-layer header types of the
+interface associated with the pcap descriptor.
+.B pcap_list_datalinks()
+allocates an array to hold the list and sets
+.IR *dlt_buf
+to point to that array.
+.LP
+The caller is responsible for freeing the array with
+.BR pcap_free_datalinks() ,
+which frees the list of link-layer header types pointed to by
+.IR dlt_list .
+.LP
+It must not be called on a pcap descriptor created by
+.B \%pcap_create(3PCAP)
+that has not yet been activated by
+.BR \%pcap_activate(3PCAP) .
+.SH RETURN VALUE
+.B pcap_list_datalinks()
+returns the number of link-layer header types in the array on success,
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated,
+and
+.B PCAP_ERROR
+on other errors.
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B \%pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_datalink_val_to_name(3PCAP),
+pcap-linktype(@MAN_MISC_INFO@)
diff --git a/lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap b/lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap
new file mode 100644
index 0000000..1d3fc9a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap
@@ -0,0 +1,81 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "22 August 2018"
+.SH NAME
+pcap_list_tstamp_types, pcap_free_tstamp_types \- get a list of time
+stamp types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp);
+void pcap_free_tstamp_types(int *tstamp_types);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_tstamp_types()
+is used to get a list of the supported time stamp types of the interface
+associated with the pcap descriptor.
+.B pcap_list_tstamp_types()
+allocates an array to hold the list and sets
+.I *tstamp_typesp
+to point to the array.
+See
+.BR pcap-tstamp (7)
+for a list of all the time stamp types.
+.PP
+The caller is responsible for freeing the array with
+.BR pcap_free_tstamp_types() ,
+which frees the list pointed to by
+.IR tstamp_types .
+.SH RETURN VALUE
+.B pcap_list_tstamp_types()
+returns the number of time stamp types in the array on success and
+.B PCAP_ERROR
+on failure.
+A return value of one means that the only time stamp type supported is
+the one in the list, which is the capture device's default time stamp
+type. A return value of zero means that the only time stamp type
+supported is
+.BR PCAP_TSTAMP_HOST ,
+which is the capture device's default time stamp type (only older
+versions of libpcap will return that; newer versions will always return
+one or more types).
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+These functions became available in libpcap release 1.2.1. In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
+.SH SEE ALSO
+pcap(3PCAP), pcap_tstamp_type_val_to_name(3PCAP),
+pcap-tstamp(7)
diff --git a/lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap.in b/lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap.in
new file mode 100644
index 0000000..e2487f7
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_list_tstamp_types.3pcap.in
@@ -0,0 +1,81 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LIST_TSTAMP_TYPES 3PCAP "22 August 2018"
+.SH NAME
+pcap_list_tstamp_types, pcap_free_tstamp_types \- get a list of time
+stamp types supported by a capture device, and free that list
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_list_tstamp_types(pcap_t *p, int **tstamp_typesp);
+void pcap_free_tstamp_types(int *tstamp_types);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_list_tstamp_types()
+is used to get a list of the supported time stamp types of the interface
+associated with the pcap descriptor.
+.B pcap_list_tstamp_types()
+allocates an array to hold the list and sets
+.I *tstamp_typesp
+to point to the array.
+See
+.BR pcap-tstamp (@MAN_MISC_INFO@)
+for a list of all the time stamp types.
+.PP
+The caller is responsible for freeing the array with
+.BR pcap_free_tstamp_types() ,
+which frees the list pointed to by
+.IR tstamp_types .
+.SH RETURN VALUE
+.B pcap_list_tstamp_types()
+returns the number of time stamp types in the array on success and
+.B PCAP_ERROR
+on failure.
+A return value of one means that the only time stamp type supported is
+the one in the list, which is the capture device's default time stamp
+type. A return value of zero means that the only time stamp type
+supported is
+.BR PCAP_TSTAMP_HOST ,
+which is the capture device's default time stamp type (only older
+versions of libpcap will return that; newer versions will always return
+one or more types).
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH BACKWARD COMPATIBILITY
+.PP
+These functions became available in libpcap release 1.2.1. In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
+.SH SEE ALSO
+pcap(3PCAP), pcap_tstamp_type_val_to_name(3PCAP),
+pcap-tstamp(@MAN_MISC_INFO@)
diff --git a/lib/libpcap/libpcap/pcap_lookupdev.3pcap b/lib/libpcap/libpcap/pcap_lookupdev.3pcap
new file mode 100644
index 0000000..29f09e3
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_lookupdev.3pcap
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOKUPDEV 3PCAP "8 September 2017"
+.SH NAME
+pcap_lookupdev \- find the default device on which to capture
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+[DEPRECATED] char *pcap_lookupdev(char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B This interface is obsoleted by
+.BR pcap_findalldevs (3PCAP).
+To find a default device on which to capture, call
+.B pcap_findalldevs()
+and, if the list it returns is not empty, use the first device in the
+list. (If the list is empty, there are no devices on which capture is
+possible.)
+.LP
+.B pcap_lookupdev()
+returns a pointer to a string giving the name of a network device
+suitable for use with
+.B pcap_create(3PCAP)
+and
+.BR \%pcap_activate(3PCAP) ,
+or with
+.BR pcap_open_live(3PCAP) ,
+and with
+.BR pcap_lookupnet(3PCAP) .
+If there is an error,
+.B NULL
+is returned and
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP)
+.SH BUGS
+The pointer returned by
+.B pcap_lookupdev()
+points to a static buffer; subsequent calls to
+.B pcap_lookupdev()
+in the same thread, or calls to
+.B pcap_lookupdev()
+in another thread, may overwrite that buffer.
+.LP
+In WinPcap, this function may return a UTF-16 string rather than an
+ASCII or UTF-8 string.
+
diff --git a/lib/libpcap/libpcap/pcap_lookupnet.3pcap b/lib/libpcap/libpcap/pcap_lookupnet.3pcap
new file mode 100644
index 0000000..f609445
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_lookupnet.3pcap
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOKUPNET 3PCAP "25 July 2018"
+.SH NAME
+pcap_lookupnet \- find the IPv4 network number and netmask for a device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_lookupnet(const char *device, bpf_u_int32 *netp,
+.ti +8
+bpf_u_int32 *maskp, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_lookupnet()
+is used to determine the IPv4 network number and mask
+associated with the network device
+.IR device .
+Both
+.I netp
+and
+.I maskp
+are
+.I bpf_u_int32
+pointers.
+.SH RETURN VALUE
+.B pcap_lookupnet()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_loop.3pcap b/lib/libpcap/libpcap/pcap_loop.3pcap
new file mode 100644
index 0000000..0193714
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_loop.3pcap
@@ -0,0 +1,206 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_LOOP 3PCAP "25 July 2018"
+.SH NAME
+pcap_loop, pcap_dispatch \- process packets from a live capture or savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+typedef void (*pcap_handler)(u_char *user, const struct pcap_pkthdr *h,
+.ti +8
+ const u_char *bytes);
+.ft
+.LP
+.ft B
+int pcap_loop(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user);
+int pcap_dispatch(pcap_t *p, int cnt,
+.ti +8
+pcap_handler callback, u_char *user);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_loop()
+processes packets from a live capture or ``savefile'' until
+.I cnt
+packets are processed, the end of the ``savefile'' is
+reached when reading from a ``savefile'',
+.B pcap_breakloop(3PCAP)
+is called, or an error occurs.
+It does
+.B not
+return when live packet buffer timeouts occur.
+A value of \-1 or 0 for
+.I cnt
+is equivalent to infinity, so that packets are processed until another
+ending condition occurs.
+.PP
+.B pcap_dispatch()
+processes packets from a live capture or ``savefile'' until
+.I cnt
+packets are processed, the end of the current bufferful of packets is
+reached when doing a live capture, the end of the ``savefile'' is
+reached when reading from a ``savefile'',
+.B pcap_breakloop()
+is called, or an error occurs.
+Thus, when doing a live capture,
+.I cnt
+is the maximum number of packets to process before returning, but is not
+a minimum number; when reading a live capture, only one
+bufferful of packets is read at a time, so fewer than
+.I cnt
+packets may be processed. A value of \-1 or 0 for
+.I cnt
+causes all the packets received in one buffer to be processed when
+reading a live capture, and causes all the packets in the file to be
+processed when reading a ``savefile''.
+.PP
+Note that, when doing a live capture on some platforms, if the read
+timeout expires when there are no packets available,
+.B pcap_dispatch()
+will return 0, even when not in non-blocking mode, as there are no
+packets to process. Applications should be prepared for this to happen,
+but must not rely on it happening.
+.PP
+.ft B
+(In older versions of libpcap, the behavior when
+\fIcnt\fP
+was 0 was undefined; different platforms and devices behaved
+differently, so code that must work with older versions of libpcap
+should use \-1, not 0, as the value of
+\fIcnt\fP.)
+.ft R
+.PP
+.I callback
+specifies a
+.I pcap_handler
+routine to be called with three arguments:
+a
+.I u_char
+pointer which is passed in the
+.I user
+argument to
+.B pcap_loop()
+or
+.BR pcap_dispatch() ,
+a
+.I const struct pcap_pkthdr
+pointer pointing to the packet time stamp and lengths, and a
+.I const u_char
+pointer to the first
+.B caplen
+(as given in the
+.I struct pcap_pkthdr
+a pointer to which is passed to the callback routine)
+bytes of data from the packet. The
+.I struct pcap_pkthdr
+and the packet data are not to be freed by the callback routine, and are
+not guaranteed to be valid after the callback routine returns; if the
+code needs them to be valid after the callback, it must make a copy of
+them.
+.PP
+The bytes of data from the packet begin with a link-layer header. The
+format of the link-layer header is indicated by the return value of the
+.B pcap_datalink(3PCAP)
+routine when handed the
+.B pcap_t
+value also passed to
+.B pcap_loop()
+or
+.BR pcap_dispatch() .
+.I https://www.tcpdump.org/linktypes.html
+lists the values
+.B pcap_datalink()
+can return and describes the packet formats that
+correspond to those values. The value it returns will be valid for all
+packets received unless and until
+.B pcap_set_datalink(3PCAP)
+is called; after a successful call to
+.BR pcap_set_datalink() ,
+all subsequent packets will have a link-layer header of the type
+specified by the link-layer header type value passed to
+.BR pcap_set_datalink() .
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet. For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.SH RETURN VALUE
+.B pcap_loop()
+returns 0 if
+.I cnt
+is exhausted or if, when reading from a ``savefile'', no more packets
+are available. It returns
+.B PCAP_ERROR
+if an error occurs or
+.B PCAP_ERROR_BREAK
+if the loop terminated due to a call to
+.B pcap_breakloop()
+before any packets were processed.
+It does
+.B not
+return when live packet buffer timeouts occur; instead, it attempts to
+read more packets.
+.PP
+.B pcap_dispatch()
+returns the number of packets processed on success; this can be 0 if no
+packets were read from a live capture (if, for example, they were
+discarded because they didn't pass the packet filter, or if, on
+platforms that support a packet buffer timeout that starts before any
+packets arrive, the timeout expires before any packets arrive, or if the
+file descriptor for the capture device is in non-blocking mode and no
+packets were available to be read) or if no more packets are available
+in a ``savefile.'' It returns
+.B PCAP_ERROR
+if an error occurs or
+.B PCAP_ERROR_BREAK
+if the loop terminated due to a call to
+.B pcap_breakloop()
+before any packets were processed.
+.ft B
+If your application uses pcap_breakloop(),
+make sure that you explicitly check for PCAP_ERROR and PCAP_ERROR_BREAK,
+rather than just checking for a return value < 0.
+.ft R
+.PP
+If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_major_version.3pcap b/lib/libpcap/libpcap/pcap_major_version.3pcap
new file mode 100644
index 0000000..2fedfd2
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_major_version.3pcap
@@ -0,0 +1,54 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_MAJOR_VERSION 3PCAP "8 January 2018"
+.SH NAME
+pcap_major_version, pcap_minor_version \- get the version number of a savefile
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_major_version(pcap_t *p);
+int pcap_minor_version(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+If
+.I p
+refers to a ``savefile'',
+.B pcap_major_version()
+returns the major number of the file format of the ``savefile'' and
+.B pcap_minor_version()
+returns the minor number of the file format of the ``savefile''. The
+version number is stored in the ``savefile''; note that the meaning of
+its values depends on the type of ``savefile'' (for example, pcap or
+pcapng).
+.PP
+If
+.I p
+refers to a live capture, the values returned by
+.B pcap_major_version()
+and
+.B pcap_minor_version()
+are not meaningful.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_next_ex.3pcap b/lib/libpcap/libpcap/pcap_next_ex.3pcap
new file mode 100644
index 0000000..f0eb82d
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_next_ex.3pcap
@@ -0,0 +1,144 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_NEXT_EX 3PCAP "25 July 2018"
+.SH NAME
+pcap_next_ex, pcap_next \- read the next packet from a pcap_t
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_next_ex(pcap_t *p, struct pcap_pkthdr **pkt_header,
+.ti +8
+const u_char **pkt_data);
+const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_next_ex()
+reads the next packet and returns a success/failure indication.
+If the packet was read without problems, the pointer pointed to by the
+.I pkt_header
+argument is set to point to the
+.I pcap_pkthdr
+struct for the packet, and the
+pointer pointed to by the
+.I pkt_data
+argument is set to point to the data in the packet. The
+.I struct pcap_pkthdr
+and the packet data are not to be freed by the caller, and are not
+guaranteed to be valid after the next call to
+.BR pcap_next_ex() ,
+.BR pcap_next() ,
+.BR pcap_loop(3PCAP) ,
+or
+.BR pcap_dispatch(3PCAP) ;
+if the code needs them to remain valid, it must make a copy of them.
+.PP
+.B pcap_next()
+reads the next packet (by calling
+.B pcap_dispatch()
+with a
+.I cnt
+of 1) and returns a
+.I u_char
+pointer to the data in that packet. The
+packet data is not to be freed by the caller, and is not
+guaranteed to be valid after the next call to
+.BR pcap_next_ex() ,
+.BR pcap_next() ,
+.BR pcap_loop() ,
+or
+.BR pcap_dispatch() ;
+if the code needs it to remain valid, it must make a copy of it.
+The
+.I pcap_pkthdr
+structure pointed to by
+.I h
+is filled in with the appropriate values for the packet.
+.PP
+The bytes of data from the packet begin with a link-layer header. The
+format of the link-layer header is indicated by the return value of the
+.B pcap_datalink(PCAP)
+routine when handed the
+.B pcap_t
+value also passed to
+.B pcap_loop()
+or
+.BR pcap_dispatch() .
+.I https://www.tcpdump.org/linktypes.html
+lists the values
+.B pcap_datalink()
+can return and describes the packet formats that
+correspond to those values. The value it returns will be valid for all
+packets received unless and until
+.B pcap_set_datalink(3PCAP)
+is called; after a successful call to
+.BR pcap_set_datalink() ,
+all subsequent packets will have a link-layer header of the type
+specified by the link-layer header type value passed to
+.BR pcap_set_datalink() .
+.PP
+Do
+.B NOT
+assume that the packets for a given capture or ``savefile`` will have
+any given link-layer header type, such as
+.B DLT_EN10MB
+for Ethernet. For example, the "any" device on Linux will have a
+link-layer header type of
+.B DLT_LINUX_SLL
+even if all devices on the system at the time the "any" device is opened
+have some other data link type, such as
+.B DLT_EN10MB
+for Ethernet.
+.SH RETURN VALUE
+.B pcap_next_ex()
+returns 1 if the packet was read without problems, 0 if packets are
+being read from a live capture and the packet buffer timeout expired,
+.B PCAP_ERROR
+if an error occurred while reading the packet, and
+.B PCAP_ERROR_BREAK
+if packets
+are being read from a ``savefile'' and there are no more packets to read
+from the savefile. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.PP
+.B pcap_next()
+returns a pointer to the packet data on success, and returns
+.B NULL
+if an error occurred, or if no packets were read from a live capture
+(if, for example, they were discarded because they didn't pass the
+packet filter, or if, on platforms that support a packet buffer timeout
+that starts before any packets arrive, the timeout expires before any
+packets arrive, or if the file descriptor for the capture device is in
+non-blocking mode and no packets were available to be read), or if no
+more packets are available in a ``savefile.'' Unfortunately, there is no
+way to determine whether an error occurred or not.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_ng.3 b/lib/libpcap/libpcap/pcap_ng.3
new file mode 100644
index 0000000..6fc80df
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_ng.3
@@ -0,0 +1,625 @@
+.\"
+.\" Copyright (c) 2012-2013 Apple Inc. All rights reserved.
+.\"
+.\" @APPLE_LICENSE_HEADER_START@
+.\"
+.\" This file contains Original Code and/or Modifications of Original Code
+.\" as defined in and that are subject to the Apple Public Source License
+.\" Version 2.0 (the 'License'). You may not use this file except in
+.\" compliance with the License. Please obtain a copy of the License at
+.\" http://www.opensource.apple.com/apsl/ and read it before using this
+.\" file.
+.\"
+.\" The Original Code and all software distributed under the License are
+.\" distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+.\" EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+.\" INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+.\" FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+.\" Please see the License for the specific language governing rights and
+.\" limitations under the License.
+.\"
+.\" @APPLE_LICENSE_HEADER_END@
+.Dd 20 March 2013
+.Dt PCAP_NG 3PCAP
+.Os
+.
+.Sh NAME
+.
+.Nm pcap_ng
+.Nd pcap library extensions for the new pcap-ng file format
+.
+.Sh SYNOPSIS
+.
+.In pcap/pcap-ng.h
+.Ft pcap_t *
+.Fo pcap_ng_fopen_offline
+.Fa "FILE *fp"
+.Fa "char *errbuf"
+.Fc
+.Ft pcap_t *
+.Fo pcap_ng_open_offline
+.Fa "const char *fname"
+.Fa "char *errbuf"
+.Fc
+.Ft pcap_dumper_t *
+.Fo pcap_ng_dump_open
+.Fa "pcap_t *p"
+.Fa "const char *file"
+.Fc
+.Ft pcap_dumper_t *
+.Fo pcap_ng_dump_fopen
+.Fa "pcap_t *p"
+.Fa "FILE *fp"
+.Fc
+.Ft void
+.Fo pcap_ng_dump
+.Fa "u_char *user"
+.Fa "struct pcap_pkthdr *h"
+.Fa "u_char *sp"
+.Fc
+.Ft void
+.Fo pcap_ng_dump_close
+.Fa "pcap_dumper_t *p"
+.Fc
+.Ft pcapng_block_t
+.Fo pcap_ng_block_alloc
+.Fa "size_t len"
+.Fc
+.Ft size_t
+.Fo pcap_ng_block_size_max
+.Fa "void"
+.Fc
+.Ft int
+.Fo pcap_ng_block_reset
+.Fa "pcapng_block_t block"
+.Fc
+.Ft int
+.Fo pcap_ng_free_block
+.Fa "pcapng_block_t block"
+.Fc
+.Ft bpf_u_int32
+.Fo pcap_ng_dump_block
+.Fa "FILE *stream"
+.Fa "pcapng_block_t block"
+.Fc
+.Ft bpf_u_int32
+.Fo pcap_ng_externalize_block
+.Fa "int fd"
+.Fa "pcapng_block_t block"
+.Fc
+.Ft pcapng_block_t
+.Fo pcap_ng_block_alloc_with_raw_block
+.Fa "pcap_t *p"
+.Fa "u_char *rawblock"
+.Fc
+.Ft int
+.Fo pcap_ng_block_init_with_raw_block
+.Fa "pcapng_block_t block"
+.Fa "pcap_t *p"
+.Fa "u_char *rawblock"
+.Fc
+.Ft bpf_u_int32
+.Fo pcap_ng_block_get_type
+.Fa "pcapng_block_t block"
+.Fc
+.Ft bpf_u_int32
+.Fo pcap_ng_block_get_len
+.Fa "pcapng_block_t block"
+.Fc
+.Ft int
+.Fo pcap_ng_block_is_swapped
+.Fa "pcapng_block_t block"
+.Fc
+.Ft struct pcapng_section_header_fields *
+.Fo pcap_ng_get_section_header_fields
+.Fa "pcapng_block_t block"
+.Fc
+.Ft struct pcapng_interface_description_fields *
+.Fo pcap_ng_get_interface_description_fields
+.Fa "pcapng_block_t block"
+.Fc
+.Ft struct pcapng_enhanced_packet_fields *
+.Fo pcap_ng_get_enhanced_packet_fields
+.Fa "pcapng_block_t block"
+.Fc
+.Ft struct pcapng_simple_packet_fields *
+.Fo pcap_ng_get_simple_packet_fields
+.Fa "pcapng_block_t block"
+.Fc
+.Ft struct pcapng_packet_fields *
+.Fo pcap_ng_get_packet_fields
+.Fa "pcapng_block_t block"
+.Fc
+.Ft struct pcapng_process_information_fields *
+.Fo pcap_ng_get_process_information_fields
+.Fa "pcapng_block_t block"
+.Fc
+.Ft bpf_u_int32
+.Fo pcap_ng_block_packet_copy_data
+.Fa "pcapng_block_t block"
+.Fa "const void * data"
+.Fa "bpf_u_int32 caplen"
+.Fc
+.Ft bpf_u_int32
+.Fo pcap_ng_block_packet_set_data
+.Fa "pcapng_block_t block"
+.Fa "const void * data"
+.Fa "bpf_u_int32 caplen"
+.Fc
+.Ft void *
+.Fo pcap_ng_block_packet_get_data_ptr
+.Fa "pcapng_block_t block"
+.Fc
+.Ft bpf_u_int32
+.Fo pcap_ng_block_packet_get_data_len
+.Fa "pcapng_block_t block"
+.Fc
+.Ft int
+.Fo pcap_ng_block_does_support_data
+.Fa "pcapng_block_t block"
+.Fc
+.Ft int
+.Fo pcap_ng_block_add_option_with_value
+.Fa "pcapng_block_t block"
+.Fa "u_short code"
+.Fa "const void *buffer"
+.Fa "u_short length"
+.Fc
+.Ft int
+.Fo pcap_ng_block_add_option_with_value_string
+.Fa "pcapng_block_t block"
+.Fa "u_short code"
+.Fa "const char *string"
+.Fc
+.Ft pcapng_option_t
+.Fo pcap_ng_block_get_option
+.Fa "pcapng_option_t option"
+.Fa "u_short code"
+.Fc
+.Ft void
+.Fo pcap_ng_block_iterate_options
+.Fa "pcapng_block_t block"
+.Fa "void * context"
+.Fa "pcap_ng_block_option_iterator_func opt_iterator_func"
+.Fc
+.Ft pcapng_name_record_t
+.Fo pcap_ng_block_add_name_record_with_ip4
+.Fa "pcapng_block_t block"
+.Fa "struct in_addr * in4"
+.Fa "const void ** names"
+.Fc
+.Ft pcapng_name_record_t
+.Fo pcap_ng_block_add_name_record_with_ip6
+.Fa "pcapng_block_t block"
+.Fa "struct in6_addr * in6"
+.Fa "const void ** names"
+.Fc
+.Ft void
+.Fo pcap_ng_block_iterate_name_records
+.Fa "pcapng_name_record_t record"
+.Fa "pcapng_name_record_iterator_func fn"
+.Fc
+.Ft int
+.Fo dlt_to_linktype
+.Fa "int dlt"
+.Fc
+.Ft int
+.Fo linktype_to_dlt
+.Fa "int linktype"
+.Fc
+.
+.Sh DESCRIPTION
+.
+The
+.Nm
+collection of functions and data structure is an extension to the
+.Xr pcap 3PCAP
+library to read and write capture files in the Pcap-ng file
+format.
+.Pp
+While the traditional
+.Xr pcap 3PCAP
+API is packet oriented, the
+.Nm
+API uses pcap-ng blocks as the fundamental type of object.
+The following standard pcap-ng block types are supported:
+.Bl -bullet -offset indent -compact
+.It
+section header
+.It
+interface description
+.It
+the three types of packet blocks
+.It
+interface statistic
+.It
+name resolution
+.El
+as well a custom block type for process information.
+.Pp
+While it's possible to access the raw content of a block, the bulk of the
+API provides accessor functions to facilitate the parsing and the creation of
+blocks and options.
+.Pp
+The purpose of this API is to provide sequential access to capture files using the
+Pcap-ng file format and it does not offer any facility for random access or
+direct edition of pcan-ng file (no addition, removal or modification of pcap-ng blocks
+that are present in a capture file).
+.
+.Ss "Opening a pcap-ng file"
+.
+To open a handle for a pcap-ng capture file from which to read pcap-ng
+blocks use either
+.Fn pcap_ng_fopen_offline
+or
+.Fn pcap_ng_open_offline .
+As these functions return a NULL value if the file is not in the pcap-ng
+format, one should then try opening the file using
+.Fn pcap_fopen_offline 3PCAP
+or
+.Fn pcap_open_offline 3PCAP .
+.Pp
+To open a new pcap-ng capture file to save pcap-ng blocks use either
+.Fn pcap_ng_dump_open
+or
+.Fn pcap_ng_dump_fopen .
+.Pp
+The above functions return a
+.Vt pcap_t
+that may be used with most of the
+.Xr pcap 3PCAP
+functions that accept a capture handle.
+.Pp
+When used with a
+.Vt pcap_t
+handle of file in the pcap-ng format,
+.Fn pcap_datalink 3PCAP
+return the pseudo data link type
+.Vt DLT_PCAPNG
+as a pcap-ng file may contain packets with different data link type.
+.Pp
+Call
+.Fn pcap_ng_dump_close
+to close the handle of a pcap-ng file.
+.
+.Ss "Reading pcap-ng blocks"
+.
+To read blocks from a pcap-ng file opened by
+.Fn pcap_ng_fopen_offline
+or
+.Fn pcap_ng_open_offline
+simply call the traditional functions
+.Fn pcap_dispatch
+or
+.Fn pcap_loop
+or
+.Fn pcap_next
+or
+.Fn pcap_next_ex .
+The difference is that instead of getting a pointer to a packet, the function or
+the callback gets a buffer to a raw pcap-ng block.
+.Pp
+The raw pcap-ng may be parsed manually or it may be passed to the function
+.Fn pcap_ng_create_with_raw_block
+to create an internalized representation of the block and used with other
+.Nm
+accessor functions.
+.
+.Ss "Writing pcap-ng blocks"
+.
+The function
+.Fn pcap_ng_dump_block
+takes a
+.Vt pcapng_block_t
+object, and writes it to the capture file in the pcap-ng file format.
+.
+.Ss "Creating a pcap-ng block internalized object"
+.
+Internalized pcap-ng block objects are represented by the opaque data type
+.Vt pcapng_block_t
+and accessor functions may be used to read and write the content of a
+.Vt pcapng_block_t
+object (header and options). A
+.Vt pcapng_block_t
+object may be re-used to mimimize memory allocations.
+.Pp
+The function
+.Fn pcap_ng_block_alloc
+allocates a
+.Vt pcapng_block_t
+object to hold an pcap-ng block data structure.
+This allocate a work buffer to hold the raw data block content
+so the given size should be large enough to hold the largest expected
+raw block size.
+.Pp
+If the size given to
+.Fn pcap_ng_block_alloc
+is greater than the value returned by
+.Fn pcap_ng_block_size_max
+then the allocation fails and
+.Fn pcap_ng_block_alloc
+returns NULL.
+.Pp
+To reuse an existing internalized
+.Vt pcapng_block_t
+object, use the function
+.Fn pcap_ng_block_reset
+as it is more efficient to reuse than to allocate a new data structure
+of each pcap-ng block being read or written.
+.Pp
+The function
+.Fn pcap_ng_free_block
+deletes the memory used by the
+.Vt pcapng_block_t
+object.
+.Pp
+The function
+.Fn pcap_ng_block_init_with_raw_block
+parses a raw pcap-ng block buffer into an internalized form using
+an existing
+.Vt pcapng_block_t
+object. This is typically used when reading from a
+pcap-ng capture file.
+.Pp
+The function
+.Fn pcap_ng_block_alloc_with_raw_block
+creates a
+.Vt pcapng_block_t
+object from a raw pcap-ng buffer buffer.
+.
+.Ss "Getting information about a pcap-ng block"
+.
+The function
+.Fn pcap_ng_block_get_type
+returns the type of a
+.Vt pcapng_block_t
+object.
+.Pp
+The function
+.Fn pcap_ng_block_is_swapped
+returns the byte order of a
+.Vt pcapng_block_t
+object. This is useful when reading pcap-ng blocks and options from a
+pcap-ng capture file. This actually reflects the byte order magic of the
+section header block.
+.Pp
+The function
+.Fn pcap_ng_block_get_len
+returns the length of the externalized form of a
+.Vt pcapng_block_t
+object.
+.Pp
+The following functions return the fixed header size corresponding to the
+supported block types:
+.Bl -bullet -offset indent -compact
+.It
+.Fn pcapng_section_header_fields
+.It
+.Fn pcapng_interface_description_fields
+.It
+.Fn pcapng_enhanced_packet_fields
+.It
+.Fn pcapng_simple_packet_fields
+.It
+.Fn pcapng_packet_fields
+.It
+.Fn pcapng_process_information_fields
+.El
+.
+.Ss "Accessing the data of packet blocks"
+.
+The same functions may be used to access the data portion of the three
+types of packet blocks:
+.Bl -item -offset indent -compact
+.It
+enhanced packet block
+.It
+simple packet block
+.It
+packet block
+.El
+.Pp
+The function
+.Fn pcap_ng_block_packet_copy_data
+copies the content of the passed data buffer into the
+.Vt pcapng_block_t
+packet object. This may involve memory allocation to hold the data.
+.Pp
+The function
+.Nm pcap_ng_block_packet_set_data
+uses the passed data buffer as a pointer reference to an external
+buffer. Using
+.Fn pcap_ng_block_packet_set_data
+is more efficient than
+.Fn pcap_ng_block_packet_copy_data
+as this does not involve data movement or memory allocation,
+but the caller must make sure the passed data buffer is kept intact for
+the lifetime of the
+.Vt pcapng_block_t
+packet object.
+.Pp
+The function
+.Fn pcap_ng_block_delete_data
+empties the
+.Vt pcapng_block_t
+packet object from any data so its length becomes zero.
+.Pp
+The function
+.Fn pcap_ng_block_packet_get_data_ptr
+returns a pointer on the beginning of the data portion of the
+.Vt pcapng_block_t
+packet object.
+.Pp
+The function
+.Fn pcap_ng_block_packet_get_data_len
+returns the length of the data referred to by the
+.Vt pcapng_block_t
+packet object.
+.Pp
+The function
+.Fn pcap_ng_block_does_support_data
+returns a non-zero value when the passed
+.Vt pcapng_block_t
+in a pcap-ng block with data of variable length.
+.
+.Ss "Accessing pcap-ng options"
+.
+To add an option to a
+.Vt pcapng_block_t
+packet object use the function
+.Fn pcap_ng_block_add_option_with_value .
+.Pp
+When the option value is a null terminated string, one may use the
+function
+.Fn pcap_ng_block_add_option_with_string
+that includes the terminating null byte in the option value.
+.Pp
+To get a single option value one may use the function
+.Fn pcap_ng_block_get_option
+when an option may appear at most once in a pcap-ng block.
+.Pp
+The function
+.sFn pcap_ng_block_iterate_options
+walks the list of options
+.Vt pcapng_block_t
+and calls the given callback function of each option.
+.
+.Ss "Keeping track of interface information"
+.
+.Nm
+provides utility functions to help keep track of
+interface information associated with a
+.Vt pcap_t
+handle using the data structure
+.Vt struct pcap_if_info .
+The interface IDs being specific to a given section, the list
+of interface information should be cleared whenever a new section is being
+processed.
+.Pp
+The function
+.Fn pcap_add_if_info
+add an interface information. The interface ID is assigned sequentially so
+the corresponding interface block needs to be written to the save file
+to avoid reference to missing interfaces caused by filtering.
+.Pp
+The function
+.Fn pcap_find_if_info_by_name
+returns the
+.Vt struct pcap_if_info
+that matches the given name.
+.Pp
+The function
+.Fn pcap_find_if_info_by_id
+returns the
+.Vt struct pcap_if_info
+that matches the given interface id.
+.Pp
+The function
+.Fn pcap_free_if_info
+frees
+.Vt struct pcap_if_info
+and removes it from the pcap_t handle. Removing a single
+.Vt struct pcap_if_info
+is not a common usage.
+.Pp
+The function
+.Fn pcap_clear_if_infos
+removes all the
+.Vt struct pcap_if_info
+structures from a
+.Vt pcap_t *
+handle. This is useful when processing a new section header block as the
+interface IDs are valid with a section.
+.Pp
+Use the function
+.Fn pcap_ng_init_section_info
+to reinitialize the section specific data like interface information and
+process information. This should be used when adding a new section
+header. This is also useful when saving to a new packet capture files,
+for example when "rotating" files.
+.
+.Ss "Keeping track of process information"
+.
+.Nm
+provide utility functions to help keep track of
+process information associated with a
+.Vt pcap_t
+handle using the data structure
+.Vt struct pcap_proc_info .
+The process information indexes being specific to a given section,
+the list of process information should be cleared whenever a new section
+is being processed.
+.Pp
+The function
+.Fn pcap_add_proc_info
+adds a process information.
+.Pp
+The function
+.Fn pcap_find_proc_info
+returns the
+.Vt struct pcap_proc_info
+that matches the given process name and ID.
+.Pp
+The function
+.Fn pcap_find_proc_info_by_index
+returns the
+.Vt struct pcap_proc_info
+that matches the given process information index.
+.Pp
+The function
+.Fn pcap_free_proc_info
+frees
+.Vt struct pcap_proc_info
+and removes it from the pcap_t handle. Removing a single
+.Vt struct pcap_proc_info
+is not a common usage.
+.Pp
+The function
+.Fn pcap_clear_proc_infos
+removes all the
+.Vt struct pcap_proc_info
+structures from a
+.Vt pcap_t *
+handle. This is useful when processing a new section header block as the
+process information indexes are valid within a section.
+.
+.Ss "Handling special pktap and iptap interfaces"
+.
+.Pp
+The function
+.Fn pcap_setup_pktap_interface
+creates a cloned pktap or iptap interface to be used as a capture device.
+.Pp
+The function
+.Fn pcap_cleanup_pktap_interface
+destroys a cloned pktap or iptap interface that was used as a capture device.
+.
+.Ss "Dumping packet with ptkap header"
+.
+The function
+.Fn pcap_ng_dump_pktap
+saves a packet with a
+.Vt struct pcap_pkthdr
+header as a pcap-ng enhanced data block. It handles the packet metadata
+information from the
+.Vt struct pcap_pkthdr
+and creates process information blocks and interface information blocks as
+needed. It returns 1 if the packet passes the filter, 0 otherwise.
+.
+The function
+.Fn pcap_ng_dump_pktap_comment
+saves a packet like
+.Fn pcap_ng_dump_pktap
+with the addition of a comment string parameter that is added
+to the pcap-ng enhanced data block.
+.
+.Sh SEE ALSO
+.
+.Xr pcap_dump_open 3PCAP ,
+.Xr pcap_dump_fopen 3PCAP ,
+.Xr pcap_dump 3PCAP ,
+.Xr pcap_dump_close 3PCAP ,
+.Xr tcpdump 1
+.Pp
+.Pa http://www.winpcap.org/ntar/draft/PCAP-DumpFileFormat.html
+.Pa http://wiki.wireshark.org/Development/PcapNg
diff --git a/lib/libpcap/libpcap/pcap_offline_filter.3pcap b/lib/libpcap/libpcap/pcap_offline_filter.3pcap
new file mode 100644
index 0000000..724f836
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_offline_filter.3pcap
@@ -0,0 +1,55 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OFFLINE_FILTER 3PCAP "7 April 2014"
+.SH NAME
+pcap_offline_filter \- check whether a filter matches a packet
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_offline_filter(const struct bpf_program *fp,
+.ti +8
+const struct pcap_pkthdr *h, const u_char *pkt)
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_offline_filter()
+checks whether a filter matches a packet.
+.I fp
+is a pointer to a
+.I bpf_program
+struct, usually the result of a call to
+.BR pcap_compile(3PCAP) .
+.I h
+points to the
+.I pcap_pkthdr
+structure for the packet, and
+.I pkt
+points to the data in the packet.
+.SH RETURN VALUE
+.B pcap_offline_filter()
+returns the return value of the filter program. This will be zero if
+the packet doesn't match the filter and non-zero if the packet matches
+the filter.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_open_dead.3pcap b/lib/libpcap/libpcap/pcap_open_dead.3pcap
new file mode 100644
index 0000000..8522a2c
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_open_dead.3pcap
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_DEAD 3PCAP "3 January 2014"
+.SH NAME
+pcap_open_dead, pcap_open_dead_with_tstamp_precision \- open a fake
+pcap_t for compiling filters or opening a capture for output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_dead(int linktype, int snaplen);
+pcap_t *pcap_open_dead_with_tstamp_precision(int linktype, int snaplen,
+ u_int precision);
+.ft
+.fi
+.SH DESCRIPTION
+.PP
+.B pcap_open_dead()
+and
+.B pcap_open_dead_with_tstamp_precision()
+are used for creating a
+.B pcap_t
+structure to use when calling the other functions in libpcap. It is
+typically used when just using libpcap for compiling BPF code; it can
+also be used if using
+.BR pcap_dump_open(3PCAP) ,
+.BR pcap_dump(3PCAP) ,
+and
+.B pcap_dump_close(3PCAP)
+to write a savefile if there is no
+.B pcap_t
+that supplies the packets to be written.
+.PP
+.I linktype
+specifies the link-layer type for the
+.BR pcap_t .
+.PP
+.I snaplen
+specifies the snapshot length for the
+.BR pcap_t .
+.PP
+When
+.BR pcap_open_dead_with_tstamp_precision() ,
+is used to create a
+.B pcap_t
+for use with
+.BR pcap_dump_open() ,
+.I precision
+specifies the time stamp precision for packets;
+.B PCAP_TSTAMP_PRECISION_MICRO
+should be specified if the packets to be written have time stamps in
+seconds and microseconds, and
+.B PCAP_TSTAMP_PRECISION_NANO
+should be specified if the packets to be written have time stamps in
+seconds and nanoseconds. Its value does not affect
+.BR pcap_compile(3PCAP) .
+.SH SEE ALSO
+pcap(3PCAP), \%pcap-linktype(7)
diff --git a/lib/libpcap/libpcap/pcap_open_dead.3pcap.in b/lib/libpcap/libpcap/pcap_open_dead.3pcap.in
new file mode 100644
index 0000000..97a97f3
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_open_dead.3pcap.in
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_DEAD 3PCAP "3 January 2014"
+.SH NAME
+pcap_open_dead, pcap_open_dead_with_tstamp_precision \- open a fake
+pcap_t for compiling filters or opening a capture for output
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_dead(int linktype, int snaplen);
+pcap_t *pcap_open_dead_with_tstamp_precision(int linktype, int snaplen,
+ u_int precision);
+.ft
+.fi
+.SH DESCRIPTION
+.PP
+.B pcap_open_dead()
+and
+.B pcap_open_dead_with_tstamp_precision()
+are used for creating a
+.B pcap_t
+structure to use when calling the other functions in libpcap. It is
+typically used when just using libpcap for compiling BPF code; it can
+also be used if using
+.BR pcap_dump_open(3PCAP) ,
+.BR pcap_dump(3PCAP) ,
+and
+.B pcap_dump_close(3PCAP)
+to write a savefile if there is no
+.B pcap_t
+that supplies the packets to be written.
+.PP
+.I linktype
+specifies the link-layer type for the
+.BR pcap_t .
+.PP
+.I snaplen
+specifies the snapshot length for the
+.BR pcap_t .
+.PP
+When
+.BR pcap_open_dead_with_tstamp_precision() ,
+is used to create a
+.B pcap_t
+for use with
+.BR pcap_dump_open() ,
+.I precision
+specifies the time stamp precision for packets;
+.B PCAP_TSTAMP_PRECISION_MICRO
+should be specified if the packets to be written have time stamps in
+seconds and microseconds, and
+.B PCAP_TSTAMP_PRECISION_NANO
+should be specified if the packets to be written have time stamps in
+seconds and nanoseconds. Its value does not affect
+.BR pcap_compile(3PCAP) .
+.SH SEE ALSO
+pcap(3PCAP), \%pcap-linktype(@MAN_MISC_INFO@)
diff --git a/lib/libpcap/libpcap/pcap_open_live.3pcap b/lib/libpcap/libpcap/pcap_open_live.3pcap
new file mode 100644
index 0000000..3286e29
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_open_live.3pcap
@@ -0,0 +1,90 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_LIVE 3PCAP "6 December 2017"
+.SH NAME
+pcap_open_live \- open a device for capturing
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_live(const char *device, int snaplen,
+.ti +8
+int promisc, int to_ms, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_live()
+is used to obtain a packet capture handle to look
+at packets on the network.
+.I device
+is a string that specifies the network device to open; on Linux systems
+with 2.2 or later kernels, a
+.I device
+argument of "any" or
+.B NULL
+can be used to capture packets from all interfaces.
+.PP
+.I snaplen
+specifies the snapshot length to be set on the handle.
+.PP
+.I promisc
+specifies if the interface is to be put into promiscuous mode.
+.PP
+.I to_ms
+specifies the packet buffer timeout, as a non-negative value, in
+milliseconds. (See
+.BR pcap (3PCAP)
+for an explanation of the packet buffer timeout.)
+.SH RETURN VALUE
+.B pcap_open_live()
+returns a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+may also be set to warning text when
+.B pcap_open_live()
+succeeds; to detect this case the caller should store a zero-length string in
+.I errbuf
+before calling
+.B pcap_open_live()
+and display the warning to the user if
+.I errbuf
+is no longer a zero-length string.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_open_offline.3pcap b/lib/libpcap/libpcap/pcap_open_offline.3pcap
new file mode 100644
index 0000000..b50cea4
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_open_offline.3pcap
@@ -0,0 +1,116 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_OFFLINE 3PCAP "8 January 2018 "
+.SH NAME
+pcap_open_offline, pcap_open_offline_with_tstamp_precision,
+pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_offline(const char *fname, char *errbuf);
+pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname,
+ u_int precision, char *errbuf);
+pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
+pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp,
+ u_int precision, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_offline()
+and
+.B pcap_open_offline_with_tstamp_precision()
+are called to open a ``savefile'' for reading.
+.PP
+.I fname
+specifies the name of the file to open. The file can have the pcap file
+format as described in
+.BR pcap-savefile (5),
+which is the file format used by, among other programs,
+.BR tcpdump (1)
+and
+.BR tcpslice (1),
+or can have the pcapng file format, although not all pcapng files can
+be read.
+The name "-" is a synonym for
+.BR stdin .
+.PP
+.B pcap_open_offline_with_tstamp_precision()
+takes an additional
+.I precision
+argument specifying the time stamp precision desired;
+if
+.B PCAP_TSTAMP_PRECISION_MICRO
+is specified, packet time stamps will be supplied in seconds and
+microseconds,
+and if
+.B PCAP_TSTAMP_PRECISION_NANO
+is specified, packet time stamps will be supplied in seconds and
+nanoseconds. If the time stamps in the file do not have the same
+precision as the requested precision, they will be scaled up or down as
+necessary before being supplied.
+.PP
+Alternatively, you may call
+.B pcap_fopen_offline()
+or
+.B pcap_fopen_offline_with_tstamp_precision()
+to read dumped data from an existing open stream
+.IR fp .
+.B pcap_fopen_offline_with_tstamp_precision()
+takes an additional
+.I precision
+argument as described above.
+Note that on Windows, that stream should be opened in binary mode.
+.SH RETURN VALUE
+.BR pcap_open_offline() ,
+.BR pcap_open_offline_with_tstamp_precision() ,
+.BR pcap_fopen_offline() ,
+and
+.B pcap_fopen_offline_with_tstamp_precision()
+return a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH BACKWARD COMPATIBILITY
+.B pcap_open_offline_with_tstamp_precision
+and
+.B pcap_fopen_offline_with_tstamp_precision
+became available in libpcap release 1.5.1. In previous releases, time
+stamps from a savefile are always given in seconds and microseconds.
+.SH SEE ALSO
+pcap(3PCAP), pcap-savefile(5)
diff --git a/lib/libpcap/libpcap/pcap_open_offline.3pcap.in b/lib/libpcap/libpcap/pcap_open_offline.3pcap.in
new file mode 100644
index 0000000..2bfbbac
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_open_offline.3pcap.in
@@ -0,0 +1,116 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_OPEN_OFFLINE 3PCAP "8 January 2018 "
+.SH NAME
+pcap_open_offline, pcap_open_offline_with_tstamp_precision,
+pcap_fopen_offline, pcap_fopen_offline_with_tstamp_precision \- open a saved capture file for reading
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+pcap_t *pcap_open_offline(const char *fname, char *errbuf);
+pcap_t *pcap_open_offline_with_tstamp_precision(const char *fname,
+ u_int precision, char *errbuf);
+pcap_t *pcap_fopen_offline(FILE *fp, char *errbuf);
+pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *fp,
+ u_int precision, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_open_offline()
+and
+.B pcap_open_offline_with_tstamp_precision()
+are called to open a ``savefile'' for reading.
+.PP
+.I fname
+specifies the name of the file to open. The file can have the pcap file
+format as described in
+.BR pcap-savefile (@MAN_FILE_FORMATS@),
+which is the file format used by, among other programs,
+.BR tcpdump (1)
+and
+.BR tcpslice (1),
+or can have the pcapng file format, although not all pcapng files can
+be read.
+The name "-" is a synonym for
+.BR stdin .
+.PP
+.B pcap_open_offline_with_tstamp_precision()
+takes an additional
+.I precision
+argument specifying the time stamp precision desired;
+if
+.B PCAP_TSTAMP_PRECISION_MICRO
+is specified, packet time stamps will be supplied in seconds and
+microseconds,
+and if
+.B PCAP_TSTAMP_PRECISION_NANO
+is specified, packet time stamps will be supplied in seconds and
+nanoseconds. If the time stamps in the file do not have the same
+precision as the requested precision, they will be scaled up or down as
+necessary before being supplied.
+.PP
+Alternatively, you may call
+.B pcap_fopen_offline()
+or
+.B pcap_fopen_offline_with_tstamp_precision()
+to read dumped data from an existing open stream
+.IR fp .
+.B pcap_fopen_offline_with_tstamp_precision()
+takes an additional
+.I precision
+argument as described above.
+Note that on Windows, that stream should be opened in binary mode.
+.SH RETURN VALUE
+.BR pcap_open_offline() ,
+.BR pcap_open_offline_with_tstamp_precision() ,
+.BR pcap_fopen_offline() ,
+and
+.B pcap_fopen_offline_with_tstamp_precision()
+return a
+.I pcap_t *
+on success and
+.B NULL
+on failure.
+If
+.B NULL
+is returned,
+.I errbuf
+is filled in with an appropriate error message.
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH BACKWARD COMPATIBILITY
+.B pcap_open_offline_with_tstamp_precision
+and
+.B pcap_fopen_offline_with_tstamp_precision
+became available in libpcap release 1.5.1. In previous releases, time
+stamps from a savefile are always given in seconds and microseconds.
+.SH SEE ALSO
+pcap(3PCAP), pcap-savefile(@MAN_FILE_FORMATS@)
diff --git a/lib/libpcap/libpcap/pcap_set_buffer_size.3pcap b/lib/libpcap/libpcap/pcap_set_buffer_size.3pcap
new file mode 100644
index 0000000..684f739
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_buffer_size.3pcap
@@ -0,0 +1,45 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_BUFFER_SIZE 3PCAP "3 January 2014"
+.SH NAME
+pcap_set_buffer_size \- set the buffer size for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_buffer_size(pcap_t *p, int buffer_size);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_buffer_size()
+sets the buffer size that will be used on a capture handle when
+the handle is activated to
+.IR buffer_size ,
+which is in units of bytes.
+.SH RETURN VALUE
+.B pcap_set_buffer_size()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_datalink.3pcap b/lib/libpcap/libpcap/pcap_set_datalink.3pcap
new file mode 100644
index 0000000..66cfdb1
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_datalink.3pcap
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_DATALINK 3PCAP "25 July 2018"
+.SH NAME
+pcap_set_datalink \- set the link-layer header type to be used by a
+capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_datalink(pcap_t *p, int dlt);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_datalink()
+is used to set the current link-layer header type of the pcap descriptor
+to the type specified by
+.IR dlt .
+.SH RETURN VALUE
+.B pcap_set_datalink()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP), pcap_datalink_name_to_val(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap b/lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap
new file mode 100644
index 0000000..93a2797
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap
@@ -0,0 +1,95 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "22 August 2018"
+.SH NAME
+pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
+handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_immediate_mode(pcap_t *p, int immediate_mode);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_immediate_mode()
+sets whether immediate mode should be set on a capture handle when
+the handle is activated. In immediate mode, packets are always
+delivered as soon as they arrive, with no buffering.
+If
+.I immediate_mode
+is non-zero, immediate mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_immediate_mode()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.5.0. In previous
+releases, if immediate delivery of packets is required:
+.IP
+on FreeBSD, NetBSD, OpenBSD, DragonFly BSD, macOS, and Solaris 11,
+immediate mode must be turned on with a
+.B BIOCIMMEDIATE
+.BR ioctl (2),
+as documented in
+.BR bpf(4) ,
+on the descriptor returned by
+.B pcap_fileno(3PCAP),
+after
+.BR pcap_activate(3PCAP)
+is called;
+.IP
+on Solaris 10 and earlier versions of Solaris, immediate mode must be
+turned on by using a read timeout of 0 when opening the device (this
+will not provide immediate delivery of packets on other platforms, so
+don't assume it's sufficient);
+.IP
+on Digital UNIX/Tru64 UNIX, immediate mode must be turned on by doing a
+.B BIOCMBIC
+.BR ioctl ,
+as documented in
+.BR packetfilter(7) ,
+to clear the
+.B ENBATCH
+flag on the descriptor returned by
+.B pcap_fileno(3PCAP),
+after
+.BR pcap_activate(3PCAP)
+is called;
+.IP
+on Windows, immediate mode must be turned on by calling
+.B pcap_setmintocopy()
+with a size of 0.
+.PP
+On Linux, with previous releases of libpcap, capture devices are always
+in immediate mode; however, in 1.5.0 and later, they are, by default,
+.B not
+in immediate mode, so if
+.B pcap_set_immediate_mode()
+is available, it should be used.
+.PP
+On other platforms, capture devices are always in immediate mode.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap.in b/lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap.in
new file mode 100644
index 0000000..2fe45c5
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_immediate_mode.3pcap.in
@@ -0,0 +1,95 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_IMMEDIATE_MODE 3PCAP "22 August 2018"
+.SH NAME
+pcap_set_immediate_mode \- set immediate mode for a not-yet-activated capture
+handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_immediate_mode(pcap_t *p, int immediate_mode);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_immediate_mode()
+sets whether immediate mode should be set on a capture handle when
+the handle is activated. In immediate mode, packets are always
+delivered as soon as they arrive, with no buffering.
+If
+.I immediate_mode
+is non-zero, immediate mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_immediate_mode()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.5.0. In previous
+releases, if immediate delivery of packets is required:
+.IP
+on FreeBSD, NetBSD, OpenBSD, DragonFly BSD, macOS, and Solaris 11,
+immediate mode must be turned on with a
+.B BIOCIMMEDIATE
+.BR ioctl (2),
+as documented in
+.BR bpf(@MAN_DEVICES@) ,
+on the descriptor returned by
+.B pcap_fileno(3PCAP),
+after
+.BR pcap_activate(3PCAP)
+is called;
+.IP
+on Solaris 10 and earlier versions of Solaris, immediate mode must be
+turned on by using a read timeout of 0 when opening the device (this
+will not provide immediate delivery of packets on other platforms, so
+don't assume it's sufficient);
+.IP
+on Digital UNIX/Tru64 UNIX, immediate mode must be turned on by doing a
+.B BIOCMBIC
+.BR ioctl ,
+as documented in
+.BR packetfilter(7) ,
+to clear the
+.B ENBATCH
+flag on the descriptor returned by
+.B pcap_fileno(3PCAP),
+after
+.BR pcap_activate(3PCAP)
+is called;
+.IP
+on Windows, immediate mode must be turned on by calling
+.B pcap_setmintocopy()
+with a size of 0.
+.PP
+On Linux, with previous releases of libpcap, capture devices are always
+in immediate mode; however, in 1.5.0 and later, they are, by default,
+.B not
+in immediate mode, so if
+.B pcap_set_immediate_mode()
+is available, it should be used.
+.PP
+On other platforms, capture devices are always in immediate mode.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_promisc.3pcap b/lib/libpcap/libpcap/pcap_set_promisc.3pcap
new file mode 100644
index 0000000..fcd797a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_promisc.3pcap
@@ -0,0 +1,46 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_PROMISC 3PCAP "3 January 2014"
+.SH NAME
+pcap_set_promisc \- set promiscuous mode for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_promisc(pcap_t *p, int promisc);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_promisc()
+sets whether promiscuous mode should be set on a capture handle when
+the handle is activated.
+If
+.I promisc
+is non-zero, promiscuous mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_promisc()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_protocol_linux.3pcap b/lib/libpcap/libpcap/pcap_set_protocol_linux.3pcap
new file mode 100644
index 0000000..873017b
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_protocol_linux.3pcap
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_PROTOCOL_LINUX 3PCAP "24 August 2017"
+.SH NAME
+pcap_set_protocol_linux \- set capture protocol for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_protocol_linux(pcap_t *p, int protocol);
+.ft
+.fi
+.SH DESCRIPTION
+On network interface devices on Linux,
+.B pcap_set_protocol_linux()
+sets the protocol to be used in the
+.BR socket (2)
+call to create a capture socket when the handle is activated. The
+argument is a link-layer protocol value, such as the values in the
+.B <linux/if_ether.h>
+header file, specified in host byte order.
+If
+.I protocol
+is non-zero, packets of that protocol will be captured when the
+handle is activated, otherwise, all packets will be captured. This
+function is only provided on Linux, and, if it is used on any device
+other than a network interface, it will have no effect.
+.LP
+It should not be used in portable code; instead, a filter should be
+specified with
+.BR pcap_setfilter(3PCAP) .
+.LP
+If a given network interface provides a standard link-layer header, with
+a standard packet type, but provides some packet types with a different
+socket-layer protocol type from the one in the link-layer header, that
+packet type cannot be filtered with a filter specified with
+.B pcap_setfilter()
+but can be filtered by specifying the socket-layer protocol type using
+.BR pcap_set_protocol_linux() .
+.SH RETURN VALUE
+.B pcap_set_protocol_linux()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.9.0.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_rfmon.3pcap b/lib/libpcap/libpcap/pcap_set_rfmon.3pcap
new file mode 100644
index 0000000..691518a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_rfmon.3pcap
@@ -0,0 +1,47 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_RFMON 3PCAP "3 January 2014"
+.SH NAME
+pcap_set_rfmon \- set monitor mode for a not-yet-activated capture
+handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_rfmon(pcap_t *p, int rfmon);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_rfmon()
+sets whether monitor mode should be set on a capture handle when
+the handle is activated.
+If
+.I rfmon
+is non-zero, monitor mode will be set, otherwise it will not be set.
+.SH RETURN VALUE
+.B pcap_set_rfmon()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP),
+pcap_can_set_rfmon(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_snaplen.3pcap b/lib/libpcap/libpcap/pcap_set_snaplen.3pcap
new file mode 100644
index 0000000..44eb154
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_snaplen.3pcap
@@ -0,0 +1,44 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_SNAPLEN 3PCAP "3 January 2014"
+.SH NAME
+pcap_set_snaplen \- set the snapshot length for a not-yet-activated
+capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_snaplen(pcap_t *p, int snaplen);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_snaplen()
+sets the snapshot length to be used on a capture handle when the handle
+is activated to
+.IR snaplen .
+.SH RETURN VALUE
+.B pcap_set_snaplen()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap(3PCAP), pcap_create(3PCAP), pcap_activate(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_timeout.3pcap b/lib/libpcap/libpcap/pcap_set_timeout.3pcap
new file mode 100644
index 0000000..e67b813
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_timeout.3pcap
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_TIMEOUT 3PCAP "6 December 2017"
+.SH NAME
+pcap_set_timeout \- set the packet buffer timeout for a
+not-yet-activated capture handle
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.LP
+.ft B
+int pcap_set_timeout(pcap_t *p, int to_ms);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_timeout()
+sets the packet buffer timeout that will be used on a capture handle
+when the handle is activated to
+.IR to_ms ,
+which is in units of milliseconds. (See
+.BR pcap (3PCAP)
+for an explanation of the packet buffer timeout.)
+.LP
+The behavior, if the timeout isn't specified, is undefined, as is the
+behavior if the timeout is set to zero or to a negative value. We
+recommend always setting the timeout to a non-zero value unless
+immediate mode is set, in which case the timeout has no effect.
+.SH RETURN VALUE
+.B pcap_set_timeout()
+returns 0 on success or
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH SEE ALSO
+pcap_create(3PCAP), pcap_activate(3PCAP),
+\%pcap_set_immediate_mode(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap b/lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap
new file mode 100644
index 0000000..0600354
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap
@@ -0,0 +1,66 @@
+.\"Copyright (c) 2013, Michal Sekletar
+.\"All rights reserved.
+.\"
+.\"Redistribution and use in source and binary forms, with or without
+.\"modification, are permitted provided that the following conditions
+.\"are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\" products derived from this software without specific prior
+.\" written permission.
+.\"
+.\"THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "5 February 2015"
+.SH NAME
+pcap_set_tstamp_precision \- set the time stamp precision returned in
+captures
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_tstamp_precision()
+sets the precision of the time stamp desired for packets captured on the pcap
+descriptor to the type specified by
+.IR tstamp_precision .
+It must be called on a pcap descriptor created by
+.B pcap_create(3PCAP)
+that has not yet been activated by
+.BR pcap_activate(3PCAP) .
+Two time stamp precisions are supported, microseconds and nanoseconds. One can
+use options
+.B PCAP_TSTAMP_PRECISION_MICRO and
+.B PCAP_TSTAMP_PRECISION_NANO
+to request desired precision. By default, time stamps are in microseconds.
+.SH RETURN VALUE
+.B pcap_set_tstamp_precision()
+returns 0 on success if the specified time stamp precision is expected to be
+supported by the capture device,
+.B PCAP_ERROR_TSTAMP_PRECISION_NOTSUP
+if the capture device does not support the requested time stamp
+precision,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1. In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_get_tstamp_precision(3PCAP),
+pcap-tstamp(7)
diff --git a/lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap.in b/lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap.in
new file mode 100644
index 0000000..dc2b4b3
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_tstamp_precision.3pcap.in
@@ -0,0 +1,66 @@
+.\"Copyright (c) 2013, Michal Sekletar
+.\"All rights reserved.
+.\"
+.\"Redistribution and use in source and binary forms, with or without
+.\"modification, are permitted provided that the following conditions
+.\"are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\" 3. The names of the authors may not be used to endorse or promote
+.\" products derived from this software without specific prior
+.\" written permission.
+.\"
+.\"THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+.\"IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+.\"WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+.TH PCAP_SET_TSTAMP_PRECISION 3PCAP "5 February 2015"
+.SH NAME
+pcap_set_tstamp_precision \- set the time stamp precision returned in
+captures
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_tstamp_precision(pcap_t *p, int tstamp_precision);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_tstamp_precision()
+sets the precision of the time stamp desired for packets captured on the pcap
+descriptor to the type specified by
+.IR tstamp_precision .
+It must be called on a pcap descriptor created by
+.B pcap_create(3PCAP)
+that has not yet been activated by
+.BR pcap_activate(3PCAP) .
+Two time stamp precisions are supported, microseconds and nanoseconds. One can
+use options
+.B PCAP_TSTAMP_PRECISION_MICRO and
+.B PCAP_TSTAMP_PRECISION_NANO
+to request desired precision. By default, time stamps are in microseconds.
+.SH RETURN VALUE
+.B pcap_set_tstamp_precision()
+returns 0 on success if the specified time stamp precision is expected to be
+supported by the capture device,
+.B PCAP_ERROR_TSTAMP_PRECISION_NOTSUP
+if the capture device does not support the requested time stamp
+precision,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated.
+.SH BACKWARD COMPATIBILITY
+This function became available in libpcap release 1.5.1. In previous
+releases, time stamps from a capture device or savefile are always given
+in seconds and microseconds.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_get_tstamp_precision(3PCAP),
+pcap-tstamp(@MAN_MISC_INFO@)
diff --git a/lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap b/lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap
new file mode 100644
index 0000000..4754278
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap
@@ -0,0 +1,70 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_TSTAMP_TYPE 3PCAP "22 August 2018"
+.SH NAME
+pcap_set_tstamp_type \- set the time stamp type to be used by a
+capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_tstamp_type(pcap_t *p, int tstamp_type);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_tstamp_type()
+sets the type of time stamp desired for packets captured on the pcap
+descriptor to the type specified by
+.IR tstamp_type .
+It must be called on a pcap descriptor created by
+.B pcap_create(3PCAP)
+that has not yet been activated by
+.BR pcap_activate(3PCAP) .
+.B pcap_list_tstamp_types(3PCAP)
+will give a list of the time stamp types supported by a given capture
+device.
+See
+.BR pcap-tstamp (7)
+for a list of all the time stamp types.
+.SH RETURN VALUE
+.B pcap_set_tstamp_type()
+returns 0 on success if the specified time stamp type is expected to be
+supported by the capture device,
+.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
+if the specified time stamp type is not supported by the
+capture device,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated, and
+.B PCAP_ERROR_CANTSET_TSTAMP_TYPE
+if the capture device doesn't support setting the time stamp type (only
+older versions of libpcap will return that; newer versions will always
+allow the time stamp type to be set to the default type).
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.2.1. In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_tstamp_type_name_to_val(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap.in b/lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap.in
new file mode 100644
index 0000000..9833f46
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_set_tstamp_type.3pcap.in
@@ -0,0 +1,70 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SET_TSTAMP_TYPE 3PCAP "22 August 2018"
+.SH NAME
+pcap_set_tstamp_type \- set the time stamp type to be used by a
+capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_set_tstamp_type(pcap_t *p, int tstamp_type);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_set_tstamp_type()
+sets the type of time stamp desired for packets captured on the pcap
+descriptor to the type specified by
+.IR tstamp_type .
+It must be called on a pcap descriptor created by
+.B pcap_create(3PCAP)
+that has not yet been activated by
+.BR pcap_activate(3PCAP) .
+.B pcap_list_tstamp_types(3PCAP)
+will give a list of the time stamp types supported by a given capture
+device.
+See
+.BR pcap-tstamp (@MAN_MISC_INFO@)
+for a list of all the time stamp types.
+.SH RETURN VALUE
+.B pcap_set_tstamp_type()
+returns 0 on success if the specified time stamp type is expected to be
+supported by the capture device,
+.B PCAP_WARNING_TSTAMP_TYPE_NOTSUP
+if the specified time stamp type is not supported by the
+capture device,
+.B PCAP_ERROR_ACTIVATED
+if called on a capture handle that has been activated, and
+.B PCAP_ERROR_CANTSET_TSTAMP_TYPE
+if the capture device doesn't support setting the time stamp type (only
+older versions of libpcap will return that; newer versions will always
+allow the time stamp type to be set to the default type).
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.2.1. In previous
+releases, the time stamp type cannot be set; only the default time stamp
+type offered by a capture source is available.
+.SH SEE ALSO
+pcap(3PCAP),
+pcap_tstamp_type_name_to_val(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_setdirection.3pcap b/lib/libpcap/libpcap/pcap_setdirection.3pcap
new file mode 100644
index 0000000..f174b98
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_setdirection.3pcap
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETDIRECTION 3PCAP "25 July 2018"
+.SH NAME
+pcap_setdirection \- set the direction for which packets will be captured
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_setdirection(pcap_t *p, pcap_direction_t d);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setdirection()
+is used to specify a direction that packets will be captured.
+.I d
+is one of the constants
+.BR PCAP_D_IN ,
+.B PCAP_D_OUT
+or
+.BR PCAP_D_INOUT .
+.B PCAP_D_IN
+will only capture packets received by the device,
+.B PCAP_D_OUT
+will only capture packets sent by the device and
+.B PCAP_D_INOUT
+will capture packets received by or sent by the device.
+.B PCAP_D_INOUT
+is the default setting if this function is not called.
+.PP
+.B pcap_setdirection()
+isn't necessarily fully supported on all platforms; some platforms might
+return an error for all values, and some other platforms might not
+support
+.BR PCAP_D_OUT .
+.PP
+This operation is not supported if a ``savefile'' is being read.
+.SH RETURN VALUE
+.B pcap_setdirection()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_setfilter.3pcap b/lib/libpcap/libpcap/pcap_setfilter.3pcap
new file mode 100644
index 0000000..8729693
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_setfilter.3pcap
@@ -0,0 +1,55 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETFILTER 3PCAP "25 July 2018"
+.SH NAME
+pcap_setfilter \- set the filter
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_setfilter(pcap_t *p, struct bpf_program *fp);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setfilter()
+is used to specify a filter program.
+.I fp
+is a pointer to a
+.I bpf_program
+struct, usually the result of a call to
+.BR \%pcap_compile(3PCAP) .
+.SH RETURN VALUE
+.B pcap_setfilter()
+returns 0 on success and
+.B PCAP_ERROR
+on failure. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_setnonblock.3pcap b/lib/libpcap/libpcap/pcap_setnonblock.3pcap
new file mode 100644
index 0000000..e8adebe
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_setnonblock.3pcap
@@ -0,0 +1,85 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SETNONBLOCK 3PCAP "25 July 2018"
+.SH NAME
+pcap_setnonblock, pcap_getnonblock \- set or get the state of
+non-blocking mode on a capture device
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.nf
+.ft B
+char errbuf[PCAP_ERRBUF_SIZE];
+.ft
+.LP
+.ft B
+int pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf);
+int pcap_getnonblock(pcap_t *p, char *errbuf);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_setnonblock()
+puts a capture handle into ``non-blocking'' mode, or takes it out
+of ``non-blocking'' mode, depending on whether the
+.I nonblock
+argument is non-zero or zero. It has no effect on ``savefiles''.
+If there is an error,
+.B PCAP_ERROR
+is returned and
+.I errbuf
+is filled in with an appropriate error message; otherwise, 0 is
+returned.
+In
+``non-blocking'' mode, an attempt to read from the capture descriptor
+with
+.B pcap_dispatch(3PCAP)
+will, if no packets are currently available to be read, return 0
+immediately rather than blocking waiting for packets to arrive.
+.B pcap_loop(3PCAP)
+and
+.B pcap_next(3PCAP)
+will not work in ``non-blocking'' mode.
+.PP
+When first activated with
+.B pcap_activate(3PCAP)
+or opened with
+.B pcap_open_live(3PCAP) ,
+a capture handle is not in ``non-blocking mode''; a call to
+.B pcap_setnonblock()
+is required in order to put it into ``non-blocking'' mode.
+.SH RETURN VALUE
+.B pcap_getnonblock()
+returns the current ``non-blocking'' state of the capture descriptor; it
+always returns 0 on ``savefiles''.
+If there is an error,
+.B PCAP_ERROR
+is returned and
+.I errbuf
+is filled in with an appropriate error message.
+.PP
+.I errbuf
+is assumed to be able to hold at least
+.B PCAP_ERRBUF_SIZE
+chars.
+.SH SEE ALSO
+pcap(3PCAP), pcap_next_ex(3PCAP), pcap_geterr(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_snapshot.3pcap b/lib/libpcap/libpcap/pcap_snapshot.3pcap
new file mode 100644
index 0000000..ee54bb0
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_snapshot.3pcap
@@ -0,0 +1,52 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_SNAPSHOT 3PCAP "7 April 2014"
+.SH NAME
+pcap_snapshot \- get the snapshot length
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_snapshot(pcap_t *p);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_snapshot()
+returns the snapshot length specified when
+.B pcap_set_snaplen(3PCAP)
+or
+.B pcap_open_live(3PCAP)
+was called, for a live capture, or the snapshot length from the capture
+file, for a ``savefile''.
+.PP
+It must not be called on a pcap descriptor created by
+.B \%pcap_create(3PCAP)
+that has not yet been activated by
+.BR \%pcap_activate(3PCAP) .
+.SH RETURN VALUE
+.B pcap_snapshot()
+returns the snapshot length on success and
+.B PCAP_ERROR_NOT_ACTIVATED
+if called on a capture handle that has been created but not activated.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_stats.3pcap b/lib/libpcap/libpcap/pcap_stats.3pcap
new file mode 100644
index 0000000..465dada
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_stats.3pcap
@@ -0,0 +1,100 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STATS 3PCAP "25 July 2018"
+.SH NAME
+pcap_stats \- get capture statistics
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_stats(pcap_t *p, struct pcap_stat *ps);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_stats()
+fills in the
+.B struct pcap_stat
+pointed to by its second argument. The values represent
+packet statistics from the start of the run to the time of the call.
+.PP
+.B pcap_stats()
+is supported only on live captures, not on ``savefiles''; no statistics
+are stored in ``savefiles'', so no statistics are available when reading
+from a ``savefile''.
+.PP
+A
+.B struct pcap_stat
+has the following members:
+.RS
+.TP
+.B ps_recv
+number of packets received;
+.TP
+.B ps_drop
+number of packets dropped because there was no room in the operating
+system's buffer when they arrived, because packets weren't being read
+fast enough;
+.TP
+.B ps_ifdrop
+number of packets dropped by the network interface or its driver.
+.RE
+.PP
+The statistics do not behave the same way on all platforms.
+.B ps_recv
+might count packets whether they passed any filter set with
+.BR pcap_setfilter (3PCAP)
+or not, or it might count only packets that pass the filter.
+It also might, or might not, count packets dropped because there was no
+room in the operating system's buffer when they arrived.
+.B ps_drop
+is not available on all platforms; it is zero on platforms where it's
+not available. If packet filtering is done in libpcap, rather than in
+the operating system, it would count packets that don't pass the filter.
+Both
+.B ps_recv
+and
+.B ps_drop
+might, or might not, count packets not yet read from the operating
+system and thus not yet seen by the application.
+.B ps_ifdrop
+might, or might not, be implemented; if it's zero, that might mean that
+no packets were dropped by the interface, or it might mean that the
+statistic is unavailable, so it should not be treated as an indication
+that the interface did not drop any packets.
+.SH RETURN VALUE
+.B pcap_stats()
+returns 0 on success and returns
+.B PCAP_ERROR
+if there is an error or if
+.I p
+doesn't support packet statistics. If
+.B PCAP_ERROR
+is returned,
+.B pcap_geterr(3PCAP)
+or
+.B pcap_perror(3PCAP)
+may be called with
+.I p
+as an argument to fetch or display the error text.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_statustostr.3pcap b/lib/libpcap/libpcap/pcap_statustostr.3pcap
new file mode 100644
index 0000000..9c2057a
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_statustostr.3pcap
@@ -0,0 +1,41 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STATUSTOSTR 3PCAP "3 January 2014"
+.SH NAME
+pcap_statustostr \- convert a PCAP_ERROR_ or PCAP_WARNING_ value to a string
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_statustostr(int error);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_statustostr()
+converts a
+.B PCAP_ERROR_
+or
+.B PCAP_WARNING_
+value returned by a libpcap routine to an error string.
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_strerror.3pcap b/lib/libpcap/libpcap/pcap_strerror.3pcap
new file mode 100644
index 0000000..a5775f4
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_strerror.3pcap
@@ -0,0 +1,40 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_STRERROR 3PCAP "3 January 2014"
+.SH NAME
+pcap_strerror \- convert an errno value to a string
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_strerror(int error);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_strerror()
+is provided in case
+.BR strerror (3)
+isn't available. It returns an error message string corresponding to
+.IR error .
+.SH SEE ALSO
+pcap(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_tstamp_type_name_to_val.3pcap b/lib/libpcap/libpcap/pcap_tstamp_type_name_to_val.3pcap
new file mode 100644
index 0000000..fdcc6c6
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_tstamp_type_name_to_val.3pcap
@@ -0,0 +1,48 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_TSTAMP_TYPE_NAME_TO_VAL 3PCAP "22 August 2018"
+.SH NAME
+pcap_tstamp_type_name_to_val \- get the time stamp type value
+corresponding to a time stamp type name
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap/pcap.h>
+.ft
+.LP
+.ft B
+int pcap_tstamp_type_name_to_val(const char *name);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_tstamp_type_name_to_val()
+translates a time stamp type name to the corresponding time stamp type
+value. The translation is case-insensitive.
+.SH RETURN VALUE
+.B pcap_tstamp_type_name_to_val()
+returns time stamp type value on success and
+.B PCAP_ERROR
+on failure.
+.SH BACKWARD COMPATIBILITY
+.PP
+This function became available in libpcap release 1.2.1.
+.SH SEE ALSO
+pcap(3PCAP), pcap_tstamp_type_val_to_name(3PCAP)
diff --git a/lib/libpcap/libpcap/pcap_tstamp_type_val_to_name.3pcap b/lib/libpcap/libpcap/pcap_tstamp_type_val_to_name.3pcap
new file mode 100644
index 0000000..9374f48
--- /dev/null
+++ b/lib/libpcap/libpcap/pcap_tstamp_type_val_to_name.3pcap
@@ -0,0 +1,52 @@
+.\"
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH PCAP_TSTAMP_TYPE_VAL_TO_NAME 3PCAP "22 August 2018"
+.SH NAME
+pcap_tstamp_type_val_to_name, pcap_tstamp_type_val_to_description \- get
+a name or description for a time stamp type value
+.SH SYNOPSIS
+.nf
+.ft B
+#include <pcap.h>
+.ft
+.LP
+.ft B
+const char *pcap_tstamp_type_val_to_name(int tstamp_type);
+const char *pcap_tstamp_type_val_to_description(int tstamp_type);
+.ft
+.fi
+.SH DESCRIPTION
+.B pcap_tstamp_type_val_to_name()
+translates a time stamp type value to the corresponding time stamp type
+name.
+.B NULL
+is returned on failure.
+.PP
+.B pcap_tstamp_type_val_to_description()
+translates a time stamp type value to a short description of that time
+stamp type.
+.B NULL
+is returned on failure.
+.SH BACKWARD COMPATIBILITY
+.PP
+These functions became available in libpcap release 1.2.1.
+.SH SEE ALSO
+pcap(3PCAP), pcap_tstamp_type_name_to_val(3PCAP)
diff --git a/lib/libpcap/libpcap/pcapng-private.h b/lib/libpcap/libpcap/pcapng-private.h
new file mode 100644
index 0000000..221c52c
--- /dev/null
+++ b/lib/libpcap/libpcap/pcapng-private.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2012-2015 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifndef libpcapng_pcapng_private_h
+#define libpcapng_pcapng_private_h
+
+#include <sys/queue.h>
+
+#include "pcap/pcap-ng.h"
+
+struct pcapng_block {
+ u_char *pcapng_bufptr;
+ size_t pcapng_buflen;
+ int pcapng_buf_is_external;
+
+ uint32_t pcapng_block_type;
+ size_t pcapng_block_len;
+ int pcapng_block_swapped;
+
+ size_t pcapng_fields_len;
+
+ u_char *pcapng_data_ptr;
+ size_t pcapng_data_len;
+ u_int32_t pcapng_cap_len;
+ int pcapng_data_is_external;
+
+ size_t pcapng_records_len;
+ size_t pcapng_options_len;
+
+ union {
+ struct pcapng_section_header_fields _section_header;
+ struct pcapng_interface_description_fields _interface_description;
+ struct pcapng_packet_fields _packet;
+ struct pcapng_simple_packet_fields _simple_packet;
+ struct pcapng_interface_statistics_fields _interface_statistics;
+ struct pcapng_enhanced_packet_fields _enhanced_packet;
+ struct pcapng_process_information_fields _process_information;
+ struct pcapng_os_event_fields _os_event_information;
+ struct pcapng_decryption_secrets_fields _decryption_secrets;
+ } block_fields_;
+};
+
+#define pcap_ng_shb_fields block_fields_._section_header
+#define pcap_ng_idb_fields block_fields_._interface_description
+#define pcap_ng_opb_fields block_fields_._packet
+#define pcap_ng_spb_fields block_fields_._simple_packet
+#define pcap_ng_isb_fields block_fields_._interface_statistics
+#define pcap_ng_epb_fields block_fields_._enhanced_packet
+#define pcap_ng_pib_fields block_fields_._process_information
+#define pcap_ng_osev_fields block_fields_._os_event_information
+#define pcap_ng_dsb_fields block_fields_._decryption_secrets
+
+/* Representation of on file data structure items */
+#define PCAPNG_BYTE_ORDER_MAGIC 0x1A2B3C4D
+#define PCAPNG_MAJOR_VERSION 1
+#define PCAPNG_MINOR_VERSION 0
+
+#endif
diff --git a/lib/libpcap/libpcap/pcapng.c b/lib/libpcap/libpcap/pcapng.c
new file mode 100644
index 0000000..1f1dfd0
--- /dev/null
+++ b/lib/libpcap/libpcap/pcapng.c
@@ -0,0 +1,1405 @@
+/*
+ * Copyright (c) 2012-2015 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <err.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <sys/uio.h>
+#include "pcapng-private.h"
+
+#include "pcap-int.h"
+#include "pcap-common.h"
+#include "sf-pcapng.h"
+#include "pcap-util.h"
+
+/*
+ * Block cursor - used when processing the contents of a block.
+ * Contains a pointer into the data being processed and a count
+ * of bytes remaining in the block.
+ */
+struct block_cursor {
+ u_char *data;
+ size_t data_remaining;
+ bpf_u_int32 block_type;
+};
+
+
+#define PAD_32BIT(x) ((x + 3) & ~3)
+#define PAD_64BIT(x) ((x + 7) & ~7)
+#define PADDED_OPTION_LEN(x) ((x) ? PAD_32BIT(x) + sizeof(struct pcapng_option_header) : 0)
+
+
+void *
+pcap_ng_block_header_ptr(pcapng_block_t block)
+{
+ return (block->pcapng_bufptr);
+}
+
+void *
+pcap_ng_block_fields_ptr(pcapng_block_t block)
+{
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header));
+}
+
+void *
+pcap_ng_block_data_ptr(pcapng_block_t block)
+{
+ if (block->pcapng_data_is_external)
+ return (block->pcapng_data_ptr);
+ else
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len);
+}
+
+void *
+pcap_ng_block_records_ptr(pcapng_block_t block)
+{
+ if (block->pcapng_block_type != PCAPNG_BT_NRB)
+ return (NULL);
+
+ if (block->pcapng_data_is_external)
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len);
+ else
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len +
+ block->pcapng_data_len);
+}
+
+void *
+pcap_ng_block_options_ptr(pcapng_block_t block)
+{
+ if (block->pcapng_block_type == PCAPNG_BT_SPB)
+ return (NULL);
+
+ if (block->pcapng_data_is_external)
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len +
+ block->pcapng_records_len);
+ else
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len +
+ block->pcapng_data_len +
+ block->pcapng_records_len);
+}
+
+void *
+pcap_ng_block_trailer_ptr(pcapng_block_t block)
+{
+ if (block->pcapng_data_is_external)
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len +
+ block->pcapng_records_len +
+ block->pcapng_options_len);
+ else
+ return (block->pcapng_bufptr +
+ sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len +
+ block->pcapng_data_len +
+ block->pcapng_records_len +
+ block->pcapng_options_len);
+}
+
+pcapng_block_t
+pcap_ng_block_alloc(size_t len)
+{
+ size_t totallen;
+ u_char *ptr;
+ struct pcapng_block *block;
+
+ if (len > pcap_ng_block_size_max())
+ return (NULL);
+
+ /*
+ * The internal block structure is prepended
+ */
+ totallen = PAD_64BIT(sizeof(struct pcapng_block)) + len;
+ ptr = malloc(totallen);
+ if (ptr == NULL)
+ return (NULL);
+
+ block = (struct pcapng_block *)ptr;
+ bzero(block, sizeof(struct pcapng_block));
+
+ block->pcapng_bufptr = ptr + PAD_64BIT(sizeof(struct pcapng_block));
+ block->pcapng_buflen = len;
+
+ return (block);
+}
+
+size_t
+pcap_ng_block_size_max()
+{
+ return (2 * MAXIMUM_SNAPLEN);
+}
+
+void
+pcap_ng_free_block(pcapng_block_t block)
+{
+ free(block);
+}
+
+bpf_u_int32
+pcap_ng_block_get_type(pcapng_block_t block)
+{
+ return (block->pcapng_block_type);
+}
+
+bpf_u_int32
+pcap_ng_block_get_len(pcapng_block_t block)
+{
+ return ((bpf_u_int32)block->pcapng_block_len);
+}
+
+int
+pcap_ng_block_is_swapped(pcapng_block_t block)
+{
+ return (block->pcapng_block_swapped);
+}
+
+int
+pcapng_update_block_length(pcapng_block_t block)
+{
+ block->pcapng_block_len = sizeof(struct pcapng_block_header) +
+ block->pcapng_fields_len +
+ block->pcapng_data_len +
+ block->pcapng_records_len +
+ block->pcapng_options_len +
+ sizeof(struct pcapng_block_trailer);
+
+ if (block->pcapng_block_len > block->pcapng_buflen) {
+ errx(EX_SOFTWARE, "%s block len %lu greater than buffer size %lu",
+ __func__, block->pcapng_block_len, block->pcapng_buflen);
+ }
+
+ return (0);
+}
+
+int
+pcap_ng_block_reset(pcapng_block_t block, bpf_u_int32 type)
+{
+ bzero(&block->block_fields_, sizeof(block->block_fields_));
+
+ switch (type) {
+ case PCAPNG_BT_SHB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_section_header_fields);
+
+ block->pcap_ng_shb_fields.byte_order_magic = PCAPNG_BYTE_ORDER_MAGIC;
+ block->pcap_ng_shb_fields.major_version = PCAPNG_VERSION_MAJOR;
+ block->pcap_ng_shb_fields.minor_version = PCAPNG_VERSION_MINOR;
+ block->pcap_ng_shb_fields.section_length = (uint64_t)-1;
+ break;
+
+ case PCAPNG_BT_IDB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_interface_description_fields);
+ break;
+
+ case PCAPNG_BT_PB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_packet_fields);
+ break;
+
+ case PCAPNG_BT_SPB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_simple_packet_fields);
+ break;
+
+ case PCAPNG_BT_NRB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = 0;
+ break;
+
+ case PCAPNG_BT_ISB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_interface_statistics_fields);
+ break;
+
+ case PCAPNG_BT_EPB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_enhanced_packet_fields);
+ break;
+
+ case PCAPNG_BT_PIB:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_process_information_fields);
+ break;
+
+ case PCAPNG_BT_OSEV:
+ block->pcapng_block_type = type;
+ block->pcapng_fields_len = sizeof(struct pcapng_os_event_fields);
+ break;
+
+ case PCAPNG_BT_DSB:
+ block->pcapng_block_type = PCAPNG_BT_DSB;
+ block->pcapng_fields_len = sizeof(struct pcapng_decryption_secrets_fields);
+ break;
+
+ default:
+ return (PCAP_ERROR);
+ }
+
+ block->pcapng_data_ptr = NULL;
+ block->pcapng_data_len = 0;
+ block->pcapng_cap_len = 0;
+ block->pcapng_data_is_external = 0;
+
+ block->pcapng_records_len = 0;
+
+ block->pcapng_options_len = 0;
+
+ pcapng_update_block_length(block);
+
+ return (0);
+}
+
+struct pcapng_section_header_fields *
+pcap_ng_get_section_header_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_SHB)
+ return &block->pcap_ng_shb_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_interface_description_fields *
+pcap_ng_get_interface_description_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_IDB)
+ return &block->pcap_ng_idb_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_enhanced_packet_fields *
+pcap_ng_get_enhanced_packet_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_EPB)
+ return &block->pcap_ng_epb_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_simple_packet_fields *
+pcap_ng_get_simple_packet_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_SPB)
+ return &block->pcap_ng_spb_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_packet_fields *
+pcap_ng_get_packet_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_PB)
+ return &block->pcap_ng_opb_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_interface_statistics_fields *
+pcap_ng_get_interface_statistics_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_ISB)
+ return &block->pcap_ng_isb_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_process_information_fields *
+pcap_ng_get_process_information_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_PIB)
+ return &block->pcap_ng_pib_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_os_event_fields *
+pcap_ng_get_os_event_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_OSEV)
+ return &block->pcap_ng_osev_fields;
+ else
+ return NULL;
+}
+
+struct pcapng_decryption_secrets_fields *
+pcap_ng_get_decryption_secrets_fields(pcapng_block_t block)
+{
+ if (block != NULL && block->pcapng_block_type == PCAPNG_BT_DSB)
+ return &block->pcap_ng_dsb_fields;
+ else
+ return NULL;
+}
+
+int
+pcap_ng_block_does_support_data(pcapng_block_t block)
+{
+ switch (block->pcapng_block_type) {
+ case PCAPNG_BT_PB:
+ case PCAPNG_BT_SPB:
+ case PCAPNG_BT_EPB:
+ case PCAPNG_BT_OSEV:
+ case PCAPNG_BT_DSB:
+ return (1);
+ /* NOT REACHED */
+
+ default:
+ break;
+ }
+ return (0);
+}
+
+void *
+pcap_ng_block_packet_get_data_ptr(pcapng_block_t block)
+{
+ if (pcap_ng_block_does_support_data(block) == 0)
+ return (NULL);
+
+ return (block->pcapng_data_ptr);
+}
+
+bpf_u_int32
+pcap_ng_block_packet_get_data_len(pcapng_block_t block)
+{
+ if (pcap_ng_block_does_support_data(block) == 0)
+ return (0);
+
+ return (block->pcapng_cap_len);
+}
+
+bpf_u_int32
+pcap_ng_block_packet_copy_data(pcapng_block_t block, const void *ptr,
+ bpf_u_int32 caplen)
+{
+ bpf_u_int32 padding_len = PAD_32BIT(caplen) - caplen;
+
+ if (pcap_ng_block_does_support_data(block) == 0)
+ return (PCAP_ERROR);
+
+ if (block->pcapng_block_len + PAD_32BIT(caplen) > block->pcapng_buflen) {
+ warnx("%s block len %lu greater than buffer size %lu",
+ __func__, block->pcapng_block_len, block->pcapng_buflen);
+ return (PCAP_ERROR);
+ }
+ /*
+ * Move the name records and options if necessary
+ */
+ if (block->pcapng_records_len > 0 || block->pcapng_options_len > 0) {
+ u_char *tmp = pcap_ng_block_records_ptr(block) ?
+ pcap_ng_block_records_ptr(block) :
+ pcap_ng_block_options_ptr(block);
+ size_t len = block->pcapng_records_len + block->pcapng_options_len;
+ int32_t offset = PAD_32BIT(caplen) - (int32_t)block->pcapng_data_len;
+
+ bcopy(tmp, tmp + offset, len);
+ }
+
+ /*
+ * TBD: if records or options exist, should move them or error out
+ */
+ block->pcapng_data_is_external = 0;
+ block->pcapng_data_ptr = pcap_ng_block_data_ptr(block);
+ bcopy(ptr, block->pcapng_data_ptr, caplen);
+ if (padding_len > 0)
+ bzero(block->pcapng_data_ptr + caplen, padding_len);
+ block->pcapng_cap_len = caplen;
+ block->pcapng_data_len = PAD_32BIT(caplen);
+
+ pcapng_update_block_length(block);
+
+ return (0);
+}
+
+bpf_u_int32
+pcap_ng_block_packet_set_data(pcapng_block_t block, const void *ptr,
+ bpf_u_int32 caplen)
+{
+ if (pcap_ng_block_does_support_data(block) == 0)
+ return (PCAP_ERROR);
+
+ block->pcapng_data_is_external = 1;
+ block->pcapng_data_ptr = (u_char *)ptr;
+ block->pcapng_cap_len = caplen;
+ block->pcapng_data_len = PAD_32BIT(caplen);
+
+ pcapng_update_block_length(block);
+
+ return (0);
+}
+
+int
+pcap_ng_block_add_option_with_value(pcapng_block_t block, u_short code,
+ const void *value, u_short value_len)
+{
+ size_t optlen = sizeof(struct pcapng_option_header) + PAD_32BIT(value_len);
+ struct pcapng_option_header *opt_header;
+ bpf_u_int32 padding_len = PAD_32BIT(value_len) - value_len;
+ u_char *buffer;
+ u_char *block_option_ptr = pcap_ng_block_options_ptr(block);
+
+ if (block_option_ptr == NULL) {
+ warnx("%s options not supported for block type %u",
+ __func__, block->pcapng_block_type);
+ return (PCAP_ERROR);
+ }
+
+ if (optlen + block->pcapng_block_len > block->pcapng_buflen) {
+ warnx("%s block len %lu greater than buffer size %lu",
+ __func__, block->pcapng_block_len, block->pcapng_buflen);
+ return (PCAP_ERROR);
+ }
+
+ opt_header = (struct pcapng_option_header *)(block_option_ptr + block->pcapng_options_len);
+ /* Insert before the end of option */
+ if (block->pcapng_options_len > 0)
+ opt_header -= 1;
+ opt_header->option_code = code;
+ opt_header->option_length = value_len;
+
+ buffer = (u_char *)(opt_header + 1);
+
+ bcopy(value, buffer, value_len);
+
+ if (padding_len > 0)
+ bzero(buffer + value_len, padding_len);
+
+ /* Add end of option when first option added */
+ if (block->pcapng_options_len == 0)
+ block->pcapng_options_len = sizeof(struct pcapng_option_header);
+
+ block->pcapng_options_len += optlen;
+
+ /* Set the end of option at the end of the options */
+ opt_header = (struct pcapng_option_header *)(block_option_ptr + block->pcapng_options_len);
+ opt_header -= 1;
+ opt_header->option_code = PCAPNG_OPT_ENDOFOPT;
+ opt_header->option_length = 0;
+
+ pcapng_update_block_length(block);
+
+ return (0);
+}
+
+int
+pcap_ng_block_add_option_with_string(pcapng_block_t block, u_short code, const char *str)
+{
+ return (pcap_ng_block_add_option_with_value(block, code, str, strlen(str) + 1));
+}
+
+int
+pcap_ng_block_add_option_with_uuid(pcapng_block_t block, u_short code, const uuid_t uu)
+{
+ return (pcap_ng_block_add_option_with_value(block, code, uu, sizeof(uuid_t)));
+}
+
+
+static struct pcapng_option_header *
+get_opthdr_from_block_data(struct pcapng_option_header *opthdr, int swapped,
+ struct block_cursor *cursor, char *errbuf)
+{
+ struct pcapng_option_header *optp;
+
+ optp = get_from_block_data(cursor, sizeof(*opthdr), errbuf);
+ if (optp == NULL) {
+ /*
+ * Option header is cut short.
+ */
+ return (NULL);
+ }
+ *opthdr = *optp;
+ /*
+ * Byte-swap it if necessary.
+ */
+ if (swapped) {
+ opthdr->option_code = SWAPSHORT(opthdr->option_code);
+ opthdr->option_length = SWAPSHORT(opthdr->option_length);
+ }
+
+ return (opthdr);
+}
+
+static void *
+get_optvalue_from_block_data(struct block_cursor *cursor,
+ struct pcapng_option_header *opthdr, char *errbuf)
+{
+ size_t padded_option_len;
+ void *optvalue;
+
+ /* Pad option length to 4-byte boundary */
+ padded_option_len = opthdr->option_length;
+ padded_option_len = ((padded_option_len + 3)/4)*4;
+
+ optvalue = get_from_block_data(cursor, padded_option_len, errbuf);
+ if (optvalue == NULL) {
+ /*
+ * Option value is cut short.
+ */
+ return (NULL);
+ }
+
+ return (optvalue);
+}
+
+
+int
+pcap_ng_block_get_option(pcapng_block_t block, u_short code, struct pcapng_option_info *option_info)
+{
+ struct pcapng_option_header opthdr;
+ int swapped;
+ int num_of_options = 0;
+ struct block_cursor cursor;
+ static char errbuf[PCAP_ERRBUF_SIZE + 1];
+
+ if (option_info == NULL)
+ return (PCAP_ERROR);
+ if (block->pcapng_options_len == 0)
+ goto done;
+
+ swapped = block->pcapng_block_swapped;
+
+ cursor.block_type = block->pcapng_block_type;
+ cursor.data = pcap_ng_block_options_ptr(block);
+ cursor.data_remaining = block->pcapng_options_len;
+
+ while (get_opthdr_from_block_data(&opthdr, swapped, &cursor, errbuf)) {
+ void *value = get_optvalue_from_block_data(&cursor, &opthdr, errbuf);
+
+ /*
+ * If option is cut short we cannot parse it, give up
+ */
+ if (opthdr.option_length != 0 && value == NULL)
+ break;
+
+ if (code == opthdr.option_code) {
+ option_info->code = opthdr.option_code;
+ option_info->length = opthdr.option_length;
+ option_info->value = value;
+
+ num_of_options = 1;
+ break;
+ }
+ /*
+ * Detect end of option delimiter
+ */
+ if (opthdr.option_code == PCAPNG_OPT_ENDOFOPT)
+ break;
+ }
+
+done:
+ return (num_of_options);
+}
+
+int
+pcnapng_block_iterate_options(pcapng_block_t block,
+ pcapng_option_iterator_func opt_iterator_func,
+ void *context)
+{
+ struct pcapng_option_header opthdr;
+ int swapped;
+ int num_of_options = 0;
+ struct block_cursor cursor;
+ static char errbuf[PCAP_ERRBUF_SIZE + 1];
+
+ if (block == NULL || opt_iterator_func == NULL)
+ return (PCAP_ERROR);
+ swapped = block->pcapng_block_swapped;
+
+ cursor.block_type = block->pcapng_block_type;
+ cursor.data = pcap_ng_block_options_ptr(block);
+ cursor.data_remaining = block->pcapng_options_len;
+
+ while (get_opthdr_from_block_data(&opthdr, swapped, &cursor, errbuf)) {
+ void *value = get_optvalue_from_block_data(&cursor, &opthdr, errbuf);
+ struct pcapng_option_info option_info;
+
+ /*
+ * If option is cut short we cannot parse it, give up
+ */
+ if (opthdr.option_length != 0 && value == NULL)
+ break;
+
+ option_info.code = opthdr.option_code;
+ option_info.length = opthdr.option_length;
+ option_info.value = value;
+
+ num_of_options++;
+
+ opt_iterator_func(block, &option_info, context);
+
+ /*
+ * Detect end of option delimiter
+ */
+ if (opthdr.option_code == PCAPNG_OPT_ENDOFOPT)
+ break;
+ }
+
+done:
+ return (num_of_options);
+}
+
+int
+pcnapng_block_iterate_name_records(pcapng_block_t block,
+ pcapng_name_record_iterator_func record_iterator_func,
+ void *context)
+{
+ struct pcapng_record_header recordhdr;
+ int swapped;
+ int num_of_records = 0;
+ struct block_cursor cursor;
+ static char errbuf[PCAP_ERRBUF_SIZE + 1];
+
+ if (block == NULL || record_iterator_func == NULL)
+ return (PCAP_ERROR);
+ swapped = block->pcapng_block_swapped;
+
+ cursor.block_type = block->pcapng_block_type;
+ cursor.data = pcap_ng_block_records_ptr(block);
+ cursor.data_remaining = block->pcapng_records_len;
+
+ /*
+ * Note that we take advantage of the fact that name record headers
+ * have the same layout as option headers
+ */
+ while (get_opthdr_from_block_data((struct pcapng_option_header *)&recordhdr,
+ swapped, &cursor, errbuf)) {
+ struct pcapng_name_record_info record_info;
+ void *value =
+ get_optvalue_from_block_data(&cursor,
+ (struct pcapng_option_header *)&recordhdr,
+ errbuf);
+
+ /*
+ * If record is cut short we cannot parse it, give up
+ */
+ if (recordhdr.record_length != 0 && value == NULL)
+ break;
+
+ record_info.code = recordhdr.record_type;
+ record_info.length = recordhdr.record_length;
+ record_info.value = value;
+
+ num_of_records++;
+
+ /*
+ * Detect end of option delimiter
+ */
+ if (record_info.code == PCAPNG_NRES_ENDOFRECORD)
+ break;
+ }
+
+done:
+ return (num_of_records);
+}
+
+int
+pcap_ng_block_add_name_record_common(pcapng_block_t block, uint32_t type,
+ size_t addrlen, void *addr, const char **names)
+{
+ size_t names_len = 0;
+ int i;
+ const char *p;
+ size_t record_len = 0;
+ struct pcapng_record_header *record_hdr;
+ size_t padding_len;
+ u_char *buffer;
+ size_t offset;
+ u_char *block_records_ptr = pcap_ng_block_records_ptr(block);
+
+ if (block_records_ptr == NULL)
+ return (PCAP_ERROR);
+
+ for (i = 0; ; i++) {
+ p = names[i];
+ if (p == NULL || *p == 0)
+ break;
+ names_len += strlen(p) + 1;
+ }
+
+ record_len = sizeof(struct pcapng_record_header) + addrlen + PAD_32BIT(names_len);
+ if (record_len + block->pcapng_block_len > block->pcapng_buflen) {
+ warnx("%s block len %lu greater than buffer size %lu",
+ __func__, block->pcapng_block_len, block->pcapng_buflen);
+ return (PCAP_ERROR);
+ }
+
+ /*
+ * Move the options if necessary
+ */
+ if (block->pcapng_options_len > 0) {
+ u_char *tmp = pcap_ng_block_options_ptr(block);
+
+ bcopy(tmp, tmp + record_len, block->pcapng_options_len);
+ }
+
+ padding_len = PAD_32BIT(names_len) - names_len;
+
+ record_hdr = (struct pcapng_record_header*)(block_records_ptr + block->pcapng_records_len);
+ if (block->pcapng_records_len > 0)
+ record_hdr -= 1;
+ record_hdr->record_type = type;
+ record_hdr->record_length = addrlen + PAD_32BIT(names_len);
+
+ buffer = (u_char *)(record_hdr + 1);
+ bcopy(addr, buffer, addrlen);
+ offset = addrlen;
+ for (i = 0; ; i++) {
+ p = names[i];
+ if (p == NULL || *p == 0)
+ break;
+ u_short slen = strlen(p) + 1;
+ bcopy(p, buffer, slen);
+ offset += slen;
+ }
+ if (padding_len > 0)
+ bzero(buffer + offset, padding_len);
+
+ block->pcapng_records_len += record_len;
+
+ pcapng_update_block_length(block);
+
+ return (0);
+}
+
+int
+pcap_ng_block_add_name_record_with_ip4(pcapng_block_t block,
+ struct in_addr *in4,
+ const char **names)
+{
+ if (block->pcapng_block_type != PCAPNG_BT_NRB)
+ return (PCAP_ERROR);
+
+ return pcap_ng_block_add_name_record_common(block,
+ PCAPNG_NRES_IP4RECORD,
+ sizeof(struct in_addr),
+ in4,
+ names);
+}
+
+int
+pcap_ng_block_add_name_record_with_ip6(pcapng_block_t block,
+ struct in6_addr *in6,
+ const char **names)
+{
+ if (block->pcapng_block_type != PCAPNG_BT_NRB)
+ return (PCAP_ERROR);
+
+ return pcap_ng_block_add_name_record_common(block,
+ PCAPNG_NRES_IP4RECORD,
+ sizeof(struct in6_addr),
+ in6,
+ names);
+}
+
+bpf_u_int32
+pcap_ng_externalize_block(void *buffer, size_t buflen, pcapng_block_t block)
+{
+ struct pcapng_block_header block_header;
+ struct pcapng_block_trailer block_trailer;
+ bpf_u_int32 bytes_written = 0;
+ u_char *ptr;
+
+ if (buffer == NULL || buflen < block->pcapng_block_len)
+ return (0);
+
+ ptr = buffer;
+ block_header.block_type = block->pcapng_block_type;
+ block_header.total_length = (bpf_u_int32)block->pcapng_block_len;
+ bcopy(&block_header, ptr + bytes_written, sizeof(struct pcapng_block_header));
+ bytes_written += sizeof(struct pcapng_block_header);
+
+ switch (block->pcapng_block_type) {
+ case PCAPNG_BT_SHB:
+ case PCAPNG_BT_IDB:
+ case PCAPNG_BT_PB:
+ case PCAPNG_BT_SPB:
+ case PCAPNG_BT_NRB:
+ case PCAPNG_BT_ISB:
+ case PCAPNG_BT_EPB:
+ case PCAPNG_BT_PIB:
+ case PCAPNG_BT_OSEV:
+ if (block->pcapng_block_type == PCAPNG_BT_PB) {
+ if(block->pcap_ng_opb_fields.caplen == 0)
+ block->pcap_ng_opb_fields.caplen = block->pcapng_cap_len;
+ if(block->pcap_ng_opb_fields.len == 0)
+ block->pcap_ng_opb_fields.len = block->pcapng_cap_len;
+ }
+ if (block->pcapng_block_type == PCAPNG_BT_SPB) {
+ if(block->pcap_ng_spb_fields.len == 0)
+ block->pcap_ng_spb_fields.len = block->pcapng_cap_len;
+ }
+ if (block->pcapng_block_type == PCAPNG_BT_EPB) {
+ if(block->pcap_ng_epb_fields.caplen == 0)
+ block->pcap_ng_epb_fields.caplen = block->pcapng_cap_len;
+ if(block->pcap_ng_epb_fields.len == 0)
+ block->pcap_ng_epb_fields.len = block->pcapng_cap_len;
+ }
+ if (block->pcapng_block_type == PCAPNG_BT_OSEV) {
+ if(block->pcap_ng_osev_fields.len == 0)
+ block->pcap_ng_osev_fields.len = block->pcapng_cap_len;
+ }
+
+ if (block->pcapng_fields_len > 0) {
+ bcopy(&block->pcap_ng_shb_fields, ptr + bytes_written, block->pcapng_fields_len);
+ bytes_written += block->pcapng_fields_len;
+ }
+ break;
+ default:
+ /* Unknown block */
+ return (0);
+ break;
+ }
+
+
+ if (block->pcapng_data_len > 0) {
+ bpf_u_int32 padding_len = PAD_32BIT(block->pcapng_cap_len) - block->pcapng_cap_len;
+
+ bcopy(block->pcapng_data_ptr, ptr + bytes_written, block->pcapng_cap_len);
+ bytes_written += block->pcapng_cap_len;
+
+ if (padding_len > 0) {
+ bzero(ptr + bytes_written, padding_len);
+ bytes_written += padding_len;
+ }
+ }
+
+ if (block->pcapng_records_len > 0) {
+ bcopy(pcap_ng_block_records_ptr(block), ptr + bytes_written, block->pcapng_records_len);
+ bytes_written += block->pcapng_records_len;
+ }
+ if (block->pcapng_options_len > 0) {
+ bcopy(pcap_ng_block_options_ptr(block), ptr + bytes_written, block->pcapng_options_len);
+ bytes_written += block->pcapng_options_len;
+ }
+
+ block_trailer.total_length = (bpf_u_int32)block->pcapng_block_len;
+ bcopy(&block_trailer, ptr + bytes_written, bytes_written);
+ bytes_written += sizeof(struct pcapng_block_trailer);
+
+ return (bytes_written);
+}
+
+bpf_u_int32
+pcap_ng_dump_block(pcap_dumper_t *p, pcapng_block_t block)
+{
+ struct pcapng_block_header *block_header;
+ struct pcapng_block_trailer *block_trailer;
+ bpf_u_int32 bytes_written = 0;
+ struct iovec iov[4];
+ int iovcnt;
+ char data_padding[3] = { 0, 0, 0 };
+
+ block_header = (struct pcapng_block_header *)pcap_ng_block_header_ptr(block);
+ block_header->block_type = block->pcapng_block_type;
+ block_header->total_length = (bpf_u_int32)block->pcapng_block_len;
+
+ switch (block->pcapng_block_type) {
+ case PCAPNG_BT_SHB:
+ case PCAPNG_BT_IDB:
+ case PCAPNG_BT_PB:
+ case PCAPNG_BT_NRB:
+ case PCAPNG_BT_ISB:
+ case PCAPNG_BT_EPB:
+ case PCAPNG_BT_PIB:
+ case PCAPNG_BT_OSEV:
+ case PCAPNG_BT_DSB:
+ if (block->pcapng_block_type == PCAPNG_BT_PB) {
+ if (block->pcap_ng_opb_fields.caplen == 0)
+ block->pcap_ng_opb_fields.caplen = block->pcapng_cap_len;
+ if (block->pcap_ng_opb_fields.len == 0)
+ block->pcap_ng_opb_fields.len = block->pcapng_cap_len;
+ }
+ if (block->pcapng_block_type == PCAPNG_BT_SPB) {
+ if (block->pcap_ng_spb_fields.len == 0)
+ block->pcap_ng_spb_fields.len = block->pcapng_cap_len;
+ }
+ if (block->pcapng_block_type == PCAPNG_BT_EPB) {
+ if (block->pcap_ng_epb_fields.caplen == 0)
+ block->pcap_ng_epb_fields.caplen = block->pcapng_cap_len;
+ if (block->pcap_ng_epb_fields.len == 0)
+ block->pcap_ng_epb_fields.len = block->pcapng_cap_len;
+ }
+
+ // Copy the fixed fields if any
+ if (block->pcapng_fields_len > 0) {
+ bcopy(&block->pcap_ng_shb_fields, pcap_ng_block_fields_ptr(block), block->pcapng_fields_len);
+ }
+ break;
+ default:
+ /* Unknown block */
+ return (0);
+ break;
+ }
+
+ block_trailer = pcap_ng_block_trailer_ptr(block);
+ block_trailer->total_length = block_header->total_length;
+
+ iovcnt = 0;
+ iov[iovcnt].iov_len = sizeof(struct pcapng_block_header) + block->pcapng_fields_len;
+ iov[iovcnt].iov_base = block->pcapng_bufptr;
+ iovcnt++;
+
+ if (block->pcapng_data_len > 0) {
+ bpf_u_int32 padding_len = PAD_32BIT(block->pcapng_cap_len) - block->pcapng_cap_len;
+
+ iov[iovcnt].iov_len = block->pcapng_cap_len;
+ iov[iovcnt].iov_base = block->pcapng_data_ptr;
+ iovcnt++;
+
+ /* This is suboptimal... */
+ if (padding_len > 0) {
+ iov[iovcnt].iov_len = padding_len;
+ iov[iovcnt].iov_base = data_padding;
+ iovcnt++;
+ }
+ }
+ /*
+ * The name records, options and block trailer are contiguous
+ */
+ iov[iovcnt].iov_len = block->pcapng_records_len +
+ block->pcapng_options_len +
+ sizeof(struct pcapng_block_trailer);
+ if (block->pcapng_records_len > 0)
+ iov[iovcnt].iov_base = pcap_ng_block_records_ptr(block);
+ else if (block->pcapng_options_len > 0)
+ iov[iovcnt].iov_base = pcap_ng_block_options_ptr(block);
+ else
+ iov[iovcnt].iov_base = block_trailer;
+ iovcnt++;
+
+ bytes_written += writev(p->f->_file, iov, iovcnt);
+
+ return (bytes_written);
+}
+
+int
+pcap_ng_block_internalize_common(pcapng_block_t *pblock, pcap_t *p, u_char *raw_block)
+{
+ pcapng_block_t block = NULL;
+ struct pcapng_block_header bh = *(struct pcapng_block_header *)raw_block;
+ struct block_cursor cursor;
+ int swapped = 0;
+
+ if (pblock == NULL || raw_block == NULL)
+ return (PCAP_ERROR);
+
+ if (p != NULL)
+ swapped = p->swapped;
+
+ if (swapped) {
+ bh.block_type = SWAPLONG(bh.block_type);
+ bh.total_length = SWAPLONG(bh.total_length);
+ }
+
+ switch (bh.block_type) {
+ case PCAPNG_BT_SHB:
+ pcap_ng_init_section_info(p);
+ break;
+ case PCAPNG_BT_IDB:
+ case PCAPNG_BT_PB:
+ case PCAPNG_BT_SPB:
+ case PCAPNG_BT_NRB:
+ case PCAPNG_BT_ISB:
+ case PCAPNG_BT_EPB:
+ case PCAPNG_BT_PIB:
+ case PCAPNG_BT_OSEV:
+ case PCAPNG_BT_DSB:
+ break;
+ default:
+ (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Unknown block type length %u",
+ __func__, bh.block_type);
+ goto fail;
+ }
+ /* Check the length is reasonable, limit to 1 MBytes */
+ if (bh.total_length > 1024 * 1024) {
+ (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Block total length %u is greater than 16 MB",
+ __func__, bh.total_length);
+ goto fail;
+ }
+
+ /*
+ * Some ntar files from wireshark.org do not round up the total block length to
+ * a multiple of 4 bytes -- they must ignore the 32 bit alignment of the block body!
+ */
+ bh.total_length = PAD_32BIT(bh.total_length);
+
+ if (*pblock == NULL) {
+ block = pcap_ng_block_alloc(bh.total_length);
+ if (block == NULL) {
+ (void) snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: Unknown block type %u",
+ __func__, bh.block_type);
+ goto fail;
+ }
+ } else {
+ block = *pblock;
+ }
+ block->pcapng_bufptr = raw_block;
+ block->pcapng_buflen = bh.total_length;
+ block->pcapng_buf_is_external = 1;
+ pcap_ng_block_reset(block, bh.block_type);
+ block->pcapng_block_len = bh.total_length;
+ block->pcapng_block_swapped = swapped;
+
+ cursor.data = raw_block + sizeof(struct pcapng_block_header);
+ cursor.data_remaining = bh.total_length -
+ sizeof(struct pcapng_block_header) -
+ sizeof(struct pcapng_block_trailer);
+ cursor.block_type = bh.block_type;
+
+ switch (bh.block_type) {
+ case PCAPNG_BT_SHB: {
+ struct pcapng_section_header_fields *shbp = pcap_ng_get_section_header_fields(block);
+ struct pcapng_section_header_fields *rawshb;
+
+ rawshb = get_from_block_data(&cursor, sizeof(struct pcapng_section_header_fields), p->errbuf);
+ if (rawshb == NULL)
+ goto fail;
+
+ shbp->byte_order_magic = rawshb->byte_order_magic;
+ shbp->major_version = rawshb->major_version;
+ shbp->minor_version = rawshb->minor_version;
+ shbp->section_length = rawshb->section_length;
+ if (swapped) {
+ shbp->byte_order_magic = SWAPLONG(shbp->byte_order_magic);
+ shbp->major_version = SWAPSHORT(shbp->major_version);
+ shbp->minor_version = SWAPSHORT(shbp->minor_version);
+ shbp->section_length = SWAPLONGLONG(shbp->section_length);
+ }
+
+ break;
+ }
+ case PCAPNG_BT_IDB: {
+ struct pcapng_interface_description_fields *idbp = pcap_ng_get_interface_description_fields(block);
+ struct pcapng_interface_description_fields *rawidb;
+
+ rawidb = get_from_block_data(&cursor, sizeof(struct pcapng_interface_description_fields), p->errbuf);
+ if (rawidb == NULL)
+ goto fail;
+
+ idbp->idb_linktype = rawidb->idb_linktype;
+ idbp->idb_reserved = rawidb->idb_reserved;
+ idbp->idb_snaplen = rawidb->idb_snaplen;
+ if (swapped) {
+ idbp->idb_linktype = SWAPSHORT(idbp->idb_linktype);
+ idbp->idb_reserved = SWAPSHORT(idbp->idb_reserved);
+ idbp->idb_snaplen = SWAPLONG(idbp->idb_snaplen);
+ }
+
+ break;
+ }
+ case PCAPNG_BT_ISB: {
+ struct pcapng_interface_statistics_fields *isbp = pcap_ng_get_interface_statistics_fields(block);
+ struct pcapng_interface_statistics_fields *rawisb;
+
+ rawisb = get_from_block_data(&cursor, sizeof(struct pcapng_interface_statistics_fields), p->errbuf);
+ if (rawisb == NULL)
+ goto fail;
+
+ isbp->interface_id = rawisb->interface_id;
+ isbp->timestamp_high = rawisb->timestamp_high;
+ isbp->timestamp_low = rawisb->timestamp_low;
+ if (swapped) {
+ isbp->interface_id = SWAPSHORT(isbp->interface_id);
+ isbp->timestamp_high = SWAPLONG(isbp->timestamp_high);
+ isbp->timestamp_low = SWAPLONG(isbp->timestamp_low);
+ }
+
+ break;
+ }
+ case PCAPNG_BT_EPB: {
+ struct pcapng_enhanced_packet_fields *epbp = pcap_ng_get_enhanced_packet_fields(block);
+ struct pcapng_enhanced_packet_fields *rawepb;
+ void *data;
+
+ rawepb = get_from_block_data(&cursor, sizeof(struct pcapng_enhanced_packet_fields), p->errbuf);
+ if (rawepb == NULL)
+ goto fail;
+
+ epbp->interface_id = rawepb->interface_id;
+ epbp->timestamp_high = rawepb->timestamp_high;
+ epbp->timestamp_low = rawepb->timestamp_low;
+ epbp->caplen = rawepb->caplen;
+ epbp->len = rawepb->len;
+ if (swapped) {
+ epbp->interface_id = SWAPLONG(epbp->interface_id);
+ epbp->timestamp_high = SWAPLONG(epbp->timestamp_high);
+ epbp->timestamp_low = SWAPLONG(epbp->timestamp_low);
+ epbp->caplen = SWAPLONG(epbp->caplen);
+ epbp->len = SWAPLONG(epbp->len);
+ }
+ data = get_from_block_data(&cursor, PAD_32BIT(epbp->caplen), p->errbuf);
+ if (data == NULL)
+ goto fail;
+ block->pcapng_data_is_external = 0;
+ block->pcapng_data_ptr = (u_char *)data;
+ block->pcapng_cap_len = epbp->caplen;
+ block->pcapng_data_len = PAD_32BIT(epbp->caplen);
+
+ break;
+ }
+ case PCAPNG_BT_SPB: {
+ struct pcapng_simple_packet_fields *spbp = pcap_ng_get_simple_packet_fields(block);
+ struct pcapng_simple_packet_fields *rawspb;
+ void *data;
+ uint32_t caplen;
+
+ rawspb = get_from_block_data(&cursor, sizeof(struct pcapng_simple_packet_fields), p->errbuf);
+ if (rawspb == NULL)
+ goto fail;
+
+ spbp->len = rawspb->len;
+ if (swapped) {
+ spbp->len = SWAPLONG(spbp->len);
+ }
+ caplen = bh.total_length - sizeof(struct pcapng_simple_packet_fields) -
+ sizeof(struct pcapng_block_header) - sizeof(struct pcapng_block_trailer);
+ if (caplen > spbp->len)
+ caplen = spbp->len;
+ data = get_from_block_data(&cursor, PAD_32BIT(caplen), p->errbuf);
+ if (data == NULL)
+ goto fail;
+ block->pcapng_data_is_external = 0;
+ block->pcapng_data_ptr = (u_char *)data;
+ block->pcapng_cap_len = caplen;
+ block->pcapng_data_len = PAD_32BIT(caplen);
+
+ break;
+ }
+ case PCAPNG_BT_PB: {
+ struct pcapng_packet_fields *pbp = pcap_ng_get_packet_fields(block);
+ struct pcapng_packet_fields *rawpb;
+ void *data;
+
+ rawpb = get_from_block_data(&cursor, sizeof(struct pcapng_packet_fields), p->errbuf);
+ if (rawpb == NULL)
+ goto fail;
+
+ pbp->interface_id = rawpb->interface_id;
+ pbp->drops_count = rawpb->drops_count;
+ pbp->timestamp_high = rawpb->timestamp_high;
+ pbp->timestamp_low = rawpb->timestamp_low;
+ pbp->caplen = rawpb->caplen;
+ pbp->len = rawpb->len;
+ if (swapped) {
+ /* these were written in opposite byte order */
+ pbp->interface_id = SWAPSHORT(pbp->interface_id);
+ pbp->drops_count = SWAPSHORT(pbp->drops_count);
+ pbp->timestamp_high = SWAPLONG(pbp->timestamp_high);
+ pbp->timestamp_low = SWAPLONG(pbp->timestamp_low);
+ pbp->caplen = SWAPLONG(pbp->caplen);
+ pbp->len = SWAPLONG(pbp->len);
+ }
+
+ data = get_from_block_data(&cursor, PAD_32BIT(pbp->caplen), p->errbuf);
+ if (data == NULL)
+ goto fail;
+ block->pcapng_data_is_external = 0;
+ block->pcapng_data_ptr = (u_char *)data;
+ block->pcapng_cap_len = pbp->caplen;
+ block->pcapng_data_len = PAD_32BIT(pbp->caplen);
+
+ break;
+ }
+ case PCAPNG_BT_PIB: {
+ struct pcapng_process_information_fields *pibp = pcap_ng_get_process_information_fields(block);
+ struct pcapng_process_information_fields *rawpib;
+
+ rawpib = get_from_block_data(&cursor, sizeof(struct pcapng_process_information_fields), p->errbuf);
+ if (rawpib == NULL)
+ goto fail;
+
+ pibp->process_id = rawpib->process_id;
+ if (swapped) {
+ pibp->process_id = SWAPSHORT(rawpib->process_id);
+ }
+ break;
+ }
+ case PCAPNG_BT_NRB: {
+ struct pcapng_record_header *rh;
+
+ while (1) {
+ size_t record_len;
+
+ rh = get_from_block_data(&cursor, sizeof(struct pcapng_record_header), p->errbuf);
+ if (rh == NULL)
+ goto fail;
+
+ if (swapped)
+ record_len = SWAPSHORT(rh->record_length);
+ else
+ record_len = rh->record_length;
+
+ if (get_from_block_data(&cursor, PCAPNG_ROUNDUP32(record_len), p->errbuf) == NULL)
+ goto fail;
+
+ block->pcapng_records_len += sizeof(struct pcapng_record_header) +
+ PCAPNG_ROUNDUP32(record_len);
+
+ if (rh->record_type == PCAPNG_NRES_ENDOFRECORD)
+ break;
+ }
+ break;
+ }
+ case PCAPNG_BT_OSEV: {
+ struct pcapng_os_event_fields *osevp = pcap_ng_get_os_event_fields(block);
+ struct pcapng_os_event_fields *rawosevp;
+ void *data;
+ uint32_t caplen;
+
+ rawosevp = get_from_block_data(&cursor, sizeof(struct pcapng_os_event_fields), p->errbuf);
+ if (rawosevp == NULL)
+ goto fail;
+
+ osevp->type = rawosevp->type;
+ osevp->timestamp_high = rawosevp->timestamp_high;
+ osevp->timestamp_low = rawosevp->timestamp_low;
+ osevp->len = rawosevp->len;
+ if (swapped) {
+ osevp->type = SWAPLONG(osevp->type);
+ osevp->timestamp_high = SWAPLONG(osevp->timestamp_high);
+ osevp->timestamp_low = SWAPLONG(osevp->timestamp_low);
+ osevp->len = SWAPLONG(osevp->len);
+ }
+ caplen = bh.total_length - sizeof(struct pcapng_os_event_fields) -
+ sizeof(struct pcapng_block_header) - sizeof(struct pcapng_block_trailer);
+ if (caplen > osevp->len)
+ caplen = osevp->len;
+ data = get_from_block_data(&cursor, PAD_32BIT(caplen), p->errbuf);
+ if (data == NULL)
+ goto fail;
+ block->pcapng_data_is_external = 0;
+ block->pcapng_data_ptr = (u_char *)data;
+ block->pcapng_cap_len = caplen;
+ block->pcapng_data_len = PAD_32BIT(caplen);
+ break;
+ }
+ case PCAPNG_BT_DSB: {
+ struct pcapng_decryption_secrets_fields *dsp = pcap_ng_get_decryption_secrets_fields(block);
+ struct pcapng_decryption_secrets_fields *rawdsp;
+ void *data;
+ uint32_t caplen;
+
+ rawdsp = get_from_block_data(&cursor, sizeof(struct pcapng_decryption_secrets_fields), p->errbuf);
+ if (rawdsp == NULL)
+ goto fail;
+ dsp->secrets_type = rawdsp->secrets_type;
+ dsp->secrets_length = rawdsp->secrets_length;
+ if (swapped) {
+ dsp->secrets_type = SWAPLONG(dsp->secrets_type);
+ dsp->secrets_length = SWAPLONG(dsp->secrets_length);
+ }
+
+ caplen = bh.total_length - sizeof(struct pcapng_decryption_secrets_fields) -
+ sizeof(struct pcapng_block_header) - sizeof(struct pcapng_block_trailer);
+ if (caplen > dsp->secrets_length)
+ caplen = dsp->secrets_length;
+ data = get_from_block_data(&cursor, PAD_32BIT(caplen), p->errbuf);
+ if (data == NULL)
+ goto fail;
+ block->pcapng_data_is_external = 0;
+ block->pcapng_data_ptr = (u_char *)data;
+ block->pcapng_cap_len = caplen;
+ block->pcapng_data_len = PAD_32BIT(caplen);
+ break;
+ }
+ default:
+ goto fail;
+ }
+
+ /*
+ * Finally compute the length of the options as options come last in blocks
+ */
+ while (1) {
+ size_t optlen;
+ struct pcapng_option_header *opt;
+
+ opt = get_from_block_data(&cursor, sizeof(struct pcapng_option_header), p->errbuf);
+ /*
+ * No, or no more options
+ */
+ if (opt == NULL)
+ break;
+
+ if (swapped)
+ optlen = SWAPSHORT(opt->option_length);
+ else
+ optlen = opt->option_length;
+
+ if (get_from_block_data(&cursor, PCAPNG_ROUNDUP32(optlen), p->errbuf) == NULL)
+ goto fail;
+
+ block->pcapng_options_len += sizeof(struct pcapng_option_header) + PCAPNG_ROUNDUP32(optlen);
+
+ if (opt->option_code == PCAPNG_OPT_ENDOFOPT)
+ break;
+ }
+
+ /* Success */
+ if (*pblock == NULL)
+ *pblock = block;
+ return (0);
+
+fail:
+ if (*pblock == NULL && block != NULL)
+ pcap_ng_free_block(block);
+ return (PCAP_ERROR);
+}
+
+int
+pcap_ng_block_init_with_raw_block(pcapng_block_t block, pcap_t *p, u_char *raw_block)
+{
+ return pcap_ng_block_internalize_common(&block, p, raw_block);
+}
+
+pcapng_block_t
+pcap_ng_block_alloc_with_raw_block(pcap_t *p, u_char *raw_block)
+{
+ pcapng_block_t block = NULL;
+
+ if (pcap_ng_block_internalize_common(&block, p, raw_block) == 0)
+ return (block);
+ else
+ return (NULL);
+}
diff --git a/lib/libpcap/libpcap/portability.h b/lib/libpcap/libpcap/portability.h
new file mode 100644
index 0000000..543846e
--- /dev/null
+++ b/lib/libpcap/libpcap/portability.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef portability_h
+#define portability_h
+
+/*
+ * Helpers for portability between Windows and UN*X and between different
+ * flavors of UN*X.
+ */
+#include <stdarg.h> /* we declare varargs functions on some platforms */
+
+#include "pcap/funcattrs.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef HAVE_STRLCAT
+ #define pcap_strlcat strlcat
+#else
+ #if defined(_MSC_VER) || defined(__MINGW32__)
+ /*
+ * strncat_s() is supported at least back to Visual
+ * Studio 2005.
+ */
+ #define pcap_strlcat(x, y, z) \
+ strncat_s((x), (z), (y), _TRUNCATE)
+ #else
+ /*
+ * Define it ourselves.
+ */
+ extern size_t pcap_strlcat(char * restrict dst, const char * restrict src, size_t dstsize);
+ #endif
+#endif
+
+#ifdef HAVE_STRLCPY
+ #define pcap_strlcpy strlcpy
+#else
+ #if defined(_MSC_VER) || defined(__MINGW32__)
+ /*
+ * strncpy_s() is supported at least back to Visual
+ * Studio 2005.
+ */
+ #define pcap_strlcpy(x, y, z) \
+ strncpy_s((x), (z), (y), _TRUNCATE)
+ #else
+ /*
+ * Define it ourselves.
+ */
+ extern size_t pcap_strlcpy(char * restrict dst, const char * restrict src, size_t dstsize);
+ #endif
+#endif
+
+#ifdef _MSC_VER
+ #define isascii __isascii
+
+ /*
+ * If <crtdbg.h> has been included, and _DEBUG is defined, and
+ * __STDC__ is zero, <crtdbg.h> will define strdup() to call
+ * _strdup_dbg(). So if it's already defined, don't redefine
+ * it.
+ */
+ #ifndef strdup
+ #define strdup _strdup
+ #endif
+#endif
+
+/*
+ * On Windows, snprintf(), with that name and with C99 behavior - i.e.,
+ * guaranteeing that the formatted string is null-terminated - didn't
+ * appear until Visual Studio 2015. Prior to that, the C runtime had
+ * only _snprintf(), which *doesn't* guarantee that the string is
+ * null-terminated if it is truncated due to the buffer being too
+ * small. We therefore can't just define snprintf to be _snprintf
+ * and define vsnprintf to be _vsnprintf, as we're relying on null-
+ * termination of strings in all cases.
+ *
+ * We also want to allow this to be built with versions of Visual Studio
+ * prior to VS 2015, so we can't rely on snprintf() being present.
+ *
+ * And we want to make sure that, if we support plugins in the future,
+ * a routine with C99 snprintf() behavior will be available to them.
+ * We also don't want it to collide with the C library snprintf() if
+ * there is one.
+ *
+ * So we make pcap_snprintf() and pcap_vsnprintf() available, either by
+ * #defining them to be snprintf or vsnprintf, respectively, or by
+ * defining our own versions and exporting them.
+ */
+#ifdef HAVE_SNPRINTF
+#define pcap_snprintf snprintf
+#else
+extern int pcap_snprintf(char *, size_t, PCAP_FORMAT_STRING(const char *), ...)
+ PCAP_PRINTFLIKE(3, 4);
+#endif
+
+#ifdef HAVE_VSNPRINTF
+#define pcap_vsnprintf vsnprintf
+#else
+extern int pcap_vsnprintf(char *, size_t, const char *, va_list ap);
+#endif
+
+/*
+ * We also want asprintf(), for some cases where we use it to construct
+ * dynamically-allocated variable-length strings.
+ */
+#ifdef HAVE_ASPRINTF
+#define pcap_asprintf asprintf
+#else
+extern int pcap_asprintf(char **, PCAP_FORMAT_STRING(const char *), ...)
+ PCAP_PRINTFLIKE(2, 3);
+#endif
+
+#ifdef HAVE_VASPRINTF
+#define pcap_vasprintf vasprintf
+#else
+extern int pcap_vasprintf(char **, const char *, va_list ap);
+#endif
+
+#ifdef HAVE_STRTOK_R
+ #define pcap_strtok_r strtok_r
+#else
+ #ifdef _WIN32
+ /*
+ * Microsoft gives it a different name.
+ */
+ #define pcap_strtok_r strtok_s
+ #else
+ /*
+ * Define it ourselves.
+ */
+ extern char *pcap_strtok_r(char *, const char *, char **);
+ #endif
+#endif /* HAVE_STRTOK_R */
+
+#ifdef _WIN32
+ #if !defined(__cplusplus)
+ #define inline __inline
+ #endif
+#endif /* _WIN32 */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libpcap/libpcap/ppp.h b/lib/libpcap/libpcap/ppp.h
new file mode 100644
index 0000000..d6e70c1
--- /dev/null
+++ b/lib/libpcap/libpcap/ppp.h
@@ -0,0 +1,57 @@
+/*
+ * Point to Point Protocol (PPP) RFC1331
+ *
+ * Copyright 1989 by Carnegie Mellon.
+ *
+ * Permission to use, copy, modify, and distribute this program for any
+ * purpose and without fee is hereby granted, provided that this copyright
+ * and permission notice appear on all copies and supporting documentation,
+ * the name of Carnegie Mellon not be used in advertising or publicity
+ * pertaining to distribution of the program without specific prior
+ * permission, and notice be given in supporting documentation that copying
+ * and distribution is by permission of Carnegie Mellon and Stanford
+ * University. Carnegie Mellon makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+#define PPP_ADDRESS 0xff /* The address byte value */
+#define PPP_CONTROL 0x03 /* The control byte value */
+
+#define PPP_PPPD_IN 0x00 /* non-standard for DLT_PPP_PPPD */
+#define PPP_PPPD_OUT 0x01 /* non-standard for DLT_PPP_PPPD */
+
+/* Protocol numbers */
+#define PPP_IP 0x0021 /* Raw IP */
+#define PPP_OSI 0x0023 /* OSI Network Layer */
+#define PPP_NS 0x0025 /* Xerox NS IDP */
+#define PPP_DECNET 0x0027 /* DECnet Phase IV */
+#define PPP_APPLE 0x0029 /* Appletalk */
+#define PPP_IPX 0x002b /* Novell IPX */
+#define PPP_VJC 0x002d /* Van Jacobson Compressed TCP/IP */
+#define PPP_VJNC 0x002f /* Van Jacobson Uncompressed TCP/IP */
+#define PPP_BRPDU 0x0031 /* Bridging PDU */
+#define PPP_STII 0x0033 /* Stream Protocol (ST-II) */
+#define PPP_VINES 0x0035 /* Banyan Vines */
+#define PPP_IPV6 0x0057 /* Internet Protocol version 6 */
+
+#define PPP_HELLO 0x0201 /* 802.1d Hello Packets */
+#define PPP_LUXCOM 0x0231 /* Luxcom */
+#define PPP_SNS 0x0233 /* Sigma Network Systems */
+#define PPP_MPLS_UCAST 0x0281 /* rfc 3032 */
+#define PPP_MPLS_MCAST 0x0283 /* rfc 3022 */
+
+#define PPP_IPCP 0x8021 /* IP Control Protocol */
+#define PPP_OSICP 0x8023 /* OSI Network Layer Control Protocol */
+#define PPP_NSCP 0x8025 /* Xerox NS IDP Control Protocol */
+#define PPP_DECNETCP 0x8027 /* DECnet Control Protocol */
+#define PPP_APPLECP 0x8029 /* Appletalk Control Protocol */
+#define PPP_IPXCP 0x802b /* Novell IPX Control Protocol */
+#define PPP_STIICP 0x8033 /* Strean Protocol Control Protocol */
+#define PPP_VINESCP 0x8035 /* Banyan Vines Control Protocol */
+#define PPP_IPV6CP 0x8057 /* IPv6 Control Protocol */
+#define PPP_MPLSCP 0x8281 /* rfc 3022 */
+
+#define PPP_LCP 0xc021 /* Link Control Protocol */
+#define PPP_PAP 0xc023 /* Password Authentication Protocol */
+#define PPP_LQM 0xc025 /* Link Quality Monitoring */
+#define PPP_CHAP 0xc223 /* Challenge Handshake Authentication Protocol */
diff --git a/lib/libpcap/libpcap/rpcap-protocol.c b/lib/libpcap/libpcap/rpcap-protocol.c
new file mode 100644
index 0000000..692f7c5
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcap-protocol.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (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 Politecnico di Torino, CACE Technologies
+ * nor the names 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h> /* for strlen(), ... */
+#include <stdlib.h> /* for malloc(), free(), ... */
+#include <stdarg.h> /* for functions with variable number of arguments */
+#include <errno.h> /* for the errno variable */
+#include "sockutils.h"
+#include "portability.h"
+#include "rpcap-protocol.h"
+#include <pcap/pcap.h>
+
+/*
+ * This file contains functions used both by the rpcap client and the
+ * rpcap daemon.
+ */
+
+/*
+ * This function sends a RPCAP error to our peer.
+ *
+ * It has to be called when the main program detects an error.
+ * It will send to our peer the 'buffer' specified by the user.
+ * This function *does not* request a RPCAP CLOSE connection. A CLOSE
+ * command must be sent explicitly by the program, since we do not know
+ * whether the error can be recovered in some way or if it is a
+ * non-recoverable one.
+ *
+ * \param sock: the socket we are currently using.
+ *
+ * \param ver: the protocol version we want to put in the reply.
+ *
+ * \param errcode: a integer which tells the other party the type of error
+ * we had.
+ *
+ * \param error: an user-allocated (and '0' terminated) buffer that contains
+ * the error description that has to be transmitted to our peer. The
+ * error message cannot be longer than PCAP_ERRBUF_SIZE.
+ *
+ * \param errbuf: a pointer to a user-allocated buffer (of size
+ * PCAP_ERRBUF_SIZE) that will contain the error message (in case there
+ * is one). It could be network problem.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The
+ * error message is returned in the 'errbuf' variable.
+ */
+int
+rpcap_senderror(SOCKET sock, uint8 ver, unsigned short errcode, const char *error, char *errbuf)
+{
+ char sendbuf[RPCAP_NETBUF_SIZE]; /* temporary buffer in which data to be sent is buffered */
+ int sendbufidx = 0; /* index which keeps the number of bytes currently buffered */
+ uint16 length;
+
+ length = (uint16)strlen(error);
+
+ if (length > PCAP_ERRBUF_SIZE)
+ length = PCAP_ERRBUF_SIZE;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, ver, RPCAP_MSG_ERROR, errcode, length);
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ if (sock_bufferize(error, length, sendbuf, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE))
+ return -1;
+
+ if (sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) < 0)
+ return -1;
+
+ return 0;
+}
+
+/*
+ * This function fills in a structure of type rpcap_header.
+ *
+ * It is provided just because the creation of an rpcap header is a common
+ * task. It accepts all the values that appears into an rpcap_header, and
+ * it puts them in place using the proper hton() calls.
+ *
+ * \param header: a pointer to a user-allocated buffer which will contain
+ * the serialized header, ready to be sent on the network.
+ *
+ * \param ver: a value (in the host byte order) which will be placed into the
+ * header.ver field and that represents the protocol version number of the
+ * current message.
+ *
+ * \param type: a value (in the host byte order) which will be placed into the
+ * header.type field and that represents the type of the current message.
+ *
+ * \param value: a value (in the host byte order) which will be placed into
+ * the header.value field and that has a message-dependent meaning.
+ *
+ * \param length: a value (in the host by order) which will be placed into
+ * the header.length field, representing the payload length of the message.
+ *
+ * \return Nothing. The serialized header is returned into the 'header'
+ * variable.
+ */
+void
+rpcap_createhdr(struct rpcap_header *header, uint8 ver, uint8 type, uint16 value, uint32 length)
+{
+ memset(header, 0, sizeof(struct rpcap_header));
+
+ header->ver = ver;
+ header->type = type;
+ header->value = htons(value);
+ header->plen = htonl(length);
+}
+
+/*
+ * Convert a message type to a string containing the type name.
+ */
+static const char *requests[] =
+{
+ NULL, /* not a valid message type */
+ "RPCAP_MSG_ERROR",
+ "RPCAP_MSG_FINDALLIF_REQ",
+ "RPCAP_MSG_OPEN_REQ",
+ "RPCAP_MSG_STARTCAP_REQ",
+ "RPCAP_MSG_UPDATEFILTER_REQ",
+ "RPCAP_MSG_CLOSE",
+ "RPCAP_MSG_PACKET",
+ "RPCAP_MSG_AUTH_REQ",
+ "RPCAP_MSG_STATS_REQ",
+ "RPCAP_MSG_ENDCAP_REQ",
+ "RPCAP_MSG_SETSAMPLING_REQ",
+};
+#define NUM_REQ_TYPES (sizeof requests / sizeof requests[0])
+
+static const char *replies[] =
+{
+ NULL,
+ NULL, /* this would be a reply to RPCAP_MSG_ERROR */
+ "RPCAP_MSG_FINDALLIF_REPLY",
+ "RPCAP_MSG_OPEN_REPLY",
+ "RPCAP_MSG_STARTCAP_REPLY",
+ "RPCAP_MSG_UPDATEFILTER_REPLY",
+ NULL, /* this would be a reply to RPCAP_MSG_CLOSE */
+ NULL, /* this would be a reply to RPCAP_MSG_PACKET */
+ "RPCAP_MSG_AUTH_REPLY",
+ "RPCAP_MSG_STATS_REPLY",
+ "RPCAP_MSG_ENDCAP_REPLY",
+ "RPCAP_MSG_SETSAMPLING_REPLY",
+};
+#define NUM_REPLY_TYPES (sizeof replies / sizeof replies[0])
+
+const char *
+rpcap_msg_type_string(uint8 type)
+{
+ if (type & RPCAP_MSG_IS_REPLY) {
+ type &= ~RPCAP_MSG_IS_REPLY;
+ if (type >= NUM_REPLY_TYPES)
+ return NULL;
+ return replies[type];
+ } else {
+ if (type >= NUM_REQ_TYPES)
+ return NULL;
+ return requests[type];
+ }
+}
diff --git a/lib/libpcap/libpcap/rpcap-protocol.h b/lib/libpcap/libpcap/rpcap-protocol.h
new file mode 100644
index 0000000..8ae8b62
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcap-protocol.h
@@ -0,0 +1,423 @@
+/*
+ * Copyright (c) 2002 - 2005 NetGroup, Politecnico di Torino (Italy)
+ * Copyright (c) 2005 - 2008 CACE Technologies, Davis (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 Politecnico di Torino, CACE Technologies
+ * nor the names 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.
+ *
+ */
+
+#ifndef __RPCAP_PROTOCOL_H__
+#define __RPCAP_PROTOCOL_H__
+
+#define RPCAP_DEFAULT_NETPORT "2002" /* Default port on which the RPCAP daemon is waiting for connections. */
+/* Default port on which the client workstation is waiting for connections in case of active mode. */
+#define RPCAP_DEFAULT_NETPORT_ACTIVE "2003"
+#define RPCAP_DEFAULT_NETADDR "" /* Default network address on which the RPCAP daemon binds to. */
+
+/*
+ * Minimum and maximum supported versions of the protocol.
+ *
+ * If new message types are added, the protocol version MUST be changed,
+ * so that a client knows, from the negotiated protocol version, what
+ * messages can be sent to the server.
+ *
+ * If the format of an existing message type is changed, the protocol
+ * version MUST be changed, so that each side knows, from the negotiated
+ * protocol version, what format should be used.
+ *
+ * The RPCAP_MSG_ERROR format MUST not change, as it's used to, among
+ * other things, report "incorrect version number" errors, where, if
+ * the format changed, the sender of the message might not know what
+ * versions the recipient would understand, or might know a version
+ * they support (the version number they sent) but might not know
+ * the format of the message in that version.
+ *
+ * Other message versions SHOULD not change, as that would complicate
+ * the process of interpreting the message, making it version-dependent.
+ * Introducing a new message with a new format is preferable.
+ *
+ * Version negotiation is done as part of the authentication process:
+ *
+ * The client sends an authentication request, with a version number
+ * of 0. All servers must accept authentication requests with a version
+ * number of 0, even if they don't support version 0 for any other
+ * requests.
+ *
+ * The server attempts to authenticate the client. If that succeeds,
+ * older servers - which only support version 0 - will send an
+ * authentication reply with no payload. Newer servers - which might
+ * support other versions - will send an authentication reply with
+ * a payload giving the minimum and maximum versions it supports.
+ *
+ * The client attempts to find the largest version number that is
+ * in both its range of supported versions and the server's supported
+ * versions. If it fails, it gives up; otherwise, it uses that version.
+ */
+#define RPCAP_MIN_VERSION 0
+#define RPCAP_MAX_VERSION 0
+
+/*
+ * Version numbers are unsigned, so if RPCAP_MIN_VERSION is 0, they
+ * are >= the minimum version, by definition; don't check against
+ * RPCAP_MIN_VERSION, as you may get compiler warnings that the
+ * comparison will always succeed.
+ */
+#if RPCAP_MIN_VERSION == 0
+#define RPCAP_VERSION_IS_SUPPORTED(v) \
+ ((v) <= RPCAP_MAX_VERSION)
+#else
+#define RPCAP_VERSION_IS_SUPPORTED(v) \
+ ((v) >= RPCAP_MIN_VERSION && (v) <= RPCAP_MAX_VERSION)
+#endif
+
+/*
+ * Separators used for the host list.
+ *
+ * It is used:
+ * - by the rpcapd daemon, when you types a list of allowed connecting hosts
+ * - by the rpcap client in active mode, when the client waits for incoming
+ * connections from other hosts
+ */
+#define RPCAP_HOSTLIST_SEP " ,;\n\r"
+
+/*********************************************************
+ * *
+ * Protocol messages formats *
+ * *
+ *********************************************************/
+/*
+ * WARNING: This file defines some structures that are used to transfer
+ * data on the network.
+ * Note that your compiler MUST not insert padding into these structures
+ * for better alignment.
+ * These structures have been created in order to be correctly aligned to
+ * a 32-bit boundary, but be careful in any case.
+ *
+ * The layout of these structures MUST not be changed. If a packet
+ * format is different in different versions of the protocol, versions
+ * of the structure should be provided for all the different versions or
+ * version ranges (if more than one version of the protocol has the same
+ * layout) that we support.
+ */
+
+/*
+ * WARNING: These typedefs MUST be of a specific size.
+ * You might have to change them on your platform.
+ *
+ * XXX - use the C99 types? Microsoft's newer versions of Visual Studio
+ * support them.
+ */
+typedef unsigned char uint8; /* 8-bit unsigned integer */
+typedef unsigned short uint16; /* 16-bit unsigned integer */
+typedef unsigned int uint32; /* 32-bit unsigned integer */
+typedef int int32; /* 32-bit signed integer */
+
+/* Common header for all the RPCAP messages */
+struct rpcap_header
+{
+ uint8 ver; /* RPCAP version number */
+ uint8 type; /* RPCAP message type (error, findalldevs, ...) */
+ uint16 value; /* Message-dependent value (not always used) */
+ uint32 plen; /* Length of the payload of this RPCAP message */
+};
+
+/*
+ * Format of data that may appear at the end of an authentication reply,
+ * giving the minimum and maximum versions of the protocol that the
+ * server supports.
+ *
+ * Older servers don't provide this; they support only version 0.
+ */
+struct rpcap_authreply
+{
+ uint8 minvers; /* Minimum version supported */
+ uint8 maxvers; /* Maximum version supported */
+};
+
+/* Format of the message for the interface description (findalldevs command) */
+struct rpcap_findalldevs_if
+{
+ uint16 namelen; /* Length of the interface name */
+ uint16 desclen; /* Length of the interface description */
+ uint32 flags; /* Interface flags */
+ uint16 naddr; /* Number of addresses */
+ uint16 dummy; /* Must be zero */
+};
+
+/*
+ * Format of an address as sent over the wire.
+ *
+ * Do *NOT* use struct sockaddr_storage, as the layout for that is
+ * machine-dependent.
+ *
+ * RFC 2553 gives two sample layouts, both of which are 128 bytes long,
+ * both of which are aligned on an 8-byte boundary, and both of which
+ * have 2 bytes before the address data.
+ *
+ * However, one has a 2-byte address family value at the beginning
+ * and the other has a 1-byte address length value and a 1-byte
+ * address family value; this reflects the fact that the original
+ * BSD sockaddr structure had a 2-byte address family value, which
+ * was later changed to a 1-byte address length value and a 1-byte
+ * address family value, when support for variable-length OSI
+ * network-layer addresses was added.
+ *
+ * Furthermore, Solaris's struct sockaddr_storage is 256 bytes
+ * long.
+ *
+ * This structure is supposed to be aligned on an 8-byte boundary;
+ * the message header is 8 bytes long, so we don't have to do
+ * anything to ensure it's aligned on that boundary within a packet,
+ * so we just define it as 128 bytes long, with a 2-byte address
+ * family. (We only support IPv4 and IPv6 addresses, which are fixed-
+ * length.) That way, it's the same size as sockaddr_storage on
+ * Windows, and it'll look like what an older Windows client will
+ * expect.
+ *
+ * In addition, do *NOT* use the host's AF_ value for an address,
+ * as the value for AF_INET6 is machine-dependent. We use the
+ * Windows value, so it'll look like what an older Windows client
+ * will expect.
+ *
+ * (The Windows client is the only one that has been distributed
+ * as a standard part of *pcap; UN*X clients are probably built
+ * from source by the user or administrator, so they're in a
+ * better position to upgrade an old client. Therefore, we
+ * try to make what goes over the wire look like what comes
+ * from a Windows server.)
+ */
+struct rpcap_sockaddr
+{
+ uint16 family; /* Address family */
+ char data[128-2]; /* Data */
+};
+
+/*
+ * Format of an IPv4 address as sent over the wire.
+ */
+#define RPCAP_AF_INET 2 /* Value on all OSes */
+struct rpcap_sockaddr_in
+{
+ uint16 family; /* Address family */
+ uint16 port; /* Port number */
+ uint32 addr; /* IPv4 address */
+ uint8 zero[8]; /* Padding */
+};
+
+/*
+ * Format of an IPv6 address as sent over the wire.
+ */
+#define RPCAP_AF_INET6 23 /* Value on Windows */
+struct rpcap_sockaddr_in6
+{
+ uint16 family; /* Address family */
+ uint16 port; /* Port number */
+ uint32 flowinfo; /* IPv6 flow information */
+ uint8 addr[16]; /* IPv6 address */
+ uint32 scope_id; /* Scope zone index */
+};
+
+/* Format of the message for the address listing (findalldevs command) */
+struct rpcap_findalldevs_ifaddr
+{
+ struct rpcap_sockaddr addr; /* Network address */
+ struct rpcap_sockaddr netmask; /* Netmask for that address */
+ struct rpcap_sockaddr broadaddr; /* Broadcast address for that address */
+ struct rpcap_sockaddr dstaddr; /* P2P destination address for that address */
+};
+
+/*
+ * \brief Format of the message of the connection opening reply (open command).
+ *
+ * This structure transfers over the network some of the values useful on the client side.
+ */
+struct rpcap_openreply
+{
+ int32 linktype; /* Link type */
+ int32 tzoff; /* Timezone offset */
+};
+
+/* Format of the message that starts a remote capture (startcap command) */
+struct rpcap_startcapreq
+{
+ uint32 snaplen; /* Length of the snapshot (number of bytes to capture for each packet) */
+ uint32 read_timeout; /* Read timeout in milliseconds */
+ uint16 flags; /* Flags (see RPCAP_STARTCAPREQ_FLAG_xxx) */
+ uint16 portdata; /* Network port on which the client is waiting at (if 'serveropen') */
+};
+
+/* Format of the reply message that devoted to start a remote capture (startcap reply command) */
+struct rpcap_startcapreply
+{
+ int32 bufsize; /* Size of the user buffer allocated by WinPcap; it can be different from the one we chose */
+ uint16 portdata; /* Network port on which the server is waiting at (passive mode only) */
+ uint16 dummy; /* Must be zero */
+};
+
+/*
+ * \brief Format of the header which encapsulates captured packets when transmitted on the network.
+ *
+ * This message requires the general header as well, since we want to be able to exchange
+ * more information across the network in the future (for example statistics, and kind like that).
+ */
+struct rpcap_pkthdr
+{
+ uint32 timestamp_sec; /* 'struct timeval' compatible, it represents the 'tv_sec' field */
+ uint32 timestamp_usec; /* 'struct timeval' compatible, it represents the 'tv_usec' field */
+ uint32 caplen; /* Length of portion present in the capture */
+ uint32 len; /* Real length this packet (off wire) */
+ uint32 npkt; /* Ordinal number of the packet (i.e. the first one captured has '1', the second one '2', etc) */
+};
+
+/* General header used for the pcap_setfilter() command; keeps just the number of BPF instructions */
+struct rpcap_filter
+{
+ uint16 filtertype; /* type of the filter transferred (BPF instructions, ...) */
+ uint16 dummy; /* Must be zero */
+ uint32 nitems; /* Number of items contained into the filter (e.g. BPF instructions for BPF filters) */
+};
+
+/* Structure that keeps a single BPF instuction; it is repeated 'ninsn' times according to the 'rpcap_filterbpf' header */
+struct rpcap_filterbpf_insn
+{
+ uint16 code; /* opcode of the instruction */
+ uint8 jt; /* relative offset to jump to in case of 'true' */
+ uint8 jf; /* relative offset to jump to in case of 'false' */
+ int32 k; /* instruction-dependent value */
+};
+
+/* Structure that keeps the data required for the authentication on the remote host */
+struct rpcap_auth
+{
+ uint16 type; /* Authentication type */
+ uint16 dummy; /* Must be zero */
+ uint16 slen1; /* Length of the first authentication item (e.g. username) */
+ uint16 slen2; /* Length of the second authentication item (e.g. password) */
+};
+
+/* Structure that keeps the statistics about the number of packets captured, dropped, etc. */
+struct rpcap_stats
+{
+ uint32 ifrecv; /* Packets received by the kernel filter (i.e. pcap_stats.ps_recv) */
+ uint32 ifdrop; /* Packets dropped by the network interface (e.g. not enough buffers) (i.e. pcap_stats.ps_ifdrop) */
+ uint32 krnldrop; /* Packets dropped by the kernel filter (i.e. pcap_stats.ps_drop) */
+ uint32 svrcapt; /* Packets captured by the RPCAP daemon and sent on the network */
+};
+
+/* Structure that is needed to set sampling parameters */
+struct rpcap_sampling
+{
+ uint8 method; /* Sampling method */
+ uint8 dummy1; /* Must be zero */
+ uint16 dummy2; /* Must be zero */
+ uint32 value; /* Parameter related to the sampling method */
+};
+
+/*
+ * Messages field coding.
+ *
+ * These values are used in messages sent over the network, and MUST
+ * not be changed.
+ */
+#define RPCAP_MSG_IS_REPLY 0x080 /* Flag indicating a reply */
+
+#define RPCAP_MSG_ERROR 1 /* Message that keeps an error notification */
+#define RPCAP_MSG_FINDALLIF_REQ 2 /* Request to list all the remote interfaces */
+#define RPCAP_MSG_OPEN_REQ 3 /* Request to open a remote device */
+#define RPCAP_MSG_STARTCAP_REQ 4 /* Request to start a capture on a remote device */
+#define RPCAP_MSG_UPDATEFILTER_REQ 5 /* Send a compiled filter into the remote device */
+#define RPCAP_MSG_CLOSE 6 /* Close the connection with the remote peer */
+#define RPCAP_MSG_PACKET 7 /* This is a 'data' message, which carries a network packet */
+#define RPCAP_MSG_AUTH_REQ 8 /* Message that keeps the authentication parameters */
+#define RPCAP_MSG_STATS_REQ 9 /* It requires to have network statistics */
+#define RPCAP_MSG_ENDCAP_REQ 10 /* Stops the current capture, keeping the device open */
+#define RPCAP_MSG_SETSAMPLING_REQ 11 /* Set sampling parameters */
+
+#define RPCAP_MSG_FINDALLIF_REPLY (RPCAP_MSG_FINDALLIF_REQ | RPCAP_MSG_IS_REPLY) /* Keeps the list of all the remote interfaces */
+#define RPCAP_MSG_OPEN_REPLY (RPCAP_MSG_OPEN_REQ | RPCAP_MSG_IS_REPLY) /* The remote device has been opened correctly */
+#define RPCAP_MSG_STARTCAP_REPLY (RPCAP_MSG_STARTCAP_REQ | RPCAP_MSG_IS_REPLY) /* The capture is starting correctly */
+#define RPCAP_MSG_UPDATEFILTER_REPLY (RPCAP_MSG_UPDATEFILTER_REQ | RPCAP_MSG_IS_REPLY) /* The filter has been applied correctly on the remote device */
+#define RPCAP_MSG_AUTH_REPLY (RPCAP_MSG_AUTH_REQ | RPCAP_MSG_IS_REPLY) /* Sends a message that says 'ok, authorization successful' */
+#define RPCAP_MSG_STATS_REPLY (RPCAP_MSG_STATS_REQ | RPCAP_MSG_IS_REPLY) /* Message that keeps the network statistics */
+#define RPCAP_MSG_ENDCAP_REPLY (RPCAP_MSG_ENDCAP_REQ | RPCAP_MSG_IS_REPLY) /* Confirms that the capture stopped successfully */
+#define RPCAP_MSG_SETSAMPLING_REPLY (RPCAP_MSG_SETSAMPLING_REQ | RPCAP_MSG_IS_REPLY) /* Confirms that the capture stopped successfully */
+
+#define RPCAP_STARTCAPREQ_FLAG_PROMISC 0x00000001 /* Enables promiscuous mode (default: disabled) */
+#define RPCAP_STARTCAPREQ_FLAG_DGRAM 0x00000002 /* Use a datagram (i.e. UDP) connection for the data stream (default: use TCP)*/
+#define RPCAP_STARTCAPREQ_FLAG_SERVEROPEN 0x00000004 /* The server has to open the data connection toward the client */
+#define RPCAP_STARTCAPREQ_FLAG_INBOUND 0x00000008 /* Capture only inbound packets (take care: the flag has no effect with promiscuous enabled) */
+#define RPCAP_STARTCAPREQ_FLAG_OUTBOUND 0x00000010 /* Capture only outbound packets (take care: the flag has no effect with promiscuous enabled) */
+
+#define RPCAP_UPDATEFILTER_BPF 1 /* This code tells us that the filter is encoded with the BPF/NPF syntax */
+
+/*
+ * Network error codes.
+ *
+ * These values are used in messages sent over the network, and MUST
+ * not be changed.
+ */
+#define PCAP_ERR_NETW 1 /* Network error */
+#define PCAP_ERR_INITTIMEOUT 2 /* The RPCAP initial timeout has expired */
+#define PCAP_ERR_AUTH 3 /* Generic authentication error */
+#define PCAP_ERR_FINDALLIF 4 /* Generic findalldevs error */
+#define PCAP_ERR_NOREMOTEIF 5 /* The findalldevs was ok, but the remote end had no interfaces to list */
+#define PCAP_ERR_OPEN 6 /* Generic pcap_open error */
+#define PCAP_ERR_UPDATEFILTER 7 /* Generic updatefilter error */
+#define PCAP_ERR_GETSTATS 8 /* Generic pcap_stats error */
+#define PCAP_ERR_READEX 9 /* Generic pcap_next_ex error */
+#define PCAP_ERR_HOSTNOAUTH 10 /* The host is not authorized to connect to this server */
+#define PCAP_ERR_REMOTEACCEPT 11 /* Generic pcap_remoteaccept error */
+#define PCAP_ERR_STARTCAPTURE 12 /* Generic pcap_startcapture error */
+#define PCAP_ERR_ENDCAPTURE 13 /* Generic pcap_endcapture error */
+#define PCAP_ERR_RUNTIMETIMEOUT 14 /* The RPCAP run-time timeout has expired */
+#define PCAP_ERR_SETSAMPLING 15 /* Error during the settings of sampling parameters */
+#define PCAP_ERR_WRONGMSG 16 /* The other end endpoint sent a message which has not been recognized */
+#define PCAP_ERR_WRONGVER 17 /* The other end endpoint has a version number that is not compatible with our */
+#define PCAP_ERR_AUTH_FAILED 18 /* The user couldn't be authenticated */
+#define PCAP_ERR_TLS_REQUIRED 19 /* The server requires TLS to connect */
+#define PCAP_ERR_AUTH_TYPE_NOTSUP 20 /* The authentication type isn't supported */
+
+/*
+ * \brief Buffer used by socket functions to send-receive packets.
+ * In case you plan to have messages larger than this value, you have to increase it.
+ */
+#define RPCAP_NETBUF_SIZE 64000
+
+/*********************************************************
+ * *
+ * Routines used by the rpcap client and rpcap daemon *
+ * *
+ *********************************************************/
+
+#include "sockutils.h"
+
+extern void rpcap_createhdr(struct rpcap_header *header, uint8 ver, uint8 type, uint16 value, uint32 length);
+extern const char *rpcap_msg_type_string(uint8 type);
+extern int rpcap_senderror(SOCKET sock, uint8 ver, uint16 errcode, const char *error, char *errbuf);
+
+#endif
diff --git a/lib/libpcap/libpcap/rpcapd/CMakeLists.txt b/lib/libpcap/libpcap/rpcapd/CMakeLists.txt
new file mode 100644
index 0000000..1821c85
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/CMakeLists.txt
@@ -0,0 +1,163 @@
+if(UNIX)
+ check_function_exists(crypt HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+ if(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+ set(HAVE_CRYPT TRUE)
+ else(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+ check_library_exists(crypt crypt "" HAVE_CRYPT_IN_LIBCRYPT)
+ if(HAVE_CRYPT_IN_LIBCRYPT)
+ set(RPCAPD_LINK_LIBRARIES ${RPCAPD_LINK_LIBRARIES} crypt)
+ set(HAVE_CRYPT TRUE)
+ else(HAVE_CRYPT_IN_LIBCRYPT)
+ message(WARNING "crypt() not found. Won't be able to build rpcapd.")
+ endif(HAVE_CRYPT_IN_LIBCRYPT)
+ endif(HAVE_CRYPT_IN_SYSTEM_LIBRARIES)
+endif(UNIX)
+
+#
+# On UN*X, we need pthreads and crypt().
+#
+if(WIN32 OR ((CMAKE_USE_PTHREADS_INIT OR PTHREADS_FOUND) AND HAVE_CRYPT))
+ if(UNIX)
+ #
+ # Do we have getspnam()?
+ #
+ check_function_exists(getspnam HAVE_GETSPNAM)
+
+ #
+ # Find library needed for getaddrinfo.
+ # NOTE: if you hand check_library_exists as its last argument a variable
+ # that's been set, it skips the test, so we need different variables.
+ #
+ include(CheckLibraryExists)
+ check_function_exists(getaddrinfo STDLIBS_HAVE_GETADDRINFO)
+ if(NOT STDLIBS_HAVE_GETADDRINFO)
+ check_library_exists(xnet getaddrinfo "" LIBXNET_HAS_GETADDRINFO)
+ if(LIBXNET_HAS_GETADDRINFO)
+ set(RPCAPD_LINK_LIBRARIES ${RPCAPD_LINK_LIBRARIES} xnet)
+ else(LIBXNET_HAS_GETADDRINFO)
+ include(CMakePushCheckState)
+ cmake_push_check_state()
+ set(CMAKE_REQUIRED_LIBRARIES nsl)
+ check_library_exists(socket getaddrinfo "" LIBSOCKET_HAS_GETADDRINFO)
+ cmake_pop_check_state()
+ if(LIBSOCKET_HAS_GETADDRINFO)
+ set(RPCAPD_LINK_LIBRARIES ${RPCAPD_LINK_LIBRARIES} socket nsl)
+ endif(LIBSOCKET_HAS_GETADDRINFO)
+ endif(LIBXNET_HAS_GETADDRINFO)
+ endif(NOT STDLIBS_HAVE_GETADDRINFO)
+ endif(UNIX)
+
+ if(WIN32)
+ set(RPCAPD_EXTRA_SOURCES
+ win32-svc.c
+ ${pcap_SOURCE_DIR}/missing/getopt.c
+ ${pcap_SOURCE_DIR}/missing/win_snprintf.c
+ rpcapd.rc)
+ include_directories(${pcap_SOURCE_DIR}/rpcapd ${pcap_SOURCE_DIR}/missing)
+ endif(WIN32)
+
+ add_executable(rpcapd
+ daemon.c
+ fileconf.c
+ log.c
+ rpcapd.c
+ ${pcap_SOURCE_DIR}/rpcap-protocol.c
+ ${pcap_SOURCE_DIR}/sockutils.c
+ ${pcap_SOURCE_DIR}/fmtutils.c
+ ${RPCAPD_EXTRA_SOURCES}
+ )
+
+ if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+ set_target_properties(rpcapd PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+ endif()
+
+ #
+ # By default, build rpcapd universal with the appropriate set of
+ # architectures for the OS on which we're doing the build.
+ #
+ if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "")
+ #
+ # Get the major version of Darwin.
+ #
+ string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}")
+
+ if(SYSTEM_VERSION_MAJOR EQUAL 9)
+ #
+ # Leopard. Build for 32-bit x86 and 32-bit PowerPC, with
+ # 32-bit x86 first.
+ #
+ set(OSX_PROGRAM_ARCHITECTURES "i386;ppc")
+ elseif(SYSTEM_VERSION_MAJOR EQUAL 10)
+ #
+ # Snow Leopard. Build for x86-64 and 32-bit x86, with
+ # x86-64 first.
+ #
+ set(OSX_PROGRAM_ARCHITECTURES "x86_64;i386")
+ else()
+ #
+ # Post-Snow Leopard. Build only for x86-64.
+ # XXX - update if and when Apple adds ARM-based Macs.
+ # (You're on your own for iOS etc.)
+ #
+ set(OSX_PROGRAM_ARCHITECTURES "x86_64")
+ endif()
+
+ set_target_properties(rpcapd PROPERTIES
+ OSX_ARCHITECTURES "${OSX_PROGRAM_ARCHITECTURES}")
+ endif()
+
+ if(WIN32)
+ target_link_libraries(rpcapd ${LIBRARY_NAME}
+ ${RPCAPD_LINK_LIBRARIES} ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+ else(WIN32)
+ target_link_libraries(rpcapd ${LIBRARY_NAME}_static
+ ${RPCAPD_LINK_LIBRARIES} ${PCAP_LINK_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+ endif(WIN32)
+
+ ######################################
+ # Install rpcap daemon and man pages
+ ######################################
+
+ #
+ # "Define GNU standard installation directories", which actually
+ # are also defined, to some degree, by autotools, and at least
+ # some of which are general UN*X conventions.
+ #
+ include(GNUInstallDirs)
+
+ set(MANADMIN_EXPAND rpcapd.manadmin.in)
+
+ set(MANFILE_EXPAND rpcapd-config.manfile.in)
+
+ if(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ install(TARGETS rpcapd DESTINATION bin/amd64)
+ else(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+ install(TARGETS rpcapd DESTINATION bin)
+ endif(MSVC AND CMAKE_SIZEOF_VOID_P EQUAL 8)
+
+ # On UN*X, and on Windows when not using MSVC, generate process man
+ # pages and arrange that they be installed.
+ if(NOT MSVC)
+ #
+ # Man pages.
+ #
+ # For each section of the manual for which we have man pages
+ # that require macro expansion, do the expansion.
+ #
+ set(MANADMIN "")
+ foreach(TEMPLATE_MANPAGE ${MANADMIN_EXPAND})
+ string(REPLACE ".manadmin.in" ".${MAN_ADMIN_COMMANDS}" MANPAGE ${TEMPLATE_MANPAGE})
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+ set(MANADMIN ${MANADMIN} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+ endforeach(TEMPLATE_MANPAGE)
+ install(FILES ${MANADMIN} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_ADMIN_COMMANDS})
+
+ set(MANFILE "")
+ foreach(TEMPLATE_MANPAGE ${MANFILE_EXPAND})
+ string(REPLACE ".manfile.in" ".${MAN_FILE_FORMATS}" MANPAGE ${TEMPLATE_MANPAGE})
+ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY)
+ set(MANFILE ${MANFILE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE})
+ endforeach(TEMPLATE_MANPAGE)
+ install(FILES ${MANFILE} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_FILE_FORMATS})
+ endif(NOT MSVC)
+endif(WIN32 OR ((CMAKE_USE_PTHREADS_INIT OR PTHREADS_FOUND) AND HAVE_CRYPT))
diff --git a/lib/libpcap/libpcap/rpcapd/Makefile b/lib/libpcap/libpcap/rpcapd/Makefile
new file mode 100644
index 0000000..114f8b7
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/Makefile
@@ -0,0 +1,141 @@
+# Copyright (c) 1993, 1994, 1995, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = /usr/local
+exec_prefix = ${prefix}
+datarootdir = ${prefix}/share
+# Pathname of directory to install the configure program
+bindir = ${exec_prefix}/bin
+# Pathname of directory to install the rpcapd daemon
+sbindir = ${exec_prefix}/sbin
+# Pathname of directory to install the include files
+includedir = ${prefix}/include
+# Pathname of directory to install the library
+libdir = ${exec_prefix}/lib
+# Pathname of directory to install the man pages
+mandir = ${datarootdir}/man
+
+# VPATH
+srcdir = .
+
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = gcc
+AR = ar
+LN_S = ln -s
+MKDEP =
+CCOPT = -fvisibility=hidden -fno-common
+INCLS = -I. -I.. -I. -I./.. -I/usr/local/include
+DEFS = -DHAVE_CONFIG_H
+ADDLOBJS =
+ADDLARCHIVEOBJS =
+LIBS =
+PTHREAD_LIBS =
+CROSSFLAGS=
+CFLAGS = -g -O2 ${CROSSFLAGS}
+LDFLAGS = ${CROSSFLAGS}
+DYEXT = dylib
+V_RPATH_OPT =
+DEPENDENCY_CFLAG =
+PROG=libpcap
+RPCAPD_LIBS =
+
+# Standard CFLAGS
+FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+ @rm -f $@
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+SRC = daemon.c \
+ fileconf.c \
+ log.c \
+ rpcapd.c
+
+OBJ = $(SRC:.c=.o) ../rpcap-protocol.o ../sockutils.o ../fmtutils.o
+PUBHDR =
+
+HDR = $(PUBHDR) log.h
+
+TAGFILES = \
+ $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) rpcapd
+
+MANADMIN = \
+ rpcapd.manadmin.in
+
+MANFILE = \
+ rpcapd-config.manfile.in
+
+rpcapd: $(OBJ) ../libpcap.a
+ $(CC) $(CCOPT) $(CFLAGS) $(LDFLAGS) \
+ -o $@ $(OBJ) ../libpcap.a $(LIBS) $(RPCAPD_LIBS) $(PTHREAD_LIBS)
+clean:
+ rm -f $(CLEANFILES)
+
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
+ config.h stamp-h stamp-h.in
+ rm -f $(MANADMIN:.in=) $(MANFILE:.in=)
+ rm -rf autom4te.cache
+
+install: rpcapd
+ [ -d $(DESTDIR)$(sbindir) ] || \
+ (mkdir -p $(DESTDIR)$(sbindir); chmod 755 $(DESTDIR)$(sbindir))
+ $(INSTALL_PROGRAM) rpcapd $(DESTDIR)$(sbindir)/rpcapd
+ [ -d $(DESTDIR)$(mandir)/man8 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man8; chmod 755 $(DESTDIR)$(mandir)/man8)
+ [ -d $(DESTDIR)$(mandir)/man5 ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man5; chmod 755 $(DESTDIR)$(mandir)/man5)
+ for i in $(MANADMIN); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manadmin.in/.manadmin/'` \
+ $(DESTDIR)$(mandir)/man8/`echo $$i | sed 's/.manadmin.in/.8/'`; done
+ for i in $(MANFILE); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+ $(DESTDIR)$(mandir)/man5/`echo $$i | sed 's/.manfile.in/.5/'`; done
+
+uninstall:
+ rm -f $(DESTDIR)$(sbindir)/rpcapd
+ for i in $(MANADMIN); do \
+ rm -f $(DESTDIR)$(mandir)/man8/`echo $$i | sed 's/.manadmin.in/.8/'`; done
+ for i in $(MANFILE); do \
+ rm -f $(DESTDIR)$(mandir)/man5/`echo $$i | sed 's/.manfile.in/.5/'`; done
+
+tags: $(TAGFILES)
+ ctags -wtd $(TAGFILES)
+
+depend:
+ ../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/lib/libpcap/libpcap/rpcapd/Makefile.in b/lib/libpcap/libpcap/rpcapd/Makefile.in
new file mode 100644
index 0000000..88e632a
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/Makefile.in
@@ -0,0 +1,141 @@
+# Copyright (c) 1993, 1994, 1995, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+# Pathname of directory to install the configure program
+bindir = @bindir@
+# Pathname of directory to install the rpcapd daemon
+sbindir = @sbindir@
+# Pathname of directory to install the include files
+includedir = @includedir@
+# Pathname of directory to install the library
+libdir = @libdir@
+# Pathname of directory to install the man pages
+mandir = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = @CC@
+AR = @AR@
+LN_S = @LN_S@
+MKDEP = @MKDEP@
+CCOPT = @V_CCOPT@
+INCLS = -I. -I.. -I@srcdir@ -I@srcdir@/.. @V_INCLS@
+DEFS = @DEFS@ @V_DEFS@
+ADDLOBJS = @ADDLOBJS@
+ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
+LIBS = @LIBS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+CROSSFLAGS=
+CFLAGS = @CFLAGS@ ${CROSSFLAGS}
+LDFLAGS = @LDFLAGS@ ${CROSSFLAGS}
+DYEXT = @DYEXT@
+V_RPATH_OPT = @V_RPATH_OPT@
+DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
+PROG=libpcap
+RPCAPD_LIBS = @RPCAPD_LIBS@
+
+# Standard CFLAGS
+FULL_CFLAGS = $(CCOPT) @V_PROG_CCOPT_FAT@ $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+ @rm -f $@
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+SRC = daemon.c \
+ fileconf.c \
+ log.c \
+ rpcapd.c
+
+OBJ = $(SRC:.c=.o) ../rpcap-protocol.o ../sockutils.o ../fmtutils.o
+PUBHDR =
+
+HDR = $(PUBHDR) log.h
+
+TAGFILES = \
+ $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) rpcapd
+
+MANADMIN = \
+ rpcapd.manadmin.in
+
+MANFILE = \
+ rpcapd-config.manfile.in
+
+rpcapd: $(OBJ) ../libpcap.a
+ $(CC) $(CCOPT) $(CFLAGS) $(LDFLAGS) @V_PROG_LDFLAGS_FAT@ \
+ -o $@ $(OBJ) ../libpcap.a $(LIBS) $(RPCAPD_LIBS) $(PTHREAD_LIBS)
+clean:
+ rm -f $(CLEANFILES)
+
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
+ config.h stamp-h stamp-h.in
+ rm -f $(MANADMIN:.in=) $(MANFILE:.in=)
+ rm -rf autom4te.cache
+
+install: rpcapd
+ [ -d $(DESTDIR)$(sbindir) ] || \
+ (mkdir -p $(DESTDIR)$(sbindir); chmod 755 $(DESTDIR)$(sbindir))
+ $(INSTALL_PROGRAM) rpcapd $(DESTDIR)$(sbindir)/rpcapd
+ [ -d $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@ ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@)
+ [ -d $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@ ] || \
+ (mkdir -p $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@; chmod 755 $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@)
+ for i in $(MANADMIN); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manadmin.in/.manadmin/'` \
+ $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@/`echo $$i | sed 's/.manadmin.in/.@MAN_ADMIN_COMMANDS@/'`; done
+ for i in $(MANFILE); do \
+ $(INSTALL_DATA) `echo $$i | sed 's/.manfile.in/.manfile/'` \
+ $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+
+uninstall:
+ rm -f $(DESTDIR)$(sbindir)/rpcapd
+ for i in $(MANADMIN); do \
+ rm -f $(DESTDIR)$(mandir)/man@MAN_ADMIN_COMMANDS@/`echo $$i | sed 's/.manadmin.in/.@MAN_ADMIN_COMMANDS@/'`; done
+ for i in $(MANFILE); do \
+ rm -f $(DESTDIR)$(mandir)/man@MAN_FILE_FORMATS@/`echo $$i | sed 's/.manfile.in/.@MAN_FILE_FORMATS@/'`; done
+
+tags: $(TAGFILES)
+ ctags -wtd $(TAGFILES)
+
+depend:
+ ../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/lib/libpcap/libpcap/rpcapd/config_params.h b/lib/libpcap/libpcap/rpcapd/config_params.h
new file mode 100644
index 0000000..c219ce1
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/config_params.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifndef __CONFIG_PARAMS_H__
+#define __CONFIG_PARAMS_H__
+
+//
+// Parameters set from the configuration file.
+//
+
+#define MAX_LINE 2048 /* Maximum chars allowed for the host list (in passive mode) */
+#define MAX_HOST_LIST 64000
+#define MAX_ACTIVE_LIST 10
+
+struct active_pars
+{
+ char address[MAX_LINE + 1]; // keeps the network address (either numeric or literal) to of the active client
+ char port[MAX_LINE + 1]; // keeps the network port to bind to
+ int ai_family; // address faimly to use
+};
+
+extern char hostlist[MAX_HOST_LIST + 1]; //!< Keeps the list of the hosts that are allowed to connect to this server
+extern struct active_pars activelist[MAX_ACTIVE_LIST]; //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
+extern int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise
+extern char loadfile[MAX_LINE + 1]; //!< Name of the file from which we have to load the configuration
+
+#endif
diff --git a/lib/libpcap/libpcap/rpcapd/daemon.c b/lib/libpcap/libpcap/rpcapd/daemon.c
new file mode 100644
index 0000000..209dba2
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/daemon.c
@@ -0,0 +1,2747 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+#include "varattrs.h"
+
+#include <errno.h> // for the errno variable
+#include <stdlib.h> // for malloc(), free(), ...
+#include <string.h> // for strlen(), ...
+
+#ifdef _WIN32
+ #include <process.h> // for threads
+#else
+ #include <unistd.h>
+ #include <pthread.h>
+ #include <signal.h>
+ #include <sys/time.h>
+ #include <sys/types.h> // for select() and such
+ #include <pwd.h> // for password management
+#endif
+
+#ifdef HAVE_GETSPNAM
+#include <shadow.h> // for password management
+#endif
+
+#include <pcap.h> // for libpcap/WinPcap calls
+
+#include "fmtutils.h"
+#include "sockutils.h" // for socket calls
+#include "portability.h"
+#include "rpcap-protocol.h"
+#include "daemon.h"
+#include "log.h"
+
+//
+// Timeout, in seconds, when we're waiting for a client to send us an
+// authentication request; if they don't send us a request within that
+// interval, we drop the connection, so we don't stay stuck forever.
+//
+#define RPCAP_TIMEOUT_INIT 90
+
+//
+// Timeout, in seconds, when we're waiting for an authenticated client
+// to send us a request, if a capture isn't in progress; if they don't
+// send us a request within that interval, we drop the connection, so
+// we don't stay stuck forever.
+//
+#define RPCAP_TIMEOUT_RUNTIME 180
+
+//
+// Time, in seconds, that we wait after a failed authentication attempt
+// before processing the next request; this prevents a client from
+// rapidly trying different accounts or passwords.
+//
+#define RPCAP_SUSPEND_WRONGAUTH 1
+
+// Parameters for the service loop.
+struct daemon_slpars
+{
+ SOCKET sockctrl; //!< SOCKET ID of the control connection
+ int isactive; //!< Not null if the daemon has to run in active mode
+ int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise
+};
+
+//
+// Data for a session managed by a thread.
+// It includes both a Boolean indicating whether we *have* a thread,
+// and a platform-dependent (UN*X vs. Windows) identifier for the
+// thread; on Windows, we could use an invalid handle to indicate
+// that we don't have a thread, but there *is* no portable "no thread"
+// value for a pthread_t on UN*X.
+//
+struct session {
+ SOCKET sockctrl;
+ SOCKET sockdata;
+ uint8 protocol_version;
+ pcap_t *fp;
+ unsigned int TotCapt;
+ int have_thread;
+#ifdef _WIN32
+ HANDLE thread;
+#else
+ pthread_t thread;
+#endif
+};
+
+// Locally defined functions
+static int daemon_msg_err(SOCKET sockctrl, uint32 plen);
+static int daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen);
+static int daemon_AuthUserPwd(char *username, char *password, char *errbuf);
+
+static int daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars,
+ uint32 plen);
+
+static int daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars,
+ uint32 plen, char *source, size_t sourcelen);
+static int daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars,
+ uint32 plen, char *source, struct session **sessionp,
+ struct rpcap_sampling *samp_param);
+static int daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+ struct session *session);
+
+static int daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+ struct session *session, uint32 plen);
+static int daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp, char *errbuf);
+
+static int daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+ struct session *session, uint32 plen, struct pcap_stat *stats,
+ unsigned int svrcapt);
+
+static int daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars,
+ uint32 plen, struct rpcap_sampling *samp_param);
+
+static void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout);
+#ifdef _WIN32
+static unsigned __stdcall daemon_thrdatamain(void *ptr);
+#else
+static void *daemon_thrdatamain(void *ptr);
+static void noop_handler(int sign);
+#endif
+
+static int rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp);
+static int rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf);
+static int rpcapd_discard(SOCKET sock, uint32 len);
+static void session_close(struct session *);
+
+static int is_url(const char *source);
+
+int
+daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
+ int nullAuthAllowed)
+{
+ struct daemon_slpars pars; // service loop parameters
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+ char errmsgbuf[PCAP_ERRBUF_SIZE + 1]; // buffer for errors to send to the client
+ int host_port_check_status;
+ int nrecv;
+ struct rpcap_header header; // RPCAP message general header
+ uint32 plen; // payload length from header
+ int authenticated = 0; // 1 if the client has successfully authenticated
+ char source[PCAP_BUF_SIZE+1]; // keeps the string that contains the interface to open
+ int got_source = 0; // 1 if we've gotten the source from an open request
+#ifndef _WIN32
+ struct sigaction action;
+#endif
+ struct session *session = NULL; // struct session main variable
+ const char *msg_type_string; // string for message type
+ int client_told_us_to_close = 0; // 1 if the client told us to close the capture
+
+ // needed to save the values of the statistics
+ struct pcap_stat stats;
+ unsigned int svrcapt;
+
+ struct rpcap_sampling samp_param; // in case sampling has been requested
+
+ // Structures needed for the select() call
+ fd_set rfds; // set of socket descriptors we have to check
+ struct timeval tv; // maximum time the select() can block waiting for data
+ int retval; // select() return value
+
+ *errbuf = 0; // Initialize errbuf
+
+ // Set parameters structure
+ pars.sockctrl = sockctrl;
+ pars.isactive = isactive; // active mode
+ pars.nullAuthAllowed = nullAuthAllowed;
+
+ //
+ // We have a connection.
+ //
+ // If it's a passive mode connection, check whether the connecting
+ // host is among the ones allowed.
+ //
+ // In either case, we were handed a copy of the host list; free it
+ // as soon as we're done with it.
+ //
+ if (pars.isactive)
+ {
+ // Nothing to do.
+ free(passiveClients);
+ passiveClients = NULL;
+ }
+ else
+ {
+ struct sockaddr_storage from;
+ socklen_t fromlen;
+
+ //
+ // Get the address of the other end of the connection.
+ //
+ fromlen = sizeof(struct sockaddr_storage);
+ if (getpeername(pars.sockctrl, (struct sockaddr *)&from,
+ &fromlen) == -1)
+ {
+ sock_geterror("getpeername()", errmsgbuf, PCAP_ERRBUF_SIZE);
+ if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+
+ //
+ // Are they in the list of host/port combinations we allow?
+ //
+ host_port_check_status = sock_check_hostlist(passiveClients, RPCAP_HOSTLIST_SEP, &from, errmsgbuf, PCAP_ERRBUF_SIZE);
+ free(passiveClients);
+ passiveClients = NULL;
+ if (host_port_check_status < 0)
+ {
+ if (host_port_check_status == -2) {
+ //
+ // We got an error; log it.
+ //
+ rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+ }
+
+ //
+ // Sorry, we can't let you in.
+ //
+ if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_HOSTNOAUTH, errmsgbuf, errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ }
+
+#ifndef _WIN32
+ //
+ // Catch SIGUSR1, but do nothing. We use it to interrupt the
+ // capture thread to break it out of a loop in which it's
+ // blocked waiting for packets to arrive.
+ //
+ // We don't want interrupted system calls to restart, so that
+ // the read routine for the pcap_t gets EINTR rather than
+ // restarting if it's blocked in a system call.
+ //
+ memset(&action, 0, sizeof (action));
+ action.sa_handler = noop_handler;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGUSR1, &action, NULL);
+#endif
+
+ //
+ // The client must first authenticate; loop until they send us a
+ // message with a version we support and credentials we accept,
+ // they send us a close message indicating that they're giving up,
+ // or we get a network error or other fatal error.
+ //
+ while (!authenticated)
+ {
+ //
+ // If we're not in active mode, we use select(), with a
+ // timeout, to wait for an authentication request; if
+ // the timeout expires, we drop the connection, so that
+ // a client can't just connect to us and leave us
+ // waiting forever.
+ //
+ if (!pars.isactive)
+ {
+ FD_ZERO(&rfds);
+ // We do not have to block here
+ tv.tv_sec = RPCAP_TIMEOUT_INIT;
+ tv.tv_usec = 0;
+
+ FD_SET(pars.sockctrl, &rfds);
+
+ retval = select(pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
+ if (retval == -1)
+ {
+ sock_geterror("select() failed", errmsgbuf, PCAP_ERRBUF_SIZE);
+ if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+
+ // The timeout has expired
+ // So, this was a fake connection. Drop it down
+ if (retval == 0)
+ {
+ if (rpcap_senderror(pars.sockctrl, 0, PCAP_ERR_INITTIMEOUT, "The RPCAP initial timeout has expired", errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ }
+
+ //
+ // Read the message header from the client.
+ //
+ nrecv = rpcapd_recv_msg_header(pars.sockctrl, &header);
+ if (nrecv == -1)
+ {
+ // Fatal error.
+ goto end;
+ }
+ if (nrecv == -2)
+ {
+ // Client closed the connection.
+ goto end;
+ }
+
+ plen = header.plen;
+
+ //
+ // While we're in the authentication pharse, all requests
+ // must use version 0.
+ //
+ if (header.ver != 0)
+ {
+ //
+ // Send it back to them with their version.
+ //
+ if (rpcap_senderror(pars.sockctrl, header.ver,
+ PCAP_ERR_WRONGVER,
+ "RPCAP version in requests in the authentication phase must be 0",
+ errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+
+ // Discard the rest of the message and drop the
+ // connection.
+ (void)rpcapd_discard(pars.sockctrl, plen);
+ goto end;
+ }
+
+ switch (header.type)
+ {
+ case RPCAP_MSG_AUTH_REQ:
+ retval = daemon_msg_auth_req(&pars, plen);
+ if (retval == -1)
+ {
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ if (retval == -2)
+ {
+ // Non-fatal error; we sent back
+ // an error message, so let them
+ // try again.
+ continue;
+ }
+
+ // OK, we're authenticated; we sent back
+ // a reply, so start serving requests.
+ authenticated = 1;
+ break;
+
+ case RPCAP_MSG_CLOSE:
+ //
+ // The client is giving up.
+ // Discard the rest of the message, if
+ // there is anything more.
+ //
+ (void)rpcapd_discard(pars.sockctrl, plen);
+ // We're done with this client.
+ goto end;
+
+ case RPCAP_MSG_ERROR:
+ // Log this and close the connection?
+ // XXX - is this what happens in active
+ // mode, where *we* initiate the
+ // connection, and the client gives us
+ // an error message rather than a "let
+ // me log in" message, indicating that
+ // we're not allowed to connect to them?
+ (void)daemon_msg_err(pars.sockctrl, plen);
+ goto end;
+
+ case RPCAP_MSG_FINDALLIF_REQ:
+ case RPCAP_MSG_OPEN_REQ:
+ case RPCAP_MSG_STARTCAP_REQ:
+ case RPCAP_MSG_UPDATEFILTER_REQ:
+ case RPCAP_MSG_STATS_REQ:
+ case RPCAP_MSG_ENDCAP_REQ:
+ case RPCAP_MSG_SETSAMPLING_REQ:
+ //
+ // These requests can't be sent until
+ // the client is authenticated.
+ //
+ msg_type_string = rpcap_msg_type_string(header.type);
+ if (msg_type_string != NULL)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s request sent before authentication was completed", msg_type_string);
+ }
+ else
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message of type %u sent before authentication was completed", header.type);
+ }
+ if (rpcap_senderror(pars.sockctrl, header.ver,
+ PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ // Discard the rest of the message.
+ if (rpcapd_discard(pars.sockctrl, plen) == -1)
+ {
+ // Network error.
+ goto end;
+ }
+ break;
+
+ case RPCAP_MSG_PACKET:
+ case RPCAP_MSG_FINDALLIF_REPLY:
+ case RPCAP_MSG_OPEN_REPLY:
+ case RPCAP_MSG_STARTCAP_REPLY:
+ case RPCAP_MSG_UPDATEFILTER_REPLY:
+ case RPCAP_MSG_AUTH_REPLY:
+ case RPCAP_MSG_STATS_REPLY:
+ case RPCAP_MSG_ENDCAP_REPLY:
+ case RPCAP_MSG_SETSAMPLING_REPLY:
+ //
+ // These are server-to-client messages.
+ //
+ msg_type_string = rpcap_msg_type_string(header.type);
+ if (msg_type_string != NULL)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
+ }
+ else
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
+ }
+ if (rpcap_senderror(pars.sockctrl, header.ver,
+ PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ // Discard the rest of the message.
+ if (rpcapd_discard(pars.sockctrl, plen) == -1)
+ {
+ // Fatal error.
+ goto end;
+ }
+ break;
+
+ default:
+ //
+ // Unknown message type.
+ //
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
+ if (rpcap_senderror(pars.sockctrl, header.ver,
+ PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ // Discard the rest of the message.
+ if (rpcapd_discard(pars.sockctrl, plen) == -1)
+ {
+ // Fatal error.
+ goto end;
+ }
+ break;
+ }
+ }
+
+ //
+ // OK, the client has authenticated itself, and we can start
+ // processing regular requests from it.
+ //
+
+ //
+ // We don't have any statistics yet.
+ //
+ stats.ps_ifdrop = 0;
+ stats.ps_recv = 0;
+ stats.ps_drop = 0;
+ svrcapt = 0;
+
+ //
+ // Service requests.
+ //
+ for (;;)
+ {
+ errbuf[0] = 0; // clear errbuf
+
+ // Avoid zombies connections; check if the connection is opens but no commands are performed
+ // from more than RPCAP_TIMEOUT_RUNTIME
+ // Conditions:
+ // - I have to be in normal mode (no active mode)
+ // - if the device is open, I don't have to be in the middle of a capture (session->sockdata)
+ // - if the device is closed, I have always to check if a new command arrives
+ //
+ // Be carefully: the capture can have been started, but an error occurred (so session != NULL, but
+ // sockdata is 0
+ if ((!pars.isactive) && ((session == NULL) || ((session != NULL) && (session->sockdata == 0))))
+ {
+ // Check for the initial timeout
+ FD_ZERO(&rfds);
+ // We do not have to block here
+ tv.tv_sec = RPCAP_TIMEOUT_RUNTIME;
+ tv.tv_usec = 0;
+
+ FD_SET(pars.sockctrl, &rfds);
+
+ retval = select(pars.sockctrl + 1, &rfds, NULL, NULL, &tv);
+ if (retval == -1)
+ {
+ sock_geterror("select() failed", errmsgbuf, PCAP_ERRBUF_SIZE);
+ if (rpcap_senderror(pars.sockctrl, 0,
+ PCAP_ERR_NETW, errmsgbuf, errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+
+ // The timeout has expired
+ // So, this was a fake connection. Drop it down
+ if (retval == 0)
+ {
+ if (rpcap_senderror(pars.sockctrl, 0,
+ PCAP_ERR_INITTIMEOUT,
+ "The RPCAP initial timeout has expired",
+ errbuf) == -1)
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ }
+
+ //
+ // Read the message header from the client.
+ //
+ nrecv = rpcapd_recv_msg_header(pars.sockctrl, &header);
+ if (nrecv == -1)
+ {
+ // Fatal error.
+ goto end;
+ }
+ if (nrecv == -2)
+ {
+ // Client closed the connection.
+ goto end;
+ }
+
+ plen = header.plen;
+
+ //
+ // Did the client specify a protocol version that we
+ // support?
+ //
+ if (!RPCAP_VERSION_IS_SUPPORTED(header.ver))
+ {
+ //
+ // Tell them it's not a supported version.
+ // Send the error message with their version,
+ // so they don't reject it as having the wrong
+ // version.
+ //
+ if (rpcap_senderror(pars.sockctrl,
+ header.ver, PCAP_ERR_WRONGVER,
+ "RPCAP version in message isn't supported by the server",
+ errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+
+ // Discard the rest of the message.
+ (void)rpcapd_discard(pars.sockctrl, plen);
+ // Give up on them.
+ goto end;
+ }
+
+ switch (header.type)
+ {
+ case RPCAP_MSG_ERROR: // The other endpoint reported an error
+ {
+ (void)daemon_msg_err(pars.sockctrl, plen);
+ // Do nothing; just exit; the error code is already into the errbuf
+ // XXX - actually exit....
+ break;
+ }
+
+ case RPCAP_MSG_FINDALLIF_REQ:
+ {
+ if (daemon_msg_findallif_req(header.ver, &pars, plen) == -1)
+ {
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ break;
+ }
+
+ case RPCAP_MSG_OPEN_REQ:
+ {
+ //
+ // Process the open request, and keep
+ // the source from it, for use later
+ // when the capture is started.
+ //
+ // XXX - we don't care if the client sends
+ // us multiple open requests, the last
+ // one wins.
+ //
+ retval = daemon_msg_open_req(header.ver, &pars,
+ plen, source, sizeof(source));
+ if (retval == -1)
+ {
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ got_source = 1;
+ break;
+ }
+
+ case RPCAP_MSG_STARTCAP_REQ:
+ {
+ if (!got_source)
+ {
+ // They never told us what device
+ // to capture on!
+ if (rpcap_senderror(pars.sockctrl,
+ header.ver,
+ PCAP_ERR_STARTCAPTURE,
+ "No capture device was specified",
+ errbuf) == -1)
+ {
+ // Fatal error; log an
+ // error and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ if (rpcapd_discard(pars.sockctrl, plen) == -1)
+ {
+ goto end;
+ }
+ break;
+ }
+
+ if (daemon_msg_startcap_req(header.ver, &pars,
+ plen, source, &session, &samp_param) == -1)
+ {
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ break;
+ }
+
+ case RPCAP_MSG_UPDATEFILTER_REQ:
+ {
+ if (session)
+ {
+ if (daemon_msg_updatefilter_req(header.ver,
+ &pars, session, plen) == -1)
+ {
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ }
+ else
+ {
+ if (rpcap_senderror(pars.sockctrl,
+ header.ver, PCAP_ERR_UPDATEFILTER,
+ "Device not opened. Cannot update filter",
+ errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ }
+ break;
+ }
+
+ case RPCAP_MSG_CLOSE: // The other endpoint close the pcap session
+ {
+ //
+ // Indicate to our caller that the client
+ // closed the control connection.
+ // This is used only in case of active mode.
+ //
+ client_told_us_to_close = 1;
+ rpcapd_log(LOGPRIO_DEBUG, "The other end system asked to close the connection.");
+ goto end;
+ }
+
+ case RPCAP_MSG_STATS_REQ:
+ {
+ if (daemon_msg_stats_req(header.ver, &pars,
+ session, plen, &stats, svrcapt) == -1)
+ {
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ break;
+ }
+
+ case RPCAP_MSG_ENDCAP_REQ: // The other endpoint close the current capture session
+ {
+ if (session)
+ {
+ // Save statistics (we can need them in the future)
+ if (pcap_stats(session->fp, &stats))
+ {
+ svrcapt = session->TotCapt;
+ }
+ else
+ {
+ stats.ps_ifdrop = 0;
+ stats.ps_recv = 0;
+ stats.ps_drop = 0;
+ svrcapt = 0;
+ }
+
+ if (daemon_msg_endcap_req(header.ver,
+ &pars, session) == -1)
+ {
+ free(session);
+ session = NULL;
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ free(session);
+ session = NULL;
+ }
+ else
+ {
+ rpcap_senderror(pars.sockctrl,
+ header.ver, PCAP_ERR_ENDCAPTURE,
+ "Device not opened. Cannot close the capture",
+ errbuf);
+ }
+ break;
+ }
+
+ case RPCAP_MSG_SETSAMPLING_REQ:
+ {
+ if (daemon_msg_setsampling_req(header.ver,
+ &pars, plen, &samp_param) == -1)
+ {
+ // Fatal error; a message has
+ // been logged, so just give up.
+ goto end;
+ }
+ break;
+ }
+
+ case RPCAP_MSG_AUTH_REQ:
+ {
+ //
+ // We're already authenticated; you don't
+ // get to reauthenticate.
+ //
+ rpcapd_log(LOGPRIO_INFO, "The client sent an RPCAP_MSG_AUTH_REQ message after authentication was completed");
+ if (rpcap_senderror(pars.sockctrl, header.ver,
+ PCAP_ERR_WRONGMSG,
+ "RPCAP_MSG_AUTH_REQ request sent after authentication was completed",
+ errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ // Discard the rest of the message.
+ if (rpcapd_discard(pars.sockctrl, plen) == -1)
+ {
+ // Fatal error.
+ goto end;
+ }
+ goto end;
+
+ case RPCAP_MSG_PACKET:
+ case RPCAP_MSG_FINDALLIF_REPLY:
+ case RPCAP_MSG_OPEN_REPLY:
+ case RPCAP_MSG_STARTCAP_REPLY:
+ case RPCAP_MSG_UPDATEFILTER_REPLY:
+ case RPCAP_MSG_AUTH_REPLY:
+ case RPCAP_MSG_STATS_REPLY:
+ case RPCAP_MSG_ENDCAP_REPLY:
+ case RPCAP_MSG_SETSAMPLING_REPLY:
+ //
+ // These are server-to-client messages.
+ //
+ msg_type_string = rpcap_msg_type_string(header.type);
+ if (msg_type_string != NULL)
+ {
+ rpcapd_log(LOGPRIO_INFO, "The client sent a %s server-to-client message", msg_type_string);
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message %s received from client", msg_type_string);
+ }
+ else
+ {
+ rpcapd_log(LOGPRIO_INFO, "The client sent a server-to-client message of type %u", header.type);
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Server-to-client message of type %u received from client", header.type);
+ }
+ if (rpcap_senderror(pars.sockctrl, header.ver,
+ PCAP_ERR_WRONGMSG, errmsgbuf, errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ // Discard the rest of the message.
+ if (rpcapd_discard(pars.sockctrl, plen) == -1)
+ {
+ // Fatal error.
+ goto end;
+ }
+ goto end;
+
+ default:
+ //
+ // Unknown message type.
+ //
+ rpcapd_log(LOGPRIO_INFO, "The client sent a message of type %u", header.type);
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Unknown message type %u", header.type);
+ if (rpcap_senderror(pars.sockctrl, header.ver,
+ PCAP_ERR_WRONGMSG, errbuf, errmsgbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto end;
+ }
+ // Discard the rest of the message.
+ if (rpcapd_discard(pars.sockctrl, plen) == -1)
+ {
+ // Fatal error.
+ goto end;
+ }
+ goto end;
+ }
+ }
+ }
+
+end:
+ // The service loop is finishing up.
+ // If we have a capture session running, close it.
+ if (session)
+ {
+ session_close(session);
+ free(session);
+ session = NULL;
+ }
+
+ sock_close(sockctrl, NULL, 0);
+
+ // Print message and return
+ rpcapd_log(LOGPRIO_DEBUG, "I'm exiting from the child loop");
+
+ return client_told_us_to_close;
+}
+
+/*
+ * This handles the RPCAP_MSG_ERR message.
+ */
+static int
+daemon_msg_err(SOCKET sockctrl, uint32 plen)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+ char remote_errbuf[PCAP_ERRBUF_SIZE];
+
+ if (plen >= PCAP_ERRBUF_SIZE)
+ {
+ /*
+ * Message is too long; just read as much of it as we
+ * can into the buffer provided, and discard the rest.
+ */
+ if (sock_recv(sockctrl, remote_errbuf, PCAP_ERRBUF_SIZE - 1,
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ {
+ // Network error.
+ rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+ return -1;
+ }
+ if (rpcapd_discard(sockctrl, plen - (PCAP_ERRBUF_SIZE - 1)) == -1)
+ {
+ // Network error.
+ return -1;
+ }
+
+ /*
+ * Null-terminate it.
+ */
+ remote_errbuf[PCAP_ERRBUF_SIZE - 1] = '\0';
+ }
+ else if (plen == 0)
+ {
+ /* Empty error string. */
+ remote_errbuf[0] = '\0';
+ }
+ else
+ {
+ if (sock_recv(sockctrl, remote_errbuf, plen,
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ {
+ // Network error.
+ rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+ return -1;
+ }
+
+ /*
+ * Null-terminate it.
+ */
+ remote_errbuf[plen] = '\0';
+ }
+ // Log the message
+ rpcapd_log(LOGPRIO_ERROR, "Error from client: %s", remote_errbuf);
+ return 0;
+}
+
+/*
+ * This handles the RPCAP_MSG_AUTH_REQ message.
+ * It checks if the authentication credentials supplied by the user are valid.
+ *
+ * This function is called if the daemon receives a RPCAP_MSG_AUTH_REQ
+ * message in its authentication loop. It reads the body of the
+ * authentication message from the network and checks whether the
+ * credentials are valid.
+ *
+ * \param sockctrl: the socket for the control connection.
+ *
+ * \param nullAuthAllowed: '1' if the NULL authentication is allowed.
+ *
+ * \param errbuf: a user-allocated buffer in which the error message
+ * (if one) has to be written. It must be at least PCAP_ERRBUF_SIZE
+ * bytes long.
+ *
+ * \return '0' if everything is fine, '-1' if an unrecoverable error occurred,
+ * or '-2' if the authentication failed. For errors, an error message is
+ * returned in the 'errbuf' variable; this gives a message for the
+ * unrecoverable error or for the authentication failure.
+ */
+static int
+daemon_msg_auth_req(struct daemon_slpars *pars, uint32 plen)
+{
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+ char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to send to the client
+ int status;
+ struct rpcap_auth auth; // RPCAP authentication header
+ char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
+ int sendbufidx = 0; // index which keeps the number of bytes currently buffered
+ struct rpcap_authreply *authreply; // authentication reply message
+
+ status = rpcapd_recv(pars->sockctrl, (char *) &auth, sizeof(struct rpcap_auth), &plen, errmsgbuf);
+ if (status == -1)
+ {
+ return -1;
+ }
+ if (status == -2)
+ {
+ goto error;
+ }
+
+ switch (ntohs(auth.type))
+ {
+ case RPCAP_RMTAUTH_NULL:
+ {
+ if (!pars->nullAuthAllowed)
+ {
+ // Send the client an error reply.
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+ "Authentication failed; NULL authentication not permitted.");
+ if (rpcap_senderror(pars->sockctrl, 0,
+ PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+ goto error_noreply;
+ }
+ break;
+ }
+
+ case RPCAP_RMTAUTH_PWD:
+ {
+ char *username, *passwd;
+ uint32 usernamelen, passwdlen;
+
+ usernamelen = ntohs(auth.slen1);
+ username = (char *) malloc (usernamelen + 1);
+ if (username == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errmsgbuf,
+ PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+ goto error;
+ }
+ status = rpcapd_recv(pars->sockctrl, username, usernamelen, &plen, errmsgbuf);
+ if (status == -1)
+ {
+ free(username);
+ return -1;
+ }
+ if (status == -2)
+ {
+ free(username);
+ goto error;
+ }
+ username[usernamelen] = '\0';
+
+ passwdlen = ntohs(auth.slen2);
+ passwd = (char *) malloc (passwdlen + 1);
+ if (passwd == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errmsgbuf,
+ PCAP_ERRBUF_SIZE, errno, "malloc() failed");
+ free(username);
+ goto error;
+ }
+ status = rpcapd_recv(pars->sockctrl, passwd, passwdlen, &plen, errmsgbuf);
+ if (status == -1)
+ {
+ free(username);
+ free(passwd);
+ return -1;
+ }
+ if (status == -2)
+ {
+ free(username);
+ free(passwd);
+ goto error;
+ }
+ passwd[passwdlen] = '\0';
+
+ if (daemon_AuthUserPwd(username, passwd, errmsgbuf))
+ {
+ //
+ // Authentication failed. Let the client
+ // know.
+ //
+ free(username);
+ free(passwd);
+ if (rpcap_senderror(pars->sockctrl, 0,
+ PCAP_ERR_AUTH_FAILED, errmsgbuf, errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ //
+ // Suspend for 1 second, so that they can't
+ // hammer us with repeated tries with an
+ // attack such as a dictionary attack.
+ //
+ // WARNING: this delay is inserted only
+ // at this point; if the client closes the
+ // connection and reconnects, the suspension
+ // time does not have any effect.
+ //
+ sleep_secs(RPCAP_SUSPEND_WRONGAUTH);
+ goto error_noreply;
+ }
+
+ free(username);
+ free(passwd);
+ break;
+ }
+
+ default:
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+ "Authentication type not recognized.");
+ if (rpcap_senderror(pars->sockctrl, 0,
+ PCAP_ERR_AUTH_TYPE_NOTSUP, errmsgbuf, errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+ goto error_noreply;
+ }
+
+ // The authentication succeeded; let the client know.
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, 0,
+ RPCAP_MSG_AUTH_REPLY, 0, sizeof(struct rpcap_authreply));
+
+ authreply = (struct rpcap_authreply *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_authreply), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ //
+ // Indicate to our peer what versions we support.
+ //
+ memset(authreply, 0, sizeof(struct rpcap_authreply));
+ authreply->minvers = RPCAP_MIN_VERSION;
+ authreply->maxvers = RPCAP_MAX_VERSION;
+
+ // Send the reply.
+ if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ // That failed; log a messsage and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ // Check if all the data has been read; if not, discard the data in excess
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ return -1;
+ }
+
+ return 0;
+
+error:
+ if (rpcap_senderror(pars->sockctrl, 0, PCAP_ERR_AUTH, errmsgbuf,
+ errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+error_noreply:
+ // Check if all the data has been read; if not, discard the data in excess
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ return -1;
+ }
+
+ return -2;
+}
+
+static int
+daemon_AuthUserPwd(char *username, char *password, char *errbuf)
+{
+#ifdef _WIN32
+ /*
+ * Warning: the user which launches the process must have the
+ * SE_TCB_NAME right.
+ * This corresponds to have the "Act as part of the Operating System"
+ * turned on (administrative tools, local security settings, local
+ * policies, user right assignment)
+ * However, it seems to me that if you run it as a service, this
+ * right should be provided by default.
+ *
+ * XXX - hopefully, this returns errors such as ERROR_LOGON_FAILURE,
+ * which merely indicates that the user name or password is
+ * incorrect, not whether it's the user name or the password
+ * that's incorrect, so a client that's trying to brute-force
+ * accounts doesn't know whether it's the user name or the
+ * password that's incorrect, so it doesn't know whether to
+ * stop trying to log in with a given user name and move on
+ * to another user name.
+ */
+ DWORD error;
+ HANDLE Token;
+ char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to log
+
+ if (LogonUser(username, ".", password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, &Token) == 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+ error = GetLastError();
+ if (error != ERROR_LOGON_FAILURE)
+ {
+ // Some error other than an authentication error;
+ // log it.
+ pcap_fmt_errmsg_for_win32_err(errmsgbuf,
+ PCAP_ERRBUF_SIZE, error, "LogonUser() failed");
+ rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+ }
+ return -1;
+ }
+
+ // This call should change the current thread to the selected user.
+ // I didn't test it.
+ if (ImpersonateLoggedOnUser(Token) == 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+ pcap_fmt_errmsg_for_win32_err(errmsgbuf, PCAP_ERRBUF_SIZE,
+ GetLastError(), "ImpersonateLoggedOnUser() failed");
+ rpcapd_log(LOGPRIO_ERROR, "%s", errmsgbuf);
+ CloseHandle(Token);
+ return -1;
+ }
+
+ CloseHandle(Token);
+ return 0;
+
+#else
+ /*
+ * See
+ *
+ * http://www.unixpapa.com/incnote/passwd.html
+ *
+ * We use the Solaris/Linux shadow password authentication if
+ * we have getspnam(), otherwise we just do traditional
+ * authentication, which, on some platforms, might work, even
+ * with shadow passwords, if we're running as root. Traditional
+ * authenticaion won't work if we're not running as root, as
+ * I think these days all UN*Xes either won't return the password
+ * at all with getpwnam() or will only do so if you're root.
+ *
+ * XXX - perhaps what we *should* be using is PAM, if we have
+ * it. That might hide all the details of username/password
+ * authentication, whether it's done with a visible-to-root-
+ * only password database or some other authentication mechanism,
+ * behind its API.
+ */
+ int error;
+ struct passwd *user;
+ char *user_password;
+#ifdef HAVE_GETSPNAM
+ struct spwd *usersp;
+#endif
+ char *crypt_password;
+
+ // This call is needed to get the uid
+ if ((user = getpwnam(username)) == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+ return -1;
+ }
+
+#ifdef HAVE_GETSPNAM
+ // This call is needed to get the password; otherwise 'x' is returned
+ if ((usersp = getspnam(username)) == NULL)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+ return -1;
+ }
+ user_password = usersp->sp_pwdp;
+#else
+ /*
+ * XXX - what about other platforms?
+ * The unixpapa.com page claims this Just Works on *BSD if you're
+ * running as root - it's from 2000, so it doesn't indicate whether
+ * macOS (which didn't come out until 2001, under the name Mac OS
+ * X) behaves like the *BSDs or not, and might also work on AIX.
+ * HP-UX does something else.
+ *
+ * Again, hopefully PAM hides all that.
+ */
+ user_password = user->pw_passwd;
+#endif
+
+ //
+ // The Single UNIX Specification says that if crypt() fails it
+ // sets errno, but some implementatons that haven't been run
+ // through the SUS test suite might not do so.
+ //
+ errno = 0;
+ crypt_password = crypt(password, user_password);
+ if (crypt_password == NULL)
+ {
+ error = errno;
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+ if (error == 0)
+ {
+ // It didn't set errno.
+ rpcapd_log(LOGPRIO_ERROR, "crypt() failed");
+ }
+ else
+ {
+ rpcapd_log(LOGPRIO_ERROR, "crypt() failed: %s",
+ strerror(error));
+ }
+ return -1;
+ }
+ if (strcmp(user_password, crypt_password) != 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication failed");
+ return -1;
+ }
+
+ if (setuid(user->pw_uid))
+ {
+ error = errno;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ error, "setuid");
+ rpcapd_log(LOGPRIO_ERROR, "setuid() failed: %s",
+ strerror(error));
+ return -1;
+ }
+
+/* if (setgid(user->pw_gid))
+ {
+ error = errno;
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "setgid");
+ rpcapd_log(LOGPRIO_ERROR, "setgid() failed: %s",
+ strerror(error));
+ return -1;
+ }
+*/
+ return 0;
+
+#endif
+
+}
+
+static int
+daemon_msg_findallif_req(uint8 ver, struct daemon_slpars *pars, uint32 plen)
+{
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+ char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to send to the client
+ char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
+ int sendbufidx = 0; // index which keeps the number of bytes currently buffered
+ pcap_if_t *alldevs = NULL; // pointer to the header of the interface chain
+ pcap_if_t *d; // temp pointer needed to scan the interface chain
+ struct pcap_addr *address; // pcap structure that keeps a network address of an interface
+ struct rpcap_findalldevs_if *findalldevs_if;// rpcap structure that packet all the data of an interface together
+ uint32 replylen; // length of reply payload
+ uint16 nif = 0; // counts the number of interface listed
+
+ // Discard the rest of the message; there shouldn't be any payload.
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ // Network error.
+ return -1;
+ }
+
+ // Retrieve the device list
+ if (pcap_findalldevs(&alldevs, errmsgbuf) == -1)
+ goto error;
+
+ if (alldevs == NULL)
+ {
+ if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_NOREMOTEIF,
+ "No interfaces found! Make sure libpcap/WinPcap is properly installed"
+ " and you have the right to access to the remote device.",
+ errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+ return 0;
+ }
+
+ // This checks the number of interfaces and computes the total
+ // length of the payload.
+ replylen = 0;
+ for (d = alldevs; d != NULL; d = d->next)
+ {
+ nif++;
+
+ if (d->description)
+ replylen += strlen(d->description);
+ if (d->name)
+ replylen += strlen(d->name);
+
+ replylen += sizeof(struct rpcap_findalldevs_if);
+
+ for (address = d->addresses; address != NULL; address = address->next)
+ {
+ /*
+ * Send only IPv4 and IPv6 addresses over the wire.
+ */
+ switch (address->addr->sa_family)
+ {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ replylen += (sizeof(struct rpcap_sockaddr) * 4);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // RPCAP findalldevs command
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+ RPCAP_MSG_FINDALLIF_REPLY, nif, replylen);
+
+ // send the interface list
+ for (d = alldevs; d != NULL; d = d->next)
+ {
+ uint16 lname, ldescr;
+
+ findalldevs_if = (struct rpcap_findalldevs_if *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_findalldevs_if), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ memset(findalldevs_if, 0, sizeof(struct rpcap_findalldevs_if));
+
+ if (d->description) ldescr = (short) strlen(d->description);
+ else ldescr = 0;
+ if (d->name) lname = (short) strlen(d->name);
+ else lname = 0;
+
+ findalldevs_if->desclen = htons(ldescr);
+ findalldevs_if->namelen = htons(lname);
+ findalldevs_if->flags = htonl(d->flags);
+
+ for (address = d->addresses; address != NULL; address = address->next)
+ {
+ /*
+ * Send only IPv4 and IPv6 addresses over the wire.
+ */
+ switch (address->addr->sa_family)
+ {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ findalldevs_if->naddr++;
+ break;
+
+ default:
+ break;
+ }
+ }
+ findalldevs_if->naddr = htons(findalldevs_if->naddr);
+
+ if (sock_bufferize(d->name, lname, sendbuf, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if (sock_bufferize(d->description, ldescr, sendbuf, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errmsgbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ // send all addresses
+ for (address = d->addresses; address != NULL; address = address->next)
+ {
+ struct rpcap_sockaddr *sockaddr;
+
+ /*
+ * Send only IPv4 and IPv6 addresses over the wire.
+ */
+ switch (address->addr->sa_family)
+ {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+ if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+ daemon_seraddr((struct sockaddr_storage *) address->addr, sockaddr);
+
+ sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+ if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+ daemon_seraddr((struct sockaddr_storage *) address->netmask, sockaddr);
+
+ sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+ if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+ daemon_seraddr((struct sockaddr_storage *) address->broadaddr, sockaddr);
+
+ sockaddr = (struct rpcap_sockaddr *) &sendbuf[sendbufidx];
+ if (sock_bufferize(NULL, sizeof(struct rpcap_sockaddr), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+ daemon_seraddr((struct sockaddr_storage *) address->dstaddr, sockaddr);
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ // We no longer need the device list. Free it.
+ pcap_freealldevs(alldevs);
+
+ // Send a final command that says "now send it!"
+ if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ return 0;
+
+error:
+ if (alldevs)
+ pcap_freealldevs(alldevs);
+
+ if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_FINDALLIF,
+ errmsgbuf, errbuf) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ \param plen: the length of the current message (needed in order to be able
+ to discard excess data in the message, if present)
+*/
+static int
+daemon_msg_open_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+ char *source, size_t sourcelen)
+{
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+ char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to send to the client
+ pcap_t *fp; // pcap_t main variable
+ int nread;
+ char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
+ int sendbufidx = 0; // index which keeps the number of bytes currently buffered
+ struct rpcap_openreply *openreply; // open reply message
+
+ if (plen > sourcelen - 1)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string too long");
+ goto error;
+ }
+
+ nread = sock_recv(pars->sockctrl, source, plen,
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+ return -1;
+ }
+ source[nread] = '\0';
+ plen -= nread;
+
+ // Is this a URL rather than a device?
+ // If so, reject it.
+ if (is_url(source))
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Source string refers to a remote device");
+ goto error;
+ }
+
+ // Open the selected device
+ // This is a fake open, since we do that only to get the needed parameters, then we close the device again
+ if ((fp = pcap_open_live(source,
+ 1500 /* fake snaplen */,
+ 0 /* no promis */,
+ 1000 /* fake timeout */,
+ errmsgbuf)) == NULL)
+ goto error;
+
+ // Now, I can send a RPCAP open reply message
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+ RPCAP_MSG_OPEN_REPLY, 0, sizeof(struct rpcap_openreply));
+
+ openreply = (struct rpcap_openreply *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_openreply), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ memset(openreply, 0, sizeof(struct rpcap_openreply));
+ openreply->linktype = htonl(pcap_datalink(fp));
+ openreply->tzoff = 0; /* This is always 0 for live captures */
+
+ // We're done with the pcap_t.
+ pcap_close(fp);
+
+ // Send the reply.
+ if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+ return 0;
+
+error:
+ if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_OPEN,
+ errmsgbuf, errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ // Check if all the data has been read; if not, discard the data in excess
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ \param plen: the length of the current message (needed in order to be able
+ to discard excess data in the message, if present)
+*/
+static int
+daemon_msg_startcap_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+ char *source, struct session **sessionp,
+ struct rpcap_sampling *samp_param _U_)
+{
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+ char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to send to the client
+ char portdata[PCAP_BUF_SIZE]; // temp variable needed to derive the data port
+ char peerhost[PCAP_BUF_SIZE]; // temp variable needed to derive the host name of our peer
+ struct session *session = NULL; // saves state of session
+ int status;
+ char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
+ int sendbufidx = 0; // index which keeps the number of bytes currently buffered
+
+ // socket-related variables
+ struct addrinfo hints; // temp, needed to open a socket connection
+ struct addrinfo *addrinfo; // temp, needed to open a socket connection
+ struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine
+ socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine
+ int ret; // return value from functions
+
+ // RPCAP-related variables
+ struct rpcap_startcapreq startcapreq; // start capture request message
+ struct rpcap_startcapreply *startcapreply; // start capture reply message
+ int serveropen_dp; // keeps who is going to open the data connection
+
+ addrinfo = NULL;
+
+ status = rpcapd_recv(pars->sockctrl, (char *) &startcapreq,
+ sizeof(struct rpcap_startcapreq), &plen, errmsgbuf);
+ if (status == -1)
+ {
+ goto fatal_error;
+ }
+ if (status == -2)
+ {
+ goto error;
+ }
+
+ startcapreq.flags = ntohs(startcapreq.flags);
+
+ // Create a session structure
+ session = malloc(sizeof(struct session));
+ if (session == NULL)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Can't allocate session structure");
+ goto error;
+ }
+
+ session->sockdata = INVALID_SOCKET;
+ // We don't have a thread yet.
+ session->have_thread = 0;
+ //
+ // We *shouldn't* have to initialize the thread indicator
+ // itself, because the compiler *should* realize that we
+ // only use this if have_thread isn't 0, but we *do* have
+ // to do it, because not all compilers *do* realize that.
+ //
+ // There is no "invalid thread handle" value for a UN*X
+ // pthread_t, so we just zero it out.
+ //
+#ifdef _WIN32
+ session->thread = INVALID_HANDLE_VALUE;
+#else
+ memset(&session->thread, 0, sizeof(session->thread));
+#endif
+
+ // Open the selected device
+ if ((session->fp = pcap_open_live(source,
+ ntohl(startcapreq.snaplen),
+ (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? 1 : 0 /* local device, other flags not needed */,
+ ntohl(startcapreq.read_timeout),
+ errmsgbuf)) == NULL)
+ goto error;
+
+#if 0
+ // Apply sampling parameters
+ fp->rmt_samp.method = samp_param->method;
+ fp->rmt_samp.value = samp_param->value;
+#endif
+
+ /*
+ We're in active mode if:
+ - we're using TCP, and the user wants us to be in active mode
+ - we're using UDP
+ */
+ serveropen_dp = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || pars->isactive;
+
+ /*
+ Gets the sockaddr structure referred to the other peer in the ctrl connection
+
+ We need that because:
+ - if we're in passive mode, we need to know the address family we want to use
+ (the same used for the ctrl socket)
+ - if we're in active mode, we need to know the network address of the other host
+ we want to connect to
+ */
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getpeername(pars->sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getpeername()", errmsgbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_family = saddr.ss_family;
+
+ // Now we have to create a new socket to send packets
+ if (serveropen_dp) // Data connection is opened by the server toward the client
+ {
+ pcap_snprintf(portdata, sizeof portdata, "%d", ntohs(startcapreq.portdata));
+
+ // Get the name of the other peer (needed to connect to that specific network address)
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, peerhost,
+ sizeof(peerhost), NULL, 0, NI_NUMERICHOST))
+ {
+ sock_geterror("getnameinfo()", errmsgbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if ((session->sockdata = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ goto error;
+ }
+ else // Data connection is opened by the client toward the server
+ {
+ hints.ai_flags = AI_PASSIVE;
+
+ // Let's the server socket pick up a free network port for us
+ if (sock_initaddress(NULL, "0", &hints, &addrinfo, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if ((session->sockdata = sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errmsgbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ goto error;
+
+ // get the complete sockaddr structure used in the data connection
+ saddrlen = sizeof(struct sockaddr_storage);
+ if (getsockname(session->sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
+ {
+ sock_geterror("getsockname()", errmsgbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+
+ // Get the local port the system picked up
+ if (getnameinfo((struct sockaddr *) &saddr, saddrlen, NULL,
+ 0, portdata, sizeof(portdata), NI_NUMERICSERV))
+ {
+ sock_geterror("getnameinfo()", errmsgbuf, PCAP_ERRBUF_SIZE);
+ goto error;
+ }
+ }
+
+ // addrinfo is no longer used
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ // Needed to send an error on the ctrl connection
+ session->sockctrl = pars->sockctrl;
+ session->protocol_version = ver;
+
+ // Now I can set the filter
+ ret = daemon_unpackapplyfilter(pars->sockctrl, session, &plen, errmsgbuf);
+ if (ret == -1)
+ {
+ // Fatal error. A message has been logged; just give up.
+ goto fatal_error;
+ }
+ if (ret == -2)
+ {
+ // Non-fatal error. Send an error message to the client.
+ goto error;
+ }
+
+ // Now, I can send a RPCAP start capture reply message
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx,
+ RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+ RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply));
+
+ startcapreply = (struct rpcap_startcapreply *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ memset(startcapreply, 0, sizeof(struct rpcap_startcapreply));
+ startcapreply->bufsize = htonl(pcap_bufsize(session->fp));
+
+ if (!serveropen_dp)
+ {
+ unsigned short port = (unsigned short)strtoul(portdata,NULL,10);
+ startcapreply->portdata = htons(port);
+ }
+
+ if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ goto fatal_error;
+ }
+
+ if (!serveropen_dp)
+ {
+ SOCKET socktemp; // We need another socket, since we're going to accept() a connection
+
+ // Connection creation
+ saddrlen = sizeof(struct sockaddr_storage);
+
+ socktemp = accept(session->sockdata, (struct sockaddr *) &saddr, &saddrlen);
+
+ if (socktemp == INVALID_SOCKET)
+ {
+ sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "Accept of data connection failed: %s",
+ errbuf);
+ goto error;
+ }
+
+ // Now that I accepted the connection, the server socket is no longer needed
+ sock_close(session->sockdata, NULL, 0);
+ session->sockdata = socktemp;
+ }
+
+ // Now we have to create a new thread to receive packets
+#ifdef _WIN32
+ session->thread = (HANDLE)_beginthreadex(NULL, 0, daemon_thrdatamain,
+ (void *) session, 0, NULL);
+ if (session->thread == 0)
+ {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread");
+ goto error;
+ }
+#else
+ ret = pthread_create(&session->thread, NULL, daemon_thrdatamain,
+ (void *) session);
+ if (ret != 0)
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ ret, "Error creating the data thread");
+ goto error;
+ }
+#endif
+ session->have_thread = 1;
+
+ // Check if all the data has been read; if not, discard the data in excess
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ goto fatal_error;
+
+ *sessionp = session;
+ return 0;
+
+error:
+ //
+ // Not a fatal error, so send the client an error message and
+ // keep serving client requests.
+ //
+ *sessionp = NULL;
+
+ if (addrinfo)
+ freeaddrinfo(addrinfo);
+
+ if (session)
+ {
+ session_close(session);
+ free(session);
+ }
+
+ if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_STARTCAPTURE,
+ errmsgbuf, errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ // Check if all the data has been read; if not, discard the data in excess
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ // Network error.
+ return -1;
+ }
+
+ return 0;
+
+fatal_error:
+ //
+ // Fatal network error, so don't try to communicate with
+ // the client, just give up.
+ //
+ *sessionp = NULL;
+
+ if (session)
+ {
+ session_close(session);
+ free(session);
+ }
+
+ return -1;
+}
+
+static int
+daemon_msg_endcap_req(uint8 ver, struct daemon_slpars *pars,
+ struct session *session)
+{
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+ struct rpcap_header header;
+
+ session_close(session);
+
+ rpcap_createhdr(&header, ver, RPCAP_MSG_ENDCAP_REPLY, 0, 0);
+
+ if (sock_send(pars->sockctrl, (char *) &header, sizeof(struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ return 0;
+}
+
+//
+// We impose a limit on the filter program size, so that, on Windows,
+// where there's only one server process with multiple threads, it's
+// harder to eat all the server address space by sending larger filter
+// programs. (This isn't an issue on UN*X, where there are multiple
+// server processes, one per client connection.)
+//
+// We pick a value that limits each filter to 64K; that value is twice
+// the in-kernel limit for Linux and 16 times the in-kernel limit for
+// *BSD and macOS.
+//
+// It also prevents an overflow on 32-bit platforms when calculating
+// the total size of the filter program. (It's not an issue on 64-bit
+// platforms with a 64-bit size_t, as the filter size is 32 bits.)
+//
+#define RPCAP_BPF_MAXINSNS 8192
+
+static int
+daemon_unpackapplyfilter(SOCKET sockctrl, struct session *session, uint32 *plenp, char *errmsgbuf)
+{
+ int status;
+ struct rpcap_filter filter;
+ struct rpcap_filterbpf_insn insn;
+ struct bpf_insn *bf_insn;
+ struct bpf_program bf_prog;
+ unsigned int i;
+
+ status = rpcapd_recv(sockctrl, (char *) &filter,
+ sizeof(struct rpcap_filter), plenp, errmsgbuf);
+ if (status == -1)
+ {
+ return -1;
+ }
+ if (status == -2)
+ {
+ return -2;
+ }
+
+ bf_prog.bf_len = ntohl(filter.nitems);
+
+ if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
+ return -2;
+ }
+
+ if (bf_prog.bf_len > RPCAP_BPF_MAXINSNS)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE,
+ "Filter program is larger than the maximum size of %u instructions",
+ RPCAP_BPF_MAXINSNS);
+ return -2;
+ }
+ bf_insn = (struct bpf_insn *) malloc (sizeof(struct bpf_insn) * bf_prog.bf_len);
+ if (bf_insn == NULL)
+ {
+ pcap_fmt_errmsg_for_errno(errmsgbuf, PCAP_ERRBUF_SIZE,
+ errno, "malloc() failed");
+ return -2;
+ }
+
+ bf_prog.bf_insns = bf_insn;
+
+ for (i = 0; i < bf_prog.bf_len; i++)
+ {
+ status = rpcapd_recv(sockctrl, (char *) &insn,
+ sizeof(struct rpcap_filterbpf_insn), plenp, errmsgbuf);
+ if (status == -1)
+ {
+ return -1;
+ }
+ if (status == -2)
+ {
+ return -2;
+ }
+
+ bf_insn->code = ntohs(insn.code);
+ bf_insn->jf = insn.jf;
+ bf_insn->jt = insn.jt;
+ bf_insn->k = ntohl(insn.k);
+
+ bf_insn++;
+ }
+
+ if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
+ return -2;
+ }
+
+ if (pcap_setfilter(session->fp, &bf_prog))
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", pcap_geterr(session->fp));
+ return -2;
+ }
+
+ return 0;
+}
+
+static int
+daemon_msg_updatefilter_req(uint8 ver, struct daemon_slpars *pars,
+ struct session *session, uint32 plen)
+{
+ char errbuf[PCAP_ERRBUF_SIZE];
+ char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to send to the client
+ int ret; // status of daemon_unpackapplyfilter()
+ struct rpcap_header header; // keeps the answer to the updatefilter command
+
+ ret = daemon_unpackapplyfilter(pars->sockctrl, session, &plen, errmsgbuf);
+ if (ret == -1)
+ {
+ // Fatal error. A message has been logged; just give up.
+ return -1;
+ }
+ if (ret == -2)
+ {
+ // Non-fatal error. Send an error reply to the client.
+ goto error;
+ }
+
+ // Check if all the data has been read; if not, discard the data in excess
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ // Network error.
+ return -1;
+ }
+
+ // A response is needed, otherwise the other host does not know that everything went well
+ rpcap_createhdr(&header, ver, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
+
+ if (sock_send(pars->sockctrl, (char *) &header, sizeof (struct rpcap_header), pcap_geterr(session->fp), PCAP_ERRBUF_SIZE))
+ {
+ // That failed; log a messsage and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ return 0;
+
+error:
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ return -1;
+ }
+ rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_UPDATEFILTER,
+ errmsgbuf, NULL);
+
+ return 0;
+}
+
+/*!
+ \brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
+*/
+static int
+daemon_msg_setsampling_req(uint8 ver, struct daemon_slpars *pars, uint32 plen,
+ struct rpcap_sampling *samp_param)
+{
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+ char errmsgbuf[PCAP_ERRBUF_SIZE];
+ struct rpcap_header header;
+ struct rpcap_sampling rpcap_samp;
+ int status;
+
+ status = rpcapd_recv(pars->sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling), &plen, errmsgbuf);
+ if (status == -1)
+ {
+ return -1;
+ }
+ if (status == -2)
+ {
+ goto error;
+ }
+
+ // Save these settings in the pcap_t
+ samp_param->method = rpcap_samp.method;
+ samp_param->value = ntohl(rpcap_samp.value);
+
+ // A response is needed, otherwise the other host does not know that everything went well
+ rpcap_createhdr(&header, ver, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
+
+ if (sock_send(pars->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ // That failed; log a messsage and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ return -1;
+ }
+
+ return 0;
+
+error:
+ if (rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_SETSAMPLING,
+ errmsgbuf, errbuf) == -1)
+ {
+ // That failed; log a message and give up.
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ // Check if all the data has been read; if not, discard the data in excess
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int
+daemon_msg_stats_req(uint8 ver, struct daemon_slpars *pars,
+ struct session *session, uint32 plen, struct pcap_stat *stats,
+ unsigned int svrcapt)
+{
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+ char errmsgbuf[PCAP_ERRBUF_SIZE]; // buffer for errors to send to the client
+ char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
+ int sendbufidx = 0; // index which keeps the number of bytes currently buffered
+ struct rpcap_stats *netstats; // statistics sent on the network
+
+ // Checks that the header does not contain other data; if so, discard it
+ if (rpcapd_discard(pars->sockctrl, plen) == -1)
+ {
+ // Network error.
+ return -1;
+ }
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf, ver,
+ RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
+
+ netstats = (struct rpcap_stats *) &sendbuf[sendbufidx];
+
+ if (sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
+ &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errmsgbuf, PCAP_ERRBUF_SIZE) == -1)
+ goto error;
+
+ if (session && session->fp)
+ {
+ if (pcap_stats(session->fp, stats) == -1)
+ {
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "%s", pcap_geterr(session->fp));
+ goto error;
+ }
+
+ netstats->ifdrop = htonl(stats->ps_ifdrop);
+ netstats->ifrecv = htonl(stats->ps_recv);
+ netstats->krnldrop = htonl(stats->ps_drop);
+ netstats->svrcapt = htonl(session->TotCapt);
+ }
+ else
+ {
+ // We have to keep compatibility with old applications,
+ // which ask for statistics also when the capture has
+ // already stopped.
+ netstats->ifdrop = htonl(stats->ps_ifdrop);
+ netstats->ifrecv = htonl(stats->ps_recv);
+ netstats->krnldrop = htonl(stats->ps_drop);
+ netstats->svrcapt = htonl(svrcapt);
+ }
+
+ // Send the packet
+ if (sock_send(pars->sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Send to client failed: %s", errbuf);
+ return -1;
+ }
+
+ return 0;
+
+error:
+ rpcap_senderror(pars->sockctrl, ver, PCAP_ERR_GETSTATS,
+ errmsgbuf, NULL);
+ return 0;
+}
+
+#ifdef _WIN32
+static unsigned __stdcall
+#else
+static void *
+#endif
+daemon_thrdatamain(void *ptr)
+{
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // error buffer
+ struct session *session; // pointer to the struct session for this session
+ int retval; // general variable used to keep the return value of other functions
+ struct rpcap_pkthdr *net_pkt_header;// header of the packet
+ struct pcap_pkthdr *pkt_header; // pointer to the buffer that contains the header of the current packet
+ u_char *pkt_data; // pointer to the buffer that contains the current packet
+ size_t sendbufsize; // size for the send buffer
+ char *sendbuf; // temporary buffer in which data to be sent is buffered
+ int sendbufidx; // index which keeps the number of bytes currently buffered
+ int status;
+#ifndef _WIN32
+ sigset_t sigusr1; // signal set with just SIGUSR1
+#endif
+
+ session = (struct session *) ptr;
+
+ session->TotCapt = 0; // counter which is incremented each time a packet is received
+
+ // Initialize errbuf
+ memset(errbuf, 0, sizeof(errbuf));
+
+ //
+ // We need a buffer large enough to hold a buffer large enough
+ // for a maximum-size packet for this pcap_t.
+ //
+ if (pcap_snapshot(session->fp) < 0)
+ {
+ //
+ // The snapshot length is negative.
+ // This "should not happen".
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "Unable to allocate the buffer for this child thread: snapshot length of %d is negative",
+ pcap_snapshot(session->fp));
+ sendbuf = NULL; // we can't allocate a buffer, so nothing to free
+ goto error;
+ }
+ //
+ // size_t is unsigned, and the result of pcap_snapshot() is signed;
+ // on no platform that we support is int larger than size_t.
+ // This means that, unless the extra information we prepend to
+ // a maximum-sized packet is impossibly large, the sum of the
+ // snapshot length and the size of that extra information will
+ // fit in a size_t.
+ //
+ // So we don't need to make sure that sendbufsize will overflow.
+ //
+ sendbufsize = sizeof(struct rpcap_header) + sizeof(struct rpcap_pkthdr) + pcap_snapshot(session->fp);
+ sendbuf = (char *) malloc (sendbufsize);
+ if (sendbuf == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR,
+ "Unable to allocate the buffer for this child thread");
+ goto error;
+ }
+
+#ifndef _WIN32
+ //
+ // Set the signal set to include just SIGUSR1, and block that
+ // signal; we only want it unblocked when we're reading
+ // packets - we dn't want any other system calls, such as
+ // ones being used to send to the client or to log messages,
+ // to be interrupted.
+ //
+ sigemptyset(&sigusr1);
+ sigaddset(&sigusr1, SIGUSR1);
+ pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
+#endif
+
+ // Retrieve the packets
+ for (;;)
+ {
+#ifndef _WIN32
+ //
+ // Unblock SIGUSR1 while we might be waiting for packets.
+ //
+ pthread_sigmask(SIG_UNBLOCK, &sigusr1, NULL);
+#endif
+ retval = pcap_next_ex(session->fp, &pkt_header, (const u_char **) &pkt_data); // cast to avoid a compiler warning
+#ifndef _WIN32
+ //
+ // Now block it again.
+ //
+ pthread_sigmask(SIG_BLOCK, &sigusr1, NULL);
+#endif
+ if (retval < 0)
+ break; // error
+ if (retval == 0) // Read timeout elapsed
+ continue;
+
+ sendbufidx = 0;
+
+ // Bufferize the general header
+ if (sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
+ &sendbufidx, sendbufsize, SOCKBUF_CHECKONLY, errbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR,
+ "sock_bufferize() error sending packet message: %s",
+ errbuf);
+ goto error;
+ }
+
+ rpcap_createhdr((struct rpcap_header *) sendbuf,
+ session->protocol_version, RPCAP_MSG_PACKET, 0,
+ (uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen));
+
+ net_pkt_header = (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
+
+ // Bufferize the pkt header
+ if (sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL,
+ &sendbufidx, sendbufsize, SOCKBUF_CHECKONLY, errbuf,
+ PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR,
+ "sock_bufferize() error sending packet message: %s",
+ errbuf);
+ goto error;
+ }
+
+ net_pkt_header->caplen = htonl(pkt_header->caplen);
+ net_pkt_header->len = htonl(pkt_header->len);
+ net_pkt_header->npkt = htonl(++(session->TotCapt));
+ net_pkt_header->timestamp_sec = htonl(pkt_header->ts.tv_sec);
+ net_pkt_header->timestamp_usec = htonl(pkt_header->ts.tv_usec);
+
+ // Bufferize the pkt data
+ if (sock_bufferize((char *) pkt_data, pkt_header->caplen,
+ sendbuf, &sendbufidx, sendbufsize, SOCKBUF_BUFFERIZE,
+ errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR,
+ "sock_bufferize() error sending packet message: %s",
+ errbuf);
+ goto error;
+ }
+
+ // Send the packet
+ // If the client dropped the connection, don't report an
+ // error, just quit.
+ status = sock_send(session->sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE);
+ if (status < 0)
+ {
+ if (status == -1)
+ {
+ //
+ // Error other than "client closed the
+ // connection out from under us"; report
+ // it.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "Send of packet to client failed: %s",
+ errbuf);
+ }
+
+ //
+ // Give up in either case.
+ //
+ goto error;
+ }
+ }
+
+ if (retval < 0 && retval != PCAP_ERROR_BREAK)
+ {
+ //
+ // Failed with an error other than "we were told to break
+ // out of the loop".
+ //
+ // The latter just means that the client told us to stop
+ // capturing, so there's no error to report.
+ //
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(session->fp));
+ rpcap_senderror(session->sockctrl, session->protocol_version,
+ PCAP_ERR_READEX, errbuf, NULL);
+ }
+
+error:
+ //
+ // The main thread will clean up the session structure.
+ //
+ free(sendbuf);
+
+ return 0;
+}
+
+#ifndef _WIN32
+//
+// Do-nothing handler for SIGUSR1; the sole purpose of SIGUSR1 is to
+// interrupt the data thread if it's blocked in a system call waiting
+// for packets to arrive.
+//
+static void noop_handler(int sign _U_)
+{
+}
+#endif
+
+/*!
+ \brief It serializes a network address.
+
+ It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
+ that can be used to be sent on the network. Basically, it applies all the hton()
+ conversion required to the input variable.
+
+ \param sockaddrin a 'sockaddr_storage' pointer to the variable that has to be
+ serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
+
+ \param sockaddrout an 'rpcap_sockaddr' pointer to the variable that will contain
+ the serialized data. This variable has to be allocated by the user.
+
+ \warning This function supports only AF_INET and AF_INET6 address families.
+*/
+static void
+daemon_seraddr(struct sockaddr_storage *sockaddrin, struct rpcap_sockaddr *sockaddrout)
+{
+ memset(sockaddrout, 0, sizeof(struct sockaddr_storage));
+
+ // There can be the case in which the sockaddrin is not available
+ if (sockaddrin == NULL) return;
+
+ // Warning: we support only AF_INET and AF_INET6
+ switch (sockaddrin->ss_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *sockaddrin_ipv4;
+ struct rpcap_sockaddr_in *sockaddrout_ipv4;
+
+ sockaddrin_ipv4 = (struct sockaddr_in *) sockaddrin;
+ sockaddrout_ipv4 = (struct rpcap_sockaddr_in *) sockaddrout;
+ sockaddrout_ipv4->family = htons(RPCAP_AF_INET);
+ sockaddrout_ipv4->port = htons(sockaddrin_ipv4->sin_port);
+ memcpy(&sockaddrout_ipv4->addr, &sockaddrin_ipv4->sin_addr, sizeof(sockaddrout_ipv4->addr));
+ memset(sockaddrout_ipv4->zero, 0, sizeof(sockaddrout_ipv4->zero));
+ break;
+ }
+
+#ifdef AF_INET6
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *sockaddrin_ipv6;
+ struct rpcap_sockaddr_in6 *sockaddrout_ipv6;
+
+ sockaddrin_ipv6 = (struct sockaddr_in6 *) sockaddrin;
+ sockaddrout_ipv6 = (struct rpcap_sockaddr_in6 *) sockaddrout;
+ sockaddrout_ipv6->family = htons(RPCAP_AF_INET6);
+ sockaddrout_ipv6->port = htons(sockaddrin_ipv6->sin6_port);
+ sockaddrout_ipv6->flowinfo = htonl(sockaddrin_ipv6->sin6_flowinfo);
+ memcpy(&sockaddrout_ipv6->addr, &sockaddrin_ipv6->sin6_addr, sizeof(sockaddrout_ipv6->addr));
+ sockaddrout_ipv6->scope_id = htonl(sockaddrin_ipv6->sin6_scope_id);
+ break;
+ }
+#endif
+ }
+}
+
+
+/*!
+ \brief Suspends a thread for secs seconds.
+*/
+void sleep_secs(int secs)
+{
+#ifdef _WIN32
+ Sleep(secs*1000);
+#else
+ unsigned secs_remaining;
+
+ if (secs <= 0)
+ return;
+ secs_remaining = secs;
+ while (secs_remaining != 0)
+ secs_remaining = sleep(secs_remaining);
+#endif
+}
+
+/*
+ * Read the header of a message.
+ */
+static int
+rpcapd_recv_msg_header(SOCKET sock, struct rpcap_header *headerp)
+{
+ int nread;
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+
+ nread = sock_recv(sock, (char *) headerp, sizeof(struct rpcap_header),
+ SOCK_RECEIVEALL_YES|SOCK_EOF_ISNT_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ {
+ // Network error.
+ rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+ return -1;
+ }
+ if (nread == 0)
+ {
+ // Immediate EOF; that's treated like a close message.
+ return -2;
+ }
+ headerp->plen = ntohl(headerp->plen);
+ return 0;
+}
+
+/*
+ * Read data from a message.
+ * If we're trying to read more data that remains, puts an error
+ * message into errmsgbuf and returns -2. Otherwise, tries to read
+ * the data and, if that succeeds, subtracts the amount read from
+ * the number of bytes of data that remains.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int
+rpcapd_recv(SOCKET sock, char *buffer, size_t toread, uint32 *plen, char *errmsgbuf)
+{
+ int nread;
+ char errbuf[PCAP_ERRBUF_SIZE]; // buffer for network errors
+
+ if (toread > *plen)
+ {
+ // Tell the client and continue.
+ pcap_snprintf(errmsgbuf, PCAP_ERRBUF_SIZE, "Message payload is too short");
+ return -2;
+ }
+ nread = sock_recv(sock, buffer, toread,
+ SOCK_RECEIVEALL_YES|SOCK_EOF_IS_ERROR, errbuf, PCAP_ERRBUF_SIZE);
+ if (nread == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+ return -1;
+ }
+ *plen -= nread;
+ return 0;
+}
+
+/*
+ * Discard data from a connection.
+ * Mostly used to discard wrong-sized messages.
+ * Returns 0 on success, logs a message and returns -1 on a network
+ * error.
+ */
+static int
+rpcapd_discard(SOCKET sock, uint32 len)
+{
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+
+ if (len != 0)
+ {
+ if (sock_discard(sock, len, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ // Network error.
+ rpcapd_log(LOGPRIO_ERROR, "Read from client failed: %s", errbuf);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+//
+// Shut down any packet-capture thread associated with the session,
+// close the SSL handle for the data socket if we have one, close
+// the data socket if we have one, and close the underlying packet
+// capture handle if we have one.
+//
+// We do not, of course, touch the controlling socket that's also
+// copied into the session, as the service loop might still use it.
+//
+static void session_close(struct session *session)
+{
+ if (session->have_thread)
+ {
+ //
+ // Tell the data connection thread main capture loop to
+ // break out of that loop.
+ //
+ // This may be sufficient to wake up a blocked thread,
+ // but it's not guaranteed to be sufficient.
+ //
+ pcap_breakloop(session->fp);
+
+#ifdef _WIN32
+ //
+ // Set the event on which a read would block, so that,
+ // if it's currently blocked waiting for packets to
+ // arrive, it'll wake up, so it can see the "break
+ // out of the loop" indication. (pcap_breakloop()
+ // might do this, but older versions don't. Setting
+ // it twice should, at worst, cause an extra wakeup,
+ // which shouldn't be a problem.)
+ //
+ // XXX - what about modules other than NPF?
+ //
+ SetEvent(pcap_getevent(session->fp));
+
+ //
+ // Wait for the thread to exit, so we don't close
+ // sockets out from under it.
+ //
+ // XXX - have a timeout, so we don't wait forever?
+ //
+ WaitForSingleObject(session->thread, INFINITE);
+
+ //
+ // Release the thread handle, as we're done with
+ // it.
+ //
+ CloseHandle(session->thread);
+ session->have_thread = 0;
+ session->thread = INVALID_HANDLE_VALUE;
+#else
+ //
+ // Send a SIGUSR1 signal to the thread, so that, if
+ // it's currently blocked waiting for packets to arrive,
+ // it'll wake up (we've turned off SA_RESTART for
+ // SIGUSR1, so that the system call in which it's blocked
+ // should return EINTR rather than restarting).
+ //
+ pthread_kill(session->thread, SIGUSR1);
+
+ //
+ // Wait for the thread to exit, so we don't close
+ // sockets out from under it.
+ //
+ // XXX - have a timeout, so we don't wait forever?
+ //
+ pthread_join(session->thread, NULL);
+ session->have_thread = 0;
+ memset(&session->thread, 0, sizeof(session->thread));
+#endif
+ }
+
+ if (session->sockdata != INVALID_SOCKET)
+ {
+ sock_close(session->sockdata, NULL, 0);
+ session->sockdata = INVALID_SOCKET;
+ }
+
+ if (session->fp)
+ {
+ pcap_close(session->fp);
+ session->fp = NULL;
+ }
+}
+
+//
+// Check whether a capture source string is a URL or not.
+// This includes URLs that refer to a local device; a scheme, followed
+// by ://, followed by *another* scheme and ://, is just silly, and
+// anybody who supplies that will get an error.
+//
+static int
+is_url(const char *source)
+{
+ char *colonp;
+
+ /*
+ * RFC 3986 says:
+ *
+ * URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
+ *
+ * hier-part = "//" authority path-abempty
+ * / path-absolute
+ * / path-rootless
+ * / path-empty
+ *
+ * authority = [ userinfo "@" ] host [ ":" port ]
+ *
+ * userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
+ *
+ * Step 1: look for the ":" at the end of the scheme.
+ * A colon in the source is *NOT* sufficient to indicate that
+ * this is a URL, as interface names on some platforms might
+ * include colons (e.g., I think some Solaris interfaces
+ * might).
+ */
+ colonp = strchr(source, ':');
+ if (colonp == NULL)
+ {
+ /*
+ * The source is the device to open. It's not a URL.
+ */
+ return (0);
+ }
+
+ /*
+ * All schemes must have "//" after them, i.e. we only support
+ * hier-part = "//" authority path-abempty, not
+ * hier-part = path-absolute
+ * hier-part = path-rootless
+ * hier-part = path-empty
+ *
+ * We need that in order to distinguish between a local device
+ * name that happens to contain a colon and a URI.
+ */
+ if (strncmp(colonp + 1, "//", 2) != 0)
+ {
+ /*
+ * The source is the device to open. It's not a URL.
+ */
+ return (0);
+ }
+
+ /*
+ * It's a URL.
+ */
+ return (1);
+}
diff --git a/lib/libpcap/libpcap/rpcapd/daemon.h b/lib/libpcap/libpcap/rpcapd/daemon.h
new file mode 100644
index 0000000..74e17da
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/daemon.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifndef __DAEMON_H__
+#define __DAEMON_H__
+
+//
+// Returns 1 if the client closed the control connection explicitly, 0
+// otherwise; the return value is used only by callers that call us
+// for active mode.
+//
+int daemon_serviceloop(SOCKET sockctrl, int isactive, char *passiveClients,
+ int nullAuthAllowed);
+
+void sleep_secs(int secs);
+
+#endif
diff --git a/lib/libpcap/libpcap/rpcapd/fileconf.c b/lib/libpcap/libpcap/rpcapd/fileconf.c
new file mode 100644
index 0000000..2f15c01
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/fileconf.c
@@ -0,0 +1,557 @@
+/*
+ * Copyright (c) 1987, 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <signal.h>
+#include <pcap.h> // for PCAP_ERRBUF_SIZE
+
+#include "portability.h"
+#include "rpcapd.h"
+#include "config_params.h" // configuration file parameters
+#include "fileconf.h"
+#include "rpcap-protocol.h"
+#include "log.h"
+
+//
+// Parameter names.
+//
+#define PARAM_ACTIVECLIENT "ActiveClient"
+#define PARAM_PASSIVECLIENT "PassiveClient"
+#define PARAM_NULLAUTHPERMIT "NullAuthPermit"
+
+static char *skipws(char *ptr);
+
+void fileconf_read(void)
+{
+ FILE *fp;
+ unsigned int num_active_clients;
+
+ if ((fp = fopen(loadfile, "r")) != NULL)
+ {
+ char line[MAX_LINE + 1];
+ unsigned int lineno;
+
+ hostlist[0] = 0;
+ num_active_clients = 0;
+ lineno = 0;
+
+ while (fgets(line, MAX_LINE, fp) != NULL)
+ {
+ size_t linelen;
+ char *ptr;
+ char *param;
+ size_t result;
+ size_t toklen;
+
+ lineno++;
+
+ linelen = strlen(line);
+ if (line[linelen - 1] != '\n')
+ {
+ int c;
+
+ //
+ // Either the line doesn't fit in
+ // the buffer, or we got an EOF
+ // before the EOL. Assume it's the
+ // former.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u is longer than %u characters",
+ loadfile, lineno, MAX_LINE);
+
+ //
+ // Eat characters until we get an NL.
+ //
+ while ((c = getc(fp)) != '\n')
+ {
+ if (c == EOF)
+ goto done;
+ }
+
+ //
+ // Try the next line.
+ //
+ continue;
+ }
+ ptr = line;
+
+ //
+ // Skip leading white space, if any.
+ //
+ ptr = skipws(ptr);
+ if (ptr == NULL)
+ {
+ // Blank line.
+ continue;
+ }
+
+ //
+ // Is the next character a "#"? If so, this
+ // line is a comment; skip to the next line.
+ //
+ if (*ptr == '#')
+ continue;
+
+ //
+ // Is the next character alphabetic? If not,
+ // this isn't a valid parameter name.
+ //
+ if (!isascii((unsigned char)*ptr) ||
+ !isalpha((unsigned char)*ptr))
+ {
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u doesn't have a valid parameter name",
+ loadfile, lineno);
+ continue;
+ }
+
+ //
+ // Grab the first token, which is made of
+ // alphanumerics, underscores, and hyphens.
+ // That's the name of the parameter being set.
+ //
+ param = ptr;
+ while (isascii((unsigned char)*ptr) &&
+ (isalnum((unsigned char)*ptr) || *ptr == '-' || *ptr == '_'))
+ ptr++;
+
+ //
+ // Skip over white space, if any.
+ //
+ ptr = skipws(ptr);
+ if (ptr == NULL || *ptr != '=')
+ {
+ //
+ // We hit the end of the line before
+ // finding a non-white space character,
+ // or we found one but it's not an "=".
+ // That means there's no "=", so this
+ // line is invalid. Complain and skip
+ // this line.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has a parameter but no =",
+ loadfile, lineno);
+ continue;
+ }
+
+ //
+ // We found the '='; set it to '\0', and skip
+ // past it.
+ //
+ *ptr++ = '\0';
+
+ //
+ // Skip past any white space after the "=".
+ //
+ ptr = skipws(ptr);
+ if (ptr == NULL)
+ {
+ //
+ // The value is empty.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has a parameter but no value",
+ loadfile, lineno);
+ continue;
+ }
+
+ //
+ // OK, what parameter is this?
+ //
+ if (strcmp(param, PARAM_ACTIVECLIENT) == 0) {
+ //
+ // Add this to the list of active clients.
+ //
+ char *address, *port;
+
+ //
+ // We can't have more than MAX_ACTIVE_LIST
+ // active clients.
+ //
+ if (num_active_clients >= MAX_ACTIVE_LIST)
+ {
+ //
+ // Too many entries for the active
+ // client list. Complain and
+ // ignore it.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has an %s parameter, but we already have %u active clients",
+ loadfile, lineno, PARAM_ACTIVECLIENT,
+ MAX_ACTIVE_LIST);
+ continue;
+ }
+
+ //
+ // Get the address.
+ // It's terminated by a host list separator
+ // *or* a #; there *shouldn't* be a #, as
+ // that starts a comment, and that would
+ // mean that we have no port.
+ //
+ address = ptr;
+ toklen = strcspn(ptr, RPCAP_HOSTLIST_SEP "#");
+ ptr += toklen; // skip to the terminator
+ if (toklen == 0)
+ {
+ if (isascii((unsigned char)*ptr) &&
+ (isspace((unsigned char)*ptr) || *ptr == '#' || *ptr == '\0'))
+ {
+ //
+ // The first character it saw
+ // was a whitespace character
+ // or a comment character.
+ // This means that there's
+ // no value.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has a parameter but no value",
+ loadfile, lineno);
+ }
+ else
+ {
+ //
+ // This means that the first
+ // character it saw was a
+ // separator. This means that
+ // there's no address in the
+ // value, just a port.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has an %s parameter with a value containing no address",
+ loadfile, lineno, PARAM_ACTIVECLIENT);
+ }
+ continue;
+ }
+
+ //
+ // Null-terminate the address, and skip past
+ // it.
+ //
+ *ptr++ = '\0';
+
+ //
+ // Skip any white space following the
+ // separating character.
+ //
+ ptr = skipws(ptr);
+ if (ptr == NULL)
+ {
+ //
+ // The value is empty, so there's
+ // no port in the value.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has an %s parameter with a value containing no port",
+ loadfile, lineno, PARAM_ACTIVECLIENT);
+ continue;
+ }
+
+ //
+ // Get the port.
+ // We look for a white space character
+ // or a # as a terminator; the # introduces
+ // a comment that runs to the end of the
+ // line.
+ //
+ port = ptr;
+ toklen = strcspn(ptr, " \t#\r\n");
+ ptr += toklen;
+ if (toklen == 0)
+ {
+ //
+ // The value is empty, so there's
+ // no port in the value.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has an %s parameter with a value containing no port",
+ loadfile, lineno, PARAM_ACTIVECLIENT);
+ continue;
+ }
+
+ //
+ // Null-terminate the port, and skip past
+ // it.
+ //
+ *ptr++ = '\0';
+ result = pcap_strlcpy(activelist[num_active_clients].address, address, sizeof(activelist[num_active_clients].address));
+ if (result >= sizeof(activelist[num_active_clients].address))
+ {
+ //
+ // It didn't fit.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has an %s parameter with an address with more than %u characters",
+ loadfile, lineno, PARAM_ACTIVECLIENT,
+ (unsigned int)(sizeof(activelist[num_active_clients].address) - 1));
+ continue;
+ }
+ if (strcmp(port, "DEFAULT") == 0) // the user choose a custom port
+ result = pcap_strlcpy(activelist[num_active_clients].port, RPCAP_DEFAULT_NETPORT_ACTIVE, sizeof(activelist[num_active_clients].port));
+ else
+ result = pcap_strlcpy(activelist[num_active_clients].port, port, sizeof(activelist[num_active_clients].port));
+ if (result >= sizeof(activelist[num_active_clients].address))
+ {
+ //
+ // It didn't fit.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has an %s parameter with an port with more than %u characters",
+ loadfile, lineno, PARAM_ACTIVECLIENT,
+ (unsigned int)(sizeof(activelist[num_active_clients].port) - 1));
+ continue;
+ }
+
+ num_active_clients++;
+ }
+ else if (strcmp(param, PARAM_PASSIVECLIENT) == 0)
+ {
+ char *eos;
+ char *host;
+
+ //
+ // Get the host.
+ // We look for a white space character
+ // or a # as a terminator; the # introduces
+ // a comment that runs to the end of the
+ // line.
+ //
+ host = ptr;
+ toklen = strcspn(ptr, " \t#\r\n");
+ if (toklen == 0)
+ {
+ //
+ // The first character it saw
+ // was a whitespace character
+ // or a comment character.
+ // This means that there's
+ // no value.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has a parameter but no value",
+ loadfile, lineno);
+ continue;
+ }
+ ptr += toklen;
+ *ptr++ = '\0';
+
+ //
+ // Append this to the host list.
+ // Save the curren end-of-string for the
+ // host list, in case the new host doesn't
+ // fit, so that we can discard the partially-
+ // copied host name.
+ //
+ eos = hostlist + strlen(hostlist);
+ if (eos != hostlist)
+ {
+ //
+ // The list is not empty, so prepend
+ // a comma before adding this host.
+ //
+ result = pcap_strlcat(hostlist, ",", sizeof(hostlist));
+ if (result >= sizeof(hostlist))
+ {
+ //
+ // It didn't fit. Discard
+ // the comma (which wasn't
+ // added, but...), complain,
+ // and ignore this line.
+ //
+ *eos = '\0';
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has a %s parameter with a host name that doesn't fit",
+ loadfile, lineno, PARAM_PASSIVECLIENT);
+ continue;
+ }
+ }
+ result = pcap_strlcat(hostlist, host, sizeof(hostlist));
+ if (result >= sizeof(hostlist))
+ {
+ //
+ // It didn't fit. Discard the comma,
+ // complain, and ignore this line.
+ //
+ *eos = '\0';
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has a %s parameter with a host name that doesn't fit",
+ loadfile, lineno, PARAM_PASSIVECLIENT);
+ continue;
+ }
+ }
+ else if (strcmp(param, PARAM_NULLAUTHPERMIT) == 0)
+ {
+ char *setting;
+
+ //
+ // Get the setting.
+ // We look for a white space character
+ // or a # as a terminator; the # introduces
+ // a comment that runs to the end of the
+ // line.
+ //
+ setting = ptr;
+ toklen = strcspn(ptr, " \t#\r\n");
+ ptr += toklen;
+ if (toklen == 0)
+ {
+ //
+ // The first character it saw
+ // was a whitespace character
+ // or a comment character.
+ // This means that there's
+ // no value.
+ //
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has a parameter but no value",
+ loadfile, lineno);
+ continue;
+ }
+ *ptr++ = '\0';
+
+ //
+ // XXX - should we complain if it's
+ // neither "yes" nor "no"?
+ //
+ if (strcmp(setting, "YES") == 0)
+ nullAuthAllowed = 1;
+ else
+ nullAuthAllowed = 0;
+ }
+ else
+ {
+ rpcapd_log(LOGPRIO_ERROR,
+ "%s, line %u has an unknown parameter %s",
+ loadfile, lineno, param);
+ continue;
+ }
+ }
+
+done:
+ // clear the remaining fields of the active list
+ for (int i = num_active_clients; i < MAX_ACTIVE_LIST; i++)
+ {
+ activelist[i].address[0] = 0;
+ activelist[i].port[0] = 0;
+ num_active_clients++;
+ }
+
+ rpcapd_log(LOGPRIO_DEBUG, "New passive host list: %s", hostlist);
+ fclose(fp);
+ }
+}
+
+int fileconf_save(const char *savefile)
+{
+ FILE *fp;
+
+ if ((fp = fopen(savefile, "w")) != NULL)
+ {
+ char *token; /*, *port;*/ // temp, needed to separate items into the hostlist
+ char temphostlist[MAX_HOST_LIST + 1];
+ int i = 0;
+ char *lasts;
+
+ fprintf(fp, "# Configuration file help.\n\n");
+
+ // Save list of clients which are allowed to connect to us in passive mode
+ fprintf(fp, "# Hosts which are allowed to connect to this server (passive mode)\n");
+ fprintf(fp, "# Format: PassiveClient = <name or address>\n\n");
+
+ strncpy(temphostlist, hostlist, MAX_HOST_LIST);
+ temphostlist[MAX_HOST_LIST] = 0;
+
+ token = pcap_strtok_r(temphostlist, RPCAP_HOSTLIST_SEP, &lasts);
+ while(token != NULL)
+ {
+ fprintf(fp, "%s = %s\n", PARAM_PASSIVECLIENT, token);
+ token = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+ }
+
+
+ // Save list of clients which are allowed to connect to us in active mode
+ fprintf(fp, "\n\n");
+ fprintf(fp, "# Hosts to which this server is trying to connect to (active mode)\n");
+ fprintf(fp, "# Format: ActiveClient = <name or address>, <port | DEFAULT>\n\n");
+
+
+ while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0))
+ {
+ fprintf(fp, "%s = %s, %s\n", PARAM_ACTIVECLIENT,
+ activelist[i].address, activelist[i].port);
+ i++;
+ }
+
+ // Save if we want to permit NULL authentication
+ fprintf(fp, "\n\n");
+ fprintf(fp, "# Permit NULL authentication: YES or NO\n\n");
+
+ fprintf(fp, "%s = %s\n", PARAM_NULLAUTHPERMIT,
+ nullAuthAllowed ? "YES" : "NO");
+
+ fclose(fp);
+ return 0;
+ }
+ else
+ {
+ return -1;
+ }
+
+}
+
+//
+// Skip over white space.
+// If we hit a CR or LF, return NULL, otherwise return a pointer to
+// the first non-white space character. Replace white space characters
+// other than CR or LF with '\0', so that, if we're skipping white space
+// after a token, the token is null-terminated.
+//
+static char *skipws(char *ptr)
+{
+ while (isascii((unsigned char)*ptr) && isspace((unsigned char)*ptr)) {
+ if (*ptr == '\r' || *ptr == '\n')
+ return NULL;
+ *ptr++ = '\0';
+ }
+ return ptr;
+}
diff --git a/lib/libpcap/libpcap/rpcapd/fileconf.h b/lib/libpcap/libpcap/rpcapd/fileconf.h
new file mode 100644
index 0000000..912dd32
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/fileconf.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifndef __FILECONF_H__
+#define __FILECONF_H__
+
+void fileconf_read(void);
+int fileconf_save(const char *savefile);
+
+#endif
diff --git a/lib/libpcap/libpcap/rpcapd/log.c b/lib/libpcap/libpcap/rpcapd/log.c
new file mode 100644
index 0000000..7b5fee5
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/log.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <syslog.h>
+#endif
+
+#include "portability.h"
+
+#include "log.h"
+
+static int log_to_systemlog;
+static int log_debug_messages;
+
+static void rpcapd_vlog_stderr(log_priority,
+ PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
+
+static void rpcapd_vlog_stderr(log_priority priority, const char *message, va_list ap)
+{
+ const char *tag;
+
+ /*
+ * Squelch warnings from compilers that *don't* assume that
+ * priority always has a valid enum value and therefore don't
+ * assume that we'll always go through one of the case arms.
+ *
+ * If we have a default case, compilers that *do* assume that
+ * will then complain about the default case code being
+ * unreachable.
+ *
+ * Damned if you do, damned if you don't.
+ */
+ tag = "";
+
+ switch (priority) {
+
+ case LOGPRIO_DEBUG:
+ tag = "DEBUG: ";
+ break;
+
+ case LOGPRIO_INFO:
+ tag = "";
+ break;
+
+ case LOGPRIO_WARNING:
+ tag = "warning: ";
+ break;
+
+ case LOGPRIO_ERROR:
+ tag = "error: ";
+ break;
+ }
+
+ fprintf(stderr, "rpcapd: %s", tag);
+ vfprintf(stderr, message, ap);
+ putc('\n', stderr);
+}
+
+static void rpcapd_vlog_systemlog(log_priority,
+ PCAP_FORMAT_STRING(const char *), va_list) PCAP_PRINTFLIKE(2, 0);
+
+#ifdef _WIN32
+#define MESSAGE_SUBKEY \
+ "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\rpcapd"
+
+static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
+ va_list ap)
+{
+#if 0
+ static int initialized = 0;
+ HKEY hey_handle;
+ static HANDLE log_handle;
+ WORD eventlog_type;
+ DWORD event_id;
+ char msgbuf[1024];
+ char *strings[1];
+
+ if (!initialized) {
+ /*
+ * Register our message stuff in the Registry.
+ *
+ * First, create the registry key for us. If the key
+ * already exists, this succeeds and returns a handle
+ * for it.
+ */
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, MESSAGE_SUBKEY,
+ &key_handle) != ERROR_SUCCESS) {
+ /*
+ * Failed - give up and just log this message,
+ * and all subsequent messages, to the
+ * standard error.
+ */
+ log_to_systemlog = 0;
+ initialized = 1;
+ rpcapd_vlog_stderr(priority, message, ap);
+ return;
+ }
+ log_handle = RegisterEventSource(NULL, "rpcapd");
+ initialized = 1;
+ }
+
+ switch (priority) {
+
+ case LOGPRIO_DEBUG:
+ //
+ // XXX - what *should* we do about debug messages?
+ //
+ eventlog_type = EVENTLOG_INFORMATION_TYPE;
+ event_id = RPCAPD_INFO_ID;
+ break;
+
+ case LOGPRIO_INFO:
+ eventlog_type = EVENTLOG_INFORMATION_TYPE;
+ event_id = RPCAPD_INFO_ID;
+ break;
+
+ case LOGPRIO_WARNING:
+ eventlog_type = EVENTLOG_WARNING_TYPE;
+ event_id = RPCAPD_WARNING_ID;
+ break;
+
+ case LOGPRIO_ERROR:
+ eventlog_type = EVENTLOG_ERROR_TYPE;
+ event_id = RPCAPD_ERROR_ID;
+ break;
+
+ default:
+ /* Don't do this. */
+ return;
+ }
+
+ vsprintf(msgbuf, message, ap);
+
+ strings[0] = msgbuf;
+ /*
+ * If this fails, how are we going to report it?
+ */
+ (void) ReportEvent(log_handle, eventlog_type, 0, event_id, NULL, 1, 0,
+ strings, NULL);
+#else
+ rpcapd_vlog_stderr(priority, message, ap);
+#endif
+}
+#else
+static void rpcapd_vlog_systemlog(log_priority priority, const char *message,
+ va_list ap)
+{
+ static int initialized = 0;
+ int syslog_priority;
+
+ if (!initialized) {
+ //
+ // Open the log.
+ //
+ openlog("rpcapd", LOG_PID, LOG_DAEMON);
+ initialized = 1;
+ }
+
+ switch (priority) {
+
+ case LOGPRIO_DEBUG:
+ syslog_priority = LOG_DEBUG;
+ break;
+
+ case LOGPRIO_INFO:
+ syslog_priority = LOG_INFO;
+ break;
+
+ case LOGPRIO_WARNING:
+ syslog_priority = LOG_WARNING;
+ break;
+
+ case LOGPRIO_ERROR:
+ syslog_priority = LOG_ERR;
+ break;
+
+ default:
+ /* Don't do this. */
+ return;
+ }
+
+#ifdef HAVE_VSYSLOG
+ vsyslog(syslog_priority, message, ap);
+#else
+ /*
+ * Thanks, IBM, for not providing vsyslog() in AIX!
+ *
+ * They also warn that the syslog functions shouldn't
+ * be used in multithreaded programs, but the only thing
+ * obvious that seems to make the syslog_r functions
+ * better is that they have an additional argument
+ * that points to the information that's static to
+ * the syslog code in non-thread-safe versions. Most
+ * of that data is set by openlog(); since we already
+ * do an openlog before doing logging, and don't
+ * change that data afterwards, I suspect that, in
+ * practice, the regular syslog routines are OK for
+ * us (especially given that we'd end up having one
+ * static struct syslog_data anyway, which means we'd
+ * just be like the non-thread-safe version).
+ */
+ char logbuf[1024+1];
+
+ pcap_vsnprintf(logbuf, sizeof logbuf, message, ap);
+ syslog(syslog_priority, "%s", logbuf);
+#endif
+}
+#endif
+
+void rpcapd_log_set(int log_to_systemlog_arg, int log_debug_messages_arg)
+{
+ log_debug_messages = log_debug_messages_arg;
+ log_to_systemlog = log_to_systemlog_arg;
+}
+
+void rpcapd_log(log_priority priority, const char *message, ...)
+{
+ va_list ap;
+
+ if (priority != LOGPRIO_DEBUG || log_debug_messages) {
+ va_start(ap, message);
+ if (log_to_systemlog)
+ {
+ rpcapd_vlog_systemlog(priority, message, ap);
+ }
+ else
+ {
+ rpcapd_vlog_stderr(priority, message, ap);
+ }
+ va_end(ap);
+ }
+}
diff --git a/lib/libpcap/libpcap/rpcapd/log.h b/lib/libpcap/libpcap/rpcapd/log.h
new file mode 100644
index 0000000..28a6cee
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/log.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1998
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "pcap/funcattrs.h"
+
+extern void rpcapd_log_set(int, int);
+
+typedef enum {
+ LOGPRIO_DEBUG,
+ LOGPRIO_INFO,
+ LOGPRIO_WARNING,
+ LOGPRIO_ERROR
+} log_priority;
+
+extern void rpcapd_log(log_priority priority,
+ PCAP_FORMAT_STRING(const char *message), ...) PCAP_PRINTFLIKE(2, 3);
diff --git a/lib/libpcap/libpcap/rpcapd/org.tcpdump.rpcapd.plist b/lib/libpcap/libpcap/rpcapd/org.tcpdump.rpcapd.plist
new file mode 100644
index 0000000..db3223a
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/org.tcpdump.rpcapd.plist
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>Disabled</key>
+ <false/>
+ <key>Label</key>
+ <string>com.tcpdump.rpcapd</string>
+ <key>Program</key>
+ <string>/usr/local/libexec/rpcapd</string>
+ <key>ProgramArguments</key>
+ <array>
+ <string>/usr/local/libexec/rpcapd</string>
+ <string>-i</string>
+ </array>
+ <key>Sockets</key>
+ <dict>
+ <key>Listeners</key>
+ <dict>
+ <key>SockServiceName</key>
+ <string>2002</string>
+ </dict>
+ </dict>
+ <key>inetdCompatibility</key>
+ <dict>
+ <key>Wait</key>
+ <false/>
+ </dict>
+</dict>
+</plist>
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile b/lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile
new file mode 100644
index 0000000..c451420
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH RPCAPD-CONFIG 5 "6 January 2019"
+.SH NAME
+rpcapd-config \- rpcapd configuration file format
+.SH DESCRIPTION
+An
+.B rpcapd
+configuration file allows parameters to be set for
+.BR rpcapd (8).
+.LP
+A # introduces a comment that runs to the end of the line. Blank lines,
+and lines with only a comment, are ignored. Leading and trailing white
+space on a line are also ignored.
+.LP
+Lines that set a parameter are of the form
+.IP
+\fIparameter\fB=\fIvalue\fR
+.LP
+Whitespace preceding or following the = is ignored.
+.LP
+The
+.IR parameter s
+are:
+.TP
+.B ActiveClient
+.I value
+is a host name or IP addresse, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default active mode port for rpcapd, port 2003.
+Each
+.B ActiveClient
+line adds the host and port to the list of clients to which the server
+should connect in active mode.
+.TP
+.B PassiveClient
+.I value
+is a host name or IP addresse, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default passive mode port for rpcapd, port 2002.
+Each
+.B PassiveClient
+line adds the host and port to the list of clients addresses and ports
+that are allowed to connect to the server in passive mode.
+.TP
+.B NullAuthPermit
+.I value
+is either
+.B YES
+or
+.BR NO .
+.B YES
+means that null authentication is permitted;
+.B No
+means that it is not permitted.
+.SH SEE ALSO
+rpcapd(8)
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile.in b/lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile.in
new file mode 100644
index 0000000..1a87529
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd-config.manfile.in
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1994, 1996, 1997
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that: (1) source code distributions
+.\" retain the above copyright notice and this paragraph in its entirety, (2)
+.\" distributions including binary code include the above copyright notice and
+.\" this paragraph in its entirety in the documentation or other materials
+.\" provided with the distribution, and (3) all advertising materials mentioning
+.\" features or use of this software display the following acknowledgement:
+.\" ``This product includes software developed by the University of California,
+.\" Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+.\" the University nor the names of its contributors may be used to endorse
+.\" or promote products derived from this software without specific prior
+.\" written permission.
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+.\" WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+.\"
+.TH RPCAPD-CONFIG @MAN_FILE_FORMATS@ "6 January 2019"
+.SH NAME
+rpcapd-config \- rpcapd configuration file format
+.SH DESCRIPTION
+An
+.B rpcapd
+configuration file allows parameters to be set for
+.BR rpcapd (@MAN_ADMIN_COMMANDS@).
+.LP
+A # introduces a comment that runs to the end of the line. Blank lines,
+and lines with only a comment, are ignored. Leading and trailing white
+space on a line are also ignored.
+.LP
+Lines that set a parameter are of the form
+.IP
+\fIparameter\fB=\fIvalue\fR
+.LP
+Whitespace preceding or following the = is ignored.
+.LP
+The
+.IR parameter s
+are:
+.TP
+.B ActiveClient
+.I value
+is a host name or IP addresse, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default active mode port for rpcapd, port 2003.
+Each
+.B ActiveClient
+line adds the host and port to the list of clients to which the server
+should connect in active mode.
+.TP
+.B PassiveClient
+.I value
+is a host name or IP addresse, followed by a comma,
+semicolon, or space, followed by a port name and address or
+.BR DEFAULT .
+.B DEFAULT
+specifies the default passive mode port for rpcapd, port 2002.
+Each
+.B PassiveClient
+line adds the host and port to the list of clients addresses and ports
+that are allowed to connect to the server in passive mode.
+.TP
+.B NullAuthPermit
+.I value
+is either
+.B YES
+or
+.BR NO .
+.B YES
+means that null authentication is permitted;
+.B No
+means that it is not permitted.
+.SH SEE ALSO
+rpcapd(@MAN_ADMIN_COMMANDS@)
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.c b/lib/libpcap/libpcap/rpcapd/rpcapd.c
new file mode 100644
index 0000000..430acdc
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.c
@@ -0,0 +1,1359 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "ftmacros.h"
+
+#include <errno.h> // for the errno variable
+#include <string.h> // for strtok, etc
+#include <stdlib.h> // for malloc(), free(), ...
+#include <pcap.h> // for PCAP_ERRBUF_SIZE
+#include <signal.h> // for signal()
+
+#include "fmtutils.h"
+#include "sockutils.h" // for socket calls
+#include "varattrs.h" // for _U_
+#include "portability.h"
+#include "rpcapd.h"
+#include "config_params.h" // configuration file parameters
+#include "fileconf.h" // for the configuration file management
+#include "rpcap-protocol.h"
+#include "daemon.h" // the true main() method of this daemon
+#include "log.h"
+
+#ifdef _WIN32
+ #include <process.h> // for thread stuff
+ #include "win32-svc.h" // for Win32 service stuff
+ #include "getopt.h" // for getopt()-for-Windows
+#else
+ #include <fcntl.h> // for open()
+ #include <unistd.h> // for exit()
+ #include <sys/wait.h> // waitpid()
+#endif
+
+//
+// Element in list of sockets on which we're listening for connections.
+//
+struct listen_sock {
+ struct listen_sock *next;
+ SOCKET sock;
+};
+
+// Global variables
+char hostlist[MAX_HOST_LIST + 1]; //!< Keeps the list of the hosts that are allowed to connect to this server
+struct active_pars activelist[MAX_ACTIVE_LIST]; //!< Keeps the list of the hosts (host, port) on which I want to connect to (active mode)
+int nullAuthAllowed; //!< '1' if we permit NULL authentication, '0' otherwise
+static struct listen_sock *listen_socks; //!< sockets on which we listen
+char loadfile[MAX_LINE + 1]; //!< Name of the file from which we have to load the configuration
+static int passivemode = 1; //!< '1' if we want to run in passive mode as well
+static struct addrinfo mainhints; //!< temporary struct to keep settings needed to open the new socket
+static char address[MAX_LINE + 1]; //!< keeps the network address (either numeric or literal) to bind to
+static char port[MAX_LINE + 1]; //!< keeps the network port to bind to
+#ifdef _WIN32
+static HANDLE state_change_event; //!< event to signal that a state change should take place
+#endif
+static volatile sig_atomic_t shutdown_server; //!< '1' if the server is to shut down
+static volatile sig_atomic_t reread_config; //!< '1' if the server is to re-read its configuration
+
+extern char *optarg; // for getopt()
+
+// Function definition
+#ifdef _WIN32
+static unsigned __stdcall main_active(void *ptr);
+static BOOL WINAPI main_ctrl_event(DWORD);
+#else
+static void *main_active(void *ptr);
+static void main_terminate(int sign);
+static void main_reread_config(int sign);
+#endif
+static void accept_connections(void);
+static void accept_connection(SOCKET listen_sock);
+#ifndef _WIN32
+static void main_reap_children(int sign);
+#endif
+#ifdef _WIN32
+static unsigned __stdcall main_passive_serviceloop_thread(void *ptr);
+#endif
+
+#define RPCAP_ACTIVE_WAIT 30 /* Waiting time between two attempts to open a connection, in active mode (default: 30 sec) */
+
+/*!
+ \brief Prints the usage screen if it is launched in console mode.
+*/
+static void printusage(void)
+{
+ const char *usagetext =
+ "USAGE:"
+ " " PROGRAM_NAME " [-b <address>] [-p <port>] [-4] [-l <host_list>] [-a <host,port>]\n"
+ " [-n] [-v] [-d] "
+#ifndef _WIN32
+ "[-i] "
+#endif
+ "[-D] [-s <config_file>] [-f <config_file>]\n\n"
+ " -b <address> the address to bind to (either numeric or literal).\n"
+ " Default: binds to all local IPv4 and IPv6 addresses\n\n"
+ " -p <port> the port to bind to.\n"
+ " Default: binds to port " RPCAP_DEFAULT_NETPORT "\n\n"
+ " -4 use only IPv4.\n"
+ " Default: use both IPv4 and IPv6 waiting sockets\n\n"
+ " -l <host_list> a file that contains a list of hosts that are allowed\n"
+ " to connect to this server (if more than one, list them one\n"
+ " per line).\n"
+ " We suggest to use literal names (instead of numeric ones)\n"
+ " in order to avoid problems with different address families.\n\n"
+ " -n permit NULL authentication (usually used with '-l')\n\n"
+ " -a <host,port> run in active mode when connecting to 'host' on port 'port'\n"
+ " In case 'port' is omitted, the default port (" RPCAP_DEFAULT_NETPORT_ACTIVE ") is used\n\n"
+ " -v run in active mode only (default: if '-a' is specified, it\n"
+ " accepts passive connections as well)\n\n"
+ " -d run in daemon mode (UNIX only) or as a service (Win32 only)\n"
+ " Warning (Win32): this switch is provided automatically when\n"
+ " the service is started from the control panel\n\n"
+#ifndef _WIN32
+ " -i run in inetd mode (UNIX only)\n\n"
+#endif
+ " -D log debugging messages\n\n"
+ " -s <config_file> save the current configuration to file\n\n"
+ " -f <config_file> load the current configuration from file; all switches\n"
+ " specified from the command line are ignored\n\n"
+ " -h print this help screen\n\n";
+
+ (void)fprintf(stderr, "RPCAPD, a remote packet capture daemon.\n"
+ "Compiled with %s\n\n", pcap_lib_version());
+ printf("%s", usagetext);
+}
+
+
+
+//! Program main
+int main(int argc, char *argv[])
+{
+ char savefile[MAX_LINE + 1]; // name of the file on which we have to save the configuration
+ int log_to_systemlog = 0; // Non-zero if we should log to the "system log" rather than the standard error
+ int isdaemon = 0; // Non-zero if the user wants to run this program as a daemon
+#ifndef _WIN32
+ int isrunbyinetd = 0; // Non-zero if this is being run by inetd or something inetd-like
+#endif
+ int log_debug_messages = 0; // Non-zero if the user wants debug messages logged
+ int retval; // keeps the returning value from several functions
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+#ifndef _WIN32
+ struct sigaction action;
+#endif
+
+ savefile[0] = 0;
+ loadfile[0] = 0;
+ hostlist[0] = 0;
+
+ // Initialize errbuf
+ memset(errbuf, 0, sizeof(errbuf));
+
+ strncpy(address, RPCAP_DEFAULT_NETADDR, MAX_LINE);
+ strncpy(port, RPCAP_DEFAULT_NETPORT, MAX_LINE);
+
+ // Prepare to open a new server socket
+ memset(&mainhints, 0, sizeof(struct addrinfo));
+
+ mainhints.ai_family = PF_UNSPEC;
+ mainhints.ai_flags = AI_PASSIVE; // Ready to a bind() socket
+ mainhints.ai_socktype = SOCK_STREAM;
+
+ // Getting the proper command line options
+ while ((retval = getopt(argc, argv, "b:dDhip:4l:na:s:f:v")) != -1)
+ {
+ switch (retval)
+ {
+ case 'D':
+ log_debug_messages = 1;
+ rpcapd_log_set(log_to_systemlog, log_debug_messages);
+ break;
+ case 'b':
+ strncpy(address, optarg, MAX_LINE);
+ break;
+ case 'p':
+ strncpy(port, optarg, MAX_LINE);
+ break;
+ case '4':
+ mainhints.ai_family = PF_INET; // IPv4 server only
+ break;
+ case 'd':
+ isdaemon = 1;
+ log_to_systemlog = 1;
+ rpcapd_log_set(log_to_systemlog, log_debug_messages);
+ break;
+ case 'i':
+#ifdef _WIN32
+ printusage();
+ exit(1);
+#else
+ isrunbyinetd = 1;
+ log_to_systemlog = 1;
+ rpcapd_log_set(log_to_systemlog, log_debug_messages);
+#endif
+ break;
+ case 'n':
+ nullAuthAllowed = 1;
+ break;
+ case 'v':
+ passivemode = 0;
+ break;
+ case 'l':
+ {
+ strncpy(hostlist, optarg, sizeof(hostlist));
+ break;
+ }
+ case 'a':
+ {
+ char *tmpaddress, *tmpport;
+ char *lasts;
+ int i = 0;
+
+ tmpaddress = pcap_strtok_r(optarg, RPCAP_HOSTLIST_SEP, &lasts);
+
+ while ((tmpaddress != NULL) && (i < MAX_ACTIVE_LIST))
+ {
+ tmpport = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+
+ pcap_strlcpy(activelist[i].address, tmpaddress, MAX_LINE);
+
+ if ((tmpport == NULL) || (strcmp(tmpport, "DEFAULT") == 0)) // the user choose a custom port
+ pcap_strlcpy(activelist[i].port, RPCAP_DEFAULT_NETPORT_ACTIVE, MAX_LINE);
+ else
+ pcap_strlcpy(activelist[i].port, tmpport, MAX_LINE);
+
+ tmpaddress = pcap_strtok_r(NULL, RPCAP_HOSTLIST_SEP, &lasts);
+
+ i++;
+ }
+
+ if (i > MAX_ACTIVE_LIST)
+ rpcapd_log(LOGPRIO_ERROR, "Only MAX_ACTIVE_LIST active connections are currently supported.");
+
+ // I don't initialize the remaining part of the structure, since
+ // it is already zeroed (it is a global var)
+ break;
+ }
+ case 'f':
+ pcap_strlcpy(loadfile, optarg, MAX_LINE);
+ break;
+ case 's':
+ pcap_strlcpy(savefile, optarg, MAX_LINE);
+ break;
+ case 'h':
+ printusage();
+ exit(0);
+ /*NOTREACHED*/
+ default:
+ exit(1);
+ /*NOTREACHED*/
+ }
+ }
+
+#ifndef _WIN32
+ if (isdaemon && isrunbyinetd)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "rpcapd: -d and -i can't be used together");
+ exit(1);
+ }
+#endif
+
+ if (sock_init(errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(-1);
+ }
+
+ if (savefile[0] && fileconf_save(savefile))
+ rpcapd_log(LOGPRIO_DEBUG, "Error when saving the configuration to file");
+
+ // If the file does not exist, it keeps the settings provided by the command line
+ if (loadfile[0])
+ fileconf_read();
+
+#ifdef WIN32
+ //
+ // Create a handle to signal the main loop to tell it to do
+ // something.
+ //
+ state_change_event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (state_change_event == NULL)
+ {
+ sock_geterror("Can't create state change event", errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(2);
+ }
+
+ //
+ // Catch control signals.
+ //
+ if (!SetConsoleCtrlHandler(main_ctrl_event, TRUE))
+ {
+ sock_geterror("Can't set control handler", errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(2);
+ }
+#else
+ memset(&action, 0, sizeof (action));
+ action.sa_handler = main_terminate;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGTERM, &action, NULL);
+ memset(&action, 0, sizeof (action));
+ action.sa_handler = main_reap_children;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGCHLD, &action, NULL);
+ // Ignore SIGPIPE - we'll get EPIPE when trying to write to a closed
+ // connection, we don't want to get killed by a signal in that case
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+#ifndef _WIN32
+ if (isrunbyinetd)
+ {
+ //
+ // -i was specified, indicating that this is being run
+ // by inetd or something that can run network daemons
+ // as if it were inetd (xinetd, launchd, systemd, etc.).
+ //
+ // We assume that the program that launched us just
+ // duplicated a single socket for the connection
+ // to our standard input, output, and error, so we
+ // can just use the standard input as our control
+ // socket.
+ //
+ int sockctrl;
+ int devnull_fd;
+
+ //
+ // Duplicate the standard input as the control socket.
+ //
+ sockctrl = dup(0);
+ if (sockctrl == -1)
+ {
+ sock_geterror("Can't dup standard input", errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(2);
+ }
+
+ //
+ // Try to set the standard input, output, and error
+ // to /dev/null.
+ //
+ devnull_fd = open("/dev/null", O_RDWR);
+ if (devnull_fd != -1)
+ {
+ //
+ // If this fails, just drive on.
+ //
+ (void)dup2(devnull_fd, 0);
+ (void)dup2(devnull_fd, 1);
+ (void)dup2(devnull_fd, 2);
+ close(devnull_fd);
+ }
+
+ //
+ // Handle this client.
+ // This is passive mode, so we don't care whether we were
+ // told by the client to close.
+ //
+ char *hostlist_copy = strdup(hostlist);
+ if (hostlist_copy == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+ exit(0);
+ }
+ (void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
+ nullAuthAllowed);
+
+ //
+ // Nothing more to do.
+ //
+ exit(0);
+ }
+#endif
+
+ if (isdaemon)
+ {
+ //
+ // This is being run as a daemon.
+ // On UN*X, it might be manually run, or run from an
+ // rc file.
+ //
+#ifndef _WIN32
+ int pid;
+
+ //
+ // Daemonize ourselves.
+ //
+ // Unix Network Programming, pg 336
+ //
+ if ((pid = fork()) != 0)
+ exit(0); // Parent terminates
+
+ // First child continues
+ // Set daemon mode
+ setsid();
+
+ // generated under unix with 'kill -HUP', needed to reload the configuration
+ memset(&action, 0, sizeof (action));
+ action.sa_handler = main_reread_config;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGHUP, &action, NULL);
+
+ if ((pid = fork()) != 0)
+ exit(0); // First child terminates
+
+ // LINUX WARNING: the current linux implementation of pthreads requires a management thread
+ // to handle some hidden stuff. So, as soon as you create the first thread, two threads are
+ // created. Fom this point on, the number of threads active are always one more compared
+ // to the number you're expecting
+
+ // Second child continues
+// umask(0);
+// chdir("/");
+#else
+ //
+ // This is being run as a service on Windows.
+ //
+ // If this call succeeds, it is blocking on Win32
+ //
+ if (svc_start() != 1)
+ rpcapd_log(LOGPRIO_DEBUG, "Unable to start the service");
+
+ // When the previous call returns, the entire application has to be stopped.
+ exit(0);
+#endif
+ }
+ else // Console mode
+ {
+#ifndef _WIN32
+ // Enable the catching of Ctrl+C
+ memset(&action, 0, sizeof (action));
+ action.sa_handler = main_terminate;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGINT, &action, NULL);
+
+ // generated under unix with 'kill -HUP', needed to reload the configuration
+ // We do not have this kind of signal in Win32
+ memset(&action, 0, sizeof (action));
+ action.sa_handler = main_reread_config;
+ action.sa_flags = 0;
+ sigemptyset(&action.sa_mask);
+ sigaction(SIGHUP, &action, NULL);
+#endif
+
+ printf("Press CTRL + C to stop the server...\n");
+ }
+
+ // If we're a Win32 service, we have already called this function in the service_main
+ main_startup();
+
+ // The code should never arrive here (since the main_startup is blocking)
+ // however this avoids a compiler warning
+ exit(0);
+}
+
+void main_startup(void)
+{
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+ struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket
+ int i;
+#ifdef _WIN32
+ HANDLE threadId; // handle for the subthread
+#else
+ pid_t pid;
+#endif
+
+ i = 0;
+ addrinfo = NULL;
+ memset(errbuf, 0, sizeof(errbuf));
+
+ // Starts all the active threads
+ while ((i < MAX_ACTIVE_LIST) && (activelist[i].address[0] != 0))
+ {
+ activelist[i].ai_family = mainhints.ai_family;
+
+#ifdef _WIN32
+ threadId = (HANDLE)_beginthreadex(NULL, 0, main_active,
+ (void *)&activelist[i], 0, NULL);
+ if (threadId == 0)
+ {
+ rpcapd_log(LOGPRIO_DEBUG, "Error creating the active child threads");
+ continue;
+ }
+ CloseHandle(threadId);
+#else
+ if ((pid = fork()) == 0) // I am the child
+ {
+ main_active((void *) &activelist[i]);
+ exit(0);
+ }
+#endif
+ i++;
+ }
+
+ /*
+ * The code that manages the active connections is not blocking;
+ * the code that manages the passive connection is blocking.
+ * So, if the user does not want to run in passive mode, we have
+ * to block the main thread here, otherwise the program ends and
+ * all threads are stopped.
+ *
+ * WARNING: this means that in case we have only active mode,
+ * the program does not terminate even if all the child thread
+ * terminates. The user has always to press Ctrl+C (or send a
+ * SIGTERM) to terminate the program.
+ */
+ if (passivemode)
+ {
+ struct addrinfo *tempaddrinfo;
+
+ //
+ // Get a list of sockets on which to listen.
+ //
+ if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+ return;
+ }
+
+ for (tempaddrinfo = addrinfo; tempaddrinfo;
+ tempaddrinfo = tempaddrinfo->ai_next)
+ {
+ SOCKET sock;
+ struct listen_sock *sock_info;
+
+ if ((sock = sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ {
+ switch (tempaddrinfo->ai_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *in;
+ char addrbuf[INET_ADDRSTRLEN];
+
+ in = (struct sockaddr_in *)tempaddrinfo->ai_addr;
+ rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
+ inet_ntop(AF_INET, &in->sin_addr,
+ addrbuf, sizeof (addrbuf)),
+ ntohs(in->sin_port),
+ errbuf);
+ break;
+ }
+
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *in6;
+ char addrbuf[INET6_ADDRSTRLEN];
+
+ in6 = (struct sockaddr_in6 *)tempaddrinfo->ai_addr;
+ rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for %s:%u: %s",
+ inet_ntop(AF_INET6, &in6->sin6_addr,
+ addrbuf, sizeof (addrbuf)),
+ ntohs(in6->sin6_port),
+ errbuf);
+ break;
+ }
+
+ default:
+ rpcapd_log(LOGPRIO_WARNING, "Can't listen on socket for address family %u: %s",
+ tempaddrinfo->ai_family,
+ errbuf);
+ break;
+ }
+ continue;
+ }
+
+ sock_info = (struct listen_sock *) malloc(sizeof (struct listen_sock));
+ if (sock_info == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Can't allocate structure for listen socket");
+ exit(2);
+ }
+ sock_info->sock = sock;
+ sock_info->next = listen_socks;
+ listen_socks = sock_info;
+ }
+
+ freeaddrinfo(addrinfo);
+
+ if (listen_socks == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Can't listen on any address");
+ exit(2);
+ }
+
+ //
+ // Now listen on all of them, waiting for connections.
+ //
+ accept_connections();
+ }
+
+ //
+ // We're done; exit.
+ //
+ rpcapd_log(LOGPRIO_DEBUG, PROGRAM_NAME " is closing.\n");
+
+#ifndef _WIN32
+ //
+ // Sends a KILL signal to all the processes in this process's
+ // process group; i.e., it kills all the child processes
+ // we've created.
+ //
+ // XXX - that also includes us, so we will be killed as well;
+ // that may cause a message to be printed or logged.
+ //
+ kill(0, SIGKILL);
+#endif
+
+ //
+ // Just leave. We shouldn't need to clean up sockets or
+ // anything else, and if we try to do so, we'll could end
+ // up closing sockets, or shutting Winsock down, out from
+ // under service loops, causing all sorts of noisy error
+ // messages.
+ //
+ // We shouldn't need to worry about cleaning up any resources
+ // such as handles, sockets, threads, etc. - exit() should
+ // terminate the process, causing all those resources to be
+ // cleaned up (including the threads; Microsoft claims in the
+ // ExitProcess() documentation that, if ExitProcess() is called,
+ // "If a thread is waiting on a kernel object, it will not be
+ // terminated until the wait has completed.", but claims in the
+ // _beginthread()/_beginthreadex() documentation that "All threads
+ // are terminated if any thread calls abort, exit, _exit, or
+ // ExitProcess." - the latter appears to be the case, even for
+ // threads waiting on the event for a pcap_t).
+ //
+ exit(0);
+}
+
+#ifdef _WIN32
+static void
+send_state_change_event(void)
+{
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+
+ if (!SetEvent(state_change_event))
+ {
+ sock_geterror("SetEvent on shutdown event failed", errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ }
+}
+
+void
+send_shutdown_notification(void)
+{
+ //
+ // Indicate that the server should shut down.
+ //
+ shutdown_server = 1;
+
+ //
+ // Send a state change event, to wake up WSAWaitForMultipleEvents().
+ //
+ send_state_change_event();
+}
+
+void
+send_reread_configuration_notification(void)
+{
+ //
+ // Indicate that the server should re-read its configuration file.
+ //
+ reread_config = 1;
+
+ //
+ // Send a state change event, to wake up WSAWaitForMultipleEvents().
+ //
+ send_state_change_event();
+}
+
+static BOOL WINAPI main_ctrl_event(DWORD ctrltype)
+{
+ //
+ // ctrltype is one of:
+ //
+ // CTRL_C_EVENT - we got a ^C; this is like SIGINT
+ // CTRL_BREAK_EVENT - we got Ctrl+Break
+ // CTRL_CLOSE_EVENT - the console was closed; this is like SIGHUP
+ // CTRL_LOGOFF_EVENT - a user is logging off; this is received
+ // only by services
+ // CTRL_SHUTDOWN_EVENT - the systemis shutting down; this is
+ // received only by services
+ //
+ // For now, we treat all but CTRL_LOGOFF_EVENT as indications
+ // that we should shut down.
+ //
+ switch (ctrltype)
+ {
+ case CTRL_C_EVENT:
+ case CTRL_BREAK_EVENT:
+ case CTRL_CLOSE_EVENT:
+ case CTRL_SHUTDOWN_EVENT:
+ //
+ // Set a shutdown notification.
+ //
+ send_shutdown_notification();
+ break;
+
+ default:
+ break;
+ }
+
+ //
+ // We handled this.
+ //
+ return TRUE;
+}
+#else
+static void main_terminate(int sign _U_)
+{
+ //
+ // Note that the server should shut down.
+ // select() should get an EINTR error when we return,
+ // so it will wake up and know it needs to check the flag.
+ //
+ shutdown_server = 1;
+}
+
+static void main_reread_config(int sign _U_)
+{
+ //
+ // Note that the server should re-read its configuration file.
+ // select() should get an EINTR error when we return,
+ // so it will wake up and know it needs to check the flag.
+ //
+ reread_config = 1;
+}
+
+static void main_reap_children(int sign _U_)
+{
+ pid_t pid;
+ int exitstat;
+
+ // Reap all child processes that have exited.
+ // For reference, Stevens, pg 128
+
+ while ((pid = waitpid(-1, &exitstat, WNOHANG)) > 0)
+ rpcapd_log(LOGPRIO_DEBUG, "Child terminated");
+
+ return;
+}
+#endif
+
+//
+// Loop waiting for incoming connections and accepting them.
+//
+static void
+accept_connections(void)
+{
+#ifdef _WIN32
+ struct listen_sock *sock_info;
+ DWORD num_events;
+ WSAEVENT *events;
+ int i;
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+
+ //
+ // How big does the set of events need to be?
+ // One for the shutdown event, plus one for every socket on which
+ // we'll be listening.
+ //
+ num_events = 1; // shutdown event
+ for (sock_info = listen_socks; sock_info;
+ sock_info = sock_info->next)
+ {
+ if (num_events == WSA_MAXIMUM_WAIT_EVENTS)
+ {
+ //
+ // WSAWaitForMultipleEvents() doesn't support
+ // more than WSA_MAXIMUM_WAIT_EVENTS events
+ // on which to wait.
+ //
+ rpcapd_log(LOGPRIO_ERROR, "Too many sockets on which to listen");
+ exit(2);
+ }
+ num_events++;
+ }
+
+ //
+ // Allocate the array of events.
+ //
+ events = (WSAEVENT *) malloc(num_events * sizeof (WSAEVENT));
+ if (events == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Can't allocate array of events which to listen");
+ exit(2);
+ }
+
+ //
+ // Fill it in.
+ //
+ events[0] = state_change_event; // state change event first
+ for (sock_info = listen_socks, i = 1; sock_info;
+ sock_info = sock_info->next, i++)
+ {
+ WSAEVENT event;
+
+ //
+ // Create an event that is signaled if there's a connection
+ // to accept on the socket in question.
+ //
+ event = WSACreateEvent();
+ if (event == WSA_INVALID_EVENT)
+ {
+ sock_geterror("Can't create socket event", errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(2);
+ }
+ if (WSAEventSelect(sock_info->sock, event, FD_ACCEPT) == SOCKET_ERROR)
+ {
+ sock_geterror("Can't setup socket event", errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(2);
+ }
+ events[i] = event;
+ }
+
+ for (;;)
+ {
+ //
+ // Wait for incoming connections.
+ //
+ DWORD ret;
+
+ ret = WSAWaitForMultipleEvents(num_events, events, FALSE,
+ WSA_INFINITE, FALSE);
+ if (ret == WSA_WAIT_FAILED)
+ {
+ sock_geterror("WSAWaitForMultipleEvents failed", errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(2);
+ }
+
+ if (ret == WSA_WAIT_EVENT_0)
+ {
+ //
+ // The state change event was set.
+ //
+ if (shutdown_server)
+ {
+ //
+ // Time to quit. Exit the loop.
+ //
+ break;
+ }
+ if (reread_config)
+ {
+ //
+ // We should re-read the configuration
+ // file.
+ //
+ reread_config = 0; // clear the indicator
+ fileconf_read();
+ }
+ }
+
+ //
+ // Check each socket.
+ //
+ for (sock_info = listen_socks, i = 1; sock_info;
+ sock_info = sock_info->next, i++)
+ {
+ WSANETWORKEVENTS network_events;
+
+ if (WSAEnumNetworkEvents(sock_info->sock,
+ events[i], &network_events) == SOCKET_ERROR)
+ {
+ sock_geterror("WSAEnumNetworkEvents failed",
+ errbuf, PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ exit(2);
+ }
+ if (network_events.lNetworkEvents & FD_ACCEPT)
+ {
+ //
+ // Did an error occur?
+ //
+ if (network_events.iErrorCode[FD_ACCEPT_BIT] != 0)
+ {
+ //
+ // Yes - report it and keep going.
+ //
+ sock_fmterror("Socket error",
+ network_events.iErrorCode[FD_ACCEPT_BIT],
+ errbuf,
+ PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ continue;
+ }
+
+ //
+ // Accept the connection.
+ //
+ accept_connection(sock_info->sock);
+ }
+ }
+ }
+#else
+ struct listen_sock *sock_info;
+ int num_sock_fds;
+
+ //
+ // How big does the bitset of sockets on which to select() have
+ // to be?
+ //
+ num_sock_fds = 0;
+ for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
+ {
+ if (sock_info->sock + 1 > num_sock_fds)
+ {
+ if ((unsigned int)(sock_info->sock + 1) >
+ (unsigned int)FD_SETSIZE)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Socket FD is too bit for an fd_set");
+ exit(2);
+ }
+ num_sock_fds = sock_info->sock + 1;
+ }
+ }
+
+ for (;;)
+ {
+ fd_set sock_fds;
+ int ret;
+
+ //
+ // Set up an fd_set for all the sockets on which we're
+ // listening.
+ //
+ // This set is modified by select(), so we have to
+ // construct it anew each time.
+ //
+ FD_ZERO(&sock_fds);
+ for (sock_info = listen_socks; sock_info;
+ sock_info = sock_info->next)
+ {
+ FD_SET(sock_info->sock, &sock_fds);
+ }
+
+ //
+ // Wait for incoming connections.
+ //
+ ret = select(num_sock_fds, &sock_fds, NULL, NULL, NULL);
+ if (ret == -1)
+ {
+ if (errno == EINTR)
+ {
+ //
+ // If this is a "terminate the
+ // server" signal, exit the loop,
+ // otherwise just keep trying.
+ //
+ if (shutdown_server)
+ {
+ //
+ // Time to quit. Exit the loop.
+ //
+ break;
+ }
+ if (reread_config)
+ {
+ //
+ // We should re-read the configuration
+ // file.
+ //
+ reread_config = 0; // clear the indicator
+ fileconf_read();
+ }
+
+ //
+ // Go back and wait again.
+ //
+ continue;
+ }
+ else
+ {
+ rpcapd_log(LOGPRIO_ERROR, "select failed: %s",
+ strerror(errno));
+ exit(2);
+ }
+ }
+
+ //
+ // Check each socket.
+ //
+ for (sock_info = listen_socks; sock_info;
+ sock_info = sock_info->next)
+ {
+ if (FD_ISSET(sock_info->sock, &sock_fds))
+ {
+ //
+ // Accept the connection.
+ //
+ accept_connection(sock_info->sock);
+ }
+ }
+ }
+#endif
+
+ //
+ // Close all the listen sockets.
+ //
+ for (sock_info = listen_socks; sock_info; sock_info = sock_info->next)
+ {
+ closesocket(sock_info->sock);
+ }
+ sock_cleanup();
+}
+
+#ifdef _WIN32
+//
+// A structure to hold the parameters to the daemon service loop
+// thread on Windows.
+//
+// (On UN*X, there is no need for this explicit copy since the
+// fork "inherits" the parent stack.)
+//
+struct params_copy {
+ SOCKET sockctrl;
+ char *hostlist;
+};
+#endif
+
+//
+// Accept a connection and start a worker thread, on Windows, or a
+// worker process, on UN*X, to handle the connection.
+//
+static void
+accept_connection(SOCKET listen_sock)
+{
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+ SOCKET sockctrl; // keeps the socket ID for this control connection
+ struct sockaddr_storage from; // generic sockaddr_storage variable
+ socklen_t fromlen; // keeps the length of the sockaddr_storage variable
+
+#ifdef _WIN32
+ HANDLE threadId; // handle for the subthread
+ u_long off = 0;
+ struct params_copy *params_copy = NULL;
+#else
+ pid_t pid;
+#endif
+
+ // Initialize errbuf
+ memset(errbuf, 0, sizeof(errbuf));
+
+ for (;;)
+ {
+ // Accept the connection
+ fromlen = sizeof(struct sockaddr_storage);
+
+ sockctrl = accept(listen_sock, (struct sockaddr *) &from, &fromlen);
+
+ if (sockctrl != INVALID_SOCKET)
+ {
+ // Success.
+ break;
+ }
+
+ // The accept() call can return this error when a signal is catched
+ // In this case, we have simply to ignore this error code
+ // Stevens, pg 124
+#ifdef _WIN32
+ if (WSAGetLastError() == WSAEINTR)
+#else
+ if (errno == EINTR)
+#endif
+ continue;
+
+ // Don't check for errors here, since the error can be due to the fact that the thread
+ // has been killed
+ sock_geterror("accept()", errbuf, PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "Accept of control connection from client failed: %s",
+ errbuf);
+ return;
+ }
+
+#ifdef _WIN32
+ //
+ // Put the socket back into blocking mode; doing WSAEventSelect()
+ // on the listen socket makes that socket non-blocking, and it
+ // appears that sockets returned from an accept() on that socket
+ // are also non-blocking.
+ //
+ // First, we have to un-WSAEventSelect() this socket, and then
+ // we can turn non-blocking mode off.
+ //
+ // If this fails, we aren't guaranteed that, for example, any
+ // of the error message will be sent - if it can't be put in
+ // the socket queue, the send will just fail.
+ //
+ // So we just log the message and close the connection.
+ //
+ if (WSAEventSelect(sockctrl, NULL, 0) == SOCKET_ERROR)
+ {
+ sock_geterror("WSAEventSelect()", errbuf, PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ sock_close(sockctrl, NULL, 0);
+ return;
+ }
+ if (ioctlsocket(sockctrl, FIONBIO, &off) == SOCKET_ERROR)
+ {
+ sock_geterror("ioctlsocket(FIONBIO)", errbuf, PCAP_ERRBUF_SIZE);
+ rpcapd_log(LOGPRIO_ERROR, "%s", errbuf);
+ sock_close(sockctrl, NULL, 0);
+ return;
+ }
+
+ //
+ // Make a copy of the host list to pass to the new thread, so that
+ // if we update it in the main thread, it won't catch us in the
+ // middle of updating it.
+ //
+ // daemon_serviceloop() will free it once it's done with it.
+ //
+ char *hostlist_copy = strdup(hostlist);
+ if (hostlist_copy == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+ sock_close(sockctrl, NULL, 0);
+ return;
+ }
+
+ //
+ // Allocate a location to hold the values of sockctrl.
+ // It will be freed in the newly-created thread once it's
+ // finished with it.
+ //
+ params_copy = malloc(sizeof(*params_copy));
+ if (params_copy == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Out of memory allocating the parameter copy structure");
+ free(hostlist_copy);
+ sock_close(sockctrl, NULL, 0);
+ return;
+ }
+ params_copy->sockctrl = sockctrl;
+ params_copy->hostlist = hostlist_copy;
+
+ threadId = (HANDLE)_beginthreadex(NULL, 0,
+ main_passive_serviceloop_thread, (void *) params_copy, 0, NULL);
+ if (threadId == 0)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Error creating the child thread");
+ free(params_copy);
+ free(hostlist_copy);
+ sock_close(sockctrl, NULL, 0);
+ return;
+ }
+ CloseHandle(threadId);
+#else /* _WIN32 */
+ pid = fork();
+ if (pid == -1)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Error creating the child process: %s",
+ strerror(errno));
+ sock_close(sockctrl, NULL, 0);
+ return;
+ }
+ if (pid == 0)
+ {
+ //
+ // Child process.
+ //
+ // Close the socket on which we're listening (must
+ // be open only in the parent).
+ //
+ closesocket(listen_sock);
+
+#if 0
+ //
+ // Modify thread params so that it can be killed at any time
+ // XXX - is this necessary? This is the main and, currently,
+ // only thread in the child process, and nobody tries to
+ // cancel us, although *we* may cancel the thread that's
+ // handling the capture loop.
+ //
+ if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL))
+ goto end;
+ if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL))
+ goto end;
+#endif
+
+ //
+ // Run the service loop.
+ // This is passive mode, so we don't care whether we were
+ // told by the client to close.
+ //
+ char *hostlist_copy = strdup(hostlist);
+ if (hostlist_copy == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+ exit(0);
+ }
+ (void)daemon_serviceloop(sockctrl, 0, hostlist_copy,
+ nullAuthAllowed);
+
+ exit(0);
+ }
+
+ // I am the parent
+ // Close the socket for this session (must be open only in the child)
+ closesocket(sockctrl);
+#endif /* _WIN32 */
+}
+
+/*!
+ \brief 'true' main of the program in case the active mode is turned on.
+
+ This function loops forever trying to connect to the remote host, until the
+ daemon is turned down.
+
+ \param ptr: it keeps the 'activepars' parameters. It is a 'void *'
+ just because the thread APIs want this format.
+*/
+#ifdef _WIN32
+static unsigned __stdcall
+#else
+static void *
+#endif
+main_active(void *ptr)
+{
+ char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed
+ SOCKET sockctrl; // keeps the socket ID for this control connection
+ struct addrinfo hints; // temporary struct to keep settings needed to open the new socket
+ struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket
+ struct active_pars *activepars;
+
+ activepars = (struct active_pars *) ptr;
+
+ // Prepare to open a new server socket
+ memset(&hints, 0, sizeof(struct addrinfo));
+ // WARNING Currently it supports only ONE socket family among IPv4 and IPv6
+ hints.ai_family = AF_INET; // PF_UNSPEC to have both IPv4 and IPv6 server
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_family = activepars->ai_family;
+
+ rpcapd_log(LOGPRIO_DEBUG, "Connecting to host %s, port %s, using protocol %s",
+ activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
+ (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
+
+ // Initialize errbuf
+ memset(errbuf, 0, sizeof(errbuf));
+
+ // Do the work
+ if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1)
+ {
+ rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+ return 0;
+ }
+
+ for (;;)
+ {
+ int activeclose;
+
+ if ((sockctrl = sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == INVALID_SOCKET)
+ {
+ rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s",
+ activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4":
+ (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified");
+
+ rpcapd_log(LOGPRIO_DEBUG, "%s", errbuf);
+
+ sleep_secs(RPCAP_ACTIVE_WAIT);
+
+ continue;
+ }
+
+ char *hostlist_copy = strdup(hostlist);
+ if (hostlist_copy == NULL)
+ {
+ rpcapd_log(LOGPRIO_ERROR, "Out of memory copying the host/port list");
+ activeclose = 0;
+ sock_close(sockctrl, NULL, 0);
+ }
+ else
+ {
+ //
+ // daemon_serviceloop() will free the copy.
+ //
+ activeclose = daemon_serviceloop(sockctrl, 1,
+ hostlist_copy, nullAuthAllowed);
+ }
+
+ // If the connection is closed by the user explicitely, don't try to connect to it again
+ // just exit the program
+ if (activeclose == 1)
+ break;
+ }
+
+ freeaddrinfo(addrinfo);
+ return 0;
+}
+
+#ifdef _WIN32
+//
+// Main routine of a passive-mode service thread.
+//
+unsigned __stdcall main_passive_serviceloop_thread(void *ptr)
+{
+ struct params_copy params = *(struct params_copy *)ptr;
+ free(ptr);
+
+ //
+ // Handle this client.
+ // This is passive mode, so we don't care whether we were
+ // told by the client to close.
+ //
+ (void)daemon_serviceloop(params.sockctrl, 0, params.hostlist,
+ nullAuthAllowed);
+
+ return 0;
+}
+#endif
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.h b/lib/libpcap/libpcap/rpcapd/rpcapd.h
new file mode 100644
index 0000000..90ba7ff
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifndef __RPCAPD_H__
+#define __RPCAPD_H__
+
+#define PROGRAM_NAME "rpcapd"
+#define SOCKET_MAXCONN 10 /* Maximum number of connections queued into the accept() */
+#ifdef _WIN32
+void send_shutdown_notification(void); // Send notification to shut down the daemon
+void send_reread_configuration_notification(void); // Send notification to re-read the configuration file
+#endif
+void main_startup(void);
+
+#endif
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.inetd.conf b/lib/libpcap/libpcap/rpcapd/rpcapd.inetd.conf
new file mode 100644
index 0000000..86823f0
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.inetd.conf
@@ -0,0 +1 @@
+2002 stream tcp nowait root /usr/local/sbin/rpcapd rpcapd -i
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.manadmin b/lib/libpcap/libpcap/rpcapd/rpcapd.manadmin
new file mode 100644
index 0000000..e4bbc8f
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.manadmin
@@ -0,0 +1,233 @@
+.\" rpcapd.8
+.\"
+.\" Copyright (c) 2002-2005 NetGroup, Politecnico di Torino (Italy)
+.\" Copyright (c) 2005-2009 CACE Technologies
+.\" Copyright (c) 2018- The TCPdump Group
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Politecnico di Torino nor the names 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.
+.\"
+.TH RPCAPD 8 "April 20, 2018"
+.SH NAME
+rpcapd \- capture daemon to be controlled by a remote libpcap application
+.SH SYNOPSIS
+.na
+rpcapd
+[
+.B \-b
+.I address
+] [
+.B \-p
+.I port
+] [
+.B \-4
+] [
+.B \-l
+.I host_list
+]
+.br
+.ti +8
+[
+.B \-a
+.IR host , port
+] [
+.B \-n
+] [
+.B \-v
+] [
+.B \-d
+] [
+.B \-i
+]
+.br
+.ti +8
+[
+.B \-D
+] [
+.B \-s
+.I config_file
+] [
+.B \-f
+.I config_file
+]
+.br
+.ad
+.SH DESCRIPTION
+.LP
+\fIRpcapd\fP is a daemon (Unix) or service (Win32) that allows the capture
+and filter part of libpcap to be run on a remote system.
+.LP
+Rpcapd can run in two modes: passive mode (default) and active mode.
+.LP
+In passive mode, the client (e.g., a network sniffer) connects to
+.BR rpcapd .
+It then sends hem the appropriate commands to start the capture.
+.LP
+In active mode,
+.B rpcapd
+tries to establish a connection toward the client
+(e.g., a network sniffer). The client then sends the appropriate commands
+to rpcapd to start the capture.
+.LP
+Active mode is useful in case
+.B rpcapd
+is run behind a firewall and
+cannot receive connections from the external world. In this case,
+.B rpcapd
+can be configured to establish the connection to a given host,
+which has to be configured in order to wait for that connection. After
+establishing the connection, the protocol continues its job in almost
+the same way in both active and passive mode.
+.SH Configuration file
+.LP
+The user can create a configuration file in the same folder of the
+executable, and put the configuration commands in there. In order for
+rpcapd to execute the commands, you have to restart it on Win32, i.e.
+the initialization file is parsed only at the beginning). The UNIX
+version of rpcapd will reread the configuration file when receiving a
+HUP signel. In that case, all the existing connections remain in place,
+while the new connections will be created according to the new parameters.
+.LP
+In case a user does not want to create the configuration file manually,
+they can launch rpcapd with the requested parameters plus "-s filename".
+Rpcapd will parse all the parameters and save them into the specified
+configuration file.
+.SH Installing rpcapd on Win32
+.LP
+The remote daemon is installed automatically when installing WinPcap.
+The installation process places the rpcapd file into the WinPcap folder.
+This file can be executed either from the command line, or as a service.
+For instance, the installation process updates the list of available
+services list and it creates a new item (Remote Packet Capture Protocol
+v.0 (experimental) ). To avoid security problems, the service is
+inactive and it has to be started manually (control panel -
+administrative tools - services - start).
+.LP
+The service has a set of "standard" parameters, i.e. it is launched
+with the
+.B \-d
+flag (in order to make it run as a service) and the
+.B "-f rpcapd.ini"
+flag.
+.SH Starting rpcapd on Win32
+.LP
+The rpcapd executable can be launched directly, i.e. it can run in the
+foreground as well (not as a daemon/service). The procedure is quite
+simple: you have to invoke the executable from the command line with all
+the requested parameters except for the
+.B \-d
+flag. The capture server will
+start in the foreground.
+.SH Installing rpcapd on Unix-like systems
+TBD
+.SH Starting rpcapd on Unix-like systems
+.B rpcapd
+needs sufficient privileges to perform packet capture, e.g.
+run as root or be owned by root and have suid set. Most operating
+systems provide more elegant solutions when run as user than the
+above solutions, all of them different.
+.SH OPTIONS
+.TP
+.BI \-b " address"
+Bind to the IP address specified by
+.I address
+(either numeric or literal).
+By default,
+.B rpcapd
+binds to all local IPv4 and IPv6 addresses.
+.TP
+.BI \-p " port"
+Bind to the port specified by
+.IR port .
+By default,
+.B rpcapd
+binds to port 2002.
+.TP
+.B \-4
+Listen only on IPv4 addresses.
+By default,
+.B rpcapd
+listens on both IPv4 and IPv6 addresses.
+.TP
+.BI -l " host_list"
+Only allow hosts specified in the
+.I host_list
+argument to connect to this server.
+.I host_list
+is a list of host names or IP addresses, separated by commas.
+We suggest that you use use host names rather than literal IP addresses
+in order to avoid problems with different address families.
+.TP
+.B \-n
+Permit NULL authentication (usually used with
+.BR \-l ).
+.TP
+.BI \-a " host" , "port"
+Run in active mode, connecting to host
+.I host
+on port
+.IR port .
+In case
+.I port
+is omitted, the default port (2003) is used.
+.TP
+.B -v
+Run in active mode only; by default, if
+.B \-a
+is specified,
+.B rpcapd
+it accepts passive connections as well.
+.TP
+.B \-d
+Run in daemon mode (UNIX only) or as a service (Win32 only)
+Warning (Win32): this switch is provided automatically when
+the service is started from the control panel.
+.TP
+.B \-i
+Run in inetd mode (UNIX only).
+.TP
+.B \-D
+Log debugging messages.
+.TP
+.BI \-s " config_file"
+Save the current configuration to
+.I config_file
+in the format specified by
+.BR rpcapd-config (5).
+.TP
+.BI \-f " config_file"
+Load the current configuration from
+.I config_file
+in the format specified by
+.BR rpcapd-config (5);
+all switches specified from the command line are ignored.
+.TP
+.B \-h
+Print this help screen.
+.br
+.ad
+.SH "SEE ALSO"
+pcap(3PCAP), rpcapd-config(5)
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.manadmin.in b/lib/libpcap/libpcap/rpcapd/rpcapd.manadmin.in
new file mode 100644
index 0000000..0a9d4e0
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.manadmin.in
@@ -0,0 +1,233 @@
+.\" rpcapd.8
+.\"
+.\" Copyright (c) 2002-2005 NetGroup, Politecnico di Torino (Italy)
+.\" Copyright (c) 2005-2009 CACE Technologies
+.\" Copyright (c) 2018- The TCPdump Group
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must 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 Politecnico di Torino nor the names 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.
+.\"
+.TH RPCAPD @MAN_ADMIN_COMMANDS@ "April 20, 2018"
+.SH NAME
+rpcapd \- capture daemon to be controlled by a remote libpcap application
+.SH SYNOPSIS
+.na
+rpcapd
+[
+.B \-b
+.I address
+] [
+.B \-p
+.I port
+] [
+.B \-4
+] [
+.B \-l
+.I host_list
+]
+.br
+.ti +8
+[
+.B \-a
+.IR host , port
+] [
+.B \-n
+] [
+.B \-v
+] [
+.B \-d
+] [
+.B \-i
+]
+.br
+.ti +8
+[
+.B \-D
+] [
+.B \-s
+.I config_file
+] [
+.B \-f
+.I config_file
+]
+.br
+.ad
+.SH DESCRIPTION
+.LP
+\fIRpcapd\fP is a daemon (Unix) or service (Win32) that allows the capture
+and filter part of libpcap to be run on a remote system.
+.LP
+Rpcapd can run in two modes: passive mode (default) and active mode.
+.LP
+In passive mode, the client (e.g., a network sniffer) connects to
+.BR rpcapd .
+It then sends hem the appropriate commands to start the capture.
+.LP
+In active mode,
+.B rpcapd
+tries to establish a connection toward the client
+(e.g., a network sniffer). The client then sends the appropriate commands
+to rpcapd to start the capture.
+.LP
+Active mode is useful in case
+.B rpcapd
+is run behind a firewall and
+cannot receive connections from the external world. In this case,
+.B rpcapd
+can be configured to establish the connection to a given host,
+which has to be configured in order to wait for that connection. After
+establishing the connection, the protocol continues its job in almost
+the same way in both active and passive mode.
+.SH Configuration file
+.LP
+The user can create a configuration file in the same folder of the
+executable, and put the configuration commands in there. In order for
+rpcapd to execute the commands, you have to restart it on Win32, i.e.
+the initialization file is parsed only at the beginning). The UNIX
+version of rpcapd will reread the configuration file when receiving a
+HUP signel. In that case, all the existing connections remain in place,
+while the new connections will be created according to the new parameters.
+.LP
+In case a user does not want to create the configuration file manually,
+they can launch rpcapd with the requested parameters plus "-s filename".
+Rpcapd will parse all the parameters and save them into the specified
+configuration file.
+.SH Installing rpcapd on Win32
+.LP
+The remote daemon is installed automatically when installing WinPcap.
+The installation process places the rpcapd file into the WinPcap folder.
+This file can be executed either from the command line, or as a service.
+For instance, the installation process updates the list of available
+services list and it creates a new item (Remote Packet Capture Protocol
+v.0 (experimental) ). To avoid security problems, the service is
+inactive and it has to be started manually (control panel -
+administrative tools - services - start).
+.LP
+The service has a set of "standard" parameters, i.e. it is launched
+with the
+.B \-d
+flag (in order to make it run as a service) and the
+.B "-f rpcapd.ini"
+flag.
+.SH Starting rpcapd on Win32
+.LP
+The rpcapd executable can be launched directly, i.e. it can run in the
+foreground as well (not as a daemon/service). The procedure is quite
+simple: you have to invoke the executable from the command line with all
+the requested parameters except for the
+.B \-d
+flag. The capture server will
+start in the foreground.
+.SH Installing rpcapd on Unix-like systems
+TBD
+.SH Starting rpcapd on Unix-like systems
+.B rpcapd
+needs sufficient privileges to perform packet capture, e.g.
+run as root or be owned by root and have suid set. Most operating
+systems provide more elegant solutions when run as user than the
+above solutions, all of them different.
+.SH OPTIONS
+.TP
+.BI \-b " address"
+Bind to the IP address specified by
+.I address
+(either numeric or literal).
+By default,
+.B rpcapd
+binds to all local IPv4 and IPv6 addresses.
+.TP
+.BI \-p " port"
+Bind to the port specified by
+.IR port .
+By default,
+.B rpcapd
+binds to port 2002.
+.TP
+.B \-4
+Listen only on IPv4 addresses.
+By default,
+.B rpcapd
+listens on both IPv4 and IPv6 addresses.
+.TP
+.BI -l " host_list"
+Only allow hosts specified in the
+.I host_list
+argument to connect to this server.
+.I host_list
+is a list of host names or IP addresses, separated by commas.
+We suggest that you use use host names rather than literal IP addresses
+in order to avoid problems with different address families.
+.TP
+.B \-n
+Permit NULL authentication (usually used with
+.BR \-l ).
+.TP
+.BI \-a " host" , "port"
+Run in active mode, connecting to host
+.I host
+on port
+.IR port .
+In case
+.I port
+is omitted, the default port (2003) is used.
+.TP
+.B -v
+Run in active mode only; by default, if
+.B \-a
+is specified,
+.B rpcapd
+it accepts passive connections as well.
+.TP
+.B \-d
+Run in daemon mode (UNIX only) or as a service (Win32 only)
+Warning (Win32): this switch is provided automatically when
+the service is started from the control panel.
+.TP
+.B \-i
+Run in inetd mode (UNIX only).
+.TP
+.B \-D
+Log debugging messages.
+.TP
+.BI \-s " config_file"
+Save the current configuration to
+.I config_file
+in the format specified by
+.BR rpcapd-config (@MAN_FILE_FORMATS@).
+.TP
+.BI \-f " config_file"
+Load the current configuration from
+.I config_file
+in the format specified by
+.BR rpcapd-config (@MAN_FILE_FORMATS@);
+all switches specified from the command line are ignored.
+.TP
+.B \-h
+Print this help screen.
+.br
+.ad
+.SH "SEE ALSO"
+pcap(3PCAP), rpcapd-config(@MAN_FILE_FORMATS@)
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.rc b/lib/libpcap/libpcap/rpcapd/rpcapd.rc
new file mode 100644
index 0000000..695c00b
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.rc
@@ -0,0 +1,39 @@
+#include "config.h"
+#undef PACKAGE_NAME
+#include <winver.h>
+#include <rpcapd.h>
+#define PACKAGE_NAME PROGRAM_NAME
+
+ VS_VERSION_INFO VERSIONINFO
+ FILEVERSION PACKAGE_VERSION_DLL
+ PRODUCTVERSION PACKAGE_VERSION_DLL
+ FILEFLAGSMASK 0x3fL
+ FILEOS VOS__WINDOWS32
+ FILETYPE VFT_APP
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "040904b0"
+ BEGIN
+ VALUE "Comments", "https://github.com/the-tcpdump-group/libpcap/"
+ VALUE "CompanyName", "The TCPdump Group"
+ VALUE "FileDescription", "Remote Packet Capture Daemon"
+ VALUE "FileVersion", "PACKAGE_VERSION_DLL"
+ VALUE "InternalName", PACKAGE_NAME
+ VALUE "LegalCopyright", "Copyright (c) The TCPdump Group"
+ VALUE "LegalTrademarks", ""
+ VALUE "OriginalFilename", "rpcapd.exe"
+ VALUE "ProductName", PACKAGE_NAME
+ VALUE "ProductVersion", PACKAGE_VERSION
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x0, 1200
+ END
+ END
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.socket b/lib/libpcap/libpcap/rpcapd/rpcapd.socket
new file mode 100644
index 0000000..9d5a0bd
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.socket
@@ -0,0 +1,9 @@
+[Unit]
+Description=Rpcap Socket for Per-Connection Servers
+
+[Socket]
+ListenStream=2002
+Accept=yes
+
+[Install]
+WantedBy=sockets.target
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd.xinetd.conf b/lib/libpcap/libpcap/rpcapd/rpcapd.xinetd.conf
new file mode 100644
index 0000000..2c79348
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd.xinetd.conf
@@ -0,0 +1,8 @@
+service rpcap {
+ socket_type = stream
+ protocol = tcp
+ wait = no
+ user = root
+ server = /usr/local/sbin/rpcapd
+ server_args = -i
+}
diff --git a/lib/libpcap/libpcap/rpcapd/rpcapd@.service b/lib/libpcap/libpcap/rpcapd/rpcapd@.service
new file mode 100644
index 0000000..92d1171
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/rpcapd@.service
@@ -0,0 +1,6 @@
+[Unit]
+Description=Rpcap Per-Connection Server
+
+[Service]
+ExecStart=-/usr/local/sbin/rpcapd -i
+StandardInput=socket
diff --git a/lib/libpcap/libpcap/rpcapd/win32-svc.c b/lib/libpcap/libpcap/rpcapd/win32-svc.c
new file mode 100644
index 0000000..3a19910
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/win32-svc.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+
+#include "rpcapd.h"
+#include <pcap.h> // for PCAP_ERRBUF_SIZE
+#include "fmtutils.h"
+#include "portability.h"
+#include "fileconf.h"
+#include "log.h"
+
+static SERVICE_STATUS_HANDLE service_status_handle;
+static SERVICE_STATUS service_status;
+
+static void WINAPI svc_main(DWORD argc, char **argv);
+static void update_svc_status(DWORD state, DWORD progress_indicator);
+
+int svc_start(void)
+{
+ int rc;
+ SERVICE_TABLE_ENTRY ste[] =
+ {
+ { PROGRAM_NAME, svc_main },
+ { NULL, NULL }
+ };
+ char string[PCAP_ERRBUF_SIZE];
+
+ // This call is blocking. A new thread is created which will launch
+ // the svc_main() function
+ if ((rc = StartServiceCtrlDispatcher(ste)) == 0) {
+ pcap_fmt_errmsg_for_win32_err(string, sizeof (string),
+ GetLastError(), "StartServiceCtrlDispatcher() failed");
+ rpcapd_log(LOGPRIO_ERROR, "%s", string);
+ }
+
+ return rc; // FALSE if this is not started as a service
+}
+
+void WINAPI svc_control_handler(DWORD Opcode)
+{
+ switch(Opcode)
+ {
+ case SERVICE_CONTROL_STOP:
+ //
+ // XXX - is this sufficient to clean up the service?
+ // To be really honest, only the main socket and
+ // such these stuffs are cleared; however the threads
+ // that are running are not stopped.
+ // This can be seen by placing a breakpoint at the
+ // end of svc_main(), in which you will see that is
+ // never reached. However, as soon as you set the
+ // service status to "stopped", the
+ // StartServiceCtrlDispatcher() returns and the main
+ // thread ends. Then, Win32 has a good automatic
+ // cleanup, so that all the threads which are still
+ // running are stopped when the main thread ends.
+ //
+ send_shutdown_notification();
+
+ update_svc_status(SERVICE_STOP_PENDING, 0);
+ break;
+
+ /*
+ Pause and Continue have an usual meaning and they are used just to be able
+ to change the running parameters at run-time. In other words, they act
+ like the SIGHUP signal on UNIX. All the running threads continue to run and
+ they are not paused at all.
+ Particularly,
+ - PAUSE does nothing
+ - CONTINUE re-reads the configuration file and creates the new threads that
+ can be needed according to the new configuration.
+ */
+ case SERVICE_CONTROL_PAUSE:
+ update_svc_status(SERVICE_PAUSED, 0);
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ update_svc_status(SERVICE_RUNNING, 0);
+ //
+ // Tell the main loop to re-read the configuration.
+ //
+ send_reread_configuration_notification();
+ break;
+
+ case SERVICE_CONTROL_INTERROGATE:
+ // Fall through to send current status.
+ // WARNING: not implemented
+ update_svc_status(SERVICE_RUNNING, 0);
+ MessageBox(NULL, "Not implemented", "warning", MB_OK);
+ break;
+
+ case SERVICE_CONTROL_PARAMCHANGE:
+ //
+ // Tell the main loop to re-read the configuration.
+ //
+ send_reread_configuration_notification();
+ break;
+ }
+
+ // Send current status.
+ return;
+}
+
+void WINAPI svc_main(DWORD argc, char **argv)
+{
+ service_status_handle = RegisterServiceCtrlHandler(PROGRAM_NAME, svc_control_handler);
+
+ if (!service_status_handle)
+ return;
+
+ service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS;
+ service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE;
+ // | SERVICE_ACCEPT_SHUTDOWN ;
+ update_svc_status(SERVICE_RUNNING, 0);
+
+ //
+ // Service requests until we're told to stop.
+ //
+ main_startup();
+
+ //
+ // It returned, so we were told to stop.
+ //
+ update_svc_status(SERVICE_STOPPED, 0);
+}
+
+static void
+update_svc_status(DWORD state, DWORD progress_indicator)
+{
+ service_status.dwWin32ExitCode = NO_ERROR;
+ service_status.dwCurrentState = state;
+ service_status.dwCheckPoint = progress_indicator;
+ service_status.dwWaitHint = 0;
+ SetServiceStatus(service_status_handle, &service_status);
+}
+
+/*
+sc create rpcapd DisplayName= "Remote Packet Capture Protocol v.0 (experimental)" binpath= "C:\cvsroot\winpcap\wpcap\PRJ\Debug\rpcapd -d -f rpcapd.ini"
+sc description rpcapd "Allows to capture traffic on this host from a remote machine."
+*/
diff --git a/lib/libpcap/libpcap/rpcapd/win32-svc.h b/lib/libpcap/libpcap/rpcapd/win32-svc.h
new file mode 100644
index 0000000..3f511d2
--- /dev/null
+++ b/lib/libpcap/libpcap/rpcapd/win32-svc.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+int svc_start(void);
diff --git a/lib/libpcap/libpcap/savefile.c b/lib/libpcap/libpcap/savefile.c
new file mode 100644
index 0000000..5204f96
--- /dev/null
+++ b/lib/libpcap/libpcap/savefile.c
@@ -0,0 +1,724 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * savefile.c - supports offline use of tcpdump
+ * Extraction/creation by Jeffrey Mogul, DECWRL
+ * Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif /* _WIN32 */
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h> /* for INT_MAX */
+
+#include "pcap-int.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "sf-pcap.h"
+#include "sf-pcapng.h"
+#include "pcap-common.h"
+
+#ifdef __APPLE__
+static pcap_t *
+pcap_fopen_offline_internal(FILE *fp, u_int precision,
+ char *errbuf, int isng);
+
+#endif /* __APPLE__ */
+
+#ifdef _WIN32
+/*
+ * These aren't exported on Windows, because they would only work if both
+ * WinPcap/Npcap and the code using it were to use the Universal CRT; otherwise,
+ * a FILE structure in WinPcap/Npcap and a FILE structure in the code using it
+ * could be different if they're using different versions of the C runtime.
+ *
+ * Instead, pcap/pcap.h defines them as macros that wrap the hopen versions,
+ * with the wrappers calling _fileno() and _get_osfhandle() themselves,
+ * so that they convert the appropriate CRT version's FILE structure to
+ * a HANDLE (which is OS-defined, not CRT-defined, and is part of the Win32
+ * and Win64 ABIs).
+ */
+static pcap_t *pcap_fopen_offline_with_tstamp_precision(FILE *, u_int, char *);
+static pcap_t *pcap_fopen_offline(FILE *, char *);
+#endif
+
+/*
+ * Setting O_BINARY on DOS/Windows is a bit tricky
+ */
+#if defined(_WIN32)
+ #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY)
+#elif defined(MSDOS)
+ #if defined(__HIGHC__)
+ #define SET_BINMODE(f) setmode(f, O_BINARY)
+ #else
+ #define SET_BINMODE(f) setmode(fileno(f), O_BINARY)
+ #endif
+#endif
+
+static int
+sf_getnonblock(pcap_t *p _U_)
+{
+ /*
+ * This is a savefile, not a live capture file, so never say
+ * it's in non-blocking mode.
+ */
+ return (0);
+}
+
+static int
+sf_setnonblock(pcap_t *p, int nonblock _U_)
+{
+ /*
+ * This is a savefile, not a live capture file, so reject
+ * requests to put it in non-blocking mode. (If it's a
+ * pipe, it could be put in non-blocking mode, but that
+ * would significantly complicate the code to read packets,
+ * as it would have to handle reading partial packets and
+ * keeping the state of the read.)
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Savefiles cannot be put into non-blocking mode");
+ return (-1);
+}
+
+static int
+sf_stats(pcap_t *p, struct pcap_stat *ps _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Statistics aren't available from savefiles");
+ return (-1);
+}
+
+#ifdef _WIN32
+static struct pcap_stat *
+sf_stats_ex(pcap_t *p, int *size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Statistics aren't available from savefiles");
+ return (NULL);
+}
+
+static int
+sf_setbuff(pcap_t *p, int dim)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The kernel buffer size cannot be set while reading from a file");
+ return (-1);
+}
+
+static int
+sf_setmode(pcap_t *p, int mode)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "impossible to set mode while reading from a file");
+ return (-1);
+}
+
+static int
+sf_setmintocopy(pcap_t *p, int size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The mintocopy parameter cannot be set while reading from a file");
+ return (-1);
+}
+
+static HANDLE
+sf_getevent(pcap_t *pcap)
+{
+ (void)pcap_snprintf(pcap->errbuf, sizeof(pcap->errbuf),
+ "The read event cannot be retrieved while reading from a file");
+ return (INVALID_HANDLE_VALUE);
+}
+
+static int
+sf_oid_get_request(pcap_t *p, bpf_u_int32 oid _U_, void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID get request cannot be performed on a file");
+ return (PCAP_ERROR);
+}
+
+static int
+sf_oid_set_request(pcap_t *p, bpf_u_int32 oid _U_, const void *data _U_,
+ size_t *lenp _U_)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "An OID set request cannot be performed on a file");
+ return (PCAP_ERROR);
+}
+
+static u_int
+sf_sendqueue_transmit(pcap_t *p, pcap_send_queue *queue, int sync)
+{
+ pcap_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+ PCAP_ERRBUF_SIZE);
+ return (0);
+}
+
+static int
+sf_setuserbuffer(pcap_t *p, int size)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "The user buffer cannot be set when reading from a file");
+ return (-1);
+}
+
+static int
+sf_live_dump(pcap_t *p, char *filename, int maxsize, int maxpacks)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed when reading from a file");
+ return (-1);
+}
+
+static int
+sf_live_dump_ended(pcap_t *p, int sync)
+{
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "Live packet dumping cannot be performed on a pcap_open_dead pcap_t");
+ return (-1);
+}
+
+static PAirpcapHandle
+sf_get_airpcap_handle(pcap_t *pcap)
+{
+ return (NULL);
+}
+#endif
+
+static int
+sf_inject(pcap_t *p, const void *buf _U_, size_t size _U_)
+{
+ pcap_strlcpy(p->errbuf, "Sending packets isn't supported on savefiles",
+ PCAP_ERRBUF_SIZE);
+ return (-1);
+}
+
+/*
+ * Set direction flag: Which packets do we accept on a forwarding
+ * single device? IN, OUT or both?
+ */
+static int
+sf_setdirection(pcap_t *p, pcap_direction_t d _U_)
+{
+ pcap_snprintf(p->errbuf, sizeof(p->errbuf),
+ "Setting direction is not supported on savefiles");
+ return (-1);
+}
+
+void
+sf_cleanup(pcap_t *p)
+{
+ if (p->rfile != stdin)
+ (void)fclose(p->rfile);
+ if (p->buffer != NULL)
+ free(p->buffer);
+ pcap_freecode(&p->fcode);
+}
+
+pcap_t *
+pcap_open_offline_with_tstamp_precision(const char *fname, u_int precision,
+ char *errbuf)
+{
+ FILE *fp;
+ pcap_t *p;
+
+ if (fname == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "A null pointer was supplied as the file name");
+ return (NULL);
+ }
+ if (fname[0] == '-' && fname[1] == '\0')
+ {
+ fp = stdin;
+#if defined(_WIN32) || defined(MSDOS)
+ /*
+ * We're reading from the standard input, so put it in binary
+ * mode, as savefiles are binary files.
+ */
+ SET_BINMODE(fp);
+#endif
+ }
+ else {
+ /*
+ * "b" is supported as of C90, so *all* UN*Xes should
+ * support it, even though it does nothing. It's
+ * required on Windows, as the file is a binary file
+ * and must be read in binary mode.
+ */
+ fp = fopen(fname, "rb");
+ if (fp == NULL) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s", fname);
+ return (NULL);
+ }
+ }
+ p = pcap_fopen_offline_with_tstamp_precision(fp, precision, errbuf);
+ if (p == NULL) {
+ if (fp != stdin)
+ fclose(fp);
+ }
+ return (p);
+}
+
+pcap_t *
+pcap_open_offline(const char *fname, char *errbuf)
+{
+ return (pcap_open_offline_with_tstamp_precision(fname,
+ PCAP_TSTAMP_PRECISION_MICRO, errbuf));
+}
+
+#ifdef _WIN32
+pcap_t* pcap_hopen_offline_with_tstamp_precision(intptr_t osfd, u_int precision,
+ char *errbuf)
+{
+ int fd;
+ FILE *file;
+
+ fd = _open_osfhandle(osfd, _O_RDONLY);
+ if ( fd < 0 )
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "_open_osfhandle");
+ return NULL;
+ }
+
+ file = _fdopen(fd, "rb");
+ if ( file == NULL )
+ {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "_fdopen");
+ _close(fd);
+ return NULL;
+ }
+
+ return pcap_fopen_offline_with_tstamp_precision(file, precision,
+ errbuf);
+}
+
+pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf)
+{
+ return pcap_hopen_offline_with_tstamp_precision(osfd,
+ PCAP_TSTAMP_PRECISION_MICRO, errbuf);
+}
+#endif
+
+/*
+ * Given a link-layer header type and snapshot length, return a
+ * snapshot length to use when reading the file; it's guaranteed
+ * to be > 0 and <= INT_MAX.
+ *
+ * XXX - the only reason why we limit it to <= INT_MAX is so that
+ * it fits in p->snapshot, and the only reason that p->snapshot is
+ * signed is that pcap_snapshot() returns an int, not an unsigned int.
+ */
+bpf_u_int32
+pcap_adjust_snapshot(bpf_u_int32 linktype, bpf_u_int32 snaplen)
+{
+ if (snaplen == 0 || snaplen > INT_MAX) {
+ /*
+ * Bogus snapshot length; use the maximum for this
+ * link-layer type as a fallback.
+ *
+ * XXX - we don't clamp snapshot lengths that are
+ * <= INT_MAX but > max_snaplen_for_dlt(linktype),
+ * so a capture file could cause us to allocate
+ * a Really Big Buffer.
+ */
+ snaplen = max_snaplen_for_dlt(linktype);
+ }
+ return snaplen;
+}
+
+#if __APPLE__
+static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *, int) = {
+#else
+static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *) = {
+#endif /* __APPLE__ */
+ pcap_check_header,
+ pcap_ng_check_header
+};
+
+#define N_FILE_TYPES (sizeof check_headers / sizeof check_headers[0])
+
+#ifdef _WIN32
+static
+#endif
+pcap_t *
+pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision,
+ char *errbuf)
+{
+#ifdef __APPLE__
+ return pcap_fopen_offline_internal(fp, precision, errbuf, 0);
+}
+
+pcap_t *
+pcap_ng_open_offline(const char *fname, char *errbuf)
+{
+ FILE *fp;
+ pcap_t *p;
+
+ if (fname[0] == '-' && fname[1] == '\0')
+ {
+ fp = stdin;
+#if defined(_WIN32) || defined(MSDOS)
+ /*
+ * We're reading from the standard input, so put it in binary
+ * mode, as savefiles are binary files.
+ */
+ SET_BINMODE(fp);
+#endif
+ }
+ else {
+#if !defined(_WIN32) && !defined(MSDOS)
+ fp = fopen(fname, "r");
+#else
+ fp = fopen(fname, "rb");
+#endif
+ if (fp == NULL) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname,
+ pcap_strerror(errno));
+ return (NULL);
+ }
+ }
+ p = pcap_fopen_offline_internal(fp,
+ PCAP_TSTAMP_PRECISION_MICRO,
+ errbuf, 1);
+ if (p == NULL) {
+ if (fp != stdin)
+ fclose(fp);
+ }
+ return (p);
+}
+
+pcap_t *
+pcap_ng_fopen_offline(FILE *fp, char *errbuf)
+{
+ return pcap_fopen_offline_internal(fp,
+ PCAP_TSTAMP_PRECISION_MICRO,
+ errbuf, 1);
+}
+
+
+static pcap_t *
+pcap_fopen_offline_internal(FILE *fp, u_int precision,
+ char *errbuf, int isng)
+{
+#endif /* __APPLE__ */
+ register pcap_t *p;
+ uint8_t magic[4];
+ size_t amt_read;
+ u_int i;
+ int err;
+#ifdef __APPLE__
+ off_t offset = ftello(fp);
+
+ p = NULL;
+#endif /* __APPLE__ */
+
+ /*
+ * Read the first 4 bytes of the file; the network analyzer dump
+ * file formats we support (pcap and pcapng), and several other
+ * formats we might support in the future (such as snoop, DOS and
+ * Windows Sniffer, and Microsoft Network Monitor) all have magic
+ * numbers that are unique in their first 4 bytes.
+ */
+ amt_read = fread(&magic, 1, sizeof(magic), fp);
+ if (amt_read != sizeof(magic)) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "error reading dump file");
+ } else {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %" PRIsize " file header bytes, only got %" PRIsize,
+ sizeof(magic), amt_read);
+ }
+#ifdef __APPLE__
+ goto bad;
+#else
+ return (NULL);
+#endif /* __APPLE__ */
+ }
+
+#ifdef __APPLE__
+ /*
+ * When using the PCAP-NG extension APIs we are expected a PCAP-NG file
+ */
+ if (isng) {
+ p = pcap_ng_check_header(magic, fp, precision, errbuf, &err, isng);
+ if (p != NULL) {
+ /*
+ * Yup, that's a PCAP-NG file.
+ */
+ goto found;
+ }
+ if (err == 0)
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "not a pcap-ng file");
+ goto bad;
+ }
+#endif /* __APPLE__ */
+
+ /*
+ * Try all file types.
+ */
+ for (i = 0; i < N_FILE_TYPES; i++) {
+#if __APPLE__
+ p = (*check_headers[i])(magic, fp, precision, errbuf, &err, isng);
+#else
+ p = (*check_headers[i])(magic, fp, precision, errbuf, &err);
+#endif /* __APPLE__ */
+ if (p != NULL) {
+ /* Yup, that's it. */
+ goto found;
+ }
+ if (err) {
+ /*
+ * Error trying to read the header.
+ */
+#ifdef __APPLE__
+ goto bad;
+#else
+ return (NULL);
+#endif /* __APPLE__ */
+ }
+ }
+
+ /*
+ * Well, who knows what this mess is....
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "unknown file format");
+#ifdef __APPLE__
+ goto bad;
+#else
+ return (NULL);
+#endif /* __APPLE__ */
+
+found:
+ p->rfile = fp;
+
+ /* Padding only needed for live capture fcode */
+ p->fddipad = 0;
+
+#if !defined(_WIN32) && !defined(MSDOS)
+ /*
+ * You can do "select()" and "poll()" on plain files on most
+ * platforms, and should be able to do so on pipes.
+ *
+ * You can't do "select()" on anything other than sockets in
+ * Windows, so, on Win32 systems, we don't have "selectable_fd".
+ */
+ p->selectable_fd = fileno(fp);
+#endif
+
+#ifdef __APPLE__
+ p->read_op = isng ? pcap_ng_offline_read : pcap_offline_read;
+#else
+ p->read_op = pcap_offline_read;
+#endif /* __APPLE__ */
+ p->inject_op = sf_inject;
+ p->setfilter_op = install_bpf_program;
+ p->setdirection_op = sf_setdirection;
+ p->set_datalink_op = NULL; /* we don't support munging link-layer headers */
+ p->getnonblock_op = sf_getnonblock;
+ p->setnonblock_op = sf_setnonblock;
+ p->stats_op = sf_stats;
+#ifdef _WIN32
+ p->stats_ex_op = sf_stats_ex;
+ p->setbuff_op = sf_setbuff;
+ p->setmode_op = sf_setmode;
+ p->setmintocopy_op = sf_setmintocopy;
+ p->getevent_op = sf_getevent;
+ p->oid_get_request_op = sf_oid_get_request;
+ p->oid_set_request_op = sf_oid_set_request;
+ p->sendqueue_transmit_op = sf_sendqueue_transmit;
+ p->setuserbuffer_op = sf_setuserbuffer;
+ p->live_dump_op = sf_live_dump;
+ p->live_dump_ended_op = sf_live_dump_ended;
+ p->get_airpcap_handle_op = sf_get_airpcap_handle;
+#endif
+
+ /*
+ * For offline captures, the standard one-shot callback can
+ * be used for pcap_next()/pcap_next_ex().
+ */
+ p->oneshot_callback = pcap_oneshot;
+
+ /*
+ * Savefiles never require special BPF code generation.
+ */
+ p->bpf_codegen_flags = 0;
+
+ p->activated = 1;
+
+ return (p);
+
+#ifdef __APPLE__
+ bad:
+ fseeko(fp, offset, SEEK_SET);
+ if (p != NULL)
+ free(p);
+ return (NULL);
+#endif /* __APPLE__ */
+}
+
+#ifdef _WIN32
+static
+#endif
+pcap_t *
+pcap_fopen_offline(FILE *fp, char *errbuf)
+{
+ return (pcap_fopen_offline_with_tstamp_precision(fp,
+ PCAP_TSTAMP_PRECISION_MICRO, errbuf));
+}
+
+/*
+ * Read packets from a capture file, and call the callback for each
+ * packet.
+ * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
+ */
+int
+pcap_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct bpf_insn *fcode;
+ int status = 0;
+ int n = 0;
+ u_char *data;
+
+ while (status == 0) {
+ struct pcap_pkthdr h;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else
+ return (n);
+ }
+
+ status = p->next_packet_op(p, &h, &data);
+ if (status) {
+ if (status == 1)
+ return (0);
+ return (status);
+ }
+
+ if ((fcode = p->fcode.bf_insns) == NULL ||
+ bpf_filter(fcode, data, h.len, h.caplen)) {
+ (*callback)(user, &h, data);
+ if (++n >= cnt && cnt > 0)
+ break;
+ }
+ }
+ /*XXX this breaks semantics tcpslice expects */
+ return (n);
+}
+
+#ifdef __APPLE__
+/*
+ * Read blocks from a capture file, and call the callback for each
+ * packet.
+ * If cnt > 0, return after 'cnt' packets, otherwise continue until eof.
+ */
+int
+pcap_ng_offline_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user)
+{
+ struct bpf_insn *fcode;
+ int status = 0;
+ int n = 0;
+ u_char *data;
+
+ while (status == 0) {
+ struct pcap_pkthdr h;
+
+ /*
+ * Has "pcap_breakloop()" been called?
+ * If so, return immediately - if we haven't read any
+ * packets, clear the flag and return -2 to indicate
+ * that we were told to break out of the loop, otherwise
+ * leave the flag set, so that the *next* call will break
+ * out of the loop without having read any packets, and
+ * return the number of packets we've processed so far.
+ */
+ if (p->break_loop) {
+ if (n == 0) {
+ p->break_loop = 0;
+ return (-2);
+ } else
+ return (n);
+ }
+
+ /*
+ * The begining of the block is always returned into p->buffer
+ * even when data is NULL (because it's not a data block)
+ */
+ status = p->next_packet_op(p, &h, &data);
+ if (status) {
+ if (status == 1)
+ return (0);
+ return (status);
+ }
+
+ /*
+ * TBD
+ * Have one filter per link type
+ */
+ if ((fcode = p->fcode.bf_insns) == NULL ||
+ data == NULL ||
+ bpf_filter(fcode, data, h.len, h.caplen)) {
+ (*callback)(user, &h, p->buffer);
+ if (++n >= cnt && cnt > 0)
+ break;
+ }
+ }
+ /*XXX this breaks semantics tcpslice expects */
+ return (n);
+}
+#endif /* __APPLE__ */
+
diff --git a/lib/libpcap/libpcap/scanner.l b/lib/libpcap/libpcap/scanner.l
new file mode 100644
index 0000000..effcf81
--- /dev/null
+++ b/lib/libpcap/libpcap/scanner.l
@@ -0,0 +1,522 @@
+%top {
+/* Must come first for _LARGE_FILE_API on AIX. */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * Must come first to avoid warnings on Windows.
+ *
+ * Flex-generated scanners may only include <inttypes.h> if __STDC_VERSION__
+ * is defined with a value >= 199901, meaning "full C99", and MSVC may not
+ * define it with that value, because it isn't 100% C99-compliant, even
+ * though it has an <inttypes.h> capable of defining everything the Flex
+ * scanner needs.
+ *
+ * We, however, will include it if we know we have an MSVC version that has
+ * it; this means that we may define the INTn_MAX and UINTn_MAX values in
+ * scanner.c, and then include <stdint.h>, which may define them differently
+ * (same value, but different string of characters), causing compiler warnings.
+ *
+ * If we include it here, and they're defined, that'll prevent scanner.c
+ * from defining them. So we include <pcap/pcap-inttypes.h>, to get
+ * <inttypes.h> if we have it.
+ */
+#include <pcap/pcap-inttypes.h>
+
+#include "diag-control.h"
+}
+
+/*
+ * We want a reentrant scanner.
+ */
+%option reentrant
+
+/*
+ * And we need to pass the compiler state to the scanner.
+ */
+%option extra-type="compiler_state_t *"
+
+/*
+ * We don't use input, so don't generate code for it.
+ */
+%option noinput
+
+/*
+ * We don't use unput, so don't generate code for it.
+ */
+%option nounput
+
+/*
+ * We don't read from the terminal.
+ */
+%option never-interactive
+
+/*
+ * We want to stop processing when we get to the end of the input.
+ */
+%option noyywrap
+
+/*
+ * We want to generate code that can be used by a reentrant parser
+ * generated by Bison or Berkeley YACC.
+ */
+%option bison-bridge
+
+%{
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include <ctype.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include "gencode.h"
+
+#include "grammar.h"
+
+/*
+ * Earlier versions of Flex don't declare these, so we declare them
+ * ourselves to squelch warnings.
+ */
+int pcap_get_column(yyscan_t);
+void pcap_set_column(int, yyscan_t);
+
+#ifdef INET6
+
+#ifdef _WIN32
+#include <winsock2.h>
+#include <ws2tcpip.h>
+/*
+ * To quote the MSDN page for getaddrinfo() at
+ *
+ * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx
+ *
+ * "Support for getaddrinfo on Windows 2000 and older versions
+ * The getaddrinfo function was added to the Ws2_32.dll on Windows XP and
+ * later. To execute an application that uses this function on earlier
+ * versions of Windows, then you need to include the Ws2tcpip.h and
+ * Wspiapi.h files. When the Wspiapi.h include file is added, the
+ * getaddrinfo function is defined to the WspiapiGetAddrInfo inline
+ * function in the Wspiapi.h file. At runtime, the WspiapiGetAddrInfo
+ * function is implemented in such a way that if the Ws2_32.dll or the
+ * Wship6.dll (the file containing getaddrinfo in the IPv6 Technology
+ * Preview for Windows 2000) does not include getaddrinfo, then a
+ * version of getaddrinfo is implemented inline based on code in the
+ * Wspiapi.h header file. This inline code will be used on older Windows
+ * platforms that do not natively support the getaddrinfo function."
+ *
+ * We use getaddrinfo(), so we include Wspiapi.h here.
+ */
+#include <wspiapi.h>
+#else /* _WIN32 */
+#include <sys/socket.h> /* for "struct sockaddr" in "struct addrinfo" */
+#include <netdb.h> /* for "struct addrinfo" */
+#endif /* _WIN32 */
+
+/* Workaround for AIX 4.3 */
+#if !defined(AI_NUMERICHOST)
+#define AI_NUMERICHOST 0x04
+#endif
+
+#endif /*INET6*/
+
+#include <pcap/namedb.h>
+#include "grammar.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+static int stoi(char *);
+static inline int xdtoi(int);
+
+/*
+ * Disable diagnostics in the code generated by Flex.
+ */
+DIAG_OFF_FLEX
+
+%}
+
+N ([0-9]+|(0X|0x)[0-9A-Fa-f]+)
+B ([0-9A-Fa-f][0-9A-Fa-f]?)
+B2 ([0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f])
+W ([0-9A-Fa-f][0-9A-Fa-f]?[0-9A-Fa-f]?[0-9A-Fa-f]?)
+
+%a 18400
+%o 21500
+%e 7600
+%k 4550
+%p 27600
+%n 2000
+
+V680 {W}:{W}:{W}:{W}:{W}:{W}:{W}:{W}
+
+V670 ::{W}:{W}:{W}:{W}:{W}:{W}:{W}
+V671 {W}::{W}:{W}:{W}:{W}:{W}:{W}
+V672 {W}:{W}::{W}:{W}:{W}:{W}:{W}
+V673 {W}:{W}:{W}::{W}:{W}:{W}:{W}
+V674 {W}:{W}:{W}:{W}::{W}:{W}:{W}
+V675 {W}:{W}:{W}:{W}:{W}::{W}:{W}
+V676 {W}:{W}:{W}:{W}:{W}:{W}::{W}
+V677 {W}:{W}:{W}:{W}:{W}:{W}:{W}::
+
+V660 ::{W}:{W}:{W}:{W}:{W}:{W}
+V661 {W}::{W}:{W}:{W}:{W}:{W}
+V662 {W}:{W}::{W}:{W}:{W}:{W}
+V663 {W}:{W}:{W}::{W}:{W}:{W}
+V664 {W}:{W}:{W}:{W}::{W}:{W}
+V665 {W}:{W}:{W}:{W}:{W}::{W}
+V666 {W}:{W}:{W}:{W}:{W}:{W}::
+
+V650 ::{W}:{W}:{W}:{W}:{W}
+V651 {W}::{W}:{W}:{W}:{W}
+V652 {W}:{W}::{W}:{W}:{W}
+V653 {W}:{W}:{W}::{W}:{W}
+V654 {W}:{W}:{W}:{W}::{W}
+V655 {W}:{W}:{W}:{W}:{W}::
+
+V640 ::{W}:{W}:{W}:{W}
+V641 {W}::{W}:{W}:{W}
+V642 {W}:{W}::{W}:{W}
+V643 {W}:{W}:{W}::{W}
+V644 {W}:{W}:{W}:{W}::
+
+V630 ::{W}:{W}:{W}
+V631 {W}::{W}:{W}
+V632 {W}:{W}::{W}
+V633 {W}:{W}:{W}::
+
+V620 ::{W}:{W}
+V621 {W}::{W}
+V622 {W}:{W}::
+
+V610 ::{W}
+V611 {W}::
+
+V600 ::
+
+V6604 {W}:{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+
+V6504 ::{W}:{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6514 {W}::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6524 {W}:{W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6534 {W}:{W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6544 {W}:{W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N}
+V6554 {W}:{W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6404 ::{W}:{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6414 {W}::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6424 {W}:{W}::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6434 {W}:{W}:{W}::{W}:{N}\.{N}\.{N}\.{N}
+V6444 {W}:{W}:{W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6304 ::{W}:{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6314 {W}::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6324 {W}:{W}::{W}:{N}\.{N}\.{N}\.{N}
+V6334 {W}:{W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6204 ::{W}:{W}:{N}\.{N}\.{N}\.{N}
+V6214 {W}::{W}:{N}\.{N}\.{N}\.{N}
+V6224 {W}:{W}::{N}\.{N}\.{N}\.{N}
+
+V6104 ::{W}:{N}\.{N}\.{N}\.{N}
+V6114 {W}::{N}\.{N}\.{N}\.{N}
+
+V6004 ::{N}\.{N}\.{N}\.{N}
+
+
+V6 ({V680}|{V670}|{V671}|{V672}|{V673}|{V674}|{V675}|{V676}|{V677}|{V660}|{V661}|{V662}|{V663}|{V664}|{V665}|{V666}|{V650}|{V651}|{V652}|{V653}|{V654}|{V655}|{V640}|{V641}|{V642}|{V643}|{V644}|{V630}|{V631}|{V632}|{V633}|{V620}|{V621}|{V622}|{V610}|{V611}|{V600}|{V6604}|{V6504}|{V6514}|{V6524}|{V6534}|{V6544}|{V6554}|{V6404}|{V6414}|{V6424}|{V6434}|{V6444}|{V6304}|{V6314}|{V6324}|{V6334}|{V6204}|{V6214}|{V6224}|{V6104}|{V6114}|{V6004})
+
+MAC ({B}:{B}:{B}:{B}:{B}:{B}|{B}\-{B}\-{B}\-{B}\-{B}\-{B}|{B}\.{B}\.{B}\.{B}\.{B}\.{B}|{B2}\.{B2}\.{B2}|{B2}{3})
+
+
+
+%%
+dst return DST;
+src return SRC;
+
+link|ether|ppp|slip return LINK;
+fddi|tr|wlan return LINK;
+arp return ARP;
+rarp return RARP;
+ip return IP;
+sctp return SCTP;
+tcp return TCP;
+udp return UDP;
+icmp return ICMP;
+igmp return IGMP;
+igrp return IGRP;
+pim return PIM;
+vrrp return VRRP;
+carp return CARP;
+radio return RADIO;
+
+ip6 return IPV6;
+icmp6 return ICMPV6;
+ah return AH;
+esp return ESP;
+
+atalk return ATALK;
+aarp return AARP;
+decnet return DECNET;
+lat return LAT;
+sca return SCA;
+moprc return MOPRC;
+mopdl return MOPDL;
+
+iso return ISO;
+esis return ESIS;
+es-is return ESIS;
+isis return ISIS;
+is-is return ISIS;
+l1 return L1;
+l2 return L2;
+iih return IIH;
+lsp return LSP;
+snp return SNP;
+csnp return CSNP;
+psnp return PSNP;
+
+clnp return CLNP;
+
+stp return STP;
+
+ipx return IPX;
+
+netbeui return NETBEUI;
+
+host return HOST;
+net return NET;
+mask return NETMASK;
+port return PORT;
+portrange return PORTRANGE;
+proto return PROTO;
+protochain return PROTOCHAIN;
+
+gateway return GATEWAY;
+
+type return TYPE;
+subtype return SUBTYPE;
+direction|dir return DIR;
+address1|addr1 return ADDR1;
+address2|addr2 return ADDR2;
+address3|addr3 return ADDR3;
+address4|addr4 return ADDR4;
+ra return RA;
+ta return TA;
+
+less return LESS;
+greater return GREATER;
+byte return CBYTE;
+broadcast return TK_BROADCAST;
+multicast return TK_MULTICAST;
+
+and|"&&" return AND;
+or|"||" return OR;
+not return '!';
+
+len|length return LEN;
+inbound return INBOUND;
+outbound return OUTBOUND;
+
+vlan return VLAN;
+mpls return MPLS;
+pppoed return PPPOED;
+pppoes return PPPOES;
+geneve return GENEVE;
+
+lane return LANE;
+llc return LLC;
+metac return METAC;
+bcc return BCC;
+oam return OAM;
+oamf4 return OAMF4;
+oamf4ec return OAMF4EC;
+oamf4sc return OAMF4SC;
+sc return SC;
+ilmic return ILMIC;
+vpi return VPI;
+vci return VCI;
+connectmsg return CONNECTMSG;
+metaconnect return METACONNECT;
+
+on|ifname return PF_IFNAME;
+rset|ruleset return PF_RSET;
+rnr|rulenum return PF_RNR;
+srnr|subrulenum return PF_SRNR;
+reason return PF_REASON;
+action return PF_ACTION;
+
+fisu return FISU;
+lssu return LSSU;
+lsu return LSSU;
+msu return MSU;
+hfisu return HFISU;
+hlssu return HLSSU;
+hmsu return HMSU;
+sio return SIO;
+opc return OPC;
+dpc return DPC;
+sls return SLS;
+hsio return HSIO;
+hopc return HOPC;
+hdpc return HDPC;
+hsls return HSLS;
+
+[ \r\n\t] ;
+[+\-*/%:\[\]!<>()&|\^=] return yytext[0];
+">=" return GEQ;
+"<=" return LEQ;
+"!=" return NEQ;
+"==" return '=';
+"<<" return LSH;
+">>" return RSH;
+${B} { yylval->s = sdup(yyextra, yytext); return AID; }
+{MAC} { yylval->s = sdup(yyextra, yytext); return EID; }
+{N} { yylval->i = stoi((char *)yytext); return NUM; }
+({N}\.{N})|({N}\.{N}\.{N})|({N}\.{N}\.{N}\.{N}) {
+ yylval->s = sdup(yyextra, (char *)yytext); return HID; }
+{V6} {
+#ifdef INET6
+ struct addrinfo hints, *res;
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(yytext, NULL, &hints, &res)) {
+ bpf_set_error(yyextra, "bogus IPv6 address %s", yytext);
+ yylval->s = NULL;
+ } else {
+ freeaddrinfo(res);
+ yylval->s = sdup(yyextra, (char *)yytext);
+ }
+#else
+ bpf_set_error(yyextra, "IPv6 address %s not supported", yytext);
+ yylval->s = NULL;
+#endif /*INET6*/
+ return HID6;
+ }
+{B}:+({B}:+)+ { bpf_set_error(yyextra, "bogus ethernet address %s", yytext); yylval->s = NULL; return EID; }
+icmptype { yylval->i = 0; return NUM; }
+icmpcode { yylval->i = 1; return NUM; }
+icmp-echoreply { yylval->i = 0; return NUM; }
+icmp-unreach { yylval->i = 3; return NUM; }
+icmp-sourcequench { yylval->i = 4; return NUM; }
+icmp-redirect { yylval->i = 5; return NUM; }
+icmp-echo { yylval->i = 8; return NUM; }
+icmp-routeradvert { yylval->i = 9; return NUM; }
+icmp-routersolicit { yylval->i = 10; return NUM; }
+icmp-timxceed { yylval->i = 11; return NUM; }
+icmp-paramprob { yylval->i = 12; return NUM; }
+icmp-tstamp { yylval->i = 13; return NUM; }
+icmp-tstampreply { yylval->i = 14; return NUM; }
+icmp-ireq { yylval->i = 15; return NUM; }
+icmp-ireqreply { yylval->i = 16; return NUM; }
+icmp-maskreq { yylval->i = 17; return NUM; }
+icmp-maskreply { yylval->i = 18; return NUM; }
+
+icmp6type { yylval->i = 0; return NUM; }
+icmp6code { yylval->i = 1; return NUM; }
+
+icmp6-echo { yylval->i = 128; return NUM; }
+icmp6-echoreply { yylval->i = 129; return NUM; }
+icmp6-multicastlistenerquery { yylval->i = 130; return NUM; }
+icmp6-multicastlistenerreportv1 { yylval->i = 131; return NUM; }
+icmp6-multicastlistenerdone { yylval->i = 132; return NUM; }
+icmp6-routersolicit { yylval->i = 133; return NUM; }
+icmp6-routeradvert { yylval->i = 134; return NUM; }
+icmp6-neighborsolicit { yylval->i = 135; return NUM; }
+icmp6-neighboradvert { yylval->i = 136; return NUM; }
+icmp6-redirect { yylval->i = 137; return NUM; }
+icmp6-routerrenum { yylval->i = 138; return NUM; }
+icmp6-nodeinformationquery { yylval->i = 139; return NUM; }
+icmp6-nodeinformationresponse { yylval->i = 140; return NUM; }
+icmp6-ineighbordiscoverysolicit { yylval->i = 141; return NUM; }
+icmp6-ineighbordiscoveryadvert { yylval->i = 142; return NUM; }
+icmp6-multicastlistenerreportv2 { yylval->i = 143; return NUM; }
+icmp6-homeagentdiscoveryrequest { yylval->i = 144; return NUM; }
+icmp6-homeagentdiscoveryreply { yylval->i = 145; return NUM; }
+icmp6-mobileprefixsolicit { yylval->i = 146; return NUM; }
+icmp6-mobileprefixadvert { yylval->i = 147; return NUM; }
+icmp6-certpathsolicit { yylval->i = 148; return NUM; }
+icmp6-certpathadvert { yylval->i = 149; return NUM; }
+icmp6-multicastrouteradvert { yylval->i = 151; return NUM; }
+icmp6-multicastroutersolicit { yylval->i = 152; return NUM; }
+icmp6-multicastrouterterm { yylval->i = 153; return NUM; }
+
+tcpflags { yylval->i = 13; return NUM; }
+tcp-fin { yylval->i = 0x01; return NUM; }
+tcp-syn { yylval->i = 0x02; return NUM; }
+tcp-rst { yylval->i = 0x04; return NUM; }
+tcp-push { yylval->i = 0x08; return NUM; }
+tcp-ack { yylval->i = 0x10; return NUM; }
+tcp-urg { yylval->i = 0x20; return NUM; }
+tcp-ece { yylval->i = 0x40; return NUM; }
+tcp-cwr { yylval->i = 0x80; return NUM; }
+[A-Za-z0-9]([-_.A-Za-z0-9]*[.A-Za-z0-9])? {
+ yylval->s = sdup(yyextra, (char *)yytext); return ID; }
+"\\"[^ !()\n\t]+ { yylval->s = sdup(yyextra, (char *)yytext + 1); return ID; }
+. { return LEX_ERROR; }
+%%
+
+/*
+ * Turn diagnostics back on, so we check the code that we've written.
+ */
+DIAG_ON_FLEX
+
+/* Hex digit to integer. */
+static inline int
+xdtoi(int c)
+{
+ if (isdigit(c))
+ return c - '0';
+ else if (islower(c))
+ return c - 'a' + 10;
+ else
+ return c - 'A' + 10;
+}
+
+/*
+ * Convert string to integer. Just like atoi(), but checks for
+ * preceding 0x or 0 and uses hex or octal instead of decimal.
+ */
+static int
+stoi(char *s)
+{
+ int base = 10;
+ int n = 0;
+
+ if (*s == '0') {
+ if (s[1] == 'x' || s[1] == 'X') {
+ s += 2;
+ base = 16;
+ }
+ else {
+ base = 8;
+ s += 1;
+ }
+ }
+ while (*s)
+ n = n * base + xdtoi(*s++);
+
+ return n;
+}
diff --git a/lib/libpcap/libpcap/sf-pcap.c b/lib/libpcap/libpcap/sf-pcap.c
new file mode 100644
index 0000000..039415e
--- /dev/null
+++ b/lib/libpcap/libpcap/sf-pcap.c
@@ -0,0 +1,1324 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcap.c - libpcap-file-format-specific code from savefile.c
+ * Extraction/creation by Jeffrey Mogul, DECWRL
+ * Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap-types.h>
+#ifdef _WIN32
+#include <io.h>
+#include <fcntl.h>
+#endif /* _WIN32 */
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h> /* for INT_MAX */
+
+#include "pcap-int.h"
+
+#include "pcap-common.h"
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "sf-pcap.h"
+
+#ifdef __APPLE__
+#include <limits.h>
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+#endif /* __APPLE__ */
+
+/*
+ * Setting O_BINARY on DOS/Windows is a bit tricky
+ */
+#if defined(_WIN32)
+ #define SET_BINMODE(f) _setmode(_fileno(f), _O_BINARY)
+#elif defined(MSDOS)
+ #if defined(__HIGHC__)
+ #define SET_BINMODE(f) setmode(f, O_BINARY)
+ #else
+ #define SET_BINMODE(f) setmode(fileno(f), O_BINARY)
+ #endif
+#endif
+
+/*
+ * Standard libpcap format.
+ */
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+/*
+ * Alexey Kuznetzov's modified libpcap format.
+ */
+#define KUZNETZOV_TCPDUMP_MAGIC 0xa1b2cd34
+
+/*
+ * Reserved for Francisco Mesquita <francisco.mesquita@radiomovel.pt>
+ * for another modified format.
+ */
+#define FMESQUITA_TCPDUMP_MAGIC 0xa1b234cd
+
+/*
+ * Navtel Communcations' format, with nanosecond timestamps,
+ * as per a request from Dumas Hwang <dumas.hwang@navtelcom.com>.
+ */
+#define NAVTEL_TCPDUMP_MAGIC 0xa12b3c4d
+
+/*
+ * Normal libpcap format, except for seconds/nanoseconds timestamps,
+ * as per a request by Ulf Lamping <ulf.lamping@web.de>
+ */
+#define NSEC_TCPDUMP_MAGIC 0xa1b23c4d
+
+/*
+ * Mechanism for storing information about a capture in the upper
+ * 6 bits of a linktype value in a capture file.
+ *
+ * LT_LINKTYPE_EXT(x) extracts the additional information.
+ *
+ * The rest of the bits are for a value describing the link-layer
+ * value. LT_LINKTYPE(x) extracts that value.
+ */
+#define LT_LINKTYPE(x) ((x) & 0x03FFFFFF)
+#define LT_LINKTYPE_EXT(x) ((x) & 0xFC000000)
+
+static int pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **datap);
+
+#ifdef _WIN32
+/*
+ * This isn't exported on Windows, because it would only work if both
+ * libpcap and the code using it were using the same C runtime; otherwise they
+ * would be using different definitions of a FILE structure.
+ *
+ * Instead we define this as a macro in pcap/pcap.h that wraps the hopen
+ * version that we do export, passing it a raw OS HANDLE, as defined by the
+ * Win32 / Win64 ABI, obtained from the _fileno() and _get_osfhandle()
+ * functions of the appropriate CRT.
+ */
+static pcap_dumper_t *pcap_dump_fopen(pcap_t *p, FILE *f);
+#endif /* _WIN32 */
+
+/*
+ * Private data for reading pcap savefiles.
+ */
+typedef enum {
+ NOT_SWAPPED,
+ SWAPPED,
+ MAYBE_SWAPPED
+} swapped_type_t;
+
+typedef enum {
+ PASS_THROUGH,
+ SCALE_UP,
+ SCALE_DOWN
+} tstamp_scale_type_t;
+
+struct pcap_sf {
+ size_t hdrsize;
+ swapped_type_t lengths_swapped;
+ tstamp_scale_type_t scale_type;
+};
+
+/*
+ * Check whether this is a pcap savefile and, if it is, extract the
+ * relevant information from the header.
+ */
+#ifdef __APPLE__
+pcap_t *
+pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
+ int *err, int isng)
+#else
+pcap_t *
+pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf,
+ int *err)
+#endif /* __APPLE__ */
+{
+ bpf_u_int32 magic_int;
+ struct pcap_file_header hdr;
+ size_t amt_read;
+ pcap_t *p;
+ int swapped = 0;
+ struct pcap_sf *ps;
+
+ /*
+ * Assume no read errors.
+ */
+ *err = 0;
+
+ /*
+ * Check whether the first 4 bytes of the file are the magic
+ * number for a pcap savefile, or for a byte-swapped pcap
+ * savefile.
+ */
+ memcpy(&magic_int, magic, sizeof(magic_int));
+ if (magic_int != TCPDUMP_MAGIC &&
+ magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
+ magic_int != NSEC_TCPDUMP_MAGIC) {
+ magic_int = SWAPLONG(magic_int);
+ if (magic_int != TCPDUMP_MAGIC &&
+ magic_int != KUZNETZOV_TCPDUMP_MAGIC &&
+ magic_int != NSEC_TCPDUMP_MAGIC)
+ return (NULL); /* nope */
+ swapped = 1;
+ }
+
+ /*
+ * They are. Put the magic number in the header, and read
+ * the rest of the header.
+ */
+ hdr.magic = magic_int;
+ amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1,
+ sizeof(hdr) - sizeof(hdr.magic), fp);
+ if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "error reading dump file");
+ } else {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %" PRIsize " file header bytes, only got %" PRIsize,
+ sizeof(hdr), amt_read);
+ }
+ *err = 1;
+ return (NULL);
+ }
+
+ /*
+ * If it's a byte-swapped capture file, byte-swap the header.
+ */
+ if (swapped) {
+ hdr.version_major = SWAPSHORT(hdr.version_major);
+ hdr.version_minor = SWAPSHORT(hdr.version_minor);
+ hdr.thiszone = SWAPLONG(hdr.thiszone);
+ hdr.sigfigs = SWAPLONG(hdr.sigfigs);
+ hdr.snaplen = SWAPLONG(hdr.snaplen);
+ hdr.linktype = SWAPLONG(hdr.linktype);
+ }
+
+ if (hdr.version_major < PCAP_VERSION_MAJOR) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "archaic pcap savefile format");
+ *err = 1;
+ return (NULL);
+ }
+
+ /*
+ * currently only versions 2.[0-4] are supported with
+ * the exception of 543.0 for DG/UX tcpdump.
+ */
+ if (! ((hdr.version_major == PCAP_VERSION_MAJOR &&
+ hdr.version_minor <= PCAP_VERSION_MINOR) ||
+ (hdr.version_major == 543 &&
+ hdr.version_minor == 0))) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "unsupported pcap savefile version %u.%u",
+ hdr.version_major, hdr.version_minor);
+ *err = 1;
+ return NULL;
+ }
+
+#ifdef __APPLE__
+ if (hdr.snaplen > MAXIMUM_SNAPLEN && hdr.snaplen != INT_MAX &&
+ hdr.snaplen != UINT32_MAX) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "invalid file capture length %u, bigger than "
+ "maximum of %u", hdr.snaplen, MAXIMUM_SNAPLEN);
+ *err = 1;
+ return NULL;
+ }
+#endif /* __APPLE__ */
+
+ /*
+ * OK, this is a good pcap file.
+ * Allocate a pcap_t for it.
+ */
+ p = pcap_open_offline_common(errbuf, sizeof (struct pcap_sf));
+ if (p == NULL) {
+ /* Allocation failed. */
+ *err = 1;
+ return (NULL);
+ }
+ p->swapped = swapped;
+ p->version_major = hdr.version_major;
+ p->version_minor = hdr.version_minor;
+ p->tzoff = hdr.thiszone;
+ p->linktype = linktype_to_dlt(LT_LINKTYPE(hdr.linktype));
+ p->linktype_ext = LT_LINKTYPE_EXT(hdr.linktype);
+ p->snapshot = pcap_adjust_snapshot(p->linktype, hdr.snaplen);
+
+ p->next_packet_op = pcap_next_packet;
+
+ ps = p->priv;
+
+ p->opt.tstamp_precision = precision;
+
+ /*
+ * Will we need to scale the timestamps to match what the
+ * user wants?
+ */
+ switch (precision) {
+
+ case PCAP_TSTAMP_PRECISION_MICRO:
+ if (magic_int == NSEC_TCPDUMP_MAGIC) {
+ /*
+ * The file has nanoseconds, the user
+ * wants microseconds; scale the
+ * precision down.
+ */
+ ps->scale_type = SCALE_DOWN;
+ } else {
+ /*
+ * The file has microseconds, the
+ * user wants microseconds; nothing to do.
+ */
+ ps->scale_type = PASS_THROUGH;
+ }
+ break;
+
+ case PCAP_TSTAMP_PRECISION_NANO:
+ if (magic_int == NSEC_TCPDUMP_MAGIC) {
+ /*
+ * The file has nanoseconds, the
+ * user wants nanoseconds; nothing to do.
+ */
+ ps->scale_type = PASS_THROUGH;
+ } else {
+ /*
+ * The file has microoseconds, the user
+ * wants nanoseconds; scale the
+ * precision up.
+ */
+ ps->scale_type = SCALE_UP;
+ }
+ break;
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "unknown time stamp resolution %u", precision);
+ free(p);
+ *err = 1;
+ return (NULL);
+ }
+
+ /*
+ * We interchanged the caplen and len fields at version 2.3,
+ * in order to match the bpf header layout. But unfortunately
+ * some files were written with version 2.3 in their headers
+ * but without the interchanged fields.
+ *
+ * In addition, DG/UX tcpdump writes out files with a version
+ * number of 543.0, and with the caplen and len fields in the
+ * pre-2.3 order.
+ */
+ switch (hdr.version_major) {
+
+ case 2:
+ if (hdr.version_minor < 3)
+ ps->lengths_swapped = SWAPPED;
+ else if (hdr.version_minor == 3)
+ ps->lengths_swapped = MAYBE_SWAPPED;
+ else
+ ps->lengths_swapped = NOT_SWAPPED;
+ break;
+
+ case 543:
+ ps->lengths_swapped = SWAPPED;
+ break;
+
+ default:
+ ps->lengths_swapped = NOT_SWAPPED;
+ break;
+ }
+
+ if (magic_int == KUZNETZOV_TCPDUMP_MAGIC) {
+ /*
+ * XXX - the patch that's in some versions of libpcap
+ * changes the packet header but not the magic number,
+ * and some other versions with this magic number have
+ * some extra debugging information in the packet header;
+ * we'd have to use some hacks^H^H^H^H^Hheuristics to
+ * detect those variants.
+ *
+ * Ethereal does that, but it does so by trying to read
+ * the first two packets of the file with each of the
+ * record header formats. That currently means it seeks
+ * backwards and retries the reads, which doesn't work
+ * on pipes. We want to be able to read from a pipe, so
+ * that strategy won't work; we'd have to buffer some
+ * data ourselves and read from that buffer in order to
+ * make that work.
+ */
+ ps->hdrsize = sizeof(struct pcap_sf_patched_pkthdr);
+
+ if (p->linktype == DLT_EN10MB) {
+ /*
+ * This capture might have been done in raw mode
+ * or cooked mode.
+ *
+ * If it was done in cooked mode, p->snapshot was
+ * passed to recvfrom() as the buffer size, meaning
+ * that the most packet data that would be copied
+ * would be p->snapshot. However, a faked Ethernet
+ * header would then have been added to it, so the
+ * most data that would be in a packet in the file
+ * would be p->snapshot + 14.
+ *
+ * We can't easily tell whether the capture was done
+ * in raw mode or cooked mode, so we'll assume it was
+ * cooked mode, and add 14 to the snapshot length.
+ * That means that, for a raw capture, the snapshot
+ * length will be misleading if you use it to figure
+ * out why a capture doesn't have all the packet data,
+ * but there's not much we can do to avoid that.
+ *
+ * But don't grow the snapshot length past the
+ * maximum value of an int.
+ */
+ if (p->snapshot <= INT_MAX - 14)
+ p->snapshot += 14;
+ else
+ p->snapshot = INT_MAX;
+ }
+ } else
+ ps->hdrsize = sizeof(struct pcap_sf_pkthdr);
+
+ /*
+ * Allocate a buffer for the packet data.
+ * Choose the minimum of the file's snapshot length and 2K bytes;
+ * that should be enough for most network packets - we'll grow it
+ * if necessary. That way, we don't allocate a huge chunk of
+ * memory just because there's a huge snapshot length, as the
+ * snapshot length might be larger than the size of the largest
+ * packet.
+ */
+ p->bufsize = p->snapshot;
+ if (p->bufsize > 2048)
+ p->bufsize = 2048;
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+ free(p);
+ *err = 1;
+ return (NULL);
+ }
+
+ p->cleanup_op = sf_cleanup;
+
+ return (p);
+}
+
+/*
+ * Grow the packet buffer to the specified size.
+ */
+static int
+grow_buffer(pcap_t *p, u_int bufsize)
+{
+ void *bigger_buffer;
+
+ bigger_buffer = realloc(p->buffer, bufsize);
+ if (bigger_buffer == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+ return (0);
+ }
+ p->buffer = bigger_buffer;
+ p->bufsize = bufsize;
+ return (1);
+}
+
+/*
+ * Read and return the next packet from the savefile. Return the header
+ * in hdr and a pointer to the contents in data. Return 0 on success, 1
+ * if there were no more packets, and -1 on an error.
+ */
+static int
+pcap_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
+{
+ struct pcap_sf *ps = p->priv;
+ struct pcap_sf_patched_pkthdr sf_hdr;
+ FILE *fp = p->rfile;
+ size_t amt_read;
+ bpf_u_int32 t;
+
+ /*
+ * Read the packet header; the structure we use as a buffer
+ * is the longer structure for files generated by the patched
+ * libpcap, but if the file has the magic number for an
+ * unpatched libpcap we only read as many bytes as the regular
+ * header has.
+ */
+ amt_read = fread(&sf_hdr, 1, ps->hdrsize, fp);
+ if (amt_read != ps->hdrsize) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "error reading dump file");
+ return (-1);
+ } else {
+ if (amt_read != 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %" PRIsize " header bytes, only got %" PRIsize,
+ ps->hdrsize, amt_read);
+ return (-1);
+ }
+ /* EOF */
+ return (1);
+ }
+ }
+#ifdef __APPLE__
+ memset(hdr->comment, 0, sizeof(hdr->comment));
+#endif
+
+ if (p->swapped) {
+ /* these were written in opposite byte order */
+ hdr->caplen = SWAPLONG(sf_hdr.caplen);
+ hdr->len = SWAPLONG(sf_hdr.len);
+ hdr->ts.tv_sec = SWAPLONG(sf_hdr.ts.tv_sec);
+ hdr->ts.tv_usec = SWAPLONG(sf_hdr.ts.tv_usec);
+ } else {
+ hdr->caplen = sf_hdr.caplen;
+ hdr->len = sf_hdr.len;
+ hdr->ts.tv_sec = sf_hdr.ts.tv_sec;
+ hdr->ts.tv_usec = sf_hdr.ts.tv_usec;
+ }
+
+ switch (ps->scale_type) {
+
+ case PASS_THROUGH:
+ /*
+ * Just pass the time stamp through.
+ */
+ break;
+
+ case SCALE_UP:
+ /*
+ * File has microseconds, user wants nanoseconds; convert
+ * it.
+ */
+ hdr->ts.tv_usec = hdr->ts.tv_usec * 1000;
+ break;
+
+ case SCALE_DOWN:
+ /*
+ * File has nanoseconds, user wants microseconds; convert
+ * it.
+ */
+ hdr->ts.tv_usec = hdr->ts.tv_usec / 1000;
+ break;
+ }
+
+ /* Swap the caplen and len fields, if necessary. */
+ switch (ps->lengths_swapped) {
+
+ case NOT_SWAPPED:
+ break;
+
+ case MAYBE_SWAPPED:
+ if (hdr->caplen <= hdr->len) {
+ /*
+ * The captured length is <= the actual length,
+ * so presumably they weren't swapped.
+ */
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case SWAPPED:
+ t = hdr->caplen;
+ hdr->caplen = hdr->len;
+ hdr->len = t;
+ break;
+ }
+
+ /*
+ * Is the packet bigger than we consider sane?
+ */
+ if (hdr->caplen > max_snaplen_for_dlt(p->linktype)) {
+ /*
+ * Yes. This may be a damaged or fuzzed file.
+ *
+ * Is it bigger than the snapshot length?
+ * (We don't treat that as an error if it's not
+ * bigger than the maximum we consider sane; see
+ * below.)
+ */
+ if (hdr->caplen > (bpf_u_int32)p->snapshot) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "invalid packet capture length %u, bigger than "
+ "snaplen of %d", hdr->caplen, p->snapshot);
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "invalid packet capture length %u, bigger than "
+ "maximum of %u", hdr->caplen,
+ max_snaplen_for_dlt(p->linktype));
+ }
+ return (-1);
+ }
+
+ if (hdr->caplen > (bpf_u_int32)p->snapshot) {
+ /*
+ * The packet is bigger than the snapshot length
+ * for this file.
+ *
+ * This can happen due to Solaris 2.3 systems tripping
+ * over the BUFMOD problem and not setting the snapshot
+ * length correctly in the savefile header.
+ *
+ * libpcap 0.4 and later on Solaris 2.3 should set the
+ * snapshot length correctly in the pcap file header,
+ * even though they don't set a snapshot length in bufmod
+ * (the buggy bufmod chops off the *beginning* of the
+ * packet if a snapshot length is specified); they should
+ * also reduce the captured length, as supplied to the
+ * per-packet callback, to the snapshot length if it's
+ * greater than the snapshot length, so the code using
+ * libpcap should see the packet cut off at the snapshot
+ * length, even though the full packet is copied up to
+ * userland.
+ *
+ * However, perhaps some versions of libpcap failed to
+ * set the snapshot length currectly in the file header
+ * or the per-packet header, or perhaps this is a
+ * corrupted safefile or a savefile built/modified by a
+ * fuzz tester, so we check anyway. We grow the buffer
+ * to be big enough for the snapshot length, read up
+ * to the snapshot length, discard the rest of the
+ * packet, and report the snapshot length as the captured
+ * length; we don't want to hand our caller a packet
+ * bigger than the snapshot length, because they might
+ * be assuming they'll never be handed such a packet,
+ * and might copy the packet into a snapshot-length-
+ * sized buffer, assuming it'll fit.
+ */
+ size_t bytes_to_discard;
+ size_t bytes_to_read, bytes_read;
+ char discard_buf[4096];
+
+ if (hdr->caplen > p->bufsize) {
+ /*
+ * Grow the buffer to the snapshot length.
+ */
+ if (!grow_buffer(p, p->snapshot))
+ return (-1);
+ }
+
+ /*
+ * Read the first p->snapshot bytes into the buffer.
+ */
+ amt_read = fread(p->buffer, 1, p->snapshot, fp);
+ if (amt_read != (bpf_u_int32)p->snapshot) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "error reading dump file");
+ } else {
+ /*
+ * Yes, this uses hdr->caplen; technically,
+ * it's true, because we would try to read
+ * and discard the rest of those bytes, and
+ * that would fail because we got EOF before
+ * the read finished.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
+ p->snapshot, amt_read);
+ }
+ return (-1);
+ }
+
+ /*
+ * Now read and discard what's left.
+ */
+ bytes_to_discard = hdr->caplen - p->snapshot;
+ bytes_read = amt_read;
+ while (bytes_to_discard != 0) {
+ bytes_to_read = bytes_to_discard;
+ if (bytes_to_read > sizeof (discard_buf))
+ bytes_to_read = sizeof (discard_buf);
+ amt_read = fread(discard_buf, 1, bytes_to_read, fp);
+ bytes_read += amt_read;
+ if (amt_read != bytes_to_read) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "error reading dump file");
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
+ hdr->caplen, bytes_read);
+ }
+ return (-1);
+ }
+ bytes_to_discard -= amt_read;
+ }
+
+ /*
+ * Adjust caplen accordingly, so we don't get confused later
+ * as to how many bytes we have to play with.
+ */
+ hdr->caplen = p->snapshot;
+ } else {
+ /*
+ * The packet is within the snapshot length for this file.
+ */
+ if (hdr->caplen > p->bufsize) {
+ /*
+ * Grow the buffer to the next power of 2, or
+ * the snaplen, whichever is lower.
+ */
+ u_int new_bufsize;
+
+ new_bufsize = hdr->caplen;
+ /*
+ * http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
+ */
+ new_bufsize--;
+ new_bufsize |= new_bufsize >> 1;
+ new_bufsize |= new_bufsize >> 2;
+ new_bufsize |= new_bufsize >> 4;
+ new_bufsize |= new_bufsize >> 8;
+ new_bufsize |= new_bufsize >> 16;
+ new_bufsize++;
+
+ if (new_bufsize > (u_int)p->snapshot)
+ new_bufsize = p->snapshot;
+
+ if (!grow_buffer(p, new_bufsize))
+ return (-1);
+ }
+
+ /* read the packet itself */
+ amt_read = fread(p->buffer, 1, hdr->caplen, fp);
+ if (amt_read != hdr->caplen) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(p->errbuf,
+ PCAP_ERRBUF_SIZE, errno,
+ "error reading dump file");
+ } else {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "truncated dump file; tried to read %u captured bytes, only got %" PRIsize,
+ hdr->caplen, amt_read);
+ }
+ return (-1);
+ }
+ }
+ *data = p->buffer;
+
+ if (p->swapped)
+ swap_pseudo_headers(p->linktype, hdr, *data);
+
+ return (0);
+}
+
+static int
+sf_write_header(pcap_t *p, FILE *fp, int linktype, int thiszone, int snaplen)
+{
+ struct pcap_file_header hdr;
+
+ hdr.magic = p->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? NSEC_TCPDUMP_MAGIC : TCPDUMP_MAGIC;
+ hdr.version_major = PCAP_VERSION_MAJOR;
+ hdr.version_minor = PCAP_VERSION_MINOR;
+
+ hdr.thiszone = thiszone;
+ hdr.snaplen = snaplen;
+ hdr.sigfigs = 0;
+ hdr.linktype = linktype;
+
+ if (fwrite((char *)&hdr, sizeof(hdr), 1, fp) != 1)
+ return (-1);
+
+ return (0);
+}
+
+/*
+ * Output a packet to the initialized dump file.
+ */
+void
+pcap_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+{
+ register FILE *f;
+ struct pcap_sf_pkthdr sf_hdr;
+
+#ifdef __APPLE__
+ f = ((pcap_dumper_t *)user)->f;
+#else
+ f = (FILE *)user;
+#endif /* __APPLE__ */
+ sf_hdr.ts.tv_sec = h->ts.tv_sec;
+ sf_hdr.ts.tv_usec = h->ts.tv_usec;
+ sf_hdr.caplen = h->caplen;
+ sf_hdr.len = h->len;
+ /* XXX we should check the return status */
+ (void)fwrite(&sf_hdr, sizeof(sf_hdr), 1, f);
+ (void)fwrite(sp, h->caplen, 1, f);
+}
+
+#ifdef __APPLE__
+pcap_dumper_t *
+pcap_alloc_dumper(pcap_t *p, FILE *f)
+{
+ pcap_dumper_t *dumper;
+
+ dumper = calloc(1, sizeof(struct pcap_dumper));
+ if (dumper == NULL) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "cannot allocate struct pcap_dumper, error %s",
+ strerror(errno));
+ return (NULL);
+ }
+ dumper->f = f;
+
+ return (dumper);
+}
+#endif /* __APPLE__ */
+
+static pcap_dumper_t *
+pcap_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
+{
+#ifdef __APPLE__
+ pcap_dumper_t *dumper;
+
+ dumper = pcap_alloc_dumper(p, f);
+ if (dumper == NULL)
+ return (NULL);
+#endif /* __APPLE__ */
+
+#if defined(_WIN32) || defined(MSDOS)
+ /*
+ * If we're writing to the standard output, put it in binary
+ * mode, as savefiles are binary files.
+ *
+ * Otherwise, we turn off buffering.
+ * XXX - why? And why not on the standard output?
+ */
+ if (f == stdout)
+ SET_BINMODE(f);
+ else
+ setvbuf(f, NULL, _IONBF, 0);
+#endif
+ if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
+#ifdef __APPLE__
+ free(dumper);
+#endif /* __APPLE__ */
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't write to %s", fname);
+ if (f != stdout)
+ (void)fclose(f);
+ return (NULL);
+ }
+#ifdef __APPLE__
+ return (dumper);
+#else
+ return ((pcap_dumper_t *)f);
+#endif /* __APPLE__ */
+
+}
+
+/*
+ * Initialize so that sf_write() will output to the file named 'fname'.
+ */
+pcap_dumper_t *
+pcap_dump_open(pcap_t *p, const char *fname)
+{
+ FILE *f;
+ int linktype;
+
+ /*
+ * If this pcap_t hasn't been activated, it doesn't have a
+ * link-layer type, so we can't use it.
+ */
+ if (!p->activated) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: not-yet-activated pcap_t passed to pcap_dump_open",
+ fname);
+ return (NULL);
+ }
+ linktype = dlt_to_linktype(p->linktype);
+ if (linktype == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: link-layer type %d isn't supported in savefiles",
+ fname, p->linktype);
+ return (NULL);
+ }
+ linktype |= p->linktype_ext;
+
+ if (fname == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A null pointer was supplied as the file name");
+ return NULL;
+ }
+ if (fname[0] == '-' && fname[1] == '\0') {
+ f = stdout;
+ fname = "standard output";
+ } else {
+ /*
+ * "b" is supported as of C90, so *all* UN*Xes should
+ * support it, even though it does nothing. It's
+ * required on Windows, as the file is a binary file
+ * and must be written in binary mode.
+ */
+ f = fopen(fname, "wb");
+ if (f == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s", fname);
+ return (NULL);
+ }
+ }
+ return (pcap_setup_dump(p, linktype, f, fname));
+}
+
+#ifdef _WIN32
+/*
+ * Initialize so that sf_write() will output to a stream wrapping the given raw
+ * OS file HANDLE.
+ */
+pcap_dumper_t *
+pcap_dump_hopen(pcap_t *p, intptr_t osfd)
+{
+ int fd;
+ FILE *file;
+
+ fd = _open_osfhandle(osfd, _O_APPEND);
+ if (fd < 0) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "_open_osfhandle");
+ return NULL;
+ }
+
+ file = _fdopen(fd, "wb");
+ if (file == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "_fdopen");
+ _close(fd);
+ return NULL;
+ }
+
+ return pcap_dump_fopen(p, file);
+}
+#endif /* _WIN32 */
+
+/*
+ * Initialize so that sf_write() will output to the given stream.
+ */
+#ifdef _WIN32
+static
+#endif /* _WIN32 */
+pcap_dumper_t *
+pcap_dump_fopen(pcap_t *p, FILE *f)
+{
+ int linktype;
+
+ linktype = dlt_to_linktype(p->linktype);
+ if (linktype == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "stream: link-layer type %d isn't supported in savefiles",
+ p->linktype);
+ return (NULL);
+ }
+ linktype |= p->linktype_ext;
+
+ return (pcap_setup_dump(p, linktype, f, "stream"));
+}
+
+pcap_dumper_t *
+pcap_dump_open_append(pcap_t *p, const char *fname)
+{
+ FILE *f;
+ int linktype;
+ size_t amt_read;
+ struct pcap_file_header ph;
+
+ linktype = dlt_to_linktype(p->linktype);
+ if (linktype == -1) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: link-layer type %d isn't supported in savefiles",
+ fname, linktype);
+ return (NULL);
+ }
+
+ if (fname == NULL) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "A null pointer was supplied as the file name");
+ return NULL;
+ }
+ if (fname[0] == '-' && fname[1] == '\0')
+ return (pcap_setup_dump(p, linktype, stdout, "standard output"));
+
+ /*
+ * "a" will cause the file *not* to be truncated if it exists
+ * but will cause it to be created if it doesn't. It will
+ * also cause all writes to be done at the end of the file,
+ * but will allow reads to be done anywhere in the file. This
+ * is what we need, because we need to read from the beginning
+ * of the file to see if it already has a header and packets
+ * or if it doesn't.
+ *
+ * "b" is supported as of C90, so *all* UN*Xes should support it,
+ * even though it does nothing. It's required on Windows, as the
+ * file is a binary file and must be read in binary mode.
+ */
+ f = fopen(fname, "ab+");
+ if (f == NULL) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s", fname);
+ return (NULL);
+ }
+
+#ifdef __APPLE__
+ pcap_dumper_t *dumper;
+
+ dumper = pcap_alloc_dumper(p, f);
+#endif /* __APPLE__ */
+
+ /*
+ * Try to read a pcap header.
+ *
+ * We do not assume that the file will be positioned at the
+ * beginning immediately after we've opened it - we seek to
+ * the beginning. ISO C says it's implementation-defined
+ * whether the file position indicator is at the beginning
+ * or the end of the file after an append-mode open, and
+ * it wasn't obvious from the Single UNIX Specification
+ * or the Microsoft documentation how that works on SUS-
+ * compliant systems or on Windows.
+ */
+ if (fseek(f, 0, SEEK_SET) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't seek to the beginning of %s", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ amt_read = fread(&ph, 1, sizeof (ph), f);
+ if (amt_read != sizeof (ph)) {
+ if (ferror(f)) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "%s", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ } else if (feof(f) && amt_read > 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: truncated pcap file header", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ }
+
+#if defined(_WIN32) || defined(MSDOS)
+ /*
+ * We turn off buffering.
+ * XXX - why? And why not on the standard output?
+ */
+ setvbuf(f, NULL, _IONBF, 0);
+#endif
+
+ /*
+ * If a header is already present and:
+ *
+ * it's not for a pcap file of the appropriate resolution
+ * and the right byte order for this machine;
+ *
+ * the link-layer header types don't match;
+ *
+ * the snapshot lengths don't match;
+ *
+ * return an error.
+ */
+ if (amt_read > 0) {
+ /*
+ * A header is already present.
+ * Do the checks.
+ */
+ switch (ph.magic) {
+
+ case TCPDUMP_MAGIC:
+ if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_MICRO) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different time stamp precision, cannot append to file", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ break;
+
+ case NSEC_TCPDUMP_MAGIC:
+ if (p->opt.tstamp_precision != PCAP_TSTAMP_PRECISION_NANO) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different time stamp precision, cannot append to file", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ break;
+
+ case SWAPLONG(TCPDUMP_MAGIC):
+ case SWAPLONG(NSEC_TCPDUMP_MAGIC):
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different byte order, cannot append to file", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+
+ case KUZNETZOV_TCPDUMP_MAGIC:
+ case SWAPLONG(KUZNETZOV_TCPDUMP_MAGIC):
+ case NAVTEL_TCPDUMP_MAGIC:
+ case SWAPLONG(NAVTEL_TCPDUMP_MAGIC):
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: not a pcap file to which we can append", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+
+ default:
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: not a pcap file", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+
+ /*
+ * Good version?
+ */
+ if (ph.version_major != PCAP_VERSION_MAJOR ||
+ ph.version_minor != PCAP_VERSION_MINOR) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: version is %u.%u, cannot append to file", fname,
+ ph.version_major, ph.version_minor);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ if ((bpf_u_int32)linktype != ph.linktype) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different linktype, cannot append to file", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ if ((bpf_u_int32)p->snapshot != ph.snaplen) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: different snaplen, cannot append to file", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ } else {
+ /*
+ * A header isn't present; attempt to write it.
+ */
+ if (sf_write_header(p, f, linktype, p->tzoff, p->snapshot) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't write to %s", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+ }
+
+ /*
+ * Start writing at the end of the file.
+ *
+ * XXX - this shouldn't be necessary, given that we're opening
+ * the file in append mode, and ISO C specifies that all writes
+ * are done at the end of the file in that mode.
+ */
+ if (fseek(f, 0, SEEK_END) == -1) {
+ pcap_fmt_errmsg_for_errno(p->errbuf, PCAP_ERRBUF_SIZE,
+ errno, "Can't seek to the end of %s", fname);
+#ifdef __APPLE__
+ (void)pcap_dump_close(dumper);
+#else
+ (void)fclose(f);
+#endif /* __APPLE__ */
+ return (NULL);
+ }
+#ifdef __APPLE__
+ return (dumper);
+#else
+ return ((pcap_dumper_t *)f);
+#endif /* __APPLE__ */
+}
+
+FILE *
+pcap_dump_file(pcap_dumper_t *p)
+{
+#ifdef __APPLE__
+ return (p->f);
+#else
+ return ((FILE *)p);
+#endif /* __APPLE__ */
+}
+
+long
+pcap_dump_ftell(pcap_dumper_t *p)
+{
+#ifdef __APPLE__
+ return (ftell(p->f));
+#else
+ return (ftell((FILE *)p));
+#endif /* __APPLE__ */
+}
+
+#if defined(HAVE_FSEEKO)
+/*
+ * We have fseeko(), so we have ftello().
+ * If we have large file support (files larger than 2^31-1 bytes),
+ * ftello() will give us a current file position with more than 32
+ * bits.
+ */
+int64_t
+pcap_dump_ftell64(pcap_dumper_t *p)
+{
+#ifdef __APPLE__
+ return (ftello(p->f));
+#else
+ return (ftello((FILE *)p));
+#endif /* __APPLE__ */
+}
+#elif defined(_MSC_VER)
+/*
+ * We have Visual Studio; we support only 2005 and later, so we have
+ * _ftelli64().
+ */
+int64_t
+pcap_dump_ftell64(pcap_dumper_t *p)
+{
+ return (_ftelli64((FILE *)p));
+}
+#else
+/*
+ * We don't have ftello() or _ftelli64(), so fall back on ftell().
+ * Either long is 64 bits, in which case ftell() should suffice,
+ * or this is probably an older 32-bit UN*X without large file
+ * support, which means you'll probably get errors trying to
+ * write files > 2^31-1, so it won't matter anyway.
+ *
+ * XXX - what about MinGW?
+ */
+int64_t
+pcap_dump_ftell64(pcap_dumper_t *p)
+{
+#ifdef __APPLE__
+ return (ftell(p->f));
+#else
+ return (ftell((FILE *)p));
+#endif /* __APPLE__ */
+}
+#endif
+
+int
+pcap_dump_flush(pcap_dumper_t *p)
+{
+#ifdef __APPLE__
+ if (fflush(p->f) == EOF)
+#else
+ if (fflush((FILE *)p) == EOF)
+#endif
+ return (-1);
+ else
+ return (0);
+}
+
+void
+pcap_dump_close(pcap_dumper_t *p)
+{
+#ifdef __APPLE__
+ if (p == NULL)
+ return;
+
+ if (p->dump_block != NULL) {
+ pcap_ng_free_block(p->dump_block);
+ p->dump_block = NULL;
+ }
+ pcap_if_info_set_clear(&p->dump_if_info_set);
+ pcap_proc_info_set_clear(&p->dump_proc_info_set);
+
+#ifdef notyet
+ if (ferror(p->f))
+ return-an-error;
+ /* XXX should check return from fclose() too */
+#endif
+ (void)fclose(p->f);
+ free(p);
+#else /* __APPLE__ */
+
+#ifdef notyet
+ if (ferror((FILE *)p))
+ return-an-error;
+ /* XXX should check return from fclose() too */
+#endif
+ (void)fclose((FILE *)p);
+
+#endif /* __APPLE__ */
+
+}
diff --git a/lib/libpcap/libpcap/sf-pcap.h b/lib/libpcap/libpcap/sf-pcap.h
new file mode 100644
index 0000000..ba10e1e
--- /dev/null
+++ b/lib/libpcap/libpcap/sf-pcap.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcap.h - libpcap-file-format-specific routines
+ * Extraction/creation by Jeffrey Mogul, DECWRL
+ * Modified by Steve McCanne, LBL.
+ *
+ * Used to save the received packet headers, after filtering, to
+ * a file, and then read them later.
+ * The first record in the file contains saved values for the machine
+ * dependent values so we can print the dump file on any architecture.
+ */
+
+#ifndef sf_pcap_h
+#define sf_pcap_h
+
+#ifdef __APPLE__
+extern pcap_t *pcap_check_header(const uint8_t *magic, FILE *fp,
+u_int precision, char *errbuf, int *err, int isng);
+#else
+extern pcap_t *pcap_check_header(const uint8_t *magic, FILE *fp,
+u_int precision, char *errbuf, int *err);
+#endif /* __APPLE__ */
+
+#endif
diff --git a/lib/libpcap/libpcap/sf-pcapng.c b/lib/libpcap/libpcap/sf-pcapng.c
new file mode 100644
index 0000000..4909447
--- /dev/null
+++ b/lib/libpcap/libpcap/sf-pcapng.c
@@ -0,0 +1,1888 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcapng.c - pcapng-file-format-specific code from savefile.c
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap/pcap-inttypes.h>
+
+#include <errno.h>
+#include <memory.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "pcap-int.h"
+
+#include "pcap-common.h"
+
+#ifdef __APPLE__
+#include "pcap-util.h"
+#include <limits.h>
+
+#ifndef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#endif
+#endif /* __APPLE__ */
+
+#ifdef HAVE_OS_PROTO_H
+#include "os-proto.h"
+#endif
+
+#include "sf-pcapng.h"
+
+/*
+ * Block types.
+ */
+
+/*
+ * Common part at the beginning of all blocks.
+ */
+struct block_header {
+ bpf_u_int32 block_type;
+ bpf_u_int32 total_length;
+};
+
+/*
+ * Common trailer at the end of all blocks.
+ */
+struct block_trailer {
+ bpf_u_int32 total_length;
+};
+
+/*
+ * Common options.
+ */
+#define OPT_ENDOFOPT 0 /* end of options */
+#define OPT_COMMENT 1 /* comment string */
+
+/*
+ * Option header.
+ */
+struct option_header {
+ u_short option_code;
+ u_short option_length;
+};
+
+/*
+ * Structures for the part of each block type following the common
+ * part.
+ */
+
+/*
+ * Section Header Block.
+ */
+#define BT_SHB 0x0A0D0D0A
+#define BT_SHB_INSANE_MAX 1024U*1024U*1U /* 1MB should be enough */
+struct section_header_block {
+ bpf_u_int32 byte_order_magic;
+ u_short major_version;
+ u_short minor_version;
+ uint64_t section_length;
+ /* followed by options and trailer */
+};
+
+/*
+ * Byte-order magic value.
+ */
+#define BYTE_ORDER_MAGIC 0x1A2B3C4D
+
+/*
+ * Current version number. If major_version isn't PCAP_NG_VERSION_MAJOR,
+ * that means that this code can't read the file.
+ */
+#define PCAP_NG_VERSION_MAJOR 1
+#define PCAP_NG_VERSION_MINOR 0
+
+/*
+ * Interface Description Block.
+ */
+#define BT_IDB 0x00000001
+
+struct interface_description_block {
+ u_short linktype;
+ u_short reserved;
+ bpf_u_int32 snaplen;
+ /* followed by options and trailer */
+};
+
+/*
+ * Options in the IDB.
+ */
+#define IF_NAME 2 /* interface name string */
+#define IF_DESCRIPTION 3 /* interface description string */
+#define IF_IPV4ADDR 4 /* interface's IPv4 address and netmask */
+#define IF_IPV6ADDR 5 /* interface's IPv6 address and prefix length */
+#define IF_MACADDR 6 /* interface's MAC address */
+#define IF_EUIADDR 7 /* interface's EUI address */
+#define IF_SPEED 8 /* interface's speed, in bits/s */
+#define IF_TSRESOL 9 /* interface's time stamp resolution */
+#define IF_TZONE 10 /* interface's time zone */
+#define IF_FILTER 11 /* filter used when capturing on interface */
+#define IF_OS 12 /* string OS on which capture on this interface was done */
+#define IF_FCSLEN 13 /* FCS length for this interface */
+#define IF_TSOFFSET 14 /* time stamp offset for this interface */
+
+/*
+ * Enhanced Packet Block.
+ */
+#define BT_EPB 0x00000006
+
+struct enhanced_packet_block {
+ bpf_u_int32 interface_id;
+ bpf_u_int32 timestamp_high;
+ bpf_u_int32 timestamp_low;
+ bpf_u_int32 caplen;
+ bpf_u_int32 len;
+ /* followed by packet data, options, and trailer */
+};
+
+/*
+ * Simple Packet Block.
+ */
+#define BT_SPB 0x00000003
+
+struct simple_packet_block {
+ bpf_u_int32 len;
+ /* followed by packet data and trailer */
+};
+
+/*
+ * Packet Block.
+ */
+#define BT_PB 0x00000002
+
+struct packet_block {
+ u_short interface_id;
+ u_short drops_count;
+ bpf_u_int32 timestamp_high;
+ bpf_u_int32 timestamp_low;
+ bpf_u_int32 caplen;
+ bpf_u_int32 len;
+ /* followed by packet data, options, and trailer */
+};
+
+/*
+ * Block cursor - used when processing the contents of a block.
+ * Contains a pointer into the data being processed and a count
+ * of bytes remaining in the block.
+ */
+struct block_cursor {
+ u_char *data;
+ size_t data_remaining;
+ bpf_u_int32 block_type;
+};
+
+typedef enum {
+ PASS_THROUGH,
+ SCALE_UP_DEC,
+ SCALE_DOWN_DEC,
+ SCALE_UP_BIN,
+ SCALE_DOWN_BIN
+} tstamp_scale_type_t;
+
+/*
+ * Per-interface information.
+ */
+struct pcap_ng_if {
+#ifdef __APPLE__
+ /*
+ * Note:
+ * The code related to snaplen field is taken from master of tcpdump.org
+ * so we will have to remove the __APPLE__ conditionals related to this field
+ * the next time we sync-up with the next RELEASE version from tcpdump.org
+ */
+ uint32_t snaplen; /* snapshot length */
+#endif /* __APPLE__ */
+ uint64_t tsresol; /* time stamp resolution */
+ tstamp_scale_type_t scale_type; /* how to scale */
+ uint64_t scale_factor; /* time stamp scale factor for power-of-10 tsresol */
+ uint64_t tsoffset; /* time stamp offset */
+};
+
+/*
+ * Per-pcap_t private data.
+ *
+ * max_blocksize is the maximum size of a block that we'll accept. We
+ * reject blocks bigger than this, so we don't consume too much memory
+ * with a truly huge block. It can change as we see IDBs with different
+ * link-layer header types. (Currently, we don't support IDBs with
+ * different link-layer header types, but we will support it in the
+ * future, when we offer file-reading APIs that support it.)
+ *
+ * XXX - that's an issue on ILP32 platforms, where the maximum block
+ * size of 2^31-1 would eat all but one byte of the entire address space.
+ * It's less of an issue on ILP64/LLP64 platforms, but the actual size
+ * of the address space may be limited by 1) the number of *significant*
+ * address bits (currently, x86-64 only supports 48 bits of address), 2)
+ * any limitations imposed by the operating system; 3) any limitations
+ * imposed by the amount of available backing store for anonymous pages,
+ * so we impose a limit regardless of the size of a pointer.
+ */
+struct pcap_ng_sf {
+ uint64_t user_tsresol; /* time stamp resolution requested by the user */
+ u_int max_blocksize; /* don't grow buffer size past this */
+ bpf_u_int32 ifcount; /* number of interfaces seen in this capture */
+ bpf_u_int32 ifaces_size; /* size of array below */
+ struct pcap_ng_if *ifaces; /* array of interface information */
+};
+
+/*
+ * The maximum block size we start with; we use an arbitrary value of
+ * 16 MiB.
+ */
+#define INITIAL_MAX_BLOCKSIZE (16*1024*1024)
+
+/*
+ * Maximum block size for a given maximum snapshot length; we define it
+ * as the size of an EPB with a max_snaplen-sized packet and 128KB of
+ * options.
+ */
+#define MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen) \
+ (sizeof (struct block_header) + \
+ sizeof (struct enhanced_packet_block) + \
+ (max_snaplen) + 131072 + \
+ sizeof (struct block_trailer))
+
+#ifdef __APPLE__
+static int pcap_ng_next_block(pcap_t *p, struct pcap_pkthdr *hdr,
+ u_char **data);
+static int pcap_ng_next_internal(pcap_t *p, struct pcap_pkthdr *hdr,
+ u_char **data, int pktonly);
+void pcap_ng_cleanup(pcap_t *p);
+#else
+static void pcap_ng_cleanup(pcap_t *p);
+#endif /* __APPLE__ */
+
+static int pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr,
+ u_char **data);
+
+static int
+read_bytes(FILE *fp, void *buf, size_t bytes_to_read, int fail_on_eof,
+ char *errbuf)
+{
+ size_t amt_read;
+
+ amt_read = fread(buf, 1, bytes_to_read, fp);
+ if (amt_read != bytes_to_read) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "error reading dump file");
+ } else {
+ if (amt_read == 0 && !fail_on_eof)
+ return (0); /* EOF */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "truncated pcapng dump file; tried to read %" PRIsize " bytes, only got %" PRIsize,
+ bytes_to_read, amt_read);
+ }
+ return (-1);
+ }
+ return (1);
+}
+
+static int
+read_block(FILE *fp, pcap_t *p, struct block_cursor *cursor, char *errbuf)
+{
+ struct pcap_ng_sf *ps;
+ int status;
+ struct block_header bhdr;
+ struct block_trailer *btrlr;
+ u_char *bdata;
+ size_t data_remaining;
+
+ ps = p->priv;
+
+ status = read_bytes(fp, &bhdr, sizeof(bhdr), 0, errbuf);
+ if (status <= 0)
+ return (status); /* error or EOF */
+
+ if (p->swapped) {
+ bhdr.block_type = SWAPLONG(bhdr.block_type);
+ bhdr.total_length = SWAPLONG(bhdr.total_length);
+ }
+
+ /*
+ * Is this block "too small" - i.e., is it shorter than a block
+ * header plus a block trailer?
+ */
+ if (bhdr.total_length < sizeof(struct block_header) +
+ sizeof(struct block_trailer)) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "block in pcapng dump file has a length of %u < %" PRIsize,
+ bhdr.total_length,
+ sizeof(struct block_header) + sizeof(struct block_trailer));
+ return (-1);
+ }
+
+ /*
+ * Is the block total length a multiple of 4?
+ */
+ if ((bhdr.total_length % 4) != 0) {
+ /*
+ * No. Report that as an error.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "block in pcapng dump file has a length of %u that is not a multiple of 4" PRIsize,
+ bhdr.total_length);
+ return (-1);
+ }
+
+ /*
+ * Is the buffer big enough?
+ */
+ if (p->bufsize < bhdr.total_length) {
+ /*
+ * No - make it big enough, unless it's too big, in
+ * which case we fail.
+ */
+ void *bigger_buffer;
+
+ if (bhdr.total_length > ps->max_blocksize) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "pcapng block size %u > maximum %u", bhdr.total_length,
+ ps->max_blocksize);
+ return (-1);
+ }
+ bigger_buffer = realloc(p->buffer, bhdr.total_length);
+ if (bigger_buffer == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+ return (-1);
+ }
+ p->buffer = bigger_buffer;
+ }
+
+ /*
+ * Copy the stuff we've read to the buffer, and read the rest
+ * of the block.
+ */
+ memcpy(p->buffer, &bhdr, sizeof(bhdr));
+ bdata = (u_char *)p->buffer + sizeof(bhdr);
+ data_remaining = bhdr.total_length - sizeof(bhdr);
+ if (read_bytes(fp, bdata, data_remaining, 1, errbuf) == -1)
+ return (-1);
+
+ /*
+ * Get the block size from the trailer.
+ */
+ btrlr = (struct block_trailer *)(bdata + data_remaining - sizeof (struct block_trailer));
+ if (p->swapped)
+ btrlr->total_length = SWAPLONG(btrlr->total_length);
+
+ /*
+ * Is the total length from the trailer the same as the total
+ * length from the header?
+ */
+ if (bhdr.total_length != btrlr->total_length) {
+ /*
+ * No.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "block total length in header and trailer don't match");
+ return (-1);
+ }
+
+ /*
+ * Initialize the cursor.
+ */
+ cursor->data = bdata;
+ cursor->data_remaining = data_remaining - sizeof(struct block_trailer);
+ cursor->block_type = bhdr.block_type;
+ return (1);
+}
+
+#ifdef __APPLE__
+void *
+#else
+static void *
+#endif /* __APPLE__ */
+get_from_block_data(struct block_cursor *cursor, size_t chunk_size,
+ char *errbuf)
+{
+ void *data;
+
+ /*
+ * Make sure we have the specified amount of data remaining in
+ * the block data.
+ */
+ if (cursor->data_remaining < chunk_size) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "block of type %u in pcapng dump file is too short",
+ cursor->block_type);
+ return (NULL);
+ }
+
+ /*
+ * Return the current pointer, and skip past the chunk.
+ */
+ data = cursor->data;
+ cursor->data += chunk_size;
+ cursor->data_remaining -= chunk_size;
+ return (data);
+}
+
+static struct option_header *
+get_opthdr_from_block_data(pcap_t *p, struct block_cursor *cursor, char *errbuf)
+{
+ struct option_header *opthdr;
+
+ opthdr = get_from_block_data(cursor, sizeof(*opthdr), errbuf);
+ if (opthdr == NULL) {
+ /*
+ * Option header is cut short.
+ */
+ return (NULL);
+ }
+
+ /*
+ * Byte-swap it if necessary.
+ */
+ if (p->swapped) {
+ opthdr->option_code = SWAPSHORT(opthdr->option_code);
+ opthdr->option_length = SWAPSHORT(opthdr->option_length);
+ }
+
+ return (opthdr);
+}
+
+static void *
+get_optvalue_from_block_data(struct block_cursor *cursor,
+ struct option_header *opthdr, char *errbuf)
+{
+ size_t padded_option_len;
+ void *optvalue;
+
+ /* Pad option length to 4-byte boundary */
+ padded_option_len = opthdr->option_length;
+ padded_option_len = ((padded_option_len + 3)/4)*4;
+
+ optvalue = get_from_block_data(cursor, padded_option_len, errbuf);
+ if (optvalue == NULL) {
+ /*
+ * Option value is cut short.
+ */
+ return (NULL);
+ }
+
+ return (optvalue);
+}
+
+static int
+process_idb_options(pcap_t *p, struct block_cursor *cursor, uint64_t *tsresol,
+ uint64_t *tsoffset, int *is_binary, char *errbuf)
+{
+ struct option_header *opthdr;
+ void *optvalue;
+ int saw_tsresol, saw_tsoffset;
+ uint8_t tsresol_opt;
+ u_int i;
+
+ saw_tsresol = 0;
+ saw_tsoffset = 0;
+ while (cursor->data_remaining != 0) {
+ /*
+ * Get the option header.
+ */
+ opthdr = get_opthdr_from_block_data(p, cursor, errbuf);
+ if (opthdr == NULL) {
+ /*
+ * Option header is cut short.
+ */
+ return (-1);
+ }
+
+ /*
+ * Get option value.
+ */
+ optvalue = get_optvalue_from_block_data(cursor, opthdr,
+ errbuf);
+ if (optvalue == NULL) {
+ /*
+ * Option value is cut short.
+ */
+ return (-1);
+ }
+
+ switch (opthdr->option_code) {
+
+ case OPT_ENDOFOPT:
+ if (opthdr->option_length != 0) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Interface Description Block has opt_endofopt option with length %u != 0",
+ opthdr->option_length);
+ return (-1);
+ }
+ goto done;
+
+ case IF_TSRESOL:
+ if (opthdr->option_length != 1) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Interface Description Block has if_tsresol option with length %u != 1",
+ opthdr->option_length);
+ return (-1);
+ }
+ if (saw_tsresol) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Interface Description Block has more than one if_tsresol option");
+ return (-1);
+ }
+ saw_tsresol = 1;
+ memcpy(&tsresol_opt, optvalue, sizeof(tsresol_opt));
+ if (tsresol_opt & 0x80) {
+ /*
+ * Resolution is negative power of 2.
+ */
+ uint8_t tsresol_shift = (tsresol_opt & 0x7F);
+
+ if (tsresol_shift > 63) {
+ /*
+ * Resolution is too high; 2^-{res}
+ * won't fit in a 64-bit value.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Interface Description Block if_tsresol option resolution 2^-%u is too high",
+ tsresol_shift);
+ return (-1);
+ }
+ *is_binary = 1;
+ *tsresol = ((uint64_t)1) << tsresol_shift;
+ } else {
+ /*
+ * Resolution is negative power of 10.
+ */
+ if (tsresol_opt > 19) {
+ /*
+ * Resolution is too high; 2^-{res}
+ * won't fit in a 64-bit value (the
+ * largest power of 10 that fits
+ * in a 64-bit value is 10^19, as
+ * the largest 64-bit unsigned
+ * value is ~1.8*10^19).
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Interface Description Block if_tsresol option resolution 10^-%u is too high",
+ tsresol_opt);
+ return (-1);
+ }
+ *is_binary = 0;
+ *tsresol = 1;
+ for (i = 0; i < tsresol_opt; i++)
+ *tsresol *= 10;
+ }
+ break;
+
+ case IF_TSOFFSET:
+ if (opthdr->option_length != 8) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Interface Description Block has if_tsoffset option with length %u != 8",
+ opthdr->option_length);
+ return (-1);
+ }
+ if (saw_tsoffset) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Interface Description Block has more than one if_tsoffset option");
+ return (-1);
+ }
+ saw_tsoffset = 1;
+ memcpy(tsoffset, optvalue, sizeof(*tsoffset));
+ if (p->swapped)
+ *tsoffset = SWAPLL(*tsoffset);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+done:
+ return (0);
+}
+
+static int
+#ifdef __APPLE__
+add_interface(pcap_t *p, struct interface_description_block *idbp,
+ struct block_cursor *cursor, char *errbuf)
+#else
+add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf)
+#endif /* __APPLE__ */
+{
+ struct pcap_ng_sf *ps;
+ uint64_t tsresol;
+ uint64_t tsoffset;
+ int is_binary;
+
+ ps = p->priv;
+
+ /*
+ * Count this interface.
+ */
+ ps->ifcount++;
+
+ /*
+ * Grow the array of per-interface information as necessary.
+ */
+ if (ps->ifcount > ps->ifaces_size) {
+ /*
+ * We need to grow the array.
+ */
+ bpf_u_int32 new_ifaces_size;
+ struct pcap_ng_if *new_ifaces;
+
+ if (ps->ifaces_size == 0) {
+ /*
+ * It's currently empty.
+ *
+ * (The Clang static analyzer doesn't do enough,
+ * err, umm, dataflow *analysis* to realize that
+ * ps->ifaces_size == 0 if ps->ifaces == NULL,
+ * and so complains about a possible zero argument
+ * to realloc(), so we check for the former
+ * condition to shut it up.
+ *
+ * However, it doesn't complain that one of the
+ * multiplications below could overflow, which is
+ * a real, albeit extremely unlikely, problem (you'd
+ * need a pcapng file with tens of millions of
+ * interfaces).)
+ */
+ new_ifaces_size = 1;
+ new_ifaces = malloc(sizeof (struct pcap_ng_if));
+ } else {
+ /*
+ * It's not currently empty; double its size.
+ * (Perhaps overkill once we have a lot of interfaces.)
+ *
+ * Check for overflow if we double it.
+ */
+ if (ps->ifaces_size * 2 < ps->ifaces_size) {
+ /*
+ * The maximum number of interfaces before
+ * ps->ifaces_size overflows is the largest
+ * possible 32-bit power of 2, as we do
+ * size doubling.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "more than %u interfaces in the file",
+ 0x80000000U);
+ return (0);
+ }
+
+ /*
+ * ps->ifaces_size * 2 doesn't overflow, so it's
+ * safe to multiply.
+ */
+ new_ifaces_size = ps->ifaces_size * 2;
+
+ /*
+ * Now make sure that's not so big that it overflows
+ * if we multiply by sizeof (struct pcap_ng_if).
+ *
+ * That can happen on 32-bit platforms, with a 32-bit
+ * size_t; it shouldn't happen on 64-bit platforms,
+ * with a 64-bit size_t, as new_ifaces_size is
+ * 32 bits.
+ */
+ if (new_ifaces_size * sizeof (struct pcap_ng_if) < new_ifaces_size) {
+ /*
+ * As this fails only with 32-bit size_t,
+ * the multiplication was 32x32->32, and
+ * the largest 32-bit value that can safely
+ * be multiplied by sizeof (struct pcap_ng_if)
+ * without overflow is the largest 32-bit
+ * (unsigned) value divided by
+ * sizeof (struct pcap_ng_if).
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "more than %u interfaces in the file",
+ 0xFFFFFFFFU / ((u_int)sizeof (struct pcap_ng_if)));
+ return (0);
+ }
+ new_ifaces = realloc(ps->ifaces, new_ifaces_size * sizeof (struct pcap_ng_if));
+ }
+ if (new_ifaces == NULL) {
+ /*
+ * We ran out of memory.
+ * Give up.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "out of memory for per-interface information (%u interfaces)",
+ ps->ifcount);
+ return (0);
+ }
+ ps->ifaces_size = new_ifaces_size;
+ ps->ifaces = new_ifaces;
+ }
+
+#ifdef __APPLE__
+ ps->ifaces[ps->ifcount - 1].snaplen = idbp->snaplen;
+#endif /* __APPLE__*/
+
+ /*
+ * Set the default time stamp resolution and offset.
+ */
+ tsresol = 1000000; /* microsecond resolution */
+ is_binary = 0; /* which is a power of 10 */
+ tsoffset = 0; /* absolute timestamps */
+
+ /*
+ * Now look for various time stamp options, so we know
+ * how to interpret the time stamps for this interface.
+ */
+ if (process_idb_options(p, cursor, &tsresol, &tsoffset, &is_binary,
+ errbuf) == -1)
+ return (0);
+
+ ps->ifaces[ps->ifcount - 1].tsresol = tsresol;
+ ps->ifaces[ps->ifcount - 1].tsoffset = tsoffset;
+
+ /*
+ * Determine whether we're scaling up or down or not
+ * at all for this interface.
+ */
+ if (tsresol == ps->user_tsresol) {
+ /*
+ * The resolution is the resolution the user wants,
+ * so we don't have to do scaling.
+ */
+ ps->ifaces[ps->ifcount - 1].scale_type = PASS_THROUGH;
+ } else if (tsresol > ps->user_tsresol) {
+ /*
+ * The resolution is greater than what the user wants,
+ * so we have to scale the timestamps down.
+ */
+ if (is_binary)
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_BIN;
+ else {
+ /*
+ * Calculate the scale factor.
+ */
+ ps->ifaces[ps->ifcount - 1].scale_factor = tsresol/ps->user_tsresol;
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_DOWN_DEC;
+ }
+ } else {
+ /*
+ * The resolution is less than what the user wants,
+ * so we have to scale the timestamps up.
+ */
+ if (is_binary)
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_BIN;
+ else {
+ /*
+ * Calculate the scale factor.
+ */
+ ps->ifaces[ps->ifcount - 1].scale_factor = ps->user_tsresol/tsresol;
+ ps->ifaces[ps->ifcount - 1].scale_type = SCALE_UP_DEC;
+ }
+ }
+ return (1);
+}
+
+/*
+ * Check whether this is a pcapng savefile and, if it is, extract the
+ * relevant information from the header.
+ */
+#ifdef __APPLE__
+pcap_t *
+pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
+ char *errbuf, int *err, int isng)
+#else
+pcap_t *
+pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision,
+ char *errbuf, int *err)
+#endif /* __APPLE__ */
+{
+ bpf_u_int32 magic_int;
+ size_t amt_read;
+ bpf_u_int32 total_length;
+ bpf_u_int32 byte_order_magic;
+ struct block_header *bhdrp;
+ struct section_header_block *shbp;
+ pcap_t *p;
+ int swapped = 0;
+ struct pcap_ng_sf *ps;
+ int status;
+ struct block_cursor cursor;
+#ifdef __APPLE__
+ struct interface_description_block *idbp = NULL;
+ long file_offset = ftell(fp);
+#else
+ struct interface_description_block *idbp;
+#endif /* __APPLE__ */
+ /*
+ * Assume no read errors.
+ */
+ *err = 0;
+
+ /*
+ * Check whether the first 4 bytes of the file are the block
+ * type for a pcapng savefile.
+ */
+ memcpy(&magic_int, magic, sizeof(magic_int));
+ if (magic_int != BT_SHB) {
+ /*
+ * XXX - check whether this looks like what the block
+ * type would be after being munged by mapping between
+ * UN*X and DOS/Windows text file format and, if it
+ * does, look for the byte-order magic number in
+ * the appropriate place and, if we find it, report
+ * this as possibly being a pcapng file transferred
+ * between UN*X and Windows in text file format?
+ */
+ return (NULL); /* nope */
+ }
+
+ /*
+ * OK, they are. However, that's just \n\r\r\n, so it could,
+ * conceivably, be an ordinary text file.
+ *
+ * It could not, however, conceivably be any other type of
+ * capture file, so we can read the rest of the putative
+ * Section Header Block; put the block type in the common
+ * header, read the rest of the common header and the
+ * fixed-length portion of the SHB, and look for the byte-order
+ * magic value.
+ */
+ amt_read = fread(&total_length, 1, sizeof(total_length), fp);
+ if (amt_read < sizeof(total_length)) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "error reading dump file");
+ *err = 1;
+ return (NULL); /* fail */
+ }
+
+ /*
+ * Possibly a weird short text file, so just say
+ * "not pcapng".
+ */
+ return (NULL);
+ }
+ amt_read = fread(&byte_order_magic, 1, sizeof(byte_order_magic), fp);
+ if (amt_read < sizeof(byte_order_magic)) {
+ if (ferror(fp)) {
+ pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
+ errno, "error reading dump file");
+ *err = 1;
+ return (NULL); /* fail */
+ }
+
+ /*
+ * Possibly a weird short text file, so just say
+ * "not pcapng".
+ */
+ return (NULL);
+ }
+ if (byte_order_magic != BYTE_ORDER_MAGIC) {
+ byte_order_magic = SWAPLONG(byte_order_magic);
+ if (byte_order_magic != BYTE_ORDER_MAGIC) {
+ /*
+ * Not a pcapng file.
+ */
+ return (NULL);
+ }
+ swapped = 1;
+ total_length = SWAPLONG(total_length);
+ }
+
+ /*
+ * Check the sanity of the total length.
+ */
+ if (total_length < sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer) ||
+ (total_length > BT_SHB_INSANE_MAX)) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "Section Header Block in pcapng dump file has invalid length %" PRIsize " < _%u_ < %u (BT_SHB_INSANE_MAX)",
+ sizeof(*bhdrp) + sizeof(*shbp) + sizeof(struct block_trailer),
+ total_length,
+ BT_SHB_INSANE_MAX);
+
+ *err = 1;
+ return (NULL);
+ }
+
+ /*
+ * OK, this is a good pcapng file.
+ * Allocate a pcap_t for it.
+ */
+ p = pcap_open_offline_common(errbuf, sizeof (struct pcap_ng_sf));
+ if (p == NULL) {
+ /* Allocation failed. */
+ *err = 1;
+ return (NULL);
+ }
+ p->swapped = swapped;
+ ps = p->priv;
+
+ /*
+ * What precision does the user want?
+ */
+ switch (precision) {
+
+ case PCAP_TSTAMP_PRECISION_MICRO:
+ ps->user_tsresol = 1000000;
+ break;
+
+ case PCAP_TSTAMP_PRECISION_NANO:
+ ps->user_tsresol = 1000000000;
+ break;
+
+ default:
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "unknown time stamp resolution %u", precision);
+ free(p);
+ *err = 1;
+ return (NULL);
+ }
+
+ p->opt.tstamp_precision = precision;
+
+ /*
+ * Allocate a buffer into which to read blocks. We default to
+ * the maximum of:
+ *
+ * the total length of the SHB for which we read the header;
+ *
+ * 2K, which should be more than large enough for an Enhanced
+ * Packet Block containing a full-size Ethernet frame, and
+ * leaving room for some options.
+ *
+ * If we find a bigger block, we reallocate the buffer, up to
+ * the maximum size. We start out with a maximum size of
+ * INITIAL_MAX_BLOCKSIZE; if we see any link-layer header types
+ * with a maximum snapshot that results in a larger maximum
+ * block length, we boost the maximum.
+ */
+ p->bufsize = 2048;
+ if (p->bufsize < total_length)
+ p->bufsize = total_length;
+ p->buffer = malloc(p->bufsize);
+ if (p->buffer == NULL) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, "out of memory");
+ free(p);
+ *err = 1;
+ return (NULL);
+ }
+ ps->max_blocksize = INITIAL_MAX_BLOCKSIZE;
+
+ /*
+ * Copy the stuff we've read to the buffer, and read the rest
+ * of the SHB.
+ */
+ bhdrp = (struct block_header *)p->buffer;
+ shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header));
+ bhdrp->block_type = magic_int;
+ bhdrp->total_length = total_length;
+ shbp->byte_order_magic = byte_order_magic;
+ if (read_bytes(fp,
+ (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
+ total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)),
+ 1, errbuf) == -1)
+ goto fail;
+
+ if (p->swapped) {
+ /*
+ * Byte-swap the fields we've read.
+ */
+ shbp->major_version = SWAPSHORT(shbp->major_version);
+ shbp->minor_version = SWAPSHORT(shbp->minor_version);
+
+ /*
+ * XXX - we don't care about the section length.
+ */
+ }
+ /* currently only SHB version 1.0 is supported */
+ if (! (shbp->major_version == PCAP_NG_VERSION_MAJOR &&
+ shbp->minor_version == PCAP_NG_VERSION_MINOR)) {
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "unsupported pcapng savefile version %u.%u",
+ shbp->major_version, shbp->minor_version);
+ goto fail;
+ }
+ p->version_major = shbp->major_version;
+ p->version_minor = shbp->minor_version;
+
+ /*
+ * Save the time stamp resolution the user requested.
+ */
+ p->opt.tstamp_precision = precision;
+
+ /*
+ * Now start looking for an Interface Description Block.
+ */
+ for (;;) {
+ /*
+ * Read the next block.
+ */
+ status = read_block(fp, p, &cursor, errbuf);
+ if (status == 0) {
+ /* EOF - no IDB in this file */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "the capture file has no Interface Description Blocks");
+ goto fail;
+ }
+ if (status == -1)
+ goto fail; /* error */
+ switch (cursor.block_type) {
+
+ case BT_IDB:
+ /*
+ * Get a pointer to the fixed-length portion of the
+ * IDB.
+ */
+ idbp = get_from_block_data(&cursor, sizeof(*idbp),
+ errbuf);
+ if (idbp == NULL)
+ goto fail; /* error */
+
+ /*
+ * Byte-swap it if necessary.
+ */
+ if (p->swapped) {
+ idbp->linktype = SWAPSHORT(idbp->linktype);
+ idbp->snaplen = SWAPLONG(idbp->snaplen);
+ }
+
+ /*
+ * Try to add this interface.
+ */
+#ifdef __APPLE__
+ if (!add_interface(p, idbp, &cursor, errbuf))
+ goto fail;
+#else
+ if (!add_interface(p, &cursor, errbuf))
+ goto fail;
+#endif /* __APPLE__ */
+ goto done;
+
+ case BT_EPB:
+ case BT_SPB:
+ case BT_PB:
+ /*
+ * Saw a packet before we saw any IDBs. That's
+ * not valid, as we don't know what link-layer
+ * encapsulation the packet has.
+ */
+ pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE,
+ "the capture file has a packet block before any Interface Description Blocks");
+ goto fail;
+
+ default:
+ /*
+ * Just ignore it.
+ */
+ break;
+ }
+ }
+
+done:
+ p->tzoff = 0; /* XXX - not used in pcap */
+ p->linktype = linktype_to_dlt(idbp->linktype);
+ p->snapshot = pcap_adjust_snapshot(p->linktype, idbp->snaplen);
+ p->linktype_ext = 0;
+
+ /*
+ * If the maximum block size for a packet with the maximum
+ * snapshot length for this DLT_ is bigger than the current
+ * maximum block size, increase the maximum.
+ */
+ if (MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype)) > ps->max_blocksize)
+ ps->max_blocksize = MAX_BLOCKSIZE_FOR_SNAPLEN(max_snaplen_for_dlt(p->linktype));
+
+ p->next_packet_op = pcap_ng_next_packet;
+ p->cleanup_op = pcap_ng_cleanup;
+
+#ifdef __APPLE__
+ /*
+ * Special using block based API
+ */
+ if (isng) {
+ p->next_packet_op = pcap_ng_next_block;
+ /*
+ * Rewind to begining of Section Header Block
+ */
+ if (file_offset < 4) {
+ snprintf(errbuf, PCAP_ERRBUF_SIZE, "bad file offset");
+ goto fail;
+ }
+ file_offset -= 4;
+ fseek(fp, file_offset, SEEK_SET);
+
+ p->linktype = DLT_PCAPNG;
+ }
+#endif /* __APPLE__ */
+
+ return (p);
+
+fail:
+ free(ps->ifaces);
+ free(p->buffer);
+ free(p);
+ *err = 1;
+ return (NULL);
+}
+
+#ifdef __APPLE__
+void
+#else
+static void
+#endif /* __APPLE__ */
+pcap_ng_cleanup(pcap_t *p)
+{
+ struct pcap_ng_sf *ps = p->priv;
+
+ free(ps->ifaces);
+ sf_cleanup(p);
+}
+
+/*
+ * Read and return the next packet from the savefile. Return the header
+ * in hdr and a pointer to the contents in data. Return 0 on success, 1
+ * if there were no more packets, and -1 on an error.
+ */
+static int
+pcap_ng_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
+{
+#ifdef __APPLE__
+ return (pcap_ng_next_internal(p, hdr, data, 1));
+}
+
+static int
+pcap_ng_next_block(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data)
+{
+ return (pcap_ng_next_internal(p, hdr, data, 0));
+}
+
+static int
+pcap_ng_next_internal(pcap_t *p, struct pcap_pkthdr *hdr, u_char **data, int pktonly)
+{
+#endif /* __APPLE__ */
+ struct pcap_ng_sf *ps = p->priv;
+ struct block_cursor cursor;
+ int status;
+ struct enhanced_packet_block *epbp;
+ struct simple_packet_block *spbp;
+ struct packet_block *pbp;
+ bpf_u_int32 interface_id = 0xFFFFFFFF;
+ struct interface_description_block *idbp;
+ struct section_header_block *shbp;
+ FILE *fp = p->rfile;
+ uint64_t t, sec, frac;
+
+#ifdef __APPLE__
+ struct option_header *opthdr;
+ unsigned char packetpad;
+
+ /*
+ * To silence Xcode static analyzer that doesn't know this depends on pcap_ng_check_header
+ * that initialized user_tsresol to non-zero value
+ */
+ if (ps->user_tsresol == 0) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "internal error, check_header did not set user_tsresol");
+ return (-1);
+ }
+#endif /* __APPLE__ */
+
+ /*
+ * Look for an Enhanced Packet Block, a Simple Packet Block,
+ * or a Packet Block.
+ */
+ for (;;) {
+ /*
+ * Read the block type and length; those are common
+ * to all blocks.
+ */
+ status = read_block(fp, p, &cursor, p->errbuf);
+ if (status == 0)
+ return (1); /* EOF */
+ if (status == -1)
+ return (-1); /* error */
+ switch (cursor.block_type) {
+
+ case BT_EPB:
+ /*
+ * Get a pointer to the fixed-length portion of the
+ * EPB.
+ */
+ epbp = get_from_block_data(&cursor, sizeof(*epbp),
+ p->errbuf);
+ if (epbp == NULL)
+ return (-1); /* error */
+
+ /*
+ * Byte-swap it if necessary.
+ */
+ if (p->swapped) {
+ /* these were written in opposite byte order */
+ interface_id = SWAPLONG(epbp->interface_id);
+ hdr->caplen = SWAPLONG(epbp->caplen);
+ hdr->len = SWAPLONG(epbp->len);
+ t = ((uint64_t)SWAPLONG(epbp->timestamp_high)) << 32 |
+ SWAPLONG(epbp->timestamp_low);
+ } else {
+ interface_id = epbp->interface_id;
+ hdr->caplen = epbp->caplen;
+ hdr->len = epbp->len;
+ t = ((uint64_t)epbp->timestamp_high) << 32 |
+ epbp->timestamp_low;
+ }
+ goto found;
+
+ case BT_SPB:
+ /*
+ * Get a pointer to the fixed-length portion of the
+ * SPB.
+ */
+ spbp = get_from_block_data(&cursor, sizeof(*spbp),
+ p->errbuf);
+ if (spbp == NULL)
+ return (-1); /* error */
+
+ /*
+ * SPB packets are assumed to have arrived on
+ * the first interface.
+ */
+ interface_id = 0;
+
+ /*
+ * Byte-swap it if necessary.
+ */
+ if (p->swapped) {
+ /* these were written in opposite byte order */
+ hdr->len = SWAPLONG(spbp->len);
+ } else
+ hdr->len = spbp->len;
+
+ /*
+ * The SPB doesn't give the captured length;
+ * it's the minimum of the snapshot length
+ * and the packet length.
+ */
+ hdr->caplen = hdr->len;
+ if (hdr->caplen > (bpf_u_int32)p->snapshot)
+ hdr->caplen = p->snapshot;
+ t = 0; /* no time stamps */
+ goto found;
+
+ case BT_PB:
+ /*
+ * Get a pointer to the fixed-length portion of the
+ * PB.
+ */
+ pbp = get_from_block_data(&cursor, sizeof(*pbp),
+ p->errbuf);
+ if (pbp == NULL)
+ return (-1); /* error */
+
+ /*
+ * Byte-swap it if necessary.
+ */
+ if (p->swapped) {
+ /* these were written in opposite byte order */
+ interface_id = SWAPSHORT(pbp->interface_id);
+ hdr->caplen = SWAPLONG(pbp->caplen);
+ hdr->len = SWAPLONG(pbp->len);
+ t = ((uint64_t)SWAPLONG(pbp->timestamp_high)) << 32 |
+ SWAPLONG(pbp->timestamp_low);
+ } else {
+ interface_id = pbp->interface_id;
+ hdr->caplen = pbp->caplen;
+ hdr->len = pbp->len;
+ t = ((uint64_t)pbp->timestamp_high) << 32 |
+ pbp->timestamp_low;
+ }
+ goto found;
+
+ case BT_IDB:
+ /*
+ * Interface Description Block. Get a pointer
+ * to its fixed-length portion.
+ */
+ idbp = get_from_block_data(&cursor, sizeof(*idbp),
+ p->errbuf);
+ if (idbp == NULL)
+ return (-1); /* error */
+
+ /*
+ * Byte-swap it if necessary.
+ */
+ if (p->swapped) {
+ idbp->linktype = SWAPSHORT(idbp->linktype);
+ idbp->snaplen = SWAPLONG(idbp->snaplen);
+ }
+
+ /*
+ * If the link-layer type or snapshot length
+ * differ from the ones for the first IDB we
+ * saw, quit.
+ *
+ * XXX - just discard packets from those
+ * interfaces?
+ */
+#ifdef __APPLE__
+ if (!pktonly) {
+ goto skip_link_checks;
+ }
+#endif /* __APPLE__ */
+ if (p->linktype != idbp->linktype) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "an interface has a type %u different from the type of the first interface",
+ idbp->linktype);
+ return (-1);
+ }
+
+ /*
+ * Check against the *adjusted* value of this IDB's
+ * snapshot length.
+ */
+ if ((bpf_u_int32)p->snapshot !=
+ pcap_adjust_snapshot(p->linktype, idbp->snaplen)) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "an interface has a snapshot length %u different from the type of the first interface",
+ idbp->snaplen);
+ return (-1);
+ }
+ /*
+ * Try to add this interface.
+ */
+#ifdef __APPLE__
+skip_link_checks:
+ if (!add_interface(p, idbp, &cursor, p->errbuf))
+ return (-1);
+#else
+ if (!add_interface(p, &cursor, p->errbuf))
+ return (-1);
+#endif /* __APPLE__ */
+ break;
+
+ case BT_SHB:
+ /*
+ * Section Header Block. Get a pointer
+ * to its fixed-length portion.
+ */
+ shbp = get_from_block_data(&cursor, sizeof(*shbp),
+ p->errbuf);
+ if (shbp == NULL)
+ return (-1); /* error */
+
+ /*
+ * Assume the byte order of this section is
+ * the same as that of the previous section.
+ * We'll check for that later.
+ */
+ if (p->swapped) {
+ shbp->byte_order_magic =
+ SWAPLONG(shbp->byte_order_magic);
+ shbp->major_version =
+ SWAPSHORT(shbp->major_version);
+ }
+
+ /*
+ * Make sure the byte order doesn't change;
+ * pcap_is_swapped() shouldn't change its
+ * return value in the middle of reading a capture.
+ */
+ switch (shbp->byte_order_magic) {
+
+ case BYTE_ORDER_MAGIC:
+ /*
+ * OK.
+ */
+ break;
+
+ case SWAPLONG(BYTE_ORDER_MAGIC):
+ /*
+ * Byte order changes.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "the file has sections with different byte orders");
+ return (-1);
+
+ default:
+ /*
+ * Not a valid SHB.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "the file has a section with a bad byte order magic field");
+ return (-1);
+ }
+
+ /*
+ * Make sure the major version is the version
+ * we handle.
+ */
+ if (shbp->major_version != PCAP_NG_VERSION_MAJOR) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "unknown pcapng savefile major version number %u",
+ shbp->major_version);
+ return (-1);
+ }
+
+ /*
+ * Reset the interface count; this section should
+ * have its own set of IDBs. If any of them
+ * don't have the same interface type, snapshot
+ * length, or resolution as the first interface
+ * we saw, we'll fail. (And if we don't see
+ * any IDBs, we'll fail when we see a packet
+ * block.)
+ */
+ ps->ifcount = 0;
+ break;
+
+ default:
+ /*
+ * Not a packet block, IDB, or SHB; ignore it.
+ */
+ break;
+ }
+
+#ifdef __APPLE__
+ if (pktonly == 0)
+ return (0);
+#endif /* __APPLE__ */
+ }
+
+found:
+ /*
+ * Is the interface ID an interface we know?
+ */
+ if (interface_id >= ps->ifcount) {
+ /*
+ * Yes. Fail.
+ */
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "a packet arrived on interface %u, but there's no Interface Description Block for that interface",
+ interface_id);
+ return (-1);
+ }
+
+#ifdef __APPLE__
+ if (hdr->caplen > (bpf_u_int32)ps->ifaces[interface_id].snaplen) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "invalid packet capture length %u, bigger than "
+ "snaplen of %d", hdr->caplen, p->snapshot);
+ return (-1);
+ }
+#else /* __APPLE__ */
+ if (hdr->caplen > (bpf_u_int32)p->snapshot) {
+ pcap_snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "invalid packet capture length %u, bigger than "
+ "snaplen of %d", hdr->caplen, p->snapshot);
+ return (-1);
+ }
+#endif /* __APPLE__ */
+
+ /*
+ * Convert the time stamp to seconds and fractions of a second,
+ * with the fractions being in units of the file-supplied resolution.
+ */
+ sec = t / ps->ifaces[interface_id].tsresol + ps->ifaces[interface_id].tsoffset;
+ frac = t % ps->ifaces[interface_id].tsresol;
+
+ /*
+ * Convert the fractions from units of the file-supplied resolution
+ * to units of the user-requested resolution.
+ */
+ switch (ps->ifaces[interface_id].scale_type) {
+
+ case PASS_THROUGH:
+ /*
+ * The interface resolution is what the user wants,
+ * so we're done.
+ */
+ break;
+
+ case SCALE_UP_DEC:
+ /*
+ * The interface resolution is less than what the user
+ * wants; scale the fractional part up to the units of
+ * the resolution the user requested by multiplying by
+ * the quotient of the user-requested resolution and the
+ * file-supplied resolution.
+ *
+ * Those resolutions are both powers of 10, and the user-
+ * requested resolution is greater than the file-supplied
+ * resolution, so the quotient in question is an integer.
+ * We've calculated that quotient already, so we just
+ * multiply by it.
+ */
+ frac *= ps->ifaces[interface_id].scale_factor;
+ break;
+
+ case SCALE_UP_BIN:
+ /*
+ * The interface resolution is less than what the user
+ * wants; scale the fractional part up to the units of
+ * the resolution the user requested by multiplying by
+ * the quotient of the user-requested resolution and the
+ * file-supplied resolution.
+ *
+ * The file-supplied resolution is a power of 2, so the
+ * quotient is not an integer, so, in order to do this
+ * entirely with integer arithmetic, we multiply by the
+ * user-requested resolution and divide by the file-
+ * supplied resolution.
+ *
+ * XXX - Is there something clever we could do here,
+ * given that we know that the file-supplied resolution
+ * is a power of 2? Doing a multiplication followed by
+ * a division runs the risk of overflowing, and involves
+ * two non-simple arithmetic operations.
+ */
+ frac *= ps->user_tsresol;
+ frac /= ps->ifaces[interface_id].tsresol;
+ break;
+
+ case SCALE_DOWN_DEC:
+ /*
+ * The interface resolution is greater than what the user
+ * wants; scale the fractional part up to the units of
+ * the resolution the user requested by multiplying by
+ * the quotient of the user-requested resolution and the
+ * file-supplied resolution.
+ *
+ * Those resolutions are both powers of 10, and the user-
+ * requested resolution is less than the file-supplied
+ * resolution, so the quotient in question isn't an
+ * integer, but its reciprocal is, and we can just divide
+ * by the reciprocal of the quotient. We've calculated
+ * the reciprocal of that quotient already, so we must
+ * divide by it.
+ */
+ frac /= ps->ifaces[interface_id].scale_factor;
+ break;
+
+
+ case SCALE_DOWN_BIN:
+ /*
+ * The interface resolution is greater than what the user
+ * wants; convert the fractional part to units of the
+ * resolution the user requested by multiplying by the
+ * quotient of the user-requested resolution and the
+ * file-supplied resolution. We do that by multiplying
+ * by the user-requested resolution and dividing by the
+ * file-supplied resolution, as the quotient might not
+ * fit in an integer.
+ *
+ * The file-supplied resolution is a power of 2, so the
+ * quotient is not an integer, and neither is its
+ * reciprocal, so, in order to do this entirely with
+ * integer arithmetic, we multiply by the user-requested
+ * resolution and divide by the file-supplied resolution.
+ *
+ * XXX - Is there something clever we could do here,
+ * given that we know that the file-supplied resolution
+ * is a power of 2? Doing a multiplication followed by
+ * a division runs the risk of overflowing, and involves
+ * two non-simple arithmetic operations.
+ */
+ frac *= ps->user_tsresol;
+ frac /= ps->ifaces[interface_id].tsresol;
+ break;
+ }
+#ifdef _WIN32
+ /*
+ * tv_sec and tv_used in the Windows struct timeval are both
+ * longs.
+ */
+ hdr->ts.tv_sec = (long)sec;
+ hdr->ts.tv_usec = (long)frac;
+#else
+ /*
+ * tv_sec in the UN*X struct timeval is a time_t; tv_usec is
+ * suseconds_t in UN*Xes that work the way the current Single
+ * UNIX Standard specify - but not all older UN*Xes necessarily
+ * support that type, so just cast to int.
+ */
+ hdr->ts.tv_sec = (time_t)sec;
+ hdr->ts.tv_usec = (int)frac;
+#endif
+
+ /*
+ * Get a pointer to the packet data.
+ */
+ *data = get_from_block_data(&cursor, hdr->caplen, p->errbuf);
+ if (*data == NULL)
+ return (-1);
+#ifdef __APPLE__
+ /*
+ * Skip padding.
+ */
+ packetpad = 4 - (hdr->caplen % 4);
+ if (hdr->caplen % 4 != 0 &&
+ get_from_block_data(&cursor, packetpad, p->errbuf) == NULL)
+ return (-1);
+
+ memset(hdr->comment, 0, sizeof(hdr->comment));
+
+ if ((opthdr = get_opthdr_from_block_data(p, &cursor, p->errbuf)) != NULL &&
+ opthdr->option_code == OPT_COMMENT && opthdr->option_length > 0) {
+ char *optvalue;
+ optvalue = get_optvalue_from_block_data(&cursor, opthdr, p->errbuf);
+ if (optvalue == NULL)
+ return (-1);
+ memcpy(hdr->comment, optvalue, sizeof(hdr->comment));
+ }
+#endif /* __APPLE */
+
+ if (p->swapped)
+ swap_pseudo_headers(p->linktype, hdr, *data);
+
+ return (0);
+}
+
+#ifdef __APPLE__
+
+static int
+sf_ng_write_header(FILE *fp, int linktype, int thiszone, int snaplen)
+{
+ struct pcapng_block_header bh;
+ struct pcapng_section_header_fields shb;
+ struct pcapng_interface_description_fields idb;
+ struct pcapng_block_trailer bt;
+ size_t len;
+
+ /*
+ * Section Header Block
+ */
+ len = sizeof(bh) + sizeof(shb) + sizeof(bt);
+ bh.block_type = PCAPNG_BT_SHB;
+ bh.total_length = (bpf_u_int32)len;
+
+ shb.byte_order_magic = PCAPNG_BYTE_ORDER_MAGIC;
+ shb.major_version = PCAPNG_VERSION_MAJOR;
+ shb.minor_version = 0;
+ shb.section_length = 0xFFFFFFFFFFFFFFFF;
+
+ bt.total_length = (bpf_u_int32)len;
+
+ if (fwrite((char *)&bh, sizeof(bh), 1, fp) != 1)
+ return (-1);
+
+ if (fwrite((char *)&shb, sizeof(shb), 1, fp) != 1)
+ return (-1);
+
+ if (fwrite((char *)&bt, sizeof(bt), 1, fp) != 1)
+ return (-1);
+
+ /*
+ * Interface Description Block
+ */
+ len = sizeof(bh) + sizeof(idb) + sizeof(bt);
+ bh.block_type = PCAPNG_BT_IDB;
+ bh.total_length = (bpf_u_int32)len;
+
+ idb.idb_reserved = 0;
+ idb.idb_linktype = linktype;
+ idb.idb_snaplen = snaplen;
+
+ bt.total_length = (bpf_u_int32)len;
+
+ if (fwrite((char *)&bh, sizeof(bh), 1, fp) != 1)
+ return (-1);
+
+ if (fwrite((char *)&idb, sizeof(idb), 1, fp) != 1)
+ return (-1);
+
+ if (fwrite((char *)&bt, sizeof(bt), 1, fp) != 1)
+ return (-1);
+
+ return (0);
+}
+
+static pcap_dumper_t *
+pcap_ng_setup_dump(pcap_t *p, int linktype, FILE *f, const char *fname)
+{
+ pcap_dumper_t *dumper;
+
+ dumper = pcap_alloc_dumper(p,f);
+ if (dumper == NULL)
+ return (NULL);
+
+ if (sf_ng_write_header(dumper->f, linktype, p->tzoff, p->snapshot) == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Can't write to %s: %s",
+ fname, pcap_strerror(errno));
+ pcap_dump_close(dumper);
+ return (NULL);
+ }
+ fflush(dumper->f);
+ p->shb_added = 1;
+ dumper->shb_added = 1;
+
+ return (dumper);
+}
+
+pcap_dumper_t *
+pcap_ng_dump_open(pcap_t *p, const char *fname)
+{
+ FILE *f;
+ int linktype;
+
+ /*
+ * If this pcap_t hasn't been activated, it doesn't have a
+ * link-layer type, so we can't use it.
+ */
+ if (!p->activated) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: not-yet-activated pcap_t passed to pcap_ng_dump_open",
+ fname);
+ return (NULL);
+ }
+
+ if (fname[0] == '-' && fname[1] == '\0') {
+ f = stdout;
+ fname = "standard output";
+ } else {
+ f = fopen(fname, "wb");
+ if (f == NULL) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s",
+ fname, pcap_strerror(errno));
+ return (NULL);
+ }
+ }
+
+ /*
+ * Make sure a section header will be added and that
+ * any information to a previous section gets cleared.
+ */
+ pcap_ng_init_section_info(p);
+
+ /*
+ * When using the block based API, the section header and
+ * interface description blocks are given by the caller
+ */
+ if (p->linktype != DLT_PKTAP && p->linktype != DLT_PCAPNG) {
+ linktype = dlt_to_linktype(p->linktype);
+ if (linktype == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "%s: link-layer type %d isn't supported in savefiles",
+ fname, p->linktype);
+ if (f != stdout)
+ fclose(f);
+ return (NULL);
+ }
+ linktype |= p->linktype_ext;
+
+ return (pcap_ng_setup_dump(p, linktype, f, fname));
+ } else {
+ return (pcap_alloc_dumper(p, f));
+ }
+}
+
+pcap_dumper_t *
+pcap_ng_dump_fopen(pcap_t *p, FILE *f)
+{
+ int linktype;
+
+ linktype = dlt_to_linktype(p->linktype);
+ if (linktype == -1) {
+ snprintf(p->errbuf, PCAP_ERRBUF_SIZE,
+ "stream: link-layer type %d isn't supported in savefiles",
+ p->linktype);
+ return (NULL);
+ }
+ linktype |= p->linktype_ext;
+
+ return (pcap_ng_setup_dump(p, linktype, f, "stream"));
+}
+
+void
+pcap_ng_dump(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+{
+ FILE *f;
+ uint64_t ts;
+ struct pcapng_block_header bh;
+ struct pcapng_enhanced_packet_fields epb;
+ struct pcapng_block_trailer bt;
+ unsigned char packetpad = 0;
+ size_t len = sizeof(bh) + sizeof(epb) + h->caplen + sizeof(bt);
+ struct pcapng_option_header ohcomm;
+ struct pcapng_option_header oht;
+ size_t commlen = 0;
+ unsigned char commpad = 0;
+
+ if (h->comment[0]) {
+ /* Comment option */
+ commlen = strlen(h->comment);
+ ohcomm.option_code = PCAPNG_OPT_COMMENT;
+ ohcomm.option_length = commlen;
+ len += sizeof(ohcomm) + commlen;
+ if (commlen % 4 != 0) {
+ commpad = 4 - (commlen % 4);
+ len += commpad;
+ }
+ /* Option terminator */
+ oht.option_code = PCAPNG_OPT_ENDOFOPT;
+ oht.option_length = 0;
+ len += sizeof(oht);
+ }
+
+ if (h->caplen % 4 != 0) {
+ packetpad = 4 - (h->caplen % 4);
+ len += packetpad;
+ }
+
+ bh.block_type = PCAPNG_BT_EPB;
+ bh.total_length = (bpf_u_int32)len;
+
+ epb.caplen = h->caplen;
+ epb.interface_id = 0;
+ epb.len = h->len;
+ /* Microsecond resolution */
+ ts = h->ts.tv_sec * 1000000 + h->ts.tv_usec;
+ epb.timestamp_high = ts >> 32;
+ epb.timestamp_low = ts & 0xffffffff;
+
+ bt.total_length = (bpf_u_int32)len;
+
+ f = ((pcap_dumper_t *)user)->f;
+ /* XXX we should check the return status */
+ /* Header */
+ (void)fwrite(&bh, sizeof(bh), 1, f);
+ (void)fwrite(&epb, sizeof(epb), 1, f);
+ /* Packet */
+ (void)fwrite(sp, h->caplen, 1, f);
+ if (packetpad)
+ (void)fseek(f, packetpad, SEEK_CUR);
+ /* Options */
+ if (h->comment[0]) {
+ (void)fwrite(&ohcomm, sizeof(ohcomm), 1, f);
+ (void)fwrite(h->comment, commlen, 1, f);
+ if (commpad)
+ (void)fseek(f, commpad, SEEK_CUR);
+ (void)fwrite(&oht, sizeof(oht), 1, f);
+ }
+ (void)fwrite(&bt, sizeof(bt), 1, f);
+}
+
+void
+pcap_ng_dump_close(pcap_dumper_t *p)
+{
+ /*
+ * XXX we could add an interface statistics block at the end
+ * of the file.
+ */
+ return pcap_dump_close(p);
+}
+
+#endif /* __APPLE__ */
+
diff --git a/lib/libpcap/libpcap/sf-pcapng.h b/lib/libpcap/libpcap/sf-pcapng.h
new file mode 100644
index 0000000..463dda7
--- /dev/null
+++ b/lib/libpcap/libpcap/sf-pcapng.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * sf-pcapng.h - pcapng-file-format-specific routines
+ *
+ * Used to read pcapng savefiles.
+ */
+
+#ifndef sf_pcapng_h
+#define sf_pcapng_h
+
+#ifdef __APPLE__
+extern pcap_t *pcap_ng_check_header(const uint8_t *magic, FILE *fp,
+ u_int precision, char *errbuf, int *err, int isng);
+
+struct block_cursor;
+void *
+get_from_block_data(struct block_cursor *cursor, size_t chunk_size,
+ char *errbuf);
+#else
+extern pcap_t *pcap_ng_check_header(const uint8_t *magic, FILE *fp,
+ u_int precision, char *errbuf, int *err);
+#endif /* __APPLE__ */
+
+#endif
diff --git a/lib/libpcap/libpcap/sockutils.c b/lib/libpcap/libpcap/sockutils.c
new file mode 100644
index 0000000..d3e9464
--- /dev/null
+++ b/lib/libpcap/libpcap/sockutils.c
@@ -0,0 +1,1637 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+/*
+ * \file sockutils.c
+ *
+ * The goal of this file is to provide a common set of primitives for socket
+ * manipulation.
+ *
+ * Although the socket interface defined in the RFC 2553 (and its updates)
+ * is excellent, there are still differences between the behavior of those
+ * routines on UN*X and Windows, and between UN*Xes.
+ *
+ * These calls provide an interface similar to the socket interface, but
+ * that hides the differences between operating systems. It does not
+ * attempt to significantly improve on the socket interface in other
+ * ways.
+ */
+
+#include "ftmacros.h"
+
+#include <string.h>
+#include <errno.h> /* for the errno variable */
+#include <stdio.h> /* for the stderr file */
+#include <stdlib.h> /* for malloc() and free() */
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#else
+#define INT_MAX 2147483647
+#endif
+
+#include "pcap-int.h"
+
+#include "sockutils.h"
+#include "portability.h"
+
+#ifdef _WIN32
+ /*
+ * Winsock initialization.
+ *
+ * Ask for WinSock 2.2.
+ */
+ #define WINSOCK_MAJOR_VERSION 2
+ #define WINSOCK_MINOR_VERSION 2
+
+ static int sockcount = 0; /*!< Variable that allows calling the WSAStartup() only one time */
+#endif
+
+/* Some minor differences between UNIX and Win32 */
+#ifdef _WIN32
+ #define SHUT_WR SD_SEND /* The control code for shutdown() is different in Win32 */
+#endif
+
+/* Size of the buffer that has to keep error messages */
+#define SOCK_ERRBUF_SIZE 1024
+
+/* Constants; used in order to keep strings here */
+#define SOCKET_NO_NAME_AVAILABLE "No name available"
+#define SOCKET_NO_PORT_AVAILABLE "No port available"
+#define SOCKET_NAME_NULL_DAD "Null address (possibly DAD Phase)"
+
+/*
+ * On UN*X, send() and recv() return ssize_t.
+ *
+ * On Windows, send() and recv() return an int.
+ *
+ * Wth MSVC, there *is* no ssize_t.
+ *
+ * With MinGW, there is an ssize_t type; it is either an int (32 bit)
+ * or a long long (64 bit).
+ *
+ * So, on Windows, if we don't have ssize_t defined, define it as an
+ * int, so we can use it, on all platforms, as the type of variables
+ * that hold the return values from send() and recv().
+ */
+#if defined(_WIN32) && !defined(_SSIZE_T_DEFINED)
+typedef int ssize_t;
+#endif
+
+/****************************************************
+ * *
+ * Locally defined functions *
+ * *
+ ****************************************************/
+
+static int sock_ismcastaddr(const struct sockaddr *saddr);
+
+/****************************************************
+ * *
+ * Function bodies *
+ * *
+ ****************************************************/
+
+/*
+ * Format an error message given an errno value (UN*X) or a WinSock error
+ * (Windows).
+ */
+void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen)
+{
+ if (errbuf == NULL)
+ return;
+
+#ifdef _WIN32
+ pcap_fmt_errmsg_for_win32_err(errbuf, errbuflen, errcode,
+ "%s", caller);
+#else
+ pcap_fmt_errmsg_for_errno(errbuf, errbuflen, errcode,
+ "%s", caller);
+#endif
+}
+
+/*
+ * \brief It retrieves the error message after an error occurred in the socket interface.
+ *
+ * This function is defined because of the different way errors are returned in UNIX
+ * and Win32. This function provides a consistent way to retrieve the error message
+ * (after a socket error occurred) on all the platforms.
+ *
+ * \param caller: a pointer to a user-allocated string which contains a message that has
+ * to be printed *before* the true error message. It could be, for example, 'this error
+ * comes from the recv() call at line 31'.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return No return values. The error message is returned in the 'string' parameter.
+ */
+void sock_geterror(const char *caller, char *errbuf, int errbuflen)
+{
+#ifdef _WIN32
+ sock_fmterror(caller, GetLastError(), errbuf, errbuflen);
+#else
+ sock_fmterror(caller, errno, errbuf, errbuflen);
+#endif
+}
+
+/*
+ * \brief This function initializes the socket mechanism if it hasn't
+ * already been initialized or reinitializes it after it has been
+ * cleaned up.
+ *
+ * On UN*Xes, it doesn't need to do anything; on Windows, it needs to
+ * initialize Winsock.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain
+ * the complete error message. This buffer has to be at least 'errbuflen'
+ * in length. It can be NULL; in this case no error message is supplied.
+ *
+ * \param errbuflen: length of the buffer that will contains the error.
+ * The error message cannot be larger than 'errbuflen - 1' because the
+ * last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The
+ * error message is returned in the buffer pointed to by 'errbuf' variable.
+ */
+#ifdef _WIN32
+int sock_init(char *errbuf, int errbuflen)
+{
+ if (sockcount == 0)
+ {
+ WSADATA wsaData; /* helper variable needed to initialize Winsock */
+
+ if (WSAStartup(MAKEWORD(WINSOCK_MAJOR_VERSION,
+ WINSOCK_MINOR_VERSION), &wsaData) != 0)
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "Failed to initialize Winsock\n");
+
+ WSACleanup();
+
+ return -1;
+ }
+ }
+
+ sockcount++;
+ return 0;
+}
+#else
+int sock_init(char *errbuf _U_, int errbuflen _U_)
+{
+ /*
+ * Nothing to do on UN*Xes.
+ */
+ return 0;
+}
+#endif
+
+/*
+ * \brief This function cleans up the socket mechanism if we have no
+ * sockets left open.
+ *
+ * On UN*Xes, it doesn't need to do anything; on Windows, it needs
+ * to clean up Winsock.
+ *
+ * \return No error values.
+ */
+void sock_cleanup(void)
+{
+#ifdef _WIN32
+ sockcount--;
+
+ if (sockcount == 0)
+ WSACleanup();
+#endif
+}
+
+/*
+ * \brief It checks if the sockaddr variable contains a multicast address.
+ *
+ * \return '0' if the address is multicast, '-1' if it is not.
+ */
+static int sock_ismcastaddr(const struct sockaddr *saddr)
+{
+ if (saddr->sa_family == PF_INET)
+ {
+ struct sockaddr_in *saddr4 = (struct sockaddr_in *) saddr;
+ if (IN_MULTICAST(ntohl(saddr4->sin_addr.s_addr))) return 0;
+ else return -1;
+ }
+ else
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+ if (IN6_IS_ADDR_MULTICAST(&saddr6->sin6_addr)) return 0;
+ else return -1;
+ }
+}
+
+/*
+ * \brief It initializes a network connection both from the client and the server side.
+ *
+ * In case of a client socket, this function calls socket() and connect().
+ * In the meanwhile, it checks for any socket error.
+ * If an error occurs, it writes the error message into 'errbuf'.
+ *
+ * In case of a server socket, the function calls socket(), bind() and listen().
+ *
+ * This function is usually preceeded by the sock_initaddress().
+ *
+ * \param addrinfo: pointer to an addrinfo variable which will be used to
+ * open the socket and such. This variable is the one returned by the previous call to
+ * sock_initaddress().
+ *
+ * \param server: '1' if this is a server socket, '0' otherwise.
+ *
+ * \param nconn: number of the connections that are allowed to wait into the listen() call.
+ * This value has no meanings in case of a client socket.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return the socket that has been opened (that has to be used in the following sockets calls)
+ * if everything is fine, INVALID_SOCKET if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen)
+{
+ SOCKET sock;
+#if defined(SO_NOSIGPIPE) || defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY)
+ int on = 1;
+#endif
+
+ sock = socket(addrinfo->ai_family, addrinfo->ai_socktype, addrinfo->ai_protocol);
+ if (sock == INVALID_SOCKET)
+ {
+ sock_geterror("socket()", errbuf, errbuflen);
+ return INVALID_SOCKET;
+ }
+
+ /*
+ * Disable SIGPIPE, if we have SO_NOSIGPIPE. We don't want to
+ * have to deal with signals if the peer closes the connection,
+ * especially in client programs, which may not even be aware that
+ * they're sending to sockets.
+ */
+#ifdef SO_NOSIGPIPE
+ if (setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (char *)&on,
+ sizeof (int)) == -1)
+ {
+ sock_geterror("setsockopt(SO_NOSIGPIPE)", errbuf, errbuflen);
+ closesocket(sock);
+ return INVALID_SOCKET;
+ }
+#endif
+
+ /* This is a server socket */
+ if (server)
+ {
+ /*
+ * Allow a new server to bind the socket after the old one
+ * exited, even if lingering sockets are still present.
+ *
+ * Don't treat an error as a failure.
+ */
+ int optval = 1;
+ (void)setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+ (char *)&optval, sizeof (optval));
+
+#if defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY)
+ /*
+ * Force the use of IPv6-only addresses.
+ *
+ * RFC 3493 indicates that you can support IPv4 on an
+ * IPv6 socket:
+ *
+ * https://tools.ietf.org/html/rfc3493#section-3.7
+ *
+ * and that this is the default behavior. This means
+ * that if we first create an IPv6 socket bound to the
+ * "any" address, it is, in effect, also bound to the
+ * IPv4 "any" address, so when we create an IPv4 socket
+ * and try to bind it to the IPv4 "any" address, it gets
+ * EADDRINUSE.
+ *
+ * Not all network stacks support IPv4 on IPv6 sockets;
+ * pre-NT 6 Windows stacks don't support it, and the
+ * OpenBSD stack doesn't support it for security reasons
+ * (see the OpenBSD inet6(4) man page). Therefore, we
+ * don't want to rely on this behavior.
+ *
+ * So we try to disable it, using either the IPV6_V6ONLY
+ * option from RFC 3493:
+ *
+ * https://tools.ietf.org/html/rfc3493#section-5.3
+ *
+ * or the IPV6_BINDV6ONLY option from older UN*Xes.
+ */
+#ifndef IPV6_V6ONLY
+ /* For older systems */
+ #define IPV6_V6ONLY IPV6_BINDV6ONLY
+#endif /* IPV6_V6ONLY */
+ if (addrinfo->ai_family == PF_INET6)
+ {
+ if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+ (char *)&on, sizeof (int)) == -1)
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "setsockopt(IPV6_V6ONLY)");
+ closesocket(sock);
+ return INVALID_SOCKET;
+ }
+ }
+#endif /* defined(IPV6_V6ONLY) || defined(IPV6_BINDV6ONLY) */
+
+ /* WARNING: if the address is a mcast one, I should place the proper Win32 code here */
+ if (bind(sock, addrinfo->ai_addr, (int) addrinfo->ai_addrlen) != 0)
+ {
+ sock_geterror("bind()", errbuf, errbuflen);
+ closesocket(sock);
+ return INVALID_SOCKET;
+ }
+
+ if (addrinfo->ai_socktype == SOCK_STREAM)
+ if (listen(sock, nconn) == -1)
+ {
+ sock_geterror("listen()", errbuf, errbuflen);
+ closesocket(sock);
+ return INVALID_SOCKET;
+ }
+
+ /* server side ended */
+ return sock;
+ }
+ else /* we're the client */
+ {
+ struct addrinfo *tempaddrinfo;
+ char *errbufptr;
+ size_t bufspaceleft;
+
+ tempaddrinfo = addrinfo;
+ errbufptr = errbuf;
+ bufspaceleft = errbuflen;
+ *errbufptr = 0;
+
+ /*
+ * We have to loop though all the addinfo returned.
+ * For instance, we can have both IPv6 and IPv4 addresses, but the service we're trying
+ * to connect to is unavailable in IPv6, so we have to try in IPv4 as well
+ */
+ while (tempaddrinfo)
+ {
+
+ if (connect(sock, tempaddrinfo->ai_addr, (int) tempaddrinfo->ai_addrlen) == -1)
+ {
+ size_t msglen;
+ char TmpBuffer[100];
+ char SocketErrorMessage[SOCK_ERRBUF_SIZE];
+
+ /*
+ * We have to retrieve the error message before any other socket call completes, otherwise
+ * the error message is lost
+ */
+ sock_geterror("Connect to socket failed",
+ SocketErrorMessage, sizeof(SocketErrorMessage));
+
+ /* Returns the numeric address of the host that triggered the error */
+ sock_getascii_addrport((struct sockaddr_storage *) tempaddrinfo->ai_addr, TmpBuffer, sizeof(TmpBuffer), NULL, 0, NI_NUMERICHOST, TmpBuffer, sizeof(TmpBuffer));
+
+ pcap_snprintf(errbufptr, bufspaceleft,
+ "Is the server properly installed on %s? %s", TmpBuffer, SocketErrorMessage);
+
+ /* In case more then one 'connect' fails, we manage to keep all the error messages */
+ msglen = strlen(errbufptr);
+
+ errbufptr[msglen] = ' ';
+ errbufptr[msglen + 1] = 0;
+
+ bufspaceleft = bufspaceleft - (msglen + 1);
+ errbufptr += (msglen + 1);
+
+ tempaddrinfo = tempaddrinfo->ai_next;
+ }
+ else
+ break;
+ }
+
+ /*
+ * Check how we exit from the previous loop
+ * If tempaddrinfo is equal to NULL, it means that all the connect() failed.
+ */
+ if (tempaddrinfo == NULL)
+ {
+ closesocket(sock);
+ return INVALID_SOCKET;
+ }
+ else
+ return sock;
+ }
+}
+
+/*
+ * \brief Closes the present (TCP and UDP) socket connection.
+ *
+ * This function sends a shutdown() on the socket in order to disable send() calls
+ * (while recv() ones are still allowed). Then, it closes the socket.
+ *
+ * \param sock: the socket identifier of the connection that has to be closed.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable.
+ */
+int sock_close(SOCKET sock, char *errbuf, int errbuflen)
+{
+ /*
+ * SHUT_WR: subsequent calls to the send function are disallowed.
+ * For TCP sockets, a FIN will be sent after all data is sent and
+ * acknowledged by the Server.
+ */
+ if (shutdown(sock, SHUT_WR))
+ {
+ sock_geterror("shutdown()", errbuf, errbuflen);
+ /* close the socket anyway */
+ closesocket(sock);
+ return -1;
+ }
+
+ closesocket(sock);
+ return 0;
+}
+
+/*
+ * gai_errstring() has some problems:
+ *
+ * 1) on Windows, Microsoft explicitly says it's not thread-safe;
+ * 2) on UN*X, the Single UNIX Specification doesn't say it *is*
+ * thread-safe, so an implementation might use a static buffer
+ * for unknown error codes;
+ * 3) the error message for the most likely error, EAI_NONAME, is
+ * truly horrible on several platforms ("nodename nor servname
+ * provided, or not known"? It's typically going to be "not
+ * known", not "oopsie, I passed null pointers for the host name
+ * and service name", not to mention they forgot the "neither");
+ *
+ * so we roll our own.
+ */
+static void
+get_gai_errstring(char *errbuf, int errbuflen, const char *prefix, int err,
+ const char *hostname, const char *portname)
+{
+ char hostport[PCAP_ERRBUF_SIZE];
+
+ if (hostname != NULL && portname != NULL)
+ pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s:%s",
+ hostname, portname);
+ else if (hostname != NULL)
+ pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "%s",
+ hostname);
+ else if (portname != NULL)
+ pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, ":%s",
+ portname);
+ else
+ pcap_snprintf(hostport, PCAP_ERRBUF_SIZE, "<no host or port!>");
+ switch (err)
+ {
+#ifdef EAI_ADDRFAMILY
+ case EAI_ADDRFAMILY:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sAddress family for %s not supported",
+ prefix, hostport);
+ break;
+#endif
+
+ case EAI_AGAIN:
+ pcap_snprintf(errbuf, errbuflen,
+ "%s%s could not be resolved at this time",
+ prefix, hostport);
+ break;
+
+ case EAI_BADFLAGS:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sThe ai_flags parameter for looking up %s had an invalid value",
+ prefix, hostport);
+ break;
+
+ case EAI_FAIL:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sA non-recoverable error occurred when attempting to resolve %s",
+ prefix, hostport);
+ break;
+
+ case EAI_FAMILY:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sThe address family for looking up %s was not recognized",
+ prefix, hostport);
+ break;
+
+ case EAI_MEMORY:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sOut of memory trying to allocate storage when looking up %s",
+ prefix, hostport);
+ break;
+
+ /*
+ * RFC 2553 had both EAI_NODATA and EAI_NONAME.
+ *
+ * RFC 3493 has only EAI_NONAME.
+ *
+ * Some implementations define EAI_NODATA and EAI_NONAME
+ * to the same value, others don't. If EAI_NODATA is
+ * defined and isn't the same as EAI_NONAME, we handle
+ * EAI_NODATA.
+ */
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
+ case EAI_NODATA:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sNo address associated with %s",
+ prefix, hostport);
+ break;
+#endif
+
+ case EAI_NONAME:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sThe host name %s couldn't be resolved",
+ prefix, hostport);
+ break;
+
+ case EAI_SERVICE:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sThe service value specified when looking up %s as not recognized for the socket type",
+ prefix, hostport);
+ break;
+
+ case EAI_SOCKTYPE:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sThe socket type specified when looking up %s as not recognized",
+ prefix, hostport);
+ break;
+
+#ifdef EAI_SYSTEM
+ case EAI_SYSTEM:
+ /*
+ * Assumed to be UN*X.
+ */
+ pcap_snprintf(errbuf, errbuflen,
+ "%sAn error occurred when looking up %s: %s",
+ prefix, hostport, pcap_strerror(errno));
+ break;
+#endif
+
+#ifdef EAI_BADHINTS
+ case EAI_BADHINTS:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sInvalid value for hints when looking up %s",
+ prefix, hostport);
+ break;
+#endif
+
+#ifdef EAI_PROTOCOL
+ case EAI_PROTOCOL:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sResolved protocol when looking up %s is unknown",
+ prefix, hostport);
+ break;
+#endif
+
+#ifdef EAI_OVERFLOW
+ case EAI_OVERFLOW:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sArgument buffer overflow when looking up %s",
+ prefix, hostport);
+ break;
+#endif
+
+ default:
+ pcap_snprintf(errbuf, errbuflen,
+ "%sgetaddrinfo() error %d when looking up %s",
+ prefix, err, hostport);
+ break;
+ }
+}
+
+/*
+ * \brief Checks that the address, port and flags given are valids and it returns an 'addrinfo' structure.
+ *
+ * This function basically calls the getaddrinfo() calls, and it performs a set of sanity checks
+ * to control that everything is fine (e.g. a TCP socket cannot have a mcast address, and such).
+ * If an error occurs, it writes the error message into 'errbuf'.
+ *
+ * \param host: a pointer to a string identifying the host. It can be
+ * a host name, a numeric literal address, or NULL or "" (useful
+ * in case of a server socket which has to bind to all addresses).
+ *
+ * \param port: a pointer to a user-allocated buffer containing the network port to use.
+ *
+ * \param hints: an addrinfo variable (passed by reference) containing the flags needed to create the
+ * addrinfo structure appropriately.
+ *
+ * \param addrinfo: it represents the true returning value. This is a pointer to an addrinfo variable
+ * (passed by reference), which will be allocated by this function and returned back to the caller.
+ * This variable will be used in the next sockets calls.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
+ * in the 'errbuf' variable. The addrinfo variable that has to be used in the following sockets calls is
+ * returned into the addrinfo parameter.
+ *
+ * \warning The 'addrinfo' variable has to be deleted by the programmer by calling freeaddrinfo() when
+ * it is no longer needed.
+ *
+ * \warning This function requires the 'hints' variable as parameter. The semantic of this variable is the same
+ * of the one of the corresponding variable used into the standard getaddrinfo() socket function. We suggest
+ * the programmer to look at that function in order to set the 'hints' variable appropriately.
+ */
+int sock_initaddress(const char *host, const char *port,
+ struct addrinfo *hints, struct addrinfo **addrinfo, char *errbuf, int errbuflen)
+{
+ int retval;
+
+ retval = getaddrinfo(host, port, hints, addrinfo);
+ if (retval != 0)
+ {
+ if (errbuf)
+ {
+ get_gai_errstring(errbuf, errbuflen, "", retval,
+ host, port);
+ }
+ return -1;
+ }
+ /*
+ * \warning SOCKET: I should check all the accept() in order to bind to all addresses in case
+ * addrinfo has more han one pointers
+ */
+
+ /*
+ * This software only supports PF_INET and PF_INET6.
+ *
+ * XXX - should we just check that at least *one* address is
+ * either PF_INET or PF_INET6, and, when using the list,
+ * ignore all addresses that are neither? (What, no IPX
+ * support? :-))
+ */
+ if (((*addrinfo)->ai_family != PF_INET) &&
+ ((*addrinfo)->ai_family != PF_INET6))
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): socket type not supported");
+ freeaddrinfo(*addrinfo);
+ *addrinfo = NULL;
+ return -1;
+ }
+
+ /*
+ * You can't do multicast (or broadcast) TCP.
+ */
+ if (((*addrinfo)->ai_socktype == SOCK_STREAM) &&
+ (sock_ismcastaddr((*addrinfo)->ai_addr) == 0))
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "getaddrinfo(): multicast addresses are not valid when using TCP streams");
+ freeaddrinfo(*addrinfo);
+ *addrinfo = NULL;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * \brief It sends the amount of data contained into 'buffer' on the given socket.
+ *
+ * This function basically calls the send() socket function and it checks that all
+ * the data specified in 'buffer' (of size 'size') will be sent. If an error occurs,
+ * it writes the error message into 'errbuf'.
+ * In case the socket buffer does not have enough space, it loops until all data
+ * has been sent.
+ *
+ * \param socket: the connected socket currently opened.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer in which data is contained.
+ *
+ * \param size: number of bytes that have to be sent.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if an error other than
+ * "connection reset" or "peer has closed the receive side" occurred,
+ * '-2' if we got one of those errors.
+ * For errors, an error message is returned in the 'errbuf' variable.
+ */
+int sock_send(SOCKET sock, const char *buffer, size_t size,
+ char *errbuf, int errbuflen)
+{
+ int remaining;
+ ssize_t nsent;
+
+ if (size > INT_MAX)
+ {
+ if (errbuf)
+ {
+ pcap_snprintf(errbuf, errbuflen,
+ "Can't send more than %u bytes with sock_send",
+ INT_MAX);
+ }
+ return -1;
+ }
+ remaining = (int)size;
+
+ do {
+#ifdef MSG_NOSIGNAL
+ /*
+ * Send with MSG_NOSIGNAL, so that we don't get SIGPIPE
+ * on errors on stream-oriented sockets when the other
+ * end breaks the connection.
+ * The EPIPE error is still returned.
+ */
+ nsent = send(sock, buffer, remaining, MSG_NOSIGNAL);
+#else
+ nsent = send(sock, buffer, remaining, 0);
+#endif
+
+ if (nsent == -1)
+ {
+ /*
+ * If the client closed the connection out from
+ * under us, there's no need to log that as an
+ * error.
+ */
+ int errcode;
+
+#ifdef _WIN32
+ errcode = GetLastError();
+ if (errcode == WSAECONNRESET ||
+ errcode == WSAECONNABORTED)
+ {
+ /*
+ * WSAECONNABORTED appears to be the error
+ * returned in Winsock when you try to send
+ * on a connection where the peer has closed
+ * the receive side.
+ */
+ return -2;
+ }
+ sock_fmterror("send()", errcode, errbuf, errbuflen);
+#else
+ errcode = errno;
+ if (errcode == ECONNRESET || errcode == EPIPE)
+ {
+ /*
+ * EPIPE is what's returned on UN*X when
+ * you try to send on a connection when
+ * the peer has closed the receive side.
+ */
+ return -2;
+ }
+ sock_fmterror("send()", errcode, errbuf, errbuflen);
+#endif
+ return -1;
+ }
+
+ remaining -= nsent;
+ buffer += nsent;
+ } while (remaining != 0);
+
+ return 0;
+}
+
+/*
+ * \brief It copies the amount of data contained into 'buffer' into 'tempbuf'.
+ * and it checks for buffer overflows.
+ *
+ * This function basically copies 'size' bytes of data contained into 'buffer'
+ * into 'tempbuf', starting at offset 'offset'. Before that, it checks that the
+ * resulting buffer will not be larger than 'totsize'. Finally, it updates
+ * the 'offset' variable in order to point to the first empty location of the buffer.
+ *
+ * In case the function is called with 'checkonly' equal to 1, it does not copy
+ * the data into the buffer. It only checks for buffer overflows and it updates the
+ * 'offset' variable. This mode can be useful when the buffer already contains the
+ * data (maybe because the producer writes directly into the target buffer), so
+ * only the buffer overflow check has to be made.
+ * In this case, both 'buffer' and 'tempbuf' can be NULL values.
+ *
+ * This function is useful in case the userland application does not know immediately
+ * all the data it has to write into the socket. This function provides a way to create
+ * the "stream" step by step, appending the new data to the old one. Then, when all the
+ * data has been bufferized, the application can call the sock_send() function.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer that keeps the data
+ * that has to be copied.
+ *
+ * \param size: number of bytes that have to be copied.
+ *
+ * \param tempbuf: user-allocated buffer (of size 'totsize') in which data
+ * has to be copied.
+ *
+ * \param offset: an index into 'tempbuf' which keeps the location of its first
+ * empty location.
+ *
+ * \param totsize: total size of the buffer in which data is being copied.
+ *
+ * \param checkonly: '1' if we do not want to copy data into the buffer and we
+ * want just do a buffer ovreflow control, '0' if data has to be copied as well.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred. The error message
+ * is returned in the 'errbuf' variable. When the function returns, 'tempbuf' will
+ * have the new string appended, and 'offset' will keep the length of that buffer.
+ * In case of 'checkonly == 1', data is not copied, but 'offset' is updated in any case.
+ *
+ * \warning This function assumes that the buffer in which data has to be stored is
+ * large 'totbuf' bytes.
+ *
+ * \warning In case of 'checkonly', be carefully to call this function *before* copying
+ * the data into the buffer. Otherwise, the control about the buffer overflow is useless.
+ */
+int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen)
+{
+ if ((*offset + size) > totsize)
+ {
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "Not enough space in the temporary send buffer.");
+ return -1;
+ }
+
+ if (!checkonly)
+ memcpy(tempbuf + (*offset), buffer, size);
+
+ (*offset) += size;
+
+ return 0;
+}
+
+/*
+ * \brief It waits on a connected socket and it manages to receive data.
+ *
+ * This function basically calls the recv() socket function and it checks that no
+ * error occurred. If that happens, it writes the error message into 'errbuf'.
+ *
+ * This function changes its behavior according to the 'receiveall' flag: if we
+ * want to receive exactly 'size' byte, it loops on the recv() until all the requested
+ * data is arrived. Otherwise, it returns the data currently available.
+ *
+ * In case the socket does not have enough data available, it cycles on the recv()
+ * until the requested data (of size 'size') is arrived.
+ * In this case, it blocks until the number of bytes read is equal to 'size'.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param buffer: a char pointer to a user-allocated buffer in which data has to be stored
+ *
+ * \param size: size of the allocated buffer. WARNING: this indicates the number of bytes
+ * that we are expecting to be read.
+ *
+ * \param flags:
+ *
+ * SOCK_RECEIVALL_XXX:
+ *
+ * if SOCK_RECEIVEALL_NO, return as soon as some data is ready
+ * if SOCK_RECEIVALL_YES, wait until 'size' data has been
+ * received (in case the socket does not have enough data available).
+ *
+ * SOCK_EOF_XXX:
+ *
+ * if SOCK_EOF_ISNT_ERROR, if the first read returns 0, just return 0,
+ * and return an error on any subsequent read that returns 0;
+ * if SOCK_EOF_IS_ERROR, if any read returns 0, return an error.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return the number of bytes read if everything is fine, '-1' if some errors occurred.
+ * The error message is returned in the 'errbuf' variable.
+ */
+
+int sock_recv(SOCKET sock, void *buffer, size_t size, int flags,
+ char *errbuf, int errbuflen)
+{
+ char *bufp = buffer;
+ int remaining;
+ ssize_t nread;
+
+ if (size == 0)
+ {
+ return 0;
+ }
+ if (size > INT_MAX)
+ {
+ if (errbuf)
+ {
+ pcap_snprintf(errbuf, errbuflen,
+ "Can't read more than %u bytes with sock_recv",
+ INT_MAX);
+ }
+ return -1;
+ }
+
+ bufp = (char *) buffer;
+ remaining = (int) size;
+
+ /*
+ * We don't use MSG_WAITALL because it's not supported in
+ * Win32.
+ */
+ for (;;) {
+ nread = recv(sock, bufp, remaining, 0);
+
+ if (nread == -1)
+ {
+#ifndef _WIN32
+ if (errno == EINTR)
+ return -3;
+#endif
+ sock_geterror("recv()", errbuf, errbuflen);
+ return -1;
+ }
+
+ if (nread == 0)
+ {
+ if ((flags & SOCK_EOF_IS_ERROR) ||
+ (remaining != (int) size))
+ {
+ /*
+ * Either we've already read some data,
+ * or we're always supposed to return
+ * an error on EOF.
+ */
+ if (errbuf)
+ {
+ pcap_snprintf(errbuf, errbuflen,
+ "The other host terminated the connection.");
+ }
+ return -1;
+ }
+ else
+ return 0;
+ }
+
+ /*
+ * Do we want to read the amount requested, or just return
+ * what we got?
+ */
+ if (!(flags & SOCK_RECEIVEALL_YES))
+ {
+ /*
+ * Just return what we got.
+ */
+ return (int) nread;
+ }
+
+ bufp += nread;
+ remaining -= nread;
+
+ if (remaining == 0)
+ return (int) size;
+ }
+}
+
+/*
+ * Receives a datagram from a socket.
+ *
+ * Returns the size of the datagram on success or -1 on error.
+ */
+int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+ char *errbuf, int errbuflen)
+{
+ ssize_t nread;
+#ifndef _WIN32
+ struct msghdr message;
+ struct iovec iov;
+#endif
+
+ if (size == 0)
+ {
+ return 0;
+ }
+ if (size > INT_MAX)
+ {
+ if (errbuf)
+ {
+ pcap_snprintf(errbuf, errbuflen,
+ "Can't read more than %u bytes with sock_recv_dgram",
+ INT_MAX);
+ }
+ return -1;
+ }
+
+ /*
+ * This should be a datagram socket, so we should get the
+ * entire datagram in one recv() or recvmsg() call, and
+ * don't need to loop.
+ */
+#ifdef _WIN32
+ nread = recv(sock, buffer, size, 0);
+ if (nread == SOCKET_ERROR)
+ {
+ /*
+ * To quote the MSDN documentation for recv(),
+ * "If the datagram or message is larger than
+ * the buffer specified, the buffer is filled
+ * with the first part of the datagram, and recv
+ * generates the error WSAEMSGSIZE. For unreliable
+ * protocols (for example, UDP) the excess data is
+ * lost..."
+ *
+ * So if the message is bigger than the buffer
+ * supplied to us, the excess data is discarded,
+ * and we'll report an error.
+ */
+ sock_geterror("recv()", errbuf, errbuflen);
+ return -1;
+ }
+#else /* _WIN32 */
+ /*
+ * The Single UNIX Specification says that a recv() on
+ * a socket for a message-oriented protocol will discard
+ * the excess data. It does *not* indicate that the
+ * receive will fail with, for example, EMSGSIZE.
+ *
+ * Therefore, we use recvmsg(), which appears to be
+ * the only way to get a "message truncated" indication
+ * when receiving a message for a message-oriented
+ * protocol.
+ */
+ message.msg_name = NULL; /* we don't care who it's from */
+ message.msg_namelen = 0;
+ iov.iov_base = buffer;
+ iov.iov_len = size;
+ message.msg_iov = &iov;
+ message.msg_iovlen = 1;
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ message.msg_control = NULL; /* we don't care about control information */
+ message.msg_controllen = 0;
+#endif
+#ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS
+ message.msg_flags = 0;
+#endif
+ nread = recvmsg(sock, &message, 0);
+ if (nread == -1)
+ {
+ if (errno == EINTR)
+ return -3;
+ sock_geterror("recv()", errbuf, errbuflen);
+ return -1;
+ }
+#ifdef HAVE_STRUCT_MSGHDR_MSG_FLAGS
+ /*
+ * XXX - Solaris supports this, but only if you ask for the
+ * X/Open version of recvmsg(); should we use that, or will
+ * that cause other problems?
+ */
+ if (message.msg_flags & MSG_TRUNC)
+ {
+ /*
+ * Message was bigger than the specified buffer size.
+ *
+ * Report this as an error, as the Microsoft documentation
+ * implies we'd do in a similar case on Windows.
+ */
+ pcap_snprintf(errbuf, errbuflen, "recv(): Message too long");
+ return -1;
+ }
+#endif /* HAVE_STRUCT_MSGHDR_MSG_FLAGS */
+#endif /* _WIN32 */
+
+ /*
+ * The size we're reading fits in an int, so the return value
+ * will fit in an int.
+ */
+ return (int)nread;
+}
+
+/*
+ * \brief It discards N bytes that are currently waiting to be read on the current socket.
+ *
+ * This function is useful in case we receive a message we cannot understand (e.g.
+ * wrong version number when receiving a network packet), so that we have to discard all
+ * data before reading a new message.
+ *
+ * This function will read 'size' bytes from the socket and discard them.
+ * It defines an internal buffer in which data will be copied; however, in case
+ * this buffer is not large enough, it will cycle in order to read everything as well.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param size: number of bytes that have to be discarded.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '0' if everything is fine, '-1' if some errors occurred.
+ * The error message is returned in the 'errbuf' variable.
+ */
+int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen)
+{
+#define TEMP_BUF_SIZE 32768
+
+ char buffer[TEMP_BUF_SIZE]; /* network buffer, to be used when the message is discarded */
+
+ /*
+ * A static allocation avoids the need of a 'malloc()' each time we want to discard a message
+ * Our feeling is that a buffer if 32KB is enough for most of the application;
+ * in case this is not enough, the "while" loop discards the message by calling the
+ * sockrecv() several times.
+ * We do not want to create a bigger variable because this causes the program to exit on
+ * some platforms (e.g. BSD)
+ */
+ while (size > TEMP_BUF_SIZE)
+ {
+ if (sock_recv(sock, buffer, TEMP_BUF_SIZE, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+ return -1;
+
+ size -= TEMP_BUF_SIZE;
+ }
+
+ /*
+ * If there is still data to be discarded
+ * In this case, the data can fit into the temporary buffer
+ */
+ if (size)
+ {
+ if (sock_recv(sock, buffer, size, SOCK_RECEIVEALL_YES, errbuf, errbuflen) == -1)
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * \brief Checks that one host (identified by the sockaddr_storage structure) belongs to an 'allowed list'.
+ *
+ * This function is useful after an accept() call in order to check if the connecting
+ * host is allowed to connect to me. To do that, we have a buffer that keeps the list of the
+ * allowed host; this function checks the sockaddr_storage structure of the connecting host
+ * against this host list, and it returns '0' is the host is included in this list.
+ *
+ * \param hostlist: pointer to a string that contains the list of the allowed host.
+ *
+ * \param sep: a string that keeps the separators used between the hosts (for example the
+ * space character) in the host list.
+ *
+ * \param from: a sockaddr_storage structure, as it is returned by the accept() call.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns:
+ * - '1' if the host list is empty
+ * - '0' if the host belongs to the host list (and therefore it is allowed to connect)
+ * - '-1' in case the host does not belong to the host list (and therefore it is not allowed to connect
+ * - '-2' in case or error. The error message is returned in the 'errbuf' variable.
+ */
+int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen)
+{
+ /* checks if the connecting host is among the ones allowed */
+ if ((hostlist) && (hostlist[0]))
+ {
+ char *token; /* temp, needed to separate items into the hostlist */
+ struct addrinfo *addrinfo, *ai_next;
+ char *temphostlist;
+ char *lasts;
+ int getaddrinfo_failed = 0;
+
+ /*
+ * The problem is that strtok modifies the original variable by putting '0' at the end of each token
+ * So, we have to create a new temporary string in which the original content is kept
+ */
+ temphostlist = strdup(hostlist);
+ if (temphostlist == NULL)
+ {
+ sock_geterror("sock_check_hostlist(), malloc() failed", errbuf, errbuflen);
+ return -2;
+ }
+
+ token = pcap_strtok_r(temphostlist, sep, &lasts);
+
+ /* it avoids a warning in the compilation ('addrinfo used but not initialized') */
+ addrinfo = NULL;
+
+ while (token != NULL)
+ {
+ struct addrinfo hints;
+ int retval;
+
+ addrinfo = NULL;
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+
+ retval = getaddrinfo(token, NULL, &hints, &addrinfo);
+ if (retval != 0)
+ {
+ if (errbuf)
+ get_gai_errstring(errbuf, errbuflen,
+ "Allowed host list error: ",
+ retval, token, NULL);
+
+ /*
+ * Note that at least one call to getaddrinfo()
+ * failed.
+ */
+ getaddrinfo_failed = 1;
+
+ /* Get next token */
+ token = pcap_strtok_r(NULL, sep, &lasts);
+ continue;
+ }
+
+ /* ai_next is required to preserve the content of addrinfo, in order to deallocate it properly */
+ ai_next = addrinfo;
+ while (ai_next)
+ {
+ if (sock_cmpaddr(from, (struct sockaddr_storage *) ai_next->ai_addr) == 0)
+ {
+ free(temphostlist);
+ freeaddrinfo(addrinfo);
+ return 0;
+ }
+
+ /*
+ * If we are here, it means that the current address does not matches
+ * Let's try with the next one in the header chain
+ */
+ ai_next = ai_next->ai_next;
+ }
+
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+
+ /* Get next token */
+ token = pcap_strtok_r(NULL, sep, &lasts);
+ }
+
+ if (addrinfo)
+ {
+ freeaddrinfo(addrinfo);
+ addrinfo = NULL;
+ }
+
+ free(temphostlist);
+
+ if (getaddrinfo_failed) {
+ /*
+ * At least one getaddrinfo() call failed;
+ * treat that as an error, so rpcapd knows
+ * that it should log it locally as well
+ * as telling the client about it.
+ */
+ return -2;
+ } else {
+ /*
+ * All getaddrinfo() calls succeeded, but
+ * the host wasn't in the list.
+ */
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "The host is not in the allowed host list. Connection refused.");
+ return -1;
+ }
+ }
+
+ /* No hostlist, so we have to return 'empty list' */
+ return 1;
+}
+
+/*
+ * \brief Compares two addresses contained into two sockaddr_storage structures.
+ *
+ * This function is useful to compare two addresses, given their internal representation,
+ * i.e. an sockaddr_storage structure.
+ *
+ * The two structures do not need to be sockaddr_storage; you can have both 'sockaddr_in' and
+ * sockaddr_in6, properly acsted in order to be compliant to the function interface.
+ *
+ * This function will return '0' if the two addresses matches, '-1' if not.
+ *
+ * \param first: a sockaddr_storage structure, (for example the one that is returned by an
+ * accept() call), containing the first address to compare.
+ *
+ * \param second: a sockaddr_storage structure containing the second address to compare.
+ *
+ * \return '0' if the addresses are equal, '-1' if they are different.
+ */
+int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second)
+{
+ if (first->ss_family == second->ss_family)
+ {
+ if (first->ss_family == AF_INET)
+ {
+ if (memcmp(&(((struct sockaddr_in *) first)->sin_addr),
+ &(((struct sockaddr_in *) second)->sin_addr),
+ sizeof(struct in_addr)) == 0)
+ return 0;
+ }
+ else /* address family is AF_INET6 */
+ {
+ if (memcmp(&(((struct sockaddr_in6 *) first)->sin6_addr),
+ &(((struct sockaddr_in6 *) second)->sin6_addr),
+ sizeof(struct in6_addr)) == 0)
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/*
+ * \brief It gets the address/port the system picked for this socket (on connected sockets).
+ *
+ * It is used to return the address and port the server picked for our socket on the local machine.
+ * It works only on:
+ * - connected sockets
+ * - server sockets
+ *
+ * On unconnected client sockets it does not work because the system dynamically chooses a port
+ * only when the socket calls a send() call.
+ *
+ * \param sock: the connected socket currently opened.
+ *
+ * \param address: it contains the address that will be returned by the function. This buffer
+ * must be properly allocated by the user. The address can be either literal or numeric depending
+ * on the value of 'Flags'.
+ *
+ * \param addrlen: the length of the 'address' buffer.
+ *
+ * \param port: it contains the port that will be returned by the function. This buffer
+ * must be properly allocated by the user.
+ *
+ * \param portlen: the length of the 'port' buffer.
+ *
+ * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function)
+ * that determine if the resulting address must be in numeric / literal form, and so on.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns '-1' if this function succeeds, '0' otherwise.
+ * The address and port corresponding are returned back in the buffers 'address' and 'port'.
+ * In any case, the returned strings are '0' terminated.
+ *
+ * \warning If the socket is using a connectionless protocol, the address may not be available
+ * until I/O occurs on the socket.
+ */
+int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
+{
+ struct sockaddr_storage mysockaddr;
+ socklen_t sockaddrlen;
+
+
+ sockaddrlen = sizeof(struct sockaddr_storage);
+
+ if (getsockname(sock, (struct sockaddr *) &mysockaddr, &sockaddrlen) == -1)
+ {
+ sock_geterror("getsockname()", errbuf, errbuflen);
+ return 0;
+ }
+
+ /* Returns the numeric address of the host that triggered the error */
+ return sock_getascii_addrport(&mysockaddr, address, addrlen, port, portlen, flags, errbuf, errbuflen);
+}
+
+/*
+ * \brief It retrieves two strings containing the address and the port of a given 'sockaddr' variable.
+ *
+ * This function is basically an extended version of the inet_ntop(), which does not exist in
+ * Winsock because the same result can be obtained by using the getnameinfo().
+ * However, differently from inet_ntop(), this function is able to return also literal names
+ * (e.g. 'localhost') dependently from the 'Flags' parameter.
+ *
+ * The function accepts a sockaddr_storage variable (which can be returned by several functions
+ * like bind(), connect(), accept(), and more) and it transforms its content into a 'human'
+ * form. So, for instance, it is able to translate an hex address (stored in binary form) into
+ * a standard IPv6 address like "::1".
+ *
+ * The behavior of this function depends on the parameters we have in the 'Flags' variable, which
+ * are the ones allowed in the standard getnameinfo() socket function.
+ *
+ * \param sockaddr: a 'sockaddr_in' or 'sockaddr_in6' structure containing the address that
+ * need to be translated from network form into the presentation form. This structure must be
+ * zero-ed prior using it, and the address family field must be filled with the proper value.
+ * The user must cast any 'sockaddr_in' or 'sockaddr_in6' structures to 'sockaddr_storage' before
+ * calling this function.
+ *
+ * \param address: it contains the address that will be returned by the function. This buffer
+ * must be properly allocated by the user. The address can be either literal or numeric depending
+ * on the value of 'Flags'.
+ *
+ * \param addrlen: the length of the 'address' buffer.
+ *
+ * \param port: it contains the port that will be returned by the function. This buffer
+ * must be properly allocated by the user.
+ *
+ * \param portlen: the length of the 'port' buffer.
+ *
+ * \param flags: a set of flags (the ones defined into the getnameinfo() standard socket function)
+ * that determine if the resulting address must be in numeric / literal form, and so on.
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return It returns '-1' if this function succeeds, '0' otherwise.
+ * The address and port corresponding to the given SockAddr are returned back in the buffers 'address'
+ * and 'port'.
+ * In any case, the returned strings are '0' terminated.
+ */
+int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen)
+{
+ socklen_t sockaddrlen;
+ int retval; /* Variable that keeps the return value; */
+
+ retval = -1;
+
+#ifdef _WIN32
+ if (sockaddr->ss_family == AF_INET)
+ sockaddrlen = sizeof(struct sockaddr_in);
+ else
+ sockaddrlen = sizeof(struct sockaddr_in6);
+#else
+ sockaddrlen = sizeof(struct sockaddr_storage);
+#endif
+
+ if ((flags & NI_NUMERICHOST) == 0) /* Check that we want literal names */
+ {
+ if ((sockaddr->ss_family == AF_INET6) &&
+ (memcmp(&((struct sockaddr_in6 *) sockaddr)->sin6_addr, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", sizeof(struct in6_addr)) == 0))
+ {
+ if (address)
+ pcap_strlcpy(address, SOCKET_NAME_NULL_DAD, addrlen);
+ return retval;
+ }
+ }
+
+ if (getnameinfo((struct sockaddr *) sockaddr, sockaddrlen, address, addrlen, port, portlen, flags) != 0)
+ {
+ /* If the user wants to receive an error message */
+ if (errbuf)
+ {
+ sock_geterror("getnameinfo()", errbuf, errbuflen);
+ errbuf[errbuflen - 1] = 0;
+ }
+
+ if (address)
+ {
+ pcap_strlcpy(address, SOCKET_NO_NAME_AVAILABLE, addrlen);
+ address[addrlen - 1] = 0;
+ }
+
+ if (port)
+ {
+ pcap_strlcpy(port, SOCKET_NO_PORT_AVAILABLE, portlen);
+ port[portlen - 1] = 0;
+ }
+
+ retval = 0;
+ }
+
+ return retval;
+}
+
+/*
+ * \brief It translates an address from the 'presentation' form into the 'network' form.
+ *
+ * This function basically replaces inet_pton(), which does not exist in Winsock because
+ * the same result can be obtained by using the getaddrinfo().
+ * An additional advantage is that 'Address' can be both a numeric address (e.g. '127.0.0.1',
+ * like in inet_pton() ) and a literal name (e.g. 'localhost').
+ *
+ * This function does the reverse job of sock_getascii_addrport().
+ *
+ * \param address: a zero-terminated string which contains the name you have to
+ * translate. The name can be either literal (e.g. 'localhost') or numeric (e.g. '::1').
+ *
+ * \param sockaddr: a user-allocated sockaddr_storage structure which will contains the
+ * 'network' form of the requested address.
+ *
+ * \param addr_family: a constant which can assume the following values:
+ * - 'AF_INET' if we want to ping an IPv4 host
+ * - 'AF_INET6' if we want to ping an IPv6 host
+ * - 'AF_UNSPEC' if we do not have preferences about the protocol used to ping the host
+ *
+ * \param errbuf: a pointer to an user-allocated buffer that will contain the complete
+ * error message. This buffer has to be at least 'errbuflen' in length.
+ * It can be NULL; in this case the error cannot be printed.
+ *
+ * \param errbuflen: length of the buffer that will contains the error. The error message cannot be
+ * larger than 'errbuflen - 1' because the last char is reserved for the string terminator.
+ *
+ * \return '-1' if the translation succeeded, '-2' if there was some non critical error, '0'
+ * otherwise. In case it fails, the content of the SockAddr variable remains unchanged.
+ * A 'non critical error' can occur in case the 'Address' is a literal name, which can be mapped
+ * to several network addresses (e.g. 'foo.bar.com' => '10.2.2.2' and '10.2.2.3'). In this case
+ * the content of the SockAddr parameter will be the address corresponding to the first mapping.
+ *
+ * \warning The sockaddr_storage structure MUST be allocated by the user.
+ */
+int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen)
+{
+ int retval;
+ struct addrinfo *addrinfo;
+ struct addrinfo hints;
+
+ memset(&hints, 0, sizeof(hints));
+
+ hints.ai_family = addr_family;
+
+ if ((retval = sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen)) == -1)
+ return 0;
+
+ if (addrinfo->ai_family == PF_INET)
+ memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in));
+ else
+ memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in6));
+
+ if (addrinfo->ai_next != NULL)
+ {
+ freeaddrinfo(addrinfo);
+
+ if (errbuf)
+ pcap_snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned");
+ return -2;
+ }
+
+ freeaddrinfo(addrinfo);
+ return -1;
+}
diff --git a/lib/libpcap/libpcap/sockutils.h b/lib/libpcap/libpcap/sockutils.h
new file mode 100644
index 0000000..8a45b3d
--- /dev/null
+++ b/lib/libpcap/libpcap/sockutils.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2002 - 2003
+ * NetGroup, Politecnico di Torino (Italy)
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Politecnico di Torino nor the names 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.
+ *
+ */
+
+#ifndef __SOCKUTILS_H__
+#define __SOCKUTILS_H__
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+#include "pcap/socket.h"
+
+#ifndef _WIN32
+ /* UN*X */
+ #include <unistd.h> /* close() */
+
+ /*!
+ * \brief In Winsock, the close() call cannot be used on a socket;
+ * closesocket() must be used.
+ * We define closesocket() to be a wrapper around close() on UN*X,
+ * so that it can be used on both platforms.
+ */
+ #define closesocket(a) close(a)
+#endif
+
+/*
+ * MingW headers include this definition, but only for Windows XP and above.
+ * MSDN states that this function is available for most versions on Windows.
+ */
+#if ((defined(__MINGW32__)) && (_WIN32_WINNT < 0x0501))
+int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
+ char*,DWORD,int);
+#endif
+
+/*
+ * \defgroup SockUtils Cross-platform socket utilities (IPv4-IPv6)
+ */
+
+/*
+ * \addtogroup SockUtils
+ * \{
+ */
+
+/*
+ * \defgroup ExportedStruct Exported Structures and Definitions
+ */
+
+/*
+ * \addtogroup ExportedStruct
+ * \{
+ */
+
+/****************************************************
+ * *
+ * Exported functions / definitions *
+ * *
+ ****************************************************/
+
+/* 'checkonly' flag, into the rpsock_bufferize() */
+#define SOCKBUF_CHECKONLY 1
+/* no 'checkonly' flag, into the rpsock_bufferize() */
+#define SOCKBUF_BUFFERIZE 0
+
+/* no 'server' flag; it opens a client socket */
+#define SOCKOPEN_CLIENT 0
+/* 'server' flag; it opens a server socket */
+#define SOCKOPEN_SERVER 1
+
+/*
+ * Flags for sock_recv().
+ */
+#define SOCK_RECEIVEALL_NO 0x00000000 /* Don't wait to receive all data */
+#define SOCK_RECEIVEALL_YES 0x00000001 /* Wait to receive all data */
+
+#define SOCK_EOF_ISNT_ERROR 0x00000000 /* Return 0 on EOF */
+#define SOCK_EOF_IS_ERROR 0x00000002 /* Return an error on EOF */
+
+/*
+ * \}
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * \defgroup ExportedFunc Exported Functions
+ */
+
+/*
+ * \addtogroup ExportedFunc
+ * \{
+ */
+
+int sock_init(char *errbuf, int errbuflen);
+void sock_cleanup(void);
+void sock_fmterror(const char *caller, int errcode, char *errbuf, int errbuflen);
+void sock_geterror(const char *caller, char *errbuf, int errbufsize);
+int sock_initaddress(const char *address, const char *port,
+ struct addrinfo *hints, struct addrinfo **addrinfo,
+ char *errbuf, int errbuflen);
+int sock_recv(SOCKET sock, void *buffer, size_t size, int receiveall,
+ char *errbuf, int errbuflen);
+int sock_recv_dgram(SOCKET sock, void *buffer, size_t size,
+ char *errbuf, int errbuflen);
+SOCKET sock_open(struct addrinfo *addrinfo, int server, int nconn, char *errbuf, int errbuflen);
+int sock_close(SOCKET sock, char *errbuf, int errbuflen);
+
+int sock_send(SOCKET sock, const char *buffer, size_t size,
+ char *errbuf, int errbuflen);
+int sock_bufferize(const char *buffer, int size, char *tempbuf, int *offset, int totsize, int checkonly, char *errbuf, int errbuflen);
+int sock_discard(SOCKET sock, int size, char *errbuf, int errbuflen);
+int sock_check_hostlist(char *hostlist, const char *sep, struct sockaddr_storage *from, char *errbuf, int errbuflen);
+int sock_cmpaddr(struct sockaddr_storage *first, struct sockaddr_storage *second);
+
+int sock_getmyinfo(SOCKET sock, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen);
+
+int sock_getascii_addrport(const struct sockaddr_storage *sockaddr, char *address, int addrlen, char *port, int portlen, int flags, char *errbuf, int errbuflen);
+int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen);
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+ * \}
+ */
+
+/*
+ * \}
+ */
+
+#endif
diff --git a/lib/libpcap/libpcap/sunatmpos.h b/lib/libpcap/libpcap/sunatmpos.h
new file mode 100644
index 0000000..787de85
--- /dev/null
+++ b/lib/libpcap/libpcap/sunatmpos.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1997 Yen Yen Lim and North Dakota State University
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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 Yen Yen Lim and
+ North Dakota State University
+ * 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.
+ */
+
+/* SunATM header for ATM packet */
+#define SUNATM_DIR_POS 0
+#define SUNATM_VPI_POS 1
+#define SUNATM_VCI_POS 2
+#define SUNATM_PKT_BEGIN_POS 4 /* Start of ATM packet */
+
+/* Protocol type values in the bottom for bits of the byte at SUNATM_DIR_POS. */
+#define PT_LANE 0x01 /* LANE */
+#define PT_LLC 0x02 /* LLC encapsulation */
+#define PT_ILMI 0x05 /* ILMI */
+#define PT_QSAAL 0x06 /* Q.SAAL */
diff --git a/lib/libpcap/libpcap/testprogs/CMakeLists.txt b/lib/libpcap/libpcap/testprogs/CMakeLists.txt
new file mode 100644
index 0000000..b8ef9b7
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/CMakeLists.txt
@@ -0,0 +1,40 @@
+if(MSVC)
+ file(GLOB PROJECT_SOURCE_LIST_WIN32_C ${pcap_SOURCE_DIR}/missing/getopt.c)
+ include_directories(${pcap_SOURCE_DIR}/missing)
+endif(MSVC)
+
+add_custom_target(testprogs)
+
+macro(add_test_executable _executable)
+ add_executable(${_executable} EXCLUDE_FROM_ALL
+ ${_executable}.c ${PROJECT_SOURCE_LIST_WIN32_C})
+ if(NOT C_ADDITIONAL_FLAGS STREQUAL "")
+ set_target_properties(${_executable} PROPERTIES
+ COMPILE_FLAGS ${C_ADDITIONAL_FLAGS})
+ endif()
+ if(WIN32)
+ target_link_libraries(${_executable}
+ ${ARGN} ${LIBRARY_NAME} ${PCAP_LINK_LIBRARIES})
+ else(WIN32)
+ target_link_libraries(${_executable}
+ ${ARGN} ${LIBRARY_NAME}_static ${PCAP_LINK_LIBRARIES})
+ endif(WIN32)
+ add_dependencies(testprogs ${_executable})
+endmacro()
+
+add_test_executable(can_set_rfmon_test)
+add_test_executable(capturetest)
+add_test_executable(filtertest)
+add_test_executable(findalldevstest)
+add_test_executable(opentest)
+add_test_executable(reactivatetest)
+
+if(NOT WIN32)
+ add_test_executable(selpolltest)
+endif()
+
+add_test_executable(threadsignaltest ${CMAKE_THREAD_LIBS_INIT})
+
+if(NOT WIN32)
+ add_test_executable(valgrindtest)
+endif()
diff --git a/lib/libpcap/libpcap/testprogs/Makefile b/lib/libpcap/libpcap/testprogs/Makefile
new file mode 100644
index 0000000..f642799
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/Makefile
@@ -0,0 +1,144 @@
+# Copyright (c) 1993, 1994, 1995, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = /usr/local
+exec_prefix = ${prefix}
+datarootdir = ${prefix}/share
+# Pathname of directory to install the configure program
+bindir = ${exec_prefix}/bin
+# Pathname of directory to install the rpcapd daemon
+sbindir = ${exec_prefix}/sbin
+# Pathname of directory to install the include files
+includedir = ${prefix}/include
+# Pathname of directory to install the library
+libdir = ${exec_prefix}/lib
+# Pathname of directory to install the man pages
+mandir = ${datarootdir}/man
+
+# VPATH
+srcdir = .
+
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = gcc
+AR = ar
+LN_S = ln -s
+MKDEP =
+CCOPT = -fvisibility=hidden -fno-common
+INCLS = -I. -I.. -I. -I./.. -I/usr/local/include
+DEFS = -DHAVE_CONFIG_H
+ADDLOBJS =
+ADDLARCHIVEOBJS =
+LIBS =
+PTHREAD_LIBS =
+CROSSFLAGS=
+CFLAGS = -g -O2 ${CROSSFLAGS}
+LDFLAGS = ${CROSSFLAGS}
+DYEXT = dylib
+V_RPATH_OPT =
+DEPENDENCY_CFLAG =
+EXTRA_NETWORK_LIBS=
+
+# Standard CFLAGS for building test programs
+FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = /usr/bin/install -c
+INSTALL_PROGRAM = ${INSTALL}
+INSTALL_DATA = ${INSTALL} -m 644
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+ @rm -f $@
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+SRC = valgrindtest.c \
+ capturetest.c \
+ can_set_rfmon_test.c \
+ filtertest.c \
+ findalldevstest.c \
+ opentest.c \
+ reactivatetest.c \
+ selpolltest.c \
+ threadsignaltest.c
+
+TESTS = $(SRC:.c=)
+
+TAGFILES = \
+ $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) $(TESTS)
+
+all: $(TESTS)
+
+capturetest: $(srcdir)/capturetest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o capturetest $(srcdir)/capturetest.c ../libpcap.a $(LIBS)
+
+can_set_rfmon_test: $(srcdir)/can_set_rfmon_test.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o can_set_rfmon_test $(srcdir)/can_set_rfmon_test.c ../libpcap.a $(LIBS)
+
+filtertest: $(srcdir)/filtertest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/filtertest.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
+
+findalldevstest: $(srcdir)/findalldevstest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o findalldevstest $(srcdir)/findalldevstest.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
+
+opentest: $(srcdir)/opentest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o opentest $(srcdir)/opentest.c ../libpcap.a $(LIBS)
+
+reactivatetest: $(srcdir)/reactivatetest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o reactivatetest $(srcdir)/reactivatetest.c ../libpcap.a $(LIBS)
+
+selpolltest: $(srcdir)/selpolltest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/selpolltest.c ../libpcap.a $(LIBS)
+
+threadsignaltest: $(srcdir)/threadsignaltest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o threadsignaltest $(srcdir)/threadsignaltest.c ../libpcap.a $(LIBS) $(PTHREAD_LIBS)
+
+valgrindtest: $(srcdir)/valgrindtest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/valgrindtest.c ../libpcap.a $(LIBS)
+
+clean:
+ rm -f $(CLEANFILES)
+ rm -rf *.dSYM
+
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
+ config.h stamp-h stamp-h.in
+ rm -rf autom4te.cache
+
+install:
+
+uninstall:
+
+tags: $(TAGFILES)
+ ctags -wtd $(TAGFILES)
+
+depend:
+ ../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/lib/libpcap/libpcap/testprogs/Makefile.in b/lib/libpcap/libpcap/testprogs/Makefile.in
new file mode 100644
index 0000000..ec0a472
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/Makefile.in
@@ -0,0 +1,144 @@
+# Copyright (c) 1993, 1994, 1995, 1996
+# The Regents of the University of California. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that: (1) source code distributions
+# retain the above copyright notice and this paragraph in its entirety, (2)
+# distributions including binary code include the above copyright notice and
+# this paragraph in its entirety in the documentation or other materials
+# provided with the distribution, and (3) all advertising materials mentioning
+# features or use of this software display the following acknowledgement:
+# ``This product includes software developed by the University of California,
+# Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+# the University nor the names of its contributors may be used to endorse
+# or promote products derived from this software without specific prior
+# written permission.
+# THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+# WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+
+#
+# Various configurable paths (remember to edit Makefile.in, not Makefile)
+#
+
+# Top level hierarchy
+prefix = @prefix@
+exec_prefix = @exec_prefix@
+datarootdir = @datarootdir@
+# Pathname of directory to install the configure program
+bindir = @bindir@
+# Pathname of directory to install the rpcapd daemon
+sbindir = @sbindir@
+# Pathname of directory to install the include files
+includedir = @includedir@
+# Pathname of directory to install the library
+libdir = @libdir@
+# Pathname of directory to install the man pages
+mandir = @mandir@
+
+# VPATH
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+#
+# You shouldn't need to edit anything below.
+#
+
+LD = /usr/bin/ld
+CC = @CC@
+AR = @AR@
+LN_S = @LN_S@
+MKDEP = @MKDEP@
+CCOPT = @V_CCOPT@
+INCLS = -I. -I.. -I@srcdir@ -I@srcdir@/.. @V_INCLS@
+DEFS = @DEFS@ @V_DEFS@
+ADDLOBJS = @ADDLOBJS@
+ADDLARCHIVEOBJS = @ADDLARCHIVEOBJS@
+LIBS = @LIBS@
+PTHREAD_LIBS = @PTHREAD_LIBS@
+CROSSFLAGS=
+CFLAGS = @CFLAGS@ ${CROSSFLAGS}
+LDFLAGS = @LDFLAGS@ ${CROSSFLAGS}
+DYEXT = @DYEXT@
+V_RPATH_OPT = @V_RPATH_OPT@
+DEPENDENCY_CFLAG = @DEPENDENCY_CFLAG@
+EXTRA_NETWORK_LIBS=@EXTRA_NETWORK_LIBS@
+
+# Standard CFLAGS for building test programs
+FULL_CFLAGS = $(CCOPT) $(INCLS) $(DEFS) $(CFLAGS)
+
+INSTALL = @INSTALL@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_DATA = @INSTALL_DATA@
+
+# Explicitly define compilation rule since SunOS 4's make doesn't like gcc.
+# Also, gcc does not remove the .o before forking 'as', which can be a
+# problem if you don't own the file but can write to the directory.
+.c.o:
+ @rm -f $@
+ $(CC) $(FULL_CFLAGS) -c $(srcdir)/$*.c
+
+SRC = @VALGRINDTEST_SRC@ \
+ capturetest.c \
+ can_set_rfmon_test.c \
+ filtertest.c \
+ findalldevstest.c \
+ opentest.c \
+ reactivatetest.c \
+ selpolltest.c \
+ threadsignaltest.c
+
+TESTS = $(SRC:.c=)
+
+TAGFILES = \
+ $(SRC) $(HDR)
+
+CLEANFILES = $(OBJ) $(TESTS)
+
+all: $(TESTS)
+
+capturetest: $(srcdir)/capturetest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o capturetest $(srcdir)/capturetest.c ../libpcap.a $(LIBS)
+
+can_set_rfmon_test: $(srcdir)/can_set_rfmon_test.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o can_set_rfmon_test $(srcdir)/can_set_rfmon_test.c ../libpcap.a $(LIBS)
+
+filtertest: $(srcdir)/filtertest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o filtertest $(srcdir)/filtertest.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
+
+findalldevstest: $(srcdir)/findalldevstest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o findalldevstest $(srcdir)/findalldevstest.c ../libpcap.a $(EXTRA_NETWORK_LIBS) $(LIBS)
+
+opentest: $(srcdir)/opentest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o opentest $(srcdir)/opentest.c ../libpcap.a $(LIBS)
+
+reactivatetest: $(srcdir)/reactivatetest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o reactivatetest $(srcdir)/reactivatetest.c ../libpcap.a $(LIBS)
+
+selpolltest: $(srcdir)/selpolltest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o selpolltest $(srcdir)/selpolltest.c ../libpcap.a $(LIBS)
+
+threadsignaltest: $(srcdir)/threadsignaltest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o threadsignaltest $(srcdir)/threadsignaltest.c ../libpcap.a $(LIBS) $(PTHREAD_LIBS)
+
+valgrindtest: $(srcdir)/valgrindtest.c ../libpcap.a
+ $(CC) $(FULL_CFLAGS) -I. -L. -o valgrindtest $(srcdir)/valgrindtest.c ../libpcap.a $(LIBS)
+
+clean:
+ rm -f $(CLEANFILES)
+ rm -rf *.dSYM
+
+distclean: clean
+ rm -f Makefile config.cache config.log config.status \
+ config.h stamp-h stamp-h.in
+ rm -rf autom4te.cache
+
+install:
+
+uninstall:
+
+tags: $(TAGFILES)
+ ctags -wtd $(TAGFILES)
+
+depend:
+ ../$(MKDEP) -c "$(CC)" -m "$(DEPENDENCY_CFLAG)" $(CFLAGS) $(DEFS) $(INCLS) $(SRC)
diff --git a/lib/libpcap/libpcap/testprogs/can_set_rfmon_test.c b/lib/libpcap/libpcap/testprogs/can_set_rfmon_test.c
new file mode 100644
index 0000000..f6188ba
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/can_set_rfmon_test.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include <pcap.h>
+
+#include "pcap/funcattrs.h"
+
+static const char *program_name;
+
+/* Forwards */
+static void PCAP_NORETURN error(PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(1,2);
+
+int
+main(int argc, char **argv)
+{
+ const char *cp;
+ pcap_t *pd;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ int status;
+
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ if (argc != 2) {
+ fprintf(stderr, "Usage: %s <device>\n", program_name);
+ return 2;
+ }
+
+ pd = pcap_create(argv[1], ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ status = pcap_can_set_rfmon(pd);
+ if (status < 0) {
+ if (status == PCAP_ERROR)
+ error("%s: pcap_can_set_rfmon failed: %s", argv[1],
+ pcap_geterr(pd));
+ else
+ error("%s: pcap_can_set_rfmon failed: %s", argv[1],
+ pcap_statustostr(status));
+ return 1;
+ }
+ printf("%s: Monitor mode %s be set\n", argv[1], status ? "can" : "cannot");
+ return 0;
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/lib/libpcap/libpcap/testprogs/capturetest.c b/lib/libpcap/libpcap/testprogs/capturetest.c
new file mode 100644
index 0000000..d625cb4
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/capturetest.c
@@ -0,0 +1,299 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#ifdef _WIN32
+ #include "getopt.h"
+#else
+ #include <unistd.h>
+#endif
+#include <errno.h>
+#include <sys/types.h>
+
+#include <pcap.h>
+
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+ #include "portability.h"
+#endif
+
+static char *program_name;
+
+/* Forwards */
+static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static char *copy_argv(char **);
+
+static pcap_t *pd;
+
+int
+main(int argc, char **argv)
+{
+ register int op;
+ register char *cp, *cmdbuf, *device;
+ long longarg;
+ char *p;
+ int timeout = 1000;
+ int immediate = 0;
+ int nonblock = 0;
+ pcap_if_t *devlist;
+ bpf_u_int32 localnet, netmask;
+ struct bpf_program fcode;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ int status;
+ int packet_count;
+
+ device = NULL;
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "i:mnt:")) != -1) {
+ switch (op) {
+
+ case 'i':
+ device = optarg;
+ break;
+
+ case 'm':
+ immediate = 1;
+ break;
+
+ case 'n':
+ nonblock = 1;
+ break;
+
+ case 't':
+ longarg = strtol(optarg, &p, 10);
+ if (p == optarg || *p != '\0') {
+ error("Timeout value \"%s\" is not a number",
+ optarg);
+ /* NOTREACHED */
+ }
+ if (longarg < 0) {
+ error("Timeout value %ld is negative", longarg);
+ /* NOTREACHED */
+ }
+ if (longarg > INT_MAX) {
+ error("Timeout value %ld is too large (> %d)",
+ longarg, INT_MAX);
+ /* NOTREACHED */
+ }
+ timeout = (int)longarg;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (device == NULL) {
+ if (pcap_findalldevs(&devlist, ebuf) == -1)
+ error("%s", ebuf);
+ if (devlist == NULL)
+ error("no interfaces available for capture");
+ device = strdup(devlist->name);
+ pcap_freealldevs(devlist);
+ }
+ *ebuf = '\0';
+ pd = pcap_create(device, ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ status = pcap_set_snaplen(pd, 65535);
+ if (status != 0)
+ error("%s: pcap_set_snaplen failed: %s",
+ device, pcap_statustostr(status));
+ if (immediate) {
+ status = pcap_set_immediate_mode(pd, 1);
+ if (status != 0)
+ error("%s: pcap_set_immediate_mode failed: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_set_timeout(pd, timeout);
+ if (status != 0)
+ error("%s: pcap_set_timeout failed: %s",
+ device, pcap_statustostr(status));
+ status = pcap_activate(pd);
+ if (status < 0) {
+ /*
+ * pcap_activate() failed.
+ */
+ error("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ } else if (status > 0) {
+ /*
+ * pcap_activate() succeeded, but it's warning us
+ * of a problem it had.
+ */
+ warning("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ }
+ if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+ localnet = 0;
+ netmask = 0;
+ warning("%s", ebuf);
+ }
+ cmdbuf = copy_argv(&argv[optind]);
+
+ if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+ error("%s", pcap_geterr(pd));
+
+ if (pcap_setfilter(pd, &fcode) < 0)
+ error("%s", pcap_geterr(pd));
+ if (pcap_setnonblock(pd, nonblock, ebuf) == -1)
+ error("pcap_setnonblock failed: %s", ebuf);
+ printf("Listening on %s\n", device);
+ for (;;) {
+ packet_count = 0;
+ status = pcap_dispatch(pd, -1, countme,
+ (u_char *)&packet_count);
+ if (status < 0)
+ break;
+ if (status != 0) {
+ printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
+ status, packet_count);
+ }
+ }
+ if (status == -2) {
+ /*
+ * We got interrupted, so perhaps we didn't
+ * manage to finish a line we were printing.
+ * Print an extra newline, just in case.
+ */
+ putchar('\n');
+ }
+ (void)fflush(stdout);
+ if (status == -1) {
+ /*
+ * Error. Report it.
+ */
+ (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+ program_name, pcap_geterr(pd));
+ }
+ pcap_close(pd);
+ pcap_freecode(&fcode);
+ free(cmdbuf);
+ exit(status == -1 ? 1 : 0);
+}
+
+static void
+countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
+{
+ int *counterp = (int *)user;
+
+ (*counterp)++;
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "Usage: %s [ -mn ] [ -i interface ] [ -t timeout] [expression]\n",
+ program_name);
+ exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: WARNING: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+ register char **p;
+ register u_int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = (char *)malloc(len);
+ if (buf == NULL)
+ error("copy_argv: malloc");
+
+ p = argv;
+ dst = buf;
+ while ((src = *p++) != NULL) {
+ while ((*dst++ = *src++) != '\0')
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
diff --git a/lib/libpcap/libpcap/testprogs/filtertest.c b/lib/libpcap/libpcap/testprogs/filtertest.c
new file mode 100644
index 0000000..7e2d6d6
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/filtertest.c
@@ -0,0 +1,359 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef _WIN32
+ #include "getopt.h"
+ #include "unix.h"
+#else
+ #include <unistd.h>
+#endif
+#include <fcntl.h>
+#include <errno.h>
+#ifdef _WIN32
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+#else
+ #include <sys/socket.h>
+ #include <arpa/inet.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "pcap/funcattrs.h"
+
+#ifdef BDEBUG
+/*
+ * We have pcap_set_optimizer_debug() and pcap_set_print_dot_graph() in
+ * libpcap; declare them (they're not declared by any libpcap header,
+ * because they're special hacks, only available if libpcap was configured
+ * to include them, and only intended for use by libpcap developers trying
+ * to debug the optimizer for filter expressions).
+ */
+PCAP_API void pcap_set_optimizer_debug(int);
+PCAP_API void pcap_set_print_dot_graph(int);
+#endif
+
+static char *program_name;
+
+/* Forwards */
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warn(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+
+/*
+ * On Windows, we need to open the file in binary mode, so that
+ * we get all the bytes specified by the size we get from "fstat()".
+ * On UNIX, that's not necessary. O_BINARY is defined on Windows;
+ * we define it as 0 if it's not defined, so it does nothing.
+ */
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static char *
+read_infile(char *fname)
+{
+ register int i, fd, cc;
+ register char *cp;
+ struct stat buf;
+
+ fd = open(fname, O_RDONLY|O_BINARY);
+ if (fd < 0)
+ error("can't open %s: %s", fname, pcap_strerror(errno));
+
+ if (fstat(fd, &buf) < 0)
+ error("can't stat %s: %s", fname, pcap_strerror(errno));
+
+ cp = malloc((u_int)buf.st_size + 1);
+ if (cp == NULL)
+ error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
+ fname, pcap_strerror(errno));
+ cc = read(fd, cp, (u_int)buf.st_size);
+ if (cc < 0)
+ error("read %s: %s", fname, pcap_strerror(errno));
+ if (cc != buf.st_size)
+ error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
+
+ close(fd);
+ /* replace "# comment" with spaces */
+ for (i = 0; i < cc; i++) {
+ if (cp[i] == '#')
+ while (i < cc && cp[i] != '\n')
+ cp[i++] = ' ';
+ }
+ cp[cc] = '\0';
+ return (cp);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warn(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: WARNING: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+ register char **p;
+ register u_int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = (char *)malloc(len);
+ if (buf == NULL)
+ error("copy_argv: malloc");
+
+ p = argv;
+ dst = buf;
+ while ((src = *p++) != NULL) {
+ while ((*dst++ = *src++) != '\0')
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
+
+int
+main(int argc, char **argv)
+{
+ char *cp;
+ int op;
+ int dflag;
+ int gflag;
+ char *infile;
+ int Oflag;
+ long snaplen;
+ char *p;
+ int dlt;
+ int have_fcode = 0;
+ bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN;
+ char *cmdbuf;
+ pcap_t *pd;
+ struct bpf_program fcode;
+
+#ifdef _WIN32
+ if (pcap_wsockinit() != 0)
+ return 1;
+#endif /* _WIN32 */
+
+ dflag = 1;
+ gflag = 0;
+
+ infile = NULL;
+ Oflag = 1;
+ snaplen = 68;
+
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "dF:gm:Os:")) != -1) {
+ switch (op) {
+
+ case 'd':
+ ++dflag;
+ break;
+
+ case 'g':
+#ifdef BDEBUG
+ ++gflag;
+#else
+ error("libpcap and filtertest not built with optimizer debugging enabled");
+#endif
+ break;
+
+ case 'F':
+ infile = optarg;
+ break;
+
+ case 'O':
+ Oflag = 0;
+ break;
+
+ case 'm': {
+ bpf_u_int32 addr;
+
+ switch (inet_pton(AF_INET, optarg, &addr)) {
+
+ case 0:
+ error("invalid netmask %s", optarg);
+ break;
+
+ case -1:
+ error("invalid netmask %s: %s", optarg,
+ pcap_strerror(errno));
+ break;
+
+ case 1:
+ netmask = addr;
+ break;
+ }
+ break;
+ }
+
+ case 's': {
+ char *end;
+
+ snaplen = strtol(optarg, &end, 0);
+ if (optarg == end || *end != '\0'
+ || snaplen < 0 || snaplen > 65535)
+ error("invalid snaplen %s", optarg);
+ else if (snaplen == 0)
+ snaplen = 65535;
+ break;
+ }
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (optind >= argc) {
+ usage();
+ /* NOTREACHED */
+ }
+
+ dlt = pcap_datalink_name_to_val(argv[optind]);
+ if (dlt < 0) {
+ dlt = (int)strtol(argv[optind], &p, 10);
+ if (p == argv[optind] || *p != '\0')
+ error("invalid data link type %s", argv[optind]);
+ }
+
+ if (infile)
+ cmdbuf = read_infile(infile);
+ else
+ cmdbuf = copy_argv(&argv[optind+1]);
+
+#ifdef BDEBUG
+ pcap_set_optimizer_debug(dflag);
+ pcap_set_print_dot_graph(gflag);
+#endif
+
+ pd = pcap_open_dead(dlt, snaplen);
+ if (pd == NULL)
+ error("Can't open fake pcap_t");
+
+ if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0)
+ error("%s", pcap_geterr(pd));
+
+ have_fcode = 1;
+ if (!bpf_validate(fcode.bf_insns, fcode.bf_len))
+ warn("Filter doesn't pass validation");
+
+#ifdef BDEBUG
+ if (cmdbuf != NULL) {
+ // replace line feed with space
+ for (cp = cmdbuf; *cp != '\0'; ++cp) {
+ if (*cp == '\r' || *cp == '\n') {
+ *cp = ' ';
+ }
+ }
+ // only show machine code if BDEBUG defined, since dflag > 3
+ printf("machine codes for filter: %s\n", cmdbuf);
+ } else
+ printf("machine codes for empty filter:\n");
+#endif
+
+ bpf_dump(&fcode, dflag);
+ free(cmdbuf);
+ if (have_fcode)
+ pcap_freecode (&fcode);
+ pcap_close(pd);
+ exit(0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s, with %s\n", program_name,
+ pcap_lib_version());
+ (void)fprintf(stderr,
+#ifdef BDEBUG
+ "Usage: %s [-dgO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n",
+#else
+ "Usage: %s [-dO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n",
+#endif
+ program_name);
+ exit(1);
+}
diff --git a/lib/libpcap/libpcap/testprogs/findalldevstest.c b/lib/libpcap/libpcap/testprogs/findalldevstest.c
new file mode 100644
index 0000000..e535e25
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/findalldevstest.c
@@ -0,0 +1,311 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#ifdef _WIN32
+ #include <winsock2.h>
+ #include <ws2tcpip.h>
+ #include <windows.h>
+#else
+ #include <sys/socket.h>
+ #include <netinet/in.h>
+ #include <arpa/inet.h>
+ #include <netdb.h>
+ #include <unistd.h>
+#endif
+
+#include <pcap.h>
+
+#include "pcap/funcattrs.h"
+
+static int ifprint(pcap_if_t *d);
+static char *iptos(bpf_u_int32 in);
+
+#ifdef _WIN32
+#include "portability.h"
+
+/*
+ * Generate a string for a Win32-specific error (i.e. an error generated when
+ * calling a Win32 API).
+ * For errors occurred during standard C calls, we still use pcap_strerror()
+ */
+#define ERRBUF_SIZE 1024
+static const char *
+win32_strerror(DWORD error)
+{
+ static char errbuf[ERRBUF_SIZE+1];
+ size_t errlen;
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+ ERRBUF_SIZE, NULL);
+
+ /*
+ * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
+ * message. Get rid of it.
+ */
+ errlen = strlen(errbuf);
+ if (errlen >= 2) {
+ errbuf[errlen - 1] = '\0';
+ errbuf[errlen - 2] = '\0';
+ errlen -= 2;
+ }
+ return errbuf;
+}
+
+static char *
+getpass(const char *prompt)
+{
+ HANDLE console_handle = GetStdHandle(STD_INPUT_HANDLE);
+ DWORD console_mode, save_console_mode;
+ static char password[128+1];
+ char *p;
+
+ fprintf(stderr, "%s", prompt);
+
+ /*
+ * Turn off echoing.
+ */
+ if (!GetConsoleMode(console_handle, &console_mode)) {
+ fprintf(stderr, "Can't get console mode: %s\n",
+ win32_strerror(GetLastError()));
+ exit(1);
+ }
+ save_console_mode = console_mode;
+ console_mode &= ~ENABLE_ECHO_INPUT;
+ if (!SetConsoleMode(console_handle, console_mode)) {
+ fprintf(stderr, "Can't set console mode: %s\n",
+ win32_strerror(GetLastError()));
+ exit(1);
+ }
+ if (fgets(password, sizeof password, stdin) == NULL) {
+ fprintf(stderr, "\n");
+ SetConsoleMode(console_handle, save_console_mode);
+ exit(1);
+ }
+ fprintf(stderr, "\n");
+ SetConsoleMode(console_handle, save_console_mode);
+ p = strchr(password, '\n');
+ if (p != NULL)
+ *p = '\0';
+ return password;
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ pcap_if_t *alldevs;
+ pcap_if_t *d;
+ bpf_u_int32 net, mask;
+ int exit_status = 0;
+ char errbuf[PCAP_ERRBUF_SIZE+1];
+#ifdef ENABLE_REMOTE
+ struct pcap_rmtauth auth;
+ char username[128+1];
+ char *p;
+ char *password;
+#endif
+
+#ifdef ENABLE_REMOTE
+ if (argc >= 2)
+ {
+ if (pcap_findalldevs_ex(argv[1], NULL, &alldevs, errbuf) == -1)
+ {
+ /*
+ * OK, try it with a user name and password.
+ */
+ fprintf(stderr, "User name: ");
+ if (fgets(username, sizeof username, stdin) == NULL)
+ exit(1);
+ p = strchr(username, '\n');
+ if (p != NULL)
+ *p = '\0';
+ password = getpass("Password: ");
+ auth.type = RPCAP_RMTAUTH_PWD;
+ auth.username = username;
+ auth.password = password;
+ if (pcap_findalldevs_ex(argv[1], &auth, &alldevs, errbuf) == -1)
+ {
+ fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
+ exit(1);
+ }
+ }
+ }
+ else
+#endif
+ {
+ if (pcap_findalldevs(&alldevs, errbuf) == -1)
+ {
+ fprintf(stderr,"Error in pcap_findalldevs: %s\n",errbuf);
+ exit(1);
+ }
+ }
+ for(d=alldevs;d;d=d->next)
+ {
+ if (!ifprint(d))
+ exit_status = 2;
+ }
+
+ if (alldevs != NULL)
+ {
+ if (pcap_lookupnet(alldevs->name, &net, &mask, errbuf) < 0)
+ {
+ fprintf(stderr,"Error in pcap_lookupnet: %s\n",errbuf);
+ exit_status = 2;
+ }
+ else
+ {
+ printf("Preferred device is on network: %s/%s\n",iptos(net), iptos(mask));
+ }
+ }
+
+ pcap_freealldevs(alldevs);
+ exit(exit_status);
+}
+
+static int ifprint(pcap_if_t *d)
+{
+ pcap_addr_t *a;
+ char ipv4_buf[INET_ADDRSTRLEN];
+ char ipv6_buf[INET6_ADDRSTRLEN];
+ const char *sep;
+ int status = 1; /* success */
+
+ printf("%s\n",d->name);
+ if (d->description)
+ printf("\tDescription: %s\n",d->description);
+ printf("\tFlags: ");
+ sep = "";
+ if (d->flags & PCAP_IF_UP) {
+ printf("%sUP", sep);
+ sep = ", ";
+ }
+ if (d->flags & PCAP_IF_RUNNING) {
+ printf("%sRUNNING", sep);
+ sep = ", ";
+ }
+ if (d->flags & PCAP_IF_LOOPBACK) {
+ printf("%sLOOPBACK", sep);
+ sep = ", ";
+ }
+ if (d->flags & PCAP_IF_WIRELESS) {
+ printf("%sWIRELESS", sep);
+ switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
+
+ case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+ printf(" (association status unknown)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+ printf(" (associated)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+ printf(" (not associated)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+ break;
+ }
+ } else {
+ switch (d->flags & PCAP_IF_CONNECTION_STATUS) {
+
+ case PCAP_IF_CONNECTION_STATUS_UNKNOWN:
+ printf(" (connection status unknown)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_CONNECTED:
+ printf(" (connected)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_DISCONNECTED:
+ printf(" (disconnected)");
+ break;
+
+ case PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE:
+ break;
+ }
+ }
+ sep = ", ";
+ printf("\n");
+
+ for(a=d->addresses;a;a=a->next) {
+ if (a->addr != NULL)
+ switch(a->addr->sa_family) {
+ case AF_INET:
+ printf("\tAddress Family: AF_INET\n");
+ if (a->addr)
+ printf("\t\tAddress: %s\n",
+ inet_ntop(AF_INET,
+ &((struct sockaddr_in *)(a->addr))->sin_addr,
+ ipv4_buf, sizeof ipv4_buf));
+ if (a->netmask)
+ printf("\t\tNetmask: %s\n",
+ inet_ntop(AF_INET,
+ &((struct sockaddr_in *)(a->netmask))->sin_addr,
+ ipv4_buf, sizeof ipv4_buf));
+ if (a->broadaddr)
+ printf("\t\tBroadcast Address: %s\n",
+ inet_ntop(AF_INET,
+ &((struct sockaddr_in *)(a->broadaddr))->sin_addr,
+ ipv4_buf, sizeof ipv4_buf));
+ if (a->dstaddr)
+ printf("\t\tDestination Address: %s\n",
+ inet_ntop(AF_INET,
+ &((struct sockaddr_in *)(a->dstaddr))->sin_addr,
+ ipv4_buf, sizeof ipv4_buf));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ printf("\tAddress Family: AF_INET6\n");
+ if (a->addr)
+ printf("\t\tAddress: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->addr))->sin6_addr.s6_addr,
+ ipv6_buf, sizeof ipv6_buf));
+ if (a->netmask)
+ printf("\t\tNetmask: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->netmask))->sin6_addr.s6_addr,
+ ipv6_buf, sizeof ipv6_buf));
+ if (a->broadaddr)
+ printf("\t\tBroadcast Address: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->broadaddr))->sin6_addr.s6_addr,
+ ipv6_buf, sizeof ipv6_buf));
+ if (a->dstaddr)
+ printf("\t\tDestination Address: %s\n",
+ inet_ntop(AF_INET6,
+ ((struct sockaddr_in6 *)(a->dstaddr))->sin6_addr.s6_addr,
+ ipv6_buf, sizeof ipv6_buf));
+ break;
+#endif
+ default:
+ printf("\tAddress Family: Unknown (%d)\n", a->addr->sa_family);
+ break;
+ }
+ else
+ {
+ fprintf(stderr, "\tWarning: a->addr is NULL, skipping this address.\n");
+ status = 0;
+ }
+ }
+ printf("\n");
+ return status;
+}
+
+/* From tcptraceroute */
+#define IPTOSBUFFERS 12
+static char *iptos(bpf_u_int32 in)
+{
+ static char output[IPTOSBUFFERS][3*4+3+1];
+ static short which;
+ u_char *p;
+
+ p = (u_char *)&in;
+ which = (which + 1 == IPTOSBUFFERS ? 0 : which + 1);
+ sprintf(output[which], "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
+ return output[which];
+}
diff --git a/lib/libpcap/libpcap/testprogs/opentest.c b/lib/libpcap/libpcap/testprogs/opentest.c
new file mode 100644
index 0000000..bad38eb
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/opentest.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#ifdef _WIN32
+ #include "getopt.h"
+#else
+ #include <unistd.h>
+#endif
+#include <errno.h>
+
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+ #include "portability.h"
+#endif
+
+#define MAXIMUM_SNAPLEN 65535
+
+static char *program_name;
+
+/* Forwards */
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+
+int
+main(int argc, char **argv)
+{
+ register int op;
+ register char *cp, *device;
+ int dorfmon, dopromisc, snaplen, useactivate, bufsize;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ pcap_if_t *devlist;
+ pcap_t *pd;
+ int status = 0;
+
+ device = NULL;
+ dorfmon = 0;
+ dopromisc = 0;
+ snaplen = MAXIMUM_SNAPLEN;
+ bufsize = 0;
+ useactivate = 0;
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "i:Ips:aB:")) != -1) {
+ switch (op) {
+
+ case 'i':
+ device = optarg;
+ break;
+
+ case 'I':
+ dorfmon = 1;
+ useactivate = 1; /* required for rfmon */
+ break;
+
+ case 'p':
+ dopromisc = 1;
+ break;
+
+ case 's': {
+ char *end;
+
+ snaplen = strtol(optarg, &end, 0);
+ if (optarg == end || *end != '\0'
+ || snaplen < 0 || snaplen > MAXIMUM_SNAPLEN)
+ error("invalid snaplen %s", optarg);
+ else if (snaplen == 0)
+ snaplen = MAXIMUM_SNAPLEN;
+ break;
+ }
+
+ case 'B':
+ bufsize = atoi(optarg)*1024;
+ if (bufsize <= 0)
+ error("invalid packet buffer size %s", optarg);
+ useactivate = 1; /* required for bufsize */
+ break;
+
+ case 'a':
+ useactivate = 1;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (device == NULL) {
+ if (pcap_findalldevs(&devlist, ebuf) == -1)
+ error("%s", ebuf);
+ if (devlist == NULL)
+ error("no interfaces available for capture");
+ device = strdup(devlist->name);
+ pcap_freealldevs(devlist);
+ }
+ if (useactivate) {
+ pd = pcap_create(device, ebuf);
+ if (pd == NULL)
+ error("%s: pcap_create failed: %s", device, ebuf);
+ status = pcap_set_snaplen(pd, snaplen);
+ if (status != 0)
+ error("%s: pcap_set_snaplen failed: %s",
+ device, pcap_statustostr(status));
+ if (dopromisc) {
+ status = pcap_set_promisc(pd, 1);
+ if (status != 0)
+ error("%s: pcap_set_promisc failed: %s",
+ device, pcap_statustostr(status));
+ }
+ if (dorfmon) {
+ status = pcap_set_rfmon(pd, 1);
+ if (status != 0)
+ error("%s: pcap_set_rfmon failed: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_set_timeout(pd, 1000);
+ if (status != 0)
+ error("%s: pcap_set_timeout failed: %s",
+ device, pcap_statustostr(status));
+ if (bufsize != 0) {
+ status = pcap_set_buffer_size(pd, bufsize);
+ if (status != 0)
+ error("%s: pcap_set_buffer_size failed: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_activate(pd);
+ if (status < 0) {
+ /*
+ * pcap_activate() failed.
+ */
+ error("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ } else if (status > 0) {
+ /*
+ * pcap_activate() succeeded, but it's warning us
+ * of a problem it had.
+ */
+ warning("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ } else
+ printf("%s opened successfully\n", device);
+ } else {
+ *ebuf = '\0';
+ pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ else if (*ebuf)
+ warning("%s", ebuf);
+ else
+ printf("%s opened successfully\n", device);
+ }
+ pcap_close(pd);
+ exit(status < 0 ? 1 : 0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr,
+ "Usage: %s [ -Ipa ] [ -i interface ] [ -s snaplen ] [ -B bufsize ]\n",
+ program_name);
+ exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: WARNING: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
diff --git a/lib/libpcap/libpcap/testprogs/reactivatetest.c b/lib/libpcap/libpcap/testprogs/reactivatetest.c
new file mode 100644
index 0000000..d7f3e32
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/reactivatetest.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "pcap/funcattrs.h"
+
+/* Forwards */
+static void PCAP_NORETURN error(PCAP_FORMAT_STRING(const char *), ...) PCAP_PRINTFLIKE(1,2);
+
+int
+main(void)
+{
+ char ebuf[PCAP_ERRBUF_SIZE];
+ pcap_t *pd;
+ int status = 0;
+
+ pd = pcap_open_live("lo0", 65535, 0, 1000, ebuf);
+ if (pd == NULL) {
+ pd = pcap_open_live("lo", 65535, 0, 1000, ebuf);
+ if (pd == NULL) {
+ error("Neither lo0 nor lo could be opened: %s",
+ ebuf);
+ return 2;
+ }
+ }
+ status = pcap_activate(pd);
+ if (status != PCAP_ERROR_ACTIVATED) {
+ if (status == 0)
+ error("pcap_activate() of opened pcap_t succeeded");
+ else if (status == PCAP_ERROR)
+ error("pcap_activate() of opened pcap_t failed with %s, not PCAP_ERROR_ACTIVATED",
+ pcap_geterr(pd));
+ else
+ error("pcap_activate() of opened pcap_t failed with %s, not PCAP_ERROR_ACTIVATED",
+ pcap_statustostr(status));
+ }
+ return 0;
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "reactivatetest: ");
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/lib/libpcap/libpcap/testprogs/selpolltest.c b/lib/libpcap/libpcap/testprogs/selpolltest.c
new file mode 100644
index 0000000..329281d
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/selpolltest.c
@@ -0,0 +1,443 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+/*
+ * Tests how select() and poll() behave on the selectable file descriptor
+ * for a pcap_t.
+ *
+ * This would be significantly different on Windows, as it'd test
+ * how WaitForMultipleObjects() would work on the event handle for a
+ * pcap_t.
+ */
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#ifdef HAVE_SYS_SELECT_H
+#include <sys/select.h>
+#else
+#include <sys/time.h> /* older UN*Xes */
+#endif
+#include <poll.h>
+
+#include "pcap/funcattrs.h"
+
+static char *program_name;
+
+/* Forwards */
+static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static char *copy_argv(char **);
+
+static pcap_t *pd;
+
+int
+main(int argc, char **argv)
+{
+ register int op;
+ bpf_u_int32 localnet, netmask;
+ register char *cp, *cmdbuf, *device;
+ int doselect, dopoll, dotimeout, dononblock;
+ const char *mechanism;
+ struct bpf_program fcode;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ pcap_if_t *devlist;
+ int selectable_fd;
+ struct timeval *required_timeout;
+ int status;
+ int packet_count;
+
+ device = NULL;
+ doselect = 0;
+ dopoll = 0;
+ mechanism = NULL;
+ dotimeout = 0;
+ dononblock = 0;
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "i:sptn")) != -1) {
+ switch (op) {
+
+ case 'i':
+ device = optarg;
+ break;
+
+ case 's':
+ doselect = 1;
+ mechanism = "select() and pcap_dispatch()";
+ break;
+
+ case 'p':
+ dopoll = 1;
+ mechanism = "poll() and pcap_dispatch()";
+ break;
+
+ case 't':
+ dotimeout = 1;
+ break;
+
+ case 'n':
+ dononblock = 1;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (doselect && dopoll) {
+ fprintf(stderr, "selpolltest: choose select (-s) or poll (-p), but not both\n");
+ return 1;
+ }
+ if (dotimeout && !doselect && !dopoll) {
+ fprintf(stderr, "selpolltest: timeout (-t) requires select (-s) or poll (-p)\n");
+ return 1;
+ }
+ if (device == NULL) {
+ if (pcap_findalldevs(&devlist, ebuf) == -1)
+ error("%s", ebuf);
+ if (devlist == NULL)
+ error("no interfaces available for capture");
+ device = strdup(devlist->name);
+ pcap_freealldevs(devlist);
+ }
+ *ebuf = '\0';
+ pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ else if (*ebuf)
+ warning("%s", ebuf);
+ if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+ localnet = 0;
+ netmask = 0;
+ warning("%s", ebuf);
+ }
+ cmdbuf = copy_argv(&argv[optind]);
+
+ if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+ error("%s", pcap_geterr(pd));
+ if (pcap_setfilter(pd, &fcode) < 0)
+ error("%s", pcap_geterr(pd));
+
+ if (doselect || dopoll) {
+ /*
+ * We need either an FD on which to do select()/poll()
+ * or, if there isn't one, a timeout to use in select()/
+ * poll().
+ */
+ selectable_fd = pcap_get_selectable_fd(pd);
+ if (selectable_fd == -1) {
+ printf("Listening on %s, using %s, with a timeout\n",
+ device, mechanism);
+ required_timeout = pcap_get_required_select_timeout(pd);
+ if (required_timeout == NULL)
+ error("select()/poll() isn't supported on %s, even with a timeout",
+ device);
+
+ /*
+ * As we won't be notified by select() or poll()
+ * that a read can be done, we'll have to periodically
+ * try reading from the device every time the required
+ * timeout expires, and we don't want those attempts
+ * to block if nothing has arrived in that interval,
+ * so we want to force non-blocking mode.
+ */
+ dononblock = 1;
+ } else {
+ printf("Listening on %s, using %s\n", device,
+ mechanism);
+ required_timeout = NULL;
+ }
+ } else
+ printf("Listening on %s, using pcap_dispatch()\n", device);
+
+ if (dononblock) {
+ if (pcap_setnonblock(pd, 1, ebuf) == -1)
+ error("pcap_setnonblock failed: %s", ebuf);
+ }
+ if (doselect) {
+ for (;;) {
+ fd_set setread, setexcept;
+ struct timeval seltimeout;
+
+ FD_ZERO(&setread);
+ if (selectable_fd != -1) {
+ FD_SET(selectable_fd, &setread);
+ FD_ZERO(&setexcept);
+ FD_SET(selectable_fd, &setexcept);
+ }
+ if (dotimeout) {
+ seltimeout.tv_sec = 0;
+ if (required_timeout != NULL &&
+ required_timeout->tv_usec < 1000)
+ seltimeout.tv_usec = required_timeout->tv_usec;
+ else
+ seltimeout.tv_usec = 1000;
+ status = select(selectable_fd + 1, &setread,
+ NULL, &setexcept, &seltimeout);
+ } else if (required_timeout != NULL) {
+ seltimeout = *required_timeout;
+ status = select(selectable_fd + 1, &setread,
+ NULL, &setexcept, &seltimeout);
+ } else {
+ status = select((selectable_fd == -1) ?
+ 0 : selectable_fd + 1, &setread,
+ NULL, &setexcept, NULL);
+ }
+ if (status == -1) {
+ printf("Select returns error (%s)\n",
+ strerror(errno));
+ } else {
+ if (selectable_fd == -1) {
+ if (status != 0)
+ printf("Select returned a descriptor\n");
+ } else {
+ if (status == 0)
+ printf("Select timed out: ");
+ else
+ printf("Select returned a descriptor: ");
+ if (FD_ISSET(selectable_fd, &setread))
+ printf("readable, ");
+ else
+ printf("not readable, ");
+ if (FD_ISSET(selectable_fd, &setexcept))
+ printf("exceptional condition\n");
+ else
+ printf("no exceptional condition\n");
+ }
+ packet_count = 0;
+ status = pcap_dispatch(pd, -1, countme,
+ (u_char *)&packet_count);
+ if (status < 0)
+ break;
+ /*
+ * Don't report this if we're using a
+ * required timeout and we got no packets,
+ * because that could be a very short timeout,
+ * and we don't want to spam the user with
+ * a ton of "no packets" reports.
+ */
+ if (status != 0 || packet_count != 0 ||
+ required_timeout != NULL) {
+ printf("%d packets seen, %d packets counted after select returns\n",
+ status, packet_count);
+ }
+ }
+ }
+ } else if (dopoll) {
+ for (;;) {
+ struct pollfd fd;
+ int polltimeout;
+
+ fd.fd = selectable_fd;
+ fd.events = POLLIN;
+ if (dotimeout)
+ polltimeout = 1;
+ else if (required_timeout != NULL &&
+ required_timeout->tv_usec >= 1000)
+ polltimeout = required_timeout->tv_usec/1000;
+ else
+ polltimeout = -1;
+ status = poll(&fd, (selectable_fd == -1) ? 0 : 1, polltimeout);
+ if (status == -1) {
+ printf("Poll returns error (%s)\n",
+ strerror(errno));
+ } else {
+ if (selectable_fd == -1) {
+ if (status != 0)
+ printf("Poll returned a descriptor\n");
+ } else {
+ if (status == 0)
+ printf("Poll timed out\n");
+ else {
+ printf("Poll returned a descriptor: ");
+ if (fd.revents & POLLIN)
+ printf("readable, ");
+ else
+ printf("not readable, ");
+ if (fd.revents & POLLERR)
+ printf("exceptional condition, ");
+ else
+ printf("no exceptional condition, ");
+ if (fd.revents & POLLHUP)
+ printf("disconnect, ");
+ else
+ printf("no disconnect, ");
+ if (fd.revents & POLLNVAL)
+ printf("invalid\n");
+ else
+ printf("not invalid\n");
+ }
+ }
+ packet_count = 0;
+ status = pcap_dispatch(pd, -1, countme,
+ (u_char *)&packet_count);
+ if (status < 0)
+ break;
+ /*
+ * Don't report this if we're using a
+ * required timeout and we got no packets,
+ * because that could be a very short timeout,
+ * and we don't want to spam the user with
+ * a ton of "no packets" reports.
+ */
+ if (status != 0 || packet_count != 0 ||
+ required_timeout != NULL) {
+ printf("%d packets seen, %d packets counted after poll returns\n",
+ status, packet_count);
+ }
+ }
+ }
+ } else {
+ for (;;) {
+ packet_count = 0;
+ status = pcap_dispatch(pd, -1, countme,
+ (u_char *)&packet_count);
+ if (status < 0)
+ break;
+ printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
+ status, packet_count);
+ }
+ }
+ if (status == -2) {
+ /*
+ * We got interrupted, so perhaps we didn't
+ * manage to finish a line we were printing.
+ * Print an extra newline, just in case.
+ */
+ putchar('\n');
+ }
+ (void)fflush(stdout);
+ if (status == -1) {
+ /*
+ * Error. Report it.
+ */
+ (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+ program_name, pcap_geterr(pd));
+ }
+ pcap_close(pd);
+ exit(status == -1 ? 1 : 0);
+}
+
+static void
+countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
+{
+ int *counterp = (int *)user;
+
+ (*counterp)++;
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
+ program_name);
+ exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: WARNING: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+ register char **p;
+ register u_int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = (char *)malloc(len);
+ if (buf == NULL)
+ error("copy_argv: malloc");
+
+ p = argv;
+ dst = buf;
+ while ((src = *p++) != NULL) {
+ while ((*dst++ = *src++) != '\0')
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
diff --git a/lib/libpcap/libpcap/testprogs/threadsignaltest.c b/lib/libpcap/libpcap/testprogs/threadsignaltest.c
new file mode 100644
index 0000000..a60bb49
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/threadsignaltest.c
@@ -0,0 +1,393 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <limits.h>
+#ifdef _WIN32
+ #include <winsock2.h>
+ #include <windows.h>
+
+ #define THREAD_HANDLE HANDLE
+ #define THREAD_FUNC_ARG_TYPE LPVOID
+ #define THREAD_FUNC_RETURN_TYPE DWORD __stdcall
+
+ #include "getopt.h"
+#else
+ #include <pthread.h>
+ #include <signal.h>
+ #include <unistd.h>
+
+ #define THREAD_HANDLE pthread_t
+ #define THREAD_FUNC_ARG_TYPE void *
+ #define THREAD_FUNC_RETURN_TYPE void *
+#endif
+#include <errno.h>
+#include <sys/types.h>
+
+#include <pcap.h>
+
+#include "pcap/funcattrs.h"
+
+#ifdef _WIN32
+ #include "portability.h"
+#endif
+
+static char *program_name;
+
+/* Forwards */
+static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static char *copy_argv(char **);
+
+static pcap_t *pd;
+
+#ifdef _WIN32
+/*
+ * Generate a string for a Win32-specific error (i.e. an error generated when
+ * calling a Win32 API).
+ * For errors occurred during standard C calls, we still use pcap_strerror()
+ */
+#define ERRBUF_SIZE 1024
+static const char *
+win32_strerror(DWORD error)
+{
+ static char errbuf[ERRBUF_SIZE+1];
+ size_t errlen;
+
+ FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf,
+ ERRBUF_SIZE, NULL);
+
+ /*
+ * "FormatMessage()" "helpfully" sticks CR/LF at the end of the
+ * message. Get rid of it.
+ */
+ errlen = strlen(errbuf);
+ if (errlen >= 2) {
+ errbuf[errlen - 1] = '\0';
+ errbuf[errlen - 2] = '\0';
+ errlen -= 2;
+ }
+ return errbuf;
+}
+#else
+static void
+catch_sigusr1(int sig _U_)
+{
+ printf("Got SIGUSR1\n");
+}
+#endif
+
+static void
+sleep_secs(int secs)
+{
+#ifdef _WIN32
+ Sleep(secs*1000);
+#else
+ unsigned secs_remaining;
+
+ if (secs <= 0)
+ return;
+ secs_remaining = secs;
+ while (secs_remaining != 0)
+ secs_remaining = sleep(secs_remaining);
+#endif
+}
+
+static THREAD_FUNC_RETURN_TYPE
+capture_thread_func(THREAD_FUNC_ARG_TYPE arg)
+{
+ char *device = arg;
+ int packet_count;
+ int status;
+#ifndef _WIN32
+ struct sigaction action;
+ sigset_t mask;
+#endif
+
+#ifndef _WIN32
+ sigemptyset(&mask);
+ action.sa_handler = catch_sigusr1;
+ action.sa_mask = mask;
+ action.sa_flags = 0;
+ if (sigaction(SIGUSR1, &action, NULL) == -1)
+ error("Can't catch SIGUSR1: %s", strerror(errno));
+#endif
+
+ printf("Listening on %s\n", device);
+ for (;;) {
+ packet_count = 0;
+ status = pcap_dispatch(pd, -1, countme,
+ (u_char *)&packet_count);
+ if (status < 0)
+ break;
+ if (status != 0) {
+ printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
+ status, packet_count);
+ } else
+ printf("No packets seen by pcap_dispatch\n");
+ }
+ if (status == -2) {
+ /*
+ * We got interrupted, so perhaps we didn't
+ * manage to finish a line we were printing.
+ * Print an extra newline, just in case.
+ */
+ putchar('\n');
+ printf("Loop got broken\n");
+ }
+ (void)fflush(stdout);
+ if (status == -1) {
+ /*
+ * Error. Report it.
+ */
+ (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+ program_name, pcap_geterr(pd));
+ }
+ return 0;
+}
+
+int
+main(int argc, char **argv)
+{
+ register int op;
+ register char *cp, *cmdbuf, *device;
+ int immediate = 0;
+ pcap_if_t *devlist;
+ bpf_u_int32 localnet, netmask;
+ struct bpf_program fcode;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ int status;
+ THREAD_HANDLE capture_thread;
+#ifndef _WIN32
+ void *retval;
+#endif
+
+ device = NULL;
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "i:")) != -1) {
+ switch (op) {
+
+ case 'i':
+ device = optarg;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (device == NULL) {
+ if (pcap_findalldevs(&devlist, ebuf) == -1)
+ error("%s", ebuf);
+ if (devlist == NULL)
+ error("no interfaces available for capture");
+ device = strdup(devlist->name);
+ pcap_freealldevs(devlist);
+ }
+ *ebuf = '\0';
+ pd = pcap_create(device, ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ status = pcap_set_snaplen(pd, 65535);
+ if (status != 0)
+ error("%s: pcap_set_snaplen failed: %s",
+ device, pcap_statustostr(status));
+ if (immediate) {
+ status = pcap_set_immediate_mode(pd, 1);
+ if (status != 0)
+ error("%s: pcap_set_immediate_mode failed: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_set_timeout(pd, 5*60*1000);
+ if (status != 0)
+ error("%s: pcap_set_timeout failed: %s",
+ device, pcap_statustostr(status));
+ status = pcap_activate(pd);
+ if (status < 0) {
+ /*
+ * pcap_activate() failed.
+ */
+ error("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ } else if (status > 0) {
+ /*
+ * pcap_activate() succeeded, but it's warning us
+ * of a problem it had.
+ */
+ warning("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ }
+ if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+ localnet = 0;
+ netmask = 0;
+ warning("%s", ebuf);
+ }
+ cmdbuf = copy_argv(&argv[optind]);
+
+ if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+ error("%s", pcap_geterr(pd));
+
+ if (pcap_setfilter(pd, &fcode) < 0)
+ error("%s", pcap_geterr(pd));
+
+#ifdef _WIN32
+ capture_thread = CreateThread(NULL, 0, capture_thread_func, device,
+ 0, NULL);
+ if (capture_thread == NULL)
+ error("Can't create capture thread: %s",
+ win32_strerror(GetLastError()));
+#else
+ status = pthread_create(&capture_thread, NULL, capture_thread_func,
+ device);
+ if (status != 0)
+ error("Can't create capture thread: %s", strerror(status));
+#endif
+ sleep_secs(60);
+ pcap_breakloop(pd);
+#ifdef _WIN32
+ printf("Setting event\n");
+ if (!SetEvent(pcap_getevent(pd)))
+ error("Can't set event for pcap_t: %s",
+ win32_strerror(GetLastError()));
+ if (WaitForSingleObject(capture_thread, INFINITE) == WAIT_FAILED)
+ error("Wait for thread termination failed: %s",
+ win32_strerror(GetLastError()));
+ CloseHandle(capture_thread);
+#else
+ printf("Sending SIGUSR1\n");
+ status = pthread_kill(capture_thread, SIGUSR1);
+ if (status != 0)
+ warning("Can't interrupt capture thread: %s", strerror(status));
+ status = pthread_join(capture_thread, &retval);
+ if (status != 0)
+ error("Wait for thread termination failed: %s",
+ strerror(status));
+#endif
+
+ pcap_close(pd);
+ pcap_freecode(&fcode);
+ exit(status == -1 ? 1 : 0);
+}
+
+static void
+countme(u_char *user, const struct pcap_pkthdr *h _U_, const u_char *sp _U_)
+{
+ int *counterp = (int *)user;
+
+ (*counterp)++;
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "Usage: %s [ -m ] [ -i interface ] [ -t timeout] [expression]\n",
+ program_name);
+ exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: WARNING: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+ register char **p;
+ register u_int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = (char *)malloc(len);
+ if (buf == NULL)
+ error("copy_argv: malloc");
+
+ p = argv;
+ dst = buf;
+ while ((src = *p++) != NULL) {
+ while ((*dst++ = *src++) != '\0')
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
diff --git a/lib/libpcap/libpcap/testprogs/unix.h b/lib/libpcap/libpcap/testprogs/unix.h
new file mode 100644
index 0000000..68ef4cb
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/unix.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 1994, 1995, 1996
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the Computer Systems
+ * Engineering Group at Lawrence Berkeley Laboratory.
+ * 4. Neither the name of the University nor of the Laboratory may be used
+ * to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef unix_h
+#define unix_h
+
+/*
+ * Definitions to make MSVC C runtime library structures and functions
+ * look like the UNIX structures and functions they are intended to
+ * resemble.
+ */
+#ifdef _MSC_VER
+ #define stat _stat
+ #define fstat _fstat
+
+ #define open _open
+ #define O_RDONLY _O_RDONLY
+ #define O_WRONLY _O_WRONLY
+ #define O_RDWR _O_RDWR
+ #define O_BINARY _O_BINARY
+ #define O_CREAT _O_CREAT
+ #define O_TRUNC _O_TRUNC
+ #define read _read
+ #define write _write
+ #define close _close
+#endif
+
+#endif
diff --git a/lib/libpcap/libpcap/testprogs/valgrindtest.c b/lib/libpcap/libpcap/testprogs/valgrindtest.c
new file mode 100644
index 0000000..104ef6a
--- /dev/null
+++ b/lib/libpcap/libpcap/testprogs/valgrindtest.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "varattrs.h"
+
+/*
+ * This doesn't actually test libpcap itself; it tests whether
+ * valgrind properly handles the APIs libpcap uses. If it doesn't,
+ * we end up getting patches submitted to "fix" references that
+ * valgrind claims are being made to uninitialized data, when, in
+ * fact, the OS isn't making any such references - or we get
+ * valgrind *not* detecting *actual* incorrect references.
+ *
+ * Both BPF and Linux socket filters aren't handled correctly
+ * by some versions of valgrind. See valgrind bug 318203 for
+ * Linux:
+ *
+ * https://bugs.kde.org/show_bug.cgi?id=318203
+ *
+ * and valgrind bug 312989 for macOS:
+ *
+ * https://bugs.kde.org/show_bug.cgi?id=312989
+ *
+ * The fixes for both of those are checked into the official valgrind
+ * repository.
+ *
+ * The unofficial FreeBSD port has similar issues to the official macOS
+ * port, for similar reasons.
+ */
+#ifndef lint
+static const char copyright[] _U_ =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "pcap/funcattrs.h"
+
+#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(_AIX) || defined(sun)
+/* OS with BPF - use BPF */
+#define USE_BPF
+#elif defined(linux)
+/* Linux - use socket filters */
+#define USE_SOCKET_FILTERS
+#else
+#error "Unknown platform or platform that doesn't support Valgrind"
+#endif
+
+#if defined(USE_BPF)
+
+#include <sys/ioctl.h>
+#include <net/bpf.h>
+
+/*
+ * Make "pcap.h" not include "pcap/bpf.h"; we are going to include the
+ * native OS version, as we're going to be doing our own ioctls to
+ * make sure that, in the uninitialized-data tests, the filters aren't
+ * checked by libpcap before being handed to BPF.
+ */
+#define PCAP_DONT_INCLUDE_PCAP_BPF_H
+
+#elif defined(USE_SOCKET_FILTERS)
+
+#include <sys/socket.h>
+#include <linux/types.h>
+#include <linux/filter.h>
+
+#endif
+
+#include <pcap.h>
+
+static char *program_name;
+
+/* Forwards */
+static void PCAP_NORETURN usage(void);
+static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+static void warning(const char *, ...) PCAP_PRINTFLIKE(1, 2);
+
+/*
+ * On Windows, we need to open the file in binary mode, so that
+ * we get all the bytes specified by the size we get from "fstat()".
+ * On UNIX, that's not necessary. O_BINARY is defined on Windows;
+ * we define it as 0 if it's not defined, so it does nothing.
+ */
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static char *
+read_infile(char *fname)
+{
+ register int i, fd, cc;
+ register char *cp;
+ struct stat buf;
+
+ fd = open(fname, O_RDONLY|O_BINARY);
+ if (fd < 0)
+ error("can't open %s: %s", fname, pcap_strerror(errno));
+
+ if (fstat(fd, &buf) < 0)
+ error("can't stat %s: %s", fname, pcap_strerror(errno));
+
+ cp = malloc((u_int)buf.st_size + 1);
+ if (cp == NULL)
+ error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
+ fname, pcap_strerror(errno));
+ cc = read(fd, cp, (u_int)buf.st_size);
+ if (cc < 0)
+ error("read %s: %s", fname, pcap_strerror(errno));
+ if (cc != buf.st_size)
+ error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
+
+ close(fd);
+ /* replace "# comment" with spaces */
+ for (i = 0; i < cc; i++) {
+ if (cp[i] == '#')
+ while (i < cc && cp[i] != '\n')
+ cp[i++] = ' ';
+ }
+ cp[cc] = '\0';
+ return (cp);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: WARNING: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+ register char **p;
+ register u_int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = (char *)malloc(len);
+ if (buf == NULL)
+ error("copy_argv: malloc");
+
+ p = argv;
+ dst = buf;
+ while ((src = *p++) != NULL) {
+ while ((*dst++ = *src++) != '\0')
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
+
+#define INSN_COUNT 17
+
+int
+main(int argc, char **argv)
+{
+ char *cp, *device;
+ int op;
+ int dorfmon, useactivate;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ char *infile;
+ const char *cmdbuf;
+ pcap_if_t *devlist;
+ pcap_t *pd;
+ int status = 0;
+ int pcap_fd;
+#if defined(USE_BPF)
+ struct bpf_program bad_fcode;
+ struct bpf_insn uninitialized[INSN_COUNT];
+#elif defined(USE_SOCKET_FILTERS)
+ struct sock_fprog bad_fcode;
+ struct sock_filter uninitialized[INSN_COUNT];
+#endif
+ struct bpf_program fcode;
+
+ device = NULL;
+ dorfmon = 0;
+ useactivate = 0;
+ infile = NULL;
+
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "aF:i:I")) != -1) {
+ switch (op) {
+
+ case 'a':
+ useactivate = 1;
+ break;
+
+ case 'F':
+ infile = optarg;
+ break;
+
+ case 'i':
+ device = optarg;
+ break;
+
+ case 'I':
+ dorfmon = 1;
+ useactivate = 1; /* required for rfmon */
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (device == NULL) {
+ /*
+ * No interface specified; get whatever pcap_lookupdev()
+ * finds.
+ */
+ if (pcap_findalldevs(&devlist, ebuf) == -1)
+ error("%s", ebuf);
+ if (devlist == NULL)
+ error("no interfaces available for capture");
+ device = strdup(devlist->name);
+ pcap_freealldevs(devlist);
+ }
+
+ if (infile != NULL) {
+ /*
+ * Filter specified with "-F" and a file containing
+ * a filter.
+ */
+ cmdbuf = read_infile(infile);
+ } else {
+ if (optind < argc) {
+ /*
+ * Filter specified with arguments on the
+ * command line.
+ */
+ cmdbuf = copy_argv(&argv[optind+1]);
+ } else {
+ /*
+ * No filter specified; use an empty string, which
+ * compiles to an "accept all" filter.
+ */
+ cmdbuf = "";
+ }
+ }
+
+ if (useactivate) {
+ pd = pcap_create(device, ebuf);
+ if (pd == NULL)
+ error("%s: pcap_create() failed: %s", device, ebuf);
+ status = pcap_set_snaplen(pd, 65535);
+ if (status != 0)
+ error("%s: pcap_set_snaplen failed: %s",
+ device, pcap_statustostr(status));
+ status = pcap_set_promisc(pd, 1);
+ if (status != 0)
+ error("%s: pcap_set_promisc failed: %s",
+ device, pcap_statustostr(status));
+ if (dorfmon) {
+ status = pcap_set_rfmon(pd, 1);
+ if (status != 0)
+ error("%s: pcap_set_rfmon failed: %s",
+ device, pcap_statustostr(status));
+ }
+ status = pcap_set_timeout(pd, 1000);
+ if (status != 0)
+ error("%s: pcap_set_timeout failed: %s",
+ device, pcap_statustostr(status));
+ status = pcap_activate(pd);
+ if (status < 0) {
+ /*
+ * pcap_activate() failed.
+ */
+ error("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ } else if (status > 0) {
+ /*
+ * pcap_activate() succeeded, but it's warning us
+ * of a problem it had.
+ */
+ warning("%s: %s\n(%s)", device,
+ pcap_statustostr(status), pcap_geterr(pd));
+ }
+ } else {
+ *ebuf = '\0';
+ pd = pcap_open_live(device, 65535, 1, 1000, ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ else if (*ebuf)
+ warning("%s", ebuf);
+ }
+
+ pcap_fd = pcap_fileno(pd);
+
+ /*
+ * Try setting a filter with an uninitialized bpf_program
+ * structure. This should cause valgrind to report a
+ * problem.
+ *
+ * We don't check for errors, because it could get an
+ * error due to a bad pointer or count.
+ */
+#if defined(USE_BPF)
+ ioctl(pcap_fd, BIOCSETF, &bad_fcode);
+#elif defined(USE_SOCKET_FILTERS)
+ setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode,
+ sizeof(bad_fcode));
+#endif
+
+ /*
+ * Try setting a filter with an initialized bpf_program
+ * structure that points to an uninitialized program.
+ * That should also cause valgrind to report a problem.
+ *
+ * We don't check for errors, because it could get an
+ * error due to a bad pointer or count.
+ */
+#if defined(USE_BPF)
+ bad_fcode.bf_len = INSN_COUNT;
+ bad_fcode.bf_insns = uninitialized;
+ ioctl(pcap_fd, BIOCSETF, &bad_fcode);
+#elif defined(USE_SOCKET_FILTERS)
+ bad_fcode.len = INSN_COUNT;
+ bad_fcode.filter = uninitialized;
+ setsockopt(pcap_fd, SOL_SOCKET, SO_ATTACH_FILTER, &bad_fcode,
+ sizeof(bad_fcode));
+#endif
+
+ /*
+ * Now compile a filter and set the filter with that.
+ * That should *not* cause valgrind to report a
+ * problem.
+ */
+ if (pcap_compile(pd, &fcode, cmdbuf, 1, 0) < 0)
+ error("can't compile filter: %s", pcap_geterr(pd));
+ if (pcap_setfilter(pd, &fcode) < 0)
+ error("can't set filter: %s", pcap_geterr(pd));
+
+ pcap_close(pd);
+ exit(status < 0 ? 1 : 0);
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "%s, with %s\n", program_name,
+ pcap_lib_version());
+ (void)fprintf(stderr,
+ "Usage: %s [-aI] [ -F file ] [ -I interface ] [ expression ]\n",
+ program_name);
+ exit(1);
+}
diff --git a/lib/libpcap/libpcap/tests/hex_and_ascii_print.c b/lib/libpcap/libpcap/tests/hex_and_ascii_print.c
new file mode 100644
index 0000000..6ee836e
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/hex_and_ascii_print.c
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2013 Apple Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+#include <stdio.h>
+#include <ctype.h>
+
+#define MAXBUF 16
+
+void
+hex_and_ascii_print(const char *prefix, const void *data,
+ size_t len, const char *suffix)
+{
+ size_t i, j, k;
+ unsigned char *ptr = (unsigned char *)data;
+ unsigned char hexbuf[3 * MAXBUF + 1];
+ unsigned char asciibuf[MAXBUF + 1];
+
+ for (i = 0; i < len; i += MAXBUF) {
+ for (j = i, k = 0; j < i + MAXBUF && j < len; j++) {
+ unsigned char msnbl = ptr[j] >> 4;
+ unsigned char lsnbl = ptr[j] & 0x0f;
+
+ if (isprint(ptr[j]))
+ asciibuf[j % MAXBUF] = ptr[j];
+ else
+ asciibuf[j % MAXBUF] = '.';
+ asciibuf[(j % MAXBUF) + 1] = 0;
+
+ hexbuf[k++] = msnbl < 10 ? msnbl + '0' : msnbl + 'a' - 10;
+ hexbuf[k++] = lsnbl < 10 ? lsnbl + '0' : lsnbl + 'a' - 10;
+ if ((j % 2) == 1)
+ hexbuf[k++] = ' ';
+ }
+ for (; j < i + MAXBUF;j++) {
+ hexbuf[k++] = ' ';
+ hexbuf[k++] = ' ';
+ if ((j % 2) == 1)
+ hexbuf[k++] = ' ';
+ }
+ hexbuf[k] = 0;
+ printf("%s%s %s%s", prefix, hexbuf, asciibuf, suffix);
+ }
+}
diff --git a/lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c b/lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c
new file mode 100644
index 0000000..6d95e35
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/ngdumppktap/ngdumppktap.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright (c) 2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <net/bpf.h>
+#include <net/pktap.h>
+
+#include <assert.h>
+#include <err.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <uuid/uuid.h>
+
+#include "pcap/pcap-ng.h"
+#include "pcap-util.h"
+#include "pcap-pktap.h"
+
+bool capture_done = false;
+bool cap_pktap_v2 = false;
+bool dump_pktap_v1 = true;
+bool dump_pktap_v2 = false;
+const char *filename = "pktap.pcapng";
+const char *ifname = "pktap";
+bool truncation = false;
+int max_count = INT_MAX;
+int verbosity = 0;
+size_t max_length = 0;
+uint32_t snap_len = 0;
+bool want_pktap = true;
+
+struct dump_info {
+ pcap_t *p_cap;
+
+ char *ifname_v1;
+ pcap_dumper_t *dumper_v1;
+ char *filename_v1;
+ int packet_count_v1;
+ size_t total_pktap_header_space;
+ size_t total_bpf_length_v1;
+
+ char *ifname_v2;
+ pcap_dumper_t *dumper_v2;
+ char *filename_v2;
+ int packet_count_v2;
+ size_t total_pktap_v2_hdr_space;
+ size_t total_bpf_length_v2;
+};
+
+#define MAX_PACKET_LEN 65535
+
+static u_char temp_buffer[1024 * 1024];
+
+static void
+print_pktap_header(const struct pktap_header *pktp_hdr)
+{
+ uuid_string_t uuidstr, euuidstr;
+
+ fprintf(stderr, "pth_length %u (sizeof(struct pktap_header) %lu)\n",
+ pktp_hdr->pth_length, sizeof(struct pktap_header));
+ fprintf(stderr, "pth_type_next %u\n", pktp_hdr->pth_type_next);
+ fprintf(stderr, "pth_dlt %u\n", pktp_hdr->pth_dlt);
+ fprintf(stderr, "pth_ifname %s pth_iftype %d\n", pktp_hdr->pth_ifname, pktp_hdr->pth_iftype);
+ fprintf(stderr, "pth_flags 0x%x\n", pktp_hdr->pth_flags);
+ fprintf(stderr, "pth_protocol_family %u\n", pktp_hdr->pth_protocol_family);
+ fprintf(stderr, "pth_frame_pre_length %u pth_frame_post_length %u\n",
+ pktp_hdr->pth_frame_pre_length, pktp_hdr->pth_frame_post_length);
+ fprintf(stderr, "pth_svc %u\n", pktp_hdr->pth_svc);
+ fprintf(stderr, "pth_flowid %u\n", pktp_hdr->pth_flowid);
+ fprintf(stderr, "pth_ipproto %u\n", pktp_hdr->pth_ipproto);
+ fprintf(stderr, "pth_pid %u pth_epid %u\n", pktp_hdr->pth_pid, pktp_hdr->pth_epid);
+ fprintf(stderr, "pth_comm %s pth_ecomm %s\n", pktp_hdr->pth_comm, pktp_hdr->pth_ecomm);
+ uuid_unparse(pktp_hdr->pth_uuid, uuidstr);
+ uuid_unparse(pktp_hdr->pth_euuid, euuidstr);
+ fprintf(stderr, "pth_uuid %s pth_euuid %s\n",
+ uuid_is_null(pktp_hdr->pth_uuid) ? "" : uuidstr,
+ uuid_is_null(pktp_hdr->pth_euuid) ? "" : euuidstr);
+}
+
+static void
+print_pktap_v2_hdr(const struct pktap_v2_hdr *pktp_hdr)
+{
+ uuid_string_t uuidstr, euuidstr;
+ char *ptr = (char *)pktp_hdr;
+
+ fprintf(stderr, "pth2_length %u (sizeof(struct pktap_v2_hdr) %lu)\n",
+ pktp_hdr->pth_length, sizeof(struct pktap_v2_hdr));
+ fprintf(stderr, "pth2_dlt %u\n", pktp_hdr->pth_dlt);
+ fprintf(stderr, "pth2_ifname %s pth2_iftype %d\n",
+ pktp_hdr->pth_ifname_offset != 0 ? ptr + pktp_hdr->pth_ifname_offset : "",
+ pktp_hdr->pth_iftype);
+ fprintf(stderr, "pth2_flags 0x%x\n", pktp_hdr->pth_flags);
+ fprintf(stderr, "pth2_protocol_family %u\n", pktp_hdr->pth_protocol_family);
+ fprintf(stderr, "pth2_frame_pre_length %u pth2_frame_post_length %u\n",
+ pktp_hdr->pth_frame_pre_length, pktp_hdr->pth_frame_post_length);
+ fprintf(stderr, "pth2_svc %u\n", pktp_hdr->pth_svc);
+ fprintf(stderr, "pth2_flowid %u\n", pktp_hdr->pth_flowid);
+ fprintf(stderr, "pth2_ipproto %u\n", pktp_hdr->pth_ipproto);
+ fprintf(stderr, "pth2_pid %u pth2_e_pid %u\n", pktp_hdr->pth_pid, pktp_hdr->pth_e_pid);
+
+ fprintf(stderr, "pth2_comm %s pth2_ecomm %s\n",
+ pktp_hdr->pth_comm_offset != 0 ? ptr + pktp_hdr->pth_comm_offset : "",
+ pktp_hdr->pth_e_comm_offset != 0 ? ptr + pktp_hdr->pth_e_comm_offset : "");
+ if (pktp_hdr->pth_uuid_offset != 0)
+ uuid_unparse(*(const uuid_t *)(ptr + pktp_hdr->pth_uuid_offset), uuidstr);
+ if (pktp_hdr->pth_e_uuid_offset != 0)
+ uuid_unparse(*(const uuid_t *)(ptr + pktp_hdr->pth_e_uuid_offset), euuidstr);
+ fprintf(stderr, "pth2_uuid %s pth2_euuid %s\n",
+ pktp_hdr->pth_uuid_offset == 0 ? "" : uuidstr,
+ pktp_hdr->pth_e_uuid_offset == 0 ? "" : euuidstr);
+}
+static size_t
+convert_pktap_header_to_v2(const struct pktap_header *pktp_hdr, struct pktap_v2_hdr_space *pktap_v2_hdr_space)
+{
+ struct pktap_v2_hdr *pktap_v2_hdr;
+
+ pktap_v2_hdr = &pktap_v2_hdr_space->pth_hdr;
+
+ COPY_PKTAP_COMMON_FIELDS_TO_V2(pktap_v2_hdr, pktp_hdr);
+
+ if (!uuid_is_null(pktp_hdr->pth_uuid)) {
+ size_t len = sizeof(uuid_t);
+ uint8_t *ptr;
+
+ pktap_v2_hdr->pth_uuid_offset = pktap_v2_hdr->pth_length;
+ ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_uuid_offset;
+ uuid_copy(*(uuid_t *)ptr, pktp_hdr->pth_uuid);
+
+ pktap_v2_hdr->pth_length += len;
+ assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space));
+ }
+
+ if (!uuid_is_null(pktp_hdr->pth_euuid)) {
+ size_t len = sizeof(uuid_t);
+ uint8_t *ptr;
+
+ pktap_v2_hdr->pth_e_uuid_offset = pktap_v2_hdr->pth_length;
+ ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_e_uuid_offset;
+ uuid_copy(*(uuid_t *)ptr, pktp_hdr->pth_euuid);
+
+ pktap_v2_hdr->pth_length += len;
+ assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space));
+ }
+
+ if (strlen(pktp_hdr->pth_ifname) > 0) {
+ size_t len;
+ uint8_t *ptr;
+
+ pktap_v2_hdr->pth_ifname_offset = pktap_v2_hdr->pth_length;
+ ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_ifname_offset;
+ len = 1 + strlcpy((char *)ptr, pktp_hdr->pth_ifname, sizeof(pktap_v2_hdr_space->pth_ifname));
+
+ pktap_v2_hdr->pth_length += len;
+ assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space));
+ }
+
+ if (strlen(pktp_hdr->pth_comm) > 0) {
+ size_t len;
+ uint8_t *ptr;
+
+ pktap_v2_hdr->pth_comm_offset = pktap_v2_hdr->pth_length;
+ ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_comm_offset;
+ len = 1 + strlcpy((char *)ptr, pktp_hdr->pth_comm, sizeof(pktap_v2_hdr_space->pth_comm));
+
+ pktap_v2_hdr->pth_length += len;
+ assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space));
+ }
+
+ if (strlen(pktp_hdr->pth_ecomm) > 0) {
+ size_t len;
+ uint8_t *ptr;
+
+ pktap_v2_hdr->pth_e_comm_offset = pktap_v2_hdr->pth_length;
+ ptr = ((uint8_t *)pktap_v2_hdr) + pktap_v2_hdr->pth_e_comm_offset;
+ len = 1 + strlcpy((char *)ptr, pktp_hdr->pth_ecomm, sizeof(pktap_v2_hdr_space->pth_e_comm));
+
+ pktap_v2_hdr->pth_length += len;
+ assert(pktap_v2_hdr->pth_length < sizeof(struct pktap_v2_hdr_space));
+ }
+
+ return (pktap_v2_hdr->pth_length);
+}
+
+static size_t
+convert_v2_to_pktap_header(const struct pktap_v2_hdr *pktap_v2_hdr_src, struct pktap_header *pktap_header_dst)
+{
+ uint8_t *ptr = (uint8_t *)pktap_v2_hdr_src;
+
+ pktap_header_dst->pth_length = sizeof(struct pktap_header);
+ pktap_header_dst->pth_type_next = PTH_TYPE_PACKET;
+ pktap_header_dst->pth_dlt = pktap_v2_hdr_src->pth_dlt;
+ pktap_header_dst->pth_frame_pre_length = pktap_v2_hdr_src->pth_frame_pre_length;
+ pktap_header_dst->pth_frame_pre_length = pktap_v2_hdr_src->pth_frame_pre_length;
+ pktap_header_dst->pth_iftype = pktap_v2_hdr_src->pth_iftype;
+ pktap_header_dst->pth_ipproto = pktap_v2_hdr_src->pth_ipproto;
+ pktap_header_dst->pth_protocol_family = pktap_v2_hdr_src->pth_protocol_family;
+ pktap_header_dst->pth_svc = pktap_v2_hdr_src->pth_svc;
+ pktap_header_dst->pth_flowid = pktap_v2_hdr_src->pth_flowid;
+ pktap_header_dst->pth_pid = pktap_v2_hdr_src->pth_pid;
+ pktap_header_dst->pth_epid = pktap_v2_hdr_src->pth_e_pid;
+ pktap_header_dst->pth_flags = pktap_v2_hdr_src->pth_flags;
+ pktap_header_dst->pth_flags &= ~PTH_FLAG_V2_HDR;
+
+ if (pktap_v2_hdr_src->pth_uuid_offset != 0)
+ uuid_copy(pktap_header_dst->pth_uuid, (ptr + pktap_v2_hdr_src->pth_uuid_offset));
+
+ if (pktap_v2_hdr_src->pth_e_uuid_offset != 0)
+ uuid_copy(pktap_header_dst->pth_euuid, (ptr + pktap_v2_hdr_src->pth_e_uuid_offset));
+
+ if (pktap_v2_hdr_src->pth_ifname_offset != 0)
+ strlcpy(pktap_header_dst->pth_ifname, (char *)(ptr + pktap_v2_hdr_src->pth_ifname_offset), sizeof(pktap_header_dst->pth_ifname));
+
+ if (pktap_v2_hdr_src->pth_comm_offset != 0)
+ strlcpy(pktap_header_dst->pth_comm, (char *)(ptr + pktap_v2_hdr_src->pth_comm_offset), sizeof(pktap_header_dst->pth_comm));
+
+ if (pktap_v2_hdr_src->pth_e_comm_offset != 0)
+ strlcpy(pktap_header_dst->pth_ecomm, (char *)(ptr + pktap_v2_hdr_src->pth_e_comm_offset), sizeof(pktap_header_dst->pth_ecomm));
+
+ return (sizeof(struct pktap_header));
+}
+
+static bool
+save_pktap_v1(struct dump_info *dump_info, const struct pcap_pkthdr *h, const u_char *bytes)
+{
+ int status;
+ struct pcap_pkthdr pcap_pkthdr;
+
+ memcpy(&pcap_pkthdr, h, sizeof(struct pcap_pkthdr));
+
+ if (snap_len > 0 && pcap_pkthdr.caplen > snap_len) {
+ pcap_pkthdr.caplen = snap_len;
+ }
+ if (((struct pktap_v2_hdr *)bytes)->pth_flags & PTH_FLAG_V2_HDR) {
+ const struct pktap_v2_hdr *pktap_v2_hdr = (struct pktap_v2_hdr *)bytes;
+ struct pktap_header pktap_header_space;
+ struct pktap_header pktap_header_space_bis;
+ size_t v1_hdr_len;
+ struct pktap_v2_hdr_space pktap_v2_hdr_space;
+ size_t v2_hdr_len;
+
+ memset(&pktap_header_space, 0, sizeof(struct pktap_header));
+ memset(&pktap_header_space_bis, 0, sizeof(struct pktap_header));
+ memset(&pktap_v2_hdr_space, 0, sizeof(struct pktap_v2_hdr_space));
+
+
+ v1_hdr_len = convert_v2_to_pktap_header(pktap_v2_hdr, &pktap_header_space);
+ assert(v1_hdr_len == sizeof(struct pktap_header));
+
+ if (verbosity > 1) {
+ print_pktap_v2_hdr(pktap_v2_hdr);
+ print_pktap_header(&pktap_header_space);
+ }
+ v2_hdr_len = convert_pktap_header_to_v2(&pktap_header_space, &pktap_v2_hdr_space);
+
+ /*
+ * The conversion is not symetrical because the strings in the pktap_v2_hdr
+ * are of variable length and null uuid and empty string are omitted
+ * Note that BPF may pass empty string and null uuid
+ * We can compare the conversion to pktap_header
+ */
+ (void) convert_v2_to_pktap_header(&pktap_v2_hdr_space.pth_hdr, &pktap_header_space_bis);
+ assert(memcmp(&pktap_header_space, &pktap_header_space_bis, v1_hdr_len) == 0);
+
+ assert(pcap_pkthdr.caplen + sizeof(struct pktap_header) - pktap_v2_hdr->pth_length <= sizeof(temp_buffer));
+
+ memcpy(temp_buffer, &pktap_header_space, sizeof(struct pktap_header));
+ memcpy(temp_buffer + sizeof(struct pktap_header), bytes + pktap_v2_hdr->pth_length,
+ pcap_pkthdr.caplen - pktap_v2_hdr->pth_length);
+
+ pcap_pkthdr.caplen += sizeof(struct pktap_header) - pktap_v2_hdr->pth_length;
+ pcap_pkthdr.len += sizeof(struct pktap_header) - pktap_v2_hdr->pth_length;
+
+ status = pcap_ng_dump_pktap(dump_info->p_cap, dump_info->dumper_v1,
+ &pcap_pkthdr, temp_buffer);
+ if (status == 0) {
+ warnx("%s: pcap_ng_dump_pktap: %s\n",
+ __func__, pcap_geterr(dump_info->p_cap));
+ return (false);
+ }
+ } else if (((struct pktap_header *)bytes)->pth_type_next == PTH_TYPE_PACKET) {
+ status = pcap_ng_dump_pktap(dump_info->p_cap, dump_info->dumper_v1,
+ &pcap_pkthdr, bytes);
+ if (status == 0) {
+ warnx("%s: pcap_ng_dump_pktap: %s\n",
+ __func__, pcap_geterr(dump_info->p_cap));
+ return (false);
+ }
+ } else {
+ warnx("%s: unkwnown pktap_header type\n",
+ __func__);
+ return (false);
+ }
+
+ dump_info->packet_count_v1++;
+ dump_info->total_bpf_length_v1 += sizeof(struct bpf_hdr) + pcap_pkthdr.caplen;
+ dump_info->total_pktap_header_space += sizeof(struct pktap_header);
+
+ if (verbosity > 0) {
+ fprintf(stderr, "%s: v1 packet count: %d total bpf length: %lu\n",
+ __func__, dump_info->packet_count_v1, dump_info->total_bpf_length_v1);
+ }
+
+ return (true);
+}
+
+static void
+zero_out_unused_pktap_header_fields_for_v2(struct pktap_header *pktp_hdr)
+{
+ pktp_hdr->pth_ifunit = 0;
+ pktp_hdr->pth_tstamp.tv_sec = 0;
+ pktp_hdr->pth_tstamp.tv_usec = 0;
+}
+
+static bool
+save_pktap_v2(struct dump_info *dump_info, const struct pcap_pkthdr *h, const u_char *bytes)
+{
+ int status;
+ struct pcap_pkthdr pcap_pkthdr;
+
+ memcpy(&pcap_pkthdr, h, sizeof(struct pcap_pkthdr));
+
+ if (snap_len > 0 && pcap_pkthdr.caplen > snap_len) {
+ pcap_pkthdr.caplen = snap_len;
+ }
+
+ if (((struct pktap_v2_hdr *)bytes)->pth_flags & PTH_FLAG_V2_HDR) {
+ const struct pktap_v2_hdr *pktap_v2_hdr = (struct pktap_v2_hdr *)bytes;
+ struct pktap_header pktap_header_space;
+ size_t v1_hdr_len;
+
+ v1_hdr_len = convert_v2_to_pktap_header(pktap_v2_hdr, &pktap_header_space);
+ assert(v1_hdr_len == sizeof(struct pktap_header));
+
+ dump_info->total_pktap_v2_hdr_space += pktap_v2_hdr->pth_length;
+
+ status = pcap_ng_dump_pktap_v2(dump_info->p_cap, dump_info->dumper_v2,
+ &pcap_pkthdr, bytes, NULL);
+ if (status == 0) {
+ warnx("%s: pcap_ng_dump_pktap_v2: %s\n",
+ __func__, pcap_geterr(dump_info->p_cap));
+ pcap_breakloop(dump_info->p_cap);
+ }
+ } else if (((struct pktap_header *)bytes)->pth_type_next == PTH_TYPE_PACKET) {
+ const struct pktap_header *pktp_hdr = (struct pktap_header *)bytes;
+ struct pktap_header pktap_header_space;
+ size_t v1_hdr_len;
+ struct pktap_v2_hdr_space pktap_v2_hdr_space;
+ size_t v2_hdr_len;
+ size_t offset;
+ u_char *new_bytes;
+ struct pktap_header pktap_header_copy;
+
+ memset(&pktap_header_space, 0, sizeof(struct pktap_header));
+ memset(&pktap_header_copy, 0, sizeof(struct pktap_header));
+
+ /*
+ * Zero out the fields in the pktap_header we do not care about
+ */
+ memcpy(&pktap_header_copy, pktp_hdr, sizeof(struct pktap_header));
+ zero_out_unused_pktap_header_fields_for_v2(&pktap_header_copy);
+
+ v2_hdr_len = convert_pktap_header_to_v2(&pktap_header_copy, &pktap_v2_hdr_space);
+
+ if (verbosity > 1) {
+ print_pktap_header(&pktap_header_copy);
+ print_pktap_v2_hdr(&pktap_v2_hdr_space.pth_hdr);
+ }
+ dump_info->total_pktap_v2_hdr_space += pktap_v2_hdr_space.pth_hdr.pth_length;
+
+ v1_hdr_len = convert_v2_to_pktap_header(&pktap_v2_hdr_space.pth_hdr, &pktap_header_space);
+ assert(v1_hdr_len == sizeof(struct pktap_header));
+ assert(memcmp(&pktap_header_copy, &pktap_header_space, sizeof(struct pktap_header)) == 0);
+
+ offset = sizeof(struct pktap_header) - v2_hdr_len;
+ new_bytes = (u_char *)bytes + offset;
+ memcpy(new_bytes, &pktap_v2_hdr_space, v2_hdr_len);
+
+ pcap_pkthdr.caplen -= offset;
+ pcap_pkthdr.len -= offset;
+ status = pcap_ng_dump_pktap_v2(dump_info->p_cap, dump_info->dumper_v2,
+ &pcap_pkthdr, new_bytes, NULL);
+ if (status == 0) {
+ warnx("%s: pcap_ng_dump_pktap_v2: %s\n",
+ __func__, pcap_geterr(dump_info->p_cap));
+ return (false);
+ }
+ } else {
+ warnx("%s: unkwnown pktap header type\n",
+ __func__);
+ return (false);
+ }
+
+ dump_info->packet_count_v2++;
+ dump_info->total_bpf_length_v2 += sizeof(struct bpf_hdr) + pcap_pkthdr.caplen;
+
+ if (verbosity > 0) {
+ fprintf(stderr, "%s: v2 packet count: %d total bpf length: %lu\n",
+ __func__, dump_info->packet_count_v2, dump_info->total_bpf_length_v2);
+ }
+
+ return (true);
+}
+
+
+static void
+readcallback(u_char *user, const struct pcap_pkthdr *h, const u_char *bytes)
+{
+ struct dump_info *dump_info = (struct dump_info *) user;
+ bool v1_done = false;
+ bool v2_done = false;
+
+ if (dump_pktap_v1) {
+ if ((max_count != 0 && dump_info->packet_count_v1 > max_count) ||
+ (max_length != 0 && dump_info->total_bpf_length_v1 >= max_length)) {
+ v1_done = true;
+ } else if (!save_pktap_v1(dump_info, h, bytes)) {
+ v1_done = true;
+ v2_done = true;
+ }
+ } else {
+ v1_done = true;
+ }
+
+ if (dump_pktap_v2) {
+ if ((max_count != 0 && dump_info->packet_count_v2 > max_count) ||
+ (max_length != 0 && dump_info->total_bpf_length_v2 >= max_length)) {
+ v2_done = true;
+ } else if (!save_pktap_v2(dump_info, h, bytes)) {
+ v2_done = true;
+ }
+ } else {
+ v2_done = true;
+ }
+
+ if (capture_done || (v1_done && v2_done)) {
+ if (verbosity > 0) {
+ fprintf(stderr, "%s: done\n",
+ __func__);
+ }
+ pcap_breakloop(dump_info->p_cap);
+ }
+}
+
+static void
+usage(void)
+{
+#define OPTION_FMT " %-20s %s\n"
+ printf("# usage: %s [-c 1|2] [-d 1|-1|2|-2] [-f filename] [-h] [-i ifname] [-l max_length] [-n max_count] [-s snap_len] [-t 0|1] [-v]\n",
+ getprogname());
+ printf(OPTION_FMT, "-c 1|2", "capture version 1 'struct pktap_header' or version 2 'struct pktap_hdr_v2' (v1 by default)");
+ printf(OPTION_FMT, "-d 1|-1|2|-2", "dump using version 1 pcap_ng_dump_pktap() and/or version 2 pcap_ng_dump_pktap_v2() (v1 by default)");
+ printf(OPTION_FMT, "-f filename", "file name for dump file (to be prefixed with 'v1_' or 'v2'");
+ printf(OPTION_FMT, "-h", "display this help");
+ printf(OPTION_FMT, "-i ifname", "capture interface name (pktap by default)");
+ printf(OPTION_FMT, "-l max_length", "maximum length of packet captured (unlimited by default");
+ printf(OPTION_FMT, "-n max_count", "maximum number of packet to capture (unlimited by default");
+ printf(OPTION_FMT, "-s snap_len", "snap len (unlimited by default)");
+ printf(OPTION_FMT, "-t 0|1", "truncation mode (off by default)");
+ printf(OPTION_FMT, "-v", "increase versbosity");
+}
+
+void
+parse_command_line(int argc, char * const argv[])
+{
+ int ch;
+
+ if (argc == 1) {
+ usage();
+ exit(EX_OK);
+ }
+ while ((ch = getopt(argc, argv, "c:d:f:hi:l:n:qs:t:vw:")) != -1) {
+ switch (ch) {
+ case 'c':
+ if (strcmp(optarg, "1") == 0) {
+ cap_pktap_v2 = false;
+ } else if (strcmp(optarg, "2") == 0) {
+ cap_pktap_v2 = true;
+ } else {
+ warnx("bad parameter '%s' for option '-%c'", optarg, ch);
+ usage();
+ exit(EX_USAGE);
+ }
+ break;
+
+ case 'd':
+ if (strcmp(optarg, "1") == 0) {
+ dump_pktap_v1 = true;
+ } else if (strcmp(optarg, "-1") == 0) {
+ dump_pktap_v1 = false;
+ } else if (strcmp(optarg, "2") == 0) {
+ dump_pktap_v2 = true;
+ } else if (strcmp(optarg, "-2") == 0) {
+ dump_pktap_v2 = false;
+ } else {
+ warnx("bad parameter '%s' for option '-%c'", optarg, ch);
+ usage();
+ exit(EX_USAGE);
+ }
+ break;
+
+ case 'f':
+ filename = optarg;
+ break;
+
+ case 'h':
+ usage();
+ exit(EX_OK);
+
+ case 'i':
+ ifname = optarg;
+ break;
+
+ case 'l':
+ max_length = strtoul(optarg, NULL, 0);
+ break;
+
+ case 'n':
+ max_count = atoi(optarg);
+ break;
+
+ case 'q':
+ verbosity--;
+ break;
+
+ case 's':
+ snap_len = (uint32_t) strtoul(optarg, NULL, 0);
+ break;
+
+ case 't':
+ truncation = !!atoi(optarg);
+ break;
+
+ case 'v':
+ verbosity++;
+ break;
+
+ case 'w':
+ want_pktap = !!atoi(optarg);
+ break;
+
+ default:
+ usage();
+ exit(EX_USAGE);
+ }
+ }
+}
+
+void
+signal_handler(int sig)
+{
+ capture_done = true;
+}
+
+int
+main(int argc, char * const argv[]) {
+ char ebuf[PCAP_ERRBUF_SIZE];
+ int status;
+ struct dump_info dump_info = {};
+
+ parse_command_line(argc, argv);
+
+ dump_info.ifname_v1 = pcap_setup_pktap_interface(ifname, ebuf);
+ if (dump_info.ifname_v1 == NULL) {
+ errx(EX_OSERR, "pcap_setup_pktap_interface(%s) fail - %s",
+ ifname, ebuf);
+ }
+ dump_info.ifname_v2 = pcap_setup_pktap_interface(ifname, ebuf);
+ if (dump_info.ifname_v2 == NULL) {
+ errx(EX_OSERR, "pcap_setup_pktap_interface(pktap) fail - %s",
+ ebuf);
+ }
+
+ dump_info.p_cap = pcap_create(ifname, ebuf);
+ if (dump_info.p_cap == NULL) {
+ errx(EX_OSERR, "pcap_create(%s) fail - %s",
+ ifname, ebuf);
+ }
+ status = pcap_set_timeout(dump_info.p_cap, 1000);
+ if (status != 0) {
+ errx(EX_OSERR, "pcap_create(%s) fail - %s",
+ ifname, pcap_statustostr(status));
+ }
+
+ /*
+ * Must be called before pcap_activate()
+ */
+ pcap_set_want_pktap(dump_info.p_cap, want_pktap);
+ pcap_set_pktap_hdr_v2(dump_info.p_cap, cap_pktap_v2);
+ pcap_set_truncation_mode(dump_info.p_cap, truncation);
+ if (snap_len > 0)
+ pcap_set_snaplen(dump_info.p_cap, snap_len);
+
+ status = pcap_activate(dump_info.p_cap);
+ if (status < 0) {
+ if (status == PCAP_ERROR) {
+ errx(EX_OSERR, "pcap_activate(%s) fail - %s",
+ ifname, pcap_geterr(dump_info.p_cap));
+ } else {
+ errx(EX_OSERR, "pcap_activate(%s) fail - %s %s",
+ ifname, pcap_statustostr(status), pcap_geterr(dump_info.p_cap));
+ }
+ }
+
+ if (verbosity) {
+ int dlt = pcap_datalink(dump_info.p_cap);
+ const char *dltname = pcap_datalink_val_to_name(dlt);
+ int n_dlts, i;
+ int *dlts = 0;
+
+ fprintf(stderr, "wantpktap %d\n", want_pktap);
+
+ fprintf(stderr, "pcap_datalink: %d name: %s\n", dlt, dltname);
+
+ n_dlts = pcap_list_datalinks(dump_info.p_cap, &dlts);
+
+ for (i = 0; i < n_dlts; i++) {
+ dltname = pcap_datalink_val_to_name(dlts[i]);
+ fprintf(stderr, "pcap_list_datalinks[%d]: %d name: %s\n", i, dlts[i], dltname);
+ }
+ pcap_free_datalinks(dlts);
+ }
+
+ if (dump_pktap_v1) {
+ dump_info.filename_v1 = malloc(PATH_MAX);
+ snprintf(dump_info.filename_v1, PATH_MAX, "v1_%s", filename);
+ dump_info.dumper_v1 = pcap_ng_dump_open(dump_info.p_cap, dump_info.filename_v1);
+ if (dump_info.dumper_v1 == NULL) {
+ errx(EX_OSERR, "pcap_ng_dump_open(%s) fail - %s",
+ dump_info.filename_v1, pcap_geterr(dump_info.p_cap));
+ }
+ }
+
+ if (dump_pktap_v2) {
+ dump_info.filename_v2 = malloc(PATH_MAX);
+ snprintf(dump_info.filename_v2, PATH_MAX, "v2_%s", filename);
+ dump_info.dumper_v2 = pcap_ng_dump_open(dump_info.p_cap, dump_info.filename_v2);
+ if (dump_info.dumper_v2 == NULL) {
+ errx(EX_OSERR, "pcap_ng_dump_open(%s) fail - %s",
+ dump_info.filename_v2, pcap_geterr(dump_info.p_cap));
+ }
+ }
+
+ /* to stop the capture */
+ signal(SIGINT, signal_handler);
+
+ while (true) {
+ status = pcap_dispatch(dump_info.p_cap, -1, readcallback, (u_char *) &dump_info);
+ if (status == -1) {
+ errx(EX_OSERR, "pcap_dispatch(%s) fail - %s",
+ ifname, pcap_geterr(dump_info.p_cap));
+ } else if (status == -2) {
+ /* pcap_breakloop() called */
+ break;
+ }
+ }
+
+ if (dump_pktap_v1) {
+ pcap_dump_close(dump_info.dumper_v1);
+ fprintf(stderr, "v1 file: %s packet count: %d total bpf length: %lu pktap header space %lu\n",
+ dump_info.filename_v1, dump_info.packet_count_v1,
+ dump_info.total_bpf_length_v1, dump_info.total_pktap_header_space);
+ }
+ if (dump_pktap_v2) {
+ pcap_dump_close(dump_info.dumper_v2);
+ fprintf(stderr, "v2 file: %s packet count: %d total bpf length: %lu pktap v2 hdr space %lu\n",
+ dump_info.filename_v2, dump_info.packet_count_v2,
+ dump_info.total_bpf_length_v2, dump_info.total_pktap_v2_hdr_space);
+ }
+ pcap_close(dump_info.p_cap);
+
+ exit(EX_OK);
+}
diff --git a/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.1 b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.1
new file mode 100644
index 0000000..e2420e5
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.1
@@ -0,0 +1,79 @@
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 10/12/12 \" DATE
+.Dt ngdumptest 1 \" Program name and manual section number
+.Os Darwin
+.Sh NAME \" Section Header - required - don't modify
+.Nm ngdumptest,
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line.
+.Nm Other_name_for_same_program(),
+.Nm Yet another name for the same program.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd This line parsed for whatis database.
+.Sh SYNOPSIS \" Section Header - required - don't modify
+.Nm
+.Op Fl abcd \" [-abcd]
+.Op Fl a Ar path \" [-a path]
+.Op Ar file \" [file]
+.Op Ar \" [file ...]
+.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
+arg2 ... \" Arguments
+.Sh DESCRIPTION \" Section Header - required - don't modify
+Use the .Nm macro to refer to your program throughout the man page like such:
+.Nm
+Underlining is accomplished with the .Ar macro like this:
+.Ar underlined text .
+.Pp \" Inserts a space
+A list of items with descriptions:
+.Bl -tag -width -indent \" Begins a tagged list
+.It item a \" Each item preceded by .It macro
+Description of item a
+.It item b
+Description of item b
+.El \" Ends the list
+.Pp
+A list of flags and their descriptions:
+.Bl -tag -width -indent \" Differs from above in tag removed
+.It Fl a \"-a flag as a list item
+Description of -a flag
+.It Fl b
+Description of -b flag
+.El \" Ends the list
+.Pp
+.\" .Sh ENVIRONMENT \" May not be needed
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
+.\" .It Ev ENV_VAR_1
+.\" Description of ENV_VAR_1
+.\" .It Ev ENV_VAR_2
+.\" Description of ENV_VAR_2
+.\" .El
+.Sh FILES \" File used or created by the topic of the man page
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /usr/share/file_name
+FILE_1 description
+.It Pa /Users/joeuser/Library/really_long_file_name
+FILE_2 description
+.El \" Ends the list
+.\" .Sh DIAGNOSTICS \" May not be needed
+.\" .Bl -diag
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .El
+.Sh SEE ALSO
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr a 1 ,
+.Xr b 1 ,
+.Xr c 1 ,
+.Xr a 2 ,
+.Xr b 2 ,
+.Xr a 3 ,
+.Xr b 3
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file
diff --git a/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c
new file mode 100644
index 0000000..e9fbcc7
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/ngdumptest/ngdumptest.c
@@ -0,0 +1,702 @@
+/*
+ * Copyright (c) 2012-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include <stdio.h>
+#include <err.h>
+#include <sysexits.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/kern_event.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <uuid/uuid.h>
+#include <net/pktap.h>
+
+#include "pcap/bpf.h"
+
+#include "pcap/pcap-ng.h"
+#include "pcap-util.h"
+
+enum {
+ SIMPLE_PACKET = 0,
+ ENHANCED_PACKET = 1,
+ OBSOLETE_PACKET = 2,
+ PKTAP_PACKET = 3
+};
+
+const char *if_name = NULL;
+int type_of_packet = ENHANCED_PACKET;
+char *proc_name = NULL;
+uint32_t proc_pid = -1;
+uuid_t proc_uuid;
+int32_t proc_index = -1;
+const char *comment = NULL;
+pcap_t *pcap = NULL;
+pcap_dumper_t *dumper = NULL;
+size_t ext_len = 65536;
+void *ext_buffer = NULL;
+int first_comment = 0;
+unsigned char *packet_data = NULL;
+size_t packet_length = 0;
+unsigned long num_data_blocks = 1;
+int copy_data_buffer = 0;
+int verbose = 0;
+
+void hex_and_ascii_print(const char *, const void *, size_t, const char *);
+
+void
+help(const char *str)
+{
+ printf("# usage: %s options...\n", str);
+ printf("# options in order of dependency:\n");
+ printf(" %-36s # %s\n", "-4 ipv4:name[:name...]", "IPv4 name resolution record");
+ printf(" %-36s # %s\n", "-6 ipv6:name[:name...]", "IPv6 name resolution record");
+ printf(" %-36s # %s\n", "-C", "copy data packet from data buffer");
+ printf(" %-36s # %s\n", "-c string", "comment option");
+ printf(" %-36s # %s\n", "-D length", "packet data length");
+ printf(" %-36s # %s\n", "-d string", "packet data as a string");
+ printf(" %-36s # %s\n", "-f", "first comment option");
+ printf(" %-36s # %s\n", "-k len", "kernel event of given len");
+ printf(" %-36s # %s\n", "-i name", "interface name");
+ printf(" %-36s # %s\n", "-n num_data", "number of data blocks");
+ printf(" %-36s # %s\n", "-p name:pid:uuid", "process name, pid and uuid");
+ printf(" %-36s # %s\n", "-p type:data", "secrets type (number), secrets data (string)");
+ printf(" %-36s # %s\n", "-t (simple|enhanced|obsolote|pktap)", "type of packet");
+ printf(" %-36s # %s\n", " ", "note obsolete is not implemented");
+ printf(" %-36s # %s\n", "-w name", "packet capture file name");
+ printf(" %-36s # %s\n", "-x [buffer_length]", "externalize in buffer of given length");
+}
+
+void
+write_block(pcapng_block_t block)
+{
+ bpf_u_int32 n;
+
+ if (dumper != NULL) {
+ n = pcap_ng_dump_block(dumper, block);
+ if (n != pcap_ng_block_get_len(block))
+ printf("%s: block len %u != pcap_ng_block_get_len() %u\n",
+ __func__, pcap_ng_block_get_len(block), n);
+ }
+ if (ext_buffer != NULL) {
+ n = pcap_ng_externalize_block(ext_buffer, ext_len, block);
+ hex_and_ascii_print("", ext_buffer, pcap_ng_block_get_len(block), "\n");
+ if (n != pcap_ng_block_get_len(block))
+ printf("%s: block len %u != pcap_ng_externalize_block() %u\n",
+ __func__, pcap_ng_block_get_len(block), n);
+ }
+}
+
+void
+make_interface_description_block(const char *name)
+{
+ struct pcapng_interface_description_fields *idb_fields;
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ if (verbose)
+ printf("%s\n", __func__);
+
+ pcap_ng_block_reset(block, PCAPNG_BT_IDB);
+
+ if (first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ idb_fields = pcap_ng_get_interface_description_fields(block);
+ idb_fields->idb_linktype = DLT_RAW;
+ idb_fields->idb_snaplen = 65536;
+
+ if (!first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ pcap_ng_block_add_option_with_string(block, PCAPNG_IF_NAME, name);
+
+ write_block(block);
+
+ pcap_ng_free_block(block);
+
+}
+
+void
+make_process_information_block(const char *name, uint32_t pid, const uuid_t uu)
+{
+ struct pcapng_process_information_fields *pib_fields;
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ if (verbose)
+ printf("%s\n", __func__);
+
+ pcap_ng_block_reset(block, PCAPNG_BT_PIB);
+
+ if (first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ pib_fields = pcap_ng_get_process_information_fields(block);
+ pib_fields->process_id = pid;
+
+ if (!first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ if (name != NULL)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_PIB_NAME, name);
+
+ if (uuid_is_null(uu) == 0)
+ pcap_ng_block_add_option_with_uuid(block, PCAPNG_PIB_UUID, uu);
+
+ write_block(block);
+
+ pcap_ng_free_block(block);
+}
+
+void
+make_kern_event_block(struct kern_event_msg *event)
+{
+ struct pcapng_os_event_fields *osev_fields;
+ struct timeval ts;
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ if (verbose)
+ printf("%s\n", __func__);
+
+ gettimeofday(&ts, NULL);
+
+ pcap_ng_block_reset(block, PCAPNG_BT_OSEV);
+
+ if (first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ osev_fields = pcap_ng_get_os_event_fields(block);
+ osev_fields->type = PCAPNG_OSEV_KEV;
+ osev_fields->timestamp_high = (bpf_u_int32)ts.tv_sec;
+ osev_fields->timestamp_low = ts.tv_usec;
+ osev_fields->len = event->total_size;
+
+ if (copy_data_buffer)
+ pcap_ng_block_packet_copy_data(block, event, event->total_size);
+ else
+ pcap_ng_block_packet_set_data(block, event, event->total_size);
+
+ if (!first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ write_block(block);
+
+ pcap_ng_free_block(block);
+}
+
+void
+make_decryption_secrets_block(uint32_t type, size_t len, uint8_t *data)
+{
+ struct pcapng_decryption_secrets_fields *dsb_fields;
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ if (verbose)
+ printf("%s\n", __func__);
+
+ pcap_ng_block_reset(block, PCAPNG_BT_DSB);
+
+ if (first_comment && comment) {
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+ }
+
+ dsb_fields = pcap_ng_get_decryption_secrets_fields(block);
+ dsb_fields->secrets_type = type;
+ dsb_fields->secrets_length = (uint32_t)len;
+
+ if (copy_data_buffer) {
+ pcap_ng_block_packet_copy_data(block, data, dsb_fields->secrets_length);
+ } else {
+ pcap_ng_block_packet_set_data(block, data, dsb_fields->secrets_length);
+ }
+ if (!first_comment && comment) {
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+ }
+ write_block(block);
+
+ pcap_ng_free_block(block);
+}
+
+void
+make_data_block(const void *data, size_t len)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_data_blocks; i++) {
+ if (verbose)
+ printf("%s\n", __func__);
+
+ switch (type_of_packet) {
+ case SIMPLE_PACKET: {
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ pcap_ng_block_reset(block, PCAPNG_BT_SPB);
+
+ if (first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ if (copy_data_buffer)
+ pcap_ng_block_packet_copy_data(block, data, (bpf_u_int32)len);
+ else
+ pcap_ng_block_packet_set_data(block, data, (bpf_u_int32)len);
+
+ if (!first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ write_block(block);
+
+ pcap_ng_free_block(block);
+ break;
+ }
+ case ENHANCED_PACKET: {
+ struct pcapng_enhanced_packet_fields *epb_fields;
+ uint32_t pktflags = PCAPNG_PBF_DIR_OUTBOUND | PCAPNG_PBF_DIR_INBOUND;
+ uint32_t pmdflags = PCAPNG_EPB_PMDF_NEW_FLOW | PCAPNG_EPB_PMDF_REXMIT |
+ PCAPNG_EPB_PMDF_KEEP_ALIVE | PCAPNG_EPB_PMDF_SOCKET | PCAPNG_EPB_PMDF_NEXUS_CHANNEL;
+
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ pcap_ng_block_reset(block, PCAPNG_BT_EPB);
+
+ if (first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ epb_fields = pcap_ng_get_enhanced_packet_fields(block);
+ epb_fields->caplen = (bpf_u_int32)len;
+ epb_fields->len = (bpf_u_int32)len;
+ epb_fields->interface_id = 0;
+ epb_fields->timestamp_high = 10000;
+ epb_fields->timestamp_low = 2000;
+
+ if (copy_data_buffer)
+ pcap_ng_block_packet_copy_data(block, data, (bpf_u_int32)len);
+ else
+ pcap_ng_block_packet_set_data(block, data, (bpf_u_int32)len);
+
+ if (proc_name != NULL) {
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PIB_INDEX, &proc_index, sizeof(proc_index));
+ }
+ if (!first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_FLAGS , &pktflags, 4);
+
+ pcap_ng_block_add_option_with_value(block, PCAPNG_EPB_PMD_FLAGS, &pmdflags, 4);
+
+ write_block(block);
+
+ pcap_ng_free_block(block);
+ break;
+ }
+ case PKTAP_PACKET: {
+ struct pcap_pkthdr h;
+ u_char *buffer = malloc(sizeof(struct pktap_header) + len);
+ struct pktap_header *pktp_hdr;
+
+ bzero(&h, sizeof(struct pcap_pkthdr));
+ h.ts.tv_sec = 10000;
+ h.ts.tv_usec = 2000;
+ h.caplen = (bpf_u_int32) (sizeof(struct pktap_header) + len);
+ h.len = (bpf_u_int32) (sizeof(struct pktap_header) + len);
+
+ pktp_hdr = (struct pktap_header *)buffer;
+ bzero(pktp_hdr, sizeof(struct pktap_header));
+ bcopy(data, pktp_hdr + 1, len);
+ pktp_hdr->pth_length = sizeof(struct pktap_header);
+ snprintf(pktp_hdr->pth_ifname, sizeof(pktp_hdr->pth_ifname), "%s", if_name);
+ pktp_hdr->pth_pid = proc_pid;
+ pktp_hdr->pth_epid = -1;
+ if (proc_name != NULL) {
+ snprintf(pktp_hdr->pth_comm, sizeof(pktp_hdr->pth_comm), "%s", proc_name);
+ }
+ uuid_copy(pktp_hdr->pth_uuid, proc_uuid);
+
+ if (comment != NULL) {
+ if (pcap_ng_dump_pktap_comment(pcap, dumper, &h, buffer, comment) == 0)
+ warnx("pcap_ng_dump_pktap() error %s\n", pcap_geterr(pcap));
+ } else {
+ if (pcap_ng_dump_pktap(pcap, dumper, &h, buffer) == 0)
+ warnx("pcap_ng_dump_pktap() error %s\n", pcap_geterr(pcap));
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+}
+
+void
+make_section_header_block()
+{
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ if (verbose)
+ printf("%s\n", __func__);
+
+ pcap_ng_block_reset(block, PCAPNG_BT_SHB);
+
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT,
+ "section header block");
+
+ write_block(block);
+
+ pcap_ng_free_block(block);
+}
+
+void
+make_name_resolution_record(int af, void *addr, char **names)
+{
+ pcapng_block_t block = pcap_ng_block_alloc(pcap_ng_block_size_max());
+
+ if (verbose)
+ printf("%s\n", __func__);
+
+ pcap_ng_block_reset(block, PCAPNG_BT_NRB);
+
+ if (first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ if (af == AF_INET) {
+ pcap_ng_block_add_name_record_with_ip4(block, (struct in_addr *)addr, (const char **)names);
+ } else {
+ pcap_ng_block_add_name_record_with_ip6(block, (struct in6_addr *)addr, (const char **)names);
+ }
+
+ if (!first_comment && comment)
+ pcap_ng_block_add_option_with_string(block, PCAPNG_OPT_COMMENT, comment);
+
+ write_block(block);
+
+ pcap_ng_free_block(block);
+}
+
+int
+main(int argc, char * const argv[])
+{
+ int ch;
+ const char *file_name = NULL;
+ int kevid = 0;
+
+ if (argc == 1) {
+ help(argv[0]);
+ return (0);
+ }
+
+ /*
+ * Loop through argument to build PCAP-NG block
+ * Optionally write to file
+ */
+ while ((ch = getopt(argc, argv, "4:6:Cc:D:d:fk:hi:n:p:s:t:w:xv")) != -1) {
+ switch (ch) {
+ case 'C':
+ copy_data_buffer = 1;
+ break;
+
+ case 'c':
+ comment = optarg;
+ break;
+
+ case 'D': {
+ int i;
+
+ packet_length = strtoul(optarg, NULL, 0);
+ packet_data = malloc(packet_length);
+ for (i = 0; i < packet_length; i++) {
+ packet_data[i] = i % 256;
+ }
+
+ make_data_block(packet_data, packet_length);
+ free(packet_data);
+ break;
+ }
+ case 'd':
+ packet_length = strlen(optarg);
+ packet_data = (unsigned char *)optarg;
+ make_data_block(packet_data, packet_length);
+ break;
+
+ case 'f':
+ first_comment = 1;
+ break;
+
+ case 'k': {
+ struct kern_event_msg *kevmsg = NULL;
+ u_long len;
+
+ len = strtoul(optarg, NULL, 0);
+ if (len < sizeof(struct kern_event_msg)) {
+ fprintf(stderr, "malformed arguments for option 'n'\n");
+ help(argv[0]);
+ return (0);
+ }
+ kevmsg = (struct kern_event_msg *)calloc(1, len);
+ kevmsg->total_size = (u_int32_t)len;
+ kevmsg->vendor_code = KEV_VENDOR_APPLE;
+ kevmsg->kev_class = KEV_NETWORK_CLASS;
+ kevmsg->kev_subclass = KEV_DL_SUBCLASS;
+ kevmsg->id = kevid++;
+ kevmsg->event_code = KEV_DL_LINK_QUALITY_METRIC_CHANGED;
+
+ make_kern_event_block(kevmsg);
+ free(kevmsg);
+ break;
+ }
+ case 'h':
+ help(argv[0]);
+ return (0);
+
+ case 'i':
+ if_name = optarg;
+
+ make_interface_description_block(if_name);
+
+ break;
+
+ case '4':
+ case '6': {
+ int af;
+ int name_count = 0;
+ char *ptr = strchr(optarg, ':');
+ char **names = NULL;
+ int i;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ int retval;
+
+
+ if (ptr == NULL) {
+ fprintf(stderr, "malformed arguments for option 'n'\n");
+ help(argv[0]);
+ return (0);
+ }
+ do {
+ ptr++;
+ name_count += 1;
+ } while ((ptr = strchr(ptr, ':')) != NULL);
+
+ names = calloc(name_count +1, sizeof(char *));
+
+ ptr = strchr(optarg, ':');
+ *ptr = '\0';
+
+ if (ch == '4') {
+ af = AF_INET;
+ retval = inet_pton(af, optarg, &ina);
+ } else {
+ af = AF_INET6;
+ retval = inet_pton(af, optarg, &in6a);
+ }
+ if (retval == 0)
+ errx(1, "This is not an %s address: '%s'\n",
+ af == AF_INET ? "IPv4" : "IPv6",
+ optarg);
+ else if (retval == -1)
+ err(1, "inet_pton(%s) failed\n", optarg);
+
+ for (i = 0; i < name_count; i++) {
+ char *end;
+ ptr++;
+ end = strchr(ptr, ':');
+ if (end != NULL)
+ *end = '\0';
+
+ names[i] = strdup(ptr);
+ if (end != NULL)
+ ptr = end;
+ }
+
+ if (af == AF_INET)
+ make_name_resolution_record(af, &ina, names);
+ else
+ make_name_resolution_record(af, &in6a, names);
+ break;
+ }
+
+ case 'n': {
+ num_data_blocks = strtoul(optarg, NULL, 0);
+ break;
+ }
+
+ case 'p': {
+ char *ptr;
+ char *tofree;
+
+ tofree = strdup(optarg);
+ if (tofree == NULL)
+ errx(1, "### strdup() failed");
+ ptr = tofree;
+
+ if (proc_name != NULL) {
+ free(proc_name);
+ proc_name = NULL;
+ }
+ proc_pid = -1;
+ uuid_clear(proc_uuid);
+
+ do {
+ char *str;
+
+ if ((str = strsep(&ptr, ":")) == NULL)
+ errx(1, "-p argument missing");
+
+ if (*str != 0)
+ proc_name = strdup(str);
+
+ if ((str = strsep(&ptr, ":")) == NULL)
+ break;
+ if (*str != 0) {
+ char *ep;
+
+ proc_pid = (uint32_t)strtoul(str, &ep, 0);
+ if (*ep || ep == optarg) {
+ fprintf(stderr, "malformed pid for option 'p'\n");
+ help(argv[0]);
+ exit (0);
+ }
+ }
+ if ((str = strsep(&ptr, ":")) == NULL)
+ break;
+ if (*str != 0) {
+ if (uuid_parse(str, proc_uuid) != 0) {
+ fprintf(stderr, "malformed uuid for option 'p'\n");
+ help(argv[0]);
+ return (0);
+ }
+ }
+ } while (0);
+ free(proc_name);
+ free(tofree);
+
+ proc_index += 1;
+
+ make_process_information_block(proc_name, proc_pid, proc_uuid);
+
+ break;
+ }
+ case 's': {
+ char *ptr;
+ char *tofree;
+ char *str;
+ size_t len;
+
+ uint32_t secrets_type = 0;
+ uint32_t secrets_length = 0;
+ uint8_t *secrets_data = NULL;
+
+ tofree = strdup(optarg);
+ if (tofree == NULL)
+ errx(1, "### strdup() failed");
+ ptr = tofree;
+
+ if ((str = strsep(&ptr, ":")) == NULL)
+ errx(1, "-p argument missing");
+
+ secrets_type = (uint32_t)strtoul(str, NULL, 0);
+
+ if ((str = strsep(&ptr, ":")) == NULL)
+ errx(1, "-p argument missing");
+
+ /* replace the final '\0' by '\n' */
+ len = strlen(str);
+ secrets_length = (uint32_t)(len + 1);
+ secrets_data = calloc(secrets_length, 1);
+ if (secrets_data == NULL) {
+ err(EX_OSERR, "calloc()");
+ }
+ memcpy(secrets_data, str, len);
+ secrets_data[len] = '\n';
+ free(secrets_data);
+ free(tofree);
+
+ make_decryption_secrets_block(secrets_type, secrets_length, secrets_data);
+ break;
+ }
+ case 't':
+ if (*optarg == 's')
+ type_of_packet = SIMPLE_PACKET;
+ else if (*optarg == 'e')
+ type_of_packet = ENHANCED_PACKET;
+ else if (*optarg == 'o')
+ type_of_packet = OBSOLETE_PACKET;
+ else if (*optarg == 'p')
+ type_of_packet = PKTAP_PACKET;
+ break;
+
+ case 'v':
+ verbose++;
+ break;
+
+ case 'w':
+ file_name = optarg;
+
+ if (dumper != NULL)
+ pcap_ng_dump_close(dumper);
+
+ if (pcap == NULL) {
+ pcap = pcap_open_dead(DLT_PCAPNG, 65536);
+ if (pcap == NULL)
+ err(EX_OSERR, "pcap_open_dead(DLT_PCAPNG, 65536) failed\n");
+ }
+ dumper = pcap_ng_dump_open(pcap, file_name);
+ if (pcap == NULL)
+ err(EX_OSERR, "pcap_ng_dump_open(%s) failed\n", file_name);
+
+
+ make_section_header_block();
+ break;
+
+ case 'x':
+ if (optind < argc) {
+ if (argv[optind][0] != '-') {
+ char *endptr;
+ unsigned long num = strtoul(argv[optind], &endptr, 0);
+ if (endptr != NULL && *endptr == '\0') {
+ optind++;
+ ext_len = num;
+ }
+ }
+ }
+ ext_buffer = malloc(ext_len);
+ if (ext_buffer == NULL)
+ errx(EX_OSERR, "malloc(%lu) failed", ext_len);
+ break;
+ default:
+ help(argv[0]);
+ return (0);
+ }
+ }
+
+ if (dumper != NULL)
+ pcap_ng_dump_close(dumper);
+
+ return (0);
+}
diff --git a/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.1 b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.1
new file mode 100644
index 0000000..38132a6
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.1
@@ -0,0 +1,79 @@
+.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
+.\"See Also:
+.\"man mdoc.samples for a complete listing of options
+.\"man mdoc for the short list of editing options
+.\"/usr/share/misc/mdoc.template
+.Dd 9/4/12 \" DATE
+.Dt ngofflinereadtest 1 \" Program name and manual section number
+.Os Darwin
+.Sh NAME \" Section Header - required - don't modify
+.Nm ngofflinereadtest,
+.\" The following lines are read in generating the apropos(man -k) database. Use only key
+.\" words here as the database is built based on the words here and in the .ND line.
+.Nm Other_name_for_same_program(),
+.Nm Yet another name for the same program.
+.\" Use .Nm macro to designate other names for the documented program.
+.Nd This line parsed for whatis database.
+.Sh SYNOPSIS \" Section Header - required - don't modify
+.Nm
+.Op Fl abcd \" [-abcd]
+.Op Fl a Ar path \" [-a path]
+.Op Ar file \" [file]
+.Op Ar \" [file ...]
+.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
+arg2 ... \" Arguments
+.Sh DESCRIPTION \" Section Header - required - don't modify
+Use the .Nm macro to refer to your program throughout the man page like such:
+.Nm
+Underlining is accomplished with the .Ar macro like this:
+.Ar underlined text .
+.Pp \" Inserts a space
+A list of items with descriptions:
+.Bl -tag -width -indent \" Begins a tagged list
+.It item a \" Each item preceded by .It macro
+Description of item a
+.It item b
+Description of item b
+.El \" Ends the list
+.Pp
+A list of flags and their descriptions:
+.Bl -tag -width -indent \" Differs from above in tag removed
+.It Fl a \"-a flag as a list item
+Description of -a flag
+.It Fl b
+Description of -b flag
+.El \" Ends the list
+.Pp
+.\" .Sh ENVIRONMENT \" May not be needed
+.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
+.\" .It Ev ENV_VAR_1
+.\" Description of ENV_VAR_1
+.\" .It Ev ENV_VAR_2
+.\" Description of ENV_VAR_2
+.\" .El
+.Sh FILES \" File used or created by the topic of the man page
+.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
+.It Pa /usr/share/file_name
+FILE_1 description
+.It Pa /Users/joeuser/Library/really_long_file_name
+FILE_2 description
+.El \" Ends the list
+.\" .Sh DIAGNOSTICS \" May not be needed
+.\" .Bl -diag
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .It Diagnostic Tag
+.\" Diagnostic informtion here.
+.\" .El
+.Sh SEE ALSO
+.\" List links in ascending order by section, alphabetically within a section.
+.\" Please do not reference files that do not exist without filing a bug report
+.Xr a 1 ,
+.Xr b 1 ,
+.Xr c 1 ,
+.Xr a 2 ,
+.Xr b 2 ,
+.Xr a 3 ,
+.Xr b 3
+.\" .Sh BUGS \" Document known, unremedied bugs
+.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file
diff --git a/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c
new file mode 100644
index 0000000..7dbb0e9
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/ngofflinereadtest/ngofflinereadtest.c
@@ -0,0 +1,710 @@
+/*
+ * Copyright (c) 2012-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+#include "pcap/pcap-ng.h"
+#include <stdio.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+#include <sysexits.h>
+
+struct section_info {
+ struct section_info *next;
+ struct pcapng_section_header_fields shb;
+ pcap_t *pcap;
+ u_int32_t if_count;
+ struct interface_info *if_list;
+};
+
+struct interface_info {
+ struct interface_info *next;
+ struct pcapng_interface_description_fields idb;
+ struct section_info *section_info;
+ u_int32_t interface_id;
+ char *if_name;
+ char *if_desc;
+};
+
+struct section_info *section_list = NULL;
+struct section_info *current_section = NULL;
+
+int mode_raw = 0;
+int mode_block = 0;
+int mode_pcap = 0;
+int mode_test = 0;
+
+#define PAD32(x) (((x) + 3) & ~3)
+
+void hex_and_ascii_print(const char *, const void *, size_t, const char *);
+
+struct section_info *
+new_section_info(pcap_t *pcap, struct pcapng_section_header_fields *shb)
+{
+ struct section_info *section_info = calloc(1, sizeof(struct section_info));
+
+ if (section_info == NULL)
+ return NULL;
+
+ section_info->pcap = pcap;
+ section_info->shb = *shb;
+
+ if (section_list == NULL) {
+ section_list = section_info;
+ } else {
+ section_info->next = section_list;
+ section_list = section_info;
+ }
+ current_section = section_info;
+
+ return section_info;
+}
+
+void
+interface_option_iterator(pcapng_block_t block, struct pcapng_option_info *option_info, void *context)
+{
+ struct interface_info *interface_info = (struct interface_info *)context;
+
+ switch (option_info->code) {
+ case 0:
+ break;
+
+ case 1:
+ break;
+
+ case 2:
+ interface_info->if_name = malloc(option_info->length + 1);
+ if (interface_info->if_name == NULL)
+ break;
+ snprintf(interface_info->if_name, option_info->length + 1, "%s", option_info->value);
+ break;
+ case 3:
+ interface_info->if_desc = malloc(option_info->length + 1);
+ if (interface_info->if_desc == NULL)
+ break;
+ snprintf(interface_info->if_desc, option_info->length + 1, "%s", option_info->value);
+ break;
+ case 4:
+ break;
+ case 5:
+ break;
+ case 6:
+ break;
+ case 7:
+ break;
+ case 8:
+ break;
+ case 9:
+ break;
+ case 10:
+ break;
+ case 11:
+ break;
+ case 12:
+ break;
+ case 13:
+ break;
+ case 14:
+ break;
+ default:
+ break;
+ }
+}
+
+struct interface_info *
+new_interface_info(struct section_info *section_info, pcapng_block_t block)
+{
+ if (section_info == NULL)
+ return NULL;
+
+ struct interface_info *interface_info = calloc(1, sizeof(struct interface_info));
+
+ if (interface_info == NULL)
+ return NULL;
+
+ interface_info->section_info = section_info;
+ interface_info->interface_id = section_info->if_count;
+ section_info->if_count++;
+ if (section_info->if_list == NULL) {
+ section_info->if_list = interface_info;
+ } else {
+ interface_info->next = section_info->if_list;
+ section_info->if_list = interface_info;
+ }
+ (void) pcnapng_block_iterate_options(block,
+ interface_option_iterator,
+ interface_info);
+
+ return interface_info;
+}
+
+struct interface_info *
+find_interface_info_by_id(u_int16_t interface_id)
+{
+ struct interface_info *interface_info;
+
+ if (current_section == NULL)
+ return (NULL);
+
+ if (interface_id + 1 > current_section->if_count)
+ return (NULL);
+
+ for (interface_info = current_section->if_list;
+ interface_info != NULL;
+ interface_info = interface_info->next) {
+ if (interface_info->interface_id == interface_id)
+ return (interface_info);
+ }
+ return (NULL);
+}
+
+void
+block_option_iterator(pcapng_block_t block, struct pcapng_option_info *option_info, void *context)
+{
+ printf(" block_type %u context %p option_code %u value_len %u value_ptr %p\n",
+ pcap_ng_block_get_type(block), context,
+ option_info->code, option_info->length,
+ option_info->value
+ );
+ switch (option_info->code) {
+ case 0:
+ printf(" opt_endofopt\n");
+ break;
+
+ case 1:
+ printf(" opt_comment: %-*s\n",
+ option_info->length, option_info->value);
+ break;
+
+ default:
+ /*
+ * Each block type has its own option code space
+ */
+ switch (pcap_ng_block_get_type(block)) {
+ case PCAPNG_BT_SHB:
+ switch (option_info->code) {
+ case 2:
+ printf(" shb_hardware: %-*s\n",
+ option_info->length, option_info->value);
+ break;
+ case 3:
+ printf(" shb_os: %-*s\n",
+ option_info->length, option_info->value);
+ break;
+ case 4:
+ printf(" shb_userappl: %-*s\n",
+ option_info->length, option_info->value);
+ break;
+ default:
+ printf(" <unkown shb option>\n");
+ break;
+ }
+ break;
+
+ case PCAPNG_BT_IDB:
+ switch (option_info->code) {
+ case 2:
+ printf(" if_name: %-*s\n",
+ option_info->length, option_info->value);
+ break;
+ case 3:
+ printf(" if_desc: %-*s\n",
+ option_info->length, option_info->value);
+ break;
+ case 4:
+ printf(" if_IPv4addr\n");
+ break;
+ case 5:
+ printf(" if_IPv6addr\n");
+ break;
+ case 6:
+ printf(" if_MACaddr\n");
+ break;
+ case 7:
+ printf(" if_EUIaddr\n");
+ break;
+ case 8:
+ printf(" if_speed\n");
+ break;
+ case 9:
+ printf(" if_tsresol\n");
+ break;
+ case 10:
+ printf(" if_tzone\n");
+ break;
+ case 11:
+ printf(" if_filter %-*s\n",
+ option_info->length, option_info->value);
+ break;
+ case 12:
+ printf(" if_os %-*s\n",
+ option_info->length, option_info->value);
+ break;
+ case 13:
+ printf(" if_fcslen\n");
+ break;
+ case 14:
+ printf(" if_tsoffset\n");
+ break;
+ default:
+ printf(" <unkown idb option>\n");
+ break;
+ }
+ break;
+
+ case PCAPNG_BT_EPB:
+ switch (option_info->code) {
+ case 2:
+ printf(" epb_flags\n");
+ break;
+ case 3:
+ printf(" epb_hash\n");
+ break;
+ case 4:
+ printf(" epb_dropcount\n");
+ break;
+ case PCAPNG_EPB_PIB_INDEX:
+ printf(" epb_pib\n");
+ break;
+ case PCAPNG_EPB_SVC:
+ printf(" epb_svc\n");
+ break;
+ case PCAPNG_EPB_PMD_FLAGS:
+ printf(" epb_pmd_flags\n");
+ break;
+ default:
+ printf(" <unkown epb option>\n");
+ break;
+ }
+ break;
+
+ case PCAPNG_BT_SPB:
+ printf(" <invalid spb option>\n");
+ break;
+
+ case PCAPNG_BT_PB:
+ switch (option_info->code) {
+ case 2:
+ printf(" pack_flags\n");
+ break;
+ case 3:
+ printf(" pack_hash\n");
+ break;
+ default:
+ printf(" <unkown pb option>\n");
+ break;
+ }
+ break;
+
+ case PCAPNG_BT_PIB: {
+ switch (option_info->code) {
+ case 2:
+ printf(" proc_name\n");
+ break;
+ case 3:
+ printf(" proc_path\n");
+ break;
+ case 4:
+ printf(" proc_uuid\n");
+ break;
+ default:
+ printf(" <unkown pib option>\n");
+ break;
+ }
+ break;
+ }
+ case PCAPNG_BT_ISB: {
+ break;
+ }
+ case PCAPNG_BT_NRB: {
+ break;
+ }
+ default:
+ break;
+ }
+ break;
+ }
+ if (option_info->value) {
+ hex_and_ascii_print(" ", option_info->value, option_info->length, "\n");
+ }
+}
+
+void
+read_callback(u_char *user, const struct pcap_pkthdr *hdr, const u_char *bytes)
+{
+ pcap_t *pcap = (pcap_t *)user;
+ struct pcapng_option_info option_info;
+ u_char *optptr = NULL;
+
+ /* Access the raw block */
+ if (mode_raw) {
+ struct pcapng_block_header *block_header = (struct pcapng_block_header*)bytes;
+
+ printf("raw hdr caplen %u len %u\n", hdr->caplen, hdr->len);
+
+ printf("#\n# user %p hdr.caplen %u hdr.len %u block_header.blocktype 0x%x block_header.totallength %u\n",
+ user, hdr->caplen, hdr->len,
+ block_header->block_type, block_header->total_length);
+
+ hex_and_ascii_print("", bytes, block_header->total_length, "\n");
+
+ switch (block_header->block_type) {
+ case PCAPNG_BT_SHB: {
+ struct pcapng_section_header_fields *shb = (struct pcapng_section_header_fields *)(block_header + 1);
+ printf("# Section Header Block\n");
+ printf(" byte_order_magic 0x%x major_version %u minor_version %u section_length %llu\n",
+ shb->byte_order_magic, shb->major_version, shb->minor_version, shb->section_length);
+
+ hex_and_ascii_print("", shb, sizeof(struct pcapng_section_header_fields), "\n");
+
+ optptr = (u_char *)(shb + 1);
+
+ break;
+ }
+ case PCAPNG_BT_IDB: {
+ struct pcapng_interface_description_fields *idb = (struct pcapng_interface_description_fields *)(block_header + 1);
+ printf("# Interface Description Block\n");
+ printf(" linktype %u reserved %u snaplen %u\n",
+ idb->idb_linktype, idb->idb_reserved, idb->idb_snaplen);
+
+ hex_and_ascii_print("", idb, sizeof(struct pcapng_interface_description_fields), "\n");
+ optptr = (u_char *)(idb + 1);
+
+ break;
+ }
+ case PCAPNG_BT_EPB: {
+ struct pcapng_enhanced_packet_fields *epb = (struct pcapng_enhanced_packet_fields *)(block_header + 1);
+ printf("# Enhanced Packet Block\n");
+ printf(" interface_id %u timestamp_high %u timestamp_low %u caplen %u len %u\n",
+ epb->interface_id, epb->timestamp_high, epb->timestamp_low, epb->caplen, epb->len);
+
+ hex_and_ascii_print("", epb, sizeof(struct pcapng_enhanced_packet_fields), "\n");
+ hex_and_ascii_print("", epb + 1, epb->caplen, "\n");
+
+ optptr = (u_char *)(epb + 1);
+ optptr += PAD32(epb->caplen);
+
+ break;
+ }
+ case PCAPNG_BT_SPB: {
+ struct pcapng_simple_packet_fields *spb = (struct pcapng_simple_packet_fields *)(block_header + 1);
+ printf("# Simple Packet Block\n");
+ printf(" len %u\n",
+ spb->len);
+
+ hex_and_ascii_print("", spb, sizeof(struct pcapng_simple_packet_fields), "\n");
+ hex_and_ascii_print("", spb + 1, spb->len, "\n");
+ break;
+ }
+ case PCAPNG_BT_PB: {
+ struct pcapng_packet_fields *pb = (struct pcapng_packet_fields *)(block_header + 1);
+ printf("# Packet Block\n");
+ printf(" interface_id %u drops_count %u timestamp_high %u timestamp_low %u caplen %u len %u\n",
+ pb->interface_id, pb->drops_count, pb->timestamp_high, pb->timestamp_low, pb->caplen, pb->len);
+
+ hex_and_ascii_print("", pb, sizeof(struct pcapng_packet_fields), "\n");
+
+ hex_and_ascii_print("", pb + 1, pb->caplen, "\n");
+
+ break;
+ }
+ case PCAPNG_BT_PIB: {
+ struct pcapng_process_information_fields *pib = (struct pcapng_process_information_fields *)(block_header + 1);
+ printf("# Process Information Block\n");
+ printf(" process_id %u\n",
+ pib->process_id);
+ hex_and_ascii_print("", pib, sizeof(struct pcapng_process_information_fields), "\n");
+ break;
+ }
+ case PCAPNG_BT_ISB: {
+ printf("# Interface Statistics Block\n");
+ break;
+ }
+ case PCAPNG_BT_NRB: {
+ printf("# Name Record Block\n");
+ break;
+ }
+ case PCAPNG_BT_OSEV: {
+ printf("# Name Record Block\n");
+ break;
+ }
+ case PCAPNG_BT_DSB: {
+ printf("# Decryption Secrets Block\n");
+ break;
+ }
+ default:
+ printf("# Unknown Block\n");
+ break;
+ }
+ if (optptr) {
+ size_t optlen = block_header->total_length - (optptr - bytes);
+
+ hex_and_ascii_print("", optptr, optlen, "\n");
+ }
+
+ }
+ /* Create block object */
+ if (mode_block) {
+ pcapng_block_t block = pcap_ng_block_alloc_with_raw_block(pcap, (u_char *)bytes);
+
+ if (block == NULL) {
+ printf(" pcap_ng_block_alloc_with_raw_block() failed: %s\n", pcap_geterr(pcap));
+ return;
+ }
+
+ switch (pcap_ng_block_get_type(block)) {
+ case PCAPNG_BT_SHB: {
+ struct pcapng_section_header_fields *shb = pcap_ng_get_section_header_fields(block);
+ printf("# Section Header Block\n");
+ printf(" byte_order_magic 0x%x major_version %u minor_version %u section_length %llu\n",
+ shb->byte_order_magic, shb->major_version, shb->minor_version, shb->section_length);
+
+ (void)new_section_info(pcap, shb);
+ break;
+ }
+ case PCAPNG_BT_IDB: {
+ struct pcapng_interface_description_fields *idb = pcap_ng_get_interface_description_fields(block);
+ printf("# Interface Description Block\n");
+ printf(" linktype %u reserved %u snaplen %u\n",
+ idb->idb_linktype, idb->idb_reserved, idb->idb_snaplen);
+ if (pcap_ng_block_get_option(block, PCAPNG_IF_NAME, &option_info) == 1)
+ if (option_info.value)
+ printf(" interface name: %s\n", option_info.value);
+
+ (void)new_interface_info(current_section, block);
+ break;
+ }
+ case PCAPNG_BT_EPB: {
+ struct pcapng_enhanced_packet_fields *epb = pcap_ng_get_enhanced_packet_fields(block);
+ printf("# Enhanced Packet Block\n");
+ printf(" interface_id %u timestamp_high %u timestamp_low %u caplen %u len %u\n",
+ epb->interface_id, epb->timestamp_high, epb->timestamp_low, epb->caplen, epb->len);
+ break;
+ }
+ case PCAPNG_BT_SPB: {
+ struct pcapng_simple_packet_fields *spb = pcap_ng_get_simple_packet_fields(block);
+ printf("# Simple Packet Block\n");
+ printf(" len %u\n",
+ spb->len);
+ break;
+ }
+ case PCAPNG_BT_PB: {
+ struct pcapng_packet_fields *pb = pcap_ng_get_packet_fields(block);
+ printf("# Packet Block\n");
+ printf(" interface_id %u drops_count %u timestamp_high %u timestamp_low %u caplen %u len %u\n",
+ pb->interface_id, pb->drops_count, pb->timestamp_high, pb->timestamp_low, pb->caplen, pb->len);
+ break;
+ }
+ case PCAPNG_BT_PIB: {
+ struct pcapng_process_information_fields *pib = pcap_ng_get_process_information_fields(block);
+ printf("# Process Information Block\n");
+ printf(" process_id %u\n",
+ pib->process_id);
+
+ if (pcap_ng_block_get_option(block, PCAPNG_PIB_NAME, &option_info) == 1) {
+ if (option_info.value)
+ printf(" process name: %s\n", option_info.value);
+ }
+ if (pcap_ng_block_get_option(block, PCAPNG_PIB_UUID, &option_info) == 1) {
+ if (option_info.value) {
+ uuid_string_t uu_str;
+
+ uuid_unparse_lower(option_info.value, uu_str);
+
+ printf(" process uuid: %s\n", uu_str);
+ }
+ }
+break;
+ }
+ case PCAPNG_BT_ISB: {
+ printf("# Interface Statistics Block\n");
+ break;
+ }
+ case PCAPNG_BT_NRB: {
+ printf("# Name Record Block\n");
+ break;
+ }
+ case PCAPNG_BT_OSEV: {
+ struct pcapng_os_event_fields *osev_fields;
+
+ printf("# OS Event Block\n");
+
+ osev_fields = pcap_ng_get_os_event_fields(block);
+
+ printf(" type %u timestamp_high %u timestamp_low %u len %u\n",
+ osev_fields->type,
+ osev_fields->timestamp_high,
+ osev_fields->timestamp_low,
+ osev_fields->len);
+ break;
+ }
+ case PCAPNG_BT_DSB: {
+ struct pcapng_decryption_secrets_fields *dsb_fields;
+
+ printf("# Decryption Secrets Block\n");
+
+ dsb_fields = pcap_ng_get_decryption_secrets_fields(block);
+
+ printf(" secrets_type 0x%x secrets_length %u\n",
+ dsb_fields->secrets_type,
+ dsb_fields->secrets_length);
+
+ break;
+ }
+ default:
+ printf("# Unknown Block\n");
+ break;
+ }
+ if (pcap_ng_block_does_support_data(block)) {
+ hex_and_ascii_print("", pcap_ng_block_packet_get_data_ptr(block), pcap_ng_block_packet_get_data_len(block), "\n");
+ }
+
+ pcnapng_block_iterate_options(block, block_option_iterator, NULL);
+ }
+}
+
+#define SWAPLONG(y) \
+((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+#define SWAPSHORT(y) \
+( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )
+#define SWAPLONGLONG(y) \
+(SWAPLONG((unsigned long)(y)) << 32 | SWAPLONG((unsigned long)((y) >> 32)))
+
+void
+test_pcap_ng_fopen_offline(const char *filename, char *errbuf)
+{
+ FILE *fp;
+ off_t offset;
+ pcap_t *pcap;
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ warn("fopen(%s) failed", filename);
+ return;
+ }
+ offset = ftello(fp);
+
+ pcap = pcap_ng_fopen_offline(fp, errbuf);
+ if (pcap == NULL) {
+ warnx("pcap_ng_fopen_offline(%s) failed: %s\n",
+ filename, errbuf);
+ if (ftello(fp) != offset)
+ errx(EX_OSERR, "pcap_ng_fopen_offline(%s) ftello(fp) (%llu) != offset (%llu)",
+ filename, ftello(fp), offset);
+ } else {
+ pcap_close(pcap);
+ }
+
+ fp = fopen(filename, "r");
+ if (fp == NULL) {
+ warn("fopen(%s) failed", filename);
+ return;
+ }
+ offset = ftello(fp);
+
+ pcap = pcap_fopen_offline(fp, errbuf);
+ if (pcap == NULL) {
+ warnx("pcap_fopen_offline(%s) failed: %s\n",
+ filename, errbuf);
+ if (ftello(fp) != offset)
+ errx(EX_OSERR, "pcap_fopen_offline(%s) ftello(fp) (%llu) != offset (%llu)",
+ filename, ftello(fp), offset);
+ } else {
+ pcap_close(pcap);
+ }
+
+ fclose(fp);
+
+ fprintf(stderr, "TEST PASSED\n");
+}
+
+int
+main(int argc, const char * argv[])
+{
+ int i;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ for (i = 1; i < argc; i++) {
+ pcap_t *pcap;
+
+ if (strcmp(argv[i], "-h") == 0) {
+ char *path = strdup((argv[0]));
+ printf("# usage: %s [-raw] [-block] [-pcap] [-test] file\n", getprogname());
+ if (path != NULL)
+ free(path);
+ exit(0);
+ } else if (strcmp(argv[i], "-raw") == 0) {
+ mode_raw = 1;
+ continue;
+ } else if (strcmp(argv[i], "-block") == 0) {
+ mode_block = 1;
+ continue;
+ } else if (strcmp(argv[i], "-pcap") == 0) {
+ mode_pcap = 1;
+ continue;
+ } else if (strcmp(argv[i], "-test") == 0) {
+ mode_test = 1;
+ continue;
+ }
+
+ printf("#\n# opening %s\n#\n", argv[i]);
+
+ if (mode_test != 0) {
+ test_pcap_ng_fopen_offline(argv[i], errbuf);
+ continue;
+ }
+
+ if (mode_block == 0 && mode_raw == 0) {
+ mode_block = 1;
+ }
+ if (mode_pcap == 0) {
+ pcap = pcap_ng_open_offline(argv[i], errbuf);
+ if (pcap == NULL) {
+ warnx("pcap_ng_open_offline(%s) failed: %s\n",
+ argv[i], errbuf);
+ continue;
+ }
+ } else {
+ pcap = pcap_open_offline(argv[i], errbuf);
+ if (pcap == NULL) {
+ warnx("pcap_open_offline(%s) failed: %s\n",
+ argv[i], errbuf);
+ continue;
+ }
+ }
+ int result = pcap_dispatch(pcap, -1, read_callback, (u_char *)pcap);
+ if (result < 0) {
+ warnx("pcap_dispatch failed: %s\n",
+ pcap_statustostr(result));
+ } else {
+ printf("# read %d packets\n", result);
+ }
+ pcap_close(pcap);
+ }
+ return 0;
+}
diff --git a/lib/libpcap/libpcap/tests/nonblocktest.c b/lib/libpcap/libpcap/tests/nonblocktest.c
new file mode 100644
index 0000000..70a6bfd
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/nonblocktest.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static const char copyright[] =
+ "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\
+The Regents of the University of California. All rights reserved.\n";
+#endif
+
+#include <pcap.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/select.h>
+#include <poll.h>
+
+char *program_name;
+
+/* Forwards */
+static void countme(u_char *, const struct pcap_pkthdr *, const u_char *);
+static void usage(void) __attribute__((noreturn));
+static void error(const char *, ...);
+static void warning(const char *, ...);
+static char *copy_argv(char **);
+
+static pcap_t *pd;
+
+extern int optind;
+extern int opterr;
+extern char *optarg;
+
+int
+main(int argc, char **argv)
+{
+ register int op;
+ bpf_u_int32 localnet, netmask;
+ register char *cp, *cmdbuf, *device;
+ struct bpf_program fcode;
+ char ebuf[PCAP_ERRBUF_SIZE];
+ int status;
+ int packet_count;
+
+ device = NULL;
+ if ((cp = strrchr(argv[0], '/')) != NULL)
+ program_name = cp + 1;
+ else
+ program_name = argv[0];
+
+ opterr = 0;
+ while ((op = getopt(argc, argv, "i:")) != -1) {
+ switch (op) {
+
+ case 'i':
+ device = optarg;
+ break;
+
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+ }
+
+ if (device == NULL) {
+ device = pcap_lookupdev(ebuf);
+ if (device == NULL)
+ error("%s", ebuf);
+ }
+ *ebuf = '\0';
+ pd = pcap_open_live(device, 65535, 0, 1000, ebuf);
+ if (pd == NULL)
+ error("%s", ebuf);
+ else if (*ebuf)
+ warning("%s", ebuf);
+ if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) {
+ localnet = 0;
+ netmask = 0;
+ warning("%s", ebuf);
+ }
+ cmdbuf = copy_argv(&argv[optind]);
+
+ if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0)
+ error("%s", pcap_geterr(pd));
+
+ if (pcap_setfilter(pd, &fcode) < 0)
+ error("%s", pcap_geterr(pd));
+ if (pcap_setnonblock(pd, 1, ebuf) == -1)
+ error("pcap_setnonblock failed: %s", ebuf);
+ printf("Listening on %s\n", device);
+ for (;;) {
+ packet_count = 0;
+ status = pcap_dispatch(pd, -1, countme,
+ (u_char *)&packet_count);
+ if (status < 0)
+ break;
+ if (status != 0) {
+ printf("%d packets seen, %d packets counted after pcap_dispatch returns\n",
+ status, packet_count);
+ }
+ }
+ if (status == -2) {
+ /*
+ * We got interrupted, so perhaps we didn't
+ * manage to finish a line we were printing.
+ * Print an extra newline, just in case.
+ */
+ putchar('\n');
+ }
+ (void)fflush(stdout);
+ if (status == -1) {
+ /*
+ * Error. Report it.
+ */
+ (void)fprintf(stderr, "%s: pcap_loop: %s\n",
+ program_name, pcap_geterr(pd));
+ }
+ pcap_close(pd);
+ exit(status == -1 ? 1 : 0);
+}
+
+static void
+countme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
+{
+ int *counterp = (int *)user;
+
+ (*counterp)++;
+}
+
+static void
+usage(void)
+{
+ (void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n",
+ program_name);
+ exit(1);
+}
+
+/* VARARGS */
+static void
+error(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+ exit(1);
+ /* NOTREACHED */
+}
+
+/* VARARGS */
+static void
+warning(const char *fmt, ...)
+{
+ va_list ap;
+
+ (void)fprintf(stderr, "%s: WARNING: ", program_name);
+ va_start(ap, fmt);
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ if (*fmt) {
+ fmt += strlen(fmt);
+ if (fmt[-1] != '\n')
+ (void)fputc('\n', stderr);
+ }
+}
+
+/*
+ * Copy arg vector into a new buffer, concatenating arguments with spaces.
+ */
+static char *
+copy_argv(register char **argv)
+{
+ register char **p;
+ register u_int len = 0;
+ char *buf;
+ char *src, *dst;
+
+ p = argv;
+ if (*p == 0)
+ return 0;
+
+ while (*p)
+ len += strlen(*p++) + 1;
+
+ buf = (char *)malloc(len);
+ if (buf == NULL)
+ error("copy_argv: malloc");
+
+ p = argv;
+ dst = buf;
+ while ((src = *p++) != NULL) {
+ while ((*dst++ = *src++) != '\0')
+ ;
+ dst[-1] = ' ';
+ }
+ dst[-1] = '\0';
+
+ return buf;
+}
diff --git a/lib/libpcap/libpcap/tests/offlinereadtest.c b/lib/libpcap/libpcap/tests/offlinereadtest.c
new file mode 100644
index 0000000..f5f23fe
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/offlinereadtest.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2017-2018 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ *
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
+
+#include <pcap.h>
+#include <stdio.h>
+#include <err.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libgen.h>
+
+
+#define PAD32(x) (((x) + 3) & ~3)
+#define SWAPLONG(y) \
+((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff))
+#define SWAPSHORT(y) \
+( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) )
+#define SWAPLONGLONG(y) \
+(SWAPLONG((unsigned long)(y)) << 32 | SWAPLONG((unsigned long)((y) >> 32)))
+
+void hex_and_ascii_print(const char *, const void *, size_t, const char *);
+
+void
+read_callback(u_char *user, const struct pcap_pkthdr *hdr, const u_char *bytes)
+{
+ fprintf(stderr, "pcap_pkthdr ts %ld.%06d caplen %u len %u\n",
+ hdr->ts.tv_sec,
+ hdr->ts.tv_usec,
+ hdr->caplen,
+ hdr->len);
+
+ hex_and_ascii_print("", bytes, hdr->caplen, "\n");
+}
+
+int
+main(int argc, const char * argv[])
+{
+ int i;
+ char errbuf[PCAP_ERRBUF_SIZE];
+
+ for (i = 1; i < argc; i++) {
+ pcap_t *pcap;
+
+ if (strcmp(argv[i], "-h") == 0) {
+ char *path = strdup((argv[0]));
+ printf("# usage: %s file...\n", getprogname());
+ if (path != NULL)
+ free(path);
+ exit(0);
+ }
+
+ printf("#\n# opening %s\n#\n", argv[i]);
+
+ pcap = pcap_open_offline(argv[i], errbuf);
+ if (pcap == NULL) {
+ warnx("pcap_open_offline(%s) failed: %s\n",
+ argv[i], errbuf);
+ continue;
+ }
+ int result = pcap_loop(pcap, -1, read_callback, (u_char *)pcap);
+ if (result < 0) {
+ warnx("pcap_dispatch failed: %s\n",
+ pcap_statustostr(result));
+ } else {
+ printf("# read %d packets\n", result);
+ }
+ pcap_close(pcap);
+ }
+ return 0;
+}
diff --git a/lib/libpcap/libpcap/tests/shb-option-too-long.pcapng b/lib/libpcap/libpcap/tests/shb-option-too-long.pcapng
new file mode 100644
index 0000000..f773974
--- /dev/null
+++ b/lib/libpcap/libpcap/tests/shb-option-too-long.pcapng
Binary files differ
diff --git a/lib/libpcap/libpcap/varattrs.h b/lib/libpcap/libpcap/varattrs.h
new file mode 100644
index 0000000..05bfe8c
--- /dev/null
+++ b/lib/libpcap/libpcap/varattrs.h
@@ -0,0 +1,59 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
+/*
+ * Copyright (c) 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must 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.
+ */
+
+#ifndef varattrs_h
+#define varattrs_h
+
+#include <pcap/compiler-tests.h>
+
+/*
+ * Attributes to apply to variables, using various compiler-specific
+ * extensions.
+ */
+
+#if __has_attribute(unused) \
+ || PCAP_IS_AT_LEAST_GNUC_VERSION(2,0)
+ /*
+ * Compiler with support for __attribute__((unused)), or GCC 2.0 and
+ * later, so it supports __attribute__((unused)).
+ */
+ #define _U_ __attribute__((unused))
+#else
+ /*
+ * We don't know of any way to mark a variable as unused.
+ */
+ #define _U_
+#endif
+
+#endif
diff --git a/lib/libpcap/patches/pcap-bpf.c.diff b/lib/libpcap/patches/pcap-bpf.c.diff
new file mode 100644
index 0000000..e6dadd2
--- /dev/null
+++ b/lib/libpcap/patches/pcap-bpf.c.diff
@@ -0,0 +1,11 @@
+--- pcap-bpf.c.orig 2008-10-10 19:42:44.000000000 -0700
++++ pcap-bpf.c 2009-09-01 19:54:11.000000000 -0700
+@@ -1860,7 +1860,7 @@
+ * (Treating it as such doesn't fix the timeout
+ * problem described below.)
+ */
+- struct timeval to;
++ struct BPF_TIMEVAL to;
+ to.tv_sec = p->md.timeout / 1000;
+ to.tv_usec = (p->md.timeout * 1000) % 1000000;
+ if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) {