summaryrefslogtreecommitdiffstats
path: root/contrib/ipfilter/iplang
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>1997-11-16 04:52:19 +0000
committerpeter <peter@FreeBSD.org>1997-11-16 04:52:19 +0000
commit594e73c3109178aa1c5317785aaa284a0c135ff4 (patch)
tree1abde20e1d717a2bf3509de2189cbe7fa3c9f91e /contrib/ipfilter/iplang
parentc4dc16ff2222e864e5ab4d236e0de3a2cb5b54da (diff)
downloadFreeBSD-src-594e73c3109178aa1c5317785aaa284a0c135ff4.zip
FreeBSD-src-594e73c3109178aa1c5317785aaa284a0c135ff4.tar.gz
Import ipfilter 3.2.1 (update from 3.1.8)
Diffstat (limited to 'contrib/ipfilter/iplang')
-rw-r--r--contrib/ipfilter/iplang/BNF69
-rw-r--r--contrib/ipfilter/iplang/Makefile30
-rw-r--r--contrib/ipfilter/iplang/iplang.h51
-rw-r--r--contrib/ipfilter/iplang/iplang.tst11
-rw-r--r--contrib/ipfilter/iplang/iplang_l.l313
-rw-r--r--contrib/ipfilter/iplang/iplang_y.y1858
6 files changed, 2332 insertions, 0 deletions
diff --git a/contrib/ipfilter/iplang/BNF b/contrib/ipfilter/iplang/BNF
new file mode 100644
index 0000000..b5fb8d0
--- /dev/null
+++ b/contrib/ipfilter/iplang/BNF
@@ -0,0 +1,69 @@
+line ::= iface | arp | send | defrouter | ipv4line .
+
+iface ::= ifhdr "{" ifaceopts "}" ";" .
+ifhdr ::= "interface" | "iface" .
+ifaceopts ::= "ifname" name | "mtu" mtu | "v4addr" ipaddr |
+ "eaddr" eaddr .
+
+send ::= "send" ";" | "send" "{" sendbodyopts "}" ";" .
+sendbodyopts ::= sendbody [ sendbodyopts ] .
+sendbody ::= "ifname" name | "via" ipaddr .
+
+defrouter ::= "router" ipaddr .
+
+arp ::= "arp" "{" arpbodyopts "}" ";" .
+arpbodyopts ::= arpbody [ arpbodyopts ] .
+arpbody ::= "v4addr" ipaddr | "eaddr" eaddr .
+
+bodyline ::= ipv4line | tcpline | udpline | icmpline | dataline .
+
+ipv4line ::= "ipv4" "{" ipv4bodyopts "}" ";" .
+ipv4bodyopts ::= ipv4body [ ipv4bodyopts ] | bodyline .
+ipv4body ::= "proto" protocol | "src" ipaddr | "dst" ipaddr |
+ "off" number | "v" number | "hl" number| "id" number |
+ "ttl" number | "tos" number | "sum" number | "len" number |
+ "opt" "{" ipv4optlist "}" ";" .
+ipv4optlist ::= ipv4option [ ipv4optlist ] .
+ipv4optlist = "nop" | "rr" | "zsu" | "mtup" | "mtur" | "encode" | "ts" |
+ "tr" | "sec" | "lsrr" | "e-sec" | "cipso" | "satid" |
+ "ssrr" | "addext" | "visa" | "imitd" | "eip" | "finn" |
+ "secclass" ipv4secclass.
+ipv4secclass := "unclass" | "confid" | "reserv-1" | "reserv-2" |
+ "reserv-3" | "reserv-4" | "secret" | "topsecret" .
+
+tcpline ::= "tcp" "{" tcpbodyopts "}" ";" .
+tcpbodyopts ::= tcpbody [ tcpbodyopts ] | bodyline .
+tcpbody ::= "sport" port | "dport" port | "seq" number | "ack" number |
+ "off" number | "urp" number | "win" number | "sum" number |
+ "flags" tcpflags | data .
+
+udpline ::= "udp" "{" udpbodyopts "}" ";" .
+udpbodyopts ::= udpbody [ udpbodyopts ] | bodyline .
+udpbody ::= "sport" port | "dport" port | "len" number | "sum" number |
+ data .
+
+icmpline ::= "icmp" "{" icmpbodyopts "}" ";" .
+icmpbodyopts ::= icmpbody [ icmpbodyopts ] | bodyline .
+icmpbody ::= "type" icmptype [ "code" icmpcode ] .
+icmptype ::= "echorep" | "echorep" "{" echoopts "}" ";" | "unreach" |
+ "unreach" "{" unreachtype "}" ";" | "squench" | "redir" |
+ "redir" "{" redirtype "}" ";" | "echo" "{" echoopts "}" ";" |
+ "echo" | "routerad" | "routersol" | "timex" |
+ "timex" "{" timextype "}" ";" | "paramprob" |
+ "paramprob" "{" parapptype "}" ";" | "timest" | "timestrep" |
+ "inforeq" | "inforep" | "maskreq" | "maskrep" .
+
+echoopts ::= echoopts [ icmpechoopts ] .
+unreachtype ::= "net-unr" | "host-unr" | "proto-unr" | "port-unr" |
+ "needfrag" | "srcfail" | "net-unk" | "host-unk" | "isolate" |
+ "net-prohib" | "host-prohib" | "net-tos" | "host-tos" |
+ "filter-prohib" | "host-preced" | "cutoff-preced" .
+redirtype ::= "net-redir" | "host-redir" | "tos-net-redir" |
+ "tos-host-redir" .
+timextype ::= "intrans" | "reass" .
+paramptype ::= "optabsent" .
+
+data ::= "data" "{" databodyopts "}" ";" .
+databodyopts ::= "len" number | "value" string | "file" filename .
+
+icmpechoopts ::= "icmpseq" number | "icmpid" number .
diff --git a/contrib/ipfilter/iplang/Makefile b/contrib/ipfilter/iplang/Makefile
new file mode 100644
index 0000000..4537e8d
--- /dev/null
+++ b/contrib/ipfilter/iplang/Makefile
@@ -0,0 +1,30 @@
+#
+# Redistribution and use in source and binary forms are permitted
+# provided that this notice is preserved and due credit is given
+# to the original author and the contributors.
+#
+#CC=gcc -Wuninitialized -Wstrict-prototypes -Werror -O
+CFLAGS=-I..
+
+all: $(DESTDIR)/y.tab.o $(DESTDIR)/lex.yy.o y.tab.o lex.yy.o
+
+$(DESTDIR)/y.tab.o: y.tab.c
+ $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c y.tab.c -o $@
+
+$(DESTDIR)/lex.yy.o: lex.yy.c
+ $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c lex.yy.c -o $@
+
+y.tab.o: y.tab.c
+ $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c y.tab.c -o $@
+
+lex.yy.o: lex.yy.c
+ $(CC) $(DEBUG) -I. -I.. -I../ipsend $(CFLAGS) $(LINUX) -c lex.yy.c -o $@
+
+lex.yy.c: iplang_l.l y.tab.h
+ lex iplang_l.l
+
+y.tab.c y.tab.h: iplang_y.y
+ yacc -d iplang_y.y
+
+clean:
+ /bin/rm -f *.o lex.yy.c y.tab.c y.tab.h
diff --git a/contrib/ipfilter/iplang/iplang.h b/contrib/ipfilter/iplang/iplang.h
new file mode 100644
index 0000000..a7a13f9
--- /dev/null
+++ b/contrib/ipfilter/iplang/iplang.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1997 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ */
+typedef struct iface {
+ int if_MTU;
+ char *if_name;
+ struct in_addr if_addr;
+ struct ether_addr if_eaddr;
+ struct iface *if_next;
+ int if_fd;
+} iface_t;
+
+
+typedef struct send {
+ struct iface *snd_if;
+ struct in_addr snd_gw;
+} send_t;
+
+
+typedef struct arp {
+ struct in_addr arp_addr;
+ struct ether_addr arp_eaddr;
+ struct arp *arp_next;
+} arp_t;
+
+
+typedef struct aniphdr {
+ union {
+ ip_t *ahu_ip;
+ char *ahu_data;
+ tcphdr_t *ahu_tcp;
+ udphdr_t *ahu_udp;
+ icmphdr_t *ahu_icmp;
+ } ah_un;
+ int ah_optlen;
+ int ah_lastopt;
+ int ah_p;
+ size_t ah_len;
+ struct aniphdr *ah_next;
+ struct aniphdr *ah_prev;
+} aniphdr_t;
+
+#define ah_ip ah_un.ahu_ip
+#define ah_data ah_un.ahu_data
+#define ah_tcp ah_un.ahu_tcp
+#define ah_udp ah_un.ahu_udp
+#define ah_icmp ah_un.ahu_icmp
diff --git a/contrib/ipfilter/iplang/iplang.tst b/contrib/ipfilter/iplang/iplang.tst
new file mode 100644
index 0000000..9a8c35e
--- /dev/null
+++ b/contrib/ipfilter/iplang/iplang.tst
@@ -0,0 +1,11 @@
+#
+interface { ifname le0; mtu 1500; }
+
+ipv4 {
+ src 1.1.1.1; dst 2.2.2.2;
+ tcp {
+ seq 12345; ack 0; sport 9999; dport 23; flags S;
+ data { value "abcdef"; } ;
+ }
+}
+send { via 10.1.1.1; }
diff --git a/contrib/ipfilter/iplang/iplang_l.l b/contrib/ipfilter/iplang/iplang_l.l
new file mode 100644
index 0000000..c136e91
--- /dev/null
+++ b/contrib/ipfilter/iplang/iplang_l.l
@@ -0,0 +1,313 @@
+%e 1500
+%p 4000
+%a 4000
+%o 6000
+%{
+/*
+ * Copyright (C) 1997 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * $Id: iplang_l.l,v 2.0.2.15.2.1 1997/11/05 11:04:04 darrenr Exp $
+ */
+#include <stdio.h>
+#include <string.h>
+#include <sys/param.h>
+#if defined(__SVR4) || defined(__sysv__)
+#include <sys/stream.h>
+#endif
+#include <sys/types.h>
+#include <netinet/in_systm.h>
+#include <netinet/in.h>
+#include "y.tab.h"
+#include "ip_compat.h"
+#include "ipf.h"
+
+#ifndef __P
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+extern int opts;
+
+int lineNum = 0, proto = 0, oldproto = 0, next = -1, laststate = 0;
+int *prstack = NULL, numpr = 0, state = 0, token = 0;
+
+void yyerror __P((char *));
+void push_proto __P((void));
+void pop_proto __P((void));
+int next_state __P((int, int));
+int next_item __P((int));
+int save_token __P((void));
+void swallow __P((void));
+int yylex __P((void));
+%}
+
+%%
+[ \t\r] ;
+\n { lineNum++; swallow(); }
+interface |
+iface { return next_state(IL_INTERFACE, -1); }
+name |
+ifname { return next_state(IL_IFNAME, IL_TOKEN); }
+router { return next_state(IL_DEFROUTER, IL_TOKEN); }
+mtu { return next_state(IL_MTU, IL_NUMBER); }
+eaddr { return next_state(IL_EADDR, IL_TOKEN); }
+v4addr { return next_state(IL_V4ADDR, IL_TOKEN); }
+ipv4 { return next_state(IL_IPV4, -1); }
+v { return next_state(IL_V4V, IL_TOKEN); }
+proto { return next_state(IL_V4PROTO, IL_TOKEN); }
+hl { return next_state(IL_V4HL, IL_TOKEN); }
+id { return next_state(IL_V4ID, IL_TOKEN); }
+ttl { return next_state(IL_V4TTL, IL_TOKEN); }
+tos { return next_state(IL_V4TOS, IL_TOKEN); }
+src { return next_state(IL_V4SRC, IL_TOKEN); }
+dst { return next_state(IL_V4DST, IL_TOKEN); }
+opt { return next_state(IL_OPT, -1); }
+len { return next_state(IL_LEN, IL_TOKEN); }
+off { return next_state(IL_OFF, IL_TOKEN); }
+sum { return next_state(IL_SUM, IL_TOKEN); }
+tcp { return next_state(IL_TCP, -1); }
+sport { return next_state(IL_SPORT, IL_TOKEN); }
+dport { return next_state(IL_DPORT, IL_TOKEN); }
+seq { return next_state(IL_TCPSEQ, IL_TOKEN); }
+ack { return next_state(IL_TCPACK, IL_TOKEN); }
+flags { return next_state(IL_TCPFL, IL_TOKEN); }
+urp { return next_state(IL_TCPURP, IL_TOKEN); }
+win { return next_state(IL_TCPWIN, IL_TOKEN); }
+udp { return next_state(IL_UDP, -1); }
+send { return next_state(IL_SEND, -1); }
+via { return next_state(IL_VIA, IL_TOKEN); }
+arp { return next_state(IL_ARP, -1); }
+data { return next_state(IL_DATA, -1); }
+value { return next_state(IL_DVALUE, IL_TOKEN); }
+file { return next_state(IL_DFILE, IL_TOKEN); }
+nop { return next_state(IL_IPO_NOP, -1); }
+eol { return next_state(IL_IPO_EOL, -1); }
+rr { return next_state(IL_IPO_RR, -1); }
+zsu { return next_state(IL_IPO_ZSU, -1); }
+mtup { return next_state(IL_IPO_MTUP, -1); }
+mtur { return next_state(IL_IPO_MTUR, -1); }
+encode { return next_state(IL_IPO_ENCODE, -1); }
+ts { return next_state(IL_IPO_TS, -1); }
+tr { return next_state(IL_IPO_TR, -1); }
+sec { return next_state(IL_IPO_SEC, -1); }
+secclass { return next_state(IL_IPO_SECCLASS, IL_TOKEN); }
+lsrr { return next_state(IL_IPO_LSRR, -1); }
+esec { return next_state(IL_IPO_ESEC, -1); }
+cipso { return next_state(IL_IPO_CIPSO, -1); }
+satid { return next_state(IL_IPO_SATID, -1); }
+ssrr { return next_state(IL_IPO_SSRR, -1); }
+addext { return next_state(IL_IPO_ADDEXT, -1); }
+visa { return next_state(IL_IPO_VISA, -1); }
+imitd { return next_state(IL_IPO_IMITD, -1); }
+eip { return next_state(IL_IPO_EIP, -1); }
+finn { return next_state(IL_IPO_FINN, -1); }
+mss { return next_state(IL_TCPO_MSS, IL_TOKEN); }
+wscale { return next_state(IL_TCPO_MSS, IL_TOKEN); }
+reserv-4 { return next_state(IL_IPS_RESERV4, -1); }
+topsecret { return next_state(IL_IPS_TOPSECRET, -1); }
+secret { return next_state(IL_IPS_SECRET, -1); }
+reserv-3 { return next_state(IL_IPS_RESERV3, -1); }
+confid { return next_state(IL_IPS_CONFID, -1); }
+unclass { return next_state(IL_IPS_UNCLASS, -1); }
+reserv-2 { return next_state(IL_IPS_RESERV2, -1); }
+reserv-1 { return next_state(IL_IPS_RESERV1, -1); }
+icmp { return next_state(IL_ICMP, -1); }
+type { return next_state(IL_ICMPTYPE, -1); }
+code { return next_state(IL_ICMPCODE, -1); }
+echorep { return next_state(IL_ICMP_ECHOREPLY, -1); }
+unreach { return next_state(IL_ICMP_UNREACH, -1); }
+squench { return next_state(IL_ICMP_SOURCEQUENCH, -1); }
+redir { return next_state(IL_ICMP_REDIRECT, -1); }
+echo { return next_state(IL_ICMP_ECHO, -1); }
+routerad { return next_state(IL_ICMP_ROUTERADVERT, -1); }
+routersol { return next_state(IL_ICMP_ROUTERSOLICIT, -1); }
+timex { return next_state(IL_ICMP_TIMXCEED, -1); }
+paramprob { return next_state(IL_ICMP_PARAMPROB, -1); }
+timest { return next_state(IL_ICMP_TSTAMP, -1); }
+timestrep { return next_state(IL_ICMP_TSTAMPREPLY, -1); }
+inforeq { return next_state(IL_ICMP_IREQ, -1); }
+inforep { return next_state(IL_ICMP_IREQREPLY, -1); }
+maskreq { return next_state(IL_ICMP_MASKREQ, -1); }
+maskrep { return next_state(IL_ICMP_MASKREPLY, -1); }
+net-unr { return next_state(IL_ICMP_UNREACH_NET, -1); }
+host-unr { return next_state(IL_ICMP_UNREACH_HOST, -1); }
+proto-unr { return next_state(IL_ICMP_UNREACH_PROTOCOL, -1); }
+port-unr { return next_state(IL_ICMP_UNREACH_PORT, -1); }
+needfrag { return next_state(IL_ICMP_UNREACH_NEEDFRAG, -1); }
+srcfail { return next_state(IL_ICMP_UNREACH_SRCFAIL, -1); }
+net-unk { return next_state(IL_ICMP_UNREACH_NET_UNKNOWN, -1); }
+host-unk { return next_state(IL_ICMP_UNREACH_HOST_UNKNOWN, -1); }
+isolate { return next_state(IL_ICMP_UNREACH_ISOLATED, -1); }
+net-prohib { return next_state(IL_ICMP_UNREACH_NET_PROHIB, -1); }
+host-prohib { return next_state(IL_ICMP_UNREACH_HOST_PROHIB, -1); }
+net-tos { return next_state(IL_ICMP_UNREACH_TOSNET, -1); }
+host-tos { return next_state(IL_ICMP_UNREACH_TOSHOST, -1); }
+filter-prohib { return next_state(IL_ICMP_UNREACH_FILTER_PROHIB, -1); }
+host-preced { return next_state(IL_ICMP_UNREACH_HOST_PRECEDENCE, -1); }
+cutoff-preced { return next_state(IL_ICMP_UNREACH_PRECEDENCE_CUTOFF, -1); }
+net-redir { return next_state(IL_ICMP_REDIRECT_NET, -1); }
+host-redir { return next_state(IL_ICMP_REDIRECT_HOST, -1); }
+tos-net-redir { return next_state(IL_ICMP_REDIRECT_TOSNET, -1); }
+tos-host-redir { return next_state(IL_ICMP_REDIRECT_TOSHOST, -1); }
+intrans { return next_state(IL_ICMP_TIMXCEED_INTRANS, -1); }
+reass { return next_state(IL_ICMP_TIMXCEED_REASS, -1); }
+optabsent { return next_state(IL_ICMP_PARAMPROB_OPTABSENT, -1); }
+otime { return next_state(IL_ICMP_OTIME, -1); }
+rtime { return next_state(IL_ICMP_RTIME, -1); }
+ttime { return next_state(IL_ICMP_TTIME, -1); }
+icmpseq { return next_state(IL_ICMP_SEQ, -1); }
+icmpid { return next_state(IL_ICMP_SEQ, -1); }
+\{ { push_proto(); return next_item('{'); }
+\} { pop_proto(); return next_item('}'); }
+\. { return next_item(IL_DOT); }
+; { return next_item(';'); }
+[0-9]+ { return next_item(IL_NUMBER); }
+[0-9a-fA-F] { return next_item(IL_HEXDIGIT); }
+: { return next_item(IL_COLON); }
+#[^\n]* { return next_item(IL_COMMENT); }
+[^ {}\n\t;]* { return next_item(IL_TOKEN); }
+\"[^\"]*\" { return next_item(IL_TOKEN); }
+%%
+void yyerror(msg)
+char *msg;
+{
+ fprintf(stderr, "%s error at \"%s\", line %d\n", msg, yytext,
+ lineNum + 1);
+ exit(1);
+}
+
+
+void push_proto()
+{
+ numpr++;
+ if (!prstack)
+ prstack = (int *)malloc(sizeof(int));
+ else
+ prstack = (int *)realloc((char *)prstack, numpr * sizeof(int));
+ prstack[numpr - 1] = oldproto;
+}
+
+
+void pop_proto()
+{
+ numpr--;
+ proto = prstack[numpr];
+ if (!numpr) {
+ free(prstack);
+ prstack = NULL;
+ return;
+ }
+ prstack = (int *)realloc((char *)prstack, numpr * sizeof(int));
+}
+
+
+int save_token()
+{
+ static char *buf = NULL;
+
+ if (buf && (buf == yylval.str))
+ free(buf);
+ buf = yylval.str = strdup(yytext);
+ return IL_TOKEN;
+}
+
+
+int next_item(nstate)
+int nstate;
+{
+ if (next == IL_TOKEN) {
+ next = -1;
+ return save_token();
+ }
+ next = -1;
+ if (nstate == IL_NUMBER)
+ yylval.num = atoi(yytext);
+ token++;
+ return nstate;
+}
+
+
+int next_state(nstate, fornext)
+int nstate, fornext;
+{
+ token++;
+
+ if (next == IL_TOKEN) {
+ next = -1;
+ return save_token();
+ }
+
+ next = fornext;
+
+ switch (nstate)
+ {
+ case IL_IPV4 :
+ case IL_TCP :
+ case IL_UDP :
+ case IL_ICMP :
+ case IL_DATA :
+ case IL_INTERFACE :
+ case IL_ARP :
+ oldproto = proto;
+ proto = nstate;
+ break;
+ case IL_SUM :
+ if (proto == IL_IPV4)
+ nstate = IL_V4SUM;
+ else if (proto == IL_TCP)
+ nstate = IL_TCPSUM;
+ else if (proto == IL_UDP)
+ nstate = IL_UDPSUM;
+ break;
+ case IL_OPT :
+ if (proto == IL_IPV4)
+ nstate = IL_V4OPT;
+ else if (proto == IL_TCP)
+ nstate = IL_TCPOPT;
+ break;
+ case IL_IPO_NOP :
+ if (proto == IL_TCP)
+ nstate = IL_TCPO_NOP;
+ break;
+ case IL_IPO_EOL :
+ if (proto == IL_TCP)
+ nstate = IL_TCPO_EOL;
+ break;
+ case IL_IPO_TS :
+ if (proto == IL_TCP)
+ nstate = IL_TCPO_TS;
+ break;
+ case IL_OFF :
+ if (proto == IL_IPV4)
+ nstate = IL_V4OFF;
+ else if (proto == IL_TCP)
+ nstate = IL_TCPOFF;
+ break;
+ case IL_LEN :
+ if (proto == IL_IPV4)
+ nstate = IL_V4LEN;
+ else if (proto == IL_UDP)
+ nstate = IL_UDPLEN;
+ break;
+ }
+ return nstate;
+}
+
+
+void swallow()
+{
+ int c = input();
+
+ if (c == '#') {
+ while ((c != '\n') && (c != EOF))
+ c = input();
+ }
+ unput(c);
+}
diff --git a/contrib/ipfilter/iplang/iplang_y.y b/contrib/ipfilter/iplang/iplang_y.y
new file mode 100644
index 0000000..6d56bc5
--- /dev/null
+++ b/contrib/ipfilter/iplang/iplang_y.y
@@ -0,0 +1,1858 @@
+%{
+/*
+ * Copyright (C) 1997 by Darren Reed.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and due credit is given
+ * to the original author and the contributors.
+ *
+ * $Id: iplang_y.y,v 2.0.2.18.2.2 1997/11/05 11:04:19 darrenr Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#if !defined(__SVR4) && !defined(__svr4__)
+#include <strings.h>
+#else
+#include <sys/byteorder.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_icmp.h>
+#ifndef linux
+#include <netinet/ip_var.h>
+#endif
+#include <netinet/tcp.h>
+#include <netinet/udp.h>
+#include <net/if.h>
+#ifndef linux
+#include <netinet/if_ether.h>
+#endif
+#include <netdb.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+#include <resolv.h>
+#include <ctype.h>
+#include "ipsend.h"
+#include "ip_compat.h"
+#include "ipf.h"
+#include "iplang.h"
+
+extern struct ether_addr *ether_aton __P((char *));
+
+extern int opts;
+extern struct ipopt_names ionames[];
+extern int state, state, lineNum, token;
+extern int yylineno;
+extern char yytext[];
+extern FILE *yyin;
+int yylex __P((void));
+#define YYDEBUG 1
+#if !defined(ultrix) && !defined(hpux)
+int yydebug = 1;
+#else
+extern int yydebug;
+#endif
+
+iface_t *iflist = NULL, **iftail = &iflist;
+iface_t *cifp = NULL;
+arp_t *arplist = NULL, **arptail = &arplist, *carp = NULL;
+struct in_addr defrouter;
+send_t sending;
+char *sclass = NULL;
+u_short c_chksum __P((u_short *, u_int, u_long));
+u_long p_chksum __P((u_short *, u_int));
+
+u_long ipbuffer[67584/sizeof(u_long)]; /* 66K */
+aniphdr_t *aniphead = NULL, *canip = NULL, **aniptail = &aniphead;
+ip_t *ip = NULL;
+udphdr_t *udp = NULL;
+tcphdr_t *tcp = NULL;
+icmphdr_t *icmp = NULL;
+
+struct statetoopt {
+ int sto_st;
+ int sto_op;
+};
+
+struct in_addr getipv4addr __P((char *arg));
+u_short getportnum __P((char *, char *));
+struct ether_addr *geteaddr __P((char *, struct ether_addr *));
+void *new_header __P((int));
+void free_aniplist __P((void));
+void inc_anipheaders __P((int));
+void new_data __P((void));
+void set_datalen __P((char **));
+void set_datafile __P((char **));
+void set_data __P((char **));
+void new_packet __P((void));
+void set_ipv4proto __P((char **));
+void set_ipv4src __P((char **));
+void set_ipv4dst __P((char **));
+void set_ipv4off __P((char **));
+void set_ipv4v __P((char **));
+void set_ipv4hl __P((char **));
+void set_ipv4ttl __P((char **));
+void set_ipv4tos __P((char **));
+void set_ipv4id __P((char **));
+void set_ipv4sum __P((char **));
+void set_ipv4len __P((char **));
+void new_tcpheader __P((void));
+void set_tcpsport __P((char **));
+void set_tcpdport __P((char **));
+void set_tcpseq __P((char **));
+void set_tcpack __P((char **));
+void set_tcpoff __P((char **));
+void set_tcpurp __P((char **));
+void set_tcpwin __P((char **));
+void set_tcpsum __P((char **));
+void set_tcpflags __P((char **));
+void set_tcpopt __P((int, char **));
+void end_tcpopt __P((void));
+void new_udpheader __P((void));
+void set_udplen __P((char **));
+void set_udpsum __P((char **));
+void prep_packet __P((void));
+void packet_done __P((void));
+void new_interface __P((void));
+void check_interface __P((void));
+void set_ifname __P((char **));
+void set_ifmtu __P((int));
+void set_ifv4addr __P((char **));
+void set_ifeaddr __P((char **));
+void new_arp __P((void));
+void set_arpeaddr __P((char **));
+void set_arpv4addr __P((char **));
+void reset_send __P((void));
+void set_sendif __P((char **));
+void set_sendvia __P((char **));
+void set_defaultrouter __P((char **));
+void new_icmpheader __P((void));
+void set_icmpcode __P((int));
+void set_icmptype __P((int));
+void set_icmpcodetok __P((char **));
+void set_icmptypetok __P((char **));
+void set_icmpid __P((int));
+void set_icmpseq __P((int));
+void set_icmpotime __P((int));
+void set_icmprtime __P((int));
+void set_icmpttime __P((int));
+void set_icmpmtu __P((int));
+void set_redir __P((int, char **));
+void new_ipv4opt __P((void));
+void set_icmppprob __P((int));
+void add_ipopt __P((int, void *));
+void end_ipopt __P((void));
+void set_secclass __P((char **));
+void free_anipheader __P((void));
+void end_ipv4 __P((void));
+void end_icmp __P((void));
+void end_udp __P((void));
+void end_tcp __P((void));
+void end_data __P((void));
+void yyerror __P((char *));
+void iplang __P((FILE *));
+int yyparse __P((void));
+%}
+%union {
+ char *str;
+ int num;
+}
+%token <num> IL_NUMBER
+%type <num> number digits optnumber
+%token <str> IL_TOKEN
+%type <str> token optoken
+%token IL_HEXDIGIT IL_COLON IL_DOT IL_EOF IL_COMMENT
+%token IL_INTERFACE IL_IFNAME IL_MTU IL_EADDR
+%token IL_IPV4 IL_V4PROTO IL_V4SRC IL_V4DST IL_V4OFF IL_V4V IL_V4HL IL_V4TTL
+%token IL_V4TOS IL_V4SUM IL_V4LEN IL_V4OPT IL_V4ID
+%token IL_TCP IL_SPORT IL_DPORT IL_TCPFL IL_TCPSEQ IL_TCPACK IL_TCPOFF
+%token IL_TCPWIN IL_TCPSUM IL_TCPURP IL_TCPOPT IL_TCPO_NOP IL_TCPO_EOL
+%token IL_TCPO_MSS IL_TCPO_WSCALE IL_TCPO_TS
+%token IL_UDP IL_UDPLEN IL_UDPSUM
+%token IL_ICMP IL_ICMPTYPE IL_ICMPCODE
+%token IL_SEND IL_VIA
+%token IL_ARP
+%token IL_DEFROUTER
+%token IL_SUM IL_OFF IL_LEN IL_V4ADDR IL_OPT
+%token IL_DATA IL_DLEN IL_DVALUE IL_DFILE
+%token IL_IPO_NOP IL_IPO_RR IL_IPO_ZSU IL_IPO_MTUP IL_IPO_MTUR IL_IPO_EOL
+%token IL_IPO_TS IL_IPO_TR IL_IPO_SEC IL_IPO_LSRR IL_IPO_ESEC
+%token IL_IPO_SATID IL_IPO_SSRR IL_IPO_ADDEXT IL_IPO_VISA IL_IPO_IMITD
+%token IL_IPO_EIP IL_IPO_FINN IL_IPO_SECCLASS IL_IPO_CIPSO IL_IPO_ENCODE
+%token IL_IPS_RESERV4 IL_IPS_TOPSECRET IL_IPS_SECRET IL_IPS_RESERV3
+%token IL_IPS_CONFID IL_IPS_UNCLASS IL_IPS_RESERV2 IL_IPS_RESERV1
+%token IL_ICMP_ECHOREPLY IL_ICMP_UNREACH IL_ICMP_UNREACH_NET
+%token IL_ICMP_UNREACH_HOST IL_ICMP_UNREACH_PROTOCOL IL_ICMP_UNREACH_PORT
+%token IL_ICMP_UNREACH_NEEDFRAG IL_ICMP_UNREACH_SRCFAIL
+%token IL_ICMP_UNREACH_NET_UNKNOWN IL_ICMP_UNREACH_HOST_UNKNOWN
+%token IL_ICMP_UNREACH_ISOLATED IL_ICMP_UNREACH_NET_PROHIB
+%token IL_ICMP_UNREACH_HOST_PROHIB IL_ICMP_UNREACH_TOSNET
+%token IL_ICMP_UNREACH_TOSHOST IL_ICMP_UNREACH_FILTER_PROHIB
+%token IL_ICMP_UNREACH_HOST_PRECEDENCE IL_ICMP_UNREACH_PRECEDENCE_CUTOFF
+%token IL_ICMP_SOURCEQUENCH IL_ICMP_REDIRECT IL_ICMP_REDIRECT_NET
+%token IL_ICMP_REDIRECT_HOST IL_ICMP_REDIRECT_TOSNET
+%token IL_ICMP_REDIRECT_TOSHOST IL_ICMP_ECHO IL_ICMP_ROUTERADVERT
+%token IL_ICMP_ROUTERSOLICIT IL_ICMP_TIMXCEED IL_ICMP_TIMXCEED_INTRANS
+%token IL_ICMP_TIMXCEED_REASS IL_ICMP_PARAMPROB IL_ICMP_PARAMPROB_OPTABSENT
+%token IL_ICMP_TSTAMP IL_ICMP_TSTAMPREPLY IL_ICMP_IREQ IL_ICMP_IREQREPLY
+%token IL_ICMP_MASKREQ IL_ICMP_MASKREPLY IL_ICMP_SEQ IL_ICMP_ID
+%token IL_ICMP_OTIME IL_ICMP_RTIME IL_ICMP_TTIME
+
+%%
+file: line
+ | line file
+ | IL_COMMENT
+ | IL_COMMENT file
+ ;
+
+line: iface
+ | arp
+ | send
+ | defrouter
+ | ipline
+ ;
+
+iface: ifhdr '{' ifaceopts '}' ';' { check_interface(); }
+ ;
+
+ifhdr: IL_INTERFACE { new_interface(); }
+ ;
+
+ifaceopts:
+ ifaceopt
+ | ifaceopt ifaceopts
+ ;
+
+ifaceopt:
+ IL_IFNAME token { set_ifname(&yylval.str); }
+ | IL_MTU number { set_ifmtu(yylval.num); }
+ | IL_V4ADDR token { set_ifv4addr(&yylval.str); }
+ | IL_EADDR token { set_ifeaddr(&yylval.str); }
+ ;
+
+send: sendhdr '{' sendbody '}' ';' { packet_done(); }
+ | sendhdr ';' { packet_done(); }
+ ;
+
+sendhdr:
+ IL_SEND { reset_send(); }
+ ;
+
+sendbody:
+ sendopt
+ | sendbody sendopt
+ ;
+
+sendopt:
+ IL_IFNAME token { set_sendif(&yylval.str); }
+ | IL_VIA token { set_sendvia(&yylval.str); }
+ ;
+
+arp: arphdr '{' arpbody '}' ';'
+ ;
+
+arphdr: IL_ARP { new_arp(); }
+ ;
+
+arpbody:
+ arpopt
+ | arpbody arpopt
+ ;
+
+arpopt: IL_V4ADDR token { set_arpv4addr(&yylval.str); }
+ | IL_EADDR token { set_arpeaddr(&yylval.str); }
+ ;
+
+defrouter:
+ IL_DEFROUTER token { set_defaultrouter(&yylval.str); }
+ ;
+
+bodyline:
+ ipline
+ | tcp tcpline
+ | udp udpline
+ | icmp icmpline
+ | data dataline
+ ;
+
+ipline: ipv4 '{' ipv4body '}' ';' { end_ipv4(); }
+ ;
+
+ipv4: IL_IPV4 { new_packet(); }
+
+ipv4body:
+ ipv4type
+ | ipv4type ipv4body
+ | bodyline
+ ;
+
+ipv4type:
+ IL_V4PROTO token { set_ipv4proto(&yylval.str); }
+ | IL_V4SRC token { set_ipv4src(&yylval.str); }
+ | IL_V4DST token { set_ipv4dst(&yylval.str); }
+ | IL_V4OFF token { set_ipv4off(&yylval.str); }
+ | IL_V4V token { set_ipv4v(&yylval.str); }
+ | IL_V4HL token { set_ipv4hl(&yylval.str); }
+ | IL_V4ID token { set_ipv4id(&yylval.str); }
+ | IL_V4TTL token { set_ipv4ttl(&yylval.str); }
+ | IL_V4TOS token { set_ipv4tos(&yylval.str); }
+ | IL_V4SUM token { set_ipv4sum(&yylval.str); }
+ | IL_V4LEN token { set_ipv4len(&yylval.str); }
+ | ipv4opt '{' ipv4optlist '}' ';' { end_ipopt(); }
+ ;
+
+tcp: IL_TCP { new_tcpheader(); }
+ ;
+
+tcpline:
+ '{' tcpheader '}' ';' { end_tcp(); }
+ ;
+
+tcpheader:
+ tcpbody tcpheader
+ | bodyline
+ ;
+
+tcpbody:
+ IL_SPORT token { set_tcpsport(&yylval.str); }
+ | IL_DPORT token { set_tcpdport(&yylval.str); }
+ | IL_TCPSEQ token { set_tcpseq(&yylval.str); }
+ | IL_TCPACK token { set_tcpack(&yylval.str); }
+ | IL_TCPOFF token { set_tcpoff(&yylval.str); }
+ | IL_TCPURP token { set_tcpurp(&yylval.str); }
+ | IL_TCPWIN token { set_tcpwin(&yylval.str); }
+ | IL_TCPSUM token { set_tcpsum(&yylval.str); }
+ | IL_TCPFL token { set_tcpflags(&yylval.str); }
+ | IL_TCPOPT '{' tcpopts '}' ';' { end_tcpopt(); }
+ ;
+
+tcpopts:
+ | tcpopt tcpopts
+ ;
+
+tcpopt: IL_TCPO_NOP ';' { set_tcpopt(IL_TCPO_NOP, NULL); }
+ | IL_TCPO_EOL ';' { set_tcpopt(IL_TCPO_EOL, NULL); }
+ | IL_TCPO_MSS optoken { set_tcpopt(IL_TCPO_MSS,&yylval.str);}
+ | IL_TCPO_WSCALE optoken { set_tcpopt(IL_TCPO_MSS,&yylval.str);}
+ | IL_TCPO_TS optoken { set_tcpopt(IL_TCPO_TS, &yylval.str);}
+ ;
+
+udp: IL_UDP { new_udpheader(); }
+ ;
+
+udpline:
+ '{' udpheader '}' ';' { end_udp(); }
+ ;
+
+
+udpheader:
+ udpbody
+ | udpbody udpheader
+ | bodyline
+ ;
+
+udpbody:
+ IL_SPORT token { set_tcpsport(&yylval.str); }
+ | IL_DPORT token { set_tcpdport(&yylval.str); }
+ | IL_UDPLEN token { set_udplen(&yylval.str); }
+ | IL_UDPSUM token { set_udpsum(&yylval.str); }
+ ;
+
+icmp: IL_ICMP { new_icmpheader(); }
+ ;
+
+icmpline:
+ '{' icmpbody '}' ';' { end_icmp(); }
+ ;
+
+icmpbody:
+ icmpheader
+ | icmpheader bodyline
+ ;
+
+icmpheader:
+ IL_ICMPTYPE icmptype
+ | IL_ICMPTYPE icmptype icmpcode
+ ;
+
+icmpcode:
+ IL_ICMPCODE token { set_icmpcodetok(&yylval.str); }
+ ;
+
+icmptype:
+ IL_ICMP_ECHOREPLY ';' { set_icmptype(ICMP_ECHOREPLY); }
+ | IL_ICMP_ECHOREPLY '{' icmpechoopts '}' ';'
+ | unreach
+ | IL_ICMP_SOURCEQUENCH ';' { set_icmptype(ICMP_SOURCEQUENCH); }
+ | redirect
+ | IL_ICMP_ROUTERADVERT ';' { set_icmptype(ICMP_ROUTERADVERT); }
+ | IL_ICMP_ROUTERSOLICIT ';' { set_icmptype(ICMP_ROUTERSOLICIT); }
+ | IL_ICMP_ECHO ';' { set_icmptype(ICMP_ECHO); }
+ | IL_ICMP_ECHO '{' icmpechoopts '}' ';'
+ | IL_ICMP_TIMXCEED ';' { set_icmptype(ICMP_TIMXCEED); }
+ | IL_ICMP_TIMXCEED '{' exceed '}' ';'
+ | IL_ICMP_TSTAMP ';' { set_icmptype(ICMP_TSTAMP); }
+ | IL_ICMP_TSTAMPREPLY ';' { set_icmptype(ICMP_TSTAMPREPLY); }
+ | IL_ICMP_TSTAMPREPLY '{' icmptsopts '}' ';'
+ | IL_ICMP_IREQ ';' { set_icmptype(ICMP_IREQ); }
+ | IL_ICMP_IREQREPLY ';' { set_icmptype(ICMP_IREQREPLY); }
+ | IL_ICMP_IREQREPLY '{' data dataline '}' ';'
+ | IL_ICMP_MASKREQ ';' { set_icmptype(ICMP_MASKREQ); }
+ | IL_ICMP_MASKREPLY ';' { set_icmptype(ICMP_MASKREPLY); }
+ | IL_ICMP_MASKREPLY '{' token '}' ';'
+ | IL_ICMP_PARAMPROB ';' { set_icmptype(ICMP_PARAMPROB); }
+ | IL_ICMP_PARAMPROB '{' paramprob '}' ';'
+ | IL_TOKEN ';' { set_icmptypetok(&yylval.str); }
+ ;
+
+icmpechoopts:
+ | icmpechoopts icmpecho
+ ;
+
+icmpecho:
+ IL_ICMP_SEQ number { set_icmpseq(yylval.num); }
+ | IL_ICMP_ID number { set_icmpid(yylval.num); }
+ ;
+
+icmptsopts:
+ | icmptsopts icmpts ';'
+ ;
+
+icmpts: IL_ICMP_OTIME number { set_icmpotime(yylval.num); }
+ | IL_ICMP_RTIME number { set_icmprtime(yylval.num); }
+ | IL_ICMP_TTIME number { set_icmpttime(yylval.num); }
+ ;
+
+unreach:
+ IL_ICMP_UNREACH
+ | IL_ICMP_UNREACH '{' unreachopts '}' ';'
+ ;
+
+unreachopts:
+ IL_ICMP_UNREACH_NET line
+ | IL_ICMP_UNREACH_HOST line
+ | IL_ICMP_UNREACH_PROTOCOL line
+ | IL_ICMP_UNREACH_PORT line
+ | IL_ICMP_UNREACH_NEEDFRAG number ';' { set_icmpmtu(yylval.num); }
+ | IL_ICMP_UNREACH_SRCFAIL line
+ | IL_ICMP_UNREACH_NET_UNKNOWN line
+ | IL_ICMP_UNREACH_HOST_UNKNOWN line
+ | IL_ICMP_UNREACH_ISOLATED line
+ | IL_ICMP_UNREACH_NET_PROHIB line
+ | IL_ICMP_UNREACH_HOST_PROHIB line
+ | IL_ICMP_UNREACH_TOSNET line
+ | IL_ICMP_UNREACH_TOSHOST line
+ | IL_ICMP_UNREACH_FILTER_PROHIB line
+ | IL_ICMP_UNREACH_HOST_PRECEDENCE line
+ | IL_ICMP_UNREACH_PRECEDENCE_CUTOFF line
+ ;
+
+redirect:
+ IL_ICMP_REDIRECT
+ | IL_ICMP_REDIRECT '{' redirectopts '}' ';'
+ ;
+
+redirectopts:
+ | IL_ICMP_REDIRECT_NET token { set_redir(0, &yylval.str); }
+ | IL_ICMP_REDIRECT_HOST token { set_redir(1, &yylval.str); }
+ | IL_ICMP_REDIRECT_TOSNET token { set_redir(2, &yylval.str); }
+ | IL_ICMP_REDIRECT_TOSHOST token { set_redir(3, &yylval.str); }
+ ;
+
+exceed:
+ IL_ICMP_TIMXCEED_INTRANS line
+ | IL_ICMP_TIMXCEED_REASS line
+ ;
+
+paramprob:
+ IL_ICMP_PARAMPROB_OPTABSENT
+ | IL_ICMP_PARAMPROB_OPTABSENT paraprobarg
+
+paraprobarg:
+ '{' number '}' ';' { set_icmppprob(yylval.num); }
+ ;
+
+ipv4opt: IL_V4OPT { new_ipv4opt(); }
+ ;
+
+ipv4optlist:
+ | ipv4opts ipv4optlist
+ ;
+
+ipv4opts:
+ IL_IPO_NOP ';' { add_ipopt(IL_IPO_NOP, NULL); }
+ | IL_IPO_RR optnumber { add_ipopt(IL_IPO_RR, &yylval.num); }
+ | IL_IPO_ZSU ';' { add_ipopt(IL_IPO_ZSU, NULL); }
+ | IL_IPO_MTUP ';' { add_ipopt(IL_IPO_MTUP, NULL); }
+ | IL_IPO_MTUR ';' { add_ipopt(IL_IPO_MTUR, NULL); }
+ | IL_IPO_ENCODE ';' { add_ipopt(IL_IPO_ENCODE, NULL); }
+ | IL_IPO_TS ';' { add_ipopt(IL_IPO_TS, NULL); }
+ | IL_IPO_TR ';' { add_ipopt(IL_IPO_TR, NULL); }
+ | IL_IPO_SEC ';' { add_ipopt(IL_IPO_SEC, NULL); }
+ | IL_IPO_SECCLASS secclass { add_ipopt(IL_IPO_SECCLASS, sclass); }
+ | IL_IPO_LSRR token { add_ipopt(IL_IPO_LSRR,&yylval.str); }
+ | IL_IPO_ESEC ';' { add_ipopt(IL_IPO_ESEC, NULL); }
+ | IL_IPO_CIPSO ';' { add_ipopt(IL_IPO_CIPSO, NULL); }
+ | IL_IPO_SATID optnumber { add_ipopt(IL_IPO_SATID,&yylval.num);}
+ | IL_IPO_SSRR token { add_ipopt(IL_IPO_SSRR,&yylval.str); }
+ | IL_IPO_ADDEXT ';' { add_ipopt(IL_IPO_ADDEXT, NULL); }
+ | IL_IPO_VISA ';' { add_ipopt(IL_IPO_VISA, NULL); }
+ | IL_IPO_IMITD ';' { add_ipopt(IL_IPO_IMITD, NULL); }
+ | IL_IPO_EIP ';' { add_ipopt(IL_IPO_EIP, NULL); }
+ | IL_IPO_FINN ';' { add_ipopt(IL_IPO_FINN, NULL); }
+ ;
+
+secclass:
+ IL_IPS_RESERV4 ';' { set_secclass(&yylval.str); }
+ | IL_IPS_TOPSECRET ';' { set_secclass(&yylval.str); }
+ | IL_IPS_SECRET ';' { set_secclass(&yylval.str); }
+ | IL_IPS_RESERV3 ';' { set_secclass(&yylval.str); }
+ | IL_IPS_CONFID ';' { set_secclass(&yylval.str); }
+ | IL_IPS_UNCLASS ';' { set_secclass(&yylval.str); }
+ | IL_IPS_RESERV2 ';' { set_secclass(&yylval.str); }
+ | IL_IPS_RESERV1 ';' { set_secclass(&yylval.str); }
+ ;
+
+data: IL_DATA { new_data(); }
+ ;
+
+dataline:
+ '{' databody '}' ';' { end_data(); }
+ ;
+
+databody: dataopts
+ | dataopts databody
+ ;
+
+dataopts:
+ IL_DLEN token { set_datalen(&yylval.str); }
+ | IL_DVALUE token { set_data(&yylval.str); }
+ | IL_DFILE token { set_datafile(&yylval.str); }
+ ;
+
+token: IL_TOKEN ';'
+ ;
+
+optoken: ';' { $$ = ""; }
+ | token
+ ;
+
+number: digits ';'
+ ;
+
+optnumber: ';' { $$ = 0; }
+ | number
+ ;
+
+digits: IL_NUMBER
+ | digits IL_NUMBER
+ ;
+%%
+
+struct statetoopt toipopts[] = {
+ { IL_IPO_NOP, IPOPT_NOP },
+ { IL_IPO_RR, IPOPT_RR },
+ { IL_IPO_ZSU, IPOPT_ZSU },
+ { IL_IPO_MTUP, IPOPT_MTUP },
+ { IL_IPO_MTUR, IPOPT_MTUR },
+ { IL_IPO_ENCODE, IPOPT_ENCODE },
+ { IL_IPO_TS, IPOPT_TS },
+ { IL_IPO_TR, IPOPT_TR },
+ { IL_IPO_SEC, IPOPT_SECURITY },
+ { IL_IPO_SECCLASS, IPOPT_SECURITY },
+ { IL_IPO_LSRR, IPOPT_LSRR },
+ { IL_IPO_ESEC, IPOPT_E_SEC },
+ { IL_IPO_CIPSO, IPOPT_CIPSO },
+ { IL_IPO_SATID, IPOPT_SATID },
+ { IL_IPO_SSRR, IPOPT_SSRR },
+ { IL_IPO_ADDEXT, IPOPT_ADDEXT },
+ { IL_IPO_VISA, IPOPT_VISA },
+ { IL_IPO_IMITD, IPOPT_IMITD },
+ { IL_IPO_EIP, IPOPT_EIP },
+ { IL_IPO_FINN, IPOPT_FINN },
+ { 0, 0 }
+};
+
+struct statetoopt tosecopts[] = {
+ { IL_IPS_RESERV4, IPSO_CLASS_RES4 },
+ { IL_IPS_TOPSECRET, IPSO_CLASS_TOPS },
+ { IL_IPS_SECRET, IPSO_CLASS_SECR },
+ { IL_IPS_RESERV3, IPSO_CLASS_RES3 },
+ { IL_IPS_CONFID, IPSO_CLASS_CONF },
+ { IL_IPS_UNCLASS, IPSO_CLASS_UNCL },
+ { IL_IPS_RESERV2, IPSO_CLASS_RES2 },
+ { IL_IPS_RESERV1, IPSO_CLASS_RES1 },
+ { 0, 0 }
+};
+
+#ifdef bsdi
+struct ether_addr *
+ether_aton(s)
+ char *s;
+{
+ static struct ether_addr n;
+ u_int i[6];
+
+ if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
+ &i[2], &i[3], &i[4], &i[5]) == 6) {
+ n.ether_addr_octet[0] = (u_char)i[0];
+ n.ether_addr_octet[1] = (u_char)i[1];
+ n.ether_addr_octet[2] = (u_char)i[2];
+ n.ether_addr_octet[3] = (u_char)i[3];
+ n.ether_addr_octet[4] = (u_char)i[4];
+ n.ether_addr_octet[5] = (u_char)i[5];
+ return &n;
+ }
+ return NULL;
+}
+#endif
+
+#ifdef bsdi
+struct ether_addr *
+ether_aton(s)
+ char *s;
+{
+ static struct ether_addr n;
+ u_int i[6];
+
+ if (sscanf(s, " %x:%x:%x:%x:%x:%x ", &i[0], &i[1],
+ &i[2], &i[3], &i[4], &i[5]) == 6) {
+ n.ether_addr_octet[0] = (u_char)i[0];
+ n.ether_addr_octet[1] = (u_char)i[1];
+ n.ether_addr_octet[2] = (u_char)i[2];
+ n.ether_addr_octet[3] = (u_char)i[3];
+ n.ether_addr_octet[4] = (u_char)i[4];
+ n.ether_addr_octet[5] = (u_char)i[5];
+ return &n;
+ }
+ return NULL;
+}
+#endif
+
+
+struct in_addr getipv4addr(arg)
+char *arg;
+{
+ struct hostent *hp;
+ struct in_addr in;
+
+ in.s_addr = 0xffffffff;
+
+ if ((hp = gethostbyname(arg)))
+ bcopy(hp->h_addr, &in.s_addr, sizeof(struct in_addr));
+ else
+ in.s_addr = inet_addr(arg);
+ return in;
+}
+
+
+u_short getportnum(pr, name)
+char *pr, *name;
+{
+ struct servent *sp;
+
+ if (!(sp = getservbyname(name, pr)))
+ return atoi(name);
+ return sp->s_port;
+}
+
+
+struct ether_addr *geteaddr(arg, buf)
+char *arg;
+struct ether_addr *buf;
+{
+ struct ether_addr *e;
+
+#if !defined(hpux) && !defined(linux)
+ e = ether_aton(arg);
+ if (!e)
+ fprintf(stderr, "Invalid ethernet address: %s\n", arg);
+ else
+# ifdef __FreeBSD__
+ bcopy(e->octet, buf->octet, sizeof(e->octet));
+# else
+ bcopy(e->ether_addr_octet, buf->ether_addr_octet,
+ sizeof(e->ether_addr_octet));
+# endif
+ return e;
+#else
+ return NULL;
+#endif
+}
+
+
+void *new_header(type)
+int type;
+{
+ aniphdr_t *aip, *oip = canip;
+ int sz = 0;
+
+ aip = (aniphdr_t *)calloc(1, sizeof(*aip));
+ *aniptail = aip;
+ aniptail = &aip->ah_next;
+ aip->ah_p = type;
+ aip->ah_prev = oip;
+ canip = aip;
+
+ if (type == IPPROTO_UDP)
+ sz = sizeof(udphdr_t);
+ else if (type == IPPROTO_TCP)
+ sz = sizeof(tcphdr_t);
+ else if (type == IPPROTO_ICMP)
+ sz = sizeof(icmphdr_t);
+ else if (type == IPPROTO_IP)
+ sz = sizeof(ip_t);
+
+ if (oip)
+ canip->ah_data = oip->ah_data + oip->ah_len;
+ else
+ canip->ah_data = (char *)ipbuffer;
+
+ /*
+ * Increase the size fields in all wrapping headers.
+ */
+ for (aip = aniphead; aip; aip = aip->ah_next) {
+ aip->ah_len += sz;
+ if (aip->ah_p == IPPROTO_IP)
+ aip->ah_ip->ip_len += sz;
+ else if (aip->ah_p == IPPROTO_UDP)
+ aip->ah_udp->uh_ulen += sz;
+ }
+ return (void *)canip->ah_data;
+}
+
+
+void free_aniplist()
+{
+ aniphdr_t *aip, **aipp = &aniphead;
+
+ while ((aip = *aipp)) {
+ *aipp = aip->ah_next;
+ free(aip);
+ }
+ aniptail = &aniphead;
+}
+
+
+void inc_anipheaders(inc)
+int inc;
+{
+ aniphdr_t *aip;
+
+ for (aip = aniphead; aip; aip = aip->ah_next) {
+ aip->ah_len += inc;
+ if (aip->ah_p == IPPROTO_IP)
+ aip->ah_ip->ip_len += inc;
+ else if (aip->ah_p == IPPROTO_UDP)
+ aip->ah_udp->uh_ulen += inc;
+ }
+}
+
+
+void new_data()
+{
+ (void) new_header(-1);
+ canip->ah_len = 0;
+}
+
+
+void set_datalen(arg)
+char **arg;
+{
+ int len;
+
+ len = strtol(*arg, NULL, 0);
+ inc_anipheaders(len);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_data(arg)
+char **arg;
+{
+ u_char *s = (u_char *)*arg, *t = (u_char *)canip->ah_data, c;
+ int len = 0, todo = 0, quote = 0, val = 0;
+
+ while ((c = *s++)) {
+ if (todo) {
+ if (isdigit(c)) {
+ todo--;
+ if (c > '7') {
+ fprintf(stderr, "octal with %c!\n", c);
+ break;
+ }
+ val <<= 3;
+ val |= (c - '0');
+ }
+ if (!isdigit(c) || !todo) {
+ *t++ = (u_char)(val & 0xff);
+ todo = 0;
+ }
+ }
+ if (quote) {
+ if (isdigit(c)) {
+ todo = 2;
+ if (c > '7') {
+ fprintf(stderr, "octal with %c!\n", c);
+ break;
+ }
+ val = (c - '0');
+ } else {
+ switch (c)
+ {
+ case '\"' :
+ *t++ = '\"';
+ break;
+ case '\\' :
+ *t++ = '\\';
+ break;
+ case 'n' :
+ *t++ = '\n';
+ break;
+ case 'r' :
+ *t++ = '\r';
+ break;
+ case 't' :
+ *t++ = '\t';
+ break;
+ }
+ quote = 0;
+ }
+ continue;
+ }
+
+ if (c == '\\')
+ quote = 1;
+ else
+ *t++ = c;
+ }
+ if (quote)
+ *t++ = '\\';
+ len = t - (u_char *)canip->ah_data;
+ inc_anipheaders(len - canip->ah_len);
+ canip->ah_len = len;
+}
+
+
+void set_datafile(arg)
+char **arg;
+{
+ struct stat sb;
+ char *file = *arg;
+ int fd, len;
+
+ if ((fd = open(file, O_RDONLY)) == -1) {
+ perror("open");
+ exit(-1);
+ }
+
+ if (fstat(fd, &sb) == -1) {
+ perror("fstat");
+ exit(-1);
+ }
+
+ if ((sb.st_size + aniphead->ah_len ) > 65535) {
+ fprintf(stderr, "data file %s too big to include.\n", file);
+ close(fd);
+ return;
+ }
+ if ((len = read(fd, canip->ah_data, sb.st_size)) == -1) {
+ perror("read");
+ close(fd);
+ return;
+ }
+ inc_anipheaders(len);
+ canip->ah_len += len;
+ close(fd);
+}
+
+
+void new_packet()
+{
+ static u_short id = 0;
+
+ if (!aniphead)
+ bzero((char *)ipbuffer, sizeof(ipbuffer));
+
+ ip = (ip_t *)new_header(IPPROTO_IP);
+ ip->ip_v = IPVERSION;
+ ip->ip_hl = sizeof(ip_t) >> 2;
+ ip->ip_len = sizeof(ip_t);
+ ip->ip_ttl = 63;
+ ip->ip_id = htons(id++);
+}
+
+
+void set_ipv4proto(arg)
+char **arg;
+{
+ struct protoent *pr;
+
+ if ((pr = getprotobyname(*arg)))
+ ip->ip_p = pr->p_proto;
+ else
+ if (!(ip->ip_p = atoi(*arg)))
+ fprintf(stderr, "unknown protocol %s\n", *arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4src(arg)
+char **arg;
+{
+ ip->ip_src = getipv4addr(*arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4dst(arg)
+char **arg;
+{
+ ip->ip_dst = getipv4addr(*arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4off(arg)
+char **arg;
+{
+ ip->ip_off = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4v(arg)
+char **arg;
+{
+ ip->ip_v = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4hl(arg)
+char **arg;
+{
+ int newhl, inc;
+
+ newhl = strtol(*arg, NULL, 0);
+ inc = (newhl - ip->ip_hl) << 2;
+ ip->ip_len += inc;
+ ip->ip_hl = newhl;
+ canip->ah_len += inc;
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4ttl(arg)
+char **arg;
+{
+ ip->ip_ttl = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4tos(arg)
+char **arg;
+{
+ ip->ip_tos = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4id(arg)
+char **arg;
+{
+ ip->ip_id = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4sum(arg)
+char **arg;
+{
+ ip->ip_sum = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ipv4len(arg)
+char **arg;
+{
+ int len;
+
+ len = strtol(*arg, NULL, 0);
+ inc_anipheaders(len - ip->ip_len);
+ ip->ip_len = len;
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void new_tcpheader()
+{
+
+ if ((ip->ip_p) && (ip->ip_p != IPPROTO_TCP)) {
+ fprintf(stderr, "protocol %d specified with TCP!\n", ip->ip_p);
+ return;
+ }
+ ip->ip_p = IPPROTO_TCP;
+
+ tcp = (tcphdr_t *)new_header(IPPROTO_TCP);
+ tcp->th_win = 4096;
+ tcp->th_off = sizeof(*tcp) >> 2;
+}
+
+
+void set_tcpsport(arg)
+char **arg;
+{
+ u_short *port;
+ char *pr;
+
+ if (ip->ip_p == IPPROTO_UDP) {
+ port = &udp->uh_sport;
+ pr = "udp";
+ } else {
+ port = &tcp->th_sport;
+ pr = "udp";
+ }
+
+ *port = getportnum(pr, *arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpdport(arg)
+char **arg;
+{
+ u_short *port;
+ char *pr;
+
+ if (ip->ip_p == IPPROTO_UDP) {
+ port = &udp->uh_dport;
+ pr = "udp";
+ } else {
+ port = &tcp->th_dport;
+ pr = "udp";
+ }
+
+ *port = getportnum(pr, *arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpseq(arg)
+char **arg;
+{
+ tcp->th_seq = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpack(arg)
+char **arg;
+{
+ tcp->th_ack = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpoff(arg)
+char **arg;
+{
+ int off;
+
+ off = strtol(*arg, NULL, 0);
+ inc_anipheaders((off - tcp->th_off) << 2);
+ tcp->th_off = off;
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpurp(arg)
+char **arg;
+{
+ tcp->th_urp = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpwin(arg)
+char **arg;
+{
+ tcp->th_win = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpsum(arg)
+char **arg;
+{
+ tcp->th_sum = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpflags(arg)
+char **arg;
+{
+ static char flags[] = "ASURPF";
+ static int flagv[] = { TH_ACK, TH_SYN, TH_URG, TH_RST, TH_PUSH,
+ TH_FIN } ;
+ char *s, *t;
+
+ for (s = *arg; *s; s++)
+ if (!(t = strchr(flags, *s))) {
+ if (s - *arg) {
+ fprintf(stderr, "unknown TCP flag %c\n", *s);
+ break;
+ }
+ tcp->th_flags = strtol(*arg, NULL, 0);
+ break;
+ } else
+ tcp->th_flags |= flagv[t - flags];
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_tcpopt(state, arg)
+int state;
+char **arg;
+{
+ u_char *s;
+ int val, len, val2, pad, optval;
+
+ if (arg && *arg)
+ val = atoi(*arg);
+ else
+ val = 0;
+
+ s = (u_char *)tcp + sizeof(*tcp) + canip->ah_optlen;
+ switch (state)
+ {
+ case IL_TCPO_EOL :
+ optval = 0;
+ len = 1;
+ break;
+ case IL_TCPO_NOP :
+ optval = 1;
+ len = 1;
+ break;
+ case IL_TCPO_MSS :
+ optval = 2;
+ len = 4;
+ break;
+ case IL_TCPO_WSCALE :
+ optval = 3;
+ len = 3;
+ break;
+ case IL_TCPO_TS :
+ optval = 8;
+ len = 10;
+ break;
+ default :
+ optval = 0;
+ len = 0;
+ break;
+ }
+
+ if (len > 1) {
+ /*
+ * prepend padding - if required.
+ */
+ if (len & 3)
+ for (pad = 4 - (len & 3); pad; pad--) {
+ *s++ = 1;
+ canip->ah_optlen++;
+ }
+ /*
+ * build tcp option
+ */
+ *s++ = (u_char)optval;
+ *s++ = (u_char)len;
+ if (len > 2) {
+ if (len == 3) { /* 1 byte - char */
+ *s++ = (u_char)val;
+ } else if (len == 4) { /* 2 bytes - short */
+ *s++ = (u_char)((val >> 8) & 0xff);
+ *s++ = (u_char)(val & 0xff);
+ } else if (len >= 6) { /* 4 bytes - long */
+ val2 = htonl(val);
+ bcopy((char *)&val2, s, 4);
+ }
+ s += (len - 2);
+ }
+ } else
+ *s++ = (u_char)optval;
+
+ canip->ah_lastopt = optval;
+ canip->ah_optlen += len;
+
+ if (arg && *arg) {
+ free(*arg);
+ *arg = NULL;
+ }
+}
+
+
+void end_tcpopt()
+{
+ int pad;
+ char *s = (char *)tcp;
+
+ s += sizeof(*tcp) + canip->ah_optlen;
+ /*
+ * pad out so that we have a multiple of 4 bytes in size fo the
+ * options. make sure last byte is EOL.
+ */
+ if (canip->ah_optlen & 3) {
+ if (canip->ah_lastopt != 1) {
+ for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
+ *s++ = 1;
+ canip->ah_optlen++;
+ }
+ canip->ah_optlen++;
+ } else {
+ s -= 1;
+
+ for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
+ *s++ = 1;
+ canip->ah_optlen++;
+ }
+ }
+ *s++ = 0;
+ }
+ tcp->th_off = (sizeof(*tcp) + canip->ah_optlen) >> 2;
+ inc_anipheaders(canip->ah_optlen);
+}
+
+
+void new_udpheader()
+{
+ if ((ip->ip_p) && (ip->ip_p != IPPROTO_UDP)) {
+ fprintf(stderr, "protocol %d specified with UDP!\n", ip->ip_p);
+ return;
+ }
+ ip->ip_p = IPPROTO_UDP;
+
+ udp = (udphdr_t *)new_header(IPPROTO_UDP);
+ udp->uh_ulen = sizeof(*udp);
+}
+
+
+void set_udplen(arg)
+char **arg;
+{
+ int len;
+
+ len = strtol(*arg, NULL, 0);
+ inc_anipheaders(len - udp->uh_ulen);
+ udp->uh_ulen = len;
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_udpsum(arg)
+char **arg;
+{
+ udp->uh_sum = strtol(*arg, NULL, 0);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void prep_packet()
+{
+ iface_t *ifp;
+ struct in_addr gwip;
+
+ ifp = sending.snd_if;
+ if (!ifp) {
+ fprintf(stderr, "no interface defined for sending!\n");
+ return;
+ }
+ if (ifp->if_fd == -1)
+ ifp->if_fd = initdevice(ifp->if_name, 0, 5);
+ gwip = sending.snd_gw;
+ if (!gwip.s_addr)
+ gwip = aniphead->ah_ip->ip_dst;
+ (void) send_ip(ifp->if_fd, ifp->if_MTU, (ip_t *)ipbuffer, gwip, 2);
+}
+
+
+void packet_done()
+{
+ char outline[80];
+ int i, j, k;
+ u_char *s = (u_char *)ipbuffer, *t = (u_char *)outline;
+
+ if (opts & OPT_VERBOSE) {
+ for (i = ip->ip_len, j = 0; i; i--, j++, s++) {
+ if (j && !(j & 0xf)) {
+ *t++ = '\n';
+ *t = '\0';
+ fputs(outline, stdout);
+ fflush(stdout);
+ t = (u_char *)outline;
+ *t = '\0';
+ }
+ sprintf((char *)t, "%02x", *s & 0xff);
+ t += 2;
+ if (!((j + 1) & 0xf)) {
+ s -= 15;
+ sprintf((char *)t, " ");
+ t += 8;
+ for (k = 16; k; k--, s++)
+ *t++ = (isprint(*s) ? *s : '.');
+ s--;
+ }
+
+ if ((j + 1) & 0xf)
+ *t++ = ' ';;
+ }
+
+ if (j & 0xf) {
+ for (k = 16 - (j & 0xf); k; k--) {
+ *t++ = ' ';
+ *t++ = ' ';
+ *t++ = ' ';
+ }
+ sprintf((char *)t, " ");
+ t += 7;
+ s -= j & 0xf;
+ for (k = j & 0xf; k; k--, s++)
+ *t++ = (isprint(*s) ? *s : '.');
+ *t++ = '\n';
+ *t = '\0';
+ }
+ fputs(outline, stdout);
+ fflush(stdout);
+ }
+
+ prep_packet();
+ free_aniplist();
+}
+
+
+void new_interface()
+{
+ cifp = (iface_t *)calloc(1, sizeof(iface_t));
+ *iftail = cifp;
+ iftail = &cifp->if_next;
+ cifp->if_fd = -1;
+}
+
+
+void check_interface()
+{
+ if (!cifp->if_name || !*cifp->if_name)
+ fprintf(stderr, "No interface name given!\n");
+ if (!cifp->if_MTU || !*cifp->if_name)
+ fprintf(stderr, "Interface %s has an MTU of 0!\n",
+ cifp->if_name);
+}
+
+
+void set_ifname(arg)
+char **arg;
+{
+ cifp->if_name = *arg;
+ *arg = NULL;
+}
+
+
+void set_ifmtu(arg)
+int arg;
+{
+ cifp->if_MTU = arg;
+}
+
+
+void set_ifv4addr(arg)
+char **arg;
+{
+ cifp->if_addr = getipv4addr(*arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_ifeaddr(arg)
+char **arg;
+{
+ (void) geteaddr(*arg, &cifp->if_eaddr);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void new_arp()
+{
+ carp = (arp_t *)calloc(1, sizeof(arp_t));
+ *arptail = carp;
+ arptail = &carp->arp_next;
+}
+
+
+void set_arpeaddr(arg)
+char **arg;
+{
+ (void) geteaddr(*arg, &carp->arp_eaddr);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_arpv4addr(arg)
+char **arg;
+{
+ carp->arp_addr = getipv4addr(*arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void reset_send()
+{
+ sending.snd_if = iflist;
+ sending.snd_gw = defrouter;
+}
+
+
+void set_sendif(arg)
+char **arg;
+{
+ iface_t *ifp;
+
+ for (ifp = iflist; ifp; ifp = ifp->if_next)
+ if (ifp->if_name && !strcmp(ifp->if_name, *arg))
+ break;
+ sending.snd_if = ifp;
+ if (!ifp)
+ fprintf(stderr, "couldn't find interface %s\n", *arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_sendvia(arg)
+char **arg;
+{
+ sending.snd_gw = getipv4addr(*arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_defaultrouter(arg)
+char **arg;
+{
+ defrouter = getipv4addr(*arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void new_icmpheader()
+{
+ if ((ip->ip_p) && (ip->ip_p != IPPROTO_ICMP)) {
+ fprintf(stderr, "protocol %d specified with ICMP!\n",
+ ip->ip_p);
+ return;
+ }
+ ip->ip_p = IPPROTO_ICMP;
+ icmp = (icmphdr_t *)new_header(IPPROTO_ICMP);
+}
+
+
+void set_icmpcode(code)
+int code;
+{
+ icmp->icmp_code = code;
+}
+
+
+void set_icmptype(type)
+int type;
+{
+ icmp->icmp_type = type;
+}
+
+
+static char *icmpcodes[] = {
+ "net-unr", "host-unr", "proto-unr", "port-unr", "needfrag", "srcfail",
+ "net-unk", "host-unk", "isolate", "net-prohib", "host-prohib",
+ "net-tos", "host-tos", NULL };
+
+void set_icmpcodetok(code)
+char **code;
+{
+ char *s;
+ int i;
+
+ for (i = 0; (s = icmpcodes[i]); i++)
+ if (!strcmp(s, *code)) {
+ icmp->icmp_code = i;
+ break;
+ }
+ if (!s)
+ fprintf(stderr, "unknown ICMP code %s\n", *code);
+ free(*code);
+ *code = NULL;
+}
+
+
+static char *icmptypes[] = {
+ "echorep", (char *)NULL, (char *)NULL, "unreach", "squench",
+ "redir", (char *)NULL, (char *)NULL, "echo", (char *)NULL,
+ (char *)NULL, "timex", "paramprob", "timest", "timestrep",
+ "inforeq", "inforep", "maskreq", "maskrep", "END"
+};
+
+void set_icmptypetok(type)
+char **type;
+{
+ char *s;
+ int i, done = 0;
+
+ for (i = 0; !(s = icmptypes[i]) || strcmp(s, "END"); i++)
+ if (s && !strcmp(s, *type)) {
+ icmp->icmp_type = i;
+ done = 1;
+ break;
+ }
+ if (!done)
+ fprintf(stderr, "unknown ICMP type %s\n", *type);
+ free(*type);
+ *type = NULL;
+}
+
+
+void set_icmpid(arg)
+int arg;
+{
+ icmp->icmp_id = arg;
+}
+
+
+void set_icmpseq(arg)
+int arg;
+{
+ icmp->icmp_seq = arg;
+}
+
+
+void set_icmpotime(arg)
+int arg;
+{
+ icmp->icmp_otime = arg;
+}
+
+
+void set_icmprtime(arg)
+int arg;
+{
+ icmp->icmp_rtime = arg;
+}
+
+
+void set_icmpttime(arg)
+int arg;
+{
+ icmp->icmp_ttime = arg;
+}
+
+
+void set_icmpmtu(arg)
+int arg;
+{
+#if BSD >= 199306
+ icmp->icmp_nextmtu = arg;
+#endif
+}
+
+
+void set_redir(redir, arg)
+int redir;
+char **arg;
+{
+ icmp->icmp_code = redir;
+ icmp->icmp_gwaddr = getipv4addr(*arg);
+ free(*arg);
+ *arg = NULL;
+}
+
+
+void set_icmppprob(num)
+int num;
+{
+ icmp->icmp_pptr = num;
+}
+
+
+void new_ipv4opt()
+{
+ new_header(-2);
+}
+
+
+void add_ipopt(state, ptr)
+int state;
+void *ptr;
+{
+ struct ipopt_names *io;
+ struct statetoopt *sto;
+ char numbuf[16], *arg, **param = ptr;
+ int inc, hlen;
+
+ if (state == IL_IPO_RR || state == IL_IPO_SATID) {
+ if (param)
+ sprintf(numbuf, "%d", *(int *)param);
+ else
+ strcpy(numbuf, "0");
+ arg = numbuf;
+ } else
+ arg = param ? *param : NULL;
+
+ if (canip->ah_next) {
+ fprintf(stderr, "cannot specify options after data body\n");
+ return;
+ }
+ for (sto = toipopts; sto->sto_st; sto++)
+ if (sto->sto_st == state)
+ break;
+ if (!sto || !sto->sto_st) {
+ fprintf(stderr, "No mapping for state %d to IP option\n",
+ state);
+ return;
+ }
+
+ hlen = sizeof(ip_t) + canip->ah_optlen;
+ for (io = ionames; io->on_name; io++)
+ if (io->on_value == sto->sto_op)
+ break;
+ canip->ah_lastopt = io->on_value;
+
+ if (io->on_name) {
+ inc = addipopt((char *)ip + hlen, io, hlen - sizeof(ip_t),arg);
+ if (inc > 0) {
+ while (inc & 3) {
+ ((char *)ip)[sizeof(*ip) + inc] = IPOPT_NOP;
+ canip->ah_lastopt = IPOPT_NOP;
+ inc++;
+ }
+ hlen += inc;
+ }
+ }
+
+ canip->ah_optlen = hlen - sizeof(ip_t);
+
+ if (state != IL_IPO_RR && state != IL_IPO_SATID)
+ if (param && *param) {
+ free(*param);
+ *param = NULL;
+ }
+ sclass = NULL;
+}
+
+
+void end_ipopt()
+{
+ int pad;
+ char *s, *buf = (char *)ip;
+
+ /*
+ * pad out so that we have a multiple of 4 bytes in size fo the
+ * options. make sure last byte is EOL.
+ */
+ if (canip->ah_lastopt == IPOPT_NOP) {
+ buf[sizeof(*ip) + canip->ah_optlen - 1] = IPOPT_EOL;
+ } else if (canip->ah_lastopt != IPOPT_EOL) {
+ s = buf + sizeof(*ip) + canip->ah_optlen;
+
+ for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
+ *s++ = IPOPT_NOP;
+ *s = IPOPT_EOL;
+ canip->ah_optlen++;
+ }
+ canip->ah_optlen++;
+ } else {
+ s = buf + sizeof(*ip) + canip->ah_optlen - 1;
+
+ for (pad = 3 - (canip->ah_optlen & 3); pad; pad--) {
+ *s++ = IPOPT_NOP;
+ *s = IPOPT_EOL;
+ canip->ah_optlen++;
+ }
+ }
+ ip->ip_hl = (sizeof(*ip) + canip->ah_optlen) >> 2;
+ inc_anipheaders(canip->ah_optlen);
+ free_anipheader();
+}
+
+
+void set_secclass(arg)
+char **arg;
+{
+ sclass = *arg;
+ *arg = NULL;
+}
+
+
+void free_anipheader()
+{
+ aniphdr_t *aip;
+
+ aip = canip;
+ if ((canip = aip->ah_prev)) {
+ canip->ah_next = NULL;
+ aniptail = &canip->ah_next;
+ }
+ free(aip);
+}
+
+
+void end_ipv4()
+{
+ aniphdr_t *aip;
+
+ ip->ip_sum = 0;
+ ip->ip_sum = chksum((u_short *)ip, ip->ip_hl << 2);
+ free_anipheader();
+ for (aip = aniphead, ip = NULL; aip; aip = aip->ah_next)
+ if (aip->ah_p == IPPROTO_IP)
+ ip = aip->ah_ip;
+}
+
+
+void end_icmp()
+{
+ aniphdr_t *aip;
+
+ icmp->icmp_cksum = 0;
+ icmp->icmp_cksum = chksum((u_short *)icmp, canip->ah_len);
+ free_anipheader();
+ for (aip = aniphead, icmp = NULL; aip; aip = aip->ah_next)
+ if (aip->ah_p == IPPROTO_ICMP)
+ icmp = aip->ah_icmp;
+}
+
+
+void end_udp()
+{
+ u_long sum;
+ aniphdr_t *aip;
+ ip_t iptmp;
+
+ bzero((char *)&iptmp, sizeof(iptmp));
+ iptmp.ip_p = ip->ip_p;
+ iptmp.ip_src = ip->ip_src;
+ iptmp.ip_dst = ip->ip_dst;
+ iptmp.ip_len = ip->ip_len - (ip->ip_hl << 2);
+ sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
+ udp->uh_sum = c_chksum((u_short *)udp, (u_int)iptmp.ip_len, sum);
+ free_anipheader();
+ for (aip = aniphead, udp = NULL; aip; aip = aip->ah_next)
+ if (aip->ah_p == IPPROTO_UDP)
+ udp = aip->ah_udp;
+}
+
+
+void end_tcp()
+{
+ u_long sum;
+ aniphdr_t *aip;
+ ip_t iptmp;
+
+ bzero((char *)&iptmp, sizeof(iptmp));
+ iptmp.ip_p = ip->ip_p;
+ iptmp.ip_src = ip->ip_src;
+ iptmp.ip_dst = ip->ip_dst;
+ iptmp.ip_len = ip->ip_len - (ip->ip_hl << 2);
+ sum = p_chksum((u_short *)&iptmp, (u_int)sizeof(iptmp));
+ tcp->th_sum = 0;
+ tcp->th_sum = c_chksum((u_short *)tcp, (u_int)iptmp.ip_len, sum);
+ free_anipheader();
+ for (aip = aniphead, tcp = NULL; aip; aip = aip->ah_next)
+ if (aip->ah_p == IPPROTO_TCP)
+ tcp = aip->ah_tcp;
+}
+
+
+void end_data()
+{
+ free_anipheader();
+}
+
+
+void iplang(fp)
+FILE *fp;
+{
+ yyin = fp;
+
+ yydebug = (opts & OPT_DEBUG) ? 1 : 0;
+
+ while (!feof(fp))
+ yyparse();
+}
+
+
+u_short c_chksum(buf, len, init)
+u_short *buf;
+u_int len;
+u_long init;
+{
+ u_long sum = init;
+ int nwords = len >> 1;
+
+ for(; nwords > 0; nwords--)
+ sum += *buf++;
+ sum = (sum>>16) + (sum & 0xffff);
+ sum += (sum >>16);
+ return (~sum);
+}
+
+
+u_long p_chksum(buf,len)
+u_short *buf;
+u_int len;
+{
+ u_long sum = 0;
+ int nwords = len >> 1;
+
+ for(; nwords > 0; nwords--)
+ sum += *buf++;
+ return sum;
+}
OpenPOWER on IntegriCloud